From 254416aae70ab2e6b57fd79782c8a67196234d02 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 9 Dec 2009 16:43:52 -0500 Subject: wireless: report reasonable bitrate for MCS rates through wext Previously, cfg80211 had reported "0" for MCS (i.e. 802.11n) bitrates through the wireless extensions interface. However, nl80211 was converting MCS rates into a reasonable bitrate number. This patch moves the nl80211 code to cfg80211 where it is now shared between both the nl80211 interface and the wireless extensions interface. Signed-off-by: John W. Linville --- net/wireless/core.h | 2 ++ net/wireless/nl80211.c | 37 ++----------------------------------- net/wireless/util.c | 33 +++++++++++++++++++++++++++++++++ net/wireless/wext-compat.c | 5 +---- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/net/wireless/core.h b/net/wireless/core.h index 4ef3efc94106..35b712127143 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -378,6 +378,8 @@ int rdev_set_freq(struct cfg80211_registered_device *rdev, struct wireless_dev *for_wdev, int freq, enum nl80211_channel_type channel_type); +u16 cfg80211_calculate_bitrate(struct rate_info *rate); + #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) #else diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a6028433e3a0..7cb0d647fc34 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1637,39 +1637,6 @@ static int parse_station_flags(struct genl_info *info, return 0; } -static u16 nl80211_calculate_bitrate(struct rate_info *rate) -{ - int modulation, streams, bitrate; - - if (!(rate->flags & RATE_INFO_FLAGS_MCS)) - return rate->legacy; - - /* the formula below does only work for MCS values smaller than 32 */ - if (rate->mcs >= 32) - return 0; - - modulation = rate->mcs & 7; - streams = (rate->mcs >> 3) + 1; - - bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? - 13500000 : 6500000; - - if (modulation < 4) - bitrate *= (modulation + 1); - else if (modulation == 4) - bitrate *= (modulation + 2); - else - bitrate *= (modulation + 3); - - bitrate *= streams; - - if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) - bitrate = (bitrate / 9) * 10; - - /* do NOT round down here */ - return (bitrate + 50000) / 100000; -} - static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct net_device *dev, u8 *mac_addr, struct station_info *sinfo) @@ -1716,8 +1683,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, if (!txrate) goto nla_put_failure; - /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */ - bitrate = nl80211_calculate_bitrate(&sinfo->txrate); + /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ + bitrate = cfg80211_calculate_bitrate(&sinfo->txrate); if (bitrate > 0) NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); diff --git a/net/wireless/util.c b/net/wireless/util.c index 59361fdcb5d0..a3c841a255db 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -720,3 +720,36 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, return err; } + +u16 cfg80211_calculate_bitrate(struct rate_info *rate) +{ + int modulation, streams, bitrate; + + if (!(rate->flags & RATE_INFO_FLAGS_MCS)) + return rate->legacy; + + /* the formula below does only work for MCS values smaller than 32 */ + if (rate->mcs >= 32) + return 0; + + modulation = rate->mcs & 7; + streams = (rate->mcs >> 3) + 1; + + bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? + 13500000 : 6500000; + + if (modulation < 4) + bitrate *= (modulation + 1); + else if (modulation == 4) + bitrate *= (modulation + 2); + else + bitrate *= (modulation + 3); + + bitrate *= streams; + + if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) + bitrate = (bitrate / 9) * 10; + + /* do NOT round down here */ + return (bitrate + 50000) / 100000; +} diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 584eb4826e02..2fa8de1140e9 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1256,10 +1256,7 @@ int cfg80211_wext_giwrate(struct net_device *dev, if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) return -EOPNOTSUPP; - rate->value = 0; - - if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS)) - rate->value = 100000 * sinfo.txrate.legacy; + rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); return 0; } -- cgit v1.2.3 From 15920d8afc87861672e16fa95ae2764b065d6dd3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 30 Aug 2009 20:18:41 -0600 Subject: wireless: hostap, fix oops due to early probing interrupt BugLink: https://bugs.launchpad.net/ubuntu/+bug/254837 Spurious shared interrupts or early probing interrupts can cause the hostap interrupt handler to oops before the driver has fully configured the IO base port addresses. In some cases the oops can be because the hardware shares an interrupt line, on other cases it is due to a race condition between probing for the hardware and configuring the IO base port. The latter occurs because the probing is required to determin the hardware port address which is only determined when the probe can interrupt the hardware (catch 22). This patch catches this pre-configured condition to avoid the oops. Signed-off-by: Colin Ian King Signed-off-by: Stefan Bader Acked-by: Tim Gardner Acked-by: Stefan Bader Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_hw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index ff9b5c882184..d70732819423 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -2618,6 +2618,15 @@ static irqreturn_t prism2_interrupt(int irq, void *dev_id) int events = 0; u16 ev; + /* Detect early interrupt before driver is fully configued */ + if (!dev->base_addr) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", + dev->name); + } + return IRQ_HANDLED; + } + iface = netdev_priv(dev); local = iface->local; -- cgit v1.2.3 From abe60632f311d515b082b450504ee24006023951 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Nov 2009 17:46:18 +0100 Subject: mac80211: make station management completely depend on vif The station management currently uses the virtual interface, but you cannot add the same station to multiple virtual interfaces if you're communicating with it in multiple ways. This restriction should be lifted so that in the future we can, for instance, support bluetooth 3 with an access point that mac80211 is already associated to. We can do that by requiring all sta_info_get users to provide the virtual interface and making the RX code aware that an address may match more than one station struct. Thanks to the previous patches this one isn't all that large and except for the RX and TX status paths changes has low complexity. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 3 +- net/mac80211/agg-tx.c | 4 +- net/mac80211/cfg.c | 25 ++++------ net/mac80211/ibss.c | 2 +- net/mac80211/key.c | 2 +- net/mac80211/mesh_hwmp.c | 2 +- net/mac80211/mesh_plink.c | 4 +- net/mac80211/mlme.c | 10 ++-- net/mac80211/rx.c | 119 +++++++++++++++++++++++++--------------------- net/mac80211/sta_info.c | 18 ++++--- net/mac80211/sta_info.h | 29 ++++++++++- net/mac80211/status.c | 8 ++-- net/mac80211/tx.c | 9 ++-- 13 files changed, 134 insertions(+), 101 deletions(-) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 51c7dc3c4c3b..f16d49d474b4 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -83,12 +83,11 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 initiator, u16 reason) { - struct ieee80211_local *local = sdata->local; struct sta_info *sta; rcu_read_lock(); - sta = sta_info_get(local, ra); + sta = sta_info_get(sdata, ra); if (!sta) { rcu_read_unlock(); return; diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5e3a7eccef5a..b05de532c379 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -441,7 +441,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) } rcu_read_lock(); - sta = sta_info_get(local, ra); + sta = sta_info_get(sdata, ra); if (!sta) { rcu_read_unlock(); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -564,7 +564,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) #endif /* CONFIG_MAC80211_HT_DEBUG */ rcu_read_lock(); - sta = sta_info_get(local, ra); + sta = sta_info_get(sdata, ra); if (!sta) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Could not find station: %pM\n", ra); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 93ee1fd5c08d..14e1f4015a72 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -150,7 +150,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); if (mac_addr) { - sta = sta_info_get(sdata->local, mac_addr); + sta = sta_info_get(sdata, mac_addr); if (!sta) { ieee80211_key_free(key); err = -ENOENT; @@ -181,7 +181,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, if (mac_addr) { ret = -ENOENT; - sta = sta_info_get(sdata->local, mac_addr); + sta = sta_info_get(sdata, mac_addr); if (!sta) goto out_unlock; @@ -228,7 +228,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); if (mac_addr) { - sta = sta_info_get(sdata->local, mac_addr); + sta = sta_info_get(sdata, mac_addr); if (!sta) goto out; @@ -414,15 +414,13 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_info *sinfo) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct sta_info *sta; int ret = -ENOENT; rcu_read_lock(); - /* XXX: verify sta->dev == dev */ - - sta = sta_info_get(local, mac); + sta = sta_info_get(sdata, mac); if (sta) { ret = 0; sta_set_sinfo(sta, sinfo); @@ -778,8 +776,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, if (mac) { rcu_read_lock(); - /* XXX: get sta belonging to dev */ - sta = sta_info_get(local, mac); + sta = sta_info_get(sdata, mac); if (!sta) { rcu_read_unlock(); return -ENOENT; @@ -800,14 +797,14 @@ static int ieee80211_change_station(struct wiphy *wiphy, u8 *mac, struct station_parameters *params) { + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wiphy_priv(wiphy); struct sta_info *sta; struct ieee80211_sub_if_data *vlansdata; rcu_read_lock(); - /* XXX: get sta belonging to dev */ - sta = sta_info_get(local, mac); + sta = sta_info_get(sdata, mac); if (!sta) { rcu_read_unlock(); return -ENOENT; @@ -846,7 +843,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; struct sta_info *sta; @@ -855,7 +851,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); - sta = sta_info_get(local, next_hop); + sta = sta_info_get(sdata, next_hop); if (!sta) { rcu_read_unlock(); return -ENOENT; @@ -894,7 +890,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop) { - struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; struct mesh_path *mpath; struct sta_info *sta; @@ -903,7 +898,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, rcu_read_lock(); - sta = sta_info_get(local, next_hop); + sta = sta_info_get(sdata, next_hop); if (!sta) { rcu_read_unlock(); return -ENOENT; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 10d13856f86c..1925be9b82fb 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -252,7 +252,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); - sta = sta_info_get(local, mgmt->sa); + sta = sta_info_get(sdata, mgmt->sa); if (sta) { u32 prev_rates; diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 659a42d529e3..ac1a777674f6 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -421,7 +421,7 @@ void ieee80211_key_link(struct ieee80211_key *key, */ /* same here, the AP could be using QoS */ - ap = sta_info_get(key->local, key->sdata->u.mgd.bssid); + ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid); if (ap) { if (test_sta_flags(ap, WLAN_STA_WME)) key->conf.flags |= diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 833b2f3670c5..b836892f0ba9 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -335,7 +335,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, bool process = true; rcu_read_lock(); - sta = sta_info_get(local, mgmt->sa); + sta = sta_info_get(sdata, mgmt->sa); if (!sta) { rcu_read_unlock(); return 0; diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 0f7c6e6a4248..8fcf56ee7743 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -234,7 +234,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data rcu_read_lock(); - sta = sta_info_get(local, hw_addr); + sta = sta_info_get(sdata, hw_addr); if (!sta) { sta = mesh_plink_alloc(sdata, hw_addr, rates); if (!sta) { @@ -455,7 +455,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m rcu_read_lock(); - sta = sta_info_get(local, mgmt->sa); + sta = sta_info_get(sdata, mgmt->sa); if (!sta && ftype != PLINK_OPEN) { mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6dc7b5ad9a41..c16667a7c8df 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -202,7 +202,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, ieee80211_hw_config(local, 0); rcu_read_lock(); - sta = sta_info_get(local, bssid); + sta = sta_info_get(sdata, bssid); if (sta) rate_control_rate_update(local, sband, sta, IEEE80211_RC_HT_CHANGED); @@ -1070,7 +1070,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, netif_carrier_off(sdata->dev); rcu_read_lock(); - sta = sta_info_get(local, bssid); + sta = sta_info_get(sdata, bssid); if (sta) ieee80211_sta_tear_down_BA_sessions(sta); rcu_read_unlock(); @@ -1109,7 +1109,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); - sta = sta_info_get(local, bssid); + sta = sta_info_get(sdata, bssid); if (!sta) { rcu_read_unlock(); return; @@ -1489,7 +1489,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); /* Add STA entry for the AP */ - sta = sta_info_get(local, wk->bss->cbss.bssid); + sta = sta_info_get(sdata, wk->bss->cbss.bssid); if (!sta) { newsta = true; @@ -1857,7 +1857,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, rcu_read_lock(); - sta = sta_info_get(local, bssid); + sta = sta_info_get(sdata, bssid); if (WARN_ON(!sta)) { rcu_read_unlock(); return; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f237df408378..5bae28693da8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1472,7 +1472,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; struct net_device *dev = sdata->dev; - struct ieee80211_local *local = rx->local; struct sk_buff *skb, *xmit_skb; struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; struct sta_info *dsta; @@ -1495,8 +1494,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); } else { - dsta = sta_info_get(local, skb->data); - if (dsta && dsta->sdata->dev == dev) { + dsta = sta_info_get(sdata, skb->data); + if (dsta) { /* * The destination station is associated to * this AP (in this VLAN), so send the frame @@ -2363,6 +2362,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, int prepares; struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; + struct sta_info *sta, *tmp; + bool found_sta = false; hdr = (struct ieee80211_hdr *)skb->data; memset(&rx, 0, sizeof(rx)); @@ -2379,68 +2380,76 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, ieee80211_parse_qos(&rx); ieee80211_verify_alignment(&rx); - rx.sta = sta_info_get(local, hdr->addr2); - if (rx.sta) - rx.sdata = rx.sta->sdata; - - if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { - rx.flags |= IEEE80211_RX_RA_MATCH; - prepares = prepare_for_handlers(rx.sdata, &rx, hdr); - if (prepares) { - if (status->flag & RX_FLAG_MMIC_ERROR) { - if (rx.flags & IEEE80211_RX_RA_MATCH) - ieee80211_rx_michael_mic_report(hdr, &rx); - } else - prev = rx.sdata; + if (ieee80211_is_data(hdr->frame_control)) { + for_each_sta_info(local, hdr->addr2, sta, tmp) { + rx.sta = sta; + found_sta = true; + rx.sdata = sta->sdata; + + rx.flags |= IEEE80211_RX_RA_MATCH; + prepares = prepare_for_handlers(rx.sdata, &rx, hdr); + if (prepares) { + if (status->flag & RX_FLAG_MMIC_ERROR) { + if (rx.flags & IEEE80211_RX_RA_MATCH) + ieee80211_rx_michael_mic_report(hdr, &rx); + } else + prev = rx.sdata; + } } - } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) - continue; + } + if (!found_sta) { + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; - if (sdata->vif.type == NL80211_IFTYPE_MONITOR || - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - continue; + if (sdata->vif.type == NL80211_IFTYPE_MONITOR || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + continue; - rx.flags |= IEEE80211_RX_RA_MATCH; - prepares = prepare_for_handlers(sdata, &rx, hdr); + rx.sta = sta_info_get(sdata, hdr->addr2); - if (!prepares) - continue; + rx.flags |= IEEE80211_RX_RA_MATCH; + prepares = prepare_for_handlers(sdata, &rx, hdr); - if (status->flag & RX_FLAG_MMIC_ERROR) { - rx.sdata = sdata; - if (rx.flags & IEEE80211_RX_RA_MATCH) - ieee80211_rx_michael_mic_report(hdr, &rx); - continue; - } + if (!prepares) + continue; - /* - * frame is destined for this interface, but if it's not - * also for the previous one we handle that after the - * loop to avoid copying the SKB once too much - */ + if (status->flag & RX_FLAG_MMIC_ERROR) { + rx.sdata = sdata; + if (rx.flags & IEEE80211_RX_RA_MATCH) + ieee80211_rx_michael_mic_report(hdr, + &rx); + continue; + } - if (!prev) { - prev = sdata; - continue; - } + /* + * frame is destined for this interface, but if it's + * not also for the previous one we handle that after + * the loop to avoid copying the SKB once too much + */ - /* - * frame was destined for the previous interface - * so invoke RX handlers for it - */ + if (!prev) { + prev = sdata; + continue; + } - skb_new = skb_copy(skb, GFP_ATOMIC); - if (!skb_new) { - if (net_ratelimit()) - printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s\n", - wiphy_name(local->hw.wiphy), - prev->dev->name); - continue; + /* + * frame was destined for the previous interface + * so invoke RX handlers for it + */ + + skb_new = skb_copy(skb, GFP_ATOMIC); + if (!skb_new) { + if (net_ratelimit()) + printk(KERN_DEBUG "%s: failed to copy " + "multicast frame for %s\n", + wiphy_name(local->hw.wiphy), + prev->dev->name); + continue; + } + ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); + prev = sdata; } - ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); - prev = sdata; } if (prev) ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 71f370dd24bc..c58a23eea58c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -103,13 +103,16 @@ static int sta_info_hash_del(struct ieee80211_local *local, } /* protected by RCU */ -struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) +struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, + const u8 *addr) { + struct ieee80211_local *local = sdata->local; struct sta_info *sta; sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); while (sta) { - if (memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) + if (sta->sdata == sdata && + memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) break; sta = rcu_dereference(sta->hnext); } @@ -377,7 +380,7 @@ int sta_info_insert(struct sta_info *sta) spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (sta_info_get(local, sta->sta.addr)) { + if (sta_info_get(sdata, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); err = -EEXIST; goto out_free; @@ -843,11 +846,12 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, const u8 *addr) { - struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); + struct sta_info *sta, *nxt; - if (!sta) - return NULL; - return &sta->sta; + /* Just return a random station ... first in list ... */ + for_each_sta_info(hw_to_local(hw), addr, sta, nxt) + return &sta->sta; + return NULL; } EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b4810f6aa94f..c8208236e896 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -403,9 +403,34 @@ static inline u32 get_sta_flags(struct sta_info *sta) #define STA_INFO_CLEANUP_INTERVAL (10 * HZ) /* - * Get a STA info, must have be under RCU read lock. + * Get a STA info, must be under RCU read lock. */ -struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); +struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, + const u8 *addr); + +static inline +void for_each_sta_info_type_check(struct ieee80211_local *local, + const u8 *addr, + struct sta_info *sta, + struct sta_info *nxt) +{ +} + +#define for_each_sta_info(local, _addr, sta, nxt) \ + for ( /* initialise loop */ \ + sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ + nxt = sta ? rcu_dereference(sta->hnext) : NULL; \ + /* typecheck */ \ + for_each_sta_info_type_check(local, (_addr), sta, nxt), \ + /* continue condition */ \ + sta; \ + /* advance loop */ \ + sta = nxt, \ + nxt = sta ? rcu_dereference(sta->hnext) : NULL \ + ) \ + /* compare address and run code only if it matches */ \ + if (memcmp(sta->sta.addr, (_addr), ETH_ALEN) == 0) + /* * Get STA info by index, BROKEN! */ diff --git a/net/mac80211/status.c b/net/mac80211/status.c index d78f36c64c7b..32fe327acf4e 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -146,7 +146,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_tx_status_rtap_hdr *rthdr; struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; - struct sta_info *sta; + struct sta_info *sta, *tmp; int retry_count = -1, i; bool injected; @@ -166,9 +166,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) sband = local->hw.wiphy->bands[info->band]; - sta = sta_info_get(local, hdr->addr1); + for_each_sta_info(local, hdr->addr1, sta, tmp) { + /* skip wrong virtual interface */ + if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN)) + continue; - if (sta) { if (!(info->flags & IEEE80211_TX_STAT_ACK) && test_sta_flags(sta, WLAN_STA_PS_STA)) { /* diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8834cc93c716..b913bfc34a9f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1055,7 +1055,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) tx->sta = rcu_dereference(sdata->u.vlan.sta); if (!tx->sta) - tx->sta = sta_info_get(local, hdr->addr1); + tx->sta = sta_info_get(sdata, hdr->addr1); if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { @@ -1761,9 +1761,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ if (!is_multicast_ether_addr(hdr.addr1)) { rcu_read_lock(); - sta = sta_info_get(local, hdr.addr1); - /* XXX: in the future, use sdata to look up the sta */ - if (sta && sta->sdata == sdata) + sta = sta_info_get(sdata, hdr.addr1); + if (sta) sta_flags = get_sta_flags(sta); rcu_read_unlock(); } @@ -1922,7 +1921,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, ieee80211_tx(sdata, skb, true); } else { hdr = (struct ieee80211_hdr *)skb->data; - sta = sta_info_get(local, hdr->addr1); + sta = sta_info_get(sdata, hdr->addr1); ret = __ieee80211_tx(local, &skb, sta, true); if (ret != IEEE80211_TX_OK) -- cgit v1.2.3 From 47846c9b0c10808d9337d2e7d09361f3e0a0a71a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Nov 2009 17:46:19 +0100 Subject: mac80211: reduce reliance on netdev For bluetooth 3, we will most likely not have a netdev for a virtual interface (sdata), so prepare for that by reducing the reliance on having a netdev. This patch moves the name and address fields into the sdata struct and uses them from there all over. Some work is needed to keep them sync'ed, but that's not a lot of work and in slow paths anyway. In doing so, this also reduces the number of pointer dereferences in many places, because of things like sdata->dev->dev_addr becoming sdata->vif.addr. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 ++ net/mac80211/agg-rx.c | 6 ++--- net/mac80211/agg-tx.c | 14 +++++----- net/mac80211/cfg.c | 2 +- net/mac80211/debugfs_key.c | 2 +- net/mac80211/debugfs_netdev.c | 55 ++++---------------------------------- net/mac80211/debugfs_netdev.h | 9 +++---- net/mac80211/debugfs_sta.c | 2 +- net/mac80211/driver-ops.h | 4 +-- net/mac80211/driver-trace.h | 12 ++++----- net/mac80211/ht.c | 6 ++--- net/mac80211/ibss.c | 32 +++++++++++----------- net/mac80211/ieee80211_i.h | 5 +++- net/mac80211/iface.c | 62 ++++++++++++++++++++++++++++++++++++++++--- net/mac80211/main.c | 17 ++++++++---- net/mac80211/mesh.c | 4 +-- net/mac80211/mesh_hwmp.c | 18 ++++++------- net/mac80211/mesh_pathtbl.c | 6 ++--- net/mac80211/mesh_plink.c | 2 +- net/mac80211/mlme.c | 62 +++++++++++++++++++++---------------------- net/mac80211/pm.c | 2 +- net/mac80211/rx.c | 43 +++++++++++++++--------------- net/mac80211/scan.c | 2 +- net/mac80211/spectmgmt.c | 4 +-- net/mac80211/sta_info.c | 8 +++--- net/mac80211/status.c | 2 +- net/mac80211/tx.c | 33 +++++++++++------------ net/mac80211/util.c | 14 +++++----- 28 files changed, 223 insertions(+), 207 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2aff4906b2ae..e94cc526b0f6 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -659,12 +659,14 @@ struct ieee80211_conf { * @type: type of this virtual interface * @bss_conf: BSS configuration for this interface, either our own * or the BSS we're associated to + * @addr: address of this interface * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *). */ struct ieee80211_vif { enum nl80211_iftype type; struct ieee80211_bss_conf bss_conf; + u8 addr[ETH_ALEN]; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); }; diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index f16d49d474b4..37ecdeddd5ac 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -135,7 +135,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", sdata->dev->name); + "for addba resp frame\n", sdata->name); return; } @@ -143,10 +143,10 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b05de532c379..209be60564ce 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -58,17 +58,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for addba request frame\n", sdata->dev->name); + "for addba request frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); @@ -104,7 +104,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "bar frame\n", sdata->dev->name); + "bar frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -113,7 +113,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); memcpy(bar->ra, ra, ETH_ALEN); - memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); + memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; bar_control |= (u16)(tid << 12); @@ -489,7 +489,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_WARNING "%s: Not enough memory, " - "dropping start BA session", skb->dev->name); + "dropping start BA session", sdata->name); #endif return; } @@ -621,7 +621,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_WARNING "%s: Not enough memory, " - "dropping stop BA session", skb->dev->name); + "dropping stop BA session", sdata->name); #endif return; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 14e1f4015a72..fcfa1bf776a7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -729,7 +729,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, } else sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (compare_ether_addr(mac, dev->dev_addr) == 0) + if (compare_ether_addr(mac, sdata->vif.addr) == 0) return -EINVAL; if (is_multicast_ether_addr(mac)) diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index e0f5224630da..d12e743cb4e1 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -56,7 +56,7 @@ KEY_CONF_FILE(keyidx, D); KEY_CONF_FILE(hw_key_idx, D); KEY_FILE(flags, X); KEY_FILE(tx_rx_count, D); -KEY_READ(ifindex, sdata->dev->ifindex, 20, "%d\n"); +KEY_READ(ifindex, sdata->name, IFNAMSIZ + 2, "%s\n"); KEY_OPS(ifindex); static ssize_t key_algorithm_read(struct file *file, diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 472b2039906c..5d9c797635a9 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -280,16 +280,11 @@ static void add_files(struct ieee80211_sub_if_data *sdata) } } -static int notif_registered; - void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) { char buf[10+IFNAMSIZ]; - if (!notif_registered) - return; - - sprintf(buf, "netdev:%s", sdata->dev->name); + sprintf(buf, "netdev:%s", sdata->name); sdata->debugfs.dir = debugfs_create_dir(buf, sdata->local->hw.wiphy->debugfsdir); add_files(sdata); @@ -304,58 +299,18 @@ void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) sdata->debugfs.dir = NULL; } -static int netdev_notify(struct notifier_block *nb, - unsigned long state, - void *ndev) +void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata) { - struct net_device *dev = ndev; struct dentry *dir; - struct ieee80211_sub_if_data *sdata; - char buf[10+IFNAMSIZ]; - - if (state != NETDEV_CHANGENAME) - return 0; - - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) - return 0; - - if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) - return 0; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); + char buf[10 + IFNAMSIZ]; dir = sdata->debugfs.dir; if (!dir) - return 0; + return; - sprintf(buf, "netdev:%s", dev->name); + sprintf(buf, "netdev:%s", sdata->name); if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " "dir to %s\n", buf); - - return 0; -} - -static struct notifier_block mac80211_debugfs_netdev_notifier = { - .notifier_call = netdev_notify, -}; - -void ieee80211_debugfs_netdev_init(void) -{ - int err; - - err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier); - if (err) { - printk(KERN_ERR - "mac80211: failed to install netdev notifier," - " disabling per-netdev debugfs!\n"); - } else - notif_registered = 1; -} - -void ieee80211_debugfs_netdev_exit(void) -{ - unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier); - notif_registered = 0; } diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h index 7af731f0b731..79025e79f4d6 100644 --- a/net/mac80211/debugfs_netdev.h +++ b/net/mac80211/debugfs_netdev.h @@ -6,8 +6,7 @@ #ifdef CONFIG_MAC80211_DEBUGFS void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); -void ieee80211_debugfs_netdev_init(void); -void ieee80211_debugfs_netdev_exit(void); +void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata); #else static inline void ieee80211_debugfs_add_netdev( struct ieee80211_sub_if_data *sdata) @@ -15,10 +14,8 @@ static inline void ieee80211_debugfs_add_netdev( static inline void ieee80211_debugfs_remove_netdev( struct ieee80211_sub_if_data *sdata) {} -static inline void ieee80211_debugfs_netdev_init(void) -{} - -static inline void ieee80211_debugfs_netdev_exit(void) +static inline void ieee80211_debugfs_rename_netdev( + struct ieee80211_sub_if_data *sdata) {} #endif diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 3f41608c8081..374ff6f98a9c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -44,7 +44,7 @@ static const struct file_operations sta_ ##name## _ops = { \ STA_OPS(name) STA_FILE(aid, sta.aid, D); -STA_FILE(dev, sdata->dev->name, S); +STA_FILE(dev, sdata->name, S); STA_FILE(rx_packets, rx_packets, LU); STA_FILE(tx_packets, tx_packets, LU); STA_FILE(rx_bytes, rx_bytes, LU); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 921dd9c9ff62..a4002657dac5 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -39,7 +39,7 @@ static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { int ret = local->ops->add_interface(&local->hw, conf); - trace_drv_add_interface(local, conf->mac_addr, conf->vif, ret); + trace_drv_add_interface(local, conf->vif, ret); return ret; } @@ -47,7 +47,7 @@ static inline void drv_remove_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { local->ops->remove_interface(&local->hw, conf); - trace_drv_remove_interface(local, conf->mac_addr, conf->vif); + trace_drv_remove_interface(local, conf->vif); } static inline int drv_config(struct ieee80211_local *local, u32 changed) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index ee94ea0c67e9..7b155b947209 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -70,11 +70,10 @@ TRACE_EVENT(drv_stop, TRACE_EVENT(drv_add_interface, TP_PROTO(struct ieee80211_local *local, - const u8 *addr, struct ieee80211_vif *vif, int ret), - TP_ARGS(local, addr, vif, ret), + TP_ARGS(local, vif, ret), TP_STRUCT__entry( LOCAL_ENTRY @@ -86,7 +85,7 @@ TRACE_EVENT(drv_add_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, addr, 6); + memcpy(__entry->addr, vif->addr, 6); __entry->ret = ret; ), @@ -97,10 +96,9 @@ TRACE_EVENT(drv_add_interface, ); TRACE_EVENT(drv_remove_interface, - TP_PROTO(struct ieee80211_local *local, - const u8 *addr, struct ieee80211_vif *vif), + TP_PROTO(struct ieee80211_local *local, struct ieee80211_vif *vif), - TP_ARGS(local, addr, vif), + TP_ARGS(local, vif), TP_STRUCT__entry( LOCAL_ENTRY @@ -111,7 +109,7 @@ TRACE_EVENT(drv_remove_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, addr, 6); + memcpy(__entry->addr, vif->addr, 6); ), TP_printk( diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 3787455fb696..45ebd062a2fb 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -106,7 +106,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for delba frame\n", sdata->dev->name); + "for delba frame\n", sdata->name); return; } @@ -114,10 +114,10 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 1925be9b82fb..ef6c6b2401d1 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -117,7 +117,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); mgmt->u.beacon.timestamp = cpu_to_le64(tsf); @@ -266,7 +266,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: updated supp_rates set " "for %pM based on beacon info (0x%llx | " "0x%llx -> 0x%llx)\n", - sdata->dev->name, + sdata->name, sta->sta.addr, (unsigned long long) prev_rates, (unsigned long long) supp_rates, @@ -364,7 +364,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: beacon TSF higher than " "local TSF - IBSS merge with BSSID %pM\n", - sdata->dev->name, mgmt->bssid); + sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); @@ -393,7 +393,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { if (net_ratelimit()) printk(KERN_DEBUG "%s: No room for a new IBSS STA entry %pM\n", - sdata->dev->name, addr); + sdata->name, addr); return NULL; } @@ -402,7 +402,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", - wiphy_name(local->hw.wiphy), addr, sdata->dev->name); + wiphy_name(local->hw.wiphy), addr, sdata->name); #endif sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); @@ -466,7 +466,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " - "IBSS networks with same SSID (merge)\n", sdata->dev->name); + "IBSS networks with same SSID (merge)\n", sdata->name); ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); } @@ -488,13 +488,13 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) * random number generator get different BSSID. */ get_random_bytes(bssid, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= sdata->dev->dev_addr[i]; + bssid[i] ^= sdata->vif.addr[i]; bssid[0] &= ~0x01; bssid[0] |= 0x02; } printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", - sdata->dev->name, bssid); + sdata->name, bssid); sband = local->hw.wiphy->bands[ifibss->channel->band]; @@ -523,7 +523,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", - sdata->dev->name, active_ibss); + sdata->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ if (active_ibss) @@ -552,7 +552,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" " based on configured SSID\n", - sdata->dev->name, bss->cbss.bssid); + sdata->name, bss->cbss.bssid); ieee80211_sta_join_ibss(sdata, bss); ieee80211_rx_bss_put(local, bss); @@ -571,7 +571,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) } else if (time_after(jiffies, ifibss->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " - "join\n", sdata->dev->name); + "join\n", sdata->name); ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); @@ -585,7 +585,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) return; } printk(KERN_DEBUG "%s: IBSS not allowed on" - " %d MHz\n", sdata->dev->name, + " %d MHz\n", sdata->name, local->hw.conf.channel->center_freq); /* No IBSS found - decrease scan interval and continue @@ -619,7 +619,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" " (tx_last_beacon=%d)\n", - sdata->dev->name, mgmt->sa, mgmt->da, + sdata->name, mgmt->sa, mgmt->da, mgmt->bssid, tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ @@ -637,7 +637,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " "from %pM\n", - sdata->dev->name, mgmt->sa); + sdata->name, mgmt->sa); #endif return; } @@ -657,7 +657,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, memcpy(resp->da, mgmt->sa, ETH_ALEN); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", - sdata->dev->name, resp->da); + sdata->name, resp->da); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); @@ -671,7 +671,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, size_t baselen; struct ieee802_11_elems elems; - if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 419f186cfcf0..178e329f9257 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -140,7 +140,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; struct ieee80211_tx_data { struct sk_buff *skb; - struct net_device *dev; struct ieee80211_local *local; struct ieee80211_sub_if_data *sdata; struct sta_info *sta; @@ -433,6 +432,8 @@ struct ieee80211_sub_if_data { int drop_unencrypted; + char name[IFNAMSIZ]; + /* * keep track of whether the HT opmode (stored in * vif.bss_info.ht_operation_mode) is valid. @@ -937,6 +938,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss); /* interface handling */ +int ieee80211_iface_init(void); +void ieee80211_iface_exit(void); int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct net_device **new_dev, enum nl80211_iftype type, struct vif_params *params); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 80c16f6e2af6..a6e6da3cab70 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -60,6 +60,22 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static int ieee80211_change_mac(struct net_device *dev, void *addr) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + int ret; + + if (netif_running(dev)) + return -EBUSY; + + ret = eth_mac_addr(dev, addr); + + if (ret == 0) + memcpy(sdata->vif.addr, addr, ETH_ALEN); + + return ret; +} + static inline int identical_mac_addr_allowed(int type1, int type2) { return type1 == NL80211_IFTYPE_MONITOR || @@ -234,7 +250,7 @@ static int ieee80211_open(struct net_device *dev) default: conf.vif = &sdata->vif; conf.type = sdata->vif.type; - conf.mac_addr = dev->dev_addr; + conf.mac_addr = sdata->vif.addr; res = drv_add_interface(local, &conf); if (res) goto err_stop; @@ -514,7 +530,7 @@ static int ieee80211_stop(struct net_device *dev) conf.vif = &sdata->vif; conf.type = sdata->vif.type; - conf.mac_addr = dev->dev_addr; + conf.mac_addr = sdata->vif.addr; /* disable all keys for as long as this netdev is down */ ieee80211_disable_keys(sdata); drv_remove_interface(local, &conf); @@ -651,7 +667,7 @@ static const struct net_device_ops ieee80211_dataif_ops = { .ndo_start_xmit = ieee80211_subif_start_xmit, .ndo_set_multicast_list = ieee80211_set_multicast_list, .ndo_change_mtu = ieee80211_change_mtu, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = ieee80211_change_mac, }; static const struct net_device_ops ieee80211_monitorif_ops = { @@ -794,6 +810,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ sdata = netdev_priv(ndev); ndev->ieee80211_ptr = &sdata->wdev; + memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); + memcpy(sdata->name, ndev->name, IFNAMSIZ); /* initialise type-independent data */ sdata->wdev.wiphy = local->hw.wiphy; @@ -945,3 +963,41 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) if (chg) ieee80211_hw_config(local, chg); } + +static int netdev_notify(struct notifier_block *nb, + unsigned long state, + void *ndev) +{ + struct net_device *dev = ndev; + struct ieee80211_sub_if_data *sdata; + + if (state != NETDEV_CHANGENAME) + return 0; + + if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) + return 0; + + if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) + return 0; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + memcpy(sdata->name, sdata->name, IFNAMSIZ); + + ieee80211_debugfs_rename_netdev(sdata); + return 0; +} + +static struct notifier_block mac80211_netdev_notifier = { + .notifier_call = netdev_notify, +}; + +int ieee80211_iface_init(void) +{ + return register_netdevice_notifier(&mac80211_netdev_notifier); +} + +void ieee80211_iface_exit(void) +{ + unregister_netdevice_notifier(&mac80211_netdev_notifier); +} diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 8116d1a96a4a..dbf05b4dd003 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -32,7 +32,6 @@ #include "led.h" #include "cfg.h" #include "debugfs.h" -#include "debugfs_netdev.h" void ieee80211_configure_filter(struct ieee80211_local *local) { @@ -173,7 +172,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; else if (sdata->vif.type == NL80211_IFTYPE_AP) - sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; + sdata->vif.bss_conf.bssid = sdata->vif.addr; else if (ieee80211_vif_is_mesh(&sdata->vif)) { sdata->vif.bss_conf.bssid = zero; } else { @@ -672,11 +671,19 @@ static int __init ieee80211_init(void) ret = rc80211_pid_init(); if (ret) - return ret; + goto err_pid; - ieee80211_debugfs_netdev_init(); + ret = ieee80211_iface_init(); + if (ret) + goto err_netdev; return 0; + err_netdev: + rc80211_pid_exit(); + err_pid: + rc80211_minstrel_exit(); + + return ret; } static void __exit ieee80211_exit(void) @@ -693,7 +700,7 @@ static void __exit ieee80211_exit(void) if (mesh_allocated) ieee80211s_stop(); - ieee80211_debugfs_netdev_exit(); + ieee80211_iface_exit(); } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c0fe46493f71..63299b72a7b0 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -457,7 +457,7 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: running mesh housekeeping\n", - sdata->dev->name); + sdata->name); #endif ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); @@ -565,7 +565,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, /* ignore ProbeResp to foreign address */ if (stype == IEEE80211_STYPE_PROBE_RESP && - compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) + compare_ether_addr(mgmt->da, sdata->vif.addr)) return; baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index b836892f0ba9..664f5cc2b273 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -128,9 +128,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID == SA */ - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; @@ -222,7 +222,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, IEEE80211_STYPE_ACTION); memcpy(mgmt->da, ra, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; @@ -374,7 +374,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, new_metric = MAX_METRIC; exp_time = TU_TO_EXP_TIME(orig_lifetime); - if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) { /* This MP is the originator, we are not interested in this * frame, except for updating transmitter's path info. */ @@ -486,7 +486,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, mhwmp_dbg("received PREQ from %pM\n", orig_addr); - if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { + if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { mhwmp_dbg("PREQ is for us\n"); forward = false; reply = true; @@ -579,7 +579,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, * replies */ target_addr = PREP_IE_TARGET_ADDR(prep_elem); - if (memcmp(target_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) /* destination, no forwarding required */ return; @@ -890,7 +890,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) target_flags = MP_F_RF; spin_unlock_bh(&mpath->state_lock); - mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, + mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->vif.addr, cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, cpu_to_le32(mpath->sn), broadcast_addr, 0, ttl, cpu_to_le32(lifetime), 0, @@ -939,7 +939,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (time_after(jiffies, mpath->exp_time + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && - !memcmp(sdata->dev->dev_addr, hdr->addr4, ETH_ALEN) && + !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && !(mpath->flags & MESH_PATH_RESOLVING) && !(mpath->flags & MESH_PATH_FIXED)) { mesh_queue_preq(mpath, @@ -1010,7 +1010,7 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, + mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, cpu_to_le32(++ifmsh->sn), 0, NULL, 0, broadcast_addr, 0, MESH_TTL, 0, 0, 0, sdata); diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index a8da23905c70..fbef678f64c8 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -260,7 +260,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) int err = 0; u32 hash_idx; - if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) /* never add ourselves as neighbours */ return -ENOTSUPP; @@ -377,7 +377,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) int err = 0; u32 hash_idx; - if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) + if (memcmp(dst, sdata->vif.addr, ETH_ALEN) == 0) /* never add ourselves as neighbours */ return -ENOTSUPP; @@ -605,7 +605,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct mesh_path *mpath; u32 sn = 0; - if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { + if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { u8 *ra, *da; da = hdr->addr3; diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 8fcf56ee7743..7985e5150898 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -169,7 +169,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ mgmt->u.action.category = MESH_PLINK_CATEGORY; mgmt->u.action.u.plink_action.action_code = action; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c16667a7c8df..cd5dcc3d8c2b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -248,7 +248,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, wk->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", sdata->dev->name); + "frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -282,7 +282,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); if (!is_zero_ether_addr(wk->prev_bssid)) { @@ -443,7 +443,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for " - "deauth/disassoc frame\n", sdata->dev->name); + "deauth/disassoc frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -451,7 +451,7 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); skb_put(skb, 2); @@ -484,7 +484,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for " - "pspoll frame\n", sdata->dev->name); + "pspoll frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -499,7 +499,7 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); - memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); + memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); @@ -519,7 +519,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " - "frame\n", sdata->dev->name); + "frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -532,7 +532,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, fc |= cpu_to_le16(IEEE80211_FCTL_PM); nullfunc->frame_control = fc; memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; @@ -948,7 +948,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, wk->tries++; if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", - sdata->dev->name, wk->bss->cbss.bssid); + sdata->name, wk->bss->cbss.bssid); /* * Most likely AP is not in the range so remove the @@ -966,7 +966,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", - sdata->dev->name, wk->bss->cbss.bssid, + sdata->name, wk->bss->cbss.bssid, wk->tries); /* @@ -993,7 +993,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with AP %pM" " timed out\n", - sdata->dev->name, wk->bss->cbss.bssid); + sdata->name, wk->bss->cbss.bssid); /* * Most likely AP is not in the range so remove the @@ -1011,7 +1011,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", - sdata->dev->name, wk->bss->cbss.bssid, wk->tries); + sdata->name, wk->bss->cbss.bssid, wk->tries); ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, wk->bss->cbss.bssid, NULL, 0, 0); @@ -1133,7 +1133,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with AP %pM" " timed out\n", - sdata->dev->name, wk->bss->cbss.bssid); + sdata->name, wk->bss->cbss.bssid); /* * Most likely AP is not in the range so remove the @@ -1151,7 +1151,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", - sdata->dev->name, wk->bss->cbss.bssid, wk->tries); + sdata->name, wk->bss->cbss.bssid, wk->tries); ieee80211_send_assoc(sdata, wk); wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; @@ -1212,7 +1212,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (beacon && net_ratelimit()) printk(KERN_DEBUG "%s: detected beacon loss from AP " - "- sending probe request\n", sdata->dev->name); + "- sending probe request\n", sdata->name); #endif /* @@ -1269,7 +1269,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgd_work *wk) { wk->state = IEEE80211_MGD_STATE_IDLE; - printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); + printk(KERN_DEBUG "%s: authenticated\n", sdata->name); } @@ -1366,7 +1366,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", - sdata->dev->name, bssid, reason_code); + sdata->name, bssid, reason_code); if (!wk) { ieee80211_set_disassoc(sdata, true); @@ -1400,7 +1400,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", - sdata->dev->name, mgmt->sa, reason_code); + sdata->name, mgmt->sa, reason_code); ieee80211_set_disassoc(sdata, false); return RX_MGMT_CFG80211_DISASSOC; @@ -1444,7 +1444,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " "status=%d aid=%d)\n", - sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, + sdata->name, reassoc ? "Rea" : "A", mgmt->sa, capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); pos = mgmt->u.assoc_resp.variable; @@ -1458,7 +1458,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ms = tu * 1024 / 1000; printk(KERN_DEBUG "%s: AP rejected association temporarily; " "comeback duration %u TU (%u ms)\n", - sdata->dev->name, tu, ms); + sdata->name, tu, ms); wk->timeout = jiffies + msecs_to_jiffies(ms); if (ms > IEEE80211_ASSOC_TIMEOUT) run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); @@ -1467,23 +1467,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - sdata->dev->name, status_code); + sdata->name, status_code); wk->state = IEEE80211_MGD_STATE_IDLE; return RX_MGMT_CFG80211_ASSOC; } if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", sdata->dev->name, aid); + "set\n", sdata->name, aid); aid &= ~(BIT(15) | BIT(14)); if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", - sdata->dev->name); + sdata->name); return RX_MGMT_NONE; } - printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); + printk(KERN_DEBUG "%s: associated\n", sdata->name); ifmgd->aid = aid; rcu_read_lock(); @@ -1498,7 +1498,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", sdata->dev->name); + " the AP\n", sdata->name); return RX_MGMT_NONE; } @@ -1576,7 +1576,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, int err = sta_info_insert(sta); if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", sdata->dev->name, err); + " the AP (error %d)\n", sdata->name, err); rcu_read_unlock(); return RX_MGMT_NONE; } @@ -1671,7 +1671,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ASSERT_MGD_MTX(ifmgd); - if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) return; /* ignore ProbeResp to foreign address */ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; @@ -1686,7 +1686,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, /* direct probe may be part of the association flow */ if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { printk(KERN_DEBUG "%s: direct probe responded\n", - sdata->dev->name); + sdata->name); wk->tries = 0; wk->state = IEEE80211_MGD_STATE_AUTH; WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); @@ -1779,7 +1779,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) { printk(KERN_DEBUG "%s: cancelling probereq poll due " - "to a received beacon\n", sdata->dev->name); + "to a received beacon\n", sdata->name); } #endif ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; @@ -2554,7 +2554,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", - sdata->dev->name, bssid, req->reason_code); + sdata->name, bssid, req->reason_code); ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, req->reason_code, @@ -2583,7 +2583,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", - sdata->dev->name, req->bss->bssid, req->reason_code); + sdata->name, req->bss->bssid, req->reason_code); ieee80211_set_disassoc(sdata, false); diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index e535f1c988fe..05ccaadb6a0e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -102,7 +102,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) conf.vif = &sdata->vif; conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; + conf.mac_addr = sdata->vif.addr; drv_remove_interface(local, &conf); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5bae28693da8..d0136e3da487 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -283,15 +283,15 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, skb->protocol = htons(ETH_P_802_2); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) - continue; - if (sdata->vif.type != NL80211_IFTYPE_MONITOR) continue; if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) continue; + if (!netif_running(sdata->dev)) + continue; + if (prev_dev) { skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { @@ -476,7 +476,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); - char *dev_addr = rx->sdata->dev->dev_addr; + char *dev_addr = rx->sdata->vif.addr; if (ieee80211_is_data(hdr->frame_control)) { if (is_multicast_ether_addr(hdr->addr1)) { @@ -1024,7 +1024,7 @@ static void ap_sta_ps_start(struct sta_info *sta) drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", - sdata->dev->name, sta->sta.addr, sta->sta.aid); + sdata->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -1038,13 +1038,13 @@ static void ap_sta_ps_end(struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n", - sdata->dev->name, sta->sta.addr, sta->sta.aid); + sdata->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) { #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n", - sdata->dev->name, sta->sta.addr, sta->sta.aid); + sdata->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ return; } @@ -1156,7 +1156,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: RX reassembly removed oldest " "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " "addr1=%pM addr2=%pM\n", - sdata->dev->name, idx, + sdata->name, idx, jiffies - entry->first_frag_time, entry->seq, entry->last_frag, hdr->addr1, hdr->addr2); #endif @@ -1424,7 +1424,6 @@ static int __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; - struct net_device *dev = sdata->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; if (ieee80211_has_a4(hdr->frame_control) && @@ -1436,7 +1435,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) return -1; - return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); + return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); } /* @@ -1453,7 +1452,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) * of whether the frame was encrypted or not. */ if (ehdr->h_proto == htons(ETH_P_PAE) && - (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 || + (compare_ether_addr(ehdr->h_dest, rx->sdata->vif.addr) == 0 || compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) return true; @@ -1721,7 +1720,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) /* Frame has reached destination. Don't forward */ if (!is_multicast_ether_addr(hdr->addr1) && - compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0) + compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) return RX_CONTINUE; mesh_hdr->ttl--; @@ -1738,10 +1737,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (!fwd_skb && net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone mesh frame\n", - sdata->dev->name); + sdata->name); fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; - memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); info = IEEE80211_SKB_CB(fwd_skb); memset(info, 0, sizeof(*info)); info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; @@ -1870,7 +1869,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb; struct ieee80211_mgmt *resp; - if (compare_ether_addr(mgmt->da, sdata->dev->dev_addr) != 0) { + if (compare_ether_addr(mgmt->da, sdata->vif.addr) != 0) { /* Not to own unicast address */ return; } @@ -1894,7 +1893,7 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, resp = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(resp, 0, 24); memcpy(resp->da, mgmt->sa, ETH_ALEN); - memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(resp->sa, sdata->vif.addr, ETH_ALEN); memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); @@ -2274,7 +2273,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, if (!bssid && !sdata->u.mgd.use_4addr) return 0; if (!multicast && - compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { + compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { if (!(sdata->dev->flags & IFF_PROMISC)) return 0; rx->flags &= ~IEEE80211_RX_RA_MATCH; @@ -2291,7 +2290,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; rx->flags &= ~IEEE80211_RX_RA_MATCH; } else if (!multicast && - compare_ether_addr(sdata->dev->dev_addr, + compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { if (!(sdata->dev->flags & IFF_PROMISC)) return 0; @@ -2308,7 +2307,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, break; case NL80211_IFTYPE_MESH_POINT: if (!multicast && - compare_ether_addr(sdata->dev->dev_addr, + compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { if (!(sdata->dev->flags & IFF_PROMISC)) return 0; @@ -2319,11 +2318,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP: if (!bssid) { - if (compare_ether_addr(sdata->dev->dev_addr, + if (compare_ether_addr(sdata->vif.addr, hdr->addr1)) return 0; } else if (!ieee80211_bssid_match(bssid, - sdata->dev->dev_addr)) { + sdata->vif.addr)) { if (!(rx->flags & IEEE80211_RX_IN_SCAN)) return 0; rx->flags &= ~IEEE80211_RX_RA_MATCH; @@ -2444,7 +2443,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, printk(KERN_DEBUG "%s: failed to copy " "multicast frame for %s\n", wiphy_name(local->hw.wiphy), - prev->dev->name); + prev->name); continue; } ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 4cf387c944bf..d3381ba5f457 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -147,7 +147,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) presp = ieee80211_is_probe_resp(fc); if (presp) { /* ignore ProbeResp to foreign address */ - if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + if (memcmp(mgmt->da, sdata->vif.addr, ETH_ALEN)) return RX_DROP_MONITOR; presp = true; diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index aa743a895cf9..7733f66ee2c4 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c @@ -35,7 +35,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", sdata->dev->name); + "measurement report frame\n", sdata->name); return; } @@ -43,7 +43,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); memset(msr_report, 0, 24); memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN); memcpy(msr_report->bssid, bssid, ETH_ALEN); msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c58a23eea58c..294f1b8b1545 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -372,7 +372,7 @@ int sta_info_insert(struct sta_info *sta) goto out_free; } - if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || + if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || is_multicast_ether_addr(sta->sta.addr))) { err = -EINVAL; goto out_free; @@ -831,7 +831,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", - sdata->dev->name, sta->sta.addr); + sdata->name, sta->sta.addr); #endif __sta_info_unlink(&sta); if (sta) @@ -889,7 +889,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " - "since STA not sleeping anymore\n", sdata->dev->name, + "since STA not sleeping anymore\n", sdata->name, sta->sta.addr, sta->sta.aid, sent - buffered, buffered); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -948,7 +948,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) */ printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " "though there are no buffered frames for it\n", - sdata->dev->name, sta->sta.addr); + sdata->name, sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 32fe327acf4e..b4608f11a40f 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -168,7 +168,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) for_each_sta_info(local, hdr->addr1, sta, tmp) { /* skip wrong virtual interface */ - if (memcmp(hdr->addr2, sta->sdata->dev->dev_addr, ETH_ALEN)) + if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) continue; if (!(info->flags & IEEE80211_TX_STAT_ACK) && diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b913bfc34a9f..ac48c86ae6b3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -223,7 +223,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: dropped data frame to not " "associated station %pM\n", - tx->dev->name, hdr->addr1); + tx->sdata->name, hdr->addr1); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); return TX_DROP; @@ -331,7 +331,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG if (net_ratelimit()) printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n", - tx->dev->name); + tx->sdata->name); #endif dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); } else @@ -391,7 +391,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) if (net_ratelimit()) { printk(KERN_DEBUG "%s: STA %pM TX " "buffer full - dropping oldest frame\n", - tx->dev->name, sta->sta.addr); + tx->sdata->name, sta->sta.addr); } #endif dev_kfree_skb(old); @@ -416,7 +416,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG else if (unlikely(staflags & WLAN_STA_PS_STA)) { printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " - "set -> send frame\n", tx->dev->name, + "set -> send frame\n", tx->sdata->name, sta->sta.addr); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ @@ -549,7 +549,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) "%s: Dropped data frame as no usable bitrate found while " "scanning and associated. Target station: " "%pM on %d GHz band\n", - tx->dev->name, hdr->addr1, + tx->sdata->name, hdr->addr1, tx->channel->band ? 5 : 2)) return TX_DROP; @@ -1021,7 +1021,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, memset(tx, 0, sizeof(*tx)); tx->skb = skb; - tx->dev = sdata->dev; /* use original interface */ tx->local = local; tx->sdata = sdata; tx->channel = local->hw.conf.channel; @@ -1474,7 +1473,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, continue; if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) continue; - if (compare_ether_addr(tmp_sdata->dev->dev_addr, + if (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) { sdata = tmp_sdata; break; @@ -1638,7 +1637,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 30; @@ -1652,7 +1651,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); /* DA BSSID SA */ memcpy(hdr.addr1, skb->data, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 24; break; @@ -1660,7 +1659,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 30; @@ -1674,8 +1673,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } - if (compare_ether_addr(dev->dev_addr, - skb->data + ETH_ALEN) == 0) { + if (compare_ether_addr(sdata->vif.addr, + skb->data + ETH_ALEN) == 0) { hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, skb->data, skb->data + ETH_ALEN); meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, @@ -1705,7 +1704,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, } } hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, - mesh_da, dev->dev_addr); + mesh_da, sdata->vif.addr); rcu_read_unlock(); if (is_mesh_mcast) meshhdrlen = @@ -1730,7 +1729,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); /* RA TA DA SA */ - memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); + memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr.addr3, skb->data, ETH_ALEN); memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); hdrlen = 30; @@ -1781,7 +1780,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, unlikely(!is_multicast_ether_addr(hdr.addr1) && !(sta_flags & WLAN_STA_AUTHORIZED) && !(ethertype == ETH_P_PAE && - compare_ether_addr(dev->dev_addr, + compare_ether_addr(sdata->vif.addr, skb->data + ETH_ALEN) == 0))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) @@ -2145,8 +2144,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(sdata->vif.bss_conf.beacon_int); mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d09f78bb2442..d45760eae6c7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -469,7 +469,7 @@ void ieee80211_iterate_active_interfaces( break; } if (netif_running(sdata->dev)) - iterator(data, sdata->dev->dev_addr, + iterator(data, sdata->vif.addr, &sdata->vif); } @@ -503,7 +503,7 @@ void ieee80211_iterate_active_interfaces_atomic( break; } if (netif_running(sdata->dev)) - iterator(data, sdata->dev->dev_addr, + iterator(data, sdata->vif.addr, &sdata->vif); } @@ -848,7 +848,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", sdata->dev->name); + "frame\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -858,7 +858,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); memcpy(mgmt->da, bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, bssid, ETH_ALEN); mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); @@ -949,7 +949,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ie_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", sdata->dev->name); + "request\n", sdata->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -958,7 +958,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, memset(mgmt, 0, 24); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); if (dst) { memcpy(mgmt->da, dst, ETH_ALEN); memcpy(mgmt->bssid, dst, ETH_ALEN); @@ -1051,7 +1051,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) netif_running(sdata->dev)) { conf.vif = &sdata->vif; conf.type = sdata->vif.type; - conf.mac_addr = sdata->dev->dev_addr; + conf.mac_addr = sdata->vif.addr; res = drv_add_interface(local, &conf); } } -- cgit v1.2.3 From 12375ef933fa8271396ed0c1e318cb1bd2e2689d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 25 Nov 2009 20:30:31 +0100 Subject: mac80211: trace interface name It's not all that useful to have the vif/sdata pointer, we'd rather refer to the interfaces by their name. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-rx.c | 6 ++---- net/mac80211/agg-tx.c | 7 +++---- net/mac80211/driver-ops.h | 29 +++++++++++++++-------------- net/mac80211/driver-trace.h | 38 ++++++++++++++++++++------------------ net/mac80211/key.c | 4 ++-- net/mac80211/main.c | 3 +-- net/mac80211/pm.c | 2 +- net/mac80211/rx.c | 2 +- net/mac80211/sta_info.c | 6 +++--- net/mac80211/util.c | 2 +- 10 files changed, 49 insertions(+), 50 deletions(-) diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 37ecdeddd5ac..a978e666ed6f 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -41,8 +41,7 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - if (drv_ampdu_action(local, &sta->sdata->vif, - IEEE80211_AMPDU_RX_STOP, + if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, &sta->sta, tid, NULL)) printk(KERN_DEBUG "HW problem - can not stop rx " "aggregation for tid %d\n", tid); @@ -280,8 +279,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, goto end; } - ret = drv_ampdu_action(local, &sta->sdata->vif, - IEEE80211_AMPDU_RX_START, + ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, &sta->sta, tid, &start_seq_num); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 209be60564ce..ceda36618d3c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -144,7 +144,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); - ret = drv_ampdu_action(local, &sta->sdata->vif, + ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_STOP, &sta->sta, tid, NULL); @@ -303,8 +303,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) start_seq_num = sta->tid_seq[tid]; - ret = drv_ampdu_action(local, &sdata->vif, - IEEE80211_AMPDU_TX_START, + ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, pubsta, tid, &start_seq_num); if (ret) { @@ -420,7 +419,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ieee80211_agg_splice_finish(local, sta, tid); spin_unlock(&local->ampdu_lock); - drv_ampdu_action(local, &sta->sdata->vif, + drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_TX_OPERATIONAL, &sta->sta, tid, NULL); } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index a4002657dac5..727e4cf7b8a6 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -39,7 +39,7 @@ static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { int ret = local->ops->add_interface(&local->hw, conf); - trace_drv_add_interface(local, conf->vif, ret); + trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); return ret; } @@ -47,7 +47,7 @@ static inline void drv_remove_interface(struct ieee80211_local *local, struct ieee80211_if_init_conf *conf) { local->ops->remove_interface(&local->hw, conf); - trace_drv_remove_interface(local, conf->vif); + trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); } static inline int drv_config(struct ieee80211_local *local, u32 changed) @@ -58,13 +58,13 @@ static inline int drv_config(struct ieee80211_local *local, u32 changed) } static inline void drv_bss_info_changed(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *info, u32 changed) { if (local->ops->bss_info_changed) - local->ops->bss_info_changed(&local->hw, vif, info, changed); - trace_drv_bss_info_changed(local, vif, info, changed); + local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); + trace_drv_bss_info_changed(local, sdata, info, changed); } static inline u64 drv_prepare_multicast(struct ieee80211_local *local, @@ -106,12 +106,13 @@ static inline int drv_set_tim(struct ieee80211_local *local, } static inline int drv_set_key(struct ieee80211_local *local, - enum set_key_cmd cmd, struct ieee80211_vif *vif, + enum set_key_cmd cmd, + struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - int ret = local->ops->set_key(&local->hw, cmd, vif, sta, key); - trace_drv_set_key(local, cmd, vif, sta, key, ret); + int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); + trace_drv_set_key(local, cmd, sdata, sta, key, ret); return ret; } @@ -179,13 +180,13 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, } static inline void drv_sta_notify(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { if (local->ops->sta_notify) - local->ops->sta_notify(&local->hw, vif, cmd, sta); - trace_drv_sta_notify(local, vif, cmd, sta); + local->ops->sta_notify(&local->hw, &sdata->vif, cmd, sta); + trace_drv_sta_notify(local, sdata, cmd, sta); } static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, @@ -239,16 +240,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) } static inline int drv_ampdu_action(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn) { int ret = -EOPNOTSUPP; if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, vif, action, + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, sta, tid, ssn); - trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret); + trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, ret); return ret; } diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7b155b947209..ee2d19a25ce1 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -25,10 +25,12 @@ static inline void trace_ ## name(proto) {} #define STA_PR_FMT " sta:%pM" #define STA_PR_ARG __entry->sta_addr -#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, vif) -#define VIF_ASSIGN __entry->vif_type = vif ? vif->type : 0; __entry->vif = vif -#define VIF_PR_FMT " vif:%p(%d)" -#define VIF_PR_ARG __entry->vif, __entry->vif_type +#define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ + __string(vif_name, sdata->dev ? sdata->dev->name : "") +#define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ + __assign_str(vif_name, sdata->dev ? sdata->dev->name : "") +#define VIF_PR_FMT " vif:%s(%d)" +#define VIF_PR_ARG __get_str(vif_name), __entry->vif_type TRACE_EVENT(drv_start, TP_PROTO(struct ieee80211_local *local, int ret), @@ -70,10 +72,10 @@ TRACE_EVENT(drv_stop, TRACE_EVENT(drv_add_interface, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, int ret), - TP_ARGS(local, vif, ret), + TP_ARGS(local, sdata, ret), TP_STRUCT__entry( LOCAL_ENTRY @@ -85,7 +87,7 @@ TRACE_EVENT(drv_add_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, vif->addr, 6); + memcpy(__entry->addr, sdata->vif.addr, 6); __entry->ret = ret; ), @@ -96,9 +98,9 @@ TRACE_EVENT(drv_add_interface, ); TRACE_EVENT(drv_remove_interface, - TP_PROTO(struct ieee80211_local *local, struct ieee80211_vif *vif), + TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), - TP_ARGS(local, vif), + TP_ARGS(local, sdata), TP_STRUCT__entry( LOCAL_ENTRY @@ -109,7 +111,7 @@ TRACE_EVENT(drv_remove_interface, TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - memcpy(__entry->addr, vif->addr, 6); + memcpy(__entry->addr, sdata->vif.addr, 6); ), TP_printk( @@ -163,11 +165,11 @@ TRACE_EVENT(drv_config, TRACE_EVENT(drv_bss_info_changed, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *info, u32 changed), - TP_ARGS(local, vif, info, changed), + TP_ARGS(local, sdata, info, changed), TP_STRUCT__entry( LOCAL_ENTRY @@ -291,11 +293,11 @@ TRACE_EVENT(drv_set_tim, TRACE_EVENT(drv_set_key, TP_PROTO(struct ieee80211_local *local, - enum set_key_cmd cmd, struct ieee80211_vif *vif, + enum set_key_cmd cmd, struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *sta, struct ieee80211_key_conf *key, int ret), - TP_ARGS(local, cmd, vif, sta, key, ret), + TP_ARGS(local, cmd, sdata, sta, key, ret), TP_STRUCT__entry( LOCAL_ENTRY @@ -489,11 +491,11 @@ TRACE_EVENT(drv_set_rts_threshold, TRACE_EVENT(drv_sta_notify, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum sta_notify_cmd cmd, struct ieee80211_sta *sta), - TP_ARGS(local, vif, cmd, sta), + TP_ARGS(local, sdata, cmd, sta), TP_STRUCT__entry( LOCAL_ENTRY @@ -654,12 +656,12 @@ TRACE_EVENT(drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, - struct ieee80211_vif *vif, + struct ieee80211_sub_if_data *sdata, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, int ret), - TP_ARGS(local, vif, action, sta, tid, ssn, ret), + TP_ARGS(local, sdata, action, sta, tid, ssn, ret), TP_STRUCT__entry( LOCAL_ENTRY diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ac1a777674f6..32ee6d0ee34d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -139,7 +139,7 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); + ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf); if (!ret) { spin_lock_bh(&todo_lock); @@ -181,7 +181,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) struct ieee80211_sub_if_data, u.ap); - ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, + ret = drv_set_key(key->local, DISABLE_KEY, sdata, sta, &key->conf); if (ret) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index dbf05b4dd003..98320a94c270 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -222,8 +222,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } } - drv_bss_info_changed(local, &sdata->vif, - &sdata->vif.bss_conf, changed); + drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); } u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 05ccaadb6a0e..05e161c3cbc5 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -65,7 +65,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, &sta->sta); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d0136e3da487..ebab696def5b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1021,7 +1021,7 @@ static void ap_sta_ps_start(struct sta_info *sta) atomic_inc(&sdata->bss->num_sta_ps); set_sta_flags(sta, WLAN_STA_PS_STA); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", sdata->name, sta->sta.addr, sta->sta.aid); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 294f1b8b1545..d1a77e79d7a9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -397,7 +397,7 @@ int sta_info_insert(struct sta_info *sta) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); sdata = sta->sdata; } @@ -537,7 +537,7 @@ static void __sta_info_unlink(struct sta_info **sta) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, + drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, &(*sta)->sta); sdata = (*sta)->sdata; } @@ -876,7 +876,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; int sent, buffered; - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); + drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); if (!skb_queue_empty(&sta->ps_tx_buf)) sta_info_clear_tim_bit(sta); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d45760eae6c7..d54dbe8e09ba 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1066,7 +1066,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, + drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); } spin_unlock_irqrestore(&local->sta_lock, flags); -- cgit v1.2.3 From 411132628f95dd3d51b84e0e2d8ff8f4f2d09cdb Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Wed, 25 Nov 2009 21:00:30 -0500 Subject: ath9k_hw: remove unused ath9k_hw_devname() and ath9k_hw_probe() Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2ec61f08cfdb..917f70f7a28e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -343,30 +343,6 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) return true; } -static const char *ath9k_hw_devname(u16 devid) -{ - switch (devid) { - case AR5416_DEVID_PCI: - return "Atheros 5416"; - case AR5416_DEVID_PCIE: - return "Atheros 5418"; - case AR9160_DEVID_PCI: - return "Atheros 9160"; - case AR5416_AR9100_DEVID: - return "Atheros 9100"; - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - return "Atheros 9280"; - case AR9285_DEVID_PCIE: - return "Atheros 9285"; - case AR5416_DEVID_AR9287_PCI: - case AR5416_DEVID_AR9287_PCIE: - return "Atheros 9287"; - } - - return NULL; -} - static void ath9k_hw_init_config(struct ath_hw *ah) { int i; @@ -1266,12 +1242,6 @@ static void ath9k_hw_init_user_settings(struct ath_hw *ah) ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); } -const char *ath9k_hw_probe(u16 vendorid, u16 devid) -{ - return vendorid == ATHEROS_VENDOR_ID ? - ath9k_hw_devname(devid) : NULL; -} - void ath9k_hw_detach(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -- cgit v1.2.3 From 5e0ec316522e0372b633407c903b88f58859303f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Nov 2009 00:51:54 +0100 Subject: ar9170: remove dead definitions This patch removes dead infrastructure which was meant for an out-of-tree rate control algorithm. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 2 -- drivers/net/wireless/ath/ar9170/main.c | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 9f9459860d82..d95a7d47af04 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -109,7 +109,6 @@ struct ar9170_rxstream_mpdu_merge { bool has_plcp; }; -#define AR9170_NUM_MAX_BA_RETRY 5 #define AR9170_NUM_TID 16 #define WME_BA_BMP_SIZE 64 #define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) @@ -143,7 +142,6 @@ struct ar9170_sta_tid { u16 tid; enum ar9170_tid_state state; bool active; - u8 retry; }; #define AR9170_QUEUE_TIMEOUT 64 diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index f9d6db8d013e..cbf59b1590bf 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2366,7 +2366,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; sta_info->agg[i].active = false; sta_info->agg[i].ssn = 0; - sta_info->agg[i].retry = 0; sta_info->agg[i].tid = i; INIT_LIST_HEAD(&sta_info->agg[i].list); skb_queue_head_init(&sta_info->agg[i].queue); -- cgit v1.2.3 From 53a76b58b66e77164c4a79c38da49b808d67477e Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Nov 2009 00:52:51 +0100 Subject: ar9170: improve network latency AR9170 has the bad habit of choking when traffic builds up. Tests have shown that this can partially be attributed to a huge buildup of backlogged frames. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 2 ++ drivers/net/wireless/ath/ar9170/main.c | 34 +++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index d95a7d47af04..44c54b834a00 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -152,6 +152,8 @@ struct ar9170_sta_tid { #define AR9170_NUM_TX_STATUS 128 #define AR9170_NUM_TX_AGG_MAX 30 +#define AR9170_NUM_TX_LIMIT_HARD AR9170_TXQ_DEPTH +#define AR9170_NUM_TX_LIMIT_SOFT (AR9170_TXQ_DEPTH - 10) struct ar9170 { struct ieee80211_hw *hw; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index cbf59b1590bf..3cec2f16c657 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -430,7 +430,7 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) spin_lock_irqsave(&ar->tx_stats_lock, flags); ar->tx_stats[queue].len--; - if (skb_queue_empty(&ar->tx_pending[queue])) { + if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) { #ifdef AR9170_QUEUE_STOP_DEBUG printk(KERN_DEBUG "%s: wake queue %d\n", wiphy_name(ar->hw->wiphy), queue); @@ -1716,6 +1716,21 @@ static void ar9170_tx(struct ar9170 *ar) for (i = 0; i < __AR9170_NUM_TXQ; i++) { spin_lock_irqsave(&ar->tx_stats_lock, flags); + frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, + skb_queue_len(&ar->tx_pending[i])); + + if (remaining_space < frames) { +#ifdef AR9170_QUEUE_DEBUG + printk(KERN_DEBUG "%s: tx quota reached queue:%d, " + "remaining slots:%d, needed:%d\n", + wiphy_name(ar->hw->wiphy), i, remaining_space, + frames); +#endif /* AR9170_QUEUE_DEBUG */ + frames = remaining_space; + } + + ar->tx_stats[i].len += frames; + ar->tx_stats[i].count += frames; if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { #ifdef AR9170_QUEUE_DEBUG printk(KERN_DEBUG "%s: queue %d full\n", @@ -1733,25 +1748,8 @@ static void ar9170_tx(struct ar9170 *ar) __ar9170_dump_txstats(ar); #endif /* AR9170_QUEUE_STOP_DEBUG */ ieee80211_stop_queue(ar->hw, i); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - continue; - } - - frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, - skb_queue_len(&ar->tx_pending[i])); - - if (remaining_space < frames) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: tx quota reached queue:%d, " - "remaining slots:%d, needed:%d\n", - wiphy_name(ar->hw->wiphy), i, remaining_space, - frames); -#endif /* AR9170_QUEUE_DEBUG */ - frames = remaining_space; } - ar->tx_stats[i].len += frames; - ar->tx_stats[i].count += frames; spin_unlock_irqrestore(&ar->tx_stats_lock, flags); if (!frames) -- cgit v1.2.3 From 15b098bbf79f06a09d3a15b911eb43295979deed Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Nov 2009 00:56:55 +0100 Subject: ar9170: remove redundant frame flags The flags in question were once useful for debugging. Time has passed and now they do nothing more than duplicating txinfo->flags. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 5 --- drivers/net/wireless/ath/ar9170/main.c | 55 +++++++++++++------------------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 44c54b834a00..b99a8c2053d8 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -248,13 +248,8 @@ struct ar9170_sta_info { unsigned int ampdu_max_len; }; -#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) -#define AR9170_TX_FLAG_NO_ACK BIT(1) -#define AR9170_TX_FLAG_BLOCK_ACK BIT(2) - struct ar9170_tx_info { unsigned long timeout; - unsigned int flags; }; #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 3cec2f16c657..d8ecf8554d01 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -213,10 +213,10 @@ static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; struct ieee80211_hdr *hdr = (void *) txc->frame_data; - printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " + printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d " "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), + ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr), le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), jiffies_to_msecs(arinfo->timeout - jiffies)); } @@ -440,22 +440,17 @@ void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) } spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { - ar9170_tx_ampdu_callback(ar, skb); - } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - - skb_queue_tail(&ar->tx_status[queue], skb); - } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { + if (info->flags & IEEE80211_TX_CTL_NO_ACK) { ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); } else { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: unsupported frame flags!\n", - wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - dev_kfree_skb_any(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + ar9170_tx_ampdu_callback(ar, skb); + } else { + arinfo->timeout = jiffies + + msecs_to_jiffies(AR9170_TX_TIMEOUT); + + skb_queue_tail(&ar->tx_status[queue], skb); + } } if (!ar->tx_stats[queue].len && @@ -1407,17 +1402,6 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (unlikely(!info->control.sta)) - goto err_out; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; - - goto out; - } - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); /* * WARNING: * Putting the QoS queue bits into an unexplored territory is @@ -1431,12 +1415,17 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc->phy_control |= cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; - } else { - arinfo->flags = AR9170_TX_FLAG_NO_ACK; + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + if (unlikely(!info->control.sta)) + goto err_out; + + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); + } else { + txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); + } } -out: return 0; err_out: @@ -1771,7 +1760,7 @@ static void ar9170_tx(struct ar9170 *ar) arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_TX_TIMEOUT); - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + if (info->flags & IEEE80211_TX_CTL_AMPDU) atomic_inc(&ar->tx_ampdu_pending); #ifdef AR9170_QUEUE_DEBUG @@ -1782,7 +1771,7 @@ static void ar9170_tx(struct ar9170 *ar) err = ar->tx(ar, skb); if (unlikely(err)) { - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) + if (info->flags & IEEE80211_TX_CTL_AMPDU) atomic_dec(&ar->tx_ampdu_pending); frames_failed++; -- cgit v1.2.3 From 07bc54575b413688d1586407a73793df8f68d115 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Nov 2009 00:59:48 +0100 Subject: ar9170: small misc changes This patch aggregates a bunch of small random changes that won't fit really anywhere else properly. 1. move tid-locating macro into a separate function. 2. remove redundant NULL check. 3. add modulation mask definition Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/hw.h | 1 + drivers/net/wireless/ath/ar9170/main.c | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 701ddb7d8400..0a1d4c28e68a 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h @@ -276,6 +276,7 @@ struct ar9170_tx_control { #define AR9170_TX_MAC_RATE_PROBE 0x8000 /* either-or */ +#define AR9170_TX_PHY_MOD_MASK 0x00000003 #define AR9170_TX_PHY_MOD_CCK 0x00000000 #define AR9170_TX_PHY_MOD_OFDM 0x00000001 #define AR9170_TX_PHY_MOD_HT 0x00000002 diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index d8ecf8554d01..20f04ab2b13e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -194,12 +194,15 @@ static inline u16 ar9170_get_seq(struct sk_buff *skb) return ar9170_get_seq_h((void *) txc->frame_data); } +static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr) +{ + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + static inline u16 ar9170_get_tid(struct sk_buff *skb) { struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; + return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data); } #define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) @@ -1660,8 +1663,7 @@ static bool ar9170_tx_ampdu(struct ar9170 *ar) * tell the FW/HW that this is the last frame, * that way it will wait for the immediate block ack. */ - if (likely(skb_peek_tail(&agg))) - ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); + ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); #ifdef AR9170_TXAGG_DEBUG printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", -- cgit v1.2.3 From 7dffb55b8a73228499ee65a3439f82112f4391c7 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 29 Nov 2009 01:01:14 +0100 Subject: ar9170: fix AC_VIDEO txop parameter This patch fixes a rather embarrassing typo. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index ddc8c09dc79e..857e86104295 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c @@ -117,7 +117,7 @@ int ar9170_set_qos(struct ar9170 *ar) ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, ar->edcf[0].txop | ar->edcf[1].txop << 16); ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, - ar->edcf[1].txop | ar->edcf[3].txop << 16); + ar->edcf[2].txop | ar->edcf[3].txop << 16); ar9170_regwrite_finish(); -- cgit v1.2.3 From b7339b1de0f7b6b8c95a6df87ea2221521328d11 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:17:38 +0200 Subject: wl1251: add tx queue status to debugfs Sometimes when debugging the state is good info. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251.h | 1 + drivers/net/wireless/wl12xx/wl1251_debugfs.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 054533f7a124..6301578d1565 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -247,6 +247,7 @@ struct wl1251_debugfs { struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; struct dentry *tx_queue_len; + struct dentry *tx_queue_status; struct dentry *retry_count; struct dentry *excessive_retries; diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c index a00723059f83..0ccba57fb9fb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1251_debugfs.c @@ -237,6 +237,27 @@ static const struct file_operations tx_queue_len_ops = { .open = wl1251_open_file_generic, }; +static ssize_t tx_queue_status_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct wl1251 *wl = file->private_data; + char buf[3], status; + int len; + + if (wl->tx_queue_stopped) + status = 's'; + else + status = 'r'; + + len = scnprintf(buf, sizeof(buf), "%c\n", status); + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations tx_queue_status_ops = { + .read = tx_queue_status_read, + .open = wl1251_open_file_generic, +}; + static void wl1251_debugfs_delete_files(struct wl1251 *wl) { DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); @@ -331,6 +352,7 @@ static void wl1251_debugfs_delete_files(struct wl1251 *wl) DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); DEBUGFS_DEL(tx_queue_len); + DEBUGFS_DEL(tx_queue_status); DEBUGFS_DEL(retry_count); DEBUGFS_DEL(excessive_retries); } @@ -431,6 +453,7 @@ static int wl1251_debugfs_add_files(struct wl1251 *wl) DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); + DEBUGFS_ADD(tx_queue_status, wl->debugfs.rootdir); DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); -- cgit v1.2.3 From d67e261829d405ed19a6c2e648f224e352012f52 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:17:45 +0200 Subject: wl1251: print a debug message when tx_queue is full This debug message was missing and caused incomplete log messages. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index ff4be7bf5d36..0417745d7fc4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -395,6 +395,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * the queue here, otherwise the queue will get too long. */ if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { + wl1251_debug(DEBUG_TX, "op_tx: tx_queue full, stop queues"); ieee80211_stop_queues(wl->hw); /* -- cgit v1.2.3 From 478fdf2bcef73747eb99bc6dd3565f093942647a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:17:52 +0200 Subject: wl1251: fix error handling in wl1251_op_config() Not all return values were checked and one exit from function didn't put firmware sleep after the error. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 0417745d7fc4..24050d56a9de 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -645,20 +645,25 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) * through the bss_info_changed() hook. */ ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + if (ret < 0) + goto out_sleep; } else if (!(conf->flags & IEEE80211_CONF_PS) && wl->psm_requested) { wl1251_debug(DEBUG_PSM, "psm disabled"); wl->psm_requested = false; - if (wl->psm) + if (wl->psm) { ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); + if (ret < 0) + goto out_sleep; + } } if (conf->power_level != wl->power_level) { ret = wl1251_acx_tx_power(wl, conf->power_level); if (ret < 0) - goto out; + goto out_sleep; wl->power_level = conf->power_level; } -- cgit v1.2.3 From b5a167942cb388cc5f1a6085cb3506d5bf47517d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:17:59 +0200 Subject: wl1251: reduce ELP wakeup timeout The original TI driver uses 100 ms timeout ELP wakeup timeout, better to use the same. Otherwise problems with wakeup might get unnoticed. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_ps.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 9931b197ff77..54a27200f3b6 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c @@ -26,7 +26,8 @@ #include "wl1251_cmd.h" #include "wl1251_io.h" -#define WL1251_WAKEUP_TIMEOUT 2000 +/* in ms */ +#define WL1251_WAKEUP_TIMEOUT 100 void wl1251_elp_work(struct work_struct *work) { -- cgit v1.2.3 From 7fa6282a1775bd41508220e65ba0cb92235b67d4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:06 +0200 Subject: wl1251: simplify ELP wakeup time calculation The wakeup time calculation was too complicated, simplify it. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_ps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index 54a27200f3b6..851dfb65e474 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c @@ -68,7 +68,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl) int wl1251_ps_elp_wakeup(struct wl1251 *wl) { - unsigned long timeout; + unsigned long timeout, start; u32 elp_reg; if (!wl->elp) @@ -76,6 +76,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) wl1251_debug(DEBUG_PSM, "waking up chip from elp"); + start = jiffies; timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); @@ -96,8 +97,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) } wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", - jiffies_to_msecs(jiffies) - - (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); + jiffies_to_msecs(jiffies - start)); wl->elp = false; -- cgit v1.2.3 From cdd1e9a91ea55594cbcc9847dbb9392e341cbefd Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:12 +0200 Subject: wl1251: use __dev_alloc_skb() on RX RX is handled in a workqueue therefore allocating for GFP_ATOMIC is overkill and not required. Based on a patch for wl1271 by Luis R. Rodriguez. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index f84cc89cbffc..b56732226cc0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -126,7 +126,7 @@ static void wl1251_rx_body(struct wl1251 *wl, if (wl->rx_current_buffer) rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; - skb = dev_alloc_skb(length); + skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1251_error("Couldn't allocate RX frame"); return; -- cgit v1.2.3 From 86dff7a7955f1e14c1f2c142312462fae70ea7e4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:19 +0200 Subject: wl1251: implement acx_ac_cfg to configure hardware queues Needed for WMM. Signed-off-by: Kalle Valo Reviewed-by: Janne Ylalehto Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.c | 33 ++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_acx.h | 32 +++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_init.c | 5 ++++ drivers/net/wireless/wl12xx/wl1251_init.h | 47 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_main.c | 27 ++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_tx.h | 20 +++++++++++++ 6 files changed, 164 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index acfa086dbfc5..b409c75499dd 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c @@ -976,3 +976,36 @@ out: kfree(acx); return ret; } + +int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifs, u16 txop) +{ + struct wl1251_acx_ac_cfg *acx; + int ret = 0; + + wl1251_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " + "aifs %d txop %d", ac, cw_min, cw_max, aifs, txop); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->ac = ac; + acx->cw_min = cw_min; + acx->cw_max = cw_max; + acx->aifsn = aifs; + acx->txop_limit = txop; + + ret = wl1251_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); + if (ret < 0) { + wl1251_warning("acx ac cfg failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 652371432cd8..56793245b287 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -1166,6 +1166,36 @@ struct wl1251_acx_wr_tbtt_and_dtim { u8 padding; } __attribute__ ((packed)); +struct wl1251_acx_ac_cfg { + struct acx_header header; + + /* + * Access Category - The TX queue's access category + * (refer to AccessCategory_enum) + */ + u8 ac; + + /* + * The contention window minimum size (in slots) for + * the access class. + */ + u8 cw_min; + + /* + * The contention window maximum size (in slots) for + * the access class. + */ + u16 cw_max; + + /* The AIF value (in slots) for the access class. */ + u8 aifsn; + + u8 reserved; + + /* The TX Op Limit (in microseconds) for the access class. */ + u16 txop_limit; +} __attribute__ ((packed)); + /************************************************************************* Host Interrupt Register (WiLink -> Host) @@ -1322,5 +1352,7 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); int wl1251_acx_rate_policies(struct wl1251 *wl); int wl1251_acx_mem_cfg(struct wl1251 *wl); int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); +int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifs, u16 txop); #endif /* __WL1251_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index 5cb573383eeb..5aad56ea7153 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c @@ -294,6 +294,11 @@ static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) goto out; } + wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); + wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); + wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); + wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); + out: kfree(config); return ret; diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h index b3b25ec885ea..269cefb3e7d4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ b/drivers/net/wireless/wl12xx/wl1251_init.h @@ -26,6 +26,53 @@ #include "wl1251.h" +enum { + /* best effort/legacy */ + AC_BE = 0, + + /* background */ + AC_BK = 1, + + /* video */ + AC_VI = 2, + + /* voice */ + AC_VO = 3, + + /* broadcast dummy access category */ + AC_BCAST = 4, + + NUM_ACCESS_CATEGORIES = 4 +}; + +/* following are defult values for the IE fields*/ +#define CWMIN_BK 15 +#define CWMIN_BE 15 +#define CWMIN_VI 7 +#define CWMIN_VO 3 +#define CWMAX_BK 1023 +#define CWMAX_BE 63 +#define CWMAX_VI 15 +#define CWMAX_VO 7 + +/* slot number setting to start transmission at PIFS interval */ +#define AIFS_PIFS 1 + +/* + * slot number setting to start transmission at DIFS interval - normal DCF + * access + */ +#define AIFS_DIFS 2 + +#define AIFSN_BK 7 +#define AIFSN_BE 3 +#define AIFSN_VI AIFS_PIFS +#define AIFSN_VO AIFS_PIFS +#define TXOP_BK 0 +#define TXOP_BE 0 +#define TXOP_VI 3008 +#define TXOP_VO 1504 + int wl1251_hw_init_hwenc_config(struct wl1251 *wl); int wl1251_hw_init_templates_config(struct wl1251 *wl); int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 24050d56a9de..c1c7cb5aea2b 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1285,6 +1285,32 @@ static struct ieee80211_channel wl1251_channels[] = { { .hw_value = 13, .center_freq = 2472}, }; +static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct wl1251 *wl = hw->priv; + int ret; + + mutex_lock(&wl->mutex); + + wl1251_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); + + ret = wl1251_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), + params->cw_min, params->cw_max, + params->aifs, params->txop); + + wl1251_ps_elp_sleep(wl); + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + /* can't be const, mac80211 writes to this */ static struct ieee80211_supported_band wl1251_band_2ghz = { .channels = wl1251_channels, @@ -1305,6 +1331,7 @@ static const struct ieee80211_ops wl1251_ops = { .hw_scan = wl1251_op_hw_scan, .bss_info_changed = wl1251_op_bss_info_changed, .set_rts_threshold = wl1251_op_set_rts_threshold, + .conf_tx = wl1251_op_conf_tx, }; static int wl1251_register_hw(struct wl1251 *wl) diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index 7c1c1665c810..b7bead8b0aeb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h @@ -26,6 +26,7 @@ #define __WL1251_TX_H__ #include +#include "wl1251_acx.h" /* * @@ -209,6 +210,25 @@ struct tx_result { u8 done_2; } __attribute__ ((packed)); +static inline int wl1251_tx_get_queue(int queue) +{ + /* FIXME: use best effort until WMM is enabled */ + return QOS_AC_BE; + + switch (queue) { + case 0: + return QOS_AC_VO; + case 1: + return QOS_AC_VI; + case 2: + return QOS_AC_BE; + case 3: + return QOS_AC_BK; + default: + return QOS_AC_BE; + } +} + void wl1251_tx_work(struct work_struct *work); void wl1251_tx_complete(struct wl1251 *wl); void wl1251_tx_flush(struct wl1251 *wl); -- cgit v1.2.3 From 27336f1c0cd68fb9ae45493321f0d6980144230e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:27 +0200 Subject: wl1251: implement wl1251_acx_tid_cfg() Needed for WMM. Signed-off-by: Kalle Valo Reviewed-by: Janne Ylalehto Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_acx.c | 36 ++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_acx.h | 55 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_main.c | 11 +++++++ 3 files changed, 102 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index b409c75499dd..beff084040b5 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c @@ -1009,3 +1009,39 @@ out: kfree(acx); return ret; } + +int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, + enum wl1251_acx_channel_type type, + u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, + enum wl1251_acx_ack_policy ack_policy) +{ + struct wl1251_acx_tid_cfg *acx; + int ret = 0; + + wl1251_debug(DEBUG_ACX, "acx tid cfg %d type %d tsid %d " + "ps_scheme %d ack_policy %d", queue, type, tsid, + ps_scheme, ack_policy); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->queue = queue; + acx->type = type; + acx->tsid = tsid; + acx->ps_scheme = ps_scheme; + acx->ack_policy = ack_policy; + + ret = wl1251_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); + if (ret < 0) { + wl1251_warning("acx tid cfg failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 56793245b287..26160c45784c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h @@ -1196,6 +1196,57 @@ struct wl1251_acx_ac_cfg { u16 txop_limit; } __attribute__ ((packed)); + +enum wl1251_acx_channel_type { + CHANNEL_TYPE_DCF = 0, + CHANNEL_TYPE_EDCF = 1, + CHANNEL_TYPE_HCCA = 2, +}; + +enum wl1251_acx_ps_scheme { + /* regular ps: simple sending of packets */ + WL1251_ACX_PS_SCHEME_LEGACY = 0, + + /* sending a packet triggers a unscheduled apsd downstream */ + WL1251_ACX_PS_SCHEME_UPSD_TRIGGER = 1, + + /* a pspoll packet will be sent before every data packet */ + WL1251_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, + + /* scheduled apsd mode */ + WL1251_ACX_PS_SCHEME_SAPSD = 3, +}; + +enum wl1251_acx_ack_policy { + WL1251_ACX_ACK_POLICY_LEGACY = 0, + WL1251_ACX_ACK_POLICY_NO_ACK = 1, + WL1251_ACX_ACK_POLICY_BLOCK = 2, +}; + +struct wl1251_acx_tid_cfg { + struct acx_header header; + + /* tx queue id number (0-7) */ + u8 queue; + + /* channel access type for the queue, enum wl1251_acx_channel_type */ + u8 type; + + /* EDCA: ac index (0-3), HCCA: traffic stream id (8-15) */ + u8 tsid; + + /* ps scheme of the specified queue, enum wl1251_acx_ps_scheme */ + u8 ps_scheme; + + /* the tx queue ack policy, enum wl1251_acx_ack_policy */ + u8 ack_policy; + + u8 padding[3]; + + /* not supported */ + u32 apsdconf[2]; +} __attribute__ ((packed)); + /************************************************************************* Host Interrupt Register (WiLink -> Host) @@ -1354,5 +1405,9 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl); int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, u8 aifs, u16 txop); +int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, + enum wl1251_acx_channel_type type, + u8 tsid, enum wl1251_acx_ps_scheme ps_scheme, + enum wl1251_acx_ack_policy ack_policy); #endif /* __WL1251_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index c1c7cb5aea2b..74770ada37de 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1302,7 +1302,18 @@ static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), params->cw_min, params->cw_max, params->aifs, params->txop); + if (ret < 0) + goto out_sleep; + + ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), + CHANNEL_TYPE_DCF, + wl1251_tx_get_queue(queue), + WL1251_ACX_PS_SCHEME_LEGACY, + WL1251_ACX_ACK_POLICY_LEGACY); + if (ret < 0) + goto out_sleep; +out_sleep: wl1251_ps_elp_sleep(wl); out: -- cgit v1.2.3 From 49e1b9faed736b20ad9a785638919341b567a595 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:33 +0200 Subject: wl1251: implement WMM Now that necessary commands for WMM are implemented, implement queue handling for WMM. But WMM is not enabled yet, only one queue is used. Signed-off-by: Kalle Valo Reviewed-by: Janne Ylalehto Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 2 +- drivers/net/wireless/wl12xx/wl1251_tx.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 74770ada37de..563c84fc575c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1306,7 +1306,7 @@ static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, goto out_sleep; ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), - CHANNEL_TYPE_DCF, + CHANNEL_TYPE_EDCF, wl1251_tx_get_queue(queue), WL1251_ACX_PS_SCHEME_LEGACY, WL1251_ACX_ACK_POLICY_LEGACY); diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index f85970615849..faa23efd05a1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -167,8 +167,7 @@ static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, tx_hdr->expiry_time = cpu_to_le32(1 << 16); tx_hdr->id = id; - /* FIXME: how to get the correct queue id? */ - tx_hdr->xmit_queue = 0; + tx_hdr->xmit_queue = wl1251_tx_get_queue(skb_get_queue_mapping(skb)); wl1251_tx_control(tx_hdr, control, fc); wl1251_tx_frag_block_num(tx_hdr); @@ -237,8 +236,9 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, wl1251_mem_write(wl, addr, skb->data, len); - wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", - tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); + wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x " + "queue %d", tx_hdr->id, skb, tx_hdr->length, + tx_hdr->rate, tx_hdr->xmit_queue); return 0; } -- cgit v1.2.3 From 46cb35f5e761306b031029af2061ea263359a764 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:40 +0200 Subject: wl1251: update tx_hdr when aliging skb in tx Before transmission when aligning the buffer to 4-byte bounday, tx_hdr needs to be updated. Otherwise debug logs print false data. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index faa23efd05a1..c8223185efd2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -219,6 +219,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, /* align the buffer on a 4-byte boundary */ skb_reserve(skb, offset); memmove(skb->data, src, skb->len); + tx_hdr = (struct tx_double_buffer_desc *) skb->data; } else { wl1251_info("No handler, fixme!"); return -EINVAL; -- cgit v1.2.3 From da2fb4e9c215b8f0f8954818691549f8a34135be Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 30 Nov 2009 10:18:47 +0200 Subject: wl1251: enable WMM Everything is ready now and we can enable WMM in mac80211. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 2 ++ drivers/net/wireless/wl12xx/wl1251_tx.h | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 563c84fc575c..63511ca131b1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1388,6 +1388,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->wiphy->max_scan_ssids = 1; wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; + wl->hw->queues = 4; + ret = wl1251_register_hw(wl); if (ret) goto out; diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h index b7bead8b0aeb..55856c6bb97a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl12xx/wl1251_tx.h @@ -212,9 +212,6 @@ struct tx_result { static inline int wl1251_tx_get_queue(int queue) { - /* FIXME: use best effort until WMM is enabled */ - return QOS_AC_BE; - switch (queue) { case 0: return QOS_AC_VO; -- cgit v1.2.3 From cef6e91280b724e93b0fb8a9fd3e6bf072f54c81 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 30 Nov 2009 21:50:07 +0200 Subject: rndis_wlan: move copy of module parameters to separate function Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2ecbedb26e15..8dd9224c2d4e 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2594,23 +2594,9 @@ end: /* * driver/device initialization */ -static int bcm4320a_early_init(struct usbnet *usbdev) -{ - /* bcm4320a doesn't handle configuration parameters well. Try - * set any and you get partially zeroed mac and broken device. - */ - - return 0; -} - -static int bcm4320b_early_init(struct usbnet *usbdev) +static void rndis_copy_module_params(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - char buf[8]; - - /* Early initialization settings, setting these won't have effect - * if called after generic_rndis_bind(). - */ priv->param_country[0] = modparam_country[0]; priv->param_country[1] = modparam_country[1]; @@ -2652,6 +2638,27 @@ static int bcm4320b_early_init(struct usbnet *usbdev) priv->param_workaround_interval = 500; else priv->param_workaround_interval = modparam_workaround_interval; +} + +static int bcm4320a_early_init(struct usbnet *usbdev) +{ + /* bcm4320a doesn't handle configuration parameters well. Try + * set any and you get partially zeroed mac and broken device. + */ + + return 0; +} + +static int bcm4320b_early_init(struct usbnet *usbdev) +{ + struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); + char buf[8]; + + rndis_copy_module_params(usbdev); + + /* Early initialization settings, setting these won't have effect + * if called after generic_rndis_bind(). + */ rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); rndis_set_config_parameter_str(usbdev, "FrameBursting", -- cgit v1.2.3 From 6e850af58f93be8f1b4b79eb9c79d06788f38e78 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Mon, 30 Nov 2009 21:50:13 +0200 Subject: rndis_wlan: copy module parameters for bcm4320a devices too rndis_wlan didn't copy module parameters for bcm4320a to private structure. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 8dd9224c2d4e..305c106fdc1c 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2642,6 +2642,11 @@ static void rndis_copy_module_params(struct usbnet *usbdev) static int bcm4320a_early_init(struct usbnet *usbdev) { + /* copy module parameters for bcm4320a so that iwconfig reports txpower + * and workaround parameter is copied to private structure correctly. + */ + rndis_copy_module_params(usbdev); + /* bcm4320a doesn't handle configuration parameters well. Try * set any and you get partially zeroed mac and broken device. */ -- cgit v1.2.3 From 4a40ccf8140d6b973d8b02dd5467b1fd876c0654 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sat, 12 Dec 2009 18:04:46 -0600 Subject: rtl8180: Remove usage of deprecated 'qual' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building rtl8180, the following warning occurs: CC [M] drivers/net/wireless/rtl818x/rtl8180_dev.o drivers/net/wireless/rtl818x/rtl8180_dev.c: In function ‘rtl8180_handle_rx’: drivers/net/wireless/rtl818x/rtl8180_dev.c:135: warning: ‘qual’ is deprecated (declared at include/net/mac80211.h:562) Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index a1a3dd15c664..8a40a1439984 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -132,7 +132,6 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) rx_status.antenna = (flags2 >> 15) & 1; /* TODO: improve signal/rssi reporting */ - rx_status.qual = flags2 & 0xFF; rx_status.signal = (flags2 >> 8) & 0x7F; /* XXX: is this correct? */ rx_status.rate_idx = (flags >> 20) & 0xF; -- cgit v1.2.3 From 59d9cb071d6209f2e8df2d16228cfdc7bab1f2d1 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 17 Dec 2009 13:54:57 +0100 Subject: mac80211: remove payload alignment warning The payload alignment warning enabled by MAC80211_DEBUG_PACKET_ALIGNMENT is difficult. To fix it, a firmware change is needed but in most cases that's very difficult. So the benefit from the warning is low and most probably it just creates more confusion for people who just enable all warnings (like it did for me). Remove the unaligned IP payload warning and the kconfig option. But leave the unaligned packet warning, it will be enabled with MAC80211_VERBOSE_DEBUG. Signed-off-by: Kalle Valo Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Kconfig | 12 ------------ net/mac80211/rx.c | 27 +++++++-------------------- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index a10d508b07e1..a952b7f8c648 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -96,18 +96,6 @@ menuconfig MAC80211_DEBUG_MENU ---help--- This option collects various mac80211 debug settings. -config MAC80211_DEBUG_PACKET_ALIGNMENT - bool "Enable packet alignment debugging" - depends on MAC80211_DEBUG_MENU - ---help--- - This option is recommended for driver authors and strongly - discouraged for everybody else, it will trigger a warning - when a driver hands mac80211 a buffer that is aligned in - a way that will cause problems with the IP stack on some - architectures. - - Say N unless you're writing a mac80211 based driver. - config MAC80211_NOINLINE bool "Do not inline TX/RX handlers" depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ebab696def5b..dbfd684e3e2e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -361,7 +361,9 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) * boundary. In the case of regular frames, this simply means aligning the * payload to a four-byte boundary (because either the IP header is directly * contained, or IV/RFC1042 headers that have a length divisible by four are - * in front of it). + * in front of it). If the payload data is not properly aligned and the + * architecture doesn't support efficient unaligned operations, mac80211 + * will align the data. * * With A-MSDU frames, however, the payload data address must yield two modulo * four because there are 14-byte 802.3 headers within the A-MSDU frames that @@ -375,25 +377,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) */ static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; - int hdrlen; - -#ifndef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT - return; +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + WARN_ONCE((unsigned long)rx->skb->data & 1, + "unaligned packet at 0x%p\n", rx->skb->data); #endif - - if (WARN_ONCE((unsigned long)rx->skb->data & 1, - "unaligned packet at 0x%p\n", rx->skb->data)) - return; - - if (!ieee80211_is_data_present(hdr->frame_control)) - return; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - if (rx->flags & IEEE80211_RX_AMSDU) - hdrlen += ETH_HLEN; - WARN_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3, - "unaligned IP payload at 0x%p\n", rx->skb->data + hdrlen); } @@ -1510,7 +1497,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) if (skb) { int align __maybe_unused; -#if defined(CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT) || !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS /* * 'align' will only take the values 0 or 2 here * since all frames are required to be aligned -- cgit v1.2.3 From 3b377ea9d4efc94dc52fe41b4dfdb463635ab298 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 18 Dec 2009 17:59:01 -0500 Subject: wireless: support internal statically compiled regulatory database This patch provides infrastructure for machine translation of the regulatory rules database used by CRDA into a C data structure. It includes code for searching that database as an alternative to dynamic regulatory rules updates via CRDA. Most people should use CRDA instead of this infrastructure, but it provides a better alternative than the WIRELESS_OLD_REGULATORY infrastructure (which can now be removed). Signed-off-by: John W. Linville --- Documentation/networking/regulatory.txt | 24 +++++++ net/wireless/.gitignore | 1 + net/wireless/Kconfig | 16 +++++ net/wireless/Makefile | 6 ++ net/wireless/db.txt | 17 +++++ net/wireless/genregdb.awk | 118 +++++++++++++++++++++++++++++++ net/wireless/reg.c | 120 +++++++++++++++++++++++++------- net/wireless/regdb.h | 7 ++ 8 files changed, 285 insertions(+), 24 deletions(-) create mode 100644 net/wireless/.gitignore create mode 100644 net/wireless/db.txt create mode 100644 net/wireless/genregdb.awk create mode 100644 net/wireless/regdb.h diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt index ee31369e9e5b..9551622d0a7b 100644 --- a/Documentation/networking/regulatory.txt +++ b/Documentation/networking/regulatory.txt @@ -188,3 +188,27 @@ Then in some part of your code after your wiphy has been registered: &mydriver_jp_regdom.reg_rules[i], sizeof(struct ieee80211_reg_rule)); regulatory_struct_hint(rd); + +Statically compiled regulatory database +--------------------------------------- + +In most situations the userland solution using CRDA as described +above is the preferred solution. However in some cases a set of +rules built into the kernel itself may be desirable. To account +for this situation, a configuration option has been provided +(i.e. CONFIG_CFG80211_INTERNAL_REGDB). With this option enabled, +the wireless database information contained in net/wireless/db.txt is +used to generate a data structure encoded in net/wireless/regdb.c. +That option also enables code in net/wireless/reg.c which queries +the data in regdb.c as an alternative to using CRDA. + +The file net/wireless/db.txt should be kept up-to-date with the db.txt +file available in the git repository here: + + git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git + +Again, most users in most situations should be using the CRDA package +provided with their distribution, and in most other situations users +should be building and using CRDA on their own rather than using +this option. If you are not absolutely sure that you should be using +CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_. diff --git a/net/wireless/.gitignore b/net/wireless/.gitignore new file mode 100644 index 000000000000..c33451b896d9 --- /dev/null +++ b/net/wireless/.gitignore @@ -0,0 +1 @@ +regdb.c diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 90e93a5701aa..8419971f07c5 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -109,6 +109,22 @@ config WIRELESS_OLD_REGULATORY Say N and if you say Y, please tell us why. The default is N. +config CFG80211_INTERNAL_REGDB + bool "use statically compiled regulatory rules database" if EMBEDDED + default n + depends on CFG80211 + ---help--- + This option generates an internal data structure representing + the wireless regulatory rules described in net/wireless/db.txt + and includes code to query that database. This is an alternative + to using CRDA for defining regulatory rules for the kernel. + + For details see: + + http://wireless.kernel.org/en/developers/Regulatory + + Most distributions have a CRDA package. So if unsure, say N. + config CFG80211_WEXT bool "cfg80211 wireless extensions compatibility" depends on CFG80211 diff --git a/net/wireless/Makefile b/net/wireless/Makefile index f07c8dc7aab2..e77e508126fa 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -13,5 +13,11 @@ cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o +cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o ccflags-y += -D__CHECK_ENDIAN__ + +$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk + @$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@ + +clean-files := regdb.c diff --git a/net/wireless/db.txt b/net/wireless/db.txt new file mode 100644 index 000000000000..a2fc3a09ccdc --- /dev/null +++ b/net/wireless/db.txt @@ -0,0 +1,17 @@ +# +# This file is a placeholder to prevent accidental build breakage if someone +# enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to +# enable that build option. +# +# You should be using CRDA instead. It is even better if you use the CRDA +# package provided by your distribution, since they will probably keep it +# up-to-date on your behalf. +# +# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will +# need to replace this file with one containing appropriately formatted +# regulatory rules that cover the regulatory domains you will be using. Your +# best option is to extract the db.txt file from the wireless-regdb git +# repository: +# +# git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git +# diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk new file mode 100644 index 000000000000..8316cf075ce9 --- /dev/null +++ b/net/wireless/genregdb.awk @@ -0,0 +1,118 @@ +#!/usr/bin/awk -f +# +# genregdb.awk -- generate regdb.c from db.txt +# +# Actually, it reads from stdin (presumed to be db.txt) and writes +# to stdout (presumed to be regdb.c), but close enough... +# +# Copyright 2009 John W. Linville +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# + +BEGIN { + active = 0 + rules = 0; + print "/*" + print " * DO NOT EDIT -- file generated from data in db.txt" + print " */" + print "" + print "#include " + print "#include " + print "" + regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n" +} + +/^[ \t]*#/ { + /* Ignore */ +} + +!active && /^[ \t]*$/ { + /* Ignore */ +} + +!active && /country/ { + country=$2 + sub(/:/, "", country) + printf "static const struct ieee80211_regdomain regdom_%s = {\n", country + printf "\t.alpha2 = \"%s\",\n", country + printf "\t.reg_rules = {\n" + active = 1 + regdb = regdb "\t®dom_" country ",\n" +} + +active && /^[ \t]*\(/ { + start = $1 + sub(/\(/, "", start) + end = $3 + bw = $5 + sub(/\),/, "", bw) + gain = $6 + sub(/\(/, "", gain) + sub(/,/, "", gain) + power = $7 + sub(/\)/, "", power) + sub(/,/, "", power) + # power might be in mW... + units = $8 + sub(/\)/, "", units) + sub(/,/, "", units) + if (units == "mW") { + if (power == 100) { + power = 20 + } else if (power == 200) { + power = 23 + } else if (power == 500) { + power = 27 + } else if (power == 1000) { + power = 30 + } else { + print "Unknown power value in database!" + } + } + flagstr = "" + for (i=8; i<=NF; i++) + flagstr = flagstr $i + split(flagstr, flagarray, ",") + flags = "" + for (arg in flagarray) { + if (flagarray[arg] == "NO-OFDM") { + flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | " + } else if (flagarray[arg] == "NO-CCK") { + flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | " + } else if (flagarray[arg] == "NO-INDOOR") { + flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | " + } else if (flagarray[arg] == "NO-OUTDOOR") { + flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | " + } else if (flagarray[arg] == "DFS") { + flags = flags "\n\t\t\tNL80211_RRF_DFS | " + } else if (flagarray[arg] == "PTP-ONLY") { + flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | " + } else if (flagarray[arg] == "PTMP-ONLY") { + flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | " + } else if (flagarray[arg] == "PASSIVE-SCAN") { + flags = flags "\n\t\t\tNL80211_RRF_PASSIVE_SCAN | " + } else if (flagarray[arg] == "NO-IBSS") { + flags = flags "\n\t\t\tNL80211_RRF_NO_IBSS | " + } + } + flags = flags "0" + printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags + rules++ +} + +active && /^[ \t]*$/ { + active = 0 + printf "\t},\n" + printf "\t.n_reg_rules = %d\n", rules + printf "};\n\n" + rules = 0; +} + +END { + print regdb "};" + print "" + print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);" +} diff --git a/net/wireless/reg.c b/net/wireless/reg.c index c01470e7de15..65f86264f7bb 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -40,6 +40,7 @@ #include #include "core.h" #include "reg.h" +#include "regdb.h" #include "nl80211.h" /* Receipt of information from last regulatory request */ @@ -360,6 +361,98 @@ static bool country_ie_integrity_changes(u32 checksum) return false; } +static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, + const struct ieee80211_regdomain *src_regd) +{ + struct ieee80211_regdomain *regd; + int size_of_regd = 0; + unsigned int i; + + size_of_regd = sizeof(struct ieee80211_regdomain) + + ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); + + regd = kzalloc(size_of_regd, GFP_KERNEL); + if (!regd) + return -ENOMEM; + + memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); + + for (i = 0; i < src_regd->n_reg_rules; i++) + memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], + sizeof(struct ieee80211_reg_rule)); + + *dst_regd = regd; + return 0; +} + +#ifdef CONFIG_CFG80211_INTERNAL_REGDB +struct reg_regdb_search_request { + char alpha2[2]; + struct list_head list; +}; + +static LIST_HEAD(reg_regdb_search_list); +static DEFINE_SPINLOCK(reg_regdb_search_lock); + +static void reg_regdb_search(struct work_struct *work) +{ + struct reg_regdb_search_request *request; + const struct ieee80211_regdomain *curdom, *regdom; + int i, r; + + spin_lock(®_regdb_search_lock); + while (!list_empty(®_regdb_search_list)) { + request = list_first_entry(®_regdb_search_list, + struct reg_regdb_search_request, + list); + list_del(&request->list); + + for (i=0; ialpha2, curdom->alpha2, 2)) { + r = reg_copy_regd(®dom, curdom); + if (r) + break; + spin_unlock(®_regdb_search_lock); + mutex_lock(&cfg80211_mutex); + set_regdom(regdom); + mutex_unlock(&cfg80211_mutex); + spin_lock(®_regdb_search_lock); + break; + } + } + + kfree(request); + } + spin_unlock(®_regdb_search_lock); +} + +static DECLARE_WORK(reg_regdb_work, reg_regdb_search); + +static void reg_regdb_query(const char *alpha2) +{ + struct reg_regdb_search_request *request; + + if (!alpha2) + return; + + request = kzalloc(sizeof(struct reg_regdb_search_request), GFP_KERNEL); + if (!request) + return; + + memcpy(request->alpha2, alpha2, 2); + + spin_lock(®_regdb_search_lock); + list_add_tail(&request->list, ®_regdb_search_list); + spin_unlock(®_regdb_search_lock); + + schedule_work(®_regdb_work); +} +#else +static inline void reg_regdb_query(const char *alpha2) {} +#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + /* * This lets us keep regulatory code which is updated on a regulatory * basis in userspace. @@ -379,6 +472,9 @@ static int call_crda(const char *alpha2) printk(KERN_INFO "cfg80211: Calling CRDA to update world " "regulatory domain\n"); + /* query internal regulatory database (if it exists) */ + reg_regdb_query(alpha2); + country_env[8] = alpha2[0]; country_env[9] = alpha2[1]; @@ -1367,30 +1463,6 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, } EXPORT_SYMBOL(wiphy_apply_custom_regulatory); -static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, - const struct ieee80211_regdomain *src_regd) -{ - struct ieee80211_regdomain *regd; - int size_of_regd = 0; - unsigned int i; - - size_of_regd = sizeof(struct ieee80211_regdomain) + - ((src_regd->n_reg_rules + 1) * sizeof(struct ieee80211_reg_rule)); - - regd = kzalloc(size_of_regd, GFP_KERNEL); - if (!regd) - return -ENOMEM; - - memcpy(regd, src_regd, sizeof(struct ieee80211_regdomain)); - - for (i = 0; i < src_regd->n_reg_rules; i++) - memcpy(®d->reg_rules[i], &src_regd->reg_rules[i], - sizeof(struct ieee80211_reg_rule)); - - *dst_regd = regd; - return 0; -} - /* * Return value which can be used by ignore_request() to indicate * it has been determined we should intersect two regulatory domains diff --git a/net/wireless/regdb.h b/net/wireless/regdb.h new file mode 100644 index 000000000000..818222c92513 --- /dev/null +++ b/net/wireless/regdb.h @@ -0,0 +1,7 @@ +#ifndef __REGDB_H__ +#define __REGDB_H__ + +extern const struct ieee80211_regdomain *reg_regdb[]; +extern int reg_regdb_size; + +#endif /* __REGDB_H__ */ -- cgit v1.2.3 From 3a41bbd515d449604f3488c5f8dd62802f09d19b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 10 Dec 2009 14:37:24 -0800 Subject: iwlwifi: log CT_CARD_DISABLED flag Change name from RF_CARD_DISABLED to CT_CARD_DISABLED to match the indication from uCode, also log the debug message when the condition detected in iwl_rx_card_state_notif() Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 12 +++++++----- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b8377efb3ba7..954b8ae2c880 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -689,12 +689,14 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); unsigned long status = priv->status; - IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", + IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n", (flags & HW_CARD_DISABLED) ? "Kill" : "On", - (flags & SW_CARD_DISABLED) ? "Kill" : "On"); + (flags & SW_CARD_DISABLED) ? "Kill" : "On", + (flags & CT_CARD_DISABLED) ? + "Reached" : "Not reached"); if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | - RF_CARD_DISABLED)) { + CT_CARD_DISABLED)) { iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); @@ -708,10 +710,10 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, iwl_write_direct32(priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); } - if (flags & RF_CARD_DISABLED) + if (flags & CT_CARD_DISABLED) iwl_tt_enter_ct_kill(priv); } - if (!(flags & RF_CARD_DISABLED)) + if (!(flags & CT_CARD_DISABLED)) iwl_tt_exit_ct_kill(priv); if (flags & HW_CARD_DISABLED) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e91507531923..28f3800c560e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2510,7 +2510,7 @@ struct iwl_card_state_notif { #define HW_CARD_DISABLED 0x01 #define SW_CARD_DISABLED 0x02 -#define RF_CARD_DISABLED 0x04 +#define CT_CARD_DISABLED 0x04 #define RXON_CARD_DISABLED 0x10 struct iwl_ct_kill_config { -- cgit v1.2.3 From 696bdee3ba216186e21997d20a839b76158346e6 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 10 Dec 2009 14:37:25 -0800 Subject: iwlwifi: dump "Control and Status Register" when detect uCode HW/SW error When uCode HW/SW error detected, dumping important CSR (Control and Status Registers) values. Also add "csr" debugfs file to dump the current values of CSR defined in CSR table to syslog. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 + drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 73 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 25 ++++++++++ 7 files changed, 105 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8414178bcff4..9d4fdd7a1134 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -105,6 +105,7 @@ static struct iwl_lib_ops iwl1000_lib = { .load_ucode = iwl5000_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e2f8615c8c9b..5a277cdffd07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1465,6 +1465,7 @@ struct iwl_lib_ops iwl5000_lib = { .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, .load_ucode = iwl5000_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, @@ -1517,6 +1518,7 @@ static struct iwl_lib_ops iwl5150_lib = { .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, .load_ucode = iwl5000_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 74e571049273..fec43771c49e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -215,6 +215,7 @@ static struct iwl_lib_ops iwl6000_lib = { .load_ucode = iwl5000_load_ucode, .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 574d36658702..47ece91e4505 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1363,6 +1363,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) clear_bit(STATUS_HCMD_ACTIVE, &priv->status); priv->cfg->ops->lib->dump_nic_error_log(priv); + if (priv->cfg->ops->lib->dump_csr) + priv->cfg->ops->lib->dump_csr(priv); priv->cfg->ops->lib->dump_nic_event_log(priv, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) @@ -3191,6 +3193,77 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) EXPORT_SYMBOL(iwl_update_stats); #endif +const static char *get_csr_string(int cmd) +{ + switch (cmd) { + IWL_CMD(CSR_HW_IF_CONFIG_REG); + IWL_CMD(CSR_INT_COALESCING); + IWL_CMD(CSR_INT); + IWL_CMD(CSR_INT_MASK); + IWL_CMD(CSR_FH_INT_STATUS); + IWL_CMD(CSR_GPIO_IN); + IWL_CMD(CSR_RESET); + IWL_CMD(CSR_GP_CNTRL); + IWL_CMD(CSR_HW_REV); + IWL_CMD(CSR_EEPROM_REG); + IWL_CMD(CSR_EEPROM_GP); + IWL_CMD(CSR_OTP_GP_REG); + IWL_CMD(CSR_GIO_REG); + IWL_CMD(CSR_GP_UCODE_REG); + IWL_CMD(CSR_GP_DRIVER_REG); + IWL_CMD(CSR_UCODE_DRV_GP1); + IWL_CMD(CSR_UCODE_DRV_GP2); + IWL_CMD(CSR_LED_REG); + IWL_CMD(CSR_DRAM_INT_TBL_REG); + IWL_CMD(CSR_GIO_CHICKEN_BITS); + IWL_CMD(CSR_ANA_PLL_CFG); + IWL_CMD(CSR_HW_REV_WA_REG); + IWL_CMD(CSR_DBG_HPET_MEM_REG); + default: + return "UNKNOWN"; + + } +} + +void iwl_dump_csr(struct iwl_priv *priv) +{ + int i; + u32 csr_tbl[] = { + CSR_HW_IF_CONFIG_REG, + CSR_INT_COALESCING, + CSR_INT, + CSR_INT_MASK, + CSR_FH_INT_STATUS, + CSR_GPIO_IN, + CSR_RESET, + CSR_GP_CNTRL, + CSR_HW_REV, + CSR_EEPROM_REG, + CSR_EEPROM_GP, + CSR_OTP_GP_REG, + CSR_GIO_REG, + CSR_GP_UCODE_REG, + CSR_GP_DRIVER_REG, + CSR_UCODE_DRV_GP1, + CSR_UCODE_DRV_GP2, + CSR_LED_REG, + CSR_DRAM_INT_TBL_REG, + CSR_GIO_CHICKEN_BITS, + CSR_ANA_PLL_CFG, + CSR_HW_REV_WA_REG, + CSR_DBG_HPET_MEM_REG + }; + IWL_ERR(priv, "CSR values:\n"); + IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " + "CSR_INT_PERIODIC_REG)\n"); + for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { + IWL_ERR(priv, " %25s: 0X%08x\n", + get_csr_string(csr_tbl[i]), + iwl_read32(priv, csr_tbl[i])); + } +} +EXPORT_SYMBOL(iwl_dump_csr); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 675b7df632fc..f5e79cf0a318 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -171,6 +171,7 @@ struct iwl_lib_ops { int (*load_ucode)(struct iwl_priv *priv); void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); void (*dump_nic_error_log)(struct iwl_priv *priv); + void (*dump_csr)(struct iwl_priv *priv); int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); /* power management */ struct iwl_apm_ops apm_ops; @@ -582,6 +583,7 @@ int iwl_pci_resume(struct pci_dev *pdev); ******************************************************/ void iwl_dump_nic_error_log(struct iwl_priv *priv); void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); +void iwl_dump_csr(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv); #else diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d61293ab67c9..86a67672598d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -109,6 +109,7 @@ struct iwl_debugfs { struct dentry *file_power_save_status; struct dentry *file_clear_ucode_statistics; struct dentry *file_clear_traffic_statistics; + struct dentry *file_csr; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 21e0f6699daf..2be3549be01d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1845,6 +1845,28 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_csr_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int csr; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &csr) != 1) + return -EFAULT; + + if (priv->cfg->ops->lib->dump_csr) + priv->cfg->ops->lib->dump_csr(priv); + + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1859,6 +1881,7 @@ DEBUGFS_READ_FILE_OPS(tx_power); DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); +DEBUGFS_WRITE_FILE_OPS(csr); /* * Create the debugfs files and directories @@ -1909,6 +1932,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); + DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); @@ -1966,6 +1990,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) file_clear_ucode_statistics); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_clear_traffic_statistics); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_ucode_rx_stats); -- cgit v1.2.3 From a9e1cb6a78ea8a74c49bf76726a2942f636a833b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 10 Dec 2009 14:37:26 -0800 Subject: iwlwifi: add continuous uCode event log capability In order to help uCode debugging, adding the capability to provide continuous uCode event logging function. uCode events is located in round-robin event queue and filled by uCode, by enable continuous event logging, driver check the write pointer and log the newly added events in iwl_bg_ucode_trace() timer function. There is still possibility of missing events if event queue being wrapped before next event dump; but with this capability, we can have much better understanding of the uCode behavior during runtime; it can help to debug the uCode related issues. Methods to enable/disable the continuous event log: step 1: enable ucode trace timer "echo 1 > /sys/kernel/debug/ieee80211/phyX/iwlagn/debug/ucode_tracing" step 2: start ftrace sudo ./trace-cmd record -e iwlwifi_ucode:* sleep 1d step 3: stop ftrace sudo ./trace-cmd report trace.dat step 4: disable ucode trace timer "echo 0 > /sys/kernel/debug/ieee80211/phyX/iwlagn/debug/ucode_tracing" use "ucode_tracing" debugfs file to display number of event queue wrapped when driver attempt the continuous event logging. If event queue being wrapped more than once when driver has opportunity to log the event; it indicated there are events missing in the event log trace. This continuous event log function only available for 4965 and newer NICs. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 130 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 56 ++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 29 +++++++ drivers/net/wireless/iwlwifi/iwl-devtrace.c | 2 + drivers/net/wireless/iwlwifi/iwl-devtrace.h | 44 ++++++++++ 6 files changed, 262 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 954b8ae2c880..4d85c28e38e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -657,6 +657,131 @@ static void iwl_bg_statistics_periodic(unsigned long data) iwl_send_statistics_request(priv, CMD_ASYNC, false); } + +static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, + u32 start_idx, u32 num_events, + u32 mode) +{ + u32 i; + u32 ptr; /* SRAM byte address of log data */ + u32 ev, time, data; /* event log data */ + unsigned long reg_flags; + + if (mode == 0) + ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32)); + else + ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); + + /* Make sure device is powered up for SRAM reads */ + spin_lock_irqsave(&priv->reg_lock, reg_flags); + if (iwl_grab_nic_access(priv)) { + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return; + } + + /* Set starting address; reads will auto-increment */ + _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); + rmb(); + + /* + * "time" is actually "data" for mode 0 (no timestamp). + * place event id # at far right for easier visual parsing. + */ + for (i = 0; i < num_events; i++) { + ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + if (mode == 0) { + trace_iwlwifi_dev_ucode_cont_event(priv, + 0, time, ev); + } else { + data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); + trace_iwlwifi_dev_ucode_cont_event(priv, + time, data, ev); + } + } + /* Allow device to power down */ + iwl_release_nic_access(priv); + spin_unlock_irqrestore(&priv->reg_lock, reg_flags); +} + +void iwl_continuous_event_trace(struct iwl_priv *priv) +{ + u32 capacity; /* event log capacity in # entries */ + u32 base; /* SRAM byte address of event log header */ + u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ + u32 num_wraps; /* # times uCode wrapped to top of log */ + u32 next_entry; /* index of next entry to be written by uCode */ + + if (priv->ucode_type == UCODE_INIT) + base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); + else + base = le32_to_cpu(priv->card_alive.log_event_table_ptr); + if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { + capacity = iwl_read_targ_mem(priv, base); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); + } else + return; + + if (num_wraps == priv->event_log.num_wraps) { + iwl_print_cont_event_trace(priv, + base, priv->event_log.next_entry, + next_entry - priv->event_log.next_entry, + mode); + priv->event_log.non_wraps_count++; + } else { + if ((num_wraps - priv->event_log.num_wraps) > 1) + priv->event_log.wraps_more_count++; + else + priv->event_log.wraps_once_count++; + trace_iwlwifi_dev_ucode_wrap_event(priv, + num_wraps - priv->event_log.num_wraps, + next_entry, priv->event_log.next_entry); + if (next_entry < priv->event_log.next_entry) { + iwl_print_cont_event_trace(priv, base, + priv->event_log.next_entry, + capacity - priv->event_log.next_entry, + mode); + + iwl_print_cont_event_trace(priv, base, 0, + next_entry, mode); + } else { + iwl_print_cont_event_trace(priv, base, + next_entry, capacity - next_entry, + mode); + + iwl_print_cont_event_trace(priv, base, 0, + next_entry, mode); + } + } + priv->event_log.num_wraps = num_wraps; + priv->event_log.next_entry = next_entry; +} + +/** + * iwl_bg_ucode_trace - Timer callback to log ucode event + * + * The timer is continually set to execute every + * UCODE_TRACE_PERIOD milliseconds after the last timer expired + * this function is to perform continuous uCode event logging operation + * if enabled + */ +static void iwl_bg_ucode_trace(unsigned long data) +{ + struct iwl_priv *priv = (struct iwl_priv *)data; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (priv->event_log.ucode_trace) { + iwl_continuous_event_trace(priv); + /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */ + mod_timer(&priv->ucode_trace, + jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); + } +} + static void iwl_rx_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -3128,6 +3253,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) priv->statistics_periodic.data = (unsigned long)priv; priv->statistics_periodic.function = iwl_bg_statistics_periodic; + init_timer(&priv->ucode_trace); + priv->ucode_trace.data = (unsigned long)priv; + priv->ucode_trace.function = iwl_bg_ucode_trace; + if (!priv->cfg->use_isr_legacy) tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) iwl_irq_tasklet, (unsigned long)priv); @@ -3146,6 +3275,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->alive_start); cancel_work_sync(&priv->beacon_update); del_timer_sync(&priv->statistics_periodic); + del_timer_sync(&priv->ucode_trace); } static void iwl_init_hw_rates(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 86a67672598d..58e0462cafa3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -110,6 +110,7 @@ struct iwl_debugfs { struct dentry *file_clear_ucode_statistics; struct dentry *file_clear_traffic_statistics; struct dentry *file_csr; + struct dentry *file_ucode_tracing; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2be3549be01d..822de46e4f34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1867,6 +1867,58 @@ static ssize_t iwl_dbgfs_csr_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_ucode_tracing_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char buf[128]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", + priv->event_log.ucode_trace ? "On" : "Off"); + pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", + priv->event_log.non_wraps_count); + pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", + priv->event_log.wraps_once_count); + pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", + priv->event_log.wraps_more_count); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} + +static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int trace; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &trace) != 1) + return -EFAULT; + + if (trace) { + priv->event_log.ucode_trace = true; + /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ + mod_timer(&priv->ucode_trace, + jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); + } else { + priv->event_log.ucode_trace = false; + del_timer_sync(&priv->ucode_trace); + } + + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1882,6 +1934,7 @@ DEBUGFS_READ_FILE_OPS(power_save_status); DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); DEBUGFS_WRITE_FILE_OPS(csr); +DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); /* * Create the debugfs files and directories @@ -1939,6 +1992,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_tracing, debug, S_IWUSR | S_IRUSR); } DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); DEBUGFS_ADD_BOOL(disable_chain_noise, rf, @@ -2002,6 +2056,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) file_sensitivity); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_chain_noise); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. + file_ucode_tracing); } DEBUGFS_REMOVE(priv->dbgfs->dir_debug); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2673e9a4db92..b3a29c7cdbc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -984,6 +984,32 @@ struct iwl_switch_rxon { __le16 channel; }; +/* + * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds + * to perform continuous uCode event logging operation if enabled + */ +#define UCODE_TRACE_PERIOD (100) + +/* + * iwl_event_log: current uCode event log position + * + * @ucode_trace: enable/disable ucode continuous trace timer + * @num_wraps: how many times the event buffer wraps + * @next_entry: the entry just before the next one that uCode would fill + * @non_wraps_count: counter for no wrap detected when dump ucode events + * @wraps_once_count: counter for wrap once detected when dump ucode events + * @wraps_more_count: counter for wrap more than once detected + * when dump ucode events + */ +struct iwl_event_log { + bool ucode_trace; + u32 num_wraps; + u32 next_entry; + int non_wraps_count; + int wraps_once_count; + int wraps_more_count; +}; + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1261,6 +1287,7 @@ struct iwl_priv { u32 disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list statistics_periodic; + struct timer_list ucode_trace; bool hw_ready; /*For 3945*/ #define IWL_DEFAULT_TX_POWER 0x0F @@ -1268,6 +1295,8 @@ struct iwl_priv { struct iwl3945_notif_statistics statistics_39; u32 sta_supp_rates; + + struct iwl_event_log event_log; }; /*iwl_priv */ static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index e7d88d1da15d..bf46308b17fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -11,4 +11,6 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); +EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); +EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 21361968ab7e..0819f990be6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -64,6 +64,50 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) ); +#undef TRACE_SYSTEM +#define TRACE_SYSTEM iwlwifi_ucode + +TRACE_EVENT(iwlwifi_dev_ucode_cont_event, + TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), + TP_ARGS(priv, time, data, ev), + TP_STRUCT__entry( + PRIV_ENTRY + + __field(u32, time) + __field(u32, data) + __field(u32, ev) + ), + TP_fast_assign( + PRIV_ASSIGN; + __entry->time = time; + __entry->data = data; + __entry->ev = ev; + ), + TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", + __entry->priv, __entry->time, __entry->data, __entry->ev) +); + +TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, + TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry), + TP_ARGS(priv, wraps, n_entry, p_entry), + TP_STRUCT__entry( + PRIV_ENTRY + + __field(u32, wraps) + __field(u32, n_entry) + __field(u32, p_entry) + ), + TP_fast_assign( + PRIV_ASSIGN; + __entry->wraps = wraps; + __entry->n_entry = n_entry; + __entry->p_entry = p_entry; + ), + TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", + __entry->priv, __entry->wraps, __entry->n_entry, + __entry->p_entry) +); + #undef TRACE_SYSTEM #define TRACE_SYSTEM iwlwifi -- cgit v1.2.3 From b03d7d0fd3d23b7cf130fa702f4ae3b1bc827d4b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 14 Dec 2009 14:12:20 -0800 Subject: iwlwifi: on-screen event log dump This feature enables the on-screen uCode event log dump. The original method will append the event log to syslog; with this capability, we also enable the user to write script to capture the events which provide additional flexibility to help uCode debugging Method 1) change to debugfs directory (sys/kernel/debug/phyX/iwlagn/data) 2) #cat log_event Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 104 +++++++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 24 ++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 101 +++++++++++++++++++-------- 6 files changed, 171 insertions(+), 69 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ecc23ec1f6a4..28f6eb5f2cba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -227,7 +227,8 @@ extern void iwl3945_rx_replenish(void *data); extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr,int left); -extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); +extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display); extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4d85c28e38e2..0b3669f317a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1832,8 +1832,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) * iwl_print_event_log - Dump error event log to syslog * */ -static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode) +static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode, + int pos, char **buf, size_t bufsz) { u32 i; u32 base; /* SRAM byte address of event log header */ @@ -1843,7 +1844,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, unsigned long reg_flags; if (num_events == 0) - return; + return pos; if (priv->ucode_type == UCODE_INIT) base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); else @@ -1871,27 +1872,44 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ - trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); - IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOG:0x%08x:%04u\n", + time, ev); + } else { + trace_iwlwifi_dev_ucode_event(priv, 0, + time, ev); + IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", + time, ev); + } } else { data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "EVT_LOGT:%010u:0x%08x:%04u\n", + time, data, ev); + } else { + IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", time, data, ev); - trace_iwlwifi_dev_ucode_event(priv, time, data, ev); + trace_iwlwifi_dev_ucode_event(priv, time, + data, ev); + } } } /* Allow device to power down */ iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return pos; } /** * iwl_print_last_event_logs - Dump the newest # of event log to syslog */ -static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, - u32 num_wraps, u32 next_entry, - u32 size, u32 mode) +static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, + u32 num_wraps, u32 next_entry, + u32 size, u32 mode, + int pos, char **buf, size_t bufsz) { /* * display the newest DEFAULT_LOG_ENTRIES entries @@ -1899,21 +1917,26 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, */ if (num_wraps) { if (next_entry < size) { - iwl_print_event_log(priv, - capacity - (size - next_entry), - size - next_entry, mode); - iwl_print_event_log(priv, 0, - next_entry, mode); + pos = iwl_print_event_log(priv, + capacity - (size - next_entry), + size - next_entry, mode, + pos, buf, bufsz); + pos = iwl_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); } else - iwl_print_event_log(priv, next_entry - size, - size, mode); + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); } else { - if (next_entry < size) - iwl_print_event_log(priv, 0, next_entry, mode); - else - iwl_print_event_log(priv, next_entry - size, - size, mode); + if (next_entry < size) { + pos = iwl_print_event_log(priv, 0, next_entry, + mode, pos, buf, bufsz); + } else { + pos = iwl_print_event_log(priv, next_entry - size, + size, mode, pos, buf, bufsz); + } } + return pos; } /* For sanity check only. Actual size is determined by uCode, typ. 512 */ @@ -1921,7 +1944,8 @@ static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) -void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) +int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display) { u32 base; /* SRAM byte address of event log header */ u32 capacity; /* event log capacity in # entries */ @@ -1929,6 +1953,8 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ u32 size; /* # entries that we'll print */ + int pos = 0; + size_t bufsz = 0; if (priv->ucode_type == UCODE_INIT) base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); @@ -1939,7 +1965,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) IWL_ERR(priv, "Invalid event log pointer 0x%08X for %s uCode\n", base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); - return; + return pos; } /* event log header */ @@ -1965,7 +1991,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) /* bail out if nothing in log */ if (size == 0) { IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return; + return pos; } #ifdef CONFIG_IWLWIFI_DEBUG @@ -1980,6 +2006,15 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) size); #ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + if (full_log) + bufsz = capacity * 48; + else + bufsz = size * 48; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return pos; + } if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { /* * if uCode has wrapped back to top of log, @@ -1987,17 +2022,22 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) * i.e the next one that uCode would fill. */ if (num_wraps) - iwl_print_event_log(priv, next_entry, - capacity - next_entry, mode); + pos = iwl_print_event_log(priv, next_entry, + capacity - next_entry, mode, + pos, buf, bufsz); /* (then/else) start at top of log */ - iwl_print_event_log(priv, 0, next_entry, mode); + pos = iwl_print_event_log(priv, 0, + next_entry, mode, pos, buf, bufsz); } else - iwl_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode); + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); #else - iwl_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode); + pos = iwl_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); #endif + return pos; } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 47ece91e4505..c3c31dc9fd4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1365,7 +1365,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv) priv->cfg->ops->lib->dump_nic_error_log(priv); if (priv->cfg->ops->lib->dump_csr) priv->cfg->ops->lib->dump_csr(priv); - priv->cfg->ops->lib->dump_nic_event_log(priv, false); + priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) iwl_print_rx_config_cmd(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f5e79cf0a318..650d3808d24a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -169,7 +169,8 @@ struct iwl_lib_ops { int (*is_valid_rtc_data_addr)(u32 addr); /* 1st ucode load */ int (*load_ucode)(struct iwl_priv *priv); - void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); + int (*dump_nic_event_log)(struct iwl_priv *priv, + bool full_log, char **buf, bool display); void (*dump_nic_error_log)(struct iwl_priv *priv); void (*dump_csr)(struct iwl_priv *priv); int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); @@ -582,7 +583,8 @@ int iwl_pci_resume(struct pci_dev *pdev); * Error Handling Debugging ******************************************************/ void iwl_dump_nic_error_log(struct iwl_priv *priv); -void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); +int iwl_dump_nic_event_log(struct iwl_priv *priv, + bool full_log, char **buf, bool display); void iwl_dump_csr(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 822de46e4f34..ee5aed12a4b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -420,6 +420,23 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, return ret; } +static ssize_t iwl_dbgfs_log_event_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -ENOMEM; + + pos = priv->cfg->ops->lib->dump_nic_event_log(priv, true, &buf, true); + if (pos && buf) { + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + } + return ret; +} + static ssize_t iwl_dbgfs_log_event_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) @@ -436,7 +453,8 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, if (sscanf(buf, "%d", &event_log_flag) != 1) return -EFAULT; if (event_log_flag == 1) - priv->cfg->ops->lib->dump_nic_event_log(priv, true); + priv->cfg->ops->lib->dump_nic_event_log(priv, true, + NULL, false); return count; } @@ -859,7 +877,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, } DEBUGFS_READ_WRITE_FILE_OPS(sram); -DEBUGFS_WRITE_FILE_OPS(log_event); +DEBUGFS_READ_WRITE_FILE_OPS(log_event); DEBUGFS_READ_FILE_OPS(nvm); DEBUGFS_READ_FILE_OPS(stations); DEBUGFS_READ_FILE_OPS(channels); @@ -1965,7 +1983,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(log_event, data, S_IWUSR); + DEBUGFS_ADD_FILE(log_event, data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(stations, data, S_IRUSR); DEBUGFS_ADD_FILE(channels, data, S_IRUSR); DEBUGFS_ADD_FILE(status, data, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2a28a1f8b1fe..f7c7ff4264fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1560,8 +1560,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) * iwl3945_print_event_log - Dump error event log to syslog * */ -static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode) +static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, + u32 num_events, u32 mode, + int pos, char **buf, size_t bufsz) { u32 i; u32 base; /* SRAM byte address of event log header */ @@ -1571,7 +1572,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, unsigned long reg_flags; if (num_events == 0) - return; + return pos; base = le32_to_cpu(priv->card_alive.log_event_table_ptr); @@ -1597,26 +1598,43 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (mode == 0) { /* data, ev */ - IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); - trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "0x%08x:%04u\n", + time, ev); + } else { + IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); + trace_iwlwifi_dev_ucode_event(priv, 0, + time, ev); + } } else { data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); - trace_iwlwifi_dev_ucode_event(priv, time, data, ev); + if (bufsz) { + pos += scnprintf(*buf + pos, bufsz - pos, + "%010u:0x%08x:%04u\n", + time, data, ev); + } else { + IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", + time, data, ev); + trace_iwlwifi_dev_ucode_event(priv, time, + data, ev); + } } } /* Allow device to power down */ iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->reg_lock, reg_flags); + return pos; } /** * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog */ -static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, +static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, u32 num_wraps, u32 next_entry, - u32 size, u32 mode) + u32 size, u32 mode, + int pos, char **buf, size_t bufsz) { /* * display the newest DEFAULT_LOG_ENTRIES entries @@ -1624,21 +1642,28 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, */ if (num_wraps) { if (next_entry < size) { - iwl3945_print_event_log(priv, - capacity - (size - next_entry), - size - next_entry, mode); - iwl3945_print_event_log(priv, 0, - next_entry, mode); + pos = iwl3945_print_event_log(priv, + capacity - (size - next_entry), + size - next_entry, mode, + pos, buf, bufsz); + pos = iwl3945_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); } else - iwl3945_print_event_log(priv, next_entry - size, - size, mode); + pos = iwl3945_print_event_log(priv, next_entry - size, + size, mode, + pos, buf, bufsz); } else { if (next_entry < size) - iwl3945_print_event_log(priv, 0, next_entry, mode); + pos = iwl3945_print_event_log(priv, 0, + next_entry, mode, + pos, buf, bufsz); else - iwl3945_print_event_log(priv, next_entry - size, - size, mode); + pos = iwl3945_print_event_log(priv, next_entry - size, + size, mode, + pos, buf, bufsz); } + return pos; } /* For sanity check only. Actual size is determined by uCode, typ. 512 */ @@ -1646,7 +1671,8 @@ static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) -void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) +int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, + char **buf, bool display) { u32 base; /* SRAM byte address of event log header */ u32 capacity; /* event log capacity in # entries */ @@ -1654,11 +1680,13 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) u32 num_wraps; /* # times uCode wrapped to top of log */ u32 next_entry; /* index of next entry to be written by uCode */ u32 size; /* # entries that we'll print */ + int pos = 0; + size_t bufsz = 0; base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!iwl3945_hw_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return; + return pos; } /* event log header */ @@ -1684,7 +1712,7 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) /* bail out if nothing in log */ if (size == 0) { IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return; + return pos; } #ifdef CONFIG_IWLWIFI_DEBUG @@ -1700,25 +1728,38 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) size); #ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + if (full_log) + bufsz = capacity * 48; + else + bufsz = size * 48; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return pos; + } if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { /* if uCode has wrapped back to top of log, * start at the oldest entry, * i.e the next one that uCode would fill. */ if (num_wraps) - iwl3945_print_event_log(priv, next_entry, - capacity - next_entry, mode); + pos = iwl3945_print_event_log(priv, next_entry, + capacity - next_entry, mode, + pos, buf, bufsz); /* (then/else) start at top of log */ - iwl3945_print_event_log(priv, 0, next_entry, mode); + pos = iwl3945_print_event_log(priv, 0, next_entry, mode, + pos, buf, bufsz); } else - iwl3945_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode); + pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); #else - iwl3945_print_last_event_logs(priv, capacity, num_wraps, - next_entry, size, mode); + pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, + next_entry, size, mode, + pos, buf, bufsz); #endif - + return pos; } static void iwl3945_irq_tasklet(struct iwl_priv *priv) -- cgit v1.2.3 From 4309af2735825115a982acf4c2c868b5c5671e7f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 14 Dec 2009 14:12:21 -0800 Subject: iwlwifi: remove extra error msg on sensitivity calibration Do not need to log error when fail the sensitivity command, driver will send sensitivity write command to uCode after each sensitivity calibration if station is associated with AP. It is a normal case when user unload the module or shutdown the system while still associated with the AP, since uCode already on the way down, it will not reply the sensitivity write request; report error in this case will give misleading information, remove the error checking here to provide a clean shutdown if no other error detected. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-calib.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 95a57b36a7ea..dc61906290e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -414,7 +414,6 @@ static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ static int iwl_sensitivity_write(struct iwl_priv *priv) { - int ret = 0; struct iwl_sensitivity_cmd cmd ; struct iwl_sensitivity_data *data = NULL; struct iwl_host_cmd cmd_out = { @@ -477,11 +476,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - ret = iwl_send_cmd(priv, &cmd_out); - if (ret) - IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); - - return ret; + return iwl_send_cmd(priv, &cmd_out); } void iwl_init_sensitivity(struct iwl_priv *priv) -- cgit v1.2.3 From 050e8a47dc8b056c880f380ffd01055669f8fe68 Mon Sep 17 00:00:00 2001 From: Kenichi HORIO Date: Fri, 4 Dec 2009 23:46:56 +0100 Subject: rt73usb: add WLI-U2-H54HP Signed-off-by: Kenichi HORIO Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ced3b6ab5e16..6ce88d3c3b65 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2354,6 +2354,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, /* Buffalo */ { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, -- cgit v1.2.3 From c70762f9acad654002704f1e53436a0ba3356c31 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Fri, 4 Dec 2009 23:46:57 +0100 Subject: rt2x00 : bail out of regbusy_read if device is removed. platform rfkill is async thus we may try to read while the device is already off. Signed-off-by: Alban Browaeys Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0feb4d0e4668..801be436cf1d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -41,6 +41,9 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, { unsigned int i; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return 0; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, offset, reg); if (!rt2x00_get_field32(*reg, field)) -- cgit v1.2.3 From 6a325d856bc4509f29164fe42501b6909cf57dcf Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Fri, 4 Dec 2009 23:46:58 +0100 Subject: rt2x00 : modify padding location. The padding is to be added between header and payload for the only header need padding case. Signed-off-by: Benoit PAPILLAULT Signed-off-by: Alban Browaeys Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 239afc7a9c0b..842c4e3c83ca 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -197,7 +197,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) * the payload is already properly aligned. */ skb_push(skb, header_align); - memmove(skb->data, skb->data + header_align, frame_length); + memmove(skb->data, skb->data + header_align, header_length); skbdesc->flags |= SKBDESC_L2_PADDED; } else { /* -- cgit v1.2.3 From e81e0aef32bfa7f593b14479b9c7eaa7196798ac Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Fri, 4 Dec 2009 23:46:59 +0100 Subject: rt2x00 : avoid timestamp for monitor injected frame. Do not include timestamp for a frame that has been injected through a monitor interface. Signed-off-by: Benoit PAPILLAULT Signed-off-by: Alban Browaeys Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 842c4e3c83ca..b8f09547787d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -387,10 +387,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Beacons and probe responses require the tsf timestamp - * to be inserted into the frame. + * to be inserted into the frame, except for a frame that has been injected + * through a monitor interface. This latter is needed for testing a + * monitor interface. */ - if (ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_probe_resp(hdr->frame_control)) + if ((ieee80211_is_beacon(hdr->frame_control) || + ieee80211_is_probe_resp(hdr->frame_control)) && + (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED))) __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); /* -- cgit v1.2.3 From 1398d4580eff2656f3a808ec24744ce5a842db35 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Fri, 4 Dec 2009 23:47:00 +0100 Subject: rt2x00 : trim the skb after having the l2pad removed. Otherwise we end up truncating the skb before removing the l2pad thus we might have the truncated part become garbage while getting it back in remove_l2pad. For the same issue: remove the skb_trim from the rt2800 fill_rxdone (it is done after l2pad removal in rt2x00lib_rxdone). Signed-off-by: Alban Browaeys Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 1 - drivers/net/wireless/rt2x00/rt2800usb.c | 1 - drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index dfc886fcb44d..6fcb2bb840b2 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -927,7 +927,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, * Remove TXWI descriptor from start of buffer. */ skb_pull(entry->skb, RXWI_DESC_SIZE); - skb_trim(entry->skb, rxdesc->size); } /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index af85d18cdbe7..1db8667a6ff1 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -663,7 +663,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, * Remove RXWI descriptor from start of buffer. */ skb_pull(entry->skb, skbdesc->desc_len); - skb_trim(entry->skb, rxdesc->size); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 06c43ca39bf8..cc6bcc5a20c7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -385,9 +385,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - /* Trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); - /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. @@ -409,6 +406,9 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, else rt2x00queue_align_payload(entry->skb, header_length); + /* Trim buffer to correct size */ + skb_trim(entry->skb, rxdesc.size); + /* * Check if the frame was received using HT. In that case, * the rate is the MCS index and should be passed to mac80211 -- cgit v1.2.3 From 77e73d1849c860d22ebba8826ad162ccfda4c535 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 4 Dec 2009 23:47:01 +0100 Subject: rt2x00: Further L2 padding fixes. Fix a couple of more bugs in the L2 padding code: 1. Compute the amount of L2 padding correctly (in 3 places). 2. Trim the skb correctly when the L2 padding has been applied. Also introduce a central macro the compute the L2 padding size. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++++ drivers/net/wireless/rt2x00/rt2x00queue.c | 8 +++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4d841c07c970..194dae01d0c3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -103,6 +103,12 @@ #define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate)) #define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) +/* + * Determine the number of L2 padding bytes required between the header and + * the payload. + */ +#define L2PAD_SIZE(__hdrlen) (-(__hdrlen) & 3) + /* * Determine the alignment requirement, * to make sure the 802.11 payload is padded to a 4-byte boundrary diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index b8f09547787d..21d58769a1a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -181,7 +181,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) unsigned int frame_length = skb->len; unsigned int header_align = ALIGN_SIZE(skb, 0); unsigned int payload_align = ALIGN_SIZE(skb, header_length); - unsigned int l2pad = 4 - (payload_align - header_align); + unsigned int l2pad = L2PAD_SIZE(header_length); if (header_align == payload_align) { /* @@ -216,6 +216,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) memmove(skb->data + header_length + l2pad, skb->data + header_length + l2pad + payload_align, frame_length - header_length); + skb_trim(skb, frame_length + l2pad); skbdesc->flags |= SKBDESC_L2_PADDED; } } @@ -223,7 +224,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int l2pad = 4 - (header_length & 3); + unsigned int l2pad = L2PAD_SIZE(header_length); if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) return; @@ -346,7 +347,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Header and alignment information. */ txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); /* * Check whether this frame is to be acked. -- cgit v1.2.3 From 354e39dbb19f29ef28a9c2db9e55ff2a7435b35a Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 4 Dec 2009 23:47:02 +0100 Subject: rt2x00: Remove SKBDESC_L2_PADDED flag. With the improved L2 padding code, this flag is no longer necessary, as the rt2x00queue_remove_l2pad is capable of detecting by itself if L2 padding is applied. For received frames the RX descriptor flag is still being checked. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 5 +---- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +--- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 +----- drivers/net/wireless/rt2x00/rt2x00queue.h | 5 +---- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 6fcb2bb840b2..458378c4e500 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -835,7 +835,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); struct queue_entry_priv_pci *entry_priv = entry->priv_data; __le32 *rxd = entry_priv->desc; __le32 *rxwi = (__le32 *)entry->skb->data; @@ -883,10 +882,8 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { + if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; - skbdesc->flags |= SKBDESC_L2_PADDED; - } if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) rxdesc->flags |= RX_FLAG_SHORT_GI; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 1db8667a6ff1..13baec485eb6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -625,10 +625,8 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) { + if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; - skbdesc->flags |= SKBDESC_L2_PADDED; - } if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) rxdesc->flags |= RX_FLAG_SHORT_GI; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 21d58769a1a7..719f4aebcaf6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -177,7 +177,6 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int frame_length = skb->len; unsigned int header_align = ALIGN_SIZE(skb, 0); unsigned int payload_align = ALIGN_SIZE(skb, header_length); @@ -198,7 +197,6 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) */ skb_push(skb, header_align); memmove(skb->data, skb->data + header_align, header_length); - skbdesc->flags |= SKBDESC_L2_PADDED; } else { /* * @@ -217,16 +215,14 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) skb->data + header_length + l2pad + payload_align, frame_length - header_length); skb_trim(skb, frame_length + l2pad); - skbdesc->flags |= SKBDESC_L2_PADDED; } } void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int l2pad = L2PAD_SIZE(header_length); - if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) + if (!l2pad) return; memmove(skb->data + l2pad, skb->data, header_length); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 70775e5ba1ac..c1e482bb37b3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -92,8 +92,6 @@ enum data_queue_qid { * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by * mac80211 but was stripped for processing by the driver. - * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, - * the padded bytes are located between header and payload. * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, * don't try to pass it back. */ @@ -101,8 +99,7 @@ enum skb_frame_desc_flags { SKBDESC_DMA_MAPPED_RX = 1 << 0, SKBDESC_DMA_MAPPED_TX = 1 << 1, SKBDESC_IV_STRIPPED = 1 << 2, - SKBDESC_L2_PADDED = 1 << 3, - SKBDESC_NOT_MAC80211 = 1 << 4, + SKBDESC_NOT_MAC80211 = 1 << 3, }; /** -- cgit v1.2.3 From 2e331462fcb3d897921d8a0af4fca1b08c1b7269 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 4 Dec 2009 23:47:03 +0100 Subject: rt2x00: Reorganize L2 padding inserting function. Simplify the rt2x00queue_insert_l2pad function by handling the alignment operations one by one. Do not special case special circumstances. Basically first perform header alignment, and then perform payload alignment (if any payload does exist). This results in a properly aligned skb. The end result is better readable code, with better results, as now L2 padding is inserted only when a payload is actually present in the frame. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 60 ++++++++++++++----------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 719f4aebcaf6..7452fa850a0f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -177,45 +177,38 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) { - unsigned int frame_length = skb->len; + unsigned int payload_length = skb->len - header_length; unsigned int header_align = ALIGN_SIZE(skb, 0); unsigned int payload_align = ALIGN_SIZE(skb, header_length); unsigned int l2pad = L2PAD_SIZE(header_length); - if (header_align == payload_align) { - /* - * Both header and payload must be moved the same - * amount of bytes to align them properly. This means - * we don't use the L2 padding but just move the entire - * frame. - */ - rt2x00queue_align_frame(skb); - } else if (!payload_align) { - /* - * Simple L2 padding, only the header needs to be moved, - * the payload is already properly aligned. - */ - skb_push(skb, header_align); - memmove(skb->data, skb->data + header_align, header_length); - } else { - /* - * - * Complicated L2 padding, both header and payload need - * to be moved. By default we only move to the start - * of the buffer, so our header alignment needs to be - * increased if there is not enough room for the header - * to be moved. - */ - if (payload_align > header_align) - header_align += 4; + /* + * Adjust the header alignment if the payload needs to be moved more + * than the header. + */ + if (payload_align > header_align) + header_align += 4; + + /* There is nothing to do if no alignment is needed */ + if (!header_align) + return; - skb_push(skb, header_align); - memmove(skb->data, skb->data + header_align, header_length); + /* Reserve the amount of space needed in front of the frame */ + skb_push(skb, header_align); + + /* + * Move the header. + */ + memmove(skb->data, skb->data + header_align, header_length); + + /* Move the payload, if present and if required */ + if (payload_length && payload_align) memmove(skb->data + header_length + l2pad, skb->data + header_length + l2pad + payload_align, - frame_length - header_length); - skb_trim(skb, frame_length + l2pad); - } + payload_length); + + /* Trim the skb to the correct size */ + skb_trim(skb, header_length + l2pad + payload_length); } void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) @@ -343,7 +336,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Header and alignment information. */ txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) + if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && + (entry->skb->len > txdesc->header_length)) txdesc->l2pad = L2PAD_SIZE(txdesc->header_length); /* -- cgit v1.2.3 From b734083349d1f1aab1edc810cef02e8046251b48 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 4 Dec 2009 23:47:04 +0100 Subject: rt2x00: Only remove L2 padding in received frames if there is payload. L2 padding will only be present when there is actual payload present. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cc6bcc5a20c7..d7711e4d4751 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -401,7 +401,9 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, (rxdesc.flags & RX_FLAG_IV_STRIPPED)) rt2x00crypto_rx_insert_iv(entry->skb, header_length, &rxdesc); - else if (rxdesc.dev_flags & RXDONE_L2PAD) + else if (header_length && + (rxdesc.size > header_length) && + (rxdesc.dev_flags & RXDONE_L2PAD)) rt2x00queue_remove_l2pad(entry->skb, header_length); else rt2x00queue_align_payload(entry->skb, header_length); -- cgit v1.2.3 From 9c8427d9deca1c0c2415c8da0e731e13fc89d111 Mon Sep 17 00:00:00 2001 From: Benoit PAPILLAULT Date: Fri, 4 Dec 2009 23:47:05 +0100 Subject: rt2x00: Disable RX aggregation for rt2800usb RX aggregation is a way to receive multiple 802.11 frames in one RX buffer. However, we don't know yet how to handle this case in rt2800usb_fill_rxdone and this has probably no impact on RX performance as well, so we disable it Signed-off-by: Benoit Papillault Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 13baec485eb6..9c4412b42e5b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -295,9 +295,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); - /* Don't use bulk in aggregation when working with USB 1.1 */ - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, - (rt2x00dev->rx->usb_maxpacket == 512)); + rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0); rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); /* * Total room for RX frames in kilobytes, PBF might still exceed -- cgit v1.2.3 From 5de42f9eeafa7d54ffb833e0526d4828e194fddb Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Fri, 4 Dec 2009 23:47:06 +0100 Subject: rt2x00: Fix rt2800usb RX frame format and as such L2PAD According to Ralink source code, the RX frame format is RXINFO + RXWI + 802.11 frame + RXD, including various padding. Before this patch, we were using RXD + RXWI + 802.11 frame, so RXD was not correct. Doing this, we fix the L2PAD bit which is now correctly set on received frames. Signed-off-by: Benoit Papillault Acked-by: Ivo van Doorn Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800usb.c | 38 ++++++++++---- drivers/net/wireless/rt2x00/rt2800usb.h | 90 +++++++++++++++++++++++++-------- 2 files changed, 97 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 9c4412b42e5b..40295b454ff6 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -571,41 +571,57 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - __le32 *rxd = (__le32 *)entry->skb->data; + __le32 *rxi = (__le32 *)entry->skb->data; __le32 *rxwi; - u32 rxd0; + __le32 *rxd; + u32 rxi0; u32 rxwi0; u32 rxwi1; u32 rxwi2; u32 rxwi3; + u32 rxd0; + int rx_pkt_len; + + /* + * RX frame format is : + * | RXINFO | RXWI | header | L2 pad | payload | pad | RXD | USB pad | + * |<------------ rx_pkt_len -------------->| + */ + rt2x00_desc_read(rxi, 0, &rxi0); + rx_pkt_len = rt2x00_get_field32(rxi0, RXINFO_W0_USB_DMA_RX_PKT_LEN); + + rxwi = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE); + + /* + * FIXME : we need to check for rx_pkt_len validity + */ + rxd = (__le32 *)(entry->skb->data + RXINFO_DESC_SIZE + rx_pkt_len); /* * Copy descriptor to the skbdesc->desc buffer, making it safe from * moving of frame data in rt2x00usb. */ - memcpy(skbdesc->desc, rxd, skbdesc->desc_len); - rxd = (__le32 *)skbdesc->desc; - rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)]; + memcpy(skbdesc->desc, rxi, skbdesc->desc_len); /* * It is now safe to read the descriptor on all architectures. */ - rt2x00_desc_read(rxd, 0, &rxd0); rt2x00_desc_read(rxwi, 0, &rxwi0); rt2x00_desc_read(rxwi, 1, &rxwi1); rt2x00_desc_read(rxwi, 2, &rxwi2); rt2x00_desc_read(rxwi, 3, &rxwi3); + rt2x00_desc_read(rxd, 0, &rxd0); - if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR)) + if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); rxdesc->cipher_status = - rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR); + rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); } - if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) { + if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { /* * Hardware has stripped IV/EIV data from 802.11 frame during * decryption. Unfortunately the descriptor doesn't contain @@ -620,10 +636,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, rxdesc->flags |= RX_FLAG_MMIC_ERROR; } - if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS)) + if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) rxdesc->dev_flags |= RXDONE_MY_BSS; - if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) + if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) rxdesc->dev_flags |= RXDONE_L2PAD; if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 1e4340a182ef..d1d8ae94b4d4 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -79,6 +79,8 @@ */ #define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) #define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) +#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) +#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) /* * TX Info structure @@ -100,6 +102,54 @@ #define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) #define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) +/* + * RX Info structure + */ + +/* + * Word 0 + */ + +#define RXINFO_W0_USB_DMA_RX_PKT_LEN FIELD32(0x0000ffff) + +/* + * RX WI structure + */ + +/* + * Word0 + */ +#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) +#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) +#define RXWI_W0_BSSID FIELD32(0x00001c00) +#define RXWI_W0_UDF FIELD32(0x0000e000) +#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) +#define RXWI_W0_TID FIELD32(0xf0000000) + +/* + * Word1 + */ +#define RXWI_W1_FRAG FIELD32(0x0000000f) +#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) +#define RXWI_W1_MCS FIELD32(0x007f0000) +#define RXWI_W1_BW FIELD32(0x00800000) +#define RXWI_W1_SHORT_GI FIELD32(0x01000000) +#define RXWI_W1_STBC FIELD32(0x06000000) +#define RXWI_W1_PHYMODE FIELD32(0xc0000000) + +/* + * Word2 + */ +#define RXWI_W2_RSSI0 FIELD32(0x000000ff) +#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) +#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) + +/* + * Word3 + */ +#define RXWI_W3_SNR0 FIELD32(0x000000ff) +#define RXWI_W3_SNR1 FIELD32(0x0000ff00) + /* * RX descriptor format for RX Ring. */ @@ -115,25 +165,25 @@ * AMSDU: rx with 802.3 header, not 802.11 header. */ -#define RXINFO_W0_BA FIELD32(0x00000001) -#define RXINFO_W0_DATA FIELD32(0x00000002) -#define RXINFO_W0_NULLDATA FIELD32(0x00000004) -#define RXINFO_W0_FRAG FIELD32(0x00000008) -#define RXINFO_W0_UNICAST_TO_ME FIELD32(0x00000010) -#define RXINFO_W0_MULTICAST FIELD32(0x00000020) -#define RXINFO_W0_BROADCAST FIELD32(0x00000040) -#define RXINFO_W0_MY_BSS FIELD32(0x00000080) -#define RXINFO_W0_CRC_ERROR FIELD32(0x00000100) -#define RXINFO_W0_CIPHER_ERROR FIELD32(0x00000600) -#define RXINFO_W0_AMSDU FIELD32(0x00000800) -#define RXINFO_W0_HTC FIELD32(0x00001000) -#define RXINFO_W0_RSSI FIELD32(0x00002000) -#define RXINFO_W0_L2PAD FIELD32(0x00004000) -#define RXINFO_W0_AMPDU FIELD32(0x00008000) -#define RXINFO_W0_DECRYPTED FIELD32(0x00010000) -#define RXINFO_W0_PLCP_RSSI FIELD32(0x00020000) -#define RXINFO_W0_CIPHER_ALG FIELD32(0x00040000) -#define RXINFO_W0_LAST_AMSDU FIELD32(0x00080000) -#define RXINFO_W0_PLCP_SIGNAL FIELD32(0xfff00000) +#define RXD_W0_BA FIELD32(0x00000001) +#define RXD_W0_DATA FIELD32(0x00000002) +#define RXD_W0_NULLDATA FIELD32(0x00000004) +#define RXD_W0_FRAG FIELD32(0x00000008) +#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) +#define RXD_W0_MULTICAST FIELD32(0x00000020) +#define RXD_W0_BROADCAST FIELD32(0x00000040) +#define RXD_W0_MY_BSS FIELD32(0x00000080) +#define RXD_W0_CRC_ERROR FIELD32(0x00000100) +#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) +#define RXD_W0_AMSDU FIELD32(0x00000800) +#define RXD_W0_HTC FIELD32(0x00001000) +#define RXD_W0_RSSI FIELD32(0x00002000) +#define RXD_W0_L2PAD FIELD32(0x00004000) +#define RXD_W0_AMPDU FIELD32(0x00008000) +#define RXD_W0_DECRYPTED FIELD32(0x00010000) +#define RXD_W0_PLCP_RSSI FIELD32(0x00020000) +#define RXD_W0_CIPHER_ALG FIELD32(0x00040000) +#define RXD_W0_LAST_AMSDU FIELD32(0x00080000) +#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) #endif /* RT2800USB_H */ -- cgit v1.2.3 From e54be4e7356c0612b48407d3b0647a29cb82e254 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Fri, 4 Dec 2009 23:47:07 +0100 Subject: rt2x00: Fix trimming of L2 padded frames. Ensure that frames without payload are properly trimmed in rt2x00queue_insert_l2pad. This should fix the bug reported by Benoit Papillault in: http://marc.info/?l=linux-wireless&m=125974773006734&w=2 Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 7452fa850a0f..3d8fb684b4eb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -180,7 +180,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) unsigned int payload_length = skb->len - header_length; unsigned int header_align = ALIGN_SIZE(skb, 0); unsigned int payload_align = ALIGN_SIZE(skb, header_length); - unsigned int l2pad = L2PAD_SIZE(header_length); + unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; /* * Adjust the header alignment if the payload needs to be moved more -- cgit v1.2.3 From ca99861d5421c91f5a8fd3a77acb4b7be14f119d Mon Sep 17 00:00:00 2001 From: gregor kowski Date: Wed, 9 Dec 2009 23:25:05 +0100 Subject: mac80211 : fix a race with update_tkip_key The mac80211 tkip code won't call update_tkip_key, if rx packets are received without KEY_FLAG_UPLOADED_TO_HARDWARE. This can happen on first packet because the hardware key stuff is called asynchronously with todo workqueue. This patch workaround that by tracking if we sent the key to the driver. Signed-off-by: Gregor Kowski Signed-off-by: John W. Linville --- net/mac80211/key.h | 8 +++++++- net/mac80211/tkip.c | 38 ++++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/net/mac80211/key.h b/net/mac80211/key.h index a49f93b79e92..bdc2968c2bbe 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -59,11 +59,17 @@ enum ieee80211_internal_key_flags { KEY_FLAG_TODO_DEFMGMTKEY = BIT(6), }; +enum ieee80211_internal_tkip_state { + TKIP_STATE_NOT_INIT, + TKIP_STATE_PHASE1_DONE, + TKIP_STATE_PHASE1_HW_UPLOADED, +}; + struct tkip_ctx { u32 iv32; u16 iv16; u16 p1k[5]; - int initialized; + enum ieee80211_internal_tkip_state state; }; struct ieee80211_key { diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 4921d724b6c7..b73454a507f9 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -100,7 +100,7 @@ static void tkip_mixing_phase1(const u8 *tk, struct tkip_ctx *ctx, p1k[3] += tkipS(p1k[2] ^ get_unaligned_le16(tk + 12 + j)); p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i; } - ctx->initialized = 1; + ctx->state = TKIP_STATE_PHASE1_DONE; } static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx, @@ -183,7 +183,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, /* Update the p1k only when the iv16 in the packet wraps around, this * might occur after the wrap around of iv16 in the key in case of * fragmented packets. */ - if (iv16 == 0 || !ctx->initialized) + if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32); if (type == IEEE80211_TKIP_P1_KEY) { @@ -209,7 +209,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; /* Calculate per-packet key */ - if (ctx->iv16 == 0 || !ctx->initialized) + if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT) tkip_mixing_phase1(tk, ctx, ta, ctx->iv32); tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); @@ -259,7 +259,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if ((keyid >> 6) != key->conf.keyidx) return TKIP_DECRYPT_INVALID_KEYIDX; - if (key->u.tkip.rx[queue].initialized && + if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT && (iv32 < key->u.tkip.rx[queue].iv32 || (iv32 == key->u.tkip.rx[queue].iv32 && iv16 <= key->u.tkip.rx[queue].iv16))) { @@ -275,11 +275,11 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if (only_iv) { res = TKIP_DECRYPT_OK; - key->u.tkip.rx[queue].initialized = 1; + key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; goto done; } - if (!key->u.tkip.rx[queue].initialized || + if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT || key->u.tkip.rx[queue].iv32 != iv32) { /* IV16 wrapped around - perform TKIP phase 1 */ tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); @@ -299,18 +299,20 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, printk("\n"); } #endif - if (key->local->ops->update_tkip_key && - key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { - static const u8 bcast[ETH_ALEN] = - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *sta_addr = key->sta->sta.addr; - - if (is_multicast_ether_addr(ra)) - sta_addr = bcast; - - drv_update_tkip_key(key->local, &key->conf, sta_addr, - iv32, key->u.tkip.rx[queue].p1k); - } + } + if (key->local->ops->update_tkip_key && + key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && + key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { + static const u8 bcast[ETH_ALEN] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const u8 *sta_addr = key->sta->sta.addr; + + if (is_multicast_ether_addr(ra)) + sta_addr = bcast; + + drv_update_tkip_key(key->local, &key->conf, sta_addr, + iv32, key->u.tkip.rx[queue].p1k); + key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; } tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); -- cgit v1.2.3 From eaf85ca7fecb218fc41ff57c1642ca73b097aabb Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Dec 2009 10:18:37 +0800 Subject: wireless: add ieee80211_amsdu_to_8023s Move the A-MSDU handling code from mac80211 to cfg80211 so that more drivers can use it. The new created function ieee80211_amsdu_to_8023s converts an A-MSDU frame to a list of 802.3 frames. Cc: Johannes Berg Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- include/net/cfg80211.h | 22 +++++++++- net/mac80211/rx.c | 106 ++++++++++--------------------------------------- net/wireless/util.c | 99 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 90 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0884b9a0f778..542a477a94da 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1578,7 +1578,7 @@ unsigned int ieee80211_hdrlen(__le16 fc); * @addr: the device MAC address * @iftype: the virtual interface type */ -int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, +int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype); /** @@ -1589,9 +1589,27 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, * @bssid: the network bssid (used only for iftype STATION and ADHOC) * @qos: build 802.11 QoS data frame */ -int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, +int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype, u8 *bssid, bool qos); +/** + * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame + * + * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of + * 802.3 frames. The @list will be empty if the decode fails. The + * @skb is consumed after the function returns. + * + * @skb: The input IEEE 802.11n A-MSDU frame. + * @list: The output list of 802.3 frames. It must be allocated and + * initialized by by the caller. + * @addr: The device MAC address. + * @iftype: The device interface type. + * @extra_headroom: The hardware extra headroom for SKBs in the @list. + */ +void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, + const u8 *addr, enum nl80211_iftype iftype, + const unsigned int extra_headroom); + /** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame * @skb: the data frame diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index dbfd684e3e2e..a182e423109b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1541,16 +1541,10 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) { struct net_device *dev = rx->sdata->dev; - struct ieee80211_local *local = rx->local; - u16 ethertype; - u8 *payload; - struct sk_buff *skb = rx->skb, *frame = NULL; + struct sk_buff *skb = rx->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; - const struct ethhdr *eth; - int remaining, err; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; + struct sk_buff_head frame_list; if (unlikely(!ieee80211_is_data(fc))) return RX_CONTINUE; @@ -1561,94 +1555,34 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_AMSDU)) return RX_CONTINUE; - err = __ieee80211_data_to_8023(rx); - if (unlikely(err)) + if (ieee80211_has_a4(hdr->frame_control) && + rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !rx->sdata->u.vlan.sta) return RX_DROP_UNUSABLE; - skb->dev = dev; - - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - - /* skip the wrapping header */ - eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); - if (!eth) + if (is_multicast_ether_addr(hdr->addr1) && + ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + rx->sdata->u.vlan.sta) || + (rx->sdata->vif.type == NL80211_IFTYPE_STATION && + rx->sdata->u.mgd.use_4addr))) return RX_DROP_UNUSABLE; - while (skb != frame) { - u8 padding; - __be16 len = eth->h_proto; - unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); - - remaining = skb->len; - memcpy(dst, eth->h_dest, ETH_ALEN); - memcpy(src, eth->h_source, ETH_ALEN); + skb->dev = dev; + __skb_queue_head_init(&frame_list); - padding = ((4 - subframe_len) & 0x3); - /* the last MSDU has no padding */ - if (subframe_len > remaining) - return RX_DROP_UNUSABLE; + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, + rx->sdata->vif.type, + rx->local->hw.extra_tx_headroom); - skb_pull(skb, sizeof(struct ethhdr)); - /* if last subframe reuse skb */ - if (remaining <= subframe_len + padding) - frame = skb; - else { - /* - * Allocate and reserve two bytes more for payload - * alignment since sizeof(struct ethhdr) is 14. - */ - frame = dev_alloc_skb( - ALIGN(local->hw.extra_tx_headroom, 4) + - subframe_len + 2); - - if (frame == NULL) - return RX_DROP_UNUSABLE; - - skb_reserve(frame, - ALIGN(local->hw.extra_tx_headroom, 4) + - sizeof(struct ethhdr) + 2); - memcpy(skb_put(frame, ntohs(len)), skb->data, - ntohs(len)); - - eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + - padding); - if (!eth) { - dev_kfree_skb(frame); - return RX_DROP_UNUSABLE; - } - } - - skb_reset_network_header(frame); - frame->dev = dev; - frame->priority = skb->priority; - rx->skb = frame; - - payload = frame->data; - ethertype = (payload[6] << 8) | payload[7]; - - if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - compare_ether_addr(payload, - bridge_tunnel_header) == 0)) { - /* remove RFC1042 or Bridge-Tunnel - * encapsulation and replace EtherType */ - skb_pull(frame, 6); - memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); - } else { - memcpy(skb_push(frame, sizeof(__be16)), - &len, sizeof(__be16)); - memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); - } + while (!skb_queue_empty(&frame_list)) { + rx->skb = __skb_dequeue(&frame_list); if (!ieee80211_frame_allowed(rx, fc)) { - if (skb == frame) /* last frame */ - return RX_DROP_UNUSABLE; - dev_kfree_skb(frame); + dev_kfree_skb(rx->skb); continue; } + dev->stats.rx_packets++; + dev->stats.rx_bytes += rx->skb->len; ieee80211_deliver_skb(rx); } diff --git a/net/wireless/util.c b/net/wireless/util.c index a3c841a255db..23557c1d0a9c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -285,7 +285,7 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) } } -int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, +int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; @@ -383,7 +383,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr, } EXPORT_SYMBOL(ieee80211_data_to_8023); -int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, +int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype, u8 *bssid, bool qos) { struct ieee80211_hdr hdr; @@ -497,6 +497,101 @@ int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr, } EXPORT_SYMBOL(ieee80211_data_from_8023); + +void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, + const u8 *addr, enum nl80211_iftype iftype, + const unsigned int extra_headroom) +{ + struct sk_buff *frame = NULL; + u16 ethertype; + u8 *payload; + const struct ethhdr *eth; + int remaining, err; + u8 dst[ETH_ALEN], src[ETH_ALEN]; + + err = ieee80211_data_to_8023(skb, addr, iftype); + if (err) + goto out; + + /* skip the wrapping header */ + eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); + if (!eth) + goto out; + + while (skb != frame) { + u8 padding; + __be16 len = eth->h_proto; + unsigned int subframe_len = sizeof(struct ethhdr) + ntohs(len); + + remaining = skb->len; + memcpy(dst, eth->h_dest, ETH_ALEN); + memcpy(src, eth->h_source, ETH_ALEN); + + padding = (4 - subframe_len) & 0x3; + /* the last MSDU has no padding */ + if (subframe_len > remaining) + goto purge; + + skb_pull(skb, sizeof(struct ethhdr)); + /* reuse skb for the last subframe */ + if (remaining <= subframe_len + padding) + frame = skb; + else { + unsigned int hlen = ALIGN(extra_headroom, 4); + /* + * Allocate and reserve two bytes more for payload + * alignment since sizeof(struct ethhdr) is 14. + */ + frame = dev_alloc_skb(hlen + subframe_len + 2); + if (!frame) + goto purge; + + skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2); + memcpy(skb_put(frame, ntohs(len)), skb->data, + ntohs(len)); + + eth = (struct ethhdr *)skb_pull(skb, ntohs(len) + + padding); + if (!eth) { + dev_kfree_skb(frame); + goto purge; + } + } + + skb_reset_network_header(frame); + frame->dev = skb->dev; + frame->priority = skb->priority; + + payload = frame->data; + ethertype = (payload[6] << 8) | payload[7]; + + if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + compare_ether_addr(payload, + bridge_tunnel_header) == 0)) { + /* remove RFC1042 or Bridge-Tunnel + * encapsulation and replace EtherType */ + skb_pull(frame, 6); + memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); + } else { + memcpy(skb_push(frame, sizeof(__be16)), &len, + sizeof(__be16)); + memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); + } + __skb_queue_tail(list, frame); + } + + return; + + purge: + __skb_queue_purge(list); + out: + dev_kfree_skb(skb); +} +EXPORT_SYMBOL(ieee80211_amsdu_to_8023s); + /* Given a data frame determine the 802.1p/1d tag to use. */ unsigned int cfg80211_classify8021d(struct sk_buff *skb) { -- cgit v1.2.3 From 18974b5b0b5e758d416c550553b143e5c8038281 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Dec 2009 10:18:38 +0800 Subject: iwmc3200wifi: rx aggregation support When the device receives an A-MSDU frame (indicated by flag IWM_RX_TICKET_AMSDU_MSK), use ieee80211_amsdu_to_8023s to convert it to a list of 802.3 frames and handled them to upper layer. Cc: Johannes Berg Acked-by: Samuel Ortiz Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 46 ++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 72c27a3e5528..6bd253ac533f 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1534,6 +1534,33 @@ static void classify8023(struct sk_buff *skb) } } +static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) +{ + struct wireless_dev *wdev = iwm_to_wdev(iwm); + struct net_device *ndev = iwm_to_ndev(iwm); + struct sk_buff_head list; + struct sk_buff *frame; + + IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); + + __skb_queue_head_init(&list); + ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); + + while ((frame = __skb_dequeue(&list))) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += frame->len; + + frame->protocol = eth_type_trans(frame, ndev); + frame->ip_summed = CHECKSUM_NONE; + memset(frame->cb, 0, sizeof(frame->cb)); + + if (netif_rx_ni(frame) == NET_RX_DROP) { + IWM_ERR(iwm, "Packet dropped\n"); + ndev->stats.rx_dropped++; + } + } +} + static void iwm_rx_process_packet(struct iwm_priv *iwm, struct iwm_rx_packet *packet, struct iwm_rx_ticket_node *ticket_node) @@ -1548,25 +1575,34 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, switch (le16_to_cpu(ticket_node->ticket->action)) { case IWM_RX_TICKET_RELEASE: IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); - classify8023(skb); + iwm_rx_adjust_packet(iwm, packet, ticket_node); + skb->dev = iwm_to_ndev(iwm); + classify8023(skb); + + if (le16_to_cpu(ticket_node->ticket->flags) & + IWM_RX_TICKET_AMSDU_MSK) { + iwm_rx_process_amsdu(iwm, skb); + break; + } + ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); if (ret < 0) { IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " "%d\n", ret); + kfree_skb(packet->skb); break; } IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); - skb->dev = iwm_to_ndev(iwm); + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); skb->ip_summed = CHECKSUM_NONE; memset(skb->cb, 0, sizeof(skb->cb)); - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += skb->len; - if (netif_rx_ni(skb) == NET_RX_DROP) { IWM_ERR(iwm, "Packet dropped\n"); ndev->stats.rx_dropped++; -- cgit v1.2.3 From 0f78231bffb868a30e8533aace142213266bb811 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 1 Dec 2009 13:37:02 +0100 Subject: mac80211: enable spatial multiplexing powersave Enable spatial multiplexing in mac80211 by telling the driver what to do and, where necessary, sending action frames to the AP to update the requested SMPS mode. Also includes a trivial implementation for hwsim that just logs the requested mode. For now, the userspace interface is in debugfs only, and let you toggle the requested mode at any time. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 24 ++++++-- include/linux/ieee80211.h | 25 +++++++- include/net/mac80211.h | 59 ++++++++++++++++++ net/mac80211/cfg.c | 49 +++++++++++++++ net/mac80211/debugfs_netdev.c | 111 +++++++++++++++++++++++++++++++++- net/mac80211/driver-trace.h | 2 + net/mac80211/ht.c | 47 ++++++++++++++ net/mac80211/ieee80211_i.h | 14 +++++ net/mac80211/main.c | 24 ++++++++ net/mac80211/mlme.c | 63 +++++++++++++++++-- net/mac80211/status.c | 38 ++++++++++++ net/mac80211/util.c | 74 +++++++++++++++++++++++ 12 files changed, 518 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 88e41176e7fd..92c669ebb358 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -618,12 +618,26 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) { struct mac80211_hwsim_data *data = hw->priv; struct ieee80211_conf *conf = &hw->conf; - - printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n", + static const char *chantypes[4] = { + [NL80211_CHAN_NO_HT] = "noht", + [NL80211_CHAN_HT20] = "ht20", + [NL80211_CHAN_HT40MINUS] = "ht40-", + [NL80211_CHAN_HT40PLUS] = "ht40+", + }; + static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { + [IEEE80211_SMPS_AUTOMATIC] = "auto", + [IEEE80211_SMPS_OFF] = "off", + [IEEE80211_SMPS_STATIC] = "static", + [IEEE80211_SMPS_DYNAMIC] = "dynamic", + }; + + printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", wiphy_name(hw->wiphy), __func__, conf->channel->center_freq, + chantypes[conf->channel_type], !!(conf->flags & IEEE80211_CONF_IDLE), - !!(conf->flags & IEEE80211_CONF_PS)); + !!(conf->flags & IEEE80211_CONF_PS), + smps_modes[conf->smps_mode]); data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); @@ -1082,7 +1096,9 @@ static int __init init_mac80211_hwsim(void) BIT(NL80211_IFTYPE_MESH_POINT); hw->flags = IEEE80211_HW_MFP_CAPABLE | - IEEE80211_HW_SIGNAL_DBM; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_STATIC_SMPS | + IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; /* ask mac80211 to reserve space for magic */ hw->vif_data_size = sizeof(struct hwsim_vif_priv); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d9724a28c0c2..e8d43d0ff2c3 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -707,6 +707,10 @@ struct ieee80211_mgmt { u8 action; u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; } __attribute__ ((packed)) sa_query; + struct { + u8 action; + u8 smps_control; + } __attribute__ ((packed)) ht_smps; } u; } __attribute__ ((packed)) action; } u; @@ -824,6 +828,7 @@ struct ieee80211_ht_cap { #define IEEE80211_HT_CAP_LDPC_CODING 0x0001 #define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 #define IEEE80211_HT_CAP_SM_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 #define IEEE80211_HT_CAP_GRN_FLD 0x0010 #define IEEE80211_HT_CAP_SGI_20 0x0020 #define IEEE80211_HT_CAP_SGI_40 0x0040 @@ -839,6 +844,7 @@ struct ieee80211_ht_cap { /* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ #define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 #define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 /* * Maximum length of AMPDU that the STA can receive. @@ -922,12 +928,17 @@ struct ieee80211_ht_info { #define IEEE80211_MAX_AMPDU_BUF 0x40 -/* Spatial Multiplexing Power Save Modes */ +/* Spatial Multiplexing Power Save Modes (for capability) */ #define WLAN_HT_CAP_SM_PS_STATIC 0 #define WLAN_HT_CAP_SM_PS_DYNAMIC 1 #define WLAN_HT_CAP_SM_PS_INVALID 2 #define WLAN_HT_CAP_SM_PS_DISABLED 3 +/* for SM power control field lower two bits */ +#define WLAN_HT_SMPS_CONTROL_DISABLED 0 +#define WLAN_HT_SMPS_CONTROL_STATIC 1 +#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -1150,6 +1161,18 @@ enum ieee80211_spectrum_mgmt_actioncode { WLAN_ACTION_SPCT_CHL_SWITCH = 4, }; +/* HT action codes */ +enum ieee80211_ht_actioncode { + WLAN_HT_ACTION_NOTIFY_CHANWIDTH = 0, + WLAN_HT_ACTION_SMPS = 1, + WLAN_HT_ACTION_PSMP = 2, + WLAN_HT_ACTION_PCO_PHASE = 3, + WLAN_HT_ACTION_CSI = 4, + WLAN_HT_ACTION_NONCOMPRESSED_BF = 5, + WLAN_HT_ACTION_COMPRESSED_BF = 6, + WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7, +}; + /* Security key length */ enum ieee80211_key_len { WLAN_KEY_LEN_WEP40 = 5, diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e94cc526b0f6..e6b6bf81d5b9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -597,8 +597,10 @@ enum ieee80211_conf_flags { * @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed + * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed */ enum ieee80211_conf_changed { + IEEE80211_CONF_CHANGE_SMPS = BIT(1), IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), IEEE80211_CONF_CHANGE_MONITOR = BIT(3), IEEE80211_CONF_CHANGE_PS = BIT(4), @@ -608,6 +610,21 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_IDLE = BIT(8), }; +/** + * enum ieee80211_smps_mode - spatial multiplexing power save mode + * + * @ + */ +enum ieee80211_smps_mode { + IEEE80211_SMPS_AUTOMATIC, + IEEE80211_SMPS_OFF, + IEEE80211_SMPS_STATIC, + IEEE80211_SMPS_DYNAMIC, + + /* keep last */ + IEEE80211_SMPS_NUM_MODES, +}; + /** * struct ieee80211_conf - configuration of the device * @@ -636,6 +653,10 @@ enum ieee80211_conf_changed { * @short_frame_max_tx_count: Maximum number of transmissions for a "short" * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the * number of transmissions not the number of retries + * + * @smps_mode: spatial multiplexing powersave mode; note that + * %IEEE80211_SMPS_STATIC is used when the device is not + * configured for an HT channel */ struct ieee80211_conf { u32 flags; @@ -648,6 +669,7 @@ struct ieee80211_conf { struct ieee80211_channel *channel; enum nl80211_channel_type channel_type; + enum ieee80211_smps_mode smps_mode; }; /** @@ -930,6 +952,16 @@ enum ieee80211_tkip_key_type { * @IEEE80211_HW_BEACON_FILTER: * Hardware supports dropping of irrelevant beacon frames to * avoid waking up cpu. + * + * @IEEE80211_HW_SUPPORTS_STATIC_SMPS: + * Hardware supports static spatial multiplexing powersave, + * ie. can turn off all but one chain even on HT connections + * that should be using more chains. + * + * @IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS: + * Hardware supports dynamic spatial multiplexing powersave, + * ie. can turn off all but one chain and then wake the rest + * up as required after, for example, rts/cts handshake. */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -947,6 +979,8 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, IEEE80211_HW_MFP_CAPABLE = 1<<13, IEEE80211_HW_BEACON_FILTER = 1<<14, + IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, + IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, }; /** @@ -1214,6 +1248,31 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * signal strength threshold checking. */ +/** + * DOC: Spatial multiplexing power save + * + * SMPS (Spatial multiplexing power save) is a mechanism to conserve + * power in an 802.11n implementation. For details on the mechanism + * and rationale, please refer to 802.11 (as amended by 802.11n-2009) + * "11.2.3 SM power save". + * + * The mac80211 implementation is capable of sending action frames + * to update the AP about the station's SMPS mode, and will instruct + * the driver to enter the specific mode. It will also announce the + * requested SMPS mode during the association handshake. Hardware + * support for this feature is required, and can be indicated by + * hardware flags. + * + * The default mode will be "automatic", which nl80211/cfg80211 + * defines to be dynamic SMPS in (regular) powersave, and SMPS + * turned off otherwise. + * + * To support this feature, the driver must set the appropriate + * hardware support flags, and handle the SMPS flag to the config() + * operation. It will then with this mechanism be instructed to + * enter the requested SMPS mode while associated to an HT AP. + */ + /** * DOC: Frame filtering * diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fcfa1bf776a7..8c35418d1c96 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1318,6 +1318,50 @@ static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) } #endif +int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, + enum ieee80211_smps_mode smps_mode) +{ + const u8 *ap; + enum ieee80211_smps_mode old_req; + int err; + + old_req = sdata->u.mgd.req_smps; + sdata->u.mgd.req_smps = smps_mode; + + if (old_req == smps_mode && + smps_mode != IEEE80211_SMPS_AUTOMATIC) + return 0; + + /* + * If not associated, or current association is not an HT + * association, there's no need to send an action frame. + */ + if (!sdata->u.mgd.associated || + sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { + mutex_lock(&sdata->local->iflist_mtx); + ieee80211_recalc_smps(sdata->local, sdata); + mutex_unlock(&sdata->local->iflist_mtx); + return 0; + } + + ap = sdata->u.mgd.associated->cbss.bssid; + + if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { + if (sdata->u.mgd.powersave) + smps_mode = IEEE80211_SMPS_DYNAMIC; + else + smps_mode = IEEE80211_SMPS_OFF; + } + + /* send SM PS frame to AP */ + err = ieee80211_send_smps_action(sdata, smps_mode, + ap, ap); + if (err) + sdata->u.mgd.req_smps = old_req; + + return err; +} + static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) { @@ -1335,6 +1379,11 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, sdata->u.mgd.powersave = enabled; conf->dynamic_ps_timeout = timeout; + /* no change, but if automatic follow powersave */ + mutex_lock(&sdata->u.mgd.mtx); + __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); + mutex_unlock(&sdata->u.mgd.mtx); + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 5d9c797635a9..355983503885 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -41,6 +41,30 @@ static ssize_t ieee80211_if_read( return ret; } +static ssize_t ieee80211_if_write( + struct ieee80211_sub_if_data *sdata, + const char __user *userbuf, + size_t count, loff_t *ppos, + ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) +{ + u8 *buf; + ssize_t ret = -ENODEV; + + buf = kzalloc(count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + rtnl_lock(); + if (sdata->dev->reg_state == NETREG_REGISTERED) + ret = (*write)(sdata, buf, count); + rtnl_unlock(); + + return ret; +} + #define IEEE80211_IF_FMT(name, field, format_string) \ static ssize_t ieee80211_if_fmt_##name( \ const struct ieee80211_sub_if_data *sdata, char *buf, \ @@ -71,7 +95,7 @@ static ssize_t ieee80211_if_fmt_##name( \ return scnprintf(buf, buflen, "%pM\n", sdata->field); \ } -#define __IEEE80211_IF_FILE(name) \ +#define __IEEE80211_IF_FILE(name, _write) \ static ssize_t ieee80211_if_read_##name(struct file *file, \ char __user *userbuf, \ size_t count, loff_t *ppos) \ @@ -82,12 +106,24 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ } \ static const struct file_operations name##_ops = { \ .read = ieee80211_if_read_##name, \ + .write = (_write), \ .open = mac80211_open_file_generic, \ } +#define __IEEE80211_IF_FILE_W(name) \ +static ssize_t ieee80211_if_write_##name(struct file *file, \ + const char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + return ieee80211_if_write(file->private_data, userbuf, count, \ + ppos, ieee80211_if_parse_##name); \ +} \ +__IEEE80211_IF_FILE(name, ieee80211_if_write_##name) + + #define IEEE80211_IF_FILE(name, field, format) \ IEEE80211_IF_FMT_##format(name, field) \ - __IEEE80211_IF_FILE(name) + __IEEE80211_IF_FILE(name, NULL) /* common attributes */ IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); @@ -99,6 +135,70 @@ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); +static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, + enum ieee80211_smps_mode smps_mode) +{ + struct ieee80211_local *local = sdata->local; + int err; + + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_STATIC_SMPS) && + smps_mode == IEEE80211_SMPS_STATIC) + return -EINVAL; + + /* auto should be dynamic if in PS mode */ + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) && + (smps_mode == IEEE80211_SMPS_DYNAMIC || + smps_mode == IEEE80211_SMPS_AUTOMATIC)) + return -EINVAL; + + /* supported only on managed interfaces for now */ + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + mutex_lock(&local->iflist_mtx); + err = __ieee80211_request_smps(sdata, smps_mode); + mutex_unlock(&local->iflist_mtx); + + return err; +} + +static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { + [IEEE80211_SMPS_AUTOMATIC] = "auto", + [IEEE80211_SMPS_OFF] = "off", + [IEEE80211_SMPS_STATIC] = "static", + [IEEE80211_SMPS_DYNAMIC] = "dynamic", +}; + +static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, + char *buf, int buflen) +{ + if (sdata->vif.type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + return snprintf(buf, buflen, "request: %s\nused: %s\n", + smps_modes[sdata->u.mgd.req_smps], + smps_modes[sdata->u.mgd.ap_smps]); +} + +static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, + const char *buf, int buflen) +{ + enum ieee80211_smps_mode mode; + + for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) { + if (strncmp(buf, smps_modes[mode], buflen) == 0) { + int err = ieee80211_set_smps(sdata, mode); + if (!err) + return buflen; + return err; + } + } + + return -EINVAL; +} + +__IEEE80211_IF_FILE_W(smps); + /* AP attributes */ IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); @@ -109,7 +209,7 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( return scnprintf(buf, buflen, "%u\n", skb_queue_len(&sdata->u.ap.ps_bc_buf)); } -__IEEE80211_IF_FILE(num_buffered_multicast); +__IEEE80211_IF_FILE(num_buffered_multicast, NULL); /* WDS attributes */ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); @@ -158,6 +258,10 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ sdata, &name##_ops); +#define DEBUGFS_ADD_MODE(name, mode) \ + debugfs_create_file(#name, mode, sdata->debugfs.dir, \ + sdata, &name##_ops); + static void add_sta_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted, sta); @@ -167,6 +271,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(bssid, sta); DEBUGFS_ADD(aid, sta); DEBUGFS_ADD(capab, sta); + DEBUGFS_ADD_MODE(smps, 0600); } static void add_ap_files(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index ee2d19a25ce1..7a849b920165 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -140,6 +140,7 @@ TRACE_EVENT(drv_config, __field(u8, short_frame_max_tx_count) __field(int, center_freq) __field(int, channel_type) + __field(int, smps) ), TP_fast_assign( @@ -155,6 +156,7 @@ TRACE_EVENT(drv_config, __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; __entry->center_freq = local->hw.conf.channel->center_freq; __entry->channel_type = local->hw.conf.channel_type; + __entry->smps = local->hw.conf.smps_mode; ), TP_printk( diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 45ebd062a2fb..63b8f86b7f16 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -166,3 +166,50 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, spin_unlock_bh(&sta->lock); } } + +int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, + enum ieee80211_smps_mode smps, const u8 *da, + const u8 *bssid) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *action_frame; + + /* 27 = header + category + action + smps mode */ + skb = dev_alloc_skb(27 + local->hw.extra_tx_headroom); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, local->hw.extra_tx_headroom); + action_frame = (void *)skb_put(skb, 27); + memcpy(action_frame->da, da, ETH_ALEN); + memcpy(action_frame->sa, sdata->dev->dev_addr, ETH_ALEN); + memcpy(action_frame->bssid, bssid, ETH_ALEN); + action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + action_frame->u.action.category = WLAN_CATEGORY_HT; + action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); + case IEEE80211_SMPS_OFF: + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DISABLED; + break; + case IEEE80211_SMPS_STATIC: + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_STATIC; + break; + case IEEE80211_SMPS_DYNAMIC: + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DYNAMIC; + break; + } + + /* we'll do more on status of this frame */ + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; + ieee80211_tx_skb(sdata, skb); + + return 0; +} diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 178e329f9257..e63aecbddfbe 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -297,6 +297,8 @@ struct ieee80211_if_managed { unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ + enum ieee80211_smps_mode req_smps, /* requested smps mode */ + ap_smps; /* smps mode AP thinks we're in */ unsigned long request; @@ -587,6 +589,9 @@ struct ieee80211_local { /* used for uploading changed mc list */ struct work_struct reconfig_filter; + /* used to reconfigure hardware SM PS */ + struct work_struct recalc_smps; + /* aggregated multicast list */ struct dev_addr_list *mc_list; int mc_count; @@ -760,6 +765,8 @@ struct ieee80211_local { int user_power_level; /* in dBm */ int power_constr_level; /* in dBm */ + enum ieee80211_smps_mode smps_mode; + struct work_struct restart_work; #ifdef CONFIG_MAC80211_DEBUGFS @@ -978,6 +985,9 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code); +int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, + enum ieee80211_smps_mode smps, const u8 *da, + const u8 *bssid); void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u16 initiator, u16 reason); @@ -1088,6 +1098,10 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, u32 ieee80211_sta_get_rates(struct ieee80211_local *local, struct ieee802_11_elems *elems, enum ieee80211_band band); +int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, + enum ieee80211_smps_mode smps_mode); +void ieee80211_recalc_smps(struct ieee80211_local *local, + struct ieee80211_sub_if_data *forsdata); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 98320a94c270..e1293e8ed83a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -113,6 +113,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) changed |= IEEE80211_CONF_CHANGE_CHANNEL; } + if (!conf_is_ht(&local->hw.conf)) { + /* + * mac80211.h documents that this is only valid + * when the channel is set to an HT type, and + * that otherwise STATIC is used. + */ + local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC; + } else if (local->hw.conf.smps_mode != local->smps_mode) { + local->hw.conf.smps_mode = local->smps_mode; + changed |= IEEE80211_CONF_CHANGE_SMPS; + } + if (scan_chan) power = chan->max_power; else @@ -297,6 +309,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_restart_hw); +static void ieee80211_recalc_smps_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, recalc_smps); + + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_smps(local, NULL); + mutex_unlock(&local->iflist_mtx); +} + struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, const struct ieee80211_ops *ops) { @@ -370,6 +392,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_WORK(&local->restart_work, ieee80211_restart_work); INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); + INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work); + local->smps_mode = IEEE80211_SMPS_OFF; INIT_WORK(&local->dynamic_ps_enable_work, ieee80211_dynamic_ps_enable_work); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cd5dcc3d8c2b..0a762a9ba4df 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -398,6 +398,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, __le16 tmp; u32 flags = local->hw.conf.channel->flags; + /* determine capability flags */ + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (flags & IEEE80211_CHAN_NO_HT40PLUS) { @@ -413,17 +415,64 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, break; } - tmp = cpu_to_le16(cap); - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2); + /* set SM PS mode properly */ + cap &= ~IEEE80211_HT_CAP_SM_PS; + /* new association always uses requested smps mode */ + if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { + if (ifmgd->powersave) + ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; + else + ifmgd->ap_smps = IEEE80211_SMPS_OFF; + } else + ifmgd->ap_smps = ifmgd->req_smps; + + switch (ifmgd->ap_smps) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); + case IEEE80211_SMPS_OFF: + cap |= WLAN_HT_CAP_SM_PS_DISABLED << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_STATIC: + cap |= WLAN_HT_CAP_SM_PS_STATIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_DYNAMIC: + cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + } + + /* reserve and fill IE */ + + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); *pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_cap); memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + + /* capability flags */ + tmp = cpu_to_le16(cap); memcpy(pos, &tmp, sizeof(u16)); pos += sizeof(u16); - /* TODO: needs a define here for << 2 */ + + /* AMPDU parameters */ *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << 2); + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + + /* MCS set */ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + + /* extended capabilities */ + pos += sizeof(__le16); + + /* BF capabilities */ + pos += sizeof(__le32); + + /* antenna selection */ + pos += sizeof(u8); } IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; @@ -932,6 +981,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); + ieee80211_recalc_smps(local, sdata); mutex_unlock(&local->iflist_mtx); netif_start_queue(sdata->dev); @@ -2327,6 +2377,11 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; mutex_init(&ifmgd->mtx); + + if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS) + ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC; + else + ifmgd->req_smps = IEEE80211_SMPS_OFF; } /* scan finished notification */ diff --git a/net/mac80211/status.c b/net/mac80211/status.c index b4608f11a40f..0c0850d37dda 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -134,6 +134,40 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, dev_kfree_skb(skb); } +static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt = (void *) skb->data; + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + + if (ieee80211_is_action(mgmt->frame_control) && + sdata->vif.type == NL80211_IFTYPE_STATION && + mgmt->u.action.category == WLAN_CATEGORY_HT && + mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS) { + /* + * This update looks racy, but isn't -- if we come + * here we've definitely got a station that we're + * talking to, and on a managed interface that can + * only be the AP. And the only other place updating + * this variable is before we're associated. + */ + switch (mgmt->u.action.u.ht_smps.smps_control) { + case WLAN_HT_SMPS_CONTROL_DYNAMIC: + sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_DYNAMIC; + break; + case WLAN_HT_SMPS_CONTROL_STATIC: + sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_STATIC; + break; + case WLAN_HT_SMPS_CONTROL_DISABLED: + default: /* shouldn't happen since we don't send that */ + sta->sdata->u.mgd.ap_smps = IEEE80211_SMPS_OFF; + break; + } + + ieee80211_queue_work(&local->hw, &local->recalc_smps); + } +} + void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) { struct sk_buff *skb2; @@ -210,6 +244,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rate_control_tx_status(local, sband, sta, skb); if (ieee80211_vif_is_mesh(&sta->sdata->vif)) ieee80211s_update_metric(local, sta, skb); + + if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && + (info->flags & IEEE80211_TX_STAT_ACK)) + ieee80211_frame_acked(sta, skb); } rcu_read_unlock(); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d54dbe8e09ba..086ef6257b4b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1170,3 +1170,77 @@ int ieee80211_reconfig(struct ieee80211_local *local) return 0; } +static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, + enum ieee80211_smps_mode *smps_mode) +{ + if (ifmgd->associated) { + *smps_mode = ifmgd->ap_smps; + + if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) { + if (ifmgd->powersave) + *smps_mode = IEEE80211_SMPS_DYNAMIC; + else + *smps_mode = IEEE80211_SMPS_OFF; + } + + return 1; + } + + return 0; +} + +/* must hold iflist_mtx */ +void ieee80211_recalc_smps(struct ieee80211_local *local, + struct ieee80211_sub_if_data *forsdata) +{ + struct ieee80211_sub_if_data *sdata; + enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF; + int count = 0; + + if (forsdata) + WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx)); + + WARN_ON(!mutex_is_locked(&local->iflist_mtx)); + + /* + * This function could be improved to handle multiple + * interfaces better, but right now it makes any + * non-station interfaces force SM PS to be turned + * off. If there are multiple station interfaces it + * could also use the best possible mode, e.g. if + * one is in static and the other in dynamic then + * dynamic is ok. + */ + + list_for_each_entry(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + if (sdata->vif.type != NL80211_IFTYPE_STATION) + goto set; + if (sdata != forsdata) { + /* + * This nested is ok -- we are holding the iflist_mtx + * so can't get here twice or so. But it's required + * since normally we acquire it first and then the + * iflist_mtx. + */ + mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING); + count += check_mgd_smps(&sdata->u.mgd, &smps_mode); + mutex_unlock(&sdata->u.mgd.mtx); + } else + count += check_mgd_smps(&sdata->u.mgd, &smps_mode); + + if (count > 1) { + smps_mode = IEEE80211_SMPS_OFF; + break; + } + } + + if (smps_mode == local->smps_mode) + return; + + set: + local->smps_mode = smps_mode; + /* changed flag is auto-detected for this */ + ieee80211_hw_config(local, 0); +} -- cgit v1.2.3 From 8b73d13a21ae889e747cac180ff27c5a0a88e6a4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 1 Dec 2009 14:24:24 +0100 Subject: mac80211_hwsim: implement ampdu action Not that we actually ever aggregate anything, but it could potentially be useful anyhow to simulate aggregation sessions. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 92c669ebb358..89f527ee1a10 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -841,6 +841,31 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, } #endif +static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + switch (action) { + case IEEE80211_AMPDU_TX_START: + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP: + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + break; + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + + static const struct ieee80211_ops mac80211_hwsim_ops = { .tx = mac80211_hwsim_tx, @@ -855,6 +880,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = .set_tim = mac80211_hwsim_set_tim, .conf_tx = mac80211_hwsim_conf_tx, CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) + .ampdu_action = mac80211_hwsim_ampdu_action, }; -- cgit v1.2.3 From f38fd12fa7b7b98e158a9b31d388da34eef25c22 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 1 Dec 2009 18:29:42 +0100 Subject: mac80211: allow disabling 40MHz on 2.4GHz In some situations it is required that a system be configured with no support for 40 MHz channels in the 2.4 GHz band. Rather than imposing any such restrictions on everybody, allow configuration a system like that with a module parameter. It is writable at runtime but only takes effect at the time of the next association. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/main.c | 6 ++++++ net/mac80211/mlme.c | 6 ++++++ net/mac80211/util.c | 14 +++++++++++--- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e63aecbddfbe..6fb3f7181536 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -881,6 +881,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_configure_filter(struct ieee80211_local *local); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); +extern bool ieee80211_disable_40mhz_24ghz; + /* STA code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index e1293e8ed83a..25f52098b636 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -33,6 +33,12 @@ #include "cfg.h" #include "debugfs.h" + +bool ieee80211_disable_40mhz_24ghz; +module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); +MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, + "Disable 40MHz support in the 2.4GHz band"); + void ieee80211_configure_filter(struct ieee80211_local *local) { u64 mc; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0a762a9ba4df..a7472c979c63 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -400,6 +400,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, /* determine capability flags */ + if (ieee80211_disable_40mhz_24ghz && + sband->band == IEEE80211_BAND_2GHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: if (flags & IEEE80211_CHAN_NO_HT40PLUS) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 086ef6257b4b..acb6626ad0a4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -908,16 +908,24 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, } if (sband->ht_cap.ht_supported) { - __le16 tmp = cpu_to_le16(sband->ht_cap.cap); + u16 cap = sband->ht_cap.cap; + __le16 tmp; + + if (ieee80211_disable_40mhz_24ghz && + sband->band == IEEE80211_BAND_2GHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } *pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_cap); memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + tmp = cpu_to_le16(cap); memcpy(pos, &tmp, sizeof(u16)); pos += sizeof(u16); - /* TODO: needs a define here for << 2 */ *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << 2); + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); pos += sizeof(sband->ht_cap.mcs); pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ -- cgit v1.2.3 From 5fba4af32ceeb935b3926714df9a64a33c2c9cf5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Dec 2009 12:43:42 +0100 Subject: cfg80211: avoid sending spurious deauth to userspace Before commit ca9034592823e8179511e48a78731f95bfdd766c Author: Holger Schurig Date: Tue Oct 13 13:45:28 2009 +0200 cfg80211: remove warning in deauth case we assumed that drivers never give us spurious deauth frames because they filter them out based on the auth state they keep track of. This turned out to be racy, because userspace might deauth while the AP is also sending a deauth frame, so the warning was removed. However, in that case we should not tell userspace about the AP's frame if it requested deauth "first", where "first" means it came to cfg80211 first. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/mlme.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1001db4912f7..acaeaa784d68 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -137,22 +137,23 @@ void __cfg80211_send_deauth(struct net_device *dev, struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; const u8 *bssid = mgmt->bssid; int i; + bool found = false; ASSERT_WDEV_LOCK(wdev); - nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); - if (wdev->current_bss && memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; + found = true; } else for (i = 0; i < MAX_AUTH_BSSES; i++) { if (wdev->auth_bsses[i] && memcmp(wdev->auth_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) { cfg80211_unhold_bss(wdev->auth_bsses[i]); cfg80211_put_bss(&wdev->auth_bsses[i]->pub); wdev->auth_bsses[i] = NULL; + found = true; break; } if (wdev->authtry_bsses[i] && @@ -160,10 +161,16 @@ void __cfg80211_send_deauth(struct net_device *dev, cfg80211_unhold_bss(wdev->authtry_bsses[i]); cfg80211_put_bss(&wdev->authtry_bsses[i]->pub); wdev->authtry_bsses[i] = NULL; + found = true; break; } } + if (!found) + return; + + nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL); + if (wdev->sme_state == CFG80211_SME_CONNECTED) { u16 reason_code; bool from_ap; -- cgit v1.2.3 From 5d1ec85f00e999dba61bdcbd959d62439d418e56 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Dec 2009 12:43:43 +0100 Subject: mac80211: dont try to use existing sta for AP Clean out some cruft that could use an already existing sta_info struct -- that case cannot happen. Also, there's a bug there -- if allocation/insertion fails then it is possible that we are left in a lingering state where mac80211 waits for the AP, cfg80211 waits for mac80211, but the AP has already replied. Since there's no way to indicate an internal error, pretend there was a timeout, i.e. that the AP never responded. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 57 ++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a7472c979c63..5174bfc5710d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -75,6 +75,9 @@ enum rx_mgmt_action { /* caller must call cfg80211_send_disassoc() */ RX_MGMT_CFG80211_DISASSOC, + /* caller must tell cfg80211 about internal error */ + RX_MGMT_CFG80211_ASSOC_ERROR, + /* caller must call cfg80211_auth_timeout() & free work */ RX_MGMT_CFG80211_AUTH_TO, @@ -1479,8 +1482,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; u8 *pos; u32 changed = 0; - int i, j; - bool have_higher_than_11mbit = false, newsta = false; + int i, j, err; + bool have_higher_than_11mbit = false; u16 ap_ht_cap_flags; /* @@ -1542,30 +1545,18 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: associated\n", sdata->name); ifmgd->aid = aid; - rcu_read_lock(); - - /* Add STA entry for the AP */ - sta = sta_info_get(sdata, wk->bss->cbss.bssid); + sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); if (!sta) { - newsta = true; - - rcu_read_unlock(); - - sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); - if (!sta) { - printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", sdata->name); - return RX_MGMT_NONE; - } - - set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_ASSOC_AP); - if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) - set_sta_flags(sta, WLAN_STA_AUTHORIZED); - - rcu_read_lock(); + printk(KERN_DEBUG "%s: failed to alloc STA entry for" + " the AP\n", sdata->name); + return RX_MGMT_CFG80211_ASSOC_ERROR; } + set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | + WLAN_STA_ASSOC_AP); + if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) + set_sta_flags(sta, WLAN_STA_AUTHORIZED); + rates = 0; basic_rates = 0; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -1628,18 +1619,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) set_sta_flags(sta, WLAN_STA_WME); - if (newsta) { - int err = sta_info_insert(sta); - if (err) { - printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", sdata->name, err); - rcu_read_unlock(); - return RX_MGMT_NONE; - } + err = sta_info_insert(sta); + sta = NULL; + if (err) { + printk(KERN_DEBUG "%s: failed to insert STA entry for" + " the AP (error %d)\n", sdata->name, err); + return RX_MGMT_CFG80211_ASSOC_ERROR; } - rcu_read_unlock(); - if (elems.wmm_param) ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param, elems.wmm_param_len); @@ -2084,6 +2071,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, case RX_MGMT_CFG80211_DEAUTH: cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); break; + case RX_MGMT_CFG80211_ASSOC_ERROR: + /* an internal error -- pretend timeout for now */ + cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); + break; default: WARN(1, "unexpected: %d", rma); } -- cgit v1.2.3 From c24ef46e6b1597e54f185e0b48eb9073ef155a8c Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:25:56 +0100 Subject: libertas: use priv->mesh_tlv instead of priv->mesh_fw_ver Both variables contained the same information (no mesh, old mesh, new mesh). So we can get rid of one variable. Also move the mesh-version test from cmd.c into mesh.c. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 13 ------------- drivers/net/wireless/libertas/defs.h | 7 ------- drivers/net/wireless/libertas/dev.h | 1 - drivers/net/wireless/libertas/mesh.c | 23 ++++++++++++++++------- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index b9b371bfa30f..dd69191f24eb 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -143,19 +143,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", cmd.hwifversion, cmd.version); - /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ - /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ - /* 5.110.22 have mesh command with 0xa3 command id */ - /* 10.0.0.p0 FW brings in mesh config command with different id */ - /* Check FW version MSB and initialize mesh_fw_ver */ - if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) - priv->mesh_fw_ver = MESH_FW_OLD; - else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && - (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) - priv->mesh_fw_ver = MESH_FW_NEW; - else - priv->mesh_fw_ver = MESH_NONE; - /* Clamp region code to 8-bit since FW spec indicates that it should * only ever be 8-bit, even though the field size is 16-bit. Some firmware * returns non-zero high 8 bits here. diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 6b6ea9f7bf5b..ea3f10ef4e00 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -397,13 +397,6 @@ enum KEY_INFO_WPA { KEY_INFO_WPA_ENABLED = 0x04 }; -/** mesh_fw_ver */ -enum _mesh_fw_ver { - MESH_NONE = 0, /* MESH is not supported */ - MESH_FW_OLD, /* MESH is supported in FW V5 */ - MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ -}; - /* Default values for fwt commands. */ #define FWT_DEFAULT_METRIC 0 #define FWT_DEFAULT_DIR 1 diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6a8d2b291d8c..505b8feaa8b4 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -42,7 +42,6 @@ struct lbs_private { u32 mesh_connect_status; struct lbs_mesh_stats mstats; int mesh_open; - int mesh_fw_ver; int mesh_autostart_enabled; uint16_t mesh_tlv; u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 2f91c9b808af..1d94f7d4efc8 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -196,7 +196,12 @@ int lbs_init_mesh(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MESH); - if (priv->mesh_fw_ver == MESH_FW_OLD) { + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ + /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ + /* 5.110.22 have mesh command with 0xa3 command id */ + /* 10.0.0.p0 FW brings in mesh config command with different id */ + /* Check FW version MSB and initialize mesh_fw_ver */ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { /* Enable mesh, if supported, and work out which TLV it uses. 0x100 + 291 is an unofficial value used in 5.110.20.pXX 0x100 + 37 is the official value used in 5.110.21.pXX @@ -218,7 +223,9 @@ int lbs_init_mesh(struct lbs_private *priv) priv->channel)) priv->mesh_tlv = 0; } - } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + } else + if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { /* 10.0.0.pXX new firmwares should succeed with TLV * 0x100+37; Do not invoke command with old TLV. */ @@ -227,6 +234,8 @@ int lbs_init_mesh(struct lbs_private *priv) priv->channel)) priv->mesh_tlv = 0; } + + if (priv->mesh_tlv) { lbs_add_mesh(priv); @@ -416,10 +425,10 @@ struct net_device *lbs_mesh_set_dev(struct lbs_private *priv, struct net_device *dev, struct rxpd *rxpd) { if (priv->mesh_dev) { - if (priv->mesh_fw_ver == MESH_FW_OLD) { + if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) { if (rxpd->rx_control & RxPD_MESH_FRAME) dev = priv->mesh_dev; - } else if (priv->mesh_fw_ver == MESH_FW_NEW) { + } else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) { if (rxpd->u.bss.bss_num == MESH_IFACE_ID) dev = priv->mesh_dev; } @@ -432,9 +441,9 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, struct net_device *dev, struct txpd *txpd) { if (dev == priv->mesh_dev) { - if (priv->mesh_fw_ver == MESH_FW_OLD) + if (priv->mesh_tlv == TLV_TYPE_OLD_MESH_ID) txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); - else if (priv->mesh_fw_ver == MESH_FW_NEW) + else if (priv->mesh_tlv == TLV_TYPE_MESH_ID) txpd->u.bss.bss_num = MESH_IFACE_ID; } } @@ -538,7 +547,7 @@ static int __lbs_mesh_config_send(struct lbs_private *priv, * Command id is 0xac for v10 FW along with mesh interface * id in bits 14-13-12. */ - if (priv->mesh_fw_ver == MESH_FW_NEW) + if (priv->mesh_tlv == TLV_TYPE_MESH_ID) command = CMD_MESH_CONFIG | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); -- cgit v1.2.3 From d6ede678c138061f5202b519f8f8d6372e2cb5bb Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:25:57 +0100 Subject: libertas: remove mesh_autostart_enabled and sync_channel mesh_autostart_enabled was nowhere set. Rumor is that this is used in the OLPC tree, but they never did submit their code upstream. After removing this code, it turned out that the sync_channel stuff is now also unused, so get rid of that as well. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmdresp.c | 16 ++-------------- drivers/net/wireless/libertas/dev.h | 2 -- drivers/net/wireless/libertas/main.c | 13 ------------- 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 21d57690c20a..0334a58820ee 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -485,20 +485,8 @@ int lbs_process_event(struct lbs_private *priv, u32 event) break; case MACREG_INT_CODE_MESH_AUTO_STARTED: - /* Ignore spurious autostart events if autostart is disabled */ - if (!priv->mesh_autostart_enabled) { - lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); - break; - } - lbs_pr_info("EVENT: MESH_AUTO_STARTED\n"); - priv->mesh_connect_status = LBS_CONNECTED; - if (priv->mesh_open) { - netif_carrier_on(priv->mesh_dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - } - priv->mode = IW_MODE_ADHOC; - schedule_work(&priv->sync_channel); + /* Ignore spurious autostart events */ + lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); break; default: diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 505b8feaa8b4..159de3ec9c44 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -42,11 +42,9 @@ struct lbs_private { u32 mesh_connect_status; struct lbs_mesh_stats mstats; int mesh_open; - int mesh_autostart_enabled; uint16_t mesh_tlv; u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 mesh_ssid_len; - struct work_struct sync_channel; /* Monitor mode */ struct net_device *rtap_net_dev; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index db38a5a719fa..b0799e347ba2 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -806,18 +806,6 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv) return 0; } -static void lbs_sync_channel_worker(struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, - sync_channel); - - lbs_deb_enter(LBS_DEB_MAIN); - if (lbs_update_channel(priv)) - lbs_pr_info("Channel synchronization failed."); - lbs_deb_leave(LBS_DEB_MAIN); -} - - static int lbs_init_adapter(struct lbs_private *priv) { size_t bufsize; @@ -997,7 +985,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); priv->mesh_open = 0; sprintf(priv->mesh_ssid, "mesh"); -- cgit v1.2.3 From 55e1ff924414111a6afbfde00375a1302aef9353 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:25:58 +0100 Subject: libertas: move mesh-related definitions into mesh.h Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.h | 12 ------------ drivers/net/wireless/libertas/mesh.h | 9 +++++++++ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 2862748aef70..cb4138a55fdf 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -110,18 +110,6 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); -/* Mesh related */ - -int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, - struct cmd_ds_mesh_access *cmd); - -int lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type); - -int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); - - /* Commands only used in wext.c, assoc. and scan.c */ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index fea9b5d005fc..b642d5d11699 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -46,11 +46,20 @@ void lbs_mesh_set_txpd(struct lbs_private *priv, /* Command handling */ struct cmd_ds_command; +struct cmd_ds_mesh_access; +struct cmd_ds_mesh_config; int lbs_cmd_bt_access(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf); int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf); +int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, + struct cmd_ds_mesh_access *cmd); +int lbs_mesh_config_send(struct lbs_private *priv, + struct cmd_ds_mesh_config *cmd, + uint16_t action, uint16_t type); +int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); + /* Persistent configuration */ -- cgit v1.2.3 From cd74468b8c56c1a809d9b7f913f11d8181c3a0b2 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:25:59 +0100 Subject: libertas: decouple mesh and rtap While it's might be technically true that only MESH-enabled firmwares are also RTAP-enabled, I like to have this decoupled. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index b0799e347ba2..ad3434011897 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1062,6 +1062,17 @@ void lbs_remove_card(struct lbs_private *priv) EXPORT_SYMBOL_GPL(lbs_remove_card); +static int lbs_rtap_supported(struct lbs_private *priv) +{ + if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) + return 1; + + /* newer firmware use a capability mask */ + return ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && + (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)); +} + + int lbs_start_card(struct lbs_private *priv) { struct net_device *dev = priv->dev; @@ -1081,12 +1092,14 @@ int lbs_start_card(struct lbs_private *priv) lbs_update_channel(priv); + lbs_init_mesh(priv); + /* * While rtap isn't related to mesh, only mesh-enabled * firmware implements the rtap functionality via * CMD_802_11_MONITOR_MODE. */ - if (lbs_init_mesh(priv)) { + if (lbs_rtap_supported(priv)) { if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) lbs_pr_err("cannot register lbs_rtap attribute\n"); } @@ -1120,7 +1133,9 @@ void lbs_stop_card(struct lbs_private *priv) netif_carrier_off(dev); lbs_debugfs_remove_one(priv); - if (lbs_deinit_mesh(priv)) + lbs_deinit_mesh(priv); + + if (lbs_rtap_supported(priv)) device_remove_file(&dev->dev, &dev_attr_lbs_rtap); /* Delete the timeout of the currently processing command */ -- cgit v1.2.3 From e4da1a81a967c05dfde6f0498cff1f6fe6683f52 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:26:00 +0100 Subject: libertas: move mesh SSID initialization into mesh.c Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 4 ---- drivers/net/wireless/libertas/mesh.c | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ad3434011897..127b7f60c320 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -986,10 +986,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - priv->mesh_open = 0; - sprintf(priv->mesh_ssid, "mesh"); - priv->mesh_ssid_len = 4; - priv->wol_criteria = 0xffffffff; priv->wol_gpio = 0xff; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 1d94f7d4efc8..4f67c8b62edc 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -237,6 +237,9 @@ int lbs_init_mesh(struct lbs_private *priv) if (priv->mesh_tlv) { + sprintf(priv->mesh_ssid, "mesh"); + priv->mesh_ssid_len = 4; + lbs_add_mesh(priv); if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) -- cgit v1.2.3 From 602114ae595af6c89eab149cf9f939e3f7ef4a34 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:26:01 +0100 Subject: libertas: add access functions for mesh open/connect status Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 2 +- drivers/net/wireless/libertas/main.c | 5 ++--- drivers/net/wireless/libertas/mesh.c | 3 ++- drivers/net/wireless/libertas/mesh.h | 6 ++++++ drivers/net/wireless/libertas/scan.c | 2 +- drivers/net/wireless/libertas/tx.c | 2 +- drivers/net/wireless/libertas/wext.c | 6 +++--- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index dd69191f24eb..4a198113f9be 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1304,7 +1304,7 @@ int lbs_execute_next_command(struct lbs_private *priv) if ((priv->psmode != LBS802_11POWERMODECAM) && (priv->psstate == PS_STATE_FULL_POWER) && ((priv->connect_status == LBS_CONNECTED) || - (priv->mesh_connect_status == LBS_CONNECTED))) { + lbs_mesh_connected(priv))) { if (priv->secinfo.WPAenabled || priv->secinfo.WPA2enabled) { /* check for valid WPA group keys */ diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 127b7f60c320..64b327d4548b 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -123,7 +123,7 @@ static ssize_t lbs_rtap_set(struct device *dev, if (priv->monitormode == monitor_mode) return strlen(buf); if (!priv->monitormode) { - if (priv->infra_open || priv->mesh_open) + if (priv->infra_open || lbs_mesh_open(priv)) return -EBUSY; if (priv->mode == IW_MODE_INFRA) lbs_cmd_80211_deauthenticate(priv, @@ -619,7 +619,7 @@ static int lbs_thread(void *data) if (priv->connect_status == LBS_CONNECTED) netif_wake_queue(priv->dev); if (priv->mesh_dev && - priv->mesh_connect_status == LBS_CONNECTED) + lbs_mesh_connected(priv)) netif_wake_queue(priv->mesh_dev); } } @@ -833,7 +833,6 @@ static int lbs_init_adapter(struct lbs_private *priv) memset(priv->current_addr, 0xff, ETH_ALEN); priv->connect_status = LBS_DISCONNECTED; - priv->mesh_connect_status = LBS_DISCONNECTED; priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; priv->mode = IW_MODE_INFRA; priv->channel = DEFAULT_AD_HOC_CHANNEL; diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 4f67c8b62edc..954cd00f7452 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -196,6 +195,8 @@ int lbs_init_mesh(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MESH); + priv->mesh_connect_status = LBS_DISCONNECTED; + /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ /* 5.110.22 have mesh command with 0xa3 command id */ diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index b642d5d11699..388c39281b7d 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -84,4 +84,10 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, uint32_t stringset, uint8_t *s); +/* Accessors */ + +#define lbs_mesh_open(priv) (priv->mesh_open) +#define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) + + #endif diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index c6a6c042b82f..4a0c3e3cd3b1 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -640,7 +640,7 @@ out: if (!priv->tx_pending_len) netif_wake_queue(priv->dev); } - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) { + if (priv->mesh_dev && lbs_mesh_connected(priv)) { netif_carrier_on(priv->mesh_dev); if (!priv->tx_pending_len) netif_wake_queue(priv->mesh_dev); diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 315d1ce286ca..52d244ea3d97 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -198,7 +198,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) if (priv->connect_status == LBS_CONNECTED) netif_wake_queue(priv->dev); - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) + if (priv->mesh_dev && lbs_mesh_connected(priv)) netif_wake_queue(priv->mesh_dev); } EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index a8eb9e1fcf36..c0c7bc40b109 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -192,7 +192,7 @@ static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) lbs_deb_enter(LBS_DEB_WEXT); if ((priv->connect_status != LBS_CONNECTED) && - (priv->mesh_connect_status != LBS_CONNECTED)) + !lbs_mesh_connected(priv)) memcpy(rates, lbs_bg_rates, MAX_RATES); else memcpy(rates, priv->curbssparams.rates, MAX_RATES); @@ -307,7 +307,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, /* Use nickname to indicate that mesh is on */ - if (priv->mesh_connect_status == LBS_CONNECTED) { + if (lbs_mesh_connected(priv)) { strncpy(extra, "Mesh", 12); extra[12] = '\0'; dwrq->length = strlen(extra); @@ -863,7 +863,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) /* If we're not associated, all quality values are meaningless */ if ((priv->connect_status != LBS_CONNECTED) && - (priv->mesh_connect_status != LBS_CONNECTED)) + !lbs_mesh_connected(priv)) goto out; /* Quality by RSSI */ -- cgit v1.2.3 From 4143a23de096910e3ceb0939f41de6ffb8c59475 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:26:02 +0100 Subject: libertas: make mesh configurable Mostly for the embedded people that know beforehand that they don't need MESH at all and want to save some bytes, but also helpful for the upcoming cfg80211 transition. text data bss dec hex filename 114264 2308 140 116712 1c7e8 libertas.ko with mesh 105026 2000 140 107166 1a29e libertas.ko without mesh -------------------------------------------------- -9238 -308 -9546 Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/Kconfig | 6 ++++++ drivers/net/wireless/libertas/Makefile | 2 +- drivers/net/wireless/libertas/cmd.c | 4 ++++ drivers/net/wireless/libertas/dev.h | 2 ++ drivers/net/wireless/libertas/ethtool.c | 2 ++ drivers/net/wireless/libertas/mesh.h | 17 +++++++++++++++++ drivers/net/wireless/libertas/wext.c | 20 +++++++++++++++----- 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig index 30aa9d48d67e..0485c9957575 100644 --- a/drivers/net/wireless/libertas/Kconfig +++ b/drivers/net/wireless/libertas/Kconfig @@ -37,3 +37,9 @@ config LIBERTAS_DEBUG depends on LIBERTAS ---help--- Debugging support. + +config LIBERTAS_MESH + bool "Enable mesh support" + depends on LIBERTAS + help + This enables Libertas' MESH support, used by e.g. the OLPC people. diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index b188cd97a053..45e870e33117 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile @@ -5,11 +5,11 @@ libertas-y += cmdresp.o libertas-y += debugfs.o libertas-y += ethtool.o libertas-y += main.o -libertas-y += mesh.o libertas-y += rx.o libertas-y += scan.o libertas-y += tx.o libertas-y += wext.o +libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o usb8xxx-objs += if_usb.o libertas_cs-objs += if_cs.o diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a198113f9be..4a0d8f4188ca 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -998,6 +998,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = 0; break; +#ifdef CONFIG_LIBERTAS_MESH + case CMD_BT_ACCESS: ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); break; @@ -1006,6 +1008,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); break; +#endif + case CMD_802_11_BEACON_CTRL: ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); break; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 159de3ec9c44..7330ab8521cc 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -39,12 +39,14 @@ struct lbs_private { /* Mesh */ struct net_device *mesh_dev; /* Virtual device */ +#ifdef CONFIG_LIBERTAS_MESH u32 mesh_connect_status; struct lbs_mesh_stats mstats; int mesh_open; uint16_t mesh_tlv; u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 mesh_ssid_len; +#endif /* Monitor mode */ struct net_device *rtap_net_dev; diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 63d020374c2b..3804a58d7f4e 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -114,9 +114,11 @@ const struct ethtool_ops lbs_ethtool_ops = { .get_drvinfo = lbs_ethtool_get_drvinfo, .get_eeprom = lbs_ethtool_get_eeprom, .get_eeprom_len = lbs_ethtool_get_eeprom_len, +#ifdef CONFIG_LIBERTAS_MESH .get_sset_count = lbs_mesh_ethtool_get_sset_count, .get_ethtool_stats = lbs_mesh_ethtool_get_stats, .get_strings = lbs_mesh_ethtool_get_strings, +#endif .get_wol = lbs_ethtool_get_wol, .set_wol = lbs_ethtool_set_wol, }; diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h index 388c39281b7d..e2573303a328 100644 --- a/drivers/net/wireless/libertas/mesh.h +++ b/drivers/net/wireless/libertas/mesh.h @@ -9,6 +9,8 @@ #include +#ifdef CONFIG_LIBERTAS_MESH + /* Mesh statistics */ struct lbs_mesh_stats { u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ @@ -89,5 +91,20 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev, #define lbs_mesh_open(priv) (priv->mesh_open) #define lbs_mesh_connected(priv) (priv->mesh_connect_status == LBS_CONNECTED) +#else + +#define lbs_init_mesh(priv) +#define lbs_deinit_mesh(priv) +#define lbs_add_mesh(priv) +#define lbs_remove_mesh(priv) +#define lbs_mesh_set_dev(priv, dev, rxpd) (dev) +#define lbs_mesh_set_txpd(priv, dev, txpd) +#define lbs_mesh_config(priv, enable, chan) +#define lbs_mesh_open(priv) (0) +#define lbs_mesh_connected(priv) (0) + +#endif + + #endif diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c0c7bc40b109..f07ba0b6c5f1 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -298,6 +298,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, return 0; } +#ifdef CONFIG_LIBERTAS_MESH static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { @@ -321,6 +322,7 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, lbs_deb_leave(LBS_DEB_WEXT); return 0; } +#endif static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) @@ -422,6 +424,7 @@ static int lbs_get_mode(struct net_device *dev, return 0; } +#ifdef CONFIG_LIBERTAS_MESH static int mesh_wlan_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) @@ -433,6 +436,7 @@ static int mesh_wlan_get_mode(struct net_device *dev, lbs_deb_leave(LBS_DEB_WEXT); return 0; } +#endif static int lbs_get_txpow(struct net_device *dev, struct iw_request_info *info, @@ -1010,6 +1014,7 @@ out: return ret; } +#ifdef CONFIG_LIBERTAS_MESH static int lbs_mesh_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) @@ -1061,6 +1066,7 @@ out: lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } +#endif static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) @@ -2110,6 +2116,7 @@ out: return ret; } +#ifdef CONFIG_LIBERTAS_MESH static int lbs_mesh_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) @@ -2163,6 +2170,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); return ret; } +#endif /** * @brief Connect to the AP or Ad-hoc Network with specific bssid @@ -2269,7 +2277,13 @@ static const iw_handler lbs_handler[] = { (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ }; +struct iw_handler_def lbs_handler_def = { + .num_standard = ARRAY_SIZE(lbs_handler), + .standard = (iw_handler *) lbs_handler, + .get_wireless_stats = lbs_get_wireless_stats, +}; +#ifdef CONFIG_LIBERTAS_MESH static const iw_handler mesh_wlan_handler[] = { (iw_handler) NULL, /* SIOCSIWCOMMIT */ (iw_handler) lbs_get_name, /* SIOCGIWNAME */ @@ -2327,14 +2341,10 @@ static const iw_handler mesh_wlan_handler[] = { (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ }; -struct iw_handler_def lbs_handler_def = { - .num_standard = ARRAY_SIZE(lbs_handler), - .standard = (iw_handler *) lbs_handler, - .get_wireless_stats = lbs_get_wireless_stats, -}; struct iw_handler_def mesh_handler_def = { .num_standard = ARRAY_SIZE(mesh_wlan_handler), .standard = (iw_handler *) mesh_wlan_handler, .get_wireless_stats = lbs_get_wireless_stats, }; +#endif -- cgit v1.2.3 From 0e78ff8fcc6dabeda313719deb751afbd20bea41 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:26:03 +0100 Subject: libertas: remove priv->capability This variable was once set to WLAN_CAPABILITY_SHORT_PREAMBLE and there's no code that could change the variable to something else. Therefore it seems this is not necessary :-) Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 13 +++---------- drivers/net/wireless/libertas/cmd.c | 3 --- drivers/net/wireless/libertas/dev.h | 1 - drivers/net/wireless/libertas/main.c | 1 - 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 751067369ba8..5f58ae33405b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -807,8 +807,7 @@ static int lbs_try_associate(struct lbs_private *priv, } /* Use short preamble only when both the BSS and firmware support it */ - if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) + if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) preamble = RADIO_PREAMBLE_SHORT; ret = lbs_set_radio(priv, preamble, 1); @@ -939,8 +938,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, } /* Use short preamble only when both the BSS and firmware support it */ - if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { + if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { lbs_deb_join("AdhocJoin: Short preamble\n"); preamble = RADIO_PREAMBLE_SHORT; } @@ -1049,7 +1047,7 @@ static int lbs_adhoc_start(struct lbs_private *priv, struct assoc_request *assoc_req) { struct cmd_ds_802_11_ad_hoc_start cmd; - u8 preamble = RADIO_PREAMBLE_LONG; + u8 preamble = RADIO_PREAMBLE_SHORT; size_t ratesize = 0; u16 tmpcap = 0; int ret = 0; @@ -1057,11 +1055,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, lbs_deb_enter(LBS_DEB_ASSOC); - if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { - lbs_deb_join("ADHOC_START: Will use short preamble\n"); - preamble = RADIO_PREAMBLE_SHORT; - } - ret = lbs_set_radio(priv, preamble, 1); if (ret) goto out; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a0d8f4188ca..42051f7cad6d 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -842,9 +842,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) if (priv->fwrelease < 0x09000000) { switch (preamble) { case RADIO_PREAMBLE_SHORT: - if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) - goto out; - /* Fall through */ case RADIO_PREAMBLE_AUTO: case RADIO_PREAMBLE_LONG: cmd.control = cpu_to_le16(preamble); diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 7330ab8521cc..cf47cf53458f 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -175,7 +175,6 @@ struct lbs_private { struct bss_descriptor *networks; struct assoc_request * pending_assoc_req; struct assoc_request * in_progress_assoc_req; - u16 capability; uint16_t enablehwauto; uint16_t ratebitmap; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 64b327d4548b..f9f195f7b17c 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -839,7 +839,6 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; priv->radio_on = 1; priv->enablehwauto = 1; - priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->psmode = LBS802_11POWERMODECAM; priv->psstate = PS_STATE_FULL_POWER; priv->is_deep_sleep = 0; -- cgit v1.2.3 From 48631de9218a4563a6632e105676f42db3849c57 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Dec 2009 15:26:04 +0100 Subject: libertas: remove priv->ratebitmap Used to be a write-only-variable :-) Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 4 +--- drivers/net/wireless/libertas/dev.h | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 5f58ae33405b..5e650f358415 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -390,10 +390,8 @@ int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); - if (!ret && cmd_action == CMD_ACT_GET) { - priv->ratebitmap = le16_to_cpu(cmd.bitmap); + if (!ret && cmd_action == CMD_ACT_GET) priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); - } lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index cf47cf53458f..d5a9dcae4059 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -176,7 +176,6 @@ struct lbs_private { struct assoc_request * pending_assoc_req; struct assoc_request * in_progress_assoc_req; uint16_t enablehwauto; - uint16_t ratebitmap; /* ADHOC */ u16 beacon_period; -- cgit v1.2.3 From d80050c4c321a74cea28c6ef9695d8427a928417 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 2 Dec 2009 20:56:11 -0800 Subject: iwmc3200wifi: Avoid an offset calculation for each management frame. Determine the offset at compile time. Signed-off-by: Joe Perches Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 6bd253ac533f..0619d6a1103c 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -868,36 +868,35 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, struct iwm_umac_notif_mgt_frame *mgt_frame = (struct iwm_umac_notif_mgt_frame *)buf; struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; - u8 *ie; IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, le16_to_cpu(mgt_frame->len)); if (ieee80211_is_assoc_req(mgt->frame_control)) { - ie = mgt->u.assoc_req.variable;; - iwm->req_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + iwm->req_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.assoc_req.variable); kfree(iwm->req_ie); iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { - ie = mgt->u.reassoc_req.variable;; - iwm->req_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + iwm->req_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.reassoc_req.variable); kfree(iwm->req_ie); iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { - ie = mgt->u.assoc_resp.variable;; - iwm->resp_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.assoc_resp.variable); kfree(iwm->resp_ie); iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, iwm->resp_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { - ie = mgt->u.reassoc_resp.variable;; - iwm->resp_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + iwm->resp_ie_len = le16_to_cpu(mgt_frame->len) + - offsetof(struct ieee80211_mgmt, + u.reassoc_resp.variable); kfree(iwm->resp_ie); iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, iwm->resp_ie_len, GFP_KERNEL); -- cgit v1.2.3 From 2c7e6bc9ac7cb518cf037495932d80f71a1596f2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Dec 2009 09:26:38 +0100 Subject: mac80211: disallow fixing bitrates with hw rate control When hw rate control is used, these parameters have no meaning because the hardware cannot get at them right now, so disallow setting them. Also clean up the function a bit. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8c35418d1c96..f07c4abefe56 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1399,15 +1399,25 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - int i, err = -EINVAL; + int i; u32 target_rate; struct ieee80211_supported_band *sband; + /* + * This _could_ be supported by providing a hook for + * drivers for this function, but at this point it + * doesn't seem worth bothering. + */ + if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) + return -EOPNOTSUPP; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates + /* + * target_rate = -1, rate->fixed = 0 means auto only, so use all rates * target_rate = X, rate->fixed = 1 means only rate X - * target_rate = X, rate->fixed = 0 means all rates <= X */ + * target_rate = X, rate->fixed = 0 means all rates <= X + */ sdata->max_ratectrl_rateidx = -1; sdata->force_unicast_rateidx = -1; @@ -1418,20 +1428,18 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, else return 0; - for (i=0; i< sband->n_bitrates; i++) { - struct ieee80211_rate *brate = &sband->bitrates[i]; - int this_rate = brate->bitrate; + for (i = 0; i< sband->n_bitrates; i++) { + if (target_rate != sband->bitrates[i].bitrate) + continue; - if (target_rate == this_rate) { - sdata->max_ratectrl_rateidx = i; - if (mask->fixed) - sdata->force_unicast_rateidx = i; - err = 0; - break; - } + /* requested bitrate found */ + sdata->max_ratectrl_rateidx = i; + if (mask->fixed) + sdata->force_unicast_rateidx = i; + return 0; } - return err; + return -EINVAL; } struct cfg80211_ops mac80211_config_ops = { -- cgit v1.2.3 From 265dc7f0964e4df95ab57a9d1618689301d39a55 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 4 Dec 2009 19:10:34 +0200 Subject: mac80211_hwsim: Check all local addresses for TX Ack status Since mac80211_hwsim supports multiple virtual interfaces, we need to iterate through all active interfaces when figuring out whether there is a match during TX Ack status checking. This fixes TX status reporting for cases where secondary interfaces are used. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 89f527ee1a10..718a5f198c30 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -436,6 +436,38 @@ static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, } +struct mac80211_hwsim_addr_match_data { + bool ret; + const u8 *addr; +}; + +static void mac80211_hwsim_addr_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mac80211_hwsim_addr_match_data *md = data; + if (memcmp(mac, md->addr, ETH_ALEN) == 0) + md->ret = true; +} + + +static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, + const u8 *addr) +{ + struct mac80211_hwsim_addr_match_data md; + + if (memcmp(addr, data->hw->wiphy->perm_addr, ETH_ALEN) == 0) + return true; + + md.ret = false; + md.addr = addr; + ieee80211_iterate_active_interfaces_atomic(data->hw, + mac80211_hwsim_addr_iter, + &md); + + return md.ret; +} + + static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct sk_buff *skb) { @@ -488,8 +520,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, if (nskb == NULL) continue; - if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr, - ETH_ALEN) == 0) + if (mac80211_hwsim_addr_match(data2, hdr->addr1)) ack = true; memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(data2->hw, nskb); -- cgit v1.2.3 From c755ad34ab233afaaacd3d67190a8b74186f9fe8 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 7 Dec 2009 12:38:41 -0500 Subject: ath9k: add MCS rate index back to debufs rcstat Speaking of 802.11n rates in terms of Mbps doesn't really developers and is just useful for users. To aid debugging add the MCS index back and an HT20/HT40 mode. New screenshot: HT MCS Rate Success Retries XRetries PER 6.0: 0 0 0 0 9.0: 0 0 0 0 12.0: 26 260 0 49 18.0: 80 804 2 58 24.0: 0 0 0 0 36.0: 0 0 0 0 48.0: 0 0 0 0 54.0: 0 0 0 0 HT20 0 6.5: 1368 13660 0 48 HT20 1 13.0: 0 0 0 0 HT20 2 19.5: 0 0 0 0 HT20 3 26.0: 0 0 0 0 HT20 4 39.0: 0 0 0 0 HT20 5 52.0: 55 578 14 43 HT20 6 58.5: 29 306 8 69 HT20 7 65.0: 21 210 0 67 HT20 8 13.0: 21 210 0 56 HT20 9 26.0: 0 0 0 0 HT20 10 39.0: 0 0 0 0 HT20 11 52.0: 0 0 0 0 HT20 12 78.0: 0 0 0 0 HT20 13 104.0: 0 0 0 0 HT20 14 117.0: 0 0 0 0 HT20 15 130.0: 27 290 10 55 HT40 0 13.5: 79 687 16 17 HT40 1 27.5: 60 409 10 17 HT40 2 40.5: 56 381 21 25 HT40 3 54.0: 44 302 21 18 HT40 4 81.5: 19 171 2 14 HT40 5 108.0: 0 0 0 0 HT40 6 121.5: 0 0 0 0 HT40 7 135.0: 0 0 0 0 HT40 7 150.0: 0 0 0 0 HT40 8 27.0: 0 0 0 0 HT40 9 54.0: 0 0 0 0 HT40 10 81.0: 0 0 0 0 HT40 11 108.0: 11 100 0 18 HT40 12 162.0: 23 200 0 22 HT40 13 216.0: 61 580 0 35 HT40 14 243.0: 37 271 0 66 HT40 15 270.0: 65 217 2 73 HT40 15 300.0: 0 0 0 0 Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 38 ++++++++++++++++++++++++++++------ drivers/net/wireless/ath/ath9k/rc.h | 4 ++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index b66f72dbf7b9..592f1b70f55a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -289,23 +289,49 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, if (sc->cur_rate_table == NULL) return 0; - max = 80 + sc->cur_rate_table->rate_cnt * 64; + max = 80 + sc->cur_rate_table->rate_cnt * 1024; buf = kmalloc(max + 1, GFP_KERNEL); if (buf == NULL) return 0; buf[max] = 0; - len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success", - "Retries", "XRetries", "PER"); + len += sprintf(buf, "%6s %6s %6s " + "%10s %10s %10s %10s\n", + "HT", "MCS", "Rate", + "Success", "Retries", "XRetries", "PER"); for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; + char mcs[5]; + char htmode[5]; + int used_mcs = 0, used_htmode = 0; + + if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { + used_mcs = snprintf(mcs, 5, "%d", + sc->cur_rate_table->info[i].ratecode); + + if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) + used_htmode = snprintf(htmode, 5, "HT40"); + else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) + used_htmode = snprintf(htmode, 5, "HT20"); + else + used_htmode = snprintf(htmode, 5, "????"); + } + + mcs[used_mcs] = '\0'; + htmode[used_htmode] = '\0'; len += snprintf(buf + len, max - len, - "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000, - (ratekbps % 1000) / 100, stats->success, - stats->retries, stats->xretries, + "%6s %6s %3u.%d: " + "%10u %10u %10u %10u\n", + htmode, + mcs, + ratekbps / 1000, + (ratekbps % 1000) / 100, + stats->success, + stats->retries, + stats->xretries, stats->per); } diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 9eb96f506998..4f6d6fd442f4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -57,6 +57,10 @@ enum { || (_phy == WLAN_RC_PHY_HT_40_DS) \ || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) +#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \ + || (_phy == WLAN_RC_PHY_HT_20_DS) \ + || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ + || (_phy == WLAN_RC_PHY_HT_20_DS_HGI)) #define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ || (_phy == WLAN_RC_PHY_HT_40_DS) \ || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ -- cgit v1.2.3 From cb136f54ee11f9ead716b5ad0b10fa1c1b05271d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 7 Dec 2009 14:01:28 -0500 Subject: mac80211: make debugfs mcs set entry reflect 16 bits The MCS set is 16 bits so when debugging ensure the full 16 bits are represented. Current reading would make you think its only 8 bits. Cc: johannes@sipsolutions.net Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 374ff6f98a9c..9a1d1e40eca8 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -168,7 +168,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", htc->ht_supported ? "" : "not "); if (htc->ht_supported) { - p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.2x\n", htc->cap); + p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", htc->ampdu_factor, htc->ampdu_density); p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); -- cgit v1.2.3 From 7db94e210351e8578d4a98fed3edd4df5f10ae9d Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 7 Dec 2009 14:54:45 -0500 Subject: mac80211: parse the HT capabilities info through debugfs When debugging you want to be lazy and not have to parse bits yourself so let mac80211 debugfs do the parsing for you. This is what I get against my WRT610N: root@tux:~# cat /sys/kernel/debug/ieee80211/phy0/stations/00\:22\:6b\:aa\:bb\:01/ht_capa ht supported cap: 0x000e HT20/HT40 SM Power Save disabled No RX STBC Max AMSDU length: 7935 bytes No DSSS/CCK HT40 ampdu factor/density: 2/6 MCS mask: ff ff 00 00 00 00 00 00 00 00 MCS rx highest: 0 MCS tx params: 0 Cc: johannes@sipsolutions.net Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 48 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 9a1d1e40eca8..c833b6ce9902 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -160,7 +160,12 @@ STA_OPS(agg_status); static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[200], *p = buf; +#define PRINT_HT_CAP(_cond, _str) \ + do { \ + if (_cond) \ + p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ + } while (0) + char buf[1024], *p = buf; int i; struct sta_info *sta = file->private_data; struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; @@ -169,6 +174,47 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, htc->ht_supported ? "" : "not "); if (htc->ht_supported) { p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); + + PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP"); + PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); + PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); + + PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 0, "Static SM Power Save"); + PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 1, "Dynamic SM Power Save"); + PRINT_HT_CAP(((htc->cap >> 2) & 0x3) == 3, "SM Power Save disabled"); + + PRINT_HT_CAP((htc->cap & BIT(4)), "RX Greenfield"); + PRINT_HT_CAP((htc->cap & BIT(5)), "RX HT20 SGI"); + PRINT_HT_CAP((htc->cap & BIT(6)), "RX HT40 SGI"); + PRINT_HT_CAP((htc->cap & BIT(7)), "TX STBC"); + + PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 0, "No RX STBC"); + PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 1, "RX STBC 1-stream"); + PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 2, "RX STBC 2-streams"); + PRINT_HT_CAP(((htc->cap >> 8) & 0x3) == 3, "RX STBC 3-streams"); + + PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); + + PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " + "3839 bytes"); + PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " + "7935 bytes"); + + /* + * For beacons and probe response this would mean the BSS + * does or does not allow the usage of DSSS/CCK HT40. + * Otherwise it means the STA does or does not use + * DSSS/CCK HT40. + */ + PRINT_HT_CAP((htc->cap & BIT(12)), "DSSS/CCK HT40"); + PRINT_HT_CAP(!(htc->cap & BIT(12)), "No DSSS/CCK HT40"); + + /* BIT(13) is reserved */ + + PRINT_HT_CAP((htc->cap & BIT(14)), "40 MHz Intolerant"); + + PRINT_HT_CAP((htc->cap & BIT(15)), "L-SIG TXOP protection"); + p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", htc->ampdu_factor, htc->ampdu_density); p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); -- cgit v1.2.3 From 9da3e068142ec7856b2f13261dcf0660fad32b61 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 7 Dec 2009 15:57:50 -0500 Subject: mac80211: only bother printing highest data rate on debugfs if its set IEEE-802.11n spec says the RX highest data rate field does not specify the highest supported RX data rate if its not set. Ignore it if not set then. Refer to section 7.3.56.4 Cc: johannes@sipsolutions.net Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 5 ++++- net/mac80211/debugfs_sta.c | 12 ++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index e8d43d0ff2c3..098bedcde9bb 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -775,7 +775,10 @@ struct ieee80211_bar { /** * struct ieee80211_mcs_info - MCS information * @rx_mask: RX mask - * @rx_highest: highest supported RX rate + * @rx_highest: highest supported RX rate. If set represents + * the highest supported RX data rate in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. * @tx_params: TX parameters */ struct ieee80211_mcs_info { diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index c833b6ce9902..0d4a759ba72c 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -218,11 +218,19 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", htc->ampdu_factor, htc->ampdu_density); p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); + for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", htc->mcs.rx_mask[i]); - p += scnprintf(p, sizeof(buf)+buf-p, "\nMCS rx highest: %d\n", - le16_to_cpu(htc->mcs.rx_highest)); + p += scnprintf(p, sizeof(buf)+buf-p, "\n"); + + /* If not set this is meaningless */ + if (le16_to_cpu(htc->mcs.rx_highest)) { + p += scnprintf(p, sizeof(buf)+buf-p, + "MCS rx highest: %d Mbps\n", + le16_to_cpu(htc->mcs.rx_highest)); + } + p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", htc->mcs.tx_params); } -- cgit v1.2.3 From 5b6e2f12edd6c46e87a2775321f1912d19be4b35 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Tue, 8 Dec 2009 15:21:34 +0100 Subject: ar9170usb: add Sphairon Homelink 1202 USB ID Signed-off-by: Stefan Seyfried Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e0799d924057..0f361186b78f 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -84,6 +84,8 @@ static struct usb_device_id ar9170_usb_ids[] = { { USB_DEVICE(0x0cde, 0x0023) }, /* Z-Com UB82 ABG */ { USB_DEVICE(0x0cde, 0x0026) }, + /* Sphairon Homelink 1202 */ + { USB_DEVICE(0x0cde, 0x0027) }, /* Arcadyan WN7512 */ { USB_DEVICE(0x083a, 0xf522) }, /* Planex GWUS300 */ -- cgit v1.2.3 From 11466f1342a3400dd5e03da3d8c45aa4149c62d4 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Tue, 8 Dec 2009 15:21:35 +0100 Subject: zd1211rw: improve ejecting of fake CDROM The zd1211rw always assumed that the storage device is at endpoint 1, but there are devices (Spairon Homelink 1202) that are at endpoint 0. Try both, starting with 1 to make sure to not break existing setups. Signed-off-by: Stefan Seyfried Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ac19ecd19cfe..4daf1c94ec04 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1078,11 +1078,15 @@ static int eject_installer(struct usb_interface *intf) int r; /* Find bulk out endpoint */ - endpoint = &iface_desc->endpoint[1].desc; - if (usb_endpoint_dir_out(endpoint) && - usb_endpoint_xfer_bulk(endpoint)) { - bulk_out_ep = endpoint->bEndpointAddress; - } else { + for (r = 1; r >= 0; r--) { + endpoint = &iface_desc->endpoint[r].desc; + if (usb_endpoint_dir_out(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + bulk_out_ep = endpoint->bEndpointAddress; + break; + } + } + if (r == -1) { dev_err(&udev->dev, "zd1211rw: Could not find bulk out endpoint\n"); return -ENODEV; -- cgit v1.2.3 From ba37a3d0395a66b3c9164c4f4d1318317da32e96 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 10 Dec 2009 14:37:27 -0800 Subject: iwlwifi: use new mac80211 SMPS Instead of hard-coding the SM PS mode per hardware, this makes iwlwifi support the new mac80211 API for controlling the SM PS mode. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 4 --- drivers/net/wireless/iwlwifi/iwl-6000.c | 3 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 5 ++++ drivers/net/wireless/iwlwifi/iwl-core.c | 53 ++++++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 8 files changed, 32 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9d4fdd7a1134..5759f91343a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -174,7 +174,6 @@ struct iwl_cfg iwl1000_bgn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl1000_bg_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 386513b601f5..34778cf120fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2239,7 +2239,6 @@ struct iwl_cfg iwl4965_agn_cfg = { .broken_powersave = true, .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 5a277cdffd07..3236315c75be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1600,7 +1600,6 @@ struct iwl_cfg iwl5300_agn_cfg = { .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -1669,7 +1668,6 @@ struct iwl_cfg iwl5100_agn_cfg = { .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1693,7 +1691,6 @@ struct iwl_cfg iwl5350_agn_cfg = { .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1717,7 +1714,6 @@ struct iwl_cfg iwl5150_agn_cfg = { .ht_greenfield_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl5150_abg_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fec43771c49e..788457ae25a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -307,7 +307,6 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -396,7 +395,6 @@ struct iwl_cfg iwl6050_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -456,7 +454,6 @@ struct iwl_cfg iwl6000_3agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, - .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0b3669f317a4..904b5d8da860 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2623,6 +2623,10 @@ static int iwl_setup_mac(struct iwl_priv *priv) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + if (priv->cfg->sku & IWL_SKU_N) + hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | + IEEE80211_HW_SUPPORTS_STATIC_SMPS; + hw->sta_data_size = sizeof(struct iwl_station_priv); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | @@ -3361,6 +3365,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->band = IEEE80211_BAND_2GHZ; priv->iw_mode = NL80211_IFTYPE_STATION; + priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; /* Choose which receivers/antennas to use */ if (priv->cfg->ops->hcmd->set_rxon_chain) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c3c31dc9fd4d..e3b96b48b7fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -450,8 +450,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, if (priv->cfg->ht_greenfield_support) ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; ht_info->cap |= IEEE80211_HT_CAP_SGI_20; - ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & - (priv->cfg->sm_ps_mode << 2)); max_bit_rate = MAX_BIT_RATE_20_MHZ; if (priv->hw_params.ht40_channel & BIT(band)) { ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; @@ -636,7 +634,7 @@ EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); static bool is_single_rx_stream(struct iwl_priv *priv) { - return !priv->current_ht_config.is_ht || + return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || priv->current_ht_config.single_chain_sufficient; } @@ -1003,28 +1001,18 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) */ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) { - int idle_cnt = active_cnt; - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - - /* # Rx chains when idling and maybe trying to save power */ - switch (priv->cfg->sm_ps_mode) { - case WLAN_HT_CAP_SM_PS_STATIC: - idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_DYNAMIC: - idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : - IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_DISABLED: - break; - case WLAN_HT_CAP_SM_PS_INVALID: + /* # Rx chains when idling, depending on SMPS mode */ + switch (priv->current_ht_config.smps) { + case IEEE80211_SMPS_STATIC: + case IEEE80211_SMPS_DYNAMIC: + return IWL_NUM_IDLE_CHAINS_SINGLE; + case IEEE80211_SMPS_OFF: + return active_cnt; default: - IWL_ERR(priv, "invalid sm_ps mode %u\n", - priv->cfg->sm_ps_mode); - WARN_ON(1); - break; + WARN(1, "invalid SMPS mode %d", + priv->current_ht_config.smps); + return active_cnt; } - return idle_cnt; } /* up to 4 chains */ @@ -2686,6 +2674,21 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); } + if (changed & (IEEE80211_CONF_CHANGE_SMPS | + IEEE80211_CONF_CHANGE_CHANNEL)) { + /* mac80211 uses static for non-HT which is what we want */ + priv->current_ht_config.smps = conf->smps_mode; + + /* + * Recalculate chain counts. + * + * If monitor mode is enabled then mac80211 will + * set up the SM PS mode to OFF if an HT channel is + * configured. + */ + if (priv->cfg->ops->hcmd->set_rxon_chain) + priv->cfg->ops->hcmd->set_rxon_chain(priv); + } /* during scanning mac80211 will delay channel setting until * scan finish with changed = 0 @@ -2782,10 +2785,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) iwl_set_tx_power(priv, conf->power_level, false); } - /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); goto out; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 650d3808d24a..f7acbb32900a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -232,7 +232,6 @@ struct iwl_mod_params { * @chain_noise_num_beacons: number of beacons used to compute chain noise * @adv_thermal_throttle: support advance thermal throttle * @support_ct_kill_exit: support ct kill exit condition - * @sm_ps_mode: spatial multiplexing power save mode * @support_wimax_coexist: support wimax/wifi co-exist * * We enable the driver to be backward compatible wrt API version. The @@ -289,7 +288,6 @@ struct iwl_cfg { const bool supports_idle; bool adv_thermal_throttle; bool support_ct_kill_exit; - u8 sm_ps_mode; const bool support_wimax_coexist; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b3a29c7cdbc0..1e12e7340c90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -512,6 +512,7 @@ struct iwl_ht_config { bool is_ht; bool is_40mhz; bool single_chain_sufficient; + enum ieee80211_smps_mode smps; /* current smps mode */ /* BSS related data */ u8 extension_chan_offset; u8 ht_protection; -- cgit v1.2.3 From 45d5d805988f1f3c0b24dac59fbba771b1f106a8 Mon Sep 17 00:00:00 2001 From: Emese Revfy Date: Mon, 14 Dec 2009 00:59:53 +0100 Subject: iwlwifi: Constify struct iwl_ops Signed-off-by: Emese Revfy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5759f91343a5..0db1fda94a65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -141,7 +141,7 @@ static struct iwl_lib_ops iwl1000_lib = { }, }; -static struct iwl_ops iwl1000_ops = { +static const struct iwl_ops iwl1000_ops = { .ucode = &iwl5000_ucode, .lib = &iwl1000_lib, .hcmd = &iwl5000_hcmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7da1dab933d9..3708b5c204e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2811,7 +2811,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, }; -static struct iwl_ops iwl3945_ops = { +static const struct iwl_ops iwl3945_ops = { .ucode = &iwl3945_ucode, .lib = &iwl3945_lib, .hcmd = &iwl3945_hcmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 34778cf120fc..a5e3384d56b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2208,7 +2208,7 @@ static struct iwl_lib_ops iwl4965_lib = { }, }; -static struct iwl_ops iwl4965_ops = { +static const struct iwl_ops iwl4965_ops = { .ucode = &iwl4965_ucode, .lib = &iwl4965_lib, .hcmd = &iwl4965_hcmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 3236315c75be..f2b1915530e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1556,7 +1556,7 @@ static struct iwl_lib_ops iwl5150_lib = { }, }; -static struct iwl_ops iwl5000_ops = { +static const struct iwl_ops iwl5000_ops = { .ucode = &iwl5000_ucode, .lib = &iwl5000_lib, .hcmd = &iwl5000_hcmd, @@ -1564,7 +1564,7 @@ static struct iwl_ops iwl5000_ops = { .led = &iwlagn_led_ops, }; -static struct iwl_ops iwl5150_ops = { +static const struct iwl_ops iwl5150_ops = { .ucode = &iwl5000_ucode, .lib = &iwl5150_lib, .hcmd = &iwl5000_hcmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 788457ae25a8..a5a0ed4817a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -253,7 +253,7 @@ static struct iwl_lib_ops iwl6000_lib = { }, }; -static struct iwl_ops iwl6000_ops = { +static const struct iwl_ops iwl6000_ops = { .ucode = &iwl5000_ucode, .lib = &iwl6000_lib, .hcmd = &iwl5000_hcmd, @@ -268,7 +268,7 @@ static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = { .calc_rssi = iwl5000_calc_rssi, }; -static struct iwl_ops iwl6050_ops = { +static const struct iwl_ops iwl6050_ops = { .ucode = &iwl5000_ucode, .lib = &iwl6000_lib, .hcmd = &iwl5000_hcmd, -- cgit v1.2.3 From 0ce024cbcd5837596bc82861f1d3074d53e956f6 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 14 Dec 2009 14:57:00 +0530 Subject: ath9k: Clarify Interrupt mitigation ath9k currently supports only RX interrupt mitigation. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 +++++----- drivers/net/wireless/ath/ath9k/hw.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 917f70f7a28e..9474f9f6d400 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -368,7 +368,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } - ah->config.intr_mitigation = true; + ah->config.rx_intr_mitigation = true; /* * We need this for PCI devices only (Cardbus, PCI, miniPCI) @@ -1160,7 +1160,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, AR_IMR_RXORN | AR_IMR_BCNMISC; - if (ah->config.intr_mitigation) + if (ah->config.rx_intr_mitigation) ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; else ah->mask_reg |= AR_IMR_RXOK; @@ -2091,7 +2091,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, REG_WRITE(ah, AR_OBS, 8); - if (ah->config.intr_mitigation) { + if (ah->config.rx_intr_mitigation) { REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); } @@ -2751,7 +2751,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) *masked = isr & ATH9K_INT_COMMON; - if (ah->config.intr_mitigation) { + if (ah->config.rx_intr_mitigation) { if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) *masked |= ATH9K_INT_RX; } @@ -2884,7 +2884,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) } if (ints & ATH9K_INT_RX) { mask |= AR_IMR_RXERR; - if (ah->config.intr_mitigation) + if (ah->config.rx_intr_mitigation) mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; else mask |= AR_IMR_RXOK | AR_IMR_RXDESC; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e2b0c73a616f..8849450dc591 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -212,7 +212,7 @@ struct ath9k_ops_config { u32 cck_trig_low; u32 enable_ani; int serialize_regmode; - bool intr_mitigation; + bool rx_intr_mitigation; #define SPUR_DISABLE 0 #define SPUR_ENABLE_IOCTL 1 #define SPUR_ENABLE_EEPROM 2 -- cgit v1.2.3 From 05c78d6d3ec5a8325398b3866e7e6bb88940d4fd Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 14 Dec 2009 14:57:04 +0530 Subject: ath9k: Remove ANI lock Cancel/restart the ANI timer directly. With this patch, the ANI lock can be removed. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 - drivers/net/wireless/ath/ath9k/main.c | 19 ++++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index e2cef2ff5d8f..9f1f523e02eb 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -453,7 +453,6 @@ struct ath_softc { int irq; spinlock_t sc_resetlock; spinlock_t sc_serial_rw; - spinlock_t ani_lock; spinlock_t sc_pm_lock; struct mutex mutex; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c48743452515..adb0edf2c8b0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -363,14 +363,6 @@ static void ath_ani_calibrate(unsigned long data) short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; - /* - * don't calibrate when we're scanning. - * we are most likely not on our home channel. - */ - spin_lock(&sc->ani_lock); - if (sc->sc_flags & SC_OP_SCANNING) - goto set_timer; - /* Only calibrate if awake */ if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) goto set_timer; @@ -437,7 +429,6 @@ static void ath_ani_calibrate(unsigned long data) ath9k_ps_restore(sc); set_timer: - spin_unlock(&sc->ani_lock); /* * Set timer interval based on previous results. * The interval must be the shortest necessary to satisfy ANI, @@ -1610,7 +1601,6 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, spin_lock_init(&sc->wiphy_lock); spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); - spin_lock_init(&sc->ani_lock); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); @@ -3113,6 +3103,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); mutex_lock(&sc->mutex); if (ath9k_wiphy_scanning(sc)) { @@ -3128,10 +3119,8 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) aphy->state = ATH_WIPHY_SCAN; ath9k_wiphy_pause_all_forced(sc, aphy); - - spin_lock_bh(&sc->ani_lock); sc->sc_flags |= SC_OP_SCANNING; - spin_unlock_bh(&sc->ani_lock); + del_timer_sync(&common->ani.timer); mutex_unlock(&sc->mutex); } @@ -3139,13 +3128,13 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); mutex_lock(&sc->mutex); - spin_lock_bh(&sc->ani_lock); aphy->state = ATH_WIPHY_ACTIVE; sc->sc_flags &= ~SC_OP_SCANNING; sc->sc_flags |= SC_OP_FULL_RESET; - spin_unlock_bh(&sc->ani_lock); + ath_start_ani(common); ath_beacon_config(sc, NULL); mutex_unlock(&sc->mutex); } -- cgit v1.2.3 From b6ce5c33001b1dc83e6a1a6f30c5dccccea651b6 Mon Sep 17 00:00:00 2001 From: Sujith Date: Mon, 14 Dec 2009 14:57:06 +0530 Subject: ath9k: Fix TX poll routine Disable the TX hang monitoring routine when doing a scan. Monitoring for a hung situation is not really necessary during a scan run. Cc: stable@kernel.org Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index adb0edf2c8b0..6401b3521049 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -3121,6 +3121,7 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw) ath9k_wiphy_pause_all_forced(sc, aphy); sc->sc_flags |= SC_OP_SCANNING; del_timer_sync(&common->ani.timer); + cancel_delayed_work_sync(&sc->tx_complete_work); mutex_unlock(&sc->mutex); } @@ -3135,6 +3136,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) sc->sc_flags &= ~SC_OP_SCANNING; sc->sc_flags |= SC_OP_FULL_RESET; ath_start_ani(common); + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ath_beacon_config(sc, NULL); mutex_unlock(&sc->mutex); } -- cgit v1.2.3 From bc86fcbac0a86a93ee65cc31769c4e83e6ff2295 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 8 Dec 2009 20:40:54 +0000 Subject: netxen: minor suspend resume fixes o pci device should be disable at the end and it should be enable first. o Interface should be attached(netif_device_attach()) irrespective of its state. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6cae26a5bd67..41cb0af4b556 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1448,14 +1448,14 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3hot, 1); } - pci_disable_device(pdev); - return 0; } static void netxen_nic_shutdown(struct pci_dev *pdev) { if (__netxen_nic_shutdown(pdev)) return; + + pci_disable_device(pdev); } #ifdef CONFIG_PM static int @@ -1468,6 +1468,8 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) return retval; pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + pci_disable_device(pdev); return 0; } @@ -1478,13 +1480,14 @@ netxen_nic_resume(struct pci_dev *pdev) struct net_device *netdev = adapter->netdev; int err; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - err = pci_enable_device(pdev); if (err) return err; + pci_set_power_state(pdev, PCI_D0); + pci_set_master(pdev); + pci_restore_state(pdev); + adapter->ahw.crb_win = -1; adapter->ahw.ocm_win = -1; @@ -1503,11 +1506,10 @@ netxen_nic_resume(struct pci_dev *pdev) if (err) goto err_out_detach; - netif_device_attach(netdev); - netxen_config_indev_addr(netdev, NETDEV_UP); } + netif_device_attach(netdev); netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); return 0; -- cgit v1.2.3 From 6a808c6c02fb9f0ffa24ac7cca6cfc323cf98b21 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 8 Dec 2009 20:40:55 +0000 Subject: netxen: fix tx timeout recovery o In case of tx timeout, firmare may be healthy, but some pci-func may see no response from it. Force firmware reset, if some pci-func explicitly requests so. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_init.c | 3 +++ drivers/net/netxen/netxen_nic_main.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 02f8d4b4db63..ba62411f3532 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -778,6 +778,9 @@ netxen_need_fw_reset(struct netxen_adapter *adapter) if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 1; + if (adapter->need_fw_reset) + return 1; + /* last attempt had failed */ if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) return 1; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 41cb0af4b556..1aca6260909a 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2284,8 +2284,10 @@ netxen_check_health(struct netxen_adapter *adapter) } state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (state == NX_DEV_NEED_RESET) + if (state == NX_DEV_NEED_RESET) { + adapter->need_fw_reset = 1; goto detach; + } if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) return 0; -- cgit v1.2.3 From e87ad5539343366e7c634c940a930157b6fa2aae Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 8 Dec 2009 20:40:56 +0000 Subject: netxen: support pci error handlers o Support pci error detection and recovery. o Refactor suspend and resume code, to share with io_error_detected, and slot_reset callbacks o NX_NEED_AER device state added, to synchronize with firmware recovery. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hdr.h | 3 +- drivers/net/netxen/netxen_nic_main.c | 193 +++++++++++++++++++++++++++-------- 2 files changed, 150 insertions(+), 46 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index d138fc22927a..638369024908 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -969,7 +969,8 @@ enum { #define NX_DEV_READY 3 #define NX_DEV_NEED_RESET 4 #define NX_DEV_NEED_QUISCENT 5 -#define NX_DEV_FAILED 6 +#define NX_DEV_NEED_AER 6 +#define NX_DEV_FAILED 7 #define NX_RCODE_DRIVER_INFO 0x20000000 #define NX_RCODE_DRIVER_CAN_RELOAD 0x40000000 diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 1aca6260909a..f13a07f717c7 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -35,6 +35,7 @@ #include #include #include +#include MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver"); MODULE_LICENSE("GPL"); @@ -84,6 +85,7 @@ static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); static void netxen_create_diag_entries(struct netxen_adapter *adapter); static void netxen_remove_diag_entries(struct netxen_adapter *adapter); +static int nx_dev_request_aer(struct netxen_adapter *adapter); static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); static int netxen_can_start_firmware(struct netxen_adapter *adapter); @@ -1262,6 +1264,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) goto err_out_disable_pdev; + if (NX_IS_REVISION_P3(pdev->revision)) + pci_enable_pcie_error_reporting(pdev); + pci_set_master(pdev); netdev = alloc_etherdev(sizeof(struct netxen_adapter)); @@ -1409,17 +1414,19 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_release_firmware(adapter); + if (NX_IS_REVISION_P3(pdev->revision)) + pci_disable_pcie_error_reporting(pdev); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); free_netdev(netdev); } -static int __netxen_nic_shutdown(struct pci_dev *pdev) + +static void netxen_nic_detach_func(struct netxen_adapter *adapter) { - struct netxen_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; - int retval; netif_device_detach(netdev); @@ -1438,43 +1445,9 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev) nx_decr_dev_ref_cnt(adapter); clear_bit(__NX_RESETTING, &adapter->state); - - retval = pci_save_state(pdev); - if (retval) - return retval; - - if (netxen_nic_wol_supported(adapter)) { - pci_enable_wake(pdev, PCI_D3cold, 1); - pci_enable_wake(pdev, PCI_D3hot, 1); - } - - return 0; -} -static void netxen_nic_shutdown(struct pci_dev *pdev) -{ - if (__netxen_nic_shutdown(pdev)) - return; - - pci_disable_device(pdev); -} -#ifdef CONFIG_PM -static int -netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) -{ - int retval; - - retval = __netxen_nic_shutdown(pdev); - if (retval) - return retval; - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - pci_disable_device(pdev); - return 0; } -static int -netxen_nic_resume(struct pci_dev *pdev) +static int netxen_nic_attach_func(struct pci_dev *pdev) { struct netxen_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; @@ -1519,6 +1492,85 @@ err_out: nx_decr_dev_ref_cnt(adapter); return err; } + +static pci_ers_result_t netxen_io_error_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + if (nx_dev_request_aer(adapter)) + return PCI_ERS_RESULT_RECOVERED; + + netxen_nic_detach_func(adapter); + + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t netxen_io_slot_reset(struct pci_dev *pdev) +{ + int err = 0; + + err = netxen_nic_attach_func(pdev); + + return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; +} + +static void netxen_io_resume(struct pci_dev *pdev) +{ + pci_cleanup_aer_uncorrect_error_status(pdev); +} + +static void netxen_nic_shutdown(struct pci_dev *pdev) +{ + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + + netxen_nic_detach_func(adapter); + + if (pci_save_state(pdev)) + return; + + if (netxen_nic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } + + pci_disable_device(pdev); +} + +#ifdef CONFIG_PM +static int +netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + int retval; + + netxen_nic_detach_func(adapter); + + retval = pci_save_state(pdev); + if (retval) + return retval; + + if (netxen_nic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } + + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int +netxen_nic_resume(struct pci_dev *pdev) +{ + return netxen_nic_attach_func(pdev); +} #endif static int netxen_nic_open(struct net_device *netdev) @@ -2110,20 +2162,49 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) return count; } -static void +static int +nx_dev_request_aer(struct netxen_adapter *adapter) +{ + u32 state; + int ret = -EINVAL; + + if (netxen_api_lock(adapter)) + return ret; + + state = NXRD32(adapter, NX_CRB_DEV_STATE); + + if (state == NX_DEV_NEED_AER) + ret = 0; + else if (state == NX_DEV_READY) { + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_AER); + ret = 0; + } + + netxen_api_unlock(adapter); + return ret; +} + +static int nx_dev_request_reset(struct netxen_adapter *adapter) { u32 state; + int ret = -EINVAL; if (netxen_api_lock(adapter)) - return; + return ret; state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (state != NX_DEV_INITALIZING) + if (state == NX_DEV_NEED_RESET) + ret = 0; + else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); + ret = 0; + } netxen_api_unlock(adapter); + + return ret; } static int @@ -2275,18 +2356,28 @@ netxen_check_health(struct netxen_adapter *adapter) u32 state, heartbit; struct net_device *netdev = adapter->netdev; + state = NXRD32(adapter, NX_CRB_DEV_STATE); + if (state == NX_DEV_NEED_AER) + return 0; + if (netxen_nic_check_temp(adapter)) goto detach; if (adapter->need_fw_reset) { - nx_dev_request_reset(adapter); + if (nx_dev_request_reset(adapter)) + return 0; goto detach; } - state = NXRD32(adapter, NX_CRB_DEV_STATE); + /* NX_DEV_NEED_RESET, this state can be marked in two cases + * 1. Tx timeout 2. Fw hang + * Send request to destroy context in case of tx timeout only + * and doesn't required in case of Fw hang + */ if (state == NX_DEV_NEED_RESET) { adapter->need_fw_reset = 1; - goto detach; + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + goto detach; } if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) @@ -2296,12 +2387,17 @@ netxen_check_health(struct netxen_adapter *adapter) if (heartbit != adapter->heartbit) { adapter->heartbit = heartbit; adapter->fw_fail_cnt = 0; + if (adapter->need_fw_reset) + goto detach; return 0; } if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) return 0; + if (nx_dev_request_reset(adapter)) + return 0; + clear_bit(__NX_FW_ATTACHED, &adapter->state); dev_info(&netdev->dev, "firmware hang detected\n"); @@ -2731,6 +2827,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) { } #endif +static struct pci_error_handlers netxen_err_handler = { + .error_detected = netxen_io_error_detected, + .slot_reset = netxen_io_slot_reset, + .resume = netxen_io_resume, +}; + static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, @@ -2740,7 +2842,8 @@ static struct pci_driver netxen_driver = { .suspend = netxen_nic_suspend, .resume = netxen_nic_resume, #endif - .shutdown = netxen_nic_shutdown + .shutdown = netxen_nic_shutdown, + .err_handler = &netxen_err_handler }; static int __init netxen_init_module(void) -- cgit v1.2.3 From 7ef8a2127a64d131c4dbe5b843e5708f6e75552b Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Tue, 8 Dec 2009 20:40:57 +0000 Subject: netxen: fix unified fw size check o Unified firmware image size can be < 1 MB Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 76cd1f3e9fc8..c1223c92d566 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -420,7 +420,7 @@ struct status_desc { } __attribute__ ((aligned(16))); /* UNIFIED ROMIMAGE *************************/ -#define NX_UNI_FW_MIN_SIZE 0x3eb000 +#define NX_UNI_FW_MIN_SIZE 0xc8000 #define NX_UNI_DIR_SECT_PRODUCT_TBL 0x0 #define NX_UNI_DIR_SECT_BOOTLD 0x6 #define NX_UNI_DIR_SECT_FW 0x7 -- cgit v1.2.3 From 12d50c46dc0f7fd2e625c4befaa5fa5740a7a594 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Tue, 8 Dec 2009 22:26:13 +0000 Subject: tcp: Remove check in __tcp_push_pending_frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tcp_push checks tcp_send_head and calls __tcp_push_pending_frames, which again checks tcp_send_head, and this unnecessary check is done for every other caller of __tcp_push_pending_frames. Remove tcp_send_head check in __tcp_push_pending_frames and add the check to tcp_push_pending_frames. Other functions call __tcp_push_pending_frames only when tcp_send_head would evaluate to true. Signed-off-by: Krishna Kumar Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller --- include/net/tcp.h | 16 +++++++++------- net/ipv4/tcp_output.c | 5 ----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 34f5cc24d903..185e22baecb1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -856,13 +856,6 @@ static inline void tcp_check_probe_timer(struct sock *sk) icsk->icsk_rto, TCP_RTO_MAX); } -static inline void tcp_push_pending_frames(struct sock *sk) -{ - struct tcp_sock *tp = tcp_sk(sk); - - __tcp_push_pending_frames(sk, tcp_current_mss(sk), tp->nonagle); -} - static inline void tcp_init_wl(struct tcp_sock *tp, u32 seq) { tp->snd_wl1 = seq; @@ -1342,6 +1335,15 @@ static inline int tcp_write_queue_empty(struct sock *sk) return skb_queue_empty(&sk->sk_write_queue); } +static inline void tcp_push_pending_frames(struct sock *sk) +{ + if (tcp_send_head(sk)) { + struct tcp_sock *tp = tcp_sk(sk); + + __tcp_push_pending_frames(sk, tcp_current_mss(sk), tp->nonagle); + } +} + /* Start sequence of the highest skb with SACKed bit, valid only if * sacked > 0 or when the caller has ensured validity by itself. */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 383ce237640f..12b2af36eab8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1794,11 +1794,6 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, int nonagle) { - struct sk_buff *skb = tcp_send_head(sk); - - if (!skb) - return; - /* If we are closed, the bytes will have to remain here. * In time closedown will finish, we empty the write queue and * all will be happy. -- cgit v1.2.3 From afeca340c078e17ca233b3c68c3c3a70c56bfe1d Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 10 Dec 2009 07:16:52 +0000 Subject: tcp: Remove unrequired operations in tcp_push() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unrequired operations in tcp_push() Changelog: Removed a temporary skb variable from tcp_push() Signed-off-by: Krishna Kumar Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b0a26bb25e2e..8a3f05adb39b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -536,8 +536,7 @@ static inline void skb_entail(struct sock *sk, struct sk_buff *skb) tp->nonagle &= ~TCP_NAGLE_PUSH; } -static inline void tcp_mark_urg(struct tcp_sock *tp, int flags, - struct sk_buff *skb) +static inline void tcp_mark_urg(struct tcp_sock *tp, int flags) { if (flags & MSG_OOB) tp->snd_up = tp->write_seq; @@ -546,13 +545,13 @@ static inline void tcp_mark_urg(struct tcp_sock *tp, int flags, static inline void tcp_push(struct sock *sk, int flags, int mss_now, int nonagle) { - struct tcp_sock *tp = tcp_sk(sk); - if (tcp_send_head(sk)) { - struct sk_buff *skb = tcp_write_queue_tail(sk); + struct tcp_sock *tp = tcp_sk(sk); + if (!(flags & MSG_MORE) || forced_push(tp)) - tcp_mark_push(tp, skb); - tcp_mark_urg(tp, flags, skb); + tcp_mark_push(tp, tcp_write_queue_tail(sk)); + + tcp_mark_urg(tp, flags); __tcp_push_pending_frames(sk, mss_now, (flags & MSG_MORE) ? TCP_NAGLE_CORK : nonagle); } -- cgit v1.2.3 From def87cf42069a6d4fd42a2ede8f19c620a292568 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 10 Dec 2009 07:16:59 +0000 Subject: tcp: Slightly optimize tcp_sendmsg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slightly optimize tcp_sendmsg since NETIF_F_SG is used many times iteratively in the loop. The only other modification is to change: } else if (i == MAX_SKB_FRAGS || (!i && !(sk->sk_route_caps & NETIF_F_SG))) { to: } else if (i == MAX_SKB_FRAGS || !sg) { The reason why this change is correct: this code (other than the MAX_SKB_FRAGS case) executes only due to the else part of: "if (skb_tailroom(skb) > 0) {" - i.e. there was no space in the skb to put the data inline. Hence SG is false is a sufficient condition, and there is no way a fragment can be added to the skb. Changelog: - Added the above explanation for the change Signed-off-by: Krishna Kumar Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8a3f05adb39b..d5d69ea8f249 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -876,12 +876,12 @@ ssize_t tcp_sendpage(struct socket *sock, struct page *page, int offset, #define TCP_PAGE(sk) (sk->sk_sndmsg_page) #define TCP_OFF(sk) (sk->sk_sndmsg_off) -static inline int select_size(struct sock *sk) +static inline int select_size(struct sock *sk, int sg) { struct tcp_sock *tp = tcp_sk(sk); int tmp = tp->mss_cache; - if (sk->sk_route_caps & NETIF_F_SG) { + if (sg) { if (sk_can_gso(sk)) tmp = 0; else { @@ -905,7 +905,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, struct sk_buff *skb; int iovlen, flags; int mss_now, size_goal; - int err, copied; + int sg, err, copied; long timeo; lock_sock(sk); @@ -933,6 +933,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) goto out_err; + sg = sk->sk_route_caps & NETIF_F_SG; + while (--iovlen >= 0) { int seglen = iov->iov_len; unsigned char __user *from = iov->iov_base; @@ -958,8 +960,9 @@ new_segment: if (!sk_stream_memory_free(sk)) goto wait_for_sndbuf; - skb = sk_stream_alloc_skb(sk, select_size(sk), - sk->sk_allocation); + skb = sk_stream_alloc_skb(sk, + select_size(sk, sg), + sk->sk_allocation); if (!skb) goto wait_for_memory; @@ -996,9 +999,7 @@ new_segment: /* We can extend the last page * fragment. */ merge = 1; - } else if (i == MAX_SKB_FRAGS || - (!i && - !(sk->sk_route_caps & NETIF_F_SG))) { + } else if (i == MAX_SKB_FRAGS || !sg) { /* Need to add new fragment and cannot * do this because interface is non-SG, * or because all the page slots are -- cgit v1.2.3 From 068a2de57ddf4f472e32e7af868613c574ad1d88 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Wed, 9 Dec 2009 20:59:58 +0000 Subject: net: release dst entry while cache-hot for GSO case too Non-GSO code drops dst entry for performance reasons, but the same is missing for GSO code. Drop dst while cache-hot for GSO case too. Signed-off-by: Krishna Kumar Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index be9924f60ec3..a8d68cdedbbe 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1853,6 +1853,14 @@ gso: skb->next = nskb->next; nskb->next = NULL; + + /* + * If device doesnt need nskb->dst, release it right now while + * its hot in this cpu cache + */ + if (dev->priv_flags & IFF_XMIT_DST_RELEASE) + skb_dst_drop(nskb); + rc = ops->ndo_start_xmit(nskb, dev); if (unlikely(rc != NETDEV_TX_OK)) { if (rc & ~NETDEV_TX_MASK) -- cgit v1.2.3 From 31d12926e37291970dd4f6e9940df3897766a81d Mon Sep 17 00:00:00 2001 From: laurent chavey Date: Tue, 15 Dec 2009 11:15:28 +0000 Subject: net: Add rtnetlink init_rcvwnd to set the TCP initial receive window Add rtnetlink init_rcvwnd to set the TCP initial receive window size advertised by passive and active TCP connections. The current Linux TCP implementation limits the advertised TCP initial receive window to the one prescribed by slow start. For short lived TCP connections used for transaction type of traffic (i.e. http requests), bounding the advertised TCP initial receive window results in increased latency to complete the transaction. Support for setting initial congestion window is already supported using rtnetlink init_cwnd, but the feature is useless without the ability to set a larger TCP initial receive window. The rtnetlink init_rcvwnd allows increasing the TCP initial receive window, allowing TCP connection to advertise larger TCP receive window than the ones bounded by slow start. Signed-off-by: Laurent Chavey Signed-off-by: David S. Miller --- include/linux/rtnetlink.h | 2 ++ include/net/dst.h | 2 -- include/net/tcp.h | 3 ++- net/ipv4/syncookies.c | 3 ++- net/ipv4/tcp_output.c | 17 +++++++++++++---- net/ipv6/syncookies.c | 3 ++- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 05330fc5b436..9590364fe8b5 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -362,6 +362,8 @@ enum { #define RTAX_FEATURES RTAX_FEATURES RTAX_RTO_MIN, #define RTAX_RTO_MIN RTAX_RTO_MIN + RTAX_INITRWND, +#define RTAX_INITRWND RTAX_INITRWND __RTAX_MAX }; diff --git a/include/net/dst.h b/include/net/dst.h index 39c4a5963e12..ce078cda6b74 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -83,8 +83,6 @@ struct dst_entry { * (L1_CACHE_SIZE would be too much) */ #ifdef CONFIG_64BIT - long __pad_to_align_refcnt[2]; -#else long __pad_to_align_refcnt[1]; #endif /* diff --git a/include/net/tcp.h b/include/net/tcp.h index 185e22baecb1..788c99f98597 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -965,7 +965,8 @@ static inline void tcp_sack_reset(struct tcp_options_received *rx_opt) /* Determine a window scaling and initial window to offer. */ extern void tcp_select_initial_window(int __space, __u32 mss, __u32 *rcv_wnd, __u32 *window_clamp, - int wscale_ok, __u8 *rcv_wscale); + int wscale_ok, __u8 *rcv_wscale, + __u32 init_rcv_wnd); static inline int tcp_win_from_space(int space) { diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 66fd80ef2473..5c24db4a3c91 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -358,7 +358,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, tcp_select_initial_window(tcp_full_space(sk), req->mss, &req->rcv_wnd, &req->window_clamp, - ireq->wscale_ok, &rcv_wscale); + ireq->wscale_ok, &rcv_wscale, + dst_metric(&rt->u.dst, RTAX_INITRWND)); ireq->rcv_wscale = rcv_wscale; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 12b2af36eab8..4a1605d3f909 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -183,7 +183,8 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) */ void tcp_select_initial_window(int __space, __u32 mss, __u32 *rcv_wnd, __u32 *window_clamp, - int wscale_ok, __u8 *rcv_wscale) + int wscale_ok, __u8 *rcv_wscale, + __u32 init_rcv_wnd) { unsigned int space = (__space < 0 ? 0 : __space); @@ -232,7 +233,13 @@ void tcp_select_initial_window(int __space, __u32 mss, init_cwnd = 2; else if (mss > 1460) init_cwnd = 3; - if (*rcv_wnd > init_cwnd * mss) + /* when initializing use the value from init_rcv_wnd + * rather than the default from above + */ + if (init_rcv_wnd && + (*rcv_wnd > init_rcv_wnd * mss)) + *rcv_wnd = init_rcv_wnd * mss; + else if (*rcv_wnd > init_cwnd * mss) *rcv_wnd = init_cwnd * mss; } @@ -2417,7 +2424,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, &req->rcv_wnd, &req->window_clamp, ireq->wscale_ok, - &rcv_wscale); + &rcv_wscale, + dst_metric(dst, RTAX_INITRWND)); ireq->rcv_wscale = rcv_wscale; } @@ -2544,7 +2552,8 @@ static void tcp_connect_init(struct sock *sk) &tp->rcv_wnd, &tp->window_clamp, sysctl_tcp_window_scaling, - &rcv_wscale); + &rcv_wscale, + dst_metric(dst, RTAX_INITRWND)); tp->rx_opt.rcv_wscale = rcv_wscale; tp->rcv_ssthresh = tp->rcv_wnd; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 7208a06576c6..34d1f0690d7e 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -269,7 +269,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); tcp_select_initial_window(tcp_full_space(sk), req->mss, &req->rcv_wnd, &req->window_clamp, - ireq->wscale_ok, &rcv_wscale); + ireq->wscale_ok, &rcv_wscale, + dst_metric(dst, RTAX_INITRWND)); ireq->rcv_wscale = rcv_wscale; -- cgit v1.2.3 From 9fa4d67c6e4d678271798f006ca1d945e8b2bd5c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 16 Dec 2009 04:26:24 +0000 Subject: iwmc3200top: clean up fw_download 1. removed redundant NULL-pointers checks in iwmct_fw_load as release_firmware and kfree are NULL pointer friendly 2. remove redundant memset of the parser since the structure is fully initialized in iwmct_fw_parser_init function Signed-off-by: Tomas Winkler Signed-off-by: David S. Miller --- drivers/misc/iwmc3200top/fw-download.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c index 50d431e469f5..474be9228904 100644 --- a/drivers/misc/iwmc3200top/fw-download.c +++ b/drivers/misc/iwmc3200top/fw-download.c @@ -50,8 +50,7 @@ static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file, parser->file = file; parser->file_size = file_size; parser->cur_pos = 0; - parser->buf = NULL; - + parser->entry_point = 0; parser->buf = kzalloc(block_size, GFP_KERNEL); if (!parser->buf) { LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n"); @@ -298,8 +297,6 @@ int iwmct_fw_load(struct iwmct_priv *priv) __le32 addr; int ret; - /* clear parser struct */ - memset(&priv->parser, 0, sizeof(struct iwmct_parser)); /* get the firmware */ ret = request_firmware(&raw, fw_name, &priv->func->dev); @@ -317,6 +314,7 @@ int iwmct_fw_load(struct iwmct_priv *priv) LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name); + /* clear parser struct */ ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len); if (ret < 0) { LOG_ERROR(priv, FW_DOWNLOAD, @@ -324,7 +322,6 @@ int iwmct_fw_load(struct iwmct_priv *priv) goto exit; } - /* checksum */ if (!iwmct_checksum(priv)) { LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n"); ret = -EINVAL; @@ -333,23 +330,18 @@ int iwmct_fw_load(struct iwmct_priv *priv) /* download firmware to device */ while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) { - if (iwmct_download_section(priv, pdata, len, addr)) { + ret = iwmct_download_section(priv, pdata, len, addr); + if (ret) { LOG_ERROR(priv, FW_DOWNLOAD, "%s download section failed\n", fw_name); - ret = -EIO; goto exit; } } - iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK)); + ret = iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK)); exit: kfree(priv->parser.buf); - - if (raw) - release_firmware(raw); - - raw = NULL; - + release_firmware(raw); return ret; } -- cgit v1.2.3 From 0df828f670b1fd8c469f3d60472ddca0d0f51fcf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 16 Dec 2009 04:26:25 +0000 Subject: iwmc3200top: cleanup log messages 1. add TRACE level 2. use TRACE where needed to reduce the noise 3 don't INFOEX from driver 4. add DUMP level for packets dumps 5. use correct context for the log messages Signed-off-by: Tomas Winkler Signed-off-by: David S. Miller --- drivers/misc/iwmc3200top/fw-download.c | 26 ++++++++++++++++++-------- drivers/misc/iwmc3200top/log.h | 31 ++++++++++++++++++++++--------- drivers/misc/iwmc3200top/main.c | 25 ++++++++----------------- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c index 474be9228904..07055afef858 100644 --- a/drivers/misc/iwmc3200top/fw-download.c +++ b/drivers/misc/iwmc3200top/fw-download.c @@ -43,7 +43,7 @@ static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file, struct iwmct_parser *parser = &priv->parser; struct iwmct_fw_hdr *fw_hdr = &parser->versions; - LOG_INFOEX(priv, INIT, "-->\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size); @@ -69,7 +69,7 @@ static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file, parser->cur_pos += sizeof(struct iwmct_fw_hdr); - LOG_INFOEX(priv, INIT, "<--\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); return 0; } @@ -112,7 +112,7 @@ static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec, struct iwmct_dbg *dbg = &priv->dbg; struct iwmct_fw_sec_hdr *sec_hdr; - LOG_INFOEX(priv, INIT, "-->\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr) <= parser->file_size) { @@ -151,7 +151,7 @@ static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec, "finished with section cur_pos=%zd\n", parser->cur_pos); } - LOG_INFOEX(priv, INIT, "<--\n"); + LOG_TRACE(priv, INIT, "<--\n"); return 0; } @@ -166,7 +166,7 @@ static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec, int ret = 0; u32 cmd = 0; - LOG_INFOEX(priv, INIT, "-->\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n", addr, sec_size); @@ -250,7 +250,7 @@ static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec, if (sent < sec_size) ret = -EINVAL; exit: - LOG_INFOEX(priv, INIT, "<--\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); return ret; } @@ -261,7 +261,7 @@ static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump) int ret; u32 cmd; - LOG_INFOEX(priv, INIT, "-->\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "-->\n"); memset(parser->buf, 0, parser->buf_size); cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS; @@ -284,7 +284,7 @@ static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump) if (ret) LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret); - LOG_INFOEX(priv, INIT, "<--\n"); + LOG_TRACE(priv, FW_DOWNLOAD, "<--\n"); return 0; } @@ -298,6 +298,16 @@ int iwmct_fw_load(struct iwmct_priv *priv) int ret; + LOG_INFO(priv, FW_DOWNLOAD, "barker download request 0x%x is:\n", + priv->barker); + LOG_INFO(priv, FW_DOWNLOAD, "******* Top FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not"); + LOG_INFO(priv, FW_DOWNLOAD, "******* GPS FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not"); + LOG_INFO(priv, FW_DOWNLOAD, "******* BT FW %s requested ********\n", + (priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not"); + + /* get the firmware */ ret = request_firmware(&raw, fw_name, &priv->func->dev); if (ret < 0) { diff --git a/drivers/misc/iwmc3200top/log.h b/drivers/misc/iwmc3200top/log.h index aba8121f978c..4434bb16cea7 100644 --- a/drivers/misc/iwmc3200top/log.h +++ b/drivers/misc/iwmc3200top/log.h @@ -37,13 +37,26 @@ #define LOG_SEV_INFO 3 #define LOG_SEV_INFOEX 4 -#define LOG_SEV_FILTER_ALL \ - (BIT(LOG_SEV_CRITICAL) | \ - BIT(LOG_SEV_ERROR) | \ - BIT(LOG_SEV_WARNING) | \ - BIT(LOG_SEV_INFO) | \ +/* Log levels not defined for FW */ +#define LOG_SEV_TRACE 5 +#define LOG_SEV_DUMP 6 + +#define LOG_SEV_FW_FILTER_ALL \ + (BIT(LOG_SEV_CRITICAL) | \ + BIT(LOG_SEV_ERROR) | \ + BIT(LOG_SEV_WARNING) | \ + BIT(LOG_SEV_INFO) | \ BIT(LOG_SEV_INFOEX)) +#define LOG_SEV_FILTER_ALL \ + (BIT(LOG_SEV_CRITICAL) | \ + BIT(LOG_SEV_ERROR) | \ + BIT(LOG_SEV_WARNING) | \ + BIT(LOG_SEV_INFO) | \ + BIT(LOG_SEV_INFOEX) | \ + BIT(LOG_SEV_TRACE) | \ + BIT(LOG_SEV_DUMP)) + /* log source */ #define LOG_SRC_INIT 0 #define LOG_SRC_DEBUGFS 1 @@ -104,16 +117,16 @@ do { \ __func__, __LINE__, ##args); \ } while (0) -#define LOG_INFOEX(priv, src, fmt, args...) \ +#define LOG_TRACE(priv, src, fmt, args...) \ do { \ - if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFOEX)) \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_TRACE)) \ dev_dbg(priv2dev(priv), "%s %d: " fmt, \ __func__, __LINE__, ##args); \ } while (0) #define LOG_HEXDUMP(src, ptr, len) \ do { \ - if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFOEX)) \ + if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_DUMP)) \ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, \ 16, 1, ptr, len, false); \ } while (0) @@ -142,7 +155,7 @@ ssize_t store_iwmct_log_level_fw(struct device *d, #define LOG_ERROR(priv, src, fmt, args...) #define LOG_WARNING(priv, src, fmt, args...) #define LOG_INFO(priv, src, fmt, args...) -#define LOG_INFOEX(priv, src, fmt, args...) +#define LOG_TRACE(priv, src, fmt, args...) #define LOG_HEXDUMP(src, ptr, len) static inline void iwmct_log_top_message(struct iwmct_priv *priv, diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c index fafcaa481d74..38627949ff54 100644 --- a/drivers/misc/iwmc3200top/main.c +++ b/drivers/misc/iwmc3200top/main.c @@ -66,7 +66,7 @@ static void iwmct_rescan_worker(struct work_struct *ws) ret = bus_rescan_devices(priv->func->dev.bus); if (ret < 0) - LOG_INFO(priv, FW_DOWNLOAD, "bus_rescan_devices FAILED!!!\n"); + LOG_INFO(priv, INIT, "bus_rescan_devices FAILED!!!\n"); } static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg) @@ -137,7 +137,7 @@ int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len) int ret; u8 *buf; - LOG_INFOEX(priv, FW_MSG, "Sending hcmd:\n"); + LOG_TRACE(priv, FW_MSG, "Sending hcmd:\n"); /* add padding to 256 for IWMC */ ((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256; @@ -192,7 +192,7 @@ static void iwmct_irq_read_worker(struct work_struct *ws) priv = container_of(ws, struct iwmct_priv, isr_worker); - LOG_INFO(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws); + LOG_TRACE(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws); /* --------------------- Handshake with device -------------------- */ sdio_claim_host(priv->func); @@ -292,15 +292,6 @@ static void iwmct_irq_read_worker(struct work_struct *ws) sdio_release_host(priv->func); - - LOG_INFO(priv, IRQ, "barker download request 0x%x is:\n", priv->barker); - LOG_INFO(priv, IRQ, "******* Top FW %s requested ********\n", - (priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not"); - LOG_INFO(priv, IRQ, "******* GPS FW %s requested ********\n", - (priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not"); - LOG_INFO(priv, IRQ, "******* BT FW %s requested ********\n", - (priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not"); - if (priv->dbg.fw_download) iwmct_fw_load(priv); else @@ -312,7 +303,7 @@ exit_release: sdio_release_host(priv->func); exit: kfree(buf); - LOG_INFO(priv, IRQ, "exit iwmct_irq_read_worker\n"); + LOG_TRACE(priv, IRQ, "exit iwmct_irq_read_worker\n"); } static void iwmct_irq(struct sdio_func *func) @@ -325,12 +316,12 @@ static void iwmct_irq(struct sdio_func *func) priv = sdio_get_drvdata(func); - LOG_INFO(priv, IRQ, "enter iwmct_irq\n"); + LOG_TRACE(priv, IRQ, "enter iwmct_irq\n"); /* read the function's status register */ val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret); - LOG_INFO(priv, IRQ, "iir value = %d, ret=%d\n", val, ret); + LOG_TRACE(priv, IRQ, "iir value = %d, ret=%d\n", val, ret); if (!val) { LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n"); @@ -372,7 +363,7 @@ static void iwmct_irq(struct sdio_func *func) queue_work(priv->wq, &priv->isr_worker); - LOG_INFO(priv, IRQ, "exit iwmct_irq\n"); + LOG_TRACE(priv, IRQ, "exit iwmct_irq\n"); return; @@ -660,7 +651,7 @@ static int __init iwmct_init(void) /* Default log filter settings */ iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME); - iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FILTER_ALL); + iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FW_FILTER_ALL); iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME); rc = sdio_register_driver(&iwmct_driver); -- cgit v1.2.3 From fe45332ed289d91e57eca11bfd1ca75d6e420ab4 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 16 Dec 2009 04:26:26 +0000 Subject: iwmc3200top: simplify imwct_tx 1. remove address argument since we use same address IWMC_SDIO_DATA_ADDR in all cases 2. add __iwmct_tx - non locking tx function for already locked contexts Signed-off-by: Tomas Winkler Signed-off-by: David S. Miller --- drivers/misc/iwmc3200top/fw-download.c | 4 ++-- drivers/misc/iwmc3200top/iwmc3200top.h | 4 +--- drivers/misc/iwmc3200top/main.c | 34 ++++++++++++++++------------------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/drivers/misc/iwmc3200top/fw-download.c b/drivers/misc/iwmc3200top/fw-download.c index 07055afef858..9dbaeb574e63 100644 --- a/drivers/misc/iwmc3200top/fw-download.c +++ b/drivers/misc/iwmc3200top/fw-download.c @@ -228,7 +228,7 @@ static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec, hdr->cmd = cpu_to_le32(cmd); /* send it down */ /* TODO: add more proper sending and error checking */ - ret = iwmct_tx(priv, 0, parser->buf, trans_size); + ret = iwmct_tx(priv, parser->buf, trans_size); if (ret != 0) { LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d\n", ret); @@ -280,7 +280,7 @@ static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump) LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr)); /* send it down */ /* TODO: add more proper sending and error checking */ - ret = iwmct_tx(priv, 0, parser->buf, IWMC_SDIO_BLK_SIZE); + ret = iwmct_tx(priv, parser->buf, IWMC_SDIO_BLK_SIZE); if (ret) LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret); diff --git a/drivers/misc/iwmc3200top/iwmc3200top.h b/drivers/misc/iwmc3200top/iwmc3200top.h index 43bd510e1872..740ff0738ea8 100644 --- a/drivers/misc/iwmc3200top/iwmc3200top.h +++ b/drivers/misc/iwmc3200top/iwmc3200top.h @@ -196,9 +196,7 @@ struct iwmct_priv { struct list_head read_req_list; }; -extern int iwmct_tx(struct iwmct_priv *priv, unsigned int addr, - void *src, int count); - +extern int iwmct_tx(struct iwmct_priv *priv, void *src, int count); extern int iwmct_fw_load(struct iwmct_priv *priv); extern void iwmct_dbg_init_params(struct iwmct_priv *drv); diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c index 38627949ff54..dd0a3913bf6d 100644 --- a/drivers/misc/iwmc3200top/main.c +++ b/drivers/misc/iwmc3200top/main.c @@ -49,6 +49,20 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_COPYRIGHT); MODULE_FIRMWARE(FW_NAME(FW_API_VER)); + +static inline int __iwmct_tx(struct iwmct_priv *priv, void *src, int count) +{ + return sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, src, count); + +} +int iwmct_tx(struct iwmct_priv *priv, void *src, int count) +{ + int ret; + sdio_claim_host(priv->func); + ret = __iwmct_tx(priv, src, count); + sdio_release_host(priv->func); + return ret; +} /* * This workers main task is to wait for OP_OPR_ALIVE * from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed. @@ -158,27 +172,12 @@ int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len) } memcpy(buf, cmd, len); - - sdio_claim_host(priv->func); - ret = sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, buf, - FW_HCMD_BLOCK_SIZE); - sdio_release_host(priv->func); + ret = iwmct_tx(priv, buf, FW_HCMD_BLOCK_SIZE); kfree(buf); return ret; } -int iwmct_tx(struct iwmct_priv *priv, unsigned int addr, - void *src, int count) -{ - int ret; - - sdio_claim_host(priv->func); - ret = sdio_memcpy_toio(priv->func, addr, src, count); - sdio_release_host(priv->func); - - return ret; -} static void iwmct_irq_read_worker(struct work_struct *ws) { @@ -273,8 +272,7 @@ static void iwmct_irq_read_worker(struct work_struct *ws) if (barker & BARKER_DNLOAD_SYNC_MSK) { /* Send the same barker back */ - ret = sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, - buf, iosize); + ret = __iwmct_tx(priv, buf, iosize); if (ret) { LOG_ERROR(priv, IRQ, "error %d echoing barker\n", ret); -- cgit v1.2.3 From b3d18d191bb805f3effdfc083c4ce79789470b46 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:30 +0000 Subject: enic: Bug fix: use safe queue shutdown in dev->stop Fix dev->stop shutdown bug where driver was stopping xmit queue and then disabling intrs. Fix is to disable intrs first and then stop the xmit queue, otherwise an interrupt could cause the queue to be rewoken. Also, no need to explicitly do queue servicing because queues are cleaned and reset back to initial state at end of dev->stop. Servicing queues also had the side-effect of also rewakening the xmit queue, which is not what we want. Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 2 +- drivers/net/enic/enic_main.c | 62 ++++++++++++++++++-------------------------- drivers/net/enic/vnic_intr.h | 1 + 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index e1c2076228ba..8dd0105a8d9c 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -34,7 +34,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" -#define DRV_VERSION "1.1.0.100" +#define DRV_VERSION "1.1.0.241a" #define DRV_COPYRIGHT "Copyright 2008-2009 Cisco Systems, Inc" #define PFX DRV_NAME ": " diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index f875751af15e..b4a11befb3b3 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1084,34 +1084,6 @@ static int enic_rq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, return 0; } -static void enic_rq_drop_buf(struct vnic_rq *rq, - struct cq_desc *cq_desc, struct vnic_rq_buf *buf, - int skipped, void *opaque) -{ - struct enic *enic = vnic_dev_priv(rq->vdev); - struct sk_buff *skb = buf->os_buf; - - if (skipped) - return; - - pci_unmap_single(enic->pdev, buf->dma_addr, - buf->len, PCI_DMA_FROMDEVICE); - - dev_kfree_skb_any(skb); -} - -static int enic_rq_service_drop(struct vnic_dev *vdev, struct cq_desc *cq_desc, - u8 type, u16 q_number, u16 completed_index, void *opaque) -{ - struct enic *enic = vnic_dev_priv(vdev); - - vnic_rq_service(&enic->rq[q_number], cq_desc, - completed_index, VNIC_RQ_RETURN_DESC, - enic_rq_drop_buf, opaque); - - return 0; -} - static int enic_poll(struct napi_struct *napi, int budget) { struct enic *enic = container_of(napi, struct enic, napi); @@ -1304,6 +1276,24 @@ static int enic_request_intr(struct enic *enic) return err; } +static void enic_synchronize_irqs(struct enic *enic) +{ + unsigned int i; + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + case VNIC_DEV_INTR_MODE_MSI: + synchronize_irq(enic->pdev->irq); + break; + case VNIC_DEV_INTR_MODE_MSIX: + for (i = 0; i < enic->intr_count; i++) + synchronize_irq(enic->msix_entry[i].vector); + break; + default: + break; + } +} + static int enic_notify_set(struct enic *enic) { int err; @@ -1409,16 +1399,19 @@ static int enic_stop(struct net_device *netdev) unsigned int i; int err; + for (i = 0; i < enic->intr_count; i++) + vnic_intr_mask(&enic->intr[i]); + + enic_synchronize_irqs(enic); + del_timer_sync(&enic->notify_timer); spin_lock(&enic->devcmd_lock); vnic_dev_disable(enic->vdev); spin_unlock(&enic->devcmd_lock); napi_disable(&enic->napi); - netif_stop_queue(netdev); - - for (i = 0; i < enic->intr_count; i++) - vnic_intr_mask(&enic->intr[i]); + netif_carrier_off(netdev); + netif_tx_disable(netdev); for (i = 0; i < enic->wq_count; i++) { err = vnic_wq_disable(&enic->wq[i]); @@ -1436,11 +1429,6 @@ static int enic_stop(struct net_device *netdev) spin_unlock(&enic->devcmd_lock); enic_free_intr(enic); - (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ], - -1, enic_rq_service_drop, NULL); - (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ], - -1, enic_wq_service, NULL); - for (i = 0; i < enic->wq_count; i++) vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); for (i = 0; i < enic->rq_count; i++) diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h index 9a53604edce6..f79a722b6a03 100644 --- a/drivers/net/enic/vnic_intr.h +++ b/drivers/net/enic/vnic_intr.h @@ -61,6 +61,7 @@ static inline void vnic_intr_unmask(struct vnic_intr *intr) static inline void vnic_intr_mask(struct vnic_intr *intr) { iowrite32(1, &intr->ctrl->mask); + (void)ioread32(&intr->ctrl->mask); } static inline void vnic_intr_return_credits(struct vnic_intr *intr, -- cgit v1.2.3 From 2d6ddced5c99cf79c06b9b6ec1366ab63b970ea9 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:38 +0000 Subject: enic: Bug fix: try harder to fill Rx ring on skb allocation failures During dev->open(), make sure we get at least one skb on the Rx ring. Otherwise abort the interface load. Also, if we get skb allocation failures in NAPI poll while trying to replenish the ring, try again later so we don't end up starving out the Rx ring completely. Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic_main.c | 54 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index b4a11befb3b3..452a6b747e3e 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1091,6 +1091,7 @@ static int enic_poll(struct napi_struct *napi, int budget) unsigned int rq_work_to_do = budget; unsigned int wq_work_to_do = -1; /* no limit */ unsigned int work_done, rq_work_done, wq_work_done; + int err; /* Service RQ (first) and WQ */ @@ -1114,16 +1115,19 @@ static int enic_poll(struct napi_struct *napi, int budget) 0 /* don't unmask intr */, 0 /* don't reset intr timer */); - if (rq_work_done > 0) { + err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); - /* Replenish RQ - */ + /* Buffer allocation failed. Stay in polling + * mode so we can try to fill the ring again. + */ - vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); + if (err) + rq_work_done = rq_work_to_do; - } else { + if (rq_work_done < rq_work_to_do) { - /* If no work done, flush all LROs and exit polling + /* Some work done, but not enough to stay in polling, + * flush all LROs and exit polling */ if (netdev->features & NETIF_F_LRO) @@ -1142,6 +1146,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) struct net_device *netdev = enic->netdev; unsigned int work_to_do = budget; unsigned int work_done; + int err; /* Service RQ */ @@ -1149,25 +1154,30 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], work_to_do, enic_rq_service, NULL); - if (work_done > 0) { - - /* Replenish RQ - */ - - vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); - - /* Return intr event credits for this polling - * cycle. An intr event is the completion of a - * RQ packet. - */ + /* Return intr event credits for this polling + * cycle. An intr event is the completion of a + * RQ packet. + */ + if (work_done > 0) vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], work_done, 0 /* don't unmask intr */, 0 /* don't reset intr timer */); - } else { - /* If no work done, flush all LROs and exit polling + err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); + + /* Buffer allocation failed. Stay in polling mode + * so we can try to fill the ring again. + */ + + if (err) + work_done = work_to_do; + + if (work_done < work_to_do) { + + /* Some work done, but not enough to stay in polling, + * flush all LROs and exit polling */ if (netdev->features & NETIF_F_LRO) @@ -1350,11 +1360,13 @@ static int enic_open(struct net_device *netdev) } for (i = 0; i < enic->rq_count; i++) { - err = vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); - if (err) { + vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf); + /* Need at least one buffer on ring to get going */ + if (vnic_rq_desc_used(&enic->rq[i]) == 0) { printk(KERN_ERR PFX "%s: Unable to alloc receive buffers.\n", netdev->name); + err = -ENOMEM; goto err_out_notify_unset; } } -- cgit v1.2.3 From 9959a18556c73ebf2936b8df183ea7b41f38d933 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:43 +0000 Subject: enic: minimize pkt filter updates to firmware In set_multicast(), only push pkt filter changes down to firmware if pkt filter actually changes. Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 1 + drivers/net/enic/enic_main.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 8dd0105a8d9c..b090d65ad0c8 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -89,6 +89,7 @@ struct enic { spinlock_t devcmd_lock; u8 mac_addr[ETH_ALEN]; u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; + unsigned int flags; unsigned int mc_count; int csum_rx_enabled; u32 port_mtu; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 452a6b747e3e..019b1480cc0c 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -771,6 +771,7 @@ static void enic_set_multicast_list(struct net_device *netdev) int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; int allmulti = (netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > ENIC_MULTICAST_PERFECT_FILTERS); + unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0); u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; unsigned int mc_count = netdev->mc_count; unsigned int i, j; @@ -780,8 +781,11 @@ static void enic_set_multicast_list(struct net_device *netdev) spin_lock(&enic->devcmd_lock); - vnic_dev_packet_filter(enic->vdev, directed, - multicast, broadcast, promisc, allmulti); + if (enic->flags != flags) { + enic->flags = flags; + vnic_dev_packet_filter(enic->vdev, directed, + multicast, broadcast, promisc, allmulti); + } /* Is there an easier way? Trying to minimize to * calls to add/del multicast addrs. We keep the -- cgit v1.2.3 From bd2496229e702b2eb50eab5589858a3cdb7847b2 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:48 +0000 Subject: enic: Bug fix: align desc ring sizes to 32 descs Previous driver was aligning ring sizes to 16 descs, but hardware actually wants desc ring sizes to be aligned to 32 descs. Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic_res.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 32111144efc9..a605da1475c6 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c @@ -74,13 +74,13 @@ int enic_get_vnic_config(struct enic *enic) min_t(u32, ENIC_MAX_WQ_DESCS, max_t(u32, ENIC_MIN_WQ_DESCS, c->wq_desc_count)); - c->wq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */ + c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ c->rq_desc_count = min_t(u32, ENIC_MAX_RQ_DESCS, max_t(u32, ENIC_MIN_RQ_DESCS, c->rq_desc_count)); - c->rq_desc_count &= 0xfffffff0; /* must be aligned to groups of 16 */ + c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ if (c->mtu == 0) c->mtu = 1500; -- cgit v1.2.3 From 7c8445991172cc17eaca9f7de0a300c02caaa49d Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:54 +0000 Subject: enic: feature add: add ethtool -c/C support Only rx_usec and tx_usec options for ethtool -C are settable as those are the only settings that make sense to HW. Adds driver reporting of intr coalescing timer value in usec units rather than HW units. Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic.h | 2 ++ drivers/net/enic/enic_main.c | 63 +++++++++++++++++++++++++++++++++++++++++++- drivers/net/enic/enic_res.c | 12 +++++---- drivers/net/enic/vnic_enet.h | 5 ++++ drivers/net/enic/vnic_intr.c | 8 +++++- drivers/net/enic/vnic_intr.h | 2 ++ 6 files changed, 85 insertions(+), 7 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index b090d65ad0c8..ee01f5a6d0d4 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -93,6 +93,8 @@ struct enic { unsigned int mc_count; int csum_rx_enabled; u32 port_mtu; + u32 rx_coalesce_usecs; + u32 tx_coalesce_usecs; /* work queue cache line section */ ____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX]; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 019b1480cc0c..e56f41672b37 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -261,6 +261,62 @@ static void enic_set_msglevel(struct net_device *netdev, u32 value) enic->msg_enable = value; } +static int enic_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ecmd) +{ + struct enic *enic = netdev_priv(netdev); + + ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs; + ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs; + + return 0; +} + +static int enic_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ecmd) +{ + struct enic *enic = netdev_priv(netdev); + u32 tx_coalesce_usecs; + u32 rx_coalesce_usecs; + + tx_coalesce_usecs = min_t(u32, + INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), + ecmd->tx_coalesce_usecs); + rx_coalesce_usecs = min_t(u32, + INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), + ecmd->rx_coalesce_usecs); + + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + if (tx_coalesce_usecs != rx_coalesce_usecs) + return -EINVAL; + + vnic_intr_coalescing_timer_set(&enic->intr[ENIC_INTX_WQ_RQ], + INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + break; + case VNIC_DEV_INTR_MODE_MSI: + if (tx_coalesce_usecs != rx_coalesce_usecs) + return -EINVAL; + + vnic_intr_coalescing_timer_set(&enic->intr[0], + INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + break; + case VNIC_DEV_INTR_MODE_MSIX: + vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_WQ], + INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + vnic_intr_coalescing_timer_set(&enic->intr[ENIC_MSIX_RQ], + INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); + break; + default: + break; + } + + enic->tx_coalesce_usecs = tx_coalesce_usecs; + enic->rx_coalesce_usecs = rx_coalesce_usecs; + + return 0; +} + static const struct ethtool_ops enic_ethtool_ops = { .get_settings = enic_get_settings, .get_drvinfo = enic_get_drvinfo, @@ -278,6 +334,8 @@ static const struct ethtool_ops enic_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, .set_tso = enic_set_tso, + .get_coalesce = enic_get_coalesce, + .set_coalesce = enic_set_coalesce, .get_flags = ethtool_op_get_flags, .set_flags = ethtool_op_set_flags, }; @@ -363,12 +421,12 @@ static void enic_mtu_check(struct enic *enic) u32 mtu = vnic_dev_mtu(enic->vdev); if (mtu && mtu != enic->port_mtu) { + enic->port_mtu = mtu; if (mtu < enic->netdev->mtu) printk(KERN_WARNING PFX "%s: interface MTU (%d) set higher " "than switch port MTU (%d)\n", enic->netdev->name, enic->netdev->mtu, mtu); - enic->port_mtu = mtu; } } @@ -1990,6 +2048,9 @@ static int __devinit enic_probe(struct pci_dev *pdev, goto err_out_dev_deinit; } + enic->tx_coalesce_usecs = enic->config.intr_timer_usec; + enic->rx_coalesce_usecs = enic->tx_coalesce_usecs; + netdev->netdev_ops = &enic_netdev_ops; netdev->watchdog_timeo = 2 * HZ; netdev->ethtool_ops = &enic_ethtool_ops; diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index a605da1475c6..02839bf0fe8b 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c @@ -66,9 +66,9 @@ int enic_get_vnic_config(struct enic *enic) GET_CONFIG(wq_desc_count); GET_CONFIG(rq_desc_count); GET_CONFIG(mtu); - GET_CONFIG(intr_timer); GET_CONFIG(intr_timer_type); GET_CONFIG(intr_mode); + GET_CONFIG(intr_timer_usec); c->wq_desc_count = min_t(u32, ENIC_MAX_WQ_DESCS, @@ -88,15 +88,17 @@ int enic_get_vnic_config(struct enic *enic) max_t(u16, ENIC_MIN_MTU, c->mtu)); - c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer); + c->intr_timer_usec = min_t(u32, + INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), + c->intr_timer_usec); printk(KERN_INFO PFX "vNIC MAC addr %pM wq/rq %d/%d\n", enic->mac_addr, c->wq_desc_count, c->rq_desc_count); printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d " - "intr timer %d\n", + "intr timer %d usec\n", c->mtu, ENIC_SETTING(enic, TXCSUM), ENIC_SETTING(enic, RXCSUM), ENIC_SETTING(enic, TSO), - ENIC_SETTING(enic, LRO), c->intr_timer); + ENIC_SETTING(enic, LRO), c->intr_timer_usec); return 0; } @@ -303,7 +305,7 @@ void enic_init_vnic_resources(struct enic *enic) for (i = 0; i < enic->intr_count; i++) { vnic_intr_init(&enic->intr[i], - enic->config.intr_timer, + INTR_COALESCE_USEC_TO_HW(enic->config.intr_timer_usec), enic->config.intr_timer_type, mask_on_assertion); } diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h index 6332ac9391b8..8eeb6758491b 100644 --- a/drivers/net/enic/vnic_enet.h +++ b/drivers/net/enic/vnic_enet.h @@ -20,6 +20,10 @@ #ifndef _VNIC_ENIC_H_ #define _VNIC_ENIC_H_ +/* Hardware intr coalesce timer is in units of 1.5us */ +#define INTR_COALESCE_USEC_TO_HW(usec) ((usec) * 2/3) +#define INTR_COALESCE_HW_TO_USEC(usec) ((usec) * 3/2) + /* Device-specific region: enet configuration */ struct vnic_enet_config { u32 flags; @@ -30,6 +34,7 @@ struct vnic_enet_config { u8 intr_timer_type; u8 intr_mode; char devname[16]; + u32 intr_timer_usec; }; #define VENETF_TSO 0x1 /* TSO enabled */ diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c index 1f8786d7195e..3934309a9498 100644 --- a/drivers/net/enic/vnic_intr.c +++ b/drivers/net/enic/vnic_intr.c @@ -50,12 +50,18 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion) { - iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer); + vnic_intr_coalescing_timer_set(intr, coalescing_timer); iowrite32(coalescing_type, &intr->ctrl->coalescing_type); iowrite32(mask_on_assertion, &intr->ctrl->mask_on_assertion); iowrite32(0, &intr->ctrl->int_credits); } +void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, + unsigned int coalescing_timer) +{ + iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer); +} + void vnic_intr_clean(struct vnic_intr *intr) { iowrite32(0, &intr->ctrl->int_credits); diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h index f79a722b6a03..2fe6c6339e3c 100644 --- a/drivers/net/enic/vnic_intr.h +++ b/drivers/net/enic/vnic_intr.h @@ -102,6 +102,8 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, unsigned int index); void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion); +void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, + unsigned int coalescing_timer); void vnic_intr_clean(struct vnic_intr *intr); #endif /* _VNIC_INTR_H_ */ -- cgit v1.2.3 From d87fd25d5ac4cd044e21b749a8f6cac90f093c71 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Dec 2009 13:27:59 +0000 Subject: enic: whitespace cleanup; #define cleanup; more verbose err msg Some misc changes to cleanup whitespace issues and fix/remove some #define HW defintions. 1) fix some whitespace issues 2) more verbose err msg when resources aren't available to configure vnic 3) remove unused #define 4) fix RSS #define rss hash types Signed-off-by: Vasanthy Kolluri Signed-off-by: Scott Feldman Signed-off-by: David S. Miller --- drivers/net/enic/enic_main.c | 5 +++-- drivers/net/enic/vnic_dev.c | 1 - drivers/net/enic/vnic_nic.h | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index e56f41672b37..d87935ad1130 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -731,7 +731,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, /* netif_tx_lock held, process context with BHs disabled, or BH */ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb, - struct net_device *netdev) + struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); struct vnic_wq *wq = &enic->wq[0]; @@ -1824,7 +1824,8 @@ int enic_dev_init(struct enic *enic) err = enic_set_intr_mode(enic); if (err) { printk(KERN_ERR PFX - "Failed to set intr mode, aborting.\n"); + "Failed to set intr mode based on resource " + "counts and system capabilities, aborting.\n"); return err; } diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 29a48e8b59d3..69b9b70c7da0 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -36,7 +36,6 @@ struct vnic_res { }; #define VNIC_DEV_CAP_INIT 0x0001 -#define VNIC_DEV_CAP_PERBI 0x0002 struct vnic_dev { void *priv; diff --git a/drivers/net/enic/vnic_nic.h b/drivers/net/enic/vnic_nic.h index eeaf329945d8..cf80ab46d582 100644 --- a/drivers/net/enic/vnic_nic.h +++ b/drivers/net/enic/vnic_nic.h @@ -41,12 +41,12 @@ #define NIC_CFG_IG_VLAN_STRIP_EN_MASK_FIELD 1UL #define NIC_CFG_IG_VLAN_STRIP_EN_SHIFT 24 -#define NIC_CFG_RSS_HASH_TYPE_IPV4 (1 << 0) -#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 (1 << 1) -#define NIC_CFG_RSS_HASH_TYPE_IPV6 (1 << 2) -#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 (1 << 3) -#define NIC_CFG_RSS_HASH_TYPE_IPV6_EX (1 << 4) -#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX (1 << 5) +#define NIC_CFG_RSS_HASH_TYPE_IPV4 (1 << 1) +#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV4 (1 << 2) +#define NIC_CFG_RSS_HASH_TYPE_IPV6 (1 << 3) +#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 (1 << 4) +#define NIC_CFG_RSS_HASH_TYPE_IPV6_EX (1 << 5) +#define NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX (1 << 6) static inline void vnic_set_nic_cfg(u32 *nic_cfg, u8 rss_default_cpu, u8 rss_hash_type, -- cgit v1.2.3 From f83d664eef180478c2dc0a0099e9d7bc1c8177ff Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 25 Dec 2009 16:35:43 -0800 Subject: wireless: fix comments in genregdb.awk Apparently some awk versions choke on C-style comments -- who knew? :-) Signed-off-by: John W. Linville Signed-off-by: David S. Miller --- net/wireless/genregdb.awk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 8316cf075ce9..3cc9e69880a8 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk @@ -26,11 +26,11 @@ BEGIN { } /^[ \t]*#/ { - /* Ignore */ + # Ignore } !active && /^[ \t]*$/ { - /* Ignore */ + # Ignore } !active && /country/ { -- cgit v1.2.3 From bf9ae5386bca8836c16e69ab8fdbe46767d7452a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:50:59 +0000 Subject: llc: use dev_hard_header Using dev_hard_header allows us to use LLC with VLANs and potentially other Ethernet/TokernRing specific encapsulations. It also removes code duplication between LLC and Ethernet/TokenRing core code. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- drivers/net/myri_sbus.c | 6 +++--- net/8021q/vlan_dev.c | 7 +++---- net/ethernet/eth.c | 6 +++--- net/llc/llc_output.c | 45 ++++++++------------------------------------- 4 files changed, 17 insertions(+), 47 deletions(-) diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index b3513ad3b703..8b4313085359 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -716,10 +716,10 @@ static int myri_header(struct sk_buff *skb, struct net_device *dev, pad[0] = MYRI_PAD_LEN; pad[1] = 0xab; - /* Set the protocol type. For a packet of type ETH_P_802_3 we put the length - * in here instead. It is up to the 802.2 layer to carry protocol information. + /* Set the protocol type. For a packet of type ETH_P_802_3/2 we put the + * length in here instead. */ - if (type != ETH_P_802_3) + if (type != ETH_P_802_3 && type != ETH_P_802_2) eth->h_proto = htons(type); else eth->h_proto = htons(len); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b7889782047e..77a49ffdd0ef 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -263,11 +263,10 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, vhdr->h_vlan_TCI = htons(vlan_tci); /* - * Set the protocol type. For a packet of type ETH_P_802_3 we - * put the length in here instead. It is up to the 802.2 - * layer to carry protocol information. + * Set the protocol type. For a packet of type ETH_P_802_3/2 we + * put the length in here instead. */ - if (type != ETH_P_802_3) + if (type != ETH_P_802_3 && type != ETH_P_802_2) vhdr->h_vlan_encapsulated_proto = htons(type); else vhdr->h_vlan_encapsulated_proto = htons(len); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index dd3db88f8f0a..205a1c12f3c0 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -73,8 +73,8 @@ __setup("ether=", netdev_boot_setup); * @len: packet length (<= skb->len) * * - * Set the protocol type. For a packet of type ETH_P_802_3 we put the length - * in here instead. It is up to the 802.2 layer to carry protocol information. + * Set the protocol type. For a packet of type ETH_P_802_3/2 we put the length + * in here instead. */ int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, @@ -82,7 +82,7 @@ int eth_header(struct sk_buff *skb, struct net_device *dev, { struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); - if (type != ETH_P_802_3) + if (type != ETH_P_802_3 && type != ETH_P_802_2) eth->h_proto = htons(type); else eth->h_proto = htons(len); diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c index 754f4fedc852..b38a1079a98e 100644 --- a/net/llc/llc_output.c +++ b/net/llc/llc_output.c @@ -33,48 +33,19 @@ int llc_mac_hdr_init(struct sk_buff *skb, const unsigned char *sa, const unsigned char *da) { - int rc = 0; + int rc = -EINVAL; switch (skb->dev->type) { -#ifdef CONFIG_TR - case ARPHRD_IEEE802_TR: { - struct net_device *dev = skb->dev; - struct trh_hdr *trh; - - skb_push(skb, sizeof(*trh)); - skb_reset_mac_header(skb); - trh = tr_hdr(skb); - trh->ac = AC; - trh->fc = LLC_FRAME; - if (sa) - memcpy(trh->saddr, sa, dev->addr_len); - else - memset(trh->saddr, 0, dev->addr_len); - if (da) { - memcpy(trh->daddr, da, dev->addr_len); - tr_source_route(skb, trh, dev); - skb_reset_mac_header(skb); - } - break; - } -#endif + case ARPHRD_IEEE802_TR: case ARPHRD_ETHER: - case ARPHRD_LOOPBACK: { - unsigned short len = skb->len; - struct ethhdr *eth; - - skb_push(skb, sizeof(*eth)); - skb_reset_mac_header(skb); - eth = eth_hdr(skb); - eth->h_proto = htons(len); - memcpy(eth->h_dest, da, ETH_ALEN); - memcpy(eth->h_source, sa, ETH_ALEN); + case ARPHRD_LOOPBACK: + rc = dev_hard_header(skb, skb->dev, ETH_P_802_2, da, sa, + skb->len); + if (rc > 0) + rc = 0; break; - } default: - printk(KERN_WARNING "device type not supported: %d\n", - skb->dev->type); - rc = -EINVAL; + WARN(1, "device type not supported: %d\n", skb->dev->type); } return rc; } -- cgit v1.2.3 From e5cd6fe391aa8c93560bb7ffdfe334cf4d0a02e4 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:00 +0000 Subject: llc: add support for LLC_OPT_PKTINFO Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/linux/llc.h | 7 +++++++ include/net/llc_conn.h | 1 + net/llc/af_llc.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/include/linux/llc.h b/include/linux/llc.h index 7733585603f1..ad7074ba81af 100644 --- a/include/linux/llc.h +++ b/include/linux/llc.h @@ -36,6 +36,7 @@ enum llc_sockopts { LLC_OPT_BUSY_TMR_EXP, /* busy state expire time (secs). */ LLC_OPT_TX_WIN, /* tx window size. */ LLC_OPT_RX_WIN, /* rx window size. */ + LLC_OPT_PKTINFO, /* ancillary packet information. */ LLC_OPT_MAX }; @@ -70,6 +71,12 @@ enum llc_sockopts { #define LLC_SAP_RM 0xD4 /* Resource Management */ #define LLC_SAP_GLOBAL 0xFF /* Global SAP. */ +struct llc_pktinfo { + int lpi_ifindex; + unsigned char lpi_sap; + unsigned char lpi_mac[IFHWADDRLEN]; +}; + #ifdef __KERNEL__ #define LLC_SAP_DYN_START 0xC0 #define LLC_SAP_DYN_STOP 0xDE diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index e2374e34989f..fe982fd94c4a 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -76,6 +76,7 @@ struct llc_sock { u32 rx_pdu_hdr; /* used for saving header of last pdu received and caused sending FRMR. Used for resending FRMR */ + u32 cmsg_flags; }; static inline struct llc_sock *llc_sk(const struct sock *sk) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 3a66546cad06..ac691fe08076 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -47,6 +47,10 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout); #define dprintk(args...) #endif +/* Maybe we'll add some more in the future. */ +#define LLC_CMSG_PKTINFO 1 + + /** * llc_ui_next_link_no - return the next unused link number for a sap * @sap: Address of sap to get link number from. @@ -591,6 +595,20 @@ static int llc_wait_data(struct sock *sk, long timeo) return rc; } +static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb) +{ + struct llc_sock *llc = llc_sk(skb->sk); + + if (llc->cmsg_flags & LLC_CMSG_PKTINFO) { + struct llc_pktinfo info; + + info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex; + llc_pdu_decode_dsap(skb, &info.lpi_sap); + llc_pdu_decode_da(skb, info.lpi_mac); + put_cmsg(msg, SOL_LLC, LLC_OPT_PKTINFO, sizeof(info), &info); + } +} + /** * llc_ui_accept - accept a new incoming connection. * @sock: Socket which connections arrive on. @@ -812,6 +830,8 @@ copy_uaddr: memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr)); msg->msg_namelen = sizeof(*uaddr); } + if (llc_sk(sk)->cmsg_flags) + llc_cmsg_rcv(msg, skb); goto out; } @@ -1030,6 +1050,12 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, goto out; llc->rw = opt; break; + case LLC_OPT_PKTINFO: + if (opt) + llc->cmsg_flags |= LLC_CMSG_PKTINFO; + else + llc->cmsg_flags &= ~LLC_CMSG_PKTINFO; + break; default: rc = -ENOPROTOOPT; goto out; @@ -1083,6 +1109,9 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname, val = llc->k; break; case LLC_OPT_RX_WIN: val = llc->rw; break; + case LLC_OPT_PKTINFO: + val = (llc->cmsg_flags & LLC_CMSG_PKTINFO) != 0; + break; default: rc = -ENOPROTOOPT; goto out; -- cgit v1.2.3 From abf9d537fea225af60762640361af7fb233b3103 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:01 +0000 Subject: llc: add support for SO_BINDTODEVICE Using bind(MAC address) with LLC sockets has O(n) complexity, where n is the number of interfaces. To overcome this, we add support for SO_BINDTODEVICE which drops the complexity to O(1). Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- net/llc/af_llc.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index ac691fe08076..c4d1a1da813c 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -259,7 +259,14 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr) if (!sock_flag(sk, SOCK_ZAPPED)) goto out; rc = -ENODEV; - llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); + if (sk->sk_bound_dev_if) { + llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); + if (llc->dev && addr->sllc_arphrd != llc->dev->type) { + dev_put(llc->dev); + llc->dev = NULL; + } + } else + llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd); if (!llc->dev) goto out; rc = -EUSERS; @@ -310,7 +317,25 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) goto out; rc = -ENODEV; rtnl_lock(); - llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac); + if (sk->sk_bound_dev_if) { + llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if); + if (llc->dev) { + if (!addr->sllc_arphrd) + addr->sllc_arphrd = llc->dev->type; + if (llc_mac_null(addr->sllc_mac)) + memcpy(addr->sllc_mac, llc->dev->dev_addr, + IFHWADDRLEN); + if (addr->sllc_arphrd != llc->dev->type || + !llc_mac_match(addr->sllc_mac, + llc->dev->dev_addr)) { + rc = -EINVAL; + dev_put(llc->dev); + llc->dev = NULL; + } + } + } else + llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, + addr->sllc_mac); rtnl_unlock(); if (!llc->dev) goto out; -- cgit v1.2.3 From b76f5a8427ac2928c07fa4ff2144bb8db072c240 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:02 +0000 Subject: llc: convert the socket list to RCU locking For the reclamation phase we use the SLAB_DESTROY_BY_RCU mechanism, which require some extra checks in the lookup code: a) If the current socket was released, reallocated & inserted in another list it will short circuit the iteration for the current list, thus we need to restart the lookup. b) If the current socket was released, reallocated & inserted in the same list we just need to recheck it matches the look-up criteria and if not we can skip to the next element. In this case there is no need to restart the lookup, since sockets are inserted at the start of the list and the worst that will happen is that we will iterate throught some of the list elements more then once. Note that the /proc and multicast delivery was not yet converted to RCU, it still uses spinlocks for protection. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/llc.h | 7 ++-- net/llc/af_llc.c | 1 + net/llc/llc_conn.c | 93 ++++++++++++++++++++++++++++++++++++------------------ net/llc/llc_core.c | 5 +-- net/llc/llc_proc.c | 22 ++++++------- net/llc/llc_sap.c | 66 ++++++++++++++++++++++++-------------- 6 files changed, 123 insertions(+), 71 deletions(-) diff --git a/include/net/llc.h b/include/net/llc.h index 7940da1606e7..1559cf10e874 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -53,10 +54,8 @@ struct llc_sap { struct net_device *orig_dev); struct llc_addr laddr; struct list_head node; - struct { - rwlock_t lock; - struct hlist_head list; - } sk_list; + spinlock_t sk_lock; + struct hlist_nulls_head sk_list; }; #define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index c4d1a1da813c..f49f3dd6fbd3 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -140,6 +140,7 @@ static struct proto llc_proto = { .name = "LLC", .owner = THIS_MODULE, .obj_size = sizeof(struct llc_sock), + .slab_flags = SLAB_DESTROY_BY_RCU, }; /** diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index c6bab39b018e..77bb3816655e 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -468,6 +468,19 @@ static int llc_exec_conn_trans_actions(struct sock *sk, return rc; } +static inline bool llc_estab_match(const struct llc_sap *sap, + const struct llc_addr *daddr, + const struct llc_addr *laddr, + const struct sock *sk) +{ + struct llc_sock *llc = llc_sk(sk); + + return llc->laddr.lsap == laddr->lsap && + llc->daddr.lsap == daddr->lsap && + llc_mac_match(llc->laddr.mac, laddr->mac) && + llc_mac_match(llc->daddr.mac, daddr->mac); +} + /** * __llc_lookup_established - Finds connection for the remote/local sap/mac * @sap: SAP @@ -484,23 +497,26 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap, struct llc_addr *laddr) { struct sock *rc; - struct hlist_node *node; - - read_lock(&sap->sk_list.lock); - sk_for_each(rc, node, &sap->sk_list.list) { - struct llc_sock *llc = llc_sk(rc); - - if (llc->laddr.lsap == laddr->lsap && - llc->daddr.lsap == daddr->lsap && - llc_mac_match(llc->laddr.mac, laddr->mac) && - llc_mac_match(llc->daddr.mac, daddr->mac)) { - sock_hold(rc); + struct hlist_nulls_node *node; + + rcu_read_lock(); +again: + sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + if (llc_estab_match(sap, daddr, laddr, rc)) { + /* Extra checks required by SLAB_DESTROY_BY_RCU */ + if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) + goto again; + if (unlikely(llc_sk(rc)->sap != sap || + !llc_estab_match(sap, daddr, laddr, rc))) { + sock_put(rc); + continue; + } goto found; } } rc = NULL; found: - read_unlock(&sap->sk_list.lock); + rcu_read_unlock(); return rc; } @@ -516,6 +532,18 @@ struct sock *llc_lookup_established(struct llc_sap *sap, return sk; } +static inline bool llc_listener_match(const struct llc_sap *sap, + const struct llc_addr *laddr, + const struct sock *sk) +{ + struct llc_sock *llc = llc_sk(sk); + + return sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN && + llc->laddr.lsap == laddr->lsap && + (llc_mac_match(llc->laddr.mac, laddr->mac) || + llc_mac_null(llc->laddr.mac)); +} + /** * llc_lookup_listener - Finds listener for local MAC + SAP * @sap: SAP @@ -530,23 +558,26 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr) { struct sock *rc; - struct hlist_node *node; - - read_lock(&sap->sk_list.lock); - sk_for_each(rc, node, &sap->sk_list.list) { - struct llc_sock *llc = llc_sk(rc); - - if (rc->sk_type == SOCK_STREAM && rc->sk_state == TCP_LISTEN && - llc->laddr.lsap == laddr->lsap && - (llc_mac_match(llc->laddr.mac, laddr->mac) || - llc_mac_null(llc->laddr.mac))) { - sock_hold(rc); + struct hlist_nulls_node *node; + + rcu_read_lock(); +again: + sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + if (llc_listener_match(sap, laddr, rc)) { + /* Extra checks required by SLAB_DESTROY_BY_RCU */ + if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) + goto again; + if (unlikely(llc_sk(rc)->sap != sap || + !llc_listener_match(sap, laddr, rc))) { + sock_put(rc); + continue; + } goto found; } } rc = NULL; found: - read_unlock(&sap->sk_list.lock); + rcu_read_unlock(); return rc; } @@ -652,10 +683,10 @@ static int llc_find_offset(int state, int ev_type) void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) { llc_sap_hold(sap); - write_lock_bh(&sap->sk_list.lock); + spin_lock_bh(&sap->sk_lock); llc_sk(sk)->sap = sap; - sk_add_node(sk, &sap->sk_list.list); - write_unlock_bh(&sap->sk_list.lock); + sk_nulls_add_node_rcu(sk, &sap->sk_list); + spin_unlock_bh(&sap->sk_lock); } /** @@ -663,14 +694,14 @@ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) * @sap: SAP * @sk: socket * - * This function removes a connection from sk_list.list of a SAP if + * This function removes a connection from sk_list of a SAP if * the connection was in this list. */ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) { - write_lock_bh(&sap->sk_list.lock); - sk_del_node_init(sk); - write_unlock_bh(&sap->sk_list.lock); + spin_lock_bh(&sap->sk_lock); + sk_nulls_del_node_init_rcu(sk); + spin_unlock_bh(&sap->sk_lock); llc_sap_put(sap); } diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index ff4c0ab96a69..5276b9722077 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -37,7 +37,8 @@ static struct llc_sap *llc_sap_alloc(void) if (sap) { /* sap->laddr.mac - leave as a null, it's filled by bind */ sap->state = LLC_SAP_STATE_ACTIVE; - rwlock_init(&sap->sk_list.lock); + spin_lock_init(&sap->sk_lock); + INIT_HLIST_NULLS_HEAD(&sap->sk_list, 0); atomic_set(&sap->refcnt, 1); } return sap; @@ -142,7 +143,7 @@ out: */ void llc_sap_close(struct llc_sap *sap) { - WARN_ON(!hlist_empty(&sap->sk_list.list)); + WARN_ON(!hlist_nulls_empty(&sap->sk_list)); llc_del_sap(sap); kfree(sap); } diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index be47ac427f6b..6b3d033b3236 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -34,19 +34,19 @@ static struct sock *llc_get_sk_idx(loff_t pos) { struct list_head *sap_entry; struct llc_sap *sap; - struct hlist_node *node; + struct hlist_nulls_node *node; struct sock *sk = NULL; list_for_each(sap_entry, &llc_sap_list) { sap = list_entry(sap_entry, struct llc_sap, node); - read_lock_bh(&sap->sk_list.lock); - sk_for_each(sk, node, &sap->sk_list.list) { + spin_lock_bh(&sap->sk_lock); + sk_nulls_for_each(sk, node, &sap->sk_list) { if (!pos) goto found; --pos; } - read_unlock_bh(&sap->sk_list.lock); + spin_unlock_bh(&sap->sk_lock); } sk = NULL; found: @@ -73,25 +73,25 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) goto out; } sk = v; - next = sk_next(sk); + next = sk_nulls_next(sk); if (next) { sk = next; goto out; } llc = llc_sk(sk); sap = llc->sap; - read_unlock_bh(&sap->sk_list.lock); + spin_unlock_bh(&sap->sk_lock); sk = NULL; for (;;) { if (sap->node.next == &llc_sap_list) break; sap = list_entry(sap->node.next, struct llc_sap, node); - read_lock_bh(&sap->sk_list.lock); - if (!hlist_empty(&sap->sk_list.list)) { - sk = sk_head(&sap->sk_list.list); + spin_lock_bh(&sap->sk_lock); + if (!hlist_nulls_empty(&sap->sk_list)) { + sk = sk_nulls_head(&sap->sk_list); break; } - read_unlock_bh(&sap->sk_list.lock); + spin_unlock_bh(&sap->sk_lock); } out: return sk; @@ -104,7 +104,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v) struct llc_sock *llc = llc_sk(sk); struct llc_sap *sap = llc->sap; - read_unlock_bh(&sap->sk_list.lock); + spin_unlock_bh(&sap->sk_lock); } read_unlock_bh(&llc_sap_list_lock); } diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 008de1fc42ca..39760d013ce2 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -297,6 +297,17 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, llc_sap_state_process(sap, skb); } +static inline bool llc_dgram_match(const struct llc_sap *sap, + const struct llc_addr *laddr, + const struct sock *sk) +{ + struct llc_sock *llc = llc_sk(sk); + + return sk->sk_type == SOCK_DGRAM && + llc->laddr.lsap == laddr->lsap && + llc_mac_match(llc->laddr.mac, laddr->mac); +} + /** * llc_lookup_dgram - Finds dgram socket for the local sap/mac * @sap: SAP @@ -309,25 +320,41 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap, const struct llc_addr *laddr) { struct sock *rc; - struct hlist_node *node; - - read_lock_bh(&sap->sk_list.lock); - sk_for_each(rc, node, &sap->sk_list.list) { - struct llc_sock *llc = llc_sk(rc); - - if (rc->sk_type == SOCK_DGRAM && - llc->laddr.lsap == laddr->lsap && - llc_mac_match(llc->laddr.mac, laddr->mac)) { - sock_hold(rc); + struct hlist_nulls_node *node; + + rcu_read_lock_bh(); +again: + sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + if (llc_dgram_match(sap, laddr, rc)) { + /* Extra checks required by SLAB_DESTROY_BY_RCU */ + if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) + goto again; + if (unlikely(llc_sk(rc)->sap != sap || + !llc_dgram_match(sap, laddr, rc))) { + sock_put(rc); + continue; + } goto found; } } rc = NULL; found: - read_unlock_bh(&sap->sk_list.lock); + rcu_read_unlock_bh(); return rc; } +static inline bool llc_mcast_match(const struct llc_sap *sap, + const struct llc_addr *laddr, + const struct sk_buff *skb, + const struct sock *sk) +{ + struct llc_sock *llc = llc_sk(sk); + + return sk->sk_type == SOCK_DGRAM && + llc->laddr.lsap == laddr->lsap && + llc->dev == skb->dev; +} + /** * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets. * @sap: SAP @@ -341,20 +368,13 @@ static void llc_sap_mcast(struct llc_sap *sap, struct sk_buff *skb) { struct sock *sk; - struct hlist_node *node; + struct hlist_nulls_node *node; - read_lock_bh(&sap->sk_list.lock); - sk_for_each(sk, node, &sap->sk_list.list) { - struct llc_sock *llc = llc_sk(sk); + spin_lock_bh(&sap->sk_lock); + sk_nulls_for_each_rcu(sk, node, &sap->sk_list) { struct sk_buff *skb1; - if (sk->sk_type != SOCK_DGRAM) - continue; - - if (llc->laddr.lsap != laddr->lsap) - continue; - - if (llc->dev != skb->dev) + if (!llc_mcast_match(sap, laddr, skb, sk)) continue; skb1 = skb_clone(skb, GFP_ATOMIC); @@ -365,7 +385,7 @@ static void llc_sap_mcast(struct llc_sap *sap, llc_sap_rcv(sap, skb1, sk); sock_put(sk); } - read_unlock_bh(&sap->sk_list.lock); + spin_unlock_bh(&sap->sk_lock); } -- cgit v1.2.3 From 0f7b67dd9e1192976f5e5a78934c7a339ff7c45f Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:03 +0000 Subject: llc: optimize multicast delivery Optimize multicast delivery by doing the actual delivery without holding the lock. Based on the same approach used in UDP code. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- net/llc/llc_sap.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 39760d013ce2..94790e60d072 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -355,6 +355,24 @@ static inline bool llc_mcast_match(const struct llc_sap *sap, llc->dev == skb->dev; } +static void llc_do_mcast(struct llc_sap *sap, struct sk_buff *skb, + struct sock **stack, int count) +{ + struct sk_buff *skb1; + int i; + + for (i = 0; i < count; i++) { + skb1 = skb_clone(skb, GFP_ATOMIC); + if (!skb1) { + sock_put(stack[i]); + continue; + } + + llc_sap_rcv(sap, skb1, stack[i]); + sock_put(stack[i]); + } +} + /** * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets. * @sap: SAP @@ -367,25 +385,27 @@ static void llc_sap_mcast(struct llc_sap *sap, const struct llc_addr *laddr, struct sk_buff *skb) { - struct sock *sk; + int i = 0, count = 256 / sizeof(struct sock *); + struct sock *sk, *stack[count]; struct hlist_nulls_node *node; spin_lock_bh(&sap->sk_lock); sk_nulls_for_each_rcu(sk, node, &sap->sk_list) { - struct sk_buff *skb1; if (!llc_mcast_match(sap, laddr, skb, sk)) continue; - skb1 = skb_clone(skb, GFP_ATOMIC); - if (!skb1) - break; - sock_hold(sk); - llc_sap_rcv(sap, skb1, sk); - sock_put(sk); + if (i < count) + stack[i++] = sk; + else { + llc_do_mcast(sap, skb, stack, i); + i = 0; + } } spin_unlock_bh(&sap->sk_lock); + + llc_do_mcast(sap, skb, stack, i); } -- cgit v1.2.3 From 6d2e3ea284463d5ab34e9cf2a41d0b8627b95d02 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:04 +0000 Subject: llc: use a device based hash table to speed up multicast delivery This patch adds a per SAP device based hash table to solve the multicast delivery scalability issue when we have large number of interfaces and a large number of sockets bound to the same SAP. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/llc.h | 11 +++++++++++ include/net/llc_conn.h | 1 + net/llc/llc_conn.c | 10 +++++++++- net/llc/llc_sap.c | 8 ++++++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/net/llc.h b/include/net/llc.h index 1559cf10e874..dbef5917905b 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -32,6 +32,9 @@ struct llc_addr { #define LLC_SAP_STATE_INACTIVE 1 #define LLC_SAP_STATE_ACTIVE 2 +#define LLC_SK_DEV_HASH_BITS 6 +#define LLC_SK_DEV_HASH_ENTRIES (1<sk_dev_hash[ifindex % LLC_SK_DEV_HASH_ENTRIES]; +} + + #define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ #define LLC_DEST_SAP 1 /* Type 1 goes here */ #define LLC_DEST_CONN 2 /* Type 2 goes here */ diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h index fe982fd94c4a..2f97d8ddce92 100644 --- a/include/net/llc_conn.h +++ b/include/net/llc_conn.h @@ -77,6 +77,7 @@ struct llc_sock { received and caused sending FRMR. Used for resending FRMR */ u32 cmsg_flags; + struct hlist_node dev_hash_node; }; static inline struct llc_sock *llc_sk(const struct sock *sk) diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 77bb3816655e..10cdfe2db830 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -682,10 +682,15 @@ static int llc_find_offset(int state, int ev_type) */ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) { + struct llc_sock *llc = llc_sk(sk); + struct hlist_head *dev_hb = llc_sk_dev_hash(sap, llc->dev->ifindex); + llc_sap_hold(sap); - spin_lock_bh(&sap->sk_lock); llc_sk(sk)->sap = sap; + + spin_lock_bh(&sap->sk_lock); sk_nulls_add_node_rcu(sk, &sap->sk_list); + hlist_add_head(&llc->dev_hash_node, dev_hb); spin_unlock_bh(&sap->sk_lock); } @@ -699,8 +704,11 @@ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) */ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) { + struct llc_sock *llc = llc_sk(sk); + spin_lock_bh(&sap->sk_lock); sk_nulls_del_node_init_rcu(sk); + hlist_del(&llc->dev_hash_node); spin_unlock_bh(&sap->sk_lock); llc_sap_put(sap); } diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 94790e60d072..94cb706f6cc4 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -387,10 +387,14 @@ static void llc_sap_mcast(struct llc_sap *sap, { int i = 0, count = 256 / sizeof(struct sock *); struct sock *sk, *stack[count]; - struct hlist_nulls_node *node; + struct hlist_node *node; + struct llc_sock *llc; + struct hlist_head *dev_hb = llc_sk_dev_hash(sap, skb->dev->ifindex); spin_lock_bh(&sap->sk_lock); - sk_nulls_for_each_rcu(sk, node, &sap->sk_list) { + hlist_for_each_entry(llc, node, dev_hb, dev_hash_node) { + + sk = &llc->sk; if (!llc_mcast_match(sap, laddr, skb, sk)) continue; -- cgit v1.2.3 From 52d58aef5ee460fedd7f250f05e79081019f2c79 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:05 +0000 Subject: llc: replace the socket list with a local address based hash For the cases where a lot of interfaces are used in conjunction with a lot of LLC sockets bound to the same SAP, the iteration of the socket list becomes prohibitively expensive. Replacing the list with a a local address based hash significantly improves the bind and listener lookup operations as well as the datagram delivery. Connected sockets delivery is also improved, but this patch does not address the case where we have lots of sockets with the same local address connected to different remote addresses. In order to keep the socket sanity checks alive and fast a socket counter was added to the SAP structure. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/llc.h | 21 +++++++++++++++- net/llc/llc_conn.c | 70 +++++++++++++++++++++++++++++++++++++++--------------- net/llc/llc_core.c | 6 +++-- net/llc/llc_proc.c | 44 +++++++++++++++++++++++----------- net/llc/llc_sap.c | 11 ++++++++- 5 files changed, 115 insertions(+), 37 deletions(-) diff --git a/include/net/llc.h b/include/net/llc.h index dbef5917905b..709a9b37e239 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include @@ -35,6 +37,9 @@ struct llc_addr { #define LLC_SK_DEV_HASH_BITS 6 #define LLC_SK_DEV_HASH_ENTRIES (1<sk_dev_hash[ifindex % LLC_SK_DEV_HASH_ENTRIES]; } +static inline +u32 llc_sk_laddr_hashfn(struct llc_sap *sap, const struct llc_addr *laddr) +{ + return hash_32(jhash(laddr->mac, sizeof(laddr->mac), 0), + LLC_SK_LADDR_HASH_BITS); +} + +static inline +struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap, + const struct llc_addr *laddr) +{ + return &sap->sk_laddr_hash[llc_sk_laddr_hashfn(sap, laddr)]; +} #define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ #define LLC_DEST_SAP 1 /* Type 1 goes here */ diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index 10cdfe2db830..a8dde9b010da 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c @@ -498,10 +498,12 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap, { struct sock *rc; struct hlist_nulls_node *node; + int slot = llc_sk_laddr_hashfn(sap, laddr); + struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot]; rcu_read_lock(); again: - sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + sk_nulls_for_each_rcu(rc, node, laddr_hb) { if (llc_estab_match(sap, daddr, laddr, rc)) { /* Extra checks required by SLAB_DESTROY_BY_RCU */ if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) @@ -515,6 +517,13 @@ again: } } rc = NULL; + /* + * if the nulls value we got at the end of this lookup is + * not the expected one, we must restart lookup. + * We probably met an item that was moved to another chain. + */ + if (unlikely(get_nulls_value(node) != slot)) + goto again; found: rcu_read_unlock(); return rc; @@ -540,29 +549,20 @@ static inline bool llc_listener_match(const struct llc_sap *sap, return sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN && llc->laddr.lsap == laddr->lsap && - (llc_mac_match(llc->laddr.mac, laddr->mac) || - llc_mac_null(llc->laddr.mac)); + llc_mac_match(llc->laddr.mac, laddr->mac); } -/** - * llc_lookup_listener - Finds listener for local MAC + SAP - * @sap: SAP - * @laddr: address of local LLC (MAC + SAP) - * - * Search connection list of the SAP and finds connection listening on - * local mac, and local sap. Returns pointer for parent socket found, - * %NULL otherwise. - * Caller has to make sure local_bh is disabled. - */ -static struct sock *llc_lookup_listener(struct llc_sap *sap, - struct llc_addr *laddr) +static struct sock *__llc_lookup_listener(struct llc_sap *sap, + struct llc_addr *laddr) { struct sock *rc; struct hlist_nulls_node *node; + int slot = llc_sk_laddr_hashfn(sap, laddr); + struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot]; rcu_read_lock(); again: - sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + sk_nulls_for_each_rcu(rc, node, laddr_hb) { if (llc_listener_match(sap, laddr, rc)) { /* Extra checks required by SLAB_DESTROY_BY_RCU */ if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) @@ -576,11 +576,40 @@ again: } } rc = NULL; + /* + * if the nulls value we got at the end of this lookup is + * not the expected one, we must restart lookup. + * We probably met an item that was moved to another chain. + */ + if (unlikely(get_nulls_value(node) != slot)) + goto again; found: rcu_read_unlock(); return rc; } +/** + * llc_lookup_listener - Finds listener for local MAC + SAP + * @sap: SAP + * @laddr: address of local LLC (MAC + SAP) + * + * Search connection list of the SAP and finds connection listening on + * local mac, and local sap. Returns pointer for parent socket found, + * %NULL otherwise. + * Caller has to make sure local_bh is disabled. + */ +static struct sock *llc_lookup_listener(struct llc_sap *sap, + struct llc_addr *laddr) +{ + static struct llc_addr null_addr; + struct sock *rc = __llc_lookup_listener(sap, laddr); + + if (!rc) + rc = __llc_lookup_listener(sap, &null_addr); + + return rc; +} + static struct sock *__llc_lookup(struct llc_sap *sap, struct llc_addr *daddr, struct llc_addr *laddr) @@ -678,18 +707,20 @@ static int llc_find_offset(int state, int ev_type) * @sap: SAP * @sk: socket * - * This function adds a socket to sk_list of a SAP. + * This function adds a socket to the hash tables of a SAP. */ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) { struct llc_sock *llc = llc_sk(sk); struct hlist_head *dev_hb = llc_sk_dev_hash(sap, llc->dev->ifindex); + struct hlist_nulls_head *laddr_hb = llc_sk_laddr_hash(sap, &llc->laddr); llc_sap_hold(sap); llc_sk(sk)->sap = sap; spin_lock_bh(&sap->sk_lock); - sk_nulls_add_node_rcu(sk, &sap->sk_list); + sap->sk_count++; + sk_nulls_add_node_rcu(sk, laddr_hb); hlist_add_head(&llc->dev_hash_node, dev_hb); spin_unlock_bh(&sap->sk_lock); } @@ -699,7 +730,7 @@ void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk) * @sap: SAP * @sk: socket * - * This function removes a connection from sk_list of a SAP if + * This function removes a connection from the hash tables of a SAP if * the connection was in this list. */ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) @@ -709,6 +740,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk) spin_lock_bh(&sap->sk_lock); sk_nulls_del_node_init_rcu(sk); hlist_del(&llc->dev_hash_node); + sap->sk_count--; spin_unlock_bh(&sap->sk_lock); llc_sap_put(sap); } diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 5276b9722077..0c9ef8bc7655 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -33,12 +33,14 @@ DEFINE_RWLOCK(llc_sap_list_lock); static struct llc_sap *llc_sap_alloc(void) { struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC); + int i; if (sap) { /* sap->laddr.mac - leave as a null, it's filled by bind */ sap->state = LLC_SAP_STATE_ACTIVE; spin_lock_init(&sap->sk_lock); - INIT_HLIST_NULLS_HEAD(&sap->sk_list, 0); + for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) + INIT_HLIST_NULLS_HEAD(&sap->sk_laddr_hash[i], i); atomic_set(&sap->refcnt, 1); } return sap; @@ -143,7 +145,7 @@ out: */ void llc_sap_close(struct llc_sap *sap) { - WARN_ON(!hlist_nulls_empty(&sap->sk_list)); + WARN_ON(sap->sk_count); llc_del_sap(sap); kfree(sap); } diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 6b3d033b3236..09dec6307206 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -34,17 +34,22 @@ static struct sock *llc_get_sk_idx(loff_t pos) { struct list_head *sap_entry; struct llc_sap *sap; - struct hlist_nulls_node *node; struct sock *sk = NULL; + int i; list_for_each(sap_entry, &llc_sap_list) { sap = list_entry(sap_entry, struct llc_sap, node); spin_lock_bh(&sap->sk_lock); - sk_nulls_for_each(sk, node, &sap->sk_list) { - if (!pos) - goto found; - --pos; + for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) { + struct hlist_nulls_head *head = &sap->sk_laddr_hash[i]; + struct hlist_nulls_node *node; + + sk_nulls_for_each(sk, node, head) { + if (!pos) + goto found; /* keep the lock */ + --pos; + } } spin_unlock_bh(&sap->sk_lock); } @@ -61,6 +66,19 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos) return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; } +static struct sock *laddr_hash_next(struct llc_sap *sap, int bucket) +{ + struct hlist_nulls_node *node; + struct sock *sk = NULL; + + while (++bucket < LLC_SK_LADDR_HASH_ENTRIES) + sk_nulls_for_each(sk, node, &sap->sk_laddr_hash[bucket]) + goto out; + +out: + return sk; +} + static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock* sk, *next; @@ -80,17 +98,15 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) } llc = llc_sk(sk); sap = llc->sap; + sk = laddr_hash_next(sap, llc_sk_laddr_hashfn(sap, &llc->laddr)); + if (sk) + goto out; spin_unlock_bh(&sap->sk_lock); - sk = NULL; - for (;;) { - if (sap->node.next == &llc_sap_list) - break; - sap = list_entry(sap->node.next, struct llc_sap, node); + list_for_each_entry_continue(sap, &llc_sap_list, node) { spin_lock_bh(&sap->sk_lock); - if (!hlist_nulls_empty(&sap->sk_list)) { - sk = sk_nulls_head(&sap->sk_list); - break; - } + sk = laddr_hash_next(sap, -1); + if (sk) + break; /* keep the lock */ spin_unlock_bh(&sap->sk_lock); } out: diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 94cb706f6cc4..ad6e6e1cf22f 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -321,10 +321,12 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap, { struct sock *rc; struct hlist_nulls_node *node; + int slot = llc_sk_laddr_hashfn(sap, laddr); + struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot]; rcu_read_lock_bh(); again: - sk_nulls_for_each_rcu(rc, node, &sap->sk_list) { + sk_nulls_for_each_rcu(rc, node, laddr_hb) { if (llc_dgram_match(sap, laddr, rc)) { /* Extra checks required by SLAB_DESTROY_BY_RCU */ if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt))) @@ -338,6 +340,13 @@ again: } } rc = NULL; + /* + * if the nulls value we got at the end of this lookup is + * not the expected one, we must restart lookup. + * We probably met an item that was moved to another chain. + */ + if (unlikely(get_nulls_value(node) != slot)) + goto again; found: rcu_read_unlock_bh(); return rc; -- cgit v1.2.3 From 8beb9ab6c2df203e8d68cb1f48cf42604a6bed86 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:06 +0000 Subject: llc: convert llc_sap_list to RCU Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/llc.h | 2 +- net/llc/llc_core.c | 46 ++++++++++++++-------------------------------- net/llc/llc_proc.c | 11 ++++------- 3 files changed, 19 insertions(+), 40 deletions(-) diff --git a/include/net/llc.h b/include/net/llc.h index 709a9b37e239..5503b74ab170 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -93,7 +93,7 @@ struct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap, #define LLC_DEST_CONN 2 /* Type 2 goes here */ extern struct list_head llc_sap_list; -extern rwlock_t llc_sap_list_lock; +extern spinlock_t llc_sap_list_lock; extern int llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev); diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 0c9ef8bc7655..78167e81dfeb 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -23,7 +23,7 @@ #include LIST_HEAD(llc_sap_list); -DEFINE_RWLOCK(llc_sap_list_lock); +DEFINE_SPINLOCK(llc_sap_list_lock); /** * llc_sap_alloc - allocates and initializes sap. @@ -46,30 +46,6 @@ static struct llc_sap *llc_sap_alloc(void) return sap; } -/** - * llc_add_sap - add sap to station list - * @sap: Address of the sap - * - * Adds a sap to the LLC's station sap list. - */ -static void llc_add_sap(struct llc_sap *sap) -{ - list_add_tail(&sap->node, &llc_sap_list); -} - -/** - * llc_del_sap - del sap from station list - * @sap: Address of the sap - * - * Removes a sap to the LLC's station sap list. - */ -static void llc_del_sap(struct llc_sap *sap) -{ - write_lock_bh(&llc_sap_list_lock); - list_del(&sap->node); - write_unlock_bh(&llc_sap_list_lock); -} - static struct llc_sap *__llc_sap_find(unsigned char sap_value) { struct llc_sap* sap; @@ -93,13 +69,13 @@ out: */ struct llc_sap *llc_sap_find(unsigned char sap_value) { - struct llc_sap* sap; + struct llc_sap *sap; - read_lock_bh(&llc_sap_list_lock); + rcu_read_lock_bh(); sap = __llc_sap_find(sap_value); if (sap) llc_sap_hold(sap); - read_unlock_bh(&llc_sap_list_lock); + rcu_read_unlock_bh(); return sap; } @@ -120,7 +96,7 @@ struct llc_sap *llc_sap_open(unsigned char lsap, { struct llc_sap *sap = NULL; - write_lock_bh(&llc_sap_list_lock); + spin_lock_bh(&llc_sap_list_lock); if (__llc_sap_find(lsap)) /* SAP already exists */ goto out; sap = llc_sap_alloc(); @@ -128,9 +104,9 @@ struct llc_sap *llc_sap_open(unsigned char lsap, goto out; sap->laddr.lsap = lsap; sap->rcv_func = func; - llc_add_sap(sap); + list_add_tail_rcu(&sap->node, &llc_sap_list); out: - write_unlock_bh(&llc_sap_list_lock); + spin_unlock_bh(&llc_sap_list_lock); return sap; } @@ -146,7 +122,13 @@ out: void llc_sap_close(struct llc_sap *sap) { WARN_ON(sap->sk_count); - llc_del_sap(sap); + + spin_lock_bh(&llc_sap_list_lock); + list_del_rcu(&sap->node); + spin_unlock_bh(&llc_sap_list_lock); + + synchronize_rcu(); + kfree(sap); } diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index 09dec6307206..7af1ff2d1f19 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -32,14 +32,11 @@ static void llc_ui_format_mac(struct seq_file *seq, u8 *addr) static struct sock *llc_get_sk_idx(loff_t pos) { - struct list_head *sap_entry; struct llc_sap *sap; struct sock *sk = NULL; int i; - list_for_each(sap_entry, &llc_sap_list) { - sap = list_entry(sap_entry, struct llc_sap, node); - + list_for_each_entry_rcu(sap, &llc_sap_list, node) { spin_lock_bh(&sap->sk_lock); for (i = 0; i < LLC_SK_LADDR_HASH_ENTRIES; i++) { struct hlist_nulls_head *head = &sap->sk_laddr_hash[i]; @@ -62,7 +59,7 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos) { loff_t l = *pos; - read_lock_bh(&llc_sap_list_lock); + rcu_read_lock_bh(); return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; } @@ -102,7 +99,7 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (sk) goto out; spin_unlock_bh(&sap->sk_lock); - list_for_each_entry_continue(sap, &llc_sap_list, node) { + list_for_each_entry_continue_rcu(sap, &llc_sap_list, node) { spin_lock_bh(&sap->sk_lock); sk = laddr_hash_next(sap, -1); if (sk) @@ -122,7 +119,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v) spin_unlock_bh(&sap->sk_lock); } - read_unlock_bh(&llc_sap_list_lock); + rcu_read_unlock_bh(); } static int llc_seq_socket_show(struct seq_file *seq, void *v) -- cgit v1.2.3 From 3100aa9d74db9c6d8d9a3b6421721fc1aef4728f Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sat, 26 Dec 2009 11:51:08 +0000 Subject: llc: fix SAP reference counting w.r.t. socket handling The SAP ref counter gets decremented twice when deleting a socket, although for all but the first socket of a SAP the SAP ref counter was incremented only once. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- net/llc/af_llc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f49f3dd6fbd3..e35d907fba2c 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -197,10 +197,8 @@ static int llc_ui_release(struct socket *sock) llc->laddr.lsap, llc->daddr.lsap); if (!llc_send_disc(sk)) llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo); - if (!sock_flag(sk, SOCK_ZAPPED)) { - llc_sap_put(llc->sap); + if (!sock_flag(sk, SOCK_ZAPPED)) llc_sap_remove_socket(llc->sap, sk); - } release_sock(sk); if (llc->dev) dev_put(llc->dev); @@ -352,7 +350,6 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen) rc = -EBUSY; /* some other network layer is using the sap */ if (!sap) goto out; - llc_sap_hold(sap); } else { struct llc_addr laddr, daddr; struct sock *ask; -- cgit v1.2.3 From 55489b6ed6801a42636fc3d4594b77dda9c409f2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:31:33 +0100 Subject: mwl8k: firmware command code cleanup Sort firmware commands by command code, get rid of the 802_11 substring in all command names, and make sure that the command functions match the firmware command names. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 647 +++++++++++++++++++++---------------------- 1 file changed, 323 insertions(+), 324 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 59d49159cf2a..b543defdde8a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -221,7 +221,7 @@ struct mwl8k_vif { u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; - /* Index into station database.Returned by update_sta_db call */ + /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; /* Non AMPDU sequence number assigned by driver */ @@ -1897,9 +1897,9 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, } /* - * CMD_802_11_GET_STAT. + * CMD_GET_STAT. */ -struct mwl8k_cmd_802_11_get_stat { +struct mwl8k_cmd_get_stat { struct mwl8k_cmd_pkt header; __le32 stats[64]; } __attribute__((packed)); @@ -1909,10 +1909,10 @@ struct mwl8k_cmd_802_11_get_stat { #define MWL8K_STAT_FCS_ERROR 24 #define MWL8K_STAT_RTS_SUCCESS 11 -static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats) { - struct mwl8k_cmd_802_11_get_stat *cmd; + struct mwl8k_cmd_get_stat *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -1939,9 +1939,9 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, } /* - * CMD_802_11_RADIO_CONTROL. + * CMD_RADIO_CONTROL. */ -struct mwl8k_cmd_802_11_radio_control { +struct mwl8k_cmd_radio_control { struct mwl8k_cmd_pkt header; __le16 action; __le16 control; @@ -1949,10 +1949,10 @@ struct mwl8k_cmd_802_11_radio_control { } __attribute__((packed)); static int -mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) +mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) { struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_802_11_radio_control *cmd; + struct mwl8k_cmd_radio_control *cmd; int rc; if (enable == priv->radio_on && !force) @@ -1977,14 +1977,14 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) return rc; } -static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) +static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw) { - return mwl8k_cmd_802_11_radio_control(hw, 0, 0); + return mwl8k_cmd_radio_control(hw, 0, 0); } -static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) +static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) { - return mwl8k_cmd_802_11_radio_control(hw, 1, 0); + return mwl8k_cmd_radio_control(hw, 1, 0); } static int @@ -1998,15 +1998,15 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) priv->radio_short_preamble = short_preamble; - return mwl8k_cmd_802_11_radio_control(hw, 1, 1); + return mwl8k_cmd_radio_control(hw, 1, 1); } /* - * CMD_802_11_RF_TX_POWER. + * CMD_RF_TX_POWER. */ #define MWL8K_TX_POWER_LEVEL_TOTAL 8 -struct mwl8k_cmd_802_11_rf_tx_power { +struct mwl8k_cmd_rf_tx_power { struct mwl8k_cmd_pkt header; __le16 action; __le16 support_level; @@ -2015,9 +2015,9 @@ struct mwl8k_cmd_802_11_rf_tx_power { __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; } __attribute__((packed)); -static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) +static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) { - struct mwl8k_cmd_802_11_rf_tx_power *cmd; + struct mwl8k_cmd_rf_tx_power *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2159,85 +2159,61 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, } /* - * CMD_SET_SLOT. + * CMD_SET_AID. */ -struct mwl8k_cmd_set_slot { - struct mwl8k_cmd_pkt header; - __le16 action; - __u8 short_slot; -} __attribute__((packed)); - -static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) -{ - struct mwl8k_cmd_set_slot *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->short_slot = short_slot_time; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); +#define MWL8K_FRAME_PROT_DISABLED 0x00 +#define MWL8K_FRAME_PROT_11G 0x07 +#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 +#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 - return rc; -} +struct mwl8k_cmd_update_set_aid { + struct mwl8k_cmd_pkt header; + __le16 aid; -/* - * CMD_MIMO_CONFIG. - */ -struct mwl8k_cmd_mimo_config { - struct mwl8k_cmd_pkt header; - __le32 action; - __u8 rx_antenna_map; - __u8 tx_antenna_map; + /* AP's MAC address (BSSID) */ + __u8 bssid[ETH_ALEN]; + __le16 protection_mode; + __u8 supp_rates[14]; } __attribute__((packed)); -static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) +static int +mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mwl8k_cmd_mimo_config *cmd; + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + struct ieee80211_bss_conf *info = &mv_vif->bss_info; + struct mwl8k_cmd_update_set_aid *cmd; + u16 prot_mode; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); - cmd->rx_antenna_map = rx; - cmd->tx_antenna_map = tx; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_ENABLE_SNIFFER. - */ -struct mwl8k_cmd_enable_sniffer { - struct mwl8k_cmd_pkt header; - __le32 action; -} __attribute__((packed)); + cmd->aid = cpu_to_le16(info->aid); -static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) -{ - struct mwl8k_cmd_enable_sniffer *cmd; - int rc; + memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; + if (info->use_cts_prot) { + prot_mode = MWL8K_FRAME_PROT_11G; + } else { + switch (info->ht_operation_mode & + IEEE80211_HT_OP_MODE_PROTECTION) { + case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: + prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; + break; + case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: + prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; + break; + default: + prot_mode = MWL8K_FRAME_PROT_DISABLED; + break; + } + } + cmd->protection_mode = cpu_to_le16(prot_mode); - cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le32(!!enable); + memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2246,37 +2222,30 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) } /* - * CMD_SET_MAC_ADDR. + * CMD_SET_RATE. */ -struct mwl8k_cmd_set_mac_addr { - struct mwl8k_cmd_pkt header; - union { - struct { - __le16 mac_type; - __u8 mac_addr[ETH_ALEN]; - } mbss; - __u8 mac_addr[ETH_ALEN]; - }; +struct mwl8k_cmd_set_rate { + struct mwl8k_cmd_pkt header; + __u8 legacy_rates[14]; + + /* Bitmap for supported MCS codes. */ + __u8 mcs_set[16]; + __u8 reserved[16]; } __attribute__((packed)); -static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) +static int +mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_set_mac_addr *cmd; + struct mwl8k_cmd_set_rate *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - if (priv->ap_fw) { - cmd->mbss.mac_type = 0; - memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); - } else { - memcpy(cmd->mac_addr, mac, ETH_ALEN); - } + memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2284,29 +2253,40 @@ static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) return rc; } - /* - * CMD_SET_RATEADAPT_MODE. + * CMD_FINALIZE_JOIN. */ -struct mwl8k_cmd_set_rate_adapt_mode { +#define MWL8K_FJ_BEACON_MAXLEN 128 + +struct mwl8k_cmd_finalize_join { struct mwl8k_cmd_pkt header; - __le16 action; - __le16 mode; + __le32 sleep_interval; /* Number of beacon periods to sleep */ + __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; } __attribute__((packed)); -static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) +static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, + int framelen, int dtim) { - struct mwl8k_cmd_set_rate_adapt_mode *cmd; + struct mwl8k_cmd_finalize_join *cmd; + struct ieee80211_mgmt *payload = frame; + int payload_len; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->mode = cpu_to_le16(mode); + cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); + + payload_len = framelen - ieee80211_hdrlen(payload->frame_control); + if (payload_len < 0) + payload_len = 0; + else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) + payload_len = MWL8K_FJ_BEACON_MAXLEN; + + memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2315,59 +2295,57 @@ static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) } /* - * CMD_SET_WMM_MODE. + * CMD_SET_RTS_THRESHOLD. */ -struct mwl8k_cmd_set_wmm { +struct mwl8k_cmd_set_rts_threshold { struct mwl8k_cmd_pkt header; __le16 action; + __le16 threshold; } __attribute__((packed)); -static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) +static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, + u16 action, u16 threshold) { - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_set_wmm *cmd; + struct mwl8k_cmd_set_rts_threshold *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); + cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(!!enable); + cmd->action = cpu_to_le16(action); + cmd->threshold = cpu_to_le16(threshold); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); - if (!rc) - priv->wmm_enabled = enable; - return rc; } /* - * CMD_SET_RTS_THRESHOLD. + * CMD_SET_SLOT. */ -struct mwl8k_cmd_rts_threshold { +struct mwl8k_cmd_set_slot { struct mwl8k_cmd_pkt header; __le16 action; - __le16 threshold; + __u8 short_slot; } __attribute__((packed)); -static int mwl8k_rts_threshold(struct ieee80211_hw *hw, - u16 action, u16 threshold) +static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) { - struct mwl8k_cmd_rts_threshold *cmd; + struct mwl8k_cmd_set_slot *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(action); - cmd->threshold = cpu_to_le16(threshold); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->short_slot = short_slot_time; rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2426,9 +2404,9 @@ struct mwl8k_cmd_set_edca_params { MWL8K_SET_EDCA_AIFS) static int -mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, - __u16 cw_min, __u16 cw_max, - __u8 aifs, __u16 txop) +mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, + __u16 cw_min, __u16 cw_max, + __u8 aifs, __u16 txop) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_set_edca_params *cmd; @@ -2467,202 +2445,60 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, } /* - * CMD_FINALIZE_JOIN. + * CMD_SET_WMM_MODE. */ -#define MWL8K_FJ_BEACON_MAXLEN 128 - -struct mwl8k_cmd_finalize_join { +struct mwl8k_cmd_set_wmm_mode { struct mwl8k_cmd_pkt header; - __le32 sleep_interval; /* Number of beacon periods to sleep */ - __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; + __le16 action; } __attribute__((packed)); -static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, - int framelen, int dtim) +static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) { - struct mwl8k_cmd_finalize_join *cmd; - struct ieee80211_mgmt *payload = frame; - int payload_len; + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_cmd_set_wmm_mode *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); - - payload_len = framelen - ieee80211_hdrlen(payload->frame_control); - if (payload_len < 0) - payload_len = 0; - else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) - payload_len = MWL8K_FJ_BEACON_MAXLEN; - - memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); + cmd->action = cpu_to_le16(!!enable); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); - return rc; -} - -/* - * CMD_UPDATE_STADB. - */ -struct mwl8k_cmd_update_sta_db { - struct mwl8k_cmd_pkt header; - - /* See STADB_ACTION_TYPE */ - __le32 action; - - /* Peer MAC address */ - __u8 peer_addr[ETH_ALEN]; - - __le32 reserved; - - /* Peer info - valid during add/update. */ - struct peer_capability_info peer_info; -} __attribute__((packed)); - -static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, __u32 action) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; - struct mwl8k_cmd_update_sta_db *cmd; - struct peer_capability_info *peer_info; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(action); - peer_info = &cmd->peer_info; - memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); - - switch (action) { - case MWL8K_STA_DB_ADD_ENTRY: - case MWL8K_STA_DB_MODIFY_ENTRY: - /* Build peer_info block */ - peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; - peer_info->basic_caps = cpu_to_le16(info->assoc_capability); - memcpy(peer_info->legacy_rates, mwl8k_rateids, - sizeof(mwl8k_rateids)); - peer_info->interop = 1; - peer_info->amsdu_enabled = 0; - - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = peer_info->station_id; - - break; - - case MWL8K_STA_DB_DEL_ENTRY: - case MWL8K_STA_DB_FLUSH: - default: - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = 0; - break; - } - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_AID. - */ -#define MWL8K_FRAME_PROT_DISABLED 0x00 -#define MWL8K_FRAME_PROT_11G 0x07 -#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 -#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 - -struct mwl8k_cmd_update_set_aid { - struct mwl8k_cmd_pkt header; - __le16 aid; - - /* AP's MAC address (BSSID) */ - __u8 bssid[ETH_ALEN]; - __le16 protection_mode; - __u8 supp_rates[14]; -} __attribute__((packed)); - -static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; - struct mwl8k_cmd_update_set_aid *cmd; - u16 prot_mode; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->aid = cpu_to_le16(info->aid); - - memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); - - if (info->use_cts_prot) { - prot_mode = MWL8K_FRAME_PROT_11G; - } else { - switch (info->ht_operation_mode & - IEEE80211_HT_OP_MODE_PROTECTION) { - case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: - prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; - break; - case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: - prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; - break; - default: - prot_mode = MWL8K_FRAME_PROT_DISABLED; - break; - } - } - cmd->protection_mode = cpu_to_le16(prot_mode); - - memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); + if (!rc) + priv->wmm_enabled = enable; return rc; } /* - * CMD_SET_RATE. + * CMD_MIMO_CONFIG. */ -struct mwl8k_cmd_update_rateset { - struct mwl8k_cmd_pkt header; - __u8 legacy_rates[14]; - - /* Bitmap for supported MCS codes. */ - __u8 mcs_set[16]; - __u8 reserved[16]; +struct mwl8k_cmd_mimo_config { + struct mwl8k_cmd_pkt header; + __le32 action; + __u8 rx_antenna_map; + __u8 tx_antenna_map; } __attribute__((packed)); -static int mwl8k_update_rateset(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) { - struct mwl8k_cmd_update_rateset *cmd; + struct mwl8k_cmd_mimo_config *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); + cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); + cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); + cmd->rx_antenna_map = rx; + cmd->tx_antenna_map = tx; rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2755,6 +2591,169 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, return rc; } +/* + * CMD_ENABLE_SNIFFER. + */ +struct mwl8k_cmd_enable_sniffer { + struct mwl8k_cmd_pkt header; + __le32 action; +} __attribute__((packed)); + +static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) +{ + struct mwl8k_cmd_enable_sniffer *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32(!!enable); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_MAC_ADDR. + */ +struct mwl8k_cmd_set_mac_addr { + struct mwl8k_cmd_pkt header; + union { + struct { + __le16 mac_type; + __u8 mac_addr[ETH_ALEN]; + } mbss; + __u8 mac_addr[ETH_ALEN]; + }; +} __attribute__((packed)); + +static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_cmd_set_mac_addr *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + if (priv->ap_fw) { + cmd->mbss.mac_type = 0; + memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); + } else { + memcpy(cmd->mac_addr, mac, ETH_ALEN); + } + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_SET_RATEADAPT_MODE. + */ +struct mwl8k_cmd_set_rate_adapt_mode { + struct mwl8k_cmd_pkt header; + __le16 action; + __le16 mode; +} __attribute__((packed)); + +static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) +{ + struct mwl8k_cmd_set_rate_adapt_mode *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->mode = cpu_to_le16(mode); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +/* + * CMD_UPDATE_STADB. + */ +struct mwl8k_cmd_update_stadb { + struct mwl8k_cmd_pkt header; + + /* See STADB_ACTION_TYPE */ + __le32 action; + + /* Peer MAC address */ + __u8 peer_addr[ETH_ALEN]; + + __le32 reserved; + + /* Peer info - valid during add/update. */ + struct peer_capability_info peer_info; +} __attribute__((packed)); + +static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, __u32 action) +{ + struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); + struct ieee80211_bss_conf *info = &mv_vif->bss_info; + struct mwl8k_cmd_update_stadb *cmd; + struct peer_capability_info *peer_info; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + + cmd->action = cpu_to_le32(action); + peer_info = &cmd->peer_info; + memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); + + switch (action) { + case MWL8K_STA_DB_ADD_ENTRY: + case MWL8K_STA_DB_MODIFY_ENTRY: + /* Build peer_info block */ + peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; + peer_info->basic_caps = cpu_to_le16(info->assoc_capability); + memcpy(peer_info->legacy_rates, mwl8k_rateids, + sizeof(mwl8k_rateids)); + peer_info->interop = 1; + peer_info->amsdu_enabled = 0; + + rc = mwl8k_post_cmd(hw, &cmd->header); + if (rc == 0) + mv_vif->peer_id = peer_info->station_id; + + break; + + case MWL8K_STA_DB_DEL_ENTRY: + case MWL8K_STA_DB_FLUSH: + default: + rc = mwl8k_post_cmd(hw, &cmd->header); + if (rc == 0) + mv_vif->peer_id = 0; + break; + } + kfree(cmd); + + return rc; +} + /* * Interrupt handling. @@ -2836,11 +2835,11 @@ static int mwl8k_start(struct ieee80211_hw *hw) rc = mwl8k_fw_lock(hw); if (!rc) { - rc = mwl8k_cmd_802_11_radio_enable(hw); + rc = mwl8k_cmd_radio_enable(hw); if (!priv->ap_fw) { if (!rc) - rc = mwl8k_enable_sniffer(hw, 0); + rc = mwl8k_cmd_enable_sniffer(hw, 0); if (!rc) rc = mwl8k_cmd_set_pre_scan(hw); @@ -2851,10 +2850,10 @@ static int mwl8k_start(struct ieee80211_hw *hw) } if (!rc) - rc = mwl8k_cmd_setrateadaptmode(hw, 0); + rc = mwl8k_cmd_set_rateadapt_mode(hw, 0); if (!rc) - rc = mwl8k_set_wmm(hw, 0); + rc = mwl8k_cmd_set_wmm_mode(hw, 0); mwl8k_fw_unlock(hw); } @@ -2873,7 +2872,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) struct mwl8k_priv *priv = hw->priv; int i; - mwl8k_cmd_802_11_radio_disable(hw); + mwl8k_cmd_radio_disable(hw); ieee80211_stop_queues(hw); @@ -2929,7 +2928,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); /* Set and save the mac address */ - mwl8k_set_mac_addr(hw, conf->mac_addr); + mwl8k_cmd_set_mac_addr(hw, conf->mac_addr); memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); /* Back pointer to parent config block */ @@ -2952,7 +2951,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, if (priv->vif == NULL) return; - mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); + mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); priv->vif = NULL; } @@ -2964,7 +2963,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) int rc; if (conf->flags & IEEE80211_CONF_IDLE) { - mwl8k_cmd_802_11_radio_disable(hw); + mwl8k_cmd_radio_disable(hw); priv->current_channel = NULL; return 0; } @@ -2973,7 +2972,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (rc) return rc; - rc = mwl8k_cmd_802_11_radio_enable(hw); + rc = mwl8k_cmd_radio_enable(hw); if (rc) goto out; @@ -2985,7 +2984,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (conf->power_level > 18) conf->power_level = 18; - rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); + rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); if (rc) goto out; @@ -3028,7 +3027,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); /* Install rates */ - rc = mwl8k_update_rateset(hw, vif); + rc = mwl8k_cmd_set_rate(hw, vif); if (rc) goto out; @@ -3049,7 +3048,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, goto out; /* Update peer rate info */ - rc = mwl8k_cmd_update_sta_db(hw, vif, + rc = mwl8k_cmd_update_stadb(hw, vif, MWL8K_STA_DB_MODIFY_ENTRY); if (rc) goto out; @@ -3066,7 +3065,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); priv->capture_beacon = true; } else { - rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); + rc = mwl8k_cmd_update_stadb(hw, vif, MWL8K_STA_DB_DEL_ENTRY); memset(&mwl8k_vif->bss_info, 0, sizeof(struct ieee80211_bss_conf)); memset(mwl8k_vif->bssid, 0, ETH_ALEN); @@ -3114,7 +3113,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, } if (!priv->sniffer_enabled) { - if (mwl8k_enable_sniffer(hw, 1)) + if (mwl8k_cmd_enable_sniffer(hw, 1)) return 0; priv->sniffer_enabled = true; } @@ -3161,7 +3160,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, return; if (priv->sniffer_enabled) { - mwl8k_enable_sniffer(hw, 0); + mwl8k_cmd_enable_sniffer(hw, 0); priv->sniffer_enabled = false; } @@ -3211,7 +3210,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { - return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); + return mwl8k_cmd_set_rts_threshold(hw, MWL8K_CMD_SET, value); } static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, @@ -3223,14 +3222,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, rc = mwl8k_fw_lock(hw); if (!rc) { if (!priv->wmm_enabled) - rc = mwl8k_set_wmm(hw, 1); + rc = mwl8k_cmd_set_wmm_mode(hw, 1); if (!rc) - rc = mwl8k_set_edca_params(hw, queue, - params->cw_min, - params->cw_max, - params->aifs, - params->txop); + rc = mwl8k_cmd_set_edca_params(hw, queue, + params->cw_min, + params->cw_max, + params->aifs, + params->txop); mwl8k_fw_unlock(hw); } @@ -3259,7 +3258,7 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, static int mwl8k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { - return mwl8k_cmd_802_11_get_stat(hw, stats); + return mwl8k_cmd_get_stat(hw, stats); } static const struct ieee80211_ops mwl8k_ops = { @@ -3302,7 +3301,7 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) struct sk_buff *skb = priv->beacon_skb; u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; - mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); + mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim); dev_kfree_skb(skb); priv->beacon_skb = NULL; @@ -3531,14 +3530,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } /* Turn radio off */ - rc = mwl8k_cmd_802_11_radio_disable(hw); + rc = mwl8k_cmd_radio_disable(hw); if (rc) { printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); goto err_stop_firmware; } /* Clear MAC address */ - rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); + rc = mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); if (rc) { printk(KERN_ERR "%s: Cannot clear MAC address\n", wiphy_name(hw->wiphy)); -- cgit v1.2.3 From 99200a992e365a73dc67a6570524e5f3af4386dd Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:31:40 +0100 Subject: mwl8k: hw is never NULL in mwl8k_set_radio_preamble() Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b543defdde8a..aba45ca43da7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1990,11 +1990,7 @@ static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) static int mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) { - struct mwl8k_priv *priv; - - if (hw == NULL || hw->priv == NULL) - return -EINVAL; - priv = hw->priv; + struct mwl8k_priv *priv = hw->priv; priv->radio_short_preamble = short_preamble; -- cgit v1.2.3 From 74726e729291131ac2b9ab7e0bd2e18b7b03970d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:31:52 +0100 Subject: mwl8k: get rid of the AMSDU check in the transmit path Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index aba45ca43da7..18542fba1f43 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -677,14 +677,6 @@ static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) return (qos & qos_mask) | ((ack_policy & val_mask) << shift); } -static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) -{ - u16 val_mask = 1 << 7; - - /* AMSDU present Bit 7 */ - return qos | val_mask; -} - static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) { u16 val_mask = 0xff; @@ -1474,9 +1466,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) else qos = mwl8k_qos_setbit_ack(qos, MWL8K_TXD_ACK_POLICY_NORMAL); - - if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) - qos = mwl8k_qos_setbit_amsdu(qos); } dma = pci_map_single(priv->pdev, skb->data, -- cgit v1.2.3 From e0493a8dd6351a114b53790dda6bd855ae73a85c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:00 +0100 Subject: mwl8k: inline qos field manipulation functions Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 51 +++++++++----------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 18542fba1f43..8cbb52cc4269 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -658,35 +658,6 @@ struct peer_capability_info { __le16 amsdu_enabled; } __attribute__((packed)); -/* Inline functions to manipulate QoS field in data descriptor. */ -static inline u16 mwl8k_qos_setbit_eosp(u16 qos) -{ - u16 val_mask = 1 << 4; - - /* End of Service Period Bit 4 */ - return qos | val_mask; -} - -static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) -{ - u16 val_mask = 0x3; - u8 shift = 5; - u16 qos_mask = ~(val_mask << shift); - - /* Ack Policy Bit 5-6 */ - return (qos & qos_mask) | ((ack_policy & val_mask) << shift); -} - -static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) -{ - u16 val_mask = 0xff; - u8 shift = 8; - u16 qos_mask = ~(val_mask << shift); - - /* Queue Length Bits 8-15 */ - return (qos & qos_mask) | ((len & val_mask) << shift); -} - /* DMA header used by firmware and hardware. */ struct mwl8k_dma_data { __le16 fwlen; @@ -1145,16 +1116,18 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) * Packet transmission. */ -/* Transmit packet ACK policy */ -#define MWL8K_TXD_ACK_POLICY_NORMAL 0 -#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 - #define MWL8K_TXD_STATUS_OK 0x00000001 #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 +#define MWL8K_QOS_QLEN_UNSPEC 0xff00 +#define MWL8K_QOS_ACK_POLICY_MASK 0x0060 +#define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000 +#define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060 +#define MWL8K_QOS_EOSP 0x0010 + struct mwl8k_tx_desc { __le32 status; __u8 data_rate; @@ -1451,21 +1424,17 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) if (ieee80211_is_mgmt(wh->frame_control) || ieee80211_is_ctl(wh->frame_control)) { txdatarate = 0; - qos = mwl8k_qos_setbit_eosp(qos); - /* Set Queue size to unspecified */ - qos = mwl8k_qos_setbit_qlen(qos, 0xff); + qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP; } else if (ieee80211_is_data(wh->frame_control)) { txdatarate = 1; if (is_multicast_ether_addr(wh->addr1)) txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; - /* Send pkt in an aggregate if AMPDU frame. */ + qos &= ~MWL8K_QOS_ACK_POLICY_MASK; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_BLOCKACK); + qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK; else - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_NORMAL); + qos |= MWL8K_QOS_ACK_POLICY_NORMAL; } dma = pci_map_single(priv->pdev, skb->data, -- cgit v1.2.3 From 49eb691c8f48a29adfdfbdeb82433f1f8cb6524d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:13 +0100 Subject: mwl8k: initialize the mwl8k_info_tbl table using the MWL* enums Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8cbb52cc4269..5c849aa86139 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3267,14 +3267,14 @@ enum { }; static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { - { + [MWL8687] = { .part_name = "88w8687", .helper_image = "mwl8k/helper_8687.fw", .fw_image = "mwl8k/fmimage_8687.fw", .rxd_ops = &rxd_8687_ops, .modes = BIT(NL80211_IFTYPE_STATION), }, - { + [MWL8366] = { .part_name = "88w8366", .helper_image = "mwl8k/helper_8366.fw", .fw_image = "mwl8k/fmimage_8366.fw", -- cgit v1.2.3 From 647ca6b01a5289948e970ea7c1f656f9d90b0a27 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:20 +0100 Subject: mwl8k: add 2.4GHz channels 12, 13 and 14 Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 5c849aa86139..c54f8305df18 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -242,6 +242,9 @@ static const struct ieee80211_channel mwl8k_channels[] = { { .center_freq = 2452, .hw_value = 9, }, { .center_freq = 2457, .hw_value = 10, }, { .center_freq = 2462, .hw_value = 11, }, + { .center_freq = 2467, .hw_value = 12, }, + { .center_freq = 2472, .hw_value = 13, }, + { .center_freq = 2484, .hw_value = 14, }, }; static const struct ieee80211_rate mwl8k_rates[] = { -- cgit v1.2.3 From 22be40d9c53faa10d03a679160e0854ad115b610 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:38 +0100 Subject: mwl8k: get rid of the struct mwl8k_firmware abstraction Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index c54f8305df18..19fe7124d93a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -126,15 +126,6 @@ struct mwl8k_tx_queue { struct sk_buff **skb; }; -/* Pointers to the firmware data and meta information about it. */ -struct mwl8k_firmware { - /* Boot helper code */ - struct firmware *helper; - - /* Microcode */ - struct firmware *ucode; -}; - struct mwl8k_priv { void __iomem *sram; void __iomem *regs; @@ -147,7 +138,8 @@ struct mwl8k_priv { struct rxd_ops *rxd_ops; /* firmware files and meta data */ - struct mwl8k_firmware fw; + struct firmware *fw_helper; + struct firmware *fw_ucode; /* firmware access */ struct mutex fw_mutex; @@ -358,8 +350,8 @@ static void mwl8k_release_fw(struct firmware **fw) static void mwl8k_release_firmware(struct mwl8k_priv *priv) { - mwl8k_release_fw(&priv->fw.ucode); - mwl8k_release_fw(&priv->fw.helper); + mwl8k_release_fw(&priv->fw_ucode); + mwl8k_release_fw(&priv->fw_helper); } /* Request fw image */ @@ -380,7 +372,7 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) int rc; if (di->helper_image != NULL) { - rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper); + rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); if (rc) { printk(KERN_ERR "%s: Error requesting helper " "firmware file %s\n", pci_name(priv->pdev), @@ -389,11 +381,11 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) } } - rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode); + rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); if (rc) { printk(KERN_ERR "%s: Error requesting firmware file %s\n", pci_name(priv->pdev), di->fw_image); - mwl8k_release_fw(&priv->fw.helper); + mwl8k_release_fw(&priv->fw_helper); return rc; } @@ -554,13 +546,13 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, static int mwl8k_load_firmware(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; - struct firmware *fw = priv->fw.ucode; + struct firmware *fw = priv->fw_ucode; struct mwl8k_device_info *di = priv->device_info; int rc; int loops; if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { - struct firmware *helper = priv->fw.helper; + struct firmware *helper = priv->fw_helper; if (helper == NULL) { printk(KERN_ERR "%s: helper image needed but none " -- cgit v1.2.3 From be695fc4f0a7ff9c9f91d59536b029b781cfea62 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:46 +0100 Subject: mwl8k: do rx/tx ring initialisation after loading firmware Whether the firmware we have loaded is AP or STA firmware decides which receive descriptor format we have to use. Therefore, move rx/tx ring initialisation to be after firmware loading. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 104 ++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 19fe7124d93a..0ae56cb6b0b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -127,20 +127,22 @@ struct mwl8k_tx_queue { }; struct mwl8k_priv { - void __iomem *sram; - void __iomem *regs; struct ieee80211_hw *hw; - struct pci_dev *pdev; struct mwl8k_device_info *device_info; - bool ap_fw; - struct rxd_ops *rxd_ops; - /* firmware files and meta data */ + void __iomem *sram; + void __iomem *regs; + + /* firmware */ struct firmware *fw_helper; struct firmware *fw_ucode; + /* hardware/firmware parameters */ + bool ap_fw; + struct rxd_ops *rxd_ops; + /* firmware access */ struct mutex fw_mutex; struct task_struct *fw_mutex_owner; @@ -547,7 +549,6 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; struct firmware *fw = priv->fw_ucode; - struct mwl8k_device_info *di = priv->device_info; int rc; int loops; @@ -579,7 +580,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) return rc; } - if (di->modes & BIT(NL80211_IFTYPE_AP)) + if (priv->device_info->modes & BIT(NL80211_IFTYPE_AP)) iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); else iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); @@ -3300,6 +3301,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, printed_version = 1; } + rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR "%s: Cannot enable new PCI device\n", @@ -3316,6 +3318,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, pci_set_master(pdev); + hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); if (hw == NULL) { printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); @@ -3323,17 +3326,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_free_reg; } + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + priv = hw->priv; priv->hw = hw; priv->pdev = pdev; priv->device_info = &mwl8k_info_tbl[id->driver_data]; - priv->rxd_ops = priv->device_info->rxd_ops; - priv->sniffer_enabled = false; - priv->wmm_enabled = false; - priv->pending_tx_pkts = 0; - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { @@ -3356,6 +3356,37 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } } + + /* Reset firmware and hardware */ + mwl8k_hw_reset(priv); + + /* Ask userland hotplug daemon for the device firmware */ + rc = mwl8k_request_firmware(priv); + if (rc) { + printk(KERN_ERR "%s: Firmware files not found\n", + wiphy_name(hw->wiphy)); + goto err_stop_firmware; + } + + /* Load firmware into hardware */ + rc = mwl8k_load_firmware(hw); + if (rc) { + printk(KERN_ERR "%s: Cannot start firmware\n", + wiphy_name(hw->wiphy)); + goto err_stop_firmware; + } + + /* Reclaim memory once firmware is successfully loaded */ + mwl8k_release_firmware(priv); + + + priv->rxd_ops = priv->device_info->rxd_ops; + + priv->sniffer_enabled = false; + priv->wmm_enabled = false; + priv->pending_tx_pkts = 0; + + memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); priv->band.band = IEEE80211_BAND_2GHZ; priv->band.channels = priv->channels; @@ -3400,11 +3431,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Power management cookie */ priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); if (priv->cookie == NULL) - goto err_iounmap; + goto err_stop_firmware; rc = mwl8k_rxq_init(hw, 0); if (rc) - goto err_iounmap; + goto err_free_cookie; rxq_refill(hw, 0, INT_MAX); mutex_init(&priv->fw_mutex); @@ -3435,28 +3466,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_free_queues; } - /* Reset firmware and hardware */ - mwl8k_hw_reset(priv); - - /* Ask userland hotplug daemon for the device firmware */ - rc = mwl8k_request_firmware(priv); - if (rc) { - printk(KERN_ERR "%s: Firmware files not found\n", - wiphy_name(hw->wiphy)); - goto err_free_irq; - } - - /* Load firmware into hardware */ - rc = mwl8k_load_firmware(hw); - if (rc) { - printk(KERN_ERR "%s: Cannot start firmware\n", - wiphy_name(hw->wiphy)); - goto err_stop_firmware; - } - - /* Reclaim memory once firmware is successfully loaded */ - mwl8k_release_firmware(priv); - /* * Temporarily enable interrupts. Initial firmware host * commands use interrupts and avoids polling. Disable @@ -3475,14 +3484,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (rc) { printk(KERN_ERR "%s: Cannot initialise firmware\n", wiphy_name(hw->wiphy)); - goto err_stop_firmware; + goto err_free_irq; } /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); - goto err_stop_firmware; + goto err_free_irq; } /* Clear MAC address */ @@ -3490,7 +3499,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (rc) { printk(KERN_ERR "%s: Cannot clear MAC address\n", wiphy_name(hw->wiphy)); - goto err_stop_firmware; + goto err_free_irq; } /* Disable interrupts */ @@ -3501,7 +3510,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (rc) { printk(KERN_ERR "%s: Cannot register device\n", wiphy_name(hw->wiphy)); - goto err_stop_firmware; + goto err_free_irq; } printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", @@ -3513,10 +3522,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, return 0; -err_stop_firmware: - mwl8k_hw_reset(priv); - mwl8k_release_firmware(priv); - err_free_irq: iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); @@ -3526,11 +3531,16 @@ err_free_queues: mwl8k_txq_deinit(hw, i); mwl8k_rxq_deinit(hw, 0); -err_iounmap: +err_free_cookie: if (priv->cookie != NULL) pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma); +err_stop_firmware: + mwl8k_hw_reset(priv); + mwl8k_release_firmware(priv); + +err_iounmap: if (priv->regs != NULL) pci_iounmap(pdev, priv->regs); -- cgit v1.2.3 From 89a91f4f4cdae92daf3693d4852ae4958abb6c58 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:32:54 +0100 Subject: mwl8k: fix up AP vs. STA firmware image receive descriptor handling The receive descriptor ops that are currently marked as being for 8687 only are actually used for all STA firmware images, whereas the receive descriptor ops marked as 8366 are only used on 8366 when an AP firmware image is in use. Rename the receive descriptor ops to reflect this, use the STA ops unconditionally if the firmware image loaded reported the STA ready code, and rename the mwl8k_device_info::rxd_ops member to ap_rxd_ops to indicate that it should only be used if we are running on AP firmware. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 124 +++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0ae56cb6b0b3..b20820a015cc 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -92,8 +92,7 @@ struct mwl8k_device_info { char *part_name; char *helper_image; char *fw_image; - struct rxd_ops *rxd_ops; - u16 modes; + struct rxd_ops *ap_rxd_ops; }; struct mwl8k_rx_queue { @@ -580,10 +579,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) return rc; } - if (priv->device_info->modes & BIT(NL80211_IFTYPE_AP)) - iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); - else - iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); + iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); loops = 500000; do { @@ -720,9 +716,9 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) /* - * Packet reception for 88w8366. + * Packet reception for 88w8366 AP firmware. */ -struct mwl8k_rxd_8366 { +struct mwl8k_rxd_8366_ap { __le16 pkt_len; __u8 sq2; __u8 rate; @@ -740,23 +736,23 @@ struct mwl8k_rxd_8366 { __u8 rx_ctrl; } __attribute__((packed)); -#define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80 -#define MWL8K_8366_RATE_INFO_40MHZ 0x40 -#define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f) +#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 +#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 +#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) -#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 +#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 -static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) +static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) { - struct mwl8k_rxd_8366 *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST; + rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; } -static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) +static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) { - struct mwl8k_rxd_8366 *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; rxd->pkt_len = cpu_to_le16(len); rxd->pkt_phys_addr = cpu_to_le32(addr); @@ -765,12 +761,12 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, - __le16 *qos) +mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, + __le16 *qos) { - struct mwl8k_rxd_8366 *rxd = _rxd; + struct mwl8k_rxd_8366_ap *rxd = _rxd; - if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST)) + if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) return -1; rmb(); @@ -779,11 +775,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, status->signal = -rxd->rssi; status->noise = -rxd->noise_floor; - if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) { + if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { status->flag |= RX_FLAG_HT; - if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ) + if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) status->flag |= RX_FLAG_40MHZ; - status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate); + status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); } else { int i; @@ -803,17 +799,17 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, return le16_to_cpu(rxd->pkt_len); } -static struct rxd_ops rxd_8366_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_8366), - .rxd_init = mwl8k_rxd_8366_init, - .rxd_refill = mwl8k_rxd_8366_refill, - .rxd_process = mwl8k_rxd_8366_process, +static struct rxd_ops rxd_8366_ap_ops = { + .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), + .rxd_init = mwl8k_rxd_8366_ap_init, + .rxd_refill = mwl8k_rxd_8366_ap_refill, + .rxd_process = mwl8k_rxd_8366_ap_process, }; /* - * Packet reception for 88w8687. + * Packet reception for STA firmware. */ -struct mwl8k_rxd_8687 { +struct mwl8k_rxd_sta { __le16 pkt_len; __u8 link_quality; __u8 noise_level; @@ -830,26 +826,26 @@ struct mwl8k_rxd_8687 { __u8 pad2[2]; } __attribute__((packed)); -#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000 -#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) -#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) -#define MWL8K_8687_RATE_INFO_40MHZ 0x0004 -#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002 -#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001 +#define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 +#define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) +#define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) +#define MWL8K_STA_RATE_INFO_40MHZ 0x0004 +#define MWL8K_STA_RATE_INFO_SHORTGI 0x0002 +#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 -#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02 +#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 -static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr) +static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) { - struct mwl8k_rxd_8687 *rxd = _rxd; + struct mwl8k_rxd_sta *rxd = _rxd; rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); - rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST; + rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST; } -static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) +static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) { - struct mwl8k_rxd_8687 *rxd = _rxd; + struct mwl8k_rxd_sta *rxd = _rxd; rxd->pkt_len = cpu_to_le16(len); rxd->pkt_phys_addr = cpu_to_le32(addr); @@ -858,13 +854,13 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) } static int -mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, +mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, __le16 *qos) { - struct mwl8k_rxd_8687 *rxd = _rxd; + struct mwl8k_rxd_sta *rxd = _rxd; u16 rate_info; - if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST)) + if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST)) return -1; rmb(); @@ -874,16 +870,16 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, status->signal = -rxd->rssi; status->noise = -rxd->noise_level; - status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); - status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); + status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); + status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); - if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE) + if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE) status->flag |= RX_FLAG_SHORTPRE; - if (rate_info & MWL8K_8687_RATE_INFO_40MHZ) + if (rate_info & MWL8K_STA_RATE_INFO_40MHZ) status->flag |= RX_FLAG_40MHZ; - if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI) + if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI) status->flag |= RX_FLAG_SHORT_GI; - if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT) + if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) status->flag |= RX_FLAG_HT; status->band = IEEE80211_BAND_2GHZ; @@ -894,11 +890,11 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, return le16_to_cpu(rxd->pkt_len); } -static struct rxd_ops rxd_8687_ops = { - .rxd_size = sizeof(struct mwl8k_rxd_8687), - .rxd_init = mwl8k_rxd_8687_init, - .rxd_refill = mwl8k_rxd_8687_refill, - .rxd_process = mwl8k_rxd_8687_process, +static struct rxd_ops rxd_sta_ops = { + .rxd_size = sizeof(struct mwl8k_rxd_sta), + .rxd_init = mwl8k_rxd_sta_init, + .rxd_refill = mwl8k_rxd_sta_refill, + .rxd_process = mwl8k_rxd_sta_process, }; @@ -3267,15 +3263,12 @@ static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { .part_name = "88w8687", .helper_image = "mwl8k/helper_8687.fw", .fw_image = "mwl8k/fmimage_8687.fw", - .rxd_ops = &rxd_8687_ops, - .modes = BIT(NL80211_IFTYPE_STATION), }, [MWL8366] = { .part_name = "88w8366", .helper_image = "mwl8k/helper_8366.fw", .fw_image = "mwl8k/fmimage_8366.fw", - .rxd_ops = &rxd_8366_ops, - .modes = 0, + .ap_rxd_ops = &rxd_8366_ap_ops, }, }; @@ -3380,7 +3373,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, mwl8k_release_firmware(priv); - priv->rxd_ops = priv->device_info->rxd_ops; + if (priv->ap_fw) + priv->rxd_ops = priv->device_info->ap_rxd_ops; + else + priv->rxd_ops = &rxd_sta_ops; priv->sniffer_enabled = false; priv->wmm_enabled = false; @@ -3409,8 +3405,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->queues = MWL8K_TX_QUEUES; - hw->wiphy->interface_modes = priv->device_info->modes; - /* Set rssi and noise values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); @@ -3480,6 +3474,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_set_hw_spec(hw); } else { rc = mwl8k_cmd_get_hw_spec_sta(hw); + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } if (rc) { printk(KERN_ERR "%s: Cannot initialise firmware\n", -- cgit v1.2.3 From 97474782959af87f5dc8049fca3bd3b25eb68308 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:33:04 +0100 Subject: mwl8k: remove unused mwl8k_vif::priv Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index b20820a015cc..6fa2bde5b618 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -204,9 +204,6 @@ struct mwl8k_priv { /* Per interface specific private data */ struct mwl8k_vif { - /* backpointer to parent config block */ - struct mwl8k_priv *priv; - /* BSS config of AP or IBSS from mac80211*/ struct ieee80211_bss_conf bss_info; @@ -2877,9 +2874,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, mwl8k_cmd_set_mac_addr(hw, conf->mac_addr); memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); - /* Back pointer to parent config block */ - mwl8k_vif->priv = priv; - /* Set Initial sequence number to zero */ mwl8k_vif->seqno = 0; -- cgit v1.2.3 From 7dc6a7a7635365b140af969e972900866d0bf34b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Nov 2009 18:33:09 +0100 Subject: mwl8k: remove duplicate local per-vif copy of ieee80211_bss_conf Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6fa2bde5b618..97a95decf9a8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -204,12 +204,11 @@ struct mwl8k_priv { /* Per interface specific private data */ struct mwl8k_vif { - /* BSS config of AP or IBSS from mac80211*/ - struct ieee80211_bss_conf bss_info; + /* Local MAC address. */ + u8 mac_addr[ETH_ALEN]; - /* BSSID of AP or IBSS */ - u8 bssid[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; + /* BSSID of AP. */ + u8 bssid[ETH_ALEN]; /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; @@ -2123,7 +2122,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; struct mwl8k_cmd_update_set_aid *cmd; u16 prot_mode; int rc; @@ -2134,14 +2132,14 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->aid = cpu_to_le16(info->aid); + cmd->aid = cpu_to_le16(vif->bss_conf.aid); memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); - if (info->use_cts_prot) { + if (vif->bss_conf.use_cts_prot) { prot_mode = MWL8K_FRAME_PROT_11G; } else { - switch (info->ht_operation_mode & + switch (vif->bss_conf.ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION) { case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; @@ -2651,7 +2649,6 @@ static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, struct ieee80211_vif *vif, __u32 action) { struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; struct mwl8k_cmd_update_stadb *cmd; struct peer_capability_info *peer_info; int rc; @@ -2672,7 +2669,8 @@ static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, case MWL8K_STA_DB_MODIFY_ENTRY: /* Build peer_info block */ peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; - peer_info->basic_caps = cpu_to_le16(info->assoc_capability); + peer_info->basic_caps = + cpu_to_le16(vif->bss_conf.assoc_capability); memcpy(peer_info->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); peer_info->interop = 1; @@ -2960,11 +2958,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, if (rc) return; - if (info->assoc) { - memcpy(&mwl8k_vif->bss_info, info, - sizeof(struct ieee80211_bss_conf)); - - memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); + if (vif->bss_conf.assoc) { + memcpy(mwl8k_vif->bssid, vif->bss_conf.bssid, ETH_ALEN); /* Install rates */ rc = mwl8k_cmd_set_rate(hw, vif); @@ -2978,12 +2973,13 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, goto out; /* Set radio preamble */ - rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); + rc = mwl8k_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); if (rc) goto out; /* Set slot time */ - rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); + rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); if (rc) goto out; @@ -3006,8 +3002,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, priv->capture_beacon = true; } else { rc = mwl8k_cmd_update_stadb(hw, vif, MWL8K_STA_DB_DEL_ENTRY); - memset(&mwl8k_vif->bss_info, 0, - sizeof(struct ieee80211_bss_conf)); memset(mwl8k_vif->bssid, 0, ETH_ALEN); } @@ -3239,9 +3233,9 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) struct mwl8k_priv *priv = container_of(work, struct mwl8k_priv, finalize_join_worker); struct sk_buff *skb = priv->beacon_skb; - u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; - mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim); + mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, + priv->vif->bss_conf.dtim_period); dev_kfree_skb(skb); priv->beacon_skb = NULL; -- cgit v1.2.3 From b02914af4d7020828ce921a572589dd793517c09 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 10 Dec 2009 17:35:01 -0600 Subject: b43: Allow PIO mode to be selected at module load If userencounter the "Fatal DMA Problem" with a BCM43XX device, and still wish to use b43 as the driver, their only option is to rebuild the kernel with CONFIG_B43_FORCE_PIO. This patch removes this option and allows PIO mode to be selected with a load-time parameter for the module. Note that the configuration variable CONFIG_B43_PIO is also removed. Once the DMA problem with the BCM4312 devices is solved, this patch will likely be reverted. Signed-off-by: Larry Finger Tested-by: John Daiker Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 17 +---------------- drivers/net/wireless/b43/Makefile | 2 +- drivers/net/wireless/b43/b43.h | 13 ------------- drivers/net/wireless/b43/dma.c | 2 -- drivers/net/wireless/b43/main.c | 9 ++++++--- drivers/net/wireless/b43/pio.h | 40 --------------------------------------- 6 files changed, 8 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64c12e1bced3..073be566d05e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -3,6 +3,7 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && HAS_DMA select SSB select FW_LOADER + select SSB_BLOCKIO ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -78,14 +79,6 @@ config B43_SDIO If unsure, say N. -# Data transfers to the device via PIO -# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. -config B43_PIO - bool - depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) - select SSB_BLOCKIO - default y - config B43_NPHY bool "Pre IEEE 802.11n support (BROKEN)" depends on B43 && EXPERIMENTAL && BROKEN @@ -137,12 +130,4 @@ config B43_DEBUG for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. -config B43_FORCE_PIO - bool "Force usage of PIO instead of DMA" - depends on B43 && B43_DEBUG - ---help--- - This will disable DMA and always enable PIO instead. - Say N! - This is only for debugging the PIO engine code. You do - _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 84772a2542dc..5e83b6f0a3a0 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -12,7 +12,7 @@ b43-y += xmit.o b43-y += lo.o b43-y += wa.o b43-y += dma.o -b43-$(CONFIG_B43_PIO) += pio.o +b43-y += pio.o b43-y += rfkill.o b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fe3bf9491997..2f12a750bc98 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -821,11 +821,9 @@ struct b43_wl { /* The device LEDs. */ struct b43_leds leds; -#ifdef CONFIG_B43_PIO /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ u8 pio_scratchspace[110] __attribute__((__aligned__(8))); u8 pio_tailspace[4] __attribute__((__aligned__(8))); -#endif /* CONFIG_B43_PIO */ }; static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) @@ -876,20 +874,9 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) static inline bool b43_using_pio_transfers(struct b43_wldev *dev) { -#ifdef CONFIG_B43_PIO return dev->__using_pio_transfers; -#else - return 0; -#endif } -#ifdef CONFIG_B43_FORCE_PIO -# define B43_FORCE_PIO 1 -#else -# define B43_FORCE_PIO 0 -#endif - - /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 027be275e035..5dd8a210ac21 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1760,7 +1760,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev) b43_power_saving_ctl_bits(dev, 0); } -#ifdef CONFIG_B43_PIO static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, u16 mmio_base, bool enable) { @@ -1794,4 +1793,3 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev, mmio_base = b43_dmacontroller_base(type, engine_index); direct_fifo_rx(dev, type, mmio_base, enable); } -#endif /* CONFIG_B43_PIO */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 19b4eae47b59..b0b5ce950008 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -102,6 +102,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); +static int modparam_pio; +module_param_named(pio, modparam_pio, int, 0444); +MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -1786,8 +1789,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) dma_reason[4], dma_reason[5]); b43err(dev->wl, "This device does not support DMA " "on your system. Please use PIO instead.\n"); - b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in " - "your kernel configuration.\n"); + b43err(dev->wl, "Unload the b43 module and reload " + "with 'pio=1'\n"); return; } if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { @@ -4353,7 +4356,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - B43_FORCE_PIO) { + modparam_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index 7dd649c9ddad..7b3c42f93a16 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h @@ -55,8 +55,6 @@ #define B43_PIO_MAX_NR_TXPACKETS 32 -#ifdef CONFIG_B43_PIO - struct b43_pio_txpacket { /* Pointer to the TX queue we belong to. */ struct b43_pio_txqueue *queue; @@ -169,42 +167,4 @@ void b43_pio_rx(struct b43_pio_rxqueue *q); void b43_pio_tx_suspend(struct b43_wldev *dev); void b43_pio_tx_resume(struct b43_wldev *dev); - -#else /* CONFIG_B43_PIO */ - - -static inline int b43_pio_init(struct b43_wldev *dev) -{ - return 0; -} -static inline void b43_pio_free(struct b43_wldev *dev) -{ -} -static inline void b43_pio_stop(struct b43_wldev *dev) -{ -} -static inline int b43_pio_tx(struct b43_wldev *dev, - struct sk_buff *skb) -{ - return 0; -} -static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ -} -static inline void b43_pio_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline void b43_pio_rx(struct b43_pio_rxqueue *q) -{ -} -static inline void b43_pio_tx_suspend(struct b43_wldev *dev) -{ -} -static inline void b43_pio_tx_resume(struct b43_wldev *dev) -{ -} - -#endif /* CONFIG_B43_PIO */ #endif /* B43_PIO_H_ */ -- cgit v1.2.3 From 937a67e75a93b63f0b5d33612901906b8eb2a688 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:40 +0200 Subject: wl1271: updated radio parameters structure for newer firmwares In revision 6.1.0.0.288 the radio parameters structure has changed. This patch updates the driver code accordingly. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index b4fa4acb9229..de23c08738a0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -458,11 +458,12 @@ struct wl1271_radio_parms_cmd { /* Dynamic radio parameters */ /* 2.4GHz */ __le16 tx_ref_pd_voltage; - s8 tx_ref_power; + u8 tx_ref_power; s8 tx_offset_db; s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; + s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; @@ -471,15 +472,19 @@ struct wl1271_radio_parms_cmd { u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; u8 rx_fem_insertion_loss; - u8 padding2; + u8 degraded_low_to_normal_threshold; + u8 degraded_normal_to_high_threshold; + + u8 padding1; /* our own padding, not in ref driver */ /* 5GHz */ __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; + u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; + s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; @@ -488,7 +493,10 @@ struct wl1271_radio_parms_cmd { s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - u8 padding3[2]; + u8 degraded_low_to_normal_threshold_5; + u8 degraded_normal_to_high_threshold_5; + + u8 padding2[2]; } __attribute__ ((packed)); struct wl1271_cmd_cal_channel_tune { -- cgit v1.2.3 From 76c0f8d396bd306111d349cfe770e1c4fcf70248 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:41 +0200 Subject: wl1271: updated general parameters structure for newer firmwares In revision 6.1.0.0.288 the general parameters structure has changed. This patch updates the driver code accordingly. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 20 ++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_cmd.h | 15 +++++++++++++++ drivers/net/wireless/wl12xx/wl1271_conf.h | 17 +++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 13 +++++++++++++ 4 files changed, 65 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 886a9bc39cc1..fe9b187f476e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -209,6 +209,26 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; gen_parms->settings = g->settings; + gen_parms->sr_state = g->sr_state; + + memcpy(gen_parms->srf1, + g->srf1, + CONF_MAX_SMART_REFLEX_PARAMS); + memcpy(gen_parms->srf2, + g->srf2, + CONF_MAX_SMART_REFLEX_PARAMS); + memcpy(gen_parms->srf3, + g->srf3, + CONF_MAX_SMART_REFLEX_PARAMS); + memcpy(gen_parms->sr_debug_table, + g->sr_debug_table, + CONF_MAX_SMART_REFLEX_PARAMS); + + gen_parms->sr_sen_n_p = g->sr_sen_n_p; + gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; + gen_parms->sr_sen_nrn = g->sr_sen_nrn; + gen_parms->sr_sen_prn = g->sr_sen_prn; + ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); if (ret < 0) wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index de23c08738a0..057f925db2aa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd { u8 tx_bip_fem_autodetect; u8 tx_bip_fem_manufacturer; u8 settings; + + u8 sr_state; + + s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; + s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; + s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; + + s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; + + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; + + u8 padding[3]; } __attribute__ ((packed)); struct wl1271_radio_parms_cmd { diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede265..5e36cd90d0c6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -759,6 +759,9 @@ enum single_dual_band_enum { CONF_DUAL_BAND }; + +#define CONF_MAX_SMART_REFLEX_PARAMS 16 + struct conf_general_parms { /* * RF Reference Clock type / speed @@ -815,6 +818,20 @@ struct conf_general_parms { * Range: Unknown */ u8 settings; + + /* Smart reflex settings */ + u8 sr_state; + + s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; + s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; + s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; + + s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; + + u8 sr_sen_n_p; + u8 sr_sen_n_p_gain; + u8 sr_sen_nrn; + u8 sr_sen_prn; }; #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42fe..7ab45c446ab8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -259,6 +259,19 @@ static struct conf_drv_settings default_conf = { .tx_bip_fem_autodetect = 0, .tx_bip_fem_manufacturer = 1, .settings = 1, + .sr_state = 1, + .srf1 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf2 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf3 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .sr_sen_n_p = 0, + .sr_sen_n_p_gain = 0, + .sr_sen_nrn = 0, + .sr_sen_prn = 0, }, .radioparam = { .rx_trace_loss = 10, -- cgit v1.2.3 From a3e84847b042f10262f8ef66db66a0e527a00cff Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:42 +0200 Subject: wl1271: update radio and general parameters values There were some changes in the values we have to use for these settings. This patches updates them. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7ab45c446ab8..1d5b73ca23b7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -256,7 +256,7 @@ static struct conf_drv_settings default_conf = { .clk_valid_on_wakeup = 0, .dc2dcmode = 0, .single_dual_band = CONF_SINGLE_BAND, - .tx_bip_fem_autodetect = 0, + .tx_bip_fem_autodetect = 1, .tx_bip_fem_manufacturer = 1, .settings = 1, .sr_state = 1, @@ -274,8 +274,8 @@ static struct conf_drv_settings default_conf = { .sr_sen_prn = 0, }, .radioparam = { - .rx_trace_loss = 10, - .tx_trace_loss = 10, + .rx_trace_loss = 0x24, + .tx_trace_loss = 0x0, .rx_rssi_and_proc_compens = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, @@ -286,13 +286,13 @@ static struct conf_drv_settings default_conf = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - .tx_ref_pd_voltage = 0x24e, - .tx_ref_power = 0x78, + .tx_ref_pd_voltage = 0x1a9, + .tx_ref_power = 0x80, .tx_offset_db = 0x0, .tx_rate_limits_normal = { - 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, + 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, .tx_rate_limits_degraded = { - 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, + 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, .tx_channel_limits_11b = { 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, @@ -302,10 +302,10 @@ static struct conf_drv_settings default_conf = { 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, 0x20, 0x50 }, .tx_pdv_rate_offsets = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, .tx_ibias = { - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, - .rx_fem_insertion_loss = 0x14, + 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, + .rx_fem_insertion_loss = 0x0e, .tx_ref_pd_voltage_5 = { 0x0190, 0x01a4, 0x01c3, 0x01d8, 0x020a, 0x021c }, -- cgit v1.2.3 From cf18be4467b5aca1ccf3b5a72b67fc33a0b30c59 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:43 +0200 Subject: wl1271: added radio parameters configuration values newer firmwares Add new radio parameters for new structures based on firmware revision 6.1.0.0.288. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 13 +++++++++++++ drivers/net/wireless/wl12xx/wl1271_conf.h | 17 +++++++++++++---- drivers/net/wireless/wl12xx/wl1271_main.c | 10 +++++++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index fe9b187f476e..57c21454e543 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -273,6 +273,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) CONF_NUMBER_OF_RATE_GROUPS); memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, CONF_NUMBER_OF_RATE_GROUPS); + memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, + CONF_NUMBER_OF_RATE_GROUPS); memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, CONF_NUMBER_OF_CHANNELS_2_4); @@ -283,6 +285,11 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; + radio_parms->degraded_low_to_normal_threshold = + r->degraded_low_to_normal_threshold; + radio_parms->degraded_normal_to_high_threshold = + r->degraded_normal_to_high_threshold; + for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) radio_parms->tx_ref_pd_voltage_5[i] = @@ -295,6 +302,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); memcpy(radio_parms->tx_rate_limits_degraded_5, r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); + memcpy(radio_parms->tx_rate_limits_extreme_5, + r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); memcpy(radio_parms->tx_channel_limits_ofdm_5, r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, @@ -303,6 +312,10 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) CONF_NUMBER_OF_RATE_GROUPS); memcpy(radio_parms->rx_fem_insertion_loss_5, r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); + radio_parms->degraded_low_to_normal_threshold_5 = + r->degraded_low_to_normal_threshold_5; + radio_parms->degraded_normal_to_high_threshold_5 = + r->degraded_normal_to_high_threshold_5; wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", radio_parms, sizeof(*radio_parms)); diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 5e36cd90d0c6..a4bd35b0f9fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -864,12 +864,13 @@ struct conf_radio_parms { * * Range: unknown */ - s16 tx_ref_pd_voltage; - s8 tx_ref_power; + u16 tx_ref_pd_voltage; + u8 tx_ref_power; s8 tx_offset_db; s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; + s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; @@ -878,17 +879,22 @@ struct conf_radio_parms { u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; u8 rx_fem_insertion_loss; + u8 degraded_low_to_normal_threshold; + u8 degraded_normal_to_high_threshold; + + /* * Dynamic radio parameters for 5GHz * * Range: unknown */ - s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; + u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; + u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; + s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; @@ -896,6 +902,9 @@ struct conf_radio_parms { /* FIXME: this is inconsistent with the types for 2.4GHz */ s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; + + u8 degraded_low_to_normal_threshold_5; + u8 degraded_normal_to_high_threshold_5; }; #define CONF_SR_ERR_TBL_COUNT 3 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 1d5b73ca23b7..f1cb7cbd7c1c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -293,6 +293,8 @@ static struct conf_drv_settings default_conf = { 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, .tx_rate_limits_degraded = { 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, + .tx_rate_limits_extreme = { + 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, .tx_channel_limits_11b = { 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, @@ -306,6 +308,8 @@ static struct conf_drv_settings default_conf = { .tx_ibias = { 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, .rx_fem_insertion_loss = 0x0e, + .degraded_low_to_normal_threshold = 0x1e, + .degraded_normal_to_high_threshold = 0x2d, .tx_ref_pd_voltage_5 = { 0x0190, 0x01a4, 0x01c3, 0x01d8, 0x020a, 0x021c }, @@ -317,6 +321,8 @@ static struct conf_drv_settings default_conf = { 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, .tx_rate_limits_degraded_5 = { 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, + .tx_rate_limits_extreme_5 = { + 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, .tx_channel_limits_ofdm_5 = { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, @@ -328,7 +334,9 @@ static struct conf_drv_settings default_conf = { .tx_ibias_5 = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, .rx_fem_insertion_loss_5 = { - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, + .degraded_low_to_normal_threshold_5 = 0x00, + .degraded_normal_to_high_threshold_5 = 0x00 } } }; -- cgit v1.2.3 From c7f43e451ba40e66a89d51e63bc21a57824592f2 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:44 +0200 Subject: wl1271: use join command with dummy BSSID When we need to change the channel before association, we have to send a join command with a valid BSSID. With this patch we use 0baddeadbeef as the BSSID. There are ongoing discussions with TI to get this done in a cleaner way. When we go back to idle, we issue a CMD_DISCONNECT to make sure the firmware stops listening to the channel and cleans things up internally. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 75 ++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f1cb7cbd7c1c..f6d42e613a56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1130,6 +1130,47 @@ out: } #endif +static int wl1271_join_channel(struct wl1271 *wl, int channel) +{ + int ret; + /* we need to use a dummy BSSID for now */ + static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, + 0xad, 0xbe, 0xef }; + + /* disable mac filter, so we hear everything */ + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + + wl->channel = channel; + memcpy(wl->bssid, dummy_bssid, ETH_ALEN); + + ret = wl1271_cmd_join(wl); + if (ret < 0) + goto out; + + wl->joined = true; + +out: + return ret; +} + +static int wl1271_unjoin_channel(struct wl1271 *wl) +{ + int ret; + + /* to stop listening to a channel, we disconnect */ + ret = wl1271_cmd_disconnect(wl); + if (ret < 0) + goto out; + + wl->joined = false; + wl->channel = 0; + memset(wl->bssid, 0, ETH_ALEN); + wl->rx_config = WL1271_DEFAULT_RX_CONFIG; + +out: + return ret; +} + static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; @@ -1138,10 +1179,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", + wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", channel, conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level); + conf->power_level, + conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); mutex_lock(&wl->mutex); @@ -1151,16 +1193,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (ret < 0) goto out; - if (channel != wl->channel) { - /* - * We assume that the stack will configure the right channel - * before associating, so we don't need to send a join - * command here. We will join the right channel when the - * BSSID changes - */ - wl->channel = channel; + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (conf->flags & IEEE80211_CONF_IDLE && wl->joined) + wl1271_unjoin_channel(wl); + else + wl1271_join_channel(wl, channel); } + /* if the channel changes while joined, join again */ + if (channel != wl->channel && wl->joined) + wl1271_join_channel(wl, channel); + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { wl1271_info("psm enabled"); @@ -1494,6 +1537,18 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; + if ((changed & BSS_CHANGED_BSSID) && + /* + * Now we know the correct bssid, so we send a new join command + * and enable the BSSID filter + */ + memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + wl1271_cmd_join(wl); + wl->joined = true; + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; -- cgit v1.2.3 From 9cf25fed6a3b1c0792cbab3e934a4e2b6736d284 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:45 +0200 Subject: wl1271: remove workaround for disconnection Now we're using a the idle information coming from mac80211 to decide when to disconnect. If we have joined (ie. we're listening to a channel), whenever the interface goes to idle, we will issue a disconnect command. So the workaround to send a disconnect command before joining is not needed anymore. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 57c21454e543..ceb1ca63c43a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -344,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl) do_cal = false; } - /* FIXME: This is a workaround, because with the current stack, we - * cannot know when we have disassociated. So, if we have already - * joined, we disconnect before joining again. */ - if (wl->joined) { - ret = wl1271_cmd_disconnect(wl); - if (ret < 0) { - wl1271_error("failed to disconnect before rejoining"); - goto out; - } - - wl->joined = false; - } - join = kzalloc(sizeof(*join), GFP_KERNEL); if (!join) { ret = -ENOMEM; @@ -421,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl) goto out_free; } - wl->joined = true; - /* * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to * simplify locking we just sleep instead, for now -- cgit v1.2.3 From a2d0e3f13037fa7dc4094c47e0378800a064ee26 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:46 +0200 Subject: wl1271: limit TX power to 25dBm for every channel The wl1271 firmware supports maximun 25.5dBm, so the driver was returning -EINVALID to anything above that. This patch uses the channel max_power option to limit the TX power to 25dBm. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f6d42e613a56..7f164e532211 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1675,19 +1675,19 @@ static struct ieee80211_rate wl1271_rates[] = { /* can't be const, mac80211 writes to this */ static struct ieee80211_channel wl1271_channels[] = { - { .hw_value = 1, .center_freq = 2412}, - { .hw_value = 2, .center_freq = 2417}, - { .hw_value = 3, .center_freq = 2422}, - { .hw_value = 4, .center_freq = 2427}, - { .hw_value = 5, .center_freq = 2432}, - { .hw_value = 6, .center_freq = 2437}, - { .hw_value = 7, .center_freq = 2442}, - { .hw_value = 8, .center_freq = 2447}, - { .hw_value = 9, .center_freq = 2452}, - { .hw_value = 10, .center_freq = 2457}, - { .hw_value = 11, .center_freq = 2462}, - { .hw_value = 12, .center_freq = 2467}, - { .hw_value = 13, .center_freq = 2472}, + { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, + { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, + { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, + { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, + { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, + { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, + { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, + { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, + { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, + { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, + { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, + { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, + { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, }; /* can't be const, mac80211 writes to this */ -- cgit v1.2.3 From cd264769f7a571fc2a61765757ed85c56f02e9d3 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:47 +0200 Subject: wl1271: check result code from the join command We were not checking the return value from the call to wl1271_cmd_join(). Added a check to make things more reliable. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7f164e532211..bf1d0fd93bcc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1545,7 +1545,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { wl->rx_config |= CFG_BSSID_FILTER_EN; memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - wl1271_cmd_join(wl); + ret = wl1271_cmd_join(wl); + if (ret < 0) { + wl1271_warning("cmd join failed %d", ret); + goto out_sleep; + } wl->joined = true; } -- cgit v1.2.3 From bdcbbb947be9778f740797a2bfc69c44a0d54776 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:48 +0200 Subject: wl1271: set null data template when BSSID is known The call to wl1271_cmd_build_null_data() was missing when we got associated, this was causing PS to fail. This patch adds the call and now PS seems to work. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index bf1d0fd93bcc..64f8623e0325 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1545,6 +1545,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { wl->rx_config |= CFG_BSSID_FILTER_EN; memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + ret = wl1271_cmd_build_null_data(wl); + if (ret < 0) { + wl1271_warning("cmd buld null data failed %d", + ret); + goto out_sleep; + } ret = wl1271_cmd_join(wl); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); -- cgit v1.2.3 From ac9b40fac6983ab30e8b5019a5d2abda200c89d5 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:49 +0200 Subject: wl1271: use the correct macro when setting the basic rates We were using CONF_TX_RATE_MASK_ALL when calling wl1271_acx_rate_policies() during init. We should use WL1271_DEFAULT_BASIC_RATE_SET instead. The values are the same, but the latter is just the correct macro to use. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 11249b436cf1..d72ccc68b855 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -280,7 +280,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Configure TX rate classes */ - ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); + ret = wl1271_acx_rate_policies(wl, WL1271_DEFAULT_BASIC_RATE_SET); if (ret < 0) goto out_free_memmap; -- cgit v1.2.3 From 6e92b416b0aa6a59629cc32ee2b27129d73b98b8 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:50 +0200 Subject: wl1271: implement dco itrim parameters setting Newer firmwares require the dco itrim parameters to be set during initialization. This patch implements the new ACX function and calls it. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 29 +++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_acx.h | 10 ++++++++++ drivers/net/wireless/wl12xx/wl1271_conf.h | 9 +++++++++ drivers/net/wireless/wl12xx/wl1271_init.c | 4 ++++ drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++ 5 files changed, 56 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7a..a38a967ba78a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -390,6 +390,35 @@ out: return ret; } +int wl1271_acx_dco_itrim_params(struct wl1271 *wl) +{ + struct acx_dco_itrim_params *dco; + struct conf_itrim_settings *c = &wl->conf.itrim; + int ret; + + wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); + + dco = kzalloc(sizeof(*dco), GFP_KERNEL); + if (!dco) { + ret = -ENOMEM; + goto out; + } + + dco->enable = c->enable; + dco->timeout = cpu_to_le32(c->timeout); + + ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, + dco, sizeof(*dco)); + if (ret < 0) { + wl1271_warning("failed to set dco itrim parameters: %d", ret); + goto out; + } + +out: + kfree(dco); + return ret; +} + int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) { struct acx_beacon_filter_option *beacon_filter = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 2ce0a8128542..fa5d9539440d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -434,6 +434,14 @@ struct acx_smart_reflex_config_params { struct smart_reflex_err_table error_table[3]; } __attribute__ ((packed)); +struct acx_dco_itrim_params { + struct acx_header header; + + u8 enable; + u8 padding[3]; + __le32 timeout; +} __attribute__ ((packed)); + #define PTA_ANTENNA_TYPE_DEF (0) #define PTA_BT_HP_MAXTIME_DEF (2000) #define PTA_WLAN_HP_MAX_TIME_DEF (5000) @@ -1029,6 +1037,7 @@ enum { ACX_SET_SMART_REFLEX_DEBUG = 0x005A, ACX_SET_SMART_REFLEX_STATE = 0x005B, ACX_SET_SMART_REFLEX_PARAMS = 0x005F, + ACX_SET_DCO_ITRIM_PARAMS = 0x0061, DOT11_RX_MSDU_LIFE_TIME = 0x1004, DOT11_CUR_TX_PWR = 0x100D, DOT11_RX_DOT11_MODE = 0x1012, @@ -1056,6 +1065,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, void *mc_list, u32 mc_list_len); int wl1271_acx_service_period_timeout(struct wl1271 *wl); int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); +int wl1271_acx_dco_itrim_params(struct wl1271 *wl); int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); int wl1271_acx_beacon_filter_table(struct wl1271 *wl); int wl1271_acx_conn_monit_params(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index a4bd35b0f9fd..905d4287915b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -934,12 +934,21 @@ struct conf_init_settings { }; +struct conf_itrim_settings { + /* enable dco itrim */ + u8 enable; + + /* moderation timeout in microsecs from the last TX */ + u32 timeout; +}; + struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; struct conf_tx_settings tx; struct conf_conn_settings conn; struct conf_init_settings init; + struct conf_itrim_settings itrim; }; #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index d72ccc68b855..39f01d875703 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + ret = wl1271_acx_dco_itrim_params(wl); + if (ret < 0) + goto out_free_memmap; + /* Initialize connection monitoring thresholds */ ret = wl1271_acx_conn_monit_params(wl); if (ret < 0) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 64f8623e0325..8c44f4cd688d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -338,6 +338,10 @@ static struct conf_drv_settings default_conf = { .degraded_low_to_normal_threshold_5 = 0x00, .degraded_normal_to_high_threshold_5 = 0x00 } + }, + .itrim = { + .enable = false, + .timeout = 50000, } }; -- cgit v1.2.3 From 1b38ea8858fd169064683e27add43511308e521a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:51 +0200 Subject: wl1271: fix one typo in the rx_rssi_and_proc_compens values There was a typo in one of the values in the rx_rssi_and_proc_compens elemt of the Radio Parameters struct. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 8c44f4cd688d..147aab222354 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -278,7 +278,7 @@ static struct conf_drv_settings default_conf = { .tx_trace_loss = 0x0, .rx_rssi_and_proc_compens = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, - 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, + 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 }, .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, -- cgit v1.2.3 From 98b2a68473ae975bc4abdeb66cd719ccfdad9d4a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:52 +0200 Subject: wl1271: add gpio_power file in debugfs to power the chip on and off Some debugging tools require the chip to be powered on before they can work. With these tools, we shouldn't upload the firmware nor boot the firmware ourselves, so this debufs file is provided. It always contains the gpio power setting (0 = off, 1 = on). To change the power setting, just write 0 or 1 to the file. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 3 ++ drivers/net/wireless/wl12xx/wl1271_debugfs.c | 55 ++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++ 3 files changed, 61 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861f..3bec6f3b1c7f 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -276,6 +276,7 @@ struct wl1271_debugfs { struct dentry *retry_count; struct dentry *excessive_retries; + struct dentry *gpio_power; }; #define NUM_TX_QUEUES 4 @@ -442,6 +443,8 @@ struct wl1271 { struct conf_drv_settings conf; struct list_head list; + + bool gpio_power; }; int wl1271_plt_start(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index c1805e5f8964..4eaf40c57567 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c @@ -237,6 +237,57 @@ static const struct file_operations tx_queue_len_ops = { .open = wl1271_open_file_generic, }; +static ssize_t gpio_power_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + int res; + char buf[10]; + + res = scnprintf(buf, sizeof(buf), "%d\n", wl->gpio_power); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static ssize_t gpio_power_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct wl1271 *wl = file->private_data; + char buf[10]; + size_t len; + unsigned long value; + int ret; + + mutex_lock(&wl->mutex); + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) { + ret = -EFAULT; + goto out; + } + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &value); + if (ret < 0) { + wl1271_warning("illegal value in gpio_power"); + goto out; + } + + wl->set_power(!!value); + wl->gpio_power = !!value; + +out: + mutex_unlock(&wl->mutex); + return count; +} + +static const struct file_operations gpio_power_ops = { + .read = gpio_power_read, + .write = gpio_power_write, + .open = wl1271_open_file_generic +}; + static void wl1271_debugfs_delete_files(struct wl1271 *wl) { DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); @@ -333,6 +384,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl) DEBUGFS_DEL(tx_queue_len); DEBUGFS_DEL(retry_count); DEBUGFS_DEL(excessive_retries); + + DEBUGFS_DEL(gpio_power); } static int wl1271_debugfs_add_files(struct wl1271 *wl) @@ -434,6 +487,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); + DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); + out: if (ret < 0) wl1271_debugfs_delete_files(wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 147aab222354..b33bdcc1eb4e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -399,11 +399,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) static void wl1271_power_off(struct wl1271 *wl) { wl->set_power(false); + wl->gpio_power = false; } static void wl1271_power_on(struct wl1271 *wl) { wl->set_power(true); + wl->gpio_power = true; } static void wl1271_fw_status(struct wl1271 *wl, @@ -1923,6 +1925,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; + wl->gpio_power = false; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; -- cgit v1.2.3 From 8cf5e8e509950237fa0982235a703348d8b6e670 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:53 +0200 Subject: wl1271: upload only the first 468 bytes from the NVS file We were uploading the whole NVS file, but that is wrong, because the same file also contains the initialization values. For the latest firmwares, we should upload only the initial 468 bytes from the file. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_boot.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 3bec6f3b1c7f..8dfc9ec9590d 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -111,6 +111,7 @@ enum { #define WL1271_FW_NAME "wl1271-fw.bin" #define WL1271_NVS_NAME "wl1271-nvs.bin" +#define WL1271_NVS_LEN 468 /* * Enable/disable 802.11a support for WL1273 diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca3..e803b876f3f0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) if (nvs == NULL) return -ENODEV; + if (wl->nvs_len < WL1271_NVS_LEN) + return -EINVAL; + nvs_ptr = nvs; - nvs_len = wl->nvs_len; + /* only the first part of the NVS needs to be uploaded */ + nvs_len = WL1271_NVS_LEN; + + /* FIXME: read init settings from the remaining part of the NVS */ /* Update the device MAC address into the nvs */ nvs[11] = wl->mac_addr[0]; -- cgit v1.2.3 From 3ed8f2c61466f10d99585365fd2aaafaf2d4c949 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:54 +0200 Subject: wl1271: some new configuration values according to new reference In the new reference driver, some of the firmware configuration values have been changed. This patch changes them in the wl1271 driver accordingly. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.h | 4 ++-- drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index fa5d9539440d..dcd64b7919eb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -885,8 +885,8 @@ struct acx_tx_config_options { __le16 tx_compl_threshold; /* number of packets */ } __attribute__ ((packed)); -#define ACX_RX_MEM_BLOCKS 64 -#define ACX_TX_MIN_MEM_BLOCKS 64 +#define ACX_RX_MEM_BLOCKS 70 +#define ACX_TX_MIN_MEM_BLOCKS 40 #define ACX_TX_DESCRIPTORS 32 #define ACX_NUM_SSID_PROFILES 1 diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b33bdcc1eb4e..fb2221749f7b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -67,10 +67,10 @@ static struct conf_drv_settings default_conf = { .ps_poll_timeout = 15, .upsd_timeout = 15, .rts_threshold = 2347, - .rx_cca_threshold = 0xFFEF, - .irq_blk_threshold = 0, - .irq_pkt_threshold = USHORT_MAX, - .irq_timeout = 5, + .rx_cca_threshold = 0, + .irq_blk_threshold = 0xFFFF, + .irq_pkt_threshold = 0, + .irq_timeout = 600, .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, }, .tx = { @@ -172,8 +172,8 @@ static struct conf_drv_settings default_conf = { } }, .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, - .tx_compl_timeout = 5, - .tx_compl_threshold = 5 + .tx_compl_timeout = 700, + .tx_compl_threshold = 4 }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, @@ -186,12 +186,12 @@ static struct conf_drv_settings default_conf = { .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, } }, - .synch_fail_thold = 5, + .synch_fail_thold = 10, .bss_lose_timeout = 100, .beacon_rx_timeout = 10000, .broadcast_timeout = 20000, .rx_broadcast_in_ps = 1, - .ps_poll_threshold = 4, + .ps_poll_threshold = 20, .sig_trigger_count = 2, .sig_trigger = { [0] = { -- cgit v1.2.3 From 94210897e2b7df8446fdecd360342149e5b4a400 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:55 +0200 Subject: wl1271: use channel 1 when configuring the data path In the data path configuration, one of the parameters is the channel. We have been setting it to wl->channel, which is not correct in this case. This channel has nothing to do with the channel we're currently tuned to, since it is only used for calibration during this phase. Hardcoded the channel to 1, according to the reference driver. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 13 +++++++------ drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index ceb1ca63c43a..20f3e67c8e48 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -505,7 +505,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) return 0; } -int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) +int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) { struct cmd_enabledisable_path *cmd; int ret; @@ -519,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) goto out; } - cmd->channel = channel; + /* the channel here is only used for calibration, so hardcoded to 1 */ + cmd->channel = 1; if (enable) { cmd_rx = CMD_ENABLE_RX; @@ -532,22 +533,22 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("rx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); + enable ? "start" : "stop", cmd->channel); goto out; } wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", - enable ? "start" : "stop", channel); + enable ? "start" : "stop", cmd->channel); ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("tx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); + enable ? "start" : "stop", cmd->channel); return ret; } wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", - enable ? "start" : "stop", channel); + enable ? "start" : "stop", cmd->channel); out: kfree(cmd); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 057f925db2aa..09fe91297acf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -37,7 +37,7 @@ int wl1271_cmd_join(struct wl1271 *wl); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); -int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); +int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 39f01d875703..bdd4a968b37d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -289,7 +289,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Enable data path */ - ret = wl1271_cmd_data_path(wl, wl->channel, 1); + ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index fb2221749f7b..55a45d339184 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -384,7 +384,7 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_cmd_data_path(wl, wl->channel, 1); + ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) return ret; -- cgit v1.2.3 From 149e38789f3fea74b581f8ebb7eb947d3c6d8a4e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:56 +0200 Subject: wl1271: Configure smart-reflex paramter values. Configure correct values to be used with the smart-reflex configuration of the firmware. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 55a45d339184..b0f4c6efa415 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -260,12 +260,12 @@ static struct conf_drv_settings default_conf = { .tx_bip_fem_manufacturer = 1, .settings = 1, .sr_state = 1, - .srf1 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf2 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf3 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, .sr_sen_n_p = 0, -- cgit v1.2.3 From 018b171c40b613da867e054f9b6b258ae9298133 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:57 +0200 Subject: wl1271: Remove smart reflex ACX Remove the smart-reflex ACX - the associated parameters are now configured in the radio parameters config. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 53 ------------------------------- drivers/net/wireless/wl12xx/wl1271_acx.h | 21 ------------ drivers/net/wireless/wl12xx/wl1271_conf.h | 39 ----------------------- drivers/net/wireless/wl12xx/wl1271_init.c | 5 --- drivers/net/wireless/wl12xx/wl1271_main.c | 24 -------------- 5 files changed, 142 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index a38a967ba78a..ea6427ad1bcb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -1041,59 +1041,6 @@ out: return ret; } -int wl1271_acx_smart_reflex(struct wl1271 *wl) -{ - struct acx_smart_reflex_state *sr_state = NULL; - struct acx_smart_reflex_config_params *sr_param = NULL; - int i, ret; - - wl1271_debug(DEBUG_ACX, "acx smart reflex"); - - sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); - if (!sr_param) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { - struct conf_mart_reflex_err_table *e = - &(wl->conf.init.sr_err_tbl[i]); - - sr_param->error_table[i].len = e->len; - sr_param->error_table[i].upper_limit = e->upper_limit; - memcpy(sr_param->error_table[i].values, e->values, e->len); - } - - ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, - sr_param, sizeof(*sr_param)); - if (ret < 0) { - wl1271_warning("failed to set smart reflex params: %d", ret); - goto out; - } - - sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); - if (!sr_state) { - ret = -ENOMEM; - goto out; - } - - /* enable smart reflex */ - sr_state->enable = wl->conf.init.sr_enable; - - ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, - sr_state, sizeof(*sr_state)); - if (ret < 0) { - wl1271_warning("failed to set smart reflex params: %d", ret); - goto out; - } - -out: - kfree(sr_state); - kfree(sr_param); - return ret; - -} - int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) { struct wl1271_acx_bet_enable *acx = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index dcd64b7919eb..6640ebfb6162 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -415,25 +415,6 @@ struct acx_bt_wlan_coex { u8 pad[3]; } __attribute__ ((packed)); -struct acx_smart_reflex_state { - struct acx_header header; - - u8 enable; - u8 padding[3]; -} __attribute__ ((packed)); - -struct smart_reflex_err_table { - u8 len; - s8 upper_limit; - s8 values[14]; -} __attribute__ ((packed)); - -struct acx_smart_reflex_config_params { - struct acx_header header; - - struct smart_reflex_err_table error_table[3]; -} __attribute__ ((packed)); - struct acx_dco_itrim_params { struct acx_header header; @@ -1035,8 +1016,6 @@ enum { ACX_HT_BSS_OPERATION = 0x0058, ACX_COEX_ACTIVITY = 0x0059, ACX_SET_SMART_REFLEX_DEBUG = 0x005A, - ACX_SET_SMART_REFLEX_STATE = 0x005B, - ACX_SET_SMART_REFLEX_PARAMS = 0x005F, ACX_SET_DCO_ITRIM_PARAMS = 0x0061, DOT11_RX_MSDU_LIFE_TIME = 0x1004, DOT11_CUR_TX_PWR = 0x100D, diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 905d4287915b..c87ae56ce42a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -722,31 +722,6 @@ struct conf_conn_settings { u8 psm_entry_retries; }; -#define CONF_SR_ERR_TBL_MAX_VALUES 14 - -struct conf_mart_reflex_err_table { - /* - * Length of the error table values table. - * - * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES - */ - u8 len; - - /* - * Smart Reflex error table upper limit. - * - * Range: s8 - */ - s8 upper_limit; - - /* - * Smart Reflex error table values. - * - * Range: s8 - */ - s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; -}; - enum { CONF_REF_CLK_19_2_E, CONF_REF_CLK_26_E, @@ -907,21 +882,7 @@ struct conf_radio_parms { u8 degraded_normal_to_high_threshold_5; }; -#define CONF_SR_ERR_TBL_COUNT 3 - struct conf_init_settings { - /* - * Configure Smart Reflex error table values. - */ - struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; - - /* - * Smart Reflex enable flag. - * - * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled - */ - u8 sr_enable; - /* * Configure general parameters. */ diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index bdd4a968b37d..7bfd6c6a4c77 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -303,11 +303,6 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; - /* Configure smart reflex */ - ret = wl1271_acx_smart_reflex(wl); - if (ret < 0) - goto out_free_memmap; - return 0; out_free_memmap: diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b0f4c6efa415..5a6e4d446962 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -226,30 +226,6 @@ static struct conf_drv_settings default_conf = { .psm_entry_retries = 3 }, .init = { - .sr_err_tbl = { - [0] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, - 0x00 } - }, - [1] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, - 0x00 } - }, - [2] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, - 0x00 } - } - }, - .sr_enable = 1, .genparam = { .ref_clk = CONF_REF_CLK_38_4_E, .settling_time = 5, -- cgit v1.2.3 From a6fe231361e35e3d068a63bbfd2318fa4e961ec5 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:58 +0200 Subject: wl1271: Use slow rates for association messages While not associated, default the data rates to 1 and 2mbps, so that only those rates will be used for association related message transfer. Once associated, configure the full rate-set supported by the AP. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 2 -- drivers/net/wireless/wl12xx/wl1271_conf.h | 3 ++- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 8dfc9ec9590d..4b5ddba96f0b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -107,8 +107,6 @@ enum { CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) -#define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) - #define WL1271_FW_NAME "wl1271-fw.bin" #define WL1271_NVS_NAME "wl1271-nvs.bin" #define WL1271_NVS_LEN 468 diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index c87ae56ce42a..5d1b5b6493e9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -258,7 +258,8 @@ struct conf_rx_settings { #define CONF_TX_MAX_RATE_CLASSES 8 #define CONF_TX_RATE_MASK_UNSPECIFIED 0 -#define CONF_TX_RATE_MASK_ALL 0x1eff +#define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ + CONF_HW_BIT_RATE_2MBPS) #define CONF_TX_RATE_RETRY_LIMIT 10 struct conf_tx_rate_class { diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 7bfd6c6a4c77..c67889dd18fc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -284,7 +284,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Configure TX rate classes */ - ret = wl1271_acx_rate_policies(wl, WL1271_DEFAULT_BASIC_RATE_SET); + ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 5a6e4d446962..272a8fa677ef 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1180,6 +1180,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_unjoin_channel(wl); else wl1271_join_channel(wl, channel); + + if (conf->flags & IEEE80211_CONF_IDLE) { + wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); + } } /* if the channel changes while joined, join again */ @@ -1568,7 +1573,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ - wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; wl->aid = 0; } @@ -1897,7 +1901,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm_entry_retry = 0; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; + wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; -- cgit v1.2.3 From 13f2dc52c69bcca074cd12d4806953b2af45c386 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:59 +0200 Subject: wl1271: Fix event acknowledging functionality In reference source, events are acknowledged separately - fix the driver to do the same. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 6 ++---- drivers/net/wireless/wl12xx/wl1271_event.h | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index d13fdd99c85c..227caa14cbc5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -184,7 +184,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl) wl->mbox_ptr[0], wl->mbox_ptr[1]); } -int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) +int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) { struct event_mailbox mbox; int ret; @@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) return ret; /* then we let the firmware know it can go on...*/ - if (do_ack) - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, - INTR_TRIG_EVENT_ACK); + wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); return 0; } diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a8..278f9206aa56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h @@ -112,6 +112,6 @@ struct event_mailbox { int wl1271_event_unmask(struct wl1271 *wl); void wl1271_event_mbox_config(struct wl1271 *wl); -int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); +int wl1271_event_handle(struct wl1271 *wl, u8 mbox); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 272a8fa677ef..d507dae19e17 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -450,14 +450,13 @@ static void wl1271_irq_work(struct work_struct *work) intr &= WL1271_INTR_MASK; if (intr & WL1271_ACX_INTR_EVENT_A) { - bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); - wl1271_event_handle(wl, 0, do_ack); + wl1271_event_handle(wl, 0); } if (intr & WL1271_ACX_INTR_EVENT_B) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); - wl1271_event_handle(wl, 1, true); + wl1271_event_handle(wl, 1); } if (intr & WL1271_ACX_INTR_INIT_COMPLETE) -- cgit v1.2.3 From af5e084b3200ab6e3033068a34fe16fd139be17b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:00 +0200 Subject: wl1271: prevent power save entry while not associated The mac80211 sometimes requests power save entry while not associated - this will cause problems, so prevent it if not associated. Go to powersave once association is complete. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 1 + drivers/net/wireless/wl12xx/wl1271_main.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 4b5ddba96f0b..81e1c9531a3a 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -416,6 +416,7 @@ struct wl1271 { /* PSM mode requested */ bool psm_requested; + bool associated; /* retry counter for PSM entries */ u8 psm_entry_retry; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d507dae19e17..d07f03565196 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -978,6 +978,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->elp = false; wl->psm = 0; wl->psm_entry_retry = 0; + wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; @@ -1191,8 +1192,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl1271_info("psm enabled"); - wl->psm_requested = true; /* @@ -1200,7 +1199,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + if (wl->associated) { + wl1271_info("psm enabled"); + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + } } else if (!(conf->flags & IEEE80211_CONF_PS) && wl->psm_requested) { wl1271_info("psm disabled"); @@ -1548,6 +1550,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; + wl->associated = true; /* * with wl1271, we don't need to update the @@ -1572,6 +1575,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ + wl->associated = false; wl->aid = 0; } @@ -1898,6 +1902,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm = 0; wl->psm_requested = false; wl->psm_entry_retry = 0; + wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; -- cgit v1.2.3 From 9ccd921792e5b6719ff9e561438e095cba757727 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:01 +0200 Subject: wl1271: Implement chipset boot retry The wl1271 has a hardware bug which causes it to randomly (very infrequently) to fail powering up properly. This patch implements retry for the chipset boot sequence, to work around the hardware problem. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 130 ++++++++++++++++++------------ 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d07f03565196..0795bf3c60da 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -47,6 +47,8 @@ #include "wl1271_cmd.h" #include "wl1271_boot.h" +#define WL1271_BOOT_RETRIES 3 + static struct conf_drv_settings default_conf = { .sg = { .per_threshold = 7500, @@ -645,7 +647,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) - goto out_power_off; + goto out; break; case CHIP_ID_1271_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", @@ -653,38 +655,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) - goto out_power_off; + goto out; break; default: - wl1271_error("unsupported chip id: 0x%x", wl->chip.id); + wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); ret = -ENODEV; - goto out_power_off; + goto out; } if (wl->fw == NULL) { ret = wl1271_fetch_firmware(wl); if (ret < 0) - goto out_power_off; + goto out; } /* No NVS from netlink, try to get it from the filesystem */ if (wl->nvs == NULL) { ret = wl1271_fetch_nvs(wl); if (ret < 0) - goto out_power_off; + goto out; } - goto out; - -out_power_off: - wl1271_power_off(wl); - out: return ret; } int wl1271_plt_start(struct wl1271 *wl) { + int retries = WL1271_BOOT_RETRIES; int ret; mutex_lock(&wl->mutex); @@ -698,35 +696,48 @@ int wl1271_plt_start(struct wl1271 *wl) goto out; } - wl->state = WL1271_STATE_PLT; - - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out_power_off; - - wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); + while (retries) { + retries--; + ret = wl1271_chip_wakeup(wl); + if (ret < 0) + goto power_off; - ret = wl1271_plt_init(wl); - if (ret < 0) - goto out_irq_disable; + ret = wl1271_boot(wl); + if (ret < 0) + goto power_off; - /* Make sure power saving is disabled */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - goto out_irq_disable; + ret = wl1271_plt_init(wl); + if (ret < 0) + goto irq_disable; - goto out; + /* Make sure power saving is disabled */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + goto irq_disable; -out_irq_disable: - wl1271_disable_interrupts(wl); + wl->state = WL1271_STATE_PLT; + wl1271_notice("firmware booted in PLT mode (%s)", + wl->chip.fw_ver); + goto out; -out_power_off: - wl1271_power_off(wl); +irq_disable: + wl1271_disable_interrupts(wl); + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + cancel_work_sync(&wl->irq_work); + mutex_lock(&wl->mutex); +power_off: + wl1271_power_off(wl); + } + wl1271_error("firmware boot in PLT mode failed despite %d retries", + WL1271_BOOT_RETRIES); out: mutex_unlock(&wl->mutex); @@ -882,6 +893,7 @@ static struct notifier_block wl1271_dev_notifier = { static int wl1271_op_start(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; + int retries = WL1271_BOOT_RETRIES; int ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 start"); @@ -895,30 +907,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) goto out; } - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out_power_off; - - ret = wl1271_hw_init(wl); - if (ret < 0) - goto out_irq_disable; - - wl->state = WL1271_STATE_ON; + while (retries) { + retries--; + ret = wl1271_chip_wakeup(wl); + if (ret < 0) + goto power_off; - wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + ret = wl1271_boot(wl); + if (ret < 0) + goto power_off; - goto out; + ret = wl1271_hw_init(wl); + if (ret < 0) + goto irq_disable; -out_irq_disable: - wl1271_disable_interrupts(wl); + wl->state = WL1271_STATE_ON; + wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + goto out; -out_power_off: - wl1271_power_off(wl); +irq_disable: + wl1271_disable_interrupts(wl); + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + cancel_work_sync(&wl->irq_work); + mutex_lock(&wl->mutex); +power_off: + wl1271_power_off(wl); + } + wl1271_error("firmware boot failed despite %d retries", + WL1271_BOOT_RETRIES); out: mutex_unlock(&wl->mutex); -- cgit v1.2.3 From 01ac17ecb6292ceab9bfc498145491b78552b239 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:02 +0200 Subject: wl1271: Add pre-power-on sleep This patch adds a short delay before powering on the wl1271. Normally, it is not needed, but if the wl1271 has been powered off shortly before, for reliable firmware-booting this small stabilization delay is required. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 4 +++- drivers/net/wireless/wl12xx/wl1271_main.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 81e1c9531a3a..c965c4a718f3 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -458,7 +458,9 @@ int wl1271_plt_stop(struct wl1271 *wl); #define WL1271_TX_QUEUE_MAX_LENGTH 20 -/* WL1271 needs a 200ms sleep after power on */ +/* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power + on in case is has been shut down shortly before */ +#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ static inline bool wl1271_11a_enabled(void) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0795bf3c60da..0520b38e8e72 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -618,6 +618,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) struct wl1271_partition_set partition; int ret = 0; + msleep(WL1271_PRE_POWER_ON_SLEEP); wl1271_power_on(wl); msleep(WL1271_POWER_ON_SLEEP); wl1271_spi_reset(wl); -- cgit v1.2.3 From 26a63f6af58144818d4979cce1cbb8e49329f732 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:03 +0200 Subject: wl1271: Remove beacon-loss-ind from PSM entry failure handling Remove the beacon-loss indication to stack from PSM entry failure handling - this will cause more problems than it will solve due to the design of the mac80211. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 227caa14cbc5..8d0c18dec2cd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, } else { wl1271_error("PSM entry failed, giving up.\n"); wl->psm_entry_retry = 0; - *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: -- cgit v1.2.3 From e0d8bbf0d23e6b82f13b29f39593d5d13d923b2b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:04 +0200 Subject: wl1271: Add rudimentary ad-hoc support This patch adds rudimentary a-hoc support for the driver. It will allow setting up ad-hoc, and for other devices to scan and join. The beacon and probe response template setting is slightly dirty, and need to be properly implemented with support from mac80211. Also, the SSID is not configured to the firmware - the FW will not be able to respond to probe requests autonomously. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 45 +++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0520b38e8e72..d7b1bb3e08a8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1139,11 +1139,15 @@ out: static int wl1271_join_channel(struct wl1271 *wl, int channel) { - int ret; + int ret = 0; /* we need to use a dummy BSSID for now */ static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef }; + /* the dummy join is not required for ad-hoc */ + if (wl->bss_type == BSS_TYPE_IBSS) + goto out; + /* disable mac filter, so we hear everything */ wl->rx_config &= ~CFG_BSSID_FILTER_EN; @@ -1572,6 +1576,42 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl->joined = true; } + if (wl->bss_type == BSS_TYPE_IBSS) { + /* FIXME: This implements rudimentary ad-hoc support - + proper templates are on the wish list and notification + on when they change. This patch will update the templates + on every call to this function. Also, the firmware will not + answer to probe-requests as it does not have the proper + SSID set in the JOIN command. The probe-response template + is set nevertheless, as the FW will ASSERT without it */ + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) { + struct ieee80211_hdr *hdr; + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, + beacon->data, + beacon->len); + + if (ret < 0) { + dev_kfree_skb(beacon); + goto out_sleep; + } + + hdr = (struct ieee80211_hdr *) beacon->data; + hdr->frame_control = cpu_to_le16( + IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); + + ret = wl1271_cmd_template_set(wl, + CMD_TEMPL_PROBE_RESPONSE, + beacon->data, + beacon->len); + dev_kfree_skb(beacon); + if (ret < 0) + goto out_sleep; + } + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; @@ -1857,7 +1897,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS; - wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); wl->hw->wiphy->max_scan_ssids = 1; wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; -- cgit v1.2.3 From ec078d943b89c03e55ac9c8b28f39256d4d4045e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:05 +0200 Subject: wl1271: Change rates configured for templates Previously a "firmware chooses" value was used for the rates of all control message templates set to the firmware. This resulted in a too high rate to be chosen to transmit those messages. Change this by configuring a fixed low rate for the templates. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d7b1bb3e08a8..7a73aaadd04c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -78,7 +78,8 @@ static struct conf_drv_settings default_conf = { .tx = { .tx_energy_detection = 0, .rc_conf = { - .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, + .enabled_rates = CONF_HW_BIT_RATE_1MBPS | + CONF_HW_BIT_RATE_2MBPS, .short_retry_limit = 10, .long_retry_limit = 10, .aflags = 0 -- cgit v1.2.3 From 830fb67b8e37fb03cf703b4e1217fe30ce32d579 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:06 +0200 Subject: wl1271: Fix supported rate management Previously, only basic rates were used for data transmission - resulting in reduced transfer rates. This patch takes enables the firmware to take advantage of the full set of data rates supported by the AP. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 7 +++- drivers/net/wireless/wl12xx/wl1271_acx.c | 24 +++++++++---- drivers/net/wireless/wl12xx/wl1271_acx.h | 5 ++- drivers/net/wireless/wl12xx/wl1271_init.c | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 59 +++++++++++++------------------ drivers/net/wireless/wl12xx/wl1271_tx.c | 37 +++++++++++++++++++ 6 files changed, 90 insertions(+), 44 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index c965c4a718f3..9290c92522b4 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -322,6 +322,10 @@ struct wl1271 { enum wl1271_state state; struct mutex mutex; +#define WL1271_FLAG_STA_RATES_CHANGED (0) +#define WL1271_FLAG_STA_ASSOCIATED (1) + unsigned long flags; + struct wl1271_partition_set part; struct wl1271_chip chip; @@ -394,7 +398,9 @@ struct wl1271 { u16 aid; /* currently configured rate set */ + u32 sta_rate_set; u32 basic_rate_set; + u32 rate_set; /* The current band */ enum ieee80211_band band; @@ -416,7 +422,6 @@ struct wl1271 { /* PSM mode requested */ bool psm_requested; - bool associated; /* retry counter for PSM entries */ u8 psm_entry_retry; diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index ea6427ad1bcb..0ea1a48c45fa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -787,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) return 0; } -int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) +int wl1271_acx_rate_policies(struct wl1271 *wl) { struct acx_rate_policy *acx; struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; + int idx = 0; int ret = 0; wl1271_debug(DEBUG_ACX, "acx rate policies"); @@ -802,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) goto out; } - /* configure one default (one-size-fits-all) rate class */ - acx->rate_class_cnt = cpu_to_le32(1); - acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); - acx->rate_class[0].short_retry_limit = c->short_retry_limit; - acx->rate_class[0].long_retry_limit = c->long_retry_limit; - acx->rate_class[0].aflags = c->aflags; + /* configure one basic rate class */ + idx = ACX_TX_BASIC_RATE; + acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); + acx->rate_class[idx].short_retry_limit = c->short_retry_limit; + acx->rate_class[idx].long_retry_limit = c->long_retry_limit; + acx->rate_class[idx].aflags = c->aflags; + + /* configure one AP supported rate class */ + idx = ACX_TX_AP_FULL_RATE; + acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); + acx->rate_class[idx].short_retry_limit = c->short_retry_limit; + acx->rate_class[idx].long_retry_limit = c->long_retry_limit; + acx->rate_class[idx].aflags = c->aflags; + + acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); if (ret < 0) { diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 6640ebfb6162..b6a473f60658 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -826,6 +826,9 @@ struct acx_rate_class { u8 reserved; }; +#define ACX_TX_BASIC_RATE 0 +#define ACX_TX_AP_FULL_RATE 1 +#define ACX_TX_RATE_POLICY_CNT 2 struct acx_rate_policy { struct acx_header header; @@ -1058,7 +1061,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); -int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); +int wl1271_acx_rate_policies(struct wl1271 *wl); int wl1271_acx_ac_cfg(struct wl1271 *wl); int wl1271_acx_tid_cfg(struct wl1271 *wl); int wl1271_acx_frag_threshold(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index c67889dd18fc..3b4ed070f439 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -284,7 +284,7 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Configure TX rate classes */ - ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); + ret = wl1271_acx_rate_policies(wl); if (ret < 0) goto out_free_memmap; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7a73aaadd04c..775b1e82ca81 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -777,7 +777,20 @@ out: static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1271 *wl = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *sta = txinfo->control.sta; + unsigned long flags; + /* peek into the rates configured in the STA entry */ + spin_lock_irqsave(&wl->wl_lock, flags); + if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { + wl->sta_rate_set = sta->supp_rates[conf->channel->band]; + set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); + } + spin_unlock_irqrestore(&wl->wl_lock, flags); + + /* queue the packet */ skb_queue_tail(&wl->tx_queue, skb); /* @@ -1004,7 +1017,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->elp = false; wl->psm = 0; wl->psm_entry_retry = 0; - wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; @@ -1016,6 +1028,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->time_offset = 0; wl->session_counter = 0; wl->joined = false; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; + wl->flags = 0; for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -1212,8 +1227,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_IDLE) { - wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; - wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; + wl1271_acx_rate_policies(wl); } } @@ -1229,7 +1245,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - if (wl->associated) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_info("psm enabled"); ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } @@ -1522,22 +1538,6 @@ out: return ret; } -static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) -{ - struct ieee80211_supported_band *band; - u32 enabled_rates = 0; - int bit; - - band = wl->hw->wiphy->bands[wl->band]; - for (bit = 0; bit < band->n_bitrates; bit++) { - if (basic_rate_set & 0x1) - enabled_rates |= band->bitrates[bit].hw_value; - basic_rate_set >>= 1; - } - - return enabled_rates; -} - static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1616,7 +1616,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; - wl->associated = true; + set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); /* * with wl1271, we don't need to update the @@ -1641,7 +1641,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ - wl->associated = false; + clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; } @@ -1676,17 +1676,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BASIC_RATES) { - wl->basic_rate_set = wl1271_enabled_rates_get( - wl, bss_conf->basic_rates); - - ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); - if (ret < 0) { - wl1271_warning("Set rate policies failed %d", ret); - goto out_sleep; - } - } - out_sleep: wl1271_ps_elp_sleep(wl); @@ -1969,14 +1958,16 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm = 0; wl->psm_requested = false; wl->psm_entry_retry = 0; - wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; wl->gpio_power = false; + wl->flags = 0; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 00af065c77c2..75f532706332 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, pad = pad - skb->len; tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; + /* if the packets are destined for AP (have a STA entry) send them + with AP rate policies, otherwise use default basic rates */ + if (control->control.sta) + tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; + desc->tx_attr = cpu_to_le16(tx_attr); wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); @@ -214,18 +219,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) return ret; } +static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) +{ + struct ieee80211_supported_band *band; + u32 enabled_rates = 0; + int bit; + + band = wl->hw->wiphy->bands[wl->band]; + for (bit = 0; bit < band->n_bitrates; bit++) { + if (rate_set & 0x1) + enabled_rates |= band->bitrates[bit].hw_value; + rate_set >>= 1; + } + + return enabled_rates; +} + void wl1271_tx_work(struct work_struct *work) { struct wl1271 *wl = container_of(work, struct wl1271, tx_work); struct sk_buff *skb; bool woken_up = false; + u32 sta_rates = 0; int ret; + /* check if the rates supported by the AP have changed */ + if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, + &wl->flags))) { + unsigned long flags; + spin_lock_irqsave(&wl->wl_lock, flags); + sta_rates = wl->sta_rate_set; + spin_unlock_irqrestore(&wl->wl_lock, flags); + } + mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; + /* if rates have changed, re-configure the rate policy */ + if (unlikely(sta_rates)) { + wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); + wl1271_acx_rate_policies(wl); + } + while ((skb = skb_dequeue(&wl->tx_queue))) { if (!woken_up) { ret = wl1271_ps_elp_wakeup(wl, false); -- cgit v1.2.3 From 71449f8d7059b69e6e45063997d225d8202221a2 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:07 +0200 Subject: wl1271: Change booleans in struct wl1271 into a flags bitmask For cleaner implementation, change the bunch of booleans in the struct wl1271 structure into a flags bitmask. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 23 +++++--------- drivers/net/wireless/wl12xx/wl1271_cmd.c | 6 ++-- drivers/net/wireless/wl12xx/wl1271_debugfs.c | 13 ++++++-- drivers/net/wireless/wl12xx/wl1271_event.c | 11 +++---- drivers/net/wireless/wl12xx/wl1271_main.c | 45 +++++++++++----------------- drivers/net/wireless/wl12xx/wl1271_ps.c | 15 +++++----- drivers/net/wireless/wl12xx/wl1271_tx.c | 6 ++-- 7 files changed, 55 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 9290c92522b4..d0938db043b3 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -324,6 +324,13 @@ struct wl1271 { #define WL1271_FLAG_STA_RATES_CHANGED (0) #define WL1271_FLAG_STA_ASSOCIATED (1) +#define WL1271_FLAG_JOINED (2) +#define WL1271_FLAG_GPIO_POWER (3) +#define WL1271_FLAG_TX_QUEUE_STOPPED (4) +#define WL1271_FLAG_SCANNING (5) +#define WL1271_FLAG_IN_ELP (6) +#define WL1271_FLAG_PSM (7) +#define WL1271_FLAG_PSM_REQUESTED (8) unsigned long flags; struct wl1271_partition_set part; @@ -363,7 +370,6 @@ struct wl1271 { /* Frames scheduled for transmission, not handled yet */ struct sk_buff_head tx_queue; - bool tx_queue_stopped; struct work_struct tx_work; @@ -391,7 +397,6 @@ struct wl1271 { u32 mbox_ptr[2]; /* Are we currently scanning */ - bool scanning; struct wl1271_scan scan; /* Our association ID */ @@ -411,18 +416,9 @@ struct wl1271 { unsigned int rx_config; unsigned int rx_filter; - /* is firmware in elp mode */ - bool elp; - struct completion *elp_compl; struct delayed_work elp_work; - /* we can be in psm, but not in elp, we have to differentiate */ - bool psm; - - /* PSM mode requested */ - bool psm_requested; - /* retry counter for PSM entries */ u8 psm_entry_retry; @@ -441,15 +437,10 @@ struct wl1271 { struct ieee80211_vif *vif; - /* Used for a workaround to send disconnect before rejoining */ - bool joined; - /* Current chipset configuration */ struct conf_drv_settings conf; struct list_head list; - - bool gpio_power; }; int wl1271_plt_start(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 20f3e67c8e48..b5eb9edc63aa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -655,7 +655,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, channels = wl->hw->wiphy->bands[ieee_band]->channels; n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; - if (wl->scanning) + if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) return -EINVAL; params = kzalloc(sizeof(*params), GFP_KERNEL); @@ -730,7 +730,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); - wl->scanning = true; + set_bit(WL1271_FLAG_SCANNING, &wl->flags); if (wl1271_11a_enabled()) { wl->scan.state = band; if (band == WL1271_SCAN_BAND_DUAL) { @@ -748,7 +748,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); if (ret < 0) { wl1271_error("SCAN failed"); - wl->scanning = false; + clear_bit(WL1271_FLAG_SCANNING, &wl->flags); goto out; } diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index 4eaf40c57567..8d7588ca68fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c @@ -241,10 +241,12 @@ static ssize_t gpio_power_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; + bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + int res; char buf[10]; - res = scnprintf(buf, sizeof(buf), "%d\n", wl->gpio_power); + res = scnprintf(buf, sizeof(buf), "%d\n", state); return simple_read_from_buffer(user_buf, count, ppos, buf, res); } @@ -274,8 +276,13 @@ static ssize_t gpio_power_write(struct file *file, goto out; } - wl->set_power(!!value); - wl->gpio_power = !!value; + if (value) { + wl->set_power(true); + set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + } else { + wl->set_power(false); + clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); + } out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 8d0c18dec2cd..6ff535d5c7ee 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -35,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); - if (wl->scanning) { + if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, size); @@ -43,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, * to the wl1271_cmd_scan function that we are not * scanning as it checks that. */ - wl->scanning = false; + clear_bit(WL1271_FLAG_SCANNING, &wl->flags); wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, wl->scan.active, wl->scan.high_prio, @@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, false); mutex_lock(&wl->mutex); - wl->scanning = false; + clear_bit(WL1271_FLAG_SCANNING, &wl->flags); } } return 0; @@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: - if (!wl->psm) { + if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { wl->psm_entry_retry = 0; break; } @@ -135,7 +135,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * filtering) is enabled. Without PSM, the stack will receive all * beacons and can detect beacon loss by itself. */ - if (vector & BSS_LOSE_EVENT_ID && wl->psm) { + if (vector & BSS_LOSE_EVENT_ID && + test_bit(WL1271_FLAG_PSM, &wl->flags)) { wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); /* indicate to the stack, that beacons have been lost */ diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 775b1e82ca81..90a60c1147a8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -378,13 +378,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) static void wl1271_power_off(struct wl1271 *wl) { wl->set_power(false); - wl->gpio_power = false; + clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static void wl1271_power_on(struct wl1271 *wl) { wl->set_power(true); - wl->gpio_power = true; + set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static void wl1271_fw_status(struct wl1271 *wl, @@ -812,7 +812,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * protected. Maybe fix this by removing the stupid * variable altogether and checking the real queue state? */ - wl->tx_queue_stopped = true; + set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); } return NETDEV_TX_OK; @@ -985,11 +985,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) WARN_ON(wl->state != WL1271_STATE_ON); - if (wl->scanning) { + if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, true); mutex_lock(&wl->mutex); - wl->scanning = false; } wl->state = WL1271_STATE_OFF; @@ -1014,10 +1013,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; - wl->elp = false; - wl->psm = 0; wl->psm_entry_retry = 0; - wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; wl->tx_results_count = 0; @@ -1027,7 +1023,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->tx_security_seq_32 = 0; wl->time_offset = 0; wl->session_counter = 0; - wl->joined = false; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->flags = 0; @@ -1174,7 +1169,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) if (ret < 0) goto out; - wl->joined = true; + set_bit(WL1271_FLAG_JOINED, &wl->flags); out: return ret; @@ -1189,7 +1184,7 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) if (ret < 0) goto out; - wl->joined = false; + clear_bit(WL1271_FLAG_JOINED, &wl->flags); wl->channel = 0; memset(wl->bssid, 0, ETH_ALEN); wl->rx_config = WL1271_DEFAULT_RX_CONFIG; @@ -1221,7 +1216,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) goto out; if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (conf->flags & IEEE80211_CONF_IDLE && wl->joined) + if (conf->flags & IEEE80211_CONF_IDLE && + test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_unjoin_channel(wl); else wl1271_join_channel(wl, channel); @@ -1234,11 +1230,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } /* if the channel changes while joined, join again */ - if (channel != wl->channel && wl->joined) + if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_join_channel(wl, channel); - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl->psm_requested = true; + if (conf->flags & IEEE80211_CONF_PS && + !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { + set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); /* * We enter PSM only if we're already associated. @@ -1250,12 +1247,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } } else if (!(conf->flags & IEEE80211_CONF_PS) && - wl->psm_requested) { + test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { wl1271_info("psm disabled"); - wl->psm_requested = false; + clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); - if (wl->psm) + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); } @@ -1574,7 +1571,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl1271_warning("cmd join failed %d", ret); goto out_sleep; } - wl->joined = true; + set_bit(WL1271_FLAG_JOINED, &wl->flags); } if (wl->bss_type == BSS_TYPE_IBSS) { @@ -1633,7 +1630,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, goto out_sleep; /* If we want to go in PSM but we're not there yet */ - if (wl->psm_requested && !wl->psm) { + if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && + !test_bit(WL1271_FLAG_PSM, &wl->flags)) { mode = STATION_POWER_SAVE_MODE; ret = wl1271_ps_set_mode(wl, mode); if (ret < 0) @@ -1949,24 +1947,17 @@ static int __devinit wl1271_probe(struct spi_device *spi) INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); wl->channel = WL1271_DEFAULT_CHANNEL; - wl->scanning = false; wl->default_key = 0; wl->rx_counter = 0; wl->rx_config = WL1271_DEFAULT_RX_CONFIG; wl->rx_filter = WL1271_DEFAULT_RX_FILTER; - wl->elp = false; - wl->psm = 0; - wl->psm_requested = false; wl->psm_entry_retry = 0; - wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; - wl->joined = false; - wl->gpio_power = false; wl->flags = 0; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 507cd91d7eed..e407790f6771 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->elp || !wl->psm) + if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || + !test_bit(WL1271_FLAG_PSM, &wl->flags)) goto out; wl1271_debug(DEBUG_PSM, "chip to elp"); wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); - wl->elp = true; + set_bit(WL1271_FLAG_IN_ELP, &wl->flags); out: mutex_unlock(&wl->mutex); @@ -55,7 +56,7 @@ out: /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { - if (wl->psm) { + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { cancel_delayed_work(&wl->elp_work); ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(ELP_ENTRY_DELAY)); @@ -70,7 +71,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) u32 start_time = jiffies; bool pending = false; - if (!wl->elp) + if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) return 0; wl1271_debug(DEBUG_PSM, "waking up chip from elp"); @@ -101,7 +102,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) } } - wl->elp = false; + clear_bit(WL1271_FLAG_IN_ELP, &wl->flags); wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", jiffies_to_msecs(jiffies - start_time)); @@ -143,7 +144,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) if (ret < 0) return ret; - wl->psm = 1; + set_bit(WL1271_FLAG_PSM, &wl->flags); break; case STATION_ACTIVE_MODE: default: @@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) if (ret < 0) return ret; - wl->psm = 0; + clear_bit(WL1271_FLAG_PSM, &wl->flags); break; } diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 75f532706332..a288cc317d7b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -277,18 +277,18 @@ void wl1271_tx_work(struct work_struct *work) wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " "stop queues"); ieee80211_stop_queues(wl->hw); - wl->tx_queue_stopped = true; + set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); skb_queue_head(&wl->tx_queue, skb); goto out; } else if (ret < 0) { dev_kfree_skb(skb); goto out; - } else if (wl->tx_queue_stopped) { + } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, + &wl->flags)) { /* firmware buffer has space, restart queues */ wl1271_debug(DEBUG_TX, "complete_packet: waking queues"); ieee80211_wake_queues(wl->hw); - wl->tx_queue_stopped = false; } } -- cgit v1.2.3 From 38ad2d87d42ba847c100ef132e8e363513982c8b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:08 +0200 Subject: wl1271: Add support for acx_pm_config This acx configures host clock parameters in correspondence with the clock request line - the settling time of the clock, and whether fast wake-up is supported. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 28 ++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_acx.h | 9 +++++++++ drivers/net/wireless/wl12xx/wl1271_conf.h | 17 +++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_init.c | 5 +++++ drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++ 5 files changed, 63 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 0ea1a48c45fa..0b3434843476 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -1118,3 +1118,31 @@ out: kfree(acx); return ret; } + +int wl1271_acx_pm_config(struct wl1271 *wl) +{ + struct wl1271_acx_pm_config *acx = NULL; + struct conf_pm_config_settings *c = &wl->conf.pm_config; + int ret = 0; + + wl1271_debug(DEBUG_ACX, "acx pm config"); + + acx = kzalloc(sizeof(*acx), GFP_KERNEL); + if (!acx) { + ret = -ENOMEM; + goto out; + } + + acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); + acx->host_fast_wakeup_support = c->host_fast_wakeup_support; + + ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx pm config failed: %d", ret); + goto out; + } + +out: + kfree(acx); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index b6a473f60658..1bb63af64f0e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -961,6 +961,13 @@ struct wl1271_acx_arp_filter { used. */ } __attribute__((packed)); +struct wl1271_acx_pm_config { + struct acx_header header; + + __le32 host_clk_settling_time; + u8 host_fast_wakeup_support; + u8 padding[3]; +} __attribute__ ((packed)); enum { ACX_WAKE_UP_CONDITIONS = 0x0002, @@ -1025,6 +1032,7 @@ enum { DOT11_RX_DOT11_MODE = 0x1012, DOT11_RTS_THRESHOLD = 0x1013, DOT11_GROUP_ADDRESS_TBL = 0x1014, + ACX_PM_CONFIG = 0x1016, MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, @@ -1073,5 +1081,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, u8 version); +int wl1271_acx_pm_config(struct wl1271 *wl); #endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 5d1b5b6493e9..1993d63c214e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -904,6 +904,22 @@ struct conf_itrim_settings { u32 timeout; }; +struct conf_pm_config_settings { + /* + * Host clock settling time + * + * Range: 0 - 30000 us + */ + u32 host_clk_settling_time; + + /* + * Host fast wakeup support + * + * Range: true, false + */ + bool host_fast_wakeup_support; +}; + struct conf_drv_settings { struct conf_sg_settings sg; struct conf_rx_settings rx; @@ -911,6 +927,7 @@ struct conf_drv_settings { struct conf_conn_settings conn; struct conf_init_settings init; struct conf_itrim_settings itrim; + struct conf_pm_config_settings pm_config; }; #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 3b4ed070f439..c9848eecb767 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -303,6 +303,11 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + /* configure PM */ + ret = wl1271_acx_pm_config(wl); + if (ret < 0) + goto out_free_memmap; + return 0; out_free_memmap: diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 90a60c1147a8..7e6b500dfb6f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -321,6 +321,10 @@ static struct conf_drv_settings default_conf = { .itrim = { .enable = false, .timeout = 50000, + }, + .pm_config = { + .host_clk_settling_time = 5000, + .host_fast_wakeup_support = false } }; -- cgit v1.2.3 From 04477bf095afd008b73717f7a4ea1fdf18b1b5e2 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:09 +0200 Subject: wl1271: Check vif for NULL when indicating beacon-loss Because the interface is started and the vif are created and destroyed separately, there is a slim possibility beacon-loss indications occur while there is no vif - causing a kernel-oops unless checked. Add checking for the vif. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 6ff535d5c7ee..0a145afc9905 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -150,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) return ret; } - if (beacon_loss) { + if (wl->vif && beacon_loss) { /* Obviously, it's dangerous to release the mutex while we are holding many of the variables in the wl struct. That's why it's done last in the function, and care must -- cgit v1.2.3 From 8f648c00039a42e67a9dff034c77d41502dab1f3 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:10 +0200 Subject: wl1271: Prevent performing "join" before association There is a minor bug in the code causing a "join" to be performed before there is an intention to associate. Fix this. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7e6b500dfb6f..4a997381a8d0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1223,7 +1223,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (conf->flags & IEEE80211_CONF_IDLE && test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_unjoin_channel(wl); - else + else if (!(conf->flags & IEEE80211_CONF_IDLE)) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_IDLE) { -- cgit v1.2.3 From baeb66fe2306783e3b9a492b03882f2e249b2eeb Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 18 Dec 2009 17:59:02 -0500 Subject: wireless: remove CONFIG_WIRELESS_OLD_REGULATORY This is no longer needed with the availability of CONFIG_CFG80211_INTERNAL_REGDB. Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 21 ------- net/wireless/Kconfig | 15 ----- net/wireless/nl80211.c | 6 -- net/wireless/reg.c | 89 +----------------------------- 4 files changed, 2 insertions(+), 129 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 591e94448e63..86f2ec90af87 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -88,27 +88,6 @@ Who: Luis R. Rodriguez --------------------------- -What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information -When: March 2010 / desktop catchup - -Why: The old regulatory infrastructure has been replaced with a new one - which does not require statically defined regulatory domains. We do - not want to keep static regulatory domains in the kernel due to the - the dynamic nature of regulatory law and localization. We kept around - the old static definitions for the regulatory domains of: - - * US - * JP - * EU - - and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was - set. We will remove this option once the standard Linux desktop catches - up with the new userspace APIs we have implemented. - -Who: Luis R. Rodriguez - ---------------------------- - What: dev->power.power_state When: July 2007 Why: Broken design for runtime control over driver power states, confusing diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 8419971f07c5..d0ee29063e5d 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -94,21 +94,6 @@ config CFG80211_DEBUGFS If unsure, say N. -config WIRELESS_OLD_REGULATORY - bool "Old wireless static regulatory definitions" - default n - depends on CFG80211 - ---help--- - This option enables the old static regulatory information - and uses it within the new framework. This option is available - for historical reasons and it is advised to leave it off. - - For details see: - - http://wireless.kernel.org/en/developers/Regulatory - - Say N and if you say Y, please tell us why. The default is N. - config CFG80211_INTERNAL_REGDB bool "use statically compiled regulatory rules database" if EMBEDDED default n diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7cb0d647fc34..60f854377f90 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2550,12 +2550,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - /* We ignore world regdom requests with the old regdom setup */ - if (is_world_regdom(data)) - return -EINVAL; -#endif - r = regulatory_hint_user(data); return r; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index dc13c3ffeca6..87ea60d84c3c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -129,78 +129,6 @@ static char *ieee80211_regdom = "00"; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -#ifdef CONFIG_WIRELESS_OLD_REGULATORY -/* - * We assume 40 MHz bandwidth for the old regulatory work. - * We make emphasis we are using the exact same frequencies - * as before - */ - -static const struct ieee80211_regdomain us_regdom = { - .n_reg_rules = 6, - .alpha2 = "US", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), - /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 40, 6, 17, 0), - /* IEEE 802.11a, channels 48..64 */ - REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), - /* IEEE 802.11a, channels 100..124 */ - REG_RULE(5500-10, 5590+10, 40, 6, 20, NL80211_RRF_DFS), - /* IEEE 802.11a, channels 132..144 */ - REG_RULE(5660-10, 5700+10, 40, 6, 20, NL80211_RRF_DFS), - /* IEEE 802.11a, channels 149..165, outdoor */ - REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), - } -}; - -static const struct ieee80211_regdomain jp_regdom = { - .n_reg_rules = 6, - .alpha2 = "JP", - .reg_rules = { - /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13 */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, 0), - /* IEEE 802.11b/g, channel 14 */ - REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_OFDM), - /* IEEE 802.11a, channels 36..48 */ - REG_RULE(5180-10, 5240+10, 40, 6, 20, 0), - /* IEEE 802.11a, channels 52..64 */ - REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), - /* IEEE 802.11a, channels 100..144 */ - REG_RULE(5500-10, 5700+10, 40, 6, 23, NL80211_RRF_DFS), - } -}; - -static const struct ieee80211_regdomain *static_regdom(char *alpha2) -{ - if (alpha2[0] == 'U' && alpha2[1] == 'S') - return &us_regdom; - if (alpha2[0] == 'J' && alpha2[1] == 'P') - return &jp_regdom; - /* Use world roaming rules for "EU", since it was a pseudo - domain anyway... */ - if (alpha2[0] == 'E' && alpha2[1] == 'U') - return &world_regdom; - /* Default, world roaming rules */ - return &world_regdom; -} - -static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) -{ - if (rd == &us_regdom || rd == &jp_regdom || rd == &world_regdom) - return true; - return false; -} -#else -static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) -{ - return false; -} -#endif - static void reset_regdomains(void) { /* avoid freeing static information or freeing something twice */ @@ -210,8 +138,6 @@ static void reset_regdomains(void) cfg80211_world_regdom = NULL; if (cfg80211_regdomain == &world_regdom) cfg80211_regdomain = NULL; - if (is_old_static_regdom(cfg80211_regdomain)) - cfg80211_regdomain = NULL; kfree(cfg80211_regdomain); kfree(cfg80211_world_regdom); @@ -1490,8 +1416,6 @@ static int ignore_request(struct wiphy *wiphy, return REG_INTERSECT; case NL80211_REGDOM_SET_BY_DRIVER: if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { - if (is_old_static_regdom(cfg80211_regdomain)) - return 0; if (regdom_changes(pending_request->alpha2)) return 0; return -EALREADY; @@ -1528,8 +1452,7 @@ static int ignore_request(struct wiphy *wiphy, return -EAGAIN; } - if (!is_old_static_regdom(cfg80211_regdomain) && - !regdom_changes(pending_request->alpha2)) + if (!regdom_changes(pending_request->alpha2)) return -EALREADY; return 0; @@ -2111,8 +2034,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * If someone else asked us to change the rd lets only bother * checking if the alpha2 changes if CRDA was already called */ - if (!is_old_static_regdom(cfg80211_regdomain) && - !regdom_changes(rd->alpha2)) + if (!regdom_changes(rd->alpha2)) return -EINVAL; } @@ -2311,15 +2233,8 @@ int regulatory_init(void) spin_lock_init(®_requests_lock); spin_lock_init(®_pending_beacons_lock); -#ifdef CONFIG_WIRELESS_OLD_REGULATORY - cfg80211_regdomain = static_regdom(ieee80211_regdom); - - printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); - print_regdomain_info(cfg80211_regdomain); -#else cfg80211_regdomain = cfg80211_world_regdom; -#endif /* We always try to get an update for the static regdomain */ err = regulatory_hint_core(cfg80211_regdomain->alpha2); if (err) { -- cgit v1.2.3 From 00e23ce219a9ac6c5f764342ca13f8ac1bab0382 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 23 Dec 2009 00:03:22 +0100 Subject: rt2x00: Fix checks for rt2800 SOC support. Fix checking for SOC support in rt2800pci. The wrong config (an unexisting one) was checked. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 458378c4e500..96e024477b2f 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -52,8 +52,8 @@ #define CONFIG_RT2800PCI_PCI #endif -#ifdef CONFIG_RT2800PCI_WISOC_MODULE -#define CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC_MODULE +#define CONFIG_RT2800PCI_SOC #endif /* @@ -87,7 +87,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); } -#ifdef CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ @@ -98,7 +98,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) { } -#endif /* CONFIG_RT2800PCI_WISOC */ +#endif /* CONFIG_RT2800PCI_SOC */ #ifdef CONFIG_RT2800PCI_PCI static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) @@ -1251,7 +1251,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); #endif /* CONFIG_RT2800PCI_PCI */ MODULE_LICENSE("GPL"); -#ifdef CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC #if defined(CONFIG_RALINK_RT288X) __rt2x00soc_probe(RT2880, &rt2800pci_ops); #elif defined(CONFIG_RALINK_RT305X) @@ -1269,7 +1269,7 @@ static struct platform_driver rt2800soc_driver = { .suspend = rt2x00soc_suspend, .resume = rt2x00soc_resume, }; -#endif /* CONFIG_RT2800PCI_WISOC */ +#endif /* CONFIG_RT2800PCI_SOC */ #ifdef CONFIG_RT2800PCI_PCI static struct pci_driver rt2800pci_driver = { @@ -1286,7 +1286,7 @@ static int __init rt2800pci_init(void) { int ret = 0; -#ifdef CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC ret = platform_driver_register(&rt2800soc_driver); if (ret) return ret; @@ -1294,7 +1294,7 @@ static int __init rt2800pci_init(void) #ifdef CONFIG_RT2800PCI_PCI ret = pci_register_driver(&rt2800pci_driver); if (ret) { -#ifdef CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC platform_driver_unregister(&rt2800soc_driver); #endif return ret; @@ -1309,7 +1309,7 @@ static void __exit rt2800pci_exit(void) #ifdef CONFIG_RT2800PCI_PCI pci_unregister_driver(&rt2800pci_driver); #endif -#ifdef CONFIG_RT2800PCI_WISOC +#ifdef CONFIG_RT2800PCI_SOC platform_driver_unregister(&rt2800soc_driver); #endif } -- cgit v1.2.3 From ac394917f5138f9bb2774718312dec179164f3dc Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 23 Dec 2009 00:03:23 +0100 Subject: rt2x00: Let rt2800lib check CONFIG_RT2X00_LIB_USB instead of CONFIG_RT2800USB rt2800lib currently checks whether RT2800USB is enabled in the configuration. Strictly speaking this is not necessary, it only needs to know whether the generic rt2x00usb library functions are available. Therefore check for RT2X00_LIB_USB instead. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 27bf887f1453..a654551b7325 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -37,7 +37,7 @@ #include #include "rt2x00.h" -#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) +#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) #include "rt2x00usb.h" #endif #include "rt2800lib.h" @@ -1121,7 +1121,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_intf_is_usb(rt2x00dev)) { rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); -#if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) +#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, USB_MODE_RESET, REGISTER_TIMEOUT); #endif -- cgit v1.2.3 From 73a2f1259ebb49f9768aa12eee2a1071345eb7f2 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 23 Dec 2009 00:03:24 +0100 Subject: rt2x00: convert RT2800PCI_PCI and RT2800PCI_SOC Kconfig symbols to booleans. There is no need for Kconfig symbols RT2800PCI_PCI and RT2800PCI_SOC to be tristates, as they are only used to check whether RT2800 PCI or SOC support is to be compiled in. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 4 ++-- drivers/net/wireless/rt2x00/rt2800pci.c | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bf60689aaabb..3ca824a91ad9 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -54,12 +54,12 @@ config RT61PCI When compiled as a module, this driver will be called rt61pci. config RT2800PCI_PCI - tristate + boolean depends on PCI default y config RT2800PCI_SOC - tristate + boolean depends on RALINK_RT288X || RALINK_RT305X default y diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 96e024477b2f..2f9deddaf75b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -48,14 +48,6 @@ #include "rt2800.h" #include "rt2800pci.h" -#ifdef CONFIG_RT2800PCI_PCI_MODULE -#define CONFIG_RT2800PCI_PCI -#endif - -#ifdef CONFIG_RT2800PCI_SOC_MODULE -#define CONFIG_RT2800PCI_SOC -#endif - /* * Allow hardware encryption to be disabled. */ -- cgit v1.2.3 From 5122d8986232ef2a761f5cf70c31666c4d65c3e4 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 23 Dec 2009 00:03:25 +0100 Subject: rt2x00: Cleanup chip handling helper functions. Let each of them take a struct rt2x00_dev pointer as argument instead of a mixture of struct rt2x00_chip and struct rt2x00_dev pointers. Preparation for further clean ups in the rt2x00 chip handling, especially for rt2800 devices. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 5 +- drivers/net/wireless/rt2x00/rt2500pci.c | 39 +++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 38 +++++++------- drivers/net/wireless/rt2x00/rt2800lib.c | 90 ++++++++++++++++----------------- drivers/net/wireless/rt2x00/rt2800pci.c | 3 +- drivers/net/wireless/rt2x00/rt2800usb.c | 4 +- drivers/net/wireless/rt2x00/rt2x00.h | 24 ++++----- drivers/net/wireless/rt2x00/rt61pci.c | 29 +++++------ drivers/net/wireless/rt2x00/rt73usb.c | 36 ++++++------- 9 files changed, 125 insertions(+), 143 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e7f46405a418..d86d233c6810 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, /* * RF2420 chipset don't need any additional actions. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2420)) + if (rt2x00_rf(rt2x00dev, RF2420)) return; /* @@ -1343,8 +1343,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip_rf(rt2x00dev, value, reg); rt2x00_print_chip(rt2x00dev); - if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && - !rt2x00_rf(&rt2x00dev->chip, RF2421)) { + if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 408fcfc120f5..46cbc6ef66ab 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, /* * RT2525E and RT5222 need to flip TX I/Q */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); @@ -449,7 +448,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, /* * RT2525E does not need RX I/Q Flip. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) + if (rt2x00_rf(rt2x00dev, RF2525E)) rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); } else { rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); @@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, * Switch on tuning bits. * For RT2523 devices we do not need to update the R1 register. */ - if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) + if (!rt2x00_rf(rt2x00dev, RF2523)) rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); /* * For RT2525 we should first set the channel to half band higher. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + if (rt2x00_rf(rt2x00dev, RF2525)) { static const u32 vals[] = { 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, @@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, * Switch off tuning bits. * For RT2523 devices we do not need to update the R1 register. */ - if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { + if (!rt2x00_rf(rt2x00dev, RF2523)) { rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); } @@ -640,7 +639,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, * up to version C the link tuning should halt after 20 * seconds while being associated. */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D && rt2x00dev->intf_associated && count > 20) return; @@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, * should go straight to dynamic CCA tuning when they * are not associated. */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || + if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D || !rt2x00dev->intf_associated) goto dynamic_cca_tune; @@ -1507,12 +1506,12 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip_rf(rt2x00dev, value, reg); rt2x00_print_chip(rt2x00dev); - if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && - !rt2x00_rf(&rt2x00dev->chip, RF2523) && - !rt2x00_rf(&rt2x00dev->chip, RF2524) && - !rt2x00_rf(&rt2x00dev->chip, RF2525) && - !rt2x00_rf(&rt2x00dev->chip, RF2525E) && - !rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (!rt2x00_rf(rt2x00dev, RF2522) && + !rt2x00_rf(rt2x00dev, RF2523) && + !rt2x00_rf(rt2x00dev, RF2524) && + !rt2x00_rf(rt2x00dev, RF2525) && + !rt2x00_rf(rt2x00dev, RF2525E) && + !rt2x00_rf(rt2x00dev, RF5222)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { + if (rt2x00_rf(rt2x00dev, RF2522)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); spec->channels = rf_vals_bg_2522; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { + } else if (rt2x00_rf(rt2x00dev, RF2523)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); spec->channels = rf_vals_bg_2523; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { + } else if (rt2x00_rf(rt2x00dev, RF2524)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); spec->channels = rf_vals_bg_2524; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + } else if (rt2x00_rf(rt2x00dev, RF2525)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); spec->channels = rf_vals_bg_2525; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + } else if (rt2x00_rf(rt2x00dev, RF2525E)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); spec->channels = rf_vals_bg_2525e; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + } else if (rt2x00_rf(rt2x00dev, RF5222)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5222); spec->channels = rf_vals_5222; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 83f2592c59de..9e6f865c57f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -565,8 +565,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, /* * RT2525E and RT5222 need to flip TX I/Q */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); @@ -574,7 +573,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, /* * RT2525E does not need RX I/Q Flip. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) + if (rt2x00_rf(rt2x00dev, RF2525E)) rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); } else { rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); @@ -598,7 +597,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, /* * For RT2525E we should first set the channel to half band higher. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + if (rt2x00_rf(rt2x00dev, RF2525E)) { static const u32 vals[] = { 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, @@ -793,7 +792,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { + if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); rt2x00_set_field16(®, PHY_CSR2_LNA, 0); } else { @@ -1411,19 +1410,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip(rt2x00dev, RT2570, value, reg); rt2x00_print_chip(rt2x00dev); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) || - rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { - + if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || + rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } - if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && - !rt2x00_rf(&rt2x00dev->chip, RF2523) && - !rt2x00_rf(&rt2x00dev->chip, RF2524) && - !rt2x00_rf(&rt2x00dev->chip, RF2525) && - !rt2x00_rf(&rt2x00dev->chip, RF2525E) && - !rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (!rt2x00_rf(rt2x00dev, RF2522) && + !rt2x00_rf(rt2x00dev, RF2523) && + !rt2x00_rf(rt2x00dev, RF2524) && + !rt2x00_rf(rt2x00dev, RF2525) && + !rt2x00_rf(rt2x00dev, RF2525E) && + !rt2x00_rf(rt2x00dev, RF5222)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -1667,22 +1665,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { + if (rt2x00_rf(rt2x00dev, RF2522)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); spec->channels = rf_vals_bg_2522; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { + } else if (rt2x00_rf(rt2x00dev, RF2523)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); spec->channels = rf_vals_bg_2523; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { + } else if (rt2x00_rf(rt2x00dev, RF2524)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); spec->channels = rf_vals_bg_2524; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + } else if (rt2x00_rf(rt2x00dev, RF2525)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); spec->channels = rf_vals_bg_2525; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + } else if (rt2x00_rf(rt2x00dev, RF2525E)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); spec->channels = rf_vals_bg_2525e; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + } else if (rt2x00_rf(rt2x00dev, RF5222)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5222); spec->channels = rf_vals_5222; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a654551b7325..8ff7db853286 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -220,8 +220,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, /* * RT2880 and RT3052 don't support MCU requests. */ - if (rt2x00_rt(&rt2x00dev->chip, RT2880) || - rt2x00_rt(&rt2x00dev->chip, RT3052)) + if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052)) return; mutex_lock(&rt2x00dev->csr_mutex); @@ -806,12 +805,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, unsigned int tx_pin; u8 bbp; - if ((rt2x00_rt(&rt2x00dev->chip, RT3070) || - rt2x00_rt(&rt2x00dev->chip, RT3090)) && - (rt2x00_rf(&rt2x00dev->chip, RF2020) || - rt2x00_rf(&rt2x00dev->chip, RF3020) || - rt2x00_rf(&rt2x00dev->chip, RF3021) || - rt2x00_rf(&rt2x00dev->chip, RF3022))) + if ((rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3090)) && + (rt2x00_rf(rt2x00dev, RF2020) || + rt2x00_rf(rt2x00dev, RF3020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022))) rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); else rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); @@ -878,7 +877,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); rt2800_bbp_write(rt2x00dev, 3, bbp); - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { if (conf_is_ht40(conf)) { rt2800_bbp_write(rt2x00dev, 69, 0x1a); rt2800_bbp_write(rt2x00dev, 70, 0x0a); @@ -1041,7 +1040,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) + rt2x00_rev(rt2x00dev) == RT3070_VERSION) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1072,7 +1071,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count) { - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) return; /* @@ -1158,7 +1157,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2x00_rev(rt2x00dev) == RT3070_VERSION) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); @@ -1185,8 +1184,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && - rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) + if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION && + rt2x00_rev(rt2x00dev) < RT3070_VERSION) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); else rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); @@ -1465,22 +1464,22 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 73, 0x12); } - if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) + if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) rt2800_bbp_write(rt2x00dev, 84, 0x19); if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { + rt2x00_rev(rt2x00dev) == RT3070_VERSION) { rt2800_bbp_write(rt2x00dev, 70, 0x0a); rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 105, 0x05); } - if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { + if (rt2x00_rt(rt2x00dev, RT3052)) { rt2800_bbp_write(rt2x00dev, 31, 0x08); rt2800_bbp_write(rt2x00dev, 78, 0x0e); rt2800_bbp_write(rt2x00dev, 80, 0x08); @@ -1566,13 +1565,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u8 bbp; if (rt2x00_intf_is_usb(rt2x00dev) && - rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) + rt2x00_rev(rt2x00dev) != RT3070_VERSION) return 0; if (rt2x00_intf_is_pci(rt2x00dev)) { - if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && - !rt2x00_rf(&rt2x00dev->chip, RF3021) && - !rt2x00_rf(&rt2x00dev->chip, RF3022)) + if (!rt2x00_rf(rt2x00dev, RF3020) && + !rt2x00_rf(rt2x00dev, RF3021) && + !rt2x00_rf(rt2x00dev, RF3022)) return 0; } @@ -1737,7 +1736,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { + } else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) { /* * There is a max of 2 RX streams for RT28x0 series */ @@ -1839,17 +1838,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip_rf(rt2x00dev, value, reg); if (rt2x00_intf_is_usb(rt2x00dev)) { - struct rt2x00_chip *chip = &rt2x00dev->chip; - /* * The check for rt2860 is not a typo, some rt2870 hardware * identifies itself as rt2860 in the CSR register. */ - if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) || - rt2x00_check_rev(chip, 0xfff00000, 0x28700000) || - rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) { + if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) || + rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) || + rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) { rt2x00_set_chip_rt(rt2x00dev, RT2870); - } else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) { + } else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) { rt2x00_set_chip_rt(rt2x00dev, RT3070); } else { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); @@ -1858,14 +1855,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) } rt2x00_print_chip(rt2x00dev); - if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && - !rt2x00_rf(&rt2x00dev->chip, RF2850) && - !rt2x00_rf(&rt2x00dev->chip, RF2720) && - !rt2x00_rf(&rt2x00dev->chip, RF2750) && - !rt2x00_rf(&rt2x00dev->chip, RF3020) && - !rt2x00_rf(&rt2x00dev->chip, RF2020) && - !rt2x00_rf(&rt2x00dev->chip, RF3021) && - !rt2x00_rf(&rt2x00dev->chip, RF3022)) { + if (!rt2x00_rf(rt2x00dev, RF2820) && + !rt2x00_rf(rt2x00dev, RF2850) && + !rt2x00_rf(rt2x00dev, RF2720) && + !rt2x00_rf(rt2x00dev, RF2750) && + !rt2x00_rf(rt2x00dev, RF3020) && + !rt2x00_rf(rt2x00dev, RF2020) && + !rt2x00_rf(rt2x00dev, RF3021) && + !rt2x00_rf(rt2x00dev, RF3022)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2013,7 +2010,6 @@ static const struct rf_channel rf_vals_302x[] = { int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { - struct rt2x00_chip *chip = &rt2x00dev->chip; struct hw_mode_spec *spec = &rt2x00dev->spec; struct channel_info *info; char *tx_power1; @@ -2049,19 +2045,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (rt2x00_rf(chip, RF2820) || - rt2x00_rf(chip, RF2720) || - (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) { + if (rt2x00_rf(rt2x00dev, RF2820) || + rt2x00_rf(rt2x00dev, RF2720) || + (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) { spec->num_channels = 14; spec->channels = rf_vals; - } else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) { + } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals); spec->channels = rf_vals; - } else if (rt2x00_rf(chip, RF3020) || - rt2x00_rf(chip, RF2020) || - rt2x00_rf(chip, RF3021) || - rt2x00_rf(chip, RF3022)) { + } else if (rt2x00_rf(rt2x00dev, RF3020) || + rt2x00_rf(rt2x00dev, RF2020) || + rt2x00_rf(rt2x00dev, RF3021) || + rt2x00_rf(rt2x00dev, RF3022)) { spec->num_channels = ARRAY_SIZE(rf_vals_302x); spec->channels = rf_vals_302x; } @@ -2069,7 +2065,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize HT information. */ - if (!rt2x00_rf(chip, RF2020)) + if (!rt2x00_rf(rt2x00dev, RF2020)) spec->ht.ht_supported = true; else spec->ht.ht_supported = false; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2f9deddaf75b..b93eabb4fbe1 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1121,8 +1121,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires firmware. */ - if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && - !rt2x00_rt(&rt2x00dev->chip, RT3052)) + if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052)) __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 40295b454ff6..411655ecaf3a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -92,7 +92,7 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { - u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; size_t offset = 0; /* @@ -138,7 +138,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, u32 reg; u32 offset; u32 length; - u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; + u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; /* * Check which section of the firmware we need. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 194dae01d0c3..a664a999b2b0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -937,25 +937,25 @@ static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); } -static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) +static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) { - return (chipset->rt == chip); + return (rt2x00dev->chip.rt == rt); } -static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) +static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) { - return (chipset->rf == chip); + return (rt2x00dev->chip.rf == rf); } -static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) +static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev) { - return chipset->rev; + return rt2x00dev->chip.rev; } -static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, +static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev, const u32 mask, const u32 rev) { - return ((chipset->rev & mask) == rev); + return ((rt2x00dev->chip.rev & mask) == rev); } static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, @@ -964,20 +964,20 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, rt2x00dev->chip.intf = intf; } -static inline bool rt2x00_intf(const struct rt2x00_chip *chipset, +static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, enum rt2x00_chip_intf intf) { - return (chipset->intf == intf); + return (rt2x00dev->chip.intf == intf); } static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) { - return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI); + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); } static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) { - return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB); + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); } /** diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0ca589306d71..c353b497a65d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, rt61pci_bbp_read(rt2x00dev, 4, &r4); rt61pci_bbp_read(rt2x00dev, 77, &r77); - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, - rt2x00_rf(&rt2x00dev->chip, RF5325)); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325)); /* * Configure the RX antenna. @@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt61pci_bbp_read(rt2x00dev, 4, &r4); rt61pci_bbp_read(rt2x00dev, 77, &r77); - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, - rt2x00_rf(&rt2x00dev->chip, RF2529)); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); @@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF5325)) + if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) rt61pci_config_antenna_5x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) + else if (rt2x00_rf(rt2x00dev, RF2527)) rt61pci_config_antenna_2x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { + else if (rt2x00_rf(rt2x00dev, RF2529)) { if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) rt61pci_config_antenna_2x(rt2x00dev, ant); else @@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)); + smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); rt61pci_bbp_read(rt2x00dev, 3, &r3); rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); @@ -2302,10 +2298,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip_rf(rt2x00dev, value, reg); rt2x00_print_chip(rt2x00dev); - if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && - !rt2x00_rf(&rt2x00dev->chip, RF5325) && - !rt2x00_rf(&rt2x00dev->chip, RF2527) && - !rt2x00_rf(&rt2x00dev->chip, RF2529)) { + if (!rt2x00_rf(rt2x00dev, RF5225) && + !rt2x00_rf(rt2x00dev, RF5325) && + !rt2x00_rf(rt2x00dev, RF2527) && + !rt2x00_rf(rt2x00dev, RF2529)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2360,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * the antenna settings should be gathered from the NIC * eeprom word. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2529) && + if (rt2x00_rf(rt2x00dev, RF2529) && !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { rt2x00dev->default_ant.rx = ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); @@ -2571,8 +2567,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels = rf_vals_seq; } - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF5325)) { + if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_seq); } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6ce88d3c3b65..a02691294395 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, * all others contain 20 bits. */ rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, - 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527))); + 20 + (rt2x00_rf(rt2x00dev, RF5225) || + rt2x00_rf(rt2x00dev, RF2527))); rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); @@ -741,11 +741,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); - if (rt2x00_rf(&rt2x00dev->chip, RF5226) || - rt2x00_rf(&rt2x00dev->chip, RF5225)) + if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225)) rt73usb_config_antenna_5x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) + else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527)) rt73usb_config_antenna_2x(rt2x00dev, ant); } @@ -779,8 +777,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)); + smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); rt73usb_bbp_read(rt2x00dev, 3, &r3); rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); @@ -1210,8 +1207,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); reg = 0x000023b0; - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) + if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)) rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); @@ -1827,16 +1823,16 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip(rt2x00dev, RT2571, value, reg); rt2x00_print_chip(rt2x00dev); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || - rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { + if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || + rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } - if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && - !rt2x00_rf(&rt2x00dev->chip, RF2528) && - !rt2x00_rf(&rt2x00dev->chip, RF5225) && - !rt2x00_rf(&rt2x00dev->chip, RF2527)) { + if (!rt2x00_rf(rt2x00dev, RF5226) && + !rt2x00_rf(rt2x00dev, RF2528) && + !rt2x00_rf(rt2x00dev, RF5225) && + !rt2x00_rf(rt2x00dev, RF2527)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2081,17 +2077,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { + if (rt2x00_rf(rt2x00dev, RF2528)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); spec->channels = rf_vals_bg_2528; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { + } else if (rt2x00_rf(rt2x00dev, RF5226)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5226); spec->channels = rf_vals_5226; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { + } else if (rt2x00_rf(rt2x00dev, RF2527)) { spec->num_channels = 14; spec->channels = rf_vals_5225_2527; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { + } else if (rt2x00_rf(rt2x00dev, RF5225)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); spec->channels = rf_vals_5225_2527; -- cgit v1.2.3 From 643aab6733799586c798a7b54b85c34d587b25e3 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 22 Dec 2009 18:13:04 -0500 Subject: rtl8180: remove priv->mode It is only checked in add_interface, and there it is easily replaced with a check of priv->vif. If that information should become necessary, it is available in vif->type anyway. Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180.h | 1 - drivers/net/wireless/rtl818x/rtl8180_dev.c | 14 +++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..de3844fe06d8 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h @@ -60,7 +60,6 @@ struct rtl8180_priv { struct rtl818x_csr __iomem *map; const struct rtl818x_rf_ops *rf; struct ieee80211_vif *vif; - int mode; /* rtl8180 driver specific */ spinlock_t lock; diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 8a40a1439984..f01f1ef9e3be 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -82,8 +82,6 @@ static const struct ieee80211_channel rtl818x_channels[] = { }; - - void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) { struct rtl8180_priv *priv = dev->priv; @@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev) reg |= RTL818X_CMD_TX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); - priv->mode = NL80211_IFTYPE_MONITOR; return 0; err_free_rings: @@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev) u8 reg; int i; - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); reg = rtl818x_ioread8(priv, &priv->map->CMD); @@ -661,12 +656,14 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, { struct rtl8180_priv *priv = dev->priv; - if (priv->mode != NL80211_IFTYPE_MONITOR) - return -EOPNOTSUPP; + /* + * We only support one active interface at a time. + */ + if (priv->vif) + return -EBUSY; switch (conf->type) { case NL80211_IFTYPE_STATION: - priv->mode = conf->type; break; default: return -EOPNOTSUPP; @@ -688,7 +685,6 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct rtl8180_priv *priv = dev->priv; - priv->mode = NL80211_IFTYPE_MONITOR; priv->vif = NULL; } -- cgit v1.2.3 From d30506e0357e5448c7d38bb3739c451dbe4c174e Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 22 Dec 2009 18:13:05 -0500 Subject: rtl8187: remove priv->mode It is checked in add_interface, but there it is easily replaced with a check of priv->vif. If that information should become necessary, it is available in vif->type anyway. It is also checked in led_turn_on and led_turn_off, where I made the substitutions as described above. Of course, these checks seem to have been incorrect since the driver was using NL80211_IFTYPE_MONITOR to indicate no interface rather than NL80211_IFTYPE_UNSPECIFIED. Anyway, I think these checks may be extraneous...? Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187.h | 2 +- drivers/net/wireless/rtl818x/rtl8187_dev.c | 5 +---- drivers/net/wireless/rtl818x/rtl8187_leds.c | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 6af0f3f71f3a..6bb32112e65c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h @@ -92,7 +92,7 @@ struct rtl8187_priv { struct rtl818x_csr *map; const struct rtl818x_rf_ops *rf; struct ieee80211_vif *vif; - int mode; + /* The mutex protects the TX loopback state. * Any attempt to set channels concurrently locks the device. */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index bc5726dd5fe4..1cb0eff46223 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1025,12 +1025,11 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, int ret = -EOPNOTSUPP; mutex_lock(&priv->conf_mutex); - if (priv->mode != NL80211_IFTYPE_MONITOR) + if (priv->vif) goto exit; switch (conf->type) { case NL80211_IFTYPE_STATION: - priv->mode = conf->type; break; default: goto exit; @@ -1055,7 +1054,6 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev, { struct rtl8187_priv *priv = dev->priv; mutex_lock(&priv->conf_mutex); - priv->mode = NL80211_IFTYPE_MONITOR; priv->vif = NULL; mutex_unlock(&priv->conf_mutex); } @@ -1365,7 +1363,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - priv->mode = NL80211_IFTYPE_MONITOR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_RX_INCLUDES_FCS; diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index ded44c045eb2..f82aa8b4bdde 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work) struct rtl8187_led *led = &priv->led_tx; /* Don't change the LED, when the device is down. */ - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) return ; /* Skip if the LED is not registered. */ @@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work) struct rtl8187_led *led = &priv->led_tx; /* Don't change the LED, when the device is down. */ - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) + if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) return ; /* Skip if the LED is not registered. */ -- cgit v1.2.3 From 9607e6b66a0d25ca63b70d54a4283fa13d8f7c9d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:31 +0100 Subject: mac80211: add ieee80211_sdata_running Instead of always using netif_running(sdata->dev) use ieee80211_sdata_running(sdata) now which is just an inline containing netif_running() for now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 6 ++---- net/mac80211/ibss.c | 4 ++-- net/mac80211/ieee80211_i.h | 5 +++++ net/mac80211/iface.c | 10 +++++----- net/mac80211/key.c | 4 ++-- net/mac80211/main.c | 2 +- net/mac80211/mesh.c | 2 +- net/mac80211/mlme.c | 8 ++++---- net/mac80211/pm.c | 2 +- net/mac80211/rx.c | 6 +++--- net/mac80211/scan.c | 12 ++++++------ net/mac80211/sta_info.c | 2 +- net/mac80211/status.c | 2 +- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 10 +++++----- 15 files changed, 40 insertions(+), 37 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 63843e3e576a..fdac1bcbfcc0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret; - if (netif_running(dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; if (!nl80211_params_check(type, params)) return -EINVAL; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ret = ieee80211_if_change_type(sdata, type); if (ret) return ret; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ef6c6b2401d1..3a61f3ba85c9 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -744,7 +744,7 @@ static void ieee80211_ibss_work(struct work_struct *work) if (WARN_ON(local->suspended)) return; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) @@ -827,7 +827,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_ADHOC) continue; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 88b0ba6c7484..adeae03c26a3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -960,6 +960,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); u32 __ieee80211_recalc_idle(struct ieee80211_local *local); void ieee80211_recalc_idle(struct ieee80211_local *local); +static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) +{ + return netif_running(sdata->dev); +} + /* tx handling */ void ieee80211_clear_tx_pending(struct ieee80211_local *local); void ieee80211_tx_pending(unsigned long data); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a6e6da3cab70..1ceca14331d4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -65,7 +65,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); int ret; - if (netif_running(dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; ret = eth_mac_addr(dev, addr); @@ -111,7 +111,7 @@ static int ieee80211_open(struct net_device *dev) list_for_each_entry(nsdata, &local->interfaces, list) { struct net_device *ndev = nsdata->dev; - if (ndev != dev && netif_running(ndev)) { + if (ndev != dev && ieee80211_sdata_running(nsdata)) { /* * Allow only a single IBSS interface to be up at any * time. This is restricted because beacon distribution @@ -197,7 +197,7 @@ static int ieee80211_open(struct net_device *dev) struct net_device *ndev = nsdata->dev; /* - * No need to check netif_running since we do not allow + * No need to check running since we do not allow * it to start up with this invalid address. */ if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { @@ -756,7 +756,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, * and goes into the requested mode. */ - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) return -EBUSY; /* Purge and reset type-dependent state. */ @@ -930,7 +930,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) return ieee80211_idle_off(local, "scanning"); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 32ee6d0ee34d..8160d9c5372e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key, add_todo(old_key, KEY_FLAG_TODO_DELETE); add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); spin_unlock_irqrestore(&sdata->local->key_lock, flags); @@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) { ASSERT_RTNL(); - if (WARN_ON(!netif_running(sdata->dev))) + if (WARN_ON(!ieee80211_sdata_running(sdata))) return; ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d4426748ab10..e93bc558d785 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -212,7 +212,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, } if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (local->quiescing || !netif_running(sdata->dev) || + if (local->quiescing || !ieee80211_sdata_running(sdata) || test_bit(SCAN_SW_SCANNING, &local->scanning)) { sdata->vif.bss_conf.enable_beacon = false; } else { diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e0bd85e3d4b6..61080c5fad50 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work) struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct sk_buff *skb; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f9ed8b9c3f0..7f9909340c09 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -604,7 +604,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; mutex_lock(&ifmgd->mtx); @@ -750,7 +750,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) } list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; @@ -1263,7 +1263,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; bool already = false; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (sdata->local->scanning) @@ -2118,7 +2118,7 @@ static void ieee80211_sta_work(struct work_struct *work) enum rx_mgmt_action rma; bool anybusy = false; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) return; if (local->scanning) diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 05e161c3cbc5..913dc7e3b29e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -93,7 +93,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) break; } - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* disable beaconing */ diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6cbf1a7b3157..f60dfca52196 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -289,7 +289,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) continue; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (prev_dev) { @@ -2056,7 +2056,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, skb->protocol = htons(ETH_P_802_2); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type != NL80211_IFTYPE_MONITOR || @@ -2318,7 +2318,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (!found_sta) { list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_MONITOR || diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 66da0ab1d8fa..ae1830056521 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -346,7 +346,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* Tell AP we're back */ @@ -396,7 +396,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* disable beaconing */ @@ -526,7 +526,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, /* check if at least one STA interface is associated */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -571,7 +571,7 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if (sdata->vif.type == NL80211_IFTYPE_STATION) { @@ -603,7 +603,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; /* Tell AP we're back */ @@ -727,7 +727,7 @@ void ieee80211_scan_work(struct work_struct *work) /* * Avoid re-scheduling when the sdata is going away. */ - if (!netif_running(sdata->dev)) { + if (!ieee80211_sdata_running(sdata)) { ieee80211_scan_completed(&local->hw, true); return; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d1a77e79d7a9..f039e761aec1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -367,7 +367,7 @@ int sta_info_insert(struct sta_info *sta) * something inserts a STA (on one CPU) without holding the RTNL * and another CPU turns off the net device. */ - if (unlikely(!netif_running(sdata->dev))) { + if (unlikely(!ieee80211_sdata_running(sdata))) { err = -ENETDOWN; goto out_free; } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 0c0850d37dda..0ebcdda24200 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -351,7 +351,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_lock(); list_for_each_entry_rcu(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ac48c86ae6b3..1593a2ffd67a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1469,7 +1469,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) { - if (!netif_running(tmp_sdata->dev)) + if (!ieee80211_sdata_running(tmp_sdata)) continue; if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) continue; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b01972579c7c..5ffe9e831b66 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces( case NL80211_IFTYPE_MESH_POINT: break; } - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) iterator(data, sdata->vif.addr, &sdata->vif); } @@ -502,7 +502,7 @@ void ieee80211_iterate_active_interfaces_atomic( case NL80211_IFTYPE_MESH_POINT: break; } - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) iterator(data, sdata->vif.addr, &sdata->vif); } @@ -1056,7 +1056,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && - netif_running(sdata->dev)) { + ieee80211_sdata_running(sdata)) { conf.vif = &sdata->vif; conf.type = sdata->vif.type; conf.mac_addr = sdata->vif.addr; @@ -1103,7 +1103,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* Finally also reconfigure all the BSS information */ list_for_each_entry(sdata, &local->interfaces, list) { u32 changed = ~0; - if (!netif_running(sdata->dev)) + if (!ieee80211_sdata_running(sdata)) continue; switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: @@ -1131,7 +1131,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* add back keys */ list_for_each_entry(sdata, &local->interfaces, list) - if (netif_running(sdata->dev)) + if (ieee80211_sdata_running(sdata)) ieee80211_enable_keys(sdata); ieee80211_wake_queues_by_reason(hw, -- cgit v1.2.3 From a80f7c0b088187c8471b441d461e937991870661 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:32 +0100 Subject: mac80211: introduce flush operation We've long lacked a good confirmation that frames have really gone out, e.g. before going off-channel for a scan. Add a flush() operation that drivers can implement to provide that confirmation, and use it in a few places: * before scanning sends the nullfunc frames * after scanning sends the nullfunc frames, if any * when going idle, to send any pending frames Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 11 +++++++++++ include/net/mac80211.h | 5 +++++ net/mac80211/driver-ops.h | 7 +++++++ net/mac80211/driver-trace.h | 21 +++++++++++++++++++++ net/mac80211/iface.c | 2 ++ net/mac80211/scan.c | 13 +++++++++++-- 6 files changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 718a5f198c30..4dee69a38c1d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -896,6 +896,16 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, return 0; } +static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) +{ + /* + * In this special case, there's nothing we need to + * do because hwsim does transmission synchronously. + * In the future, when it does transmissions via + * userspace, we may need to do something. + */ +} + static const struct ieee80211_ops mac80211_hwsim_ops = { @@ -912,6 +922,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = .conf_tx = mac80211_hwsim_conf_tx, CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) .ampdu_action = mac80211_hwsim_ampdu_action, + .flush = mac80211_hwsim_flush, }; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 494ac69ff477..77ea34b03285 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1545,6 +1545,10 @@ enum ieee80211_ampdu_mlme_action { * and need to call wiphy_rfkill_set_hw_state() in the callback. * * @testmode_cmd: Implement a cfg80211 test mode command. + * + * @flush: Flush all pending frames from the hardware queue, making sure + * that the hardware queues are empty. If the parameter @drop is set + * to %true, pending frames may be dropped. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); @@ -1601,6 +1605,7 @@ struct ieee80211_ops { #ifdef CONFIG_NL80211_TESTMODE int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); #endif + void (*flush)(struct ieee80211_hw *hw, bool drop); }; /** diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 727e4cf7b8a6..cbe133bcdf34 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -259,4 +259,11 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local) if (local->ops->rfkill_poll) local->ops->rfkill_poll(&local->hw); } + +static inline void drv_flush(struct ieee80211_local *local, bool drop) +{ + trace_drv_flush(local, drop); + if (local->ops->flush) + local->ops->flush(&local->hw, drop); +} #endif /* __MAC80211_DRIVER_OPS */ diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7a849b920165..977cc7528bc6 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -690,6 +690,27 @@ TRACE_EVENT(drv_ampdu_action, LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret ) ); + +TRACE_EVENT(drv_flush, + TP_PROTO(struct ieee80211_local *local, bool drop), + + TP_ARGS(local, drop), + + TP_STRUCT__entry( + LOCAL_ENTRY + __field(bool, drop) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + __entry->drop = drop; + ), + + TP_printk( + LOCAL_PR_FMT " drop:%d", + LOCAL_PR_ARG, __entry->drop + ) +); #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 1ceca14331d4..389dc8d880f3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -917,6 +917,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) wiphy_name(local->hw.wiphy)); #endif + drv_flush(local, false); + local->hw.conf.flags |= IEEE80211_CONF_IDLE; return IEEE80211_CONF_CHANGE_IDLE; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ae1830056521..d98c45e5528b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -418,9 +418,10 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; + drv_flush(local, false); + ieee80211_configure_filter(local); - /* TODO: start scan as soon as all nullfunc frames are ACKed */ ieee80211_queue_delayed_work(&local->hw, &local->scan_work, IEEE80211_CHANNEL_TIME); @@ -584,8 +585,16 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca __set_bit(SCAN_OFF_CHANNEL, &local->scanning); + /* + * What if the nullfunc frames didn't arrive? + */ + drv_flush(local, false); + if (local->ops->flush) + *next_delay = 0; + else + *next_delay = HZ / 10; + /* advance to the next channel to be scanned */ - *next_delay = HZ / 10; local->next_scan_state = SCAN_SET_CHANNEL; } -- cgit v1.2.3 From 63f170e0c80a131cdd549fab7afb5036009944fc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:33 +0100 Subject: mac80211: let cfg80211 manage auth state mac80211 currently hangs on to the auth state by keeping it on the work list. That can lead to confusing behaviour like rejecting scans while authenticated to any AP (but not yet associated.) It also means that it needs to keep track of the work struct while associated for when it gets disassociated (or disassociates.) Change this to free the work struct after the authentication completed successfully and allocate a new one for associating, thereby letting cfg80211 manage the auth state. Another change necessary for this is to tell cfg80211 about all unicast deauth frames sent to mac80211 since now it can no longer check the auth state, but that check was racy anyway. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 3 +- net/mac80211/mlme.c | 173 +++++++++++++++++++-------------------------- 2 files changed, 73 insertions(+), 103 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index adeae03c26a3..e21e0301548b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -228,7 +228,7 @@ struct mesh_preq_queue { }; enum ieee80211_mgd_state { - IEEE80211_MGD_STATE_IDLE, + IEEE80211_MGD_STATE_INVALID, IEEE80211_MGD_STATE_PROBE, IEEE80211_MGD_STATE_AUTH, IEEE80211_MGD_STATE_ASSOC, @@ -285,7 +285,6 @@ struct ieee80211_if_managed { struct mutex mtx; struct ieee80211_bss *associated; - struct ieee80211_mgd_work *old_associate_work; struct list_head work_list; u8 bssid[ETH_ALEN]; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7f9909340c09..f060bc616203 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -949,11 +949,10 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, } static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, + struct ieee80211_bss *bss, u32 bss_info_changed) { struct ieee80211_local *local = sdata->local; - struct ieee80211_bss *bss = wk->bss; bss_info_changed |= BSS_CHANGED_ASSOC; /* set timing information */ @@ -966,7 +965,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, bss->cbss.capability, bss->has_erp_value, bss->erp_value); sdata->u.mgd.associated = bss; - sdata->u.mgd.old_associate_work = wk; memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); /* just to be sure */ @@ -1090,8 +1088,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, return RX_MGMT_NONE; } -static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, - bool deauth) +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; @@ -1109,16 +1106,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ifmgd->associated = NULL; memset(ifmgd->bssid, 0, ETH_ALEN); - if (deauth) { - kfree(ifmgd->old_associate_work); - ifmgd->old_associate_work = NULL; - } else { - struct ieee80211_mgd_work *wk = ifmgd->old_associate_work; - - wk->state = IEEE80211_MGD_STATE_IDLE; - list_add(&wk->list, &ifmgd->work_list); - } - /* * we need to commit the associated = NULL change because the * scan code uses that to determine whether this iface should @@ -1333,7 +1320,8 @@ EXPORT_SYMBOL(ieee80211_beacon_loss); static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgd_work *wk) { - wk->state = IEEE80211_MGD_STATE_IDLE; + list_del(&wk->list); + kfree(wk); printk(KERN_DEBUG "%s: authenticated\n", sdata->name); } @@ -1411,7 +1399,6 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, static enum rx_mgmt_action __must_check ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -1423,23 +1410,15 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ASSERT_MGD_MTX(ifmgd); - if (wk) - bssid = wk->bss->cbss.bssid; - else - bssid = ifmgd->associated->cbss.bssid; + bssid = ifmgd->associated->cbss.bssid; reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", sdata->name, bssid, reason_code); - if (!wk) { - ieee80211_set_disassoc(sdata, true); - ieee80211_recalc_idle(sdata->local); - } else { - list_del(&wk->list); - kfree(wk); - } + ieee80211_set_disassoc(sdata); + ieee80211_recalc_idle(sdata->local); return RX_MGMT_CFG80211_DEAUTH; } @@ -1468,7 +1447,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", sdata->name, mgmt->sa, reason_code); - ieee80211_set_disassoc(sdata, false); + ieee80211_set_disassoc(sdata); ieee80211_recalc_idle(sdata->local); return RX_MGMT_CFG80211_DISASSOC; } @@ -1484,6 +1463,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; + struct ieee80211_bss *bss = wk->bss; u32 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; @@ -1502,7 +1482,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (len < 24 + 6) return RX_MGMT_NONE; - if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) + if (memcmp(bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) return RX_MGMT_NONE; capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); @@ -1532,10 +1512,17 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, return RX_MGMT_NONE; } + /* + * Here the association was either successful or not. + */ + + /* delete work item -- must be before set_associated for PS */ + list_del(&wk->list); + kfree(wk); + if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", sdata->name, status_code); - wk->state = IEEE80211_MGD_STATE_IDLE; return RX_MGMT_CFG80211_ASSOC; } @@ -1553,7 +1540,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: associated\n", sdata->name); ifmgd->aid = aid; - sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); + sta = sta_info_alloc(sdata, bss->cbss.bssid, GFP_KERNEL); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" " the AP\n", sdata->name); @@ -1645,18 +1632,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, - wk->bss->cbss.bssid, + bss->cbss.bssid, ap_ht_cap_flags); - /* delete work item -- must be before set_associated for PS */ - list_del(&wk->list); - /* set AID and assoc capability, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - /* this will take ownership of wk */ - ieee80211_set_associated(sdata, wk, changed); + ieee80211_set_associated(sdata, bss, changed); /* * Start timer to probe the connection to the AP now. @@ -1999,8 +1982,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, skb->len, rx_status); break; case IEEE80211_STYPE_DEAUTH: - rma = ieee80211_rx_mgmt_deauth(sdata, NULL, - mgmt, skb->len); + rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); break; case IEEE80211_STYPE_DISASSOC: rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); @@ -2051,8 +2033,15 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, skb->len, true); break; case IEEE80211_STYPE_DEAUTH: - rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt, - skb->len); + if (skb->len >= 24 + 2 /* mgmt + deauth reason */) { + /* + * We get here if we get deauth while + * trying to auth/assoc. Telling cfg80211 + * is handled below, unconditionally. + */ + list_del(&wk->list); + kfree(wk); + } break; } /* @@ -2066,6 +2055,12 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); + if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && + (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { + WARN_ON(rma != RX_MGMT_NONE); + rma = RX_MGMT_CFG80211_DEAUTH; + } + switch (rma) { case RX_MGMT_NONE: /* no action */ @@ -2116,7 +2111,6 @@ static void ieee80211_sta_work(struct work_struct *work) struct ieee80211_mgd_work *wk, *tmp; LIST_HEAD(free_work); enum rx_mgmt_action rma; - bool anybusy = false; if (!ieee80211_sdata_running(sdata)) return; @@ -2171,7 +2165,7 @@ static void ieee80211_sta_work(struct work_struct *work) printk(KERN_DEBUG "No probe response from AP %pM" " after %dms, disconnecting.\n", bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); - ieee80211_set_disassoc(sdata, true); + ieee80211_set_disassoc(sdata); ieee80211_recalc_idle(local); mutex_unlock(&ifmgd->mtx); /* @@ -2203,8 +2197,6 @@ static void ieee80211_sta_work(struct work_struct *work) switch (wk->state) { default: WARN_ON(1); - /* fall through */ - case IEEE80211_MGD_STATE_IDLE: /* nothing */ rma = RX_MGMT_NONE; break; @@ -2227,20 +2219,19 @@ static void ieee80211_sta_work(struct work_struct *work) case RX_MGMT_CFG80211_ASSOC_TO: list_del(&wk->list); list_add(&wk->list, &free_work); - wk->tries = rma; /* small abuse but only local */ + /* + * small abuse but only local -- keep the + * action type in wk->timeout while the item + * is on the cleanup list + */ + wk->timeout = rma; break; default: WARN(1, "unexpected: %d", rma); } } - list_for_each_entry(wk, &ifmgd->work_list, list) { - if (wk->state != IEEE80211_MGD_STATE_IDLE) { - anybusy = true; - break; - } - } - if (!anybusy && + if (list_empty(&ifmgd->work_list) && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) ieee80211_queue_delayed_work(&local->hw, &local->scan_work, @@ -2249,7 +2240,8 @@ static void ieee80211_sta_work(struct work_struct *work) mutex_unlock(&ifmgd->mtx); list_for_each_entry_safe(wk, tmp, &free_work, list) { - switch (wk->tries) { + /* see above how we're using wk->timeout */ + switch (wk->timeout) { case RX_MGMT_CFG80211_AUTH_TO: cfg80211_send_auth_timeout(sdata->dev, wk->bss->cbss.bssid); @@ -2259,7 +2251,7 @@ static void ieee80211_sta_work(struct work_struct *work) wk->bss->cbss.bssid); break; default: - WARN(1, "unexpected: %d", wk->tries); + WARN(1, "unexpected: %lu", wk->timeout); } list_del(&wk->list); @@ -2487,35 +2479,18 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_mgd_work *wk, *found = NULL; + struct ieee80211_mgd_work *wk; + const u8 *ssid; int i, err; mutex_lock(&ifmgd->mtx); - list_for_each_entry(wk, &ifmgd->work_list, list) { - if (&wk->bss->cbss == req->bss && - wk->state == IEEE80211_MGD_STATE_IDLE) { - found = wk; - break; - } - } - - if (!found) { - err = -ENOLINK; - goto out; - } - - list_del(&found->list); - - wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL); + wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); if (!wk) { - list_add(&found->list, &ifmgd->work_list); err = -ENOMEM; goto out; } - list_add(&wk->list, &ifmgd->work_list); - ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) @@ -2524,8 +2499,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; - sdata->local->oper_channel = req->bss->channel; - ieee80211_hw_config(sdata->local, 0); if (req->ie && req->ie_len) { memcpy(wk->ie, req->ie, req->ie_len); @@ -2533,11 +2506,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } else wk->ie_len = 0; + wk->bss = (void *)req->bss; + + ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); + memcpy(wk->ssid, ssid + 2, ssid[1]); + wk->ssid_len = ssid[1]; + if (req->prev_bssid) memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN); wk->state = IEEE80211_MGD_STATE_ASSOC; - wk->tries = 0; wk->timeout = jiffies; /* run right away */ if (req->use_mfp) { @@ -2553,6 +2531,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, else ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; + sdata->local->oper_channel = req->bss->channel; + ieee80211_hw_config(sdata->local, 0); + + list_add(&wk->list, &ifmgd->work_list); ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); err = 0; @@ -2568,23 +2550,23 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_mgd_work *wk; - const u8 *bssid = NULL; + const u8 *bssid = req->bss->bssid; bool not_auth_yet = false; mutex_lock(&ifmgd->mtx); if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { bssid = req->bss->bssid; - ieee80211_set_disassoc(sdata, true); + ieee80211_set_disassoc(sdata); } else list_for_each_entry(wk, &ifmgd->work_list, list) { - if (&wk->bss->cbss == req->bss) { - bssid = req->bss->bssid; - if (wk->state == IEEE80211_MGD_STATE_PROBE) - not_auth_yet = true; - list_del(&wk->list); - kfree(wk); - break; - } + if (wk->state != IEEE80211_MGD_STATE_PROBE) + continue; + if (req->bss != &wk->bss->cbss) + continue; + not_auth_yet = true; + list_del(&wk->list); + kfree(wk); + break; } /* @@ -2601,17 +2583,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, return 0; } - /* - * cfg80211 should catch this ... but it's racy since - * we can receive a deauth frame, process it, hand it - * to cfg80211 while that's in a locked section already - * trying to tell us that the user wants to disconnect. - */ - if (!bssid) { - mutex_unlock(&ifmgd->mtx); - return -ENOLINK; - } - mutex_unlock(&ifmgd->mtx); printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", @@ -2648,7 +2619,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", sdata->name, req->bss->bssid, req->reason_code); - ieee80211_set_disassoc(sdata, false); + ieee80211_set_disassoc(sdata); mutex_unlock(&ifmgd->mtx); -- cgit v1.2.3 From f679f65d417c3ea3f91b4bbfb68e3951c9eb8f04 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:34 +0100 Subject: mac80211: generalise management work a bit As a first step of generalising management work, this renames a few things and puts more information directly into the struct so that auth/assoc need not access the BSS pointer as often -- in fact it can be removed from auth completely. Also since the previous patch made sure a new work item is used for association, we can make the different data a union. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 53 +++++++---- net/mac80211/mlme.c | 226 +++++++++++++++++++++++++++------------------ 2 files changed, 172 insertions(+), 107 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e21e0301548b..0339e909e0c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -227,31 +227,48 @@ struct mesh_preq_queue { u8 flags; }; -enum ieee80211_mgd_state { - IEEE80211_MGD_STATE_INVALID, - IEEE80211_MGD_STATE_PROBE, - IEEE80211_MGD_STATE_AUTH, - IEEE80211_MGD_STATE_ASSOC, +enum ieee80211_work_type { + IEEE80211_WORK_AUTH_PROBE, + IEEE80211_WORK_AUTH, + IEEE80211_WORK_ASSOC, }; -struct ieee80211_mgd_work { +struct ieee80211_work { struct list_head list; - struct ieee80211_bss *bss; - int ie_len; - u8 prev_bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 ssid_len; - unsigned long timeout; - enum ieee80211_mgd_state state; - u16 auth_alg, auth_transaction; - int tries; + struct ieee80211_channel *chan; + /* XXX: chan type? -- right now not really needed */ + unsigned long timeout; + enum ieee80211_work_type type; - u8 key[WLAN_KEY_LEN_WEP104]; - u8 key_len, key_idx; + union { + struct { + int tries; + u16 algorithm, transaction; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + u8 bssid[ETH_ALEN]; + u8 key[WLAN_KEY_LEN_WEP104]; + u8 key_len, key_idx; + bool privacy; + } auth; + struct { + struct ieee80211_bss *bss; + const u8 *supp_rates; + const u8 *ht_information_ie; + int tries; + u16 capability; + u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_len; + u8 supp_rates_len; + bool wmm_used; + } assoc; + }; + int ie_len; /* must be last */ - u8 ie[0]; /* for auth or assoc frame, not probe */ + u8 ie[0]; }; /* flags used in struct ieee80211_if_managed.flags */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f060bc616203..c65225f29bb6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -125,15 +125,15 @@ static int ecw2cw(int ecw) return (1 << ecw) - 1; } -static int ieee80211_compatible_rates(struct ieee80211_bss *bss, +static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, struct ieee80211_supported_band *sband, u32 *rates) { int i, j, count; *rates = 0; count = 0; - for (i = 0; i < bss->supp_rates_len; i++) { - int rate = (bss->supp_rates[i] & 0x7F) * 5; + for (i = 0; i < supp_rates_len; i++) { + int rate = (supp_rates[i] & 0x7F) * 5; for (j = 0; j < sband->n_bitrates; j++) if (sband->bitrates[j].bitrate == rate) { @@ -232,7 +232,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, /* frame sending functions */ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk) + struct ieee80211_work *wk) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; @@ -248,7 +248,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + wk->ie_len + - wk->ssid_len); + wk->assoc.ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " "frame\n", sdata->name); @@ -267,35 +267,37 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } - if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY) + if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; - if (wk->bss->wmm_used) + if (wk->assoc.wmm_used) wmm = 1; /* get all rates supported by the device and the AP as * some APs don't like getting a superset of their rates * in the association request (e.g. D-Link DAP 1353 in * b-only mode) */ - rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates); + rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, + wk->assoc.supp_rates_len, + sband, &rates); - if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && + if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); - memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); + memcpy(mgmt->da, wk->assoc.bssid, ETH_ALEN); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); + memcpy(mgmt->bssid, wk->assoc.bssid, ETH_ALEN); - if (!is_zero_ether_addr(wk->prev_bssid)) { + if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { skb_put(skb, 10); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); - memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid, + memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, ETH_ALEN); } else { skb_put(skb, 4); @@ -307,10 +309,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } /* SSID */ - ies = pos = skb_put(skb, 2 + wk->ssid_len); + ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); *pos++ = WLAN_EID_SSID; - *pos++ = wk->ssid_len; - memcpy(pos, wk->ssid, wk->ssid_len); + *pos++ = wk->assoc.ssid_len; + memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); /* add all rates which were marked to be used above */ supp_rates_len = rates_len; @@ -392,7 +394,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, */ if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && sband->ht_cap.ht_supported && - (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) && + (ht_ie = wk->assoc.ht_information_ie) && ht_ie[1] >= sizeof(struct ieee80211_ht_info) && (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { struct ieee80211_ht_info *ht_info = @@ -1003,23 +1005,43 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, netif_carrier_on(sdata->dev); } +static void ieee80211_remove_auth_bss(struct ieee80211_local *local, + struct ieee80211_work *wk) +{ + struct cfg80211_bss *cbss; + u16 capa_val = WLAN_CAPABILITY_ESS; + + if (wk->auth.privacy) + capa_val |= WLAN_CAPABILITY_PRIVACY; + + cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->auth.bssid, + wk->auth.ssid, wk->auth.ssid_len, + WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, + capa_val); + if (!cbss) + return; + + cfg80211_unlink_bss(local->hw.wiphy, cbss); + cfg80211_put_bss(cbss); +} + static enum rx_mgmt_action __must_check ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk) + struct ieee80211_work *wk) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - wk->tries++; - if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { + wk->auth.tries++; + if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", - sdata->name, wk->bss->cbss.bssid); + sdata->name, wk->auth.bssid); /* * Most likely AP is not in the range so remove the * bss struct for that AP. */ - cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); + ieee80211_remove_auth_bss(local, wk); /* * We might have a pending scan which had no chance to run yet @@ -1031,14 +1053,14 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", - sdata->name, wk->bss->cbss.bssid, - wk->tries); + sdata->name, wk->auth.bssid, wk->auth.tries); /* * Direct probe is sent to broadcast address as some APs * will not answer to direct packet in unassociated state. */ - ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); + ieee80211_send_probe_req(sdata, NULL, wk->auth.ssid, wk->auth.ssid_len, + NULL, 0); wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; run_again(ifmgd, wk->timeout); @@ -1049,22 +1071,21 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, static enum rx_mgmt_action __must_check ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk) + struct ieee80211_work *wk) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - wk->tries++; - if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { + wk->auth.tries++; + if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with AP %pM" - " timed out\n", - sdata->name, wk->bss->cbss.bssid); + " timed out\n", sdata->name, wk->auth.bssid); /* * Most likely AP is not in the range so remove the * bss struct for that AP. */ - cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); + ieee80211_remove_auth_bss(local, wk); /* * We might have a pending scan which had no chance to run yet @@ -1076,11 +1097,11 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", - sdata->name, wk->bss->cbss.bssid, wk->tries); + sdata->name, wk->auth.bssid, wk->auth.tries); - ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, - wk->bss->cbss.bssid, NULL, 0, 0); - wk->auth_transaction = 2; + ieee80211_send_auth(sdata, 1, wk->auth.algorithm, wk->ie, wk->ie_len, + wk->auth.bssid, NULL, 0, 0); + wk->auth.transaction = 2; wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; run_again(ifmgd, wk->timeout); @@ -1176,22 +1197,22 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) static enum rx_mgmt_action __must_check ieee80211_associate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk) + struct ieee80211_work *wk) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; - wk->tries++; - if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { + wk->assoc.tries++; + if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with AP %pM" " timed out\n", - sdata->name, wk->bss->cbss.bssid); + sdata->name, wk->assoc.bssid); /* * Most likely AP is not in the range so remove the * bss struct for that AP. */ - cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); + cfg80211_unlink_bss(local->hw.wiphy, &wk->assoc.bss->cbss); /* * We might have a pending scan which had no chance to run yet @@ -1203,7 +1224,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", - sdata->name, wk->bss->cbss.bssid, wk->tries); + sdata->name, wk->assoc.bssid, wk->assoc.tries); ieee80211_send_assoc(sdata, wk); wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; @@ -1318,7 +1339,7 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) EXPORT_SYMBOL(ieee80211_beacon_loss); static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk) + struct ieee80211_work *wk) { list_del(&wk->list); kfree(wk); @@ -1327,7 +1348,7 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, + struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt, size_t len) { @@ -1338,38 +1359,38 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.challenge) return; - ieee80211_send_auth(sdata, 3, wk->auth_alg, + ieee80211_send_auth(sdata, 3, wk->auth.algorithm, elems.challenge - 2, elems.challenge_len + 2, - wk->bss->cbss.bssid, - wk->key, wk->key_len, wk->key_idx); - wk->auth_transaction = 4; + wk->auth.bssid, wk->auth.key, wk->auth.key_len, + wk->auth.key_idx); + wk->auth.transaction = 4; } static enum rx_mgmt_action __must_check ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, + struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction, status_code; - if (wk->state != IEEE80211_MGD_STATE_AUTH) + if (wk->type != IEEE80211_WORK_AUTH) return RX_MGMT_NONE; if (len < 24 + 6) return RX_MGMT_NONE; - if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) + if (memcmp(wk->auth.bssid, mgmt->sa, ETH_ALEN) != 0) return RX_MGMT_NONE; - if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) + if (memcmp(wk->auth.bssid, mgmt->bssid, ETH_ALEN) != 0) return RX_MGMT_NONE; auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); status_code = le16_to_cpu(mgmt->u.auth.status_code); - if (auth_alg != wk->auth_alg || - auth_transaction != wk->auth_transaction) + if (auth_alg != wk->auth.algorithm || + auth_transaction != wk->auth.transaction) return RX_MGMT_NONE; if (status_code != WLAN_STATUS_SUCCESS) { @@ -1378,14 +1399,14 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, return RX_MGMT_CFG80211_AUTH; } - switch (wk->auth_alg) { + switch (wk->auth.algorithm) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: case WLAN_AUTH_FT: ieee80211_auth_completed(sdata, wk); return RX_MGMT_CFG80211_AUTH; case WLAN_AUTH_SHARED_KEY: - if (wk->auth_transaction == 4) { + if (wk->auth.transaction == 4) { ieee80211_auth_completed(sdata, wk); return RX_MGMT_CFG80211_AUTH; } else @@ -1455,7 +1476,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, static enum rx_mgmt_action __must_check ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, + struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt, size_t len, bool reassoc) { @@ -1463,7 +1484,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; - struct ieee80211_bss *bss = wk->bss; + struct ieee80211_bss *bss = wk->assoc.bss; u32 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; @@ -1693,7 +1714,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgd_work *wk, + struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { @@ -1718,11 +1739,11 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); /* direct probe may be part of the association flow */ - if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { + if (wk && wk->type == IEEE80211_WORK_AUTH_PROBE) { printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); - wk->tries = 0; - wk->state = IEEE80211_MGD_STATE_AUTH; + wk->auth.tries = 0; + wk->type = IEEE80211_WORK_AUTH; WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); } @@ -1959,7 +1980,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; - struct ieee80211_mgd_work *wk; + struct ieee80211_work *wk; enum rx_mgmt_action rma = RX_MGMT_NONE; u16 fc; @@ -2013,7 +2034,20 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, } list_for_each_entry(wk, &ifmgd->work_list, list) { - if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) + const u8 *bssid = NULL; + + switch (wk->type) { + case IEEE80211_WORK_AUTH_PROBE: + case IEEE80211_WORK_AUTH: + bssid = wk->auth.bssid; + break; + case IEEE80211_WORK_ASSOC: + bssid = wk->assoc.bssid; + break; + default: + continue; + } + if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) continue; switch (fc & IEEE80211_FCTL_STYPE) { @@ -2108,7 +2142,7 @@ static void ieee80211_sta_work(struct work_struct *work) struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd; struct sk_buff *skb; - struct ieee80211_mgd_work *wk, *tmp; + struct ieee80211_work *wk, *tmp; LIST_HEAD(free_work); enum rx_mgmt_action rma; @@ -2194,19 +2228,19 @@ static void ieee80211_sta_work(struct work_struct *work) continue; } - switch (wk->state) { + switch (wk->type) { default: WARN_ON(1); /* nothing */ rma = RX_MGMT_NONE; break; - case IEEE80211_MGD_STATE_PROBE: + case IEEE80211_WORK_AUTH_PROBE: rma = ieee80211_direct_probe(sdata, wk); break; - case IEEE80211_MGD_STATE_AUTH: + case IEEE80211_WORK_AUTH: rma = ieee80211_authenticate(sdata, wk); break; - case IEEE80211_MGD_STATE_ASSOC: + case IEEE80211_WORK_ASSOC: rma = ieee80211_associate(sdata, wk); break; } @@ -2243,12 +2277,11 @@ static void ieee80211_sta_work(struct work_struct *work) /* see above how we're using wk->timeout */ switch (wk->timeout) { case RX_MGMT_CFG80211_AUTH_TO: - cfg80211_send_auth_timeout(sdata->dev, - wk->bss->cbss.bssid); + cfg80211_send_auth_timeout(sdata->dev, wk->auth.bssid); break; case RX_MGMT_CFG80211_ASSOC_TO: cfg80211_send_assoc_timeout(sdata->dev, - wk->bss->cbss.bssid); + wk->assoc.bssid); break; default: WARN(1, "unexpected: %lu", wk->timeout); @@ -2415,7 +2448,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; const u8 *ssid; - struct ieee80211_mgd_work *wk; + struct ieee80211_work *wk; u16 auth_alg; switch (req->auth_type) { @@ -2439,7 +2472,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, if (!wk) return -ENOMEM; - wk->bss = (void *)req->bss; + memcpy(wk->auth.bssid, req->bss->bssid, ETH_ALEN);; if (req->ie && req->ie_len) { memcpy(wk->ie, req->ie, req->ie_len); @@ -2447,22 +2480,27 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, } if (req->key && req->key_len) { - wk->key_len = req->key_len; - wk->key_idx = req->key_idx; - memcpy(wk->key, req->key, req->key_len); + wk->auth.key_len = req->key_len; + wk->auth.key_idx = req->key_idx; + memcpy(wk->auth.key, req->key, req->key_len); } ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - memcpy(wk->ssid, ssid + 2, ssid[1]); - wk->ssid_len = ssid[1]; + memcpy(wk->auth.ssid, ssid + 2, ssid[1]); + wk->auth.ssid_len = ssid[1]; + + wk->auth.algorithm = auth_alg; + wk->auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; - wk->state = IEEE80211_MGD_STATE_PROBE; - wk->auth_alg = auth_alg; + wk->type = IEEE80211_WORK_AUTH_PROBE; wk->timeout = jiffies; /* run right away */ + wk->chan = req->bss->channel; /* * XXX: if still associated need to tell AP that we're going * to sleep and then change channel etc. + * For now switch channel here, later will be handled + * by submitting this as an off-channel work item. */ sdata->local->oper_channel = req->bss->channel; ieee80211_hw_config(sdata->local, 0); @@ -2479,7 +2517,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_mgd_work *wk; + struct ieee80211_work *wk; const u8 *ssid; int i, err; @@ -2506,17 +2544,27 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } else wk->ie_len = 0; - wk->bss = (void *)req->bss; + wk->assoc.bss = (void *)req->bss; + + memcpy(wk->assoc.bssid, req->bss->bssid, ETH_ALEN); + + wk->assoc.capability = req->bss->capability; + wk->assoc.wmm_used = wk->assoc.bss->wmm_used; + wk->assoc.supp_rates = wk->assoc.bss->supp_rates; + wk->assoc.supp_rates_len = wk->assoc.bss->supp_rates_len; + wk->assoc.ht_information_ie = + ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - memcpy(wk->ssid, ssid + 2, ssid[1]); - wk->ssid_len = ssid[1]; + memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); + wk->assoc.ssid_len = ssid[1]; if (req->prev_bssid) - memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN); + memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); - wk->state = IEEE80211_MGD_STATE_ASSOC; + wk->type = IEEE80211_WORK_ASSOC; wk->timeout = jiffies; /* run right away */ + wk->chan = req->bss->channel; if (req->use_mfp) { ifmgd->mfp = IEEE80211_MFP_REQUIRED; @@ -2549,7 +2597,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, void *cookie) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_mgd_work *wk; + struct ieee80211_work *wk; const u8 *bssid = req->bss->bssid; bool not_auth_yet = false; @@ -2559,9 +2607,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, bssid = req->bss->bssid; ieee80211_set_disassoc(sdata); } else list_for_each_entry(wk, &ifmgd->work_list, list) { - if (wk->state != IEEE80211_MGD_STATE_PROBE) + if (wk->type != IEEE80211_WORK_AUTH_PROBE) continue; - if (req->bss != &wk->bss->cbss) + if (memcmp(req->bss->bssid, wk->auth.bssid, ETH_ALEN)) continue; not_auth_yet = true; list_del(&wk->list); -- cgit v1.2.3 From af6b63741cc4e4dfd575d06beb333b11a8a6e0c0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:35 +0100 Subject: mac80211: generalise work handling In order to use auth/assoc for different purposes other than MLME, it needs to be split up. For other purposes, a generic work handling (potentially on another channel) will be useful. To achieve that, this patch moves much of the MLME work handling out of mlme into a new work API. The API can currently handle probing a specific AP, authentication and association. The MLME previously handled probe/authentication as one step and will continue to do so, but they are separate in the new work handling. Work items are RCU-managed to be able to check for existence of an item for a specific frame in the RX path, but they can be re-used which the MLME right now will do for its combined probe/auth step. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 2 +- net/mac80211/debugfs_netdev.c | 2 - net/mac80211/ieee80211_i.h | 59 ++- net/mac80211/iface.c | 11 +- net/mac80211/main.c | 2 + net/mac80211/mlme.c | 956 +++++++----------------------------------- net/mac80211/rx.c | 5 + net/mac80211/scan.c | 8 +- net/mac80211/work.c | 902 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 1112 insertions(+), 835 deletions(-) create mode 100644 net/mac80211/work.c diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 298cfcc1bf8d..5a1f57df7cd6 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -9,7 +9,7 @@ mac80211-y := \ scan.o \ ht.o agg-tx.o agg-rx.o \ ibss.o \ - mlme.o \ + mlme.o work.o \ iface.o \ rate.o \ michael.o \ diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 355983503885..59f6e3bcbd09 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -133,7 +133,6 @@ IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); /* STA attributes */ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); -IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode) @@ -270,7 +269,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(bssid, sta); DEBUGFS_ADD(aid, sta); - DEBUGFS_ADD(capab, sta); DEBUGFS_ADD_MODE(smps, 0600); } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0339e909e0c4..97b6076b492e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -228,41 +228,63 @@ struct mesh_preq_queue { }; enum ieee80211_work_type { - IEEE80211_WORK_AUTH_PROBE, + IEEE80211_WORK_DIRECT_PROBE, IEEE80211_WORK_AUTH, IEEE80211_WORK_ASSOC, }; +/** + * enum work_done_result - indicates what to do after work was done + * + * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. + * @WORK_DONE_REQUEUE: This work item was reset to be reused, and + * should be requeued. + */ +enum work_done_result { + WORK_DONE_DESTROY, + WORK_DONE_REQUEUE, +}; + struct ieee80211_work { struct list_head list; + struct rcu_head rcu_head; + + struct ieee80211_sub_if_data *sdata; + + enum work_done_result (*done)(struct ieee80211_work *wk, + struct sk_buff *skb); + struct ieee80211_channel *chan; /* XXX: chan type? -- right now not really needed */ + unsigned long timeout; enum ieee80211_work_type type; + u8 filter_ta[ETH_ALEN]; + union { struct { int tries; u16 algorithm, transaction; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len; - u8 bssid[ETH_ALEN]; u8 key[WLAN_KEY_LEN_WEP104]; u8 key_len, key_idx; bool privacy; - } auth; + } probe_auth; struct { struct ieee80211_bss *bss; const u8 *supp_rates; const u8 *ht_information_ie; + enum ieee80211_smps_mode smps; int tries; u16 capability; - u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; + u8 prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len; u8 supp_rates_len; - bool wmm_used; + bool wmm_used, use_11n; } assoc; }; @@ -276,17 +298,11 @@ enum ieee80211_sta_flags { IEEE80211_STA_BEACON_POLL = BIT(0), IEEE80211_STA_CONNECTION_POLL = BIT(1), IEEE80211_STA_CONTROL_PORT = BIT(2), - IEEE80211_STA_WMM_ENABLED = BIT(3), IEEE80211_STA_DISABLE_11N = BIT(4), IEEE80211_STA_CSA_RECEIVED = BIT(5), IEEE80211_STA_MFP_ENABLED = BIT(6), }; -/* flags for MLME request */ -enum ieee80211_sta_request { - IEEE80211_STA_REQ_SCAN, -}; - struct ieee80211_if_managed { struct timer_list timer; struct timer_list conn_mon_timer; @@ -302,12 +318,10 @@ struct ieee80211_if_managed { struct mutex mtx; struct ieee80211_bss *associated; - struct list_head work_list; u8 bssid[ETH_ALEN]; u16 aid; - u16 capab; struct sk_buff_head skb_queue; @@ -316,8 +330,6 @@ struct ieee80211_if_managed { enum ieee80211_smps_mode req_smps, /* requested smps mode */ ap_smps; /* smps mode AP thinks we're in */ - unsigned long request; - unsigned int flags; u32 beacon_crc; @@ -583,6 +595,15 @@ struct ieee80211_local { const struct ieee80211_ops *ops; + /* + * work stuff, potentially off-channel (in the future) + */ + struct mutex work_mtx; + struct list_head work_list; + struct timer_list work_timer; + struct work_struct work_work; + struct sk_buff_head work_skb_queue; + /* * private workqueue to mac80211. mac80211 makes this accessible * via ieee80211_queue_work() @@ -1127,6 +1148,14 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, void ieee80211_recalc_smps(struct ieee80211_local *local, struct ieee80211_sub_if_data *forsdata); +/* internal work items */ +void ieee80211_work_init(struct ieee80211_local *local); +void ieee80211_add_work(struct ieee80211_work *wk); +void free_work(struct ieee80211_work *wk); +void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); +ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb); + #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline #else diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 389dc8d880f3..7d410f15281a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -361,6 +361,11 @@ static int ieee80211_stop(struct net_device *dev) */ netif_stop_queue(dev); + /* + * Purge work for this interface. + */ + ieee80211_work_purge(sdata); + /* * Now delete all active aggregation sessions. */ @@ -928,6 +933,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) struct ieee80211_sub_if_data *sdata; int count = 0; + if (!list_empty(&local->work_list)) + return ieee80211_idle_off(local, "working"); + if (local->scanning) return ieee80211_idle_off(local, "scanning"); @@ -936,8 +944,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) continue; /* do not count disabled managed interfaces */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - !sdata->u.mgd.associated && - list_empty(&sdata->u.mgd.work_list)) + !sdata->u.mgd.associated) continue; /* do not count unused IBSS interfaces */ if (sdata->vif.type == NL80211_IFTYPE_ADHOC && diff --git a/net/mac80211/main.c b/net/mac80211/main.c index e93bc558d785..d35023ce7fa1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -395,6 +395,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); + ieee80211_work_init(local); + INIT_WORK(&local->restart_work, ieee80211_restart_work); INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index c65225f29bb6..7c1f91bcc834 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -77,12 +77,6 @@ enum rx_mgmt_action { /* caller must tell cfg80211 about internal error */ RX_MGMT_CFG80211_ASSOC_ERROR, - - /* caller must call cfg80211_auth_timeout() & free work */ - RX_MGMT_CFG80211_AUTH_TO, - - /* caller must call cfg80211_assoc_timeout() & free work */ - RX_MGMT_CFG80211_ASSOC_TO, }; /* utils */ @@ -125,27 +119,6 @@ static int ecw2cw(int ecw) return (1 << ecw) - 1; } -static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, - struct ieee80211_supported_band *sband, - u32 *rates) -{ - int i, j, count; - *rates = 0; - count = 0; - for (i = 0; i < supp_rates_len; i++) { - int rate = (supp_rates[i] & 0x7F) * 5; - - for (j = 0; j < sband->n_bitrates; j++) - if (sband->bitrates[j].bitrate == rate) { - *rates |= BIT(j); - count++; - break; - } - } - - return count; -} - /* * ieee80211_enable_ht should be called only after the operating band * has been determined as ht configuration depends on the hw's @@ -231,266 +204,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, /* frame sending functions */ -static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; - u8 *pos; - const u8 *ies, *ht_ie; - int i, len, count, rates_len, supp_rates_len; - u16 capab; - int wmm = 0; - struct ieee80211_supported_band *sband; - u32 rates = 0; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 200 + wk->ie_len + - wk->assoc.ssid_len); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", sdata->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - capab = ifmgd->capab; - - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) - capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; - } - - if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) - capab |= WLAN_CAPABILITY_PRIVACY; - if (wk->assoc.wmm_used) - wmm = 1; - - /* get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode) */ - rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, - wk->assoc.supp_rates_len, - sband, &rates); - - if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && - (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) - capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - memcpy(mgmt->da, wk->assoc.bssid, ETH_ALEN); - memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); - memcpy(mgmt->bssid, wk->assoc.bssid, ETH_ALEN); - - if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { - skb_put(skb, 10); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, - ETH_ALEN); - } else { - skb_put(skb, 4); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.assoc_req.listen_interval = - cpu_to_le16(local->hw.conf.listen_interval); - } - - /* SSID */ - ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = wk->assoc.ssid_len; - memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); - - /* add all rates which were marked to be used above */ - supp_rates_len = rates_len; - if (supp_rates_len > 8) - supp_rates_len = 8; - - len = sband->n_bitrates; - pos = skb_put(skb, supp_rates_len + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = supp_rates_len; - - count = 0; - for (i = 0; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - if (++count == 8) - break; - } - } - - if (rates_len > count) { - pos = skb_put(skb, rates_len - count + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = rates_len - count; - - for (i++; i < sband->n_bitrates; i++) { - if (BIT(i) & rates) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } - } - } - - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { - /* 1. power capabilities */ - pos = skb_put(skb, 4); - *pos++ = WLAN_EID_PWR_CAPABILITY; - *pos++ = 2; - *pos++ = 0; /* min tx power */ - *pos++ = local->hw.conf.channel->max_power; /* max tx power */ - - /* 2. supported channels */ - /* TODO: get this in reg domain format */ - pos = skb_put(skb, 2 * sband->n_channels + 2); - *pos++ = WLAN_EID_SUPPORTED_CHANNELS; - *pos++ = 2 * sband->n_channels; - for (i = 0; i < sband->n_channels; i++) { - *pos++ = ieee80211_frequency_to_channel( - sband->channels[i].center_freq); - *pos++ = 1; /* one channel in the subband*/ - } - } - - if (wk->ie_len && wk->ie) { - pos = skb_put(skb, wk->ie_len); - memcpy(pos, wk->ie, wk->ie_len); - } - - if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) { - pos = skb_put(skb, 9); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 7; /* len */ - *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *pos++ = 0x50; - *pos++ = 0xf2; - *pos++ = 2; /* WME */ - *pos++ = 0; /* WME info */ - *pos++ = 1; /* WME ver */ - *pos++ = 0; - } - - /* wmm support is a must to HT */ - /* - * IEEE802.11n does not allow TKIP/WEP as pairwise - * ciphers in HT mode. We still associate in non-ht - * mode (11a/b/g) if any one of these ciphers is - * configured as pairwise. - */ - if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && - sband->ht_cap.ht_supported && - (ht_ie = wk->assoc.ht_information_ie) && - ht_ie[1] >= sizeof(struct ieee80211_ht_info) && - (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { - struct ieee80211_ht_info *ht_info = - (struct ieee80211_ht_info *)(ht_ie + 2); - u16 cap = sband->ht_cap.cap; - __le16 tmp; - u32 flags = local->hw.conf.channel->flags; - - /* determine capability flags */ - - if (ieee80211_disable_40mhz_24ghz && - sband->band == IEEE80211_BAND_2GHZ) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_HT40PLUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_HT40MINUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - } - - /* set SM PS mode properly */ - cap &= ~IEEE80211_HT_CAP_SM_PS; - /* new association always uses requested smps mode */ - if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { - if (ifmgd->powersave) - ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; - else - ifmgd->ap_smps = IEEE80211_SMPS_OFF; - } else - ifmgd->ap_smps = ifmgd->req_smps; - - switch (ifmgd->ap_smps) { - case IEEE80211_SMPS_AUTOMATIC: - case IEEE80211_SMPS_NUM_MODES: - WARN_ON(1); - case IEEE80211_SMPS_OFF: - cap |= WLAN_HT_CAP_SM_PS_DISABLED << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_STATIC: - cap |= WLAN_HT_CAP_SM_PS_STATIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_DYNAMIC: - cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - } - - /* reserve and fill IE */ - - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - memset(pos, 0, sizeof(struct ieee80211_ht_cap)); - - /* capability flags */ - tmp = cpu_to_le16(cap); - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - - /* AMPDU parameters */ - *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); - - /* MCS set */ - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); - pos += sizeof(sband->ht_cap.mcs); - - /* extended capabilities */ - pos += sizeof(__le16); - - /* BF capabilities */ - pos += sizeof(__le32); - - /* antenna selection */ - pos += sizeof(u8); - } - - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - ieee80211_tx_skb(sdata, skb); -} - - static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, const u8 *bssid, u16 stype, u16 reason, void *cookie) @@ -751,6 +464,11 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) return; } + if (!list_empty(&local->work_list)) { + local->ps_sdata = NULL; + goto change; + } + list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) continue; @@ -761,7 +479,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) } if (count == 1 && found->u.mgd.powersave && - found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && + found->u.mgd.associated && !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL))) { s32 beaconint_us; @@ -789,6 +507,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) local->ps_sdata = NULL; } + change: ieee80211_change_ps(local); } @@ -848,7 +567,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, int count; u8 *pos; - if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) + if (local->hw.queues < 4) return; if (!wmm_param) @@ -1005,110 +724,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, netif_carrier_on(sdata->dev); } -static void ieee80211_remove_auth_bss(struct ieee80211_local *local, - struct ieee80211_work *wk) -{ - struct cfg80211_bss *cbss; - u16 capa_val = WLAN_CAPABILITY_ESS; - - if (wk->auth.privacy) - capa_val |= WLAN_CAPABILITY_PRIVACY; - - cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->auth.bssid, - wk->auth.ssid, wk->auth.ssid_len, - WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, - capa_val); - if (!cbss) - return; - - cfg80211_unlink_bss(local->hw.wiphy, cbss); - cfg80211_put_bss(cbss); -} - -static enum rx_mgmt_action __must_check -ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_local *local = sdata->local; - - wk->auth.tries++; - if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", - sdata->name, wk->auth.bssid); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - ieee80211_remove_auth_bss(local, wk); - - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &ifmgd->work); - return RX_MGMT_CFG80211_AUTH_TO; - } - - printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", - sdata->name, wk->auth.bssid, wk->auth.tries); - - /* - * Direct probe is sent to broadcast address as some APs - * will not answer to direct packet in unassociated state. - */ - ieee80211_send_probe_req(sdata, NULL, wk->auth.ssid, wk->auth.ssid_len, - NULL, 0); - - wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(ifmgd, wk->timeout); - - return RX_MGMT_NONE; -} - - -static enum rx_mgmt_action __must_check -ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_local *local = sdata->local; - - wk->auth.tries++; - if (wk->auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: authentication with AP %pM" - " timed out\n", sdata->name, wk->auth.bssid); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - ieee80211_remove_auth_bss(local, wk); - - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &ifmgd->work); - return RX_MGMT_CFG80211_AUTH_TO; - } - - printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", - sdata->name, wk->auth.bssid, wk->auth.tries); - - ieee80211_send_auth(sdata, 1, wk->auth.algorithm, wk->ie, wk->ie_len, - wk->auth.bssid, NULL, 0, 0); - wk->auth.transaction = 2; - - wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(ifmgd, wk->timeout); - - return RX_MGMT_NONE; -} - static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -1195,44 +810,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) sta_info_destroy(sta); } -static enum rx_mgmt_action __must_check -ieee80211_associate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - struct ieee80211_local *local = sdata->local; - - wk->assoc.tries++; - if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { - printk(KERN_DEBUG "%s: association with AP %pM" - " timed out\n", - sdata->name, wk->assoc.bssid); - - /* - * Most likely AP is not in the range so remove the - * bss struct for that AP. - */ - cfg80211_unlink_bss(local->hw.wiphy, &wk->assoc.bss->cbss); - - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &ifmgd->work); - return RX_MGMT_CFG80211_ASSOC_TO; - } - - printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", - sdata->name, wk->assoc.bssid, wk->assoc.tries); - ieee80211_send_assoc(sdata, wk); - - wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; - run_again(ifmgd, wk->timeout); - - return RX_MGMT_NONE; -} - void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, struct ieee80211_hdr *hdr) { @@ -1338,86 +915,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) } EXPORT_SYMBOL(ieee80211_beacon_loss); -static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk) -{ - list_del(&wk->list); - kfree(wk); - printk(KERN_DEBUG "%s: authenticated\n", sdata->name); -} - - -static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - u8 *pos; - struct ieee802_11_elems elems; - - pos = mgmt->u.auth.variable; - ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); - if (!elems.challenge) - return; - ieee80211_send_auth(sdata, 3, wk->auth.algorithm, - elems.challenge - 2, elems.challenge_len + 2, - wk->auth.bssid, wk->auth.key, wk->auth.key_len, - wk->auth.key_idx); - wk->auth.transaction = 4; -} - -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len) -{ - u16 auth_alg, auth_transaction, status_code; - - if (wk->type != IEEE80211_WORK_AUTH) - return RX_MGMT_NONE; - - if (len < 24 + 6) - return RX_MGMT_NONE; - - if (memcmp(wk->auth.bssid, mgmt->sa, ETH_ALEN) != 0) - return RX_MGMT_NONE; - - if (memcmp(wk->auth.bssid, mgmt->bssid, ETH_ALEN) != 0) - return RX_MGMT_NONE; - - auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); - auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); - status_code = le16_to_cpu(mgmt->u.auth.status_code); - - if (auth_alg != wk->auth.algorithm || - auth_transaction != wk->auth.transaction) - return RX_MGMT_NONE; - - if (status_code != WLAN_STATUS_SUCCESS) { - list_del(&wk->list); - kfree(wk); - return RX_MGMT_CFG80211_AUTH; - } - - switch (wk->auth.algorithm) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - case WLAN_AUTH_FT: - ieee80211_auth_completed(sdata, wk); - return RX_MGMT_CFG80211_AUTH; - case WLAN_AUTH_SHARED_KEY: - if (wk->auth.transaction == 4) { - ieee80211_auth_completed(sdata, wk); - return RX_MGMT_CFG80211_AUTH; - } else - ieee80211_auth_challenge(sdata, wk, mgmt, len); - break; - } - - return RX_MGMT_NONE; -} - - static enum rx_mgmt_action __must_check ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) @@ -1474,98 +971,51 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, } -static enum rx_mgmt_action __must_check -ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len, - bool reassoc) +static bool ieee80211_assoc_success(struct ieee80211_work *wk, + struct ieee80211_mgmt *mgmt, size_t len) { + struct ieee80211_sub_if_data *sdata = wk->sdata; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; struct ieee80211_bss *bss = wk->assoc.bss; + u8 *pos; u32 rates, basic_rates; - u16 capab_info, status_code, aid; + u16 capab_info, aid; struct ieee802_11_elems elems; struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - u8 *pos; u32 changed = 0; int i, j, err; bool have_higher_than_11mbit = false; u16 ap_ht_cap_flags; - /* - * AssocResp and ReassocResp have identical structure, so process both - * of them in this function. - */ - - if (len < 24 + 6) - return RX_MGMT_NONE; + /* AssocResp and ReassocResp have identical structure */ - if (memcmp(bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) - return RX_MGMT_NONE; - - capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); - status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); aid = le16_to_cpu(mgmt->u.assoc_resp.aid); - - printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " - "status=%d aid=%d)\n", - sdata->name, reassoc ? "Rea" : "A", mgmt->sa, - capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); - - pos = mgmt->u.assoc_resp.variable; - ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); - - if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && - elems.timeout_int && elems.timeout_int_len == 5 && - elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { - u32 tu, ms; - tu = get_unaligned_le32(elems.timeout_int + 1); - ms = tu * 1024 / 1000; - printk(KERN_DEBUG "%s: AP rejected association temporarily; " - "comeback duration %u TU (%u ms)\n", - sdata->name, tu, ms); - wk->timeout = jiffies + msecs_to_jiffies(ms); - if (ms > IEEE80211_ASSOC_TIMEOUT) - run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); - return RX_MGMT_NONE; - } - - /* - * Here the association was either successful or not. - */ - - /* delete work item -- must be before set_associated for PS */ - list_del(&wk->list); - kfree(wk); - - if (status_code != WLAN_STATUS_SUCCESS) { - printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - sdata->name, status_code); - return RX_MGMT_CFG80211_ASSOC; - } + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " "set\n", sdata->name, aid); aid &= ~(BIT(15) | BIT(14)); + pos = mgmt->u.assoc_resp.variable; + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", sdata->name); - return RX_MGMT_NONE; + return false; } - printk(KERN_DEBUG "%s: associated\n", sdata->name); ifmgd->aid = aid; sta = sta_info_alloc(sdata, bss->cbss.bssid, GFP_KERNEL); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" " the AP\n", sdata->name); - return RX_MGMT_CFG80211_ASSOC_ERROR; + return false; } set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | @@ -1650,7 +1100,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_set_wmm_default(sdata); if (elems.ht_info_elem && elems.wmm_param && - (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && + (sdata->local->hw.queues >= 4) && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, bss->cbss.bssid, @@ -1669,7 +1119,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); mod_beacon_timer(sdata); - return RX_MGMT_CFG80211_ASSOC; + return true; } @@ -1714,12 +1164,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, - struct ieee80211_work *wk, - struct ieee80211_mgmt *mgmt, size_t len, - struct ieee80211_rx_status *rx_status) + struct sk_buff *skb) { + struct ieee80211_mgmt *mgmt = (void *)skb->data; struct ieee80211_if_managed *ifmgd; - size_t baselen; + struct ieee80211_rx_status *rx_status = (void *) skb->cb; + size_t baselen, len = skb->len; struct ieee802_11_elems elems; ifmgd = &sdata->u.mgd; @@ -1738,15 +1188,6 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); - /* direct probe may be part of the association flow */ - if (wk && wk->type == IEEE80211_WORK_AUTH_PROBE) { - printk(KERN_DEBUG "%s: direct probe responded\n", - sdata->name); - wk->auth.tries = 0; - wk->type = IEEE80211_WORK_AUTH; - WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); - } - if (ifmgd->associated && memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && ifmgd->flags & (IEEE80211_STA_BEACON_POLL | @@ -1960,9 +1401,6 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_BEACON: - case IEEE80211_STYPE_AUTH: - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: case IEEE80211_STYPE_DEAUTH: case IEEE80211_STYPE_DISASSOC: case IEEE80211_STYPE_ACTION: @@ -1980,7 +1418,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_rx_status *rx_status; struct ieee80211_mgmt *mgmt; - struct ieee80211_work *wk; enum rx_mgmt_action rma = RX_MGMT_NONE; u16 fc; @@ -1999,8 +1436,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, rx_status); break; case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt, - skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, skb); break; case IEEE80211_STYPE_DEAUTH: rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); @@ -2033,88 +1469,11 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, goto out; } - list_for_each_entry(wk, &ifmgd->work_list, list) { - const u8 *bssid = NULL; - - switch (wk->type) { - case IEEE80211_WORK_AUTH_PROBE: - case IEEE80211_WORK_AUTH: - bssid = wk->auth.bssid; - break; - case IEEE80211_WORK_ASSOC: - bssid = wk->assoc.bssid; - break; - default: - continue; - } - if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) - continue; - - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len, - rx_status); - break; - case IEEE80211_STYPE_AUTH: - rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len); - break; - case IEEE80211_STYPE_ASSOC_RESP: - rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, - skb->len, false); - break; - case IEEE80211_STYPE_REASSOC_RESP: - rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, - skb->len, true); - break; - case IEEE80211_STYPE_DEAUTH: - if (skb->len >= 24 + 2 /* mgmt + deauth reason */) { - /* - * We get here if we get deauth while - * trying to auth/assoc. Telling cfg80211 - * is handled below, unconditionally. - */ - list_del(&wk->list); - kfree(wk); - } - break; - } - /* - * We've processed this frame for that work, so it can't - * belong to another work struct. - * NB: this is also required for correctness because the - * called functions can free 'wk', and for 'rma'! - */ - break; - } - mutex_unlock(&ifmgd->mtx); if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) { - WARN_ON(rma != RX_MGMT_NONE); - rma = RX_MGMT_CFG80211_DEAUTH; - } - - switch (rma) { - case RX_MGMT_NONE: - /* no action */ - break; - case RX_MGMT_CFG80211_AUTH: - cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len); - break; - case RX_MGMT_CFG80211_ASSOC: - cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len); - break; - case RX_MGMT_CFG80211_DEAUTH: + (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); - break; - case RX_MGMT_CFG80211_ASSOC_ERROR: - /* an internal error -- pretend timeout for now */ - cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); - break; - default: - WARN(1, "unexpected: %d", rma); - } out: kfree_skb(skb); @@ -2142,9 +1501,6 @@ static void ieee80211_sta_work(struct work_struct *work) struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd; struct sk_buff *skb; - struct ieee80211_work *wk, *tmp; - LIST_HEAD(free_work); - enum rx_mgmt_action rma; if (!ieee80211_sdata_running(sdata)) return; @@ -2214,84 +1570,7 @@ static void ieee80211_sta_work(struct work_struct *work) } } - - ieee80211_recalc_idle(local); - - list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { - if (time_is_after_jiffies(wk->timeout)) { - /* - * This work item isn't supposed to be worked on - * right now, but take care to adjust the timer - * properly. - */ - run_again(ifmgd, wk->timeout); - continue; - } - - switch (wk->type) { - default: - WARN_ON(1); - /* nothing */ - rma = RX_MGMT_NONE; - break; - case IEEE80211_WORK_AUTH_PROBE: - rma = ieee80211_direct_probe(sdata, wk); - break; - case IEEE80211_WORK_AUTH: - rma = ieee80211_authenticate(sdata, wk); - break; - case IEEE80211_WORK_ASSOC: - rma = ieee80211_associate(sdata, wk); - break; - } - - switch (rma) { - case RX_MGMT_NONE: - /* no action required */ - break; - case RX_MGMT_CFG80211_AUTH_TO: - case RX_MGMT_CFG80211_ASSOC_TO: - list_del(&wk->list); - list_add(&wk->list, &free_work); - /* - * small abuse but only local -- keep the - * action type in wk->timeout while the item - * is on the cleanup list - */ - wk->timeout = rma; - break; - default: - WARN(1, "unexpected: %d", rma); - } - } - - if (list_empty(&ifmgd->work_list) && - test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) - ieee80211_queue_delayed_work(&local->hw, - &local->scan_work, - round_jiffies_relative(0)); - mutex_unlock(&ifmgd->mtx); - - list_for_each_entry_safe(wk, tmp, &free_work, list) { - /* see above how we're using wk->timeout */ - switch (wk->timeout) { - case RX_MGMT_CFG80211_AUTH_TO: - cfg80211_send_auth_timeout(sdata->dev, wk->auth.bssid); - break; - case RX_MGMT_CFG80211_ASSOC_TO: - cfg80211_send_assoc_timeout(sdata->dev, - wk->assoc.bssid); - break; - default: - WARN(1, "unexpected: %lu", wk->timeout); - } - - list_del(&wk->list); - kfree(wk); - } - - ieee80211_recalc_idle(local); } static void ieee80211_sta_bcn_mon_timer(unsigned long data) @@ -2400,12 +1679,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) (unsigned long) sdata); skb_queue_head_init(&ifmgd->skb_queue); - INIT_LIST_HEAD(&ifmgd->work_list); - - ifmgd->capab = WLAN_CAPABILITY_ESS; ifmgd->flags = 0; - if (sdata->local->hw.queues >= 4) - ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; mutex_init(&ifmgd->mtx); @@ -2443,10 +1717,32 @@ int ieee80211_max_network_latency(struct notifier_block *nb, } /* config hooks */ +static enum work_done_result +ieee80211_probe_auth_done(struct ieee80211_work *wk, + struct sk_buff *skb) +{ + if (!skb) { + cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); + return WORK_DONE_DESTROY; + } + + if (wk->type == IEEE80211_WORK_AUTH) { + cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); + return WORK_DONE_DESTROY; + } + + mutex_lock(&wk->sdata->u.mgd.mtx); + ieee80211_rx_mgmt_probe_resp(wk->sdata, skb); + mutex_unlock(&wk->sdata->u.mgd.mtx); + + wk->type = IEEE80211_WORK_AUTH; + wk->probe_auth.tries = 0; + return WORK_DONE_REQUEUE; +} + int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, struct cfg80211_auth_request *req) { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; const u8 *ssid; struct ieee80211_work *wk; u16 auth_alg; @@ -2472,7 +1768,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, if (!wk) return -ENOMEM; - memcpy(wk->auth.bssid, req->bss->bssid, ETH_ALEN);; + memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);; if (req->ie && req->ie_len) { memcpy(wk->ie, req->ie, req->ie_len); @@ -2480,21 +1776,22 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, } if (req->key && req->key_len) { - wk->auth.key_len = req->key_len; - wk->auth.key_idx = req->key_idx; - memcpy(wk->auth.key, req->key, req->key_len); + wk->probe_auth.key_len = req->key_len; + wk->probe_auth.key_idx = req->key_idx; + memcpy(wk->probe_auth.key, req->key, req->key_len); } ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); - memcpy(wk->auth.ssid, ssid + 2, ssid[1]); - wk->auth.ssid_len = ssid[1]; + memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]); + wk->probe_auth.ssid_len = ssid[1]; - wk->auth.algorithm = auth_alg; - wk->auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; + wk->probe_auth.algorithm = auth_alg; + wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; - wk->type = IEEE80211_WORK_AUTH_PROBE; - wk->timeout = jiffies; /* run right away */ + wk->type = IEEE80211_WORK_DIRECT_PROBE; wk->chan = req->bss->channel; + wk->sdata = sdata; + wk->done = ieee80211_probe_auth_done; /* * XXX: if still associated need to tell AP that we're going @@ -2505,29 +1802,58 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, sdata->local->oper_channel = req->bss->channel; ieee80211_hw_config(sdata->local, 0); - mutex_lock(&ifmgd->mtx); - list_add(&wk->list, &sdata->u.mgd.work_list); - mutex_unlock(&ifmgd->mtx); - - ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); + ieee80211_add_work(wk); return 0; } +static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, + struct sk_buff *skb) +{ + struct ieee80211_mgmt *mgmt; + u16 status; + + if (!skb) { + cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); + return WORK_DONE_DESTROY; + } + + mgmt = (void *)skb->data; + status = le16_to_cpu(mgmt->u.assoc_resp.status_code); + + if (status == WLAN_STATUS_SUCCESS) { + mutex_lock(&wk->sdata->u.mgd.mtx); + if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { + mutex_unlock(&wk->sdata->u.mgd.mtx); + /* oops -- internal error -- send timeout for now */ + cfg80211_send_assoc_timeout(wk->sdata->dev, + wk->filter_ta); + return WORK_DONE_DESTROY; + } + mutex_unlock(&wk->sdata->u.mgd.mtx); + } + + cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); + return WORK_DONE_DESTROY; +} + int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_work *wk; const u8 *ssid; - int i, err; + int i; mutex_lock(&ifmgd->mtx); + if (ifmgd->associated) { + mutex_unlock(&ifmgd->mtx); + return -EALREADY; + } + mutex_unlock(&ifmgd->mtx); wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); - if (!wk) { - err = -ENOMEM; - goto out; - } + if (!wk) + return -ENOMEM; ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; @@ -2546,8 +1872,19 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, wk->assoc.bss = (void *)req->bss; - memcpy(wk->assoc.bssid, req->bss->bssid, ETH_ALEN); + memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); + /* new association always uses requested smps mode */ + if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { + if (ifmgd->powersave) + ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; + else + ifmgd->ap_smps = IEEE80211_SMPS_OFF; + } else + ifmgd->ap_smps = ifmgd->req_smps; + + wk->assoc.smps = ifmgd->ap_smps; + wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); wk->assoc.capability = req->bss->capability; wk->assoc.wmm_used = wk->assoc.bss->wmm_used; wk->assoc.supp_rates = wk->assoc.bss->supp_rates; @@ -2563,8 +1900,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); wk->type = IEEE80211_WORK_ASSOC; - wk->timeout = jiffies; /* run right away */ wk->chan = req->bss->channel; + wk->sdata = sdata; + wk->done = ieee80211_assoc_done; if (req->use_mfp) { ifmgd->mfp = IEEE80211_MFP_REQUIRED; @@ -2582,56 +1920,56 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, sdata->local->oper_channel = req->bss->channel; ieee80211_hw_config(sdata->local, 0); - list_add(&wk->list, &ifmgd->work_list); - ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); - - err = 0; - - out: - mutex_unlock(&ifmgd->mtx); - return err; + ieee80211_add_work(wk); + return 0; } int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, struct cfg80211_deauth_request *req, void *cookie) { + struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_work *wk; const u8 *bssid = req->bss->bssid; - bool not_auth_yet = false; mutex_lock(&ifmgd->mtx); if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { bssid = req->bss->bssid; ieee80211_set_disassoc(sdata); - } else list_for_each_entry(wk, &ifmgd->work_list, list) { - if (wk->type != IEEE80211_WORK_AUTH_PROBE) - continue; - if (memcmp(req->bss->bssid, wk->auth.bssid, ETH_ALEN)) - continue; - not_auth_yet = true; - list_del(&wk->list); - kfree(wk); - break; - } + mutex_unlock(&ifmgd->mtx); + } else { + bool not_auth_yet = false; - /* - * If somebody requests authentication and we haven't - * sent out an auth frame yet there's no need to send - * out a deauth frame either. If the state was PROBE, - * then this is the case. If it's AUTH we have sent a - * frame, and if it's IDLE we have completed the auth - * process already. - */ - if (not_auth_yet) { mutex_unlock(&ifmgd->mtx); - __cfg80211_auth_canceled(sdata->dev, bssid); - return 0; - } - mutex_unlock(&ifmgd->mtx); + mutex_lock(&local->work_mtx); + list_for_each_entry(wk, &local->work_list, list) { + if (wk->type != IEEE80211_WORK_DIRECT_PROBE) + continue; + if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) + continue; + not_auth_yet = true; + list_del(&wk->list); + free_work(wk); + break; + } + mutex_unlock(&local->work_mtx); + + /* + * If somebody requests authentication and we haven't + * sent out an auth frame yet there's no need to send + * out a deauth frame either. If the state was PROBE, + * then this is the case. If it's AUTH we have sent a + * frame, and if it's IDLE we have completed the auth + * process already. + */ + if (not_auth_yet) { + __cfg80211_auth_canceled(sdata->dev, bssid); + return 0; + } + } printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", sdata->name, bssid, req->reason_code); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f60dfca52196..bfcf09eb64b4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1945,6 +1945,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + ieee80211_rx_result rxs; if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; @@ -1952,6 +1953,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) return RX_DROP_MONITOR; + rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); + if (rxs != RX_CONTINUE) + return rxs; + if (ieee80211_vif_is_mesh(&sdata->vif)) return ieee80211_mesh_rx_mgmt(sdata, rx->skb); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index d98c45e5528b..fb89e4c0fbfd 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -434,7 +434,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req) { struct ieee80211_local *local = sdata->local; - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; int rc; if (local->scan_req) @@ -464,11 +463,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, local->scan_req = req; local->scan_sdata = sdata; - if (req != local->int_scan_req && - sdata->vif.type == NL80211_IFTYPE_STATION && - !list_empty(&ifmgd->work_list)) { - /* actually wait for the work it's doing to finish/time out */ - set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); + if (!list_empty(&local->work_list)) { + /* wait for the work to finish/time out */ return 0; } diff --git a/net/mac80211/work.c b/net/mac80211/work.c new file mode 100644 index 000000000000..8b8961d806ab --- /dev/null +++ b/net/mac80211/work.c @@ -0,0 +1,902 @@ +/* + * mac80211 work implementation + * + * Copyright 2003-2008, Jouni Malinen + * Copyright 2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * Copyright 2009, Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211_i.h" +#include "rate.h" + +#define IEEE80211_AUTH_TIMEOUT (HZ / 5) +#define IEEE80211_AUTH_MAX_TRIES 3 +#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) +#define IEEE80211_ASSOC_MAX_TRIES 3 +#define IEEE80211_MAX_PROBE_TRIES 5 + +enum work_action { + WORK_ACT_NONE, + WORK_ACT_TIMEOUT, + WORK_ACT_DONE, +}; + + +/* utils */ +static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) +{ + WARN_ON(!mutex_is_locked(&local->work_mtx)); +} + +/* + * We can have multiple work items (and connection probing) + * scheduling this timer, but we need to take care to only + * reschedule it when it should fire _earlier_ than it was + * asked for before, or if it's not pending right now. This + * function ensures that. Note that it then is required to + * run this function for all timeouts after the first one + * has happened -- the work that runs from this timer will + * do that. + */ +static void run_again(struct ieee80211_local *local, + unsigned long timeout) +{ + ASSERT_WORK_MTX(local); + + if (!timer_pending(&local->work_timer) || + time_before(timeout, local->work_timer.expires)) + mod_timer(&local->work_timer, timeout); +} + +static void work_free_rcu(struct rcu_head *head) +{ + struct ieee80211_work *wk = + container_of(head, struct ieee80211_work, rcu_head); + + kfree(wk); +} + +void free_work(struct ieee80211_work *wk) +{ + call_rcu(&wk->rcu_head, work_free_rcu); +} + +static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, + struct ieee80211_supported_band *sband, + u32 *rates) +{ + int i, j, count; + *rates = 0; + count = 0; + for (i = 0; i < supp_rates_len; i++) { + int rate = (supp_rates[i] & 0x7F) * 5; + + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == rate) { + *rates |= BIT(j); + count++; + break; + } + } + + return count; +} + +/* frame sending functions */ + +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, + struct ieee80211_work *wk) +{ + struct ieee80211_local *local = sdata->local; + struct sk_buff *skb; + struct ieee80211_mgmt *mgmt; + u8 *pos; + const u8 *ies, *ht_ie; + int i, len, count, rates_len, supp_rates_len; + u16 capab; + struct ieee80211_supported_band *sband; + u32 rates = 0; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + 200 + wk->ie_len + + wk->assoc.ssid_len); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " + "frame\n", sdata->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + sband = local->hw.wiphy->bands[wk->chan->band]; + + capab = WLAN_CAPABILITY_ESS; + + if (sband->band == IEEE80211_BAND_2GHZ) { + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + } + + if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) + capab |= WLAN_CAPABILITY_PRIVACY; + + /* + * Get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode)... + */ + rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, + wk->assoc.supp_rates_len, + sband, &rates); + + if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && + (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) + capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); + memset(mgmt, 0, 24); + memcpy(mgmt->da, wk->filter_ta, ETH_ALEN); + memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN); + + if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { + skb_put(skb, 10); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); + mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, + ETH_ALEN); + } else { + skb_put(skb, 4); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); + mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); + mgmt->u.assoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); + } + + /* SSID */ + ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); + *pos++ = WLAN_EID_SSID; + *pos++ = wk->assoc.ssid_len; + memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); + + /* add all rates which were marked to be used above */ + supp_rates_len = rates_len; + if (supp_rates_len > 8) + supp_rates_len = 8; + + len = sband->n_bitrates; + pos = skb_put(skb, supp_rates_len + 2); + *pos++ = WLAN_EID_SUPP_RATES; + *pos++ = supp_rates_len; + + count = 0; + for (i = 0; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + if (++count == 8) + break; + } + } + + if (rates_len > count) { + pos = skb_put(skb, rates_len - count + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = rates_len - count; + + for (i++; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + } + } + + if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { + /* 1. power capabilities */ + pos = skb_put(skb, 4); + *pos++ = WLAN_EID_PWR_CAPABILITY; + *pos++ = 2; + *pos++ = 0; /* min tx power */ + *pos++ = local->hw.conf.channel->max_power; /* max tx power */ + + /* 2. supported channels */ + /* TODO: get this in reg domain format */ + pos = skb_put(skb, 2 * sband->n_channels + 2); + *pos++ = WLAN_EID_SUPPORTED_CHANNELS; + *pos++ = 2 * sband->n_channels; + for (i = 0; i < sband->n_channels; i++) { + *pos++ = ieee80211_frequency_to_channel( + sband->channels[i].center_freq); + *pos++ = 1; /* one channel in the subband*/ + } + } + + if (wk->ie_len && wk->ie) { + pos = skb_put(skb, wk->ie_len); + memcpy(pos, wk->ie, wk->ie_len); + } + + if (wk->assoc.wmm_used && local->hw.queues >= 4) { + pos = skb_put(skb, 9); + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 7; /* len */ + *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ + *pos++ = 0x50; + *pos++ = 0xf2; + *pos++ = 2; /* WME */ + *pos++ = 0; /* WME info */ + *pos++ = 1; /* WME ver */ + *pos++ = 0; + } + + /* wmm support is a must to HT */ + /* + * IEEE802.11n does not allow TKIP/WEP as pairwise + * ciphers in HT mode. We still associate in non-ht + * mode (11a/b/g) if any one of these ciphers is + * configured as pairwise. + */ + if (wk->assoc.use_11n && wk->assoc.wmm_used && + (local->hw.queues >= 4) && + sband->ht_cap.ht_supported && + (ht_ie = wk->assoc.ht_information_ie) && + ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { + struct ieee80211_ht_info *ht_info = + (struct ieee80211_ht_info *)(ht_ie + 2); + u16 cap = sband->ht_cap.cap; + __le16 tmp; + u32 flags = local->hw.conf.channel->flags; + + /* determine capability flags */ + + if (ieee80211_disable_40mhz_24ghz && + sband->band == IEEE80211_BAND_2GHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (flags & IEEE80211_CHAN_NO_HT40PLUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (flags & IEEE80211_CHAN_NO_HT40MINUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + } + + /* set SM PS mode properly */ + cap &= ~IEEE80211_HT_CAP_SM_PS; + switch (wk->assoc.smps) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); + case IEEE80211_SMPS_OFF: + cap |= WLAN_HT_CAP_SM_PS_DISABLED << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_STATIC: + cap |= WLAN_HT_CAP_SM_PS_STATIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_DYNAMIC: + cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + } + + /* reserve and fill IE */ + + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + + /* capability flags */ + tmp = cpu_to_le16(cap); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + + /* AMPDU parameters */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + + /* MCS set */ + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + + /* extended capabilities */ + pos += sizeof(__le16); + + /* BF capabilities */ + pos += sizeof(__le32); + + /* antenna selection */ + pos += sizeof(u8); + } + + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + ieee80211_tx_skb(sdata, skb); +} + +static void ieee80211_remove_auth_bss(struct ieee80211_local *local, + struct ieee80211_work *wk) +{ + struct cfg80211_bss *cbss; + u16 capa_val = WLAN_CAPABILITY_ESS; + + if (wk->probe_auth.privacy) + capa_val |= WLAN_CAPABILITY_PRIVACY; + + cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta, + wk->probe_auth.ssid, wk->probe_auth.ssid_len, + WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, + capa_val); + if (!cbss) + return; + + cfg80211_unlink_bss(local->hw.wiphy, cbss); + cfg80211_put_bss(cbss); +} + +static enum work_action __must_check +ieee80211_direct_probe(struct ieee80211_work *wk) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + + wk->probe_auth.tries++; + if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", + sdata->name, wk->filter_ta); + + /* + * Most likely AP is not in the range so remove the + * bss struct for that AP. + */ + ieee80211_remove_auth_bss(local, wk); + + /* + * We might have a pending scan which had no chance to run yet + * due to work needing to be done. Hence, queue the STAs work + * again for that. + */ + ieee80211_queue_work(&local->hw, &local->work_work); + return WORK_ACT_TIMEOUT; + } + + printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", + sdata->name, wk->filter_ta, wk->probe_auth.tries); + + /* + * Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, + wk->probe_auth.ssid_len, NULL, 0); + + wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; + run_again(local, wk->timeout); + + return WORK_ACT_NONE; +} + + +static enum work_action __must_check +ieee80211_authenticate(struct ieee80211_work *wk) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + + wk->probe_auth.tries++; + if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: authentication with AP %pM" + " timed out\n", sdata->name, wk->filter_ta); + + /* + * Most likely AP is not in the range so remove the + * bss struct for that AP. + */ + ieee80211_remove_auth_bss(local, wk); + + /* + * We might have a pending scan which had no chance to run yet + * due to work needing to be done. Hence, queue the STAs work + * again for that. + */ + ieee80211_queue_work(&local->hw, &local->work_work); + return WORK_ACT_TIMEOUT; + } + + printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", + sdata->name, wk->filter_ta, wk->probe_auth.tries); + + ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, + wk->ie_len, wk->filter_ta, NULL, 0, 0); + wk->probe_auth.transaction = 2; + + wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; + run_again(local, wk->timeout); + + return WORK_ACT_NONE; +} + +static enum work_action __must_check +ieee80211_associate(struct ieee80211_work *wk) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + + wk->assoc.tries++; + if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { + printk(KERN_DEBUG "%s: association with AP %pM" + " timed out\n", + sdata->name, wk->filter_ta); + + /* + * Most likely AP is not in the range so remove the + * bss struct for that AP. + */ + if (wk->assoc.bss) + cfg80211_unlink_bss(local->hw.wiphy, + &wk->assoc.bss->cbss); + + /* + * We might have a pending scan which had no chance to run yet + * due to work needing to be done. Hence, queue the STAs work + * again for that. + */ + ieee80211_queue_work(&local->hw, &local->work_work); + return WORK_ACT_TIMEOUT; + } + + printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", + sdata->name, wk->filter_ta, wk->assoc.tries); + ieee80211_send_assoc(sdata, wk); + + wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; + run_again(local, wk->timeout); + + return WORK_ACT_NONE; +} + +static void ieee80211_auth_challenge(struct ieee80211_work *wk, + struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + u8 *pos; + struct ieee802_11_elems elems; + + pos = mgmt->u.auth.variable; + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + if (!elems.challenge) + return; + ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, + elems.challenge - 2, elems.challenge_len + 2, + wk->filter_ta, wk->probe_auth.key, + wk->probe_auth.key_len, wk->probe_auth.key_idx); + wk->probe_auth.transaction = 4; +} + +static enum work_action __must_check +ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, + struct ieee80211_mgmt *mgmt, size_t len) +{ + u16 auth_alg, auth_transaction, status_code; + + if (wk->type != IEEE80211_WORK_AUTH) + return WORK_ACT_NONE; + + if (len < 24 + 6) + return WORK_ACT_NONE; + + auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); + auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); + status_code = le16_to_cpu(mgmt->u.auth.status_code); + + if (auth_alg != wk->probe_auth.algorithm || + auth_transaction != wk->probe_auth.transaction) + return WORK_ACT_NONE; + + if (status_code != WLAN_STATUS_SUCCESS) { + printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", + wk->sdata->name, mgmt->sa, status_code); + return WORK_ACT_DONE; + } + + switch (wk->probe_auth.algorithm) { + case WLAN_AUTH_OPEN: + case WLAN_AUTH_LEAP: + case WLAN_AUTH_FT: + break; + case WLAN_AUTH_SHARED_KEY: + if (wk->probe_auth.transaction != 4) { + ieee80211_auth_challenge(wk, mgmt, len); + /* need another frame */ + return WORK_ACT_NONE; + } + break; + default: + WARN_ON(1); + return WORK_ACT_NONE; + } + + printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name); + return WORK_ACT_DONE; +} + +static enum work_action __must_check +ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, + struct ieee80211_mgmt *mgmt, size_t len, + bool reassoc) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + u16 capab_info, status_code, aid; + struct ieee802_11_elems elems; + u8 *pos; + + /* + * AssocResp and ReassocResp have identical structure, so process both + * of them in this function. + */ + + if (len < 24 + 6) + return WORK_ACT_NONE; + + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); + status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); + aid = le16_to_cpu(mgmt->u.assoc_resp.aid); + + printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " + "status=%d aid=%d)\n", + sdata->name, reassoc ? "Rea" : "A", mgmt->sa, + capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); + + pos = mgmt->u.assoc_resp.variable; + ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); + + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && + elems.timeout_int && elems.timeout_int_len == 5 && + elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { + u32 tu, ms; + tu = get_unaligned_le32(elems.timeout_int + 1); + ms = tu * 1024 / 1000; + printk(KERN_DEBUG "%s: AP rejected association temporarily; " + "comeback duration %u TU (%u ms)\n", + sdata->name, tu, ms); + wk->timeout = jiffies + msecs_to_jiffies(ms); + if (ms > IEEE80211_ASSOC_TIMEOUT) + run_again(local, wk->timeout); + return WORK_ACT_NONE; + } + + if (status_code != WLAN_STATUS_SUCCESS) + printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", + sdata->name, status_code); + else + printk(KERN_DEBUG "%s: associated\n", sdata->name); + + return WORK_ACT_DONE; +} + +static enum work_action __must_check +ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, + struct ieee80211_mgmt *mgmt, size_t len, + struct ieee80211_rx_status *rx_status) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + size_t baselen; + + ASSERT_WORK_MTX(local); + + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; + if (baselen > len) + return WORK_ACT_NONE; + + printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); + return WORK_ACT_DONE; +} + +static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status; + struct ieee80211_mgmt *mgmt; + struct ieee80211_work *wk; + enum work_action rma = WORK_ACT_NONE; + u16 fc; + + rx_status = (struct ieee80211_rx_status *) skb->cb; + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = le16_to_cpu(mgmt->frame_control); + + mutex_lock(&local->work_mtx); + + list_for_each_entry(wk, &local->work_list, list) { + const u8 *bssid = NULL; + + switch (wk->type) { + case IEEE80211_WORK_DIRECT_PROBE: + case IEEE80211_WORK_AUTH: + case IEEE80211_WORK_ASSOC: + bssid = wk->filter_ta; + break; + default: + continue; + } + + /* + * Before queuing, we already verified mgmt->sa, + * so this is needed just for matching. + */ + if (compare_ether_addr(bssid, mgmt->bssid)) + continue; + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_PROBE_RESP: + rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, + rx_status); + break; + case IEEE80211_STYPE_AUTH: + rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len); + break; + case IEEE80211_STYPE_ASSOC_RESP: + rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, + skb->len, false); + break; + case IEEE80211_STYPE_REASSOC_RESP: + rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, + skb->len, true); + break; + default: + WARN_ON(1); + } + /* + * We've processed this frame for that work, so it can't + * belong to another work struct. + * NB: this is also required for correctness for 'rma'! + */ + break; + } + + switch (rma) { + case WORK_ACT_NONE: + break; + case WORK_ACT_DONE: + list_del_rcu(&wk->list); + break; + default: + WARN(1, "unexpected: %d", rma); + } + + mutex_unlock(&local->work_mtx); + + if (rma != WORK_ACT_DONE) + goto out; + + switch (wk->done(wk, skb)) { + case WORK_DONE_DESTROY: + free_work(wk); + break; + case WORK_DONE_REQUEUE: + synchronize_rcu(); + wk->timeout = jiffies; /* run again directly */ + mutex_lock(&local->work_mtx); + list_add_tail(&wk->list, &local->work_list); + mutex_unlock(&local->work_mtx); + } + + out: + kfree_skb(skb); +} + +static void ieee80211_work_timer(unsigned long data) +{ + struct ieee80211_local *local = (void *) data; + + if (local->quiescing) + return; + + ieee80211_queue_work(&local->hw, &local->work_work); +} + +static void ieee80211_work_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, work_work); + struct sk_buff *skb; + struct ieee80211_work *wk, *tmp; + LIST_HEAD(free_work); + enum work_action rma; + + if (local->scanning) + return; + + /* + * ieee80211_queue_work() should have picked up most cases, + * here we'll pick the the rest. + */ + if (WARN(local->suspended, "work scheduled while going to suspend\n")) + return; + + /* first process frames to avoid timing out while a frame is pending */ + while ((skb = skb_dequeue(&local->work_skb_queue))) + ieee80211_work_rx_queued_mgmt(local, skb); + + ieee80211_recalc_idle(local); + + mutex_lock(&local->work_mtx); + + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + if (time_is_after_jiffies(wk->timeout)) { + /* + * This work item isn't supposed to be worked on + * right now, but take care to adjust the timer + * properly. + */ + run_again(local, wk->timeout); + continue; + } + + switch (wk->type) { + default: + WARN_ON(1); + /* nothing */ + rma = WORK_ACT_NONE; + break; + case IEEE80211_WORK_DIRECT_PROBE: + rma = ieee80211_direct_probe(wk); + break; + case IEEE80211_WORK_AUTH: + rma = ieee80211_authenticate(wk); + break; + case IEEE80211_WORK_ASSOC: + rma = ieee80211_associate(wk); + break; + } + + switch (rma) { + case WORK_ACT_NONE: + /* no action required */ + break; + case WORK_ACT_TIMEOUT: + list_del_rcu(&wk->list); + synchronize_rcu(); + list_add(&wk->list, &free_work); + break; + default: + WARN(1, "unexpected: %d", rma); + } + } + + if (list_empty(&local->work_list) && local->scan_req) + ieee80211_queue_delayed_work(&local->hw, + &local->scan_work, + round_jiffies_relative(0)); + + mutex_unlock(&local->work_mtx); + + list_for_each_entry_safe(wk, tmp, &free_work, list) { + wk->done(wk, NULL); + list_del(&wk->list); + kfree(wk); + } +} + +void ieee80211_add_work(struct ieee80211_work *wk) +{ + struct ieee80211_local *local; + + if (WARN_ON(!wk->chan)) + return; + + if (WARN_ON(!wk->sdata)) + return; + + if (WARN_ON(!wk->done)) + return; + + wk->timeout = jiffies; + + local = wk->sdata->local; + mutex_lock(&local->work_mtx); + list_add_tail(&wk->list, &local->work_list); + mutex_unlock(&local->work_mtx); + + ieee80211_queue_work(&local->hw, &local->work_work); +} + +void ieee80211_work_init(struct ieee80211_local *local) +{ + mutex_init(&local->work_mtx); + INIT_LIST_HEAD(&local->work_list); + setup_timer(&local->work_timer, ieee80211_work_timer, + (unsigned long)local); + INIT_WORK(&local->work_work, ieee80211_work_work); + skb_queue_head_init(&local->work_skb_queue); +} + +void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk, *tmp; + + mutex_lock(&local->work_mtx); + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + list_del(&wk->list); + free_work(wk); + } + mutex_unlock(&local->work_mtx); +} + +ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_mgmt *mgmt; + struct ieee80211_work *wk; + u16 fc; + + if (skb->len < 24) + return RX_DROP_MONITOR; + + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = le16_to_cpu(mgmt->frame_control); + + list_for_each_entry_rcu(wk, &local->work_list, list) { + if (sdata != wk->sdata) + continue; + if (compare_ether_addr(wk->filter_ta, mgmt->sa)) + continue; + if (compare_ether_addr(wk->filter_ta, mgmt->bssid)) + continue; + + switch (fc & IEEE80211_FCTL_STYPE) { + case IEEE80211_STYPE_AUTH: + case IEEE80211_STYPE_PROBE_RESP: + case IEEE80211_STYPE_ASSOC_RESP: + case IEEE80211_STYPE_REASSOC_RESP: + case IEEE80211_STYPE_DEAUTH: + case IEEE80211_STYPE_DISASSOC: + skb_queue_tail(&local->work_skb_queue, skb); + ieee80211_queue_work(&local->hw, &local->work_work); + return RX_QUEUED; + } + } + + return RX_CONTINUE; +} -- cgit v1.2.3 From 7d3a1c3b03c3a571a2c8c393b75558a5f4a7532a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:36 +0100 Subject: mac80211: rewrite a few work messages The station we're authenticating/associating with may not always be an AP in the sense that word is mostly understood, so print only the MAC address of the peer instead. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/work.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 8b8961d806ab..874345918e83 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -376,7 +376,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) wk->probe_auth.tries++; if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", + printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", sdata->name, wk->filter_ta); /* @@ -394,7 +394,7 @@ ieee80211_direct_probe(struct ieee80211_work *wk) return WORK_ACT_TIMEOUT; } - printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", + printk(KERN_DEBUG "%s: direct probe to %pM (try %d)\n", sdata->name, wk->filter_ta, wk->probe_auth.tries); /* @@ -419,7 +419,7 @@ ieee80211_authenticate(struct ieee80211_work *wk) wk->probe_auth.tries++; if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { - printk(KERN_DEBUG "%s: authentication with AP %pM" + printk(KERN_DEBUG "%s: authentication with %pM" " timed out\n", sdata->name, wk->filter_ta); /* @@ -437,7 +437,7 @@ ieee80211_authenticate(struct ieee80211_work *wk) return WORK_ACT_TIMEOUT; } - printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", + printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n", sdata->name, wk->filter_ta, wk->probe_auth.tries); ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, @@ -458,7 +458,7 @@ ieee80211_associate(struct ieee80211_work *wk) wk->assoc.tries++; if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { - printk(KERN_DEBUG "%s: association with AP %pM" + printk(KERN_DEBUG "%s: association with %pM" " timed out\n", sdata->name, wk->filter_ta); @@ -479,7 +479,7 @@ ieee80211_associate(struct ieee80211_work *wk) return WORK_ACT_TIMEOUT; } - printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", + printk(KERN_DEBUG "%s: associate with %pM (try %d)\n", sdata->name, wk->filter_ta, wk->assoc.tries); ieee80211_send_assoc(sdata, wk); @@ -592,9 +592,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, u32 tu, ms; tu = get_unaligned_le32(elems.timeout_int + 1); ms = tu * 1024 / 1000; - printk(KERN_DEBUG "%s: AP rejected association temporarily; " + printk(KERN_DEBUG "%s: %pM rejected association temporarily; " "comeback duration %u TU (%u ms)\n", - sdata->name, tu, ms); + sdata->name, mgmt->sa, tu, ms); wk->timeout = jiffies + msecs_to_jiffies(ms); if (ms > IEEE80211_ASSOC_TIMEOUT) run_again(local, wk->timeout); @@ -602,8 +602,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, } if (status_code != WLAN_STATUS_SUCCESS) - printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - sdata->name, status_code); + printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", + sdata->name, mgmt->sa, status_code); else printk(KERN_DEBUG "%s: associated\n", sdata->name); -- cgit v1.2.3 From 77c8144ad3ee7fae834e13cb7e83f5b7c8c5329e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:37 +0100 Subject: mac80211: refactor association Refactor the code to reserve an skb of the right size (instead of hoping 200 bytes are enough forever), and also put HT IE generation into an own function. Additionally, put the HT IE before the vendor-specific WMM IE. This still leaves things not quite ordered correctly, due to user-specified IEs, add a note about that for now. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 7 ++ net/mac80211/work.c | 239 ++++++++++++++++++++++++++++------------------------ 2 files changed, 137 insertions(+), 109 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7c1f91bcc834..ea434b5a779e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1884,6 +1884,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->ap_smps = ifmgd->req_smps; wk->assoc.smps = ifmgd->ap_smps; + /* + * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. + * We still associate in non-HT mode (11a/b/g) if any one of these + * ciphers is configured as pairwise. + * We can set this to true for non-11n hardware, that'll be checked + * separately along with the peer capabilities. + */ wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); wk->assoc.capability = req->bss->capability; wk->assoc.wmm_used = wk->assoc.bss->wmm_used; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 874345918e83..c03c22d5bca3 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -100,6 +100,102 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, /* frame sending functions */ +static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, + struct ieee80211_supported_band *sband, + struct ieee80211_channel *channel, + enum ieee80211_smps_mode smps) +{ + struct ieee80211_ht_info *ht_info; + u8 *pos; + u32 flags = channel->flags; + u16 cap = sband->ht_cap.cap; + __le16 tmp; + + if (!sband->ht_cap.ht_supported) + return; + + if (!ht_info_ie) + return; + + if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) + return; + + ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); + + /* determine capability flags */ + + if (ieee80211_disable_40mhz_24ghz && + sband->band == IEEE80211_BAND_2GHZ) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (flags & IEEE80211_CHAN_NO_HT40PLUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (flags & IEEE80211_CHAN_NO_HT40MINUS) { + cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + cap &= ~IEEE80211_HT_CAP_SGI_40; + } + break; + } + + /* set SM PS mode properly */ + cap &= ~IEEE80211_HT_CAP_SM_PS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC: + case IEEE80211_SMPS_NUM_MODES: + WARN_ON(1); + case IEEE80211_SMPS_OFF: + cap |= WLAN_HT_CAP_SM_PS_DISABLED << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_STATIC: + cap |= WLAN_HT_CAP_SM_PS_STATIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + case IEEE80211_SMPS_DYNAMIC: + cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << + IEEE80211_HT_CAP_SM_PS_SHIFT; + break; + } + + /* reserve and fill IE */ + + pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); + *pos++ = WLAN_EID_HT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_ht_cap); + memset(pos, 0, sizeof(struct ieee80211_ht_cap)); + + /* capability flags */ + tmp = cpu_to_le16(cap); + memcpy(pos, &tmp, sizeof(u16)); + pos += sizeof(u16); + + /* AMPDU parameters */ + *pos++ = sband->ht_cap.ampdu_factor | + (sband->ht_cap.ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + + /* MCS set */ + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); + pos += sizeof(sband->ht_cap.mcs); + + /* extended capabilities */ + pos += sizeof(__le16); + + /* BF capabilities */ + pos += sizeof(__le32); + + /* antenna selection */ + pos += sizeof(u8); +} + static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_work *wk) { @@ -107,15 +203,34 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; - const u8 *ies, *ht_ie; + const u8 *ies; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_supported_band *sband; u32 rates = 0; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + - sizeof(*mgmt) + 200 + wk->ie_len + - wk->assoc.ssid_len); + sband = local->hw.wiphy->bands[wk->chan->band]; + + /* + * Get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode)... + */ + rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, + wk->assoc.supp_rates_len, + sband, &rates); + + skb = alloc_skb(local->hw.extra_tx_headroom + + sizeof(*mgmt) + /* bit too much but doesn't matter */ + 2 + wk->assoc.ssid_len + /* SSID */ + 4 + rates_len + /* (extended) rates */ + 4 + /* power capability */ + 2 + 2 * sband->n_channels + /* supported channels */ + 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ + wk->ie_len + /* extra IEs */ + 9, /* WMM */ + GFP_KERNEL); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " "frame\n", sdata->name); @@ -123,8 +238,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } skb_reserve(skb, local->hw.extra_tx_headroom); - sband = local->hw.wiphy->bands[wk->chan->band]; - capab = WLAN_CAPABILITY_ESS; if (sband->band == IEEE80211_BAND_2GHZ) { @@ -137,16 +250,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; - /* - * Get all rates supported by the device and the AP as - * some APs don't like getting a superset of their rates - * in the association request (e.g. D-Link DAP 1353 in - * b-only mode)... - */ - rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, - wk->assoc.supp_rates_len, - sband, &rates); - if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; @@ -220,7 +323,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, *pos++ = WLAN_EID_PWR_CAPABILITY; *pos++ = 2; *pos++ = 0; /* min tx power */ - *pos++ = local->hw.conf.channel->max_power; /* max tx power */ + *pos++ = wk->chan->max_power; /* max tx power */ /* 2. supported channels */ /* TODO: get this in reg domain format */ @@ -234,11 +337,21 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } } + /* + * XXX: These IEs could contain (vendor-specified) + * IEs that belong after HT -- the buffer may + * need to be split up. + */ if (wk->ie_len && wk->ie) { pos = skb_put(skb, wk->ie_len); memcpy(pos, wk->ie, wk->ie_len); } + if (wk->assoc.use_11n && wk->assoc.wmm_used && + local->hw.queues >= 4) + ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, + sband, wk->chan, wk->assoc.smps); + if (wk->assoc.wmm_used && local->hw.queues >= 4) { pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; @@ -252,98 +365,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, *pos++ = 0; } - /* wmm support is a must to HT */ - /* - * IEEE802.11n does not allow TKIP/WEP as pairwise - * ciphers in HT mode. We still associate in non-ht - * mode (11a/b/g) if any one of these ciphers is - * configured as pairwise. - */ - if (wk->assoc.use_11n && wk->assoc.wmm_used && - (local->hw.queues >= 4) && - sband->ht_cap.ht_supported && - (ht_ie = wk->assoc.ht_information_ie) && - ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { - struct ieee80211_ht_info *ht_info = - (struct ieee80211_ht_info *)(ht_ie + 2); - u16 cap = sband->ht_cap.cap; - __le16 tmp; - u32 flags = local->hw.conf.channel->flags; - - /* determine capability flags */ - - if (ieee80211_disable_40mhz_24ghz && - sband->band == IEEE80211_BAND_2GHZ) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - - switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_HT40PLUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_HT40MINUS) { - cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; - } - - /* set SM PS mode properly */ - cap &= ~IEEE80211_HT_CAP_SM_PS; - switch (wk->assoc.smps) { - case IEEE80211_SMPS_AUTOMATIC: - case IEEE80211_SMPS_NUM_MODES: - WARN_ON(1); - case IEEE80211_SMPS_OFF: - cap |= WLAN_HT_CAP_SM_PS_DISABLED << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_STATIC: - cap |= WLAN_HT_CAP_SM_PS_STATIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - case IEEE80211_SMPS_DYNAMIC: - cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << - IEEE80211_HT_CAP_SM_PS_SHIFT; - break; - } - - /* reserve and fill IE */ - - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - memset(pos, 0, sizeof(struct ieee80211_ht_cap)); - - /* capability flags */ - tmp = cpu_to_le16(cap); - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - - /* AMPDU parameters */ - *pos++ = sband->ht_cap.ampdu_factor | - (sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); - - /* MCS set */ - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); - pos += sizeof(sband->ht_cap.mcs); - - /* extended capabilities */ - pos += sizeof(__le16); - - /* BF capabilities */ - pos += sizeof(__le32); - - /* antenna selection */ - pos += sizeof(u8); - } - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } -- cgit v1.2.3 From 8e664fb3fd2b04e3ac5fad7f046000ba54e0e275 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:38 +0100 Subject: mac80211: split up and insert custom IEs correctly Currently, we insert all user-specified IEs before the HT IE for association, and after the HT IE for probe requests. For association, that's correct only if the user-specified IEs are RSN only, incorrect in all other cases including WPA. Change this to split apart the user-specified IEs in two places for association: before the HT IE (e.g. RSN), after the HT IE (generally empty right now I think?) and after WMM (all other vendor-specific IEs). For probes, split the IEs in different places to be correct according to the spec. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 39 ++++++++++--- net/mac80211/ieee80211_i.h | 4 ++ net/mac80211/util.c | 134 ++++++++++++++++++++++++++++++++++++++------- net/mac80211/work.c | 43 ++++++++++++--- 4 files changed, 184 insertions(+), 36 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d62edc7df3ae..aeea282bd2fe 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1085,12 +1085,12 @@ enum ieee80211_eid { WLAN_EID_TIM = 5, WLAN_EID_IBSS_PARAMS = 6, WLAN_EID_CHALLENGE = 16, - /* 802.11d */ + WLAN_EID_COUNTRY = 7, WLAN_EID_HP_PARAMS = 8, WLAN_EID_HP_TABLE = 9, WLAN_EID_REQUEST = 10, - /* 802.11e */ + WLAN_EID_QBSS_LOAD = 11, WLAN_EID_EDCA_PARAM_SET = 12, WLAN_EID_TSPEC = 13, @@ -1113,7 +1113,7 @@ enum ieee80211_eid { WLAN_EID_PREP = 69, WLAN_EID_PERR = 70, WLAN_EID_RANN = 49, /* compatible with FreeBSD */ - /* 802.11h */ + WLAN_EID_PWR_CONSTRAINT = 32, WLAN_EID_PWR_CAPABILITY = 33, WLAN_EID_TPC_REQUEST = 34, @@ -1124,20 +1124,41 @@ enum ieee80211_eid { WLAN_EID_MEASURE_REPORT = 39, WLAN_EID_QUIET = 40, WLAN_EID_IBSS_DFS = 41, - /* 802.11g */ + WLAN_EID_ERP_INFO = 42, WLAN_EID_EXT_SUPP_RATES = 50, - /* 802.11n */ + WLAN_EID_HT_CAPABILITY = 45, WLAN_EID_HT_INFORMATION = 61, - /* 802.11i */ + WLAN_EID_RSN = 48, - WLAN_EID_TIMEOUT_INTERVAL = 56, - WLAN_EID_MMIE = 76 /* 802.11w */, + WLAN_EID_MMIE = 76, WLAN_EID_WPA = 221, WLAN_EID_GENERIC = 221, WLAN_EID_VENDOR_SPECIFIC = 221, - WLAN_EID_QOS_PARAMETER = 222 + WLAN_EID_QOS_PARAMETER = 222, + + WLAN_EID_AP_CHAN_REPORT = 51, + WLAN_EID_NEIGHBOR_REPORT = 52, + WLAN_EID_RCPI = 53, + WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, + WLAN_EID_ANTENNA_INFO = 64, + WLAN_EID_RSNI = 65, + WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, + WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, + WLAN_EID_BSS_AC_ACCESS_DELAY = 68, + WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, + WLAN_EID_MULTIPLE_BSSID = 71, + + WLAN_EID_MOBILITY_DOMAIN = 54, + WLAN_EID_FAST_BSS_TRANSITION = 55, + WLAN_EID_TIMEOUT_INTERVAL = 56, + WLAN_EID_RIC_DATA = 57, + WLAN_EID_RIC_DESCRIPTOR = 75, + + WLAN_EID_DSE_REGISTERED_LOCATION = 58, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, + WLAN_EID_EXT_CHANSWITCH_ANN = 60, }; /* Action category code */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 97b6076b492e..6ea4ffbf84d8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1148,6 +1148,10 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, void ieee80211_recalc_smps(struct ieee80211_local *local, struct ieee80211_sub_if_data *forsdata); +size_t ieee80211_ie_split(const u8 *ies, size_t ielen, + const u8 *ids, int n_ids, size_t offset); +size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); + /* internal work items */ void ieee80211_work_init(struct ieee80211_local *local); void ieee80211_add_work(struct ieee80211_work *wk); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5ffe9e831b66..1fdb80ff9241 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -881,30 +881,66 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, enum ieee80211_band band) { struct ieee80211_supported_band *sband; - u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; - int i; + u8 *pos; + size_t offset = 0, noffset; + int supp_rates_len, i; sband = local->hw.wiphy->bands[band]; pos = buffer; + supp_rates_len = min_t(int, sband->n_bitrates, 8); + *pos++ = WLAN_EID_SUPP_RATES; - supp_rates_len = pos; - *pos++ = 0; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - - if (esupp_rates_len) { - *esupp_rates_len += 1; - } else if (*supp_rates_len == 8) { - *pos++ = WLAN_EID_EXT_SUPP_RATES; - esupp_rates_len = pos; - *pos++ = 1; - } else - *supp_rates_len += 1; + *pos++ = supp_rates_len; - *pos++ = rate->bitrate / 5; + for (i = 0; i < supp_rates_len; i++) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + + /* insert "request information" if in custom IEs */ + if (ie && ie_len) { + static const u8 before_extrates[] = { + WLAN_EID_SSID, + WLAN_EID_SUPP_RATES, + WLAN_EID_REQUEST, + }; + noffset = ieee80211_ie_split(ie, ie_len, + before_extrates, + ARRAY_SIZE(before_extrates), + offset); + memcpy(pos, ie + offset, noffset - offset); + pos += noffset - offset; + offset = noffset; + } + + if (sband->n_bitrates > i) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = sband->n_bitrates - i; + + for (; i < sband->n_bitrates; i++) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } + } + + /* insert custom IEs that go before HT */ + if (ie && ie_len) { + static const u8 before_ht[] = { + WLAN_EID_SSID, + WLAN_EID_SUPP_RATES, + WLAN_EID_REQUEST, + WLAN_EID_EXT_SUPP_RATES, + WLAN_EID_DS_PARAMS, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES, + }; + noffset = ieee80211_ie_split(ie, ie_len, + before_ht, ARRAY_SIZE(before_ht), + offset); + memcpy(pos, ie + offset, noffset - offset); + pos += noffset - offset; + offset = noffset; } if (sband->ht_cap.ht_supported) { @@ -936,9 +972,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, * that calculates local->scan_ies_len. */ - if (ie) { - memcpy(pos, ie, ie_len); - pos += ie_len; + /* add any remaining custom IEs */ + if (ie && ie_len) { + noffset = ie_len; + memcpy(pos, ie + offset, noffset - offset); + pos += noffset - offset; } return pos - buffer; @@ -1252,3 +1290,59 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, /* changed flag is auto-detected for this */ ieee80211_hw_config(local, 0); } + +static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) +{ + int i; + + for (i = 0; i < n_ids; i++) + if (ids[i] == id) + return true; + return false; +} + +/** + * ieee80211_ie_split - split an IE buffer according to ordering + * + * @ies: the IE buffer + * @ielen: the length of the IE buffer + * @ids: an array with element IDs that are allowed before + * the split + * @n_ids: the size of the element ID array + * @offset: offset where to start splitting in the buffer + * + * This function splits an IE buffer by updating the @offset + * variable to point to the location where the buffer should be + * split. + * + * It assumes that the given IE buffer is well-formed, this + * has to be guaranteed by the caller! + * + * It also assumes that the IEs in the buffer are ordered + * correctly, if not the result of using this function will not + * be ordered correctly either, i.e. it does no reordering. + * + * The function returns the offset where the next part of the + * buffer starts, which may be @ielen if the entire (remainder) + * of the buffer should be used. + */ +size_t ieee80211_ie_split(const u8 *ies, size_t ielen, + const u8 *ids, int n_ids, size_t offset) +{ + size_t pos = offset; + + while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) + pos += 2 + ies[pos + 1]; + + return pos; +} + +size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) +{ + size_t pos = offset; + + while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC) + pos += 2 + ies[pos + 1]; + + return pos; +} diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c03c22d5bca3..affdd10b67ad 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -204,6 +204,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt; u8 *pos; const u8 *ies; + size_t offset = 0, noffset; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_supported_band *sband; @@ -337,14 +338,26 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } } - /* - * XXX: These IEs could contain (vendor-specified) - * IEs that belong after HT -- the buffer may - * need to be split up. - */ + /* if present, add any custom IEs that go before HT */ if (wk->ie_len && wk->ie) { - pos = skb_put(skb, wk->ie_len); - memcpy(pos, wk->ie, wk->ie_len); + static const u8 before_ht[] = { + WLAN_EID_SSID, + WLAN_EID_SUPP_RATES, + WLAN_EID_EXT_SUPP_RATES, + WLAN_EID_PWR_CAPABILITY, + WLAN_EID_SUPPORTED_CHANNELS, + WLAN_EID_RSN, + WLAN_EID_QOS_CAPA, + WLAN_EID_RRM_ENABLED_CAPABILITIES, + WLAN_EID_MOBILITY_DOMAIN, + WLAN_EID_SUPPORTED_REGULATORY_CLASSES, + }; + noffset = ieee80211_ie_split(wk->ie, wk->ie_len, + before_ht, ARRAY_SIZE(before_ht), + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, wk->ie + offset, noffset - offset); + offset = noffset; } if (wk->assoc.use_11n && wk->assoc.wmm_used && @@ -352,6 +365,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, sband, wk->chan, wk->assoc.smps); + /* if present, add any custom non-vendor IEs that go after HT */ + if (wk->ie_len && wk->ie) { + noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, + offset); + pos = skb_put(skb, noffset - offset); + memcpy(pos, wk->ie + offset, noffset - offset); + offset = noffset; + } + if (wk->assoc.wmm_used && local->hw.queues >= 4) { pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; @@ -365,6 +387,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, *pos++ = 0; } + /* add any remaining custom (i.e. vendor specific here) IEs */ + if (wk->ie_len && wk->ie) { + noffset = wk->ie_len; + pos = skb_put(skb, noffset - offset); + memcpy(pos, wk->ie + offset, noffset - offset); + } + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } -- cgit v1.2.3 From 0c1ad2cac1cb54db38fd4cc1822965071ee83f6e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:39 +0100 Subject: mac80211: proper bss private data handling cfg80211 offers private data for each BSS struct, which mac80211 uses. However, mac80211 uses internal and external (cfg80211) BSS pointers interchangeably and has a hack to put the cfg80211 bss struct into the private struct. Remove this hack, properly converting between the pointers wherever necessary. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 2 +- net/mac80211/ibss.c | 45 ++++++++++++++++++-------------- net/mac80211/ieee80211_i.h | 7 ++--- net/mac80211/main.c | 4 +-- net/mac80211/mlme.c | 64 ++++++++++++++++++++++++---------------------- net/mac80211/scan.c | 29 +++++++++++++-------- net/mac80211/work.c | 3 +-- 7 files changed, 82 insertions(+), 72 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index fdac1bcbfcc0..ea862dfc08ed 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1343,7 +1343,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, return 0; } - ap = sdata->u.mgd.associated->cbss.bssid; + ap = sdata->u.mgd.associated->bssid; if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { if (sdata->u.mgd.powersave) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3a61f3ba85c9..621a54c0573a 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -187,15 +187,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss *bss) { + struct cfg80211_bss *cbss = + container_of((void *)bss, struct cfg80211_bss, priv); struct ieee80211_supported_band *sband; u32 basic_rates; int i, j; - u16 beacon_int = bss->cbss.beacon_interval; + u16 beacon_int = cbss->beacon_interval; if (beacon_int < 10) beacon_int = 10; - sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; + sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; basic_rates = 0; @@ -212,12 +214,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, } } - __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, + __ieee80211_sta_join_ibss(sdata, cbss->bssid, beacon_int, - bss->cbss.channel, + cbss->channel, basic_rates, - bss->cbss.capability, - bss->cbss.tsf); + cbss->capability, + cbss->tsf); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -229,6 +231,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; int freq; + struct cfg80211_bss *cbss; struct ieee80211_bss *bss; struct sta_info *sta; struct ieee80211_channel *channel; @@ -283,8 +286,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!bss) return; + cbss = container_of((void *)bss, struct cfg80211_bss, priv); + /* was just updated in ieee80211_bss_info_update */ - beacon_timestamp = bss->cbss.tsf; + beacon_timestamp = cbss->tsf; /* check if we need to merge IBSS */ @@ -297,11 +302,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, goto put_bss; /* not an IBSS */ - if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS)) + if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) goto put_bss; /* different channel */ - if (bss->cbss.channel != local->oper_channel) + if (cbss->channel != local->oper_channel) goto put_bss; /* different SSID */ @@ -311,7 +316,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, goto put_bss; /* same BSSID */ - if (memcmp(bss->cbss.bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) + if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) goto put_bss; if (rx_status->flag & RX_FLAG_TSFT) { @@ -514,7 +519,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; - struct ieee80211_bss *bss; + struct cfg80211_bss *cbss; struct ieee80211_channel *chan = NULL; const u8 *bssid = NULL; int active_ibss; @@ -538,21 +543,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) chan = ifibss->channel; if (!is_zero_ether_addr(ifibss->bssid)) bssid = ifibss->bssid; - bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, - ifibss->ssid, ifibss->ssid_len, - WLAN_CAPABILITY_IBSS | - WLAN_CAPABILITY_PRIVACY, - capability); + cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, + ifibss->ssid, ifibss->ssid_len, + WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY, + capability); + + if (cbss) { + struct ieee80211_bss *bss; - if (bss) { + bss = (void *)cbss->priv; #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG " sta_find_ibss: selected %pM current " - "%pM\n", bss->cbss.bssid, ifibss->bssid); + "%pM\n", cbss->bssid, ifibss->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" " based on configured SSID\n", - sdata->name, bss->cbss.bssid); + sdata->name, cbss->bssid); ieee80211_sta_join_ibss(sdata, bss); ieee80211_rx_bss_put(local, bss); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6ea4ffbf84d8..de068ad6223b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -71,9 +71,6 @@ struct ieee80211_fragment_entry { struct ieee80211_bss { - /* Yes, this is a hack */ - struct cfg80211_bss cbss; - /* don't want to look up all the time */ size_t ssid_len; u8 ssid[IEEE80211_MAX_SSID_LEN]; @@ -274,7 +271,7 @@ struct ieee80211_work { bool privacy; } probe_auth; struct { - struct ieee80211_bss *bss; + struct cfg80211_bss *bss; const u8 *supp_rates; const u8 *ht_information_ie; enum ieee80211_smps_mode smps; @@ -317,7 +314,7 @@ struct ieee80211_if_managed { int probe_send_count; struct mutex mtx; - struct ieee80211_bss *associated; + struct cfg80211_bss *associated; u8 bssid[ETH_ALEN]; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d35023ce7fa1..5fcd3548417e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -359,9 +359,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, WIPHY_FLAG_4ADDR_STATION; wiphy->privid = mac80211_wiphy_privid; - /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ - wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - - sizeof(struct cfg80211_bss); + wiphy->bss_priv_size = sizeof(struct ieee80211_bss); local = wiphy_priv(wiphy); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ea434b5a779e..e44f1ed0b0da 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -330,7 +330,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); /* XXX: shouldn't really modify cfg80211-owned data! */ - ifmgd->associated->cbss.channel = sdata->local->oper_channel; + ifmgd->associated->channel = sdata->local->oper_channel; ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_QUEUE_STOP_REASON_CSA); @@ -357,6 +357,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel_sw_ie *sw_elem, struct ieee80211_bss *bss) { + struct cfg80211_bss *cbss = + container_of((void *)bss, struct cfg80211_bss, priv); struct ieee80211_channel *new_ch; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); @@ -390,7 +392,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, mod_timer(&ifmgd->chswitch_timer, jiffies + msecs_to_jiffies(sw_elem->count * - bss->cbss.beacon_interval)); + cbss->beacon_interval)); } } @@ -670,23 +672,24 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, } static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, - struct ieee80211_bss *bss, + struct cfg80211_bss *cbss, u32 bss_info_changed) { + struct ieee80211_bss *bss = (void *)cbss->priv; struct ieee80211_local *local = sdata->local; bss_info_changed |= BSS_CHANGED_ASSOC; /* set timing information */ - sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval; - sdata->vif.bss_conf.timestamp = bss->cbss.tsf; + sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; + sdata->vif.bss_conf.timestamp = cbss->tsf; sdata->vif.bss_conf.dtim_period = bss->dtim_period; bss_info_changed |= BSS_CHANGED_BEACON_INT; bss_info_changed |= ieee80211_handle_bss_capability(sdata, - bss->cbss.capability, bss->has_erp_value, bss->erp_value); + cbss->capability, bss->has_erp_value, bss->erp_value); - sdata->u.mgd.associated = bss; - memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); + sdata->u.mgd.associated = cbss; + memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); /* just to be sure */ sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | @@ -737,7 +740,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) if (WARN_ON(!ifmgd->associated)) return; - memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); + memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); ifmgd->associated = NULL; memset(ifmgd->bssid, 0, ETH_ALEN); @@ -833,8 +836,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; const u8 *ssid; - ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID); - ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, + ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); + ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, ssid + 2, ssid[1], NULL, 0); ifmgd->probe_send_count++; @@ -928,7 +931,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ASSERT_MGD_MTX(ifmgd); - bssid = ifmgd->associated->cbss.bssid; + bssid = ifmgd->associated->bssid; reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); @@ -957,7 +960,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, if (WARN_ON(!ifmgd->associated)) return RX_MGMT_NONE; - if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN))) + if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) return RX_MGMT_NONE; reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); @@ -979,7 +982,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sta_info *sta; - struct ieee80211_bss *bss = wk->assoc.bss; + struct cfg80211_bss *cbss = wk->assoc.bss; u8 *pos; u32 rates, basic_rates; u16 capab_info, aid; @@ -1011,7 +1014,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, ifmgd->aid = aid; - sta = sta_info_alloc(sdata, bss->cbss.bssid, GFP_KERNEL); + sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" " the AP\n", sdata->name); @@ -1103,14 +1106,13 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, (sdata->local->hw.queues >= 4) && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, - bss->cbss.bssid, - ap_ht_cap_flags); + cbss->bssid, ap_ht_cap_flags); /* set AID and assoc capability, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(sdata, bss, changed); + ieee80211_set_associated(sdata, cbss, changed); /* * Start timer to probe the connection to the AP now. @@ -1154,7 +1156,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, return; if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && - (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid, + (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)) { struct ieee80211_channel_sw_ie *sw_elem = (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; @@ -1189,7 +1191,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); if (ifmgd->associated && - memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && + memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && ifmgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL)) { ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | @@ -1262,7 +1264,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (!ifmgd->associated) return; - bssid = ifmgd->associated->cbss.bssid; + bssid = ifmgd->associated->bssid; /* * And in theory even frames from a different AP we were just @@ -1428,8 +1430,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, mutex_lock(&ifmgd->mtx); if (ifmgd->associated && - memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid, - ETH_ALEN) == 0) { + memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_BEACON: ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, @@ -1448,7 +1449,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, /* XXX: differentiate, can only happen for CSA now! */ ieee80211_sta_process_chanswitch(sdata, &mgmt->u.action.u.chan_switch.sw_elem, - ifmgd->associated); + (void *)ifmgd->associated->priv); break; } mutex_unlock(&ifmgd->mtx); @@ -1533,7 +1534,7 @@ static void ieee80211_sta_work(struct work_struct *work) ifmgd->associated) { u8 bssid[ETH_ALEN]; - memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); + memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); if (time_is_after_jiffies(ifmgd->probe_timeout)) run_again(ifmgd, ifmgd->probe_timeout); @@ -1840,6 +1841,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_assoc_request *req) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_work *wk; const u8 *ssid; int i; @@ -1870,7 +1872,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } else wk->ie_len = 0; - wk->assoc.bss = (void *)req->bss; + wk->assoc.bss = req->bss; memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); @@ -1893,9 +1895,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, */ wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); wk->assoc.capability = req->bss->capability; - wk->assoc.wmm_used = wk->assoc.bss->wmm_used; - wk->assoc.supp_rates = wk->assoc.bss->supp_rates; - wk->assoc.supp_rates_len = wk->assoc.bss->supp_rates_len; + wk->assoc.wmm_used = bss->wmm_used; + wk->assoc.supp_rates = bss->supp_rates; + wk->assoc.supp_rates_len = bss->supp_rates_len; wk->assoc.ht_information_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); @@ -1942,7 +1944,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_lock(&ifmgd->mtx); - if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { + if (ifmgd->associated == req->bss) { bssid = req->bss->bssid; ieee80211_set_disassoc(sdata); mutex_unlock(&ifmgd->mtx); @@ -2004,7 +2006,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, * to cfg80211 while that's in a locked section already * trying to tell us that the user wants to disconnect. */ - if (&ifmgd->associated->cbss != req->bss) { + if (ifmgd->associated != req->bss) { mutex_unlock(&ifmgd->mtx); return -ENOLINK; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index fb89e4c0fbfd..2a2d7f6005af 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -29,16 +29,19 @@ struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - return (void *)cfg80211_get_bss(local->hw.wiphy, - ieee80211_get_channel(local->hw.wiphy, - freq), - bssid, ssid, ssid_len, - 0, 0); + struct cfg80211_bss *cbss; + + cbss = cfg80211_get_bss(local->hw.wiphy, + ieee80211_get_channel(local->hw.wiphy, freq), + bssid, ssid, ssid_len, 0, 0); + if (!cbss) + return NULL; + return (void *)cbss->priv; } static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) { - struct ieee80211_bss *bss = (void *)cbss; + struct ieee80211_bss *bss = (void *)cbss->priv; kfree(bss_mesh_id(bss)); kfree(bss_mesh_cfg(bss)); @@ -47,7 +50,9 @@ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss) { - cfg80211_put_bss((struct cfg80211_bss *)bss); + if (!bss) + return; + cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); } struct ieee80211_bss * @@ -59,6 +64,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_channel *channel, bool beacon) { + struct cfg80211_bss *cbss; struct ieee80211_bss *bss; int clen; s32 signal = 0; @@ -68,13 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local, else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) signal = (rx_status->signal * 100) / local->hw.max_signal; - bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel, - mgmt, len, signal, GFP_ATOMIC); + cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, + mgmt, len, signal, GFP_ATOMIC); - if (!bss) + if (!cbss) return NULL; - bss->cbss.free_priv = ieee80211_rx_bss_free; + cbss->free_priv = ieee80211_rx_bss_free; + bss = (void *)cbss->priv; /* save the ERP value so that it is available at association time */ if (elems->erp_info && elems->erp_info_len >= 1) { diff --git a/net/mac80211/work.c b/net/mac80211/work.c index affdd10b67ad..0b8c31c600aa 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -517,8 +517,7 @@ ieee80211_associate(struct ieee80211_work *wk) * bss struct for that AP. */ if (wk->assoc.bss) - cfg80211_unlink_bss(local->hw.wiphy, - &wk->assoc.bss->cbss); + cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); /* * We might have a pending scan which had no chance to run yet -- cgit v1.2.3 From b203ffc3a447eb8d9e6120b783ddee081b143061 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Dec 2009 13:15:40 +0100 Subject: mac80211: Generalize off-channel operation helpers from scan code The off-channel operations for going into power save mode (station mode) or stop beaconing (AP/IBSS) are not limited to scanning. Move these into a separate file and allow them to be used for other purposes, too. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/Makefile | 2 +- net/mac80211/ieee80211_i.h | 8 ++- net/mac80211/offchannel.c | 164 +++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/scan.c | 156 ++---------------------------------------- 4 files changed, 178 insertions(+), 152 deletions(-) create mode 100644 net/mac80211/offchannel.c diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 5a1f57df7cd6..04420291e7ad 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -6,7 +6,7 @@ mac80211-y := \ sta_info.o \ wep.o \ wpa.o \ - scan.o \ + scan.o offchannel.o \ ht.o agg-tx.o agg-rx.o \ ibss.o \ mlme.o work.o \ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index de068ad6223b..fd912eb5309e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -786,7 +786,7 @@ struct ieee80211_local { unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ bool pspolling; - bool scan_ps_enabled; + bool offchannel_ps_enabled; /* * PS can only be enabled when we have exactly one managed * interface (and monitors) in PS, this then points there. @@ -981,6 +981,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss); +/* off-channel helpers */ +void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); +void ieee80211_offchannel_stop_station(struct ieee80211_local *local); +void ieee80211_offchannel_return(struct ieee80211_local *local, + bool enable_beaconing); + /* interface handling */ int ieee80211_iface_init(void); void ieee80211_iface_exit(void); diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c new file mode 100644 index 000000000000..2cd880e444d1 --- /dev/null +++ b/net/mac80211/offchannel.c @@ -0,0 +1,164 @@ +/* + * Off-channel operation helpers + * + * Copyright 2003, Jouni Malinen + * Copyright 2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * Copyright 2009 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include "ieee80211_i.h" + +/* + * inform AP that we will go to sleep so that it will buffer the frames + * while we scan + */ +static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + local->offchannel_ps_enabled = false; + + /* FIXME: what to do when local->pspolling is true? */ + + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->offchannel_ps_enabled = true; + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + + if (!(local->offchannel_ps_enabled) || + !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) + /* + * If power save was enabled, no need to send a nullfunc + * frame because AP knows that we are sleeping. But if the + * hardware is creating the nullfunc frame for power save + * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not + * enabled) and power save was enabled, the firmware just + * sent a null frame with power save disabled. So we need + * to send a new nullfunc frame to inform the AP that we + * are again sleeping. + */ + ieee80211_send_nullfunc(local, sdata, 1); +} + +/* inform AP that we are awake again, unless power save is enabled */ +static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + + if (!local->ps_sdata) + ieee80211_send_nullfunc(local, sdata, 0); + else if (local->offchannel_ps_enabled) { + /* + * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware + * will send a nullfunc frame with the powersave bit set + * even though the AP already knows that we are sleeping. + * This could be avoided by sending a null frame with power + * save bit disabled before enabling the power save, but + * this doesn't gain anything. + * + * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need + * to send a nullfunc frame because AP already knows that + * we are sleeping, let's just enable power save mode in + * hardware. + */ + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } else if (local->hw.conf.dynamic_ps_timeout > 0) { + /* + * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer + * had been running before leaving the operating channel, + * restart the timer now and send a nullfunc frame to inform + * the AP that we are awake. + */ + ieee80211_send_nullfunc(local, sdata, 0); + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); + } +} + +void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + + /* disable beaconing */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); + + /* + * only handle non-STA interfaces here, STA interfaces + * are handled in ieee80211_offchannel_stop_station(), + * e.g., from the background scan state machine + */ + if (sdata->vif.type != NL80211_IFTYPE_STATION) + netif_stop_queue(sdata->dev); + } + mutex_unlock(&local->iflist_mtx); +} + +void ieee80211_offchannel_stop_station(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + /* + * notify the AP about us leaving the channel and stop all STA interfaces + */ + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + netif_stop_queue(sdata->dev); + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_enable(sdata); + } + } + mutex_unlock(&local->iflist_mtx); +} + +void ieee80211_offchannel_return(struct ieee80211_local *local, + bool enable_beaconing) +{ + struct ieee80211_sub_if_data *sdata; + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + + /* Tell AP we're back */ + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); + netif_wake_queue(sdata->dev); + } + + /* re-enable beaconing */ + if (enable_beaconing && + (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_ADHOC || + sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) + ieee80211_bss_info_change_notify( + sdata, BSS_CHANGED_BEACON_ENABLED); + } + mutex_unlock(&local->iflist_mtx); +} diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 2a2d7f6005af..365f40975511 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -227,82 +227,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) return true; } -/* - * inform AP that we will go to sleep so that it will buffer the frames - * while we scan - */ -static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - - local->scan_ps_enabled = false; - - /* FIXME: what to do when local->pspolling is true? */ - - del_timer_sync(&local->dynamic_ps_timer); - cancel_work_sync(&local->dynamic_ps_enable_work); - - if (local->hw.conf.flags & IEEE80211_CONF_PS) { - local->scan_ps_enabled = true; - local->hw.conf.flags &= ~IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - - if (!(local->scan_ps_enabled) || - !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) - /* - * If power save was enabled, no need to send a nullfunc - * frame because AP knows that we are sleeping. But if the - * hardware is creating the nullfunc frame for power save - * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not - * enabled) and power save was enabled, the firmware just - * sent a null frame with power save disabled. So we need - * to send a new nullfunc frame to inform the AP that we - * are again sleeping. - */ - ieee80211_send_nullfunc(local, sdata, 1); -} - -/* inform AP that we are awake again, unless power save is enabled */ -static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - - if (!local->ps_sdata) - ieee80211_send_nullfunc(local, sdata, 0); - else if (local->scan_ps_enabled) { - /* - * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware - * will send a nullfunc frame with the powersave bit set - * even though the AP already knows that we are sleeping. - * This could be avoided by sending a null frame with power - * save bit disabled before enabling the power save, but - * this doesn't gain anything. - * - * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need - * to send a nullfunc frame because AP already knows that - * we are sleeping, let's just enable power save mode in - * hardware. - */ - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } else if (local->hw.conf.dynamic_ps_timeout > 0) { - /* - * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer - * had been running before leaving the operating channel, - * restart the timer now and send a nullfunc frame to inform - * the AP that we are awake. - */ - ieee80211_send_nullfunc(local, sdata, 0); - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); - } -} - void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) { struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_sub_if_data *sdata; bool was_hw_scan; mutex_lock(&local->scan_mtx); @@ -351,28 +278,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) drv_sw_scan_complete(local); - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - - /* Tell AP we're back */ - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) { - ieee80211_scan_ps_disable(sdata); - netif_wake_queue(sdata->dev); - } - } else - netif_wake_queue(sdata->dev); - - /* re-enable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_bss_info_change_notify( - sdata, BSS_CHANGED_BEACON_ENABLED); - } - mutex_unlock(&local->iflist_mtx); + ieee80211_offchannel_return(local, true); done: ieee80211_recalc_idle(local); @@ -384,8 +290,6 @@ EXPORT_SYMBOL(ieee80211_scan_completed); static int ieee80211_start_sw_scan(struct ieee80211_local *local) { - struct ieee80211_sub_if_data *sdata; - /* * Hardware/driver doesn't support hw_scan, so use software * scanning instead. First send a nullfunc frame with power save @@ -401,26 +305,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) */ drv_sw_scan_start(local); - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - - /* disable beaconing */ - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) - ieee80211_bss_info_change_notify( - sdata, BSS_CHANGED_BEACON_ENABLED); - - /* - * only handle non-STA interfaces here, STA interfaces - * are handled in the scan state machine - */ - if (sdata->vif.type != NL80211_IFTYPE_STATION) - netif_stop_queue(sdata->dev); - } - mutex_unlock(&local->iflist_mtx); + ieee80211_offchannel_stop_beaconing(local); local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; @@ -568,23 +453,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, unsigned long *next_delay) { - struct ieee80211_sub_if_data *sdata; - - /* - * notify the AP about us leaving the channel and stop all STA interfaces - */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - netif_stop_queue(sdata->dev); - if (sdata->u.mgd.associated) - ieee80211_scan_ps_enable(sdata); - } - } - mutex_unlock(&local->iflist_mtx); + ieee80211_offchannel_stop_station(local); __set_bit(SCAN_OFF_CHANNEL, &local->scanning); @@ -604,28 +473,15 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, unsigned long *next_delay) { - struct ieee80211_sub_if_data *sdata = local->scan_sdata; - /* switch back to the operating channel */ local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); /* - * notify the AP about us being back and restart all STA interfaces + * Only re-enable station mode interface now; beaconing will be + * re-enabled once the full scan has been completed. */ - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (!ieee80211_sdata_running(sdata)) - continue; - - /* Tell AP we're back */ - if (sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_scan_ps_disable(sdata); - netif_wake_queue(sdata->dev); - } - } - mutex_unlock(&local->iflist_mtx); + ieee80211_offchannel_return(local, false); __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); -- cgit v1.2.3 From 9588bbd5529461a3dacd435bf239c84c3508f569 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Dec 2009 13:15:41 +0100 Subject: cfg80211: add remain-on-channel command Add new commands for requesting the driver to remain awake on a specified channel for the specified amount of time (and another command to cancel such an operation). This can be used to implement userspace-controlled off-channel operations, like Public Action frame exchange on another channel than the operation channel. The off-channel operation should behave similarly to scan, i.e. the local station (if associated) moves into power save mode to request the AP to buffer frames for it and then moves to the other channel to allow the off-channel operation to be completed. The duration parameter can be used to request enough time to receive a response from the target station. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 36 ++++++++ include/net/cfg80211.h | 47 +++++++++++ net/wireless/chan.c | 41 +++++---- net/wireless/core.h | 3 + net/wireless/mlme.c | 27 ++++++ net/wireless/nl80211.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++- net/wireless/nl80211.h | 11 +++ 7 files changed, 368 insertions(+), 15 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index da8ea2e19273..2bfbe88837ef 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -270,6 +270,31 @@ * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices * associated with this wiphy must be down and will follow. * + * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified + * channel for the specified amount of time. This can be used to do + * off-channel operations like transmit a Public Action frame and wait for + * a response while being associated to an AP on another channel. + * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which + * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the + * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be + * optionally used to specify additional channel parameters. + * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds + * to remain on the channel. This command is also used as an event to + * notify when the requested duration starts (it may take a while for the + * driver to schedule this time due to other concurrent needs for the + * radio). + * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) + * that will be included with any events pertaining to this request; + * the cookie is also used to cancel the request. + * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a + * pending remain-on-channel duration if the desired operation has been + * completed prior to expiration of the originally requested duration. + * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the + * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to + * uniquely identify the request. + * This command is also used as an event to notify when a requested + * remain-on-channel duration has expired. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -353,6 +378,9 @@ enum nl80211_commands { NL80211_CMD_DEL_PMKSA, NL80211_CMD_FLUSH_PMKSA, + NL80211_CMD_REMAIN_ON_CHANNEL, + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -606,6 +634,10 @@ enum nl80211_commands { * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can * cache, a wiphy attribute. * + * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. + * + * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -743,6 +775,10 @@ enum nl80211_attrs { NL80211_ATTR_PMKID, NL80211_ATTR_MAX_NUM_PMKIDS, + NL80211_ATTR_DURATION, + + NL80211_ATTR_COOKIE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 542a477a94da..b66beb052054 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -988,6 +988,15 @@ struct cfg80211_pmksa { * * @dump_survey: get site survey information. * + * @remain_on_channel: Request the driver to remain awake on the specified + * channel for the specified duration to complete an off-channel + * operation (e.g., public action frame exchange). When the driver is + * ready on the requested channel, it must indicate this with an event + * notification by calling cfg80211_ready_on_channel(). + * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. + * This allows the operation to be terminated prior to timeout based on + * the duration value. + * * @testmode_cmd: run a test mode command * * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac @@ -1123,6 +1132,16 @@ struct cfg80211_ops { struct cfg80211_pmksa *pmksa); int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev); + int (*remain_on_channel)(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, + u64 *cookie); + int (*cancel_remain_on_channel)(struct wiphy *wiphy, + struct net_device *dev, + u64 cookie); + /* some temporary stuff to finish wext */ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); @@ -2147,5 +2166,33 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid, void cfg80211_disconnected(struct net_device *dev, u16 reason, u8 *ie, size_t ie_len, gfp_t gfp); +/** + * cfg80211_ready_on_channel - notification of remain_on_channel start + * @dev: network device + * @cookie: the request cookie + * @chan: The current channel (from remain_on_channel request) + * @channel_type: Channel type + * @duration: Duration in milliseconds that the driver intents to remain on the + * channel + * @gfp: allocation flags + */ +void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, gfp_t gfp); + +/** + * cfg80211_remain_on_channel_expired - remain_on_channel duration expired + * @dev: network device + * @cookie: the request cookie + * @chan: The current channel (from remain_on_channel request) + * @channel_type: Channel type + * @gfp: allocation flags + */ +void cfg80211_remain_on_channel_expired(struct net_device *dev, + u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + gfp_t gfp); #endif /* __NET_CFG80211_H */ diff --git a/net/wireless/chan.c b/net/wireless/chan.c index a46ac6c9b365..bf1737fc9a7e 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -41,44 +41,57 @@ rdev_fixed_channel(struct cfg80211_registered_device *rdev, return result; } -int rdev_set_freq(struct cfg80211_registered_device *rdev, - struct wireless_dev *for_wdev, +struct ieee80211_channel * +rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type) { struct ieee80211_channel *chan; struct ieee80211_sta_ht_cap *ht_cap; - int result; - - if (rdev_fixed_channel(rdev, for_wdev)) - return -EBUSY; - - if (!rdev->ops->set_channel) - return -EOPNOTSUPP; chan = ieee80211_get_channel(&rdev->wiphy, freq); /* Primary channel not allowed */ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) - return -EINVAL; + return NULL; if (channel_type == NL80211_CHAN_HT40MINUS && chan->flags & IEEE80211_CHAN_NO_HT40MINUS) - return -EINVAL; + return NULL; else if (channel_type == NL80211_CHAN_HT40PLUS && chan->flags & IEEE80211_CHAN_NO_HT40PLUS) - return -EINVAL; + return NULL; ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; if (channel_type != NL80211_CHAN_NO_HT) { if (!ht_cap->ht_supported) - return -EINVAL; + return NULL; if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) - return -EINVAL; + return NULL; } + return chan; +} + +int rdev_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *for_wdev, + int freq, enum nl80211_channel_type channel_type) +{ + struct ieee80211_channel *chan; + int result; + + if (rdev_fixed_channel(rdev, for_wdev)) + return -EBUSY; + + if (!rdev->ops->set_channel) + return -EOPNOTSUPP; + + chan = rdev_freq_to_chan(rdev, freq, channel_type); + if (!chan) + return -EINVAL; + result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type); if (result) return result; diff --git a/net/wireless/core.h b/net/wireless/core.h index 35b712127143..30ec95f05b52 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -374,6 +374,9 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); struct ieee80211_channel * rdev_fixed_channel(struct cfg80211_registered_device *rdev, struct wireless_dev *for_wdev); +struct ieee80211_channel * +rdev_freq_to_chan(struct cfg80211_registered_device *rdev, + int freq, enum nl80211_channel_type channel_type); int rdev_set_freq(struct cfg80211_registered_device *rdev, struct wireless_dev *for_wdev, int freq, enum nl80211_channel_type channel_type); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index acaeaa784d68..11f6469b3f98 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -680,3 +680,30 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, } } } + +void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type, + duration, gfp); +} +EXPORT_SYMBOL(cfg80211_ready_on_channel); + +void cfg80211_remain_on_channel_expired(struct net_device *dev, + u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan, + channel_type, gfp); +} +EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 60f854377f90..ff857f10cb85 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -141,6 +141,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, .len = WLAN_PMKID_LEN }, + [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, + [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, }; /* policy for the attributes */ @@ -569,6 +571,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(set_pmksa, SET_PMKSA); CMD(del_pmksa, DEL_PMKSA); CMD(flush_pmksa, FLUSH_PMKSA); + CMD(remain_on_channel, REMAIN_ON_CHANNEL); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); @@ -4283,6 +4286,143 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) } +static int nl80211_remain_on_channel(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct net_device *dev; + struct ieee80211_channel *chan; + struct sk_buff *msg; + void *hdr; + u64 cookie; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u32 freq, duration; + int err; + + if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || + !info->attrs[NL80211_ATTR_DURATION]) + return -EINVAL; + + duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); + + /* + * We should be on that channel for at least one jiffie, + * and more than 5 seconds seems excessive. + */ + if (!duration || !msecs_to_jiffies(duration) || duration > 5000) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + if (!rdev->ops->remain_on_channel) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { + channel_type = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); + if (channel_type != NL80211_CHAN_NO_HT && + channel_type != NL80211_CHAN_HT20 && + channel_type != NL80211_CHAN_HT40PLUS && + channel_type != NL80211_CHAN_HT40MINUS) + err = -EINVAL; + goto out; + } + + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + chan = rdev_freq_to_chan(rdev, freq, channel_type); + if (chan == NULL) { + err = -EINVAL; + goto out; + } + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) { + err = -ENOMEM; + goto out; + } + + hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, + NL80211_CMD_REMAIN_ON_CHANNEL); + + if (IS_ERR(hdr)) { + err = PTR_ERR(hdr); + goto free_msg; + } + + err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan, + channel_type, duration, &cookie); + + if (err) + goto free_msg; + + NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + + genlmsg_end(msg, hdr); + err = genlmsg_reply(msg, info); + goto out; + + nla_put_failure: + err = -ENOBUFS; + free_msg: + nlmsg_free(msg); + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct net_device *dev; + u64 cookie; + int err; + + if (!info->attrs[NL80211_ATTR_COOKIE]) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + if (!rdev->ops->cancel_remain_on_channel) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); + + err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); + + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -4545,8 +4685,20 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, - + { + .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, + .doit = nl80211_remain_on_channel, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + .doit = nl80211_cancel_remain_on_channel, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; + static struct genl_multicast_group nl80211_mlme_mcgrp = { .name = "mlme", }; @@ -5134,6 +5286,70 @@ nla_put_failure: nlmsg_free(msg); } +static void nl80211_send_remain_on_chan_event( + int cmd, struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type); + NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + + if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL) + NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, gfp_t gfp) +{ + nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, + rdev, netdev, cookie, chan, + channel_type, duration, gfp); +} + +void nl80211_send_remain_on_channel_cancel( + struct cfg80211_registered_device *rdev, struct net_device *netdev, + u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp) +{ + nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + rdev, netdev, cookie, chan, + channel_type, 0, gfp); +} + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 44cc2a76a1b0..a5e2de419b7a 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -59,4 +59,15 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, gfp_t gfp); +void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + u64 cookie, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, gfp_t gfp); +void nl80211_send_remain_on_channel_cancel( + struct cfg80211_registered_device *rdev, struct net_device *netdev, + u64 cookie, struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ -- cgit v1.2.3 From b8bc4b0aa9bfba755c64b11b8f60e6cfab25dc9d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:42 +0100 Subject: mac80211: support remain-on-channel command This implements the new remain-on-channel cfg80211 command in mac80211, extending the work interface. Also change the work purge code to be able to clean up events properly (pretending they timed out.) Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 24 ++++++++ net/mac80211/ieee80211_i.h | 15 +++++ net/mac80211/main.c | 3 + net/mac80211/mlme.c | 3 + net/mac80211/offchannel.c | 8 ++- net/mac80211/work.c | 134 +++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 181 insertions(+), 6 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ea862dfc08ed..2e5e841e9b7b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1441,6 +1441,28 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, return -EINVAL; } +static int ieee80211_remain_on_channel(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, + u64 *cookie) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, + duration, cookie); +} + +static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct net_device *dev, + u64 cookie) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1487,4 +1509,6 @@ struct cfg80211_ops mac80211_config_ops = { CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) .set_power_mgmt = ieee80211_set_power_mgmt, .set_bitrate_mask = ieee80211_set_bitrate_mask, + .remain_on_channel = ieee80211_remain_on_channel, + .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fd912eb5309e..23547ebacf3d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -225,9 +225,11 @@ struct mesh_preq_queue { }; enum ieee80211_work_type { + IEEE80211_WORK_ABORT, IEEE80211_WORK_DIRECT_PROBE, IEEE80211_WORK_AUTH, IEEE80211_WORK_ASSOC, + IEEE80211_WORK_REMAIN_ON_CHANNEL, }; /** @@ -283,6 +285,9 @@ struct ieee80211_work { u8 supp_rates_len; bool wmm_used, use_11n; } assoc; + struct { + unsigned long timeout; + } remain; }; int ie_len; @@ -729,6 +734,10 @@ struct ieee80211_local { enum nl80211_channel_type oper_channel_type; struct ieee80211_channel *oper_channel, *csa_channel; + /* Temporary remain-on-channel for off-channel operations */ + struct ieee80211_channel *tmp_channel; + enum nl80211_channel_type tmp_channel_type; + /* SNMP counters */ /* dot11CountersTable */ u32 dot11TransmittedFragmentCount; @@ -1162,6 +1171,12 @@ void free_work(struct ieee80211_work *wk); void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); +int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie); +int ieee80211_wk_cancel_remain_on_channel( + struct ieee80211_sub_if_data *sdata, u64 cookie); #ifdef CONFIG_MAC80211_NOINLINE #define debug_noinline noinline diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5fcd3548417e..d0a14d953f08 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -107,6 +107,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) if (scan_chan) { chan = scan_chan; channel_type = NL80211_CHAN_NO_HT; + } else if (local->tmp_channel) { + chan = scan_chan = local->tmp_channel; + channel_type = local->tmp_channel_type; } else { chan = local->oper_channel; channel_type = local->oper_channel_type; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e44f1ed0b0da..32d6e6614f9f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -857,6 +857,9 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, if (sdata->local->scanning) return; + if (sdata->local->tmp_channel) + return; + mutex_lock(&ifmgd->mtx); if (!ifmgd->associated) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 2cd880e444d1..a7bbfc40a648 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -106,9 +106,13 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) /* * only handle non-STA interfaces here, STA interfaces * are handled in ieee80211_offchannel_stop_station(), - * e.g., from the background scan state machine + * e.g., from the background scan state machine. + * + * In addition, do not stop monitor interface to allow it to be + * used from user space controlled off-channel operations. */ - if (sdata->vif.type != NL80211_IFTYPE_STATION) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_MONITOR) netif_stop_queue(sdata->dev); } mutex_unlock(&local->iflist_mtx); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 0b8c31c600aa..0acea7cf714a 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -538,6 +538,44 @@ ieee80211_associate(struct ieee80211_work *wk) return WORK_ACT_NONE; } +static enum work_action __must_check +ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) +{ + struct ieee80211_sub_if_data *sdata = wk->sdata; + struct ieee80211_local *local = sdata->local; + + /* + * First time we run, do nothing -- the generic code will + * have switched to the right channel etc. + */ + if (wk->timeout != wk->remain.timeout) { + wk->timeout = wk->remain.timeout; + return WORK_ACT_NONE; + } + + /* + * We are done serving the remain-on-channel command; kill the work + * item to allow idle state to be entered again. In addition, clear the + * temporary channel information to allow operational channel to be + * used. + */ + list_del(&wk->list); + free_work(wk); + + if (local->tmp_channel) { + cfg80211_remain_on_channel_expired(sdata->dev, (u64)wk, + local->tmp_channel, + local->tmp_channel_type, + GFP_KERNEL); + + local->tmp_channel = NULL; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_offchannel_return(local, true); + } + + return WORK_ACT_NONE; +} + static void ieee80211_auth_challenge(struct ieee80211_work *wk, struct ieee80211_mgmt *mgmt, size_t len) @@ -825,6 +863,8 @@ static void ieee80211_work_work(struct work_struct *work) /* nothing */ rma = WORK_ACT_NONE; break; + case IEEE80211_WORK_ABORT: + rma = WORK_ACT_TIMEOUT; case IEEE80211_WORK_DIRECT_PROBE: rma = ieee80211_direct_probe(wk); break; @@ -834,6 +874,9 @@ static void ieee80211_work_work(struct work_struct *work) case IEEE80211_WORK_ASSOC: rma = ieee80211_associate(wk); break; + case IEEE80211_WORK_REMAIN_ON_CHANNEL: + rma = ieee80211_remain_on_channel_timeout(wk); + break; } switch (rma) { @@ -900,14 +943,25 @@ void ieee80211_work_init(struct ieee80211_local *local) void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; - struct ieee80211_work *wk, *tmp; + struct ieee80211_work *wk; mutex_lock(&local->work_mtx); - list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + list_for_each_entry(wk, &local->work_list, list) { if (wk->sdata != sdata) continue; - list_del(&wk->list); - free_work(wk); + wk->type = IEEE80211_WORK_ABORT; + } + mutex_unlock(&local->work_mtx); + + /* run cleanups etc. */ + ieee80211_work_work(&local->work_work); + + mutex_lock(&local->work_mtx); + list_for_each_entry(wk, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + WARN_ON(1); + break; } mutex_unlock(&local->work_mtx); } @@ -949,3 +1003,75 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, return RX_CONTINUE; } + +int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk; + + wk = kzalloc(sizeof(*wk), GFP_KERNEL); + if (!wk) + return -ENOMEM; + + wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; + wk->chan = chan; + wk->sdata = sdata; + + wk->remain.timeout = jiffies + msecs_to_jiffies(duration); + + *cookie = (u64)wk; + + ieee80211_add_work(wk); + + /* + * TODO: could optimize this by leaving the station vifs in awake mode + * if they happen to be on the same channel as the requested channel + */ + ieee80211_offchannel_stop_beaconing(local); + ieee80211_offchannel_stop_station(local); + + sdata->local->tmp_channel = chan; + sdata->local->tmp_channel_type = channel_type; + ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); + + cfg80211_ready_on_channel(sdata->dev, (u64)wk, chan, channel_type, + duration, GFP_KERNEL); + + return 0; +} + +int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, + u64 cookie) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk, *tmp; + bool found = false; + + mutex_lock(&local->work_mtx); + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + if ((u64)wk == cookie) { + found = true; + list_del(&wk->list); + free_work(wk); + break; + } + } + mutex_unlock(&local->work_mtx); + + if (!found) + return -ENOENT; + + if (sdata->local->tmp_channel) { + sdata->local->tmp_channel = NULL; + ieee80211_hw_config(sdata->local, + IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_offchannel_return(sdata->local, true); + } + + ieee80211_recalc_idle(local); + + return 0; +} -- cgit v1.2.3 From e4da8c37af626001ff704fb29ea14eb58f5f7208 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:43 +0100 Subject: mac80211: make off-channel work generic This changes mac80211 to allow being off-channel for any type of work, not just the 'remain-on-channel' work. This also helps fast transition to a BSS on a different channel. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 7 ++- net/mac80211/mlme.c | 14 +---- net/mac80211/work.c | 135 +++++++++++++++++++++++++++------------------ 3 files changed, 88 insertions(+), 68 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 23547ebacf3d..a27921ee6e63 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -255,13 +255,15 @@ struct ieee80211_work { struct sk_buff *skb); struct ieee80211_channel *chan; - /* XXX: chan type? -- right now not really needed */ + enum nl80211_channel_type chan_type; unsigned long timeout; enum ieee80211_work_type type; u8 filter_ta[ETH_ALEN]; + bool started; + union { struct { int tries; @@ -286,7 +288,8 @@ struct ieee80211_work { bool wmm_used, use_11n; } assoc; struct { - unsigned long timeout; + u32 duration; + bool started; } remain; }; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 32d6e6614f9f..72920ee07885 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1105,6 +1105,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, else ieee80211_set_wmm_default(sdata); + local->oper_channel = wk->chan; + if (elems.ht_info_elem && elems.wmm_param && (sdata->local->hw.queues >= 4) && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) @@ -1797,15 +1799,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, wk->sdata = sdata; wk->done = ieee80211_probe_auth_done; - /* - * XXX: if still associated need to tell AP that we're going - * to sleep and then change channel etc. - * For now switch channel here, later will be handled - * by submitting this as an off-channel work item. - */ - sdata->local->oper_channel = req->bss->channel; - ieee80211_hw_config(sdata->local, 0); - ieee80211_add_work(wk); return 0; } @@ -1929,9 +1922,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, else ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; - sdata->local->oper_channel = req->bss->channel; - ieee80211_hw_config(sdata->local, 0); - ieee80211_add_work(wk); return 0; } diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 0acea7cf714a..0bffb6a42534 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -541,39 +541,22 @@ ieee80211_associate(struct ieee80211_work *wk) static enum work_action __must_check ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) { - struct ieee80211_sub_if_data *sdata = wk->sdata; - struct ieee80211_local *local = sdata->local; - /* * First time we run, do nothing -- the generic code will * have switched to the right channel etc. */ - if (wk->timeout != wk->remain.timeout) { - wk->timeout = wk->remain.timeout; - return WORK_ACT_NONE; - } + if (!wk->remain.started) { + wk->remain.started = true; + wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); - /* - * We are done serving the remain-on-channel command; kill the work - * item to allow idle state to be entered again. In addition, clear the - * temporary channel information to allow operational channel to be - * used. - */ - list_del(&wk->list); - free_work(wk); + cfg80211_ready_on_channel(wk->sdata->dev, (u64)wk, wk->chan, + wk->chan_type, wk->remain.duration, + GFP_KERNEL); - if (local->tmp_channel) { - cfg80211_remain_on_channel_expired(sdata->dev, (u64)wk, - local->tmp_channel, - local->tmp_channel_type, - GFP_KERNEL); - - local->tmp_channel = NULL; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - ieee80211_offchannel_return(local, true); + return WORK_ACT_NONE; } - return WORK_ACT_NONE; + return WORK_ACT_TIMEOUT; } static void ieee80211_auth_challenge(struct ieee80211_work *wk, @@ -799,7 +782,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, break; case WORK_DONE_REQUEUE: synchronize_rcu(); - wk->timeout = jiffies; /* run again directly */ + wk->started = false; /* restart */ mutex_lock(&local->work_mtx); list_add_tail(&wk->list, &local->work_list); mutex_unlock(&local->work_mtx); @@ -827,6 +810,7 @@ static void ieee80211_work_work(struct work_struct *work) struct ieee80211_work *wk, *tmp; LIST_HEAD(free_work); enum work_action rma; + bool remain_off_channel = false; if (local->scanning) return; @@ -847,6 +831,34 @@ static void ieee80211_work_work(struct work_struct *work) mutex_lock(&local->work_mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + /* mark work as started if it's on the current off-channel */ + if (!wk->started && local->tmp_channel && + wk->chan == local->tmp_channel && + wk->chan_type == local->tmp_channel_type) { + wk->started = true; + } + + if (!wk->started && !local->tmp_channel) { + /* + * TODO: could optimize this by leaving the + * station vifs in awake mode if they + * happen to be on the same channel as + * the requested channel + */ + ieee80211_offchannel_stop_beaconing(local); + ieee80211_offchannel_stop_station(local); + + local->tmp_channel = wk->chan; + local->tmp_channel_type = wk->chan_type; + ieee80211_hw_config(local, 0); + wk->started = true; + wk->timeout = jiffies; + } + + /* don't try to work with items that aren't started */ + if (!wk->started) + continue; + if (time_is_after_jiffies(wk->timeout)) { /* * This work item isn't supposed to be worked on @@ -881,7 +893,8 @@ static void ieee80211_work_work(struct work_struct *work) switch (rma) { case WORK_ACT_NONE: - /* no action required */ + /* might have changed the timeout */ + run_again(local, wk->timeout); break; case WORK_ACT_TIMEOUT: list_del_rcu(&wk->list); @@ -893,6 +906,24 @@ static void ieee80211_work_work(struct work_struct *work) } } + list_for_each_entry(wk, &local->work_list, list) { + if (!wk->started) + continue; + if (wk->chan != local->tmp_channel) + continue; + if (wk->chan_type != local->tmp_channel_type) + continue; + remain_off_channel = true; + } + + if (!remain_off_channel && local->tmp_channel) { + local->tmp_channel = NULL; + ieee80211_hw_config(local, 0); + ieee80211_offchannel_return(local, true); + /* give connection some time to breathe */ + run_again(local, jiffies + HZ/2); + } + if (list_empty(&local->work_list) && local->scan_req) ieee80211_queue_delayed_work(&local->hw, &local->scan_work, @@ -900,6 +931,8 @@ static void ieee80211_work_work(struct work_struct *work) mutex_unlock(&local->work_mtx); + ieee80211_recalc_idle(local); + list_for_each_entry_safe(wk, tmp, &free_work, list) { wk->done(wk, NULL); list_del(&wk->list); @@ -920,7 +953,7 @@ void ieee80211_add_work(struct ieee80211_work *wk) if (WARN_ON(!wk->done)) return; - wk->timeout = jiffies; + wk->started = false; local = wk->sdata->local; mutex_lock(&local->work_mtx); @@ -950,6 +983,8 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) if (wk->sdata != sdata) continue; wk->type = IEEE80211_WORK_ABORT; + wk->started = true; + wk->timeout = jiffies; } mutex_unlock(&local->work_mtx); @@ -1004,12 +1039,24 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, return RX_CONTINUE; } +static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, + struct sk_buff *skb) +{ + /* + * We are done serving the remain-on-channel command. + */ + cfg80211_remain_on_channel_expired(wk->sdata->dev, (u64)wk, + wk->chan, wk->chan_type, + GFP_KERNEL); + + return WORK_DONE_DESTROY; +} + int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie) { - struct ieee80211_local *local = sdata->local; struct ieee80211_work *wk; wk = kzalloc(sizeof(*wk), GFP_KERNEL); @@ -1018,28 +1065,16 @@ int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; wk->chan = chan; + wk->chan_type = channel_type; wk->sdata = sdata; + wk->done = ieee80211_remain_done; - wk->remain.timeout = jiffies + msecs_to_jiffies(duration); + wk->remain.duration = duration; *cookie = (u64)wk; ieee80211_add_work(wk); - /* - * TODO: could optimize this by leaving the station vifs in awake mode - * if they happen to be on the same channel as the requested channel - */ - ieee80211_offchannel_stop_beaconing(local); - ieee80211_offchannel_stop_station(local); - - sdata->local->tmp_channel = chan; - sdata->local->tmp_channel_type = channel_type; - ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); - - cfg80211_ready_on_channel(sdata->dev, (u64)wk, chan, channel_type, - duration, GFP_KERNEL); - return 0; } @@ -1053,9 +1088,8 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->work_mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { if ((u64)wk == cookie) { + wk->timeout = jiffies; found = true; - list_del(&wk->list); - free_work(wk); break; } } @@ -1064,14 +1098,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, if (!found) return -ENOENT; - if (sdata->local->tmp_channel) { - sdata->local->tmp_channel = NULL; - ieee80211_hw_config(sdata->local, - IEEE80211_CONF_CHANGE_CHANNEL); - ieee80211_offchannel_return(sdata->local, true); - } - - ieee80211_recalc_idle(local); + ieee80211_queue_work(&local->hw, &local->work_work); return 0; } -- cgit v1.2.3 From 98b6218388e345064c3f2d3c161383a18274c638 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:44 +0100 Subject: mac80211/cfg80211: add station events When, for instance, a new IBSS peer is found, userspace wants to be notified. Add events for all new stations that mac80211 learns about. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 12 ++++++++++++ net/mac80211/sta_info.c | 5 +++++ net/wireless/mlme.c | 10 ++++++++++ net/wireless/nl80211.c | 21 ++++++++++++++++++++- net/wireless/nl80211.h | 4 ++++ 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b66beb052054..add79930f47d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2195,4 +2195,16 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, enum nl80211_channel_type channel_type, gfp_t gfp); + +/** + * cfg80211_new_sta - notify userspace about station + * + * @dev: the netdev + * @mac_addr: the station's address + * @sinfo: the station information + * @gfp: allocation flags + */ +void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp); + #endif /* __NET_CFG80211_H */ diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f039e761aec1..47da552ce8a6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -359,6 +359,7 @@ int sta_info_insert(struct sta_info *sta) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; + struct station_info sinfo; unsigned long flags; int err = 0; @@ -408,6 +409,10 @@ int sta_info_insert(struct sta_info *sta) spin_unlock_irqrestore(&local->sta_lock, flags); + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); + #ifdef CONFIG_MAC80211_DEBUGFS /* * Debugfs entry adding might sleep, so schedule process diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 11f6469b3f98..3dba19e17271 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -707,3 +707,13 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, channel_type, gfp); } EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); + +void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp) +{ + struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); +} +EXPORT_SYMBOL(cfg80211_new_sta); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ff857f10cb85..e3bee3cecdfa 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1642,7 +1642,7 @@ static int parse_station_flags(struct genl_info *info, static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, int flags, struct net_device *dev, - u8 *mac_addr, struct station_info *sinfo) + const u8 *mac_addr, struct station_info *sinfo) { void *hdr; struct nlattr *sinfoattr, *txrate; @@ -5350,6 +5350,25 @@ void nl80211_send_remain_on_channel_cancel( channel_type, 0, gfp); } +void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp) +{ + struct sk_buff *msg; + + msg = nlmsg_new(NLMSG_GOODSIZE, gfp); + if (!msg) + return; + + if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); +} + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index a5e2de419b7a..14855b8fb430 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -70,4 +70,8 @@ void nl80211_send_remain_on_channel_cancel( u64 cookie, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, gfp_t gfp); +void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, + struct net_device *dev, const u8 *mac_addr, + struct station_info *sinfo, gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ -- cgit v1.2.3 From 1ed32e4fc8cfc9656cc1101e7f9617d485fcbe7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:45 +0100 Subject: mac80211: remove struct ieee80211_if_init_conf All its members (vif, mac_addr, type) are now available in the vif struct directly, so we can pass that instead of the conf struct. I generated this patch (except the mac80211 and header file changes) with this semantic patch: @@ identifier conf, fn, hw; type tp; @@ tp fn(struct ieee80211_hw *hw, -struct ieee80211_if_init_conf *conf) +struct ieee80211_vif *vif) { <... ( -conf->type +vif->type | -conf->mac_addr +vif->addr | -conf->vif +vif ) ...> } Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 12 +++---- drivers/net/wireless/at76c50x-usb.c | 6 ++-- drivers/net/wireless/ath/ar9170/main.c | 8 ++--- drivers/net/wireless/ath/ath5k/base.c | 18 +++++----- drivers/net/wireless/ath/ath9k/main.c | 28 +++++++-------- drivers/net/wireless/b43/main.c | 26 +++++++------- drivers/net/wireless/b43legacy/main.c | 24 ++++++------- drivers/net/wireless/iwlwifi/iwl-core.c | 20 +++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 4 +-- drivers/net/wireless/libertas_tf/main.c | 10 +++--- drivers/net/wireless/mac80211_hwsim.c | 18 +++++----- drivers/net/wireless/mwl8k.c | 14 ++++---- drivers/net/wireless/p54/main.c | 12 +++---- drivers/net/wireless/rt2x00/rt2x00.h | 4 +-- drivers/net/wireless/rt2x00/rt2x00mac.c | 26 +++++++------- drivers/net/wireless/rtl818x/rtl8180_dev.c | 12 +++---- drivers/net/wireless/rtl818x/rtl8187_dev.c | 10 +++--- drivers/net/wireless/wl12xx/wl1251_main.c | 14 ++++---- drivers/net/wireless/wl12xx/wl1271_main.c | 10 +++--- drivers/net/wireless/zd1211rw/zd_mac.c | 10 +++--- include/net/mac80211.h | 57 ++++++++---------------------- net/mac80211/driver-ops.h | 12 +++---- net/mac80211/iface.c | 14 ++------ net/mac80211/pm.c | 6 +--- net/mac80211/util.c | 9 ++--- 25 files changed, 170 insertions(+), 214 deletions(-) diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 39410016b4ff..e1f04bb437e3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1400,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, } static int adm8211_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct adm8211_priv *priv = dev->priv; if (priv->mode != NL80211_IFTYPE_MONITOR) return -EOPNOTSUPP; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: - priv->mode = conf->type; + priv->mode = vif->type; break; default: return -EOPNOTSUPP; @@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, ADM8211_IDLE(); - ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); - ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); + ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); + ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); adm8211_update_mode(dev); @@ -1427,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, } static void adm8211_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct adm8211_priv *priv = dev->priv; priv->mode = NL80211_IFTYPE_MONITOR; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 2517364d3ebe..0fb419936dff 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) } static int at76_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct at76_priv *priv = hw->priv; int ret = 0; @@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mtx); - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: priv->iw_mode = IW_MODE_INFRA; break; @@ -1814,7 +1814,7 @@ exit: } static void at76_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { at76_dbg(DBG_MAC80211, "%s()", __func__); } diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 20f04ab2b13e..4d27f7f67c76 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -1939,7 +1939,7 @@ err_free: } static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; struct ath_common *common = &ar->common; @@ -1952,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, goto unlock; } - ar->vif = conf->vif; - memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); + ar->vif = vif; + memcpy(common->macaddr, vif->addr, ETH_ALEN); if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { ar->rx_software_decryption = true; @@ -1973,7 +1973,7 @@ unlock: } static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ar9170 *ar = hw->priv; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a4c086f069b1..20c7e5b450aa 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); static int ath5k_start(struct ieee80211_hw *hw); static void ath5k_stop(struct ieee80211_hw *hw); static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); static int ath5k_config(struct ieee80211_hw *hw, u32 changed); static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mc_list); @@ -2785,7 +2785,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) } static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath5k_softc *sc = hw->priv; int ret; @@ -2796,22 +2796,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, goto end; } - sc->vif = conf->vif; + sc->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MONITOR: - sc->opmode = conf->type; + sc->opmode = vif->type; break; default: ret = -EOPNOTSUPP; goto end; } - ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); + ath5k_hw_set_lladdr(sc->ah, vif->addr); ath5k_mode_setup(sc); ret = 0; @@ -2822,13 +2822,13 @@ end: static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath5k_softc *sc = hw->priv; u8 mac[ETH_ALEN] = {}; mutex_lock(&sc->lock); - if (sc->vif != conf->vif) + if (sc->vif != vif) goto end; ath5k_hw_set_lladdr(sc->ah, mac); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3f5b887d0fcd..446bd23756e5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2534,12 +2534,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) } static int ath9k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_vif *avp = (void *)conf->vif->drv_priv; + struct ath_vif *avp = (void *)vif->drv_priv; enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; int ret = 0; @@ -2551,7 +2551,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, goto out; } - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: ic_opmode = NL80211_IFTYPE_STATION; break; @@ -2562,11 +2562,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ret = -ENOBUFS; goto out; } - ic_opmode = conf->type; + ic_opmode = vif->type; break; default: ath_print(common, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", conf->type); + "Interface type %d not yet supported\n", vif->type); ret = -EOPNOTSUPP; goto out; } @@ -2598,18 +2598,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. */ - if ((conf->type == NL80211_IFTYPE_STATION) || - (conf->type == NL80211_IFTYPE_ADHOC) || - (conf->type == NL80211_IFTYPE_MESH_POINT)) { + if ((vif->type == NL80211_IFTYPE_STATION) || + (vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { sc->imask |= ATH9K_INT_MIB; sc->imask |= ATH9K_INT_TSFOOR; } ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - if (conf->type == NL80211_IFTYPE_AP || - conf->type == NL80211_IFTYPE_ADHOC || - conf->type == NL80211_IFTYPE_MONITOR) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MONITOR) ath_start_ani(common); out: @@ -2618,12 +2618,12 @@ out: } static void ath9k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_vif *avp = (void *)conf->vif->drv_priv; + struct ath_vif *avp = (void *)vif->drv_priv; int i; ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); @@ -2644,7 +2644,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, sc->sc_flags &= ~SC_OP_BEACONS; for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - if (sc->beacon.bslot[i] == conf->vif) { + if (sc->beacon.bslot[i] == vif) { printk(KERN_DEBUG "%s: vif had allocated beacon " "slot\n", __func__); sc->beacon.bslot[i] = NULL; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b0b5ce950008..6634a77fc766 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4391,7 +4391,7 @@ err_busdown: } static int b43_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -4399,24 +4399,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_MESH_POINT && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_MESH_POINT && + vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_WDS && + vif->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); if (wl->operating) goto out_mutex_unlock; - b43dbg(wl, "Adding Interface type %d\n", conf->type); + b43dbg(wl, "Adding Interface type %d\n", vif->type); dev = wl->current_dev; wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + wl->vif = vif; + wl->if_type = vif->type; + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); b43_adjust_opmode(dev); b43_set_pretbtt(dev); @@ -4431,17 +4431,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, } static void b43_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev = wl->current_dev; - b43dbg(wl, "Removing Interface type %d\n", conf->type); + b43dbg(wl, "Removing Interface type %d\n", vif->type); mutex_lock(&wl->mutex); B43_WARN_ON(!wl->operating); - B43_WARN_ON(wl->vif != conf->vif); + B43_WARN_ON(wl->vif != vif); wl->vif = NULL; wl->operating = 0; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index ab6a18c2e9d9..494017e4fcc9 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3361,7 +3361,7 @@ err_kfree_lo_control: } static int b43legacy_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev; @@ -3370,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, /* TODO: allow WDS/AP devices to coexist */ - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) + if (vif->type != NL80211_IFTYPE_AP && + vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_WDS && + vif->type != NL80211_IFTYPE_ADHOC) return -EOPNOTSUPP; mutex_lock(&wl->mutex); if (wl->operating) goto out_mutex_unlock; - b43legacydbg(wl, "Adding Interface type %d\n", conf->type); + b43legacydbg(wl, "Adding Interface type %d\n", vif->type); dev = wl->current_dev; wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + wl->vif = vif; + wl->if_type = vif->type; + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_adjust_opmode(dev); @@ -3403,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, } static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); struct b43legacy_wldev *dev = wl->current_dev; unsigned long flags; - b43legacydbg(wl, "Removing Interface type %d\n", conf->type); + b43legacydbg(wl, "Removing Interface type %d\n", vif->type); mutex_lock(&wl->mutex); B43legacy_WARN_ON(!wl->operating); - B43legacy_WARN_ON(wl->vif != conf->vif); + B43legacy_WARN_ON(wl->vif != vif); wl->vif = NULL; wl->operating = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e3b96b48b7fe..14f482960d7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2584,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) EXPORT_SYMBOL(iwl_set_mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; unsigned long flags; - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); + IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); if (priv->vif) { IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); @@ -2597,19 +2597,19 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, } spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; + priv->vif = vif; + priv->iw_mode = vif->type; spin_unlock_irqrestore(&priv->lock, flags); mutex_lock(&priv->mutex); - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + if (vif->addr) { + IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); } - if (iwl_set_mode(priv, conf->type) == -EAGAIN) + if (iwl_set_mode(priv, vif->type) == -EAGAIN) /* we are not ready, will run again when ready */ set_bit(STATUS_MODE_PENDING, &priv->status); @@ -2621,7 +2621,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, EXPORT_SYMBOL(iwl_mac_add_interface); void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; @@ -2634,7 +2634,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; iwlcore_commit_rxon(priv); } - if (priv->vif == conf->vif) { + if (priv->vif == vif) { priv->vif = NULL; memset(priv->bssid, 0, ETH_ALEN); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f7acbb32900a..1728f961dcba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -332,9 +332,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); int iwl_set_mode(struct iwl_priv *priv, int mode); int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); void iwl_config_ap(struct iwl_priv *priv); int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 019431d2f8a9..15a367680f59 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) } static int lbtf_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; if (priv->vif != NULL) return -EOPNOTSUPP; - priv->vif = conf->vif; - switch (conf->type) { + priv->vif = vif; + switch (vif->type) { case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: lbtf_set_mode(priv, LBTF_AP_MODE); @@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, priv->vif = NULL; return -EOPNOTSUPP; } - lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); + lbtf_set_mac_address(priv, (u8 *) vif->addr); return 0; } static void lbtf_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct lbtf_private *priv = hw->priv; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 4dee69a38c1d..84df3fcf37b3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -584,24 +584,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_set_magic(conf->vif); + wiphy_name(hw->wiphy), __func__, vif->type, + vif->addr); + hwsim_set_magic(vif); return 0; } static void mac80211_hwsim_remove_interface( - struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) + struct ieee80211_hw *hw, struct ieee80211_vif *vif) { printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_check_magic(conf->vif); - hwsim_clear_magic(conf->vif); + wiphy_name(hw->wiphy), __func__, vif->type, + vif->addr); + hwsim_check_magic(vif); + hwsim_clear_magic(vif); } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 97a95decf9a8..c1c6ecd0c5b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2835,7 +2835,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) } static int mwl8k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; @@ -2849,7 +2849,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* * We only support managed interfaces for now. */ - if (conf->type != NL80211_IFTYPE_STATION) + if (vif->type != NL80211_IFTYPE_STATION) return -EINVAL; /* @@ -2865,24 +2865,24 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, } /* Clean out driver private area */ - mwl8k_vif = MWL8K_VIF(conf->vif); + mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); /* Set and save the mac address */ - mwl8k_cmd_set_mac_addr(hw, conf->mac_addr); - memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); + mwl8k_cmd_set_mac_addr(hw, vif->addr); + memcpy(mwl8k_vif->mac_addr, vif->addr, ETH_ALEN); /* Set Initial sequence number to zero */ mwl8k_vif->seqno = 0; - priv->vif = conf->vif; + priv->vif = vif; priv->current_channel = NULL; return 0; } static void mwl8k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 18012dbfb45d..26428e4c9c60 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev) } static int p54_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct p54_common *priv = dev->priv; @@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev, return -EOPNOTSUPP; } - priv->vif = conf->vif; + priv->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_AP: case NL80211_IFTYPE_MESH_POINT: - priv->mode = conf->type; + priv->mode = vif->type; break; default: mutex_unlock(&priv->conf_mutex); return -EOPNOTSUPP; } - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + memcpy(priv->mac_addr, vif->addr, ETH_ALEN); p54_setup_mac(priv); mutex_unlock(&priv->conf_mutex); return 0; } static void p54_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct p54_common *priv = dev->priv; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a664a999b2b0..b4c6e0a6d7e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1019,9 +1019,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); int rt2x00mac_start(struct ieee80211_hw *hw); void rt2x00mac_stop(struct ieee80211_hw *hw); int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); void rt2x00mac_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index de549c244ed8..00f1f939f1bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) EXPORT_SYMBOL_GPL(rt2x00mac_stop); int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct rt2x00_intf *intf = vif_to_intf(vif); struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); struct queue_entry *entry = NULL; unsigned int i; @@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) return -ENODEV; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_AP: /* * We don't support mixed combinations of @@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * increase interface count and start initialization. */ - if (conf->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count++; else rt2x00dev->intf_sta_count++; @@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; - if (conf->type == NL80211_IFTYPE_AP) - memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); - memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); + if (vif->type == NL80211_IFTYPE_AP) + memcpy(&intf->bssid, vif->addr, ETH_ALEN); + memcpy(&intf->mac, vif->addr, ETH_ALEN); /* * The MAC adddress must be configured after the device * has been initialized. Otherwise the device can reset * the MAC registers. */ - rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); + rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); /* * Some filters depend on the current working mode. We can force @@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct rt2x00_intf *intf = vif_to_intf(vif); /* * Don't allow interfaces to be remove while @@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || - (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) + (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || + (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) return; - if (conf->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP) rt2x00dev->intf_ap_count--; else rt2x00dev->intf_sta_count--; diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index f01f1ef9e3be..5a2b7199f5d5 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -652,7 +652,7 @@ static void rtl8180_stop(struct ieee80211_hw *dev) } static int rtl8180_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8180_priv *priv = dev->priv; @@ -662,27 +662,27 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, if (priv->vif) return -EBUSY; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: break; default: return -EOPNOTSUPP; } - priv->vif = conf->vif; + priv->vif = vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], - le32_to_cpu(*(__le32 *)conf->mac_addr)); + le32_to_cpu(*(__le32 *)vif->addr)); rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], - le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); + le16_to_cpu(*(__le16 *)(vif->addr + 4))); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); return 0; } static void rtl8180_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8180_priv *priv = dev->priv; priv->vif = NULL; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 1cb0eff46223..f336c63053c1 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1018,7 +1018,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) } static int rtl8187_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8187_priv *priv = dev->priv; int i; @@ -1028,7 +1028,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, if (priv->vif) goto exit; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: break; default: @@ -1036,12 +1036,12 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, } ret = 0; - priv->vif = conf->vif; + priv->vif = vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->MAC[i], - ((u8 *)conf->mac_addr)[i]); + ((u8 *)vif->addr)[i]); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); exit: @@ -1050,7 +1050,7 @@ exit: } static void rtl8187_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct rtl8187_priv *priv = dev->priv; mutex_lock(&priv->conf_mutex); diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 6aeffbe9e401..4e373f3dbc43 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -511,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) } static int wl1251_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; int ret = 0; wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); + vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { @@ -525,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, goto out; } - wl->vif = conf->vif; + wl->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; @@ -539,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, goto out; } - if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); + if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = wl1251_acx_station_id(wl); if (ret < 0) @@ -553,7 +553,7 @@ out: } static void wl1251_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1251 *wl = hw->priv; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4a997381a8d0..e4867b895c43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1039,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) } static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; int ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); + vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { @@ -1053,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - wl->vif = conf->vif; + wl->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; @@ -1075,7 +1075,7 @@ out: } static void wl1271_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 8a243732c519..c4f41d0016c5 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -872,7 +872,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) } static int zd_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct zd_mac *mac = zd_hw_mac(hw); @@ -880,22 +880,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, if (mac->type != NL80211_IFTYPE_UNSPECIFIED) return -EOPNOTSUPP; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - mac->type = conf->type; + mac->type = vif->type; break; default: return -EOPNOTSUPP; } - return zd_write_mac_addr(&mac->chip, conf->mac_addr); + return zd_write_mac_addr(&mac->chip, vif->addr); } static void zd_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct zd_mac *mac = zd_hw_mac(hw); mac->type = NL80211_IFTYPE_UNSPECIFIED; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 77ea34b03285..08d41357dcbe 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -701,33 +701,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) return false; } -/** - * struct ieee80211_if_init_conf - initial configuration of an interface - * - * @vif: pointer to a driver-use per-interface structure. The pointer - * itself is also used for various functions including - * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). - * @type: one of &enum nl80211_iftype constants. Determines the type of - * added/removed interface. - * @mac_addr: pointer to MAC address of the interface. This pointer is valid - * until the interface is removed (i.e. it cannot be used after - * remove_interface() callback was called for this interface). - * - * This structure is used in add_interface() and remove_interface() - * callbacks of &struct ieee80211_hw. - * - * When you allow multiple interfaces to be added to your PHY, take care - * that the hardware can actually handle multiple MAC addresses. However, - * also take care that when there's no interface left with mac_addr != %NULL - * you remove the MAC address from the device to avoid acknowledging packets - * in pure monitor mode. - */ -struct ieee80211_if_init_conf { - enum nl80211_iftype type; - struct ieee80211_vif *vif; - void *mac_addr; -}; - /** * enum ieee80211_key_alg - key algorithm * @ALG_WEP: WEP40 or WEP104 @@ -1555,9 +1528,9 @@ struct ieee80211_ops { int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); int (*add_interface)(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); void (*remove_interface)(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); + struct ieee80211_vif *vif); int (*config)(struct ieee80211_hw *hw, u32 changed); void (*bss_info_changed)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -1845,7 +1818,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, /** * ieee80211_beacon_get_tim - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @tim_offset: pointer to variable that will receive the TIM IE offset. * Set to 0 if invalid (in non-AP modes). * @tim_length: pointer to variable that will receive the TIM IE length, @@ -1873,7 +1846,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, /** * ieee80211_beacon_get - beacon generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * See ieee80211_beacon_get_tim(). */ @@ -1886,7 +1859,7 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, /** * ieee80211_rts_get - RTS frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame: pointer to the frame that is going to be protected by the RTS. * @frame_len: the frame length (in octets). * @frame_txctl: &struct ieee80211_tx_info of the frame. @@ -1905,7 +1878,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /** * ieee80211_rts_duration - Get the duration field for an RTS frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame that is going to be protected by the RTS. * @frame_txctl: &struct ieee80211_tx_info of the frame. * @@ -1920,7 +1893,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, /** * ieee80211_ctstoself_get - CTS-to-self frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame: pointer to the frame that is going to be protected by the CTS-to-self. * @frame_len: the frame length (in octets). * @frame_txctl: &struct ieee80211_tx_info of the frame. @@ -1940,7 +1913,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, /** * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. * @frame_txctl: &struct ieee80211_tx_info of the frame. * @@ -1956,7 +1929,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, /** * ieee80211_generic_frame_duration - Calculate the duration field for a frame * @hw: pointer obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @frame_len: the length of the frame. * @rate: the rate at which the frame is going to be transmitted. * @@ -1971,7 +1944,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, /** * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames * @hw: pointer as obtained from ieee80211_alloc_hw(). - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * Function for accessing buffered broadcast and multicast frames. If * hardware/firmware does not implement buffering of broadcast/multicast @@ -2139,7 +2112,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); /** * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the TID to BA on. * @@ -2150,7 +2123,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); /** * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the TID to BA on. * @@ -2178,7 +2151,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid, /** * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the desired TID to BA on. * @@ -2189,7 +2162,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); /** * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf + * @vif: &struct ieee80211_vif pointer from the add_interface callback * @ra: receiver address of the BA session recipient. * @tid: the desired TID to BA on. * @@ -2268,7 +2241,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, /** * ieee80211_beacon_loss - inform hardware does not receive beacons * - * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. + * @vif: &struct ieee80211_vif pointer from the add_interface callback. * * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and * IEEE80211_CONF_PS is set, the driver needs to inform whenever the diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index cbe133bcdf34..bc7c8f55487a 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -36,18 +36,18 @@ static inline void drv_stop(struct ieee80211_local *local) } static inline int drv_add_interface(struct ieee80211_local *local, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { - int ret = local->ops->add_interface(&local->hw, conf); - trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); + int ret = local->ops->add_interface(&local->hw, vif); + trace_drv_add_interface(local, vif_to_sdata(vif), ret); return ret; } static inline void drv_remove_interface(struct ieee80211_local *local, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { - local->ops->remove_interface(&local->hw, conf); - trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); + local->ops->remove_interface(&local->hw, vif); + trace_drv_remove_interface(local, vif_to_sdata(vif)); } static inline int drv_config(struct ieee80211_local *local, u32 changed) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7d410f15281a..00a1f4ccdaf1 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -96,7 +96,6 @@ static int ieee80211_open(struct net_device *dev) struct ieee80211_sub_if_data *nsdata; struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct ieee80211_if_init_conf conf; u32 changed = 0; int res; u32 hw_reconf_flags = 0; @@ -248,10 +247,7 @@ static int ieee80211_open(struct net_device *dev) ieee80211_configure_filter(local); break; default: - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - res = drv_add_interface(local, &conf); + res = drv_add_interface(local, &sdata->vif); if (res) goto err_stop; @@ -334,7 +330,7 @@ static int ieee80211_open(struct net_device *dev) return 0; err_del_interface: - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); err_stop: if (!local->open_count) drv_stop(local); @@ -349,7 +345,6 @@ static int ieee80211_stop(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; struct sk_buff *skb, *tmp; @@ -533,12 +528,9 @@ static int ieee80211_stop(struct net_device *dev) BSS_CHANGED_BEACON_ENABLED); } - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; /* disable all keys for as long as this netdev is down */ ieee80211_disable_keys(sdata); - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); } sdata->bss = NULL; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 913dc7e3b29e..47f818959ad7 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -10,7 +10,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; @@ -100,10 +99,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - drv_remove_interface(local, &conf); + drv_remove_interface(local, &sdata->vif); } /* stop hardware - this must stop RX */ diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1fdb80ff9241..4b930308b1fb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1075,7 +1075,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) { struct ieee80211_hw *hw = &local->hw; struct ieee80211_sub_if_data *sdata; - struct ieee80211_if_init_conf conf; struct sta_info *sta; unsigned long flags; int res; @@ -1094,12 +1093,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_MONITOR && - ieee80211_sdata_running(sdata)) { - conf.vif = &sdata->vif; - conf.type = sdata->vif.type; - conf.mac_addr = sdata->vif.addr; - res = drv_add_interface(local, &conf); - } + ieee80211_sdata_running(sdata)) + res = drv_add_interface(local, &sdata->vif); } /* add STAs back */ -- cgit v1.2.3 From 095d5ef608b58ece49f4131925700d27314ecdd8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:46 +0100 Subject: mac80211: remove requeue from work There's no need to be requeueing the work struct since we check for the scan after removing items due to possible timeouts. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/work.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 0bffb6a42534..ea89ed70734d 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -435,12 +435,6 @@ ieee80211_direct_probe(struct ieee80211_work *wk) */ ieee80211_remove_auth_bss(local, wk); - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &local->work_work); return WORK_ACT_TIMEOUT; } @@ -478,12 +472,6 @@ ieee80211_authenticate(struct ieee80211_work *wk) */ ieee80211_remove_auth_bss(local, wk); - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &local->work_work); return WORK_ACT_TIMEOUT; } @@ -519,12 +507,6 @@ ieee80211_associate(struct ieee80211_work *wk) if (wk->assoc.bss) cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); - /* - * We might have a pending scan which had no chance to run yet - * due to work needing to be done. Hence, queue the STAs work - * again for that. - */ - ieee80211_queue_work(&local->hw, &local->work_work); return WORK_ACT_TIMEOUT; } -- cgit v1.2.3 From e1781ed33a8809c58ad6c3b6d432d656446efa43 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 23 Dec 2009 13:15:47 +0100 Subject: mac80211: annotate sleeping driver ops To make it easier to notice cases of calling sleeping ops in atomic context, annotate driver-ops.h with appropiate might_sleep() calls. At the same time, also document in mac80211.h the op functions with missing contexts. mac80211 doesn't seem to use get_tx_stats anywhere currently. Just to be on the safe side, I documented it to be atomic, but hopefully the op can be removed in the future. Compile-tested only. Signed-off-by: Kalle Valo Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 43 +++++++++++++++++++++++---------- net/mac80211/driver-ops.h | 60 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 16 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 08d41357dcbe..5ee666ae4c88 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1383,7 +1383,7 @@ enum ieee80211_ampdu_mlme_action { * When the device is started it should not have a MAC address * to avoid acknowledging frames before a non-monitor device * is added. - * Must be implemented. + * Must be implemented and can sleep. * * @stop: Called after last netdevice attached to the hardware * is disabled. This should turn off the hardware (at least @@ -1391,7 +1391,7 @@ enum ieee80211_ampdu_mlme_action { * May be called right after add_interface if that rejects * an interface. If you added any work onto the mac80211 workqueue * you should ensure to cancel it on this callback. - * Must be implemented. + * Must be implemented and can sleep. * * @add_interface: Called when a netdevice attached to the hardware is * enabled. Because it is not called for monitor mode devices, @start @@ -1401,7 +1401,7 @@ enum ieee80211_ampdu_mlme_action { * interface is given in the conf parameter. * The callback may refuse to add an interface by returning a * negative error code (which will be seen in userspace.) - * Must be implemented. + * Must be implemented and can sleep. * * @remove_interface: Notifies a driver that an interface is going down. * The @stop callback is called after this if it is the last interface @@ -1410,19 +1410,20 @@ enum ieee80211_ampdu_mlme_action { * must be cleared so the device no longer acknowledges packets, * the mac_addr member of the conf structure is, however, set to the * MAC address of the device going away. - * Hence, this callback must be implemented. + * Hence, this callback must be implemented. It can sleep. * * @config: Handler for configuration requests. IEEE 802.11 code calls this * function to change hardware configuration, e.g., channel. * This function should never fail but returns a negative error code - * if it does. + * if it does. The callback can sleep. * * @bss_info_changed: Handler for configuration requests related to BSS * parameters that may vary during BSS's lifespan, and may affect low * level driver (e.g. assoc/disassoc status, erp parameters). * This function should not be used if no BSS has been set, unless * for association indication. The @changed parameter indicates which - * of the bss parameters has changed when a call is made. + * of the bss parameters has changed when a call is made. The callback + * can sleep. * * @prepare_multicast: Prepare for multicast filter configuration. * This callback is optional, and its return value is passed @@ -1430,20 +1431,22 @@ enum ieee80211_ampdu_mlme_action { * * @configure_filter: Configure the device's RX filter. * See the section "Frame filtering" for more information. - * This callback must be implemented. + * This callback must be implemented and can sleep. * * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit * must be set or cleared for a given STA. Must be atomic. * * @set_key: See the section "Hardware crypto acceleration" - * This callback can sleep, and is only called between add_interface - * and remove_interface calls, i.e. while the given virtual interface + * This callback is only called between add_interface and + * remove_interface calls, i.e. while the given virtual interface * is enabled. * Returns a negative error code if the key can't be added. + * The callback can sleep. * * @update_tkip_key: See the section "Hardware crypto acceleration" * This callback will be called in the context of Rx. Called for drivers * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. + * The callback can sleep. * * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. The scan must honour the channel @@ -1457,21 +1460,28 @@ enum ieee80211_ampdu_mlme_action { * When the scan finishes, ieee80211_scan_completed() must be called; * note that it also must be called when the scan cannot finish due to * any error unless this callback returned a negative error code. + * The callback can sleep. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. + * The callback can sleep. * - * @sw_scan_complete: Notifier function that is called just after a software scan - * finished. Can be NULL, if the driver doesn't need this notification. + * @sw_scan_complete: Notifier function that is called just after a + * software scan finished. Can be NULL, if the driver doesn't need + * this notification. + * The callback can sleep. * * @get_stats: Return low-level statistics. * Returns zero if statistics are available. + * The callback can sleep. * * @get_tkip_seq: If your device implements TKIP encryption in hardware this * callback should be provided to read the TKIP transmit IVs (both IV32 * and IV16) for the given key from hardware. + * The callback must be atomic. * * @set_rts_threshold: Configuration of RTS threshold (if device needs it) + * The callback can sleep. * * @sta_notify: Notifies low level driver about addition, removal or power * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. @@ -1480,30 +1490,36 @@ enum ieee80211_ampdu_mlme_action { * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. * Returns a negative error code on failure. + * The callback can sleep. * * @get_tx_stats: Get statistics of the current TX queue status. This is used * to get number of currently queued packets (queue length), maximum queue * size (limit), and total number of packets sent using each TX queue * (count). The 'stats' pointer points to an array that has hw->queues * items. + * The callback must be atomic. * * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, * this is only used for IBSS mode BSSID merging and debugging. Is not a * required function. + * The callback can sleep. * * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. * Currently, this is only used for IBSS mode debugging. Is not a * required function. + * The callback can sleep. * * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize * with other STAs in the IBSS. This is only used in IBSS mode. This * function is optional if the firmware/hardware takes full care of * TSF synchronization. + * The callback can sleep. * * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. * This is needed only for IBSS mode and the result of this function is * used to determine whether to reply to Probe Requests. * Returns non-zero if this device sent the last beacon. + * The callback can sleep. * * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want @@ -1512,16 +1528,19 @@ enum ieee80211_ampdu_mlme_action { * is the first frame we expect to perform the action on. Notice * that TX/RX_STOP can pass NULL for this parameter. * Returns a negative error code on failure. + * The callback must be atomic. * * @rfkill_poll: Poll rfkill hardware state. If you need this, you also * need to set wiphy->rfkill_poll to %true before registration, * and need to call wiphy_rfkill_set_hw_state() in the callback. + * The callback can sleep. * * @testmode_cmd: Implement a cfg80211 test mode command. + * The callback can sleep. * * @flush: Flush all pending frames from the hardware queue, making sure * that the hardware queues are empty. If the parameter @drop is set - * to %true, pending frames may be dropped. + * to %true, pending frames may be dropped. The callback can sleep. */ struct ieee80211_ops { int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index bc7c8f55487a..8757ea73d544 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -14,6 +14,8 @@ static inline int drv_start(struct ieee80211_local *local) { int ret; + might_sleep(); + local->started = true; smp_mb(); ret = local->ops->start(&local->hw); @@ -23,6 +25,8 @@ static inline int drv_start(struct ieee80211_local *local) static inline void drv_stop(struct ieee80211_local *local) { + might_sleep(); + local->ops->stop(&local->hw); trace_drv_stop(local); @@ -38,7 +42,11 @@ static inline void drv_stop(struct ieee80211_local *local) static inline int drv_add_interface(struct ieee80211_local *local, struct ieee80211_vif *vif) { - int ret = local->ops->add_interface(&local->hw, vif); + int ret; + + might_sleep(); + + ret = local->ops->add_interface(&local->hw, vif); trace_drv_add_interface(local, vif_to_sdata(vif), ret); return ret; } @@ -46,13 +54,19 @@ static inline int drv_add_interface(struct ieee80211_local *local, static inline void drv_remove_interface(struct ieee80211_local *local, struct ieee80211_vif *vif) { + might_sleep(); + local->ops->remove_interface(&local->hw, vif); trace_drv_remove_interface(local, vif_to_sdata(vif)); } static inline int drv_config(struct ieee80211_local *local, u32 changed) { - int ret = local->ops->config(&local->hw, changed); + int ret; + + might_sleep(); + + ret = local->ops->config(&local->hw, changed); trace_drv_config(local, changed, ret); return ret; } @@ -62,6 +76,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, struct ieee80211_bss_conf *info, u32 changed) { + might_sleep(); + if (local->ops->bss_info_changed) local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); trace_drv_bss_info_changed(local, sdata, info, changed); @@ -111,7 +127,11 @@ static inline int drv_set_key(struct ieee80211_local *local, struct ieee80211_sta *sta, struct ieee80211_key_conf *key) { - int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); + int ret; + + might_sleep(); + + ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); trace_drv_set_key(local, cmd, sdata, sta, key, ret); return ret; } @@ -121,6 +141,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, const u8 *address, u32 iv32, u16 *phase1key) { + might_sleep(); + if (local->ops->update_tkip_key) local->ops->update_tkip_key(&local->hw, conf, address, iv32, phase1key); @@ -130,13 +152,19 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, static inline int drv_hw_scan(struct ieee80211_local *local, struct cfg80211_scan_request *req) { - int ret = local->ops->hw_scan(&local->hw, req); + int ret; + + might_sleep(); + + ret = local->ops->hw_scan(&local->hw, req); trace_drv_hw_scan(local, req, ret); return ret; } static inline void drv_sw_scan_start(struct ieee80211_local *local) { + might_sleep(); + if (local->ops->sw_scan_start) local->ops->sw_scan_start(&local->hw); trace_drv_sw_scan_start(local); @@ -144,6 +172,8 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local) static inline void drv_sw_scan_complete(struct ieee80211_local *local) { + might_sleep(); + if (local->ops->sw_scan_complete) local->ops->sw_scan_complete(&local->hw); trace_drv_sw_scan_complete(local); @@ -154,6 +184,8 @@ static inline int drv_get_stats(struct ieee80211_local *local, { int ret = -EOPNOTSUPP; + might_sleep(); + if (local->ops->get_stats) ret = local->ops->get_stats(&local->hw, stats); trace_drv_get_stats(local, stats, ret); @@ -173,6 +205,9 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, u32 value) { int ret = 0; + + might_sleep(); + if (local->ops->set_rts_threshold) ret = local->ops->set_rts_threshold(&local->hw, value); trace_drv_set_rts_threshold(local, value, ret); @@ -193,6 +228,9 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params) { int ret = -EOPNOTSUPP; + + might_sleep(); + if (local->ops->conf_tx) ret = local->ops->conf_tx(&local->hw, queue, params); trace_drv_conf_tx(local, queue, params, ret); @@ -210,6 +248,9 @@ static inline int drv_get_tx_stats(struct ieee80211_local *local, static inline u64 drv_get_tsf(struct ieee80211_local *local) { u64 ret = -1ULL; + + might_sleep(); + if (local->ops->get_tsf) ret = local->ops->get_tsf(&local->hw); trace_drv_get_tsf(local, ret); @@ -218,6 +259,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local) static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) { + might_sleep(); + if (local->ops->set_tsf) local->ops->set_tsf(&local->hw, tsf); trace_drv_set_tsf(local, tsf); @@ -225,6 +268,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) static inline void drv_reset_tsf(struct ieee80211_local *local) { + might_sleep(); + if (local->ops->reset_tsf) local->ops->reset_tsf(&local->hw); trace_drv_reset_tsf(local); @@ -233,6 +278,9 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) static inline int drv_tx_last_beacon(struct ieee80211_local *local) { int ret = 1; + + might_sleep(); + if (local->ops->tx_last_beacon) ret = local->ops->tx_last_beacon(&local->hw); trace_drv_tx_last_beacon(local, ret); @@ -256,12 +304,16 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, static inline void drv_rfkill_poll(struct ieee80211_local *local) { + might_sleep(); + if (local->ops->rfkill_poll) local->ops->rfkill_poll(&local->hw); } static inline void drv_flush(struct ieee80211_local *local, bool drop) { + might_sleep(); + trace_drv_flush(local, drop); if (local->ops->flush) local->ops->flush(&local->hw, drop); -- cgit v1.2.3 From 557b0bbd62389ab438424e9f895197607666ea4d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:01:46 -0800 Subject: drivers/net/lib82596.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. The only difference in the output is that the MAC address is shown in the usual colon-separated hex notation instead of space-separated. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/lib82596.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index b117f7f8b194..b60efd4bd017 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1094,11 +1094,9 @@ static int __devinit i82596_probe(struct net_device *dev) return i; }; - DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", - dev->name, dev->base_addr)); - for (i = 0; i < 6; i++) - DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i])); - DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq)); + DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx, %pM IRQ %d.\n", + dev->name, dev->base_addr, dev->dev_addr, + dev->irq)); DEB(DEB_INIT, printk(KERN_INFO "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n", dev->name, dma, (int)sizeof(struct i596_dma), -- cgit v1.2.3 From 753cdc3304f0612766a81cddab9d8af01fcf8218 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:02:29 -0800 Subject: drivers/net/igbvf/netdev.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/igbvf/netdev.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index e9dd95f136aa..1326232c1d32 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2608,11 +2608,7 @@ static void igbvf_print_device_info(struct igbvf_adapter *adapter) struct pci_dev *pdev = adapter->pdev; dev_info(&pdev->dev, "Intel(R) 82576 Virtual Function\n"); - dev_info(&pdev->dev, "Address: %02x:%02x:%02x:%02x:%02x:%02x\n", - /* MAC address */ - netdev->dev_addr[0], netdev->dev_addr[1], - netdev->dev_addr[2], netdev->dev_addr[3], - netdev->dev_addr[4], netdev->dev_addr[5]); + dev_info(&pdev->dev, "Address: %pM\n", netdev->dev_addr); dev_info(&pdev->dev, "MAC: %d\n", hw->mac.type); } @@ -2777,11 +2773,8 @@ static int __devinit igbvf_probe(struct pci_dev *pdev, memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address: " - "%02x:%02x:%02x:%02x:%02x:%02x\n", - netdev->dev_addr[0], netdev->dev_addr[1], - netdev->dev_addr[2], netdev->dev_addr[3], - netdev->dev_addr[4], netdev->dev_addr[5]); + dev_err(&pdev->dev, "Invalid MAC Address: %pM\n", + netdev->dev_addr); err = -EIO; goto err_hw_init; } -- cgit v1.2.3 From d649a2844e49ece6309cf28cb941ef64eb69228f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:03:28 -0800 Subject: drivers/net/usb/rtl8150.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/usb/rtl8150.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index f14d225404da..dfc7e9fec3ea 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -313,20 +313,17 @@ static int rtl8150_set_mac_address(struct net_device *netdev, void *p) { struct sockaddr *addr = p; rtl8150_t *dev = netdev_priv(netdev); - int i; if (netif_running(netdev)) return -EBUSY; memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - dbg("%s: Setting MAC address to ", netdev->name); - for (i = 0; i < 5; i++) - dbg("%02X:", netdev->dev_addr[i]); - dbg("%02X\n", netdev->dev_addr[i]); + dbg("%s: Setting MAC address to %pM\n", netdev->name, netdev->dev_addr); /* Set the IDR registers. */ set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr); #ifdef EEPROM_WRITE { + int i; u8 cr; /* Get the CR contents. */ get_registers(dev, CR, 1, &cr); -- cgit v1.2.3 From aa7c68a5f75cf04e79348e8baca67c7393d8f7e4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:04:14 -0800 Subject: drivers/net/via-velocity.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 4ceb441f2687..cee8fa2d2a9f 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2702,10 +2702,8 @@ static void __devinit velocity_print_info(struct velocity_info *vptr) struct net_device *dev = vptr->dev; printk(KERN_INFO "%s: %s\n", dev->name, get_chip_name(vptr->chip_id)); - printk(KERN_INFO "%s: Ethernet Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", - dev->name, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + printk(KERN_INFO "%s: Ethernet Address: %pM\n", + dev->name, dev->dev_addr); } static u32 velocity_get_link(struct net_device *dev) -- cgit v1.2.3 From 5491f3a5623129f3d4e0c62e691c2a5e56c75d41 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:04:53 -0800 Subject: drivers/net/xilinx_emaclite.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/xilinx_emaclite.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index 8c777ba4e2b3..f7fe1aa03b42 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -925,11 +925,7 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev, /* Set the MAC address in the EmacLite device */ xemaclite_set_mac_address(lp, ndev->dev_addr); - dev_info(dev, - "MAC address is now %2x:%2x:%2x:%2x:%2x:%2x\n", - ndev->dev_addr[0], ndev->dev_addr[1], - ndev->dev_addr[2], ndev->dev_addr[3], - ndev->dev_addr[4], ndev->dev_addr[5]); + dev_info(dev, "MAC address is now %pM\n", ndev->dev_addr); ndev->netdev_ops = &xemaclite_netdev_ops; ndev->flags &= ~IFF_MULTICAST; -- cgit v1.2.3 From d998ab0bd737fad9c8e3c88eb6f52c43e90fda9a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:05:37 -0800 Subject: drivers/s390/net/qeth_l2_main.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 0b763396d5d1..038299ae3feb 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -486,22 +486,14 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, case IPA_RC_L2_DUP_MAC: case IPA_RC_L2_DUP_LAYER3_MAC: dev_warn(&card->gdev->dev, - "MAC address " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - "already exists\n", - card->dev->dev_addr[0], card->dev->dev_addr[1], - card->dev->dev_addr[2], card->dev->dev_addr[3], - card->dev->dev_addr[4], card->dev->dev_addr[5]); + "MAC address %pM already exists\n", + card->dev->dev_addr); break; case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP: case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP: dev_warn(&card->gdev->dev, - "MAC address " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - "is not authorized\n", - card->dev->dev_addr[0], card->dev->dev_addr[1], - card->dev->dev_addr[2], card->dev->dev_addr[3], - card->dev->dev_addr[4], card->dev->dev_addr[5]); + "MAC address %pM is not authorized\n", + card->dev->dev_addr); break; default: break; @@ -512,12 +504,8 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac, OSA_ADDR_LEN); dev_info(&card->gdev->dev, - "MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - "successfully registered on device %s\n", - card->dev->dev_addr[0], card->dev->dev_addr[1], - card->dev->dev_addr[2], card->dev->dev_addr[3], - card->dev->dev_addr[4], card->dev->dev_addr[5], - card->dev->name); + "MAC address %pM successfully registered on device %s\n", + card->dev->dev_addr, card->dev->name); } return 0; } -- cgit v1.2.3 From 3b8dff3622a813d093a8601dc90fb6f12183f87c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:06:45 -0800 Subject: drivers/net/usb/catc.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/usb/catc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 22b87e64a810..7d3fa06980c1 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -897,11 +897,9 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id f5u011_rxmode(catc, catc->rxmode); } dbg("Init done."); - printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, ", + printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, %pM.\n", netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate", - usbdev->bus->bus_name, usbdev->devpath); - for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]); - printk("%2.2x.\n", netdev->dev_addr[i]); + usbdev->bus->bus_name, usbdev->devpath, netdev->dev_addr); usb_set_intfdata(intf, catc); SET_NETDEV_DEV(netdev, &intf->dev); -- cgit v1.2.3 From b18fe4777f1cf7095fbe78652b72c076e300eaee Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:07:27 -0800 Subject: drivers/net/sunvnet.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/sunvnet.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index bc74db0d12f3..d65764ea1d83 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -1062,10 +1062,7 @@ static struct vnet * __devinit vnet_new(const u64 *local_mac) goto err_out_free_dev; } - printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); + printk(KERN_INFO "%s: Sun LDOM vnet %pM\n", dev->name, dev->dev_addr); list_add(&vp->list, &vnet_list); -- cgit v1.2.3 From fa876b474aa15cd1448790502a5a13f81f923446 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:08:09 -0800 Subject: drivers/net/smc911x.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 44ebbaa7457b..3c5a4f52345c 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -2017,10 +2017,8 @@ static int __devinit smc911x_probe(struct net_device *dev) "set using ifconfig\n", dev->name); } else { /* Print the Ethernet address */ - printk("%s: Ethernet addr: ", dev->name); - for (i = 0; i < 5; i++) - printk("%2.2x:", dev->dev_addr[i]); - printk("%2.2x\n", dev->dev_addr[5]); + printk("%s: Ethernet addr: %pM\n", + dev->name, dev->dev_addr); } if (lp->phy_type == 0) { -- cgit v1.2.3 From e583482091d207265953f501564056bd2c90b985 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:09:07 -0800 Subject: drivers/net/octeon/octeon_mgmt.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/octeon/octeon_mgmt.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index 050538bf155a..6fd8789ef487 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -1119,11 +1119,8 @@ static int __init octeon_mgmt_probe(struct platform_device *pdev) if (p->port >= octeon_bootinfo->mac_addr_count) dev_err(&pdev->dev, - "Error %s: Using MAC outside of the assigned range: " - "%02x:%02x:%02x:%02x:%02x:%02x\n", netdev->name, - netdev->dev_addr[0], netdev->dev_addr[1], - netdev->dev_addr[2], netdev->dev_addr[3], - netdev->dev_addr[4], netdev->dev_addr[5]); + "Error %s: Using MAC outside of the assigned range: %pM\n", + netdev->name, netdev->dev_addr); if (register_netdev(netdev)) goto err; -- cgit v1.2.3 From 30a6ae8d477dc90254eb785d8ccff6dfe7d9082e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:10:01 -0800 Subject: drivers/net/r8169.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/r8169.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 60f96c468a24..c403ce0a3d3a 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3188,15 +3188,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (netif_msg_probe(tp)) { u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - printk(KERN_INFO "%s: %s at 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "XID %08x IRQ %d\n", + printk(KERN_INFO "%s: %s at 0x%lx, %pM, XID %08x IRQ %d\n", dev->name, rtl_chip_info[tp->chipset].name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq); + dev->base_addr, dev->dev_addr, xid, dev->irq); } rtl8169_init_phy(dev, tp); -- cgit v1.2.3 From 6cd9b49d7328c4656bfc17fcb47fb814955d40d2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 29 Dec 2009 20:10:35 -0800 Subject: Subject: drivers/net/sh_eth.c: use %pM to shown MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index ca6285016dfd..ed52c0063a65 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1473,13 +1473,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev) if (ret) goto out_unregister; - /* pritnt device infomation */ - pr_info("Base address at 0x%x, ", - (u32)ndev->base_addr); - - for (i = 0; i < 5; i++) - printk("%02X:", ndev->dev_addr[i]); - printk("%02X, IRQ %d.\n", ndev->dev_addr[i], ndev->irq); + /* print device infomation */ + pr_info("Base address at 0x%x, %pM, IRQ %d.\n", + (u32)ndev->base_addr, ndev->dev_addr, ndev->irq); platform_set_drvdata(pdev, ndev); -- cgit v1.2.3 From 1f3c8804acba841b5573b953f5560d2683d2db0d Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Mon, 14 Dec 2009 10:48:58 +0000 Subject: bonding: allow arp_ip_targets on separate vlans to use arp validation This allows a bond device to specify an arp_ip_target as a host that is not on the same vlan as the base bond device and still use arp validation. A configuration like this, now works: BONDING_OPTS="mode=active-backup arp_interval=1000 arp_ip_target=10.0.100.1 arp_validate=3" 1: lo: mtu 16436 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth1: mtu 1500 qdisc pfifo_fast master bond0 qlen 1000 link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff 3: eth0: mtu 1500 qdisc pfifo_fast master bond0 qlen 1000 link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff 8: bond0: mtu 1500 qdisc noqueue link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff inet6 fe80::213:21ff:febe:33e9/64 scope link valid_lft forever preferred_lft forever 9: bond0.100@bond0: mtu 1500 qdisc noqueue link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff inet 10.0.100.2/24 brd 10.0.100.255 scope global bond0.100 inet6 fe80::213:21ff:febe:33e9/64 scope link valid_lft forever preferred_lft forever Ethernet Channel Bonding Driver: v3.6.0 (September 26, 2009) Bonding Mode: fault-tolerance (active-backup) Primary Slave: None Currently Active Slave: eth1 MII Status: up MII Polling Interval (ms): 0 Up Delay (ms): 0 Down Delay (ms): 0 ARP Polling Interval (ms): 1000 ARP IP target/s (n.n.n.n form): 10.0.100.1 Slave Interface: eth1 MII Status: up Link Failure Count: 1 Permanent HW addr: 00:40:05:30:ff:30 Slave Interface: eth0 MII Status: up Link Failure Count: 0 Permanent HW addr: 00:13:21:be:33:e9 Signed-off-by: Andy Gospodarek Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 11 +++++++++++ net/8021q/vlan_core.c | 2 ++ net/core/dev.c | 20 +++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3f0071cfe56b..6a42a1453afa 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2615,6 +2615,17 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack unsigned char *arp_ptr; __be32 sip, tip; + if (dev->priv_flags & IFF_802_1Q_VLAN) { + /* + * When using VLANS and bonding, dev and oriv_dev may be + * incorrect if the physical interface supports VLAN + * acceleration. With this change ARP validation now + * works for hosts only reachable on the VLAN interface. + */ + dev = vlan_dev_real_dev(dev); + orig_dev = dev_get_by_index_rcu(dev_net(skb->dev),skb->skb_iif); + } + if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) goto out; diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index e75a2f3b10af..c0316e0ca6e8 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -14,6 +14,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, if (skb_bond_should_drop(skb)) goto drop; + skb->skb_iif = skb->dev->ifindex; __vlan_hwaccel_put_tag(skb, vlan_tci); skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); @@ -85,6 +86,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, if (skb_bond_should_drop(skb)) goto drop; + skb->skb_iif = skb->dev->ifindex; __vlan_hwaccel_put_tag(skb, vlan_tci); skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK); diff --git a/net/core/dev.c b/net/core/dev.c index a8d68cdedbbe..f9aa699ab6cb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2495,12 +2495,26 @@ ncls: if (!skb) goto out; + /* + * Make sure frames received on VLAN interfaces stacked on + * bonding interfaces still make their way to any base bonding + * device that may have registered for a specific ptype. The + * handler may have to adjust skb->dev and orig_dev. + * + * null_or_orig can be overloaded since it will not be set when + * using VLANs on top of bonding. Putting it here prevents + * disturbing the ptype_all handlers above. + */ + if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) && + (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) { + null_or_orig = vlan_dev_real_dev(skb->dev); + } + type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { - if (ptype->type == type && - (ptype->dev == null_or_orig || ptype->dev == skb->dev || - ptype->dev == orig_dev)) { + if (ptype->type == type && (ptype->dev == null_or_orig || + ptype->dev == skb->dev || ptype->dev == orig_dev)) { if (pt_prev) ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = ptype; -- cgit v1.2.3 From 75ed0a897208c3273fd8dc0f71e1417dba5a049b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 18 Dec 2009 21:16:52 +0000 Subject: drivers/net/cxgb3: Use kzalloc for allocating only one thing Use kzalloc rather than kcalloc(1,...) The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ @@ - kcalloc(1, + kzalloc( ...) // Signed-off-by: Julia Lawall Acked-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/cxgb3_offload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index 75064eea1d87..9498361119d6 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c @@ -1252,7 +1252,7 @@ int cxgb3_offload_activate(struct adapter *adapter) struct mtutab mtutab; unsigned int l2t_capacity; - t = kcalloc(1, sizeof(*t), GFP_KERNEL); + t = kzalloc(sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; -- cgit v1.2.3 From 20dd3850bcf860561496827b711fa10fecf6e787 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 25 Dec 2009 06:47:47 +0000 Subject: can: Speed up CAN frame receiption by using ml_priv this patch removes the hlist that contains the CAN receiver filter lists. It uses the 'midlayer private' pointer ml_priv and links the filters directly to the CAN netdevice, which allows to omit the walk through the complete CAN devices hlist for each received CAN frame. This patch is tested and does not remove any locking. Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/af_can.c | 118 ++++++++++++++++--------------------------------------- net/can/af_can.h | 4 +- net/can/proc.c | 93 ++++++++++++++++++++++++++++--------------- 3 files changed, 96 insertions(+), 119 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 51adc4c2b860..bc18b084ffdb 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -77,8 +77,8 @@ static int stats_timer __read_mostly = 1; module_param(stats_timer, int, S_IRUGO); MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)"); -HLIST_HEAD(can_rx_dev_list); -static struct dev_rcv_lists can_rx_alldev_list; +/* receive filters subscribed for 'all' CAN devices */ +struct dev_rcv_lists can_rx_alldev_list; static DEFINE_SPINLOCK(can_rcvlists_lock); static struct kmem_cache *rcv_cache __read_mostly; @@ -292,28 +292,10 @@ EXPORT_SYMBOL(can_send); static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev) { - struct dev_rcv_lists *d = NULL; - struct hlist_node *n; - - /* - * find receive list for this device - * - * The hlist_for_each_entry*() macros curse through the list - * using the pointer variable n and set d to the containing - * struct in each list iteration. Therefore, after list - * iteration, d is unmodified when the list is empty, and it - * points to last list element, when the list is non-empty - * but no match in the loop body is found. I.e. d is *not* - * NULL when no match is found. We can, however, use the - * cursor variable n to decide if a match was found. - */ - - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) { - if (d->dev == dev) - break; - } - - return n ? d : NULL; + if (!dev) + return &can_rx_alldev_list; + else + return (struct dev_rcv_lists *)dev->ml_priv; } /** @@ -467,16 +449,6 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, } EXPORT_SYMBOL(can_rx_register); -/* - * can_rx_delete_device - rcu callback for dev_rcv_lists structure removal - */ -static void can_rx_delete_device(struct rcu_head *rp) -{ - struct dev_rcv_lists *d = container_of(rp, struct dev_rcv_lists, rcu); - - kfree(d); -} - /* * can_rx_delete_receiver - rcu callback for single receiver entry removal */ @@ -541,7 +513,6 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, "dev %s, id %03X, mask %03X\n", DNAME(dev), can_id, mask); r = NULL; - d = NULL; goto out; } @@ -552,10 +523,10 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, can_pstats.rcv_entries--; /* remove device structure requested by NETDEV_UNREGISTER */ - if (d->remove_on_zero_entries && !d->entries) - hlist_del_rcu(&d->list); - else - d = NULL; + if (d->remove_on_zero_entries && !d->entries) { + kfree(d); + dev->ml_priv = NULL; + } out: spin_unlock(&can_rcvlists_lock); @@ -563,10 +534,6 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, /* schedule the receiver item for deletion */ if (r) call_rcu(&r->rcu, can_rx_delete_receiver); - - /* schedule the device structure for deletion */ - if (d) - call_rcu(&d->rcu, can_rx_delete_device); } EXPORT_SYMBOL(can_rx_unregister); @@ -780,48 +747,35 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, case NETDEV_REGISTER: - /* - * create new dev_rcv_lists for this device - * - * N.B. zeroing the struct is the correct initialization - * for the embedded hlist_head structs. - * Another list type, e.g. list_head, would require - * explicit initialization. - */ - + /* create new dev_rcv_lists for this device */ d = kzalloc(sizeof(*d), GFP_KERNEL); if (!d) { printk(KERN_ERR "can: allocation of receive list failed\n"); return NOTIFY_DONE; } - d->dev = dev; - - spin_lock(&can_rcvlists_lock); - hlist_add_head_rcu(&d->list, &can_rx_dev_list); - spin_unlock(&can_rcvlists_lock); + BUG_ON(dev->ml_priv); + dev->ml_priv = d; break; case NETDEV_UNREGISTER: spin_lock(&can_rcvlists_lock); - d = find_dev_rcv_lists(dev); + d = dev->ml_priv; if (d) { - if (d->entries) { + if (d->entries) d->remove_on_zero_entries = 1; - d = NULL; - } else - hlist_del_rcu(&d->list); + else { + kfree(d); + dev->ml_priv = NULL; + } } else printk(KERN_ERR "can: notifier: receive list not " "found for dev %s\n", dev->name); spin_unlock(&can_rcvlists_lock); - if (d) - call_rcu(&d->rcu, can_rx_delete_device); - break; } @@ -853,21 +807,13 @@ static __init int can_init(void) { printk(banner); + memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list)); + rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver), 0, 0, NULL); if (!rcv_cache) return -ENOMEM; - /* - * Insert can_rx_alldev_list for reception on all devices. - * This struct is zero initialized which is correct for the - * embedded hlist heads, the dev pointer, and the entries counter. - */ - - spin_lock(&can_rcvlists_lock); - hlist_add_head_rcu(&can_rx_alldev_list.list, &can_rx_dev_list); - spin_unlock(&can_rcvlists_lock); - if (stats_timer) { /* the statistics are updated every second (timer triggered) */ setup_timer(&can_stattimer, can_stat_update, 0); @@ -887,8 +833,7 @@ static __init int can_init(void) static __exit void can_exit(void) { - struct dev_rcv_lists *d; - struct hlist_node *n, *next; + struct net_device *dev; if (stats_timer) del_timer(&can_stattimer); @@ -900,14 +845,19 @@ static __exit void can_exit(void) unregister_netdevice_notifier(&can_netdev_notifier); sock_unregister(PF_CAN); - /* remove can_rx_dev_list */ - spin_lock(&can_rcvlists_lock); - hlist_del(&can_rx_alldev_list.list); - hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) { - hlist_del(&d->list); - kfree(d); + /* remove created dev_rcv_lists from still registered CAN devices */ + rcu_read_lock(); + for_each_netdev_rcu(&init_net, dev) { + if (dev->type == ARPHRD_CAN && dev->ml_priv){ + + struct dev_rcv_lists *d = dev->ml_priv; + + BUG_ON(d->entries); + kfree(d); + dev->ml_priv = NULL; + } } - spin_unlock(&can_rcvlists_lock); + rcu_read_unlock(); rcu_barrier(); /* Wait for completion of call_rcu()'s */ diff --git a/net/can/af_can.h b/net/can/af_can.h index 18f91e37cc30..34253b84e30f 100644 --- a/net/can/af_can.h +++ b/net/can/af_can.h @@ -63,10 +63,8 @@ struct receiver { enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX }; +/* per device receive filters linked at dev->ml_priv */ struct dev_rcv_lists { - struct hlist_node list; - struct rcu_head rcu; - struct net_device *dev; struct hlist_head rx[RX_MAX]; struct hlist_head rx_sff[0x800]; int remove_on_zero_entries; diff --git a/net/can/proc.c b/net/can/proc.c index 9b9ad29be567..f4265cc9c3fb 100644 --- a/net/can/proc.c +++ b/net/can/proc.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "af_can.h" @@ -84,6 +85,9 @@ static const char rx_list_name[][8] = { [RX_EFF] = "rx_eff", }; +/* receive filters subscribed for 'all' CAN devices */ +extern struct dev_rcv_lists can_rx_alldev_list; + /* * af_can statistics stuff */ @@ -190,10 +194,6 @@ void can_stat_update(unsigned long data) /* * proc read functions - * - * From known use-cases we expect about 10 entries in a receive list to be - * printed in the proc_fs. So PAGE_SIZE is definitely enough space here. - * */ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, @@ -202,7 +202,6 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, struct receiver *r; struct hlist_node *n; - rcu_read_lock(); hlist_for_each_entry_rcu(r, n, rx_list, list) { char *fmt = (r->can_id & CAN_EFF_FLAG)? " %-5s %08X %08x %08x %08x %8ld %s\n" : @@ -212,7 +211,6 @@ static void can_print_rcvlist(struct seq_file *m, struct hlist_head *rx_list, (unsigned long)r->func, (unsigned long)r->data, r->matches, r->ident); } - rcu_read_unlock(); } static void can_print_recv_banner(struct seq_file *m) @@ -346,24 +344,39 @@ static const struct file_operations can_version_proc_fops = { .release = single_release, }; +static inline void can_rcvlist_proc_show_one(struct seq_file *m, int idx, + struct net_device *dev, + struct dev_rcv_lists *d) +{ + if (!hlist_empty(&d->rx[idx])) { + can_print_recv_banner(m); + can_print_rcvlist(m, &d->rx[idx], dev); + } else + seq_printf(m, " (%s: no entry)\n", DNAME(dev)); + +} + static int can_rcvlist_proc_show(struct seq_file *m, void *v) { /* double cast to prevent GCC warning */ int idx = (int)(long)m->private; + struct net_device *dev; struct dev_rcv_lists *d; - struct hlist_node *n; seq_printf(m, "\nreceive list '%s':\n", rx_list_name[idx]); rcu_read_lock(); - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) { - if (!hlist_empty(&d->rx[idx])) { - can_print_recv_banner(m); - can_print_rcvlist(m, &d->rx[idx], d->dev); - } else - seq_printf(m, " (%s: no entry)\n", DNAME(d->dev)); + /* receive list for 'all' CAN devices (dev == NULL) */ + d = &can_rx_alldev_list; + can_rcvlist_proc_show_one(m, idx, NULL, d); + + /* receive list for registered CAN devices */ + for_each_netdev_rcu(&init_net, dev) { + if (dev->type == ARPHRD_CAN && dev->ml_priv) + can_rcvlist_proc_show_one(m, idx, dev, dev->ml_priv); } + rcu_read_unlock(); seq_putc(m, '\n'); @@ -383,34 +396,50 @@ static const struct file_operations can_rcvlist_proc_fops = { .release = single_release, }; +static inline void can_rcvlist_sff_proc_show_one(struct seq_file *m, + struct net_device *dev, + struct dev_rcv_lists *d) +{ + int i; + int all_empty = 1; + + /* check wether at least one list is non-empty */ + for (i = 0; i < 0x800; i++) + if (!hlist_empty(&d->rx_sff[i])) { + all_empty = 0; + break; + } + + if (!all_empty) { + can_print_recv_banner(m); + for (i = 0; i < 0x800; i++) { + if (!hlist_empty(&d->rx_sff[i])) + can_print_rcvlist(m, &d->rx_sff[i], dev); + } + } else + seq_printf(m, " (%s: no entry)\n", DNAME(dev)); +} + static int can_rcvlist_sff_proc_show(struct seq_file *m, void *v) { + struct net_device *dev; struct dev_rcv_lists *d; - struct hlist_node *n; /* RX_SFF */ seq_puts(m, "\nreceive list 'rx_sff':\n"); rcu_read_lock(); - hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) { - int i, all_empty = 1; - /* check wether at least one list is non-empty */ - for (i = 0; i < 0x800; i++) - if (!hlist_empty(&d->rx_sff[i])) { - all_empty = 0; - break; - } - - if (!all_empty) { - can_print_recv_banner(m); - for (i = 0; i < 0x800; i++) { - if (!hlist_empty(&d->rx_sff[i])) - can_print_rcvlist(m, &d->rx_sff[i], - d->dev); - } - } else - seq_printf(m, " (%s: no entry)\n", DNAME(d->dev)); + + /* sff receive list for 'all' CAN devices (dev == NULL) */ + d = &can_rx_alldev_list; + can_rcvlist_sff_proc_show_one(m, NULL, d); + + /* sff receive list for registered CAN devices */ + for_each_netdev_rcu(&init_net, dev) { + if (dev->type == ARPHRD_CAN && dev->ml_priv) + can_rcvlist_sff_proc_show_one(m, dev, dev->ml_priv); } + rcu_read_unlock(); seq_putc(m, '\n'); -- cgit v1.2.3 From c1c5523dd1517250cac8b15a4acbc237c24a67d4 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 23 Dec 2009 01:27:48 +0000 Subject: can/netlink: add CAN_CTRLMODE_ONE_SHOT This patch adds the flag CAN_CTRLMODE_ONE_SHOT. It is used as mask or flag in the "struct can_ctrlmode". It allows userspace via netlink to set a CAN controller into the special "one-shot" mode. In this mode, if supported by the CAN controller, it tries only once to deliver a CAN frame and aborts it if an error (e.g.: arbitration lost) happens. Signed-off-by: Marc Kleine-Budde Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- include/linux/can/netlink.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h index 9ecbb7871c0e..c818335fbb13 100644 --- a/include/linux/can/netlink.h +++ b/include/linux/can/netlink.h @@ -80,6 +80,7 @@ struct can_ctrlmode { #define CAN_CTRLMODE_LOOPBACK 0x1 /* Loopback mode */ #define CAN_CTRLMODE_LISTENONLY 0x2 /* Listen-only mode */ #define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x8 /* One-Shot mode */ /* * CAN device statistics -- cgit v1.2.3 From ee983ac76865797a5553597a9412c835c2710f51 Mon Sep 17 00:00:00 2001 From: Amerigo Wang Date: Thu, 24 Dec 2009 17:26:48 +0000 Subject: tipc: use kconfig to limit numeric ranges We can rely on kconfig to limit these numbers, no need to limit them at compile time/run time. Users who modify these numbers manually should be responsible for themself. :) Signed-off-by: WANG Cong Cc: Per Liden Cc: Jon Maloy Cc: Allan Stephens Cc: David S. Miller Signed-off-by: David S. Miller --- net/tipc/Kconfig | 8 ++++++-- net/tipc/core.c | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig index 3b30d1130b61..dafbd533067c 100644 --- a/net/tipc/Kconfig +++ b/net/tipc/Kconfig @@ -33,6 +33,7 @@ config TIPC_ADVANCED config TIPC_ZONES int "Maximum number of zones in network" depends on TIPC_ADVANCED + range 1 255 default "3" help Max number of zones inside TIPC network. Max supported value @@ -44,10 +45,10 @@ config TIPC_ZONES config TIPC_CLUSTERS int "Maximum number of clusters in a zone" depends on TIPC_ADVANCED + range 1 1 default "1" help - ***Only 1 (one cluster in a zone) is supported by current code. - Any value set here will be overridden.*** + ***Only 1 (one cluster in a zone) is supported by current code.*** (Max number of clusters inside TIPC zone. Max supported value is 4095 clusters, minimum is 1. @@ -59,6 +60,7 @@ config TIPC_CLUSTERS config TIPC_NODES int "Maximum number of nodes in cluster" depends on TIPC_ADVANCED + range 8 2047 default "255" help Maximum number of nodes inside a TIPC cluster. Maximum @@ -70,6 +72,7 @@ config TIPC_NODES config TIPC_SLAVE_NODES int "Maximum number of slave nodes in cluster" depends on TIPC_ADVANCED + range 0 2047 default "0" help ***This capability is not supported by current code.*** @@ -83,6 +86,7 @@ config TIPC_SLAVE_NODES config TIPC_PORTS int "Maximum number of ports in a node" depends on TIPC_ADVANCED + range 217 65536 default "8191" help Maximum number of ports within a node. Maximum diff --git a/net/tipc/core.c b/net/tipc/core.c index 3256bd7d398f..52c571fedbe0 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -189,11 +189,11 @@ static int __init tipc_init(void) tipc_remote_management = 1; tipc_max_publications = 10000; tipc_max_subscriptions = 2000; - tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536); - tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 255); - tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1); - tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047); - tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); + tipc_max_ports = CONFIG_TIPC_PORTS; + tipc_max_zones = CONFIG_TIPC_ZONES; + tipc_max_clusters = CONFIG_TIPC_CLUSTERS; + tipc_max_nodes = CONFIG_TIPC_NODES; + tipc_max_slaves = CONFIG_TIPC_SLAVE_NODES; tipc_net_id = 4711; if ((res = tipc_core_start())) -- cgit v1.2.3 From ceba0b29e002e6151b6b5ead8db9c664b58d8d21 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Mon, 28 Dec 2009 15:17:24 +0000 Subject: axnet_cs: remove unnecessary spin_unlock_irqrestore axnet_cs: remove unnecessary spin_unlock_irqrestore,spin_lock_irqsave. Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/axnet_cs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index d431b59e7d11..2ee57bd52a01 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1065,14 +1065,11 @@ static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, spin_lock_irqsave(&ei_local->page_lock, flags); outb_p(0x00, e8390_base + EN0_IMR); - spin_unlock_irqrestore(&ei_local->page_lock, flags); /* * Slow phase with lock held. */ - spin_lock_irqsave(&ei_local->page_lock, flags); - ei_local->irqlock = 1; send_length = max(length, ETH_ZLEN); -- cgit v1.2.3 From 71c3ebfdb27b50dcaef38b6f70da82b9142c5fb6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 4 Jan 2010 15:21:31 +0100 Subject: netfilter: SNMP NAT: correct the size argument to kzalloc obj has type struct snmp_object **, not struct snmp_object *. But indeed it is not even clear why kmalloc is needed. The memory is freed by the end of the function, so the local variable of pointer type should be sufficient. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @disable sizeof_type_expr@ type T; T **x; @@ x = <+...sizeof( - T + *x )...+> // Signed-off-by: Julia Lawall Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_nat_snmp_basic.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index d9521f6f9ed0..0b9c7ce3d6c5 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1038,7 +1038,7 @@ static int snmp_parse_mangle(unsigned char *msg, unsigned int cls, con, tag, vers, pdutype; struct asn1_ctx ctx; struct asn1_octstr comm; - struct snmp_object **obj; + struct snmp_object *obj; if (debug > 1) hex_dump(msg, len); @@ -1148,43 +1148,34 @@ static int snmp_parse_mangle(unsigned char *msg, if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) return 0; - obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC); - if (obj == NULL) { - if (net_ratelimit()) - printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__); - return 0; - } - while (!asn1_eoc_decode(&ctx, eoc)) { unsigned int i; - if (!snmp_object_decode(&ctx, obj)) { - if (*obj) { - kfree((*obj)->id); - kfree(*obj); + if (!snmp_object_decode(&ctx, &obj)) { + if (obj) { + kfree(obj->id); + kfree(obj); } - kfree(obj); return 0; } if (debug > 1) { printk(KERN_DEBUG "bsalg: object: "); - for (i = 0; i < (*obj)->id_len; i++) { + for (i = 0; i < obj->id_len; i++) { if (i > 0) printk("."); - printk("%lu", (*obj)->id[i]); + printk("%lu", obj->id[i]); } - printk(": type=%u\n", (*obj)->type); + printk(": type=%u\n", obj->type); } - if ((*obj)->type == SNMP_IPADDR) + if (obj->type == SNMP_IPADDR) mangle_address(ctx.begin, ctx.pointer - 4 , map, check); - kfree((*obj)->id); - kfree(*obj); + kfree(obj->id); + kfree(obj); } - kfree(obj); if (!asn1_eoc_decode(&ctx, eoc)) return 0; -- cgit v1.2.3 From 89bc7a0f64de7bed2e0bc68a23d75699a610cd37 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jan 2010 16:26:03 +0100 Subject: netfilter: xt_recent: save 8 bytes per htable Moving rnd_inited into the hole after the uint8 lets go of the uint32 rnd_inited was using, plus the padding that would follow the int group. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/netfilter/xt_hashlimit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index dd16e404424f..5bdc1fbf3ad7 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -81,13 +81,13 @@ struct xt_hashlimit_htable { struct hlist_node node; /* global list of all htables */ atomic_t use; u_int8_t family; + bool rnd_initialized; struct hashlimit_cfg1 cfg; /* config */ /* used internally */ spinlock_t lock; /* lock for list_head */ u_int32_t rnd; /* random seed for hash */ - int rnd_initialized; unsigned int count; /* number entries in table */ struct timer_list timer; /* timer for gc */ @@ -150,7 +150,7 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht, * the first hashtable entry */ if (!ht->rnd_initialized) { get_random_bytes(&ht->rnd, sizeof(ht->rnd)); - ht->rnd_initialized = 1; + ht->rnd_initialized = true; } if (ht->cfg.max && ht->count >= ht->cfg.max) { @@ -235,7 +235,7 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family) atomic_set(&hinfo->use, 1); hinfo->count = 0; hinfo->family = family; - hinfo->rnd_initialized = 0; + hinfo->rnd_initialized = false; spin_lock_init(&hinfo->lock); hinfo->pde = proc_create_data(minfo->name, 0, (family == NFPROTO_IPV4) ? @@ -296,7 +296,7 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family) atomic_set(&hinfo->use, 1); hinfo->count = 0; hinfo->family = family; - hinfo->rnd_initialized = 0; + hinfo->rnd_initialized = false; spin_lock_init(&hinfo->lock); hinfo->pde = proc_create_data(minfo->name, 0, -- cgit v1.2.3 From 5191d50192ec1281e51cbcb5248cb2667ff4d896 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jan 2010 16:27:25 +0100 Subject: netfilter: xtables: do not grab random bytes at __init "It is deliberately not done in the init function, since we might not have sufficient random while booting." Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/netfilter/xt_NFQUEUE.c | 6 +++++- net/netfilter/xt_RATEEST.c | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index f28f6a5fc02d..12dcd7007c3e 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c @@ -28,6 +28,7 @@ MODULE_ALIAS("ip6t_NFQUEUE"); MODULE_ALIAS("arpt_NFQUEUE"); static u32 jhash_initval __read_mostly; +static bool rnd_inited __read_mostly; static unsigned int nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) @@ -90,6 +91,10 @@ static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) const struct xt_NFQ_info_v1 *info = par->targinfo; u32 maxid; + if (unlikely(!rnd_inited)) { + get_random_bytes(&jhash_initval, sizeof(jhash_initval)); + rnd_inited = true; + } if (info->queues_total == 0) { pr_err("NFQUEUE: number of total queues is 0\n"); return false; @@ -135,7 +140,6 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = { static int __init nfqueue_tg_init(void) { - get_random_bytes(&jhash_initval, sizeof(jhash_initval)); return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg)); } diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index d80b8192e0d4..87ae97e5516f 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -23,6 +23,7 @@ static DEFINE_MUTEX(xt_rateest_mutex); #define RATEEST_HSIZE 16 static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; static unsigned int jhash_rnd __read_mostly; +static bool rnd_inited __read_mostly; static unsigned int xt_rateest_hash(const char *name) { @@ -93,6 +94,11 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) struct gnet_estimator est; } cfg; + if (unlikely(!rnd_inited)) { + get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); + rnd_inited = true; + } + est = xt_rateest_lookup(info->name); if (est) { /* @@ -164,7 +170,6 @@ static int __init xt_rateest_tg_init(void) for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) INIT_HLIST_HEAD(&rateest_hash[i]); - get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); return xt_register_target(&xt_rateest_tg_reg); } -- cgit v1.2.3 From 294188ae32f984a072c64c959354b2f6f52f80a7 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Jan 2010 16:28:38 +0100 Subject: netfilter: xtables: obtain random bytes earlier, in checkentry We can initialize the random hash bytes on checkentry. This is preferable since it is outside the hot path. Reference: http://bugzilla.netfilter.org/show_bug.cgi?id=621 Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/netfilter/xt_connlimit.c | 17 ++++++----------- net/netfilter/xt_recent.c | 20 ++++++++------------ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 38f03f75a636..8103bef78e44 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -40,15 +40,11 @@ struct xt_connlimit_data { spinlock_t lock; }; -static u_int32_t connlimit_rnd; -static bool connlimit_rnd_inited; +static u_int32_t connlimit_rnd __read_mostly; +static bool connlimit_rnd_inited __read_mostly; static inline unsigned int connlimit_iphash(__be32 addr) { - if (unlikely(!connlimit_rnd_inited)) { - get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); - connlimit_rnd_inited = true; - } return jhash_1word((__force __u32)addr, connlimit_rnd) & 0xFF; } @@ -59,11 +55,6 @@ connlimit_iphash6(const union nf_inet_addr *addr, union nf_inet_addr res; unsigned int i; - if (unlikely(!connlimit_rnd_inited)) { - get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); - connlimit_rnd_inited = true; - } - for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) res.ip6[i] = addr->ip6[i] & mask->ip6[i]; @@ -226,6 +217,10 @@ static bool connlimit_mt_check(const struct xt_mtchk_param *par) struct xt_connlimit_info *info = par->matchinfo; unsigned int i; + if (unlikely(!connlimit_rnd_inited)) { + get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd)); + connlimit_rnd_inited = true; + } if (nf_ct_l3proto_try_module_get(par->family) < 0) { printk(KERN_WARNING "cannot load conntrack support for " "address family %u\n", par->family); diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index fc70a49c0afd..768d01ff1fea 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -90,25 +90,17 @@ static struct proc_dir_entry *recent_proc_dir; static const struct file_operations recent_old_fops, recent_mt_fops; #endif -static u_int32_t hash_rnd; -static bool hash_rnd_initted; +static u_int32_t hash_rnd __read_mostly; +static bool hash_rnd_inited __read_mostly; -static unsigned int recent_entry_hash4(const union nf_inet_addr *addr) +static inline unsigned int recent_entry_hash4(const union nf_inet_addr *addr) { - if (!hash_rnd_initted) { - get_random_bytes(&hash_rnd, sizeof(hash_rnd)); - hash_rnd_initted = true; - } return jhash_1word((__force u32)addr->ip, hash_rnd) & (ip_list_hash_size - 1); } -static unsigned int recent_entry_hash6(const union nf_inet_addr *addr) +static inline unsigned int recent_entry_hash6(const union nf_inet_addr *addr) { - if (!hash_rnd_initted) { - get_random_bytes(&hash_rnd, sizeof(hash_rnd)); - hash_rnd_initted = true; - } return jhash2((u32 *)addr->ip6, ARRAY_SIZE(addr->ip6), hash_rnd) & (ip_list_hash_size - 1); } @@ -287,6 +279,10 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) unsigned i; bool ret = false; + if (unlikely(!hash_rnd_inited)) { + get_random_bytes(&hash_rnd, sizeof(hash_rnd)); + hash_rnd_inited = true; + } if (hweight8(info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE | XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1) -- cgit v1.2.3 From 51633632ef614ef045f25d76fc7f0133d7cc60c6 Mon Sep 17 00:00:00 2001 From: Juha Leppanen Date: Mon, 4 Jan 2010 15:52:50 -0500 Subject: wl1271: fix timeout in wl1271_top_reg_read I noticed a timeout bug in /drivers/net/wireless/wl12xx/wl1271_spi.c In the current code you cannot tell why you exited the "poll for data ready" do-while loop if exiting was done after the last possible loop. Then timeout==0 regardless of (val & OCP_READY_MASK) or !(val & OCP_READY_MASK), leading to possible false timeout... Simple correction could be decreasing timeout after checking for !(val & OCP_READY_MASK), not before (Manually converted from email to an actual patch by me. -- JWL) Reported-by: "Juha Leppanen" Signed-off-by: "Juha Leppanen" Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_spi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 02978a16e732..ee9564aa6ecc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -397,8 +397,7 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) /* poll for data ready */ do { val = wl1271_spi_read32(wl, OCP_DATA_READ); - timeout--; - } while (!(val & OCP_READY_MASK) && timeout); + } while (!(val & OCP_READY_MASK) && --timeout); if (!timeout) { wl1271_warning("Top register access timed out."); -- cgit v1.2.3 From e5eb8bd9429ebd04cf906156d1fe40b52f88e82f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 4 Jan 2010 15:58:03 -0500 Subject: mac80211: fix typo added by "mac80211: fix propagation of failed..." 'Typo: it's "Hardware", not "Harware". Hmm, sometimes it's hairware :-)"' -- Holger Schurig Reported-by: Holger Schurig Signed-off-by: John W. Linville --- net/mac80211/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 7e38858a9280..29e1acca207c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1094,7 +1094,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (res) { WARN(local->suspended, "Harware became unavailable " "upon resume. This is could be a software issue" - "prior to suspend or a harware issue\n"); + "prior to suspend or a hardware issue\n"); return res; } -- cgit v1.2.3 From 6f7edb4881bf51300060e89915926e070ace8c4d Mon Sep 17 00:00:00 2001 From: "Catalin(ux) M. BOIE" Date: Tue, 5 Jan 2010 05:50:24 +0100 Subject: IPVS: Allow boot time change of hash size I was very frustrated about the fact that I have to recompile the kernel to change the hash size. So, I created this patch. If IPVS is built-in you can append ip_vs.conn_tab_bits=?? to kernel command line, or, if you built IPVS as modules, you can add options ip_vs conn_tab_bits=??. To keep everything backward compatible, you still can select the size at compile time, and that will be used as default. It has been about a year since this patch was originally posted and subsequently dropped on the basis of insufficient test data. Mark Bergsma has provided the following test results which seem to strongly support the need for larger hash table sizes: We do however run into the same problem with the default setting (212 = 4096 entries), as most of our LVS balancers handle around a million connections/SLAB entries at any point in time (around 100-150 kpps load). With only 4096 hash table entries this implies that each entry consists of a linked list of 256 connections *on average*. To provide some statistics, I did an oprofile run on an 2.6.31 kernel, with both the default 4096 table size, and the same kernel recompiled with IP_VS_CONN_TAB_BITS set to 18 (218 = 262144 entries). I built a quick test setup with a part of Wikimedia/Wikipedia's live traffic mirrored by the switch to the test host. With the default setting, at ~ 120 kpps packet load we saw a typical %si CPU usage of around 30-35%, and oprofile reported a hot spot in ip_vs_conn_in_get: samples % image name app name symbol name 1719761 42.3741 ip_vs.ko ip_vs.ko ip_vs_conn_in_get 302577 7.4554 bnx2 bnx2 /bnx2 181984 4.4840 vmlinux vmlinux __ticket_spin_lock 128636 3.1695 vmlinux vmlinux ip_route_input 74345 1.8318 ip_vs.ko ip_vs.ko ip_vs_conn_out_get 68482 1.6874 vmlinux vmlinux mwait_idle After loading the recompiled kernel with 218 entries, %si CPU usage dropped in half to around 12-18%, and oprofile looks much healthier, with only 7% spent in ip_vs_conn_in_get: samples % image name app name symbol name 265641 14.4616 bnx2 bnx2 /bnx2 143251 7.7986 vmlinux vmlinux __ticket_spin_lock 140661 7.6576 ip_vs.ko ip_vs.ko ip_vs_conn_in_get 94364 5.1372 vmlinux vmlinux mwait_idle 86267 4.6964 vmlinux vmlinux ip_route_input [ horms@verge.net.au: trivial up-port and minor style fixes ] Signed-off-by: Catalin(ux) M. BOIE Cc: Mark Bergsma Signed-off-by: Simon Horman Signed-off-by: Patrick McHardy --- include/net/ip_vs.h | 16 +++++----------- net/netfilter/ipvs/Kconfig | 4 ++++ net/netfilter/ipvs/ip_vs_conn.c | 42 ++++++++++++++++++++++++++++++----------- net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++---- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 8dc3296b7bea..a816c37417bb 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -26,6 +26,11 @@ #include /* for struct ipv6hdr */ #include /* for ipv6_addr_copy */ + +/* Connections' size value needed by ip_vs_ctl.c */ +extern int ip_vs_conn_tab_size; + + struct ip_vs_iphdr { int len; __u8 protocol; @@ -592,17 +597,6 @@ extern void ip_vs_init_hash_table(struct list_head *table, int rows); * (from ip_vs_conn.c) */ -/* - * IPVS connection entry hash table - */ -#ifndef CONFIG_IP_VS_TAB_BITS -#define CONFIG_IP_VS_TAB_BITS 12 -#endif - -#define IP_VS_CONN_TAB_BITS CONFIG_IP_VS_TAB_BITS -#define IP_VS_CONN_TAB_SIZE (1 << IP_VS_CONN_TAB_BITS) -#define IP_VS_CONN_TAB_MASK (IP_VS_CONN_TAB_SIZE - 1) - enum { IP_VS_DIR_INPUT = 0, IP_VS_DIR_OUTPUT, diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 79a698052218..c71e543d2549 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig @@ -68,6 +68,10 @@ config IP_VS_TAB_BITS each hash entry uses 8 bytes, so you can estimate how much memory is needed for your box. + You can overwrite this number setting conn_tab_bits module parameter + or by appending ip_vs.conn_tab_bits=? to the kernel command line + if IP VS was compiled built-in. + comment "IPVS transport protocol load balancing support" config IP_VS_PROTO_TCP diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 27c30cf933da..60bb41a8d8d4 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -40,6 +40,21 @@ #include +#ifndef CONFIG_IP_VS_TAB_BITS +#define CONFIG_IP_VS_TAB_BITS 12 +#endif + +/* + * Connection hash size. Default is what was selected at compile time. +*/ +int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS; +module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444); +MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size"); + +/* size and mask values */ +int ip_vs_conn_tab_size; +int ip_vs_conn_tab_mask; + /* * Connection hash table: for input and output packets lookups of IPVS */ @@ -125,11 +140,11 @@ static unsigned int ip_vs_conn_hashkey(int af, unsigned proto, if (af == AF_INET6) return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd), (__force u32)port, proto, ip_vs_conn_rnd) - & IP_VS_CONN_TAB_MASK; + & ip_vs_conn_tab_mask; #endif return jhash_3words((__force u32)addr->ip, (__force u32)port, proto, ip_vs_conn_rnd) - & IP_VS_CONN_TAB_MASK; + & ip_vs_conn_tab_mask; } @@ -760,7 +775,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos) int idx; struct ip_vs_conn *cp; - for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) { + for (idx = 0; idx < ip_vs_conn_tab_size; idx++) { ct_read_lock_bh(idx); list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) { if (pos-- == 0) { @@ -797,7 +812,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos) idx = l - ip_vs_conn_tab; ct_read_unlock_bh(idx); - while (++idx < IP_VS_CONN_TAB_SIZE) { + while (++idx < ip_vs_conn_tab_size) { ct_read_lock_bh(idx); list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) { seq->private = &ip_vs_conn_tab[idx]; @@ -976,8 +991,8 @@ void ip_vs_random_dropentry(void) /* * Randomly scan 1/32 of the whole table every second */ - for (idx = 0; idx < (IP_VS_CONN_TAB_SIZE>>5); idx++) { - unsigned hash = net_random() & IP_VS_CONN_TAB_MASK; + for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) { + unsigned hash = net_random() & ip_vs_conn_tab_mask; /* * Lock is actually needed in this loop. @@ -1029,7 +1044,7 @@ static void ip_vs_conn_flush(void) struct ip_vs_conn *cp; flush_again: - for (idx=0; idx Date: Thu, 24 Dec 2009 15:31:10 +0800 Subject: iwlwifi: remove linux/utsrelease.h dependency Commit 250cce26d5d03337aec4ff8405121f026adb4a89 uses UTS_RELEASE as the the in-tree iwlwifi driver version. However the inclusion of generated/utsrelease.h makes it a unpleasant behaviour to recompile the driver everytime when utsrelease.h is updated. In fact, the driver module is already built with the UTS_RELEASE information via vermagic of modinfo. Mark the in-tree driver with the version string "in-tree" to distinguish with those old out-of-tree drivers. Reported-by: David Miller Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1728f961dcba..8deb83bfe182 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -63,8 +63,6 @@ #ifndef __iwl_core_h__ #define __iwl_core_h__ -#include - /************************ * forward declarations * ************************/ @@ -72,7 +70,7 @@ struct iwl_host_cmd; struct iwl_cmd; -#define IWLWIFI_VERSION UTS_RELEASE "-k" +#define IWLWIFI_VERSION "in-tree:" #define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" #define DRV_AUTHOR "" -- cgit v1.2.3 From 29401f6630c02ce996561bf2667d84ecdfacb823 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Dec 2009 12:43:58 +0200 Subject: mac80211: No need to include WEXT headers here Remove the forgotten linux/wireless.h inclusion from mac80211. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/main.c | 1 - net/mac80211/scan.c | 1 - net/mac80211/util.c | 1 - 3 files changed, 3 deletions(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d0a14d953f08..468829143991 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 365f40975511..a4c63d4e6845 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -12,7 +12,6 @@ * published by the Free Software Foundation. */ -#include #include #include #include diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 29e1acca207c..4635d4e5af9e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 1990ca6113399be9249433d5ab377a2a444f1dd8 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 30 Dec 2009 14:42:20 +0200 Subject: mac80211: fix a warning related to pointer conversion to u64 cookie On a 32 bit system (in this case an omap 3430 system) gcc warned about pointer conversion: net/mac80211/work.c: In function 'ieee80211_remain_on_channel_timeout': net/mac80211/work.c:534: warning: cast from pointer to integer of different size net/mac80211/work.c: In function 'ieee80211_remain_done': net/mac80211/work.c:1030: warning: cast from pointer to integer of different size net/mac80211/work.c: In function 'ieee80211_wk_remain_on_channel': net/mac80211/work.c:1056: warning: cast from pointer to integer of different size net/mac80211/work.c: In function 'ieee80211_wk_cancel_remain_on_channel': net/mac80211/work.c:1072: warning: cast from pointer to integer of different size Fix it by casting the pointers to unsigned long instead. This makes the compiler happy again. Compile-tested only. Cc: Johannes Berg Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/work.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index ea89ed70734d..5ba75990c9fd 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -531,9 +531,9 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) wk->remain.started = true; wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); - cfg80211_ready_on_channel(wk->sdata->dev, (u64)wk, wk->chan, - wk->chan_type, wk->remain.duration, - GFP_KERNEL); + cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, + wk->chan, wk->chan_type, + wk->remain.duration, GFP_KERNEL); return WORK_ACT_NONE; } @@ -1027,7 +1027,7 @@ static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, /* * We are done serving the remain-on-channel command. */ - cfg80211_remain_on_channel_expired(wk->sdata->dev, (u64)wk, + cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk, wk->chan, wk->chan_type, GFP_KERNEL); @@ -1053,7 +1053,7 @@ int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, wk->remain.duration = duration; - *cookie = (u64)wk; + *cookie = (unsigned long) wk; ieee80211_add_work(wk); @@ -1069,7 +1069,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->work_mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { - if ((u64)wk == cookie) { + if ((unsigned long) wk == cookie) { wk->timeout = jiffies; found = true; break; -- cgit v1.2.3 From fc5f75773c0b3c5b44785e4efcc54c5f496211a9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 30 Dec 2009 15:54:03 +0200 Subject: mac80211: fix ieee80211_change_mac() to use struct sockaddr Setting the mac address from user space was buggy. For example, when executing this command: ip link set wlan0 address 00:1f:df:88:cd:55 mac80211 used the address 01:00:00:1f:df:88 instead. It was shifted two bytes. The reason was that the addr (type of void *) provided to ieee80211_change_mac() is actually of type struct sockaddr, not just the mac address array. Also the call to eth_mac_addr() expects the address to be struct sockaddr. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/iface.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 00a1f4ccdaf1..72189661fc49 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -63,15 +63,16 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) static int ieee80211_change_mac(struct net_device *dev, void *addr) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct sockaddr *sa = addr; int ret; if (ieee80211_sdata_running(sdata)) return -EBUSY; - ret = eth_mac_addr(dev, addr); + ret = eth_mac_addr(dev, sa); if (ret == 0) - memcpy(sdata->vif.addr, addr, ETH_ALEN); + memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN); return ret; } -- cgit v1.2.3 From 6976b665fc2b19900659b964bba3b55de08f264f Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 2 Jan 2010 10:31:50 +0100 Subject: mwl8k: update version number to 0.11 Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index c1c6ecd0c5b3..9545ff8d6422 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -26,7 +26,7 @@ #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" #define MWL8K_NAME KBUILD_MODNAME -#define MWL8K_VERSION "0.10" +#define MWL8K_VERSION "0.11" /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 -- cgit v1.2.3 From 4113f75187bfebccc54bf13c0ed09593023b53ca Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Jan 2010 11:50:11 -0500 Subject: cfg80211: add a regulatory debug print Instead of sprinkling code with ifdef's define REG_DBG_PRINT() instead. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 87ea60d84c3c..ab29a6135d22 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -43,6 +43,15 @@ #include "regdb.h" #include "nl80211.h" +#ifdef CONFIG_CFG80211_REG_DEBUG +#define REG_DBG_PRINT(args...) \ + do { \ + printk(KERN_DEBUG args); \ + } while (0) +#else +#define REG_DBG_PRINT(args) +#endif + /* Receipt of information from last regulatory request */ static struct regulatory_request *last_request; @@ -972,25 +981,21 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, if (r == -ERANGE && last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { -#ifdef CONFIG_CFG80211_REG_DEBUG - printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz " + REG_DBG_PRINT("cfg80211: Leaving channel %d MHz " "intact on %s - no rule found in band on " "Country IE\n", - chan->center_freq, wiphy_name(wiphy)); -#endif + chan->center_freq, wiphy_name(wiphy)); } else { /* * In this case we know the country IE has at least one reg rule * for the band so we respect its band definitions */ -#ifdef CONFIG_CFG80211_REG_DEBUG if (last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) - printk(KERN_DEBUG "cfg80211: Disabling " + REG_DBG_PRINT("cfg80211: Disabling " "channel %d MHz on %s due to " "Country IE\n", chan->center_freq, wiphy_name(wiphy)); -#endif flags |= IEEE80211_CHAN_DISABLED; chan->flags = flags; } @@ -1870,13 +1875,12 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, if (!reg_beacon) return -ENOMEM; -#ifdef CONFIG_CFG80211_REG_DEBUG - printk(KERN_DEBUG "cfg80211: Found new beacon on " - "frequency: %d MHz (Ch %d) on %s\n", - beacon_chan->center_freq, - ieee80211_frequency_to_channel(beacon_chan->center_freq), - wiphy_name(wiphy)); -#endif + REG_DBG_PRINT("cfg80211: Found new beacon on " + "frequency: %d MHz (Ch %d) on %s\n", + beacon_chan->center_freq, + ieee80211_frequency_to_channel(beacon_chan->center_freq), + wiphy_name(wiphy)); + memcpy(®_beacon->chan, beacon_chan, sizeof(struct ieee80211_channel)); -- cgit v1.2.3 From 91942230689c1758685499e82e53769d5e7f32eb Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:53:54 +0100 Subject: mwl8k: bail out if there is no AP firmware image support for this chip Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9545ff8d6422..bfaa7911b336 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3361,10 +3361,17 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, mwl8k_release_firmware(priv); - if (priv->ap_fw) + if (priv->ap_fw) { priv->rxd_ops = priv->device_info->ap_rxd_ops; - else + if (priv->rxd_ops == NULL) { + printk(KERN_ERR "%s: Driver does not have AP " + "firmware image support for this hardware\n", + wiphy_name(hw->wiphy)); + goto err_stop_firmware; + } + } else { priv->rxd_ops = &rxd_sta_ops; + } priv->sniffer_enabled = false; priv->wmm_enabled = false; -- cgit v1.2.3 From 153458ff7ed5949cd5b07a2355a34aad9891ad98 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:54:08 +0100 Subject: mwl8k: prevent freeing free IRQ if ieee80211_register_hw() fails Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index bfaa7911b336..2c286d18bae3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3501,7 +3501,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (rc) { printk(KERN_ERR "%s: Cannot register device\n", wiphy_name(hw->wiphy)); - goto err_free_irq; + goto err_free_queues; } printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", -- cgit v1.2.3 From 9a2303b93039d0f3dd578cd75fe20ebaf075f1cb Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:54:25 +0100 Subject: mwl8k: make the tx ring drain status messages somewhat more friendly Old: > phy0: timeout waiting for tx rings to drain (9 -> 5 pkts), retrying > phy0: timeout waiting for tx rings to drain (5 -> 2 pkts), retrying > phy0: tx rings drained New: > phy0: waiting for tx rings to drain (9 -> 5 pkts) > phy0: waiting for tx rings to drain (5 -> 2 pkts) > phy0: tx rings drained Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 2c286d18bae3..46a5cf214a20 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1269,8 +1269,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) } if (priv->pending_tx_pkts < oldcount) { - printk(KERN_NOTICE "%s: timeout waiting for tx " - "rings to drain (%d -> %d pkts), retrying\n", + printk(KERN_NOTICE "%s: waiting for tx rings " + "to drain (%d -> %d pkts)\n", wiphy_name(hw->wiphy), oldcount, priv->pending_tx_pkts); retry = 1; -- cgit v1.2.3 From 25d81b1e1a0cca41a71a08468a7d3a4c751c8565 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:54:41 +0100 Subject: mwl8k: move struct peer_capability_info to its only user Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 91 +++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 46a5cf214a20..3dbdea904833 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -598,54 +598,6 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) } -/* - * Defines shared between transmission and reception. - */ -/* HT control fields for firmware */ -struct ewc_ht_info { - __le16 control1; - __le16 control2; - __le16 control3; -} __attribute__((packed)); - -/* Firmware Station database operations */ -#define MWL8K_STA_DB_ADD_ENTRY 0 -#define MWL8K_STA_DB_MODIFY_ENTRY 1 -#define MWL8K_STA_DB_DEL_ENTRY 2 -#define MWL8K_STA_DB_FLUSH 3 - -/* Peer Entry flags - used to define the type of the peer node */ -#define MWL8K_PEER_TYPE_ACCESSPOINT 2 - -struct peer_capability_info { - /* Peer type - AP vs. STA. */ - __u8 peer_type; - - /* Basic 802.11 capabilities from assoc resp. */ - __le16 basic_caps; - - /* Set if peer supports 802.11n high throughput (HT). */ - __u8 ht_support; - - /* Valid if HT is supported. */ - __le16 ht_caps; - __u8 extended_ht_caps; - struct ewc_ht_info ewc_info; - - /* Legacy rate table. Intersection of our rates and peer rates. */ - __u8 legacy_rates[12]; - - /* HT rate table. Intersection of our rates and peer rates. */ - __u8 ht_rates[16]; - __u8 pad[16]; - - /* If set, interoperability mode, no proprietary extensions. */ - __u8 interop; - __u8 pad2; - __u8 station_id; - __le16 amsdu_enabled; -} __attribute__((packed)); - /* DMA header used by firmware and hardware. */ struct mwl8k_dma_data { __le16 fwlen; @@ -2630,6 +2582,49 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) /* * CMD_UPDATE_STADB. */ +#define MWL8K_STA_DB_ADD_ENTRY 0 +#define MWL8K_STA_DB_MODIFY_ENTRY 1 +#define MWL8K_STA_DB_DEL_ENTRY 2 +#define MWL8K_STA_DB_FLUSH 3 + +/* Peer Entry flags - used to define the type of the peer node */ +#define MWL8K_PEER_TYPE_ACCESSPOINT 2 + +struct ewc_ht_info { + __le16 control1; + __le16 control2; + __le16 control3; +} __attribute__((packed)); + +struct peer_capability_info { + /* Peer type - AP vs. STA. */ + __u8 peer_type; + + /* Basic 802.11 capabilities from assoc resp. */ + __le16 basic_caps; + + /* Set if peer supports 802.11n high throughput (HT). */ + __u8 ht_support; + + /* Valid if HT is supported. */ + __le16 ht_caps; + __u8 extended_ht_caps; + struct ewc_ht_info ewc_info; + + /* Legacy rate table. Intersection of our rates and peer rates. */ + __u8 legacy_rates[12]; + + /* HT rate table. Intersection of our rates and peer rates. */ + __u8 ht_rates[16]; + __u8 pad[16]; + + /* If set, interoperability mode, no proprietary extensions. */ + __u8 interop; + __u8 pad2; + __u8 station_id; + __le16 amsdu_enabled; +} __attribute__((packed)); + struct mwl8k_cmd_update_stadb { struct mwl8k_cmd_pkt header; -- cgit v1.2.3 From bbfd9128d3b4a80bea017ebdd47b31a80dc7eadf Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:55:12 +0100 Subject: mwl8k: handle station database update for AP's sta entry via ->sta_notify() Inserting and removing a hardware station database entry for the AP when we are in managed mode is currently done in ->bss_info_changed(). To prepare for adding AP mode support, implement the ->sta_notify() driver method, and let that handle inserting and removing the hardware station database entry for our AP instead. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 82 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 3dbdea904833..df0596ca710d 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -185,6 +185,10 @@ struct mwl8k_priv { bool sniffer_enabled; bool wmm_enabled; + struct work_struct sta_notify_worker; + spinlock_t sta_notify_list_lock; + struct list_head sta_notify_list; + /* XXX need to convert this to handle multiple interfaces */ bool capture_beacon; u8 capture_bssid[ETH_ALEN]; @@ -2641,7 +2645,7 @@ struct mwl8k_cmd_update_stadb { } __attribute__((packed)); static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, __u32 action) + struct ieee80211_vif *vif, __u32 action, u8 *addr) { struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); struct mwl8k_cmd_update_stadb *cmd; @@ -2657,7 +2661,7 @@ static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, cmd->action = cpu_to_le32(action); peer_info = &cmd->peer_info; - memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); + memcpy(cmd->peer_addr, addr, ETH_ALEN); switch (action) { case MWL8K_STA_DB_ADD_ENTRY: @@ -2978,12 +2982,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, if (rc) goto out; - /* Update peer rate info */ - rc = mwl8k_cmd_update_stadb(hw, vif, - MWL8K_STA_DB_MODIFY_ENTRY); - if (rc) - goto out; - /* Set AID */ rc = mwl8k_cmd_set_aid(hw, vif); if (rc) @@ -2996,7 +2994,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); priv->capture_beacon = true; } else { - rc = mwl8k_cmd_update_stadb(hw, vif, MWL8K_STA_DB_DEL_ENTRY); memset(mwl8k_vif->bssid, 0, ETH_ALEN); } @@ -3142,6 +3139,67 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) return mwl8k_cmd_set_rts_threshold(hw, MWL8K_CMD_SET, value); } +struct mwl8k_sta_notify_item +{ + struct list_head list; + struct ieee80211_vif *vif; + enum sta_notify_cmd cmd; + u8 addr[ETH_ALEN]; +}; + +static void mwl8k_sta_notify_worker(struct work_struct *work) +{ + struct mwl8k_priv *priv = + container_of(work, struct mwl8k_priv, sta_notify_worker); + + spin_lock_bh(&priv->sta_notify_list_lock); + while (!list_empty(&priv->sta_notify_list)) { + struct mwl8k_sta_notify_item *s; + int action; + + s = list_entry(priv->sta_notify_list.next, + struct mwl8k_sta_notify_item, list); + list_del(&s->list); + + spin_unlock_bh(&priv->sta_notify_list_lock); + + if (s->cmd == STA_NOTIFY_ADD) + action = MWL8K_STA_DB_MODIFY_ENTRY; + else + action = MWL8K_STA_DB_DEL_ENTRY; + mwl8k_cmd_update_stadb(priv->hw, s->vif, action, s->addr); + + kfree(s); + + spin_lock_bh(&priv->sta_notify_list_lock); + } + spin_unlock_bh(&priv->sta_notify_list_lock); +} + +static void +mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, struct ieee80211_sta *sta) +{ + struct mwl8k_priv *priv = hw->priv; + struct mwl8k_sta_notify_item *s; + + if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE) + return; + + s = kmalloc(sizeof(*s), GFP_ATOMIC); + if (s != NULL) { + s->vif = vif; + s->cmd = cmd; + memcpy(s->addr, sta->addr, ETH_ALEN); + + spin_lock(&priv->sta_notify_list_lock); + list_add_tail(&s->list, &priv->sta_notify_list); + spin_unlock(&priv->sta_notify_list_lock); + + ieee80211_queue_work(hw, &priv->sta_notify_worker); + } +} + static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { @@ -3201,6 +3259,7 @@ static const struct ieee80211_ops mwl8k_ops = { .prepare_multicast = mwl8k_prepare_multicast, .configure_filter = mwl8k_configure_filter, .set_rts_threshold = mwl8k_set_rts_threshold, + .sta_notify = mwl8k_sta_notify, .conf_tx = mwl8k_conf_tx, .get_tx_stats = mwl8k_get_tx_stats, .get_stats = mwl8k_get_stats, @@ -3404,6 +3463,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->radio_on = 0; priv->radio_short_preamble = 0; + /* Station database handling */ + INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker); + spin_lock_init(&priv->sta_notify_list_lock); + INIT_LIST_HEAD(&priv->sta_notify_list); + /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); -- cgit v1.2.3 From 0a11dfc36604d9b24deda17461b7ea69851846aa Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:55:21 +0100 Subject: mwl8k: remove mwl8k_vif::bssid, which is now useless Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index df0596ca710d..ed666b7e7e41 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -211,9 +211,6 @@ struct mwl8k_vif { /* Local MAC address. */ u8 mac_addr[ETH_ALEN]; - /* BSSID of AP. */ - u8 bssid[ETH_ALEN]; - /* Index into station database. Returned by UPDATE_STADB. */ u8 peer_id; @@ -2001,7 +1998,7 @@ struct mwl8k_cmd_set_post_scan { } __attribute__((packed)); static int -mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) +mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac) { struct mwl8k_cmd_set_post_scan *cmd; int rc; @@ -2077,7 +2074,6 @@ struct mwl8k_cmd_update_set_aid { static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); struct mwl8k_cmd_update_set_aid *cmd; u16 prot_mode; int rc; @@ -2090,7 +2086,7 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->aid = cpu_to_le16(vif->bss_conf.aid); - memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); + memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); if (vif->bss_conf.use_cts_prot) { prot_mode = MWL8K_FRAME_PROT_11G; @@ -2945,7 +2941,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct mwl8k_priv *priv = hw->priv; - struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); int rc; if ((changed & BSS_CHANGED_ASSOC) == 0) @@ -2958,8 +2953,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, return; if (vif->bss_conf.assoc) { - memcpy(mwl8k_vif->bssid, vif->bss_conf.bssid, ETH_ALEN); - /* Install rates */ rc = mwl8k_cmd_set_rate(hw, vif); if (rc) @@ -2991,10 +2984,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, * Finalize the join. Tell rx handler to process * next beacon from our BSSID. */ - memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); + memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN); priv->capture_beacon = true; - } else { - memset(mwl8k_vif->bssid, 0, ETH_ALEN); } out: @@ -3097,7 +3088,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, */ mwl8k_cmd_set_pre_scan(hw); } else { - u8 *bssid; + const u8 *bssid; /* * Enable the BSS filter. @@ -3109,7 +3100,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, */ bssid = "\x01\x00\x00\x00\x00\x00"; if (priv->vif != NULL) - bssid = MWL8K_VIF(priv->vif)->bssid; + bssid = priv->vif->bss_conf.bssid; mwl8k_cmd_set_post_scan(hw, bssid); } -- cgit v1.2.3 From a680400e8ac32adda81b5e2d7f23dfac63e064fe Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:55:42 +0100 Subject: mwl8k: move ->peer_id from mwl8k_vif to mwl8k_sta For STA firmware, move the per-peer hardware station ID to the driver-private part of struct ieee80211_sta, where it belongs. (Since issuing a hardware station database maintenance command sleeps, we can't hold a reference to the ieee80211_sta * across the command, and since we won't know the station ID until after the command completes, we need to re-lookup the sta when the command is done to write the returned station ID back to its driver-private part.) Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 119 ++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 52 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ed666b7e7e41..5b5cf9357dbf 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -211,15 +211,17 @@ struct mwl8k_vif { /* Local MAC address. */ u8 mac_addr[ETH_ALEN]; - /* Index into station database. Returned by UPDATE_STADB. */ - u8 peer_id; - /* Non AMPDU sequence number assigned by driver */ - u16 seqno; + u16 seqno; }; - #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) +struct mwl8k_sta { + /* Index into station database. Returned by UPDATE_STADB. */ + u8 peer_id; +}; +#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) + static const struct ieee80211_channel mwl8k_channels[] = { { .center_freq = 2412, .hw_value = 1, }, { .center_freq = 2417, .hw_value = 2, }, @@ -1402,7 +1404,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); tx->rate_info = 0; - tx->peer_id = mwl8k_vif->peer_id; + if (!priv->ap_fw && tx_info->control.sta != NULL) + tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; + else + tx->peer_id = 0; wmb(); tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); @@ -2582,14 +2587,6 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) /* * CMD_UPDATE_STADB. */ -#define MWL8K_STA_DB_ADD_ENTRY 0 -#define MWL8K_STA_DB_MODIFY_ENTRY 1 -#define MWL8K_STA_DB_DEL_ENTRY 2 -#define MWL8K_STA_DB_FLUSH 3 - -/* Peer Entry flags - used to define the type of the peer node */ -#define MWL8K_PEER_TYPE_ACCESSPOINT 2 - struct ewc_ht_info { __le16 control1; __le16 control2; @@ -2640,12 +2637,17 @@ struct mwl8k_cmd_update_stadb { struct peer_capability_info peer_info; } __attribute__((packed)); -static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, __u32 action, u8 *addr) +#define MWL8K_STA_DB_MODIFY_ENTRY 1 +#define MWL8K_STA_DB_DEL_ENTRY 2 + +/* Peer Entry flags - used to define the type of the peer node */ +#define MWL8K_PEER_TYPE_ACCESSPOINT 2 + +static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *addr) { - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); struct mwl8k_cmd_update_stadb *cmd; - struct peer_capability_info *peer_info; + struct peer_capability_info *p; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2654,37 +2656,38 @@ static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); + memcpy(cmd->peer_addr, addr, ETH_ALEN); - cmd->action = cpu_to_le32(action); - peer_info = &cmd->peer_info; + p = &cmd->peer_info; + p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; + p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); + memcpy(p->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); + p->interop = 1; + p->amsdu_enabled = 0; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc ? rc : p->station_id; +} + +static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *addr) +{ + struct mwl8k_cmd_update_stadb *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY); memcpy(cmd->peer_addr, addr, ETH_ALEN); - switch (action) { - case MWL8K_STA_DB_ADD_ENTRY: - case MWL8K_STA_DB_MODIFY_ENTRY: - /* Build peer_info block */ - peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; - peer_info->basic_caps = - cpu_to_le16(vif->bss_conf.assoc_capability); - memcpy(peer_info->legacy_rates, mwl8k_rateids, - sizeof(mwl8k_rateids)); - peer_info->interop = 1; - peer_info->amsdu_enabled = 0; - - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = peer_info->station_id; - - break; - - case MWL8K_STA_DB_DEL_ENTRY: - case MWL8K_STA_DB_FLUSH: - default: - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = 0; - break; - } + rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); return rc; @@ -3142,11 +3145,11 @@ static void mwl8k_sta_notify_worker(struct work_struct *work) { struct mwl8k_priv *priv = container_of(work, struct mwl8k_priv, sta_notify_worker); + struct ieee80211_hw *hw = priv->hw; spin_lock_bh(&priv->sta_notify_list_lock); while (!list_empty(&priv->sta_notify_list)) { struct mwl8k_sta_notify_item *s; - int action; s = list_entry(priv->sta_notify_list.next, struct mwl8k_sta_notify_item, list); @@ -3154,11 +3157,22 @@ static void mwl8k_sta_notify_worker(struct work_struct *work) spin_unlock_bh(&priv->sta_notify_list_lock); - if (s->cmd == STA_NOTIFY_ADD) - action = MWL8K_STA_DB_MODIFY_ENTRY; - else - action = MWL8K_STA_DB_DEL_ENTRY; - mwl8k_cmd_update_stadb(priv->hw, s->vif, action, s->addr); + if (s->cmd == STA_NOTIFY_ADD) { + int rc; + + rc = mwl8k_cmd_update_stadb_add(hw, s->vif, s->addr); + if (rc >= 0) { + struct ieee80211_sta *sta; + + rcu_read_lock(); + sta = ieee80211_find_sta(s->vif, s->addr); + if (sta != NULL) + MWL8K_STA(sta)->peer_id = rc; + rcu_read_unlock(); + } + } else { + mwl8k_cmd_update_stadb_del(hw, s->vif, s->addr); + } kfree(s); @@ -3448,6 +3462,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Set rssi and noise values to dBm */ hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); + hw->sta_data_size = sizeof(struct mwl8k_sta); priv->vif = NULL; /* Set default radio state and preamble */ -- cgit v1.2.3 From c6e9601071173fed2a77f9c435c41f3b33d1018f Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:55:52 +0100 Subject: mwl8k: honor peer rate set When calling SET_RATE, SET_AID, or when creating a station database entry for our AP, pass in the AP's rate set instead of just blindly enabling all legacy rates, so as to end up doing the right thing when talking to 11b-only APs. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 57 +++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 5b5cf9357dbf..d8eff68978f1 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -256,10 +256,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { { .bitrate = 720, .hw_value = 144, }, }; -static const u8 mwl8k_rateids[12] = { - 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, -}; - /* Set or get info from Firmware */ #define MWL8K_CMD_SET 0x0001 #define MWL8K_CMD_GET 0x0000 @@ -2076,8 +2072,25 @@ struct mwl8k_cmd_update_set_aid { __u8 supp_rates[14]; } __attribute__((packed)); +static void legacy_rate_mask_to_array(u8 *rates, u32 mask) +{ + int i; + int j; + + /* + * Clear nonstandard rates 4 and 13. + */ + mask &= 0x1fef; + + for (i = 0, j = 0; i < 14; i++) { + if (mask & (1 << i)) + rates[j++] = mwl8k_rates[i].hw_value; + } +} + static int -mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +mwl8k_cmd_set_aid(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u32 legacy_rate_mask) { struct mwl8k_cmd_update_set_aid *cmd; u16 prot_mode; @@ -2090,7 +2103,6 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->aid = cpu_to_le16(vif->bss_conf.aid); - memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); if (vif->bss_conf.use_cts_prot) { @@ -2111,7 +2123,7 @@ mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } cmd->protection_mode = cpu_to_le16(prot_mode); - memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); + legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2132,7 +2144,8 @@ struct mwl8k_cmd_set_rate { } __attribute__((packed)); static int -mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 legacy_rate_mask) { struct mwl8k_cmd_set_rate *cmd; int rc; @@ -2143,7 +2156,7 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); + legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2644,7 +2657,8 @@ struct mwl8k_cmd_update_stadb { #define MWL8K_PEER_TYPE_ACCESSPOINT 2 static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u8 *addr) + struct ieee80211_vif *vif, + u8 *addr, u32 legacy_rate_mask) { struct mwl8k_cmd_update_stadb *cmd; struct peer_capability_info *p; @@ -2662,7 +2676,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p = &cmd->peer_info; p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); - memcpy(p->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); + legacy_rate_mask_to_array(p->legacy_rates, legacy_rate_mask); p->interop = 1; p->amsdu_enabled = 0; @@ -2956,8 +2970,20 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, return; if (vif->bss_conf.assoc) { + struct ieee80211_sta *ap; + u32 legacy_rate_mask; + + rcu_read_lock(); + ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (ap != NULL) + legacy_rate_mask = ap->supp_rates[IEEE80211_BAND_2GHZ]; + rcu_read_unlock(); + + if (ap == NULL) + goto out; + /* Install rates */ - rc = mwl8k_cmd_set_rate(hw, vif); + rc = mwl8k_cmd_set_rate(hw, vif, legacy_rate_mask); if (rc) goto out; @@ -2979,7 +3005,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, goto out; /* Set AID */ - rc = mwl8k_cmd_set_aid(hw, vif); + rc = mwl8k_cmd_set_aid(hw, vif, legacy_rate_mask); if (rc) goto out; @@ -3139,6 +3165,7 @@ struct mwl8k_sta_notify_item struct ieee80211_vif *vif; enum sta_notify_cmd cmd; u8 addr[ETH_ALEN]; + u32 legacy_rate_mask; }; static void mwl8k_sta_notify_worker(struct work_struct *work) @@ -3160,7 +3187,8 @@ static void mwl8k_sta_notify_worker(struct work_struct *work) if (s->cmd == STA_NOTIFY_ADD) { int rc; - rc = mwl8k_cmd_update_stadb_add(hw, s->vif, s->addr); + rc = mwl8k_cmd_update_stadb_add(hw, s->vif, + s->addr, s->legacy_rate_mask); if (rc >= 0) { struct ieee80211_sta *sta; @@ -3196,6 +3224,7 @@ mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, s->vif = vif; s->cmd = cmd; memcpy(s->addr, sta->addr, ETH_ALEN); + s->legacy_rate_mask = sta->supp_rates[IEEE80211_BAND_2GHZ]; spin_lock(&priv->sta_notify_list_lock); list_add_tail(&s->list, &priv->sta_notify_list); -- cgit v1.2.3 From c3cbbe8a5cd2886e13e9c93e059d9761f3715665 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:56:07 +0100 Subject: mwl8k: fix changed flags handling in mwl8k_bss_info_changed() Previously, mwl8k_bss_info_changed() would refuse to do anything if the 'changed' argument indicated that the association status hadn't changed. Fix this up so that it will allow changing things like the preamble type, the slot time and the CTS-to-self protection method without having to reassociate. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 52 ++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d8eff68978f1..fa7b4fe074f5 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2958,57 +2958,71 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct mwl8k_priv *priv = hw->priv; + u32 ap_legacy_rates; int rc; - if ((changed & BSS_CHANGED_ASSOC) == 0) + if (mwl8k_fw_lock(hw)) return; - priv->capture_beacon = false; - - rc = mwl8k_fw_lock(hw); - if (rc) - return; + /* + * No need to capture a beacon if we're no longer associated. + */ + if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc) + priv->capture_beacon = false; + /* + * Get the AP's legacy rates. + */ + ap_legacy_rates = 0; if (vif->bss_conf.assoc) { struct ieee80211_sta *ap; - u32 legacy_rate_mask; rcu_read_lock(); - ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); - if (ap != NULL) - legacy_rate_mask = ap->supp_rates[IEEE80211_BAND_2GHZ]; - rcu_read_unlock(); - if (ap == NULL) + ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); + if (ap == NULL) { + rcu_read_unlock(); goto out; + } - /* Install rates */ - rc = mwl8k_cmd_set_rate(hw, vif, legacy_rate_mask); + ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; + + rcu_read_unlock(); + } + + if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { + rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates); if (rc) goto out; - /* Turn on rate adaptation */ rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, MWL8K_UCAST_RATE, NULL); if (rc) goto out; + } - /* Set radio preamble */ + if (changed & BSS_CHANGED_ERP_PREAMBLE) { rc = mwl8k_set_radio_preamble(hw, vif->bss_conf.use_short_preamble); if (rc) goto out; + } - /* Set slot time */ + if (changed & BSS_CHANGED_ERP_SLOT) { rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); if (rc) goto out; + } - /* Set AID */ - rc = mwl8k_cmd_set_aid(hw, vif, legacy_rate_mask); + if (((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) || + (changed & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT))) { + rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates); if (rc) goto out; + } + if (vif->bss_conf.assoc && + (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) { /* * Finalize the join. Tell rx handler to process * next beacon from our BSSID. -- cgit v1.2.3 From 9e1b17ead81e72d3db37b4cf15cde1f613603822 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:56:19 +0100 Subject: mwl8k: add support for 88w8363 in STA mode Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index fa7b4fe074f5..de74c111d967 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3344,11 +3344,17 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) } enum { - MWL8687 = 0, + MWL8363 = 0, + MWL8687, MWL8366, }; static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { + [MWL8363] = { + .part_name = "88w8363", + .helper_image = "mwl8k/helper_8363.fw", + .fw_image = "mwl8k/fmimage_8363.fw", + }, [MWL8687] = { .part_name = "88w8687", .helper_image = "mwl8k/helper_8687.fw", @@ -3363,6 +3369,8 @@ static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { }; static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { + { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, -- cgit v1.2.3 From 610677d2f0415570a7590790e8be376a946cd08b Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:56:46 +0100 Subject: mwl8k: allow setting HT channels Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index de74c111d967..2ae6c363f374 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2030,8 +2030,9 @@ struct mwl8k_cmd_set_rf_channel { } __attribute__((packed)); static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, - struct ieee80211_channel *channel) + struct ieee80211_conf *conf) { + struct ieee80211_channel *channel = conf->channel; struct mwl8k_cmd_set_rf_channel *cmd; int rc; @@ -2043,10 +2044,17 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_CMD_SET); cmd->current_channel = channel->hw_value; + if (channel->band == IEEE80211_BAND_2GHZ) - cmd->channel_flags = cpu_to_le32(0x00000081); - else - cmd->channel_flags = cpu_to_le32(0x00000000); + cmd->channel_flags |= cpu_to_le32(0x00000001); + + if (conf->channel_type == NL80211_CHAN_NO_HT || + conf->channel_type == NL80211_CHAN_HT20) + cmd->channel_flags |= cpu_to_le32(0x00000080); + else if (conf->channel_type == NL80211_CHAN_HT40MINUS) + cmd->channel_flags |= cpu_to_le32(0x000001900); + else if (conf->channel_type == NL80211_CHAN_HT40PLUS) + cmd->channel_flags |= cpu_to_le32(0x000000900); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2926,7 +2934,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (rc) goto out; - rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); + rc = mwl8k_cmd_set_rf_channel(hw, conf); if (rc) goto out; -- cgit v1.2.3 From 13935e2cf39b124c9a2ff0349b294e0b1e2e3aef Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:57:59 +0100 Subject: mwl8k: pass in HT capabilities and rates when associating Pass the AP's MCS rate mask to SET_RATE when associating, and make UPDATE_STADB pass in the peer's HT caps and rates when adding a new hardware station database entry. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 2ae6c363f374..e0301b6310f9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2153,7 +2153,7 @@ struct mwl8k_cmd_set_rate { static int mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 legacy_rate_mask) + u32 legacy_rate_mask, u8 *mcs_rates) { struct mwl8k_cmd_set_rate *cmd; int rc; @@ -2165,6 +2165,7 @@ mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif, cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask); + memcpy(cmd->mcs_set, mcs_rates, 16); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2666,7 +2667,7 @@ struct mwl8k_cmd_update_stadb { static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u8 *addr, u32 legacy_rate_mask) + struct ieee80211_sta *sta) { struct mwl8k_cmd_update_stadb *cmd; struct peer_capability_info *p; @@ -2679,12 +2680,18 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY); - memcpy(cmd->peer_addr, addr, ETH_ALEN); + memcpy(cmd->peer_addr, sta->addr, ETH_ALEN); p = &cmd->peer_info; p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability); - legacy_rate_mask_to_array(p->legacy_rates, legacy_rate_mask); + p->ht_support = sta->ht_cap.ht_supported; + p->ht_caps = sta->ht_cap.cap; + p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | + ((sta->ht_cap.ampdu_density & 7) << 2); + legacy_rate_mask_to_array(p->legacy_rates, + sta->supp_rates[IEEE80211_BAND_2GHZ]); + memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); p->interop = 1; p->amsdu_enabled = 0; @@ -2967,6 +2974,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, { struct mwl8k_priv *priv = hw->priv; u32 ap_legacy_rates; + u8 ap_mcs_rates[16]; int rc; if (mwl8k_fw_lock(hw)) @@ -2979,12 +2987,11 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, priv->capture_beacon = false; /* - * Get the AP's legacy rates. + * Get the AP's legacy and MCS rates. */ ap_legacy_rates = 0; if (vif->bss_conf.assoc) { struct ieee80211_sta *ap; - rcu_read_lock(); ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); @@ -2994,12 +3001,13 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, } ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; + memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); rcu_read_unlock(); } if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { - rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates); + rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates); if (rc) goto out; @@ -3186,8 +3194,7 @@ struct mwl8k_sta_notify_item struct list_head list; struct ieee80211_vif *vif; enum sta_notify_cmd cmd; - u8 addr[ETH_ALEN]; - u32 legacy_rate_mask; + struct ieee80211_sta sta; }; static void mwl8k_sta_notify_worker(struct work_struct *work) @@ -3209,19 +3216,18 @@ static void mwl8k_sta_notify_worker(struct work_struct *work) if (s->cmd == STA_NOTIFY_ADD) { int rc; - rc = mwl8k_cmd_update_stadb_add(hw, s->vif, - s->addr, s->legacy_rate_mask); + rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); if (rc >= 0) { struct ieee80211_sta *sta; rcu_read_lock(); - sta = ieee80211_find_sta(s->vif, s->addr); + sta = ieee80211_find_sta(s->vif, s->sta.addr); if (sta != NULL) MWL8K_STA(sta)->peer_id = rc; rcu_read_unlock(); } } else { - mwl8k_cmd_update_stadb_del(hw, s->vif, s->addr); + mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); } kfree(s); @@ -3245,8 +3251,7 @@ mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (s != NULL) { s->vif = vif; s->cmd = cmd; - memcpy(s->addr, sta->addr, ETH_ALEN); - s->legacy_rate_mask = sta->supp_rates[IEEE80211_BAND_2GHZ]; + s->sta = *sta; spin_lock(&priv->sta_notify_list_lock); list_add_tail(&s->list, &priv->sta_notify_list); -- cgit v1.2.3 From a2292d83b5dcb7f378956a124854d2b17fa53aa3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:58:12 +0100 Subject: mwl8k: trivial rx-only ampdu implementation AMPDU receive doesn't need any special handling, so let's enable this before tackling the transmit side. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index e0301b6310f9..57ced0db910a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3309,6 +3309,22 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw, return mwl8k_cmd_get_stat(hw, stats); } +static int +mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + switch (action) { + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) + return -ENOTSUPP; + return 0; + default: + return -ENOTSUPP; + } +} + static const struct ieee80211_ops mwl8k_ops = { .tx = mwl8k_tx, .start = mwl8k_start, @@ -3324,6 +3340,7 @@ static const struct ieee80211_ops mwl8k_ops = { .conf_tx = mwl8k_conf_tx, .get_tx_stats = mwl8k_get_tx_stats, .get_stats = mwl8k_get_stats, + .ampdu_action = mwl8k_ampdu_action, }; static void mwl8k_tx_reclaim_handler(unsigned long data) -- cgit v1.2.3 From 341c97918ab7e84a155ea8b18759425304d213b6 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 4 Jan 2010 21:58:40 +0100 Subject: mwl8k: pass GET_HW_SPEC capability bitmask up the stack This enables HT association and AMPDU in the receive direction for STA firmware images on hardware that supports it. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 57ced0db910a..23a5a3442623 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1578,6 +1578,68 @@ struct mwl8k_cmd_get_hw_spec_sta { __le32 total_rxd; } __attribute__((packed)); +#define MWL8K_CAP_MAX_AMSDU 0x20000000 +#define MWL8K_CAP_GREENFIELD 0x08000000 +#define MWL8K_CAP_AMPDU 0x04000000 +#define MWL8K_CAP_RX_STBC 0x01000000 +#define MWL8K_CAP_TX_STBC 0x00800000 +#define MWL8K_CAP_SHORTGI_40MHZ 0x00400000 +#define MWL8K_CAP_SHORTGI_20MHZ 0x00200000 +#define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000 +#define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000 +#define MWL8K_CAP_DELAY_BA 0x00003000 +#define MWL8K_CAP_MIMO 0x00000200 +#define MWL8K_CAP_40MHZ 0x00000100 + +static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) +{ + struct mwl8k_priv *priv = hw->priv; + int rx_streams; + int tx_streams; + + priv->band.ht_cap.ht_supported = 1; + + if (cap & MWL8K_CAP_MAX_AMSDU) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + if (cap & MWL8K_CAP_GREENFIELD) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; + if (cap & MWL8K_CAP_AMPDU) { + hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + priv->band.ht_cap.ampdu_density = + IEEE80211_HT_MPDU_DENSITY_NONE; + } + if (cap & MWL8K_CAP_RX_STBC) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; + if (cap & MWL8K_CAP_TX_STBC) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; + if (cap & MWL8K_CAP_SHORTGI_40MHZ) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + if (cap & MWL8K_CAP_SHORTGI_20MHZ) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + if (cap & MWL8K_CAP_DELAY_BA) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; + if (cap & MWL8K_CAP_40MHZ) + priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); + tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); + + priv->band.ht_cap.mcs.rx_mask[0] = 0xff; + if (rx_streams >= 2) + priv->band.ht_cap.mcs.rx_mask[1] = 0xff; + if (rx_streams >= 3) + priv->band.ht_cap.mcs.rx_mask[2] = 0xff; + priv->band.ht_cap.mcs.rx_mask[4] = 0x01; + priv->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + + if (rx_streams != tx_streams) { + priv->band.ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; + priv->band.ht_cap.mcs.tx_params |= (tx_streams - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; + } +} + static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; @@ -1608,6 +1670,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; + if (cmd->caps & cpu_to_le32(MWL8K_CAP_MIMO)) + mwl8k_set_ht_caps(hw, le32_to_cpu(cmd->caps)); } kfree(cmd); -- cgit v1.2.3 From f3f66b69c8ff08b46975d9e99c7ecb92a8b12eda Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 4 Jan 2010 00:52:56 +0100 Subject: mac80211: fix ampdu_action tx_start ssn The start_seq_num is taken from the station's tid_seq[tid]. This is fine, except tid_seq sequence counter is shifted by 4 bits to accommodate for frame fragmentation. Both (iwlagn & ath9k) were unaffected by this minor glitch, because they don't read the *ssn for the AMPDU_TX_START action. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ceda36618d3c..5aa8f4a3ed17 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -301,7 +301,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) * call back right away, it must see that the flow has begun */ *state |= HT_ADDBA_REQUESTED_MSK; - start_seq_num = sta->tid_seq[tid]; + start_seq_num = sta->tid_seq[tid] >> 4; ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, pubsta, tid, &start_seq_num); -- cgit v1.2.3 From 8271195e38d01f3551bb10b1c7de856cd8507882 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 5 Jan 2010 17:57:20 -0500 Subject: wireless: fix build breakage when CONFIG_CFG80211_REG_DEBUG not set Bad macro definition in "cfg80211: add a regulatory debug print"... Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 89c3e68a1cc6..f79d6613c5ff 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -44,12 +44,12 @@ #include "nl80211.h" #ifdef CONFIG_CFG80211_REG_DEBUG -#define REG_DBG_PRINT(args...) \ +#define REG_DBG_PRINT(format, args...) \ do { \ - printk(KERN_DEBUG args); \ + printk(KERN_DEBUG format , ## args); \ } while (0) #else -#define REG_DBG_PRINT(args) +#define REG_DBG_PRINT(args...) #endif /* Receipt of information from last regulatory request */ -- cgit v1.2.3 From c32bbff81c04096c7888aed3946ee90fdbfbc3a3 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 31 Dec 2009 00:49:43 +0000 Subject: sky2: Refactor sky2_get_regs into two functions Separate code deciding which registers can be accessed out of sky2_get_regs in preparation for adding more conditions into it. Signed-off-by: Mike McCormack Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 94 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1c01b96c9611..faa48410195e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3837,6 +3837,50 @@ static int sky2_get_regs_len(struct net_device *dev) return 0x4000; } +static int sky2_reg_access_ok(struct sky2_hw *hw, unsigned int b) +{ + /* This complicated switch statement is to make sure and + * only access regions that are unreserved. + * Some blocks are only valid on dual port cards. + */ + switch (b) { + /* second port */ + case 5: /* Tx Arbiter 2 */ + case 9: /* RX2 */ + case 14 ... 15: /* TX2 */ + case 17: case 19: /* Ram Buffer 2 */ + case 22 ... 23: /* Tx Ram Buffer 2 */ + case 25: /* Rx MAC Fifo 1 */ + case 27: /* Tx MAC Fifo 2 */ + case 31: /* GPHY 2 */ + case 40 ... 47: /* Pattern Ram 2 */ + case 52: case 54: /* TCP Segmentation 2 */ + case 112 ... 116: /* GMAC 2 */ + return hw->ports > 1; + + case 0: /* Control */ + case 2: /* Mac address */ + case 4: /* Tx Arbiter 1 */ + case 7: /* PCI express reg */ + case 8: /* RX1 */ + case 12 ... 13: /* TX1 */ + case 16: case 18:/* Rx Ram Buffer 1 */ + case 20 ... 21: /* Tx Ram Buffer 1 */ + case 24: /* Rx MAC Fifo 1 */ + case 26: /* Tx MAC Fifo 1 */ + case 28 ... 29: /* Descriptor and status unit */ + case 30: /* GPHY 1*/ + case 32 ... 39: /* Pattern Ram 1 */ + case 48: case 50: /* TCP Segmentation 1 */ + case 56 ... 60: /* PCI space */ + case 80 ... 84: /* GMAC 1 */ + return 1; + + default: + return 0; + } +} + /* * Returns copy of control register region * Note: ethtool_get_regs always provides full size (16k) buffer @@ -3851,55 +3895,13 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs->version = 1; for (b = 0; b < 128; b++) { - /* This complicated switch statement is to make sure and - * only access regions that are unreserved. - * Some blocks are only valid on dual port cards. - * and block 3 has some special diagnostic registers that - * are poison. - */ - switch (b) { - case 3: - /* skip diagnostic ram region */ + /* skip poisonous diagnostic ram region in block 3 */ + if (b == 3) memcpy_fromio(p + 0x10, io + 0x10, 128 - 0x10); - break; - - /* dual port cards only */ - case 5: /* Tx Arbiter 2 */ - case 9: /* RX2 */ - case 14 ... 15: /* TX2 */ - case 17: case 19: /* Ram Buffer 2 */ - case 22 ... 23: /* Tx Ram Buffer 2 */ - case 25: /* Rx MAC Fifo 1 */ - case 27: /* Tx MAC Fifo 2 */ - case 31: /* GPHY 2 */ - case 40 ... 47: /* Pattern Ram 2 */ - case 52: case 54: /* TCP Segmentation 2 */ - case 112 ... 116: /* GMAC 2 */ - if (sky2->hw->ports == 1) - goto reserved; - /* fall through */ - case 0: /* Control */ - case 2: /* Mac address */ - case 4: /* Tx Arbiter 1 */ - case 7: /* PCI express reg */ - case 8: /* RX1 */ - case 12 ... 13: /* TX1 */ - case 16: case 18:/* Rx Ram Buffer 1 */ - case 20 ... 21: /* Tx Ram Buffer 1 */ - case 24: /* Rx MAC Fifo 1 */ - case 26: /* Tx MAC Fifo 1 */ - case 28 ... 29: /* Descriptor and status unit */ - case 30: /* GPHY 1*/ - case 32 ... 39: /* Pattern Ram 1 */ - case 48: case 50: /* TCP Segmentation 1 */ - case 56 ... 60: /* PCI space */ - case 80 ... 84: /* GMAC 1 */ + else if (sky2_reg_access_ok(sky2->hw, b)) memcpy_fromio(p, io, 128); - break; - default: -reserved: + else memset(p, 0, 128); - } p += 128; io += 128; -- cgit v1.2.3 From c36531b9b2e00d9715c3a0f5788ac5311435e078 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 31 Dec 2009 00:55:31 +0000 Subject: sky2: Lock transmit queue while disabling device netif_device_detach() does not take the tx_lock, so it's possible that a call to sky2_xmit_frame is still in progress after netif_device_detach() is complete. Take netif_tx_lock() to make sure all transmits have stopped while we're disabling the devices and that no other CPU is still transmitting a frame after we've disabling the device. Proposed fix for "sky2 panic under load" reported by Berck E. Nash. Signed-off-by: Mike McCormack Signed-off-by: David S. Miller --- drivers/net/sky2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index faa48410195e..8ae8520baaf3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3176,7 +3176,9 @@ static void sky2_reset(struct sky2_hw *hw) static void sky2_detach(struct net_device *dev) { if (netif_running(dev)) { + netif_tx_lock(dev); netif_device_detach(dev); /* stop txq */ + netif_tx_unlock(dev); sky2_down(dev); } } -- cgit v1.2.3 From 572c526fb19a9a24098de814ab0601c1ce1bac82 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 2 Jan 2010 10:37:42 +0000 Subject: qlge: Turn on RX header split based on platform. Using 4-byte aligned headers is problematic for some architectures. Since qlge uses 4-byte aligned rx buffers we split headers for these architectures into a separate buffer and then recopy to align on 2-byte boundary. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 19 +++++++++++++++---- drivers/net/qlge/qlge_main.c | 6 +++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 862c1aaf3860..ee0e2bd4842f 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -54,12 +54,8 @@ #define RX_RING_SHADOW_SPACE (sizeof(u64) + \ MAX_DB_PAGES_PER_BQ(NUM_SMALL_BUFFERS) * sizeof(u64) + \ MAX_DB_PAGES_PER_BQ(NUM_LARGE_BUFFERS) * sizeof(u64)) -#define SMALL_BUFFER_SIZE 512 -#define SMALL_BUF_MAP_SIZE (SMALL_BUFFER_SIZE / 2) #define LARGE_BUFFER_MAX_SIZE 8192 #define LARGE_BUFFER_MIN_SIZE 2048 -#define MAX_SPLIT_SIZE 1023 -#define QLGE_SB_PAD 32 #define MAX_CQ 128 #define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */ @@ -737,6 +733,21 @@ enum { PRB_MX_DATA = 0xfc, /* Use semaphore */ }; +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +#define SMALL_BUFFER_SIZE 256 +#define SMALL_BUF_MAP_SIZE SMALL_BUFFER_SIZE +#define SPLT_SETTING FSC_DBRST_1024 +#define SPLT_LEN 0 +#define QLGE_SB_PAD 0 +#else +#define SMALL_BUFFER_SIZE 512 +#define SMALL_BUF_MAP_SIZE (SMALL_BUFFER_SIZE / 2) +#define SPLT_SETTING FSC_SH +#define SPLT_LEN (SPLT_HDR_EP | \ + min(SMALL_BUF_MAP_SIZE, 1023)) +#define QLGE_SB_PAD 32 +#endif + /* * CAM output format. */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 707b391afa02..c3034786965d 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3332,15 +3332,15 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Enable the function, set pagesize, enable error checking. */ value = FSC_FE | FSC_EPC_INBOUND | FSC_EPC_OUTBOUND | - FSC_EC | FSC_VM_PAGE_4K | FSC_SH; + FSC_EC | FSC_VM_PAGE_4K; + value |= SPLT_SETTING; /* Set/clear header splitting. */ mask = FSC_VM_PAGESIZE_MASK | FSC_DBL_MASK | FSC_DBRST_MASK | (value << 16); ql_write32(qdev, FSC, mask | value); - ql_write32(qdev, SPLT_HDR, SPLT_HDR_EP | - min(SMALL_BUF_MAP_SIZE, MAX_SPLIT_SIZE)); + ql_write32(qdev, SPLT_HDR, SPLT_LEN); /* Set RX packet routing to use port/pci function on which the * packet arrived on in addition to usual frame routing. -- cgit v1.2.3 From 4f848c0a9c265cb3457fbf842dbffd28e82a44fd Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 2 Jan 2010 10:37:43 +0000 Subject: qlge: Add RX frame handlers for non-split frames. New handlers are added here to handle: 1) Small frames (<256 bytes) in a single small buffer. Allocate a new skb and copy the frame. 2) Large frame (>256 bytes) in a page chunk. Allocate an skb, tack it on frags, post to napi_gro_receive(). Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 261 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 4 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c3034786965d..109bd0abe9b4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1433,6 +1433,209 @@ map_error: return NETDEV_TX_BUSY; } +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_page(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct net_device *ndev = qdev->ndev; + struct sk_buff *skb = NULL; + void *addr; + struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); + struct napi_struct *napi = &rx_ring->napi; + + skb = netdev_alloc_skb(ndev, length); + if (!skb) { + QPRINTK(qdev, DRV, ERR, "Couldn't get an skb, " + "need to unwind!.\n"); + rx_ring->rx_dropped++; + put_page(lbq_desc->p.pg_chunk.page); + return; + } + + addr = lbq_desc->p.pg_chunk.va; + prefetch(addr); + + + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", + ib_mac_rsp->flags2); + rx_ring->rx_errors++; + goto err_out; + } + + /* The max framesize filter on this chip is set higher than + * MTU since FCoE uses 2k frames. + */ + if (skb->len > ndev->mtu + ETH_HLEN) { + QPRINTK(qdev, DRV, ERR, "Segment too small, dropping.\n"); + rx_ring->rx_dropped++; + goto err_out; + } + memcpy(skb_put(skb, ETH_HLEN), addr, ETH_HLEN); + QPRINTK(qdev, RX_STATUS, DEBUG, + "%d bytes of headers and data in large. Chain " + "page to new skb and pull tail.\n", length); + skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, + lbq_desc->p.pg_chunk.offset+ETH_HLEN, + length-ETH_HLEN); + skb->len += length-ETH_HLEN; + skb->data_len += length-ETH_HLEN; + skb->truesize += length-ETH_HLEN; + + rx_ring->rx_packets++; + rx_ring->rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + if (qdev->rx_csum && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } + } + + skb_record_rx_queue(skb, rx_ring->cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb); + else + napi_gro_receive(napi, skb); + } else { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); + } + return; +err_out: + dev_kfree_skb_any(skb); + put_page(lbq_desc->p.pg_chunk.page); +} + +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_skb(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct net_device *ndev = qdev->ndev; + struct sk_buff *skb = NULL; + struct sk_buff *new_skb = NULL; + struct bq_desc *sbq_desc = ql_get_curr_sbuf(rx_ring); + + skb = sbq_desc->p.skb; + /* Allocate new_skb and copy */ + new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN); + if (new_skb == NULL) { + QPRINTK(qdev, PROBE, ERR, + "No skb available, drop the packet.\n"); + rx_ring->rx_dropped++; + return; + } + skb_reserve(new_skb, NET_IP_ALIGN); + memcpy(skb_put(new_skb, length), skb->data, length); + skb = new_skb; + + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", + ib_mac_rsp->flags2); + dev_kfree_skb_any(skb); + rx_ring->rx_errors++; + return; + } + + /* loopback self test for ethtool */ + if (test_bit(QL_SELFTEST, &qdev->flags)) { + ql_check_lb_frame(qdev, skb); + dev_kfree_skb_any(skb); + return; + } + + /* The max framesize filter on this chip is set higher than + * MTU since FCoE uses 2k frames. + */ + if (skb->len > ndev->mtu + ETH_HLEN) { + dev_kfree_skb_any(skb); + rx_ring->rx_dropped++; + return; + } + + prefetch(skb->data); + skb->dev = ndev; + if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { + QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + } + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) + QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); + + rx_ring->rx_packets++; + rx_ring->rx_bytes += skb->len; + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } + } + + skb_record_rx_queue(skb, rx_ring->cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, + vlan_id, skb); + else + napi_gro_receive(&rx_ring->napi, skb); + } else { + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); + } +} + static void ql_realign_skb(struct sk_buff *skb, int len) { void *temp_addr = skb->data; @@ -1646,14 +1849,13 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, } /* Process an inbound completion from an rx ring. */ -static void ql_process_mac_rx_intr(struct ql_adapter *qdev, +static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, struct rx_ring *rx_ring, - struct ib_mac_iocb_rsp *ib_mac_rsp) + struct ib_mac_iocb_rsp *ib_mac_rsp, + u16 vlan_id) { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; - u16 vlan_id = (le16_to_cpu(ib_mac_rsp->vlan_id) & - IB_MAC_IOCB_RSP_VLAN_MASK) QL_DUMP_IB_MAC_RSP(ib_mac_rsp); @@ -1753,6 +1955,57 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, } } +/* Process an inbound completion from an rx ring. */ +static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp) +{ + u32 length = le32_to_cpu(ib_mac_rsp->data_len); + u16 vlan_id = (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) ? + ((le16_to_cpu(ib_mac_rsp->vlan_id) & + IB_MAC_IOCB_RSP_VLAN_MASK)) : 0xffff; + + QL_DUMP_IB_MAC_RSP(ib_mac_rsp); + + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { + /* The data and headers are split into + * separate buffers. + */ + ql_process_mac_split_rx_intr(qdev, rx_ring, ib_mac_rsp, + vlan_id); + } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { + /* The data fit in a single small buffer. + * Allocate a new skb, copy the data and + * return the buffer to the free pool. + */ + ql_process_mac_rx_skb(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); + } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { + /* Non-TCP packet in a page chunk. Allocate an + * skb, tack it on frags, and send it up. + */ + ql_process_mac_rx_page(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); + } else { + struct bq_desc *lbq_desc; + + /* Free small buffer that holds the IAL */ + lbq_desc = ql_get_curr_sbuf(rx_ring); + QPRINTK(qdev, RX_ERR, ERR, "Dropping frame, len %d > mtu %d\n", + length, qdev->ndev->mtu); + + /* Unwind the large buffers for this frame. */ + while (length > 0) { + lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); + length -= (length < rx_ring->lbq_buf_size) ? + length : rx_ring->lbq_buf_size; + put_page(lbq_desc->p.pg_chunk.page); + } + } + + return (unsigned long)length; +} + /* Process an outbound completion from an rx ring. */ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, struct ob_mac_iocb_rsp *mac_rsp) -- cgit v1.2.3 From 635267130855e91f4681df5e4d26ca9ce908447f Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Sat, 2 Jan 2010 10:37:44 +0000 Subject: qlge: Add napi gro frags interface. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 109bd0abe9b4..e9d6481ed9eb 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1433,6 +1433,51 @@ map_error: return NETDEV_TX_BUSY; } +/* Process an inbound completion from an rx ring. */ +static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, + struct rx_ring *rx_ring, + struct ib_mac_iocb_rsp *ib_mac_rsp, + u32 length, + u16 vlan_id) +{ + struct sk_buff *skb; + struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); + struct skb_frag_struct *rx_frag; + int nr_frags; + struct napi_struct *napi = &rx_ring->napi; + + napi->dev = qdev->ndev; + + skb = napi_get_frags(napi); + if (!skb) { + QPRINTK(qdev, DRV, ERR, "Couldn't get an skb, exiting.\n"); + rx_ring->rx_dropped++; + put_page(lbq_desc->p.pg_chunk.page); + return; + } + prefetch(lbq_desc->p.pg_chunk.va); + rx_frag = skb_shinfo(skb)->frags; + nr_frags = skb_shinfo(skb)->nr_frags; + rx_frag += nr_frags; + rx_frag->page = lbq_desc->p.pg_chunk.page; + rx_frag->page_offset = lbq_desc->p.pg_chunk.offset; + rx_frag->size = length; + + skb->len += length; + skb->data_len += length; + skb->truesize += length; + skb_shinfo(skb)->nr_frags++; + + rx_ring->rx_packets++; + rx_ring->rx_bytes += length; + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(skb, rx_ring->cq_id); + if (qdev->vlgrp && (vlan_id != 0xffff)) + vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id); + else + napi_gro_frags(napi); +} + /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_page(struct ql_adapter *qdev, struct rx_ring *rx_ring, @@ -1980,6 +2025,14 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, */ ql_process_mac_rx_skb(qdev, rx_ring, ib_mac_rsp, length, vlan_id); + } else if ((ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK) && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T)) { + /* TCP packet in a page chunk that's been checksummed. + * Tack it on to our GRO skb and let it go. + */ + ql_process_mac_rx_gro_page(qdev, rx_ring, ib_mac_rsp, + length, vlan_id); } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { /* Non-TCP packet in a page chunk. Allocate an * skb, tack it on frags, and send it up. -- cgit v1.2.3 From 698244ace8b63896565022143ab19f141bc48993 Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Wed, 6 Jan 2010 20:35:14 -0800 Subject: phy: SMSC device Energy Detect power-down mode SMSC Ethernet Transceivers (LAN88710, LAN8710, LAN8720, LAN8187, LAN8700, LAN83C185) provide a mechanism to conserve power when the device is not connected to an active link partner (Energy Detect Mode). So this patch enables the Energy Detect power-down mode for these Transceivers. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 5123bb954dd7..ed2644a57500 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -25,6 +25,7 @@ #define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ #define MII_LAN83C185_IM 30 /* Interrupt Mask */ +#define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */ #define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ #define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ @@ -37,8 +38,10 @@ #define MII_LAN83C185_ISF_INT_ALL (0x0e) #define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ - (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) + (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4 | \ + MII_LAN83C185_ISF_INT7) +#define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */ static int smsc_phy_config_intr(struct phy_device *phydev) { @@ -59,9 +62,23 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev) { + int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); + if (rc < 0) + return rc; + + /* Enable energy detect mode for this SMSC Transceivers */ + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, + rc | MII_LAN83C185_EDPWRDOWN); + if (rc < 0) + return rc; + return smsc_phy_ack_interrupt (phydev); } +static int lan911x_config_init(struct phy_device *phydev) +{ + return smsc_phy_ack_interrupt(phydev); +} static struct phy_driver lan83c185_driver = { .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ @@ -147,7 +164,7 @@ static struct phy_driver lan911x_int_driver = { /* basic functions */ .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .config_init = smsc_phy_config_init, + .config_init = lan911x_config_init, /* IRQ related */ .ack_interrupt = smsc_phy_ack_interrupt, -- cgit v1.2.3 From 35076402a9936fa8a73b57a1f97fecbeceeec34a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2010 11:52:59 +0000 Subject: drivers/net/mac8390.c: Indent case labels Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index f8fa0c3f0f64..6b6f375440a2 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -164,70 +164,70 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count); static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) { switch (dev->dr_sw) { - case NUBUS_DRSW_3COM: - switch (dev->dr_hw) { - case NUBUS_DRHW_APPLE_SONIC_NB: - case NUBUS_DRHW_APPLE_SONIC_LC: - case NUBUS_DRHW_SONNET: - return MAC8390_NONE; - break; - default: - return MAC8390_APPLE; - break; - } + case NUBUS_DRSW_3COM: + switch (dev->dr_hw) { + case NUBUS_DRHW_APPLE_SONIC_NB: + case NUBUS_DRHW_APPLE_SONIC_LC: + case NUBUS_DRHW_SONNET: + return MAC8390_NONE; break; - - case NUBUS_DRSW_APPLE: - switch (dev->dr_hw) { - case NUBUS_DRHW_ASANTE_LC: - return MAC8390_NONE; - break; - case NUBUS_DRHW_CABLETRON: - return MAC8390_CABLETRON; - break; - default: - return MAC8390_APPLE; - break; - } + default: + return MAC8390_APPLE; break; + } + break; - case NUBUS_DRSW_ASANTE: - return MAC8390_ASANTE; + case NUBUS_DRSW_APPLE: + switch (dev->dr_hw) { + case NUBUS_DRHW_ASANTE_LC: + return MAC8390_NONE; break; - - case NUBUS_DRSW_TECHWORKS: - case NUBUS_DRSW_DAYNA2: - case NUBUS_DRSW_DAYNA_LC: - if (dev->dr_hw == NUBUS_DRHW_CABLETRON) - return MAC8390_CABLETRON; - else - return MAC8390_APPLE; + case NUBUS_DRHW_CABLETRON: + return MAC8390_CABLETRON; break; - - case NUBUS_DRSW_FARALLON: - return MAC8390_FARALLON; + default: + return MAC8390_APPLE; break; + } + break; - case NUBUS_DRSW_KINETICS: - switch (dev->dr_hw) { - case NUBUS_DRHW_INTERLAN: - return MAC8390_INTERLAN; - break; - default: - return MAC8390_KINETICS; - break; - } - break; + case NUBUS_DRSW_ASANTE: + return MAC8390_ASANTE; + break; + + case NUBUS_DRSW_TECHWORKS: + case NUBUS_DRSW_DAYNA2: + case NUBUS_DRSW_DAYNA_LC: + if (dev->dr_hw == NUBUS_DRHW_CABLETRON) + return MAC8390_CABLETRON; + else + return MAC8390_APPLE; + break; + + case NUBUS_DRSW_FARALLON: + return MAC8390_FARALLON; + break; - case NUBUS_DRSW_DAYNA: - // These correspond to Dayna Sonic cards - // which use the macsonic driver - if (dev->dr_hw == NUBUS_DRHW_SMC9194 || - dev->dr_hw == NUBUS_DRHW_INTERLAN ) - return MAC8390_NONE; - else - return MAC8390_DAYNA; + case NUBUS_DRSW_KINETICS: + switch (dev->dr_hw) { + case NUBUS_DRHW_INTERLAN: + return MAC8390_INTERLAN; break; + default: + return MAC8390_KINETICS; + break; + } + break; + + case NUBUS_DRSW_DAYNA: + // These correspond to Dayna Sonic cards + // which use the macsonic driver + if (dev->dr_hw == NUBUS_DRHW_SMC9194 || + dev->dr_hw == NUBUS_DRHW_INTERLAN ) + return MAC8390_NONE; + else + return MAC8390_DAYNA; + break; } return MAC8390_NONE; } @@ -373,54 +373,54 @@ struct net_device * __init mac8390_probe(int unit) dev->mem_end = dev->mem_start + offset; } else { switch (cardtype) { - case MAC8390_KINETICS: - case MAC8390_DAYNA: /* it's the same */ - dev->base_addr = - (int)(ndev->board->slot_addr + - DAYNA_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - DAYNA_8390_MEM); - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - case MAC8390_INTERLAN: - dev->base_addr = - (int)(ndev->board->slot_addr + - INTERLAN_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - INTERLAN_8390_MEM); - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - case MAC8390_CABLETRON: - dev->base_addr = - (int)(ndev->board->slot_addr + - CABLETRON_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - CABLETRON_8390_MEM); - /* The base address is unreadable if 0x00 - * has been written to the command register - * Reset the chip by writing E8390_NODMA + - * E8390_PAGE0 + E8390_STOP just to be - * sure - */ - i = (void *)dev->base_addr; - *i = 0x21; - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - - default: - printk(KERN_ERR "Card type %s is" - " unsupported, sorry\n", - ndev->board->name); - continue; + case MAC8390_KINETICS: + case MAC8390_DAYNA: /* it's the same */ + dev->base_addr = + (int)(ndev->board->slot_addr + + DAYNA_8390_BASE); + dev->mem_start = + (int)(ndev->board->slot_addr + + DAYNA_8390_MEM); + dev->mem_end = + dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + case MAC8390_INTERLAN: + dev->base_addr = + (int)(ndev->board->slot_addr + + INTERLAN_8390_BASE); + dev->mem_start = + (int)(ndev->board->slot_addr + + INTERLAN_8390_MEM); + dev->mem_end = + dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + case MAC8390_CABLETRON: + dev->base_addr = + (int)(ndev->board->slot_addr + + CABLETRON_8390_BASE); + dev->mem_start = + (int)(ndev->board->slot_addr + + CABLETRON_8390_MEM); + /* The base address is unreadable if 0x00 + * has been written to the command register + * Reset the chip by writing E8390_NODMA + + * E8390_PAGE0 + E8390_STOP just to be + * sure + */ + i = (void *)dev->base_addr; + *i = 0x21; + dev->mem_end = + dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + + default: + printk(KERN_ERR "Card type %s is" + " unsupported, sorry\n", + ndev->board->name); + continue; } } @@ -540,33 +540,33 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd } /* Fill in model-specific information and functions */ - switch(type) { + switch (type) { case MAC8390_FARALLON: case MAC8390_APPLE: - switch(mac8390_testio(dev->mem_start)) { - case ACCESS_UNKNOWN: - printk("Don't know how to access card memory!\n"); - return -ENODEV; - break; + switch (mac8390_testio(dev->mem_start)) { + case ACCESS_UNKNOWN: + printk("Don't know how to access card memory!\n"); + return -ENODEV; + break; - case ACCESS_16: - /* 16 bit card, register map is reversed */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &slow_sane_block_input; - ei_status.block_output = &slow_sane_block_output; - ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; - ei_status.reg_offset = back4_offsets; - break; + case ACCESS_16: + /* 16 bit card, register map is reversed */ + ei_status.reset_8390 = &mac8390_no_reset; + ei_status.block_input = &slow_sane_block_input; + ei_status.block_output = &slow_sane_block_output; + ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; + ei_status.reg_offset = back4_offsets; + break; - case ACCESS_32: - /* 32 bit card, register map is reversed */ - ei_status.reset_8390 = &mac8390_no_reset; - ei_status.block_input = &sane_block_input; - ei_status.block_output = &sane_block_output; - ei_status.get_8390_hdr = &sane_get_8390_hdr; - ei_status.reg_offset = back4_offsets; - access_bitmode = 1; - break; + case ACCESS_32: + /* 32 bit card, register map is reversed */ + ei_status.reset_8390 = &mac8390_no_reset; + ei_status.block_input = &sane_block_input; + ei_status.block_output = &sane_block_output; + ei_status.get_8390_hdr = &sane_get_8390_hdr; + ei_status.reg_offset = back4_offsets; + access_bitmode = 1; + break; } break; -- cgit v1.2.3 From 5c7fffd0e3b57cb63f50bbd710868f012d67654f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2010 11:53:00 +0000 Subject: drivers/net/mac8390.c: Remove useless memcpy casting Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 6b6f375440a2..517cee45c086 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -237,14 +237,14 @@ static enum mac8390_access __init mac8390_testio(volatile unsigned long membase) unsigned long outdata = 0xA5A0B5B0; unsigned long indata = 0x00000000; /* Try writing 32 bits */ - memcpy((char *)membase, (char *)&outdata, 4); + memcpy(membase, &outdata, 4); /* Now compare them */ if (memcmp((char *)&outdata, (char *)membase, 4) == 0) return ACCESS_32; /* Write 16 bit output */ - word_memcpy_tocard((char *)membase, (char *)&outdata, 4); + word_memcpy_tocard(membase, &outdata, 4); /* Now read it back */ - word_memcpy_fromcard((char *)&indata, (char *)membase, 4); + word_memcpy_fromcard(&indata, membase, 4); if (outdata == indata) return ACCESS_16; return ACCESS_UNKNOWN; @@ -759,7 +759,7 @@ static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; - dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4); + dayna_memcpy_fromcard(dev, hdr, hdr_start, 4); /* Fix endianness */ hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8); } @@ -801,7 +801,7 @@ static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr int ring_page) { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; - word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4); + word_memcpy_fromcard(hdr, (char *)dev->mem_start + hdr_start, 4); /* Register endianism - fix here rather than 8390.c */ hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8); } @@ -816,16 +816,17 @@ static void slow_sane_block_input(struct net_device *dev, int count, struct sk_b { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; - word_memcpy_fromcard(skb->data, (char *)dev->mem_start + - xfer_base, semi_count); + word_memcpy_fromcard(skb->data, + (char *)dev->mem_start + xfer_base, + semi_count); count -= semi_count; word_memcpy_fromcard(skb->data + semi_count, (char *)ei_status.rmem_start, count); } else { - word_memcpy_fromcard(skb->data, (char *)dev->mem_start + - xfer_base, count); + word_memcpy_fromcard(skb->data, + (char *)dev->mem_start + xfer_base, count); } } -- cgit v1.2.3 From 18c0019102228875cb0f6f252dad5148491e96b2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2010 11:53:01 +0000 Subject: drivers/net/mac8390.c: Convert printk(KERN_ to pr_( Use printk_once Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Convert printks without KERN_ to pr_info and pr_cont Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 57 ++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 517cee45c086..8bd09e280c9e 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -17,6 +17,8 @@ /* 2002-12-30: Try to support more cards, some clues from NetBSD driver */ /* 2003-12-26: Make sure Asante cards always work. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -42,7 +44,7 @@ #include static char version[] = - "mac8390.c: v0.4 2001-05-15 David Huggins-Daines and others\n"; + "v0.4 2001-05-15 David Huggins-Daines and others\n"; #define EI_SHIFT(x) (ei_local->reg_offset[x]) #define ei_inb(port) in_8(port) @@ -288,7 +290,6 @@ struct net_device * __init mac8390_probe(int unit) { struct net_device *dev; volatile unsigned short *i; - int version_disp = 0; struct nubus_dev * ndev = NULL; int err = -ENODEV; @@ -320,10 +321,7 @@ struct net_device * __init mac8390_probe(int unit) if ((cardtype = mac8390_ident(ndev)) == MAC8390_NONE) continue; - if (version_disp == 0) { - version_disp = 1; - printk(version); - } + printk_once(KERN_INFO pr_fmt(version)); dev->irq = SLOT2IRQ(ndev->board->slot); /* This is getting to be a habit */ @@ -333,16 +331,14 @@ struct net_device * __init mac8390_probe(int unit) of where its memory and registers are. */ if (nubus_get_func_dir(ndev, &dir) == -1) { - printk(KERN_ERR "%s: Unable to get Nubus functional" - " directory for slot %X!\n", + pr_err("%s: Unable to get Nubus functional directory for slot %X!\n", dev->name, ndev->board->slot); continue; } /* Get the MAC address */ if ((nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent)) == -1) { - printk(KERN_INFO "%s: Couldn't get MAC address!\n", - dev->name); + pr_info("%s: Couldn't get MAC address!\n", dev->name); continue; } else { nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); @@ -351,8 +347,7 @@ struct net_device * __init mac8390_probe(int unit) if (useresources[cardtype] == 1) { nubus_rewinddir(&dir); if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, &ent) == -1) { - printk(KERN_ERR "%s: Memory offset resource" - " for slot %X not found!\n", + pr_err("%s: Memory offset resource for slot %X not found!\n", dev->name, ndev->board->slot); continue; } @@ -362,10 +357,8 @@ struct net_device * __init mac8390_probe(int unit) dev->base_addr = dev->mem_start + 0x10000; nubus_rewinddir(&dir); if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, &ent) == -1) { - printk(KERN_INFO "%s: Memory length resource" - " for slot %X not found" - ", probing\n", - dev->name, ndev->board->slot); + pr_info("%s: Memory length resource for slot %X not found, probing\n", + dev->name, ndev->board->slot); offset = mac8390_memsize(dev->mem_start); } else { nubus_get_rsrc_mem(&offset, &ent, 4); @@ -417,8 +410,7 @@ struct net_device * __init mac8390_probe(int unit) break; default: - printk(KERN_ERR "Card type %s is" - " unsupported, sorry\n", + pr_err("Card type %s is unsupported, sorry\n", ndev->board->name); continue; } @@ -458,7 +450,7 @@ int init_module(void) dev_mac890[i] = dev; } if (!i) { - printk(KERN_NOTICE "mac8390.c: No useable cards found, driver NOT installed.\n"); + pr_notice("No useable cards found, driver NOT installed.\n"); return -ENODEV; } return 0; @@ -545,7 +537,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd case MAC8390_APPLE: switch (mac8390_testio(dev->mem_start)) { case ACCESS_UNKNOWN: - printk("Don't know how to access card memory!\n"); + pr_info("Don't know how to access card memory!\n"); return -ENODEV; break; @@ -612,20 +604,21 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd break; default: - printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name); + pr_err("Card type %s is unsupported, sorry\n", + ndev->board->name); return -ENODEV; } __NS8390_init(dev, 0); /* Good, done, now spit out some messages */ - printk(KERN_INFO "%s: %s in slot %X (type %s)\n", - dev->name, ndev->board->name, ndev->board->slot, cardname[type]); - printk(KERN_INFO - "MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", - dev->dev_addr, dev->irq, - (unsigned int)(dev->mem_end - dev->mem_start) >> 10, - dev->mem_start, access_bitmode ? 32 : 16); + pr_info("%s: %s in slot %X (type %s)\n", + dev->name, ndev->board->name, ndev->board->slot, + cardname[type]); + pr_info("MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", + dev->dev_addr, dev->irq, + (unsigned int)(dev->mem_end - dev->mem_start) >> 10, + dev->mem_start, access_bitmode ? 32 : 16); return 0; } @@ -633,7 +626,7 @@ static int mac8390_open(struct net_device *dev) { __ei_open(dev); if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) { - printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq); + pr_info("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } return 0; @@ -650,7 +643,7 @@ static void mac8390_no_reset(struct net_device *dev) { ei_status.txing = 0; if (ei_debug > 1) - printk("reset not supported\n"); + pr_info("reset not supported\n"); return; } @@ -658,11 +651,11 @@ static void interlan_reset(struct net_device *dev) { unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq)); if (ei_debug > 1) - printk("Need to reset the NS8390 t=%lu...", jiffies); + pr_info("Need to reset the NS8390 t=%lu...", jiffies); ei_status.txing = 0; target[0xC0000] = 0; if (ei_debug > 1) - printk("reset complete\n"); + pr_cont("reset complete\n"); return; } -- cgit v1.2.3 From 8e4d9696b45d966c7af5b2aeb6f98ff687c58964 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2010 11:53:02 +0000 Subject: drivers/net/mac8390.c: Checkpatch cleanups Use #include Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 229 +++++++++++++++++++++++++++----------------------- 1 file changed, 122 insertions(+), 107 deletions(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 8bd09e280c9e..8f168893caa9 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -36,9 +36,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -47,20 +47,25 @@ static char version[] = "v0.4 2001-05-15 David Huggins-Daines and others\n"; #define EI_SHIFT(x) (ei_local->reg_offset[x]) -#define ei_inb(port) in_8(port) -#define ei_outb(val,port) out_8(port,val) -#define ei_inb_p(port) in_8(port) -#define ei_outb_p(val,port) out_8(port,val) +#define ei_inb(port) in_8(port) +#define ei_outb(val, port) out_8(port, val) +#define ei_inb_p(port) in_8(port) +#define ei_outb_p(val, port) out_8(port, val) #include "lib8390.c" #define WD_START_PG 0x00 /* First page of TX buffer */ #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ #define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */ -#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG /* First page of TX buffer */ +#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG + /* First page of TX buffer */ -/* Unfortunately it seems we have to hardcode these for the moment */ -/* Shouldn't the card know about this? Does anyone know where to read it off the card? Do we trust the data provided by the card? */ +/* + * Unfortunately it seems we have to hardcode these for the moment + * Shouldn't the card know about this? + * Does anyone know where to read it off the card? + * Do we trust the data provided by the card? + */ #define DAYNA_8390_BASE 0x80000 #define DAYNA_8390_MEM 0x00000 @@ -82,7 +87,7 @@ enum mac8390_type { MAC8390_KINETICS, }; -static const char * cardname[] = { +static const char *cardname[] = { "apple", "asante", "farallon", @@ -92,7 +97,7 @@ static const char * cardname[] = { "kinetics", }; -static int word16[] = { +static const int word16[] = { 1, /* apple */ 1, /* asante */ 1, /* farallon */ @@ -103,7 +108,7 @@ static int word16[] = { }; /* on which cards do we use NuBus resources? */ -static int useresources[] = { +static const int useresources[] = { 1, /* apple */ 1, /* asante */ 1, /* farallon */ @@ -119,22 +124,22 @@ enum mac8390_access { ACCESS_16, }; -extern int mac8390_memtest(struct net_device * dev); -static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, +extern int mac8390_memtest(struct net_device *dev); +static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev, enum mac8390_type type); -static int mac8390_open(struct net_device * dev); -static int mac8390_close(struct net_device * dev); +static int mac8390_open(struct net_device *dev); +static int mac8390_close(struct net_device *dev); static void mac8390_no_reset(struct net_device *dev); static void interlan_reset(struct net_device *dev); /* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/ static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page); -static void sane_block_input(struct net_device * dev, int count, - struct sk_buff * skb, int ring_offset); -static void sane_block_output(struct net_device * dev, int count, - const unsigned char * buf, const int start_page); +static void sane_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void sane_block_output(struct net_device *dev, int count, + const unsigned char *buf, const int start_page); /* dayna_memcpy to and from card */ static void dayna_memcpy_fromcard(struct net_device *dev, void *to, @@ -150,8 +155,8 @@ static void dayna_block_input(struct net_device *dev, int count, static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); -#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c)) -#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c)) +#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c)) +#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c)) /* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */ static void slow_sane_get_8390_hdr(struct net_device *dev, @@ -222,10 +227,12 @@ static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev) break; case NUBUS_DRSW_DAYNA: - // These correspond to Dayna Sonic cards - // which use the macsonic driver + /* + * These correspond to Dayna Sonic cards + * which use the macsonic driver + */ if (dev->dr_hw == NUBUS_DRHW_SMC9194 || - dev->dr_hw == NUBUS_DRHW_INTERLAN ) + dev->dr_hw == NUBUS_DRHW_INTERLAN) return MAC8390_NONE; else return MAC8390_DAYNA; @@ -260,7 +267,7 @@ static int __init mac8390_memsize(unsigned long membase) local_irq_save(flags); /* Check up to 32K in 4K increments */ for (i = 0; i < 8; i++) { - volatile unsigned short *m = (unsigned short *) (membase + (i * 0x1000)); + volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000)); /* Unwriteable - we have a fully decoded card and the RAM end located */ @@ -275,22 +282,24 @@ static int __init mac8390_memsize(unsigned long membase) /* check for partial decode and wrap */ for (j = 0; j < i; j++) { - volatile unsigned short *p = (unsigned short *) (membase + (j * 0x1000)); + volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000)); if (*p != (0xA5A0 | j)) break; - } - } + } + } local_irq_restore(flags); - /* in any case, we stopped once we tried one block too many, - or once we reached 32K */ - return i * 0x1000; + /* + * in any case, we stopped once we tried one block too many, + * or once we reached 32K + */ + return i * 0x1000; } struct net_device * __init mac8390_probe(int unit) { struct net_device *dev; volatile unsigned short *i; - struct nubus_dev * ndev = NULL; + struct nubus_dev *ndev = NULL; int err = -ENODEV; struct nubus_dir dir; @@ -312,20 +321,23 @@ struct net_device * __init mac8390_probe(int unit) if (unit >= 0) sprintf(dev->name, "eth%d", unit); - while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, ndev))) { + while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, + ndev))) { /* Have we seen it already? */ if (slots & (1<board->slot)) continue; slots |= 1<board->slot; - if ((cardtype = mac8390_ident(ndev)) == MAC8390_NONE) + cardtype = mac8390_ident(ndev); + if (cardtype == MAC8390_NONE) continue; printk_once(KERN_INFO pr_fmt(version)); dev->irq = SLOT2IRQ(ndev->board->slot); /* This is getting to be a habit */ - dev->base_addr = ndev->board->slot_addr | ((ndev->board->slot&0xf) << 20); + dev->base_addr = (ndev->board->slot_addr | + ((ndev->board->slot & 0xf) << 20)); /* Get some Nubus info - we will trust the card's idea of where its memory and registers are. */ @@ -337,7 +349,7 @@ struct net_device * __init mac8390_probe(int unit) } /* Get the MAC address */ - if ((nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent)) == -1) { + if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) { pr_info("%s: Couldn't get MAC address!\n", dev->name); continue; } else { @@ -346,7 +358,8 @@ struct net_device * __init mac8390_probe(int unit) if (useresources[cardtype] == 1) { nubus_rewinddir(&dir); - if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, &ent) == -1) { + if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, + &ent) == -1) { pr_err("%s: Memory offset resource for slot %X not found!\n", dev->name, ndev->board->slot); continue; @@ -356,7 +369,8 @@ struct net_device * __init mac8390_probe(int unit) /* yes, this is how the Apple driver does it */ dev->base_addr = dev->mem_start + 0x10000; nubus_rewinddir(&dir); - if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, &ent) == -1) { + if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, + &ent) == -1) { pr_info("%s: Memory length resource for slot %X not found, probing\n", dev->name, ndev->board->slot); offset = mac8390_memsize(dev->mem_start); @@ -485,22 +499,23 @@ static const struct net_device_ops mac8390_netdev_ops = { #endif }; -static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, - enum mac8390_type type) +static int __init mac8390_initdev(struct net_device *dev, + struct nubus_dev *ndev, + enum mac8390_type type) { - static u32 fwrd4_offsets[16]={ + static u32 fwrd4_offsets[16] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 }; - static u32 back4_offsets[16]={ + static u32 back4_offsets[16] = { 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0 }; - static u32 fwrd2_offsets[16]={ + static u32 fwrd2_offsets[16] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, @@ -518,17 +533,17 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd /* Cabletron's TX/RX buffers are backwards */ if (type == MAC8390_CABLETRON) { - ei_status.tx_start_page = CABLETRON_TX_START_PG; - ei_status.rx_start_page = CABLETRON_RX_START_PG; - ei_status.stop_page = CABLETRON_RX_STOP_PG; - ei_status.rmem_start = dev->mem_start; - ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256; + ei_status.tx_start_page = CABLETRON_TX_START_PG; + ei_status.rx_start_page = CABLETRON_RX_START_PG; + ei_status.stop_page = CABLETRON_RX_STOP_PG; + ei_status.rmem_start = dev->mem_start; + ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256; } else { - ei_status.tx_start_page = WD_START_PG; - ei_status.rx_start_page = WD_START_PG + TX_PAGES; - ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; - ei_status.rmem_start = dev->mem_start + TX_PAGES*256; - ei_status.rmem_end = dev->mem_end; + ei_status.tx_start_page = WD_START_PG; + ei_status.rx_start_page = WD_START_PG + TX_PAGES; + ei_status.stop_page = (dev->mem_end - dev->mem_start)/256; + ei_status.rmem_start = dev->mem_start + TX_PAGES*256; + ei_status.rmem_end = dev->mem_end; } /* Fill in model-specific information and functions */ @@ -600,8 +615,8 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd ei_status.block_input = &slow_sane_block_input; ei_status.block_output = &slow_sane_block_output; ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; - ei_status.reg_offset = fwrd4_offsets; - break; + ei_status.reg_offset = fwrd4_offsets; + break; default: pr_err("Card type %s is unsupported, sorry\n", @@ -649,7 +664,7 @@ static void mac8390_no_reset(struct net_device *dev) static void interlan_reset(struct net_device *dev) { - unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq)); + unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq)); if (ei_debug > 1) pr_info("Need to reset the NS8390 t=%lu...", jiffies); ei_status.txing = 0; @@ -661,54 +676,53 @@ static void interlan_reset(struct net_device *dev) /* dayna_memcpy_fromio/dayna_memcpy_toio */ /* directly from daynaport.c by Alan Cox */ -static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) +static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, + int count) { volatile unsigned char *ptr; - unsigned char *target=to; - from<<=1; /* word, skip overhead */ - ptr=(unsigned char *)(dev->mem_start+from); + unsigned char *target = to; + from <<= 1; /* word, skip overhead */ + ptr = (unsigned char *)(dev->mem_start+from); /* Leading byte? */ - if (from&2) { + if (from & 2) { *target++ = ptr[-1]; ptr += 2; count--; } - while(count>=2) - { + while (count >= 2) { *(unsigned short *)target = *(unsigned short volatile *)ptr; ptr += 4; /* skip cruft */ target += 2; - count-=2; + count -= 2; } /* Trailing byte? */ - if(count) + if (count) *target = *ptr; } -static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count) +static void dayna_memcpy_tocard(struct net_device *dev, int to, + const void *from, int count) { volatile unsigned short *ptr; - const unsigned char *src=from; - to<<=1; /* word, skip overhead */ - ptr=(unsigned short *)(dev->mem_start+to); + const unsigned char *src = from; + to <<= 1; /* word, skip overhead */ + ptr = (unsigned short *)(dev->mem_start+to); /* Leading byte? */ - if (to&2) { /* avoid a byte write (stomps on other data) */ + if (to & 2) { /* avoid a byte write (stomps on other data) */ ptr[-1] = (ptr[-1]&0xFF00)|*src++; ptr++; count--; } - while(count>=2) - { - *ptr++=*(unsigned short *)src; /* Copy and */ + while (count >= 2) { + *ptr++ = *(unsigned short *)src; /* Copy and */ ptr++; /* skip cruft */ src += 2; - count-=2; + count -= 2; } /* Trailing byte? */ - if(count) - { + if (count) { /* card doesn't like byte writes */ - *ptr=(*ptr&0x00FF)|(*src << 8); + *ptr = (*ptr & 0x00FF) | (*src << 8); } } @@ -731,11 +745,14 @@ static void sane_block_input(struct net_device *dev, int count, if (xfer_start + count > ei_status.rmem_end) { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; - memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, semi_count); + memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, + semi_count); count -= semi_count; - memcpy_toio(skb->data + semi_count, (char *)ei_status.rmem_start, count); + memcpy_toio(skb->data + semi_count, + (char *)ei_status.rmem_start, count); } else { - memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, count); + memcpy_fromio(skb->data, (char *)dev->mem_start + xfer_base, + count); } } @@ -748,16 +765,18 @@ static void sane_block_output(struct net_device *dev, int count, } /* dayna block input/output */ -static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) +static void dayna_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, int ring_page) { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; dayna_memcpy_fromcard(dev, hdr, hdr_start, 4); /* Fix endianness */ - hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8); + hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8); } -static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) +static void dayna_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { unsigned long xfer_base = ring_offset - (WD_START_PG<<8); unsigned long xfer_start = xfer_base+dev->mem_start; @@ -765,8 +784,7 @@ static void dayna_block_input(struct net_device *dev, int count, struct sk_buff /* Note the offset math is done in card memory space which is word per long onto our space. */ - if (xfer_start + count > ei_status.rmem_end) - { + if (xfer_start + count > ei_status.rmem_end) { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count); @@ -774,15 +792,14 @@ static void dayna_block_input(struct net_device *dev, int count, struct sk_buff dayna_memcpy_fromcard(dev, skb->data + semi_count, ei_status.rmem_start - dev->mem_start, count); - } - else - { + } else { dayna_memcpy_fromcard(dev, skb->data, xfer_base, count); } } -static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf, - int start_page) +static void dayna_block_output(struct net_device *dev, int count, + const unsigned char *buf, + int start_page) { long shmem = (start_page - WD_START_PG)<<8; @@ -790,8 +807,9 @@ static void dayna_block_output(struct net_device *dev, int count, const unsigned } /* Cabletron block I/O */ -static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, - int ring_page) +static void slow_sane_get_8390_hdr(struct net_device *dev, + struct e8390_pkt_hdr *hdr, + int ring_page) { unsigned long hdr_start = (ring_page - WD_START_PG)<<8; word_memcpy_fromcard(hdr, (char *)dev->mem_start + hdr_start, 4); @@ -799,14 +817,13 @@ static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8); } -static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, - int ring_offset) +static void slow_sane_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { unsigned long xfer_base = ring_offset - (WD_START_PG<<8); unsigned long xfer_start = xfer_base+dev->mem_start; - if (xfer_start + count > ei_status.rmem_end) - { + if (xfer_start + count > ei_status.rmem_end) { /* We must wrap the input move. */ int semi_count = ei_status.rmem_end - xfer_start; word_memcpy_fromcard(skb->data, @@ -815,16 +832,14 @@ static void slow_sane_block_input(struct net_device *dev, int count, struct sk_b count -= semi_count; word_memcpy_fromcard(skb->data + semi_count, (char *)ei_status.rmem_start, count); - } - else - { + } else { word_memcpy_fromcard(skb->data, (char *)dev->mem_start + xfer_base, count); } } -static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf, - int start_page) +static void slow_sane_block_output(struct net_device *dev, int count, + const unsigned char *buf, int start_page) { long shmem = (start_page - WD_START_PG)<<8; @@ -837,10 +852,10 @@ static void word_memcpy_tocard(void *tp, const void *fp, int count) const unsigned short *from = fp; count++; - count/=2; + count /= 2; - while(count--) - *to++=*from++; + while (count--) + *to++ = *from++; } static void word_memcpy_fromcard(void *tp, const void *fp, int count) @@ -849,10 +864,10 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count) const volatile unsigned short *from = fp; count++; - count/=2; + count /= 2; - while(count--) - *to++=*from++; + while (count--) + *to++ = *from++; } -- cgit v1.2.3 From f6de7acc42de909ccc7f00916ddb4d2064f42b67 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 4 Jan 2010 11:53:03 +0000 Subject: drivers/net/mac8390.c: Add mac8390_init function Reduce indentation, make code a little neater. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 207 +++++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 102 deletions(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index 8f168893caa9..c70bd6888c89 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -295,16 +295,114 @@ static int __init mac8390_memsize(unsigned long membase) return i * 0x1000; } +static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev, + enum mac8390_type cardtype) +{ + struct nubus_dir dir; + struct nubus_dirent ent; + int offset; + volatile unsigned short *i; + + printk_once(KERN_INFO pr_fmt(version)); + + dev->irq = SLOT2IRQ(ndev->board->slot); + /* This is getting to be a habit */ + dev->base_addr = (ndev->board->slot_addr | + ((ndev->board->slot & 0xf) << 20)); + + /* + * Get some Nubus info - we will trust the card's idea + * of where its memory and registers are. + */ + + if (nubus_get_func_dir(ndev, &dir) == -1) { + pr_err("%s: Unable to get Nubus functional directory for slot %X!\n", + dev->name, ndev->board->slot); + return false; + } + + /* Get the MAC address */ + if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) { + pr_info("%s: Couldn't get MAC address!\n", dev->name); + return false; + } + + nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); + + if (useresources[cardtype] == 1) { + nubus_rewinddir(&dir); + if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, + &ent) == -1) { + pr_err("%s: Memory offset resource for slot %X not found!\n", + dev->name, ndev->board->slot); + return false; + } + nubus_get_rsrc_mem(&offset, &ent, 4); + dev->mem_start = dev->base_addr + offset; + /* yes, this is how the Apple driver does it */ + dev->base_addr = dev->mem_start + 0x10000; + nubus_rewinddir(&dir); + if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, + &ent) == -1) { + pr_info("%s: Memory length resource for slot %X not found, probing\n", + dev->name, ndev->board->slot); + offset = mac8390_memsize(dev->mem_start); + } else { + nubus_get_rsrc_mem(&offset, &ent, 4); + } + dev->mem_end = dev->mem_start + offset; + } else { + switch (cardtype) { + case MAC8390_KINETICS: + case MAC8390_DAYNA: /* it's the same */ + dev->base_addr = (int)(ndev->board->slot_addr + + DAYNA_8390_BASE); + dev->mem_start = (int)(ndev->board->slot_addr + + DAYNA_8390_MEM); + dev->mem_end = dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + case MAC8390_INTERLAN: + dev->base_addr = (int)(ndev->board->slot_addr + + INTERLAN_8390_BASE); + dev->mem_start = (int)(ndev->board->slot_addr + + INTERLAN_8390_MEM); + dev->mem_end = dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + case MAC8390_CABLETRON: + dev->base_addr = (int)(ndev->board->slot_addr + + CABLETRON_8390_BASE); + dev->mem_start = (int)(ndev->board->slot_addr + + CABLETRON_8390_MEM); + /* The base address is unreadable if 0x00 + * has been written to the command register + * Reset the chip by writing E8390_NODMA + + * E8390_PAGE0 + E8390_STOP just to be + * sure + */ + i = (void *)dev->base_addr; + *i = 0x21; + dev->mem_end = dev->mem_start + + mac8390_memsize(dev->mem_start); + break; + + default: + pr_err("Card type %s is unsupported, sorry\n", + ndev->board->name); + return false; + } + } + + return true; +} + struct net_device * __init mac8390_probe(int unit) { struct net_device *dev; - volatile unsigned short *i; struct nubus_dev *ndev = NULL; int err = -ENODEV; - struct nubus_dir dir; - struct nubus_dirent ent; - int offset; static unsigned int slots; enum mac8390_type cardtype; @@ -324,111 +422,16 @@ struct net_device * __init mac8390_probe(int unit) while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET, ndev))) { /* Have we seen it already? */ - if (slots & (1<board->slot)) + if (slots & (1 << ndev->board->slot)) continue; - slots |= 1<board->slot; + slots |= 1 << ndev->board->slot; cardtype = mac8390_ident(ndev); if (cardtype == MAC8390_NONE) continue; - printk_once(KERN_INFO pr_fmt(version)); - - dev->irq = SLOT2IRQ(ndev->board->slot); - /* This is getting to be a habit */ - dev->base_addr = (ndev->board->slot_addr | - ((ndev->board->slot & 0xf) << 20)); - - /* Get some Nubus info - we will trust the card's idea - of where its memory and registers are. */ - - if (nubus_get_func_dir(ndev, &dir) == -1) { - pr_err("%s: Unable to get Nubus functional directory for slot %X!\n", - dev->name, ndev->board->slot); - continue; - } - - /* Get the MAC address */ - if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) { - pr_info("%s: Couldn't get MAC address!\n", dev->name); + if (!mac8390_init(dev, ndev, cardtype)) continue; - } else { - nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); - } - - if (useresources[cardtype] == 1) { - nubus_rewinddir(&dir); - if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS, - &ent) == -1) { - pr_err("%s: Memory offset resource for slot %X not found!\n", - dev->name, ndev->board->slot); - continue; - } - nubus_get_rsrc_mem(&offset, &ent, 4); - dev->mem_start = dev->base_addr + offset; - /* yes, this is how the Apple driver does it */ - dev->base_addr = dev->mem_start + 0x10000; - nubus_rewinddir(&dir); - if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH, - &ent) == -1) { - pr_info("%s: Memory length resource for slot %X not found, probing\n", - dev->name, ndev->board->slot); - offset = mac8390_memsize(dev->mem_start); - } else { - nubus_get_rsrc_mem(&offset, &ent, 4); - } - dev->mem_end = dev->mem_start + offset; - } else { - switch (cardtype) { - case MAC8390_KINETICS: - case MAC8390_DAYNA: /* it's the same */ - dev->base_addr = - (int)(ndev->board->slot_addr + - DAYNA_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - DAYNA_8390_MEM); - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - case MAC8390_INTERLAN: - dev->base_addr = - (int)(ndev->board->slot_addr + - INTERLAN_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - INTERLAN_8390_MEM); - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - case MAC8390_CABLETRON: - dev->base_addr = - (int)(ndev->board->slot_addr + - CABLETRON_8390_BASE); - dev->mem_start = - (int)(ndev->board->slot_addr + - CABLETRON_8390_MEM); - /* The base address is unreadable if 0x00 - * has been written to the command register - * Reset the chip by writing E8390_NODMA + - * E8390_PAGE0 + E8390_STOP just to be - * sure - */ - i = (void *)dev->base_addr; - *i = 0x21; - dev->mem_end = - dev->mem_start + - mac8390_memsize(dev->mem_start); - break; - - default: - pr_err("Card type %s is unsupported, sorry\n", - ndev->board->name); - continue; - } - } /* Do the nasty 8390 stuff */ if (!mac8390_initdev(dev, ndev, cardtype)) -- cgit v1.2.3 From fc6a110754476362f9f4fa3199a637f2331c5993 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 4 Jan 2010 02:02:47 +0000 Subject: Phonet: zero-copy aligned GPRS RX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newer Nokia cellular modems can use aligned payload for their GPRS pipe. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pep.h | 1 + net/phonet/pep-gprs.c | 4 ++-- net/phonet/pep.c | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h index 4c61cdce4e5f..c37162547a93 100644 --- a/include/net/phonet/pep.h +++ b/include/net/phonet/pep.h @@ -77,6 +77,7 @@ static inline struct pnpipehdr *pnp_hdr(struct sk_buff *skb) enum { PNS_PIPE_DATA = 0x20, + PNS_PIPE_ALIGNED_DATA, PNS_PEP_CONNECT_REQ = 0x40, PNS_PEP_CONNECT_RESP, diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index d183509d3fa6..d01208968c83 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -96,11 +96,11 @@ static int gprs_recv(struct gprs_dev *gp, struct sk_buff *skb) goto drop; } - if (likely(skb_headroom(skb) & 3)) { + if (skb_headroom(skb) & 3) { struct sk_buff *rskb, *fs; int flen = 0; - /* Phonet Pipe data header is misaligned (3 bytes), + /* Phonet Pipe data header may be misaligned (3 bytes), * so wrap the IP packet as a single fragment of an head-less * socket buffer. The network stack will pull what it needs, * but at least, the whole IP payload is not memcpy'd. */ diff --git a/net/phonet/pep.c b/net/phonet/pep.c index b6356f3832f6..e23e30907d34 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -354,6 +354,9 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) queue = &pn->ctrlreq_queue; goto queue; + case PNS_PIPE_ALIGNED_DATA: + __skb_pull(skb, 1); + /* fall through */ case PNS_PIPE_DATA: __skb_pull(skb, 3); /* Pipe data header */ if (!pn_flow_safe(pn->rx_fc)) { -- cgit v1.2.3 From fea93ecef619b5779ca6984568517b1685079b05 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 4 Jan 2010 02:02:48 +0000 Subject: Phonet: zero-copy GPRS TX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Send aligned pipe payload if requested to do so. Then, the socket buffer needs not be fragmented anymore. Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- include/net/phonet/pep.h | 2 ++ net/phonet/pep.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h index c37162547a93..35672b1cf44a 100644 --- a/include/net/phonet/pep.h +++ b/include/net/phonet/pep.h @@ -44,6 +44,7 @@ struct pep_sock { u8 rx_fc; /* RX flow control */ u8 tx_fc; /* TX flow control */ u8 init_enable; /* auto-enable at creation */ + u8 aligned; }; static inline struct pep_sock *pep_sk(struct sock *sk) @@ -139,6 +140,7 @@ enum { PN_PIPE_SB_NEGOTIATED_FC, PN_PIPE_SB_REQUIRED_FC_TX, PN_PIPE_SB_PREFERRED_FC_RX, + PN_PIPE_SB_ALIGNED_DATA, }; /* Phonet pipe flow control models */ diff --git a/net/phonet/pep.c b/net/phonet/pep.c index e23e30907d34..72db27e3fc06 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -444,6 +444,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) struct sockaddr_pn dst; u16 peer_type; u8 pipe_handle, enabled, n_sb; + u8 aligned = 0; if (!pskb_pull(skb, sizeof(*hdr) + 4)) return -EINVAL; @@ -482,6 +483,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) return -EINVAL; peer_type = (peer_type & 0xff00) | data[0]; break; + case PN_PIPE_SB_ALIGNED_DATA: + aligned = data[0] != 0; + break; } n_sb--; } @@ -513,6 +517,7 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) newpn->rx_credits = 0; newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; newpn->init_enable = enabled; + newpn->aligned = aligned; BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); skb_queue_head(&newsk->sk_receive_queue, skb); @@ -832,11 +837,15 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) return -ENOBUFS; } - skb_push(skb, 3); + skb_push(skb, 3 + pn->aligned); skb_reset_transport_header(skb); ph = pnp_hdr(skb); ph->utid = 0; - ph->message_id = PNS_PIPE_DATA; + if (pn->aligned) { + ph->message_id = PNS_PIPE_ALIGNED_DATA; + ph->data[0] = 0; /* padding */ + } else + ph->message_id = PNS_PIPE_DATA; ph->pipe_handle = pn->pipe_handle; return pn_skb_send(sk, skb, &pipe_srv); @@ -930,6 +939,9 @@ int pep_write(struct sock *sk, struct sk_buff *skb) struct sk_buff *rskb, *fs; int flen = 0; + if (pep_sk(sk)->aligned) + return pipe_skb_send(sk, skb); + rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); if (!rskb) { kfree_skb(skb); -- cgit v1.2.3 From 82ecbcb9c6b5257929968d5b0ed536772a9b4ac5 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Mon, 4 Jan 2010 02:02:49 +0000 Subject: Phonet: reject unsupported sendmsg/recvmsg flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/datagram.c | 6 ++++-- net/phonet/pep.c | 10 +++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c index 67f072e94d00..387197b579b1 100644 --- a/net/phonet/datagram.c +++ b/net/phonet/datagram.c @@ -75,7 +75,8 @@ static int pn_sendmsg(struct kiocb *iocb, struct sock *sk, struct sk_buff *skb; int err; - if (msg->msg_flags & MSG_OOB) + if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| + MSG_CMSG_COMPAT)) return -EOPNOTSUPP; if (msg->msg_name == NULL) @@ -119,7 +120,8 @@ static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, int rval = -EOPNOTSUPP; int copylen; - if (flags & MSG_OOB) + if (flags & ~(MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_NOSIGNAL| + MSG_CMSG_COMPAT)) goto out_nofree; if (addr_len) diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 72db27e3fc06..360cf377693e 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -860,7 +860,9 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, int flags = msg->msg_flags; int err, done; - if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) + if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| + MSG_CMSG_COMPAT)) || + !(msg->msg_flags & MSG_EOR)) return -EOPNOTSUPP; skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, @@ -981,6 +983,10 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, struct sk_buff *skb; int err; + if (flags & ~(MSG_OOB|MSG_PEEK|MSG_TRUNC|MSG_DONTWAIT|MSG_WAITALL| + MSG_NOSIGNAL|MSG_CMSG_COMPAT)) + return -EOPNOTSUPP; + if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) return -ENOTCONN; @@ -988,6 +994,8 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, /* Dequeue and acknowledge control request */ struct pep_sock *pn = pep_sk(sk); + if (flags & MSG_PEEK) + return -EOPNOTSUPP; skb = skb_dequeue(&pn->ctrlreq_queue); if (skb) { pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, -- cgit v1.2.3 From d160439e7753aa19092bb12d8f4c6c918f8267e0 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Mon, 4 Jan 2010 13:03:02 +0000 Subject: 8139too: make PCI device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct pci_driver is constant in so it is worth to make pci_device_id also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: David S. Miller --- drivers/net/8139too.c | 2 +- drivers/net/pci-skeleton.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 25f7339daabd..907f2d583db8 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -231,7 +231,7 @@ static const struct { }; -static struct pci_device_id rtl8139_pci_tbl[] = { +static const struct pci_device_id rtl8139_pci_tbl[] = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 480af402affd..8ff5536a3757 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -211,7 +211,7 @@ static struct { }; -static struct pci_device_id netdrv_pci_tbl[] = { +static const struct pci_device_id netdrv_pci_tbl[] = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX }, -- cgit v1.2.3 From ca8d9ea30bc79b2965a1d169dcb2f48f02af4d2d Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Wed, 6 Jan 2010 12:56:37 +0000 Subject: fix bonding: allow arp_ip_targets on separate vlans to use arp validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Wed, Jan 06, 2010 at 10:10:03PM +0100, Eric Dumazet wrote: > Le 06/01/2010 19:38, Eric Dumazet a écrit : > > > > (net-next-2.6 doesnt work well on my bond/vlan setup, I suspect I need a bisection) > > David, I had to revert 1f3c8804acba841b5573b953f5560d2683d2db0d > (bonding: allow arp_ip_targets on separate vlans to use arp validation) > > Or else, my vlan devices dont work (unfortunatly I dont have much time > these days to debug the thing) > > My config : > > +---------+ > vlan.103 -----+ bond0 +--- eth1 (bnx2) > | + > vlan.825 -----+ +--- eth2 (tg3) > +---------+ > > $ cat /proc/net/bonding/bond0 > Ethernet Channel Bonding Driver: v3.6.0 (September 26, 2009) > > Bonding Mode: fault-tolerance (active-backup) > Primary Slave: None > Currently Active Slave: eth2 > MII Status: up > MII Polling Interval (ms): 100 > Up Delay (ms): 0 > Down Delay (ms): 0 > > Slave Interface: eth1 (bnx2) > MII Status: down > Link Failure Count: 1 > Permanent HW addr: 00:1e:0b:ec:d3:d2 > > Slave Interface: eth2 (tg3) > MII Status: up > Link Failure Count: 0 > Permanent HW addr: 00:1e:0b:92:78:50 > This patch fixes up a problem with found with commit 1f3c8804acba841b5573b953f5560d2683d2db0d. The original change overloaded null_or_orig, but doing that prevented any packet handlers that were not tied to a specific device (i.e. ptype->dev == NULL) from ever receiving any frames. The null_or_orig variable cannot be overloaded, and must be kept as NULL to prevent the frame from being ignored by packet handlers designed to accept frames on any interface. Signed-off-by: Andy Gospodarek Signed-off-by: Jay Vosburgh Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index f9aa699ab6cb..d9ab9be0c323 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2430,6 +2430,7 @@ int netif_receive_skb(struct sk_buff *skb) struct packet_type *ptype, *pt_prev; struct net_device *orig_dev; struct net_device *null_or_orig; + struct net_device *null_or_bond; int ret = NET_RX_DROP; __be16 type; @@ -2500,21 +2501,19 @@ ncls: * bonding interfaces still make their way to any base bonding * device that may have registered for a specific ptype. The * handler may have to adjust skb->dev and orig_dev. - * - * null_or_orig can be overloaded since it will not be set when - * using VLANs on top of bonding. Putting it here prevents - * disturbing the ptype_all handlers above. */ + null_or_bond = NULL; if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) && (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) { - null_or_orig = vlan_dev_real_dev(skb->dev); + null_or_bond = vlan_dev_real_dev(skb->dev); } type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { if (ptype->type == type && (ptype->dev == null_or_orig || - ptype->dev == skb->dev || ptype->dev == orig_dev)) { + ptype->dev == skb->dev || ptype->dev == orig_dev || + ptype->dev == null_or_bond)) { if (pt_prev) ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = ptype; -- cgit v1.2.3 From 65324144b50bc7022cc9b6ca8f4a536a957019e3 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Tue, 5 Jan 2010 05:50:47 +0000 Subject: net: RFC3069, private VLAN proxy arp support This is to be used together with switch technologies, like RFC3069, that where the individual ports are not allowed to communicate with each other, but they are allowed to talk to the upstream router. As described in RFC 3069, it is possible to allow these hosts to communicate through the upstream router by proxy_arp'ing. This patch basically allow proxy arp replies back to the same interface (from which the ARP request/solicitation was received). Tunable per device via proc "proxy_arp_pvlan": /proc/sys/net/ipv4/conf/*/proxy_arp_pvlan This switch technology is known by different vendor names: - In RFC 3069 it is called VLAN Aggregation. - Cisco and Allied Telesyn call it Private VLAN. - Hewlett-Packard call it Source-Port filtering or port-isolation. - Ericsson call it MAC-Forced Forwarding (RFC Draft). Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 19 +++++++++++++ include/linux/inetdevice.h | 1 + include/linux/sysctl.h | 1 + net/ipv4/arp.c | 52 +++++++++++++++++++++++++++++++--- net/ipv4/devinet.c | 1 + net/ipv4/route.c | 7 ++++- 6 files changed, 76 insertions(+), 5 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 006b39dec87d..c532884f4fec 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -692,6 +692,25 @@ proxy_arp - BOOLEAN conf/{all,interface}/proxy_arp is set to TRUE, it will be disabled otherwise +proxy_arp_pvlan - BOOLEAN + Private VLAN proxy arp. + Basically allow proxy arp replies back to the same interface + (from which the ARP request/solicitation was received). + + This is done to support (ethernet) switch features, like RFC + 3069, where the individual ports are NOT allowed to + communicate with each other, but they are allowed to talk to + the upstream router. As described in RFC 3069, it is possible + to allow these hosts to communicate through the upstream + router by proxy_arp'ing. Don't need to be used together with + proxy_arp. + + This technology is known by different names: + In RFC 3069 it is called VLAN Aggregation. + Cisco and Allied Telesyn call it Private VLAN. + Hewlett-Packard call it Source-Port filtering or port-isolation. + Ericsson call it MAC-Forced Forwarding (RFC Draft). + shared_media - BOOLEAN Send(router) or accept(host) RFC1620 shared media redirects. Overrides ip_secure_redirects. diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 699e85c01a4d..9a8c57467d3d 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -88,6 +88,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) #define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS) #define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP) +#define IN_DEV_PROXY_ARP_PVLAN(in_dev) IN_DEV_CONF_GET(in_dev, PROXY_ARP_PVLAN) #define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA) #define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS) #define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 877ba039e6a4..24ff7e3a0d59 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -482,6 +482,7 @@ enum NET_IPV4_CONF_ARP_ACCEPT=21, NET_IPV4_CONF_ARP_NOTIFY=22, NET_IPV4_CONF_ACCEPT_LOCAL=23, + NET_IPV4_CONF_PROXY_ARP_PVLAN=24, __NET_IPV4_CONF_MAX }; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index c95cd93acf29..078709233bc4 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -70,6 +70,7 @@ * bonding can change the skb before * sending (e.g. insert 8021q tag). * Harald Welte : convert to make use of jenkins hash + * Jesper D. Brouer: Proxy ARP PVLAN RFC 3069 support. */ #include @@ -524,12 +525,15 @@ int arp_bind_neighbour(struct dst_entry *dst) /* * Check if we can use proxy ARP for this path */ - -static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt) +static inline int arp_fwd_proxy(struct in_device *in_dev, + struct net_device *dev, struct rtable *rt) { struct in_device *out_dev; int imi, omi = -1; + if (rt->u.dst.dev == dev) + return 0; + if (!IN_DEV_PROXY_ARP(in_dev)) return 0; @@ -547,6 +551,43 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt) return (omi != imi && omi != -1); } +/* + * Check for RFC3069 proxy arp private VLAN (allow to send back to same dev) + * + * RFC3069 supports proxy arp replies back to the same interface. This + * is done to support (ethernet) switch features, like RFC 3069, where + * the individual ports are not allowed to communicate with each + * other, BUT they are allowed to talk to the upstream router. As + * described in RFC 3069, it is possible to allow these hosts to + * communicate through the upstream router, by proxy_arp'ing. + * + * RFC 3069: "VLAN Aggregation for Efficient IP Address Allocation" + * + * This technology is known by different names: + * In RFC 3069 it is called VLAN Aggregation. + * Cisco and Allied Telesyn call it Private VLAN. + * Hewlett-Packard call it Source-Port filtering or port-isolation. + * Ericsson call it MAC-Forced Forwarding (RFC Draft). + * + */ +static inline int arp_fwd_pvlan(struct in_device *in_dev, + struct net_device *dev, struct rtable *rt, + __be32 sip, __be32 tip) +{ + /* Private VLAN is only concerned about the same ethernet segment */ + if (rt->u.dst.dev != dev) + return 0; + + /* Don't reply on self probes (often done by windowz boxes)*/ + if (sip == tip) + return 0; + + if (IN_DEV_PROXY_ARP_PVLAN(in_dev)) + return 1; + else + return 0; +} + /* * Interface to link layer: send routine and receive handler. */ @@ -833,8 +874,11 @@ static int arp_process(struct sk_buff *skb) } goto out; } else if (IN_DEV_FORWARD(in_dev)) { - if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && - (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { + if (addr_type == RTN_UNICAST && + (arp_fwd_proxy(in_dev, dev, rt) || + arp_fwd_pvlan(in_dev, dev, rt, sip, tip) || + pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) + { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) neigh_release(n); diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5cdbc102a418..0715f4cac391 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1407,6 +1407,7 @@ static struct devinet_sysctl_table { DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), + DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e446496f564f..1cc339441e7d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1988,8 +1988,13 @@ static int __mkroute_input(struct sk_buff *skb, if (skb->protocol != htons(ETH_P_IP)) { /* Not IP (i.e. ARP). Do not create route, if it is * invalid for proxy arp. DNAT routes are always valid. + * + * Proxy arp feature have been extended to allow, ARP + * replies back to the same interface, to support + * Private VLAN switch technologies. See arp.c. */ - if (out_dev == in_dev) { + if (out_dev == in_dev && + IN_DEV_PROXY_ARP_PVLAN(in_dev) == 0) { err = -EINVAL; goto cleanup; } -- cgit v1.2.3 From 2d13bafeba24f732e89b818b8c66b07893457570 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Tue, 5 Jan 2010 05:50:52 +0000 Subject: net: Make it easier to parse /proc/net/dev contents. The contents of /proc/net/dev is annoying to parse, because it changes whether there is a space after the "ethX:" or not. It depends upon the size of the "Receive bytes" counter, if the number is below 7 digits, then there is whitespaces else if the number is 8 digits or above there is no space between the ":" and the number. This patch changes the output to assure there is always a space between the ":" and the number. Given that all existing userspace application already need to handle the whitespaces, I see no breakage of existing tools. Signed-off-by: Jesper Dangaard Brouer Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index d9ab9be0c323..a008f6987a95 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3206,7 +3206,7 @@ static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) { const struct net_device_stats *stats = dev_get_stats(dev); - seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " + seq_printf(seq, "%6s: %7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", dev->name, stats->rx_bytes, stats->rx_packets, stats->rx_errors, -- cgit v1.2.3 From 1154b299e7924f2ae8bb3ca479a6942e1edd78fc Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:28:08 +0000 Subject: drivers/atm/nicstar.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/atm/nicstar.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 3da804b1627d..50838407b117 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -807,9 +807,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) } } - printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i, - card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2], - card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]); + printk("nicstar%d: MAC address %pM\n", i, card->atmdev->esi); card->atmdev->dev_data = card; card->atmdev->ci_range.vpi_bits = card->vpibits; -- cgit v1.2.3 From ce7194d889996fb8f724148bc85a0c2c79da7b8e Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:56:52 +0000 Subject: drivers/net/ixgbe/ixgbe_common.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. The only difference in the output is that the MAC address is shown in the usual colon-separated hex notation. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_common.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 688b8ca5da32..1cedb9af63dc 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1278,19 +1278,11 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw) /* Get the MAC address from the RAR0 for later reference */ hw->mac.ops.get_mac_addr(hw, hw->mac.addr); - hw_dbg(hw, " Keeping Current RAR0 Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); - hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw_dbg(hw, " Keeping Current RAR0 Addr =%pM\n", hw->mac.addr); } else { /* Setup the receive address. */ hw_dbg(hw, "Overriding MAC Address in RAR[0]\n"); - hw_dbg(hw, " New MAC Addr =%.2X %.2X %.2X ", - hw->mac.addr[0], hw->mac.addr[1], - hw->mac.addr[2]); - hw_dbg(hw, "%.2X %.2X %.2X\n", hw->mac.addr[3], - hw->mac.addr[4], hw->mac.addr[5]); + hw_dbg(hw, " New MAC Addr =%pM\n", hw->mac.addr); hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); } -- cgit v1.2.3 From aaa09ee7287d31f57f4dc8b4acca5cd59c1595f5 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:24:23 +0000 Subject: drivers/atm/idt77252.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/atm/idt77252.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index e33ae0025b12..01f36c08cb52 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3557,10 +3557,7 @@ init_card(struct atm_dev *dev) if (tmp) { memcpy(card->atmdev->esi, tmp->dev_addr, 6); - printk("%s: ESI %02x:%02x:%02x:%02x:%02x:%02x\n", - card->name, card->atmdev->esi[0], card->atmdev->esi[1], - card->atmdev->esi[2], card->atmdev->esi[3], - card->atmdev->esi[4], card->atmdev->esi[5]); + printk("%s: ESI %pM\n", card->name, card->atmdev->esi); } /* * XXX: -- cgit v1.2.3 From 2c35294853b2e977bdfc9e401b7b6d881fcaa69b Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:37:43 +0000 Subject: drivers/firmware/iscsi_ibft.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Also, remove the 'mac' variable and use nic->mac directly. Signed-off-by: H Hartley Sweeten Acked-by: Peter Jones Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/firmware/iscsi_ibft.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index 051d1ebbd287..5aeb3b541c80 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -380,7 +380,6 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, struct ibft_nic *nic = entry->nic; void *ibft_loc = entry->header; char *str = buf; - char *mac; int val; if (!nic) @@ -421,10 +420,7 @@ static ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, str += sprintf(str, "%d\n", nic->vlan); break; case ibft_eth_mac: - mac = nic->mac; - str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n", - (u8)mac[0], (u8)mac[1], (u8)mac[2], - (u8)mac[3], (u8)mac[4], (u8)mac[5]); + str += sprintf(str, "%pM\n", nic->mac); break; case ibft_eth_hostname: str += sprintf_string(str, nic->hostname_len, -- cgit v1.2.3 From 3008ab36e23623cbe7a53bff2d495eca5426a9ce Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:22:20 +0000 Subject: drivers/atm/fore200e.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/atm/fore200e.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index bc53fed89b1e..f7d6ebaa0418 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2064,12 +2064,10 @@ fore200e_get_esi(struct fore200e* fore200e) return -EBUSY; } - printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %02x:%02x:%02x:%02x:%02x:%02x\n", + printk(FORE200E "device %s, rev. %c, S/N: %d, ESI: %pM\n", fore200e->name, (prom->hw_revision & 0xFF) + '@', /* probably meaningless with SBA boards */ - prom->serial_number & 0xFFFF, - prom->mac_addr[ 2 ], prom->mac_addr[ 3 ], prom->mac_addr[ 4 ], - prom->mac_addr[ 5 ], prom->mac_addr[ 6 ], prom->mac_addr[ 7 ]); + prom->serial_number & 0xFFFF, &prom->mac_addr[2]); for (i = 0; i < ESI_LEN; i++) { fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ]; @@ -2845,13 +2843,12 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) " interrupt line:\t\t%s\n" " physical base address:\t0x%p\n" " virtual base address:\t0x%p\n" - " factory address (ESI):\t%02x:%02x:%02x:%02x:%02x:%02x\n" + " factory address (ESI):\t%pM\n" " board serial number:\t\t%d\n\n", fore200e_irq_itoa(fore200e->irq), (void*)fore200e->phys_base, fore200e->virt_base, - fore200e->esi[0], fore200e->esi[1], fore200e->esi[2], - fore200e->esi[3], fore200e->esi[4], fore200e->esi[5], + fore200e->esi, fore200e->esi[4] * 256 + fore200e->esi[5]); return len; -- cgit v1.2.3 From 8d9ded23b3259c7f6883e97284e949af7afd4e40 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:26:49 +0000 Subject: drivers/atm/lanai.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/atm/lanai.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index cf97c34cbaf1..7fe7c324e7ef 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -998,9 +998,7 @@ static int __devinit eeprom_validate(struct lanai_dev *lanai) (unsigned int) e[EEPROM_MAC_REV + i]); return -EIO; } - DPRINTK("eeprom: MAC address = %02X:%02X:%02X:%02X:%02X:%02X\n", - e[EEPROM_MAC + 0], e[EEPROM_MAC + 1], e[EEPROM_MAC + 2], - e[EEPROM_MAC + 3], e[EEPROM_MAC + 4], e[EEPROM_MAC + 5]); + DPRINTK("eeprom: MAC address = %pM\n", &e[EEPROM_MAC]); /* Verify serial number */ lanai->serialno = eeprom_be4(lanai, EEPROM_SERIAL); v = eeprom_be4(lanai, EEPROM_SERIAL_REV); @@ -2483,14 +2481,8 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page) return sprintf(page, "revision: board=%d, pci_if=%d\n", lanai->board_rev, (int) lanai->pci->revision); if (left-- == 0) - return sprintf(page, "EEPROM ESI: " - "%02X:%02X:%02X:%02X:%02X:%02X\n", - lanai->eeprom[EEPROM_MAC + 0], - lanai->eeprom[EEPROM_MAC + 1], - lanai->eeprom[EEPROM_MAC + 2], - lanai->eeprom[EEPROM_MAC + 3], - lanai->eeprom[EEPROM_MAC + 4], - lanai->eeprom[EEPROM_MAC + 5]); + return sprintf(page, "EEPROM ESI: %pM\n", + &lanai->eeprom[EEPROM_MAC]); if (left-- == 0) return sprintf(page, "status: SOOL=%d, LOCD=%d, LED=%d, " "GPIN=%d\n", (lanai->status & STATUS_SOOL) ? 1 : 0, -- cgit v1.2.3 From 0e05a613f40a1210a050ebd1ecfd5434420ae5b2 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:45:21 +0000 Subject: drivers/media/dvb/dvb-core/dvb_net.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address and mask. The only difference in the output is that the output is shown in the usual colon-separated hex notation. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/media/dvb/dvb-core/dvb_net.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index 8b8558fcb042..da6552d32cfe 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -949,11 +949,8 @@ static int dvb_net_filter_sec_set(struct net_device *dev, (*secfilter)->filter_mask[10] = mac_mask[1]; (*secfilter)->filter_mask[11]=mac_mask[0]; - dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n", - dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n", - dev->name, mac_mask[0], mac_mask[1], mac_mask[2], - mac_mask[3], mac_mask[4], mac_mask[5]); + dprintk("%s: filter mac=%pM\n", dev->name, mac); + dprintk("%s: filter mask=%pM\n", dev->name, mac_mask); return 0; } -- cgit v1.2.3 From bf54e73691158a634ff72ebc139f38c4fa7b83f0 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:59:23 +0000 Subject: drivers/net/vxge/vxge-main.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/vxge/vxge-main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index f1c4b2a1e867..5f0e7ea0d493 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -4297,10 +4297,8 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) vxge_debug_init(VXGE_TRACE, "%s: Neterion %s Server Adapter", vdev->ndev->name, ll_config.device_hw_info.product_desc); - vxge_debug_init(VXGE_TRACE, - "%s: MAC ADDR: %02X:%02X:%02X:%02X:%02X:%02X", - vdev->ndev->name, macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); + vxge_debug_init(VXGE_TRACE, "%s: MAC ADDR: %pM", + vdev->ndev->name, macaddr); vxge_debug_init(VXGE_TRACE, "%s: Link Width x%d", vdev->ndev->name, vxge_hw_device_link_width_get(hldev)); -- cgit v1.2.3 From 829911725f4bb72c30480aab756704d588c7cd1e Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:54:01 +0000 Subject: drivers/net/atl1c/atl1c_main.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. The only difference in the output is that the MAC address is shown in the usual colon-separated hex notation. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c_main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 2f4be59b9c0b..77cde859620c 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -2596,11 +2596,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); if (netif_msg_probe(adapter)) - dev_dbg(&pdev->dev, - "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n", - adapter->hw.mac_addr[0], adapter->hw.mac_addr[1], - adapter->hw.mac_addr[2], adapter->hw.mac_addr[3], - adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); + dev_dbg(&pdev->dev, "mac address : %pM\n", + adapter->hw.mac_addr); atl1c_hw_set_mac_addr(&adapter->hw); INIT_WORK(&adapter->common_task, atl1c_common_task); -- cgit v1.2.3 From 595acf270e098ee3af92890253c5db41bc85de88 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 07:01:54 +0000 Subject: drivers/net/wimax/i2400m/fw.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/fw.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 64cdfeb299ca..e803a7dc6502 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -1041,21 +1041,14 @@ int i2400m_read_mac_addr(struct i2400m *i2400m) dev_err(dev, "BM: read mac addr failed: %d\n", result); goto error_read_mac; } - d_printf(2, dev, - "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n", - ack_buf.ack_pl[0], ack_buf.ack_pl[1], - ack_buf.ack_pl[2], ack_buf.ack_pl[3], - ack_buf.ack_pl[4], ack_buf.ack_pl[5]); + d_printf(2, dev, "mac addr is %pM\n", ack_buf.ack_pl); if (i2400m->bus_bm_mac_addr_impaired == 1) { ack_buf.ack_pl[0] = 0x00; ack_buf.ack_pl[1] = 0x16; ack_buf.ack_pl[2] = 0xd3; get_random_bytes(&ack_buf.ack_pl[3], 3); dev_err(dev, "BM is MAC addr impaired, faking MAC addr to " - "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n", - ack_buf.ack_pl[0], ack_buf.ack_pl[1], - ack_buf.ack_pl[2], ack_buf.ack_pl[3], - ack_buf.ack_pl[4], ack_buf.ack_pl[5]); + "mac addr is %pM\n", ack_buf.ack_pl); result = 0; } net_dev->addr_len = ETH_ALEN; -- cgit v1.2.3 From 1b8e664d34f2f551fd6c2d40033d29c13551292c Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:55:40 +0000 Subject: drivers/net/atl1e/atl1e_main.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. The only difference in the output is that the MAC address is shown in the usual colon-separated hex notation. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/atl1e/atl1e_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 08f8c0969e9b..2080d444068b 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -2378,10 +2378,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); - dev_dbg(&pdev->dev, "mac address : %02x-%02x-%02x-%02x-%02x-%02x\n", - adapter->hw.mac_addr[0], adapter->hw.mac_addr[1], - adapter->hw.mac_addr[2], adapter->hw.mac_addr[3], - adapter->hw.mac_addr[4], adapter->hw.mac_addr[5]); + dev_dbg(&pdev->dev, "mac address : %pM\n", adapter->hw.mac_addr); INIT_WORK(&adapter->reset_task, atl1e_reset_task); INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task); -- cgit v1.2.3 From fcb635e8c6d68bf06531603a1caa6e59ba7e356d Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 06:58:12 +0000 Subject: drivers/net/qlge/qlge_main.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index e9d6481ed9eb..25561fbdb203 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -452,9 +452,7 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) if (set) { addr = &qdev->ndev->dev_addr[0]; QPRINTK(qdev, IFUP, DEBUG, - "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5]); + "Set Mac addr %pM\n", addr); } else { memset(zero_mac_addr, 0, ETH_ALEN); addr = &zero_mac_addr[0]; -- cgit v1.2.3 From 4754b3de93f893e85d811031ff742fc7a4f53db4 Mon Sep 17 00:00:00 2001 From: hartleys Date: Tue, 5 Jan 2010 07:00:57 +0000 Subject: drivers/net/wimax/i2400m/driver.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/driver.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 96a615fe09de..6cead321bc15 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -301,24 +301,15 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) /* Extract MAC addresss */ ddi = (void *) skb->data; BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address)); - d_printf(2, dev, "GET DEVICE INFO: mac addr " - "%02x:%02x:%02x:%02x:%02x:%02x\n", - ddi->mac_address[0], ddi->mac_address[1], - ddi->mac_address[2], ddi->mac_address[3], - ddi->mac_address[4], ddi->mac_address[5]); + d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n", + ddi->mac_address); if (!memcmp(net_dev->perm_addr, ddi->mac_address, sizeof(ddi->mac_address))) goto ok; dev_warn(dev, "warning: device reports a different MAC address " "to that of boot mode's\n"); - dev_warn(dev, "device reports %02x:%02x:%02x:%02x:%02x:%02x\n", - ddi->mac_address[0], ddi->mac_address[1], - ddi->mac_address[2], ddi->mac_address[3], - ddi->mac_address[4], ddi->mac_address[5]); - dev_warn(dev, "boot mode reported %02x:%02x:%02x:%02x:%02x:%02x\n", - net_dev->perm_addr[0], net_dev->perm_addr[1], - net_dev->perm_addr[2], net_dev->perm_addr[3], - net_dev->perm_addr[4], net_dev->perm_addr[5]); + dev_warn(dev, "device reports %pM\n", ddi->mac_address); + dev_warn(dev, "boot mode reported %pM\n", net_dev->perm_addr); if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac))) dev_err(dev, "device reports an invalid MAC address, " "not updating\n"); -- cgit v1.2.3 From eacc4d6a7dc447ec4fc219af129e0fe50d21d8f7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jan 2010 01:17:27 -0800 Subject: drivers/infiniband/hw/cxgb3/iwch_cm.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. The only difference in the output is that the MAC address is shown in the usual colon-separated hex notation. Signed-off-by: H Hartley Sweeten Acked-by: Steve Wise Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb3/iwch_cm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 66b41351910a..d94388b81a40 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1371,15 +1371,8 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) tim.mac_addr = req->dst_mac; tim.vlan_tag = ntohs(req->vlan_tag); if (tdev->ctl(tdev, GET_IFF_FROM_MAC, &tim) < 0 || !tim.dev) { - printk(KERN_ERR - "%s bad dst mac %02x %02x %02x %02x %02x %02x\n", - __func__, - req->dst_mac[0], - req->dst_mac[1], - req->dst_mac[2], - req->dst_mac[3], - req->dst_mac[4], - req->dst_mac[5]); + printk(KERN_ERR "%s bad dst mac %pM\n", + __func__, req->dst_mac); goto reject; } -- cgit v1.2.3 From cf30273bea4a9d368a31869ccc6ad618e4413b66 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 7 Jan 2010 01:18:23 -0800 Subject: drivers/message/i2o/i2o_proc.c: use %pM to show MAC address Use the %pM kernel extension to display the MAC address. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- drivers/message/i2o/i2o_proc.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 7045c45da9b1..949a648f8e2e 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c @@ -111,10 +111,7 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) break; case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ - seq_printf(seq, - "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X", - serialno[2], serialno[3], - serialno[4], serialno[5], serialno[6], serialno[7]); + seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]); break; case I2O_SNFORMAT_WAN: /* WAN MAC Address */ @@ -126,10 +123,8 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ /* FIXME: Figure out what a LAN-64 address really looks like?? */ seq_printf(seq, - "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X", - serialno[8], serialno[9], - serialno[2], serialno[3], - serialno[4], serialno[5], serialno[6], serialno[7]); + "LAN-64 MAC address @ [?:%02X:%02X:?] %pM", + serialno[8], serialno[9], &serialno[2]); break; case I2O_SNFORMAT_DDM: /* I2O DDM */ -- cgit v1.2.3 From bc7259a2ce764ea16200eb9e53f6e136e918d065 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 7 Jan 2010 11:43:50 +0000 Subject: lib/vsprintf.c: Add %pMF to format FDDI bit reversed MAC addresses On Mon, 2010-01-04 at 23:43 +0000, Maciej W. Rozycki wrote: > The example below shows an address, and the sequence of bits or symbols > that would be transmitted when the address is used in the Source Address > or Destination Address fields on the MAC header. The transmission line > shows the address bits in the order transmitted, from left to right. For > IEEE 802 LANs these correspond to actual bits on the medium. The FDDI > symbols line shows how the FDDI PHY sends the address bits as encoded > symbols. > > MSB: 35:7B:12:00:00:01 > Canonical: AC-DE-48-00-00-80 > Transmission: 00110101 01111011 00010010 00000000 00000000 00000001 > FDDI Symbols: 35 7B 12 00 00 01" > > Please note that this address has its group bit clear. > > This notation is also defined in the "FDDI MEDIA ACCESS CONTROL-2 > (MAC-2)" (X3T9/92-120) document although that book does not have a need > to use the MSB form and it's skipped. Adds 6 bytes to object size for x86 New: $ size lib/vsprintf.o text data bss dec hex filename 8664 0 2 8666 21da lib/vsprintf.o $ size lib/vsprintf.o text data bss dec hex filename 8658 0 2 8660 21d4 lib/vsprintf.o Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- lib/vsprintf.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d4996cf46eb6..dc48d2b32ebd 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include /* for PAGE_SIZE */ @@ -681,11 +682,21 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; char *p = mac_addr; int i; + bool bitrev; + char separator; + + if (fmt[1] == 'F') { /* FDDI canonical format */ + bitrev = true; + separator = '-'; + } else { + bitrev = false; + separator = ':'; + } for (i = 0; i < 6; i++) { - p = pack_hex_byte(p, addr[i]); + p = pack_hex_byte(p, bitrev ? bitrev8(addr[i]) : addr[i]); if (fmt[0] == 'M' && i != 5) - *p++ = ':'; + *p++ = separator; } *p = '\0'; @@ -896,6 +907,10 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, * - 'M' For a 6-byte MAC address, it prints the address in the * usual colon-separated hex notation * - 'm' For a 6-byte MAC address, it prints the hex address without colons + * - 'MF' For a 6-byte MAC FDDI address, it prints the address + * with a dash-separated hex notation with bit reversed bytes + * - 'mF' For a 6-byte MAC FDDI address, it prints the address + * in hex notation without separators with bit reversed bytes * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) * IPv6 uses colon separated network-order 16 bit hex with leading 0's @@ -939,6 +954,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, return resource_string(buf, end, ptr, spec, fmt); case 'M': /* Colon separated: 00:01:02:03:04:05 */ case 'm': /* Contiguous: 000102030405 */ + /* [mM]F (FDDI, bit reversed) */ return mac_address_string(buf, end, ptr, spec, fmt); case 'I': /* Formatted IP supported * 4: 1.2.3.4 -- cgit v1.2.3 From 69d279eaf8f23c7d7cfc0e879c629a92bfc3e3e0 Mon Sep 17 00:00:00 2001 From: hartleys Date: Thu, 7 Jan 2010 13:24:19 +0000 Subject: drivers/net/defxx.c: use %pMF to show MAC address Use the %pMF kernel extension to display the MAC address. The address will still be displayed in the FDDI Canonical format. Signed-off-by: H Hartley Sweeten Cc: Maciej W. Rozycki Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/defxx.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 6a6ea038d7a3..e4eac4bcdf83 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -1052,12 +1052,9 @@ static int __devinit dfx_driver_init(struct net_device *dev, board_name = "DEFEA"; if (dfx_bus_pci) board_name = "DEFPA"; - pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, " - "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n", + pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n", print_name, board_name, dfx_use_mmio ? "" : "I/O ", - (long long)bar_start, dev->irq, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + (long long)bar_start, dev->irq, dev->dev_addr); /* * Get memory for descriptor block, consumer block, and other buffers -- cgit v1.2.3 From 596a530bb3af746d33ea2910a0569b9825279979 Mon Sep 17 00:00:00 2001 From: hartleys Date: Thu, 7 Jan 2010 13:27:46 +0000 Subject: drivers/net/skfp/skfddi.c: use %pMF to show MAC address Use the %pMF kernel extension to display the MAC address. The address will still be displayed in the FDDI Canonical format. Signed-off-by: H Hartley Sweeten Cc: David S. Miller Signed-off-by: David S. Miller --- drivers/net/skfp/skfddi.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index db216a728503..1f9698c0fb64 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -435,13 +435,7 @@ static int skfp_driver_init(struct net_device *dev) goto fail; } read_address(smc, NULL); - pr_debug(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", - smc->hw.fddi_canon_addr.a[0], - smc->hw.fddi_canon_addr.a[1], - smc->hw.fddi_canon_addr.a[2], - smc->hw.fddi_canon_addr.a[3], - smc->hw.fddi_canon_addr.a[4], - smc->hw.fddi_canon_addr.a[5]); + pr_debug(KERN_INFO "HW-Addr: %pMF\n", smc->hw.fddi_canon_addr.a); memcpy(dev->dev_addr, smc->hw.fddi_canon_addr.a, 6); smt_reset_defaults(smc, 0); @@ -890,15 +884,8 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) (struct fddi_addr *)dmi->dmi_addr, 1); - pr_debug(KERN_INFO "ENABLE MC ADDRESS:"); - pr_debug(" %02x %02x %02x ", - dmi->dmi_addr[0], - dmi->dmi_addr[1], - dmi->dmi_addr[2]); - pr_debug("%02x %02x %02x\n", - dmi->dmi_addr[3], - dmi->dmi_addr[4], - dmi->dmi_addr[5]); + pr_debug(KERN_INFO "ENABLE MC ADDRESS: %pMF\n", + dmi->dmi_addr); dmi = dmi->next; } // for -- cgit v1.2.3 From 109cdd66485b639b2fbfcbf59ae7ef1286520705 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:11 +0000 Subject: stmmac: use MII_BUS_ID_SIZE instead of BUS_ID_SIZE Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 508fba8fa07f..79a938117878 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -305,8 +305,8 @@ static int stmmac_init_phy(struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; /* PHY to connect */ - char bus_id[BUS_ID_SIZE]; + char phy_id[MII_BUS_ID_SIZE + 3]; + char bus_id[MII_BUS_ID_SIZE]; priv->oldlink = 0; priv->speed = 0; @@ -318,7 +318,8 @@ static int stmmac_init_phy(struct net_device *dev) } snprintf(bus_id, MII_BUS_ID_SIZE, "%x", priv->bus_id); - snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, bus_id, priv->phy_addr); + snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, + priv->phy_addr); pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id); phydev = phy_connect(dev, phy_id, &stmmac_adjust_link, 0, -- cgit v1.2.3 From 609634799eba48bb9e80ce56dfd87930f17bf6fa Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:12 +0000 Subject: stmmac: convert unicast addr list to list_head This patch converts unicast address list to standard list_head using previously introduced struct netdev_hw_addr. Note: this patch also removes a debug printk used for displaying the mac addresses. Indeed, it's is possible to dump the registers with ethtool. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/gmac.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c index 52586ee68953..982875646725 100644 --- a/drivers/net/stmmac/gmac.c +++ b/drivers/net/stmmac/gmac.c @@ -435,7 +435,7 @@ static void gmac_set_filter(struct net_device *dev) unsigned int value = 0; DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", - __func__, dev->mc_count, dev->uc_count); + __func__, dev->mc_count, dev->uc.count); if (dev->flags & IFF_PROMISC) value = GMAC_FRAME_FILTER_PR; @@ -469,25 +469,17 @@ static void gmac_set_filter(struct net_device *dev) } /* Handle multiple unicast addresses (perfect filtering)*/ - if (dev->uc_count > GMAC_MAX_UNICAST_ADDRESSES) + if (dev->uc.count > GMAC_MAX_UNICAST_ADDRESSES) /* Switch to promiscuous mode is more than 16 addrs are required */ value |= GMAC_FRAME_FILTER_PR; else { - int i; - struct dev_addr_list *uc_ptr = dev->uc_list; - - for (i = 0; i < dev->uc_count; i++) { - gmac_set_umac_addr(ioaddr, uc_ptr->da_addr, - i + 1); - - DBG(KERN_INFO "\t%d " - "- Unicast addr %02x:%02x:%02x:%02x:%02x:" - "%02x\n", i + 1, - uc_ptr->da_addr[0], uc_ptr->da_addr[1], - uc_ptr->da_addr[2], uc_ptr->da_addr[3], - uc_ptr->da_addr[4], uc_ptr->da_addr[5]); - uc_ptr = uc_ptr->next; + int reg = 1; + struct netdev_hw_addr *ha; + + list_for_each_entry(ha, &dev->uc.list, list) { + gmac_set_umac_addr(ioaddr, ha->addr, reg); + reg++; } } -- cgit v1.2.3 From 3c9732c06879d85f2fdf7ec69198c1d78da42a98 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:13 +0000 Subject: stmmac: add the new Header file for stmmac platform data Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- include/linux/stmmac.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 include/linux/stmmac.h diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h new file mode 100644 index 000000000000..32bfd1a8a48d --- /dev/null +++ b/include/linux/stmmac.h @@ -0,0 +1,53 @@ +/******************************************************************************* + + Header file for stmmac platform data + + Copyright (C) 2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#ifndef __STMMAC_PLATFORM_DATA +#define __STMMAC_PLATFORM_DATA + +/* platfrom data for platfrom device structure's platfrom_data field */ + +/* Private data for the STM on-board ethernet driver */ +struct plat_stmmacenet_data { + int bus_id; + int pbl; + int has_gmac; + void (*fix_mac_speed)(void *priv, unsigned int speed); + void (*bus_setup)(unsigned long ioaddr); +#ifdef CONFIG_STM_DRIVERS + struct stm_pad_config *pad_config; +#endif + void *bsp_priv; +}; + +struct plat_stmmacphy_data { + int bus_id; + int phy_addr; + unsigned int phy_mask; + int interface; + int (*phy_reset)(void *priv); + void *priv; +}; +#endif + -- cgit v1.2.3 From ee7946a77858f417227cf57cd647729d0dd75761 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:14 +0000 Subject: stmmac: rewiew platform data This patch rewiews and reorganises all the data come from the platform removing any dependency from the stm code. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac.h | 24 ++++++++++++++++++++++++ drivers/net/stmmac/stmmac_main.c | 16 +++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 6d2eae3040e5..0d5529fa579a 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -21,6 +21,7 @@ *******************************************************************************/ #define DRV_MODULE_VERSION "Oct_09" +#include #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define STMMAC_VLAN_TAG_USED @@ -69,6 +70,7 @@ struct stmmac_priv { int phy_mask; int (*phy_reset) (void *priv); void (*fix_mac_speed) (void *priv, unsigned int speed); + void (*bus_setup)(unsigned long ioaddr); void *bsp_priv; int phy_irq; @@ -93,6 +95,28 @@ struct stmmac_priv { #endif }; +#ifdef CONFIG_STM_DRIVERS +#include +static inline int stmmac_claim_resource(struct platform_device *pdev) +{ + int ret = 0; + struct plat_stmmacenet_data *plat_dat = pdev->dev.platform_data; + + /* Pad routing setup */ + if (IS_ERR(devm_stm_pad_claim(&pdev->dev, plat_dat->pad_config, + dev_name(&pdev->dev)))) { + printk(KERN_ERR "%s: Failed to request pads!\n", __func__); + ret = -ENODEV; + } + return ret; +} +#else +static inline int stmmac_claim_resource(struct platform_device *pdev) +{ + return 0; +} +#endif + extern int stmmac_mdio_unregister(struct net_device *ndev); extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 79a938117878..d50fe6f171ef 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -45,7 +45,6 @@ #include #include #include -#include #include "stmmac.h" #define STMMAC_RESOURCE_NAME "stmmaceth" @@ -1798,8 +1797,7 @@ static int stmmac_mac_device_setup(struct net_device *dev) static int stmmacphy_dvr_probe(struct platform_device *pdev) { - struct plat_stmmacphy_data *plat_dat; - plat_dat = (struct plat_stmmacphy_data *)((pdev->dev).platform_data); + struct plat_stmmacphy_data *plat_dat = pdev->dev.platform_data; pr_debug("stmmacphy_dvr_probe: added phy for bus %d\n", plat_dat->bus_id); @@ -1831,9 +1829,7 @@ static struct platform_driver stmmacphy_driver = { static int stmmac_associate_phy(struct device *dev, void *data) { struct stmmac_priv *priv = (struct stmmac_priv *)data; - struct plat_stmmacphy_data *plat_dat; - - plat_dat = (struct plat_stmmacphy_data *)(dev->platform_data); + struct plat_stmmacphy_data *plat_dat = dev->platform_data; DBG(probe, DEBUG, "%s: checking phy for bus %d\n", __func__, plat_dat->bus_id); @@ -1923,7 +1919,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) priv = netdev_priv(ndev); priv->device = &(pdev->dev); priv->dev = ndev; - plat_dat = (struct plat_stmmacenet_data *)((pdev->dev).platform_data); + plat_dat = pdev->dev.platform_data; priv->bus_id = plat_dat->bus_id; priv->pbl = plat_dat->pbl; /* TLI */ priv->is_gmac = plat_dat->has_gmac; /* GMAC is on board */ @@ -1933,6 +1929,11 @@ static int stmmac_dvr_probe(struct platform_device *pdev) /* Set the I/O base addr */ ndev->base_addr = (unsigned long)addr; + /* Verify embedded resource for the platform */ + ret = stmmac_claim_resource(pdev); + if (ret < 0) + goto out; + /* MAC HW revice detection */ ret = stmmac_mac_device_setup(ndev); if (ret < 0) @@ -1953,6 +1954,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev) } priv->fix_mac_speed = plat_dat->fix_mac_speed; + priv->bus_setup = plat_dat->bus_setup; priv->bsp_priv = plat_dat->bsp_priv; pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n" -- cgit v1.2.3 From ca5f12c1a82cf72ce73617dfc8ef56faf6fec30a Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:15 +0000 Subject: stmmac: perform hw bus configuration On some platforms it can be required a different configuration of the bus. This can be done by invoking the bus_setup. It is defined for all the platforms that needs this kind of configuration. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/gmac.c | 3 --- drivers/net/stmmac/stmmac_main.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c index 982875646725..c1278876ef25 100644 --- a/drivers/net/stmmac/gmac.c +++ b/drivers/net/stmmac/gmac.c @@ -400,9 +400,6 @@ static void gmac_core_init(unsigned long ioaddr) value |= GMAC_CORE_INIT; writel(value, ioaddr + GMAC_CONTROL); - /* STBus Bridge Configuration */ - /*writel(0xc5608, ioaddr + 0x00007000);*/ - /* Freeze MMC counters */ writel(0x8, ioaddr + GMAC_MMC_CTRL); /* Mask GMAC interrupts */ diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index d50fe6f171ef..a02006d57a59 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1067,6 +1067,9 @@ static int stmmac_open(struct net_device *dev) /* Copy the MAC addr into the HW */ priv->mac_type->ops->set_umac_addr(ioaddr, dev->dev_addr, 0); + /* If required, perform hw setup of the bus. */ + if (priv->bus_setup) + priv->bus_setup(ioaddr); /* Initialize the MAC Core */ priv->mac_type->ops->core_init(ioaddr); -- cgit v1.2.3 From 65818fa744e70a58d230083dda1f1cd8e5c5e2ee Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:16 +0000 Subject: stmmac: do not call fix_mac_speed if NULL On some platforms, fix_mac_speed is used for configuring some sysconf registers according to the working speed. This patch fixes the fix_mac_speed invocation that cannot be done if it is a NULL pointer. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index a02006d57a59..82ebbc0c8839 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -258,8 +258,9 @@ static void stmmac_adjust_link(struct net_device *dev) } else { ctrl &= ~priv->mac_type->hw.link.port; } - priv->fix_mac_speed(priv->bsp_priv, - phydev->speed); + if (likely(priv->fix_mac_speed)) + priv->fix_mac_speed(priv->bsp_priv, + phydev->speed); break; default: if (netif_msg_link(priv)) -- cgit v1.2.3 From db98a0b001df79ffcdd4f231c3516411786a1113 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:17 +0000 Subject: stmmac: reorganise class operations. This patch reorganises the internal stmmac ops structure. The stmmac_ops has been splitted into other three structures named: stmmac_ops stmmac_dma_ops stmmac_desc_ops This makes the code more clear and also helps the next work to make the driver more generic. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/common.h | 64 +++++++++-------- drivers/net/stmmac/gmac.c | 43 ++++++----- drivers/net/stmmac/mac100.c | 43 ++++++----- drivers/net/stmmac/stmmac.h | 2 +- drivers/net/stmmac/stmmac_ethtool.c | 8 +-- drivers/net/stmmac/stmmac_main.c | 138 +++++++++++++++++------------------- drivers/net/stmmac/stmmac_mdio.c | 10 +-- 7 files changed, 162 insertions(+), 146 deletions(-) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index e49e5188e887..95782ccf44b4 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -239,25 +239,11 @@ static inline void stmmac_get_mac_addr(unsigned long ioaddr, return; } -struct stmmac_ops { - /* MAC core initialization */ - void (*core_init) (unsigned long ioaddr) ____cacheline_aligned; - /* DMA core initialization */ - int (*dma_init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx); - /* Dump MAC registers */ - void (*dump_mac_regs) (unsigned long ioaddr); - /* Dump DMA registers */ - void (*dump_dma_regs) (unsigned long ioaddr); - /* Set tx/rx threshold in the csr6 register - * An invalid value enables the store-and-forward mode */ - void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode); - /* To track extra statistic (if supported) */ - void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, - unsigned long ioaddr); - /* RX descriptor ring initialization */ +struct stmmac_desc_ops { + /* DMA RX descriptor ring initialization */ void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size, - int disable_rx_ic); - /* TX descriptor ring initialization */ + int disable_rx_ic); + /* DMA TX descriptor ring initialization */ void (*init_tx_desc) (struct dma_desc *p, unsigned int ring_size); /* Invoked by the xmit function to prepare the tx descriptor */ @@ -281,7 +267,6 @@ struct stmmac_ops { /* Get the buffer size from the descriptor */ int (*get_tx_len) (struct dma_desc *p); /* Handle extra events on specific interrupts hw dependent */ - void (*host_irq_status) (unsigned long ioaddr); int (*get_rx_owner) (struct dma_desc *p); void (*set_rx_owner) (struct dma_desc *p); /* Get the receive frame size */ @@ -289,6 +274,28 @@ struct stmmac_ops { /* Return the reception status looking at the RDES1 */ int (*rx_status) (void *data, struct stmmac_extra_stats *x, struct dma_desc *p); +}; + +struct stmmac_dma_ops { + /* DMA core initialization */ + int (*init) (unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx); + /* Dump DMA registers */ + void (*dump_regs) (unsigned long ioaddr); + /* Set tx/rx threshold in the csr6 register + * An invalid value enables the store-and-forward mode */ + void (*dma_mode) (unsigned long ioaddr, int txmode, int rxmode); + /* To track extra statistic (if supported) */ + void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, + unsigned long ioaddr); +}; + +struct stmmac_ops { + /* MAC core initialization */ + void (*core_init) (unsigned long ioaddr) ____cacheline_aligned; + /* Dump MAC registers */ + void (*dump_regs) (unsigned long ioaddr); + /* Handle extra events on specific interrupts hw dependent */ + void (*host_irq_status) (unsigned long ioaddr); /* Multicast filter setting */ void (*set_filter) (struct net_device *dev); /* Flow control setting */ @@ -298,9 +305,9 @@ struct stmmac_ops { void (*pmt) (unsigned long ioaddr, unsigned long mode); /* Set/Get Unicast MAC addresses */ void (*set_umac_addr) (unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n); + unsigned int reg_n); void (*get_umac_addr) (unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n); + unsigned int reg_n); }; struct mac_link { @@ -314,16 +321,13 @@ struct mii_regs { unsigned int data; /* MII Data */ }; -struct hw_cap { - unsigned int version; /* Core Version register (GMAC) */ - unsigned int pmt; /* Power-Down mode (GMAC) */ - struct mac_link link; - struct mii_regs mii; -}; - struct mac_device_info { - struct hw_cap hw; - struct stmmac_ops *ops; + struct stmmac_ops *mac; + struct stmmac_desc_ops *desc; + struct stmmac_dma_ops *dma; + unsigned int pmt; /* support Power-Down */ + struct mii_regs mii; /* MII register Addresses */ + struct mac_link link; }; struct mac_device_info *gmac_setup(unsigned long addr); diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c index c1278876ef25..cf199d969227 100644 --- a/drivers/net/stmmac/gmac.c +++ b/drivers/net/stmmac/gmac.c @@ -630,19 +630,28 @@ static int gmac_get_rx_frame_len(struct dma_desc *p) return p->des01.erx.frame_length; } -struct stmmac_ops gmac_driver = { +struct stmmac_ops gmac_ops = { .core_init = gmac_core_init, - .dump_mac_regs = gmac_dump_regs, - .dma_init = gmac_dma_init, - .dump_dma_regs = gmac_dump_dma_regs, + .dump_regs = gmac_dump_regs, + .host_irq_status = gmac_irq_status, + .set_filter = gmac_set_filter, + .flow_ctrl = gmac_flow_ctrl, + .pmt = gmac_pmt, + .set_umac_addr = gmac_set_umac_addr, + .get_umac_addr = gmac_get_umac_addr, +}; + +struct stmmac_dma_ops gmac_dma_ops = { + .init = gmac_dma_init, + .dump_regs = gmac_dump_dma_regs, .dma_mode = gmac_dma_operation_mode, .dma_diagnostic_fr = gmac_dma_diagnostic_fr, +}; + +struct stmmac_desc_ops gmac_desc_ops = { .tx_status = gmac_get_tx_frame_status, .rx_status = gmac_get_rx_frame_status, .get_tx_len = gmac_get_tx_len, - .set_filter = gmac_set_filter, - .flow_ctrl = gmac_flow_ctrl, - .pmt = gmac_pmt, .init_rx_desc = gmac_init_rx_desc, .init_tx_desc = gmac_init_tx_desc, .get_tx_owner = gmac_get_tx_owner, @@ -655,9 +664,6 @@ struct stmmac_ops gmac_driver = { .set_tx_owner = gmac_set_tx_owner, .set_rx_owner = gmac_set_rx_owner, .get_rx_frame_len = gmac_get_rx_frame_len, - .host_irq_status = gmac_irq_status, - .set_umac_addr = gmac_set_umac_addr, - .get_umac_addr = gmac_get_umac_addr, }; struct mac_device_info *gmac_setup(unsigned long ioaddr) @@ -670,13 +676,16 @@ struct mac_device_info *gmac_setup(unsigned long ioaddr) mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); - mac->ops = &gmac_driver; - mac->hw.pmt = PMT_SUPPORTED; - mac->hw.link.port = GMAC_CONTROL_PS; - mac->hw.link.duplex = GMAC_CONTROL_DM; - mac->hw.link.speed = GMAC_CONTROL_FES; - mac->hw.mii.addr = GMAC_MII_ADDR; - mac->hw.mii.data = GMAC_MII_DATA; + mac->mac = &gmac_ops; + mac->desc = &gmac_desc_ops; + mac->dma = &gmac_dma_ops; + + mac->pmt = PMT_SUPPORTED; + mac->link.port = GMAC_CONTROL_PS; + mac->link.duplex = GMAC_CONTROL_DM; + mac->link.speed = GMAC_CONTROL_FES; + mac->mii.addr = GMAC_MII_ADDR; + mac->mii.data = GMAC_MII_DATA; return mac; } diff --git a/drivers/net/stmmac/mac100.c b/drivers/net/stmmac/mac100.c index 625171b6062b..45d0457ddb6e 100644 --- a/drivers/net/stmmac/mac100.c +++ b/drivers/net/stmmac/mac100.c @@ -467,19 +467,28 @@ static int mac100_get_rx_frame_len(struct dma_desc *p) return p->des01.rx.frame_length; } -struct stmmac_ops mac100_driver = { +struct stmmac_ops mac100_ops = { .core_init = mac100_core_init, - .dump_mac_regs = mac100_dump_mac_regs, - .dma_init = mac100_dma_init, - .dump_dma_regs = mac100_dump_dma_regs, + .dump_regs = mac100_dump_mac_regs, + .host_irq_status = mac100_irq_status, + .set_filter = mac100_set_filter, + .flow_ctrl = mac100_flow_ctrl, + .pmt = mac100_pmt, + .set_umac_addr = mac100_set_umac_addr, + .get_umac_addr = mac100_get_umac_addr, +}; + +struct stmmac_dma_ops mac100_dma_ops = { + .init = mac100_dma_init, + .dump_regs = mac100_dump_dma_regs, .dma_mode = mac100_dma_operation_mode, .dma_diagnostic_fr = mac100_dma_diagnostic_fr, +}; + +struct stmmac_desc_ops mac100_desc_ops = { .tx_status = mac100_get_tx_frame_status, .rx_status = mac100_get_rx_frame_status, .get_tx_len = mac100_get_tx_len, - .set_filter = mac100_set_filter, - .flow_ctrl = mac100_flow_ctrl, - .pmt = mac100_pmt, .init_rx_desc = mac100_init_rx_desc, .init_tx_desc = mac100_init_tx_desc, .get_tx_owner = mac100_get_tx_owner, @@ -492,9 +501,6 @@ struct stmmac_ops mac100_driver = { .set_tx_owner = mac100_set_tx_owner, .set_rx_owner = mac100_set_rx_owner, .get_rx_frame_len = mac100_get_rx_frame_len, - .host_irq_status = mac100_irq_status, - .set_umac_addr = mac100_set_umac_addr, - .get_umac_addr = mac100_get_umac_addr, }; struct mac_device_info *mac100_setup(unsigned long ioaddr) @@ -505,13 +511,16 @@ struct mac_device_info *mac100_setup(unsigned long ioaddr) pr_info("\tMAC 10/100\n"); - mac->ops = &mac100_driver; - mac->hw.pmt = PMT_NOT_SUPPORTED; - mac->hw.link.port = MAC_CONTROL_PS; - mac->hw.link.duplex = MAC_CONTROL_F; - mac->hw.link.speed = 0; - mac->hw.mii.addr = MAC_MII_ADDR; - mac->hw.mii.data = MAC_MII_DATA; + mac->mac = &mac100_ops; + mac->desc = &mac100_desc_ops; + mac->dma = &mac100_dma_ops; + + mac->pmt = PMT_NOT_SUPPORTED; + mac->link.port = MAC_CONTROL_PS; + mac->link.duplex = MAC_CONTROL_F; + mac->link.speed = 0; + mac->mii.addr = MAC_MII_ADDR; + mac->mii.data = MAC_MII_DATA; return mac; } diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 0d5529fa579a..44421d9667a8 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -58,7 +58,7 @@ struct stmmac_priv { int rx_csum; unsigned int dma_buf_sz; struct device *device; - struct mac_device_info *mac_type; + struct mac_device_info *hw; struct stmmac_extra_stats xstats; struct napi_struct napi; diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 694ebe6a0758..9c7ce1ea3aea 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -268,8 +268,8 @@ stmmac_set_pauseparam(struct net_device *netdev, } } else { unsigned long ioaddr = netdev->base_addr; - priv->mac_type->ops->flow_ctrl(ioaddr, phy->duplex, - priv->flow_ctrl, priv->pause); + priv->hw->mac->flow_ctrl(ioaddr, phy->duplex, + priv->flow_ctrl, priv->pause); } spin_unlock(&priv->lock); return ret; @@ -283,8 +283,8 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, int i; /* Update HW stats if supported */ - priv->mac_type->ops->dma_diagnostic_fr(&dev->stats, &priv->xstats, - ioaddr); + priv->hw->dma->dma_diagnostic_fr(&dev->stats, (void *) &priv->xstats, + ioaddr); for (i = 0; i < STMMAC_STATS_LEN; i++) { char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset; diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 82ebbc0c8839..86e910300969 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -225,38 +225,34 @@ static void stmmac_adjust_link(struct net_device *dev) if (phydev->duplex != priv->oldduplex) { new_state = 1; if (!(phydev->duplex)) - ctrl &= ~priv->mac_type->hw.link.duplex; + ctrl &= ~priv->hw->link.duplex; else - ctrl |= priv->mac_type->hw.link.duplex; + ctrl |= priv->hw->link.duplex; priv->oldduplex = phydev->duplex; } /* Flow Control operation */ if (phydev->pause) - priv->mac_type->ops->flow_ctrl(ioaddr, phydev->duplex, - fc, pause_time); + priv->hw->mac->flow_ctrl(ioaddr, phydev->duplex, + fc, pause_time); if (phydev->speed != priv->speed) { new_state = 1; switch (phydev->speed) { case 1000: if (likely(priv->is_gmac)) - ctrl &= ~priv->mac_type->hw.link.port; + ctrl &= ~priv->hw->link.port; break; case 100: case 10: if (priv->is_gmac) { - ctrl |= priv->mac_type->hw.link.port; + ctrl |= priv->hw->link.port; if (phydev->speed == SPEED_100) { - ctrl |= - priv->mac_type->hw.link. - speed; + ctrl |= priv->hw->link.speed; } else { - ctrl &= - ~(priv->mac_type->hw. - link.speed); + ctrl &= ~(priv->hw->link.speed); } } else { - ctrl &= ~priv->mac_type->hw.link.port; + ctrl &= ~priv->hw->link.port; } if (likely(priv->fix_mac_speed)) priv->fix_mac_speed(priv->bsp_priv, @@ -509,8 +505,8 @@ static void init_dma_desc_rings(struct net_device *dev) priv->cur_tx = 0; /* Clear the Rx/Tx descriptors */ - priv->mac_type->ops->init_rx_desc(priv->dma_rx, rxsize, dis_ic); - priv->mac_type->ops->init_tx_desc(priv->dma_tx, txsize); + priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic); + priv->hw->desc->init_tx_desc(priv->dma_tx, txsize); if (netif_msg_hw(priv)) { pr_info("RX descriptor ring:\n"); @@ -545,8 +541,8 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv) struct dma_desc *p = priv->dma_tx + i; if (p->des2) dma_unmap_single(priv->device, p->des2, - priv->mac_type->ops->get_tx_len(p), - DMA_TO_DEVICE); + priv->hw->desc->get_tx_len(p), + DMA_TO_DEVICE); dev_kfree_skb_any(priv->tx_skbuff[i]); priv->tx_skbuff[i] = NULL; } @@ -630,18 +626,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) { if (!priv->is_gmac) { /* MAC 10/100 */ - priv->mac_type->ops->dma_mode(priv->dev->base_addr, tc, 0); + priv->hw->dma->dma_mode(priv->dev->base_addr, tc, 0); priv->tx_coe = NO_HW_CSUM; } else { if ((priv->dev->mtu <= ETH_DATA_LEN) && (tx_coe)) { - priv->mac_type->ops->dma_mode(priv->dev->base_addr, - SF_DMA_MODE, SF_DMA_MODE); + priv->hw->dma->dma_mode(priv->dev->base_addr, + SF_DMA_MODE, SF_DMA_MODE); tc = SF_DMA_MODE; priv->tx_coe = HW_CSUM; } else { /* Checksum computation is performed in software. */ - priv->mac_type->ops->dma_mode(priv->dev->base_addr, tc, - SF_DMA_MODE); + priv->hw->dma->dma_mode(priv->dev->base_addr, tc, + SF_DMA_MODE); priv->tx_coe = NO_HW_CSUM; } } @@ -749,16 +745,16 @@ static void stmmac_tx(struct stmmac_priv *priv) struct dma_desc *p = priv->dma_tx + entry; /* Check if the descriptor is owned by the DMA. */ - if (priv->mac_type->ops->get_tx_owner(p)) + if (priv->hw->desc->get_tx_owner(p)) break; /* Verify tx error by looking at the last segment */ - last = priv->mac_type->ops->get_tx_ls(p); + last = priv->hw->desc->get_tx_ls(p); if (likely(last)) { int tx_error = - priv->mac_type->ops->tx_status(&priv->dev->stats, - &priv->xstats, - p, ioaddr); + priv->hw->desc->tx_status(&priv->dev->stats, + &priv->xstats, p, + ioaddr); if (likely(tx_error == 0)) { priv->dev->stats.tx_packets++; priv->xstats.tx_pkt_n++; @@ -770,7 +766,7 @@ static void stmmac_tx(struct stmmac_priv *priv) if (likely(p->des2)) dma_unmap_single(priv->device, p->des2, - priv->mac_type->ops->get_tx_len(p), + priv->hw->desc->get_tx_len(p), DMA_TO_DEVICE); if (unlikely(p->des3)) p->des3 = 0; @@ -791,7 +787,7 @@ static void stmmac_tx(struct stmmac_priv *priv) priv->tx_skbuff[entry] = NULL; } - priv->mac_type->ops->release_tx_desc(p); + priv->hw->desc->release_tx_desc(p); entry = (++priv->dirty_tx) % txsize; } @@ -833,7 +829,7 @@ static int stmmac_has_work(struct stmmac_priv *priv) unsigned int has_work = 0; int rxret, tx_work = 0; - rxret = priv->mac_type->ops->get_rx_owner(priv->dma_rx + + rxret = priv->hw->desc->get_rx_owner(priv->dma_rx + (priv->cur_rx % priv->dma_rx_size)); if (priv->dirty_tx != priv->cur_tx) @@ -886,7 +882,7 @@ static void stmmac_tx_err(struct stmmac_priv *priv) stmmac_dma_stop_tx(priv->dev->base_addr); dma_free_tx_skbufs(priv); - priv->mac_type->ops->init_tx_desc(priv->dma_tx, priv->dma_tx_size); + priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); priv->dirty_tx = 0; priv->cur_tx = 0; stmmac_dma_start_tx(priv->dev->base_addr); @@ -926,8 +922,8 @@ static void stmmac_dma_interrupt(struct net_device *dev) if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { /* Try to bump up the threshold */ tc += 64; - priv->mac_type->ops->dma_mode(ioaddr, tc, - SF_DMA_MODE); + priv->hw->dma->dma_mode(ioaddr, tc, + SF_DMA_MODE); priv->xstats.threshold = tc; } stmmac_tx_err(priv); @@ -1059,20 +1055,20 @@ static int stmmac_open(struct net_device *dev) init_dma_desc_rings(dev); /* DMA initialization and SW reset */ - if (unlikely(priv->mac_type->ops->dma_init(ioaddr, - priv->pbl, priv->dma_tx_phy, priv->dma_rx_phy) < 0)) { + if (unlikely(priv->hw->dma->init(ioaddr, priv->pbl, priv->dma_tx_phy, + priv->dma_rx_phy) < 0)) { pr_err("%s: DMA initialization failed\n", __func__); return -1; } /* Copy the MAC addr into the HW */ - priv->mac_type->ops->set_umac_addr(ioaddr, dev->dev_addr, 0); + priv->hw->mac->set_umac_addr(ioaddr, dev->dev_addr, 0); /* If required, perform hw setup of the bus. */ if (priv->bus_setup) priv->bus_setup(ioaddr); /* Initialize the MAC Core */ - priv->mac_type->ops->core_init(ioaddr); + priv->hw->mac->core_init(ioaddr); priv->shutdown = 0; @@ -1101,8 +1097,8 @@ static int stmmac_open(struct net_device *dev) #endif /* Dump DMA/MAC registers */ if (netif_msg_hw(priv)) { - priv->mac_type->ops->dump_mac_regs(ioaddr); - priv->mac_type->ops->dump_dma_regs(ioaddr); + priv->hw->mac->dump_regs(ioaddr); + priv->hw->dma->dump_regs(ioaddr); } if (priv->phydev) @@ -1218,8 +1214,8 @@ static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb, desc->des2 = dma_map_single(priv->device, skb->data, BUF_SIZE_8KiB, DMA_TO_DEVICE); desc->des3 = desc->des2 + BUF_SIZE_4KiB; - priv->mac_type->ops->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB, - csum_insertion); + priv->hw->desc->prepare_tx_desc(desc, 1, BUF_SIZE_8KiB, + csum_insertion); entry = (++priv->cur_tx) % txsize; desc = priv->dma_tx + entry; @@ -1228,16 +1224,17 @@ static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb, skb->data + BUF_SIZE_8KiB, buf2_size, DMA_TO_DEVICE); desc->des3 = desc->des2 + BUF_SIZE_4KiB; - priv->mac_type->ops->prepare_tx_desc(desc, 0, - buf2_size, csum_insertion); - priv->mac_type->ops->set_tx_owner(desc); + priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size, + csum_insertion); + priv->hw->desc->set_tx_owner(desc); + priv->tx_skbuff[entry] = NULL; } else { desc->des2 = dma_map_single(priv->device, skb->data, nopaged_len, DMA_TO_DEVICE); desc->des3 = desc->des2 + BUF_SIZE_4KiB; - priv->mac_type->ops->prepare_tx_desc(desc, 1, nopaged_len, - csum_insertion); + priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, + csum_insertion); } return entry; } @@ -1305,8 +1302,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int nopaged_len = skb_headlen(skb); desc->des2 = dma_map_single(priv->device, skb->data, nopaged_len, DMA_TO_DEVICE); - priv->mac_type->ops->prepare_tx_desc(desc, 1, nopaged_len, - csum_insertion); + priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, + csum_insertion); } for (i = 0; i < nfrags; i++) { @@ -1321,21 +1318,20 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) frag->page_offset, len, DMA_TO_DEVICE); priv->tx_skbuff[entry] = NULL; - priv->mac_type->ops->prepare_tx_desc(desc, 0, len, - csum_insertion); - priv->mac_type->ops->set_tx_owner(desc); + priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion); + priv->hw->desc->set_tx_owner(desc); } /* Interrupt on completition only for the latest segment */ - priv->mac_type->ops->close_tx_desc(desc); + priv->hw->desc->close_tx_desc(desc); #ifdef CONFIG_STMMAC_TIMER /* Clean IC while using timer */ if (likely(priv->tm->enable)) - priv->mac_type->ops->clear_tx_ic(desc); + priv->hw->desc->clear_tx_ic(desc); #endif /* To avoid raise condition */ - priv->mac_type->ops->set_tx_owner(first); + priv->hw->desc->set_tx_owner(first); priv->cur_tx++; @@ -1395,7 +1391,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) } RX_DBG(KERN_INFO "\trefill entry #%d\n", entry); } - priv->mac_type->ops->set_rx_owner(p + entry); + priv->hw->desc->set_rx_owner(p + entry); } return; } @@ -1416,7 +1412,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) } #endif count = 0; - while (!priv->mac_type->ops->get_rx_owner(p)) { + while (!priv->hw->desc->get_rx_owner(p)) { int status; if (count >= limit) @@ -1429,15 +1425,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) prefetch(p_next); /* read the status of the incoming frame */ - status = (priv->mac_type->ops->rx_status(&priv->dev->stats, - &priv->xstats, p)); + status = (priv->hw->desc->rx_status(&priv->dev->stats, + &priv->xstats, p)); if (unlikely(status == discard_frame)) priv->dev->stats.rx_errors++; else { struct sk_buff *skb; /* Length should omit the CRC */ - int frame_len = - priv->mac_type->ops->get_rx_frame_len(p) - 4; + int frame_len = priv->hw->desc->get_rx_frame_len(p) - 4; #ifdef STMMAC_RX_DEBUG if (frame_len > ETH_FRAME_LEN) @@ -1573,7 +1568,7 @@ static void stmmac_multicast_list(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); spin_lock(&priv->lock); - priv->mac_type->ops->set_filter(dev); + priv->hw->mac->set_filter(dev); spin_unlock(&priv->lock); return; } @@ -1627,7 +1622,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) if (priv->is_gmac) { unsigned long ioaddr = dev->base_addr; /* To handle GMAC own interrupts */ - priv->mac_type->ops->host_irq_status(ioaddr); + priv->hw->mac->host_irq_status(ioaddr); } stmmac_dma_interrupt(dev); @@ -1748,7 +1743,7 @@ static int stmmac_probe(struct net_device *dev) netif_napi_add(dev, &priv->napi, stmmac_poll, 64); /* Get the MAC address */ - priv->mac_type->ops->get_umac_addr(dev->base_addr, dev->dev_addr, 0); + priv->hw->mac->get_umac_addr(dev->base_addr, dev->dev_addr, 0); if (!is_valid_ether_addr(dev->dev_addr)) pr_warning("\tno valid MAC address;" @@ -1790,9 +1785,9 @@ static int stmmac_mac_device_setup(struct net_device *dev) if (!device) return -ENOMEM; - priv->mac_type = device; + priv->hw = device; - priv->wolenabled = priv->mac_type->hw.pmt; /* PMT supported */ + priv->wolenabled = priv->hw->pmt; /* PMT supported */ if (priv->wolenabled == PMT_SUPPORTED) priv->wolopts = WAKE_MAGIC; /* Magic Frame */ @@ -2048,18 +2043,17 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) stmmac_dma_stop_tx(dev->base_addr); stmmac_dma_stop_rx(dev->base_addr); /* Clear the Rx/Tx descriptors */ - priv->mac_type->ops->init_rx_desc(priv->dma_rx, - priv->dma_rx_size, dis_ic); - priv->mac_type->ops->init_tx_desc(priv->dma_tx, - priv->dma_tx_size); + priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, + dis_ic); + priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); stmmac_mac_disable_tx(dev->base_addr); if (device_may_wakeup(&(pdev->dev))) { /* Enable Power down mode by programming the PMT regs */ if (priv->wolenabled == PMT_SUPPORTED) - priv->mac_type->ops->pmt(dev->base_addr, - priv->wolopts); + priv->hw->mac->pmt(dev->base_addr, + priv->wolopts); } else { stmmac_mac_disable_rx(dev->base_addr); } @@ -2100,7 +2094,7 @@ static int stmmac_resume(struct platform_device *pdev) * from another devices (e.g. serial console). */ if (device_may_wakeup(&(pdev->dev))) if (priv->wolenabled == PMT_SUPPORTED) - priv->mac_type->ops->pmt(dev->base_addr, 0); + priv->hw->mac->pmt(dev->base_addr, 0); netif_device_attach(dev); diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c index 8498552a22fc..131e0a603711 100644 --- a/drivers/net/stmmac/stmmac_mdio.c +++ b/drivers/net/stmmac/stmmac_mdio.c @@ -48,8 +48,8 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); unsigned long ioaddr = ndev->base_addr; - unsigned int mii_address = priv->mac_type->hw.mii.addr; - unsigned int mii_data = priv->mac_type->hw.mii.data; + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; int data; u16 regValue = (((phyaddr << 11) & (0x0000F800)) | @@ -80,8 +80,8 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); unsigned long ioaddr = ndev->base_addr; - unsigned int mii_address = priv->mac_type->hw.mii.addr; - unsigned int mii_data = priv->mac_type->hw.mii.data; + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; u16 value = (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) @@ -112,7 +112,7 @@ static int stmmac_mdio_reset(struct mii_bus *bus) struct net_device *ndev = bus->priv; struct stmmac_priv *priv = netdev_priv(ndev); unsigned long ioaddr = ndev->base_addr; - unsigned int mii_address = priv->mac_type->hw.mii.addr; + unsigned int mii_address = priv->hw->mii.addr; if (priv->phy_reset) { pr_debug("stmmac_mdio_reset: calling phy_reset\n"); -- cgit v1.2.3 From aec7ff278145280c2c78377aeb98feed02c8b636 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:18 +0000 Subject: stmmac: move the dma out from the main This patch moves the dma related functions (interrupt, start, stop etc.) out from the main driver code. This will help to support new DMA engines. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/Makefile | 2 +- drivers/net/stmmac/common.h | 209 ++++++++-------------------- drivers/net/stmmac/dwmac_dma.h | 107 ++++++++++++++ drivers/net/stmmac/dwmac_lib.c | 263 +++++++++++++++++++++++++++++++++++ drivers/net/stmmac/gmac.c | 9 ++ drivers/net/stmmac/mac100.c | 9 ++ drivers/net/stmmac/stmmac_ethtool.c | 1 + drivers/net/stmmac/stmmac_main.c | 268 +++++------------------------------- 8 files changed, 481 insertions(+), 387 deletions(-) create mode 100644 drivers/net/stmmac/dwmac_dma.h create mode 100644 drivers/net/stmmac/dwmac_lib.c diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile index b2d7a5564dfa..c8f499a71251 100644 --- a/drivers/net/stmmac/Makefile +++ b/drivers/net/stmmac/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o -stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \ +stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o dwmac_lib.o \ mac100.o gmac.o $(stmmac-y) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 95782ccf44b4..6f8fe64dd226 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -25,131 +25,6 @@ #include "descs.h" #include -/* ********************************************* - DMA CRS Control and Status Register Mapping - * *********************************************/ -#define DMA_BUS_MODE 0x00001000 /* Bus Mode */ -#define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */ -#define DMA_RCV_POLL_DEMAND 0x00001008 /* Received Poll Demand */ -#define DMA_RCV_BASE_ADDR 0x0000100c /* Receive List Base */ -#define DMA_TX_BASE_ADDR 0x00001010 /* Transmit List Base */ -#define DMA_STATUS 0x00001014 /* Status Register */ -#define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */ -#define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */ -#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ -#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ -#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ - -/* ******************************** - DMA Control register defines - * ********************************/ -#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */ -#define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */ - -/* ************************************** - DMA Interrupt Enable register defines - * **************************************/ -/**** NORMAL INTERRUPT ****/ -#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */ -#define DMA_INTR_ENA_TIE 0x00000001 /* Transmit Interrupt */ -#define DMA_INTR_ENA_TUE 0x00000004 /* Transmit Buffer Unavailable */ -#define DMA_INTR_ENA_RIE 0x00000040 /* Receive Interrupt */ -#define DMA_INTR_ENA_ERE 0x00004000 /* Early Receive */ - -#define DMA_INTR_NORMAL (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \ - DMA_INTR_ENA_TIE) - -/**** ABNORMAL INTERRUPT ****/ -#define DMA_INTR_ENA_AIE 0x00008000 /* Abnormal Summary */ -#define DMA_INTR_ENA_FBE 0x00002000 /* Fatal Bus Error */ -#define DMA_INTR_ENA_ETE 0x00000400 /* Early Transmit */ -#define DMA_INTR_ENA_RWE 0x00000200 /* Receive Watchdog */ -#define DMA_INTR_ENA_RSE 0x00000100 /* Receive Stopped */ -#define DMA_INTR_ENA_RUE 0x00000080 /* Receive Buffer Unavailable */ -#define DMA_INTR_ENA_UNE 0x00000020 /* Tx Underflow */ -#define DMA_INTR_ENA_OVE 0x00000010 /* Receive Overflow */ -#define DMA_INTR_ENA_TJE 0x00000008 /* Transmit Jabber */ -#define DMA_INTR_ENA_TSE 0x00000002 /* Transmit Stopped */ - -#define DMA_INTR_ABNORMAL (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \ - DMA_INTR_ENA_UNE) - -/* DMA default interrupt mask */ -#define DMA_INTR_DEFAULT_MASK (DMA_INTR_NORMAL | DMA_INTR_ABNORMAL) - -/* **************************** - * DMA Status register defines - * ****************************/ -#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */ -#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */ -#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int. */ -#define DMA_STATUS_GMI 0x08000000 -#define DMA_STATUS_GLI 0x04000000 -#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ -#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ -#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ -#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */ -#define DMA_STATUS_TS_SHIFT 20 -#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */ -#define DMA_STATUS_RS_SHIFT 17 -#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */ -#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */ -#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */ -#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */ -#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */ -#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */ -#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */ -#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */ -#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */ -#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */ -#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */ -#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */ -#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */ -#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */ -#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ - -/* Other defines */ -#define HASH_TABLE_SIZE 64 -#define PAUSE_TIME 0x200 - -/* Flow Control defines */ -#define FLOW_OFF 0 -#define FLOW_RX 1 -#define FLOW_TX 2 -#define FLOW_AUTO (FLOW_TX | FLOW_RX) - -/* DMA STORE-AND-FORWARD Operation Mode */ -#define SF_DMA_MODE 1 - -#define HW_CSUM 1 -#define NO_HW_CSUM 0 - -/* GMAC TX FIFO is 8K, Rx FIFO is 16K */ -#define BUF_SIZE_16KiB 16384 -#define BUF_SIZE_8KiB 8192 -#define BUF_SIZE_4KiB 4096 -#define BUF_SIZE_2KiB 2048 - -/* Power Down and WOL */ -#define PMT_NOT_SUPPORTED 0 -#define PMT_SUPPORTED 1 - -/* Common MAC defines */ -#define MAC_CTRL_REG 0x00000000 /* MAC Control */ -#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */ -#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */ - -/* MAC Management Counters register */ -#define MMC_CONTROL 0x00000100 /* MMC Control */ -#define MMC_HIGH_INTR 0x00000104 /* MMC High Interrupt */ -#define MMC_LOW_INTR 0x00000108 /* MMC Low Interrupt */ -#define MMC_HIGH_INTR_MASK 0x0000010c /* MMC High Interrupt Mask */ -#define MMC_LOW_INTR_MASK 0x00000110 /* MMC Low Interrupt Mask */ - -#define MMC_CONTROL_MAX_FRM_MASK 0x0003ff8 /* Maximum Frame Size */ -#define MMC_CONTROL_MAX_FRM_SHIFT 3 -#define MMC_CONTROL_MAX_FRAME 0x7FF - struct stmmac_extra_stats { /* Transmit errors */ unsigned long tx_underflow ____cacheline_aligned; @@ -198,46 +73,56 @@ struct stmmac_extra_stats { unsigned long normal_irq_n; }; -/* GMAC core can compute the checksums in HW. */ -enum rx_frame_status { +#define HASH_TABLE_SIZE 64 +#define PAUSE_TIME 0x200 + +/* Flow Control defines */ +#define FLOW_OFF 0 +#define FLOW_RX 1 +#define FLOW_TX 2 +#define FLOW_AUTO (FLOW_TX | FLOW_RX) + +#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ + +#define HW_CSUM 1 +#define NO_HW_CSUM 0 +enum rx_frame_status { /* IPC status */ good_frame = 0, discard_frame = 1, csum_none = 2, }; -static inline void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], - unsigned int high, unsigned int low) -{ - unsigned long data; - - data = (addr[5] << 8) | addr[4]; - writel(data, ioaddr + high); - data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; - writel(data, ioaddr + low); +enum tx_dma_irq_status { + tx_hard_error = 1, + tx_hard_error_bump_tc = 2, + handle_tx_rx = 3, +}; - return; -} +/* GMAC TX FIFO is 8K, Rx FIFO is 16K */ +#define BUF_SIZE_16KiB 16384 +#define BUF_SIZE_8KiB 8192 +#define BUF_SIZE_4KiB 4096 +#define BUF_SIZE_2KiB 2048 -static inline void stmmac_get_mac_addr(unsigned long ioaddr, - unsigned char *addr, unsigned int high, - unsigned int low) -{ - unsigned int hi_addr, lo_addr; +/* Power Down and WOL */ +#define PMT_NOT_SUPPORTED 0 +#define PMT_SUPPORTED 1 - /* Read the MAC address from the hardware */ - hi_addr = readl(ioaddr + high); - lo_addr = readl(ioaddr + low); +/* Common MAC defines */ +#define MAC_CTRL_REG 0x00000000 /* MAC Control */ +#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */ +#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */ - /* Extract the MAC address from the high and low words */ - addr[0] = lo_addr & 0xff; - addr[1] = (lo_addr >> 8) & 0xff; - addr[2] = (lo_addr >> 16) & 0xff; - addr[3] = (lo_addr >> 24) & 0xff; - addr[4] = hi_addr & 0xff; - addr[5] = (hi_addr >> 8) & 0xff; +/* MAC Management Counters register */ +#define MMC_CONTROL 0x00000100 /* MMC Control */ +#define MMC_HIGH_INTR 0x00000104 /* MMC High Interrupt */ +#define MMC_LOW_INTR 0x00000108 /* MMC Low Interrupt */ +#define MMC_HIGH_INTR_MASK 0x0000010c /* MMC High Interrupt Mask */ +#define MMC_LOW_INTR_MASK 0x00000110 /* MMC Low Interrupt Mask */ - return; -} +#define MMC_CONTROL_MAX_FRM_MASK 0x0003ff8 /* Maximum Frame Size */ +#define MMC_CONTROL_MAX_FRM_SHIFT 3 +#define MMC_CONTROL_MAX_FRAME 0x7FF struct stmmac_desc_ops { /* DMA RX descriptor ring initialization */ @@ -287,6 +172,15 @@ struct stmmac_dma_ops { /* To track extra statistic (if supported) */ void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, unsigned long ioaddr); + void (*enable_dma_transmission) (unsigned long ioaddr); + void (*enable_dma_irq) (unsigned long ioaddr); + void (*disable_dma_irq) (unsigned long ioaddr); + void (*start_tx) (unsigned long ioaddr); + void (*stop_tx) (unsigned long ioaddr); + void (*start_rx) (unsigned long ioaddr); + void (*stop_rx) (unsigned long ioaddr); + int (*dma_interrupt) (unsigned long ioaddr, + struct stmmac_extra_stats *x); }; struct stmmac_ops { @@ -332,3 +226,8 @@ struct mac_device_info { struct mac_device_info *gmac_setup(unsigned long addr); struct mac_device_info *mac100_setup(unsigned long addr); + +extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], + unsigned int high, unsigned int low); +extern void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int high, unsigned int low); diff --git a/drivers/net/stmmac/dwmac_dma.h b/drivers/net/stmmac/dwmac_dma.h new file mode 100644 index 000000000000..de848d9f6060 --- /dev/null +++ b/drivers/net/stmmac/dwmac_dma.h @@ -0,0 +1,107 @@ +/******************************************************************************* + DWMAC DMA Header file. + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +/* DMA CRS Control and Status Register Mapping */ +#define DMA_BUS_MODE 0x00001000 /* Bus Mode */ +#define DMA_XMT_POLL_DEMAND 0x00001004 /* Transmit Poll Demand */ +#define DMA_RCV_POLL_DEMAND 0x00001008 /* Received Poll Demand */ +#define DMA_RCV_BASE_ADDR 0x0000100c /* Receive List Base */ +#define DMA_TX_BASE_ADDR 0x00001010 /* Transmit List Base */ +#define DMA_STATUS 0x00001014 /* Status Register */ +#define DMA_CONTROL 0x00001018 /* Ctrl (Operational Mode) */ +#define DMA_INTR_ENA 0x0000101c /* Interrupt Enable */ +#define DMA_MISSED_FRAME_CTR 0x00001020 /* Missed Frame Counter */ +#define DMA_CUR_TX_BUF_ADDR 0x00001050 /* Current Host Tx Buffer */ +#define DMA_CUR_RX_BUF_ADDR 0x00001054 /* Current Host Rx Buffer */ + +/* DMA Control register defines */ +#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */ +#define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */ + +/* DMA Normal interrupt */ +#define DMA_INTR_ENA_NIE 0x00010000 /* Normal Summary */ +#define DMA_INTR_ENA_TIE 0x00000001 /* Transmit Interrupt */ +#define DMA_INTR_ENA_TUE 0x00000004 /* Transmit Buffer Unavailable */ +#define DMA_INTR_ENA_RIE 0x00000040 /* Receive Interrupt */ +#define DMA_INTR_ENA_ERE 0x00004000 /* Early Receive */ + +#define DMA_INTR_NORMAL (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \ + DMA_INTR_ENA_TIE) + +/* DMA Abnormal interrupt */ +#define DMA_INTR_ENA_AIE 0x00008000 /* Abnormal Summary */ +#define DMA_INTR_ENA_FBE 0x00002000 /* Fatal Bus Error */ +#define DMA_INTR_ENA_ETE 0x00000400 /* Early Transmit */ +#define DMA_INTR_ENA_RWE 0x00000200 /* Receive Watchdog */ +#define DMA_INTR_ENA_RSE 0x00000100 /* Receive Stopped */ +#define DMA_INTR_ENA_RUE 0x00000080 /* Receive Buffer Unavailable */ +#define DMA_INTR_ENA_UNE 0x00000020 /* Tx Underflow */ +#define DMA_INTR_ENA_OVE 0x00000010 /* Receive Overflow */ +#define DMA_INTR_ENA_TJE 0x00000008 /* Transmit Jabber */ +#define DMA_INTR_ENA_TSE 0x00000002 /* Transmit Stopped */ + +#define DMA_INTR_ABNORMAL (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \ + DMA_INTR_ENA_UNE) + +/* DMA default interrupt mask */ +#define DMA_INTR_DEFAULT_MASK (DMA_INTR_NORMAL | DMA_INTR_ABNORMAL) + +/* DMA Status register defines */ +#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */ +#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */ +#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */ +#define DMA_STATUS_GMI 0x08000000 +#define DMA_STATUS_GLI 0x04000000 +#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ +#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ +#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ +#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */ +#define DMA_STATUS_TS_SHIFT 20 +#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */ +#define DMA_STATUS_RS_SHIFT 17 +#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */ +#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */ +#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */ +#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */ +#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */ +#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */ +#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */ +#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */ +#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */ +#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */ +#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */ +#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */ +#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */ +#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */ +#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ + +extern void dwmac_enable_dma_transmission(unsigned long ioaddr); +extern void dwmac_enable_dma_irq(unsigned long ioaddr); +extern void dwmac_disable_dma_irq(unsigned long ioaddr); +extern void dwmac_dma_start_tx(unsigned long ioaddr); +extern void dwmac_dma_stop_tx(unsigned long ioaddr); +extern void dwmac_dma_start_rx(unsigned long ioaddr); +extern void dwmac_dma_stop_rx(unsigned long ioaddr); +extern int dwmac_dma_interrupt(unsigned long ioaddr, + struct stmmac_extra_stats *x); diff --git a/drivers/net/stmmac/dwmac_lib.c b/drivers/net/stmmac/dwmac_lib.c new file mode 100644 index 000000000000..d4adb1eaa447 --- /dev/null +++ b/drivers/net/stmmac/dwmac_lib.c @@ -0,0 +1,263 @@ +/******************************************************************************* + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#include +#include "common.h" +#include "dwmac_dma.h" + +#undef DWMAC_DMA_DEBUG +#ifdef DWMAC_DMA_DEBUG +#define DBG(fmt, args...) printk(fmt, ## args) +#else +#define DBG(fmt, args...) do { } while (0) +#endif + +/* CSR1 enables the transmit DMA to check for new descriptor */ +void dwmac_enable_dma_transmission(unsigned long ioaddr) +{ + writel(1, ioaddr + DMA_XMT_POLL_DEMAND); +} + +void dwmac_enable_dma_irq(unsigned long ioaddr) +{ + writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); +} + +void dwmac_disable_dma_irq(unsigned long ioaddr) +{ + writel(0, ioaddr + DMA_INTR_ENA); +} + +void dwmac_dma_start_tx(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + DMA_CONTROL); + value |= DMA_CONTROL_ST; + writel(value, ioaddr + DMA_CONTROL); + return; +} + +void dwmac_dma_stop_tx(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + DMA_CONTROL); + value &= ~DMA_CONTROL_ST; + writel(value, ioaddr + DMA_CONTROL); + return; +} + +void dwmac_dma_start_rx(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + DMA_CONTROL); + value |= DMA_CONTROL_SR; + writel(value, ioaddr + DMA_CONTROL); + + return; +} + +void dwmac_dma_stop_rx(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + DMA_CONTROL); + value &= ~DMA_CONTROL_SR; + writel(value, ioaddr + DMA_CONTROL); + + return; +} + +#ifdef DWMAC_DMA_DEBUG +static void show_tx_process_state(unsigned int status) +{ + unsigned int state; + state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT; + + switch (state) { + case 0: + pr_info("- TX (Stopped): Reset or Stop command\n"); + break; + case 1: + pr_info("- TX (Running):Fetching the Tx desc\n"); + break; + case 2: + pr_info("- TX (Running): Waiting for end of tx\n"); + break; + case 3: + pr_info("- TX (Running): Reading the data " + "and queuing the data into the Tx buf\n"); + break; + case 6: + pr_info("- TX (Suspended): Tx Buff Underflow " + "or an unavailable Transmit descriptor\n"); + break; + case 7: + pr_info("- TX (Running): Closing Tx descriptor\n"); + break; + default: + break; + } + return; +} + +static void show_rx_process_state(unsigned int status) +{ + unsigned int state; + state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT; + + switch (state) { + case 0: + pr_info("- RX (Stopped): Reset or Stop command\n"); + break; + case 1: + pr_info("- RX (Running): Fetching the Rx desc\n"); + break; + case 2: + pr_info("- RX (Running):Checking for end of pkt\n"); + break; + case 3: + pr_info("- RX (Running): Waiting for Rx pkt\n"); + break; + case 4: + pr_info("- RX (Suspended): Unavailable Rx buf\n"); + break; + case 5: + pr_info("- RX (Running): Closing Rx descriptor\n"); + break; + case 6: + pr_info("- RX(Running): Flushing the current frame" + " from the Rx buf\n"); + break; + case 7: + pr_info("- RX (Running): Queuing the Rx frame" + " from the Rx buf into memory\n"); + break; + default: + break; + } + return; +} +#endif + +int dwmac_dma_interrupt(unsigned long ioaddr, + struct stmmac_extra_stats *x) +{ + int ret = 0; + /* read the status register (CSR5) */ + u32 intr_status = readl(ioaddr + DMA_STATUS); + + DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status); +#ifdef DWMAC_DMA_DEBUG + /* It displays the DMA process states (CSR5 register) */ + show_tx_process_state(intr_status); + show_rx_process_state(intr_status); +#endif + /* ABNORMAL interrupts */ + if (unlikely(intr_status & DMA_STATUS_AIS)) { + DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: "); + if (unlikely(intr_status & DMA_STATUS_UNF)) { + DBG(INFO, "transmit underflow\n"); + ret = tx_hard_error_bump_tc; + x->tx_undeflow_irq++; + } + if (unlikely(intr_status & DMA_STATUS_TJT)) { + DBG(INFO, "transmit jabber\n"); + x->tx_jabber_irq++; + } + if (unlikely(intr_status & DMA_STATUS_OVF)) { + DBG(INFO, "recv overflow\n"); + x->rx_overflow_irq++; + } + if (unlikely(intr_status & DMA_STATUS_RU)) { + DBG(INFO, "receive buffer unavailable\n"); + x->rx_buf_unav_irq++; + } + if (unlikely(intr_status & DMA_STATUS_RPS)) { + DBG(INFO, "receive process stopped\n"); + x->rx_process_stopped_irq++; + } + if (unlikely(intr_status & DMA_STATUS_RWT)) { + DBG(INFO, "receive watchdog\n"); + x->rx_watchdog_irq++; + } + if (unlikely(intr_status & DMA_STATUS_ETI)) { + DBG(INFO, "transmit early interrupt\n"); + x->tx_early_irq++; + } + if (unlikely(intr_status & DMA_STATUS_TPS)) { + DBG(INFO, "transmit process stopped\n"); + x->tx_process_stopped_irq++; + ret = tx_hard_error; + } + if (unlikely(intr_status & DMA_STATUS_FBI)) { + DBG(INFO, "fatal bus error\n"); + x->fatal_bus_error_irq++; + ret = tx_hard_error; + } + } + /* TX/RX NORMAL interrupts */ + if (intr_status & DMA_STATUS_NIS) { + x->normal_irq_n++; + if (likely((intr_status & DMA_STATUS_RI) || + (intr_status & (DMA_STATUS_TI)))) + ret = handle_tx_rx; + } + /* Optional hardware blocks, interrupts should be disabled */ + if (unlikely(intr_status & + (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) + pr_info("%s: unexpected status %08x\n", __func__, intr_status); + /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ + writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS); + + DBG(INFO, "\n\n"); + return ret; +} + + +void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], + unsigned int high, unsigned int low) +{ + unsigned long data; + + data = (addr[5] << 8) | addr[4]; + writel(data, ioaddr + high); + data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; + writel(data, ioaddr + low); + + return; +} + +void stmmac_get_mac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int high, unsigned int low) +{ + unsigned int hi_addr, lo_addr; + + /* Read the MAC address from the hardware */ + hi_addr = readl(ioaddr + high); + lo_addr = readl(ioaddr + low); + + /* Extract the MAC address from the high and low words */ + addr[0] = lo_addr & 0xff; + addr[1] = (lo_addr >> 8) & 0xff; + addr[2] = (lo_addr >> 16) & 0xff; + addr[3] = (lo_addr >> 24) & 0xff; + addr[4] = hi_addr & 0xff; + addr[5] = (hi_addr >> 8) & 0xff; + + return; +} + diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c index cf199d969227..07880922ff46 100644 --- a/drivers/net/stmmac/gmac.c +++ b/drivers/net/stmmac/gmac.c @@ -31,6 +31,7 @@ #include "stmmac.h" #include "gmac.h" +#include "dwmac_dma.h" #undef GMAC_DEBUG /*#define GMAC_DEBUG*/ @@ -646,6 +647,14 @@ struct stmmac_dma_ops gmac_dma_ops = { .dump_regs = gmac_dump_dma_regs, .dma_mode = gmac_dma_operation_mode, .dma_diagnostic_fr = gmac_dma_diagnostic_fr, + .enable_dma_transmission = dwmac_enable_dma_transmission, + .enable_dma_irq = dwmac_enable_dma_irq, + .disable_dma_irq = dwmac_disable_dma_irq, + .start_tx = dwmac_dma_start_tx, + .stop_tx = dwmac_dma_stop_tx, + .start_rx = dwmac_dma_start_rx, + .stop_rx = dwmac_dma_stop_rx, + .dma_interrupt = dwmac_dma_interrupt, }; struct stmmac_desc_ops gmac_desc_ops = { diff --git a/drivers/net/stmmac/mac100.c b/drivers/net/stmmac/mac100.c index 45d0457ddb6e..b675f7c67f6e 100644 --- a/drivers/net/stmmac/mac100.c +++ b/drivers/net/stmmac/mac100.c @@ -33,6 +33,7 @@ #include "common.h" #include "mac100.h" +#include "dwmac_dma.h" #undef MAC100_DEBUG /*#define MAC100_DEBUG*/ @@ -483,6 +484,14 @@ struct stmmac_dma_ops mac100_dma_ops = { .dump_regs = mac100_dump_dma_regs, .dma_mode = mac100_dma_operation_mode, .dma_diagnostic_fr = mac100_dma_diagnostic_fr, + .enable_dma_transmission = dwmac_enable_dma_transmission, + .enable_dma_irq = dwmac_enable_dma_irq, + .disable_dma_irq = dwmac_disable_dma_irq, + .start_tx = dwmac_dma_start_tx, + .stop_tx = dwmac_dma_stop_tx, + .start_rx = dwmac_dma_start_rx, + .stop_rx = dwmac_dma_stop_rx, + .dma_interrupt = dwmac_dma_interrupt, }; struct stmmac_desc_ops mac100_desc_ops = { diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 9c7ce1ea3aea..0abeff6193a1 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -28,6 +28,7 @@ #include #include "stmmac.h" +#include "dwmac_dma.h" #define REG_SPACE_SIZE 0x1054 #define MAC100_ETHTOOL_NAME "st_mac100" diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 86e910300969..e6c5a3cf4af2 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -571,50 +571,6 @@ static void free_dma_desc_resources(struct stmmac_priv *priv) return; } -/** - * stmmac_dma_start_tx - * @ioaddr: device I/O address - * Description: this function starts the DMA tx process. - */ -static void stmmac_dma_start_tx(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + DMA_CONTROL); - value |= DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); - return; -} - -static void stmmac_dma_stop_tx(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + DMA_CONTROL); - value &= ~DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); - return; -} - -/** - * stmmac_dma_start_rx - * @ioaddr: device I/O address - * Description: this function starts the DMA rx process. - */ -static void stmmac_dma_start_rx(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + DMA_CONTROL); - value |= DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CONTROL); - - return; -} - -static void stmmac_dma_stop_rx(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + DMA_CONTROL); - value &= ~DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CONTROL); - - return; -} - /** * stmmac_dma_operation_mode - HW DMA operation mode * @priv : pointer to the private device structure. @@ -646,88 +602,6 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) return; } -#ifdef STMMAC_DEBUG -/** - * show_tx_process_state - * @status: tx descriptor status field - * Description: it shows the Transmit Process State for CSR5[22:20] - */ -static void show_tx_process_state(unsigned int status) -{ - unsigned int state; - state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT; - - switch (state) { - case 0: - pr_info("- TX (Stopped): Reset or Stop command\n"); - break; - case 1: - pr_info("- TX (Running):Fetching the Tx desc\n"); - break; - case 2: - pr_info("- TX (Running): Waiting for end of tx\n"); - break; - case 3: - pr_info("- TX (Running): Reading the data " - "and queuing the data into the Tx buf\n"); - break; - case 6: - pr_info("- TX (Suspended): Tx Buff Underflow " - "or an unavailable Transmit descriptor\n"); - break; - case 7: - pr_info("- TX (Running): Closing Tx descriptor\n"); - break; - default: - break; - } - return; -} - -/** - * show_rx_process_state - * @status: rx descriptor status field - * Description: it shows the Receive Process State for CSR5[19:17] - */ -static void show_rx_process_state(unsigned int status) -{ - unsigned int state; - state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT; - - switch (state) { - case 0: - pr_info("- RX (Stopped): Reset or Stop command\n"); - break; - case 1: - pr_info("- RX (Running): Fetching the Rx desc\n"); - break; - case 2: - pr_info("- RX (Running):Checking for end of pkt\n"); - break; - case 3: - pr_info("- RX (Running): Waiting for Rx pkt\n"); - break; - case 4: - pr_info("- RX (Suspended): Unavailable Rx buf\n"); - break; - case 5: - pr_info("- RX (Running): Closing Rx descriptor\n"); - break; - case 6: - pr_info("- RX(Running): Flushing the current frame" - " from the Rx buf\n"); - break; - case 7: - pr_info("- RX (Running): Queuing the Rx frame" - " from the Rx buf into memory\n"); - break; - default: - break; - } - return; -} -#endif - /** * stmmac_tx: * @priv: private driver structure @@ -811,7 +685,7 @@ static inline void stmmac_enable_irq(struct stmmac_priv *priv) priv->tm->timer_start(tmrate); else #endif - writel(DMA_INTR_DEFAULT_MASK, priv->dev->base_addr + DMA_INTR_ENA); + priv->hw->dma->enable_dma_irq(priv->dev->base_addr); } static inline void stmmac_disable_irq(struct stmmac_priv *priv) @@ -821,7 +695,7 @@ static inline void stmmac_disable_irq(struct stmmac_priv *priv) priv->tm->timer_stop(); else #endif - writel(0, priv->dev->base_addr + DMA_INTR_ENA); + priv->hw->dma->disable_dma_irq(priv->dev->base_addr); } static int stmmac_has_work(struct stmmac_priv *priv) @@ -880,12 +754,12 @@ static void stmmac_tx_err(struct stmmac_priv *priv) { netif_stop_queue(priv->dev); - stmmac_dma_stop_tx(priv->dev->base_addr); + priv->hw->dma->stop_tx(priv->dev->base_addr); dma_free_tx_skbufs(priv); priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); priv->dirty_tx = 0; priv->cur_tx = 0; - stmmac_dma_start_tx(priv->dev->base_addr); + priv->hw->dma->start_tx(priv->dev->base_addr); priv->dev->stats.tx_errors++; netif_wake_queue(priv->dev); @@ -893,95 +767,27 @@ static void stmmac_tx_err(struct stmmac_priv *priv) return; } -/** - * stmmac_dma_interrupt - Interrupt handler for the driver - * @dev: net device structure - * Description: Interrupt handler for the driver (DMA). - */ -static void stmmac_dma_interrupt(struct net_device *dev) -{ - unsigned long ioaddr = dev->base_addr; - struct stmmac_priv *priv = netdev_priv(dev); - /* read the status register (CSR5) */ - u32 intr_status = readl(ioaddr + DMA_STATUS); - - DBG(intr, INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status); -#ifdef STMMAC_DEBUG - /* It displays the DMA transmit process state (CSR5 register) */ - if (netif_msg_tx_done(priv)) - show_tx_process_state(intr_status); - if (netif_msg_rx_status(priv)) - show_rx_process_state(intr_status); -#endif - /* ABNORMAL interrupts */ - if (unlikely(intr_status & DMA_STATUS_AIS)) { - DBG(intr, INFO, "CSR5[15] DMA ABNORMAL IRQ: "); - if (unlikely(intr_status & DMA_STATUS_UNF)) { - DBG(intr, INFO, "transmit underflow\n"); - if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { - /* Try to bump up the threshold */ - tc += 64; - priv->hw->dma->dma_mode(ioaddr, tc, - SF_DMA_MODE); - priv->xstats.threshold = tc; - } - stmmac_tx_err(priv); - priv->xstats.tx_undeflow_irq++; - } - if (unlikely(intr_status & DMA_STATUS_TJT)) { - DBG(intr, INFO, "transmit jabber\n"); - priv->xstats.tx_jabber_irq++; - } - if (unlikely(intr_status & DMA_STATUS_OVF)) { - DBG(intr, INFO, "recv overflow\n"); - priv->xstats.rx_overflow_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RU)) { - DBG(intr, INFO, "receive buffer unavailable\n"); - priv->xstats.rx_buf_unav_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RPS)) { - DBG(intr, INFO, "receive process stopped\n"); - priv->xstats.rx_process_stopped_irq++; - } - if (unlikely(intr_status & DMA_STATUS_RWT)) { - DBG(intr, INFO, "receive watchdog\n"); - priv->xstats.rx_watchdog_irq++; - } - if (unlikely(intr_status & DMA_STATUS_ETI)) { - DBG(intr, INFO, "transmit early interrupt\n"); - priv->xstats.tx_early_irq++; - } - if (unlikely(intr_status & DMA_STATUS_TPS)) { - DBG(intr, INFO, "transmit process stopped\n"); - priv->xstats.tx_process_stopped_irq++; - stmmac_tx_err(priv); - } - if (unlikely(intr_status & DMA_STATUS_FBI)) { - DBG(intr, INFO, "fatal bus error\n"); - priv->xstats.fatal_bus_error_irq++; - stmmac_tx_err(priv); +static void stmmac_dma_interrupt(struct stmmac_priv *priv) +{ + unsigned long ioaddr = priv->dev->base_addr; + int status; + + status = priv->hw->dma->dma_interrupt(priv->dev->base_addr, + &priv->xstats); + if (likely(status == handle_tx_rx)) + _stmmac_schedule(priv); + + else if (unlikely(status == tx_hard_error_bump_tc)) { + /* Try to bump up the dma threshold on this failure */ + if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { + tc += 64; + priv->hw->dma->dma_mode(ioaddr, tc, SF_DMA_MODE); + priv->xstats.threshold = tc; } - } - - /* TX/RX NORMAL interrupts */ - if (intr_status & DMA_STATUS_NIS) { - priv->xstats.normal_irq_n++; - if (likely((intr_status & DMA_STATUS_RI) || - (intr_status & (DMA_STATUS_TI)))) - _stmmac_schedule(priv); - } - - /* Optional hardware blocks, interrupts should be disabled */ - if (unlikely(intr_status & - (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI))) - pr_info("%s: unexpected status %08x\n", __func__, intr_status); - - /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ - writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS); - - DBG(intr, INFO, "\n\n"); + stmmac_tx_err(priv); + } else if (unlikely(status == tx_hard_error)) + stmmac_tx_err(priv); return; } @@ -1089,8 +895,8 @@ static int stmmac_open(struct net_device *dev) /* Start the ball rolling... */ DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); - stmmac_dma_start_tx(ioaddr); - stmmac_dma_start_rx(ioaddr); + priv->hw->dma->start_tx(ioaddr); + priv->hw->dma->start_rx(ioaddr); #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_start(tmrate); @@ -1142,8 +948,8 @@ static int stmmac_release(struct net_device *dev) free_irq(dev->irq, dev); /* Stop TX/RX DMA and clear the descriptors */ - stmmac_dma_stop_tx(dev->base_addr); - stmmac_dma_stop_rx(dev->base_addr); + priv->hw->dma->stop_tx(dev->base_addr); + priv->hw->dma->stop_rx(dev->base_addr); /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv); @@ -1227,7 +1033,6 @@ static unsigned int stmmac_handle_jumbo_frames(struct sk_buff *skb, priv->hw->desc->prepare_tx_desc(desc, 0, buf2_size, csum_insertion); priv->hw->desc->set_tx_owner(desc); - priv->tx_skbuff[entry] = NULL; } else { desc->des2 = dma_map_single(priv->device, skb->data, @@ -1353,8 +1158,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_bytes += skb->len; - /* CSR1 enables the transmit DMA to check for new descriptor */ - writel(1, dev->base_addr + DMA_XMT_POLL_DEMAND); + priv->hw->dma->enable_dma_transmission(dev->base_addr); return NETDEV_TX_OK; } @@ -1624,7 +1428,8 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) /* To handle GMAC own interrupts */ priv->hw->mac->host_irq_status(ioaddr); } - stmmac_dma_interrupt(dev); + + stmmac_dma_interrupt(priv); return IRQ_HANDLED; } @@ -1988,12 +1793,13 @@ out: static int stmmac_dvr_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); struct resource *res; pr_info("%s:\n\tremoving driver", __func__); - stmmac_dma_stop_rx(ndev->base_addr); - stmmac_dma_stop_tx(ndev->base_addr); + priv->hw->dma->stop_rx(ndev->base_addr); + priv->hw->dma->stop_tx(ndev->base_addr); stmmac_mac_disable_rx(ndev->base_addr); stmmac_mac_disable_tx(ndev->base_addr); @@ -2040,8 +1846,8 @@ static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) napi_disable(&priv->napi); /* Stop TX/RX DMA */ - stmmac_dma_stop_tx(dev->base_addr); - stmmac_dma_stop_rx(dev->base_addr); + priv->hw->dma->stop_tx(dev->base_addr); + priv->hw->dma->stop_rx(dev->base_addr); /* Clear the Rx/Tx descriptors */ priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, dis_ic); @@ -2101,8 +1907,8 @@ static int stmmac_resume(struct platform_device *pdev) /* Enable the MAC and DMA */ stmmac_mac_enable_rx(ioaddr); stmmac_mac_enable_tx(ioaddr); - stmmac_dma_start_tx(ioaddr); - stmmac_dma_start_rx(ioaddr); + priv->hw->dma->start_tx(ioaddr); + priv->hw->dma->start_rx(ioaddr); #ifdef CONFIG_STMMAC_TIMER priv->tm->timer_start(tmrate); -- cgit v1.2.3 From 7e848ae113ca7442ba6b44168fa2238224f37e8a Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:19 +0000 Subject: stmmac: rename mac100 as dwmac100 and fix spare coding style This patch renames the mac100.[ch] as dwmac100.[ch]; this looks more specific and appropriate for these chip series. The patch also fixes some spare coding style issues. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/Makefile | 2 +- drivers/net/stmmac/common.h | 2 +- drivers/net/stmmac/dwmac100.c | 540 +++++++++++++++++++++++++++++++++++++++ drivers/net/stmmac/dwmac100.h | 116 +++++++++ drivers/net/stmmac/mac100.c | 535 -------------------------------------- drivers/net/stmmac/mac100.h | 116 --------- drivers/net/stmmac/stmmac_main.c | 2 +- 7 files changed, 659 insertions(+), 654 deletions(-) create mode 100644 drivers/net/stmmac/dwmac100.c create mode 100644 drivers/net/stmmac/dwmac100.h delete mode 100644 drivers/net/stmmac/mac100.c delete mode 100644 drivers/net/stmmac/mac100.h diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile index c8f499a71251..2ed83859fd59 100644 --- a/drivers/net/stmmac/Makefile +++ b/drivers/net/stmmac/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o dwmac_lib.o \ - mac100.o gmac.o $(stmmac-y) + dwmac100.o gmac.o $(stmmac-y) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 6f8fe64dd226..987faaaa1920 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -225,7 +225,7 @@ struct mac_device_info { }; struct mac_device_info *gmac_setup(unsigned long addr); -struct mac_device_info *mac100_setup(unsigned long addr); +struct mac_device_info *dwmac100_setup(unsigned long addr); extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], unsigned int high, unsigned int low); diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c new file mode 100644 index 000000000000..010c8b206359 --- /dev/null +++ b/drivers/net/stmmac/dwmac100.c @@ -0,0 +1,540 @@ +/******************************************************************************* + This is the driver for the MAC 10/100 on-chip Ethernet controller + currently tested on all the ST boards based on STb7109 and stx7200 SoCs. + + DWC Ether MAC 10/100 Universal version 4.0 has been used for developing + this code. + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#include +#include +#include +#include + +#include "common.h" +#include "dwmac100.h" +#include "dwmac_dma.h" + +#undef DWMAC100_DEBUG +/*#define DWMAC100_DEBUG*/ +#ifdef DWMAC100_DEBUG +#define DBG(fmt, args...) printk(fmt, ## args) +#else +#define DBG(fmt, args...) do { } while (0) +#endif + +static void dwmac100_core_init(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + MAC_CONTROL); + + writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL); + +#ifdef STMMAC_VLAN_TAG_USED + writel(ETH_P_8021Q, ioaddr + MAC_VLAN1); +#endif + return; +} + +static void dwmac100_dump_mac_regs(unsigned long ioaddr) +{ + pr_info("\t----------------------------------------------\n" + "\t DWMAC 100 CSR (base addr = 0x%8x)\n" + "\t----------------------------------------------\n", + (unsigned int)ioaddr); + pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL, + readl(ioaddr + MAC_CONTROL)); + pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH, + readl(ioaddr + MAC_ADDR_HIGH)); + pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW, + readl(ioaddr + MAC_ADDR_LOW)); + pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n", + MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH)); + pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n", + MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW)); + pr_info("\tflow control (offset 0x%x): 0x%08x\n", + MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL)); + pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1, + readl(ioaddr + MAC_VLAN1)); + pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2, + readl(ioaddr + MAC_VLAN2)); + pr_info("\n\tMAC management counter registers\n"); + pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n", + MMC_CONTROL, readl(ioaddr + MMC_CONTROL)); + pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n", + MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR)); + pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n", + MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR)); + pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n", + MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK)); + pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n", + MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK)); + return; +} + +static int dwmac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, + u32 dma_rx) +{ + u32 value = readl(ioaddr + DMA_BUS_MODE); + /* DMA SW reset */ + value |= DMA_BUS_MODE_SFT_RESET; + writel(value, ioaddr + DMA_BUS_MODE); + do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)); + + /* Enable Application Access by writing to DMA CSR0 */ + writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT), + ioaddr + DMA_BUS_MODE); + + /* Mask interrupts by writing to CSR7 */ + writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); + + /* The base address of the RX/TX descriptor lists must be written into + * DMA CSR3 and CSR4, respectively. */ + writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); + writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); + + return 0; +} + +/* Store and Forward capability is not used at all.. + * The transmit threshold can be programmed by + * setting the TTC bits in the DMA control register.*/ +static void dwmac100_dma_operation_mode(unsigned long ioaddr, int txmode, + int rxmode) +{ + u32 csr6 = readl(ioaddr + DMA_CONTROL); + + if (txmode <= 32) + csr6 |= DMA_CONTROL_TTC_32; + else if (txmode <= 64) + csr6 |= DMA_CONTROL_TTC_64; + else + csr6 |= DMA_CONTROL_TTC_128; + + writel(csr6, ioaddr + DMA_CONTROL); + + return; +} + +static void dwmac100_dump_dma_regs(unsigned long ioaddr) +{ + int i; + + DBG(KERN_DEBUG "DWMAC 100 DMA CSR \n"); + for (i = 0; i < 9; i++) + pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i, + (DMA_BUS_MODE + i * 4), + readl(ioaddr + DMA_BUS_MODE + i * 4)); + DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n", + DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR)); + DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n", + DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR)); + return; +} + +/* DMA controller has two counters to track the number of + * the receive missed frames. */ +static void dwmac100_dma_diagnostic_fr(void *data, + struct stmmac_extra_stats *x, + unsigned long ioaddr) +{ + struct net_device_stats *stats = (struct net_device_stats *)data; + u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); + + if (unlikely(csr8)) { + if (csr8 & DMA_MISSED_FRAME_OVE) { + stats->rx_over_errors += 0x800; + x->rx_overflow_cntr += 0x800; + } else { + unsigned int ove_cntr; + ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); + stats->rx_over_errors += ove_cntr; + x->rx_overflow_cntr += ove_cntr; + } + + if (csr8 & DMA_MISSED_FRAME_OVE_M) { + stats->rx_missed_errors += 0xffff; + x->rx_missed_cntr += 0xffff; + } else { + unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); + stats->rx_missed_errors += miss_f; + x->rx_missed_cntr += miss_f; + } + } + return; +} + +static int dwmac100_get_tx_frame_status(void *data, + struct stmmac_extra_stats *x, + struct dma_desc *p, unsigned long ioaddr) +{ + int ret = 0; + struct net_device_stats *stats = (struct net_device_stats *)data; + + if (unlikely(p->des01.tx.error_summary)) { + if (unlikely(p->des01.tx.underflow_error)) { + x->tx_underflow++; + stats->tx_fifo_errors++; + } + if (unlikely(p->des01.tx.no_carrier)) { + x->tx_carrier++; + stats->tx_carrier_errors++; + } + if (unlikely(p->des01.tx.loss_carrier)) { + x->tx_losscarrier++; + stats->tx_carrier_errors++; + } + if (unlikely((p->des01.tx.excessive_deferral) || + (p->des01.tx.excessive_collisions) || + (p->des01.tx.late_collision))) + stats->collisions += p->des01.tx.collision_count; + ret = -1; + } + if (unlikely(p->des01.tx.heartbeat_fail)) { + x->tx_heartbeat++; + stats->tx_heartbeat_errors++; + ret = -1; + } + if (unlikely(p->des01.tx.deferred)) + x->tx_deferred++; + + return ret; +} + +static int dwmac100_get_tx_len(struct dma_desc *p) +{ + return p->des01.tx.buffer1_size; +} + +/* This function verifies if each incoming frame has some errors + * and, if required, updates the multicast statistics. + * In case of success, it returns csum_none becasue the device + * is not able to compute the csum in HW. */ +static int dwmac100_get_rx_frame_status(void *data, + struct stmmac_extra_stats *x, + struct dma_desc *p) +{ + int ret = csum_none; + struct net_device_stats *stats = (struct net_device_stats *)data; + + if (unlikely(p->des01.rx.last_descriptor == 0)) { + pr_warning("dwmac100 Error: Oversized Ethernet " + "frame spanned multiple buffers\n"); + stats->rx_length_errors++; + return discard_frame; + } + + if (unlikely(p->des01.rx.error_summary)) { + if (unlikely(p->des01.rx.descriptor_error)) + x->rx_desc++; + if (unlikely(p->des01.rx.partial_frame_error)) + x->rx_partial++; + if (unlikely(p->des01.rx.run_frame)) + x->rx_runt++; + if (unlikely(p->des01.rx.frame_too_long)) + x->rx_toolong++; + if (unlikely(p->des01.rx.collision)) { + x->rx_collision++; + stats->collisions++; + } + if (unlikely(p->des01.rx.crc_error)) { + x->rx_crc++; + stats->rx_crc_errors++; + } + ret = discard_frame; + } + if (unlikely(p->des01.rx.dribbling)) + ret = discard_frame; + + if (unlikely(p->des01.rx.length_error)) { + x->rx_lenght++; + ret = discard_frame; + } + if (unlikely(p->des01.rx.mii_error)) { + x->rx_mii++; + ret = discard_frame; + } + if (p->des01.rx.multicast_frame) { + x->rx_multicast++; + stats->multicast++; + } + return ret; +} + +static void dwmac100_irq_status(unsigned long ioaddr) +{ + return; +} + +static void dwmac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int reg_n) +{ + stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); +} + +static void dwmac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int reg_n) +{ + stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); +} + +static void dwmac100_set_filter(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + u32 value = readl(ioaddr + MAC_CONTROL); + + if (dev->flags & IFF_PROMISC) { + value |= MAC_CONTROL_PR; + value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | + MAC_CONTROL_HP); + } else if ((dev->mc_count > HASH_TABLE_SIZE) + || (dev->flags & IFF_ALLMULTI)) { + value |= MAC_CONTROL_PM; + value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); + writel(0xffffffff, ioaddr + MAC_HASH_HIGH); + writel(0xffffffff, ioaddr + MAC_HASH_LOW); + } else if (dev->mc_count == 0) { /* no multicast */ + value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | + MAC_CONTROL_HO | MAC_CONTROL_HP); + } else { + int i; + u32 mc_filter[2]; + struct dev_mc_list *mclist; + + /* Perfect filter mode for physical address and Hash + filter for multicast */ + value |= MAC_CONTROL_HP; + value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | + MAC_CONTROL_IF | MAC_CONTROL_HO); + + memset(mc_filter, 0, sizeof(mc_filter)); + for (i = 0, mclist = dev->mc_list; + mclist && i < dev->mc_count; i++, mclist = mclist->next) { + /* The upper 6 bits of the calculated CRC are used to + * index the contens of the hash table */ + int bit_nr = + ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; + /* The most significant bit determines the register to + * use (H/L) while the other 5 bits determine the bit + * within the register. */ + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + } + writel(mc_filter[0], ioaddr + MAC_HASH_LOW); + writel(mc_filter[1], ioaddr + MAC_HASH_HIGH); + } + + writel(value, ioaddr + MAC_CONTROL); + + DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: " + "HI 0x%08x, LO 0x%08x\n", + __func__, readl(ioaddr + MAC_CONTROL), + readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW)); + return; +} + +static void dwmac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex, + unsigned int fc, unsigned int pause_time) +{ + unsigned int flow = MAC_FLOW_CTRL_ENABLE; + + if (duplex) + flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT); + writel(flow, ioaddr + MAC_FLOW_CTRL); + + return; +} + +/* No PMT module supported for this Ethernet Controller. + * Tested on ST platforms only. + */ +static void dwmac100_pmt(unsigned long ioaddr, unsigned long mode) +{ + return; +} + +static void dwmac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size, + int disable_rx_ic) +{ + int i; + for (i = 0; i < ring_size; i++) { + p->des01.rx.own = 1; + p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1; + if (i == ring_size - 1) + p->des01.rx.end_ring = 1; + if (disable_rx_ic) + p->des01.rx.disable_ic = 1; + p++; + } + return; +} + +static void dwmac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size) +{ + int i; + for (i = 0; i < ring_size; i++) { + p->des01.tx.own = 0; + if (i == ring_size - 1) + p->des01.tx.end_ring = 1; + p++; + } + return; +} + +static int dwmac100_get_tx_owner(struct dma_desc *p) +{ + return p->des01.tx.own; +} + +static int dwmac100_get_rx_owner(struct dma_desc *p) +{ + return p->des01.rx.own; +} + +static void dwmac100_set_tx_owner(struct dma_desc *p) +{ + p->des01.tx.own = 1; +} + +static void dwmac100_set_rx_owner(struct dma_desc *p) +{ + p->des01.rx.own = 1; +} + +static int dwmac100_get_tx_ls(struct dma_desc *p) +{ + return p->des01.tx.last_segment; +} + +static void dwmac100_release_tx_desc(struct dma_desc *p) +{ + int ter = p->des01.tx.end_ring; + + /* clean field used within the xmit */ + p->des01.tx.first_segment = 0; + p->des01.tx.last_segment = 0; + p->des01.tx.buffer1_size = 0; + + /* clean status reported */ + p->des01.tx.error_summary = 0; + p->des01.tx.underflow_error = 0; + p->des01.tx.no_carrier = 0; + p->des01.tx.loss_carrier = 0; + p->des01.tx.excessive_deferral = 0; + p->des01.tx.excessive_collisions = 0; + p->des01.tx.late_collision = 0; + p->des01.tx.heartbeat_fail = 0; + p->des01.tx.deferred = 0; + + /* set termination field */ + p->des01.tx.end_ring = ter; + + return; +} + +static void dwmac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, + int csum_flag) +{ + p->des01.tx.first_segment = is_fs; + p->des01.tx.buffer1_size = len; +} + +static void dwmac100_clear_tx_ic(struct dma_desc *p) +{ + p->des01.tx.interrupt = 0; +} + +static void dwmac100_close_tx_desc(struct dma_desc *p) +{ + p->des01.tx.last_segment = 1; + p->des01.tx.interrupt = 1; +} + +static int dwmac100_get_rx_frame_len(struct dma_desc *p) +{ + return p->des01.rx.frame_length; +} + +struct stmmac_ops dwmac100_ops = { + .core_init = dwmac100_core_init, + .dump_regs = dwmac100_dump_mac_regs, + .host_irq_status = dwmac100_irq_status, + .set_filter = dwmac100_set_filter, + .flow_ctrl = dwmac100_flow_ctrl, + .pmt = dwmac100_pmt, + .set_umac_addr = dwmac100_set_umac_addr, + .get_umac_addr = dwmac100_get_umac_addr, +}; + +struct stmmac_dma_ops dwmac100_dma_ops = { + .init = dwmac100_dma_init, + .dump_regs = dwmac100_dump_dma_regs, + .dma_mode = dwmac100_dma_operation_mode, + .dma_diagnostic_fr = dwmac100_dma_diagnostic_fr, + .enable_dma_transmission = dwmac_enable_dma_transmission, + .enable_dma_irq = dwmac_enable_dma_irq, + .disable_dma_irq = dwmac_disable_dma_irq, + .start_tx = dwmac_dma_start_tx, + .stop_tx = dwmac_dma_stop_tx, + .start_rx = dwmac_dma_start_rx, + .stop_rx = dwmac_dma_stop_rx, + .dma_interrupt = dwmac_dma_interrupt, +}; + +struct stmmac_desc_ops dwmac100_desc_ops = { + .tx_status = dwmac100_get_tx_frame_status, + .rx_status = dwmac100_get_rx_frame_status, + .get_tx_len = dwmac100_get_tx_len, + .init_rx_desc = dwmac100_init_rx_desc, + .init_tx_desc = dwmac100_init_tx_desc, + .get_tx_owner = dwmac100_get_tx_owner, + .get_rx_owner = dwmac100_get_rx_owner, + .release_tx_desc = dwmac100_release_tx_desc, + .prepare_tx_desc = dwmac100_prepare_tx_desc, + .clear_tx_ic = dwmac100_clear_tx_ic, + .close_tx_desc = dwmac100_close_tx_desc, + .get_tx_ls = dwmac100_get_tx_ls, + .set_tx_owner = dwmac100_set_tx_owner, + .set_rx_owner = dwmac100_set_rx_owner, + .get_rx_frame_len = dwmac100_get_rx_frame_len, +}; + +struct mac_device_info *dwmac100_setup(unsigned long ioaddr) +{ + struct mac_device_info *mac; + + mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); + + pr_info("\tDWMAC100\n"); + + mac->mac = &dwmac100_ops; + mac->desc = &dwmac100_desc_ops; + mac->dma = &dwmac100_dma_ops; + + mac->pmt = PMT_NOT_SUPPORTED; + mac->link.port = MAC_CONTROL_PS; + mac->link.duplex = MAC_CONTROL_F; + mac->link.speed = 0; + mac->mii.addr = MAC_MII_ADDR; + mac->mii.data = MAC_MII_DATA; + + return mac; +} diff --git a/drivers/net/stmmac/dwmac100.h b/drivers/net/stmmac/dwmac100.h new file mode 100644 index 000000000000..0f8f110d004a --- /dev/null +++ b/drivers/net/stmmac/dwmac100.h @@ -0,0 +1,116 @@ +/******************************************************************************* + MAC 10/100 Header File + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +/*---------------------------------------------------------------------------- + * MAC BLOCK defines + *---------------------------------------------------------------------------*/ +/* MAC CSR offset */ +#define MAC_CONTROL 0x00000000 /* MAC Control */ +#define MAC_ADDR_HIGH 0x00000004 /* MAC Address High */ +#define MAC_ADDR_LOW 0x00000008 /* MAC Address Low */ +#define MAC_HASH_HIGH 0x0000000c /* Multicast Hash Table High */ +#define MAC_HASH_LOW 0x00000010 /* Multicast Hash Table Low */ +#define MAC_MII_ADDR 0x00000014 /* MII Address */ +#define MAC_MII_DATA 0x00000018 /* MII Data */ +#define MAC_FLOW_CTRL 0x0000001c /* Flow Control */ +#define MAC_VLAN1 0x00000020 /* VLAN1 Tag */ +#define MAC_VLAN2 0x00000024 /* VLAN2 Tag */ + +/* MAC CTRL defines */ +#define MAC_CONTROL_RA 0x80000000 /* Receive All Mode */ +#define MAC_CONTROL_BLE 0x40000000 /* Endian Mode */ +#define MAC_CONTROL_HBD 0x10000000 /* Heartbeat Disable */ +#define MAC_CONTROL_PS 0x08000000 /* Port Select */ +#define MAC_CONTROL_DRO 0x00800000 /* Disable Receive Own */ +#define MAC_CONTROL_EXT_LOOPBACK 0x00400000 /* Reserved (ext loopback?) */ +#define MAC_CONTROL_OM 0x00200000 /* Loopback Operating Mode */ +#define MAC_CONTROL_F 0x00100000 /* Full Duplex Mode */ +#define MAC_CONTROL_PM 0x00080000 /* Pass All Multicast */ +#define MAC_CONTROL_PR 0x00040000 /* Promiscuous Mode */ +#define MAC_CONTROL_IF 0x00020000 /* Inverse Filtering */ +#define MAC_CONTROL_PB 0x00010000 /* Pass Bad Frames */ +#define MAC_CONTROL_HO 0x00008000 /* Hash Only Filtering Mode */ +#define MAC_CONTROL_HP 0x00002000 /* Hash/Perfect Filtering Mode */ +#define MAC_CONTROL_LCC 0x00001000 /* Late Collision Control */ +#define MAC_CONTROL_DBF 0x00000800 /* Disable Broadcast Frames */ +#define MAC_CONTROL_DRTY 0x00000400 /* Disable Retry */ +#define MAC_CONTROL_ASTP 0x00000100 /* Automatic Pad Stripping */ +#define MAC_CONTROL_BOLMT_10 0x00000000 /* Back Off Limit 10 */ +#define MAC_CONTROL_BOLMT_8 0x00000040 /* Back Off Limit 8 */ +#define MAC_CONTROL_BOLMT_4 0x00000080 /* Back Off Limit 4 */ +#define MAC_CONTROL_BOLMT_1 0x000000c0 /* Back Off Limit 1 */ +#define MAC_CONTROL_DC 0x00000020 /* Deferral Check */ +#define MAC_CONTROL_TE 0x00000008 /* Transmitter Enable */ +#define MAC_CONTROL_RE 0x00000004 /* Receiver Enable */ + +#define MAC_CORE_INIT (MAC_CONTROL_HBD | MAC_CONTROL_ASTP) + +/* MAC FLOW CTRL defines */ +#define MAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ +#define MAC_FLOW_CTRL_PT_SHIFT 16 +#define MAC_FLOW_CTRL_PASS 0x00000004 /* Pass Control Frames */ +#define MAC_FLOW_CTRL_ENABLE 0x00000002 /* Flow Control Enable */ +#define MAC_FLOW_CTRL_PAUSE 0x00000001 /* Flow Control Busy ... */ + +/* MII ADDR defines */ +#define MAC_MII_ADDR_WRITE 0x00000002 /* MII Write */ +#define MAC_MII_ADDR_BUSY 0x00000001 /* MII Busy */ + +/*---------------------------------------------------------------------------- + * DMA BLOCK defines + *---------------------------------------------------------------------------*/ + +/* DMA Bus Mode register defines */ +#define DMA_BUS_MODE_DBO 0x00100000 /* Descriptor Byte Ordering */ +#define DMA_BUS_MODE_BLE 0x00000080 /* Big Endian/Little Endian */ +#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ +#define DMA_BUS_MODE_PBL_SHIFT 8 +#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ +#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ +#define DMA_BUS_MODE_BAR_BUS 0x00000002 /* Bar-Bus Arbitration */ +#define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */ +#define DMA_BUS_MODE_DEFAULT 0x00000000 + +/* DMA Control register defines */ +#define DMA_CONTROL_SF 0x00200000 /* Store And Forward */ + +/* Transmit Threshold Control */ +enum ttc_control { + DMA_CONTROL_TTC_DEFAULT = 0x00000000, /* Threshold is 32 DWORDS */ + DMA_CONTROL_TTC_64 = 0x00004000, /* Threshold is 64 DWORDS */ + DMA_CONTROL_TTC_128 = 0x00008000, /* Threshold is 128 DWORDS */ + DMA_CONTROL_TTC_256 = 0x0000c000, /* Threshold is 256 DWORDS */ + DMA_CONTROL_TTC_18 = 0x00400000, /* Threshold is 18 DWORDS */ + DMA_CONTROL_TTC_24 = 0x00404000, /* Threshold is 24 DWORDS */ + DMA_CONTROL_TTC_32 = 0x00408000, /* Threshold is 32 DWORDS */ + DMA_CONTROL_TTC_40 = 0x0040c000, /* Threshold is 40 DWORDS */ + DMA_CONTROL_SE = 0x00000008, /* Stop On Empty */ + DMA_CONTROL_OSF = 0x00000004, /* Operate On 2nd Frame */ +}; + +/* STMAC110 DMA Missed Frame Counter register defines */ +#define DMA_MISSED_FRAME_OVE 0x10000000 /* FIFO Overflow Overflow */ +#define DMA_MISSED_FRAME_OVE_CNTR 0x0ffe0000 /* Overflow Frame Counter */ +#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */ +#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ diff --git a/drivers/net/stmmac/mac100.c b/drivers/net/stmmac/mac100.c deleted file mode 100644 index b675f7c67f6e..000000000000 --- a/drivers/net/stmmac/mac100.c +++ /dev/null @@ -1,535 +0,0 @@ -/******************************************************************************* - This is the driver for the MAC 10/100 on-chip Ethernet controller - currently tested on all the ST boards based on STb7109 and stx7200 SoCs. - - DWC Ether MAC 10/100 Universal version 4.0 has been used for developing - this code. - - Copyright (C) 2007-2009 STMicroelectronics Ltd - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Author: Giuseppe Cavallaro -*******************************************************************************/ - -#include -#include -#include -#include - -#include "common.h" -#include "mac100.h" -#include "dwmac_dma.h" - -#undef MAC100_DEBUG -/*#define MAC100_DEBUG*/ -#ifdef MAC100_DEBUG -#define DBG(fmt, args...) printk(fmt, ## args) -#else -#define DBG(fmt, args...) do { } while (0) -#endif - -static void mac100_core_init(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + MAC_CONTROL); - - writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL); - -#ifdef STMMAC_VLAN_TAG_USED - writel(ETH_P_8021Q, ioaddr + MAC_VLAN1); -#endif - return; -} - -static void mac100_dump_mac_regs(unsigned long ioaddr) -{ - pr_info("\t----------------------------------------------\n" - "\t MAC100 CSR (base addr = 0x%8x)\n" - "\t----------------------------------------------\n", - (unsigned int)ioaddr); - pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL, - readl(ioaddr + MAC_CONTROL)); - pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH, - readl(ioaddr + MAC_ADDR_HIGH)); - pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW, - readl(ioaddr + MAC_ADDR_LOW)); - pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n", - MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH)); - pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n", - MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW)); - pr_info("\tflow control (offset 0x%x): 0x%08x\n", - MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL)); - pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1, - readl(ioaddr + MAC_VLAN1)); - pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2, - readl(ioaddr + MAC_VLAN2)); - pr_info("\n\tMAC management counter registers\n"); - pr_info("\t MMC crtl (offset 0x%x): 0x%08x\n", - MMC_CONTROL, readl(ioaddr + MMC_CONTROL)); - pr_info("\t MMC High Interrupt (offset 0x%x): 0x%08x\n", - MMC_HIGH_INTR, readl(ioaddr + MMC_HIGH_INTR)); - pr_info("\t MMC Low Interrupt (offset 0x%x): 0x%08x\n", - MMC_LOW_INTR, readl(ioaddr + MMC_LOW_INTR)); - pr_info("\t MMC High Interrupt Mask (offset 0x%x): 0x%08x\n", - MMC_HIGH_INTR_MASK, readl(ioaddr + MMC_HIGH_INTR_MASK)); - pr_info("\t MMC Low Interrupt Mask (offset 0x%x): 0x%08x\n", - MMC_LOW_INTR_MASK, readl(ioaddr + MMC_LOW_INTR_MASK)); - return; -} - -static int mac100_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, - u32 dma_rx) -{ - u32 value = readl(ioaddr + DMA_BUS_MODE); - /* DMA SW reset */ - value |= DMA_BUS_MODE_SFT_RESET; - writel(value, ioaddr + DMA_BUS_MODE); - do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)); - - /* Enable Application Access by writing to DMA CSR0 */ - writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT), - ioaddr + DMA_BUS_MODE); - - /* Mask interrupts by writing to CSR7 */ - writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); - - /* The base address of the RX/TX descriptor lists must be written into - * DMA CSR3 and CSR4, respectively. */ - writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); - writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); - - return 0; -} - -/* Store and Forward capability is not used at all.. - * The transmit threshold can be programmed by - * setting the TTC bits in the DMA control register.*/ -static void mac100_dma_operation_mode(unsigned long ioaddr, int txmode, - int rxmode) -{ - u32 csr6 = readl(ioaddr + DMA_CONTROL); - - if (txmode <= 32) - csr6 |= DMA_CONTROL_TTC_32; - else if (txmode <= 64) - csr6 |= DMA_CONTROL_TTC_64; - else - csr6 |= DMA_CONTROL_TTC_128; - - writel(csr6, ioaddr + DMA_CONTROL); - - return; -} - -static void mac100_dump_dma_regs(unsigned long ioaddr) -{ - int i; - - DBG(KERN_DEBUG "MAC100 DMA CSR \n"); - for (i = 0; i < 9; i++) - pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i, - (DMA_BUS_MODE + i * 4), - readl(ioaddr + DMA_BUS_MODE + i * 4)); - DBG(KERN_DEBUG "\t CSR20 (offset 0x%x): 0x%08x\n", - DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR)); - DBG(KERN_DEBUG "\t CSR21 (offset 0x%x): 0x%08x\n", - DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR)); - return; -} - -/* DMA controller has two counters to track the number of - the receive missed frames. */ -static void mac100_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x, - unsigned long ioaddr) -{ - struct net_device_stats *stats = (struct net_device_stats *)data; - u32 csr8 = readl(ioaddr + DMA_MISSED_FRAME_CTR); - - if (unlikely(csr8)) { - if (csr8 & DMA_MISSED_FRAME_OVE) { - stats->rx_over_errors += 0x800; - x->rx_overflow_cntr += 0x800; - } else { - unsigned int ove_cntr; - ove_cntr = ((csr8 & DMA_MISSED_FRAME_OVE_CNTR) >> 17); - stats->rx_over_errors += ove_cntr; - x->rx_overflow_cntr += ove_cntr; - } - - if (csr8 & DMA_MISSED_FRAME_OVE_M) { - stats->rx_missed_errors += 0xffff; - x->rx_missed_cntr += 0xffff; - } else { - unsigned int miss_f = (csr8 & DMA_MISSED_FRAME_M_CNTR); - stats->rx_missed_errors += miss_f; - x->rx_missed_cntr += miss_f; - } - } - return; -} - -static int mac100_get_tx_frame_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p, unsigned long ioaddr) -{ - int ret = 0; - struct net_device_stats *stats = (struct net_device_stats *)data; - - if (unlikely(p->des01.tx.error_summary)) { - if (unlikely(p->des01.tx.underflow_error)) { - x->tx_underflow++; - stats->tx_fifo_errors++; - } - if (unlikely(p->des01.tx.no_carrier)) { - x->tx_carrier++; - stats->tx_carrier_errors++; - } - if (unlikely(p->des01.tx.loss_carrier)) { - x->tx_losscarrier++; - stats->tx_carrier_errors++; - } - if (unlikely((p->des01.tx.excessive_deferral) || - (p->des01.tx.excessive_collisions) || - (p->des01.tx.late_collision))) - stats->collisions += p->des01.tx.collision_count; - ret = -1; - } - if (unlikely(p->des01.tx.heartbeat_fail)) { - x->tx_heartbeat++; - stats->tx_heartbeat_errors++; - ret = -1; - } - if (unlikely(p->des01.tx.deferred)) - x->tx_deferred++; - - return ret; -} - -static int mac100_get_tx_len(struct dma_desc *p) -{ - return p->des01.tx.buffer1_size; -} - -/* This function verifies if each incoming frame has some errors - * and, if required, updates the multicast statistics. - * In case of success, it returns csum_none becasue the device - * is not able to compute the csum in HW. */ -static int mac100_get_rx_frame_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p) -{ - int ret = csum_none; - struct net_device_stats *stats = (struct net_device_stats *)data; - - if (unlikely(p->des01.rx.last_descriptor == 0)) { - pr_warning("mac100 Error: Oversized Ethernet " - "frame spanned multiple buffers\n"); - stats->rx_length_errors++; - return discard_frame; - } - - if (unlikely(p->des01.rx.error_summary)) { - if (unlikely(p->des01.rx.descriptor_error)) - x->rx_desc++; - if (unlikely(p->des01.rx.partial_frame_error)) - x->rx_partial++; - if (unlikely(p->des01.rx.run_frame)) - x->rx_runt++; - if (unlikely(p->des01.rx.frame_too_long)) - x->rx_toolong++; - if (unlikely(p->des01.rx.collision)) { - x->rx_collision++; - stats->collisions++; - } - if (unlikely(p->des01.rx.crc_error)) { - x->rx_crc++; - stats->rx_crc_errors++; - } - ret = discard_frame; - } - if (unlikely(p->des01.rx.dribbling)) - ret = discard_frame; - - if (unlikely(p->des01.rx.length_error)) { - x->rx_lenght++; - ret = discard_frame; - } - if (unlikely(p->des01.rx.mii_error)) { - x->rx_mii++; - ret = discard_frame; - } - if (p->des01.rx.multicast_frame) { - x->rx_multicast++; - stats->multicast++; - } - return ret; -} - -static void mac100_irq_status(unsigned long ioaddr) -{ - return; -} - -static void mac100_set_umac_addr(unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n) -{ - stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); -} - -static void mac100_get_umac_addr(unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n) -{ - stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW); -} - -static void mac100_set_filter(struct net_device *dev) -{ - unsigned long ioaddr = dev->base_addr; - u32 value = readl(ioaddr + MAC_CONTROL); - - if (dev->flags & IFF_PROMISC) { - value |= MAC_CONTROL_PR; - value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | - MAC_CONTROL_HP); - } else if ((dev->mc_count > HASH_TABLE_SIZE) - || (dev->flags & IFF_ALLMULTI)) { - value |= MAC_CONTROL_PM; - value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); - writel(0xffffffff, ioaddr + MAC_HASH_HIGH); - writel(0xffffffff, ioaddr + MAC_HASH_LOW); - } else if (dev->mc_count == 0) { /* no multicast */ - value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | - MAC_CONTROL_HO | MAC_CONTROL_HP); - } else { - int i; - u32 mc_filter[2]; - struct dev_mc_list *mclist; - - /* Perfect filter mode for physical address and Hash - filter for multicast */ - value |= MAC_CONTROL_HP; - value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF - | MAC_CONTROL_HO); - - memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < dev->mc_count; i++, mclist = mclist->next) { - /* The upper 6 bits of the calculated CRC are used to - * index the contens of the hash table */ - int bit_nr = - ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - /* The most significant bit determines the register to - * use (H/L) while the other 5 bits determine the bit - * within the register. */ - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - } - writel(mc_filter[0], ioaddr + MAC_HASH_LOW); - writel(mc_filter[1], ioaddr + MAC_HASH_HIGH); - } - - writel(value, ioaddr + MAC_CONTROL); - - DBG(KERN_INFO "%s: CTRL reg: 0x%08x Hash regs: " - "HI 0x%08x, LO 0x%08x\n", - __func__, readl(ioaddr + MAC_CONTROL), - readl(ioaddr + MAC_HASH_HIGH), readl(ioaddr + MAC_HASH_LOW)); - return; -} - -static void mac100_flow_ctrl(unsigned long ioaddr, unsigned int duplex, - unsigned int fc, unsigned int pause_time) -{ - unsigned int flow = MAC_FLOW_CTRL_ENABLE; - - if (duplex) - flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT); - writel(flow, ioaddr + MAC_FLOW_CTRL); - - return; -} - -/* No PMT module supported in our SoC for the Ethernet Controller. */ -static void mac100_pmt(unsigned long ioaddr, unsigned long mode) -{ - return; -} - -static void mac100_init_rx_desc(struct dma_desc *p, unsigned int ring_size, - int disable_rx_ic) -{ - int i; - for (i = 0; i < ring_size; i++) { - p->des01.rx.own = 1; - p->des01.rx.buffer1_size = BUF_SIZE_2KiB - 1; - if (i == ring_size - 1) - p->des01.rx.end_ring = 1; - if (disable_rx_ic) - p->des01.rx.disable_ic = 1; - p++; - } - return; -} - -static void mac100_init_tx_desc(struct dma_desc *p, unsigned int ring_size) -{ - int i; - for (i = 0; i < ring_size; i++) { - p->des01.tx.own = 0; - if (i == ring_size - 1) - p->des01.tx.end_ring = 1; - p++; - } - return; -} - -static int mac100_get_tx_owner(struct dma_desc *p) -{ - return p->des01.tx.own; -} - -static int mac100_get_rx_owner(struct dma_desc *p) -{ - return p->des01.rx.own; -} - -static void mac100_set_tx_owner(struct dma_desc *p) -{ - p->des01.tx.own = 1; -} - -static void mac100_set_rx_owner(struct dma_desc *p) -{ - p->des01.rx.own = 1; -} - -static int mac100_get_tx_ls(struct dma_desc *p) -{ - return p->des01.tx.last_segment; -} - -static void mac100_release_tx_desc(struct dma_desc *p) -{ - int ter = p->des01.tx.end_ring; - - /* clean field used within the xmit */ - p->des01.tx.first_segment = 0; - p->des01.tx.last_segment = 0; - p->des01.tx.buffer1_size = 0; - - /* clean status reported */ - p->des01.tx.error_summary = 0; - p->des01.tx.underflow_error = 0; - p->des01.tx.no_carrier = 0; - p->des01.tx.loss_carrier = 0; - p->des01.tx.excessive_deferral = 0; - p->des01.tx.excessive_collisions = 0; - p->des01.tx.late_collision = 0; - p->des01.tx.heartbeat_fail = 0; - p->des01.tx.deferred = 0; - - /* set termination field */ - p->des01.tx.end_ring = ter; - - return; -} - -static void mac100_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, - int csum_flag) -{ - p->des01.tx.first_segment = is_fs; - p->des01.tx.buffer1_size = len; -} - -static void mac100_clear_tx_ic(struct dma_desc *p) -{ - p->des01.tx.interrupt = 0; -} - -static void mac100_close_tx_desc(struct dma_desc *p) -{ - p->des01.tx.last_segment = 1; - p->des01.tx.interrupt = 1; -} - -static int mac100_get_rx_frame_len(struct dma_desc *p) -{ - return p->des01.rx.frame_length; -} - -struct stmmac_ops mac100_ops = { - .core_init = mac100_core_init, - .dump_regs = mac100_dump_mac_regs, - .host_irq_status = mac100_irq_status, - .set_filter = mac100_set_filter, - .flow_ctrl = mac100_flow_ctrl, - .pmt = mac100_pmt, - .set_umac_addr = mac100_set_umac_addr, - .get_umac_addr = mac100_get_umac_addr, -}; - -struct stmmac_dma_ops mac100_dma_ops = { - .init = mac100_dma_init, - .dump_regs = mac100_dump_dma_regs, - .dma_mode = mac100_dma_operation_mode, - .dma_diagnostic_fr = mac100_dma_diagnostic_fr, - .enable_dma_transmission = dwmac_enable_dma_transmission, - .enable_dma_irq = dwmac_enable_dma_irq, - .disable_dma_irq = dwmac_disable_dma_irq, - .start_tx = dwmac_dma_start_tx, - .stop_tx = dwmac_dma_stop_tx, - .start_rx = dwmac_dma_start_rx, - .stop_rx = dwmac_dma_stop_rx, - .dma_interrupt = dwmac_dma_interrupt, -}; - -struct stmmac_desc_ops mac100_desc_ops = { - .tx_status = mac100_get_tx_frame_status, - .rx_status = mac100_get_rx_frame_status, - .get_tx_len = mac100_get_tx_len, - .init_rx_desc = mac100_init_rx_desc, - .init_tx_desc = mac100_init_tx_desc, - .get_tx_owner = mac100_get_tx_owner, - .get_rx_owner = mac100_get_rx_owner, - .release_tx_desc = mac100_release_tx_desc, - .prepare_tx_desc = mac100_prepare_tx_desc, - .clear_tx_ic = mac100_clear_tx_ic, - .close_tx_desc = mac100_close_tx_desc, - .get_tx_ls = mac100_get_tx_ls, - .set_tx_owner = mac100_set_tx_owner, - .set_rx_owner = mac100_set_rx_owner, - .get_rx_frame_len = mac100_get_rx_frame_len, -}; - -struct mac_device_info *mac100_setup(unsigned long ioaddr) -{ - struct mac_device_info *mac; - - mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); - - pr_info("\tMAC 10/100\n"); - - mac->mac = &mac100_ops; - mac->desc = &mac100_desc_ops; - mac->dma = &mac100_dma_ops; - - mac->pmt = PMT_NOT_SUPPORTED; - mac->link.port = MAC_CONTROL_PS; - mac->link.duplex = MAC_CONTROL_F; - mac->link.speed = 0; - mac->mii.addr = MAC_MII_ADDR; - mac->mii.data = MAC_MII_DATA; - - return mac; -} diff --git a/drivers/net/stmmac/mac100.h b/drivers/net/stmmac/mac100.h deleted file mode 100644 index 0f8f110d004a..000000000000 --- a/drivers/net/stmmac/mac100.h +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - MAC 10/100 Header File - - Copyright (C) 2007-2009 STMicroelectronics Ltd - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Author: Giuseppe Cavallaro -*******************************************************************************/ - -/*---------------------------------------------------------------------------- - * MAC BLOCK defines - *---------------------------------------------------------------------------*/ -/* MAC CSR offset */ -#define MAC_CONTROL 0x00000000 /* MAC Control */ -#define MAC_ADDR_HIGH 0x00000004 /* MAC Address High */ -#define MAC_ADDR_LOW 0x00000008 /* MAC Address Low */ -#define MAC_HASH_HIGH 0x0000000c /* Multicast Hash Table High */ -#define MAC_HASH_LOW 0x00000010 /* Multicast Hash Table Low */ -#define MAC_MII_ADDR 0x00000014 /* MII Address */ -#define MAC_MII_DATA 0x00000018 /* MII Data */ -#define MAC_FLOW_CTRL 0x0000001c /* Flow Control */ -#define MAC_VLAN1 0x00000020 /* VLAN1 Tag */ -#define MAC_VLAN2 0x00000024 /* VLAN2 Tag */ - -/* MAC CTRL defines */ -#define MAC_CONTROL_RA 0x80000000 /* Receive All Mode */ -#define MAC_CONTROL_BLE 0x40000000 /* Endian Mode */ -#define MAC_CONTROL_HBD 0x10000000 /* Heartbeat Disable */ -#define MAC_CONTROL_PS 0x08000000 /* Port Select */ -#define MAC_CONTROL_DRO 0x00800000 /* Disable Receive Own */ -#define MAC_CONTROL_EXT_LOOPBACK 0x00400000 /* Reserved (ext loopback?) */ -#define MAC_CONTROL_OM 0x00200000 /* Loopback Operating Mode */ -#define MAC_CONTROL_F 0x00100000 /* Full Duplex Mode */ -#define MAC_CONTROL_PM 0x00080000 /* Pass All Multicast */ -#define MAC_CONTROL_PR 0x00040000 /* Promiscuous Mode */ -#define MAC_CONTROL_IF 0x00020000 /* Inverse Filtering */ -#define MAC_CONTROL_PB 0x00010000 /* Pass Bad Frames */ -#define MAC_CONTROL_HO 0x00008000 /* Hash Only Filtering Mode */ -#define MAC_CONTROL_HP 0x00002000 /* Hash/Perfect Filtering Mode */ -#define MAC_CONTROL_LCC 0x00001000 /* Late Collision Control */ -#define MAC_CONTROL_DBF 0x00000800 /* Disable Broadcast Frames */ -#define MAC_CONTROL_DRTY 0x00000400 /* Disable Retry */ -#define MAC_CONTROL_ASTP 0x00000100 /* Automatic Pad Stripping */ -#define MAC_CONTROL_BOLMT_10 0x00000000 /* Back Off Limit 10 */ -#define MAC_CONTROL_BOLMT_8 0x00000040 /* Back Off Limit 8 */ -#define MAC_CONTROL_BOLMT_4 0x00000080 /* Back Off Limit 4 */ -#define MAC_CONTROL_BOLMT_1 0x000000c0 /* Back Off Limit 1 */ -#define MAC_CONTROL_DC 0x00000020 /* Deferral Check */ -#define MAC_CONTROL_TE 0x00000008 /* Transmitter Enable */ -#define MAC_CONTROL_RE 0x00000004 /* Receiver Enable */ - -#define MAC_CORE_INIT (MAC_CONTROL_HBD | MAC_CONTROL_ASTP) - -/* MAC FLOW CTRL defines */ -#define MAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ -#define MAC_FLOW_CTRL_PT_SHIFT 16 -#define MAC_FLOW_CTRL_PASS 0x00000004 /* Pass Control Frames */ -#define MAC_FLOW_CTRL_ENABLE 0x00000002 /* Flow Control Enable */ -#define MAC_FLOW_CTRL_PAUSE 0x00000001 /* Flow Control Busy ... */ - -/* MII ADDR defines */ -#define MAC_MII_ADDR_WRITE 0x00000002 /* MII Write */ -#define MAC_MII_ADDR_BUSY 0x00000001 /* MII Busy */ - -/*---------------------------------------------------------------------------- - * DMA BLOCK defines - *---------------------------------------------------------------------------*/ - -/* DMA Bus Mode register defines */ -#define DMA_BUS_MODE_DBO 0x00100000 /* Descriptor Byte Ordering */ -#define DMA_BUS_MODE_BLE 0x00000080 /* Big Endian/Little Endian */ -#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ -#define DMA_BUS_MODE_PBL_SHIFT 8 -#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ -#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ -#define DMA_BUS_MODE_BAR_BUS 0x00000002 /* Bar-Bus Arbitration */ -#define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */ -#define DMA_BUS_MODE_DEFAULT 0x00000000 - -/* DMA Control register defines */ -#define DMA_CONTROL_SF 0x00200000 /* Store And Forward */ - -/* Transmit Threshold Control */ -enum ttc_control { - DMA_CONTROL_TTC_DEFAULT = 0x00000000, /* Threshold is 32 DWORDS */ - DMA_CONTROL_TTC_64 = 0x00004000, /* Threshold is 64 DWORDS */ - DMA_CONTROL_TTC_128 = 0x00008000, /* Threshold is 128 DWORDS */ - DMA_CONTROL_TTC_256 = 0x0000c000, /* Threshold is 256 DWORDS */ - DMA_CONTROL_TTC_18 = 0x00400000, /* Threshold is 18 DWORDS */ - DMA_CONTROL_TTC_24 = 0x00404000, /* Threshold is 24 DWORDS */ - DMA_CONTROL_TTC_32 = 0x00408000, /* Threshold is 32 DWORDS */ - DMA_CONTROL_TTC_40 = 0x0040c000, /* Threshold is 40 DWORDS */ - DMA_CONTROL_SE = 0x00000008, /* Stop On Empty */ - DMA_CONTROL_OSF = 0x00000004, /* Operate On 2nd Frame */ -}; - -/* STMAC110 DMA Missed Frame Counter register defines */ -#define DMA_MISSED_FRAME_OVE 0x10000000 /* FIFO Overflow Overflow */ -#define DMA_MISSED_FRAME_OVE_CNTR 0x0ffe0000 /* Overflow Frame Counter */ -#define DMA_MISSED_FRAME_OVE_M 0x00010000 /* Missed Frame Overflow */ -#define DMA_MISSED_FRAME_M_CNTR 0x0000ffff /* Missed Frame Couinter */ diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index e6c5a3cf4af2..e79e00b6f147 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1585,7 +1585,7 @@ static int stmmac_mac_device_setup(struct net_device *dev) if (priv->is_gmac) device = gmac_setup(ioaddr); else - device = mac100_setup(ioaddr); + device = dwmac100_setup(ioaddr); if (!device) return -ENOMEM; -- cgit v1.2.3 From 21d437cc66dcfd0119a4905214fbbe19f3e276dc Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:20 +0000 Subject: stmmac: rename the gmac as dwmac1000 and split core and dma parts Use dwmac1000 naming instead of gmac. The patch also splits the gmac.c file in two new ones: dwmac1000_core.c and dwmac1000_dma.c. This could actually help on some architectures where different DMA engines are used. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/Makefile | 5 +- drivers/net/stmmac/common.h | 2 +- drivers/net/stmmac/descs.h | 4 +- drivers/net/stmmac/dwmac1000.h | 221 ++++++++++++ drivers/net/stmmac/dwmac1000_core.c | 245 +++++++++++++ drivers/net/stmmac/dwmac1000_dma.c | 474 ++++++++++++++++++++++++ drivers/net/stmmac/gmac.c | 700 ------------------------------------ drivers/net/stmmac/gmac.h | 204 ----------- drivers/net/stmmac/stmmac_main.c | 2 +- 9 files changed, 947 insertions(+), 910 deletions(-) create mode 100644 drivers/net/stmmac/dwmac1000.h create mode 100644 drivers/net/stmmac/dwmac1000_core.c create mode 100644 drivers/net/stmmac/dwmac1000_dma.c delete mode 100644 drivers/net/stmmac/gmac.c delete mode 100644 drivers/net/stmmac/gmac.h diff --git a/drivers/net/stmmac/Makefile b/drivers/net/stmmac/Makefile index 2ed83859fd59..c776af15fe1a 100644 --- a/drivers/net/stmmac/Makefile +++ b/drivers/net/stmmac/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac.o stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o -stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o dwmac_lib.o \ - dwmac100.o gmac.o $(stmmac-y) +stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o \ + dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \ + dwmac100.o $(stmmac-y) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 987faaaa1920..25b53d411516 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -224,7 +224,7 @@ struct mac_device_info { struct mac_link link; }; -struct mac_device_info *gmac_setup(unsigned long addr); +struct mac_device_info *dwmac1000_setup(unsigned long addr); struct mac_device_info *dwmac100_setup(unsigned long addr); extern void stmmac_set_mac_addr(unsigned long ioaddr, u8 addr[6], diff --git a/drivers/net/stmmac/descs.h b/drivers/net/stmmac/descs.h index 6d2a0b2f5e57..63a03e264694 100644 --- a/drivers/net/stmmac/descs.h +++ b/drivers/net/stmmac/descs.h @@ -1,6 +1,6 @@ /******************************************************************************* - Header File to describe the DMA descriptors - Use enhanced descriptors in case of GMAC Cores. + Header File to describe the DMA descriptors. + Enhanced descriptors have been in case of DWMAC1000 Cores. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h new file mode 100644 index 000000000000..3d54d6c99129 --- /dev/null +++ b/drivers/net/stmmac/dwmac1000.h @@ -0,0 +1,221 @@ +/******************************************************************************* + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#include +#include +#include "common.h" + +#define GMAC_CONTROL 0x00000000 /* Configuration */ +#define GMAC_FRAME_FILTER 0x00000004 /* Frame Filter */ +#define GMAC_HASH_HIGH 0x00000008 /* Multicast Hash Table High */ +#define GMAC_HASH_LOW 0x0000000c /* Multicast Hash Table Low */ +#define GMAC_MII_ADDR 0x00000010 /* MII Address */ +#define GMAC_MII_DATA 0x00000014 /* MII Data */ +#define GMAC_FLOW_CTRL 0x00000018 /* Flow Control */ +#define GMAC_VLAN_TAG 0x0000001c /* VLAN Tag */ +#define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ +#define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */ + +#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */ +enum dwmac1000_irq_status { + time_stamp_irq = 0x0200, + mmc_rx_csum_offload_irq = 0x0080, + mmc_tx_irq = 0x0040, + mmc_rx_irq = 0x0020, + mmc_irq = 0x0010, + pmt_irq = 0x0008, + pcs_ane_irq = 0x0004, + pcs_link_irq = 0x0002, + rgmii_irq = 0x0001, +}; +#define GMAC_INT_MASK 0x0000003c /* interrupt mask register */ + +/* PMT Control and Status */ +#define GMAC_PMT 0x0000002c +enum power_event { + pointer_reset = 0x80000000, + global_unicast = 0x00000200, + wake_up_rx_frame = 0x00000040, + magic_frame = 0x00000020, + wake_up_frame_en = 0x00000004, + magic_pkt_en = 0x00000002, + power_down = 0x00000001, +}; + +/* GMAC HW ADDR regs */ +#define GMAC_ADDR_HIGH(reg) (0x00000040+(reg * 8)) +#define GMAC_ADDR_LOW(reg) (0x00000044+(reg * 8)) +#define GMAC_MAX_UNICAST_ADDRESSES 16 + +#define GMAC_AN_CTRL 0x000000c0 /* AN control */ +#define GMAC_AN_STATUS 0x000000c4 /* AN status */ +#define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */ +#define GMAC_ANE_LINK 0x000000cc /* Auto-Neg. link partener ability */ +#define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */ +#define GMAC_TBI 0x000000d4 /* TBI extend status */ +#define GMAC_GMII_STATUS 0x000000d8 /* S/R-GMII status */ + +/* GMAC Configuration defines */ +#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ +#define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ +#define GMAC_CONTROL_JD 0x00400000 /* Jabber disable */ +#define GMAC_CONTROL_BE 0x00200000 /* Frame Burst Enable */ +#define GMAC_CONTROL_JE 0x00100000 /* Jumbo frame */ +enum inter_frame_gap { + GMAC_CONTROL_IFG_88 = 0x00040000, + GMAC_CONTROL_IFG_80 = 0x00020000, + GMAC_CONTROL_IFG_40 = 0x000e0000, +}; +#define GMAC_CONTROL_DCRS 0x00010000 /* Disable carrier sense during tx */ +#define GMAC_CONTROL_PS 0x00008000 /* Port Select 0:GMI 1:MII */ +#define GMAC_CONTROL_FES 0x00004000 /* Speed 0:10 1:100 */ +#define GMAC_CONTROL_DO 0x00002000 /* Disable Rx Own */ +#define GMAC_CONTROL_LM 0x00001000 /* Loop-back mode */ +#define GMAC_CONTROL_DM 0x00000800 /* Duplex Mode */ +#define GMAC_CONTROL_IPC 0x00000400 /* Checksum Offload */ +#define GMAC_CONTROL_DR 0x00000200 /* Disable Retry */ +#define GMAC_CONTROL_LUD 0x00000100 /* Link up/down */ +#define GMAC_CONTROL_ACS 0x00000080 /* Automatic Pad Stripping */ +#define GMAC_CONTROL_DC 0x00000010 /* Deferral Check */ +#define GMAC_CONTROL_TE 0x00000008 /* Transmitter Enable */ +#define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ + +#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \ + GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE) + +/* GMAC Frame Filter defines */ +#define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ +#define GMAC_FRAME_FILTER_HUC 0x00000002 /* Hash Unicast */ +#define GMAC_FRAME_FILTER_HMC 0x00000004 /* Hash Multicast */ +#define GMAC_FRAME_FILTER_DAIF 0x00000008 /* DA Inverse Filtering */ +#define GMAC_FRAME_FILTER_PM 0x00000010 /* Pass all multicast */ +#define GMAC_FRAME_FILTER_DBF 0x00000020 /* Disable Broadcast frames */ +#define GMAC_FRAME_FILTER_SAIF 0x00000100 /* Inverse Filtering */ +#define GMAC_FRAME_FILTER_SAF 0x00000200 /* Source Address Filter */ +#define GMAC_FRAME_FILTER_HPF 0x00000400 /* Hash or perfect Filter */ +#define GMAC_FRAME_FILTER_RA 0x80000000 /* Receive all mode */ +/* GMII ADDR defines */ +#define GMAC_MII_ADDR_WRITE 0x00000002 /* MII Write */ +#define GMAC_MII_ADDR_BUSY 0x00000001 /* MII Busy */ +/* GMAC FLOW CTRL defines */ +#define GMAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ +#define GMAC_FLOW_CTRL_PT_SHIFT 16 +#define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */ +#define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */ +#define GMAC_FLOW_CTRL_FCB_BPA 0x00000001 /* Flow Control Busy ... */ + +/*--- DMA BLOCK defines ---*/ +/* DMA Bus Mode register defines */ +#define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */ +#define DMA_BUS_MODE_DA 0x00000002 /* Arbitration scheme */ +#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ +#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ +/* Programmable burst length (passed thorugh platform)*/ +#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ +#define DMA_BUS_MODE_PBL_SHIFT 8 + +enum rx_tx_priority_ratio { + double_ratio = 0x00004000, /*2:1 */ + triple_ratio = 0x00008000, /*3:1 */ + quadruple_ratio = 0x0000c000, /*4:1 */ +}; + +#define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */ +#define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */ +#define DMA_BUS_MODE_RPBL_SHIFT 17 +#define DMA_BUS_MODE_USP 0x00800000 +#define DMA_BUS_MODE_4PBL 0x01000000 +#define DMA_BUS_MODE_AAL 0x02000000 + +/* DMA CRS Control and Status Register Mapping */ +#define DMA_HOST_TX_DESC 0x00001048 /* Current Host Tx descriptor */ +#define DMA_HOST_RX_DESC 0x0000104c /* Current Host Rx descriptor */ +/* DMA Bus Mode register defines */ +#define DMA_BUS_PR_RATIO_MASK 0x0000c000 /* Rx/Tx priority ratio */ +#define DMA_BUS_PR_RATIO_SHIFT 14 +#define DMA_BUS_FB 0x00010000 /* Fixed Burst */ + +/* DMA operation mode defines (start/stop tx/rx are placed in common header)*/ +#define DMA_CONTROL_DT 0x04000000 /* Disable Drop TCP/IP csum error */ +#define DMA_CONTROL_RSF 0x02000000 /* Receive Store and Forward */ +#define DMA_CONTROL_DFF 0x01000000 /* Disaable flushing */ +/* Threshold for Activating the FC */ +enum rfa { + act_full_minus_1 = 0x00800000, + act_full_minus_2 = 0x00800200, + act_full_minus_3 = 0x00800400, + act_full_minus_4 = 0x00800600, +}; +/* Threshold for Deactivating the FC */ +enum rfd { + deac_full_minus_1 = 0x00400000, + deac_full_minus_2 = 0x00400800, + deac_full_minus_3 = 0x00401000, + deac_full_minus_4 = 0x00401800, +}; +#define DMA_CONTROL_TSF 0x00200000 /* Transmit Store and Forward */ +#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ + +enum ttc_control { + DMA_CONTROL_TTC_64 = 0x00000000, + DMA_CONTROL_TTC_128 = 0x00004000, + DMA_CONTROL_TTC_192 = 0x00008000, + DMA_CONTROL_TTC_256 = 0x0000c000, + DMA_CONTROL_TTC_40 = 0x00010000, + DMA_CONTROL_TTC_32 = 0x00014000, + DMA_CONTROL_TTC_24 = 0x00018000, + DMA_CONTROL_TTC_16 = 0x0001c000, +}; +#define DMA_CONTROL_TC_TX_MASK 0xfffe3fff + +#define DMA_CONTROL_EFC 0x00000100 +#define DMA_CONTROL_FEF 0x00000080 +#define DMA_CONTROL_FUF 0x00000040 + +enum rtc_control { + DMA_CONTROL_RTC_64 = 0x00000000, + DMA_CONTROL_RTC_32 = 0x00000008, + DMA_CONTROL_RTC_96 = 0x00000010, + DMA_CONTROL_RTC_128 = 0x00000018, +}; +#define DMA_CONTROL_TC_RX_MASK 0xffffffe7 + +#define DMA_CONTROL_OSF 0x00000004 /* Operate on second frame */ + +/* MMC registers offset */ +#define GMAC_MMC_CTRL 0x100 +#define GMAC_MMC_RX_INTR 0x104 +#define GMAC_MMC_TX_INTR 0x108 +#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 + +#undef DWMAC1000_DEBUG +/* #define DWMAC1000__DEBUG */ +#undef FRAME_FILTER_DEBUG +/* #define FRAME_FILTER_DEBUG */ +#ifdef DWMAC1000__DEBUG +#define DBG(fmt, args...) printk(fmt, ## args) +#else +#define DBG(fmt, args...) do { } while (0) +#endif + +extern struct stmmac_dma_ops dwmac1000_dma_ops; +extern struct stmmac_desc_ops dwmac1000_desc_ops; diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c new file mode 100644 index 000000000000..928eac05b912 --- /dev/null +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -0,0 +1,245 @@ +/******************************************************************************* + This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. + DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for + developing this code. + + This only implements the mac core functions for this chip. + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#include +#include "dwmac1000.h" + +static void dwmac1000_core_init(unsigned long ioaddr) +{ + u32 value = readl(ioaddr + GMAC_CONTROL); + value |= GMAC_CORE_INIT; + writel(value, ioaddr + GMAC_CONTROL); + + /* STBus Bridge Configuration */ + /*writel(0xc5608, ioaddr + 0x00007000);*/ + + /* Freeze MMC counters */ + writel(0x8, ioaddr + GMAC_MMC_CTRL); + /* Mask GMAC interrupts */ + writel(0x207, ioaddr + GMAC_INT_MASK); + +#ifdef STMMAC_VLAN_TAG_USED + /* Tag detection without filtering */ + writel(0x0, ioaddr + GMAC_VLAN_TAG); +#endif + return; +} + +static void dwmac1000_dump_regs(unsigned long ioaddr) +{ + int i; + pr_info("\tDWMAC1000 regs (base addr = 0x%8x)\n", (unsigned int)ioaddr); + + for (i = 0; i < 55; i++) { + int offset = i * 4; + pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i, + offset, readl(ioaddr + offset)); + } + return; +} + +static void dwmac1000_set_umac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int reg_n) +{ + stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), + GMAC_ADDR_LOW(reg_n)); +} + +static void dwmac1000_get_umac_addr(unsigned long ioaddr, unsigned char *addr, + unsigned int reg_n) +{ + stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), + GMAC_ADDR_LOW(reg_n)); +} + +static void dwmac1000_set_filter(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int value = 0; + + DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", + __func__, dev->mc_count, dev->uc.count); + + if (dev->flags & IFF_PROMISC) + value = GMAC_FRAME_FILTER_PR; + else if ((dev->mc_count > HASH_TABLE_SIZE) + || (dev->flags & IFF_ALLMULTI)) { + value = GMAC_FRAME_FILTER_PM; /* pass all multi */ + writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); + writel(0xffffffff, ioaddr + GMAC_HASH_LOW); + } else if (dev->mc_count > 0) { + int i; + u32 mc_filter[2]; + struct dev_mc_list *mclist; + + /* Hash filter for multicast */ + value = GMAC_FRAME_FILTER_HMC; + + memset(mc_filter, 0, sizeof(mc_filter)); + for (i = 0, mclist = dev->mc_list; + mclist && i < dev->mc_count; i++, mclist = mclist->next) { + /* The upper 6 bits of the calculated CRC are used to + index the contens of the hash table */ + int bit_nr = + bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26; + /* The most significant bit determines the register to + * use (H/L) while the other 5 bits determine the bit + * within the register. */ + mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); + } + writel(mc_filter[0], ioaddr + GMAC_HASH_LOW); + writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); + } + + /* Handle multiple unicast addresses (perfect filtering)*/ + if (dev->uc.count > GMAC_MAX_UNICAST_ADDRESSES) + /* Switch to promiscuous mode is more than 16 addrs + are required */ + value |= GMAC_FRAME_FILTER_PR; + else { + int reg = 1; + struct netdev_hw_addr *ha; + + list_for_each_entry(ha, &dev->uc.list, list) { + dwmac1000_set_umac_addr(ioaddr, ha->addr, reg); + reg++; + } + } + +#ifdef FRAME_FILTER_DEBUG + /* Enable Receive all mode (to debug filtering_fail errors) */ + value |= GMAC_FRAME_FILTER_RA; +#endif + writel(value, ioaddr + GMAC_FRAME_FILTER); + + DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: " + "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER), + readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); + + return; +} + +static void dwmac1000_flow_ctrl(unsigned long ioaddr, unsigned int duplex, + unsigned int fc, unsigned int pause_time) +{ + unsigned int flow = 0; + + DBG(KERN_DEBUG "GMAC Flow-Control:\n"); + if (fc & FLOW_RX) { + DBG(KERN_DEBUG "\tReceive Flow-Control ON\n"); + flow |= GMAC_FLOW_CTRL_RFE; + } + if (fc & FLOW_TX) { + DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n"); + flow |= GMAC_FLOW_CTRL_TFE; + } + + if (duplex) { + DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time); + flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); + } + + writel(flow, ioaddr + GMAC_FLOW_CTRL); + return; +} + +static void dwmac1000_pmt(unsigned long ioaddr, unsigned long mode) +{ + unsigned int pmt = 0; + + if (mode == WAKE_MAGIC) { + DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); + pmt |= power_down | magic_pkt_en; + } else if (mode == WAKE_UCAST) { + DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); + pmt |= global_unicast; + } + + writel(pmt, ioaddr + GMAC_PMT); + return; +} + + +static void dwmac1000_irq_status(unsigned long ioaddr) +{ + u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); + + /* Not used events (e.g. MMC interrupts) are not handled. */ + if ((intr_status & mmc_tx_irq)) + DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n", + readl(ioaddr + GMAC_MMC_TX_INTR)); + if (unlikely(intr_status & mmc_rx_irq)) + DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n", + readl(ioaddr + GMAC_MMC_RX_INTR)); + if (unlikely(intr_status & mmc_rx_csum_offload_irq)) + DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n", + readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); + if (unlikely(intr_status & pmt_irq)) { + DBG(KERN_DEBUG "GMAC: received Magic frame\n"); + /* clear the PMT bits 5 and 6 by reading the PMT + * status register. */ + readl(ioaddr + GMAC_PMT); + } + + return; +} + +struct stmmac_ops dwmac1000_ops = { + .core_init = dwmac1000_core_init, + .dump_regs = dwmac1000_dump_regs, + .host_irq_status = dwmac1000_irq_status, + .set_filter = dwmac1000_set_filter, + .flow_ctrl = dwmac1000_flow_ctrl, + .pmt = dwmac1000_pmt, + .set_umac_addr = dwmac1000_set_umac_addr, + .get_umac_addr = dwmac1000_get_umac_addr, +}; + +struct mac_device_info *dwmac1000_setup(unsigned long ioaddr) +{ + struct mac_device_info *mac; + u32 uid = readl(ioaddr + GMAC_VERSION); + + pr_info("\tDWMAC1000 - user ID: 0x%x, Synopsys ID: 0x%x\n", + ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff)); + + mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); + + mac->mac = &dwmac1000_ops; + mac->desc = &dwmac1000_desc_ops; + mac->dma = &dwmac1000_dma_ops; + + mac->pmt = PMT_SUPPORTED; + mac->link.port = GMAC_CONTROL_PS; + mac->link.duplex = GMAC_CONTROL_DM; + mac->link.speed = GMAC_CONTROL_FES; + mac->mii.addr = GMAC_MII_ADDR; + mac->mii.data = GMAC_MII_DATA; + + return mac; +} diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c new file mode 100644 index 000000000000..68245508e2de --- /dev/null +++ b/drivers/net/stmmac/dwmac1000_dma.c @@ -0,0 +1,474 @@ +/******************************************************************************* + This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. + DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for + developing this code. + + This contains the functions to handle the dma and descriptors. + + Copyright (C) 2007-2009 STMicroelectronics Ltd + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Author: Giuseppe Cavallaro +*******************************************************************************/ + +#include "dwmac1000.h" +#include "dwmac_dma.h" + +static int dwmac1000_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, + u32 dma_rx) +{ + u32 value = readl(ioaddr + DMA_BUS_MODE); + /* DMA SW reset */ + value |= DMA_BUS_MODE_SFT_RESET; + writel(value, ioaddr + DMA_BUS_MODE); + do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)); + + value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL | + ((pbl << DMA_BUS_MODE_PBL_SHIFT) | + (pbl << DMA_BUS_MODE_RPBL_SHIFT)); + +#ifdef CONFIG_STMMAC_DA + value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */ +#endif + writel(value, ioaddr + DMA_BUS_MODE); + + /* Mask interrupts by writing to CSR7 */ + writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); + + /* The base address of the RX/TX descriptor lists must be written into + * DMA CSR3 and CSR4, respectively. */ + writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); + writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); + + return 0; +} + +/* Transmit FIFO flush operation */ +static void dwmac1000_flush_tx_fifo(unsigned long ioaddr) +{ + u32 csr6 = readl(ioaddr + DMA_CONTROL); + writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL); + + do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF)); +} + +static void dwmac1000_dma_operation_mode(unsigned long ioaddr, int txmode, + int rxmode) +{ + u32 csr6 = readl(ioaddr + DMA_CONTROL); + + if (txmode == SF_DMA_MODE) { + DBG(KERN_DEBUG "GMAC: enabling TX store and forward mode\n"); + /* Transmit COE type 2 cannot be done in cut-through mode. */ + csr6 |= DMA_CONTROL_TSF; + /* Operating on second frame increase the performance + * especially when transmit store-and-forward is used.*/ + csr6 |= DMA_CONTROL_OSF; + } else { + DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode" + " (threshold = %d)\n", txmode); + csr6 &= ~DMA_CONTROL_TSF; + csr6 &= DMA_CONTROL_TC_TX_MASK; + /* Set the transmit threshold */ + if (txmode <= 32) + csr6 |= DMA_CONTROL_TTC_32; + else if (txmode <= 64) + csr6 |= DMA_CONTROL_TTC_64; + else if (txmode <= 128) + csr6 |= DMA_CONTROL_TTC_128; + else if (txmode <= 192) + csr6 |= DMA_CONTROL_TTC_192; + else + csr6 |= DMA_CONTROL_TTC_256; + } + + if (rxmode == SF_DMA_MODE) { + DBG(KERN_DEBUG "GMAC: enabling RX store and forward mode\n"); + csr6 |= DMA_CONTROL_RSF; + } else { + DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode" + " (threshold = %d)\n", rxmode); + csr6 &= ~DMA_CONTROL_RSF; + csr6 &= DMA_CONTROL_TC_RX_MASK; + if (rxmode <= 32) + csr6 |= DMA_CONTROL_RTC_32; + else if (rxmode <= 64) + csr6 |= DMA_CONTROL_RTC_64; + else if (rxmode <= 96) + csr6 |= DMA_CONTROL_RTC_96; + else + csr6 |= DMA_CONTROL_RTC_128; + } + + writel(csr6, ioaddr + DMA_CONTROL); + return; +} + +/* Not yet implemented --- no RMON module */ +static void dwmac1000_dma_diagnostic_fr(void *data, + struct stmmac_extra_stats *x, unsigned long ioaddr) +{ + return; +} + +static void dwmac1000_dump_dma_regs(unsigned long ioaddr) +{ + int i; + pr_info(" DMA registers\n"); + for (i = 0; i < 22; i++) { + if ((i < 9) || (i > 17)) { + int offset = i * 4; + pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i, + (DMA_BUS_MODE + offset), + readl(ioaddr + DMA_BUS_MODE + offset)); + } + } + return; +} + +static int dwmac1000_get_tx_frame_status(void *data, + struct stmmac_extra_stats *x, + struct dma_desc *p, unsigned long ioaddr) +{ + int ret = 0; + struct net_device_stats *stats = (struct net_device_stats *)data; + + if (unlikely(p->des01.etx.error_summary)) { + DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx); + if (unlikely(p->des01.etx.jabber_timeout)) { + DBG(KERN_ERR "\tjabber_timeout error\n"); + x->tx_jabber++; + } + + if (unlikely(p->des01.etx.frame_flushed)) { + DBG(KERN_ERR "\tframe_flushed error\n"); + x->tx_frame_flushed++; + dwmac1000_flush_tx_fifo(ioaddr); + } + + if (unlikely(p->des01.etx.loss_carrier)) { + DBG(KERN_ERR "\tloss_carrier error\n"); + x->tx_losscarrier++; + stats->tx_carrier_errors++; + } + if (unlikely(p->des01.etx.no_carrier)) { + DBG(KERN_ERR "\tno_carrier error\n"); + x->tx_carrier++; + stats->tx_carrier_errors++; + } + if (unlikely(p->des01.etx.late_collision)) { + DBG(KERN_ERR "\tlate_collision error\n"); + stats->collisions += p->des01.etx.collision_count; + } + if (unlikely(p->des01.etx.excessive_collisions)) { + DBG(KERN_ERR "\texcessive_collisions\n"); + stats->collisions += p->des01.etx.collision_count; + } + if (unlikely(p->des01.etx.excessive_deferral)) { + DBG(KERN_INFO "\texcessive tx_deferral\n"); + x->tx_deferred++; + } + + if (unlikely(p->des01.etx.underflow_error)) { + DBG(KERN_ERR "\tunderflow error\n"); + dwmac1000_flush_tx_fifo(ioaddr); + x->tx_underflow++; + } + + if (unlikely(p->des01.etx.ip_header_error)) { + DBG(KERN_ERR "\tTX IP header csum error\n"); + x->tx_ip_header_error++; + } + + if (unlikely(p->des01.etx.payload_error)) { + DBG(KERN_ERR "\tAddr/Payload csum error\n"); + x->tx_payload_error++; + dwmac1000_flush_tx_fifo(ioaddr); + } + + ret = -1; + } + + if (unlikely(p->des01.etx.deferred)) { + DBG(KERN_INFO "GMAC TX status: tx deferred\n"); + x->tx_deferred++; + } +#ifdef STMMAC_VLAN_TAG_USED + if (p->des01.etx.vlan_frame) { + DBG(KERN_INFO "GMAC TX status: VLAN frame\n"); + x->tx_vlan++; + } +#endif + + return ret; +} + +static int dwmac1000_get_tx_len(struct dma_desc *p) +{ + return p->des01.etx.buffer1_size; +} + +static int dwmac1000_coe_rdes0(int ipc_err, int type, int payload_err) +{ + int ret = good_frame; + u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7; + + /* bits 5 7 0 | Frame status + * ---------------------------------------------------------- + * 0 0 0 | IEEE 802.3 Type frame (lenght < 1536 octects) + * 1 0 0 | IPv4/6 No CSUM errorS. + * 1 0 1 | IPv4/6 CSUM PAYLOAD error + * 1 1 0 | IPv4/6 CSUM IP HR error + * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS + * 0 0 1 | IPv4/6 unsupported IP PAYLOAD + * 0 1 1 | COE bypassed.. no IPv4/6 frame + * 0 1 0 | Reserved. + */ + if (status == 0x0) { + DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n"); + ret = good_frame; + } else if (status == 0x4) { + DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n"); + ret = good_frame; + } else if (status == 0x5) { + DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n"); + ret = csum_none; + } else if (status == 0x6) { + DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n"); + ret = csum_none; + } else if (status == 0x7) { + DBG(KERN_ERR + "RX Des0 status: IPv4/6 Header and Payload Error.\n"); + ret = csum_none; + } else if (status == 0x1) { + DBG(KERN_ERR + "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n"); + ret = discard_frame; + } else if (status == 0x3) { + DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n"); + ret = discard_frame; + } + return ret; +} + +static int dwmac1000_get_rx_frame_status(void *data, + struct stmmac_extra_stats *x, struct dma_desc *p) +{ + int ret = good_frame; + struct net_device_stats *stats = (struct net_device_stats *)data; + + if (unlikely(p->des01.erx.error_summary)) { + DBG(KERN_ERR "GMAC RX Error Summary... 0x%08x\n", p->des01.erx); + if (unlikely(p->des01.erx.descriptor_error)) { + DBG(KERN_ERR "\tdescriptor error\n"); + x->rx_desc++; + stats->rx_length_errors++; + } + if (unlikely(p->des01.erx.overflow_error)) { + DBG(KERN_ERR "\toverflow error\n"); + x->rx_gmac_overflow++; + } + + if (unlikely(p->des01.erx.ipc_csum_error)) + DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n"); + + if (unlikely(p->des01.erx.late_collision)) { + DBG(KERN_ERR "\tlate_collision error\n"); + stats->collisions++; + stats->collisions++; + } + if (unlikely(p->des01.erx.receive_watchdog)) { + DBG(KERN_ERR "\treceive_watchdog error\n"); + x->rx_watchdog++; + } + if (unlikely(p->des01.erx.error_gmii)) { + DBG(KERN_ERR "\tReceive Error\n"); + x->rx_mii++; + } + if (unlikely(p->des01.erx.crc_error)) { + DBG(KERN_ERR "\tCRC error\n"); + x->rx_crc++; + stats->rx_crc_errors++; + } + ret = discard_frame; + } + + /* After a payload csum error, the ES bit is set. + * It doesn't match with the information reported into the databook. + * At any rate, we need to understand if the CSUM hw computation is ok + * and report this info to the upper layers. */ + ret = dwmac1000_coe_rdes0(p->des01.erx.ipc_csum_error, + p->des01.erx.frame_type, p->des01.erx.payload_csum_error); + + if (unlikely(p->des01.erx.dribbling)) { + DBG(KERN_ERR "GMAC RX: dribbling error\n"); + ret = discard_frame; + } + if (unlikely(p->des01.erx.sa_filter_fail)) { + DBG(KERN_ERR "GMAC RX : Source Address filter fail\n"); + x->sa_rx_filter_fail++; + ret = discard_frame; + } + if (unlikely(p->des01.erx.da_filter_fail)) { + DBG(KERN_ERR "GMAC RX : Destination Address filter fail\n"); + x->da_rx_filter_fail++; + ret = discard_frame; + } + if (unlikely(p->des01.erx.length_error)) { + DBG(KERN_ERR "GMAC RX: length_error error\n"); + x->rx_lenght++; + ret = discard_frame; + } +#ifdef STMMAC_VLAN_TAG_USED + if (p->des01.erx.vlan_tag) { + DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n"); + x->rx_vlan++; + } +#endif + return ret; +} + +static void dwmac1000_init_rx_desc(struct dma_desc *p, unsigned int ring_size, + int disable_rx_ic) +{ + int i; + for (i = 0; i < ring_size; i++) { + p->des01.erx.own = 1; + p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1; + /* To support jumbo frames */ + p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1; + if (i == ring_size - 1) + p->des01.erx.end_ring = 1; + if (disable_rx_ic) + p->des01.erx.disable_ic = 1; + p++; + } + return; +} + +static void dwmac1000_init_tx_desc(struct dma_desc *p, unsigned int ring_size) +{ + int i; + + for (i = 0; i < ring_size; i++) { + p->des01.etx.own = 0; + if (i == ring_size - 1) + p->des01.etx.end_ring = 1; + p++; + } + + return; +} + +static int dwmac1000_get_tx_owner(struct dma_desc *p) +{ + return p->des01.etx.own; +} + +static int dwmac1000_get_rx_owner(struct dma_desc *p) +{ + return p->des01.erx.own; +} + +static void dwmac1000_set_tx_owner(struct dma_desc *p) +{ + p->des01.etx.own = 1; +} + +static void dwmac1000_set_rx_owner(struct dma_desc *p) +{ + p->des01.erx.own = 1; +} + +static int dwmac1000_get_tx_ls(struct dma_desc *p) +{ + return p->des01.etx.last_segment; +} + +static void dwmac1000_release_tx_desc(struct dma_desc *p) +{ + int ter = p->des01.etx.end_ring; + + memset(p, 0, sizeof(struct dma_desc)); + p->des01.etx.end_ring = ter; + + return; +} + +static void dwmac1000_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, + int csum_flag) +{ + p->des01.etx.first_segment = is_fs; + if (unlikely(len > BUF_SIZE_4KiB)) { + p->des01.etx.buffer1_size = BUF_SIZE_4KiB; + p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB; + } else { + p->des01.etx.buffer1_size = len; + } + if (likely(csum_flag)) + p->des01.etx.checksum_insertion = cic_full; +} + +static void dwmac1000_clear_tx_ic(struct dma_desc *p) +{ + p->des01.etx.interrupt = 0; +} + +static void dwmac1000_close_tx_desc(struct dma_desc *p) +{ + p->des01.etx.last_segment = 1; + p->des01.etx.interrupt = 1; +} + +static int dwmac1000_get_rx_frame_len(struct dma_desc *p) +{ + return p->des01.erx.frame_length; +} + +struct stmmac_dma_ops dwmac1000_dma_ops = { + .init = dwmac1000_dma_init, + .dump_regs = dwmac1000_dump_dma_regs, + .dma_mode = dwmac1000_dma_operation_mode, + .dma_diagnostic_fr = dwmac1000_dma_diagnostic_fr, + .enable_dma_transmission = dwmac_enable_dma_transmission, + .enable_dma_irq = dwmac_enable_dma_irq, + .disable_dma_irq = dwmac_disable_dma_irq, + .start_tx = dwmac_dma_start_tx, + .stop_tx = dwmac_dma_stop_tx, + .start_rx = dwmac_dma_start_rx, + .stop_rx = dwmac_dma_stop_rx, + .dma_interrupt = dwmac_dma_interrupt, +}; + +struct stmmac_desc_ops dwmac1000_desc_ops = { + .tx_status = dwmac1000_get_tx_frame_status, + .rx_status = dwmac1000_get_rx_frame_status, + .get_tx_len = dwmac1000_get_tx_len, + .init_rx_desc = dwmac1000_init_rx_desc, + .init_tx_desc = dwmac1000_init_tx_desc, + .get_tx_owner = dwmac1000_get_tx_owner, + .get_rx_owner = dwmac1000_get_rx_owner, + .release_tx_desc = dwmac1000_release_tx_desc, + .prepare_tx_desc = dwmac1000_prepare_tx_desc, + .clear_tx_ic = dwmac1000_clear_tx_ic, + .close_tx_desc = dwmac1000_close_tx_desc, + .get_tx_ls = dwmac1000_get_tx_ls, + .set_tx_owner = dwmac1000_set_tx_owner, + .set_rx_owner = dwmac1000_set_rx_owner, + .get_rx_frame_len = dwmac1000_get_rx_frame_len, +}; diff --git a/drivers/net/stmmac/gmac.c b/drivers/net/stmmac/gmac.c deleted file mode 100644 index 07880922ff46..000000000000 --- a/drivers/net/stmmac/gmac.c +++ /dev/null @@ -1,700 +0,0 @@ -/******************************************************************************* - This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. - DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for - developing this code. - - Copyright (C) 2007-2009 STMicroelectronics Ltd - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Author: Giuseppe Cavallaro -*******************************************************************************/ - -#include -#include -#include -#include - -#include "stmmac.h" -#include "gmac.h" -#include "dwmac_dma.h" - -#undef GMAC_DEBUG -/*#define GMAC_DEBUG*/ -#undef FRAME_FILTER_DEBUG -/*#define FRAME_FILTER_DEBUG*/ -#ifdef GMAC_DEBUG -#define DBG(fmt, args...) printk(fmt, ## args) -#else -#define DBG(fmt, args...) do { } while (0) -#endif - -static void gmac_dump_regs(unsigned long ioaddr) -{ - int i; - pr_info("\t----------------------------------------------\n" - "\t GMAC registers (base addr = 0x%8x)\n" - "\t----------------------------------------------\n", - (unsigned int)ioaddr); - - for (i = 0; i < 55; i++) { - int offset = i * 4; - pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i, - offset, readl(ioaddr + offset)); - } - return; -} - -static int gmac_dma_init(unsigned long ioaddr, int pbl, u32 dma_tx, u32 dma_rx) -{ - u32 value = readl(ioaddr + DMA_BUS_MODE); - /* DMA SW reset */ - value |= DMA_BUS_MODE_SFT_RESET; - writel(value, ioaddr + DMA_BUS_MODE); - do {} while ((readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)); - - value = /* DMA_BUS_MODE_FB | */ DMA_BUS_MODE_4PBL | - ((pbl << DMA_BUS_MODE_PBL_SHIFT) | - (pbl << DMA_BUS_MODE_RPBL_SHIFT)); - -#ifdef CONFIG_STMMAC_DA - value |= DMA_BUS_MODE_DA; /* Rx has priority over tx */ -#endif - writel(value, ioaddr + DMA_BUS_MODE); - - /* Mask interrupts by writing to CSR7 */ - writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); - - /* The base address of the RX/TX descriptor lists must be written into - * DMA CSR3 and CSR4, respectively. */ - writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); - writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); - - return 0; -} - -/* Transmit FIFO flush operation */ -static void gmac_flush_tx_fifo(unsigned long ioaddr) -{ - u32 csr6 = readl(ioaddr + DMA_CONTROL); - writel((csr6 | DMA_CONTROL_FTF), ioaddr + DMA_CONTROL); - - do {} while ((readl(ioaddr + DMA_CONTROL) & DMA_CONTROL_FTF)); -} - -static void gmac_dma_operation_mode(unsigned long ioaddr, int txmode, - int rxmode) -{ - u32 csr6 = readl(ioaddr + DMA_CONTROL); - - if (txmode == SF_DMA_MODE) { - DBG(KERN_DEBUG "GMAC: enabling TX store and forward mode\n"); - /* Transmit COE type 2 cannot be done in cut-through mode. */ - csr6 |= DMA_CONTROL_TSF; - /* Operating on second frame increase the performance - * especially when transmit store-and-forward is used.*/ - csr6 |= DMA_CONTROL_OSF; - } else { - DBG(KERN_DEBUG "GMAC: disabling TX store and forward mode" - " (threshold = %d)\n", txmode); - csr6 &= ~DMA_CONTROL_TSF; - csr6 &= DMA_CONTROL_TC_TX_MASK; - /* Set the transmit threshold */ - if (txmode <= 32) - csr6 |= DMA_CONTROL_TTC_32; - else if (txmode <= 64) - csr6 |= DMA_CONTROL_TTC_64; - else if (txmode <= 128) - csr6 |= DMA_CONTROL_TTC_128; - else if (txmode <= 192) - csr6 |= DMA_CONTROL_TTC_192; - else - csr6 |= DMA_CONTROL_TTC_256; - } - - if (rxmode == SF_DMA_MODE) { - DBG(KERN_DEBUG "GMAC: enabling RX store and forward mode\n"); - csr6 |= DMA_CONTROL_RSF; - } else { - DBG(KERN_DEBUG "GMAC: disabling RX store and forward mode" - " (threshold = %d)\n", rxmode); - csr6 &= ~DMA_CONTROL_RSF; - csr6 &= DMA_CONTROL_TC_RX_MASK; - if (rxmode <= 32) - csr6 |= DMA_CONTROL_RTC_32; - else if (rxmode <= 64) - csr6 |= DMA_CONTROL_RTC_64; - else if (rxmode <= 96) - csr6 |= DMA_CONTROL_RTC_96; - else - csr6 |= DMA_CONTROL_RTC_128; - } - - writel(csr6, ioaddr + DMA_CONTROL); - return; -} - -/* Not yet implemented --- no RMON module */ -static void gmac_dma_diagnostic_fr(void *data, struct stmmac_extra_stats *x, - unsigned long ioaddr) -{ - return; -} - -static void gmac_dump_dma_regs(unsigned long ioaddr) -{ - int i; - pr_info(" DMA registers\n"); - for (i = 0; i < 22; i++) { - if ((i < 9) || (i > 17)) { - int offset = i * 4; - pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i, - (DMA_BUS_MODE + offset), - readl(ioaddr + DMA_BUS_MODE + offset)); - } - } - return; -} - -static int gmac_get_tx_frame_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p, unsigned long ioaddr) -{ - int ret = 0; - struct net_device_stats *stats = (struct net_device_stats *)data; - - if (unlikely(p->des01.etx.error_summary)) { - DBG(KERN_ERR "GMAC TX error... 0x%08x\n", p->des01.etx); - if (unlikely(p->des01.etx.jabber_timeout)) { - DBG(KERN_ERR "\tjabber_timeout error\n"); - x->tx_jabber++; - } - - if (unlikely(p->des01.etx.frame_flushed)) { - DBG(KERN_ERR "\tframe_flushed error\n"); - x->tx_frame_flushed++; - gmac_flush_tx_fifo(ioaddr); - } - - if (unlikely(p->des01.etx.loss_carrier)) { - DBG(KERN_ERR "\tloss_carrier error\n"); - x->tx_losscarrier++; - stats->tx_carrier_errors++; - } - if (unlikely(p->des01.etx.no_carrier)) { - DBG(KERN_ERR "\tno_carrier error\n"); - x->tx_carrier++; - stats->tx_carrier_errors++; - } - if (unlikely(p->des01.etx.late_collision)) { - DBG(KERN_ERR "\tlate_collision error\n"); - stats->collisions += p->des01.etx.collision_count; - } - if (unlikely(p->des01.etx.excessive_collisions)) { - DBG(KERN_ERR "\texcessive_collisions\n"); - stats->collisions += p->des01.etx.collision_count; - } - if (unlikely(p->des01.etx.excessive_deferral)) { - DBG(KERN_INFO "\texcessive tx_deferral\n"); - x->tx_deferred++; - } - - if (unlikely(p->des01.etx.underflow_error)) { - DBG(KERN_ERR "\tunderflow error\n"); - gmac_flush_tx_fifo(ioaddr); - x->tx_underflow++; - } - - if (unlikely(p->des01.etx.ip_header_error)) { - DBG(KERN_ERR "\tTX IP header csum error\n"); - x->tx_ip_header_error++; - } - - if (unlikely(p->des01.etx.payload_error)) { - DBG(KERN_ERR "\tAddr/Payload csum error\n"); - x->tx_payload_error++; - gmac_flush_tx_fifo(ioaddr); - } - - ret = -1; - } - - if (unlikely(p->des01.etx.deferred)) { - DBG(KERN_INFO "GMAC TX status: tx deferred\n"); - x->tx_deferred++; - } -#ifdef STMMAC_VLAN_TAG_USED - if (p->des01.etx.vlan_frame) { - DBG(KERN_INFO "GMAC TX status: VLAN frame\n"); - x->tx_vlan++; - } -#endif - - return ret; -} - -static int gmac_get_tx_len(struct dma_desc *p) -{ - return p->des01.etx.buffer1_size; -} - -static int gmac_coe_rdes0(int ipc_err, int type, int payload_err) -{ - int ret = good_frame; - u32 status = (type << 2 | ipc_err << 1 | payload_err) & 0x7; - - /* bits 5 7 0 | Frame status - * ---------------------------------------------------------- - * 0 0 0 | IEEE 802.3 Type frame (lenght < 1536 octects) - * 1 0 0 | IPv4/6 No CSUM errorS. - * 1 0 1 | IPv4/6 CSUM PAYLOAD error - * 1 1 0 | IPv4/6 CSUM IP HR error - * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS - * 0 0 1 | IPv4/6 unsupported IP PAYLOAD - * 0 1 1 | COE bypassed.. no IPv4/6 frame - * 0 1 0 | Reserved. - */ - if (status == 0x0) { - DBG(KERN_INFO "RX Des0 status: IEEE 802.3 Type frame.\n"); - ret = good_frame; - } else if (status == 0x4) { - DBG(KERN_INFO "RX Des0 status: IPv4/6 No CSUM errorS.\n"); - ret = good_frame; - } else if (status == 0x5) { - DBG(KERN_ERR "RX Des0 status: IPv4/6 Payload Error.\n"); - ret = csum_none; - } else if (status == 0x6) { - DBG(KERN_ERR "RX Des0 status: IPv4/6 Header Error.\n"); - ret = csum_none; - } else if (status == 0x7) { - DBG(KERN_ERR - "RX Des0 status: IPv4/6 Header and Payload Error.\n"); - ret = csum_none; - } else if (status == 0x1) { - DBG(KERN_ERR - "RX Des0 status: IPv4/6 unsupported IP PAYLOAD.\n"); - ret = discard_frame; - } else if (status == 0x3) { - DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n"); - ret = discard_frame; - } - return ret; -} - -static int gmac_get_rx_frame_status(void *data, struct stmmac_extra_stats *x, - struct dma_desc *p) -{ - int ret = good_frame; - struct net_device_stats *stats = (struct net_device_stats *)data; - - if (unlikely(p->des01.erx.error_summary)) { - DBG(KERN_ERR "GMAC RX Error Summary... 0x%08x\n", p->des01.erx); - if (unlikely(p->des01.erx.descriptor_error)) { - DBG(KERN_ERR "\tdescriptor error\n"); - x->rx_desc++; - stats->rx_length_errors++; - } - if (unlikely(p->des01.erx.overflow_error)) { - DBG(KERN_ERR "\toverflow error\n"); - x->rx_gmac_overflow++; - } - - if (unlikely(p->des01.erx.ipc_csum_error)) - DBG(KERN_ERR "\tIPC Csum Error/Giant frame\n"); - - if (unlikely(p->des01.erx.late_collision)) { - DBG(KERN_ERR "\tlate_collision error\n"); - stats->collisions++; - stats->collisions++; - } - if (unlikely(p->des01.erx.receive_watchdog)) { - DBG(KERN_ERR "\treceive_watchdog error\n"); - x->rx_watchdog++; - } - if (unlikely(p->des01.erx.error_gmii)) { - DBG(KERN_ERR "\tReceive Error\n"); - x->rx_mii++; - } - if (unlikely(p->des01.erx.crc_error)) { - DBG(KERN_ERR "\tCRC error\n"); - x->rx_crc++; - stats->rx_crc_errors++; - } - ret = discard_frame; - } - - /* After a payload csum error, the ES bit is set. - * It doesn't match with the information reported into the databook. - * At any rate, we need to understand if the CSUM hw computation is ok - * and report this info to the upper layers. */ - ret = gmac_coe_rdes0(p->des01.erx.ipc_csum_error, - p->des01.erx.frame_type, p->des01.erx.payload_csum_error); - - if (unlikely(p->des01.erx.dribbling)) { - DBG(KERN_ERR "GMAC RX: dribbling error\n"); - ret = discard_frame; - } - if (unlikely(p->des01.erx.sa_filter_fail)) { - DBG(KERN_ERR "GMAC RX : Source Address filter fail\n"); - x->sa_rx_filter_fail++; - ret = discard_frame; - } - if (unlikely(p->des01.erx.da_filter_fail)) { - DBG(KERN_ERR "GMAC RX : Destination Address filter fail\n"); - x->da_rx_filter_fail++; - ret = discard_frame; - } - if (unlikely(p->des01.erx.length_error)) { - DBG(KERN_ERR "GMAC RX: length_error error\n"); - x->rx_lenght++; - ret = discard_frame; - } -#ifdef STMMAC_VLAN_TAG_USED - if (p->des01.erx.vlan_tag) { - DBG(KERN_INFO "GMAC RX: VLAN frame tagged\n"); - x->rx_vlan++; - } -#endif - return ret; -} - -static void gmac_irq_status(unsigned long ioaddr) -{ - u32 intr_status = readl(ioaddr + GMAC_INT_STATUS); - - /* Not used events (e.g. MMC interrupts) are not handled. */ - if ((intr_status & mmc_tx_irq)) - DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n", - readl(ioaddr + GMAC_MMC_TX_INTR)); - if (unlikely(intr_status & mmc_rx_irq)) - DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n", - readl(ioaddr + GMAC_MMC_RX_INTR)); - if (unlikely(intr_status & mmc_rx_csum_offload_irq)) - DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n", - readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD)); - if (unlikely(intr_status & pmt_irq)) { - DBG(KERN_DEBUG "GMAC: received Magic frame\n"); - /* clear the PMT bits 5 and 6 by reading the PMT - * status register. */ - readl(ioaddr + GMAC_PMT); - } - - return; -} - -static void gmac_core_init(unsigned long ioaddr) -{ - u32 value = readl(ioaddr + GMAC_CONTROL); - value |= GMAC_CORE_INIT; - writel(value, ioaddr + GMAC_CONTROL); - - /* Freeze MMC counters */ - writel(0x8, ioaddr + GMAC_MMC_CTRL); - /* Mask GMAC interrupts */ - writel(0x207, ioaddr + GMAC_INT_MASK); - -#ifdef STMMAC_VLAN_TAG_USED - /* Tag detection without filtering */ - writel(0x0, ioaddr + GMAC_VLAN_TAG); -#endif - return; -} - -static void gmac_set_umac_addr(unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n) -{ - stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), - GMAC_ADDR_LOW(reg_n)); -} - -static void gmac_get_umac_addr(unsigned long ioaddr, unsigned char *addr, - unsigned int reg_n) -{ - stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n), - GMAC_ADDR_LOW(reg_n)); -} - -static void gmac_set_filter(struct net_device *dev) -{ - unsigned long ioaddr = dev->base_addr; - unsigned int value = 0; - - DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", - __func__, dev->mc_count, dev->uc.count); - - if (dev->flags & IFF_PROMISC) - value = GMAC_FRAME_FILTER_PR; - else if ((dev->mc_count > HASH_TABLE_SIZE) - || (dev->flags & IFF_ALLMULTI)) { - value = GMAC_FRAME_FILTER_PM; /* pass all multi */ - writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); - writel(0xffffffff, ioaddr + GMAC_HASH_LOW); - } else if (dev->mc_count > 0) { - int i; - u32 mc_filter[2]; - struct dev_mc_list *mclist; - - /* Hash filter for multicast */ - value = GMAC_FRAME_FILTER_HMC; - - memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < dev->mc_count; i++, mclist = mclist->next) { - /* The upper 6 bits of the calculated CRC are used to - index the contens of the hash table */ - int bit_nr = - bitrev32(~crc32_le(~0, mclist->dmi_addr, 6)) >> 26; - /* The most significant bit determines the register to - * use (H/L) while the other 5 bits determine the bit - * within the register. */ - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - } - writel(mc_filter[0], ioaddr + GMAC_HASH_LOW); - writel(mc_filter[1], ioaddr + GMAC_HASH_HIGH); - } - - /* Handle multiple unicast addresses (perfect filtering)*/ - if (dev->uc.count > GMAC_MAX_UNICAST_ADDRESSES) - /* Switch to promiscuous mode is more than 16 addrs - are required */ - value |= GMAC_FRAME_FILTER_PR; - else { - int reg = 1; - struct netdev_hw_addr *ha; - - list_for_each_entry(ha, &dev->uc.list, list) { - gmac_set_umac_addr(ioaddr, ha->addr, reg); - reg++; - } - } - -#ifdef FRAME_FILTER_DEBUG - /* Enable Receive all mode (to debug filtering_fail errors) */ - value |= GMAC_FRAME_FILTER_RA; -#endif - writel(value, ioaddr + GMAC_FRAME_FILTER); - - DBG(KERN_INFO "\tFrame Filter reg: 0x%08x\n\tHash regs: " - "HI 0x%08x, LO 0x%08x\n", readl(ioaddr + GMAC_FRAME_FILTER), - readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW)); - - return; -} - -static void gmac_flow_ctrl(unsigned long ioaddr, unsigned int duplex, - unsigned int fc, unsigned int pause_time) -{ - unsigned int flow = 0; - - DBG(KERN_DEBUG "GMAC Flow-Control:\n"); - if (fc & FLOW_RX) { - DBG(KERN_DEBUG "\tReceive Flow-Control ON\n"); - flow |= GMAC_FLOW_CTRL_RFE; - } - if (fc & FLOW_TX) { - DBG(KERN_DEBUG "\tTransmit Flow-Control ON\n"); - flow |= GMAC_FLOW_CTRL_TFE; - } - - if (duplex) { - DBG(KERN_DEBUG "\tduplex mode: pause time: %d\n", pause_time); - flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); - } - - writel(flow, ioaddr + GMAC_FLOW_CTRL); - return; -} - -static void gmac_pmt(unsigned long ioaddr, unsigned long mode) -{ - unsigned int pmt = 0; - - if (mode == WAKE_MAGIC) { - DBG(KERN_DEBUG "GMAC: WOL Magic frame\n"); - pmt |= power_down | magic_pkt_en; - } else if (mode == WAKE_UCAST) { - DBG(KERN_DEBUG "GMAC: WOL on global unicast\n"); - pmt |= global_unicast; - } - - writel(pmt, ioaddr + GMAC_PMT); - return; -} - -static void gmac_init_rx_desc(struct dma_desc *p, unsigned int ring_size, - int disable_rx_ic) -{ - int i; - for (i = 0; i < ring_size; i++) { - p->des01.erx.own = 1; - p->des01.erx.buffer1_size = BUF_SIZE_8KiB - 1; - /* To support jumbo frames */ - p->des01.erx.buffer2_size = BUF_SIZE_8KiB - 1; - if (i == ring_size - 1) - p->des01.erx.end_ring = 1; - if (disable_rx_ic) - p->des01.erx.disable_ic = 1; - p++; - } - return; -} - -static void gmac_init_tx_desc(struct dma_desc *p, unsigned int ring_size) -{ - int i; - - for (i = 0; i < ring_size; i++) { - p->des01.etx.own = 0; - if (i == ring_size - 1) - p->des01.etx.end_ring = 1; - p++; - } - - return; -} - -static int gmac_get_tx_owner(struct dma_desc *p) -{ - return p->des01.etx.own; -} - -static int gmac_get_rx_owner(struct dma_desc *p) -{ - return p->des01.erx.own; -} - -static void gmac_set_tx_owner(struct dma_desc *p) -{ - p->des01.etx.own = 1; -} - -static void gmac_set_rx_owner(struct dma_desc *p) -{ - p->des01.erx.own = 1; -} - -static int gmac_get_tx_ls(struct dma_desc *p) -{ - return p->des01.etx.last_segment; -} - -static void gmac_release_tx_desc(struct dma_desc *p) -{ - int ter = p->des01.etx.end_ring; - - memset(p, 0, sizeof(struct dma_desc)); - p->des01.etx.end_ring = ter; - - return; -} - -static void gmac_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, - int csum_flag) -{ - p->des01.etx.first_segment = is_fs; - if (unlikely(len > BUF_SIZE_4KiB)) { - p->des01.etx.buffer1_size = BUF_SIZE_4KiB; - p->des01.etx.buffer2_size = len - BUF_SIZE_4KiB; - } else { - p->des01.etx.buffer1_size = len; - } - if (likely(csum_flag)) - p->des01.etx.checksum_insertion = cic_full; -} - -static void gmac_clear_tx_ic(struct dma_desc *p) -{ - p->des01.etx.interrupt = 0; -} - -static void gmac_close_tx_desc(struct dma_desc *p) -{ - p->des01.etx.last_segment = 1; - p->des01.etx.interrupt = 1; -} - -static int gmac_get_rx_frame_len(struct dma_desc *p) -{ - return p->des01.erx.frame_length; -} - -struct stmmac_ops gmac_ops = { - .core_init = gmac_core_init, - .dump_regs = gmac_dump_regs, - .host_irq_status = gmac_irq_status, - .set_filter = gmac_set_filter, - .flow_ctrl = gmac_flow_ctrl, - .pmt = gmac_pmt, - .set_umac_addr = gmac_set_umac_addr, - .get_umac_addr = gmac_get_umac_addr, -}; - -struct stmmac_dma_ops gmac_dma_ops = { - .init = gmac_dma_init, - .dump_regs = gmac_dump_dma_regs, - .dma_mode = gmac_dma_operation_mode, - .dma_diagnostic_fr = gmac_dma_diagnostic_fr, - .enable_dma_transmission = dwmac_enable_dma_transmission, - .enable_dma_irq = dwmac_enable_dma_irq, - .disable_dma_irq = dwmac_disable_dma_irq, - .start_tx = dwmac_dma_start_tx, - .stop_tx = dwmac_dma_stop_tx, - .start_rx = dwmac_dma_start_rx, - .stop_rx = dwmac_dma_stop_rx, - .dma_interrupt = dwmac_dma_interrupt, -}; - -struct stmmac_desc_ops gmac_desc_ops = { - .tx_status = gmac_get_tx_frame_status, - .rx_status = gmac_get_rx_frame_status, - .get_tx_len = gmac_get_tx_len, - .init_rx_desc = gmac_init_rx_desc, - .init_tx_desc = gmac_init_tx_desc, - .get_tx_owner = gmac_get_tx_owner, - .get_rx_owner = gmac_get_rx_owner, - .release_tx_desc = gmac_release_tx_desc, - .prepare_tx_desc = gmac_prepare_tx_desc, - .clear_tx_ic = gmac_clear_tx_ic, - .close_tx_desc = gmac_close_tx_desc, - .get_tx_ls = gmac_get_tx_ls, - .set_tx_owner = gmac_set_tx_owner, - .set_rx_owner = gmac_set_rx_owner, - .get_rx_frame_len = gmac_get_rx_frame_len, -}; - -struct mac_device_info *gmac_setup(unsigned long ioaddr) -{ - struct mac_device_info *mac; - u32 uid = readl(ioaddr + GMAC_VERSION); - - pr_info("\tGMAC - user ID: 0x%x, Synopsys ID: 0x%x\n", - ((uid & 0x0000ff00) >> 8), (uid & 0x000000ff)); - - mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL); - - mac->mac = &gmac_ops; - mac->desc = &gmac_desc_ops; - mac->dma = &gmac_dma_ops; - - mac->pmt = PMT_SUPPORTED; - mac->link.port = GMAC_CONTROL_PS; - mac->link.duplex = GMAC_CONTROL_DM; - mac->link.speed = GMAC_CONTROL_FES; - mac->mii.addr = GMAC_MII_ADDR; - mac->mii.data = GMAC_MII_DATA; - - return mac; -} diff --git a/drivers/net/stmmac/gmac.h b/drivers/net/stmmac/gmac.h deleted file mode 100644 index 2e82d6c9a148..000000000000 --- a/drivers/net/stmmac/gmac.h +++ /dev/null @@ -1,204 +0,0 @@ -/******************************************************************************* - Copyright (C) 2007-2009 STMicroelectronics Ltd - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Author: Giuseppe Cavallaro -*******************************************************************************/ - -#define GMAC_CONTROL 0x00000000 /* Configuration */ -#define GMAC_FRAME_FILTER 0x00000004 /* Frame Filter */ -#define GMAC_HASH_HIGH 0x00000008 /* Multicast Hash Table High */ -#define GMAC_HASH_LOW 0x0000000c /* Multicast Hash Table Low */ -#define GMAC_MII_ADDR 0x00000010 /* MII Address */ -#define GMAC_MII_DATA 0x00000014 /* MII Data */ -#define GMAC_FLOW_CTRL 0x00000018 /* Flow Control */ -#define GMAC_VLAN_TAG 0x0000001c /* VLAN Tag */ -#define GMAC_VERSION 0x00000020 /* GMAC CORE Version */ -#define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */ - -#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */ -enum gmac_irq_status { - time_stamp_irq = 0x0200, - mmc_rx_csum_offload_irq = 0x0080, - mmc_tx_irq = 0x0040, - mmc_rx_irq = 0x0020, - mmc_irq = 0x0010, - pmt_irq = 0x0008, - pcs_ane_irq = 0x0004, - pcs_link_irq = 0x0002, - rgmii_irq = 0x0001, -}; -#define GMAC_INT_MASK 0x0000003c /* interrupt mask register */ - -/* PMT Control and Status */ -#define GMAC_PMT 0x0000002c -enum power_event { - pointer_reset = 0x80000000, - global_unicast = 0x00000200, - wake_up_rx_frame = 0x00000040, - magic_frame = 0x00000020, - wake_up_frame_en = 0x00000004, - magic_pkt_en = 0x00000002, - power_down = 0x00000001, -}; - -/* GMAC HW ADDR regs */ -#define GMAC_ADDR_HIGH(reg) (0x00000040+(reg * 8)) -#define GMAC_ADDR_LOW(reg) (0x00000044+(reg * 8)) -#define GMAC_MAX_UNICAST_ADDRESSES 16 - -#define GMAC_AN_CTRL 0x000000c0 /* AN control */ -#define GMAC_AN_STATUS 0x000000c4 /* AN status */ -#define GMAC_ANE_ADV 0x000000c8 /* Auto-Neg. Advertisement */ -#define GMAC_ANE_LINK 0x000000cc /* Auto-Neg. link partener ability */ -#define GMAC_ANE_EXP 0x000000d0 /* ANE expansion */ -#define GMAC_TBI 0x000000d4 /* TBI extend status */ -#define GMAC_GMII_STATUS 0x000000d8 /* S/R-GMII status */ - -/* GMAC Configuration defines */ -#define GMAC_CONTROL_TC 0x01000000 /* Transmit Conf. in RGMII/SGMII */ -#define GMAC_CONTROL_WD 0x00800000 /* Disable Watchdog on receive */ -#define GMAC_CONTROL_JD 0x00400000 /* Jabber disable */ -#define GMAC_CONTROL_BE 0x00200000 /* Frame Burst Enable */ -#define GMAC_CONTROL_JE 0x00100000 /* Jumbo frame */ -enum inter_frame_gap { - GMAC_CONTROL_IFG_88 = 0x00040000, - GMAC_CONTROL_IFG_80 = 0x00020000, - GMAC_CONTROL_IFG_40 = 0x000e0000, -}; -#define GMAC_CONTROL_DCRS 0x00010000 /* Disable carrier sense during tx */ -#define GMAC_CONTROL_PS 0x00008000 /* Port Select 0:GMI 1:MII */ -#define GMAC_CONTROL_FES 0x00004000 /* Speed 0:10 1:100 */ -#define GMAC_CONTROL_DO 0x00002000 /* Disable Rx Own */ -#define GMAC_CONTROL_LM 0x00001000 /* Loop-back mode */ -#define GMAC_CONTROL_DM 0x00000800 /* Duplex Mode */ -#define GMAC_CONTROL_IPC 0x00000400 /* Checksum Offload */ -#define GMAC_CONTROL_DR 0x00000200 /* Disable Retry */ -#define GMAC_CONTROL_LUD 0x00000100 /* Link up/down */ -#define GMAC_CONTROL_ACS 0x00000080 /* Automatic Pad Stripping */ -#define GMAC_CONTROL_DC 0x00000010 /* Deferral Check */ -#define GMAC_CONTROL_TE 0x00000008 /* Transmitter Enable */ -#define GMAC_CONTROL_RE 0x00000004 /* Receiver Enable */ - -#define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \ - GMAC_CONTROL_IPC | GMAC_CONTROL_JE | GMAC_CONTROL_BE) - -/* GMAC Frame Filter defines */ -#define GMAC_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ -#define GMAC_FRAME_FILTER_HUC 0x00000002 /* Hash Unicast */ -#define GMAC_FRAME_FILTER_HMC 0x00000004 /* Hash Multicast */ -#define GMAC_FRAME_FILTER_DAIF 0x00000008 /* DA Inverse Filtering */ -#define GMAC_FRAME_FILTER_PM 0x00000010 /* Pass all multicast */ -#define GMAC_FRAME_FILTER_DBF 0x00000020 /* Disable Broadcast frames */ -#define GMAC_FRAME_FILTER_SAIF 0x00000100 /* Inverse Filtering */ -#define GMAC_FRAME_FILTER_SAF 0x00000200 /* Source Address Filter */ -#define GMAC_FRAME_FILTER_HPF 0x00000400 /* Hash or perfect Filter */ -#define GMAC_FRAME_FILTER_RA 0x80000000 /* Receive all mode */ -/* GMII ADDR defines */ -#define GMAC_MII_ADDR_WRITE 0x00000002 /* MII Write */ -#define GMAC_MII_ADDR_BUSY 0x00000001 /* MII Busy */ -/* GMAC FLOW CTRL defines */ -#define GMAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ -#define GMAC_FLOW_CTRL_PT_SHIFT 16 -#define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */ -#define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */ -#define GMAC_FLOW_CTRL_FCB_BPA 0x00000001 /* Flow Control Busy ... */ - -/*--- DMA BLOCK defines ---*/ -/* DMA Bus Mode register defines */ -#define DMA_BUS_MODE_SFT_RESET 0x00000001 /* Software Reset */ -#define DMA_BUS_MODE_DA 0x00000002 /* Arbitration scheme */ -#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ -#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ -/* Programmable burst length (passed thorugh platform)*/ -#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ -#define DMA_BUS_MODE_PBL_SHIFT 8 - -enum rx_tx_priority_ratio { - double_ratio = 0x00004000, /*2:1 */ - triple_ratio = 0x00008000, /*3:1 */ - quadruple_ratio = 0x0000c000, /*4:1 */ -}; - -#define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */ -#define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */ -#define DMA_BUS_MODE_RPBL_SHIFT 17 -#define DMA_BUS_MODE_USP 0x00800000 -#define DMA_BUS_MODE_4PBL 0x01000000 -#define DMA_BUS_MODE_AAL 0x02000000 - -/* DMA CRS Control and Status Register Mapping */ -#define DMA_HOST_TX_DESC 0x00001048 /* Current Host Tx descriptor */ -#define DMA_HOST_RX_DESC 0x0000104c /* Current Host Rx descriptor */ -/* DMA Bus Mode register defines */ -#define DMA_BUS_PR_RATIO_MASK 0x0000c000 /* Rx/Tx priority ratio */ -#define DMA_BUS_PR_RATIO_SHIFT 14 -#define DMA_BUS_FB 0x00010000 /* Fixed Burst */ - -/* DMA operation mode defines (start/stop tx/rx are placed in common header)*/ -#define DMA_CONTROL_DT 0x04000000 /* Disable Drop TCP/IP csum error */ -#define DMA_CONTROL_RSF 0x02000000 /* Receive Store and Forward */ -#define DMA_CONTROL_DFF 0x01000000 /* Disaable flushing */ -/* Threshold for Activating the FC */ -enum rfa { - act_full_minus_1 = 0x00800000, - act_full_minus_2 = 0x00800200, - act_full_minus_3 = 0x00800400, - act_full_minus_4 = 0x00800600, -}; -/* Threshold for Deactivating the FC */ -enum rfd { - deac_full_minus_1 = 0x00400000, - deac_full_minus_2 = 0x00400800, - deac_full_minus_3 = 0x00401000, - deac_full_minus_4 = 0x00401800, -}; -#define DMA_CONTROL_TSF 0x00200000 /* Transmit Store and Forward */ -#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ - -enum ttc_control { - DMA_CONTROL_TTC_64 = 0x00000000, - DMA_CONTROL_TTC_128 = 0x00004000, - DMA_CONTROL_TTC_192 = 0x00008000, - DMA_CONTROL_TTC_256 = 0x0000c000, - DMA_CONTROL_TTC_40 = 0x00010000, - DMA_CONTROL_TTC_32 = 0x00014000, - DMA_CONTROL_TTC_24 = 0x00018000, - DMA_CONTROL_TTC_16 = 0x0001c000, -}; -#define DMA_CONTROL_TC_TX_MASK 0xfffe3fff - -#define DMA_CONTROL_EFC 0x00000100 -#define DMA_CONTROL_FEF 0x00000080 -#define DMA_CONTROL_FUF 0x00000040 - -enum rtc_control { - DMA_CONTROL_RTC_64 = 0x00000000, - DMA_CONTROL_RTC_32 = 0x00000008, - DMA_CONTROL_RTC_96 = 0x00000010, - DMA_CONTROL_RTC_128 = 0x00000018, -}; -#define DMA_CONTROL_TC_RX_MASK 0xffffffe7 - -#define DMA_CONTROL_OSF 0x00000004 /* Operate on second frame */ - -/* MMC registers offset */ -#define GMAC_MMC_CTRL 0x100 -#define GMAC_MMC_RX_INTR 0x104 -#define GMAC_MMC_TX_INTR 0x108 -#define GMAC_MMC_RX_CSUM_OFFLOAD 0x208 diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index e79e00b6f147..16d4e1cecf8f 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1583,7 +1583,7 @@ static int stmmac_mac_device_setup(struct net_device *dev) struct mac_device_info *device; if (priv->is_gmac) - device = gmac_setup(ioaddr); + device = dwmac1000_setup(ioaddr); else device = dwmac100_setup(ioaddr); -- cgit v1.2.3 From 5e33c791233b7da47b5403344a915c1b7edaaad8 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:21 +0000 Subject: stmmac: include netdevice.h into the common.h header Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/common.h | 2 +- drivers/net/stmmac/dwmac100.c | 1 - drivers/net/stmmac/dwmac1000.h | 1 - drivers/net/stmmac/stmmac_main.c | 1 - drivers/net/stmmac/stmmac_mdio.c | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 25b53d411516..7267bcd43d06 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -23,7 +23,7 @@ *******************************************************************************/ #include "descs.h" -#include +#include struct stmmac_extra_stats { /* Transmit errors */ diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c index 010c8b206359..82dde774d4c5 100644 --- a/drivers/net/stmmac/dwmac100.c +++ b/drivers/net/stmmac/dwmac100.c @@ -26,7 +26,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#include #include #include #include diff --git a/drivers/net/stmmac/dwmac1000.h b/drivers/net/stmmac/dwmac1000.h index 3d54d6c99129..62dca0e384e7 100644 --- a/drivers/net/stmmac/dwmac1000.h +++ b/drivers/net/stmmac/dwmac1000.h @@ -20,7 +20,6 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#include #include #include "common.h" diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index 16d4e1cecf8f..a6733612d64a 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/stmmac/stmmac_mdio.c b/drivers/net/stmmac/stmmac_mdio.c index 131e0a603711..fffe1d037fe6 100644 --- a/drivers/net/stmmac/stmmac_mdio.c +++ b/drivers/net/stmmac/stmmac_mdio.c @@ -24,7 +24,6 @@ Maintainer: Giuseppe Cavallaro *******************************************************************************/ -#include #include #include -- cgit v1.2.3 From 7187c1ad1a2a005fa24aa14fa5b0e4c8322c0cd2 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:22 +0000 Subject: stmmac: improve Kconfig help Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/stmmac/Kconfig b/drivers/net/stmmac/Kconfig index 35eaa5251d7f..fb287649a305 100644 --- a/drivers/net/stmmac/Kconfig +++ b/drivers/net/stmmac/Kconfig @@ -4,8 +4,9 @@ config STMMAC_ETH select PHYLIB depends on NETDEVICES && CPU_SUBTYPE_ST40 help - This is the driver for the ST MAC 10/100/1000 on-chip Ethernet - controllers. ST Ethernet IPs are built around a Synopsys IP Core. + This is the driver for the Ethernet IPs are built around a + Synopsys IP Core and fully tested on the STMicroelectronics + platforms. if STMMAC_ETH @@ -32,7 +33,8 @@ config STMMAC_TIMER default n help Use an external timer for mitigating the number of network - interrupts. + interrupts. Currently, for SH architectures, it is possible + to use the TMU channel 2 and the SH-RTC device. choice prompt "Select Timer device" -- cgit v1.2.3 From 108316c1bd0a75ba855ce4a6540c530e1562bfb0 Mon Sep 17 00:00:00 2001 From: Giuseppe CAVALLARO Date: Wed, 6 Jan 2010 23:07:23 +0000 Subject: stmmac: update the driver's module version Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/stmmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/stmmac/stmmac.h b/drivers/net/stmmac/stmmac.h index 44421d9667a8..ba35e6943cf4 100644 --- a/drivers/net/stmmac/stmmac.h +++ b/drivers/net/stmmac/stmmac.h @@ -20,7 +20,7 @@ Author: Giuseppe Cavallaro *******************************************************************************/ -#define DRV_MODULE_VERSION "Oct_09" +#define DRV_MODULE_VERSION "Jan_2010" #include #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -- cgit v1.2.3 From a3aa18842a5303fc28fcc4d57dbd16618bd830a0 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 7 Jan 2010 11:58:11 +0000 Subject: drivers/net/: use DEFINE_PCI_DEVICE_TABLE() Use DEFINE_PCI_DEVICE_TABLE() so we get place PCI ids table into correct section in every case. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/3c59x.c | 2 +- drivers/net/8139cp.c | 2 +- drivers/net/8139too.c | 2 +- drivers/net/acenic.c | 2 +- drivers/net/amd8111e.c | 2 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/atl1c/atl1c_main.c | 2 +- drivers/net/atl1e/atl1e_main.c | 2 +- drivers/net/atlx/atl1.c | 2 +- drivers/net/atlx/atl2.c | 2 +- drivers/net/b44.c | 2 +- drivers/net/bnx2x_main.c | 2 +- drivers/net/can/sja1000/ems_pci.c | 2 +- drivers/net/can/sja1000/kvaser_pci.c | 2 +- drivers/net/cassini.c | 2 +- drivers/net/chelsio/common.h | 2 +- drivers/net/chelsio/subr.c | 2 +- drivers/net/cxgb3/cxgb3_main.c | 2 +- drivers/net/defxx.c | 2 +- drivers/net/dl2k.h | 2 +- drivers/net/e100.c | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/e1000e/netdev.c | 2 +- drivers/net/enic/enic_main.c | 2 +- drivers/net/epic100.c | 2 +- drivers/net/fealnx.c | 2 +- drivers/net/forcedeth.c | 2 +- drivers/net/hamachi.c | 2 +- drivers/net/hp100.c | 2 +- drivers/net/igb/igb_main.c | 2 +- drivers/net/igbvf/netdev.c | 2 +- drivers/net/ioc3-eth.c | 2 +- drivers/net/ipg.c | 2 +- drivers/net/irda/donauboe.c | 2 +- drivers/net/irda/via-ircc.c | 2 +- drivers/net/irda/vlsi_ir.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/jme.c | 2 +- drivers/net/mlx4/main.c | 2 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/natsemi.c | 2 +- drivers/net/ne2k-pci.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 2 +- drivers/net/niu.c | 2 +- drivers/net/ns83820.c | 2 +- drivers/net/pasemi_mac.c | 2 +- drivers/net/pci-skeleton.c | 2 +- drivers/net/pcnet32.c | 2 +- drivers/net/qla3xxx.c | 2 +- drivers/net/qlge/qlge_main.c | 2 +- drivers/net/r6040.c | 2 +- drivers/net/r8169.c | 2 +- drivers/net/rrunner.c | 2 +- drivers/net/s2io.c | 2 +- drivers/net/sc92031.c | 2 +- drivers/net/sfc/efx.c | 2 +- drivers/net/sis190.c | 2 +- drivers/net/sis900.c | 2 +- drivers/net/skfp/skfddi.c | 2 +- drivers/net/skge.c | 2 +- drivers/net/smsc9420.c | 2 +- drivers/net/spider_net.c | 2 +- drivers/net/starfire.c | 2 +- drivers/net/sundance.c | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.c | 2 +- drivers/net/tc35815.c | 2 +- drivers/net/tehuti.c | 2 +- drivers/net/tg3.c | 2 +- drivers/net/tlan.c | 2 +- drivers/net/tokenring/3c359.c | 2 +- drivers/net/tokenring/abyss.c | 2 +- drivers/net/tokenring/lanstreamer.c | 2 +- drivers/net/tokenring/olympic.c | 2 +- drivers/net/tokenring/tmspci.c | 2 +- drivers/net/tulip/de2104x.c | 2 +- drivers/net/tulip/dmfe.c | 2 +- drivers/net/tulip/tulip_core.c | 2 +- drivers/net/tulip/uli526x.c | 2 +- drivers/net/tulip/winbond-840.c | 2 +- drivers/net/tulip/xircom_cb.c | 2 +- drivers/net/typhoon.c | 2 +- drivers/net/via-rhine.c | 2 +- drivers/net/via-velocity.c | 2 +- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- drivers/net/vxge/vxge-main.c | 2 +- drivers/net/wan/dscc4.c | 2 +- drivers/net/wan/farsync.c | 2 +- drivers/net/wan/lmc/lmc_main.c | 2 +- drivers/net/wan/pc300_drv.c | 2 +- drivers/net/wan/pc300too.c | 2 +- drivers/net/wan/pci200syn.c | 2 +- drivers/net/wan/wanxl.c | 2 +- drivers/net/wireless/adm8211.c | 2 +- drivers/net/wireless/airo.c | 2 +- drivers/net/wireless/ath/ath5k/base.c | 2 +- drivers/net/wireless/ath/ath9k/pci.c | 2 +- drivers/net/wireless/atmel_pci.c | 2 +- drivers/net/wireless/hostap/hostap_pci.c | 2 +- drivers/net/wireless/hostap/hostap_plx.c | 2 +- drivers/net/wireless/ipw2x00/ipw2100.c | 2 +- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/orinoco/orinoco_nortel.c | 2 +- drivers/net/wireless/orinoco/orinoco_pci.c | 2 +- drivers/net/wireless/orinoco/orinoco_plx.c | 2 +- drivers/net/wireless/orinoco/orinoco_tmd.c | 2 +- drivers/net/wireless/p54/p54pci.c | 2 +- drivers/net/wireless/prism54/islpci_hotplug.c | 2 +- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rtl818x/rtl8180_dev.c | 2 +- drivers/net/yellowfin.c | 2 +- 118 files changed, 118 insertions(+), 118 deletions(-) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 39db0e96815d..5df46c230b07 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -375,7 +375,7 @@ static struct vortex_chip_info { }; -static struct pci_device_id vortex_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(vortex_pci_tbl) = { { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C590 }, { 0x10B7, 0x5920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C592 }, { 0x10B7, 0x5970, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C597 }, diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 3f452bcbfb9e..9d59654748b1 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -394,7 +394,7 @@ static int cp_get_eeprom(struct net_device *dev, static int cp_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data); -static struct pci_device_id cp_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(cp_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139), }, { PCI_DEVICE(PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322), }, { }, diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 907f2d583db8..321e73aabb2b 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -231,7 +231,7 @@ static const struct { }; -static const struct pci_device_id rtl8139_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(rtl8139_pci_tbl) = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index d82a9a994753..ec624ab03e88 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -134,7 +134,7 @@ #define PCI_DEVICE_ID_SGI_ACENIC 0x0009 #endif -static struct pci_device_id acenic_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(acenic_pci_tbl) = { { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, }, { PCI_VENDOR_ID_ALTEON, PCI_DEVICE_ID_ALTEON_ACENIC_COPPER, diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 766aabfdfc75..545c791f477e 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -113,7 +113,7 @@ MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0 module_param_array(dynamic_ipg, bool, NULL, 0); MODULE_PARM_DESC(dynamic_ipg, "Enable or Disable dynamic IPG, 1: Enable, 0: Disable"); -static struct pci_device_id amd8111e_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(amd8111e_pci_tbl) = { { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD8111E_7462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index dbf4de39754d..b68e1eb405ff 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -144,7 +144,7 @@ static void __devexit com20020pci_remove(struct pci_dev *pdev) free_netdev(dev); } -static struct pci_device_id com20020pci_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = { { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 77cde859620c..d98095df05be 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -35,7 +35,7 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION; * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id atl1c_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, /* required last entry */ diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 2080d444068b..d59f8e89c65d 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -35,7 +35,7 @@ char atl1e_driver_version[] = DRV_VERSION; * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id atl1e_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)}, /* required last entry */ diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index b6cf3263127c..9ba547069db3 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -232,7 +232,7 @@ static void __devinit atl1_check_options(struct atl1_adapter *adapter) /* * atl1_pci_tbl - PCI Device ID Table */ -static const struct pci_device_id atl1_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(atl1_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1)}, /* required last entry */ {0,} diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index c0451d75cdcf..255e4e7ea0ee 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -63,7 +63,7 @@ MODULE_VERSION(ATL2_DRV_VERSION); /* * atl2_pci_tbl - PCI Device ID Table */ -static struct pci_device_id atl2_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2)}, /* required last entry */ {0,} diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 4869adb69586..44b66be38134 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -102,7 +102,7 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value"); #ifdef CONFIG_B44_PCI -static const struct pci_device_id b44_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(b44_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1) }, diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 77ba13520d87..0bfdf30ea4d1 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -140,7 +140,7 @@ static struct { }; -static const struct pci_device_id bnx2x_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = { { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 }, { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E }, diff --git a/drivers/net/can/sja1000/ems_pci.c b/drivers/net/can/sja1000/ems_pci.c index fd04789d3370..87300606abb9 100644 --- a/drivers/net/can/sja1000/ems_pci.c +++ b/drivers/net/can/sja1000/ems_pci.c @@ -102,7 +102,7 @@ struct ems_pci_card { #define EMS_PCI_BASE_SIZE 4096 /* size of controller area */ -static struct pci_device_id ems_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ems_pci_tbl) = { /* CPC-PCI v1 */ {PCI_VENDOR_ID_SIEMENS, 0x2104, PCI_ANY_ID, PCI_ANY_ID,}, /* CPC-PCI v2 */ diff --git a/drivers/net/can/sja1000/kvaser_pci.c b/drivers/net/can/sja1000/kvaser_pci.c index 7dd7769b9713..441e776a7f59 100644 --- a/drivers/net/can/sja1000/kvaser_pci.c +++ b/drivers/net/can/sja1000/kvaser_pci.c @@ -109,7 +109,7 @@ struct kvaser_pci { #define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */ #define KVASER_PCI_DEVICE_ID2 0x0008 -static struct pci_device_id kvaser_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(kvaser_pci_tbl) = { {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,}, {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,}, { 0,} diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index f857afe8e488..b3a038c23af1 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -236,7 +236,7 @@ static u16 link_modes[] __devinitdata = { CAS_BMCR_SPEED1000|BMCR_FULLDPLX /* 5 : 1000bt full duplex */ }; -static struct pci_device_id cas_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(cas_pci_tbl) = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_CASSINI, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SATURN, diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 699d22c5fe09..f6462b54f823 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -334,7 +334,7 @@ static inline int t1_is_asic(const adapter_t *adapter) return adapter->params.is_asic; } -extern struct pci_device_id t1_pci_tbl[]; +extern const struct pci_device_id t1_pci_tbl[]; static inline int adapter_matches_type(const adapter_t *adapter, int version, int revision) diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 17720c6e5bfe..2402d372c886 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -528,7 +528,7 @@ static const struct board_info t1_board[] = { }; -struct pci_device_id t1_pci_tbl[] = { +DEFINE_PCI_DEVICE_TABLE(t1_pci_tbl) = { CH_DEVICE(8, 0, CH_BRD_T110_1CU), CH_DEVICE(8, 1, CH_BRD_T110_1CU), CH_DEVICE(7, 0, CH_BRD_N110_1F), diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 89bec9c3c141..73622f5312cb 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -80,7 +80,7 @@ enum { #define CH_DEVICE(devid, idx) \ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, PCI_ANY_ID, 0, 0, idx } -static const struct pci_device_id cxgb3_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(cxgb3_pci_tbl) = { CH_DEVICE(0x20, 0), /* PE9000 */ CH_DEVICE(0x21, 1), /* T302E */ CH_DEVICE(0x22, 2), /* T310E */ diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index e4eac4bcdf83..98da085445e6 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -3628,7 +3628,7 @@ static int __devinit dfx_pci_register(struct pci_dev *, const struct pci_device_id *); static void __devexit dfx_pci_unregister(struct pci_dev *); -static struct pci_device_id dfx_pci_table[] = { +static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = { { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) }, { } }; diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h index 266ec8777ca8..7caab3d26a9e 100644 --- a/drivers/net/dl2k.h +++ b/drivers/net/dl2k.h @@ -537,7 +537,7 @@ struct netdev_private { driver_data Data private to the driver. */ -static const struct pci_device_id rio_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(rio_pci_tbl) = { {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, { } diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 839fb2b136d3..5c7a155e849a 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -208,7 +208,7 @@ MODULE_PARM_DESC(use_io, "Force use of i/o access mode"); #define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } -static struct pci_device_id e100_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(e100_id_table) = { INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7e855f9bbd97..9ec7480be1d8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -42,7 +42,7 @@ static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation * Macro expands to... * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} */ -static struct pci_device_id e1000_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { INTEL_E1000_ETHERNET_DEVICE(0x1000), INTEL_E1000_ETHERNET_DEVICE(0x1001), INTEL_E1000_ETHERNET_DEVICE(0x1004), diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 762b697ce731..9ccb9010dc5b 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5325,7 +5325,7 @@ static struct pci_error_handlers e1000_err_handler = { .resume = e1000_io_resume, }; -static struct pci_device_id e1000_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 }, diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index d87935ad1130..c81bc4b1816f 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -51,7 +51,7 @@ #define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ /* Supported devices */ -static struct pci_device_id enic_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = { { PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) }, { 0, } /* end of table */ }; diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 41494f7b2ec8..1f8b11449fad 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -167,7 +167,7 @@ static const struct epic_chip_info pci_id_tbl[] = { }; -static struct pci_device_id epic_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(epic_pci_tbl) = { { 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 }, { 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 }, { 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID, diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index dac4e595589e..e6a98129d787 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1941,7 +1941,7 @@ static int netdev_close(struct net_device *dev) return 0; } -static struct pci_device_id fealnx_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(fealnx_pci_tbl) = { {0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, {0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 3c340489804a..3eb713b014f9 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -6198,7 +6198,7 @@ static void nv_shutdown(struct pci_dev *pdev) #define nv_resume NULL #endif /* CONFIG_PM */ -static struct pci_device_id pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(pci_tbl) = { { /* nForce Ethernet Controller */ PCI_DEVICE(0x10DE, 0x01C3), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER, diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index ea85075a89a2..dd72c5025e6a 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1990,7 +1990,7 @@ static void __devexit hamachi_remove_one (struct pci_dev *pdev) } } -static struct pci_device_id hamachi_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(hamachi_pci_tbl) = { { 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 90f890e7c5e1..0c2f2e8b1c47 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -210,7 +210,7 @@ MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); #endif #ifdef CONFIG_PCI -static struct pci_device_id hp100_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(hp100_pci_tbl) = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2970A, PCI_ANY_ID, PCI_ANY_ID,}, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 78963a0e128d..484fbc83739f 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -60,7 +60,7 @@ static const struct e1000_info *igb_info_tbl[] = { [board_82575] = &e1000_82575_info, }; -static struct pci_device_id igb_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 }, diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 1326232c1d32..ca0d1906e83e 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2876,7 +2876,7 @@ static struct pci_error_handlers igbvf_err_handler = { .resume = igbvf_io_resume, }; -static struct pci_device_id igbvf_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(igbvf_pci_tbl) = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf }, { } /* terminate list */ }; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 8ec15ab8c8c2..81a4c5d30733 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1383,7 +1383,7 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev) */ } -static struct pci_device_id ioc3_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ioc3_pci_tbl) = { { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID }, { 0 } }; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index ba8d246d05a0..49f35e2ed19f 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -92,7 +92,7 @@ static const char *ipg_brand_name[] = { "D-Link NIC IP1000A" }; -static struct pci_device_id ipg_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = { { PCI_VDEVICE(SUNDANCE, 0x1023), 0 }, { PCI_VDEVICE(SUNDANCE, 0x2021), 1 }, { PCI_VDEVICE(SUNDANCE, 0x1021), 2 }, diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 2d7b5c1d5572..b7e6625ca75e 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c @@ -184,7 +184,7 @@ #define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC #define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX -static struct pci_device_id toshoboe_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(toshoboe_pci_tbl) = { { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index fddb4efd5453..6533c010cf5c 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -121,7 +121,7 @@ static void iodelay(int udelay) } } -static struct pci_device_id via_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(via_pci_tbl) = { { PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, { PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, { PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index bd3c6b5ee76a..209d4bcfaced 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c @@ -59,7 +59,7 @@ MODULE_LICENSE("GPL"); static /* const */ char drivername[] = DRIVER_NAME; -static struct pci_device_id vlsi_irda_table [] = { +static DEFINE_PCI_DEVICE_TABLE(vlsi_irda_table) = { { .class = PCI_CLASS_WIRELESS_IRDA << 8, .class_mask = PCI_CLASS_SUBCLASS_MASK << 8, diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index bcd0f01d5feb..6c2d9366fe5e 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -50,7 +50,7 @@ MODULE_PARM_DESC(copybreak, * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id ixgb_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ixgb_pci_tbl) = { {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index bd64387563f0..b2f11d45e225 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -67,7 +67,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, * Class, Class Mask, private data (not used) } */ -static struct pci_device_id ixgbe_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 792b88fc3574..26eed49d3208 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2994,7 +2994,7 @@ jme_resume(struct pci_dev *pdev) } #endif -static struct pci_device_id jme_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, { } diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 291a505fd4fc..58f7f979cd2b 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -1271,7 +1271,7 @@ int mlx4_restart_one(struct pci_dev *pdev) return __mlx4_init_one(pdev, NULL); } -static struct pci_device_id mlx4_pci_table[] = { +static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = { { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 3fcb1c356e0d..c0884a9cba3c 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -4085,7 +4085,7 @@ static void myri10ge_remove(struct pci_dev *pdev) #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 #define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9 0x0009 -static struct pci_device_id myri10ge_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(myri10ge_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, {PCI_DEVICE (PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E_9)}, diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 797fe164ce27..2d7b3bbfed01 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -247,7 +247,7 @@ static struct { { "NatSemi DP8381[56]", 0, 24 }, }; -static struct pci_device_id natsemi_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(natsemi_pci_tbl) = { { PCI_VENDOR_ID_NS, 0x0020, 0x12d9, 0x000c, 0, 0, 0 }, { PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { } /* terminate list */ diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 3fcebb70151c..85aec4f10131 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -136,7 +136,7 @@ static struct { }; -static struct pci_device_id ne2k_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = { { 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 }, { 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 }, { 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 }, diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f13a07f717c7..3fdfc9b7c5b2 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -100,7 +100,7 @@ static void netxen_config_indev_addr(struct net_device *dev, unsigned long); {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} -static struct pci_device_id netxen_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(netxen_pci_tbl) = { ENTRY(PCI_DEVICE_ID_NX2031_10GXSR), ENTRY(PCI_DEVICE_ID_NX2031_10GCX4), ENTRY(PCI_DEVICE_ID_NX2031_4GCU), diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 8ce58c4c7dd3..920f0ecf7a0a 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -58,7 +58,7 @@ static void writeq(u64 val, void __iomem *reg) } #endif -static struct pci_device_id niu_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(niu_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_SUN, 0xabcd)}, {} }; diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 1f6327d41536..a3b6aa0f375d 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -2292,7 +2292,7 @@ static void __devexit ns83820_remove_one(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); } -static struct pci_device_id ns83820_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(ns83820_pci_tbl) = { { 0x100b, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, .driver_data = 0, }, { 0, }, }; diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 1673eb045e1e..d44d4a208bbf 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -1875,7 +1875,7 @@ static void __devexit pasemi_mac_remove(struct pci_dev *pdev) free_netdev(netdev); } -static struct pci_device_id pasemi_mac_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(pasemi_mac_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) }, { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) }, { }, diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 8ff5536a3757..20273832bfce 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -211,7 +211,7 @@ static struct { }; -static const struct pci_device_id netdrv_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(netdrv_pci_tbl) = { {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, {0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB }, {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX }, diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index dcc67a35e8f2..ed62ac6d9c0e 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -58,7 +58,7 @@ static const char *const version = /* * PCI device identifiers for "new style" Linux PCI Device Drivers */ -static struct pci_device_id pcnet32_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(pcnet32_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), }, diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index dd35066a7f8d..f922294fd349 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -61,7 +61,7 @@ static int msi; module_param(msi, int, 0); MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts."); -static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(ql3xxx_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3032_DEVICE_ID)}, /* required last entry */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 25561fbdb203..167a3dab2f18 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -73,7 +73,7 @@ static int qlge_irq_type = MSIX_IRQ; module_param(qlge_irq_type, int, MSIX_IRQ); MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); -static struct pci_device_id qlge_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, /* required last entry */ diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index f03e2e4a15a8..d68ba7a58631 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -1222,7 +1222,7 @@ static void __devexit r6040_remove_one(struct pci_dev *pdev) } -static struct pci_device_id r6040_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(r6040_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_RDC, 0x6040) }, { 0 } }; diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c403ce0a3d3a..c1bb24cf0793 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -168,7 +168,7 @@ static void rtl_hw_start_8169(struct net_device *); static void rtl_hw_start_8168(struct net_device *); static void rtl_hw_start_8101(struct net_device *); -static struct pci_device_id rtl8169_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c index 20a71749154a..085f4ec896d3 100644 --- a/drivers/net/rrunner.c +++ b/drivers/net/rrunner.c @@ -1688,7 +1688,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } -static struct pci_device_id rr_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(rr_pci_tbl) = { { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index cc4218667cba..ac6189005c79 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -523,7 +523,7 @@ module_param_array(rts_frm_len, uint, NULL, 0); * S2IO device table. * This table lists all the devices that this driver supports. */ -static struct pci_device_id s2io_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(s2io_tbl) = { {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI, diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index e35050322f97..fd8cb506a2bb 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1589,7 +1589,7 @@ out: return 0; } -static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(sc92031_pci_device_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) }, { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) }, { PCI_DEVICE(0x1088, 0x2031) }, diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index f983e3b507cc..3591cc9c39c8 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1940,7 +1940,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) **************************************************************************/ /* PCI device ID table */ -static struct pci_device_id efx_pci_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(efx_pci_table) = { {PCI_DEVICE(EFX_VENDID_SFC, FALCON_A_P_DEVID), .driver_data = (unsigned long) &falcon_a1_nic_type}, {PCI_DEVICE(EFX_VENDID_SFC, FALCON_B_P_DEVID), diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 31233b4c44a0..626de766443a 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -334,7 +334,7 @@ static const struct { { "SiS 191 PCI Gigabit Ethernet adapter" }, }; -static struct pci_device_id sis190_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(sis190_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, { 0, }, diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 7360d4bbf75e..20c5ce474891 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -106,7 +106,7 @@ static const char * card_names[] = { "SiS 900 PCI Fast Ethernet", "SiS 7016 PCI Fast Ethernet" }; -static struct pci_device_id sis900_pci_tbl [] = { +static DEFINE_PCI_DEVICE_TABLE(sis900_pci_tbl) = { {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016, diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 1f9698c0fb64..6b955a4f19b2 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -149,7 +149,7 @@ extern void mac_drv_rx_mode(struct s_smc *smc, int mode); extern void mac_drv_clear_rx_queue(struct s_smc *smc); extern void enable_tx_irq(struct s_smc *smc, u_short queue); -static struct pci_device_id skfddi_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(skfddi_pci_tbl) = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 379a3dc00163..5ff46eb18d0c 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -78,7 +78,7 @@ static int debug = -1; /* defaults above */ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -static const struct pci_device_id skge_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940) }, { PCI_DEVICE(PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 12f0f5d74e3c..1495a5dd4b46 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -80,7 +80,7 @@ struct smsc9420_pdata { int last_carrier; }; -static const struct pci_device_id smsc9420_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(smsc9420_id_table) = { { PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } }; diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 218524857bfc..16191998ac67 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -72,7 +72,7 @@ MODULE_PARM_DESC(tx_descriptors, "number of descriptors used " \ char spider_net_driver_name[] = "spidernet"; -static struct pci_device_id spider_net_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(spider_net_pci_tbl) = { { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SPIDER_NET, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { 0, } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 95db60adde41..c81252d9a57c 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -301,7 +301,7 @@ enum chipset { CH_6915 = 0, }; -static struct pci_device_id starfire_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(starfire_pci_tbl) = { { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 }, { 0, } }; diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index d58e1891ca60..0c972e560cf3 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -206,7 +206,7 @@ IVc. Errata #define USE_IO_OPS 1 #endif -static const struct pci_device_id sundance_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(sundance_pci_tbl) = { { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 }, { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 }, { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 }, diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index b571a1babab9..b55ceb88d93f 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -107,7 +107,7 @@ MODULE_LICENSE("GPL"); #define GEM_MODULE_NAME "gem" #define PFX GEM_MODULE_NAME ": " -static struct pci_device_id gem_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(gem_pci_tbl) = { { PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_GEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 6762f1c6ec8a..76ccd31cbf50 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -3211,7 +3211,7 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) dev_set_drvdata(&pdev->dev, NULL); } -static struct pci_device_id happymeal_pci_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(happymeal_pci_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_HAPPYMEAL) }, { } /* Terminating entry */ }; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 75a669d48e5e..033408f589fb 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -65,7 +65,7 @@ static const struct { { "TOSHIBA TC35815/TX4939" }, }; -static const struct pci_device_id tc35815_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tc35815_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815CF), .driver_data = TC35815CF }, {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_NWU), .driver_data = TC35815_NWU }, {PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939), .driver_data = TC35815_TX4939 }, diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 80b404f2b938..b907bee31fd5 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -64,7 +64,7 @@ #include "tehuti.h" -static struct pci_device_id __devinitdata bdx_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = { {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3a74d2168598..b0630cd093a3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -174,7 +174,7 @@ static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); -static struct pci_device_id tg3_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index fabaeffb3155..613943eb6e75 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -254,7 +254,7 @@ static struct board { { "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */ }; -static struct pci_device_id tlan_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100, diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index cf552d1d9629..b0d7db9d8bb4 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -117,7 +117,7 @@ MODULE_PARM_DESC(message_level, "3c359: Level of reported messages") ; * will be stuck with 1555 lines of hex #'s in the code. */ -static struct pci_device_id xl_pci_tbl[] = +static DEFINE_PCI_DEVICE_TABLE(xl_pci_tbl) = { {PCI_VENDOR_ID_3COM,PCI_DEVICE_ID_3COM_3C359, PCI_ANY_ID, PCI_ANY_ID, }, { } /* terminate list */ diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index b9db1b5a58a3..515f122777ab 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c @@ -45,7 +45,7 @@ static char version[] __devinitdata = #define ABYSS_IO_EXTENT 64 -static struct pci_device_id abyss_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(abyss_pci_tbl) = { { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, }, { } /* Terminating entry */ diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index d6ccd59c7d07..3f9d5a25562e 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -146,7 +146,7 @@ static char version[] = "LanStreamer.c v0.4.0 03/08/01 - Mike Sullivan\n" " v0.5.3 11/13/02 - Kent Yoder"; -static struct pci_device_id streamer_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(streamer_pci_tbl) = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR, PCI_ANY_ID, PCI_ANY_ID,}, {} /* terminating entry */ }; diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index df32025c5132..f010a4dc5f19 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -172,7 +172,7 @@ module_param_array(message_level, int, NULL, 0) ; static int network_monitor[OLYMPIC_MAX_ADAPTERS] = {0,}; module_param_array(network_monitor, int, NULL, 0); -static struct pci_device_id olympic_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(olympic_pci_tbl) = { {PCI_VENDOR_ID_IBM,PCI_DEVICE_ID_IBM_TR_WAKE,PCI_ANY_ID,PCI_ANY_ID,}, { } /* Terminating Entry */ }; diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c index f92fe86fdcae..d4c7c0c0a3d6 100644 --- a/drivers/net/tokenring/tmspci.c +++ b/drivers/net/tokenring/tmspci.c @@ -57,7 +57,7 @@ static struct card_info card_info_table[] = { { {0x03, 0x01}, "3Com Token Link Velocity"}, }; -static struct pci_device_id tmspci_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tmspci_pci_tbl) = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index d4255d44cb75..87ea39e2037d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -337,7 +337,7 @@ static void de21041_media_timer (unsigned long data); static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media); -static struct pci_device_id de_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(de_pci_tbl) = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index ad63621913c3..8153fdd0af91 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -2068,7 +2068,7 @@ static void dmfe_HPNA_remote_cmd_chk(struct dmfe_board_info * db) -static struct pci_device_id dmfe_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(dmfe_pci_tbl) = { { 0x1282, 0x9132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9132_ID }, { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9102_ID }, { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_DM9100_ID }, diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 0fa3140d65bf..64aa2d6af08b 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -207,7 +207,7 @@ struct tulip_chip_table tulip_tbl[] = { }; -static struct pci_device_id tulip_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(tulip_pci_tbl) = { { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21143 }, { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 }, diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index fa019cabc355..d549042a01df 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -1783,7 +1783,7 @@ static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id) } -static struct pci_device_id uli526x_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(uli526x_pci_tbl) = { { 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID }, { 0x10B9, 0x5263, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5263_ID }, { 0, } diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 869a7a0005f9..23395e1ff238 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -218,7 +218,7 @@ enum chip_capability_flags { CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8, }; -static const struct pci_device_id w840_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(w840_pci_tbl) = { { 0x1050, 0x0840, PCI_ANY_ID, 0x8153, 0, 0, 0 }, { 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 9924c4c7e2d6..c84123fd635c 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -144,7 +144,7 @@ static int link_status(struct xircom_private *card); -static struct pci_device_id xircom_pci_table[] = { +static DEFINE_PCI_DEVICE_TABLE(xircom_pci_table) = { {0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID,}, {0,}, }; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 39f1fc650be6..6e4f754c4baf 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -215,7 +215,7 @@ static struct typhoon_card_info typhoon_card_info[] __devinitdata = { * bit 8 indicates if this is a (0) copper or (1) fiber card * bits 12-16 indicate card type: (0) client and (1) server */ -static struct pci_device_id typhoon_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(typhoon_pci_tbl) = { { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990, PCI_ANY_ID, PCI_ANY_ID, 0, 0,TYPHOON_TX }, { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3CR990_TX_95, diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 593e01f64e9b..6bc924cd4583 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -266,7 +266,7 @@ enum rhine_quirks { /* Beware of PCI posted writes */ #define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0) -static const struct pci_device_id rhine_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(rhine_pci_tbl) = { { 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */ { 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */ { 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */ diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index cee8fa2d2a9f..83fc3a8dd254 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -361,7 +361,7 @@ static struct velocity_info_tbl chip_info_table[] = { * Describe the PCI device identifiers that we support in this * device driver. Used for hotplug autoloading. */ -static const struct pci_device_id velocity_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(velocity_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) }, { } }; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 9cc438282d77..b896f9386110 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -35,7 +35,7 @@ char vmxnet3_driver_name[] = "vmxnet3"; * PCI Device ID Table * Last entry must be all 0s */ -static const struct pci_device_id vmxnet3_pciid_table[] = { +static DEFINE_PCI_DEVICE_TABLE(vmxnet3_pciid_table) = { {PCI_VDEVICE(VMWARE, PCI_DEVICE_ID_VMWARE_VMXNET3)}, {0} }; diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 5f0e7ea0d493..6466bc840e6d 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -54,7 +54,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Neterion's X3100 Series 10GbE PCIe I/O" "Virtualized Server Adapter"); -static struct pci_device_id vxge_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(vxge_id_table) = { {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_WIN, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_TITAN_UNI, PCI_ANY_ID, diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 3f759daf3ca4..f88c07c13197 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -2050,7 +2050,7 @@ static int __init dscc4_setup(char *str) __setup("dscc4.setup=", dscc4_setup); #endif -static struct pci_device_id dscc4_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(dscc4_pci_tbl) = { { PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_DSCC4, PCI_ANY_ID, PCI_ANY_ID, }, { 0,} diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 9bc2e3649157..40d724a8e020 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -528,7 +528,7 @@ static int fst_debug_mask = { FST_DEBUG }; /* * PCI ID lookup table */ -static struct pci_device_id fst_pci_dev_id[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(fst_pci_dev_id) = { {PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, FST_TYPE_T2P}, diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 4b6f27e7c820..b27850377121 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -77,7 +77,7 @@ static int LMC_PKT_BUF_SZ = 1542; -static struct pci_device_id lmc_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(lmc_pci_tbl) = { { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, PCI_VENDOR_ID_LMC, PCI_ANY_ID }, { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST, diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index aec4d3955420..f4f1c00d0d23 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -251,7 +251,7 @@ static char rcsid[] = #undef PC300_DEBUG_RX #undef PC300_DEBUG_OTHER -static struct pci_device_id cpc_pci_dev_id[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(cpc_pci_dev_id) = { /* PC300/RSV or PC300/X21, 2 chan */ {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300}, /* PC300/RSV or PC300/X21, 1 chan */ diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c index 60ece54bdd94..c7ab3becd261 100644 --- a/drivers/net/wan/pc300too.c +++ b/drivers/net/wan/pc300too.c @@ -481,7 +481,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev, -static struct pci_device_id pc300_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(pc300_pci_tbl) = { { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_PC300_RX_2, PCI_ANY_ID, diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c index f1340faaf022..e2cff64a446a 100644 --- a/drivers/net/wan/pci200syn.c +++ b/drivers/net/wan/pci200syn.c @@ -417,7 +417,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev, -static struct pci_device_id pci200_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(pci200_pci_tbl) = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 }, { 0, } diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index daee8a0624ee..541c700dceef 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -814,7 +814,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, return 0; } -static struct pci_device_id wanxl_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(wanxl_pci_tbl) = { { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID, diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index e1f04bb437e3..e6ca3eb4c0d3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -39,7 +39,7 @@ static unsigned int rx_ring_size __read_mostly = 16; module_param(tx_ring_size, uint, 0); module_param(rx_ring_size, uint, 0); -static struct pci_device_id adm8211_pci_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(adm8211_pci_id_table) = { /* ADMtek ADM8211 */ { PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */ { PCI_DEVICE(0x1200, 0x8201) }, /* ? */ diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4331d675fcc6..37e4ab737f2a 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -57,7 +57,7 @@ #define DRV_NAME "airo" #ifdef CONFIG_PCI -static struct pci_device_id card_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(card_ids) = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID }, { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, }, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index fdfaf0f618f1..72e5ed51c0af 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -83,7 +83,7 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); /* Known PCI ids */ -static const struct pci_device_id ath5k_pci_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index f7af5ea54753..ee617205cb4a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -18,7 +18,7 @@ #include #include "ath9k.h" -static struct pci_device_id ath_pci_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 92f87fbe750f..9ab1192004c0 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c @@ -31,7 +31,7 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.") MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards"); -static struct pci_device_id card_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(card_ids) = { { 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID }, { 0, } }; diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index 8fdd41f4b4f2..4d97ae37499b 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -39,7 +39,7 @@ struct hostap_pci_priv { /* FIX: do we need mb/wmb/rmb with memory operations? */ -static struct pci_device_id prism2_pci_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(prism2_pci_id_table) = { /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */ { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID }, /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */ diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 0e5d51086a44..fc04ccdc5bef 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -60,7 +60,7 @@ struct hostap_plx_priv { #define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID } -static struct pci_device_id prism2_plx_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(prism2_plx_id_table) = { PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"), PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"), PLXDEV(0x126c, 0x8030, "Nortel emobility"), diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 56afcf041f81..9b72c45a7748 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -6585,7 +6585,7 @@ static void ipw2100_shutdown(struct pci_dev *pci_dev) #define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } -static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(ipw2100_pci_id_table) = { IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */ IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */ IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */ diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 09ddd3e6bedc..63c2a7ade5fb 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -11524,7 +11524,7 @@ out: } /* PCI driver stuff */ -static struct pci_device_id card_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(card_ids) = { {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0}, {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0}, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 28ffe4c826d8..6cde661ce0bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2849,7 +2849,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .broken_powersave = true, }; -struct pci_device_id iwl3945_hw_card_ids[] = { +DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3ec2fe370b58..bc532ff4f883 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -37,7 +37,7 @@ #include /* Hardware specific file defines the PCI IDs table for that hardware module */ -extern struct pci_device_id iwl3945_hw_card_ids[]; +extern const struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-csr.h" #include "iwl-prph.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 771b03c1c7c5..c8fec626b714 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3766,7 +3766,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) *****************************************************************************/ /* Hardware specific file defines the PCI IDs table for that hardware module */ -static struct pci_device_id iwl_hw_card_ids[] = { +static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { #ifdef CONFIG_IWL4965 {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index c13a4c383410..075f446b3139 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -274,7 +274,7 @@ static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static struct pci_device_id orinoco_nortel_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(orinoco_nortel_id_table) = { /* Nortel emobility PCI */ {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, /* Symbol LA-4123 PCI */ diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index fea7781948e7..bda5317cc596 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -212,7 +212,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static struct pci_device_id orinoco_pci_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(orinoco_pci_id_table) = { /* Intersil Prism 3 */ {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, /* Intersil Prism 2.5 */ diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index 3f2942a1e4f5..e0d5874ab42f 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -310,7 +310,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static struct pci_device_id orinoco_plx_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(orinoco_plx_id_table) = { {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index d3452548cc71..88cbc7902aa0 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -203,7 +203,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static struct pci_device_id orinoco_tmd_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE(orinoco_tmd_id_table) = { {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ {0,}, }; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a15962a19b2a..fab41f507bd3 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -31,7 +31,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("prism54pci"); MODULE_FIRMWARE("isl3886pci"); -static struct pci_device_id p54p_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(p54p_table) = { /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ { PCI_DEVICE(0x1260, 0x3890) }, /* 3COM 3CRWE154G72 Wireless LAN adapter */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index e4f2bb7368f2..dc14420a9adc 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -39,7 +39,7 @@ module_param(init_pcitm, int, 0); * driver_data * If you have an update for this please contact prism54-devel@prism54.org * The latest list can be found at http://prism54.org/supported_cards.php */ -static const struct pci_device_id prism54_id_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(prism54_id_tbl) = { /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ { 0x1260, 0x3890, diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d86d233c6810..aa579eb8723f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1642,7 +1642,7 @@ static const struct rt2x00_ops rt2400pci_ops = { /* * RT2400pci module information. */ -static struct pci_device_id rt2400pci_device_table[] = { +static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, { 0, } }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 46cbc6ef66ab..77ee1df7933f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1940,7 +1940,7 @@ static const struct rt2x00_ops rt2500pci_ops = { /* * RT2500pci module information. */ -static struct pci_device_id rt2500pci_device_table[] = { +static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, { 0, } }; diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b93eabb4fbe1..99095e1ee13b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1208,7 +1208,7 @@ static const struct rt2x00_ops rt2800pci_ops = { /* * RT2800pci module information. */ -static struct pci_device_id rt2800pci_device_table[] = { +static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c353b497a65d..1f97a797bc41 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2807,7 +2807,7 @@ static const struct rt2x00_ops rt61pci_ops = { /* * RT61pci module information. */ -static struct pci_device_id rt61pci_device_table[] = { +static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = { /* RT2561s */ { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, /* RT2561 v2 */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 5a2b7199f5d5..b9192bfcc557 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -33,7 +33,7 @@ MODULE_AUTHOR("Andrea Merello "); MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver"); MODULE_LICENSE("GPL"); -static struct pci_device_id rtl8180_table[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(rtl8180_table) = { /* rtl8185 */ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 0f773a9a3ff2..8b231b30fd12 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -237,7 +237,7 @@ static const struct pci_id_info pci_id_tbl[] = { { } }; -static const struct pci_device_id yellowfin_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(yellowfin_pci_tbl) = { { 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { } -- cgit v1.2.3 From 368c0ca2f0a69b0818fbc1796d8e21ff02a61b4c Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Fri, 8 Jan 2010 00:07:27 -0800 Subject: be2net: implements ethtool function to read eeprom data. The patch implements a firmware command to fetch the eeprom data. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 30 ++++++++++++++++++++++++++++ drivers/net/benet/be_cmds.h | 16 +++++++++++++++ drivers/net/benet/be_ethtool.c | 45 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 1b68bd98dc0c..b748c197408f 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1571,3 +1571,33 @@ err: spin_unlock_bh(&adapter->mcc_lock); return status; } + +extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_seeprom_read *req; + struct be_sge *sge; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + req = nonemb_cmd->va; + sge = nonembedded_sgl(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, + OPCODE_COMMON_SEEPROM_READ); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SEEPROM_READ, sizeof(*req)); + + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + status = be_mcc_notify_wait(adapter); + + spin_unlock_bh(&adapter->mcc_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 92b87ef156ed..6eed512bb6d4 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -124,6 +124,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_EQ_CREATE 13 #define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_SEEPROM_READ 30 #define OPCODE_COMMON_NTWK_RX_FILTER 34 #define OPCODE_COMMON_GET_FW_VERSION 35 #define OPCODE_COMMON_SET_FLOW_CONTROL 36 @@ -840,6 +841,19 @@ struct be_cmd_resp_ddrdma_test { u8 rcv_buff[4096]; }; +/*********************** SEEPROM Read ***********************/ + +#define BE_READ_SEEPROM_LEN 1024 +struct be_cmd_req_seeprom_read { + struct be_cmd_req_hdr hdr; + u8 rsvd0[BE_READ_SEEPROM_LEN]; +}; + +struct be_cmd_resp_seeprom_read { + struct be_cmd_req_hdr hdr; + u8 seeprom_data[BE_READ_SEEPROM_LEN]; +}; + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_cmd_POST(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, @@ -912,3 +926,5 @@ extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, u32 num_pkts, u64 pattern); extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, u32 byte_cnt, struct be_dma_mem *cmd); +extern int be_cmd_get_seeprom_data(struct be_adapter *adapter, + struct be_dma_mem *nonemb_cmd); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 298b92cbd689..c5afc0286d4d 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -536,12 +536,57 @@ be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) return be_load_fw(adapter, file_name); } +static int +be_get_eeprom_len(struct net_device *netdev) +{ + return BE_READ_SEEPROM_LEN; +} + +static int +be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, + uint8_t *data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_dma_mem eeprom_cmd; + struct be_cmd_resp_seeprom_read *resp; + int status; + + if (!eeprom->len) + return -EINVAL; + + eeprom->magic = BE_VENDOR_ID | (adapter->pdev->device<<16); + + memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem)); + eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read); + eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size, + &eeprom_cmd.dma); + + if (!eeprom_cmd.va) { + dev_err(&adapter->pdev->dev, + "Memory allocation failure. Could not read eeprom\n"); + return -ENOMEM; + } + + status = be_cmd_get_seeprom_data(adapter, &eeprom_cmd); + + if (!status) { + resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va; + memcpy(data, resp->seeprom_data, eeprom->len); + } + pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va, + eeprom_cmd.dma); + + return status; +} + const struct ethtool_ops be_ethtool_ops = { .get_settings = be_get_settings, .get_drvinfo = be_get_drvinfo, .get_wol = be_get_wol, .set_wol = be_set_wol, .get_link = ethtool_op_get_link, + .get_eeprom_len = be_get_eeprom_len, + .get_eeprom = be_read_eeprom, .get_coalesce = be_get_coalesce, .set_coalesce = be_set_coalesce, .get_ringparam = be_get_ringparam, -- cgit v1.2.3 From e2eb8e38592f28d8be4a518f44d3385272dedddb Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Fri, 8 Jan 2010 00:51:21 -0800 Subject: bnx2: Flush the register writes which setup the MSI-X table The MSI-X table size needs to be properly set before pci_enable_msix() is called. But on certain machines, the writes are delayed and the MSI-X table size is incorrectly read. By reading the BNX2_PCI_MSIX_CONTROL register, the writes are flushed and now ensure that the MSI-X table is set correctly before MSI-X is enable on the device. This patch was originally diagnosed and authored by Kalyan Ram Chintalapati . Signed-off-by: Benjamin Li Signed-off-by: Kalyan Ram Chintalapati Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 65df1de447e4..b1c20e5f7de8 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6145,6 +6145,10 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE); REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE); + /* Need to flush the previous three writes to ensure MSI-X + * is setup properly */ + REG_RD(bp, BNX2_PCI_MSIX_CONTROL); + for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; -- cgit v1.2.3 From df2f7ec8c09ce879245c3309d859218188123ef1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 8 Jan 2010 00:53:03 -0800 Subject: ep93xx_eth.c general cleanup General cleanup of the ep93xx_eth driver. 1) Use pr_fmt() to prefix the module name and __func__ to the error messages. 2) instead of 3) instead of and 4) Move the ep93xx_mdio_read (and ep93xx_mdio_write) function to eliminate the function prototype. 5) Change all the printk( messages to pr_ and remove the __func__ argument. 6) Use platform_get_{resource/irq} to get the platform resources and add an error check. 7) Use resource_size() for request_mem_region() and ioremap(). 8) Use %pM to print the MAC address at the end of the probe. 9) Use dev->dev_addr not data->dev_addr for the MAC argument because a random address could be used if the platform does not supply one. The message at the end of the probe is left as a printk since it displays cleaner without the function name that would be displayed with pr_info(). Signed-off-by: H Hartley Sweeten Acked-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/arm/ep93xx_eth.c | 140 +++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 72 deletions(-) diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index b25467ac895c..bf72d57a0afd 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -9,6 +9,8 @@ * (at your option) any later version. */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -20,9 +22,9 @@ #include #include #include -#include -#include -#include +#include + +#include #define DRV_MODULE_NAME "ep93xx-eth" #define DRV_MODULE_VERSION "0.1" @@ -185,7 +187,47 @@ struct ep93xx_priv #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off)) #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off)) -static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg); +static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg) +{ + struct ep93xx_priv *ep = netdev_priv(dev); + int data; + int i; + + wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg); + + for (i = 0; i < 10; i++) { + if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) + break; + msleep(1); + } + + if (i == 10) { + pr_info("mdio read timed out\n"); + data = 0xffff; + } else { + data = rdl(ep, REG_MIIDATA); + } + + return data; +} + +static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data) +{ + struct ep93xx_priv *ep = netdev_priv(dev); + int i; + + wrl(ep, REG_MIIDATA, data); + wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg); + + for (i = 0; i < 10; i++) { + if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) + break; + msleep(1); + } + + if (i == 10) + pr_info("mdio write timed out\n"); +} static struct net_device_stats *ep93xx_get_stats(struct net_device *dev) { @@ -217,14 +259,11 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) rstat->rstat1 = 0; if (!(rstat0 & RSTAT0_EOF)) - printk(KERN_CRIT "ep93xx_rx: not end-of-frame " - " %.8x %.8x\n", rstat0, rstat1); + pr_crit("not end-of-frame %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_EOB)) - printk(KERN_CRIT "ep93xx_rx: not end-of-buffer " - " %.8x %.8x\n", rstat0, rstat1); + pr_crit("not end-of-buffer %.8x %.8x\n", rstat0, rstat1); if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry) - printk(KERN_CRIT "ep93xx_rx: entry mismatch " - " %.8x %.8x\n", rstat0, rstat1); + pr_crit("entry mismatch %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_RWE)) { ep->stats.rx_errors++; @@ -241,8 +280,7 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) length = rstat1 & RSTAT1_FRAME_LENGTH; if (length > MAX_PKT_SIZE) { - printk(KERN_NOTICE "ep93xx_rx: invalid length " - " %.8x %.8x\n", rstat0, rstat1); + pr_notice("invalid length %.8x %.8x\n", rstat0, rstat1); goto err; } @@ -371,11 +409,9 @@ static void ep93xx_tx_complete(struct net_device *dev) tstat->tstat0 = 0; if (tstat0 & TSTAT0_FA) - printk(KERN_CRIT "ep93xx_tx_complete: frame aborted " - " %.8x\n", tstat0); + pr_crit("frame aborted %.8x\n", tstat0); if ((tstat0 & TSTAT0_BUFFER_INDEX) != entry) - printk(KERN_CRIT "ep93xx_tx_complete: entry mismatch " - " %.8x\n", tstat0); + pr_crit("entry mismatch %.8x\n", tstat0); if (tstat0 & TSTAT0_TXWE) { int length = ep->descs->tdesc[entry].tdesc1 & 0xfff; @@ -536,7 +572,7 @@ static int ep93xx_start_hw(struct net_device *dev) } if (i == 10) { - printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to reset\n"); + pr_crit("hw failed to reset\n"); return 1; } @@ -581,7 +617,7 @@ static int ep93xx_start_hw(struct net_device *dev) } if (i == 10) { - printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to start\n"); + pr_crit("hw failed to start\n"); return 1; } @@ -617,7 +653,7 @@ static void ep93xx_stop_hw(struct net_device *dev) } if (i == 10) - printk(KERN_CRIT DRV_MODULE_NAME ": hw failed to reset\n"); + pr_crit("hw failed to reset\n"); } static int ep93xx_open(struct net_device *dev) @@ -681,48 +717,6 @@ static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return generic_mii_ioctl(&ep->mii, data, cmd, NULL); } -static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - int data; - int i; - - wrl(ep, REG_MIICMD, REG_MIICMD_READ | (phy_id << 5) | reg); - - for (i = 0; i < 10; i++) { - if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) - break; - msleep(1); - } - - if (i == 10) { - printk(KERN_INFO DRV_MODULE_NAME ": mdio read timed out\n"); - data = 0xffff; - } else { - data = rdl(ep, REG_MIIDATA); - } - - return data; -} - -static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - int i; - - wrl(ep, REG_MIIDATA, data); - wrl(ep, REG_MIICMD, REG_MIICMD_WRITE | (phy_id << 5) | reg); - - for (i = 0; i < 10; i++) { - if ((rdl(ep, REG_MIISTS) & REG_MIISTS_BUSY) == 0) - break; - msleep(1); - } - - if (i == 10) - printk(KERN_INFO DRV_MODULE_NAME ": mdio write timed out\n"); -} - static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strcpy(info->driver, DRV_MODULE_NAME); @@ -825,12 +819,19 @@ static int ep93xx_eth_probe(struct platform_device *pdev) struct ep93xx_eth_data *data; struct net_device *dev; struct ep93xx_priv *ep; + struct resource *mem; + int irq; int err; if (pdev == NULL) return -ENODEV; data = pdev->dev.platform_data; + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!mem || irq < 0) + return -ENXIO; + dev = ep93xx_dev_alloc(data); if (dev == NULL) { err = -ENOMEM; @@ -842,23 +843,21 @@ static int ep93xx_eth_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - ep->res = request_mem_region(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1, - dev_name(&pdev->dev)); + ep->res = request_mem_region(mem->start, resource_size(mem), + dev_name(&pdev->dev)); if (ep->res == NULL) { dev_err(&pdev->dev, "Could not reserve memory region\n"); err = -ENOMEM; goto err_out; } - ep->base_addr = ioremap(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start); + ep->base_addr = ioremap(mem->start, resource_size(mem)); if (ep->base_addr == NULL) { dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n"); err = -EIO; goto err_out; } - ep->irq = pdev->resource[1].start; + ep->irq = irq; ep->mii.phy_id = data->phy_id; ep->mii.phy_id_mask = 0x1f; @@ -877,11 +876,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev) goto err_out; } - printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, " - "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", dev->name, - ep->irq, data->dev_addr[0], data->dev_addr[1], - data->dev_addr[2], data->dev_addr[3], - data->dev_addr[4], data->dev_addr[5]); + printk(KERN_INFO "%s: ep93xx on-chip ethernet, IRQ %d, %pM\n", + dev->name, ep->irq, dev->dev_addr); return 0; -- cgit v1.2.3 From 5856b606e69d3e4dc2d718b475e216eb30ee2006 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 8 Jan 2010 00:59:52 -0800 Subject: net/ipv6/tcp_ipv6.c: Use compressed IPv6 address Use "[compressed ipv6]:port" form suggested by: http://tools.ietf.org/id/draft-ietf-6man-text-addr-representation-03.txt Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index febfd595a40d..1c832bf198b3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -876,7 +876,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) if (genhash || memcmp(hash_location, newhash, 16) != 0) { if (net_ratelimit()) { - printk(KERN_INFO "MD5 Hash %s for (%pI6, %u)->(%pI6, %u)\n", + printk(KERN_INFO "MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n", genhash ? "failed" : "mismatch", &ip6h->saddr, ntohs(th->source), &ip6h->daddr, ntohs(th->dest)); -- cgit v1.2.3 From 2d4b6faf7d1818e9a52ae9f068ab4ffd9c3be923 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 7 Jan 2010 09:43:06 +0000 Subject: can: mscan: fix improper return if dlc < 8 in start_xmit function The start_xmit function of the MSCAN Driver did return improperly if the CAN dlc check failed (skb not freed and invalid return code). This patch adds a proper check of the frame lenght and data size and returns now correctly. The invalid skb packets are dropped silently as suggested by David Miller in the thread "[RFC] ndo_validate_skb: Let the netdev check a valid skb content" on the netdev mailing list. Furthermore, a typo has been fixed. Signed-off-by: Wolfgang Grandegger Reviewed-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/net/can/mscan/mscan.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 07346f880ca6..0dcbe8cfab64 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -4,7 +4,7 @@ * Copyright (C) 2005-2006 Andrey Volkov , * Varma Electronics Oy * Copyright (C) 2008-2009 Wolfgang Grandegger - * Copytight (C) 2008-2009 Pengutronix + * Copyright (C) 2008-2009 Pengutronix * * This program is free software; you can redistribute it and/or modify * it under the terms of the version 2 of the GNU General Public License @@ -177,8 +177,11 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) int i, rtr, buf_id; u32 can_id; - if (frame->can_dlc > 8) - return -EINVAL; + if (skb->len != sizeof(*frame) || frame->can_dlc > 8) { + kfree_skb(skb); + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } out_8(®s->cantier, 0); -- cgit v1.2.3 From bf3af54732bea5894ccc2cbde3ab566f0af7da56 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 7 Jan 2010 09:43:07 +0000 Subject: can: mscan-mpc5xxx: add support for the MPC512x processor The main differences compared to the MSCAN on the MPC5200 are: - More flexibility in choosing the CAN source clock and frequency: Three different clock sources can be selected: "ip", "ref" or "sys". For the latter two, a clock divider can be defined as well. If the clock source is not specified by the device tree, we first try to find an optimal CAN source clock based on the system clock. If that is not possible, the reference clock will be used. - The behavior of bus-off recovery is configurable: To comply with the usual handling of Socket-CAN bus-off recovery, "recovery on request" is selected (instead of automatic recovery). Note that only MPC5121 Rev. 2 and later is supported. Signed-off-by: Wolfgang Grandegger Reviewed-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/net/can/mscan/Kconfig | 7 +- drivers/net/can/mscan/mpc5xxx_can.c | 246 ++++++++++++++++++++++++++++++------ drivers/net/can/mscan/mscan.c | 51 ++++++-- drivers/net/can/mscan/mscan.h | 86 +++++++------ 4 files changed, 295 insertions(+), 95 deletions(-) diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig index cd0f2d6f375d..27d1d398e25e 100644 --- a/drivers/net/can/mscan/Kconfig +++ b/drivers/net/can/mscan/Kconfig @@ -11,12 +11,13 @@ if CAN_MSCAN config CAN_MPC5XXX tristate "Freescale MPC5xxx onboard CAN controller" - depends on PPC_MPC52xx + depends on (PPC_MPC52xx || PPC_MPC512x) ---help--- If you say yes here you get support for Freescale's MPC5xxx - onboard CAN controller. + onboard CAN controller. Currently, the MPC5200, MPC5200B and + MPC5121 (Rev. 2 and later) are supported. - This driver can also be built as a module. If so, the module + This driver can also be built as a module. If so, the module will be called mscan-mpc5xxx.ko. endif diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 1de6f6349b16..f73487f723b8 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -36,22 +37,21 @@ #define DRV_NAME "mpc5xxx_can" -static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = { +struct mpc5xxx_can_data { + unsigned int type; + u32 (*get_clock)(struct of_device *ofdev, const char *clock_name, + int *mscan_clksrc); +}; + +#ifdef CONFIG_PPC_MPC5200 +static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { { .compatible = "fsl,mpc5200-cdm", }, {} }; -/* - * Get frequency of the MSCAN clock source - * - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK) - * can be selected. According to the MPC5200 user's manual, the oscillator - * clock is the better choice as it has less jitter but due to a hardware - * bug, it can not be selected for the old MPC5200 Rev. A chips. - */ - -static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, - int clock_src) +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, + const char *clock_name, + int *mscan_clksrc) { unsigned int pvr; struct mpc52xx_cdm __iomem *cdm; @@ -61,11 +61,24 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, pvr = mfspr(SPRN_PVR); - freq = mpc5xxx_get_bus_frequency(of->node); + /* + * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock + * (IP_CLK) can be selected as MSCAN clock source. According to + * the MPC5200 user's manual, the oscillator clock is the better + * choice as it has less jitter. For this reason, it is selected + * by default. Unfortunately, it can not be selected for the old + * MPC5200 Rev. A chips due to a hardware bug (check errata). + */ + if (clock_name && strcmp(clock_name, "ip") == 0) + *mscan_clksrc = MSCAN_CLKSRC_BUS; + else + *mscan_clksrc = MSCAN_CLKSRC_XTAL; + + freq = mpc5xxx_get_bus_frequency(ofdev->node); if (!freq) return 0; - if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011) + if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011) return freq; /* Determine SYS_XTAL_IN frequency from the clock domain settings */ @@ -75,7 +88,6 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, return 0; } cdm = of_iomap(np_cdm, 0); - of_node_put(np_cdm); if (in_8(&cdm->ipb_clk_sel) & 0x1) freq *= 2; @@ -84,26 +96,174 @@ static unsigned int __devinit mpc52xx_can_clock_freq(struct of_device *of, freq *= (val & (1 << 5)) ? 8 : 4; freq /= (val & (1 << 6)) ? 12 : 16; + of_node_put(np_cdm); iounmap(cdm); return freq; } +#else /* !CONFIG_PPC_MPC5200 */ +static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, + const char *clock_name, + int *mscan_clksrc) +{ + return 0; +} +#endif /* CONFIG_PPC_MPC5200 */ + +#ifdef CONFIG_PPC_MPC512x +struct mpc512x_clockctl { + u32 spmr; /* System PLL Mode Reg */ + u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */ + u32 scfr1; /* System Clk Freq Reg 1 */ + u32 scfr2; /* System Clk Freq Reg 2 */ + u32 reserved; + u32 bcr; /* Bread Crumb Reg */ + u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */ + u32 spccr; /* SPDIF Clk Ctrl Reg */ + u32 cccr; /* CFM Clk Ctrl Reg */ + u32 dccr; /* DIU Clk Cnfg Reg */ + u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */ +}; + +static struct of_device_id __devinitdata mpc512x_clock_ids[] = { + { .compatible = "fsl,mpc5121-clock", }, + {} +}; + +static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, + const char *clock_name, + int *mscan_clksrc) +{ + struct mpc512x_clockctl __iomem *clockctl; + struct device_node *np_clock; + struct clk *sys_clk, *ref_clk; + int plen, clockidx, clocksrc = -1; + u32 sys_freq, val, clockdiv = 1, freq = 0; + const u32 *pval; + + np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); + if (!np_clock) { + dev_err(&ofdev->dev, "couldn't find clock node\n"); + return -ENODEV; + } + clockctl = of_iomap(np_clock, 0); + if (!clockctl) { + dev_err(&ofdev->dev, "couldn't map clock registers\n"); + return 0; + } + + /* Determine the MSCAN device index from the physical address */ + pval = of_get_property(ofdev->node, "reg", &plen); + BUG_ON(!pval || plen < sizeof(*pval)); + clockidx = (*pval & 0x80) ? 1 : 0; + if (*pval & 0x2000) + clockidx += 2; + + /* + * Clock source and divider selection: 3 different clock sources + * can be selected: "ip", "ref" or "sys". For the latter two, a + * clock divider can be defined as well. If the clock source is + * not specified by the device tree, we first try to find an + * optimal CAN source clock based on the system clock. If that + * is not posslible, the reference clock will be used. + */ + if (clock_name && !strcmp(clock_name, "ip")) { + *mscan_clksrc = MSCAN_CLKSRC_IPS; + freq = mpc5xxx_get_bus_frequency(ofdev->node); + } else { + *mscan_clksrc = MSCAN_CLKSRC_BUS; + + pval = of_get_property(ofdev->node, + "fsl,mscan-clock-divider", &plen); + if (pval && plen == sizeof(*pval)) + clockdiv = *pval; + if (!clockdiv) + clockdiv = 1; + + if (!clock_name || !strcmp(clock_name, "sys")) { + sys_clk = clk_get(&ofdev->dev, "sys_clk"); + if (!sys_clk) { + dev_err(&ofdev->dev, "couldn't get sys_clk\n"); + goto exit_unmap; + } + /* Get and round up/down sys clock rate */ + sys_freq = 1000000 * + ((clk_get_rate(sys_clk) + 499999) / 1000000); + + if (!clock_name) { + /* A multiple of 16 MHz would be optimal */ + if ((sys_freq % 16000000) == 0) { + clocksrc = 0; + clockdiv = sys_freq / 16000000; + freq = sys_freq / clockdiv; + } + } else { + clocksrc = 0; + freq = sys_freq / clockdiv; + } + } + + if (clocksrc < 0) { + ref_clk = clk_get(&ofdev->dev, "ref_clk"); + if (!ref_clk) { + dev_err(&ofdev->dev, "couldn't get ref_clk\n"); + goto exit_unmap; + } + clocksrc = 1; + freq = clk_get_rate(ref_clk) / clockdiv; + } + } + + /* Disable clock */ + out_be32(&clockctl->mccr[clockidx], 0x0); + if (clocksrc >= 0) { + /* Set source and divider */ + val = (clocksrc << 14) | ((clockdiv - 1) << 17); + out_be32(&clockctl->mccr[clockidx], val); + /* Enable clock */ + out_be32(&clockctl->mccr[clockidx], val | 0x10000); + } + + /* Enable MSCAN clock domain */ + val = in_be32(&clockctl->sccr[1]); + if (!(val & (1 << 25))) + out_be32(&clockctl->sccr[1], val | (1 << 25)); + + dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", + *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : + clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); + +exit_unmap: + of_node_put(np_clock); + iounmap(clockctl); + + return freq; +} +#else /* !CONFIG_PPC_MPC512x */ +static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev, + const char *clock_name, + int *mscan_clksrc) +{ + return 0; +} +#endif /* CONFIG_PPC_MPC512x */ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, const struct of_device_id *id) { + struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; struct device_node *np = ofdev->node; struct net_device *dev; struct mscan_priv *priv; void __iomem *base; - const char *clk_src; - int err, irq, clock_src; + const char *clock_name = NULL; + int irq, mscan_clksrc = 0; + int err = -ENOMEM; - base = of_iomap(ofdev->node, 0); + base = of_iomap(np, 0); if (!base) { dev_err(&ofdev->dev, "couldn't ioremap\n"); - err = -ENOMEM; - goto exit_release_mem; + return err; } irq = irq_of_parse_and_map(np, 0); @@ -114,37 +274,27 @@ static int __devinit mpc5xxx_can_probe(struct of_device *ofdev, } dev = alloc_mscandev(); - if (!dev) { - err = -ENOMEM; + if (!dev) goto exit_dispose_irq; - } priv = netdev_priv(dev); priv->reg_base = base; dev->irq = irq; - /* - * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock - * (IP_CLK) can be selected as MSCAN clock source. According to - * the MPC5200 user's manual, the oscillator clock is the better - * choice as it has less jitter. For this reason, it is selected - * by default. - */ - clk_src = of_get_property(np, "fsl,mscan-clock-source", NULL); - if (clk_src && strcmp(clk_src, "ip") == 0) - clock_src = MSCAN_CLKSRC_BUS; - else - clock_src = MSCAN_CLKSRC_XTAL; - priv->can.clock.freq = mpc52xx_can_clock_freq(ofdev, clock_src); + clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL); + + BUG_ON(!data); + priv->type = data->type; + priv->can.clock.freq = data->get_clock(ofdev, clock_name, + &mscan_clksrc); if (!priv->can.clock.freq) { - dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n"); - err = -ENODEV; + dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n"); goto exit_free_mscan; } SET_NETDEV_DEV(dev, &ofdev->dev); - err = register_mscandev(dev, clock_src); + err = register_mscandev(dev, mscan_clksrc); if (err) { dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", DRV_NAME, err); @@ -164,7 +314,7 @@ exit_dispose_irq: irq_dispose_mapping(irq); exit_unmap_mem: iounmap(base); -exit_release_mem: + return err; } @@ -225,8 +375,20 @@ static int mpc5xxx_can_resume(struct of_device *ofdev) } #endif +static struct mpc5xxx_can_data __devinitdata mpc5200_can_data = { + .type = MSCAN_TYPE_MPC5200, + .get_clock = mpc52xx_can_get_clock, +}; + +static struct mpc5xxx_can_data __devinitdata mpc5121_can_data = { + .type = MSCAN_TYPE_MPC5121, + .get_clock = mpc512x_can_get_clock, +}; + static struct of_device_id __devinitdata mpc5xxx_can_table[] = { - {.compatible = "fsl,mpc5200-mscan"}, + { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, }, + /* Note that only MPC5121 Rev. 2 (and later) is supported */ + { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, }, {}, }; @@ -255,5 +417,5 @@ static void __exit mpc5xxx_can_exit(void) module_exit(mpc5xxx_can_exit); MODULE_AUTHOR("Wolfgang Grandegger "); -MODULE_DESCRIPTION("Freescale MPC5200 CAN driver"); +MODULE_DESCRIPTION("Freescale MPC5xxx CAN driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 0dcbe8cfab64..500d18918bd5 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -152,6 +152,12 @@ static int mscan_start(struct net_device *dev) priv->shadow_canrier = 0; priv->flags = 0; + if (priv->type == MSCAN_TYPE_MPC5121) { + /* Clear pending bus-off condition */ + if (in_8(®s->canmisc) & MSCAN_BOHOLD) + out_8(®s->canmisc, MSCAN_BOHOLD); + } + err = mscan_set_mode(dev, MSCAN_NORMAL_MODE); if (err) return err; @@ -163,8 +169,29 @@ static int mscan_start(struct net_device *dev) out_8(®s->cantier, 0); /* Enable receive interrupts. */ - out_8(®s->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | - MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0); + out_8(®s->canrier, MSCAN_RX_INTS_ENABLE); + + return 0; +} + +static int mscan_restart(struct net_device *dev) +{ + struct mscan_priv *priv = netdev_priv(dev); + + if (priv->type == MSCAN_TYPE_MPC5121) { + struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD), + "bus-off state expected"); + out_8(®s->canmisc, MSCAN_BOHOLD); + /* Re-enable receive interrupts. */ + out_8(®s->canrier, MSCAN_RX_INTS_ENABLE); + } else { + if (priv->can.state <= CAN_STATE_BUS_OFF) + mscan_set_mode(dev, MSCAN_INIT_MODE); + return mscan_start(dev); + } return 0; } @@ -362,9 +389,12 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame, * automatically. To avoid that we stop the chip doing * a light-weight stop (we are in irq-context). */ - out_8(®s->cantier, 0); - out_8(®s->canrier, 0); - setbits8(®s->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ); + if (priv->type != MSCAN_TYPE_MPC5121) { + out_8(®s->cantier, 0); + out_8(®s->canrier, 0); + setbits8(®s->canctl0, + MSCAN_SLPRQ | MSCAN_INITRQ); + } can_bus_off(dev); break; default: @@ -494,9 +524,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode) switch (mode) { case CAN_MODE_START: - if (priv->can.state <= CAN_STATE_BUS_OFF) - mscan_set_mode(dev, MSCAN_INIT_MODE); - ret = mscan_start(dev); + ret = mscan_restart(dev); if (ret) break; if (netif_queue_stopped(dev)) @@ -595,18 +623,21 @@ static const struct net_device_ops mscan_netdev_ops = { .ndo_start_xmit = mscan_start_xmit, }; -int register_mscandev(struct net_device *dev, int clock_src) +int register_mscandev(struct net_device *dev, int mscan_clksrc) { struct mscan_priv *priv = netdev_priv(dev); struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; u8 ctl1; ctl1 = in_8(®s->canctl1); - if (clock_src) + if (mscan_clksrc) ctl1 |= MSCAN_CLKSRC; else ctl1 &= ~MSCAN_CLKSRC; + if (priv->type == MSCAN_TYPE_MPC5121) + ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */ + ctl1 |= MSCAN_CANE; out_8(®s->canctl1, ctl1); udelay(100); diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index 00fc4aaf1ed8..4ff966473bc9 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h @@ -38,18 +38,20 @@ #define MSCAN_CLKSRC 0x40 #define MSCAN_LOOPB 0x20 #define MSCAN_LISTEN 0x10 +#define MSCAN_BORM 0x08 #define MSCAN_WUPM 0x04 #define MSCAN_SLPAK 0x02 #define MSCAN_INITAK 0x01 -/* Use the MPC5200 MSCAN variant? */ +/* Use the MPC5XXX MSCAN variant? */ #ifdef CONFIG_PPC -#define MSCAN_FOR_MPC5200 +#define MSCAN_FOR_MPC5XXX #endif -#ifdef MSCAN_FOR_MPC5200 +#ifdef MSCAN_FOR_MPC5XXX #define MSCAN_CLKSRC_BUS 0 #define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC +#define MSCAN_CLKSRC_IPS MSCAN_CLKSRC #else #define MSCAN_CLKSRC_BUS MSCAN_CLKSRC #define MSCAN_CLKSRC_XTAL 0 @@ -136,7 +138,7 @@ #define MSCAN_EFF_RTR_SHIFT 0 #define MSCAN_EFF_FLAGS 0x18 /* IDE + SRR */ -#ifdef MSCAN_FOR_MPC5200 +#ifdef MSCAN_FOR_MPC5XXX #define _MSCAN_RESERVED_(n, num) u8 _res##n[num] #define _MSCAN_RESERVED_DSR_SIZE 2 #else @@ -165,67 +167,66 @@ struct mscan_regs { u8 cantbsel; /* + 0x14 0x0a */ u8 canidac; /* + 0x15 0x0b */ u8 reserved; /* + 0x16 0x0c */ - _MSCAN_RESERVED_(6, 5); /* + 0x17 */ -#ifndef MSCAN_FOR_MPC5200 - u8 canmisc; /* 0x0d */ -#endif + _MSCAN_RESERVED_(6, 2); /* + 0x17 */ + u8 canmisc; /* + 0x19 0x0d */ + _MSCAN_RESERVED_(7, 2); /* + 0x1a */ u8 canrxerr; /* + 0x1c 0x0e */ u8 cantxerr; /* + 0x1d 0x0f */ - _MSCAN_RESERVED_(7, 2); /* + 0x1e */ + _MSCAN_RESERVED_(8, 2); /* + 0x1e */ u16 canidar1_0; /* + 0x20 0x10 */ - _MSCAN_RESERVED_(8, 2); /* + 0x22 */ + _MSCAN_RESERVED_(9, 2); /* + 0x22 */ u16 canidar3_2; /* + 0x24 0x12 */ - _MSCAN_RESERVED_(9, 2); /* + 0x26 */ + _MSCAN_RESERVED_(10, 2); /* + 0x26 */ u16 canidmr1_0; /* + 0x28 0x14 */ - _MSCAN_RESERVED_(10, 2); /* + 0x2a */ + _MSCAN_RESERVED_(11, 2); /* + 0x2a */ u16 canidmr3_2; /* + 0x2c 0x16 */ - _MSCAN_RESERVED_(11, 2); /* + 0x2e */ + _MSCAN_RESERVED_(12, 2); /* + 0x2e */ u16 canidar5_4; /* + 0x30 0x18 */ - _MSCAN_RESERVED_(12, 2); /* + 0x32 */ + _MSCAN_RESERVED_(13, 2); /* + 0x32 */ u16 canidar7_6; /* + 0x34 0x1a */ - _MSCAN_RESERVED_(13, 2); /* + 0x36 */ + _MSCAN_RESERVED_(14, 2); /* + 0x36 */ u16 canidmr5_4; /* + 0x38 0x1c */ - _MSCAN_RESERVED_(14, 2); /* + 0x3a */ + _MSCAN_RESERVED_(15, 2); /* + 0x3a */ u16 canidmr7_6; /* + 0x3c 0x1e */ - _MSCAN_RESERVED_(15, 2); /* + 0x3e */ + _MSCAN_RESERVED_(16, 2); /* + 0x3e */ struct { u16 idr1_0; /* + 0x40 0x20 */ - _MSCAN_RESERVED_(16, 2); /* + 0x42 */ + _MSCAN_RESERVED_(17, 2); /* + 0x42 */ u16 idr3_2; /* + 0x44 0x22 */ - _MSCAN_RESERVED_(17, 2); /* + 0x46 */ + _MSCAN_RESERVED_(18, 2); /* + 0x46 */ u16 dsr1_0; /* + 0x48 0x24 */ - _MSCAN_RESERVED_(18, 2); /* + 0x4a */ + _MSCAN_RESERVED_(19, 2); /* + 0x4a */ u16 dsr3_2; /* + 0x4c 0x26 */ - _MSCAN_RESERVED_(19, 2); /* + 0x4e */ + _MSCAN_RESERVED_(20, 2); /* + 0x4e */ u16 dsr5_4; /* + 0x50 0x28 */ - _MSCAN_RESERVED_(20, 2); /* + 0x52 */ + _MSCAN_RESERVED_(21, 2); /* + 0x52 */ u16 dsr7_6; /* + 0x54 0x2a */ - _MSCAN_RESERVED_(21, 2); /* + 0x56 */ + _MSCAN_RESERVED_(22, 2); /* + 0x56 */ u8 dlr; /* + 0x58 0x2c */ - u8:8; /* + 0x59 0x2d */ - _MSCAN_RESERVED_(22, 2); /* + 0x5a */ + u8 reserved; /* + 0x59 0x2d */ + _MSCAN_RESERVED_(23, 2); /* + 0x5a */ u16 time; /* + 0x5c 0x2e */ } rx; - _MSCAN_RESERVED_(23, 2); /* + 0x5e */ + _MSCAN_RESERVED_(24, 2); /* + 0x5e */ struct { u16 idr1_0; /* + 0x60 0x30 */ - _MSCAN_RESERVED_(24, 2); /* + 0x62 */ + _MSCAN_RESERVED_(25, 2); /* + 0x62 */ u16 idr3_2; /* + 0x64 0x32 */ - _MSCAN_RESERVED_(25, 2); /* + 0x66 */ + _MSCAN_RESERVED_(26, 2); /* + 0x66 */ u16 dsr1_0; /* + 0x68 0x34 */ - _MSCAN_RESERVED_(26, 2); /* + 0x6a */ + _MSCAN_RESERVED_(27, 2); /* + 0x6a */ u16 dsr3_2; /* + 0x6c 0x36 */ - _MSCAN_RESERVED_(27, 2); /* + 0x6e */ + _MSCAN_RESERVED_(28, 2); /* + 0x6e */ u16 dsr5_4; /* + 0x70 0x38 */ - _MSCAN_RESERVED_(28, 2); /* + 0x72 */ + _MSCAN_RESERVED_(29, 2); /* + 0x72 */ u16 dsr7_6; /* + 0x74 0x3a */ - _MSCAN_RESERVED_(29, 2); /* + 0x76 */ + _MSCAN_RESERVED_(30, 2); /* + 0x76 */ u8 dlr; /* + 0x78 0x3c */ u8 tbpr; /* + 0x79 0x3d */ - _MSCAN_RESERVED_(30, 2); /* + 0x7a */ + _MSCAN_RESERVED_(31, 2); /* + 0x7a */ u16 time; /* + 0x7c 0x3e */ } tx; - _MSCAN_RESERVED_(31, 2); /* + 0x7e */ + _MSCAN_RESERVED_(32, 2); /* + 0x7e */ } __attribute__ ((packed)); #undef _MSCAN_RESERVED_ @@ -237,6 +238,15 @@ struct mscan_regs { #define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ) #define MSCAN_SET_MODE_RETRIES 255 #define MSCAN_ECHO_SKB_MAX 3 +#define MSCAN_RX_INTS_ENABLE (MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | \ + MSCAN_RSTATE1 | MSCAN_RSTATE0 | \ + MSCAN_TSTATE1 | MSCAN_TSTATE0) + +/* MSCAN type variants */ +enum { + MSCAN_TYPE_MPC5200, + MSCAN_TYPE_MPC5121 +}; #define BTR0_BRP_MASK 0x3f #define BTR0_SJW_SHIFT 6 @@ -270,6 +280,7 @@ struct tx_queue_entry { struct mscan_priv { struct can_priv can; /* must be the first member */ + unsigned int type; /* MSCAN type variants */ long open_time; unsigned long flags; void __iomem *reg_base; /* ioremap'ed address to registers */ @@ -285,12 +296,7 @@ struct mscan_priv { }; extern struct net_device *alloc_mscandev(void); -/* - * clock_src: - * 1 = The MSCAN clock source is the onchip Bus Clock. - * 0 = The MSCAN clock source is the chip Oscillator Clock. - */ -extern int register_mscandev(struct net_device *dev, int clock_src); +extern int register_mscandev(struct net_device *dev, int mscan_clksrc); extern void unregister_mscandev(struct net_device *dev); #endif /* __MSCAN_H__ */ -- cgit v1.2.3 From 959d20bfe8b90023c862dec3956054027a5a0912 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 7 Jan 2010 09:43:08 +0000 Subject: powerpc/mpc5xxx: add OF platform binding doc for FSL MSCAN devices This patch adds documentation for the MSCAN OF device bindings for the MPC512x and moves the one for the MPC5200 to the new common file "Documentation/powerpc/dts-bindings/fsl/can.txt". Signed-off-by: Wolfgang Grandegger Reviewed-by: Wolfram Sang Signed-off-by: David S. Miller --- Documentation/powerpc/dts-bindings/fsl/can.txt | 53 ++++++++++++++++++++++ Documentation/powerpc/dts-bindings/fsl/mpc5200.txt | 9 +--- 2 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 Documentation/powerpc/dts-bindings/fsl/can.txt diff --git a/Documentation/powerpc/dts-bindings/fsl/can.txt b/Documentation/powerpc/dts-bindings/fsl/can.txt new file mode 100644 index 000000000000..2fa4fcd38fd6 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/fsl/can.txt @@ -0,0 +1,53 @@ +CAN Device Tree Bindings +------------------------ + +(c) 2006-2009 Secret Lab Technologies Ltd +Grant Likely + +fsl,mpc5200-mscan nodes +----------------------- +In addition to the required compatible-, reg- and interrupt-properties, you can +also specify which clock source shall be used for the controller: + +- fsl,mscan-clock-source : a string describing the clock source. Valid values + are: "ip" for ip bus clock + "ref" for reference clock (XTAL) + "ref" is default in case this property is not + present. + +fsl,mpc5121-mscan nodes +----------------------- +In addition to the required compatible-, reg- and interrupt-properties, you can +also specify which clock source and divider shall be used for the controller: + +- fsl,mscan-clock-source : a string describing the clock source. Valid values + are: "ip" for ip bus clock + "ref" for reference clock + "sys" for system clock + If this property is not present, an optimal CAN + clock source and frequency based on the system + clock will be selected. If this is not possible, + the reference clock will be used. + +- fsl,mscan-clock-divider: for the reference and system clock, an additional + clock divider can be specified. By default, a + value of 1 is used. + +Note that the MPC5121 Rev. 1 processor is not supported. + +Examples: + can@1300 { + compatible = "fsl,mpc5121-mscan"; + interrupts = <12 0x8>; + interrupt-parent = <&ipic>; + reg = <0x1300 0x80>; + }; + + can@1380 { + compatible = "fsl,mpc5121-mscan"; + interrupts = <13 0x8>; + interrupt-parent = <&ipic>; + reg = <0x1380 0x80>; + fsl,mscan-clock-source = "ref"; + fsl,mscan-clock-divider = <3>; + }; diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt index 5c6602dbfdc2..4ccb2cd5df94 100644 --- a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt +++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt @@ -195,11 +195,4 @@ External interrupts: fsl,mpc5200-mscan nodes ----------------------- -In addition to the required compatible-, reg- and interrupt-properites, you can -also specify which clock source shall be used for the controller: - -- fsl,mscan-clock-source- a string describing the clock source. Valid values - are: "ip" for ip bus clock - "ref" for reference clock (XTAL) - "ref" is default in case this property is not - present. +See file can.txt in this directory. -- cgit v1.2.3 From 7f081d405adb5f905db11c6449319ab7c670722e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 7 Jan 2010 17:41:00 +0000 Subject: igb: add support for device reset interrupt This patch adds support for the global device reset interrupt. Without this change the drivers will report tx hangs on all ports when a global device reset occurs. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 484fbc83739f..e959b88be314 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -4110,6 +4110,9 @@ static irqreturn_t igb_msix_other(int irq, void *data) u32 icr = rd32(E1000_ICR); /* reading ICR causes bit 31 of EICR to be cleared */ + if (icr & E1000_ICR_DRSTA) + schedule_work(&adapter->reset_task); + if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; @@ -4733,6 +4736,9 @@ static irqreturn_t igb_intr_msi(int irq, void *data) igb_write_itr(q_vector); + if (icr & E1000_ICR_DRSTA) + schedule_work(&adapter->reset_task); + if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; @@ -4772,6 +4778,9 @@ static irqreturn_t igb_intr(int irq, void *data) if (!(icr & E1000_ICR_INT_ASSERTED)) return IRQ_NONE; + if (icr & E1000_ICR_DRSTA) + schedule_work(&adapter->reset_task); + if (icr & E1000_ICR_DOUTSYNC) { /* HW is reporting DMA is out of sync */ adapter->stats.doosync++; -- cgit v1.2.3 From 51f5300682f5925a11edfddfd47ed47376871974 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sat, 9 Jan 2010 23:00:32 -0800 Subject: mac8390: Fix build breakage commit 18c0019102228875cb0f6f252dad5148491e96b2 ("drivers/net/mac8390.c: Convert printk(KERN_ to pr_(") broke the build: | drivers/net/mac8390.c:306: error: expected ')' before 'version' as "version" is not a string literal, but a variable. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/mac8390.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index c70bd6888c89..a8768672dc5a 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -303,7 +303,7 @@ static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev, int offset; volatile unsigned short *i; - printk_once(KERN_INFO pr_fmt(version)); + printk_once(KERN_INFO pr_fmt("%s"), version); dev->irq = SLOT2IRQ(ndev->board->slot); /* This is getting to be a habit */ -- cgit v1.2.3 From c3f6c21d6e60e39c81c27f18ebad9c7615eff545 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 10 Jan 2010 00:43:03 +0000 Subject: NET: ipv6, remove unnecessary check Stanse found a potential null dereference in snmp6_unregister_dev. There is a check for idev being NULL, but it is dereferenced earlier. But idev cannot be NULL when passed to snmp6_unregister_dev, so remove the test. Signed-off-by: Jiri Slaby Cc: "David S. Miller" Cc: Alexey Kuznetsov Cc: "Pekka Savola (ipv6)" Cc: James Morris Cc: Hideaki YOSHIFUJI Cc: Patrick McHardy Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/ipv6/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index c9605c3ad91f..7b197b7132e0 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -259,7 +259,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) struct net *net = dev_net(idev->dev); if (!net->mib.proc_net_devsnmp6) return -ENOENT; - if (!idev || !idev->stats.proc_dir_entry) + if (!idev->stats.proc_dir_entry) return -EINVAL; remove_proc_entry(idev->stats.proc_dir_entry->name, net->mib.proc_net_devsnmp6); -- cgit v1.2.3 From c026ca581f22497c42cbe7a2004fa0d5f1bd6c42 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 10 Jan 2010 01:17:34 +0000 Subject: NET: irda, remove unnecessary checks Stanse found a potential null dereference in ircomm_tty_close and ircomm_tty_hangup. There is a check for tty being NULL, but it is dereferenced earlier. But it is bogus, the tty cannot be NULL, so remove the !tty checks. Signed-off-by: Jiri Slaby Cc: Samuel Ortiz Cc: "David S. Miller" Cc: Alan Cox Cc: Greg Kroah-Hartman Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- net/irda/ircomm/ircomm_tty.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 811984d9324b..8b85d774e47f 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -496,9 +496,6 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) IRDA_DEBUG(0, "%s()\n", __func__ ); - if (!tty) - return; - IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); @@ -1007,9 +1004,6 @@ static void ircomm_tty_hangup(struct tty_struct *tty) IRDA_ASSERT(self != NULL, return;); IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); - if (!tty) - return; - /* ircomm_tty_flush_buffer(tty); */ ircomm_tty_shutdown(self); -- cgit v1.2.3 From 50d9c84ee522ce6f61cd6a7dfce1b82a260edd3c Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:23:11 +0000 Subject: ixgbevf: Macros, data structures, useful defines and registers These two headers define the commonly used macros, data structures, register bits and register offsets used by the ixgbevf driver on the 82599 virtual function device Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/defines.h | 292 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/regs.h | 85 ++++++++++++ 2 files changed, 377 insertions(+) create mode 100644 drivers/net/ixgbevf/defines.h create mode 100644 drivers/net/ixgbevf/regs.h diff --git a/drivers/net/ixgbevf/defines.h b/drivers/net/ixgbevf/defines.h new file mode 100644 index 000000000000..c44fdb05447a --- /dev/null +++ b/drivers/net/ixgbevf/defines.h @@ -0,0 +1,292 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBEVF_DEFINES_H_ +#define _IXGBEVF_DEFINES_H_ + +/* Device IDs */ +#define IXGBE_DEV_ID_82599_VF 0x10ED + +#define IXGBE_VF_IRQ_CLEAR_MASK 7 +#define IXGBE_VF_MAX_TX_QUEUES 1 +#define IXGBE_VF_MAX_RX_QUEUES 1 +#define IXGBE_ETH_LENGTH_OF_ADDRESS 6 + +/* Link speed */ +typedef u32 ixgbe_link_speed; +#define IXGBE_LINK_SPEED_1GB_FULL 0x0020 +#define IXGBE_LINK_SPEED_10GB_FULL 0x0080 + +#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */ +#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */ +#define IXGBE_TXDCTL_ENABLE 0x02000000 /* Enable specific Tx Queue */ +#define IXGBE_LINKS_UP 0x40000000 +#define IXGBE_LINKS_SPEED 0x20000000 + +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ +#define IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE 8 +#define IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE 8 +#define IXGBE_REQ_TX_BUFFER_GRANULARITY 1024 + +/* Interrupt Vector Allocation Registers */ +#define IXGBE_IVAR_ALLOC_VAL 0x80 /* Interrupt Allocation valid */ + +#define IXGBE_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ + +/* Receive Config masks */ +#define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */ +#define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Descriptor Monitor Bypass */ +#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */ +#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */ + +/* DCA Control */ +#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */ + +/* PSRTYPE bit definitions */ +#define IXGBE_PSRTYPE_TCPHDR 0x00000010 +#define IXGBE_PSRTYPE_UDPHDR 0x00000020 +#define IXGBE_PSRTYPE_IPV4HDR 0x00000100 +#define IXGBE_PSRTYPE_IPV6HDR 0x00000200 +#define IXGBE_PSRTYPE_L2HDR 0x00001000 + +/* SRRCTL bit definitions */ +#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */ +#define IXGBE_SRRCTL_RDMTS_SHIFT 22 +#define IXGBE_SRRCTL_RDMTS_MASK 0x01C00000 +#define IXGBE_SRRCTL_DROP_EN 0x10000000 +#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F +#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00 +#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000 +#define IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000 +#define IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000 +#define IXGBE_SRRCTL_DESCTYPE_MASK 0x0E000000 + +/* Receive Descriptor bit definitions */ +#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */ +#define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */ +#define IXGBE_RXD_STAT_FLM 0x04 /* FDir Match */ +#define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ +#define IXGBE_RXDADV_NEXTP_MASK 0x000FFFF0 /* Next Descriptor Index */ +#define IXGBE_RXDADV_NEXTP_SHIFT 0x00000004 +#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ +#define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */ +#define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ +#define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ +#define IXGBE_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ +#define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */ +#define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ +#define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ +#define IXGBE_RXD_STAT_TS 0x10000 /* Time Stamp */ +#define IXGBE_RXD_STAT_SECP 0x20000 /* Security Processing */ +#define IXGBE_RXD_STAT_LB 0x40000 /* Loopback Status */ +#define IXGBE_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ +#define IXGBE_RXD_ERR_CE 0x01 /* CRC Error */ +#define IXGBE_RXD_ERR_LE 0x02 /* Length Error */ +#define IXGBE_RXD_ERR_PE 0x08 /* Packet Error */ +#define IXGBE_RXD_ERR_OSE 0x10 /* Oversize Error */ +#define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */ +#define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */ +#define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ +#define IXGBE_RXDADV_ERR_MASK 0xFFF00000 /* RDESC.ERRORS mask */ +#define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ +#define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */ +#define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */ +#define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */ +#define IXGBE_RXDADV_ERR_PE 0x08000000 /* Packet Error */ +#define IXGBE_RXDADV_ERR_OSE 0x10000000 /* Oversize Error */ +#define IXGBE_RXDADV_ERR_USE 0x20000000 /* Undersize Error */ +#define IXGBE_RXDADV_ERR_TCPE 0x40000000 /* TCP/UDP Checksum Error */ +#define IXGBE_RXDADV_ERR_IPE 0x80000000 /* IP Checksum Error */ +#define IXGBE_RXD_VLAN_ID_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ +#define IXGBE_RXD_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ +#define IXGBE_RXD_PRI_SHIFT 13 +#define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */ +#define IXGBE_RXD_CFI_SHIFT 12 + +#define IXGBE_RXDADV_STAT_DD IXGBE_RXD_STAT_DD /* Done */ +#define IXGBE_RXDADV_STAT_EOP IXGBE_RXD_STAT_EOP /* End of Packet */ +#define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */ +#define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */ +#define IXGBE_RXDADV_STAT_MASK 0x000FFFFF /* Stat/NEXTP: bit 0-19 */ +#define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */ +#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */ +#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */ +#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */ +#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */ + +#define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F +#define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0 +#define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0 +#define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0 +#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000 +#define IXGBE_RXDADV_RSCCNT_SHIFT 17 +#define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5 +#define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000 +#define IXGBE_RXDADV_SPH 0x8000 + +#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXD_ERR_CE | \ + IXGBE_RXD_ERR_LE | \ + IXGBE_RXD_ERR_PE | \ + IXGBE_RXD_ERR_OSE | \ + IXGBE_RXD_ERR_USE) + +#define IXGBE_RXDADV_ERR_FRAME_ERR_MASK ( \ + IXGBE_RXDADV_ERR_CE | \ + IXGBE_RXDADV_ERR_LE | \ + IXGBE_RXDADV_ERR_PE | \ + IXGBE_RXDADV_ERR_OSE | \ + IXGBE_RXDADV_ERR_USE) + +#define IXGBE_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ +#define IXGBE_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ +#define IXGBE_TXD_CMD_EOP 0x01000000 /* End of Packet */ +#define IXGBE_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ +#define IXGBE_TXD_CMD_IC 0x04000000 /* Insert Checksum */ +#define IXGBE_TXD_CMD_RS 0x08000000 /* Report Status */ +#define IXGBE_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ +#define IXGBE_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ +#define IXGBE_TXD_STAT_DD 0x00000001 /* Descriptor Done */ + +/* Transmit Descriptor - Advanced */ +union ixgbe_adv_tx_desc { + struct { + __le64 buffer_addr; /* Address of descriptor's data buf */ + __le32 cmd_type_len; + __le32 olinfo_status; + } read; + struct { + __le64 rsvd; /* Reserved */ + __le32 nxtseq_seed; + __le32 status; + } wb; +}; + +/* Receive Descriptor - Advanced */ +union ixgbe_adv_rx_desc { + struct { + __le64 pkt_addr; /* Packet buffer address */ + __le64 hdr_addr; /* Header buffer address */ + } read; + struct { + struct { + union { + __le32 data; + struct { + __le16 pkt_info; /* RSS, Pkt type */ + __le16 hdr_info; /* Splithdr, hdrlen */ + } hs_rss; + } lo_dword; + union { + __le32 rss; /* RSS Hash */ + struct { + __le16 ip_id; /* IP id */ + __le16 csum; /* Packet Checksum */ + } csum_ip; + } hi_dword; + } lower; + struct { + __le32 status_error; /* ext status/error */ + __le16 length; /* Packet length */ + __le16 vlan; /* VLAN tag */ + } upper; + } wb; /* writeback */ +}; + +/* Context descriptors */ +struct ixgbe_adv_tx_context_desc { + __le32 vlan_macip_lens; + __le32 seqnum_seed; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; +}; + +/* Adv Transmit Descriptor Config Masks */ +#define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */ +#define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Desc */ +#define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */ +#define IXGBE_ADVTXD_DCMD_EOP IXGBE_TXD_CMD_EOP /* End of Packet */ +#define IXGBE_ADVTXD_DCMD_IFCS IXGBE_TXD_CMD_IFCS /* Insert FCS */ +#define IXGBE_ADVTXD_DCMD_RS IXGBE_TXD_CMD_RS /* Report Status */ +#define IXGBE_ADVTXD_DCMD_DEXT IXGBE_TXD_CMD_DEXT /* Desc ext (1=Adv) */ +#define IXGBE_ADVTXD_DCMD_VLE IXGBE_TXD_CMD_VLE /* VLAN pkt enable */ +#define IXGBE_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */ +#define IXGBE_ADVTXD_STAT_DD IXGBE_TXD_STAT_DD /* Descriptor Done */ +#define IXGBE_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */ +#define IXGBE_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */ +#define IXGBE_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */ +#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */ +#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */ +#define IXGBE_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */ +#define IXGBE_ADVTXD_POPTS_SHIFT 8 /* Adv desc POPTS shift */ +#define IXGBE_ADVTXD_POPTS_IXSM (IXGBE_TXD_POPTS_IXSM << \ + IXGBE_ADVTXD_POPTS_SHIFT) +#define IXGBE_ADVTXD_POPTS_TXSM (IXGBE_TXD_POPTS_TXSM << \ + IXGBE_ADVTXD_POPTS_SHIFT) +#define IXGBE_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */ +#define IXGBE_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ +#define IXGBE_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */ +#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ +#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + +/* Interrupt register bitmasks */ + +/* Extended Interrupt Cause Read */ +#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */ +#define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */ +#define IXGBE_EICR_OTHER 0x80000000 /* Interrupt Cause Active */ + +/* Extended Interrupt Cause Set */ +#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EICS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +/* Extended Interrupt Mask Set */ +#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EIMS_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +/* Extended Interrupt Mask Clear */ +#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */ +#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */ +#define IXGBE_EIMC_OTHER IXGBE_EICR_OTHER /* INT Cause Active */ + +#define IXGBE_EIMS_ENABLE_MASK ( \ + IXGBE_EIMS_RTX_QUEUE | \ + IXGBE_EIMS_MAILBOX | \ + IXGBE_EIMS_OTHER) + +#define IXGBE_EITR_CNT_WDIS 0x80000000 + +/* Error Codes */ +#define IXGBE_ERR_INVALID_MAC_ADDR -1 +#define IXGBE_ERR_RESET_FAILED -2 + +#endif /* _IXGBEVF_DEFINES_H_ */ diff --git a/drivers/net/ixgbevf/regs.h b/drivers/net/ixgbevf/regs.h new file mode 100644 index 000000000000..12f75960aec1 --- /dev/null +++ b/drivers/net/ixgbevf/regs.h @@ -0,0 +1,85 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBEVF_REGS_H_ +#define _IXGBEVF_REGS_H_ + +#define IXGBE_VFCTRL 0x00000 +#define IXGBE_VFSTATUS 0x00008 +#define IXGBE_VFLINKS 0x00010 +#define IXGBE_VFRTIMER 0x00048 +#define IXGBE_VFRXMEMWRAP 0x03190 +#define IXGBE_VTEICR 0x00100 +#define IXGBE_VTEICS 0x00104 +#define IXGBE_VTEIMS 0x00108 +#define IXGBE_VTEIMC 0x0010C +#define IXGBE_VTEIAC 0x00110 +#define IXGBE_VTEIAM 0x00114 +#define IXGBE_VTEITR(x) (0x00820 + (4 * x)) +#define IXGBE_VTIVAR(x) (0x00120 + (4 * x)) +#define IXGBE_VTIVAR_MISC 0x00140 +#define IXGBE_VTRSCINT(x) (0x00180 + (4 * x)) +#define IXGBE_VFRDBAL(x) (0x01000 + (0x40 * x)) +#define IXGBE_VFRDBAH(x) (0x01004 + (0x40 * x)) +#define IXGBE_VFRDLEN(x) (0x01008 + (0x40 * x)) +#define IXGBE_VFRDH(x) (0x01010 + (0x40 * x)) +#define IXGBE_VFRDT(x) (0x01018 + (0x40 * x)) +#define IXGBE_VFRXDCTL(x) (0x01028 + (0x40 * x)) +#define IXGBE_VFSRRCTL(x) (0x01014 + (0x40 * x)) +#define IXGBE_VFRSCCTL(x) (0x0102C + (0x40 * x)) +#define IXGBE_VFPSRTYPE 0x00300 +#define IXGBE_VFTDBAL(x) (0x02000 + (0x40 * x)) +#define IXGBE_VFTDBAH(x) (0x02004 + (0x40 * x)) +#define IXGBE_VFTDLEN(x) (0x02008 + (0x40 * x)) +#define IXGBE_VFTDH(x) (0x02010 + (0x40 * x)) +#define IXGBE_VFTDT(x) (0x02018 + (0x40 * x)) +#define IXGBE_VFTXDCTL(x) (0x02028 + (0x40 * x)) +#define IXGBE_VFTDWBAL(x) (0x02038 + (0x40 * x)) +#define IXGBE_VFTDWBAH(x) (0x0203C + (0x40 * x)) +#define IXGBE_VFDCA_RXCTRL(x) (0x0100C + (0x40 * x)) +#define IXGBE_VFDCA_TXCTRL(x) (0x0200c + (0x40 * x)) +#define IXGBE_VFGPRC 0x0101C +#define IXGBE_VFGPTC 0x0201C +#define IXGBE_VFGORC_LSB 0x01020 +#define IXGBE_VFGORC_MSB 0x01024 +#define IXGBE_VFGOTC_LSB 0x02020 +#define IXGBE_VFGOTC_MSB 0x02024 +#define IXGBE_VFMPRC 0x01034 + +#define IXGBE_WRITE_REG(a, reg, value) writel((value), ((a)->hw_addr + (reg))) + +#define IXGBE_READ_REG(a, reg) readl((a)->hw_addr + (reg)) + +#define IXGBE_WRITE_REG_ARRAY(a, reg, offset, value) ( \ + writel((value), ((a)->hw_addr + (reg) + ((offset) << 2)))) + +#define IXGBE_READ_REG_ARRAY(a, reg, offset) ( \ + readl((a)->hw_addr + (reg) + ((offset) << 2))) + +#define IXGBE_WRITE_FLUSH(a) (IXGBE_READ_REG(a, IXGBE_VFSTATUS)) + +#endif /* _IXGBEVF_REGS_H_ */ -- cgit v1.2.3 From 3047f90bd515b38e62094eff90b299f379ab7243 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:23:31 +0000 Subject: ixgbevf: 82599 Virtual Function core functions and header This module and header file contain the core functions for the 82599 virtual function device. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/vf.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/vf.h | 168 ++++++++++++++++++++ 2 files changed, 555 insertions(+) create mode 100644 drivers/net/ixgbevf/vf.c create mode 100644 drivers/net/ixgbevf/vf.h diff --git a/drivers/net/ixgbevf/vf.c b/drivers/net/ixgbevf/vf.c new file mode 100644 index 000000000000..4b5dec0ec140 --- /dev/null +++ b/drivers/net/ixgbevf/vf.c @@ -0,0 +1,387 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "vf.h" + +/** + * ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx + * @hw: pointer to hardware structure + * + * Starts the hardware by filling the bus info structure and media type, clears + * all on chip counters, initializes receive address registers, multicast + * table, VLAN filter table, calls routine to set up link and flow control + * settings, and leaves transmit and receive units disabled and uninitialized + **/ +static s32 ixgbevf_start_hw_vf(struct ixgbe_hw *hw) +{ + /* Clear adapter stopped flag */ + hw->adapter_stopped = false; + + return 0; +} + +/** + * ixgbevf_init_hw_vf - virtual function hardware initialization + * @hw: pointer to hardware structure + * + * Initialize the hardware by resetting the hardware and then starting + * the hardware + **/ +static s32 ixgbevf_init_hw_vf(struct ixgbe_hw *hw) +{ + s32 status = hw->mac.ops.start_hw(hw); + + hw->mac.ops.get_mac_addr(hw, hw->mac.addr); + + return status; +} + +/** + * ixgbevf_reset_hw_vf - Performs hardware reset + * @hw: pointer to hardware structure + * + * Resets the hardware by reseting the transmit and receive units, masks and + * clears all interrupts. + **/ +static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 timeout = IXGBE_VF_INIT_TIMEOUT; + s32 ret_val = IXGBE_ERR_INVALID_MAC_ADDR; + u32 msgbuf[IXGBE_VF_PERMADDR_MSG_LEN]; + u8 *addr = (u8 *)(&msgbuf[1]); + + /* Call adapter stop to disable tx/rx and clear interrupts */ + hw->mac.ops.stop_adapter(hw); + + IXGBE_WRITE_REG(hw, IXGBE_VFCTRL, IXGBE_CTRL_RST); + IXGBE_WRITE_FLUSH(hw); + + /* we cannot reset while the RSTI / RSTD bits are asserted */ + while (!mbx->ops.check_for_rst(hw) && timeout) { + timeout--; + udelay(5); + } + + if (!timeout) + return IXGBE_ERR_RESET_FAILED; + + /* mailbox timeout can now become active */ + mbx->timeout = IXGBE_VF_MBX_INIT_TIMEOUT; + + msgbuf[0] = IXGBE_VF_RESET; + mbx->ops.write_posted(hw, msgbuf, 1); + + msleep(10); + + /* set our "perm_addr" based on info provided by PF */ + /* also set up the mc_filter_type which is piggy backed + * on the mac address in word 3 */ + ret_val = mbx->ops.read_posted(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN); + if (ret_val) + return ret_val; + + if (msgbuf[0] != (IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK)) + return IXGBE_ERR_INVALID_MAC_ADDR; + + memcpy(hw->mac.perm_addr, addr, IXGBE_ETH_LENGTH_OF_ADDRESS); + hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD]; + + return 0; +} + +/** + * ixgbevf_stop_hw_vf - Generic stop Tx/Rx units + * @hw: pointer to hardware structure + * + * Sets the adapter_stopped flag within ixgbe_hw struct. Clears interrupts, + * disables transmit and receive units. The adapter_stopped flag is used by + * the shared code and drivers to determine if the adapter is in a stopped + * state and should not touch the hardware. + **/ +static s32 ixgbevf_stop_hw_vf(struct ixgbe_hw *hw) +{ + u32 number_of_queues; + u32 reg_val; + u16 i; + + /* + * Set the adapter_stopped flag so other driver functions stop touching + * the hardware + */ + hw->adapter_stopped = true; + + /* Disable the receive unit by stopped each queue */ + number_of_queues = hw->mac.max_rx_queues; + for (i = 0; i < number_of_queues; i++) { + reg_val = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); + if (reg_val & IXGBE_RXDCTL_ENABLE) { + reg_val &= ~IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(i), reg_val); + } + } + + IXGBE_WRITE_FLUSH(hw); + + /* Clear interrupt mask to stop from interrupts being generated */ + IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, IXGBE_VF_IRQ_CLEAR_MASK); + + /* Clear any pending interrupts */ + IXGBE_READ_REG(hw, IXGBE_VTEICR); + + /* Disable the transmit unit. Each queue must be disabled. */ + number_of_queues = hw->mac.max_tx_queues; + for (i = 0; i < number_of_queues; i++) { + reg_val = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); + if (reg_val & IXGBE_TXDCTL_ENABLE) { + reg_val &= ~IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(i), reg_val); + } + } + + return 0; +} + +/** + * ixgbevf_mta_vector - Determines bit-vector in multicast table to set + * @hw: pointer to hardware structure + * @mc_addr: the multicast address + * + * Extracts the 12 bits, from a multicast address, to determine which + * bit-vector to set in the multicast table. The hardware uses 12 bits, from + * incoming rx multicast addresses, to determine the bit-vector to check in + * the MTA. Which of the 4 combination, of 12-bits, the hardware uses is set + * by the MO field of the MCSTCTRL. The MO field is set during initialization + * to mc_filter_type. + **/ +static s32 ixgbevf_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr) +{ + u32 vector = 0; + + switch (hw->mac.mc_filter_type) { + case 0: /* use bits [47:36] of the address */ + vector = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); + break; + case 1: /* use bits [46:35] of the address */ + vector = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); + break; + case 2: /* use bits [45:34] of the address */ + vector = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); + break; + case 3: /* use bits [43:32] of the address */ + vector = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); + break; + default: /* Invalid mc_filter_type */ + break; + } + + /* vector can only be 12-bits or boundary will be exceeded */ + vector &= 0xFFF; + return vector; +} + +/** + * ixgbevf_get_mac_addr_vf - Read device MAC address + * @hw: pointer to the HW structure + * @mac_addr: pointer to storage for retrieved MAC address + **/ +static s32 ixgbevf_get_mac_addr_vf(struct ixgbe_hw *hw, u8 *mac_addr) +{ + memcpy(mac_addr, hw->mac.perm_addr, IXGBE_ETH_LENGTH_OF_ADDRESS); + + return 0; +} + +/** + * ixgbevf_set_rar_vf - set device MAC address + * @hw: pointer to hardware structure + * @index: Receive address register to write + * @addr: Address to put into receive address register + * @vmdq: Unused in this implementation + **/ +static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, + u32 vmdq) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[3]; + u8 *msg_addr = (u8 *)(&msgbuf[1]); + s32 ret_val; + + memset(msgbuf, 0, sizeof(msgbuf)); + msgbuf[0] = IXGBE_VF_SET_MAC_ADDR; + memcpy(msg_addr, addr, 6); + ret_val = mbx->ops.write_posted(hw, msgbuf, 3); + + if (!ret_val) + ret_val = mbx->ops.read_posted(hw, msgbuf, 3); + + msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; + + /* if nacked the address was rejected, use "perm_addr" */ + if (!ret_val && + (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) + ixgbevf_get_mac_addr_vf(hw, hw->mac.addr); + + return ret_val; +} + +/** + * ixgbevf_update_mc_addr_list_vf - Update Multicast addresses + * @hw: pointer to the HW structure + * @mc_addr_list: array of multicast addresses to program + * @mc_addr_count: number of multicast addresses to program + * @next: caller supplied function to return next address in list + * + * Updates the Multicast Table Array. + **/ +static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, u8 *mc_addr_list, + u32 mc_addr_count, + ixgbe_mc_addr_itr next) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[IXGBE_VFMAILBOX_SIZE]; + u16 *vector_list = (u16 *)&msgbuf[1]; + u32 vector; + u32 cnt, i; + u32 vmdq; + + /* Each entry in the list uses 1 16 bit word. We have 30 + * 16 bit words available in our HW msg buffer (minus 1 for the + * msg type). That's 30 hash values if we pack 'em right. If + * there are more than 30 MC addresses to add then punt the + * extras for now and then add code to handle more than 30 later. + * It would be unusual for a server to request that many multi-cast + * addresses except for in large enterprise network environments. + */ + + cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; + msgbuf[0] = IXGBE_VF_SET_MULTICAST; + msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT; + + for (i = 0; i < cnt; i++) { + vector = ixgbevf_mta_vector(hw, next(hw, &mc_addr_list, &vmdq)); + vector_list[i] = vector; + } + + mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE); + + return 0; +} + +/** + * ixgbevf_set_vfta_vf - Set/Unset vlan filter table address + * @hw: pointer to the HW structure + * @vlan: 12 bit VLAN ID + * @vind: unused by VF drivers + * @vlan_on: if true then set bit, else clear bit + **/ +static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind, + bool vlan_on) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[2]; + + msgbuf[0] = IXGBE_VF_SET_VLAN; + msgbuf[1] = vlan; + /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */ + msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT; + + return mbx->ops.write_posted(hw, msgbuf, 2); +} + +/** + * ixgbevf_setup_mac_link_vf - Setup MAC link settings + * @hw: pointer to hardware structure + * @speed: Unused in this implementation + * @autoneg: Unused in this implementation + * @autoneg_wait_to_complete: Unused in this implementation + * + * Do nothing and return success. VF drivers are not allowed to change + * global settings. Maintained for driver compatibility. + **/ +static s32 ixgbevf_setup_mac_link_vf(struct ixgbe_hw *hw, + ixgbe_link_speed speed, bool autoneg, + bool autoneg_wait_to_complete) +{ + return 0; +} + +/** + * ixgbevf_check_mac_link_vf - Get link/speed status + * @hw: pointer to hardware structure + * @speed: pointer to link speed + * @link_up: true is link is up, false otherwise + * @autoneg_wait_to_complete: true when waiting for completion is needed + * + * Reads the links register to determine if link is up and the current speed + **/ +static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw, + ixgbe_link_speed *speed, + bool *link_up, + bool autoneg_wait_to_complete) +{ + u32 links_reg; + + if (!(hw->mbx.ops.check_for_rst(hw))) { + *link_up = false; + *speed = 0; + return -1; + } + + links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS); + + if (links_reg & IXGBE_LINKS_UP) + *link_up = true; + else + *link_up = false; + + if (links_reg & IXGBE_LINKS_SPEED) + *speed = IXGBE_LINK_SPEED_10GB_FULL; + else + *speed = IXGBE_LINK_SPEED_1GB_FULL; + + return 0; +} + +struct ixgbe_mac_operations ixgbevf_mac_ops = { + .init_hw = ixgbevf_init_hw_vf, + .reset_hw = ixgbevf_reset_hw_vf, + .start_hw = ixgbevf_start_hw_vf, + .get_mac_addr = ixgbevf_get_mac_addr_vf, + .stop_adapter = ixgbevf_stop_hw_vf, + .setup_link = ixgbevf_setup_mac_link_vf, + .check_link = ixgbevf_check_mac_link_vf, + .set_rar = ixgbevf_set_rar_vf, + .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf, + .set_vfta = ixgbevf_set_vfta_vf, +}; + +struct ixgbevf_info ixgbevf_vf_info = { + .mac = ixgbe_mac_82599_vf, + .mac_ops = &ixgbevf_mac_ops, +}; + diff --git a/drivers/net/ixgbevf/vf.h b/drivers/net/ixgbevf/vf.h new file mode 100644 index 000000000000..799600e92700 --- /dev/null +++ b/drivers/net/ixgbevf/vf.h @@ -0,0 +1,168 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef __IXGBE_VF_H__ +#define __IXGBE_VF_H__ + +#include +#include +#include +#include + +#include "defines.h" +#include "regs.h" +#include "mbx.h" + +struct ixgbe_hw; + +/* iterator type for walking multicast address lists */ +typedef u8* (*ixgbe_mc_addr_itr) (struct ixgbe_hw *hw, u8 **mc_addr_ptr, + u32 *vmdq); +struct ixgbe_mac_operations { + s32 (*init_hw)(struct ixgbe_hw *); + s32 (*reset_hw)(struct ixgbe_hw *); + s32 (*start_hw)(struct ixgbe_hw *); + s32 (*clear_hw_cntrs)(struct ixgbe_hw *); + enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *); + u32 (*get_supported_physical_layer)(struct ixgbe_hw *); + s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *); + s32 (*stop_adapter)(struct ixgbe_hw *); + s32 (*get_bus_info)(struct ixgbe_hw *); + + /* Link */ + s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool, bool); + s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); + s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, + bool *); + + /* RAR, Multicast, VLAN */ + s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32); + s32 (*init_rx_addrs)(struct ixgbe_hw *); + s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, + ixgbe_mc_addr_itr); + s32 (*enable_mc)(struct ixgbe_hw *); + s32 (*disable_mc)(struct ixgbe_hw *); + s32 (*clear_vfta)(struct ixgbe_hw *); + s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool); +}; + +enum ixgbe_mac_type { + ixgbe_mac_unknown = 0, + ixgbe_mac_82599_vf, + ixgbe_num_macs +}; + +struct ixgbe_mac_info { + struct ixgbe_mac_operations ops; + u8 addr[6]; + u8 perm_addr[6]; + + enum ixgbe_mac_type type; + + s32 mc_filter_type; + + bool get_link_status; + u32 max_tx_queues; + u32 max_rx_queues; + u32 max_msix_vectors; +}; + +struct ixgbe_mbx_operations { + s32 (*init_params)(struct ixgbe_hw *hw); + s32 (*read)(struct ixgbe_hw *, u32 *, u16); + s32 (*write)(struct ixgbe_hw *, u32 *, u16); + s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16); + s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16); + s32 (*check_for_msg)(struct ixgbe_hw *); + s32 (*check_for_ack)(struct ixgbe_hw *); + s32 (*check_for_rst)(struct ixgbe_hw *); +}; + +struct ixgbe_mbx_stats { + u32 msgs_tx; + u32 msgs_rx; + + u32 acks; + u32 reqs; + u32 rsts; +}; + +struct ixgbe_mbx_info { + struct ixgbe_mbx_operations ops; + struct ixgbe_mbx_stats stats; + u32 timeout; + u32 udelay; + u32 v2p_mailbox; + u16 size; +}; + +struct ixgbe_hw { + void *back; + + u8 __iomem *hw_addr; + u8 *flash_address; + unsigned long io_base; + + struct ixgbe_mac_info mac; + struct ixgbe_mbx_info mbx; + + u16 device_id; + u16 subsystem_vendor_id; + u16 subsystem_device_id; + u16 vendor_id; + + u8 revision_id; + bool adapter_stopped; +}; + +struct ixgbevf_hw_stats { + u64 base_vfgprc; + u64 base_vfgptc; + u64 base_vfgorc; + u64 base_vfgotc; + u64 base_vfmprc; + + u64 last_vfgprc; + u64 last_vfgptc; + u64 last_vfgorc; + u64 last_vfgotc; + u64 last_vfmprc; + + u64 vfgprc; + u64 vfgptc; + u64 vfgorc; + u64 vfgotc; + u64 vfmprc; +}; + +struct ixgbevf_info { + enum ixgbe_mac_type mac; + struct ixgbe_mac_operations *mac_ops; +}; + +#endif /* __IXGBE_VF_H__ */ + -- cgit v1.2.3 From cbf698dbba25741ee1b2e734a6dd4f3070a1706f Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:23:50 +0000 Subject: ixgbevf: Mailbox communication The 82599 virtual function device and the master 82599 physical function device implement a mailbox utility for communication between the devices using some SRAM scratch memory and a doorbell/answering mechanism enabled via interrupt and/or polling. This C module and accompanying header file implement the base functions for use of this feature. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/mbx.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbevf/mbx.h | 100 ++++++++++++++ 2 files changed, 441 insertions(+) create mode 100644 drivers/net/ixgbevf/mbx.c create mode 100644 drivers/net/ixgbevf/mbx.h diff --git a/drivers/net/ixgbevf/mbx.c b/drivers/net/ixgbevf/mbx.c new file mode 100644 index 000000000000..b8143501e6fc --- /dev/null +++ b/drivers/net/ixgbevf/mbx.c @@ -0,0 +1,341 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include "mbx.h" + +/** + * ixgbevf_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * + * returns 0 if it successfully received a message notification + **/ +static s32 ixgbevf_poll_for_msg(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + while (countdown && mbx->ops.check_for_msg(hw)) { + countdown--; + udelay(mbx->udelay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + + return countdown ? 0 : IXGBE_ERR_MBX; +} + +/** + * ixgbevf_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * + * returns 0 if it successfully received a message acknowledgement + **/ +static s32 ixgbevf_poll_for_ack(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + while (countdown && mbx->ops.check_for_ack(hw)) { + countdown--; + udelay(mbx->udelay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; + + return countdown ? 0 : IXGBE_ERR_MBX; +} + +/** + * ixgbevf_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully received a message notification and + * copied it into the receive buffer. + **/ +static s32 ixgbevf_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + ret_val = ixgbevf_poll_for_msg(hw); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size); + + return ret_val; +} + +/** + * ixgbevf_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +static s32 ixgbevf_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val; + + /* send msg */ + ret_val = mbx->ops.write(hw, msg, size); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = ixgbevf_poll_for_ack(hw); + + return ret_val; +} + +/** + * ixgbevf_read_v2p_mailbox - read v2p mailbox + * @hw: pointer to the HW structure + * + * This function is used to read the v2p mailbox without losing the read to + * clear status bits. + **/ +static u32 ixgbevf_read_v2p_mailbox(struct ixgbe_hw *hw) +{ + u32 v2p_mailbox = IXGBE_READ_REG(hw, IXGBE_VFMAILBOX); + + v2p_mailbox |= hw->mbx.v2p_mailbox; + hw->mbx.v2p_mailbox |= v2p_mailbox & IXGBE_VFMAILBOX_R2C_BITS; + + return v2p_mailbox; +} + +/** + * ixgbevf_check_for_bit_vf - Determine if a status bit was set + * @hw: pointer to the HW structure + * @mask: bitmask for bits to be tested and cleared + * + * This function is used to check for the read to clear bits within + * the V2P mailbox. + **/ +static s32 ixgbevf_check_for_bit_vf(struct ixgbe_hw *hw, u32 mask) +{ + u32 v2p_mailbox = ixgbevf_read_v2p_mailbox(hw); + s32 ret_val = IXGBE_ERR_MBX; + + if (v2p_mailbox & mask) + ret_val = 0; + + hw->mbx.v2p_mailbox &= ~mask; + + return ret_val; +} + +/** + * ixgbevf_check_for_msg_vf - checks to see if the PF has sent mail + * @hw: pointer to the HW structure + * + * returns 0 if the PF has set the Status bit or else ERR_MBX + **/ +static s32 ixgbevf_check_for_msg_vf(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFSTS)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; +} + +/** + * ixgbevf_check_for_ack_vf - checks to see if the PF has ACK'd + * @hw: pointer to the HW structure + * + * returns 0 if the PF has set the ACK bit or else ERR_MBX + **/ +static s32 ixgbevf_check_for_ack_vf(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, IXGBE_VFMAILBOX_PFACK)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; +} + +/** + * ixgbevf_check_for_rst_vf - checks to see if the PF has reset + * @hw: pointer to the HW structure + * + * returns true if the PF has set the reset done bit or else false + **/ +static s32 ixgbevf_check_for_rst_vf(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_ERR_MBX; + + if (!ixgbevf_check_for_bit_vf(hw, (IXGBE_VFMAILBOX_RSTD | + IXGBE_VFMAILBOX_RSTI))) { + ret_val = 0; + hw->mbx.stats.rsts++; + } + + return ret_val; +} + +/** + * ixgbevf_obtain_mbx_lock_vf - obtain mailbox lock + * @hw: pointer to the HW structure + * + * return 0 if we obtained the mailbox lock + **/ +static s32 ixgbevf_obtain_mbx_lock_vf(struct ixgbe_hw *hw) +{ + s32 ret_val = IXGBE_ERR_MBX; + + /* Take ownership of the buffer */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_VFU); + + /* reserve mailbox for vf use */ + if (ixgbevf_read_v2p_mailbox(hw) & IXGBE_VFMAILBOX_VFU) + ret_val = 0; + + return ret_val; +} + +/** + * ixgbevf_write_mbx_vf - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfully copied message into the buffer + **/ +static s32 ixgbevf_write_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) +{ + s32 ret_val; + u16 i; + + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbevf_obtain_mbx_lock_vf(hw); + if (ret_val) + goto out_no_write; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbevf_check_for_msg_vf(hw); + ixgbevf_check_for_ack_vf(hw); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_VFMBMEM, i, msg[i]); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + + /* Drop VFU and interrupt the PF to tell it a message has been sent */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_REQ); + +out_no_write: + return ret_val; +} + +/** + * ixgbevf_read_mbx_vf - Reads a message from the inbox intended for vf + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * + * returns 0 if it successfuly read message from buffer + **/ +static s32 ixgbevf_read_mbx_vf(struct ixgbe_hw *hw, u32 *msg, u16 size) +{ + s32 ret_val = 0; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbevf_obtain_mbx_lock_vf(hw); + if (ret_val) + goto out_no_read; + + /* copy the message from the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_VFMBMEM, i); + + /* Acknowledge receipt and release mailbox, then we're done */ + IXGBE_WRITE_REG(hw, IXGBE_VFMAILBOX, IXGBE_VFMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + +out_no_read: + return ret_val; +} + +/** + * ixgbevf_init_mbx_params_vf - set initial values for vf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for vf mailbox + */ +s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + /* start mailbox as timed out and let the reset_hw call set the timeout + * value to begin communications */ + mbx->timeout = 0; + mbx->udelay = IXGBE_VF_MBX_INIT_DELAY; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; + + return 0; +} + +struct ixgbe_mbx_operations ixgbevf_mbx_ops = { + .init_params = ixgbevf_init_mbx_params_vf, + .read = ixgbevf_read_mbx_vf, + .write = ixgbevf_write_mbx_vf, + .read_posted = ixgbevf_read_posted_mbx, + .write_posted = ixgbevf_write_posted_mbx, + .check_for_msg = ixgbevf_check_for_msg_vf, + .check_for_ack = ixgbevf_check_for_ack_vf, + .check_for_rst = ixgbevf_check_for_rst_vf, +}; + diff --git a/drivers/net/ixgbevf/mbx.h b/drivers/net/ixgbevf/mbx.h new file mode 100644 index 000000000000..1b0e0bf4c0f5 --- /dev/null +++ b/drivers/net/ixgbevf/mbx.h @@ -0,0 +1,100 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_MBX_H_ +#define _IXGBE_MBX_H_ + +#include "vf.h" + +#define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ +#define IXGBE_ERR_MBX -100 + +#define IXGBE_VFMAILBOX 0x002FC +#define IXGBE_VFMBMEM 0x00200 + +/* Define mailbox register bits */ +#define IXGBE_VFMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */ +#define IXGBE_VFMAILBOX_ACK 0x00000002 /* Ack PF message received */ +#define IXGBE_VFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define IXGBE_VFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define IXGBE_VFMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */ +#define IXGBE_VFMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */ +#define IXGBE_VFMAILBOX_RSTI 0x00000040 /* PF has reset indication */ +#define IXGBE_VFMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */ +#define IXGBE_VFMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */ + +#define IXGBE_PFMAILBOX(x) (0x04B00 + (4 * x)) +#define IXGBE_PFMBMEM(vfn) (0x13000 + (64 * vfn)) + +#define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */ +#define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ +#define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + +#define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ +#define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ +#define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ +#define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ + + +/* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the + * PF. The reverse is true if it is IXGBE_PF_*. + * Message ACK's are the value or'd with 0xF0000000 + */ +#define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with + * this are the ACK */ +#define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with + * this are the NACK */ +#define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still + * clear to send requests */ +#define IXGBE_VT_MSGINFO_SHIFT 16 +/* bits 23:16 are used for exra info for certain messages */ +#define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) + +#define IXGBE_VF_RESET 0x01 /* VF requests reset */ +#define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ +#define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ +#define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ +#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ + +/* length of permanent address message returned from PF */ +#define IXGBE_VF_PERMADDR_MSG_LEN 4 +/* word in permanent address message with the current multicast type */ +#define IXGBE_VF_MC_TYPE_WORD 3 + +#define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */ + +#define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ +#define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ + +/* forward declaration of the HW struct */ +struct ixgbe_hw; + +s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *); + +#endif /* _IXGBE_MBX_H_ */ -- cgit v1.2.3 From 92915f71201b43762fbe05dbfb1a1a0de9c8adb9 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:24:10 +0000 Subject: ixgbevf: Driver main and ethool interface module and main header These modules and header contain the Linux OS network interface code and core interrupt and network send/receive handlers. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/ethtool.c | 716 ++++++++ drivers/net/ixgbevf/ixgbevf.h | 318 ++++ drivers/net/ixgbevf/ixgbevf_main.c | 3571 ++++++++++++++++++++++++++++++++++++ 3 files changed, 4605 insertions(+) create mode 100644 drivers/net/ixgbevf/ethtool.c create mode 100644 drivers/net/ixgbevf/ixgbevf.h create mode 100644 drivers/net/ixgbevf/ixgbevf_main.c diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c new file mode 100644 index 000000000000..399be0c34c36 --- /dev/null +++ b/drivers/net/ixgbevf/ethtool.c @@ -0,0 +1,716 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* ethtool support for ixgbevf */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ixgbevf.h" + +#define IXGBE_ALL_RAR_ENTRIES 16 + +#ifdef ETHTOOL_GSTATS +struct ixgbe_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; + int base_stat_offset; +}; + +#define IXGBEVF_STAT(m, b) sizeof(((struct ixgbevf_adapter *)0)->m), \ + offsetof(struct ixgbevf_adapter, m), \ + offsetof(struct ixgbevf_adapter, b) +static struct ixgbe_stats ixgbe_gstrings_stats[] = { + {"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc)}, + {"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc)}, + {"rx_bytes", IXGBEVF_STAT(stats.vfgorc, stats.base_vfgorc)}, + {"tx_bytes", IXGBEVF_STAT(stats.vfgotc, stats.base_vfgotc)}, + {"tx_busy", IXGBEVF_STAT(tx_busy, zero_base)}, + {"multicast", IXGBEVF_STAT(stats.vfmprc, stats.base_vfmprc)}, + {"rx_csum_offload_good", IXGBEVF_STAT(hw_csum_rx_good, zero_base)}, + {"rx_csum_offload_errors", IXGBEVF_STAT(hw_csum_rx_error, zero_base)}, + {"tx_csum_offload_ctxt", IXGBEVF_STAT(hw_csum_tx_good, zero_base)}, + {"rx_header_split", IXGBEVF_STAT(rx_hdr_split, zero_base)}, +}; + +#define IXGBE_QUEUE_STATS_LEN 0 +#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats) + +#define IXGBEVF_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN) +#endif /* ETHTOOL_GSTATS */ +#ifdef ETHTOOL_TEST +static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { + "Register test (offline)", + "Link test (on/offline)" +}; +#define IXGBE_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) +#endif /* ETHTOOL_TEST */ + +static int ixgbevf_get_settings(struct net_device *netdev, + struct ethtool_cmd *ecmd) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u32 link_speed = 0; + bool link_up; + + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->transceiver = XCVR_DUMMY1; + ecmd->port = -1; + + hw->mac.ops.check_link(hw, &link_speed, &link_up, false); + + if (link_up) { + ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? + SPEED_10000 : SPEED_1000; + ecmd->duplex = DUPLEX_FULL; + } else { + ecmd->speed = -1; + ecmd->duplex = -1; + } + + return 0; +} + +static u32 ixgbevf_get_rx_csum(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + return adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED; +} + +static int ixgbevf_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + if (data) + adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + else + adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; + + if (netif_running(netdev)) { + if (!adapter->dev_closed) + ixgbevf_reinit_locked(adapter); + } else { + ixgbevf_reset(adapter); + } + + return 0; +} + +static int ixgbevf_set_tso(struct net_device *netdev, u32 data) +{ + if (data) { + netdev->features |= NETIF_F_TSO; + netdev->features |= NETIF_F_TSO6; + } else { + netif_tx_stop_all_queues(netdev); + netdev->features &= ~NETIF_F_TSO; + netdev->features &= ~NETIF_F_TSO6; + netif_tx_start_all_queues(netdev); + } + return 0; +} + +static u32 ixgbevf_get_msglevel(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + return adapter->msg_enable; +} + +static void ixgbevf_set_msglevel(struct net_device *netdev, u32 data) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + adapter->msg_enable = data; +} + +#define IXGBE_GET_STAT(_A_, _R_) (_A_->stats._R_) + +static char *ixgbevf_reg_names[] = { + "IXGBE_VFCTRL", + "IXGBE_VFSTATUS", + "IXGBE_VFLINKS", + "IXGBE_VFRXMEMWRAP", + "IXGBE_VFRTIMER", + "IXGBE_VTEICR", + "IXGBE_VTEICS", + "IXGBE_VTEIMS", + "IXGBE_VTEIMC", + "IXGBE_VTEIAC", + "IXGBE_VTEIAM", + "IXGBE_VTEITR", + "IXGBE_VTIVAR", + "IXGBE_VTIVAR_MISC", + "IXGBE_VFRDBAL0", + "IXGBE_VFRDBAL1", + "IXGBE_VFRDBAH0", + "IXGBE_VFRDBAH1", + "IXGBE_VFRDLEN0", + "IXGBE_VFRDLEN1", + "IXGBE_VFRDH0", + "IXGBE_VFRDH1", + "IXGBE_VFRDT0", + "IXGBE_VFRDT1", + "IXGBE_VFRXDCTL0", + "IXGBE_VFRXDCTL1", + "IXGBE_VFSRRCTL0", + "IXGBE_VFSRRCTL1", + "IXGBE_VFPSRTYPE", + "IXGBE_VFTDBAL0", + "IXGBE_VFTDBAL1", + "IXGBE_VFTDBAH0", + "IXGBE_VFTDBAH1", + "IXGBE_VFTDLEN0", + "IXGBE_VFTDLEN1", + "IXGBE_VFTDH0", + "IXGBE_VFTDH1", + "IXGBE_VFTDT0", + "IXGBE_VFTDT1", + "IXGBE_VFTXDCTL0", + "IXGBE_VFTXDCTL1", + "IXGBE_VFTDWBAL0", + "IXGBE_VFTDWBAL1", + "IXGBE_VFTDWBAH0", + "IXGBE_VFTDWBAH1" +}; + + +static int ixgbevf_get_regs_len(struct net_device *netdev) +{ + return (ARRAY_SIZE(ixgbevf_reg_names)) * sizeof(u32); +} + +static void ixgbevf_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, + void *p) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u32 *regs_buff = p; + u32 regs_len = ixgbevf_get_regs_len(netdev); + u8 i; + + memset(p, 0, regs_len); + + regs->version = (1 << 24) | hw->revision_id << 16 | hw->device_id; + + /* General Registers */ + regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); + regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); + regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); + regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); + regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFRTIMER); + + /* Interrupt */ + /* don't read EICR because it can clear interrupt causes, instead + * read EICS which is a shadow but doesn't clear EICR */ + regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); + regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); + regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); + regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); + regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); + regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); + regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); + regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); + regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); + + /* Receive DMA */ + for (i = 0; i < 2; i++) + regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); + for (i = 0; i < 2; i++) + regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); + for (i = 0; i < 2; i++) + regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); + for (i = 0; i < 2; i++) + regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); + for (i = 0; i < 2; i++) + regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); + for (i = 0; i < 2; i++) + regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); + for (i = 0; i < 2; i++) + regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); + + /* Receive */ + regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); + + /* Transmit */ + for (i = 0; i < 2; i++) + regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); + for (i = 0; i < 2; i++) + regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); + for (i = 0; i < 2; i++) + regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); + for (i = 0; i < 2; i++) + regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); + for (i = 0; i < 2; i++) + regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); + for (i = 0; i < 2; i++) + regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); + for (i = 0; i < 2; i++) + regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); + for (i = 0; i < 2; i++) + regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); + + for (i = 0; i < ARRAY_SIZE(ixgbevf_reg_names); i++) + hw_dbg(hw, "%s\t%8.8x\n", ixgbevf_reg_names[i], regs_buff[i]); +} + +static void ixgbevf_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + strlcpy(drvinfo->driver, ixgbevf_driver_name, 32); + strlcpy(drvinfo->version, ixgbevf_driver_version, 32); + + strlcpy(drvinfo->fw_version, "N/A", 4); + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); +} + +static void ixgbevf_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbevf_ring *tx_ring = adapter->tx_ring; + struct ixgbevf_ring *rx_ring = adapter->rx_ring; + + ring->rx_max_pending = IXGBEVF_MAX_RXD; + ring->tx_max_pending = IXGBEVF_MAX_TXD; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->rx_pending = rx_ring->count; + ring->tx_pending = tx_ring->count; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; +} + +static int ixgbevf_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; + int i, err; + u32 new_rx_count, new_tx_count; + bool need_tx_update = false; + bool need_rx_update = false; + + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) + return -EINVAL; + + new_rx_count = max(ring->rx_pending, (u32)IXGBEVF_MIN_RXD); + new_rx_count = min(new_rx_count, (u32)IXGBEVF_MAX_RXD); + new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); + + new_tx_count = max(ring->tx_pending, (u32)IXGBEVF_MIN_TXD); + new_tx_count = min(new_tx_count, (u32)IXGBEVF_MAX_TXD); + new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); + + if ((new_tx_count == adapter->tx_ring->count) && + (new_rx_count == adapter->rx_ring->count)) { + /* nothing to do */ + return 0; + } + + while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) + msleep(1); + + if (new_tx_count != adapter->tx_ring_count) { + tx_ring = kcalloc(adapter->num_tx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if (!tx_ring) { + err = -ENOMEM; + goto err_setup; + } + memcpy(tx_ring, adapter->tx_ring, + adapter->num_tx_queues * sizeof(struct ixgbevf_ring)); + for (i = 0; i < adapter->num_tx_queues; i++) { + tx_ring[i].count = new_tx_count; + err = ixgbevf_setup_tx_resources(adapter, + &tx_ring[i]); + if (err) { + while (i) { + i--; + ixgbevf_free_tx_resources(adapter, + &tx_ring[i]); + } + kfree(tx_ring); + goto err_setup; + } + tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; + } + need_tx_update = true; + } + + if (new_rx_count != adapter->rx_ring_count) { + rx_ring = kcalloc(adapter->num_rx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if ((!rx_ring) && (need_tx_update)) { + err = -ENOMEM; + goto err_rx_setup; + } + memcpy(rx_ring, adapter->rx_ring, + adapter->num_rx_queues * sizeof(struct ixgbevf_ring)); + for (i = 0; i < adapter->num_rx_queues; i++) { + rx_ring[i].count = new_rx_count; + err = ixgbevf_setup_rx_resources(adapter, + &rx_ring[i]); + if (err) { + while (i) { + i--; + ixgbevf_free_rx_resources(adapter, + &rx_ring[i]); + } + kfree(rx_ring); + goto err_rx_setup; + } + rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; + } + need_rx_update = true; + } + +err_rx_setup: + /* if rings need to be updated, here's the place to do it in one shot */ + if (need_tx_update || need_rx_update) { + if (netif_running(netdev)) + ixgbevf_down(adapter); + } + + /* tx */ + if (need_tx_update) { + kfree(adapter->tx_ring); + adapter->tx_ring = tx_ring; + tx_ring = NULL; + adapter->tx_ring_count = new_tx_count; + } + + /* rx */ + if (need_rx_update) { + kfree(adapter->rx_ring); + adapter->rx_ring = rx_ring; + rx_ring = NULL; + adapter->rx_ring_count = new_rx_count; + } + + /* success! */ + err = 0; + if (netif_running(netdev)) + ixgbevf_up(adapter); + +err_setup: + clear_bit(__IXGBEVF_RESETTING, &adapter->state); + return err; +} + +static int ixgbevf_get_sset_count(struct net_device *dev, int stringset) +{ + switch (stringset) { + case ETH_SS_TEST: + return IXGBE_TEST_LEN; + case ETH_SS_STATS: + return IXGBE_GLOBAL_STATS_LEN; + default: + return -EINVAL; + } +} + +static void ixgbevf_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + int i; + + ixgbevf_update_stats(adapter); + for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { + char *p = (char *)adapter + + ixgbe_gstrings_stats[i].stat_offset; + char *b = (char *)adapter + + ixgbe_gstrings_stats[i].base_stat_offset; + data[i] = ((ixgbe_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p) - + ((ixgbe_gstrings_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)b : *(u32 *)b); + } +} + +static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) +{ + char *p = (char *)data; + int i; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *ixgbe_gstrings_test, + IXGBE_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + for (i = 0; i < IXGBE_GLOBAL_STATS_LEN; i++) { + memcpy(p, ixgbe_gstrings_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + break; + } +} + +static int ixgbevf_link_test(struct ixgbevf_adapter *adapter, u64 *data) +{ + struct ixgbe_hw *hw = &adapter->hw; + bool link_up; + u32 link_speed = 0; + *data = 0; + + hw->mac.ops.check_link(hw, &link_speed, &link_up, true); + if (!link_up) + *data = 1; + + return *data; +} + +/* ethtool register test data */ +struct ixgbevf_reg_test { + u16 reg; + u8 array_len; + u8 test_type; + u32 mask; + u32 write; +}; + +/* In the hardware, registers are laid out either singly, in arrays + * spaced 0x40 bytes apart, or in contiguous tables. We assume + * most tests take place on arrays or single registers (handled + * as a single-element array) and special-case the tables. + * Table tests are always pattern tests. + * + * We also make provision for some required setup steps by specifying + * registers to be written without any read-back testing. + */ + +#define PATTERN_TEST 1 +#define SET_READ_TEST 2 +#define WRITE_NO_TEST 3 +#define TABLE32_TEST 4 +#define TABLE64_TEST_LO 5 +#define TABLE64_TEST_HI 6 + +/* default VF register test */ +static struct ixgbevf_reg_test reg_test_vf[] = { + { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, + { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, + { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, + { IXGBE_VFRDT(0), 2, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, + { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, 0 }, + { IXGBE_VFTDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, + { IXGBE_VFTDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, + { IXGBE_VFTDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, + { 0, 0, 0, 0 } +}; + +#define REG_PATTERN_TEST(R, M, W) \ +{ \ + u32 pat, val, before; \ + const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ + for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { \ + before = readl(adapter->hw.hw_addr + R); \ + writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if (val != (_test[pat] & W & M)) { \ + hw_dbg(&adapter->hw, \ + "pattern test reg %04X failed: got " \ + "0x%08X expected 0x%08X\n", \ + R, val, (_test[pat] & W & M)); \ + *data = R; \ + writel(before, adapter->hw.hw_addr + R); \ + return 1; \ + } \ + writel(before, adapter->hw.hw_addr + R); \ + } \ +} + +#define REG_SET_AND_CHECK(R, M, W) \ +{ \ + u32 val, before; \ + before = readl(adapter->hw.hw_addr + R); \ + writel((W & M), (adapter->hw.hw_addr + R)); \ + val = readl(adapter->hw.hw_addr + R); \ + if ((W & M) != (val & M)) { \ + printk(KERN_ERR "set/check reg %04X test failed: got 0x%08X " \ + "expected 0x%08X\n", R, (val & M), (W & M)); \ + *data = R; \ + writel(before, (adapter->hw.hw_addr + R)); \ + return 1; \ + } \ + writel(before, (adapter->hw.hw_addr + R)); \ +} + +static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) +{ + struct ixgbevf_reg_test *test; + u32 i; + + test = reg_test_vf; + + /* + * Perform the register test, looping through the test table + * until we either fail or reach the null entry. + */ + while (test->reg) { + for (i = 0; i < test->array_len; i++) { + switch (test->test_type) { + case PATTERN_TEST: + REG_PATTERN_TEST(test->reg + (i * 0x40), + test->mask, + test->write); + break; + case SET_READ_TEST: + REG_SET_AND_CHECK(test->reg + (i * 0x40), + test->mask, + test->write); + break; + case WRITE_NO_TEST: + writel(test->write, + (adapter->hw.hw_addr + test->reg) + + (i * 0x40)); + break; + case TABLE32_TEST: + REG_PATTERN_TEST(test->reg + (i * 4), + test->mask, + test->write); + break; + case TABLE64_TEST_LO: + REG_PATTERN_TEST(test->reg + (i * 8), + test->mask, + test->write); + break; + case TABLE64_TEST_HI: + REG_PATTERN_TEST((test->reg + 4) + (i * 8), + test->mask, + test->write); + break; + } + } + test++; + } + + *data = 0; + return *data; +} + +static void ixgbevf_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + bool if_running = netif_running(netdev); + + set_bit(__IXGBEVF_TESTING, &adapter->state); + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + /* Offline tests */ + + hw_dbg(&adapter->hw, "offline testing starting\n"); + + /* Link test performed before hardware reset so autoneg doesn't + * interfere with test result */ + if (ixgbevf_link_test(adapter, &data[1])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (if_running) + /* indicate we're in test mode */ + dev_close(netdev); + else + ixgbevf_reset(adapter); + + hw_dbg(&adapter->hw, "register testing starting\n"); + if (ixgbevf_reg_test(adapter, &data[0])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + ixgbevf_reset(adapter); + + clear_bit(__IXGBEVF_TESTING, &adapter->state); + if (if_running) + dev_open(netdev); + } else { + hw_dbg(&adapter->hw, "online testing starting\n"); + /* Online tests */ + if (ixgbevf_link_test(adapter, &data[1])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* Online tests aren't run; pass by default */ + data[0] = 0; + + clear_bit(__IXGBEVF_TESTING, &adapter->state); + } + msleep_interruptible(4 * 1000); +} + +static int ixgbevf_nway_reset(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + if (netif_running(netdev)) { + if (!adapter->dev_closed) + ixgbevf_reinit_locked(adapter); + } + + return 0; +} + +static struct ethtool_ops ixgbevf_ethtool_ops = { + .get_settings = ixgbevf_get_settings, + .get_drvinfo = ixgbevf_get_drvinfo, + .get_regs_len = ixgbevf_get_regs_len, + .get_regs = ixgbevf_get_regs, + .nway_reset = ixgbevf_nway_reset, + .get_link = ethtool_op_get_link, + .get_ringparam = ixgbevf_get_ringparam, + .set_ringparam = ixgbevf_set_ringparam, + .get_rx_csum = ixgbevf_get_rx_csum, + .set_rx_csum = ixgbevf_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_ipv6_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_msglevel = ixgbevf_get_msglevel, + .set_msglevel = ixgbevf_set_msglevel, + .get_tso = ethtool_op_get_tso, + .set_tso = ixgbevf_set_tso, + .self_test = ixgbevf_diag_test, + .get_sset_count = ixgbevf_get_sset_count, + .get_strings = ixgbevf_get_strings, + .get_ethtool_stats = ixgbevf_get_ethtool_stats, +}; + +void ixgbevf_set_ethtool_ops(struct net_device *netdev) +{ + SET_ETHTOOL_OPS(netdev, &ixgbevf_ethtool_ops); +} diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h new file mode 100644 index 000000000000..f7015efbff05 --- /dev/null +++ b/drivers/net/ixgbevf/ixgbevf.h @@ -0,0 +1,318 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBEVF_H_ +#define _IXGBEVF_H_ + +#include +#include +#include +#include + +#include "vf.h" + +/* wrapper around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer */ +struct ixgbevf_tx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + unsigned long time_stamp; + u16 length; + u16 next_to_watch; + u16 mapped_as_page; +}; + +struct ixgbevf_rx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + struct page *page; + dma_addr_t page_dma; + unsigned int page_offset; +}; + +struct ixgbevf_ring { + struct ixgbevf_adapter *adapter; /* backlink */ + void *desc; /* descriptor ring memory */ + dma_addr_t dma; /* phys. address of descriptor ring */ + unsigned int size; /* length in bytes */ + unsigned int count; /* amount of descriptors */ + unsigned int next_to_use; + unsigned int next_to_clean; + + int queue_index; /* needed for multiqueue queue management */ + union { + struct ixgbevf_tx_buffer *tx_buffer_info; + struct ixgbevf_rx_buffer *rx_buffer_info; + }; + + u16 head; + u16 tail; + + unsigned int total_bytes; + unsigned int total_packets; + + u16 reg_idx; /* holds the special value that gets the hardware register + * offset associated with this ring, which is different + * for DCB and RSS modes */ + +#if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) + /* cpu for tx queue */ + int cpu; +#endif + + u64 v_idx; /* maps directly to the index for this ring in the hardware + * vector array, can also be used for finding the bit in EICR + * and friends that represents the vector for this ring */ + + u16 work_limit; /* max work per interrupt */ + u16 rx_buf_len; +}; + +enum ixgbevf_ring_f_enum { + RING_F_NONE = 0, + RING_F_ARRAY_SIZE /* must be last in enum set */ +}; + +struct ixgbevf_ring_feature { + int indices; + int mask; +}; + +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define IXGBEVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */ + +#define MAX_RX_QUEUES 1 +#define MAX_TX_QUEUES 1 + +#define IXGBEVF_DEFAULT_TXD 1024 +#define IXGBEVF_DEFAULT_RXD 512 +#define IXGBEVF_MAX_TXD 4096 +#define IXGBEVF_MIN_TXD 64 +#define IXGBEVF_MAX_RXD 4096 +#define IXGBEVF_MIN_RXD 64 + +/* Supported Rx Buffer Sizes */ +#define IXGBEVF_RXBUFFER_64 64 /* Used for packet split */ +#define IXGBEVF_RXBUFFER_128 128 /* Used for packet split */ +#define IXGBEVF_RXBUFFER_256 256 /* Used for packet split */ +#define IXGBEVF_RXBUFFER_2048 2048 +#define IXGBEVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */ + +#define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256 + +#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + +#define IXGBE_TX_FLAGS_CSUM (u32)(1) +#define IXGBE_TX_FLAGS_VLAN (u32)(1 << 1) +#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2) +#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3) +#define IXGBE_TX_FLAGS_FCOE (u32)(1 << 4) +#define IXGBE_TX_FLAGS_FSO (u32)(1 << 5) +#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000 +#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000 +#define IXGBE_TX_FLAGS_VLAN_SHIFT 16 + +/* MAX_MSIX_Q_VECTORS of these are allocated, + * but we only use one per queue-specific vector. + */ +struct ixgbevf_q_vector { + struct ixgbevf_adapter *adapter; + struct napi_struct napi; + DECLARE_BITMAP(rxr_idx, MAX_RX_QUEUES); /* Rx ring indices */ + DECLARE_BITMAP(txr_idx, MAX_TX_QUEUES); /* Tx ring indices */ + u8 rxr_count; /* Rx ring count assigned to this vector */ + u8 txr_count; /* Tx ring count assigned to this vector */ + u8 tx_itr; + u8 rx_itr; + u32 eitr; + int v_idx; /* vector index in list */ +}; + +/* Helper macros to switch between ints/sec and what the register uses. + * And yes, it's the same math going both ways. The lowest value + * supported by all of the ixgbe hardware is 8. + */ +#define EITR_INTS_PER_SEC_TO_REG(_eitr) \ + ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8) +#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG + +#define IXGBE_DESC_UNUSED(R) \ + ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ + (R)->next_to_clean - (R)->next_to_use - 1) + +#define IXGBE_RX_DESC_ADV(R, i) \ + (&(((union ixgbe_adv_rx_desc *)((R).desc))[i])) +#define IXGBE_TX_DESC_ADV(R, i) \ + (&(((union ixgbe_adv_tx_desc *)((R).desc))[i])) +#define IXGBE_TX_CTXTDESC_ADV(R, i) \ + (&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i])) + +#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128 + +#define OTHER_VECTOR 1 +#define NON_Q_VECTORS (OTHER_VECTOR) + +#define MAX_MSIX_Q_VECTORS 2 +#define MAX_MSIX_COUNT 2 + +#define MIN_MSIX_Q_VECTORS 2 +#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NON_Q_VECTORS) + +/* board specific private data structure */ +struct ixgbevf_adapter { + struct timer_list watchdog_timer; +#ifdef NETIF_F_HW_VLAN_TX + struct vlan_group *vlgrp; +#endif + u16 bd_number; + struct work_struct reset_task; + struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; + char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; + + /* Interrupt Throttle Rate */ + u32 itr_setting; + u16 eitr_low; + u16 eitr_high; + + /* TX */ + struct ixgbevf_ring *tx_ring; /* One per active queue */ + int num_tx_queues; + u64 restart_queue; + u64 hw_csum_tx_good; + u64 lsc_int; + u64 hw_tso_ctxt; + u64 hw_tso6_ctxt; + u32 tx_timeout_count; + bool detect_tx_hung; + + /* RX */ + struct ixgbevf_ring *rx_ring; /* One per active queue */ + int num_rx_queues; + int num_rx_pools; /* == num_rx_queues in 82598 */ + int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */ + u64 hw_csum_rx_error; + u64 hw_rx_no_dma_resources; + u64 hw_csum_rx_good; + u64 non_eop_descs; + int num_msix_vectors; + int max_msix_q_vectors; /* true count of q_vectors for device */ + struct ixgbevf_ring_feature ring_feature[RING_F_ARRAY_SIZE]; + struct msix_entry *msix_entries; + + u64 rx_hdr_split; + u32 alloc_rx_page_failed; + u32 alloc_rx_buff_failed; + + /* Some features need tri-state capability, + * thus the additional *_CAPABLE flags. + */ + u32 flags; +#define IXGBE_FLAG_RX_CSUM_ENABLED (u32)(1) +#define IXGBE_FLAG_RX_1BUF_CAPABLE (u32)(1 << 1) +#define IXGBE_FLAG_RX_PS_CAPABLE (u32)(1 << 2) +#define IXGBE_FLAG_RX_PS_ENABLED (u32)(1 << 3) +#define IXGBE_FLAG_IN_NETPOLL (u32)(1 << 4) +#define IXGBE_FLAG_IMIR_ENABLED (u32)(1 << 5) +#define IXGBE_FLAG_MQ_CAPABLE (u32)(1 << 6) +#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 7) +#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 8) + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; + + /* structs defined in ixgbe_vf.h */ + struct ixgbe_hw hw; + u16 msg_enable; + struct ixgbevf_hw_stats stats; + u64 zero_base; + /* Interrupt Throttle Rate */ + u32 eitr_param; + + unsigned long state; + u32 *config_space; + u64 tx_busy; + unsigned int tx_ring_count; + unsigned int rx_ring_count; + + u32 link_speed; + bool link_up; + unsigned long link_check_timeout; + + struct work_struct watchdog_task; + bool netdev_registered; + bool dev_closed; +}; + +enum ixbgevf_state_t { + __IXGBEVF_TESTING, + __IXGBEVF_RESETTING, + __IXGBEVF_DOWN +}; + +enum ixgbevf_boards { + board_82599_vf, +}; + +extern struct ixgbevf_info ixgbevf_vf_info; +extern struct ixgbe_mac_operations ixgbevf_mbx_ops; + +/* needed by ethtool.c */ +extern char ixgbevf_driver_name[]; +extern const char ixgbevf_driver_version[]; + +extern int ixgbevf_up(struct ixgbevf_adapter *adapter); +extern void ixgbevf_down(struct ixgbevf_adapter *adapter); +extern void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter); +extern void ixgbevf_reset(struct ixgbevf_adapter *adapter); +extern void ixgbevf_set_ethtool_ops(struct net_device *netdev); +extern int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *, + struct ixgbevf_ring *); +extern int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *, + struct ixgbevf_ring *); +extern void ixgbevf_free_rx_resources(struct ixgbevf_adapter *, + struct ixgbevf_ring *); +extern void ixgbevf_free_tx_resources(struct ixgbevf_adapter *, + struct ixgbevf_ring *); +extern void ixgbevf_update_stats(struct ixgbevf_adapter *adapter); + +#ifdef ETHTOOL_OPS_COMPAT +extern int ethtool_ioctl(struct ifreq *ifr); + +#endif +extern void ixgbe_napi_add_all(struct ixgbevf_adapter *adapter); +extern void ixgbe_napi_del_all(struct ixgbevf_adapter *adapter); + +#ifdef DEBUG +extern char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw); +#define hw_dbg(hw, format, arg...) \ + printk(KERN_DEBUG "%s: " format, ixgbevf_get_hw_dev_name(hw), ##arg) +#else +#define hw_dbg(hw, format, arg...) do {} while (0) +#endif + +#endif /* _IXGBEVF_H_ */ diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c new file mode 100644 index 000000000000..39544afdc57f --- /dev/null +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -0,0 +1,3571 @@ +/******************************************************************************* + + Intel 82599 Virtual Function driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +/****************************************************************************** + Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ixgbevf.h" + +char ixgbevf_driver_name[] = "ixgbevf"; +static const char ixgbevf_driver_string[] = + "Intel(R) 82599 Virtual Function"; + +#define DRV_VERSION "1.0.0-k0" +const char ixgbevf_driver_version[] = DRV_VERSION; +static char ixgbevf_copyright[] = "Copyright (c) 2009 Intel Corporation."; + +static const struct ixgbevf_info *ixgbevf_info_tbl[] = { + [board_82599_vf] = &ixgbevf_vf_info, +}; + +/* ixgbevf_pci_tbl - PCI Device ID Table + * + * Wildcard entries (PCI_ANY_ID) should come last + * Last entry must be all 0s + * + * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, + * Class, Class Mask, private data (not used) } + */ +static struct pci_device_id ixgbevf_pci_tbl[] = { + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), + board_82599_vf}, + + /* required last entry */ + {0, } +}; +MODULE_DEVICE_TABLE(pci, ixgbevf_pci_tbl); + +MODULE_AUTHOR("Intel Corporation, "); +MODULE_DESCRIPTION("Intel(R) 82599 Virtual Function Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +#define DEFAULT_DEBUG_LEVEL_SHIFT 3 + +/* forward decls */ +static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector); +static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx, + u32 itr_reg); + +static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw, + struct ixgbevf_ring *rx_ring, + u32 val) +{ + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + IXGBE_WRITE_REG(hw, IXGBE_VFRDT(rx_ring->reg_idx), val); +} + +/* + * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors + * @adapter: pointer to adapter struct + * @direction: 0 for Rx, 1 for Tx, -1 for other causes + * @queue: queue to map the corresponding interrupt to + * @msix_vector: the vector to map to the corresponding queue + * + */ +static void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction, + u8 queue, u8 msix_vector) +{ + u32 ivar, index; + struct ixgbe_hw *hw = &adapter->hw; + if (direction == -1) { + /* other causes */ + msix_vector |= IXGBE_IVAR_ALLOC_VAL; + ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); + ivar &= ~0xFF; + ivar |= msix_vector; + IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar); + } else { + /* tx or rx causes */ + msix_vector |= IXGBE_IVAR_ALLOC_VAL; + index = ((16 * (queue & 1)) + (8 * direction)); + ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(queue >> 1)); + ivar &= ~(0xFF << index); + ivar |= (msix_vector << index); + IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(queue >> 1), ivar); + } +} + +static void ixgbevf_unmap_and_free_tx_resource(struct ixgbevf_adapter *adapter, + struct ixgbevf_tx_buffer + *tx_buffer_info) +{ + if (tx_buffer_info->dma) { + if (tx_buffer_info->mapped_as_page) + pci_unmap_page(adapter->pdev, + tx_buffer_info->dma, + tx_buffer_info->length, + PCI_DMA_TODEVICE); + else + pci_unmap_single(adapter->pdev, + tx_buffer_info->dma, + tx_buffer_info->length, + PCI_DMA_TODEVICE); + tx_buffer_info->dma = 0; + } + if (tx_buffer_info->skb) { + dev_kfree_skb_any(tx_buffer_info->skb); + tx_buffer_info->skb = NULL; + } + tx_buffer_info->time_stamp = 0; + /* tx_buffer_info must be completely set up in the transmit path */ +} + +static inline bool ixgbevf_check_tx_hang(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring, + unsigned int eop) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 head, tail; + + /* Detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of eop */ + head = readl(hw->hw_addr + tx_ring->head); + tail = readl(hw->hw_addr + tx_ring->tail); + adapter->detect_tx_hung = false; + if ((head != tail) && + tx_ring->tx_buffer_info[eop].time_stamp && + time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ)) { + /* detected Tx unit hang */ + union ixgbe_adv_tx_desc *tx_desc; + tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + printk(KERN_ERR "Detected Tx Unit Hang\n" + " Tx Queue <%d>\n" + " TDH, TDT <%x>, <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "tx_buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " jiffies <%lx>\n", + tx_ring->queue_index, + head, tail, + tx_ring->next_to_use, eop, + tx_ring->tx_buffer_info[eop].time_stamp, jiffies); + return true; + } + + return false; +} + +#define IXGBE_MAX_TXD_PWR 14 +#define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) + +/* Tx Descriptors needed, worst case */ +#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ + (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) +#ifdef MAX_SKB_FRAGS +#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ + MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ +#else +#define DESC_NEEDED TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) +#endif + +static void ixgbevf_tx_timeout(struct net_device *netdev); + +/** + * ixgbevf_clean_tx_irq - Reclaim resources after transmit completes + * @adapter: board private structure + * @tx_ring: tx ring to clean + **/ +static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring) +{ + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + union ixgbe_adv_tx_desc *tx_desc, *eop_desc; + struct ixgbevf_tx_buffer *tx_buffer_info; + unsigned int i, eop, count = 0; + unsigned int total_bytes = 0, total_packets = 0; + + i = tx_ring->next_to_clean; + eop = tx_ring->tx_buffer_info[i].next_to_watch; + eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + + while ((eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) && + (count < tx_ring->work_limit)) { + bool cleaned = false; + for ( ; !cleaned; count++) { + struct sk_buff *skb; + tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + cleaned = (i == eop); + skb = tx_buffer_info->skb; + + if (cleaned && skb) { + unsigned int segs, bytecount; + + /* gso_segs is currently only valid for tcp */ + segs = skb_shinfo(skb)->gso_segs ?: 1; + /* multiply data chunks by size of headers */ + bytecount = ((segs - 1) * skb_headlen(skb)) + + skb->len; + total_packets += segs; + total_bytes += bytecount; + } + + ixgbevf_unmap_and_free_tx_resource(adapter, + tx_buffer_info); + + tx_desc->wb.status = 0; + + i++; + if (i == tx_ring->count) + i = 0; + } + + eop = tx_ring->tx_buffer_info[i].next_to_watch; + eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); + } + + tx_ring->next_to_clean = i; + +#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) + if (unlikely(count && netif_carrier_ok(netdev) && + (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) { + /* Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ + smp_mb(); +#ifdef HAVE_TX_MQ + if (__netif_subqueue_stopped(netdev, tx_ring->queue_index) && + !test_bit(__IXGBEVF_DOWN, &adapter->state)) { + netif_wake_subqueue(netdev, tx_ring->queue_index); + ++adapter->restart_queue; + } +#else + if (netif_queue_stopped(netdev) && + !test_bit(__IXGBEVF_DOWN, &adapter->state)) { + netif_wake_queue(netdev); + ++adapter->restart_queue; + } +#endif + } + + if (adapter->detect_tx_hung) { + if (ixgbevf_check_tx_hang(adapter, tx_ring, i)) { + /* schedule immediate reset if we believe we hung */ + printk(KERN_INFO + "tx hang %d detected, resetting adapter\n", + adapter->tx_timeout_count + 1); + ixgbevf_tx_timeout(adapter->netdev); + } + } + + /* re-arm the interrupt */ + if ((count >= tx_ring->work_limit) && + (!test_bit(__IXGBEVF_DOWN, &adapter->state))) { + IXGBE_WRITE_REG(hw, IXGBE_VTEICS, tx_ring->v_idx); + } + + tx_ring->total_bytes += total_bytes; + tx_ring->total_packets += total_packets; + + adapter->net_stats.tx_bytes += total_bytes; + adapter->net_stats.tx_packets += total_packets; + + return (count < tx_ring->work_limit); +} + +/** + * ixgbevf_receive_skb - Send a completed packet up the stack + * @q_vector: structure containing interrupt and ring information + * @skb: packet to send up + * @status: hardware indication of status of receive + * @rx_ring: rx descriptor ring (for a specific queue) to setup + * @rx_desc: rx descriptor + **/ +static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector, + struct sk_buff *skb, u8 status, + struct ixgbevf_ring *ring, + union ixgbe_adv_rx_desc *rx_desc) +{ + struct ixgbevf_adapter *adapter = q_vector->adapter; + bool is_vlan = (status & IXGBE_RXD_STAT_VP); + u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan); + int ret; + + if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) { + if (adapter->vlgrp && is_vlan) + vlan_gro_receive(&q_vector->napi, + adapter->vlgrp, + tag, skb); + else + napi_gro_receive(&q_vector->napi, skb); + } else { + if (adapter->vlgrp && is_vlan) + ret = vlan_hwaccel_rx(skb, adapter->vlgrp, tag); + else + ret = netif_rx(skb); + } +} + +/** + * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum + * @adapter: address of board private structure + * @status_err: hardware indication of status of receive + * @skb: skb currently being received and modified + **/ +static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter, + u32 status_err, struct sk_buff *skb) +{ + skb->ip_summed = CHECKSUM_NONE; + + /* Rx csum disabled */ + if (!(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) + return; + + /* if IP and error */ + if ((status_err & IXGBE_RXD_STAT_IPCS) && + (status_err & IXGBE_RXDADV_ERR_IPE)) { + adapter->hw_csum_rx_error++; + return; + } + + if (!(status_err & IXGBE_RXD_STAT_L4CS)) + return; + + if (status_err & IXGBE_RXDADV_ERR_TCPE) { + adapter->hw_csum_rx_error++; + return; + } + + /* It must be a TCP or UDP packet with a valid checksum */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_rx_good++; +} + +/** + * ixgbevf_alloc_rx_buffers - Replace used receive buffers; packet split + * @adapter: address of board private structure + **/ +static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *rx_ring, + int cleaned_count) +{ + struct pci_dev *pdev = adapter->pdev; + union ixgbe_adv_rx_desc *rx_desc; + struct ixgbevf_rx_buffer *bi; + struct sk_buff *skb; + unsigned int i; + unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN; + + i = rx_ring->next_to_use; + bi = &rx_ring->rx_buffer_info[i]; + + while (cleaned_count--) { + rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + + if (!bi->page_dma && + (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) { + if (!bi->page) { + bi->page = netdev_alloc_page(adapter->netdev); + if (!bi->page) { + adapter->alloc_rx_page_failed++; + goto no_buffers; + } + bi->page_offset = 0; + } else { + /* use a half page if we're re-using */ + bi->page_offset ^= (PAGE_SIZE / 2); + } + + bi->page_dma = pci_map_page(pdev, bi->page, + bi->page_offset, + (PAGE_SIZE / 2), + PCI_DMA_FROMDEVICE); + } + + skb = bi->skb; + if (!skb) { + skb = netdev_alloc_skb(adapter->netdev, + bufsz); + + if (!skb) { + adapter->alloc_rx_buff_failed++; + goto no_buffers; + } + + /* + * Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); + + bi->skb = skb; + } + if (!bi->dma) { + bi->dma = pci_map_single(pdev, skb->data, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); + } + /* Refresh the desc even if buffer_addrs didn't change because + * each write-back erases this info. */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma); + rx_desc->read.hdr_addr = cpu_to_le64(bi->dma); + } else { + rx_desc->read.pkt_addr = cpu_to_le64(bi->dma); + } + + i++; + if (i == rx_ring->count) + i = 0; + bi = &rx_ring->rx_buffer_info[i]; + } + +no_buffers: + if (rx_ring->next_to_use != i) { + rx_ring->next_to_use = i; + if (i-- == 0) + i = (rx_ring->count - 1); + + ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i); + } +} + +static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter, + u64 qmask) +{ + u32 mask; + struct ixgbe_hw *hw = &adapter->hw; + + mask = (qmask & 0xFFFFFFFF); + IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); +} + +static inline u16 ixgbevf_get_hdr_info(union ixgbe_adv_rx_desc *rx_desc) +{ + return rx_desc->wb.lower.lo_dword.hs_rss.hdr_info; +} + +static inline u16 ixgbevf_get_pkt_info(union ixgbe_adv_rx_desc *rx_desc) +{ + return rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; +} + +static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, + struct ixgbevf_ring *rx_ring, + int *work_done, int work_to_do) +{ + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct pci_dev *pdev = adapter->pdev; + union ixgbe_adv_rx_desc *rx_desc, *next_rxd; + struct ixgbevf_rx_buffer *rx_buffer_info, *next_buffer; + struct sk_buff *skb; + unsigned int i; + u32 len, staterr; + u16 hdr_info; + bool cleaned = false; + int cleaned_count = 0; + unsigned int total_rx_bytes = 0, total_rx_packets = 0; + + i = rx_ring->next_to_clean; + rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i); + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + rx_buffer_info = &rx_ring->rx_buffer_info[i]; + + while (staterr & IXGBE_RXD_STAT_DD) { + u32 upper_len = 0; + if (*work_done >= work_to_do) + break; + (*work_done)++; + + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + hdr_info = le16_to_cpu(ixgbevf_get_hdr_info(rx_desc)); + len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> + IXGBE_RXDADV_HDRBUFLEN_SHIFT; + if (hdr_info & IXGBE_RXDADV_SPH) + adapter->rx_hdr_split++; + if (len > IXGBEVF_RX_HDR_SIZE) + len = IXGBEVF_RX_HDR_SIZE; + upper_len = le16_to_cpu(rx_desc->wb.upper.length); + } else { + len = le16_to_cpu(rx_desc->wb.upper.length); + } + cleaned = true; + skb = rx_buffer_info->skb; + prefetch(skb->data - NET_IP_ALIGN); + rx_buffer_info->skb = NULL; + + if (rx_buffer_info->dma) { + pci_unmap_single(pdev, rx_buffer_info->dma, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); + rx_buffer_info->dma = 0; + skb_put(skb, len); + } + + if (upper_len) { + pci_unmap_page(pdev, rx_buffer_info->page_dma, + PAGE_SIZE / 2, PCI_DMA_FROMDEVICE); + rx_buffer_info->page_dma = 0; + skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, + rx_buffer_info->page, + rx_buffer_info->page_offset, + upper_len); + + if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) || + (page_count(rx_buffer_info->page) != 1)) + rx_buffer_info->page = NULL; + else + get_page(rx_buffer_info->page); + + skb->len += upper_len; + skb->data_len += upper_len; + skb->truesize += upper_len; + } + + i++; + if (i == rx_ring->count) + i = 0; + + next_rxd = IXGBE_RX_DESC_ADV(*rx_ring, i); + prefetch(next_rxd); + cleaned_count++; + + next_buffer = &rx_ring->rx_buffer_info[i]; + + if (!(staterr & IXGBE_RXD_STAT_EOP)) { + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + rx_buffer_info->skb = next_buffer->skb; + rx_buffer_info->dma = next_buffer->dma; + next_buffer->skb = skb; + next_buffer->dma = 0; + } else { + skb->next = next_buffer->skb; + skb->next->prev = skb; + } + adapter->non_eop_descs++; + goto next_desc; + } + + /* ERR_MASK will only have valid bits if EOP set */ + if (unlikely(staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK)) { + dev_kfree_skb_irq(skb); + goto next_desc; + } + + ixgbevf_rx_checksum(adapter, staterr, skb); + + /* probably a little skewed due to removing CRC */ + total_rx_bytes += skb->len; + total_rx_packets++; + + /* + * Work around issue of some types of VM to VM loop back + * packets not getting split correctly + */ + if (staterr & IXGBE_RXD_STAT_LB) { + u32 header_fixup_len = skb->len - skb->data_len; + if (header_fixup_len < 14) + skb_push(skb, header_fixup_len); + } + skb->protocol = eth_type_trans(skb, adapter->netdev); + + ixgbevf_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); + adapter->netdev->last_rx = jiffies; + +next_desc: + rx_desc->wb.upper.status_error = 0; + + /* return some buffers to hardware, one at a time is too slow */ + if (cleaned_count >= IXGBEVF_RX_BUFFER_WRITE) { + ixgbevf_alloc_rx_buffers(adapter, rx_ring, + cleaned_count); + cleaned_count = 0; + } + + /* use prefetched values */ + rx_desc = next_rxd; + rx_buffer_info = &rx_ring->rx_buffer_info[i]; + + staterr = le32_to_cpu(rx_desc->wb.upper.status_error); + } + + rx_ring->next_to_clean = i; + cleaned_count = IXGBE_DESC_UNUSED(rx_ring); + + if (cleaned_count) + ixgbevf_alloc_rx_buffers(adapter, rx_ring, cleaned_count); + + rx_ring->total_packets += total_rx_packets; + rx_ring->total_bytes += total_rx_bytes; + adapter->net_stats.rx_bytes += total_rx_bytes; + adapter->net_stats.rx_packets += total_rx_packets; + + return cleaned; +} + +/** + * ixgbevf_clean_rxonly - msix (aka one shot) rx clean routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * This function is optimized for cleaning one queue only on a single + * q_vector!!! + **/ +static int ixgbevf_clean_rxonly(struct napi_struct *napi, int budget) +{ + struct ixgbevf_q_vector *q_vector = + container_of(napi, struct ixgbevf_q_vector, napi); + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbevf_ring *rx_ring = NULL; + int work_done = 0; + long r_idx; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + + ixgbevf_clean_rx_irq(q_vector, rx_ring, &work_done, budget); + + /* If all Rx work done, exit the polling mode */ + if (work_done < budget) { + napi_complete(napi); + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_enable_queues(adapter, rx_ring->v_idx); + } + + return work_done; +} + +/** + * ixgbevf_clean_rxonly_many - msix (aka one shot) rx clean routine + * @napi: napi struct with our devices info in it + * @budget: amount of work driver is allowed to do this pass, in packets + * + * This function will clean more than one rx queue associated with a + * q_vector. + **/ +static int ixgbevf_clean_rxonly_many(struct napi_struct *napi, int budget) +{ + struct ixgbevf_q_vector *q_vector = + container_of(napi, struct ixgbevf_q_vector, napi); + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbevf_ring *rx_ring = NULL; + int work_done = 0, i; + long r_idx; + u64 enable_mask = 0; + + /* attempt to distribute budget to each queue fairly, but don't allow + * the budget to go below 1 because we'll exit polling */ + budget /= (q_vector->rxr_count ?: 1); + budget = max(budget, 1); + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + ixgbevf_clean_rx_irq(q_vector, rx_ring, &work_done, budget); + enable_mask |= rx_ring->v_idx; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + +#ifndef HAVE_NETDEV_NAPI_LIST + if (!netif_running(adapter->netdev)) + work_done = 0; + +#endif + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + + /* If all Rx work done, exit the polling mode */ + if (work_done < budget) { + napi_complete(napi); + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_enable_queues(adapter, enable_mask); + } + + return work_done; +} + + +/** + * ixgbevf_configure_msix - Configure MSI-X hardware + * @adapter: board private structure + * + * ixgbevf_configure_msix sets up the hardware to properly generate MSI-X + * interrupts. + **/ +static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter) +{ + struct ixgbevf_q_vector *q_vector; + struct ixgbe_hw *hw = &adapter->hw; + int i, j, q_vectors, v_idx, r_idx; + u32 mask; + + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + /* + * Populate the IVAR table and set the ITR values to the + * corresponding register. + */ + for (v_idx = 0; v_idx < q_vectors; v_idx++) { + q_vector = adapter->q_vector[v_idx]; + /* XXX for_each_bit(...) */ + r_idx = find_first_bit(q_vector->rxr_idx, + adapter->num_rx_queues); + + for (i = 0; i < q_vector->rxr_count; i++) { + j = adapter->rx_ring[r_idx].reg_idx; + ixgbevf_set_ivar(adapter, 0, j, v_idx); + r_idx = find_next_bit(q_vector->rxr_idx, + adapter->num_rx_queues, + r_idx + 1); + } + r_idx = find_first_bit(q_vector->txr_idx, + adapter->num_tx_queues); + + for (i = 0; i < q_vector->txr_count; i++) { + j = adapter->tx_ring[r_idx].reg_idx; + ixgbevf_set_ivar(adapter, 1, j, v_idx); + r_idx = find_next_bit(q_vector->txr_idx, + adapter->num_tx_queues, + r_idx + 1); + } + + /* if this is a tx only vector halve the interrupt rate */ + if (q_vector->txr_count && !q_vector->rxr_count) + q_vector->eitr = (adapter->eitr_param >> 1); + else if (q_vector->rxr_count) + /* rx only */ + q_vector->eitr = adapter->eitr_param; + + ixgbevf_write_eitr(adapter, v_idx, q_vector->eitr); + } + + ixgbevf_set_ivar(adapter, -1, 1, v_idx); + + /* set up to autoclear timer, and the vectors */ + mask = IXGBE_EIMS_ENABLE_MASK; + mask &= ~IXGBE_EIMS_OTHER; + IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, mask); +} + +enum latency_range { + lowest_latency = 0, + low_latency = 1, + bulk_latency = 2, + latency_invalid = 255 +}; + +/** + * ixgbevf_update_itr - update the dynamic ITR value based on statistics + * @adapter: pointer to adapter + * @eitr: eitr setting (ints per sec) to give last timeslice + * @itr_setting: current throttle rate in ints/second + * @packets: the number of packets during this measurement interval + * @bytes: the number of bytes during this measurement interval + * + * Stores a new ITR value based on packets and byte + * counts during the last interrupt. The advantage of per interrupt + * computation is faster updates and more accurate ITR for the current + * traffic pattern. Constants in this function were computed + * based on theoretical maximum wire speed and thresholds were set based + * on testing data as well as attempting to minimize response time + * while increasing bulk throughput. + **/ +static u8 ixgbevf_update_itr(struct ixgbevf_adapter *adapter, + u32 eitr, u8 itr_setting, + int packets, int bytes) +{ + unsigned int retval = itr_setting; + u32 timepassed_us; + u64 bytes_perint; + + if (packets == 0) + goto update_itr_done; + + + /* simple throttlerate management + * 0-20MB/s lowest (100000 ints/s) + * 20-100MB/s low (20000 ints/s) + * 100-1249MB/s bulk (8000 ints/s) + */ + /* what was last interrupt timeslice? */ + timepassed_us = 1000000/eitr; + bytes_perint = bytes / timepassed_us; /* bytes/usec */ + + switch (itr_setting) { + case lowest_latency: + if (bytes_perint > adapter->eitr_low) + retval = low_latency; + break; + case low_latency: + if (bytes_perint > adapter->eitr_high) + retval = bulk_latency; + else if (bytes_perint <= adapter->eitr_low) + retval = lowest_latency; + break; + case bulk_latency: + if (bytes_perint <= adapter->eitr_high) + retval = low_latency; + break; + } + +update_itr_done: + return retval; +} + +/** + * ixgbevf_write_eitr - write VTEITR register in hardware specific way + * @adapter: pointer to adapter struct + * @v_idx: vector index into q_vector array + * @itr_reg: new value to be written in *register* format, not ints/s + * + * This function is made to be called by ethtool and by the driver + * when it needs to update VTEITR registers at runtime. Hardware + * specific quirks/differences are taken care of here. + */ +static void ixgbevf_write_eitr(struct ixgbevf_adapter *adapter, int v_idx, + u32 itr_reg) +{ + struct ixgbe_hw *hw = &adapter->hw; + + itr_reg = EITR_INTS_PER_SEC_TO_REG(itr_reg); + + /* + * set the WDIS bit to not clear the timer bits and cause an + * immediate assertion of the interrupt + */ + itr_reg |= IXGBE_EITR_CNT_WDIS; + + IXGBE_WRITE_REG(hw, IXGBE_VTEITR(v_idx), itr_reg); +} + +static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector) +{ + struct ixgbevf_adapter *adapter = q_vector->adapter; + u32 new_itr; + u8 current_itr, ret_itr; + int i, r_idx, v_idx = q_vector->v_idx; + struct ixgbevf_ring *rx_ring, *tx_ring; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + tx_ring = &(adapter->tx_ring[r_idx]); + ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr, + q_vector->tx_itr, + tx_ring->total_packets, + tx_ring->total_bytes); + /* if the result for this queue would decrease interrupt + * rate for this vector then use that result */ + q_vector->tx_itr = ((q_vector->tx_itr > ret_itr) ? + q_vector->tx_itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + ret_itr = ixgbevf_update_itr(adapter, q_vector->eitr, + q_vector->rx_itr, + rx_ring->total_packets, + rx_ring->total_bytes); + /* if the result for this queue would decrease interrupt + * rate for this vector then use that result */ + q_vector->rx_itr = ((q_vector->rx_itr > ret_itr) ? + q_vector->rx_itr - 1 : ret_itr); + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + current_itr = max(q_vector->rx_itr, q_vector->tx_itr); + + switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ + case lowest_latency: + new_itr = 100000; + break; + case low_latency: + new_itr = 20000; /* aka hwitr = ~200 */ + break; + case bulk_latency: + default: + new_itr = 8000; + break; + } + + if (new_itr != q_vector->eitr) { + u32 itr_reg; + + /* save the algorithm value here, not the smoothed one */ + q_vector->eitr = new_itr; + /* do an exponential smoothing */ + new_itr = ((q_vector->eitr * 90)/100) + ((new_itr * 10)/100); + itr_reg = EITR_INTS_PER_SEC_TO_REG(new_itr); + ixgbevf_write_eitr(adapter, v_idx, itr_reg); + } + + return; +} + +static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) +{ + struct net_device *netdev = data; + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u32 eicr; + + eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS); + IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr); + + return IRQ_HANDLED; +} + +static irqreturn_t ixgbevf_msix_clean_tx(int irq, void *data) +{ + struct ixgbevf_q_vector *q_vector = data; + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbevf_ring *tx_ring; + int i, r_idx; + + if (!q_vector->txr_count) + return IRQ_HANDLED; + + r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); + for (i = 0; i < q_vector->txr_count; i++) { + tx_ring = &(adapter->tx_ring[r_idx]); + tx_ring->total_bytes = 0; + tx_ring->total_packets = 0; + ixgbevf_clean_tx_irq(adapter, tx_ring); + r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, + r_idx + 1); + } + + if (adapter->itr_setting & 1) + ixgbevf_set_itr_msix(q_vector); + + return IRQ_HANDLED; +} + +/** + * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues) + * @irq: unused + * @data: pointer to our q_vector struct for this interrupt vector + **/ +static irqreturn_t ixgbevf_msix_clean_rx(int irq, void *data) +{ + struct ixgbevf_q_vector *q_vector = data; + struct ixgbevf_adapter *adapter = q_vector->adapter; + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbevf_ring *rx_ring; + int r_idx; + int i; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + for (i = 0; i < q_vector->rxr_count; i++) { + rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring->total_bytes = 0; + rx_ring->total_packets = 0; + r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, + r_idx + 1); + } + + if (!q_vector->rxr_count) + return IRQ_HANDLED; + + r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); + rx_ring = &(adapter->rx_ring[r_idx]); + /* disable interrupts on this vector only */ + IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, rx_ring->v_idx); + napi_schedule(&q_vector->napi); + + + return IRQ_HANDLED; +} + +static irqreturn_t ixgbevf_msix_clean_many(int irq, void *data) +{ + ixgbevf_msix_clean_rx(irq, data); + ixgbevf_msix_clean_tx(irq, data); + + return IRQ_HANDLED; +} + +static inline void map_vector_to_rxq(struct ixgbevf_adapter *a, int v_idx, + int r_idx) +{ + struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(r_idx, q_vector->rxr_idx); + q_vector->rxr_count++; + a->rx_ring[r_idx].v_idx = 1 << v_idx; +} + +static inline void map_vector_to_txq(struct ixgbevf_adapter *a, int v_idx, + int t_idx) +{ + struct ixgbevf_q_vector *q_vector = a->q_vector[v_idx]; + + set_bit(t_idx, q_vector->txr_idx); + q_vector->txr_count++; + a->tx_ring[t_idx].v_idx = 1 << v_idx; +} + +/** + * ixgbevf_map_rings_to_vectors - Maps descriptor rings to vectors + * @adapter: board private structure to initialize + * + * This function maps descriptor rings to the queue-specific vectors + * we were allotted through the MSI-X enabling code. Ideally, we'd have + * one vector per ring/queue, but on a constrained vector budget, we + * group the rings as "efficiently" as possible. You would add new + * mapping configurations in here. + **/ +static int ixgbevf_map_rings_to_vectors(struct ixgbevf_adapter *adapter) +{ + int q_vectors; + int v_start = 0; + int rxr_idx = 0, txr_idx = 0; + int rxr_remaining = adapter->num_rx_queues; + int txr_remaining = adapter->num_tx_queues; + int i, j; + int rqpv, tqpv; + int err = 0; + + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + /* + * The ideal configuration... + * We have enough vectors to map one per queue. + */ + if (q_vectors == adapter->num_rx_queues + adapter->num_tx_queues) { + for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++) + map_vector_to_rxq(adapter, v_start, rxr_idx); + + for (; txr_idx < txr_remaining; v_start++, txr_idx++) + map_vector_to_txq(adapter, v_start, txr_idx); + goto out; + } + + /* + * If we don't have enough vectors for a 1-to-1 + * mapping, we'll have to group them so there are + * multiple queues per vector. + */ + /* Re-adjusting *qpv takes care of the remainder. */ + for (i = v_start; i < q_vectors; i++) { + rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i); + for (j = 0; j < rqpv; j++) { + map_vector_to_rxq(adapter, i, rxr_idx); + rxr_idx++; + rxr_remaining--; + } + } + for (i = v_start; i < q_vectors; i++) { + tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i); + for (j = 0; j < tqpv; j++) { + map_vector_to_txq(adapter, i, txr_idx); + txr_idx++; + txr_remaining--; + } + } + +out: + return err; +} + +/** + * ixgbevf_request_msix_irqs - Initialize MSI-X interrupts + * @adapter: board private structure + * + * ixgbevf_request_msix_irqs allocates MSI-X vectors and requests + * interrupts from the kernel. + **/ +static int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + irqreturn_t (*handler)(int, void *); + int i, vector, q_vectors, err; + int ri = 0, ti = 0; + + /* Decrement for Other and TCP Timer vectors */ + q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + +#define SET_HANDLER(_v) (((_v)->rxr_count && (_v)->txr_count) \ + ? &ixgbevf_msix_clean_many : \ + (_v)->rxr_count ? &ixgbevf_msix_clean_rx : \ + (_v)->txr_count ? &ixgbevf_msix_clean_tx : \ + NULL) + for (vector = 0; vector < q_vectors; vector++) { + handler = SET_HANDLER(adapter->q_vector[vector]); + + if (handler == &ixgbevf_msix_clean_rx) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "rx", ri++); + } else if (handler == &ixgbevf_msix_clean_tx) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "tx", ti++); + } else if (handler == &ixgbevf_msix_clean_many) { + sprintf(adapter->name[vector], "%s-%s-%d", + netdev->name, "TxRx", vector); + } else { + /* skip this unused q_vector */ + continue; + } + err = request_irq(adapter->msix_entries[vector].vector, + handler, 0, adapter->name[vector], + adapter->q_vector[vector]); + if (err) { + hw_dbg(&adapter->hw, + "request_irq failed for MSIX interrupt " + "Error: %d\n", err); + goto free_queue_irqs; + } + } + + sprintf(adapter->name[vector], "%s:mbx", netdev->name); + err = request_irq(adapter->msix_entries[vector].vector, + &ixgbevf_msix_mbx, 0, adapter->name[vector], netdev); + if (err) { + hw_dbg(&adapter->hw, + "request_irq for msix_mbx failed: %d\n", err); + goto free_queue_irqs; + } + + return 0; + +free_queue_irqs: + for (i = vector - 1; i >= 0; i--) + free_irq(adapter->msix_entries[--vector].vector, + &(adapter->q_vector[i])); + pci_disable_msix(adapter->pdev); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + return err; +} + +static inline void ixgbevf_reset_q_vectors(struct ixgbevf_adapter *adapter) +{ + int i, q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + for (i = 0; i < q_vectors; i++) { + struct ixgbevf_q_vector *q_vector = adapter->q_vector[i]; + bitmap_zero(q_vector->rxr_idx, MAX_RX_QUEUES); + bitmap_zero(q_vector->txr_idx, MAX_TX_QUEUES); + q_vector->rxr_count = 0; + q_vector->txr_count = 0; + q_vector->eitr = adapter->eitr_param; + } +} + +/** + * ixgbevf_request_irq - initialize interrupts + * @adapter: board private structure + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ +static int ixgbevf_request_irq(struct ixgbevf_adapter *adapter) +{ + int err = 0; + + err = ixgbevf_request_msix_irqs(adapter); + + if (err) + hw_dbg(&adapter->hw, + "request_irq failed, Error %d\n", err); + + return err; +} + +static void ixgbevf_free_irq(struct ixgbevf_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int i, q_vectors; + + q_vectors = adapter->num_msix_vectors; + + i = q_vectors - 1; + + free_irq(adapter->msix_entries[i].vector, netdev); + i--; + + for (; i >= 0; i--) { + free_irq(adapter->msix_entries[i].vector, + adapter->q_vector[i]); + } + + ixgbevf_reset_q_vectors(adapter); +} + +/** + * ixgbevf_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void ixgbevf_irq_disable(struct ixgbevf_adapter *adapter) +{ + int i; + struct ixgbe_hw *hw = &adapter->hw; + + IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, ~0); + + IXGBE_WRITE_FLUSH(hw); + + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); +} + +/** + * ixgbevf_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ +static inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter, + bool queues, bool flush) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 mask; + u64 qmask; + + mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); + qmask = ~0; + + IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, mask); + + if (queues) + ixgbevf_irq_enable_queues(adapter, qmask); + + if (flush) + IXGBE_WRITE_FLUSH(hw); +} + +/** + * ixgbevf_configure_tx - Configure 82599 VF Transmit Unit after Reset + * @adapter: board private structure + * + * Configure the Tx unit of the MAC after a reset. + **/ +static void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) +{ + u64 tdba; + struct ixgbe_hw *hw = &adapter->hw; + u32 i, j, tdlen, txctrl; + + /* Setup the HW Tx Head and Tail descriptor pointers */ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct ixgbevf_ring *ring = &adapter->tx_ring[i]; + j = ring->reg_idx; + tdba = ring->dma; + tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc); + IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(j), + (tdba & DMA_BIT_MASK(32))); + IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(j), (tdba >> 32)); + IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(j), tdlen); + IXGBE_WRITE_REG(hw, IXGBE_VFTDH(j), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTDT(j), 0); + adapter->tx_ring[i].head = IXGBE_VFTDH(j); + adapter->tx_ring[i].tail = IXGBE_VFTDT(j); + /* Disable Tx Head Writeback RO bit, since this hoses + * bookkeeping if things aren't delivered in order. + */ + txctrl = IXGBE_READ_REG(hw, IXGBE_VFDCA_TXCTRL(j)); + txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN; + IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(j), txctrl); + } +} + +#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 + +static void ixgbevf_configure_srrctl(struct ixgbevf_adapter *adapter, int index) +{ + struct ixgbevf_ring *rx_ring; + struct ixgbe_hw *hw = &adapter->hw; + u32 srrctl; + + rx_ring = &adapter->rx_ring[index]; + + srrctl = IXGBE_SRRCTL_DROP_EN; + + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + u16 bufsz = IXGBEVF_RXBUFFER_2048; + /* grow the amount we can receive on large page machines */ + if (bufsz < (PAGE_SIZE / 2)) + bufsz = (PAGE_SIZE / 2); + /* cap the bufsz at our largest descriptor size */ + bufsz = min((u16)IXGBEVF_MAX_RXBUFFER, bufsz); + + srrctl |= bufsz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS; + srrctl |= ((IXGBEVF_RX_HDR_SIZE << + IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & + IXGBE_SRRCTL_BSIZEHDR_MASK); + } else { + srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; + + if (rx_ring->rx_buf_len == MAXIMUM_ETHERNET_VLAN_SIZE) + srrctl |= IXGBEVF_RXBUFFER_2048 >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; + else + srrctl |= rx_ring->rx_buf_len >> + IXGBE_SRRCTL_BSIZEPKT_SHIFT; + } + IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(index), srrctl); +} + +/** + * ixgbevf_configure_rx - Configure 82599 VF Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Rx unit of the MAC after a reset. + **/ +static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) +{ + u64 rdba; + struct ixgbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; + int i, j; + u32 rdlen; + int rx_buf_len; + + /* Decide whether to use packet split mode or not */ + if (netdev->mtu > ETH_DATA_LEN) { + if (adapter->flags & IXGBE_FLAG_RX_PS_CAPABLE) + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + else + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + } else { + if (adapter->flags & IXGBE_FLAG_RX_1BUF_CAPABLE) + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + else + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + } + + /* Set the RX buffer length according to the mode */ + if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { + /* PSRTYPE must be initialized in 82599 */ + u32 psrtype = IXGBE_PSRTYPE_TCPHDR | + IXGBE_PSRTYPE_UDPHDR | + IXGBE_PSRTYPE_IPV4HDR | + IXGBE_PSRTYPE_IPV6HDR | + IXGBE_PSRTYPE_L2HDR; + IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); + rx_buf_len = IXGBEVF_RX_HDR_SIZE; + } else { + IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, 0); + if (netdev->mtu <= ETH_DATA_LEN) + rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE; + else + rx_buf_len = ALIGN(max_frame, 1024); + } + + rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); + /* Setup the HW Rx Head and Tail Descriptor Pointers and + * the Base and Length of the Rx Descriptor Ring */ + for (i = 0; i < adapter->num_rx_queues; i++) { + rdba = adapter->rx_ring[i].dma; + j = adapter->rx_ring[i].reg_idx; + IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(j), + (rdba & DMA_BIT_MASK(32))); + IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(j), (rdba >> 32)); + IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(j), rdlen); + IXGBE_WRITE_REG(hw, IXGBE_VFRDH(j), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFRDT(j), 0); + adapter->rx_ring[i].head = IXGBE_VFRDH(j); + adapter->rx_ring[i].tail = IXGBE_VFRDT(j); + adapter->rx_ring[i].rx_buf_len = rx_buf_len; + + ixgbevf_configure_srrctl(adapter, j); + } +} + +static void ixgbevf_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + int i, j; + u32 ctrl; + + adapter->vlgrp = grp; + + for (i = 0; i < adapter->num_rx_queues; i++) { + j = adapter->rx_ring[i].reg_idx; + ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); + ctrl |= IXGBE_RXDCTL_VME; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), ctrl); + } +} + +static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + struct net_device *v_netdev; + + /* add VID to filter table */ + if (hw->mac.ops.set_vfta) + hw->mac.ops.set_vfta(hw, vid, 0, true); + /* + * Copy feature flags from netdev to the vlan netdev for this vid. + * This allows things like TSO to bubble down to our vlan device. + */ + v_netdev = vlan_group_get_device(adapter->vlgrp, vid); + v_netdev->features |= adapter->netdev->features; + vlan_group_set_device(adapter->vlgrp, vid, v_netdev); +} + +static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_disable(adapter); + + vlan_group_set_device(adapter->vlgrp, vid, NULL); + + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + ixgbevf_irq_enable(adapter, true, true); + + /* remove VID from filter table */ + if (hw->mac.ops.set_vfta) + hw->mac.ops.set_vfta(hw, vid, 0, false); +} + +static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) +{ + ixgbevf_vlan_rx_register(adapter->netdev, adapter->vlgrp); + + if (adapter->vlgrp) { + u16 vid; + for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + if (!vlan_group_get_device(adapter->vlgrp, vid)) + continue; + ixgbevf_vlan_rx_add_vid(adapter->netdev, vid); + } + } +} + +static u8 *ixgbevf_addr_list_itr(struct ixgbe_hw *hw, u8 **mc_addr_ptr, + u32 *vmdq) +{ + struct dev_mc_list *mc_ptr; + u8 *addr = *mc_addr_ptr; + *vmdq = 0; + + mc_ptr = container_of(addr, struct dev_mc_list, dmi_addr[0]); + if (mc_ptr->next) + *mc_addr_ptr = mc_ptr->next->dmi_addr; + else + *mc_addr_ptr = NULL; + + return addr; +} + +/** + * ixgbevf_set_rx_mode - Multicast set + * @netdev: network interface device structure + * + * The set_rx_method entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast mode. + **/ +static void ixgbevf_set_rx_mode(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + u8 *addr_list = NULL; + int addr_count = 0; + + /* reprogram multicast list */ + addr_count = netdev->mc_count; + if (addr_count) + addr_list = netdev->mc_list->dmi_addr; + if (hw->mac.ops.update_mc_addr_list) + hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count, + ixgbevf_addr_list_itr); +} + +static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter) +{ + int q_idx; + struct ixgbevf_q_vector *q_vector; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + struct napi_struct *napi; + q_vector = adapter->q_vector[q_idx]; + if (!q_vector->rxr_count) + continue; + napi = &q_vector->napi; + if (q_vector->rxr_count > 1) + napi->poll = &ixgbevf_clean_rxonly_many; + + napi_enable(napi); + } +} + +static void ixgbevf_napi_disable_all(struct ixgbevf_adapter *adapter) +{ + int q_idx; + struct ixgbevf_q_vector *q_vector; + int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + + for (q_idx = 0; q_idx < q_vectors; q_idx++) { + q_vector = adapter->q_vector[q_idx]; + if (!q_vector->rxr_count) + continue; + napi_disable(&q_vector->napi); + } +} + +static void ixgbevf_configure(struct ixgbevf_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int i; + + ixgbevf_set_rx_mode(netdev); + + ixgbevf_restore_vlan(adapter); + + ixgbevf_configure_tx(adapter); + ixgbevf_configure_rx(adapter); + for (i = 0; i < adapter->num_rx_queues; i++) { + struct ixgbevf_ring *ring = &adapter->rx_ring[i]; + ixgbevf_alloc_rx_buffers(adapter, ring, ring->count); + ring->next_to_use = ring->count - 1; + writel(ring->next_to_use, adapter->hw.hw_addr + ring->tail); + } +} + +#define IXGBE_MAX_RX_DESC_POLL 10 +static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, + int rxr) +{ + struct ixgbe_hw *hw = &adapter->hw; + int j = adapter->rx_ring[rxr].reg_idx; + int k; + + for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) { + if (IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)) & IXGBE_RXDCTL_ENABLE) + break; + else + msleep(1); + } + if (k >= IXGBE_MAX_RX_DESC_POLL) { + hw_dbg(hw, "RXDCTL.ENABLE on Rx queue %d " + "not set within the polling period\n", rxr); + } + + ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr], + (adapter->rx_ring[rxr].count - 1)); +} + +static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + int i, j = 0; + int num_rx_rings = adapter->num_rx_queues; + u32 txdctl, rxdctl; + + for (i = 0; i < adapter->num_tx_queues; i++) { + j = adapter->tx_ring[i].reg_idx; + txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); + /* enable WTHRESH=8 descriptors, to encourage burst writeback */ + txdctl |= (8 << 16); + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); + } + + for (i = 0; i < adapter->num_tx_queues; i++) { + j = adapter->tx_ring[i].reg_idx; + txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); + txdctl |= IXGBE_TXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), txdctl); + } + + for (i = 0; i < num_rx_rings; i++) { + j = adapter->rx_ring[i].reg_idx; + rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j)); + rxdctl |= IXGBE_RXDCTL_ENABLE; + IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl); + ixgbevf_rx_desc_queue_enable(adapter, i); + } + + ixgbevf_configure_msix(adapter); + + if (hw->mac.ops.set_rar) { + if (is_valid_ether_addr(hw->mac.addr)) + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + else + hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0); + } + + clear_bit(__IXGBEVF_DOWN, &adapter->state); + ixgbevf_napi_enable_all(adapter); + + /* enable transmits */ + netif_tx_start_all_queues(netdev); + + /* bring the link up in the watchdog, this could race with our first + * link up interrupt but shouldn't be a problem */ + adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; + adapter->link_check_timeout = jiffies; + mod_timer(&adapter->watchdog_timer, jiffies); + return 0; +} + +int ixgbevf_up(struct ixgbevf_adapter *adapter) +{ + int err; + struct ixgbe_hw *hw = &adapter->hw; + + ixgbevf_configure(adapter); + + err = ixgbevf_up_complete(adapter); + + /* clear any pending interrupts, may auto mask */ + IXGBE_READ_REG(hw, IXGBE_VTEICR); + + ixgbevf_irq_enable(adapter, true, true); + + return err; +} + +/** + * ixgbevf_clean_rx_ring - Free Rx Buffers per Queue + * @adapter: board private structure + * @rx_ring: ring to free buffers from + **/ +static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *rx_ring) +{ + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; + + /* Free all the Rx ring sk_buffs */ + + for (i = 0; i < rx_ring->count; i++) { + struct ixgbevf_rx_buffer *rx_buffer_info; + + rx_buffer_info = &rx_ring->rx_buffer_info[i]; + if (rx_buffer_info->dma) { + pci_unmap_single(pdev, rx_buffer_info->dma, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); + rx_buffer_info->dma = 0; + } + if (rx_buffer_info->skb) { + struct sk_buff *skb = rx_buffer_info->skb; + rx_buffer_info->skb = NULL; + do { + struct sk_buff *this = skb; + skb = skb->prev; + dev_kfree_skb(this); + } while (skb); + } + if (!rx_buffer_info->page) + continue; + pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2, + PCI_DMA_FROMDEVICE); + rx_buffer_info->page_dma = 0; + put_page(rx_buffer_info->page); + rx_buffer_info->page = NULL; + rx_buffer_info->page_offset = 0; + } + + size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; + memset(rx_ring->rx_buffer_info, 0, size); + + /* Zero out the descriptor ring */ + memset(rx_ring->desc, 0, rx_ring->size); + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + + if (rx_ring->head) + writel(0, adapter->hw.hw_addr + rx_ring->head); + if (rx_ring->tail) + writel(0, adapter->hw.hw_addr + rx_ring->tail); +} + +/** + * ixgbevf_clean_tx_ring - Free Tx Buffers + * @adapter: board private structure + * @tx_ring: ring to be cleaned + **/ +static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring) +{ + struct ixgbevf_tx_buffer *tx_buffer_info; + unsigned long size; + unsigned int i; + + /* Free all the Tx ring sk_buffs */ + + for (i = 0; i < tx_ring->count; i++) { + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + ixgbevf_unmap_and_free_tx_resource(adapter, tx_buffer_info); + } + + size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count; + memset(tx_ring->tx_buffer_info, 0, size); + + memset(tx_ring->desc, 0, tx_ring->size); + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + + if (tx_ring->head) + writel(0, adapter->hw.hw_addr + tx_ring->head); + if (tx_ring->tail) + writel(0, adapter->hw.hw_addr + tx_ring->tail); +} + +/** + * ixgbevf_clean_all_rx_rings - Free Rx Buffers for all queues + * @adapter: board private structure + **/ +static void ixgbevf_clean_all_rx_rings(struct ixgbevf_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + ixgbevf_clean_rx_ring(adapter, &adapter->rx_ring[i]); +} + +/** + * ixgbevf_clean_all_tx_rings - Free Tx Buffers for all queues + * @adapter: board private structure + **/ +static void ixgbevf_clean_all_tx_rings(struct ixgbevf_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + ixgbevf_clean_tx_ring(adapter, &adapter->tx_ring[i]); +} + +void ixgbevf_down(struct ixgbevf_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + u32 txdctl; + int i, j; + + /* signal that we are down to the interrupt handler */ + set_bit(__IXGBEVF_DOWN, &adapter->state); + /* disable receives */ + + netif_tx_disable(netdev); + + msleep(10); + + netif_tx_stop_all_queues(netdev); + + ixgbevf_irq_disable(adapter); + + ixgbevf_napi_disable_all(adapter); + + del_timer_sync(&adapter->watchdog_timer); + /* can't call flush scheduled work here because it can deadlock + * if linkwatch_event tries to acquire the rtnl_lock which we are + * holding */ + while (adapter->flags & IXGBE_FLAG_IN_WATCHDOG_TASK) + msleep(1); + + /* disable transmits in the hardware now that interrupts are off */ + for (i = 0; i < adapter->num_tx_queues; i++) { + j = adapter->tx_ring[i].reg_idx; + txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(j)); + IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(j), + (txdctl & ~IXGBE_TXDCTL_ENABLE)); + } + + netif_carrier_off(netdev); + + if (!pci_channel_offline(adapter->pdev)) + ixgbevf_reset(adapter); + + ixgbevf_clean_all_tx_rings(adapter); + ixgbevf_clean_all_rx_rings(adapter); +} + +void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) +{ + WARN_ON(in_interrupt()); + while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) + msleep(1); + + ixgbevf_down(adapter); + ixgbevf_up(adapter); + + clear_bit(__IXGBEVF_RESETTING, &adapter->state); +} + +void ixgbevf_reset(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + + if (hw->mac.ops.reset_hw(hw)) + hw_dbg(hw, "PF still resetting\n"); + else + hw->mac.ops.init_hw(hw); + + if (is_valid_ether_addr(adapter->hw.mac.addr)) { + memcpy(netdev->dev_addr, adapter->hw.mac.addr, + netdev->addr_len); + memcpy(netdev->perm_addr, adapter->hw.mac.addr, + netdev->addr_len); + } +} + +static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, + int vectors) +{ + int err, vector_threshold; + + /* We'll want at least 3 (vector_threshold): + * 1) TxQ[0] Cleanup + * 2) RxQ[0] Cleanup + * 3) Other (Link Status Change, etc.) + */ + vector_threshold = MIN_MSIX_COUNT; + + /* The more we get, the more we will assign to Tx/Rx Cleanup + * for the separate queues...where Rx Cleanup >= Tx Cleanup. + * Right now, we simply care about how many we'll get; we'll + * set them up later while requesting irq's. + */ + while (vectors >= vector_threshold) { + err = pci_enable_msix(adapter->pdev, adapter->msix_entries, + vectors); + if (!err) /* Success in acquiring all requested vectors. */ + break; + else if (err < 0) + vectors = 0; /* Nasty failure, quit now */ + else /* err == number of vectors we should try again with */ + vectors = err; + } + + if (vectors < vector_threshold) { + /* Can't allocate enough MSI-X interrupts? Oh well. + * This just means we'll go with either a single MSI + * vector or fall back to legacy interrupts. + */ + hw_dbg(&adapter->hw, + "Unable to allocate MSI-X interrupts\n"); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + } else { + /* + * Adjust for only the vectors we'll use, which is minimum + * of max_msix_q_vectors + NON_Q_VECTORS, or the number of + * vectors we were allocated. + */ + adapter->num_msix_vectors = vectors; + } +} + +/* + * ixgbe_set_num_queues: Allocate queues for device, feature dependant + * @adapter: board private structure to initialize + * + * This is the top level queue allocation routine. The order here is very + * important, starting with the "most" number of features turned on at once, + * and ending with the smallest set of features. This way large combinations + * can be allocated if they're turned on, and smaller combinations are the + * fallthrough conditions. + * + **/ +static void ixgbevf_set_num_queues(struct ixgbevf_adapter *adapter) +{ + /* Start with base case */ + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; + adapter->num_rx_pools = adapter->num_rx_queues; + adapter->num_rx_queues_per_pool = 1; +} + +/** + * ixgbevf_alloc_queues - Allocate memory for all rings + * @adapter: board private structure to initialize + * + * We allocate one ring per queue at run-time since we don't know the + * number of queues at compile-time. The polling_netdev array is + * intended for Multiqueue, but should work fine with a single queue. + **/ +static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter) +{ + int i; + + adapter->tx_ring = kcalloc(adapter->num_tx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if (!adapter->tx_ring) + goto err_tx_ring_allocation; + + adapter->rx_ring = kcalloc(adapter->num_rx_queues, + sizeof(struct ixgbevf_ring), GFP_KERNEL); + if (!adapter->rx_ring) + goto err_rx_ring_allocation; + + for (i = 0; i < adapter->num_tx_queues; i++) { + adapter->tx_ring[i].count = adapter->tx_ring_count; + adapter->tx_ring[i].queue_index = i; + adapter->tx_ring[i].reg_idx = i; + } + + for (i = 0; i < adapter->num_rx_queues; i++) { + adapter->rx_ring[i].count = adapter->rx_ring_count; + adapter->rx_ring[i].queue_index = i; + adapter->rx_ring[i].reg_idx = i; + } + + return 0; + +err_rx_ring_allocation: + kfree(adapter->tx_ring); +err_tx_ring_allocation: + return -ENOMEM; +} + +/** + * ixgbevf_set_interrupt_capability - set MSI-X or FAIL if not supported + * @adapter: board private structure to initialize + * + * Attempt to configure the interrupts using the best available + * capabilities of the hardware and the kernel. + **/ +static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter) +{ + int err = 0; + int vector, v_budget; + + /* + * It's easy to be greedy for MSI-X vectors, but it really + * doesn't do us much good if we have a lot more vectors + * than CPU's. So let's be conservative and only ask for + * (roughly) twice the number of vectors as there are CPU's. + */ + v_budget = min(adapter->num_rx_queues + adapter->num_tx_queues, + (int)(num_online_cpus() * 2)) + NON_Q_VECTORS; + + /* A failure in MSI-X entry allocation isn't fatal, but it does + * mean we disable MSI-X capabilities of the adapter. */ + adapter->msix_entries = kcalloc(v_budget, + sizeof(struct msix_entry), GFP_KERNEL); + if (!adapter->msix_entries) { + err = -ENOMEM; + goto out; + } + + for (vector = 0; vector < v_budget; vector++) + adapter->msix_entries[vector].entry = vector; + + ixgbevf_acquire_msix_vectors(adapter, v_budget); + +out: + return err; +} + +/** + * ixgbevf_alloc_q_vectors - Allocate memory for interrupt vectors + * @adapter: board private structure to initialize + * + * We allocate one q_vector per queue interrupt. If allocation fails we + * return -ENOMEM. + **/ +static int ixgbevf_alloc_q_vectors(struct ixgbevf_adapter *adapter) +{ + int q_idx, num_q_vectors; + struct ixgbevf_q_vector *q_vector; + int napi_vectors; + int (*poll)(struct napi_struct *, int); + + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + poll = &ixgbevf_clean_rxonly; + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + q_vector = kzalloc(sizeof(struct ixgbevf_q_vector), GFP_KERNEL); + if (!q_vector) + goto err_out; + q_vector->adapter = adapter; + q_vector->v_idx = q_idx; + q_vector->eitr = adapter->eitr_param; + if (q_idx < napi_vectors) + netif_napi_add(adapter->netdev, &q_vector->napi, + (*poll), 64); + adapter->q_vector[q_idx] = q_vector; + } + + return 0; + +err_out: + while (q_idx) { + q_idx--; + q_vector = adapter->q_vector[q_idx]; + netif_napi_del(&q_vector->napi); + kfree(q_vector); + adapter->q_vector[q_idx] = NULL; + } + return -ENOMEM; +} + +/** + * ixgbevf_free_q_vectors - Free memory allocated for interrupt vectors + * @adapter: board private structure to initialize + * + * This function frees the memory allocated to the q_vectors. In addition if + * NAPI is enabled it will delete any references to the NAPI struct prior + * to freeing the q_vector. + **/ +static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter) +{ + int q_idx, num_q_vectors; + int napi_vectors; + + num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; + napi_vectors = adapter->num_rx_queues; + + for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { + struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx]; + + adapter->q_vector[q_idx] = NULL; + if (q_idx < napi_vectors) + netif_napi_del(&q_vector->napi); + kfree(q_vector); + } +} + +/** + * ixgbevf_reset_interrupt_capability - Reset MSIX setup + * @adapter: board private structure + * + **/ +static void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter) +{ + pci_disable_msix(adapter->pdev); + kfree(adapter->msix_entries); + adapter->msix_entries = NULL; + + return; +} + +/** + * ixgbevf_init_interrupt_scheme - Determine if MSIX is supported and init + * @adapter: board private structure to initialize + * + **/ +static int ixgbevf_init_interrupt_scheme(struct ixgbevf_adapter *adapter) +{ + int err; + + /* Number of supported queues */ + ixgbevf_set_num_queues(adapter); + + err = ixgbevf_set_interrupt_capability(adapter); + if (err) { + hw_dbg(&adapter->hw, + "Unable to setup interrupt capabilities\n"); + goto err_set_interrupt; + } + + err = ixgbevf_alloc_q_vectors(adapter); + if (err) { + hw_dbg(&adapter->hw, "Unable to allocate memory for queue " + "vectors\n"); + goto err_alloc_q_vectors; + } + + err = ixgbevf_alloc_queues(adapter); + if (err) { + printk(KERN_ERR "Unable to allocate memory for queues\n"); + goto err_alloc_queues; + } + + hw_dbg(&adapter->hw, "Multiqueue %s: Rx Queue count = %u, " + "Tx Queue count = %u\n", + (adapter->num_rx_queues > 1) ? "Enabled" : + "Disabled", adapter->num_rx_queues, adapter->num_tx_queues); + + set_bit(__IXGBEVF_DOWN, &adapter->state); + + return 0; +err_alloc_queues: + ixgbevf_free_q_vectors(adapter); +err_alloc_q_vectors: + ixgbevf_reset_interrupt_capability(adapter); +err_set_interrupt: + return err; +} + +/** + * ixgbevf_sw_init - Initialize general software structures + * (struct ixgbevf_adapter) + * @adapter: board private structure to initialize + * + * ixgbevf_sw_init initializes the Adapter private data structure. + * Fields are initialized based on PCI device information and + * OS network device settings (MTU size). + **/ +static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct pci_dev *pdev = adapter->pdev; + int err; + + /* PCI config space info */ + + hw->vendor_id = pdev->vendor; + hw->device_id = pdev->device; + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id); + hw->subsystem_vendor_id = pdev->subsystem_vendor; + hw->subsystem_device_id = pdev->subsystem_device; + + hw->mbx.ops.init_params(hw); + hw->mac.max_tx_queues = MAX_TX_QUEUES; + hw->mac.max_rx_queues = MAX_RX_QUEUES; + err = hw->mac.ops.reset_hw(hw); + if (err) { + dev_info(&pdev->dev, + "PF still in reset state, assigning new address\n"); + random_ether_addr(hw->mac.addr); + } else { + err = hw->mac.ops.init_hw(hw); + if (err) { + printk(KERN_ERR "init_shared_code failed: %d\n", err); + goto out; + } + } + + /* Enable dynamic interrupt throttling rates */ + adapter->eitr_param = 20000; + adapter->itr_setting = 1; + + /* set defaults for eitr in MegaBytes */ + adapter->eitr_low = 10; + adapter->eitr_high = 20; + + /* set default ring sizes */ + adapter->tx_ring_count = IXGBEVF_DEFAULT_TXD; + adapter->rx_ring_count = IXGBEVF_DEFAULT_RXD; + + /* enable rx csum by default */ + adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + + set_bit(__IXGBEVF_DOWN, &adapter->state); + +out: + return err; +} + +static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + + adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); + adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); + adapter->stats.last_vfgorc |= + (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); + adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); + adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); + adapter->stats.last_vfgotc |= + (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); + adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); + + adapter->stats.base_vfgprc = adapter->stats.last_vfgprc; + adapter->stats.base_vfgorc = adapter->stats.last_vfgorc; + adapter->stats.base_vfgptc = adapter->stats.last_vfgptc; + adapter->stats.base_vfgotc = adapter->stats.last_vfgotc; + adapter->stats.base_vfmprc = adapter->stats.last_vfmprc; +} + +#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \ + { \ + u32 current_counter = IXGBE_READ_REG(hw, reg); \ + if (current_counter < last_counter) \ + counter += 0x100000000LL; \ + last_counter = current_counter; \ + counter &= 0xFFFFFFFF00000000LL; \ + counter |= current_counter; \ + } + +#define UPDATE_VF_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \ + { \ + u64 current_counter_lsb = IXGBE_READ_REG(hw, reg_lsb); \ + u64 current_counter_msb = IXGBE_READ_REG(hw, reg_msb); \ + u64 current_counter = (current_counter_msb << 32) | \ + current_counter_lsb; \ + if (current_counter < last_counter) \ + counter += 0x1000000000LL; \ + last_counter = current_counter; \ + counter &= 0xFFFFFFF000000000LL; \ + counter |= current_counter; \ + } +/** + * ixgbevf_update_stats - Update the board statistics counters. + * @adapter: board private structure + **/ +void ixgbevf_update_stats(struct ixgbevf_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + + UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc, + adapter->stats.vfgprc); + UPDATE_VF_COUNTER_32bit(IXGBE_VFGPTC, adapter->stats.last_vfgptc, + adapter->stats.vfgptc); + UPDATE_VF_COUNTER_36bit(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB, + adapter->stats.last_vfgorc, + adapter->stats.vfgorc); + UPDATE_VF_COUNTER_36bit(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB, + adapter->stats.last_vfgotc, + adapter->stats.vfgotc); + UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc, + adapter->stats.vfmprc); + + /* Fill out the OS statistics structure */ + adapter->net_stats.multicast = adapter->stats.vfmprc - + adapter->stats.base_vfmprc; +} + +/** + * ixgbevf_watchdog - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ +static void ixgbevf_watchdog(unsigned long data) +{ + struct ixgbevf_adapter *adapter = (struct ixgbevf_adapter *)data; + struct ixgbe_hw *hw = &adapter->hw; + u64 eics = 0; + int i; + + /* + * Do the watchdog outside of interrupt context due to the lovely + * delays that some of the newer hardware requires + */ + + if (test_bit(__IXGBEVF_DOWN, &adapter->state)) + goto watchdog_short_circuit; + + /* get one bit for every active tx/rx interrupt vector */ + for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { + struct ixgbevf_q_vector *qv = adapter->q_vector[i]; + if (qv->rxr_count || qv->txr_count) + eics |= (1 << i); + } + + IXGBE_WRITE_REG(hw, IXGBE_VTEICS, (u32)eics); + +watchdog_short_circuit: + schedule_work(&adapter->watchdog_task); +} + +/** + * ixgbevf_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + **/ +static void ixgbevf_tx_timeout(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + /* Do the reset outside of interrupt context */ + schedule_work(&adapter->reset_task); +} + +static void ixgbevf_reset_task(struct work_struct *work) +{ + struct ixgbevf_adapter *adapter; + adapter = container_of(work, struct ixgbevf_adapter, reset_task); + + /* If we're already down or resetting, just bail */ + if (test_bit(__IXGBEVF_DOWN, &adapter->state) || + test_bit(__IXGBEVF_RESETTING, &adapter->state)) + return; + + adapter->tx_timeout_count++; + + ixgbevf_reinit_locked(adapter); +} + +/** + * ixgbevf_watchdog_task - worker thread to bring link up + * @work: pointer to work_struct containing our data + **/ +static void ixgbevf_watchdog_task(struct work_struct *work) +{ + struct ixgbevf_adapter *adapter = container_of(work, + struct ixgbevf_adapter, + watchdog_task); + struct net_device *netdev = adapter->netdev; + struct ixgbe_hw *hw = &adapter->hw; + u32 link_speed = adapter->link_speed; + bool link_up = adapter->link_up; + + adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; + + /* + * Always check the link on the watchdog because we have + * no LSC interrupt + */ + if (hw->mac.ops.check_link) { + if ((hw->mac.ops.check_link(hw, &link_speed, + &link_up, false)) != 0) { + adapter->link_up = link_up; + adapter->link_speed = link_speed; + schedule_work(&adapter->reset_task); + goto pf_has_reset; + } + } else { + /* always assume link is up, if no check link + * function */ + link_speed = IXGBE_LINK_SPEED_10GB_FULL; + link_up = true; + } + adapter->link_up = link_up; + adapter->link_speed = link_speed; + + if (link_up) { + if (!netif_carrier_ok(netdev)) { + hw_dbg(&adapter->hw, "NIC Link is Up %s, ", + ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? + "10 Gbps" : "1 Gbps")); + netif_carrier_on(netdev); + netif_tx_wake_all_queues(netdev); + } else { + /* Force detection of hung controller */ + adapter->detect_tx_hung = true; + } + } else { + adapter->link_up = false; + adapter->link_speed = 0; + if (netif_carrier_ok(netdev)) { + hw_dbg(&adapter->hw, "NIC Link is Down\n"); + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + } + } + +pf_has_reset: + ixgbevf_update_stats(adapter); + + /* Force detection of hung controller every watchdog period */ + adapter->detect_tx_hung = true; + + /* Reset the timer */ + if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + (2 * HZ))); + + adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK; +} + +/** + * ixgbevf_free_tx_resources - Free Tx Resources per Queue + * @adapter: board private structure + * @tx_ring: Tx descriptor ring for a specific queue + * + * Free all transmit software resources + **/ +void ixgbevf_free_tx_resources(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring) +{ + struct pci_dev *pdev = adapter->pdev; + + + ixgbevf_clean_tx_ring(adapter, tx_ring); + + vfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info = NULL; + + pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); + + tx_ring->desc = NULL; +} + +/** + * ixgbevf_free_all_tx_resources - Free Tx Resources for All Queues + * @adapter: board private structure + * + * Free all transmit software resources + **/ +static void ixgbevf_free_all_tx_resources(struct ixgbevf_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) + if (adapter->tx_ring[i].desc) + ixgbevf_free_tx_resources(adapter, + &adapter->tx_ring[i]); + +} + +/** + * ixgbevf_setup_tx_resources - allocate Tx resources (Descriptors) + * @adapter: board private structure + * @tx_ring: tx descriptor ring (for a specific queue) to setup + * + * Return 0 on success, negative on failure + **/ +int ixgbevf_setup_tx_resources(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring) +{ + struct pci_dev *pdev = adapter->pdev; + int size; + + size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count; + tx_ring->tx_buffer_info = vmalloc(size); + if (!tx_ring->tx_buffer_info) + goto err; + memset(tx_ring->tx_buffer_info, 0, size); + + /* round up to nearest 4K */ + tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); + tx_ring->size = ALIGN(tx_ring->size, 4096); + + tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size, + &tx_ring->dma); + if (!tx_ring->desc) + goto err; + + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + tx_ring->work_limit = tx_ring->count; + return 0; + +err: + vfree(tx_ring->tx_buffer_info); + tx_ring->tx_buffer_info = NULL; + hw_dbg(&adapter->hw, "Unable to allocate memory for the transmit " + "descriptor ring\n"); + return -ENOMEM; +} + +/** + * ixgbevf_setup_all_tx_resources - allocate all queues Tx resources + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or + * more of the rings is populated (while the rest are not). It is the + * callers duty to clean those orphaned rings. + * + * Return 0 on success, negative on failure + **/ +static int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_tx_queues; i++) { + err = ixgbevf_setup_tx_resources(adapter, &adapter->tx_ring[i]); + if (!err) + continue; + hw_dbg(&adapter->hw, + "Allocation for Tx Queue %u failed\n", i); + break; + } + + return err; +} + +/** + * ixgbevf_setup_rx_resources - allocate Rx resources (Descriptors) + * @adapter: board private structure + * @rx_ring: rx descriptor ring (for a specific queue) to setup + * + * Returns 0 on success, negative on failure + **/ +int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *rx_ring) +{ + struct pci_dev *pdev = adapter->pdev; + int size; + + size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; + rx_ring->rx_buffer_info = vmalloc(size); + if (!rx_ring->rx_buffer_info) { + hw_dbg(&adapter->hw, + "Unable to vmalloc buffer memory for " + "the receive descriptor ring\n"); + goto alloc_failed; + } + memset(rx_ring->rx_buffer_info, 0, size); + + /* Round up to nearest 4K */ + rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); + rx_ring->size = ALIGN(rx_ring->size, 4096); + + rx_ring->desc = pci_alloc_consistent(pdev, rx_ring->size, + &rx_ring->dma); + + if (!rx_ring->desc) { + hw_dbg(&adapter->hw, + "Unable to allocate memory for " + "the receive descriptor ring\n"); + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + goto alloc_failed; + } + + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + + return 0; +alloc_failed: + return -ENOMEM; +} + +/** + * ixgbevf_setup_all_rx_resources - allocate all queues Rx resources + * @adapter: board private structure + * + * If this function returns with an error, then it's possible one or + * more of the rings is populated (while the rest are not). It is the + * callers duty to clean those orphaned rings. + * + * Return 0 on success, negative on failure + **/ +static int ixgbevf_setup_all_rx_resources(struct ixgbevf_adapter *adapter) +{ + int i, err = 0; + + for (i = 0; i < adapter->num_rx_queues; i++) { + err = ixgbevf_setup_rx_resources(adapter, &adapter->rx_ring[i]); + if (!err) + continue; + hw_dbg(&adapter->hw, + "Allocation for Rx Queue %u failed\n", i); + break; + } + return err; +} + +/** + * ixgbevf_free_rx_resources - Free Rx Resources + * @adapter: board private structure + * @rx_ring: ring to clean the resources from + * + * Free all receive software resources + **/ +void ixgbevf_free_rx_resources(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *rx_ring) +{ + struct pci_dev *pdev = adapter->pdev; + + ixgbevf_clean_rx_ring(adapter, rx_ring); + + vfree(rx_ring->rx_buffer_info); + rx_ring->rx_buffer_info = NULL; + + pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); + + rx_ring->desc = NULL; +} + +/** + * ixgbevf_free_all_rx_resources - Free Rx Resources for All Queues + * @adapter: board private structure + * + * Free all receive software resources + **/ +static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) +{ + int i; + + for (i = 0; i < adapter->num_rx_queues; i++) + if (adapter->rx_ring[i].desc) + ixgbevf_free_rx_resources(adapter, + &adapter->rx_ring[i]); +} + +/** + * ixgbevf_open - Called when a network interface is made active + * @netdev: network interface device structure + * + * Returns 0 on success, negative value on failure + * + * The open entry point is called when a network interface is made + * active by the system (IFF_UP). At this point all resources needed + * for transmit and receive operations are allocated, the interrupt + * handler is registered with the OS, the watchdog timer is started, + * and the stack is notified that the interface is ready. + **/ +static int ixgbevf_open(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + int err; + + /* disallow open during test */ + if (test_bit(__IXGBEVF_TESTING, &adapter->state)) + return -EBUSY; + + if (hw->adapter_stopped) { + ixgbevf_reset(adapter); + /* if adapter is still stopped then PF isn't up and + * the vf can't start. */ + if (hw->adapter_stopped) { + err = IXGBE_ERR_MBX; + printk(KERN_ERR "Unable to start - perhaps the PF" + "Driver isn't up yet\n"); + goto err_setup_reset; + } + } + + /* allocate transmit descriptors */ + err = ixgbevf_setup_all_tx_resources(adapter); + if (err) + goto err_setup_tx; + + /* allocate receive descriptors */ + err = ixgbevf_setup_all_rx_resources(adapter); + if (err) + goto err_setup_rx; + + ixgbevf_configure(adapter); + + /* + * Map the Tx/Rx rings to the vectors we were allotted. + * if request_irq will be called in this function map_rings + * must be called *before* up_complete + */ + ixgbevf_map_rings_to_vectors(adapter); + + err = ixgbevf_up_complete(adapter); + if (err) + goto err_up; + + /* clear any pending interrupts, may auto mask */ + IXGBE_READ_REG(hw, IXGBE_VTEICR); + err = ixgbevf_request_irq(adapter); + if (err) + goto err_req_irq; + + ixgbevf_irq_enable(adapter, true, true); + + return 0; + +err_req_irq: + ixgbevf_down(adapter); +err_up: + ixgbevf_free_irq(adapter); +err_setup_rx: + ixgbevf_free_all_rx_resources(adapter); +err_setup_tx: + ixgbevf_free_all_tx_resources(adapter); + ixgbevf_reset(adapter); + +err_setup_reset: + + return err; +} + +/** + * ixgbevf_close - Disables a network interface + * @netdev: network interface device structure + * + * Returns 0, this is not allowed to fail + * + * The close entry point is called when an interface is de-activated + * by the OS. The hardware is still under the drivers control, but + * needs to be disabled. A global MAC reset is issued to stop the + * hardware, and all transmit and receive resources are freed. + **/ +static int ixgbevf_close(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + ixgbevf_down(adapter); + ixgbevf_free_irq(adapter); + + ixgbevf_free_all_tx_resources(adapter); + ixgbevf_free_all_rx_resources(adapter); + + return 0; +} + +static int ixgbevf_tso(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags, u8 *hdr_len) +{ + struct ixgbe_adv_tx_context_desc *context_desc; + unsigned int i; + int err; + struct ixgbevf_tx_buffer *tx_buffer_info; + u32 vlan_macip_lens = 0, type_tucmd_mlhl; + u32 mss_l4len_idx, l4len; + + if (skb_is_gso(skb)) { + if (skb_header_cloned(skb)) { + err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + if (err) + return err; + } + l4len = tcp_hdrlen(skb); + *hdr_len += l4len; + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = ip_hdr(skb); + iph->tot_len = 0; + iph->check = 0; + tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, + 0); + adapter->hw_tso_ctxt++; + } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + ipv6_hdr(skb)->payload_len = 0; + tcp_hdr(skb)->check = + ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, + 0, IPPROTO_TCP, 0); + adapter->hw_tso6_ctxt++; + } + + i = tx_ring->next_to_use; + + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + + /* VLAN MACLEN IPLEN */ + if (tx_flags & IXGBE_TX_FLAGS_VLAN) + vlan_macip_lens |= + (tx_flags & IXGBE_TX_FLAGS_VLAN_MASK); + vlan_macip_lens |= ((skb_network_offset(skb)) << + IXGBE_ADVTXD_MACLEN_SHIFT); + *hdr_len += skb_network_offset(skb); + vlan_macip_lens |= + (skb_transport_header(skb) - skb_network_header(skb)); + *hdr_len += + (skb_transport_header(skb) - skb_network_header(skb)); + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = 0; + + /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ + type_tucmd_mlhl = (IXGBE_TXD_CMD_DEXT | + IXGBE_ADVTXD_DTYP_CTXT); + + if (skb->protocol == htons(ETH_P_IP)) + type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; + type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl); + + /* MSS L4LEN IDX */ + mss_l4len_idx = + (skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT); + mss_l4len_idx |= (l4len << IXGBE_ADVTXD_L4LEN_SHIFT); + /* use index 1 for TSO */ + mss_l4len_idx |= (1 << IXGBE_ADVTXD_IDX_SHIFT); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); + + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return true; + } + + return false; +} + +static bool ixgbevf_tx_csum(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags) +{ + struct ixgbe_adv_tx_context_desc *context_desc; + unsigned int i; + struct ixgbevf_tx_buffer *tx_buffer_info; + u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0; + + if (skb->ip_summed == CHECKSUM_PARTIAL || + (tx_flags & IXGBE_TX_FLAGS_VLAN)) { + i = tx_ring->next_to_use; + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + context_desc = IXGBE_TX_CTXTDESC_ADV(*tx_ring, i); + + if (tx_flags & IXGBE_TX_FLAGS_VLAN) + vlan_macip_lens |= (tx_flags & + IXGBE_TX_FLAGS_VLAN_MASK); + vlan_macip_lens |= (skb_network_offset(skb) << + IXGBE_ADVTXD_MACLEN_SHIFT); + if (skb->ip_summed == CHECKSUM_PARTIAL) + vlan_macip_lens |= (skb_transport_header(skb) - + skb_network_header(skb)); + + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = 0; + + type_tucmd_mlhl |= (IXGBE_TXD_CMD_DEXT | + IXGBE_ADVTXD_DTYP_CTXT); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): + type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; + case __constant_htons(ETH_P_IPV6): + /* XXX what about other V6 headers?? */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; + default: + if (unlikely(net_ratelimit())) { + printk(KERN_WARNING + "partial checksum but " + "proto=%x!\n", + skb->protocol); + } + break; + } + } + + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl); + /* use index zero for tx checksum offload */ + context_desc->mss_l4len_idx = 0; + + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + adapter->hw_csum_tx_good++; + i++; + if (i == tx_ring->count) + i = 0; + tx_ring->next_to_use = i; + + return true; + } + + return false; +} + +static int ixgbevf_tx_map(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring, + struct sk_buff *skb, u32 tx_flags, + unsigned int first) +{ + struct pci_dev *pdev = adapter->pdev; + struct ixgbevf_tx_buffer *tx_buffer_info; + unsigned int len; + unsigned int total = skb->len; + unsigned int offset = 0, size, count = 0, i; + unsigned int nr_frags = skb_shinfo(skb)->nr_frags; + unsigned int f; + + i = tx_ring->next_to_use; + + len = min(skb_headlen(skb), total); + while (len) { + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + size = min(len, (unsigned int)IXGBE_MAX_DATA_PER_TXD); + + tx_buffer_info->length = size; + tx_buffer_info->mapped_as_page = false; + tx_buffer_info->dma = pci_map_single(adapter->pdev, + skb->data + offset, + size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, tx_buffer_info->dma)) + goto dma_error; + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + len -= size; + total -= size; + offset += size; + count++; + i++; + if (i == tx_ring->count) + i = 0; + } + + for (f = 0; f < nr_frags; f++) { + struct skb_frag_struct *frag; + + frag = &skb_shinfo(skb)->frags[f]; + len = min((unsigned int)frag->size, total); + offset = frag->page_offset; + + while (len) { + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + size = min(len, (unsigned int)IXGBE_MAX_DATA_PER_TXD); + + tx_buffer_info->length = size; + tx_buffer_info->dma = pci_map_page(adapter->pdev, + frag->page, + offset, + size, + PCI_DMA_TODEVICE); + tx_buffer_info->mapped_as_page = true; + if (pci_dma_mapping_error(pdev, tx_buffer_info->dma)) + goto dma_error; + tx_buffer_info->time_stamp = jiffies; + tx_buffer_info->next_to_watch = i; + + len -= size; + total -= size; + offset += size; + count++; + i++; + if (i == tx_ring->count) + i = 0; + } + if (total == 0) + break; + } + + if (i == 0) + i = tx_ring->count - 1; + else + i = i - 1; + tx_ring->tx_buffer_info[i].skb = skb; + tx_ring->tx_buffer_info[first].next_to_watch = i; + + return count; + +dma_error: + dev_err(&pdev->dev, "TX DMA map failed\n"); + + /* clear timestamp and dma mappings for failed tx_buffer_info map */ + tx_buffer_info->dma = 0; + tx_buffer_info->time_stamp = 0; + tx_buffer_info->next_to_watch = 0; + count--; + + /* clear timestamp and dma mappings for remaining portion of packet */ + while (count >= 0) { + count--; + i--; + if (i < 0) + i += tx_ring->count; + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + ixgbevf_unmap_and_free_tx_resource(adapter, tx_buffer_info); + } + + return count; +} + +static void ixgbevf_tx_queue(struct ixgbevf_adapter *adapter, + struct ixgbevf_ring *tx_ring, int tx_flags, + int count, u32 paylen, u8 hdr_len) +{ + union ixgbe_adv_tx_desc *tx_desc = NULL; + struct ixgbevf_tx_buffer *tx_buffer_info; + u32 olinfo_status = 0, cmd_type_len = 0; + unsigned int i; + + u32 txd_cmd = IXGBE_TXD_CMD_EOP | IXGBE_TXD_CMD_RS | IXGBE_TXD_CMD_IFCS; + + cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA; + + cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT; + + if (tx_flags & IXGBE_TX_FLAGS_VLAN) + cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE; + + if (tx_flags & IXGBE_TX_FLAGS_TSO) { + cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; + + olinfo_status |= IXGBE_TXD_POPTS_TXSM << + IXGBE_ADVTXD_POPTS_SHIFT; + + /* use index 1 context for tso */ + olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT); + if (tx_flags & IXGBE_TX_FLAGS_IPV4) + olinfo_status |= IXGBE_TXD_POPTS_IXSM << + IXGBE_ADVTXD_POPTS_SHIFT; + + } else if (tx_flags & IXGBE_TX_FLAGS_CSUM) + olinfo_status |= IXGBE_TXD_POPTS_TXSM << + IXGBE_ADVTXD_POPTS_SHIFT; + + olinfo_status |= ((paylen - hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT); + + i = tx_ring->next_to_use; + while (count--) { + tx_buffer_info = &tx_ring->tx_buffer_info[i]; + tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); + tx_desc->read.buffer_addr = cpu_to_le64(tx_buffer_info->dma); + tx_desc->read.cmd_type_len = + cpu_to_le32(cmd_type_len | tx_buffer_info->length); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); + i++; + if (i == tx_ring->count) + i = 0; + } + + tx_desc->read.cmd_type_len |= cpu_to_le32(txd_cmd); + + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + + tx_ring->next_to_use = i; + writel(i, adapter->hw.hw_addr + tx_ring->tail); +} + +static int __ixgbevf_maybe_stop_tx(struct net_device *netdev, + struct ixgbevf_ring *tx_ring, int size) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + netif_stop_subqueue(netdev, tx_ring->queue_index); + /* Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); + * but since that doesn't exist yet, just open code it. */ + smp_mb(); + + /* We need to check again in a case another CPU has just + * made room available. */ + if (likely(IXGBE_DESC_UNUSED(tx_ring) < size)) + return -EBUSY; + + /* A reprieve! - use start_queue because it doesn't call schedule */ + netif_start_subqueue(netdev, tx_ring->queue_index); + ++adapter->restart_queue; + return 0; +} + +static int ixgbevf_maybe_stop_tx(struct net_device *netdev, + struct ixgbevf_ring *tx_ring, int size) +{ + if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size)) + return 0; + return __ixgbevf_maybe_stop_tx(netdev, tx_ring, size); +} + +static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbevf_ring *tx_ring; + unsigned int first; + unsigned int tx_flags = 0; + u8 hdr_len = 0; + int r_idx = 0, tso; + int count = 0; + + unsigned int f; + + tx_ring = &adapter->tx_ring[r_idx]; + + if (adapter->vlgrp && vlan_tx_tag_present(skb)) { + tx_flags |= vlan_tx_tag_get(skb); + tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; + tx_flags |= IXGBE_TX_FLAGS_VLAN; + } + + /* four things can cause us to need a context descriptor */ + if (skb_is_gso(skb) || + (skb->ip_summed == CHECKSUM_PARTIAL) || + (tx_flags & IXGBE_TX_FLAGS_VLAN)) + count++; + + count += TXD_USE_COUNT(skb_headlen(skb)); + for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) + count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); + + if (ixgbevf_maybe_stop_tx(netdev, tx_ring, count)) { + adapter->tx_busy++; + return NETDEV_TX_BUSY; + } + + first = tx_ring->next_to_use; + + if (skb->protocol == htons(ETH_P_IP)) + tx_flags |= IXGBE_TX_FLAGS_IPV4; + tso = ixgbevf_tso(adapter, tx_ring, skb, tx_flags, &hdr_len); + if (tso < 0) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + if (tso) + tx_flags |= IXGBE_TX_FLAGS_TSO; + else if (ixgbevf_tx_csum(adapter, tx_ring, skb, tx_flags) && + (skb->ip_summed == CHECKSUM_PARTIAL)) + tx_flags |= IXGBE_TX_FLAGS_CSUM; + + ixgbevf_tx_queue(adapter, tx_ring, tx_flags, + ixgbevf_tx_map(adapter, tx_ring, skb, tx_flags, first), + skb->len, hdr_len); + + netdev->trans_start = jiffies; + + ixgbevf_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); + + return NETDEV_TX_OK; +} + +/** + * ixgbevf_get_stats - Get System Network Statistics + * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. + **/ +static struct net_device_stats *ixgbevf_get_stats(struct net_device *netdev) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + /* only return the current stats */ + return &adapter->net_stats; +} + +/** + * ixgbevf_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + **/ +static int ixgbevf_set_mac(struct net_device *netdev, void *p) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + struct ixgbe_hw *hw = &adapter->hw; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); + + if (hw->mac.ops.set_rar) + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + + return 0; +} + +/** + * ixgbevf_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + **/ +static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; + + /* MTU < 68 is an error and causes problems on some kernels */ + if ((new_mtu < 68) || (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE)) + return -EINVAL; + + hw_dbg(&adapter->hw, "changing MTU from %d to %d\n", + netdev->mtu, new_mtu); + /* must set new MTU before calling down or up */ + netdev->mtu = new_mtu; + + if (netif_running(netdev)) + ixgbevf_reinit_locked(adapter); + + return 0; +} + +static void ixgbevf_shutdown(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + ixgbevf_down(adapter); + ixgbevf_free_irq(adapter); + ixgbevf_free_all_tx_resources(adapter); + ixgbevf_free_all_rx_resources(adapter); + } + +#ifdef CONFIG_PM + pci_save_state(pdev); +#endif + + pci_disable_device(pdev); +} + +#ifdef HAVE_NET_DEVICE_OPS +static const struct net_device_ops ixgbe_netdev_ops = { + .ndo_open = &ixgbevf_open, + .ndo_stop = &ixgbevf_close, + .ndo_start_xmit = &ixgbevf_xmit_frame, + .ndo_get_stats = &ixgbevf_get_stats, + .ndo_set_rx_mode = &ixgbevf_set_rx_mode, + .ndo_set_multicast_list = &ixgbevf_set_rx_mode, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = &ixgbevf_set_mac, + .ndo_change_mtu = &ixgbevf_change_mtu, + .ndo_tx_timeout = &ixgbevf_tx_timeout, + .ndo_vlan_rx_register = &ixgbevf_vlan_rx_register, + .ndo_vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid, +}; +#endif /* HAVE_NET_DEVICE_OPS */ + +static void ixgbevf_assign_netdev_ops(struct net_device *dev) +{ + struct ixgbevf_adapter *adapter; + adapter = netdev_priv(dev); +#ifdef HAVE_NET_DEVICE_OPS + dev->netdev_ops = &ixgbe_netdev_ops; +#else /* HAVE_NET_DEVICE_OPS */ + dev->open = &ixgbevf_open; + dev->stop = &ixgbevf_close; + + dev->hard_start_xmit = &ixgbevf_xmit_frame; + + dev->get_stats = &ixgbevf_get_stats; + dev->set_multicast_list = &ixgbevf_set_rx_mode; + dev->set_mac_address = &ixgbevf_set_mac; + dev->change_mtu = &ixgbevf_change_mtu; + dev->tx_timeout = &ixgbevf_tx_timeout; + dev->vlan_rx_register = &ixgbevf_vlan_rx_register; + dev->vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid; + dev->vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid; +#endif /* HAVE_NET_DEVICE_OPS */ + ixgbevf_set_ethtool_ops(dev); + dev->watchdog_timeo = 5 * HZ; +} + +/** + * ixgbevf_probe - Device Initialization Routine + * @pdev: PCI device information struct + * @ent: entry in ixgbevf_pci_tbl + * + * Returns 0 on success, negative on failure + * + * ixgbevf_probe initializes an adapter identified by a pci_dev structure. + * The OS initialization, configuring of the adapter private structure, + * and a hardware reset occur. + **/ +static int __devinit ixgbevf_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct ixgbevf_adapter *adapter = NULL; + struct ixgbe_hw *hw = NULL; + const struct ixgbevf_info *ii = ixgbevf_info_tbl[ent->driver_data]; + static int cards_found; + int err, pci_using_dac; + + err = pci_enable_device(pdev); + if (err) + return err; + + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && + !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + pci_using_dac = 1; + } else { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { + err = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(32)); + if (err) { + dev_err(&pdev->dev, "No usable DMA " + "configuration, aborting\n"); + goto err_dma; + } + } + pci_using_dac = 0; + } + + err = pci_request_regions(pdev, ixgbevf_driver_name); + if (err) { + dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err); + goto err_pci_reg; + } + + pci_set_master(pdev); + +#ifdef HAVE_TX_MQ + netdev = alloc_etherdev_mq(sizeof(struct ixgbevf_adapter), + MAX_TX_QUEUES); +#else + netdev = alloc_etherdev(sizeof(struct ixgbevf_adapter)); +#endif + if (!netdev) { + err = -ENOMEM; + goto err_alloc_etherdev; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + + pci_set_drvdata(pdev, netdev); + adapter = netdev_priv(netdev); + + adapter->netdev = netdev; + adapter->pdev = pdev; + hw = &adapter->hw; + hw->back = adapter; + adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1; + + /* + * call save state here in standalone driver because it relies on + * adapter struct to exist, and needs to call netdev_priv + */ + pci_save_state(pdev); + + hw->hw_addr = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (!hw->hw_addr) { + err = -EIO; + goto err_ioremap; + } + + ixgbevf_assign_netdev_ops(netdev); + + adapter->bd_number = cards_found; + + /* Setup hw api */ + memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops)); + hw->mac.type = ii->mac; + + memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops, + sizeof(struct ixgbe_mac_operations)); + + adapter->flags &= ~IXGBE_FLAG_RX_PS_CAPABLE; + adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED; + adapter->flags |= IXGBE_FLAG_RX_1BUF_CAPABLE; + + /* setup the private structure */ + err = ixgbevf_sw_init(adapter); + + ixgbevf_init_last_counter_stats(adapter); + +#ifdef MAX_SKB_FRAGS + netdev->features = NETIF_F_SG | + NETIF_F_IP_CSUM | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER; + + netdev->features |= NETIF_F_IPV6_CSUM; + netdev->features |= NETIF_F_TSO; + netdev->features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_TSO; + netdev->vlan_features |= NETIF_F_TSO6; + netdev->vlan_features |= NETIF_F_IP_CSUM; + netdev->vlan_features |= NETIF_F_SG; + + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + +#endif /* MAX_SKB_FRAGS */ + + /* The HW MAC address was set and/or determined in sw_init */ + memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); + memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); + + if (!is_valid_ether_addr(netdev->dev_addr)) { + printk(KERN_ERR "invalid MAC address\n"); + err = -EIO; + goto err_sw_init; + } + + init_timer(&adapter->watchdog_timer); + adapter->watchdog_timer.function = &ixgbevf_watchdog; + adapter->watchdog_timer.data = (unsigned long)adapter; + + INIT_WORK(&adapter->reset_task, ixgbevf_reset_task); + INIT_WORK(&adapter->watchdog_task, ixgbevf_watchdog_task); + + err = ixgbevf_init_interrupt_scheme(adapter); + if (err) + goto err_sw_init; + + /* pick up the PCI bus settings for reporting later */ + if (hw->mac.ops.get_bus_info) + hw->mac.ops.get_bus_info(hw); + + + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + + strcpy(netdev->name, "eth%d"); + + err = register_netdev(netdev); + if (err) + goto err_register; + + adapter->netdev_registered = true; + + /* print the MAC address */ + hw_dbg(hw, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + netdev->dev_addr[0], + netdev->dev_addr[1], + netdev->dev_addr[2], + netdev->dev_addr[3], + netdev->dev_addr[4], + netdev->dev_addr[5]); + + hw_dbg(hw, "MAC: %d\n", hw->mac.type); + + hw_dbg(hw, "LRO is disabled \n"); + + hw_dbg(hw, "Intel(R) 82599 Virtual Function\n"); + cards_found++; + return 0; + +err_register: +err_sw_init: + ixgbevf_reset_interrupt_capability(adapter); + iounmap(hw->hw_addr); +err_ioremap: + free_netdev(netdev); +err_alloc_etherdev: + pci_release_regions(pdev); +err_pci_reg: +err_dma: + pci_disable_device(pdev); + return err; +} + +/** + * ixgbevf_remove - Device Removal Routine + * @pdev: PCI device information struct + * + * ixgbevf_remove is called by the PCI subsystem to alert the driver + * that it should release a PCI device. The could be caused by a + * Hot-Plug event, or because the driver is going to be removed from + * memory. + **/ +static void __devexit ixgbevf_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbevf_adapter *adapter = netdev_priv(netdev); + + set_bit(__IXGBEVF_DOWN, &adapter->state); + + del_timer_sync(&adapter->watchdog_timer); + + cancel_work_sync(&adapter->watchdog_task); + + flush_scheduled_work(); + + if (adapter->netdev_registered) { + unregister_netdev(netdev); + adapter->netdev_registered = false; + } + + ixgbevf_reset_interrupt_capability(adapter); + + iounmap(adapter->hw.hw_addr); + pci_release_regions(pdev); + + hw_dbg(&adapter->hw, "Remove complete\n"); + + kfree(adapter->tx_ring); + kfree(adapter->rx_ring); + + free_netdev(netdev); + + pci_disable_device(pdev); +} + +static struct pci_driver ixgbevf_driver = { + .name = ixgbevf_driver_name, + .id_table = ixgbevf_pci_tbl, + .probe = ixgbevf_probe, + .remove = __devexit_p(ixgbevf_remove), + .shutdown = ixgbevf_shutdown, +}; + +/** + * ixgbe_init_module - Driver Registration Routine + * + * ixgbe_init_module is the first routine called when the driver is + * loaded. All it does is register with the PCI subsystem. + **/ +static int __init ixgbevf_init_module(void) +{ + int ret; + printk(KERN_INFO "ixgbevf: %s - version %s\n", ixgbevf_driver_string, + ixgbevf_driver_version); + + printk(KERN_INFO "%s\n", ixgbevf_copyright); + + ret = pci_register_driver(&ixgbevf_driver); + return ret; +} + +module_init(ixgbevf_init_module); + +/** + * ixgbe_exit_module - Driver Exit Cleanup Routine + * + * ixgbe_exit_module is called just before the driver is removed + * from memory. + **/ +static void __exit ixgbevf_exit_module(void) +{ + pci_unregister_driver(&ixgbevf_driver); +} + +#ifdef DEBUG +/** + * ixgbe_get_hw_dev_name - return device name string + * used by hardware layer to print debugging information + **/ +char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw) +{ + struct ixgbevf_adapter *adapter = hw->back; + return adapter->netdev->name; +} + +#endif +module_exit(ixgbevf_exit_module); + +/* ixgbevf_main.c */ -- cgit v1.2.3 From 0d3592fa28965a3083d670b430bb59c19efb6abe Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:24:31 +0000 Subject: ixgbevf: Driver Makefile 82599 Virtual Function Device Driver Makefile Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/Makefile | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 drivers/net/ixgbevf/Makefile diff --git a/drivers/net/ixgbevf/Makefile b/drivers/net/ixgbevf/Makefile new file mode 100644 index 000000000000..dd4e0d27e8cc --- /dev/null +++ b/drivers/net/ixgbevf/Makefile @@ -0,0 +1,38 @@ +################################################################################ +# +# Intel 82599 Virtual Function driver +# Copyright(c) 1999 - 2009 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# e1000-devel Mailing List +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# +################################################################################ + +# +# Makefile for the Intel(R) 82599 VF ethernet driver +# + +obj-$(CONFIG_IXGBEVF) += ixgbevf.o + +ixgbevf-objs := vf.o \ + mbx.o \ + ethtool.o \ + ixgbevf_main.o + -- cgit v1.2.3 From ecc6703cbb2bb648c7345c652a704f7af56322b8 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:24:50 +0000 Subject: ixgbevf: Kconfig, Makefile and Documentation Modifications for the Kconfig and network device Makefile to add the ixgbevf driver module to the kernel plus basic driver documentation. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- Documentation/networking/ixgbevf.txt | 90 ++++++++++++++++++++++++++++++++++++ drivers/net/Kconfig | 22 +++++++++ drivers/net/Makefile | 1 + 3 files changed, 113 insertions(+) create mode 100755 Documentation/networking/ixgbevf.txt diff --git a/Documentation/networking/ixgbevf.txt b/Documentation/networking/ixgbevf.txt new file mode 100755 index 000000000000..19015de6725f --- /dev/null +++ b/Documentation/networking/ixgbevf.txt @@ -0,0 +1,90 @@ +Linux* Base Driver for Intel(R) Network Connection +================================================== + +November 24, 2009 + +Contents +======== + +- In This Release +- Identifying Your Adapter +- Known Issues/Troubleshooting +- Support + +In This Release +=============== + +This file describes the ixgbevf Linux* Base Driver for Intel Network +Connection. + +The ixgbevf driver supports 82599-based virtual function devices that can only +be activated on kernels with CONFIG_PCI_IOV enabled. + +The ixgbevf driver supports virtual functions generated by the ixgbe driver +with a max_vfs value of 1 or greater. + +The guest OS loading the ixgbevf driver must support MSI-X interrupts. + +VLANs: There is a limit of a total of 32 shared VLANs to 1 or more VFs. + +Identifying Your Adapter +======================== + +For more information on how to identify your adapter, go to the Adapter & +Driver ID Guide at: + + http://support.intel.com/support/network/sb/CS-008441.htm + +Known Issues/Troubleshooting +============================ + + Unloading Physical Function (PF) Driver Causes System Reboots When VM is + Running and VF is Loaded on the VM + ------------------------------------------------------------------------ + Do not unload the PF driver (ixgbe) while VFs are assigned to guests. + +Support +======= + +For general information, go to the Intel support website at: + + http://support.intel.com + +or the Intel Wired Networking project hosted by Sourceforge at: + + http://sourceforge.net/projects/e1000 + +If an issue is identified with the released source code on the supported +kernel with a supported adapter, email the specific information related +to the issue to e1000-devel@lists.sf.net + +License +======= + +Intel 10 Gigabit Linux driver. +Copyright(c) 1999 - 2009 Intel Corporation. + +This program is free software; you can redistribute it and/or modify it +under the terms and conditions of the GNU General Public License, +version 2, as published by the Free Software Foundation. + +This program is distributed in the hope it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + +The full GNU General Public License is included in this distribution in +the file called "COPYING". + +Trademarks +========== + +Intel, Itanium, and Pentium are trademarks or registered trademarks of +Intel Corporation or its subsidiaries in the United States and other +countries. + +* Other names and brands may be claimed as the property of others. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dd9a09c72dff..5be6a2376f4f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2618,6 +2618,28 @@ config IXGBE_DCB If unsure, say N. +config IXGBEVF + tristate "Intel(R) 82599 Virtual Function Ethernet support" + depends on PCI_MSI + ---help--- + This driver supports Intel(R) 82599 virtual functions. For more + information on how to identify your adapter, go to the Adapter & + Driver ID Guide at: + + + + For general information and support, go to the Intel support + website at: + + + + More specific information on configuring the driver is in + . + + To compile this driver as a module, choose M here. The module + will be called ixgbevf. MSI-X interrupt support is required + for this driver to work correctly. + config IXGB tristate "Intel(R) PRO/10GbE support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index ad1346dd9da9..6746e8b8bdfc 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/ obj-$(CONFIG_IGB) += igb/ obj-$(CONFIG_IGBVF) += igbvf/ obj-$(CONFIG_IXGBE) += ixgbe/ +obj-$(CONFIG_IXGBEVF) += ixgbevf/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_IP1000) += ipg.o obj-$(CONFIG_CHELSIO_T1) += chelsio/ -- cgit v1.2.3 From 10ca132c41ecc1b55bc22667493ab75c4f6eec0d Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:25:10 +0000 Subject: ixgbe: Mailbox header and code module The 82599 virtual function device and the master 82599 physical function device implement a mailbox utility for communication between the devices using some SRAM scratch memory and a doorbell/answering mechanism enabled via interrupt and/or polling. This C module and accompanying header file implement the base functions for use of this feature. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_mbx.c | 479 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_mbx.h | 96 +++++++++ 2 files changed, 575 insertions(+) create mode 100644 drivers/net/ixgbe/ixgbe_mbx.c create mode 100644 drivers/net/ixgbe/ixgbe_mbx.h diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ixgbe/ixgbe_mbx.c new file mode 100644 index 000000000000..d75f9148eb1f --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_mbx.c @@ -0,0 +1,479 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include +#include +#include "ixgbe_type.h" +#include "ixgbe_common.h" +#include "ixgbe_mbx.h" + +/** + * ixgbe_read_mbx - Reads a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to read + * + * returns SUCCESS if it successfuly read message from buffer + **/ +s32 ixgbe_read_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + /* limit read to size of mailbox */ + if (size > mbx->size) + size = mbx->size; + + if (mbx->ops.read) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * ixgbe_write_mbx - Write a message to the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +s32 ixgbe_write_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = 0; + + if (size > mbx->size) + ret_val = IXGBE_ERR_MBX; + + else if (mbx->ops.write) + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + return ret_val; +} + +/** + * ixgbe_check_for_msg - checks to see if someone sent us mail + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 ixgbe_check_for_msg(struct ixgbe_hw *hw, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_msg) + ret_val = mbx->ops.check_for_msg(hw, mbx_id); + + return ret_val; +} + +/** + * ixgbe_check_for_ack - checks to see if someone sent us ACK + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 ixgbe_check_for_ack(struct ixgbe_hw *hw, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_ack) + ret_val = mbx->ops.check_for_ack(hw, mbx_id); + + return ret_val; +} + +/** + * ixgbe_check_for_rst - checks to see if other side has reset + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to check + * + * returns SUCCESS if the Status bit was found or else ERR_MBX + **/ +s32 ixgbe_check_for_rst(struct ixgbe_hw *hw, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (mbx->ops.check_for_rst) + ret_val = mbx->ops.check_for_rst(hw, mbx_id); + + return ret_val; +} + +/** + * ixgbe_poll_for_msg - Wait for message notification + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification + **/ +static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_msg) + goto out; + + while (countdown && mbx->ops.check_for_msg(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; +out: + return countdown ? 0 : IXGBE_ERR_MBX; +} + +/** + * ixgbe_poll_for_ack - Wait for message acknowledgement + * @hw: pointer to the HW structure + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message acknowledgement + **/ +static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + int countdown = mbx->timeout; + + if (!countdown || !mbx->ops.check_for_ack) + goto out; + + while (countdown && mbx->ops.check_for_ack(hw, mbx_id)) { + countdown--; + if (!countdown) + break; + udelay(mbx->usec_delay); + } + + /* if we failed, all future posted messages fail until reset */ + if (!countdown) + mbx->timeout = 0; +out: + return countdown ? 0 : IXGBE_ERR_MBX; +} + +/** + * ixgbe_read_posted_mbx - Wait for message notification and receive message + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully received a message notification and + * copied it into the receive buffer. + **/ +s32 ixgbe_read_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + if (!mbx->ops.read) + goto out; + + ret_val = ixgbe_poll_for_msg(hw, mbx_id); + + /* if ack received read message, otherwise we timed out */ + if (!ret_val) + ret_val = mbx->ops.read(hw, msg, size, mbx_id); +out: + return ret_val; +} + +/** + * ixgbe_write_posted_mbx - Write a message to the mailbox, wait for ack + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @mbx_id: id of mailbox to write + * + * returns SUCCESS if it successfully copied message into the buffer and + * received an ack to that message within delay * timeout period + **/ +s32 ixgbe_write_posted_mbx(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 mbx_id) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + s32 ret_val = IXGBE_ERR_MBX; + + /* exit if either we can't write or there isn't a defined timeout */ + if (!mbx->ops.write || !mbx->timeout) + goto out; + + /* send msg */ + ret_val = mbx->ops.write(hw, msg, size, mbx_id); + + /* if msg sent wait until we receive an ack */ + if (!ret_val) + ret_val = ixgbe_poll_for_ack(hw, mbx_id); +out: + return ret_val; +} + +/** + * ixgbe_init_mbx_ops_generic - Initialize MB function pointers + * @hw: pointer to the HW structure + * + * Setup the mailbox read and write message function pointers + **/ +void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + mbx->ops.read_posted = ixgbe_read_posted_mbx; + mbx->ops.write_posted = ixgbe_write_posted_mbx; +} + +static s32 ixgbe_check_for_bit_pf(struct ixgbe_hw *hw, u32 mask, s32 index) +{ + u32 mbvficr = IXGBE_READ_REG(hw, IXGBE_MBVFICR(index)); + s32 ret_val = IXGBE_ERR_MBX; + + if (mbvficr & mask) { + ret_val = 0; + IXGBE_WRITE_REG(hw, IXGBE_MBVFICR(index), mask); + } + + return ret_val; +} + +/** + * ixgbe_check_for_msg_pf - checks to see if the VF has sent mail + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 ixgbe_check_for_msg_pf(struct ixgbe_hw *hw, u16 vf_number) +{ + s32 ret_val = IXGBE_ERR_MBX; + s32 index = IXGBE_MBVFICR_INDEX(vf_number); + u32 vf_bit = vf_number % 16; + + if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFREQ_VF1 << vf_bit, + index)) { + ret_val = 0; + hw->mbx.stats.reqs++; + } + + return ret_val; +} + +/** + * ixgbe_check_for_ack_pf - checks to see if the VF has ACKed + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 ixgbe_check_for_ack_pf(struct ixgbe_hw *hw, u16 vf_number) +{ + s32 ret_val = IXGBE_ERR_MBX; + s32 index = IXGBE_MBVFICR_INDEX(vf_number); + u32 vf_bit = vf_number % 16; + + if (!ixgbe_check_for_bit_pf(hw, IXGBE_MBVFICR_VFACK_VF1 << vf_bit, + index)) { + ret_val = 0; + hw->mbx.stats.acks++; + } + + return ret_val; +} + +/** + * ixgbe_check_for_rst_pf - checks to see if the VF has reset + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * returns SUCCESS if the VF has set the Status bit or else ERR_MBX + **/ +static s32 ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number) +{ + u32 reg_offset = (vf_number < 32) ? 0 : 1; + u32 vf_shift = vf_number % 32; + u32 vflre = 0; + s32 ret_val = IXGBE_ERR_MBX; + + if (hw->mac.type == ixgbe_mac_82599EB) + vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset)); + + if (vflre & (1 << vf_shift)) { + ret_val = 0; + IXGBE_WRITE_REG(hw, IXGBE_VFLREC(reg_offset), (1 << vf_shift)); + hw->mbx.stats.rsts++; + } + + return ret_val; +} + +/** + * ixgbe_obtain_mbx_lock_pf - obtain mailbox lock + * @hw: pointer to the HW structure + * @vf_number: the VF index + * + * return SUCCESS if we obtained the mailbox lock + **/ +static s32 ixgbe_obtain_mbx_lock_pf(struct ixgbe_hw *hw, u16 vf_number) +{ + s32 ret_val = IXGBE_ERR_MBX; + u32 p2v_mailbox; + + /* Take ownership of the buffer */ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_PFU); + + /* reserve mailbox for vf use */ + p2v_mailbox = IXGBE_READ_REG(hw, IXGBE_PFMAILBOX(vf_number)); + if (p2v_mailbox & IXGBE_PFMAILBOX_PFU) + ret_val = 0; + + return ret_val; +} + +/** + * ixgbe_write_mbx_pf - Places a message in the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * returns SUCCESS if it successfully copied message into the buffer + **/ +static s32 ixgbe_write_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_number) +{ + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_write; + + /* flush msg and acks as we are overwriting the message buffer */ + ixgbe_check_for_msg_pf(hw, vf_number); + ixgbe_check_for_ack_pf(hw, vf_number); + + /* copy the caller specified message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i, msg[i]); + + /* Interrupt VF to tell it a message has been sent and release buffer*/ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_STS); + + /* update stats */ + hw->mbx.stats.msgs_tx++; + +out_no_write: + return ret_val; + +} + +/** + * ixgbe_read_mbx_pf - Read a message from the mailbox + * @hw: pointer to the HW structure + * @msg: The message buffer + * @size: Length of buffer + * @vf_number: the VF index + * + * This function copies a message from the mailbox buffer to the caller's + * memory buffer. The presumption is that the caller knows that there was + * a message due to a VF request so no polling for message is needed. + **/ +static s32 ixgbe_read_mbx_pf(struct ixgbe_hw *hw, u32 *msg, u16 size, + u16 vf_number) +{ + s32 ret_val; + u16 i; + + /* lock the mailbox to prevent pf/vf race condition */ + ret_val = ixgbe_obtain_mbx_lock_pf(hw, vf_number); + if (ret_val) + goto out_no_read; + + /* copy the message to the mailbox memory buffer */ + for (i = 0; i < size; i++) + msg[i] = IXGBE_READ_REG_ARRAY(hw, IXGBE_PFMBMEM(vf_number), i); + + /* Acknowledge the message and release buffer */ + IXGBE_WRITE_REG(hw, IXGBE_PFMAILBOX(vf_number), IXGBE_PFMAILBOX_ACK); + + /* update stats */ + hw->mbx.stats.msgs_rx++; + +out_no_read: + return ret_val; +} + +/** + * ixgbe_init_mbx_params_pf - set initial values for pf mailbox + * @hw: pointer to the HW structure + * + * Initializes the hw->mbx struct to correct values for pf mailbox + */ +void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + + if (hw->mac.type != ixgbe_mac_82599EB) + return; + + mbx->timeout = 0; + mbx->usec_delay = 0; + + mbx->size = IXGBE_VFMAILBOX_SIZE; + + mbx->stats.msgs_tx = 0; + mbx->stats.msgs_rx = 0; + mbx->stats.reqs = 0; + mbx->stats.acks = 0; + mbx->stats.rsts = 0; +} + +struct ixgbe_mbx_operations mbx_ops_82599 = { + .read = ixgbe_read_mbx_pf, + .write = ixgbe_write_mbx_pf, + .read_posted = ixgbe_read_posted_mbx, + .write_posted = ixgbe_write_posted_mbx, + .check_for_msg = ixgbe_check_for_msg_pf, + .check_for_ack = ixgbe_check_for_ack_pf, + .check_for_rst = ixgbe_check_for_rst_pf, +}; + diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h new file mode 100644 index 000000000000..be7ab3309ab7 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_mbx.h @@ -0,0 +1,96 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_MBX_H_ +#define _IXGBE_MBX_H_ + +#include "ixgbe_type.h" + +#define IXGBE_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */ +#define IXGBE_ERR_MBX -100 + +#define IXGBE_VFMAILBOX 0x002FC +#define IXGBE_VFMBMEM 0x00200 + +#define IXGBE_PFMAILBOX(x) (0x04B00 + (4 * x)) +#define IXGBE_PFMBMEM(vfn) (0x13000 + (64 * vfn)) + +#define IXGBE_PFMAILBOX_STS 0x00000001 /* Initiate message send to VF */ +#define IXGBE_PFMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */ +#define IXGBE_PFMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */ +#define IXGBE_PFMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */ +#define IXGBE_PFMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */ + +#define IXGBE_MBVFICR_VFREQ_MASK 0x0000FFFF /* bits for VF messages */ +#define IXGBE_MBVFICR_VFREQ_VF1 0x00000001 /* bit for VF 1 message */ +#define IXGBE_MBVFICR_VFACK_MASK 0xFFFF0000 /* bits for VF acks */ +#define IXGBE_MBVFICR_VFACK_VF1 0x00010000 /* bit for VF 1 ack */ + + +/* If it's a IXGBE_VF_* msg then it originates in the VF and is sent to the + * PF. The reverse is true if it is IXGBE_PF_*. + * Message ACK's are the value or'd with 0xF0000000 + */ +#define IXGBE_VT_MSGTYPE_ACK 0x80000000 /* Messages below or'd with + * this are the ACK */ +#define IXGBE_VT_MSGTYPE_NACK 0x40000000 /* Messages below or'd with + * this are the NACK */ +#define IXGBE_VT_MSGTYPE_CTS 0x20000000 /* Indicates that VF is still + clear to send requests */ +#define IXGBE_VT_MSGINFO_SHIFT 16 +/* bits 23:16 are used for exra info for certain messages */ +#define IXGBE_VT_MSGINFO_MASK (0xFF << IXGBE_VT_MSGINFO_SHIFT) + +#define IXGBE_VF_RESET 0x01 /* VF requests reset */ +#define IXGBE_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */ +#define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ +#define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ +#define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ + +/* length of permanent address message returned from PF */ +#define IXGBE_VF_PERMADDR_MSG_LEN 4 +/* word in permanent address message with the current multicast type */ +#define IXGBE_VF_MC_TYPE_WORD 3 + +#define IXGBE_PF_CONTROL_MSG 0x0100 /* PF control message */ + +#define IXGBE_VF_MBX_INIT_TIMEOUT 2000 /* number of retries on mailbox */ +#define IXGBE_VF_MBX_INIT_DELAY 500 /* microseconds between retries */ + +s32 ixgbe_read_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_read_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_write_posted_mbx(struct ixgbe_hw *, u32 *, u16, u16); +s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16); +s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16); +s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16); +void ixgbe_init_mbx_ops_generic(struct ixgbe_hw *hw); +void ixgbe_init_mbx_params_pf(struct ixgbe_hw *); + +extern struct ixgbe_mbx_operations mbx_ops_82599; + +#endif /* _IXGBE_MBX_H_ */ -- cgit v1.2.3 From 7f870475c8f102469df44a86387a03cb23e79b90 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:25:29 +0000 Subject: ixgbe: Add SR-IOV register, structure and bit defines This patch adds register definitions, bit definitions and structures used by the driver to support SR-IOV features of the 82599 controller. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 31 ++++++++++++++++++++++-- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbe/ixgbe_type.h | 53 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 8da8eb535084..ed735857695c 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -98,6 +98,23 @@ #define IXGBE_MAX_RSC_INT_RATE 162760 +#define IXGBE_MAX_VF_MC_ENTRIES 30 +#define IXGBE_MAX_VF_FUNCTIONS 64 +#define IXGBE_MAX_VFTA_ENTRIES 128 +#define MAX_EMULATION_MAC_ADDRS 16 +#define VMDQ_P(p) ((p) + adapter->num_vfs) + +struct vf_data_storage { + unsigned char vf_mac_addresses[ETH_ALEN]; + u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES]; + u16 num_vf_mc_hashes; + u16 default_vf_vlan_id; + u16 vlans_enabled; + unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN]; + bool clear_to_send; + int rar; +}; + /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer */ struct ixgbe_tx_buffer { @@ -171,7 +188,7 @@ struct ixgbe_ring { enum ixgbe_ring_f_enum { RING_F_NONE = 0, RING_F_DCB, - RING_F_VMDQ, + RING_F_VMDQ, /* SR-IOV uses the same ring feature */ RING_F_RSS, RING_F_FDIR, #ifdef IXGBE_FCOE @@ -183,7 +200,7 @@ enum ixgbe_ring_f_enum { #define IXGBE_MAX_DCB_INDICES 8 #define IXGBE_MAX_RSS_INDICES 16 -#define IXGBE_MAX_VMDQ_INDICES 16 +#define IXGBE_MAX_VMDQ_INDICES 64 #define IXGBE_MAX_FDIR_INDICES 64 #ifdef IXGBE_FCOE #define IXGBE_MAX_FCOE_INDICES 8 @@ -288,6 +305,8 @@ struct ixgbe_adapter { /* RX */ struct ixgbe_ring *rx_ring ____cacheline_aligned_in_smp; /* One per active queue */ int num_rx_queues; + int num_rx_pools; /* == num_rx_queues in 82598 */ + int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */ u64 hw_csum_rx_error; u64 hw_rx_no_dma_resources; u64 non_eop_descs; @@ -330,6 +349,8 @@ struct ixgbe_adapter { #define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27) #define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 28) #define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29) +#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 30) +#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 31) u32 flags2; #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) @@ -379,6 +400,11 @@ struct ixgbe_adapter { u64 rsc_total_flush; u32 wol; u16 eeprom_version; + + /* SR-IOV */ + DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); + unsigned int num_vfs; + struct vf_data_storage *vfinfo; }; enum ixbge_state_t { @@ -440,6 +466,7 @@ extern s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte); extern s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type); +extern void ixgbe_set_rx_mode(struct net_device *netdev); #ifdef IXGBE_FCOE extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter); extern int ixgbe_fso(struct ixgbe_adapter *adapter, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b2f11d45e225..233c3917427e 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2409,7 +2409,7 @@ static u8 *ixgbe_addr_list_itr(struct ixgbe_hw *hw, u8 **mc_addr_ptr, u32 *vmdq) * responsible for configuring the hardware for proper unicast, multicast and * promiscuous mode. **/ -static void ixgbe_set_rx_mode(struct net_device *netdev) +void ixgbe_set_rx_mode(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 84650c6ebe03..ec8ad182e2f5 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -277,6 +277,7 @@ #define IXGBE_DTXCTL 0x07E00 #define IXGBE_DMATXCTL 0x04A80 +#define IXGBE_PFDTXGSWC 0x08220 #define IXGBE_DTXMXSZRQ 0x08100 #define IXGBE_DTXTCPFLGL 0x04A88 #define IXGBE_DTXTCPFLGH 0x04A8C @@ -287,6 +288,8 @@ #define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */ #define IXGBE_DMATXCTL_GDV 0x8 /* Global Double VLAN */ #define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */ + +#define IXGBE_PFDTXGSWC_VT_LBEN 0x1 /* Local L2 VT switch enable */ #define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */ /* Tx DCA Control register : 128 of these (0-127) */ #define IXGBE_DCA_TXCTRL_82599(_i) (0x0600C + ((_i) * 0x40)) @@ -497,6 +500,7 @@ /* DCB registers */ #define IXGBE_RTRPCS 0x02430 #define IXGBE_RTTDCS 0x04900 +#define IXGBE_RTTDCS_ARBDIS 0x00000040 /* DCB arbiter disable */ #define IXGBE_RTTPCS 0x0CD00 #define IXGBE_RTRUP2TC 0x03020 #define IXGBE_RTTUP2TC 0x0C800 @@ -730,6 +734,13 @@ #define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000 #define IXGBE_GCR_CAP_VER2 0x00040000 +#define IXGBE_GCR_EXT_MSIX_EN 0x80000000 +#define IXGBE_GCR_EXT_VT_MODE_16 0x00000001 +#define IXGBE_GCR_EXT_VT_MODE_32 0x00000002 +#define IXGBE_GCR_EXT_VT_MODE_64 0x00000003 +#define IXGBE_GCR_EXT_SRIOV (IXGBE_GCR_EXT_MSIX_EN | \ + IXGBE_GCR_EXT_VT_MODE_64) + /* Time Sync Registers */ #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */ #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */ @@ -1065,6 +1076,8 @@ /* VFRE bitmask */ #define IXGBE_VFRE_ENABLE_ALL 0xFFFFFFFF +#define IXGBE_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */ + /* RDHMPN and TDHMPN bitmasks */ #define IXGBE_RDHMPN_RDICADDR 0x007FF800 #define IXGBE_RDHMPN_RDICRDREQ 0x00800000 @@ -1295,6 +1308,7 @@ /* VLAN pool filtering masks */ #define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */ #define IXGBE_VLVF_ENTRIES 64 +#define IXGBE_VLVF_VLANID_MASK 0x00000FFF #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ @@ -1843,6 +1857,12 @@ #define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */ #define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT +/* SR-IOV specific macros */ +#define IXGBE_MBVFICR_INDEX(vf_number) (vf_number >> 4) +#define IXGBE_MBVFICR(_i) (0x00710 + (_i * 4)) +#define IXGBE_VFLRE(_i) (((_i & 1) ? 0x001C0 : 0x00600)) +#define IXGBE_VFLREC(_i) (0x00700 + (_i * 4)) + /* Little Endian defines */ #ifndef __le32 #define __le32 u32 @@ -2463,6 +2483,37 @@ struct ixgbe_phy_info { bool multispeed_fiber; }; +#include "ixgbe_mbx.h" + +struct ixgbe_mbx_operations { + s32 (*init_params)(struct ixgbe_hw *hw); + s32 (*read)(struct ixgbe_hw *, u32 *, u16, u16); + s32 (*write)(struct ixgbe_hw *, u32 *, u16, u16); + s32 (*read_posted)(struct ixgbe_hw *, u32 *, u16, u16); + s32 (*write_posted)(struct ixgbe_hw *, u32 *, u16, u16); + s32 (*check_for_msg)(struct ixgbe_hw *, u16); + s32 (*check_for_ack)(struct ixgbe_hw *, u16); + s32 (*check_for_rst)(struct ixgbe_hw *, u16); +}; + +struct ixgbe_mbx_stats { + u32 msgs_tx; + u32 msgs_rx; + + u32 acks; + u32 reqs; + u32 rsts; +}; + +struct ixgbe_mbx_info { + struct ixgbe_mbx_operations ops; + struct ixgbe_mbx_stats stats; + u32 timeout; + u32 usec_delay; + u32 v2p_mailbox; + u16 size; +}; + struct ixgbe_hw { u8 __iomem *hw_addr; void *back; @@ -2472,6 +2523,7 @@ struct ixgbe_hw { struct ixgbe_phy_info phy; struct ixgbe_eeprom_info eeprom; struct ixgbe_bus_info bus; + struct ixgbe_mbx_info mbx; u16 device_id; u16 vendor_id; u16 subsystem_device_id; @@ -2486,6 +2538,7 @@ struct ixgbe_info { struct ixgbe_mac_operations *mac_ops; struct ixgbe_eeprom_operations *eeprom_ops; struct ixgbe_phy_operations *phy_ops; + struct ixgbe_mbx_operations *mbx_ops; }; -- cgit v1.2.3 From 17367270b1d7f529f5d72e8f2cf76672829eb335 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:25:48 +0000 Subject: ixgbe: Add SR-IOV specific features This module and header file add functions to support SR-IOV features of the 82599 10Gbe controller. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_sriov.c | 336 ++++++++++++++++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_sriov.h | 45 ++++++ 2 files changed, 381 insertions(+) create mode 100644 drivers/net/ixgbe/ixgbe_sriov.c create mode 100644 drivers/net/ixgbe/ixgbe_sriov.h diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c new file mode 100644 index 000000000000..74bca74d57c1 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -0,0 +1,336 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NETIF_F_HW_VLAN_TX +#include +#endif + +#include "ixgbe.h" + +#include "ixgbe_sriov.h" + +int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, + int entries, u16 *hash_list, u32 vf) +{ + struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; + int i; + + /* only so many hash values supported */ + entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES); + + /* + * salt away the number of multi cast addresses assigned + * to this VF for later use to restore when the PF multi cast + * list changes + */ + vfinfo->num_vf_mc_hashes = entries; + + /* + * VFs are limited to using the MTA hash table for their multicast + * addresses + */ + for (i = 0; i < entries; i++) { + vfinfo->vf_mc_hashes[i] = hash_list[i];; + } + + /* Flush and reset the mta with the new values */ + ixgbe_set_rx_mode(adapter->netdev); + + return 0; +} + +void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + struct vf_data_storage *vfinfo; + int i, j; + u32 vector_bit; + u32 vector_reg; + u32 mta_reg; + + for (i = 0; i < adapter->num_vfs; i++) { + vfinfo = &adapter->vfinfo[i]; + for (j = 0; j < vfinfo->num_vf_mc_hashes; j++) { + hw->addr_ctrl.mta_in_use++; + vector_reg = (vfinfo->vf_mc_hashes[j] >> 5) & 0x7F; + vector_bit = vfinfo->vf_mc_hashes[j] & 0x1F; + mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); + mta_reg |= (1 << vector_bit); + IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); + } + } +} + +int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf) +{ + u32 ctrl; + + /* Check if global VLAN already set, if not set it */ + ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); + if (!(ctrl & IXGBE_VLNCTRL_VFE)) { + /* enable VLAN tag insert/strip */ + ctrl |= IXGBE_VLNCTRL_VFE; + ctrl &= ~IXGBE_VLNCTRL_CFIEN; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); + } + + return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); +} + + +void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf) +{ + u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); + vmolr |= (IXGBE_VMOLR_AUPE | + IXGBE_VMOLR_ROMPE | + IXGBE_VMOLR_ROPE | + IXGBE_VMOLR_BAM); + IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); +} + +inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + + /* reset offloads to defaults */ + ixgbe_set_vmolr(hw, vf); + + + /* reset multicast table array for vf */ + adapter->vfinfo[vf].num_vf_mc_hashes = 0; + + /* Flush and reset the mta with the new values */ + ixgbe_set_rx_mode(adapter->netdev); + + if (adapter->vfinfo[vf].rar > 0) { + adapter->hw.mac.ops.clear_rar(&adapter->hw, + adapter->vfinfo[vf].rar); + adapter->vfinfo[vf].rar = -1; + } +} + +int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, + int vf, unsigned char *mac_addr) +{ + struct ixgbe_hw *hw = &adapter->hw; + + adapter->vfinfo[vf].rar = hw->mac.ops.set_rar(hw, vf + 1, mac_addr, + vf, IXGBE_RAH_AV); + if (adapter->vfinfo[vf].rar < 0) { + DPRINTK(DRV, ERR, "Could not set MAC Filter for VF %d\n", vf); + return -1; + } + + memcpy(adapter->vfinfo[vf].vf_mac_addresses, mac_addr, 6); + + return 0; +} + +int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) +{ + unsigned char vf_mac_addr[6]; + struct net_device *netdev = pci_get_drvdata(pdev); + struct ixgbe_adapter *adapter = netdev_priv(netdev); + unsigned int vfn = (event_mask & 0x3f); + + bool enable = ((event_mask & 0x10000000U) != 0); + + if (enable) { + random_ether_addr(vf_mac_addr); + DPRINTK(PROBE, INFO, "IOV: VF %d is enabled " + "mac %02X:%02X:%02X:%02X:%02X:%02X\n", + vfn, + vf_mac_addr[0], vf_mac_addr[1], vf_mac_addr[2], + vf_mac_addr[3], vf_mac_addr[4], vf_mac_addr[5]); + /* + * Store away the VF "permananet" MAC address, it will ask + * for it later. + */ + memcpy(adapter->vfinfo[vfn].vf_mac_addresses, vf_mac_addr, 6); + } + + return 0; +} + +inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 reg; + u32 reg_offset, vf_shift; + + vf_shift = vf % 32; + reg_offset = vf / 32; + + /* enable transmit and receive for vf */ + reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset)); + reg |= (reg | (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg); + + reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset)); + reg |= (reg | (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg); + + ixgbe_vf_reset_event(adapter, vf); +} + +static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) +{ + u32 mbx_size = IXGBE_VFMAILBOX_SIZE; + u32 msgbuf[mbx_size]; + struct ixgbe_hw *hw = &adapter->hw; + s32 retval; + int entries; + u16 *hash_list; + int add, vid; + + retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); + + if (retval) + printk(KERN_ERR "Error receiving message from VF\n"); + + /* this is a message we already processed, do nothing */ + if (msgbuf[0] & (IXGBE_VT_MSGTYPE_ACK | IXGBE_VT_MSGTYPE_NACK)) + return retval; + + /* + * until the vf completes a virtual function reset it should not be + * allowed to start any configuration. + */ + + if (msgbuf[0] == IXGBE_VF_RESET) { + unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses; + u8 *addr = (u8 *)(&msgbuf[1]); + DPRINTK(PROBE, INFO, "VF Reset msg received from vf %d\n", vf); + adapter->vfinfo[vf].clear_to_send = false; + ixgbe_vf_reset_msg(adapter, vf); + adapter->vfinfo[vf].clear_to_send = true; + + /* reply to reset with ack and vf mac address */ + msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK; + memcpy(addr, vf_mac, IXGBE_ETH_LENGTH_OF_ADDRESS); + /* + * Piggyback the multicast filter type so VF can compute the + * correct vectors + */ + msgbuf[3] = hw->mac.mc_filter_type; + ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf); + + return retval; + } + + if (!adapter->vfinfo[vf].clear_to_send) { + msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; + ixgbe_write_mbx(hw, msgbuf, 1, vf); + return retval; + } + + switch ((msgbuf[0] & 0xFFFF)) { + case IXGBE_VF_SET_MAC_ADDR: + { + u8 *new_mac = ((u8 *)(&msgbuf[1])); + if (is_valid_ether_addr(new_mac)) + ixgbe_set_vf_mac(adapter, vf, new_mac); + else + retval = -1; + } + break; + case IXGBE_VF_SET_MULTICAST: + entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) + >> IXGBE_VT_MSGINFO_SHIFT; + hash_list = (u16 *)&msgbuf[1]; + retval = ixgbe_set_vf_multicasts(adapter, entries, + hash_list, vf); + break; + case IXGBE_VF_SET_LPE: + WARN_ON((msgbuf[0] & 0xFFFF) == IXGBE_VF_SET_LPE); + break; + case IXGBE_VF_SET_VLAN: + add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) + >> IXGBE_VT_MSGINFO_SHIFT; + vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK); + retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); + break; + default: + DPRINTK(DRV, ERR, "Unhandled Msg %8.8x\n", msgbuf[0]); + retval = IXGBE_ERR_MBX; + break; + } + + /* notify the VF of the results of what it sent us */ + if (retval) + msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK; + else + msgbuf[0] |= IXGBE_VT_MSGTYPE_ACK; + + msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS; + + ixgbe_write_mbx(hw, msgbuf, 1, vf); + + return retval; +} + +static void ixgbe_rcv_ack_from_vf(struct ixgbe_adapter *adapter, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 msg = IXGBE_VT_MSGTYPE_NACK; + + /* if device isn't clear to send it shouldn't be reading either */ + if (!adapter->vfinfo[vf].clear_to_send) + ixgbe_write_mbx(hw, &msg, 1, vf); +} + +void ixgbe_msg_task(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 vf; + + for (vf = 0; vf < adapter->num_vfs; vf++) { + /* process any reset requests */ + if (!ixgbe_check_for_rst(hw, vf)) + ixgbe_vf_reset_event(adapter, vf); + + /* process any messages pending */ + if (!ixgbe_check_for_msg(hw, vf)) + ixgbe_rcv_msg_from_vf(adapter, vf); + + /* process any acks */ + if (!ixgbe_check_for_ack(hw, vf)) + ixgbe_rcv_ack_from_vf(adapter, vf); + } +} + diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ixgbe/ixgbe_sriov.h new file mode 100644 index 000000000000..664b237eacb9 --- /dev/null +++ b/drivers/net/ixgbe/ixgbe_sriov.h @@ -0,0 +1,45 @@ +/******************************************************************************* + + Intel 10 Gigabit PCI Express Linux driver + Copyright(c) 1999 - 2009 Intel Corporation. + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information: + e1000-devel Mailing List + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#ifndef _IXGBE_SRIOV_H_ +#define _IXGBE_SRIOV_H_ + +int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, + int entries, u16 *hash_list, u32 vf); +void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter); +int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf); +void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf); +void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf); +void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf); +void ixgbe_msg_task(struct ixgbe_adapter *adapter); +int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, + int vf, unsigned char *mac_addr); +int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); +void ixgbe_dump_registers(struct ixgbe_adapter *adapter); + +#endif /* _IXGBE_SRIOV_H_ */ + -- cgit v1.2.3 From 92ed72d536445334829af65c63516557fd50f554 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:26:07 +0000 Subject: ixgbe: Add SR-IOV specific modules to driver Makefile Add the mailbox and SR-IOV feature modules to the ixgbe driver Makefile. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index 21b41f42b61c..1dd867df2967 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -33,7 +33,8 @@ obj-$(CONFIG_IXGBE) += ixgbe.o ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ - ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o + ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ + ixgbe_mbx.o ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o -- cgit v1.2.3 From 096a58fdec72335d9cbee94bd10b312c5f14f8af Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:26:26 +0000 Subject: ixgbe: Add SR-IOV feature enablement code Adds code to the core 82599 module to support SR-IOV features of the 82599 network controller Signed-off-by: Greg Rose Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 126 ++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 538340527aa6..9ec296cf4c40 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -31,6 +31,7 @@ #include "ixgbe.h" #include "ixgbe_phy.h" +#include "ixgbe_mbx.h" #define IXGBE_82599_MAX_TX_QUEUES 128 #define IXGBE_82599_MAX_RX_QUEUES 128 @@ -951,8 +952,6 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) msleep(50); - - /* * Store the original AUTOC/AUTOC2 values if they have not been * stored off yet. Otherwise restore the stored original @@ -1095,9 +1094,11 @@ static s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on) { u32 regindex; + u32 vlvf_index; u32 bitindex; u32 bits; u32 first_empty_slot; + u32 vt_ctl; if (vlan > 4095) return IXGBE_ERR_PARAM; @@ -1124,76 +1125,84 @@ static s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind, /* Part 2 - * If the vind is set + * If VT mode is set * Either vlan_on * make sure the vlan is in VLVF * set the vind bit in the matching VLVFB * Or !vlan_on * clear the pool bit and possibly the vind */ - if (vind) { - /* find the vlanid or the first empty slot */ - first_empty_slot = 0; - - for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) { - bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex)); - if (!bits && !first_empty_slot) - first_empty_slot = regindex; - else if ((bits & 0x0FFF) == vlan) - break; - } + vt_ctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + if (!(vt_ctl & IXGBE_VT_CTL_VT_ENABLE)) + goto out; - if (regindex >= IXGBE_VLVF_ENTRIES) { - if (first_empty_slot) - regindex = first_empty_slot; - else { - hw_dbg(hw, "No space in VLVF.\n"); - goto out; - } + /* find the vlanid or the first empty slot */ + first_empty_slot = 0; + + for (vlvf_index = 1; vlvf_index < IXGBE_VLVF_ENTRIES; vlvf_index++) { + bits = IXGBE_READ_REG(hw, IXGBE_VLVF(vlvf_index)); + if (!bits && !first_empty_slot) + first_empty_slot = vlvf_index; + else if ((bits & 0x0FFF) == vlan) + break; + } + + if (vlvf_index >= IXGBE_VLVF_ENTRIES) { + if (first_empty_slot) + vlvf_index = first_empty_slot; + else { + hw_dbg(hw, "No space in VLVF.\n"); + goto out; } + } - if (vlan_on) { - /* set the pool bit */ - if (vind < 32) { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex * 2)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex * 2), bits); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex * 2) + 1)); - bits |= (1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex * 2) + 1), bits); - } + if (vlan_on) { + /* set the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(vlvf_index * 2)); + bits |= (1 << vind); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(vlvf_index * 2), bits); } else { - /* clear the pool bit */ - if (vind < 32) { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex * 2)); + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((vlvf_index * 2) + 1)); + bits |= (1 << (vind - 32)); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((vlvf_index * 2) + 1), bits); + } + } else { + /* clear the pool bit */ + if (vind < 32) { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB(vlvf_index * 2)); bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB(regindex * 2), bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex * 2) + 1)); - } else { - bits = IXGBE_READ_REG(hw, - IXGBE_VLVFB((regindex * 2) + 1)); - bits &= ~(1 << vind); - IXGBE_WRITE_REG(hw, - IXGBE_VLVFB((regindex * 2) + 1), bits); - bits |= IXGBE_READ_REG(hw, - IXGBE_VLVFB(regindex * 2)); - } + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB(vlvf_index * 2), bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB((vlvf_index * 2) + 1)); + } else { + bits = IXGBE_READ_REG(hw, + IXGBE_VLVFB((vlvf_index * 2) + 1)); + bits &= ~(1 << (vind - 32)); + IXGBE_WRITE_REG(hw, + IXGBE_VLVFB((vlvf_index * 2) + 1), bits); + bits |= IXGBE_READ_REG(hw, + IXGBE_VLVFB(vlvf_index * 2)); } + } - if (bits) - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), - (IXGBE_VLVF_VIEN | vlan)); - else - IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0); + if (bits) { + IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), + (IXGBE_VLVF_VIEN | vlan)); + /* if bits is non-zero then some pools/VFs are still + * using this VLAN ID. Force the VFTA entry to on */ + bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex)); + bits |= (1 << bitindex); + IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits); } + else + IXGBE_WRITE_REG(hw, IXGBE_VLVF(vlvf_index), 0); out: return 0; @@ -2655,4 +2664,5 @@ struct ixgbe_info ixgbe_82599_info = { .mac_ops = &mac_ops_82599, .eeprom_ops = &eeprom_ops_82599, .phy_ops = &phy_ops_82599, + .mbx_ops = &mbx_ops_82599, }; -- cgit v1.2.3 From 1cdd1ec8784399eef55a60887a45f3f46a1c240a Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:26:46 +0000 Subject: ixgbe: Add SR-IOV features to main module Adds SR-IOV features supported by the 82599 controller to the main driver module. If the CONFIG_PCI_IOV kernel option is selected then the SR-IOV features are enabled. Use the max_vfs module option to allocate up to 63 virtual functions per physical port. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 278 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 268 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 233c3917427e..a938dba7bdfe 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -45,6 +45,7 @@ #include "ixgbe.h" #include "ixgbe_common.h" #include "ixgbe_dcb_82599.h" +#include "ixgbe_sriov.h" char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = @@ -124,6 +125,13 @@ static struct notifier_block dca_notifier = { }; #endif +#ifdef CONFIG_PCI_IOV +static unsigned int max_vfs; +module_param(max_vfs, uint, 0); +MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate " + "per physical function"); +#endif /* CONFIG_PCI_IOV */ + MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver"); MODULE_LICENSE("GPL"); @@ -131,6 +139,41 @@ MODULE_VERSION(DRV_VERSION); #define DEFAULT_DEBUG_LEVEL_SHIFT 3 +static inline void ixgbe_disable_sriov(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 gcr; + u32 gpie; + u32 vmdctl; + +#ifdef CONFIG_PCI_IOV + /* disable iov and allow time for transactions to clear */ + pci_disable_sriov(adapter->pdev); +#endif + + /* turn off device IOV mode */ + gcr = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + gcr &= ~(IXGBE_GCR_EXT_SRIOV); + IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr); + gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); + gpie &= ~IXGBE_GPIE_VTMODE_MASK; + IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); + + /* set default pool back to 0 */ + vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + vmdctl &= ~IXGBE_VT_CTL_POOL_MASK; + IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl); + + /* take a breather then clean up driver data */ + msleep(100); + if (adapter->vfinfo) + kfree(adapter->vfinfo); + adapter->vfinfo = NULL; + + adapter->num_vfs = 0; + adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; +} + static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter) { u32 ctrl_ext; @@ -1020,7 +1063,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) /* set up to autoclear timer, and the vectors */ mask = IXGBE_EIMS_ENABLE_MASK; - mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); + if (adapter->num_vfs) + mask &= ~(IXGBE_EIMS_OTHER | + IXGBE_EIMS_MAILBOX | + IXGBE_EIMS_LSC); + else + mask &= ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask); } @@ -1249,6 +1297,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) if (eicr & IXGBE_EICR_LSC) ixgbe_check_lsc(adapter); + if (eicr & IXGBE_EICR_MAILBOX) + ixgbe_msg_task(adapter); + if (hw->mac.type == ixgbe_mac_82598EB) ixgbe_check_fan_failure(adapter, eicr); @@ -1763,6 +1814,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_GPI_SDP1; mask |= IXGBE_EIMS_GPI_SDP2; + if (adapter->num_vfs) + mask |= IXGBE_EIMS_MAILBOX; } if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE || adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) @@ -1771,6 +1824,11 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); ixgbe_irq_enable_queues(adapter, ~0); IXGBE_WRITE_FLUSH(&adapter->hw); + + if (adapter->num_vfs > 32) { + u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel); + } } /** @@ -1900,6 +1958,8 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); + if (adapter->num_vfs > 32) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0); } IXGBE_WRITE_FLUSH(&adapter->hw); if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { @@ -1984,18 +2044,32 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) if (hw->mac.type == ixgbe_mac_82599EB) { u32 rttdcs; + u32 mask; /* disable the arbiter while setting MTQC */ rttdcs = IXGBE_READ_REG(hw, IXGBE_RTTDCS); rttdcs |= IXGBE_RTTDCS_ARBDIS; IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs); - /* We enable 8 traffic classes, DCB only */ - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) - IXGBE_WRITE_REG(hw, IXGBE_MTQC, (IXGBE_MTQC_RT_ENA | - IXGBE_MTQC_8TC_8TQ)); - else + /* set transmit pool layout */ + mask = (IXGBE_FLAG_SRIOV_ENABLED | IXGBE_FLAG_DCB_ENABLED); + switch (adapter->flags & mask) { + + case (IXGBE_FLAG_SRIOV_ENABLED): + IXGBE_WRITE_REG(hw, IXGBE_MTQC, + (IXGBE_MTQC_VT_ENA | IXGBE_MTQC_64VF)); + break; + + case (IXGBE_FLAG_DCB_ENABLED): + /* We enable 8 traffic classes, DCB only */ + IXGBE_WRITE_REG(hw, IXGBE_MTQC, + (IXGBE_MTQC_RT_ENA | IXGBE_MTQC_8TC_8TQ)); + break; + + default: IXGBE_WRITE_REG(hw, IXGBE_MTQC, IXGBE_MTQC_64Q_1PB); + break; + } /* re-eable the arbiter */ rttdcs &= ~IXGBE_RTTDCS_ARBDIS; @@ -2054,12 +2128,16 @@ static u32 ixgbe_setup_mrqc(struct ixgbe_adapter *adapter) #ifdef CONFIG_IXGBE_DCB | IXGBE_FLAG_DCB_ENABLED #endif + | IXGBE_FLAG_SRIOV_ENABLED ); switch (mask) { case (IXGBE_FLAG_RSS_ENABLED): mrqc = IXGBE_MRQC_RSSEN; break; + case (IXGBE_FLAG_SRIOV_ENABLED): + mrqc = IXGBE_MRQC_VMDQEN; + break; #ifdef CONFIG_IXGBE_DCB case (IXGBE_FLAG_DCB_ENABLED): mrqc = IXGBE_MRQC_RT8TCEN; @@ -2140,7 +2218,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) int rx_buf_len; /* Decide whether to use packet split mode or not */ - adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; + /* Do not use packet split if we're in SR-IOV Mode */ + if (!adapter->num_vfs) + adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED; /* Set the RX buffer length according to the mode */ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) { @@ -2152,7 +2232,9 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR | IXGBE_PSRTYPE_L2HDR; - IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype); + IXGBE_WRITE_REG(hw, + IXGBE_PSRTYPE(adapter->num_vfs), + psrtype); } } else { if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && @@ -2238,6 +2320,30 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl); } + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { + u32 vt_reg_bits; + u32 reg_offset, vf_shift; + u32 vmdctl = IXGBE_READ_REG(hw, IXGBE_VT_CTL); + vt_reg_bits = IXGBE_VMD_CTL_VMDQ_EN + | IXGBE_VT_CTL_REPLEN; + vt_reg_bits |= (adapter->num_vfs << + IXGBE_VT_CTL_POOL_SHIFT); + IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits); + IXGBE_WRITE_REG(hw, IXGBE_MRQC, 0); + + vf_shift = adapter->num_vfs % 32; + reg_offset = adapter->num_vfs / 32; + IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0); + /* Enable only the PF's pool for Tx/Rx */ + IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (1 << vf_shift)); + IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); + ixgbe_set_vmolr(hw, adapter->num_vfs); + } + /* Program MRQC for the distribution of queues */ mrqc = ixgbe_setup_mrqc(adapter); @@ -2269,6 +2375,20 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) } IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + if (adapter->num_vfs) { + u32 reg; + + /* Map PF MAC address in RAR Entry 0 to first pool + * following VFs */ + hw->mac.ops.set_vmdq(hw, 0, adapter->num_vfs); + + /* Set up VF register offsets for selected VT Mode, i.e. + * 64 VFs for SR-IOV */ + reg = IXGBE_READ_REG(hw, IXGBE_GCR_EXT); + reg |= IXGBE_GCR_EXT_SRIOV; + IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, reg); + } + rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM); if (adapter->flags & IXGBE_FLAG_RSS_ENABLED || @@ -2449,6 +2569,8 @@ void ixgbe_set_rx_mode(struct net_device *netdev) addr_list = netdev->mc_list->dmi_addr; hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count, ixgbe_addr_list_itr); + if (adapter->num_vfs) + ixgbe_restore_vf_multicasts(adapter); } static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) @@ -2709,6 +2831,10 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) /* MSI only */ gpie = 0; } + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { + gpie &= ~IXGBE_GPIE_VTMODE_MASK; + gpie |= IXGBE_GPIE_VTMODE_64; + } /* XXX: to interrupt immediately for EICS writes, enable this */ /* gpie |= IXGBE_GPIE_EIMEN; */ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); @@ -2783,6 +2909,18 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); + if (hw->mac.type == ixgbe_mac_82599EB) { + int wait_loop = 10; + /* poll for Tx Enable ready */ + do { + msleep(1); + txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); + } while (--wait_loop && + !(txdctl & IXGBE_TXDCTL_ENABLE)); + if (!wait_loop) + DPRINTK(DRV, ERR, "Could not enable " + "Tx Queue %d\n", j); + } } for (i = 0; i < num_rx_rings; i++) { @@ -2918,7 +3056,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter) } /* reprogram the RAR[0] in case user changed it. */ - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs, + IXGBE_RAH_AV); } /** @@ -3286,6 +3425,19 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) } #endif /* IXGBE_FCOE */ +/** + * ixgbe_set_sriov_queues: Allocate queues for IOV use + * @adapter: board private structure to initialize + * + * IOV doesn't actually use anything, so just NAK the + * request for now and let the other queue routines + * figure out what to do. + */ +static inline bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter) +{ + return false; +} + /* * ixgbe_set_num_queues: Allocate queues for device, feature dependant * @adapter: board private structure to initialize @@ -3299,6 +3451,15 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter) **/ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter) { + /* Start with base case */ + adapter->num_rx_queues = 1; + adapter->num_tx_queues = 1; + adapter->num_rx_pools = adapter->num_rx_queues; + adapter->num_rx_queues_per_pool = 1; + + if (ixgbe_set_sriov_queues(adapter)) + return; + #ifdef IXGBE_FCOE if (ixgbe_set_fcoe_queues(adapter)) goto done; @@ -3569,6 +3730,24 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) } #endif /* IXGBE_FCOE */ +/** + * ixgbe_cache_ring_sriov - Descriptor ring to register mapping for sriov + * @adapter: board private structure to initialize + * + * SR-IOV doesn't use any descriptor rings but changes the default if + * no other mapping is used. + * + */ +static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) +{ + adapter->rx_ring[0].reg_idx = adapter->num_vfs * 2; + adapter->tx_ring[0].reg_idx = adapter->num_vfs * 2; + if (adapter->num_vfs) + return true; + else + return false; +} + /** * ixgbe_cache_ring_register - Descriptor ring to register mapping * @adapter: board private structure to initialize @@ -3586,6 +3765,9 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) adapter->rx_ring[0].reg_idx = 0; adapter->tx_ring[0].reg_idx = 0; + if (ixgbe_cache_ring_sriov(adapter)) + return; + #ifdef IXGBE_FCOE if (ixgbe_cache_ring_fcoe(adapter)) return; @@ -3695,6 +3877,9 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; adapter->atr_sample_rate = 0; + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) + ixgbe_disable_sriov(adapter); + ixgbe_set_num_queues(adapter); err = pci_enable_msi(adapter->pdev); @@ -5474,7 +5659,8 @@ static int ixgbe_set_mac(struct net_device *netdev, void *p) memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0, IXGBE_RAH_AV); + hw->mac.ops.set_rar(hw, 0, hw->mac.addr, adapter->num_vfs, + IXGBE_RAH_AV); return 0; } @@ -5607,6 +5793,61 @@ static const struct net_device_ops ixgbe_netdev_ops = { #endif /* IXGBE_FCOE */ }; +static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, + const struct ixgbe_info *ii) +{ +#ifdef CONFIG_PCI_IOV + struct ixgbe_hw *hw = &adapter->hw; + int err; + + if (hw->mac.type != ixgbe_mac_82599EB || !max_vfs) + return; + + /* The 82599 supports up to 64 VFs per physical function + * but this implementation limits allocation to 63 so that + * basic networking resources are still available to the + * physical function + */ + adapter->num_vfs = (max_vfs > 63) ? 63 : max_vfs; + adapter->flags |= IXGBE_FLAG_SRIOV_ENABLED; + err = pci_enable_sriov(adapter->pdev, adapter->num_vfs); + if (err) { + DPRINTK(PROBE, ERR, + "Failed to enable PCI sriov: %d\n", err); + goto err_novfs; + } + /* If call to enable VFs succeeded then allocate memory + * for per VF control structures. + */ + adapter->vfinfo = + kcalloc(adapter->num_vfs, + sizeof(struct vf_data_storage), GFP_KERNEL); + if (adapter->vfinfo) { + /* Now that we're sure SR-IOV is enabled + * and memory allocated set up the mailbox parameters + */ + ixgbe_init_mbx_params_pf(hw); + memcpy(&hw->mbx.ops, ii->mbx_ops, + sizeof(hw->mbx.ops)); + + /* Disable RSC when in SR-IOV mode */ + adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE | + IXGBE_FLAG2_RSC_ENABLED); + return; + } + + /* Oh oh */ + DPRINTK(PROBE, ERR, + "Unable to allocate memory for VF " + "Data Storage - SRIOV disabled\n"); + pci_disable_sriov(adapter->pdev); + +err_novfs: + adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED; + adapter->num_vfs = 0; +#endif /* CONFIG_PCI_IOV */ +} + /** * ixgbe_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -5781,6 +6022,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, goto err_sw_init; } + ixgbe_probe_vf(adapter, ii); + netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | @@ -5801,6 +6044,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, netdev->vlan_features |= NETIF_F_IPV6_CSUM; netdev->vlan_features |= NETIF_F_SG; + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) + adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED | + IXGBE_FLAG_DCB_ENABLED); if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED; @@ -5927,6 +6173,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, ixgbe_setup_dca(adapter); } #endif + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) { + DPRINTK(PROBE, INFO, "IOV is enabled with %d VFs\n", + adapter->num_vfs); + for (i = 0; i < adapter->num_vfs; i++) + ixgbe_vf_configuration(pdev, (i | 0x10000000)); + } + /* add san mac addr to netdev */ ixgbe_add_sanmac_netdev(netdev); @@ -5939,6 +6192,8 @@ err_register: ixgbe_clear_interrupt_scheme(adapter); err_sw_init: err_eeprom: + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) + ixgbe_disable_sriov(adapter); clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state); del_timer_sync(&adapter->sfp_timer); cancel_work_sync(&adapter->sfp_task); @@ -6007,6 +6262,9 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) if (netdev->reg_state == NETREG_REGISTERED) unregister_netdev(netdev); + if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) + ixgbe_disable_sriov(adapter); + ixgbe_clear_interrupt_scheme(adapter); ixgbe_release_hw_control(adapter); -- cgit v1.2.3 From bdbec4b86ee99b020e159f9bd604003a3ae3b0ab Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Sat, 9 Jan 2010 02:27:05 +0000 Subject: ixgbe: Fix ethtool diag test for VT mode operation Skip MAC loopback test when the adapter is set to a VT mode such as SR-IOV or VMDq Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0bd49d3b9f65..a0107b5a28e7 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1867,11 +1867,22 @@ static void ixgbe_diag_test(struct net_device *netdev, if (ixgbe_intr_test(adapter, &data[2])) eth_test->flags |= ETH_TEST_FL_FAILED; + /* If SRIOV or VMDq is enabled then skip MAC + * loopback diagnostic. */ + if (adapter->flags & (IXGBE_FLAG_SRIOV_ENABLED | + IXGBE_FLAG_VMDQ_ENABLED)) { + DPRINTK(HW, INFO, "Skip MAC loopback diagnostic in VT " + "mode\n"); + data[3] = 0; + goto skip_loopback; + } + ixgbe_reset(adapter); DPRINTK(HW, INFO, "loopback testing starting\n"); if (ixgbe_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; +skip_loopback: ixgbe_reset(adapter); clear_bit(__IXGBE_TESTING, &adapter->state); -- cgit v1.2.3 From c8e000604bce02a87742240a9b716a0f1b680c0b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 11 Jan 2010 00:44:14 -0800 Subject: lib: Kill bit-reversed FDDI MAC output case, it's bogus. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- lib/vsprintf.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index dc48d2b32ebd..e83e3e79a989 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include /* for PAGE_SIZE */ @@ -682,19 +681,16 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; char *p = mac_addr; int i; - bool bitrev; char separator; if (fmt[1] == 'F') { /* FDDI canonical format */ - bitrev = true; separator = '-'; } else { - bitrev = false; separator = ':'; } for (i = 0; i < 6; i++) { - p = pack_hex_byte(p, bitrev ? bitrev8(addr[i]) : addr[i]); + p = pack_hex_byte(p, addr[i]); if (fmt[0] == 'M' && i != 5) *p++ = separator; } @@ -908,9 +904,7 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, * usual colon-separated hex notation * - 'm' For a 6-byte MAC address, it prints the hex address without colons * - 'MF' For a 6-byte MAC FDDI address, it prints the address - * with a dash-separated hex notation with bit reversed bytes - * - 'mF' For a 6-byte MAC FDDI address, it prints the address - * in hex notation without separators with bit reversed bytes + * with a dash-separated hex notation * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) * IPv6 uses colon separated network-order 16 bit hex with leading 0's -- cgit v1.2.3 From c299bd53aa2616e6afc304b4f848186af3b3a881 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 11 Jan 2010 11:49:51 +0100 Subject: netfilter: nf_nat_ftp: remove (*mangle[]) array and functions, use %pI4 These functions merely exist to format a buffer and call nf_nat_mangle_tcp_packet. Format the buffer and perform the call in nf_nat_ftp instead. Use %pI4 for the IP address. Saves ~600 bytes of text old: $ size net/ipv4/netfilter/nf_nat_ftp.o text data bss dec hex filename 2187 160 408 2755 ac3 net/ipv4/netfilter/nf_nat_ftp.o new: $ size net/ipv4/netfilter/nf_nat_ftp.o text data bss dec hex filename 1532 112 288 1932 78c net/ipv4/netfilter/nf_nat_ftp.o Signed-off-by: Joe Perches Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_nat_ftp.c | 105 ++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 70 deletions(-) diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c index a1d5d58a58bf..86e0e84ff0a0 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/ipv4/netfilter/nf_nat_ftp.c @@ -27,76 +27,29 @@ MODULE_ALIAS("ip_nat_ftp"); /* FIXME: Time out? --RR */ -static int -mangle_rfc959_packet(struct sk_buff *skb, - __be32 newip, - u_int16_t port, - unsigned int matchoff, - unsigned int matchlen, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo) +static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type, + char *buffer, size_t buflen, + __be32 addr, u16 port) { - char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")]; - - sprintf(buffer, "%u,%u,%u,%u,%u,%u", - NIPQUAD(newip), port>>8, port&0xFF); - - pr_debug("calling nf_nat_mangle_tcp_packet\n"); - - return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, - matchlen, buffer, strlen(buffer)); -} - -/* |1|132.235.1.2|6275| */ -static int -mangle_eprt_packet(struct sk_buff *skb, - __be32 newip, - u_int16_t port, - unsigned int matchoff, - unsigned int matchlen, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo) -{ - char buffer[sizeof("|1|255.255.255.255|65535|")]; - - sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port); - - pr_debug("calling nf_nat_mangle_tcp_packet\n"); - - return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, - matchlen, buffer, strlen(buffer)); -} - -/* |1|132.235.1.2|6275| */ -static int -mangle_epsv_packet(struct sk_buff *skb, - __be32 newip, - u_int16_t port, - unsigned int matchoff, - unsigned int matchlen, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo) -{ - char buffer[sizeof("|||65535|")]; - - sprintf(buffer, "|||%u|", port); - - pr_debug("calling nf_nat_mangle_tcp_packet\n"); + switch (type) { + case NF_CT_FTP_PORT: + case NF_CT_FTP_PASV: + return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u", + ((unsigned char *)&addr)[0], + ((unsigned char *)&addr)[1], + ((unsigned char *)&addr)[2], + ((unsigned char *)&addr)[3], + port >> 8, + port & 0xFF); + case NF_CT_FTP_EPRT: + return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port); + case NF_CT_FTP_EPSV: + return snprintf(buffer, buflen, "|||%u|", port); + } - return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, - matchlen, buffer, strlen(buffer)); + return 0; } -static int (*mangle[])(struct sk_buff *, __be32, u_int16_t, - unsigned int, unsigned int, struct nf_conn *, - enum ip_conntrack_info) -= { - [NF_CT_FTP_PORT] = mangle_rfc959_packet, - [NF_CT_FTP_PASV] = mangle_rfc959_packet, - [NF_CT_FTP_EPRT] = mangle_eprt_packet, - [NF_CT_FTP_EPSV] = mangle_epsv_packet -}; - /* So, this packet has hit the connection tracking matching code. Mangle it, and change the expectation to match the new version. */ static unsigned int nf_nat_ftp(struct sk_buff *skb, @@ -110,6 +63,8 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, u_int16_t port; int dir = CTINFO2DIR(ctinfo); struct nf_conn *ct = exp->master; + char buffer[sizeof("|1|255.255.255.255|65535|")]; + unsigned int buflen; pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); @@ -132,11 +87,21 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, if (port == 0) return NF_DROP; - if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) { - nf_ct_unexpect_related(exp); - return NF_DROP; - } + buflen = nf_nat_ftp_fmt_cmd(type, buffer, sizeof(buffer), newip, port); + if (!buflen) + goto out; + + pr_debug("calling nf_nat_mangle_tcp_packet\n"); + + if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, + matchlen, buffer, buflen)) + goto out; + return NF_ACCEPT; + +out: + nf_ct_unexpect_related(exp); + return NF_DROP; } static void __exit nf_nat_ftp_fini(void) -- cgit v1.2.3 From a79e7ac4ad77e1833e8f69e99113204d03018255 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 11 Jan 2010 11:53:31 +0100 Subject: ipvs: use standardized format in sprintf Use the same format string as net/ipv4/netfilter/nf_nat_ftp.c to encode an ipv4 address and port. Both uses should be a single common function. Signed-off-by: Joe Perches Acked-by: Simon Horman Signed-off-by: Patrick McHardy --- net/netfilter/ipvs/ip_vs_ftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index 33e2c799cba7..73f38ea98f25 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c @@ -208,7 +208,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, */ from.ip = n_cp->vaddr.ip; port = n_cp->vport; - sprintf(buf, "%d,%d,%d,%d,%d,%d", NIPQUAD(from.ip), + sprintf(buf, "%u,%u,%u,%u,%u,%u", NIPQUAD(from.ip), (ntohs(port)>>8)&255, ntohs(port)&255); buf_len = strlen(buf); -- cgit v1.2.3 From 7f635d0d1bf84ad7a0032cbce9d902b9384c48b7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 11 Jan 2010 11:55:36 +0100 Subject: netfilter: xt_osf: change %pi4 to %pI4 commit 8a27f7c90ffcb791eed7574922b51fb60b08fc89 changed the output style of %pi4 to use fixed width leading zero IP addresses "001.002.003.004". It's useful when printing multiple lines of addresses, but was a change in output style for some existing uses. Using %pI4 restores the previous output style. Signed-off-by: Joe Perches Signed-off-by: Patrick McHardy --- net/netfilter/xt_osf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 4d1a41bbd5d7..4169e200588d 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -334,7 +334,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, if (info->flags & XT_OSF_LOG) nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, - "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", + "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n", f->genre, f->version, f->subtype, &ip->saddr, ntohs(tcp->source), &ip->daddr, ntohs(tcp->dest), @@ -349,7 +349,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, if (!fcount && (info->flags & XT_OSF_LOG)) nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, - "Remote OS is not known: %pi4:%u -> %pi4:%u\n", + "Remote OS is not known: %pI4:%u -> %pI4:%u\n", &ip->saddr, ntohs(tcp->source), &ip->daddr, ntohs(tcp->dest)); -- cgit v1.2.3 From d218d11133d888f9745802146a50255a4781d37a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 11 Jan 2010 16:28:01 -0800 Subject: tcp: Generalized TTL Security Mechanism This patch adds the kernel portions needed to implement RFC 5082 Generalized TTL Security Mechanism (GTSM). It is a lightweight security measure against forged packets causing DoS attacks (for BGP). This is already implemented the same way in BSD kernels. For the necessary Quagga patch http://www.gossamer-threads.com/lists/quagga/dev/17389 Description from Cisco http://www.cisco.com/en/US/docs/ios/12_3t/12_3t7/feature/guide/gt_btsh.html It does add one byte to each socket structure, but I did a little rearrangement to reuse a hole (on 64 bit), but it does grow the structure on 32 bit This should be documented on ip(4) man page and the Glibc in.h file also needs update. IPV6_MINHOPLIMIT should also be added (although BSD doesn't support that). Only TCP is supported, but could also be added to UDP, DCCP, SCTP if desired. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/linux/in.h | 2 ++ include/net/inet_sock.h | 4 +++- net/ipv4/ip_sockglue.c | 14 +++++++++++++- net/ipv4/tcp_ipv4.c | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/linux/in.h b/include/linux/in.h index b615649db129..583c76f9c30f 100644 --- a/include/linux/in.h +++ b/include/linux/in.h @@ -84,6 +84,8 @@ struct in_addr { #define IP_ORIGDSTADDR 20 #define IP_RECVORIGDSTADDR IP_ORIGDSTADDR +#define IP_MINTTL 21 + /* IP_MTU_DISCOVER values */ #define IP_PMTUDISC_DONT 0 /* Never send DF frames */ #define IP_PMTUDISC_WANT 1 /* Use per route hints */ diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index bd4c53f75ac0..83fd34437cf1 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -122,10 +122,12 @@ struct inet_sock { __be32 inet_saddr; __s16 uc_ttl; __u16 cmsg_flags; - struct ip_options *opt; __be16 inet_sport; __u16 inet_id; + + struct ip_options *opt; __u8 tos; + __u8 min_ttl; __u8 mc_ttl; __u8 pmtudisc; __u8 recverr:1, diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index cafad9baff03..644dc43a55de 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -451,7 +451,8 @@ static int do_ip_setsockopt(struct sock *sk, int level, (1<transparent = !!val; break; + case IP_MINTTL: + if (optlen < 1) + goto e_inval; + if (val < 0 || val > 255) + goto e_inval; + inet->min_ttl = val; + break; + default: err = -ENOPROTOOPT; break; @@ -1198,6 +1207,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, case IP_TRANSPARENT: val = inet->transparent; break; + case IP_MINTTL: + val = inet->min_ttl; + break; default: release_sock(sk); return -ENOPROTOOPT; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 65b8ebfd078a..382f667238ec 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1649,6 +1649,9 @@ int tcp_v4_rcv(struct sk_buff *skb) if (!sk) goto no_tcp_socket; + if (iph->ttl < inet_sk(sk)->min_ttl) + goto discard_and_relse; + process: if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait; -- cgit v1.2.3 From 3ccd4c6167d3b39d52631767ebbf8b5677c5855d Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 12 Jan 2010 02:00:46 -0800 Subject: can: Unify droping of invalid tx skbs and netdev stats To prevent the CAN drivers to operate on invalid socketbuffers the skbs are now checked and silently dropped at the xmit-function consistently. Also the netdev stats are consistently using the CAN data length code (dlc) for [rx|tx]_bytes now. Signed-off-by: Oliver Hartkopp Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/at91_can.c | 3 +++ drivers/net/can/bfin_can.c | 3 +++ drivers/net/can/mcp251x.c | 6 +----- drivers/net/can/mscan/mscan.c | 5 +---- drivers/net/can/sja1000/sja1000.c | 3 +++ drivers/net/can/ti_hecc.c | 4 +++- drivers/net/can/usb/ems_usb.c | 3 +++ drivers/net/can/vcan.c | 12 +++++++++--- include/linux/can/dev.h | 15 +++++++++++++++ 9 files changed, 41 insertions(+), 13 deletions(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 166cc7e579c0..f7287497ba6e 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -342,6 +342,9 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned int mb, prio; u32 reg_mid, reg_mcr; + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + mb = get_tx_next_mb(priv); prio = get_tx_next_prio(priv); diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 0ec1524523cc..7e1926e79e98 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -318,6 +318,9 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev) u16 val; int i; + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + netif_stop_queue(dev); /* fill id */ diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 1a72ca066a17..afa2fa45fed9 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -494,12 +494,8 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (skb->len != sizeof(struct can_frame)) { - dev_err(&spi->dev, "dropping packet - bad length\n"); - dev_kfree_skb(skb); - net->stats.tx_dropped++; + if (can_dropped_invalid_skb(net, skb)) return NETDEV_TX_OK; - } netif_stop_queue(net); priv->tx_skb = skb; diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 500d18918bd5..40827c128b65 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -204,11 +204,8 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) int i, rtr, buf_id; u32 can_id; - if (skb->len != sizeof(*frame) || frame->can_dlc > 8) { - kfree_skb(skb); - dev->stats.tx_dropped++; + if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; - } out_8(®s->cantier, 0); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 542a4f7255b4..345304d779b9 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -249,6 +249,9 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, uint8_t dreg; int i; + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + netif_stop_queue(dev); fi = dlc = cf->can_dlc; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 5c993c2da528..7d370e32a7a8 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -477,6 +477,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) u32 mbxno, mbx_mask, data; unsigned long flags; + if (can_dropped_invalid_skb(ndev, skb)) + return NETDEV_TX_OK; + mbxno = get_tx_head_mb(priv); mbx_mask = BIT(mbxno); spin_lock_irqsave(&priv->mbx_lock, flags); @@ -491,7 +494,6 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) spin_unlock_irqrestore(&priv->mbx_lock, flags); /* Prepare mailbox for transmission */ - data = min_t(u8, cf->can_dlc, 8); if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */ data |= HECC_CANMCF_RTR; data |= get_tx_head_prio(priv) << 8; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index efbb05c71bf4..ddb17e256656 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -767,6 +767,9 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN + sizeof(struct cpc_can_msg); + if (can_dropped_invalid_skb(netdev, skb)) + return NETDEV_TX_OK; + /* create a URB, and a buffer for it, and copy the data to the URB */ urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 80ac56313981..d124d837ae58 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -47,6 +47,7 @@ #include #include #include +#include #include static __initdata const char banner[] = @@ -70,10 +71,11 @@ MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)"); static void vcan_rx(struct sk_buff *skb, struct net_device *dev) { + struct can_frame *cf = (struct can_frame *)skb->data; struct net_device_stats *stats = &dev->stats; stats->rx_packets++; - stats->rx_bytes += skb->len; + stats->rx_bytes += cf->can_dlc; skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; @@ -85,11 +87,15 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) { + struct can_frame *cf = (struct can_frame *)skb->data; struct net_device_stats *stats = &dev->stats; int loop; + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + stats->tx_packets++; - stats->tx_bytes += skb->len; + stats->tx_bytes += cf->can_dlc; /* set flag whether this packet has to be looped back */ loop = skb->pkt_type == PACKET_LOOPBACK; @@ -103,7 +109,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) * CAN core already did the echo for us */ stats->rx_packets++; - stats->rx_bytes += skb->len; + stats->rx_bytes += cf->can_dlc; } kfree_skb(skb); return NETDEV_TX_OK; diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 3db7767d2a17..7e7c98a3e908 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -60,6 +60,21 @@ struct can_priv { */ #define get_can_dlc(i) (min_t(__u8, (i), 8)) +/* Drop a given socketbuffer if it does not contain a valid CAN frame. */ +static inline int can_dropped_invalid_skb(struct net_device *dev, + struct sk_buff *skb) +{ + const struct can_frame *cf = (struct can_frame *)skb->data; + + if (unlikely(skb->len != sizeof(*cf) || cf->can_dlc > 8)) { + kfree_skb(skb); + dev->stats.tx_dropped++; + return 1; + } + + return 0; +} + struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max); void free_candev(struct net_device *dev); -- cgit v1.2.3 From 14acdde6e527950f66c084dbf19bad6fbfcaeedc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 18 Dec 2009 11:26:04 -0500 Subject: ath9k: re-enable ps by default for new single chip families The newer single chip hardware family of chipsets have not been experiencing issues with power saving set by default with recent fixes merged (even into stable). The remaining issues are only reported with AR5416 and since enabling PS by default can increase power savings considerably best to take advantage of that feature as this has been tested properly. For more details on this issue see the bug report: http://bugzilla.kernel.org/show_bug.cgi?id=14267 We leave AR5416 with PS disabled by default, that seems to require some more work. Cc: stable@kernel.org Cc: Peter Stuge Cc: Justin P. Mattock Cc: Kristoffer Ericson Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 79fbbda15493..3777b8449789 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1838,6 +1838,8 @@ bad_free_hw: void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { + struct ath_hw *ah = sc->sc_ah; + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | @@ -1855,7 +1857,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + if (AR_SREV_5416(ah)) + hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->queues = 4; hw->max_rates = 4; -- cgit v1.2.3 From 81077e82c3f591578625805dd6464a27a9ff56ec Mon Sep 17 00:00:00 2001 From: Lukáš Turek <8an@praha12.net> Date: Mon, 21 Dec 2009 22:50:47 +0100 Subject: nl80211: Add new WIPHY attribute COVERAGE_CLASS The new attribute NL80211_ATTR_WIPHY_COVERAGE_CLASS sets IEEE 802.11 Coverage Class, which depends on maximum distance of nodes in a wireless network. It's required for long distance links (more than a few hundred meters). The attribute is now ignored by two non-mac80211 drivers, rndis and iwmc3200wifi, together with WIPHY_PARAM_RETRY_SHORT and WIPHY_PARAM_RETRY_LONG. If it turns out to be a problem, we could split set_wiphy_params callback or add new capability bits. Signed-off-by: Lukas Turek <8an@praha12.net> Signed-off-by: John W. Linville --- include/linux/nl80211.h | 4 ++++ include/net/cfg80211.h | 2 ++ net/wireless/core.c | 1 + net/wireless/nl80211.c | 15 +++++++++++++++ 4 files changed, 22 insertions(+) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2bfbe88837ef..d4c556de7170 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -430,6 +430,8 @@ enum nl80211_commands { * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length * larger than or equal to this use RTS/CTS handshake); allowed range: * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 + * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11 + * section 7.3.2.9; dot11CoverageClass; u8 * * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on * @NL80211_ATTR_IFNAME: network interface name @@ -779,6 +781,8 @@ enum nl80211_attrs { NL80211_ATTR_COOKIE, + NL80211_ATTR_WIPHY_COVERAGE_CLASS, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index add79930f47d..a8d5d04314b9 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -837,6 +837,7 @@ enum wiphy_params_flags { WIPHY_PARAM_RETRY_LONG = 1 << 1, WIPHY_PARAM_FRAG_THRESHOLD = 1 << 2, WIPHY_PARAM_RTS_THRESHOLD = 1 << 3, + WIPHY_PARAM_COVERAGE_CLASS = 1 << 4, }; /** @@ -1236,6 +1237,7 @@ struct wiphy { u8 retry_long; u32 frag_threshold; u32 rts_threshold; + u8 coverage_class; char fw_version[ETHTOOL_BUSINFO_LEN]; u32 hw_version; diff --git a/net/wireless/core.c b/net/wireless/core.c index c2a2c563d21a..0a545bb6ed05 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -402,6 +402,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) rdev->wiphy.retry_long = 4; rdev->wiphy.frag_threshold = (u32) -1; rdev->wiphy.rts_threshold = (u32) -1; + rdev->wiphy.coverage_class = 0; return &rdev->wiphy; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e3bee3cecdfa..c09fbcd278fb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -69,6 +69,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, + [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 }, [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, @@ -444,6 +445,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.frag_threshold); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, dev->wiphy.rts_threshold); + NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, + dev->wiphy.coverage_class); NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); @@ -684,6 +687,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) u32 changed; u8 retry_short = 0, retry_long = 0; u32 frag_threshold = 0, rts_threshold = 0; + u8 coverage_class = 0; rtnl_lock(); @@ -806,9 +810,16 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) changed |= WIPHY_PARAM_RTS_THRESHOLD; } + if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { + coverage_class = nla_get_u8( + info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); + changed |= WIPHY_PARAM_COVERAGE_CLASS; + } + if (changed) { u8 old_retry_short, old_retry_long; u32 old_frag_threshold, old_rts_threshold; + u8 old_coverage_class; if (!rdev->ops->set_wiphy_params) { result = -EOPNOTSUPP; @@ -819,6 +830,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) old_retry_long = rdev->wiphy.retry_long; old_frag_threshold = rdev->wiphy.frag_threshold; old_rts_threshold = rdev->wiphy.rts_threshold; + old_coverage_class = rdev->wiphy.coverage_class; if (changed & WIPHY_PARAM_RETRY_SHORT) rdev->wiphy.retry_short = retry_short; @@ -828,6 +840,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) rdev->wiphy.frag_threshold = frag_threshold; if (changed & WIPHY_PARAM_RTS_THRESHOLD) rdev->wiphy.rts_threshold = rts_threshold; + if (changed & WIPHY_PARAM_COVERAGE_CLASS) + rdev->wiphy.coverage_class = coverage_class; result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); if (result) { @@ -835,6 +849,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) rdev->wiphy.retry_long = old_retry_long; rdev->wiphy.frag_threshold = old_frag_threshold; rdev->wiphy.rts_threshold = old_rts_threshold; + rdev->wiphy.coverage_class = old_coverage_class; } } -- cgit v1.2.3 From 310bc676e314e92c18257bfc916951879451ee32 Mon Sep 17 00:00:00 2001 From: Lukáš Turek <8an@praha12.net> Date: Mon, 21 Dec 2009 22:50:48 +0100 Subject: mac80211: Add new callback set_coverage_class Mac80211 callback to driver set_coverage_class() sets slot time and ACK timeout for given IEEE 802.11 coverage class. The callback is optional, but it's essential for long distance links. Signed-off-by: Lukas Turek <8an@praha12.net> Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 +++++ net/mac80211/cfg.c | 7 +++++++ net/mac80211/driver-ops.h | 15 +++++++++++++++ net/mac80211/driver-trace.h | 23 +++++++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f073a2a50574..ad4b70034e77 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1533,6 +1533,10 @@ enum ieee80211_ampdu_mlme_action { * and need to call wiphy_rfkill_set_hw_state() in the callback. * The callback can sleep. * + * @set_coverage_class: Set slot time for given coverage class as specified + * in IEEE 802.11-2007 section 17.3.8.6 and modify ACK timeout + * accordingly. This callback is not required and may sleep. + * * @testmode_cmd: Implement a cfg80211 test mode command. * The callback can sleep. * @@ -1592,6 +1596,7 @@ struct ieee80211_ops { struct ieee80211_sta *sta, u16 tid, u16 *ssn); void (*rfkill_poll)(struct ieee80211_hw *hw); + void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class); #ifdef CONFIG_NL80211_TESTMODE int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); #endif diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 2e5e841e9b7b..976014c5e742 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1230,6 +1230,13 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) struct ieee80211_local *local = wiphy_priv(wiphy); int err; + if (changed & WIPHY_PARAM_COVERAGE_CLASS) { + err = drv_set_coverage_class(local, wiphy->coverage_class); + + if (err) + return err; + } + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { err = drv_set_rts_threshold(local, wiphy->rts_threshold); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 8757ea73d544..de91d39e0276 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -214,6 +214,21 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, return ret; } +static inline int drv_set_coverage_class(struct ieee80211_local *local, + u8 value) +{ + int ret = 0; + might_sleep(); + + if (local->ops->set_coverage_class) + local->ops->set_coverage_class(&local->hw, value); + else + ret = -EOPNOTSUPP; + + trace_drv_set_coverage_class(local, value, ret); + return ret; +} + static inline void drv_sta_notify(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, enum sta_notify_cmd cmd, diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 977cc7528bc6..0ea258123b8e 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -491,6 +491,29 @@ TRACE_EVENT(drv_set_rts_threshold, ) ); +TRACE_EVENT(drv_set_coverage_class, + TP_PROTO(struct ieee80211_local *local, u8 value, int ret), + + TP_ARGS(local, value, ret), + + TP_STRUCT__entry( + LOCAL_ENTRY + __field(u8, value) + __field(int, ret) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + __entry->ret = ret; + __entry->value = value; + ), + + TP_printk( + LOCAL_PR_FMT " value:%d ret:%d", + LOCAL_PR_ARG, __entry->value, __entry->ret + ) +); + TRACE_EVENT(drv_sta_notify, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, -- cgit v1.2.3 From e1aa369ec8fb981ef78bc5be3b3c58de7c5ff769 Mon Sep 17 00:00:00 2001 From: Lukáš Turek <8an@praha12.net> Date: Mon, 21 Dec 2009 22:50:49 +0100 Subject: ath5k: Fix functions for getting/setting slot time Functions ath5k_hw_get_slot_time and ath5k_hw_set_slot_time were converting microseconds to clocks only for AR5210, although it's needed for all supported devices. The conversion was moved outside the hardware-specific branches. The original code also limited minimum slot time to 9, while turbo modes use 6, this was fixed too. Signed-off-by: Lukas Turek <8an@praha12.net> Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/qcu.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index eeebb9aef206..e322a104e7fe 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -520,12 +520,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) */ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) { + unsigned int slot_time_clock; + ATH5K_TRACE(ah->ah_sc); + if (ah->ah_version == AR5K_AR5210) - return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, - AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); + slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); else - return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; + slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); + + return ath5k_hw_clocktoh(slot_time_clock & 0xffff, ah->ah_turbo); } /* @@ -533,15 +537,17 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) */ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) { + u32 slot_time_clock = ath5k_hw_htoclock(slot_time, ah->ah_turbo); + ATH5K_TRACE(ah->ah_sc); - if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) + + if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) return -EINVAL; if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, - ah->ah_turbo), AR5K_SLOT_TIME); + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); else - ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); + ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); return 0; } -- cgit v1.2.3 From 3578e6ebb305e6bf7519f6e86741772892f4d51a Mon Sep 17 00:00:00 2001 From: Lukáš Turek <8an@praha12.net> Date: Mon, 21 Dec 2009 22:50:50 +0100 Subject: ath5k: Reimplement clock rate to usec conversion The original code was correct in 802.11a mode only, 802.11b/g uses different clock rates. The new code uses values taken from FreeBSD HAL and should be correct for all modes including turbo modes. The former rate calculation was used by slope coefficient calculation function ath5k_hw_write_ofdm_timings. However, this function requires the 802.11a values even in 802.11g mode. Thus the use of ath5k_hw_htoclock was replaced by hardcoded values. Possibly the slope coefficient calculation is not related to clock rate at all. Signed-off-by: Lukas Turek <8an@praha12.net> Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 22 +++--------- drivers/net/wireless/ath/ath5k/pcu.c | 64 ++++++++++++++++++++++++++++------ drivers/net/wireless/ath/ath5k/qcu.c | 4 +-- drivers/net/wireless/ath/ath5k/reset.c | 5 ++- 4 files changed, 62 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6a2a96761111..ae311d2dcc16 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1231,6 +1231,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); +/* Clock rate related functions */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); +unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); /* Key table (WEP) functions */ extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); @@ -1310,24 +1314,6 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); * Functions used internaly */ -/* - * Translate usec to hw clock units - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) -{ - return turbo ? (usec * 80) : (usec * 40); -} - -/* - * Translate hw clock units to usec - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) -{ - return turbo ? (clock / 80) : (clock / 40); -} - static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) { return &ah->common; diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 64fc1eb9b6d9..b601ff9865fd 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -187,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); + return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, + AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); } /** @@ -200,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) { ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), - ah->ah_turbo) <= timeout) + if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) + <= timeout) return -EINVAL; AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); + ath5k_hw_htoclock(ah, timeout)); return 0; } @@ -218,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); + return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, + AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); } /** @@ -231,16 +231,60 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) { ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), - ah->ah_turbo) <= timeout) + if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) + <= timeout) return -EINVAL; AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); + ath5k_hw_htoclock(ah, timeout)); return 0; } +/** + * ath5k_hw_htoclock - Translate usec to hw clock units + * + * @ah: The &struct ath5k_hw + * @usec: value in microseconds + */ +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) +{ + return usec * ath5k_hw_get_clockrate(ah); +} + +/** + * ath5k_hw_clocktoh - Translate hw clock units to usec + * @clock: value in hw clock units + */ +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) +{ + return clock / ath5k_hw_get_clockrate(ah); +} + +/** + * ath5k_hw_get_clockrate - Get the clock rate for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + int clock; + + if (channel->hw_value & CHANNEL_5GHZ) + clock = 40; /* 802.11a */ + else if (channel->hw_value & CHANNEL_CCK) + clock = 22; /* 802.11b */ + else + clock = 44; /* 802.11g */ + + /* Clock rate in turbo modes is twice the normal rate */ + if (channel->hw_value & CHANNEL_TURBO) + clock *= 2; + + return clock; +} + /** * ath5k_hw_set_lladdr - Set station id * diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index e322a104e7fe..abe36c0d139c 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -529,7 +529,7 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) else slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); - return ath5k_hw_clocktoh(slot_time_clock & 0xffff, ah->ah_turbo); + return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); } /* @@ -537,7 +537,7 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) */ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) { - u32 slot_time_clock = ath5k_hw_htoclock(slot_time, ah->ah_turbo); + u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); ATH5K_TRACE(ah->ah_sc); diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 62954fc77869..299b33a03979 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -60,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, !(channel->hw_value & CHANNEL_OFDM)); /* Get coefficient - * ALGO: coef = (5 * clock * carrier_freq) / 2) + * ALGO: coef = (5 * clock / carrier_freq) / 2 * we scale coef by shifting clock value by 24 for * better precision since we use integers */ /* TODO: Half/quarter rate */ - clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); - + clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; /* Get exponent -- cgit v1.2.3 From 6e08d228b6d8e93d7b25b3573c6da7da179c2ae1 Mon Sep 17 00:00:00 2001 From: Lukáš Turek <8an@praha12.net> Date: Mon, 21 Dec 2009 22:50:51 +0100 Subject: ath5k: Implement mac80211 callback set_coverage_class The callback sets slot time as specified in IEEE 802.11-2007 section 17.3.8.6 (for 20MHz channels only for now) and raises ACK and CTS timeouts accordingly. The values are persistent, they are restored after device reset. Signed-off-by: Lukas Turek <8an@praha12.net> Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 ++ drivers/net/wireless/ath/ath5k/base.c | 22 +++++++++++++ drivers/net/wireless/ath/ath5k/pcu.c | 57 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath5k/reset.c | 4 +++ 4 files changed, 85 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ae311d2dcc16..66bcb506a112 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1063,6 +1063,7 @@ struct ath5k_hw { u32 ah_cw_min; u32 ah_cw_max; u32 ah_limit_tx_retries; + u8 ah_coverage_class; /* Antenna Control */ u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; @@ -1200,6 +1201,7 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); /* Protocol Control Unit Functions */ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); +extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); /* BSSID Functions */ extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); extern void ath5k_hw_set_associd(struct ath5k_hw *ah); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index fdfaf0f618f1..b5015376d4ba 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -254,6 +254,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, u32 changes); static void ath5k_sw_scan_start(struct ieee80211_hw *hw); static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); +static void ath5k_set_coverage_class(struct ieee80211_hw *hw, + u8 coverage_class); static const struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, @@ -274,6 +276,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { .bss_info_changed = ath5k_bss_info_changed, .sw_scan_start = ath5k_sw_scan_start, .sw_scan_complete = ath5k_sw_scan_complete, + .set_coverage_class = ath5k_set_coverage_class, }; /* @@ -3262,3 +3265,22 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) ath5k_hw_set_ledstate(sc->ah, sc->assoc ? AR5K_LED_ASSOC : AR5K_LED_INIT); } + +/** + * ath5k_set_coverage_class - Set IEEE 802.11 coverage class + * + * @hw: struct ieee80211_hw pointer + * @coverage_class: IEEE 802.11 coverage class number + * + * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given + * coverage class. The values are persistent, they are restored after device + * reset. + */ +static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) +{ + struct ath5k_softc *sc = hw->priv; + + mutex_lock(&sc->lock); + ath5k_hw_set_coverage_class(sc->ah, coverage_class); + mutex_unlock(&sc->lock); +} diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index b601ff9865fd..aefe84f9c04b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -285,6 +285,42 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) return clock; } +/** + * ath5k_hw_get_default_slottime - Get the default slot time for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + + if (channel->hw_value & CHANNEL_TURBO) + return 6; /* both turbo modes */ + + if (channel->hw_value & CHANNEL_CCK) + return 20; /* 802.11b */ + + return 9; /* 802.11 a/g */ +} + +/** + * ath5k_hw_get_default_sifs - Get the default SIFS for current mode + * + * @ah: The &struct ath5k_hw + */ +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) +{ + struct ieee80211_channel *channel = ah->ah_current_channel; + + if (channel->hw_value & CHANNEL_TURBO) + return 8; /* both turbo modes */ + + if (channel->hw_value & CHANNEL_5GHZ) + return 16; /* 802.11a */ + + return 10; /* 802.11 b/g */ +} + /** * ath5k_hw_set_lladdr - Set station id * @@ -1094,3 +1130,24 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) return 0; } +/** + * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class + * + * @ah: The &struct ath5k_hw + * @coverage_class: IEEE 802.11 coverage class number + * + * Sets slot time, ACK timeout and CTS timeout for given coverage class. + */ +void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) +{ + /* As defined by IEEE 802.11-2007 17.3.8.6 */ + int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; + int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; + int cts_timeout = ack_timeout; + + ath5k_hw_set_slot_time(ah, slot_time); + ath5k_hw_set_ack_timeout(ah, ack_timeout); + ath5k_hw_set_cts_timeout(ah, cts_timeout); + + ah->ah_coverage_class = coverage_class; +} diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 299b33a03979..6690923fd78c 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1316,6 +1316,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* Restore antenna mode */ ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); + /* Restore slot time and ACK timeouts */ + if (ah->ah_coverage_class > 0) + ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); + /* * Configure QCUs/DCUs */ -- cgit v1.2.3 From 3dc1de0bf23816ed557ac8addf680cd5ee57e805 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 28 Dec 2009 16:57:15 +0800 Subject: mac80211: quit addba_resp_timer if Tx BA session is torn down Make addba_resp_timer aware the HT_AGG_STATE_REQ_STOP_BA_MSK mask so that when ___ieee80211_stop_tx_ba_session() is issued the timer will quit. Otherwise when suspend happens before the timer expired, the timer handler will be called immediately after resume and messes up driver status. Signed-off-by: Zhu Yi Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 5aa8f4a3ed17..718fbcff84d2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -179,7 +179,8 @@ static void sta_addba_resp_timer_expired(unsigned long data) /* check if the TID waits for addBA response */ spin_lock_bh(&sta->lock); - if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK)) != + if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK | + HT_AGG_STATE_REQ_STOP_BA_MSK)) != HT_ADDBA_REQUESTED_MSK) { spin_unlock_bh(&sta->lock); *state = HT_AGG_STATE_IDLE; -- cgit v1.2.3 From e00cfce0cb2a397859607bf515c6de9ce064b64a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Dec 2009 12:59:19 +0200 Subject: mac80211: Select lowest rate based on basic rate set in AP mode If the basic rate set is configured to not include the lowest rate (e.g., basic rate set = 6, 12, 24 Mbps in IEEE 802.11g mode), the AP should not send out broadcast frames at 1 Mbps. This type of configuration can be used to optimize channel usage in cases where there is no need for backwards compatibility with IEEE 802.11b-only devices. In AP mode, mac80211 was unconditionally using the lowest rate for Beacon frames and similarly, with all rate control algorithms that use rate_control_send_low(), the lowest rate ended up being used for all broadcast frames (and all unicast frames that are sent before association). Change this to take into account the basic rate configuration in AP mode, i.e., use the lowest rate in the basic rate set instead of the lowest supported rate when selecting the rate. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 ++ net/mac80211/rate.c | 25 +++++++++++++++++++++++++ net/mac80211/tx.c | 24 +++++++++++++----------- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ad4b70034e77..39c516c352be 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2299,6 +2299,7 @@ enum rate_control_changed { * @max_rate_idx: user-requested maximum rate (not MCS for now) * @skb: the skb that will be transmitted, the control information in it needs * to be filled in + * @ap: whether this frame is sent out in AP mode */ struct ieee80211_tx_rate_control { struct ieee80211_hw *hw; @@ -2308,6 +2309,7 @@ struct ieee80211_tx_rate_control { struct ieee80211_tx_rate reported_rate; bool rts, short_preamble; u8 max_rate_idx; + bool ap; }; struct rate_control_ops { diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index b9007f80cb92..6349e7f4dcae 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -207,6 +207,27 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc) return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); } +static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx) +{ + u8 i; + + if (basic_rates == 0) + return; /* assume basic rates unknown and accept rate */ + if (*idx < 0) + return; + if (basic_rates & (1 << *idx)) + return; /* selected rate is a basic rate */ + + for (i = *idx + 1; i <= max_rate_idx; i++) { + if (basic_rates & (1 << i)) { + *idx = i; + return; + } + } + + /* could not find a basic rate; use original selection */ +} + bool rate_control_send_low(struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) @@ -218,6 +239,10 @@ bool rate_control_send_low(struct ieee80211_sta *sta, info->control.rates[0].count = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 1 : txrc->hw->max_rate_tries; + if (!sta && txrc->ap) + rc_send_low_broadcast(&info->control.rates[0].idx, + txrc->bss_conf->basic_rates, + txrc->sband->n_bitrates); return true; } return false; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 140da4a7f13d..4961168f5091 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -520,6 +520,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) txrc.skb = tx->skb; txrc.reported_rate.idx = -1; txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; + txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; /* set up RTS protection if desired */ if (len > tx->local->hw.wiphy->rts_threshold) { @@ -2060,6 +2061,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, struct beacon_data *beacon; struct ieee80211_supported_band *sband; enum ieee80211_band band = local->hw.conf.channel->band; + struct ieee80211_tx_rate_control txrc; sband = local->hw.wiphy->bands[band]; @@ -2167,21 +2169,21 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, info = IEEE80211_SKB_CB(skb); info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + info->flags |= IEEE80211_TX_CTL_NO_ACK; info->band = band; - /* - * XXX: For now, always use the lowest rate - */ - info->control.rates[0].idx = 0; - info->control.rates[0].count = 1; - info->control.rates[1].idx = -1; - info->control.rates[2].idx = -1; - info->control.rates[3].idx = -1; - info->control.rates[4].idx = -1; - BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); + + memset(&txrc, 0, sizeof(txrc)); + txrc.hw = hw; + txrc.sband = sband; + txrc.bss_conf = &sdata->vif.bss_conf; + txrc.skb = skb; + txrc.reported_rate.idx = -1; + txrc.max_rate_idx = sdata->max_ratectrl_rateidx; + txrc.ap = true; + rate_control_get_rate(sdata, NULL, &txrc); info->control.vif = vif; - info->flags |= IEEE80211_TX_CTL_NO_ACK; info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; out: -- cgit v1.2.3 From 37eb0b164cf9fa9f70c8500926f5cde7c652f48e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 Jan 2010 13:09:08 +0200 Subject: cfg80211/mac80211: Use more generic bitrate mask for rate control Extend struct cfg80211_bitrate_mask to actually use a bitfield mask instead of just a single fixed or maximum rate index. This change itself does not modify the behavior (except for debugfs files), but it prepares cfg80211 and mac80211 for a new nl80211 command for setting which rates can be used in TX rate control. Since frames are now going through the rate control algorithm unconditionally, the internal IEEE80211_TX_INTFL_RCALGO flag can now be removed. The RC implementations can use the rate_idx_mask value to optimize their behavior if only a single rate is enabled. The old max_rate_idx in struct ieee80211_tx_rate_control is maintained (but commented as deprecated) for backwards compatibility with existing RC implementations. Once these implementations have been updated to use the more generic rate_idx_mask, the max_rate_idx value can be removed. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- include/net/cfg80211.h | 13 ++------- include/net/mac80211.h | 8 +++--- net/mac80211/cfg.c | 32 +++------------------- net/mac80211/debugfs_netdev.c | 22 ++++++++------- net/mac80211/ieee80211_i.h | 4 +-- net/mac80211/iface.c | 8 ++++-- net/mac80211/rate.c | 63 +++++++++++++++++++++++++++++++++++-------- net/mac80211/rate.h | 5 +--- net/mac80211/tx.c | 12 +++++++-- net/wireless/wext-compat.c | 34 ++++++++++++++++++++--- 10 files changed, 122 insertions(+), 79 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a8d5d04314b9..22e062afb5a1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -857,20 +857,11 @@ enum tx_power_setting { * cfg80211_bitrate_mask - masks for bitrate control */ struct cfg80211_bitrate_mask { -/* - * As discussed in Berlin, this struct really - * should look like this: - struct { u32 legacy; - u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; + /* TODO: add support for masking MCS rates; e.g.: */ + /* u8 mcs[IEEE80211_HT_MCS_MASK_LEN]; */ } control[IEEE80211_NUM_BANDS]; - - * Since we can always fix in-kernel users, let's keep - * it simpler for now: - */ - u32 fixed; /* fixed bitrate, 0 == not fixed */ - u32 maxrate; /* in kbps, 0 == no limit */ }; /** * struct cfg80211_pmksa - PMK Security Association diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 39c516c352be..7e5af6d90b93 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -255,9 +255,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be * set by rate control algorithms to indicate probe rate, will * be cleared for fragmented frames (except on the last fragment) - * @IEEE80211_TX_INTFL_RCALGO: mac80211 internal flag, do not test or - * set this flag in the driver; indicates that the rate control - * algorithm was used and should be notified of TX status * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, * used to indicate that a pending frame requires TX processing before * it can be sent out. @@ -287,7 +284,6 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_AMPDU = BIT(10), IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), - IEEE80211_TX_INTFL_RCALGO = BIT(13), IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), IEEE80211_TX_INTFL_RETRIED = BIT(15), IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), @@ -2297,6 +2293,9 @@ enum rate_control_changed { * @short_preamble: whether mac80211 will request short-preamble transmission * if the selected rate supports it * @max_rate_idx: user-requested maximum rate (not MCS for now) + * (deprecated; this will be removed once drivers get updated to use + * rate_idx_mask) + * @rate_idx_mask: user-requested rate mask (not MCS for now) * @skb: the skb that will be transmitted, the control information in it needs * to be filled in * @ap: whether this frame is sent out in AP mode @@ -2309,6 +2308,7 @@ struct ieee80211_tx_rate_control { struct ieee80211_tx_rate reported_rate; bool rts, short_preamble; u8 max_rate_idx; + u32 rate_idx_mask; bool ap; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 976014c5e742..e5dda6fb8dff 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1406,8 +1406,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); int i; - u32 target_rate; - struct ieee80211_supported_band *sband; /* * This _could_ be supported by providing a hook for @@ -1417,35 +1415,11 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) return -EOPNOTSUPP; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - /* - * target_rate = -1, rate->fixed = 0 means auto only, so use all rates - * target_rate = X, rate->fixed = 1 means only rate X - * target_rate = X, rate->fixed = 0 means all rates <= X - */ - sdata->max_ratectrl_rateidx = -1; - sdata->force_unicast_rateidx = -1; - if (mask->fixed) - target_rate = mask->fixed / 100; - else if (mask->maxrate) - target_rate = mask->maxrate / 100; - else - return 0; + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + sdata->rc_rateidx_mask[i] = mask->control[i].legacy; - for (i = 0; i< sband->n_bitrates; i++) { - if (target_rate != sband->bitrates[i].bitrate) - continue; - - /* requested bitrate found */ - sdata->max_ratectrl_rateidx = i; - if (mask->fixed) - sdata->force_unicast_rateidx = i; - return 0; - } - - return -EINVAL; + return 0; } static int ieee80211_remain_on_channel(struct wiphy *wiphy, diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 59f6e3bcbd09..1481049f0f71 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -127,8 +127,10 @@ __IEEE80211_IF_FILE(name, ieee80211_if_write_##name) /* common attributes */ IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); -IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); -IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); +IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], + HEX); +IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], + HEX); /* STA attributes */ IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); @@ -264,8 +266,8 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, static void add_sta_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted, sta); - DEBUGFS_ADD(force_unicast_rateidx, sta); - DEBUGFS_ADD(max_ratectrl_rateidx, sta); + DEBUGFS_ADD(rc_rateidx_mask_2ghz, sta); + DEBUGFS_ADD(rc_rateidx_mask_5ghz, sta); DEBUGFS_ADD(bssid, sta); DEBUGFS_ADD(aid, sta); @@ -275,8 +277,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) static void add_ap_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted, ap); - DEBUGFS_ADD(force_unicast_rateidx, ap); - DEBUGFS_ADD(max_ratectrl_rateidx, ap); + DEBUGFS_ADD(rc_rateidx_mask_2ghz, ap); + DEBUGFS_ADD(rc_rateidx_mask_5ghz, ap); DEBUGFS_ADD(num_sta_ps, ap); DEBUGFS_ADD(dtim_count, ap); @@ -286,8 +288,8 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) static void add_wds_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted, wds); - DEBUGFS_ADD(force_unicast_rateidx, wds); - DEBUGFS_ADD(max_ratectrl_rateidx, wds); + DEBUGFS_ADD(rc_rateidx_mask_2ghz, wds); + DEBUGFS_ADD(rc_rateidx_mask_5ghz, wds); DEBUGFS_ADD(peer, wds); } @@ -295,8 +297,8 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) static void add_vlan_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD(drop_unencrypted, vlan); - DEBUGFS_ADD(force_unicast_rateidx, vlan); - DEBUGFS_ADD(max_ratectrl_rateidx, vlan); + DEBUGFS_ADD(rc_rateidx_mask_2ghz, vlan); + DEBUGFS_ADD(rc_rateidx_mask_5ghz, vlan); } static void add_monitor_files(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a27921ee6e63..3e4ac3f30857 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -494,8 +494,8 @@ struct ieee80211_sub_if_data { */ struct ieee80211_if_ap *bss; - int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ - int max_ratectrl_rateidx; /* max TX rateidx for rate control */ + /* bitmap of allowed (non-MCS) rate indexes for rate control */ + u32 rc_rateidx_mask[IEEE80211_NUM_BANDS]; union { struct ieee80211_if_ap ap; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 264a6c975f8b..fe140bf033f9 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -856,8 +856,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, INIT_LIST_HEAD(&sdata->key_list); - sdata->force_unicast_rateidx = -1; - sdata->max_ratectrl_rateidx = -1; + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + struct ieee80211_supported_band *sband; + sband = local->hw.wiphy->bands[i]; + sdata->rc_rateidx_mask[i] = + sband ? (1 << sband->n_bitrates) - 1 : 0; + } /* setup type-dependent data */ ieee80211_setup_sdata(sdata, type); diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6349e7f4dcae..c74b7c85403c 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -249,6 +249,38 @@ bool rate_control_send_low(struct ieee80211_sta *sta, } EXPORT_SYMBOL(rate_control_send_low); +static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, + int n_bitrates, u32 mask) +{ + int j; + + /* See whether the selected rate or anything below it is allowed. */ + for (j = rate->idx; j >= 0; j--) { + if (mask & (1 << j)) { + /* Okay, found a suitable rate. Use it. */ + rate->idx = j; + return; + } + } + + /* Try to find a higher rate that would be allowed */ + for (j = rate->idx + 1; j < n_bitrates; j++) { + if (mask & (1 << j)) { + /* Okay, found a suitable rate. Use it. */ + rate->idx = j; + return; + } + } + + /* + * Uh.. No suitable rate exists. This should not really happen with + * sane TX rate mask configurations. However, should someone manage to + * configure supported rates and TX rate mask in incompatible way, + * allow the frame to be transmitted with whatever the rate control + * selected. + */ +} + void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_tx_rate_control *txrc) @@ -258,6 +290,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta *ista = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); int i; + u32 mask; if (sta) { ista = &sta->sta; @@ -270,23 +303,31 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, info->control.rates[i].count = 1; } - if (sta && sdata->force_unicast_rateidx > -1) { - info->control.rates[0].idx = sdata->force_unicast_rateidx; - } else { - ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); - info->flags |= IEEE80211_TX_INTFL_RCALGO; - } + ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); /* - * try to enforce the maximum rate the user wanted + * Try to enforce the rateidx mask the user wanted. skip this if the + * default mask (allow all rates) is used to save some processing for + * the common case. */ - if (sdata->max_ratectrl_rateidx > -1) + mask = sdata->rc_rateidx_mask[info->band]; + if (mask != (1 << txrc->sband->n_bitrates) - 1) { + if (sta) { + /* Filter out rates that the STA does not support */ + mask &= sta->sta.supp_rates[info->band]; + } + /* + * Make sure the rate index selected for each TX rate is + * included in the configured mask and change the rate indexes + * if needed. + */ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + /* Rate masking supports only legacy rates for now */ if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) continue; - info->control.rates[i].idx = - min_t(s8, info->control.rates[i].idx, - sdata->max_ratectrl_rateidx); + rate_idx_match_mask(&info->control.rates[i], + txrc->sband->n_bitrates, mask); + } } BUG_ON(info->control.rates[0].idx < 0); diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index cb9bd1f65e27..669dddd40521 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -44,10 +44,7 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, struct rate_control_ref *ref = local->rate_ctrl; struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - if (likely(info->flags & IEEE80211_TX_INTFL_RCALGO)) - ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4961168f5091..d3a44812f8bf 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -519,7 +519,11 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) txrc.bss_conf = &tx->sdata->vif.bss_conf; txrc.skb = tx->skb; txrc.reported_rate.idx = -1; - txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; + txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band]; + if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) + txrc.max_rate_idx = -1; + else + txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP; /* set up RTS protection if desired */ @@ -2178,7 +2182,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, txrc.bss_conf = &sdata->vif.bss_conf; txrc.skb = skb; txrc.reported_rate.idx = -1; - txrc.max_rate_idx = sdata->max_ratectrl_rateidx; + txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; + if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) + txrc.max_rate_idx = -1; + else + txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; txrc.ap = true; rate_control_get_rate(sdata, NULL, &txrc); diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 4198243a3dff..966d2f01beac 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1204,21 +1204,47 @@ int cfg80211_wext_siwrate(struct net_device *dev, struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct cfg80211_bitrate_mask mask; + u32 fixed, maxrate; + struct ieee80211_supported_band *sband; + int band, ridx; + bool match = false; if (!rdev->ops->set_bitrate_mask) return -EOPNOTSUPP; - mask.fixed = 0; - mask.maxrate = 0; + memset(&mask, 0, sizeof(mask)); + fixed = 0; + maxrate = 0; if (rate->value < 0) { /* nothing */ } else if (rate->fixed) { - mask.fixed = rate->value / 1000; /* kbps */ + fixed = rate->value / 100000; } else { - mask.maxrate = rate->value / 1000; /* kbps */ + maxrate = rate->value / 100000; + } + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wdev->wiphy->bands[band]; + if (sband == NULL) + continue; + for (ridx = 0; ridx < sband->n_bitrates; ridx++) { + struct ieee80211_rate *srate = &sband->bitrates[ridx]; + if (fixed == srate->bitrate) { + mask.control[band].legacy = 1 << ridx; + match = true; + break; + } + if (srate->bitrate <= maxrate) { + mask.control[band].legacy |= 1 << ridx; + match = true; + } + } } + if (!match) + return -EINVAL; + return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); } EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); -- cgit v1.2.3 From 13ae75b103e07304a34ab40c9136e9f53e06475c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 29 Dec 2009 12:59:45 +0200 Subject: nl80211: New command for setting TX rate mask for rate control Add a new NL80211_CMD_SET_TX_BITRATE_MASK command and related attributes to provide support for setting TX rate mask for rate control. This uses the existing cfg80211 set_bitrate_mask operation that was previously used only with WEXT compat code (SIOCSIWRATE). The nl80211 command allows more generic configuration of allowed rates as a mask instead of fixed/max rate. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 44 +++++++++++++++++++ include/net/cfg80211.h | 4 +- net/wireless/nl80211.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 2 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index d4c556de7170..7a1c8c145b22 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -295,6 +295,10 @@ * This command is also used as an event to notify when a requested * remain-on-channel duration has expired. * + * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX + * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface + * and @NL80211_ATTR_TX_RATES the set of allowed rates. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -381,6 +385,8 @@ enum nl80211_commands { NL80211_CMD_REMAIN_ON_CHANNEL, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + NL80211_CMD_SET_TX_BITRATE_MASK, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -640,6 +646,13 @@ enum nl80211_commands { * * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. * + * @NL80211_ATTR_TX_RATES: Nested set of attributes + * (enum nl80211_tx_rate_attributes) describing TX rates per band. The + * enum nl80211_band value is used as the index (nla_type() of the nested + * data. If a band is not included, it will be configured to allow all + * rates based on negotiated supported rates information. This attribute + * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -783,6 +796,8 @@ enum nl80211_attrs { NL80211_ATTR_WIPHY_COVERAGE_CLASS, + NL80211_ATTR_TX_RATES, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1482,4 +1497,33 @@ enum nl80211_key_attributes { NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 }; +/** + * enum nl80211_tx_rate_attributes - TX rate set attributes + * @__NL80211_TXRATE_INVALID: invalid + * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection + * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with + * 1 = 500 kbps) but without the IE length restriction (at most + * %NL80211_MAX_SUPP_RATES in a single array). + * @__NL80211_TXRATE_AFTER_LAST: internal + * @NL80211_TXRATE_MAX: highest TX rate attribute + */ +enum nl80211_tx_rate_attributes { + __NL80211_TXRATE_INVALID, + NL80211_TXRATE_LEGACY, + + /* keep last */ + __NL80211_TXRATE_AFTER_LAST, + NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 +}; + +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ - 2.4 GHz ISM band + * @NL80211_BAND_5GHZ - around 5 GHz band (4.9 - 5.7 GHz) + */ +enum nl80211_band { + NL80211_BAND_2GHZ, + NL80211_BAND_5GHZ, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 22e062afb5a1..0d734413b5fb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -39,8 +39,8 @@ * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) */ enum ieee80211_band { - IEEE80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ, + IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, + IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, /* keep last */ IEEE80211_NUM_BANDS diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c09fbcd278fb..b804062e0179 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -144,6 +144,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { .len = WLAN_PMKID_LEN }, [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, + [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, }; /* policy for the attributes */ @@ -575,6 +576,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(del_pmksa, DEL_PMKSA); CMD(flush_pmksa, FLUSH_PMKSA); CMD(remain_on_channel, REMAIN_ON_CHANNEL); + CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); @@ -4438,6 +4440,109 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, return err; } +static u32 rateset_to_mask(struct ieee80211_supported_band *sband, + u8 *rates, u8 rates_len) +{ + u8 i; + u32 mask = 0; + + for (i = 0; i < rates_len; i++) { + int rate = (rates[i] & 0x7f) * 5; + int ridx; + for (ridx = 0; ridx < sband->n_bitrates; ridx++) { + struct ieee80211_rate *srate = + &sband->bitrates[ridx]; + if (rate == srate->bitrate) { + mask |= 1 << ridx; + break; + } + } + if (ridx == sband->n_bitrates) + return 0; /* rate not found */ + } + + return mask; +} + +static struct nla_policy +nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] __read_mostly = { + [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, + .len = NL80211_MAX_SUPP_RATES }, +}; + +static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, + struct genl_info *info) +{ + struct nlattr *tb[NL80211_TXRATE_MAX + 1]; + struct cfg80211_registered_device *rdev; + struct cfg80211_bitrate_mask mask; + int err, rem, i; + struct net_device *dev; + struct nlattr *tx_rates; + struct ieee80211_supported_band *sband; + + if (info->attrs[NL80211_ATTR_TX_RATES] == NULL) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + if (!rdev->ops->set_bitrate_mask) { + err = -EOPNOTSUPP; + goto unlock; + } + + memset(&mask, 0, sizeof(mask)); + /* Default to all rates enabled */ + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + sband = rdev->wiphy.bands[i]; + mask.control[i].legacy = + sband ? (1 << sband->n_bitrates) - 1 : 0; + } + + /* + * The nested attribute uses enum nl80211_band as the index. This maps + * directly to the enum ieee80211_band values used in cfg80211. + */ + nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) + { + enum ieee80211_band band = nla_type(tx_rates); + if (band < 0 || band >= IEEE80211_NUM_BANDS) { + err = -EINVAL; + goto unlock; + } + sband = rdev->wiphy.bands[band]; + if (sband == NULL) { + err = -EINVAL; + goto unlock; + } + nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), + nla_len(tx_rates), nl80211_txattr_policy); + if (tb[NL80211_TXRATE_LEGACY]) { + mask.control[band].legacy = rateset_to_mask( + sband, + nla_data(tb[NL80211_TXRATE_LEGACY]), + nla_len(tb[NL80211_TXRATE_LEGACY])); + if (mask.control[band].legacy == 0) { + err = -EINVAL; + goto unlock; + } + } + } + + err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask); + + unlock: + dev_put(dev); + cfg80211_unlock_rdev(rdev); + unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -4712,6 +4817,12 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, + .doit = nl80211_set_tx_bitrate_mask, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { -- cgit v1.2.3 From 6c0fe26581406bff3d15fd6051453e80cfe70fd6 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 30 Dec 2009 11:36:31 +0100 Subject: rt2x00: RF3052 is a valid RF chipset for USB devices as well. The RF3052 chipset is now also being integrated onto USB devices, so allow the RF chipset and don't treat it as PCI/SOC only. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 126899091707..d300ff84b717 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1862,7 +1862,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) !rt2x00_rf(rt2x00dev, RF3020) && !rt2x00_rf(rt2x00dev, RF2020) && !rt2x00_rf(rt2x00dev, RF3021) && - !rt2x00_rf(rt2x00dev, RF3022)) { + !rt2x00_rf(rt2x00dev, RF3022) && + !rt2x00_rf(rt2x00dev, RF3052)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -2047,7 +2048,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) if (rt2x00_rf(rt2x00dev, RF2820) || rt2x00_rf(rt2x00dev, RF2720) || - (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) { + rt2x00_rf(rt2x00dev, RF3052)) { spec->num_channels = 14; spec->channels = rf_vals; } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { -- cgit v1.2.3 From 67a4c1e24d58e0d88ed88539641631f6fc8a0cfd Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 30 Dec 2009 11:36:32 +0100 Subject: rt2x00: Unify rt2800 WPDMA ready waiting functions. The rt2800pci_wait_wpdma_ready and rt2800usb_wait_wpdma_ready functions are exactly the same, so unify them into rt200lib. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 1 + drivers/net/wireless/rt2x00/rt2800pci.c | 24 +++--------------------- drivers/net/wireless/rt2x00/rt2800usb.c | 22 ++-------------------- 4 files changed, 25 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d300ff84b717..ca700a402e64 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -245,6 +245,25 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2800_mcu_request); +int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) +{ + unsigned int i; + u32 reg; + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { + rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); + if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && + !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) + return 0; + + msleep(1); + } + + ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); + return -EACCES; +} +EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); + #ifdef CONFIG_RT2X00_LIB_DEBUGFS const struct rt2x00debug rt2800_rt2x00debug = { .owner = THIS_MODULE, diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 535ce22f2ac8..9adb3431374d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -139,6 +139,7 @@ void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, int rt2800_init_registers(struct rt2x00_dev *rt2x00dev); int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev); int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev); +int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b93eabb4fbe1..daea0b7c416e 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -453,24 +453,6 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); } -static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && - !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) - return 0; - - msleep(1); - } - - ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); - return -EACCES; -} - static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -479,10 +461,10 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || + if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || rt2800pci_init_queues(rt2x00dev) || rt2800_init_registers(rt2x00dev) || - rt2800pci_wait_wpdma_ready(rt2x00dev) || + rt2800_wait_wpdma_ready(rt2x00dev) || rt2800_init_bbp(rt2x00dev) || rt2800_init_rfcsr(rt2x00dev))) return -EIO; @@ -562,7 +544,7 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); /* Wait for DMA, ignore error */ - rt2800pci_wait_wpdma_ready(rt2x00dev); + rt2800_wait_wpdma_ready(rt2x00dev); } static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0510f020dcf5..82755cf8b73e 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -248,24 +248,6 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); } -static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && - !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) - return 0; - - msleep(1); - } - - ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); - return -EACCES; -} - static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -274,7 +256,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || + if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || rt2800_init_registers(rt2x00dev) || rt2800_init_bbp(rt2x00dev) || rt2800_init_rfcsr(rt2x00dev))) @@ -344,7 +326,7 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); /* Wait for DMA, ignore error */ - rt2800usb_wait_wpdma_ready(rt2x00dev); + rt2800_wait_wpdma_ready(rt2x00dev); rt2x00usb_disable_radio(rt2x00dev); } -- cgit v1.2.3 From b3579d6adcf7b24464274967a96d12467cfb11a7 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Wed, 30 Dec 2009 11:36:34 +0100 Subject: rt2x00: Make rt2800_init_led static and don't export it. It is only used within the rt2800lib module itself. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 3 +-- drivers/net/wireless/rt2x00/rt2800lib.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index ca700a402e64..529a37364eb0 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -366,7 +366,7 @@ static int rt2800_blink_set(struct led_classdev *led_cdev, return 0; } -void rt2800_init_led(struct rt2x00_dev *rt2x00dev, +static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, struct rt2x00_led *led, enum led_type type) { led->rt2x00dev = rt2x00dev; @@ -375,7 +375,6 @@ void rt2800_init_led(struct rt2x00_dev *rt2x00dev, led->led_dev.blink_set = rt2800_blink_set; led->flags = LED_INITIALIZED; } -EXPORT_SYMBOL_GPL(rt2800_init_led); #endif /* CONFIG_RT2X00_LIB_LEDS */ /* diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 9adb3431374d..ebabeae62d1b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -114,8 +114,6 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, extern const struct rt2x00debug rt2800_rt2x00debug; int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev); -void rt2800_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, enum led_type type); int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_crypto *crypto, struct ieee80211_key_conf *key); -- cgit v1.2.3 From 7044cc565b45a898c140fb185174a66f2d68a163 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:19 +0200 Subject: mac80211: add functions to create PS Poll and Nullfunc templates Some hardware, for example wl1251 and wl1271, handle the transmission of power save related frames in hardware, but the driver is responsible for creating the templates. It's better to create the templates in mac80211, that way all drivers can benefit from this. Add two new functions, ieee80211_pspoll_get() and ieee80211_nullfunc_get() which drivers need to call to get the frame. Drivers are also responsible for updating the templates after each association. Also new struct ieee80211_hdr_3addr is added to ieee80211.h to make it easy to calculate length of the Nullfunc frame. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 9 ++++++ include/net/mac80211.h | 30 ++++++++++++++++++ net/mac80211/tx.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index aeea282bd2fe..602c0692c3fc 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -130,6 +130,15 @@ struct ieee80211_hdr { u8 addr4[6]; } __attribute__ ((packed)); +struct ieee80211_hdr_3addr { + __le16 frame_control; + __le16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + __le16 seq_ctrl; +} __attribute__ ((packed)); + /** * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set * @fc: frame control bytes in little-endian byteorder diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7e5af6d90b93..75f46e26ad60 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1874,6 +1874,36 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, return ieee80211_beacon_get_tim(hw, vif, NULL, NULL); } +/** + * ieee80211_pspoll_get - retrieve a PS Poll template + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * + * Creates a PS Poll a template which can, for example, uploaded to + * hardware. The template must be updated after association so that correct + * AID, BSSID and MAC address is used. + * + * Note: Caller (or hardware) is responsible for setting the + * &IEEE80211_FCTL_PM bit. + */ +struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); + +/** + * ieee80211_nullfunc_get - retrieve a nullfunc template + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * + * Creates a Nullfunc template which can, for example, uploaded to + * hardware. The template must be updated after association so that correct + * BSSID and address is used. + * + * Note: Caller (or hardware) is responsible for setting the + * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields. + */ +struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); + /** * ieee80211_rts_get - RTS frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d3a44812f8bf..055b45b146d9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2200,6 +2200,84 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_beacon_get_tim); +struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_managed *ifmgd; + struct ieee80211_pspoll *pspoll; + struct ieee80211_local *local; + struct sk_buff *skb; + + if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) + return NULL; + + sdata = vif_to_sdata(vif); + ifmgd = &sdata->u.mgd; + local = sdata->local; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for " + "pspoll template\n", sdata->name); + return NULL; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); + memset(pspoll, 0, sizeof(*pspoll)); + pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_PSPOLL); + pspoll->aid = cpu_to_le16(ifmgd->aid); + + /* aid in PS-Poll has its two MSBs each set to 1 */ + pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); + + memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); + memcpy(pspoll->ta, vif->addr, ETH_ALEN); + + return skb; +} +EXPORT_SYMBOL(ieee80211_pspoll_get); + +struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ieee80211_hdr_3addr *nullfunc; + struct ieee80211_sub_if_data *sdata; + struct ieee80211_if_managed *ifmgd; + struct ieee80211_local *local; + struct sk_buff *skb; + + if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) + return NULL; + + sdata = vif_to_sdata(vif); + ifmgd = &sdata->u.mgd; + local = sdata->local; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "template\n", sdata->name); + return NULL; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr_3addr *) skb_put(skb, + sizeof(*nullfunc)); + memset(nullfunc, 0, sizeof(*nullfunc)); + nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS); + memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); + memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); + memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); + + return skb; +} +EXPORT_SYMBOL(ieee80211_nullfunc_get); + void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_info *frame_txctl, -- cgit v1.2.3 From d8cd189e9b1e050629f545e76b21a321f62c29bf Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:26 +0200 Subject: mac80211: use PS Poll and Nullfunc templates when sending such frames To avoid duplicate code, use ieee80211_[pspoll|nullfunc]_get() to get templates for PS Poll and Nullfunc frames in mlme.c. Compile-tested only. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 48 +++++++++--------------------------------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 97bcf2278bdb..5484cf930a87 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -249,30 +249,15 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, void ieee80211_send_pspoll(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_pspoll *pspoll; struct sk_buff *skb; - u16 fc; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll)); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for " - "pspoll frame\n", sdata->name); + skb = ieee80211_pspoll_get(&local->hw, &sdata->vif); + if (!skb) return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll)); - memset(pspoll, 0, sizeof(*pspoll)); - fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM; - pspoll->frame_control = cpu_to_le16(fc); - pspoll->aid = cpu_to_le16(ifmgd->aid); - /* aid in PS-Poll has its two MSBs each set to 1 */ - pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14); - - memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); - memcpy(pspoll->ta, sdata->vif.addr, ETH_ALEN); + pspoll = (struct ieee80211_pspoll *) skb->data; + pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); @@ -283,30 +268,15 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, int powersave) { struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - __le16 fc; + struct ieee80211_hdr_3addr *nullfunc; - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); + if (!skb) return; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " - "frame\n", sdata->name); - return; - } - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(nullfunc, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); + nullfunc = (struct ieee80211_hdr_3addr *) skb->data; if (powersave) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - nullfunc->frame_control = fc; - memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); - memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); - memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); + nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); -- cgit v1.2.3 From f7f70579340dba1e551c0e52349fde0370592174 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:32 +0200 Subject: wl1251: get PS Poll and Nullfunc templates from mac80211 Now that mac80211 creates templates for PS Poll and Nullfunc frames, use them instead of creating our own. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 58 +++++++++---------------------- 1 file changed, 16 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4e373f3dbc43..6cce86462fac 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -563,45 +563,6 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } -static int wl1251_build_null_data(struct wl1251 *wl) -{ - struct wl12xx_null_data_template template; - - if (!is_zero_ether_addr(wl->bssid)) { - memcpy(template.header.da, wl->bssid, ETH_ALEN); - memcpy(template.header.bssid, wl->bssid, ETH_ALEN); - } else { - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - } - - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - - return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, - sizeof(template)); - -} - -static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid) -{ - struct wl12xx_ps_poll_template template; - - memcpy(template.bssid, wl->bssid, ETH_ALEN); - memcpy(template.ta, wl->mac_addr, ETH_ALEN); - - /* aid in PS-Poll has its two MSBs each set to 1 */ - template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); - - template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - - return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, - sizeof(template)); - -} - static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1251 *wl = hw->priv; @@ -1101,7 +1062,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, { enum wl1251_cmd_ps_mode mode; struct wl1251 *wl = hw->priv; - struct sk_buff *beacon; + struct sk_buff *beacon, *skb; int ret; wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1115,7 +1076,13 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_BSSID) { memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - ret = wl1251_build_null_data(wl); + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); + if (!skb) + goto out_sleep; + + ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, + skb->data, skb->len); + dev_kfree_skb(skb); if (ret < 0) goto out; @@ -1136,7 +1103,14 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, wl->dtim_period); wl->aid = bss_conf->aid; - ret = wl1251_build_ps_poll(wl, wl->aid); + skb = ieee80211_pspoll_get(wl->hw, wl->vif); + if (!skb) + goto out_sleep; + + ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, + skb->data, + skb->len); + dev_kfree_skb(skb); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From 05e54ea6cce400ac34528d705179b45244f61074 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:38 +0200 Subject: mac80211: create Probe Request template Certain type of hardware, for example wl1251 and wl1271, need a template for the Probe Request. Create a function ieee80211_probereq_get() which creates the template and drivers send it to hardware. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 17 +++++++++++++++++ net/mac80211/tx.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 75f46e26ad60..e1e73c6abeff 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1904,6 +1904,23 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +/** + * ieee80211_probereq_get - retrieve a Probe Request template + * @hw: pointer obtained from ieee80211_alloc_hw(). + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @ssid: SSID buffer + * @ssid_len: length of SSID + * @ie: buffer containing all IEs except SSID for the template + * @ie_len: length of the IE buffer + * + * Creates a Probe Request template which can, for example, be uploaded to + * hardware. + */ +struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len); + /** * ieee80211_rts_get - RTS frame generation function * @hw: pointer obtained from ieee80211_alloc_hw(). diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 055b45b146d9..0661e696a1dd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2278,6 +2278,56 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_nullfunc_get); +struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *ssid, size_t ssid_len, + const u8 *ie, size_t ie_len) +{ + struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local; + struct ieee80211_hdr_3addr *hdr; + struct sk_buff *skb; + size_t ie_ssid_len; + u8 *pos; + + sdata = vif_to_sdata(vif); + local = sdata->local; + ie_ssid_len = 2 + ssid_len; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + + ie_ssid_len + ie_len); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for probe " + "request template\n", sdata->name); + return NULL; + } + + skb_reserve(skb, local->hw.extra_tx_headroom); + + hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr)); + memset(hdr, 0, sizeof(*hdr)); + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_REQ); + memset(hdr->addr1, 0xff, ETH_ALEN); + memcpy(hdr->addr2, vif->addr, ETH_ALEN); + memset(hdr->addr3, 0xff, ETH_ALEN); + + pos = skb_put(skb, ie_ssid_len); + *pos++ = WLAN_EID_SSID; + *pos++ = ssid_len; + if (ssid) + memcpy(pos, ssid, ssid_len); + pos += ssid_len; + + if (ie) { + pos = skb_put(skb, ie_len); + memcpy(pos, ie, ie_len); + } + + return skb; +} +EXPORT_SYMBOL(ieee80211_probereq_get); + void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const void *frame, size_t frame_len, const struct ieee80211_tx_info *frame_txctl, -- cgit v1.2.3 From 7c12ce8b854df346388ea56d684784e3484012cf Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:44 +0200 Subject: mac80211: use Probe Request template when sending a direct scan As mac80211 now has a separate function for creating Probe Request templates, better to use it when sending direct Probe Requests to an AP. Only the bssid needs to be updated in the template before sending it. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/util.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index bc73904d561c..72a98e844718 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1000,37 +1000,29 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + - ie_len); - if (!skb) { - printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", sdata->name); + size_t buf_len; + u8 *buf; + + /* FIXME: come up with a proper value */ + buf = kmalloc(200 + ie_len, GFP_KERNEL); + if (!buf) { + printk(KERN_DEBUG "%s: failed to allocate temporary IE " + "buffer\n", sdata->name); return; } - skb_reserve(skb, local->hw.extra_tx_headroom); - mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); - memset(mgmt, 0, 24); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); + buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, + local->hw.conf.channel->band); + + skb = ieee80211_probereq_get(&local->hw, &sdata->vif, + ssid, ssid_len, + buf, buf_len); + if (dst) { + mgmt = (struct ieee80211_mgmt *) skb->data; memcpy(mgmt->da, dst, ETH_ALEN); memcpy(mgmt->bssid, dst, ETH_ALEN); - } else { - memset(mgmt->da, 0xff, ETH_ALEN); - memset(mgmt->bssid, 0xff, ETH_ALEN); } - pos = skb_put(skb, 2 + ssid_len); - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - memcpy(pos, ssid, ssid_len); - pos += ssid_len; - - skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len, - local->hw.conf.channel->band)); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); -- cgit v1.2.3 From 3a98c30f3e8bb1f32b5bcb74a39647b3670de275 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:51 +0200 Subject: wl1251: cleanup scanning code The current scanning code wasn't following the preferred style. Move code related to scan and trigger scan to commans to wl1251_cmd.c. Because there's now less code in wl1251_hw_scan(), the function can be now merged with wl1251_op_hw_scan(). Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_cmd.c | 82 ++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1251_cmd.h | 17 ++-- drivers/net/wireless/wl12xx/wl1251_main.c | 125 ++++++------------------------ 3 files changed, 117 insertions(+), 107 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index 770f260726bd..fcbfbd7585f8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c @@ -410,3 +410,85 @@ out: kfree(cmd); return ret; } + +int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, + unsigned int n_channels, unsigned int n_probes) +{ + struct wl1251_cmd_scan *cmd; + int i, ret = 0; + + wl1251_debug(DEBUG_CMD, "cmd scan"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); + cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | + CFG_RX_MGMT_EN | + CFG_RX_BCN_EN); + cmd->params.scan_options = 0; + cmd->params.num_channels = n_channels; + cmd->params.num_probe_requests = n_probes; + cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ + cmd->params.tid_trigger = 0; + + for (i = 0; i < n_channels; i++) { + cmd->channels[i].min_duration = + cpu_to_le32(WL1251_SCAN_MIN_DURATION); + cmd->channels[i].max_duration = + cpu_to_le32(WL1251_SCAN_MAX_DURATION); + memset(&cmd->channels[i].bssid_lsb, 0xff, 4); + memset(&cmd->channels[i].bssid_msb, 0xff, 2); + cmd->channels[i].early_termination = 0; + cmd->channels[i].tx_power_att = 0; + cmd->channels[i].channel = i + 1; + } + + cmd->params.ssid_len = ssid_len; + if (ssid) + memcpy(cmd->params.ssid, ssid, ssid_len); + + ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); + if (ret < 0) { + wl1251_error("cmd scan failed: %d", ret); + goto out; + } + + wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); + + if (cmd->header.status != CMD_STATUS_SUCCESS) { + wl1251_error("cmd scan status wasn't success: %d", + cmd->header.status); + ret = -EIO; + goto out; + } + +out: + kfree(cmd); + return ret; +} + +int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) +{ + struct wl1251_cmd_trigger_scan_to *cmd; + int ret; + + wl1251_debug(DEBUG_CMD, "cmd trigger scan to"); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->timeout = timeout; + + ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); + if (ret < 0) { + wl1251_error("cmd trigger scan to failed: %d", ret); + goto out; + } + +out: + kfree(cmd); + return ret; +} diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index dff798ad0ef5..63ae3193f7c6 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -43,6 +43,9 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, size_t len); int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, void *buf, size_t buf_len); +int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, + unsigned int n_channels, unsigned int n_probes); +int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout); /* unit ms */ #define WL1251_COMMAND_TIMEOUT 2000 @@ -163,8 +166,10 @@ struct cmd_read_write_memory { #define CMDMBOX_HEADER_LEN 4 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 +#define WL1251_SCAN_MIN_DURATION 30000 +#define WL1251_SCAN_MAX_DURATION 60000 -struct basic_scan_parameters { +struct wl1251_scan_parameters { u32 rx_config_options; u32 rx_filter_options; @@ -189,11 +194,11 @@ struct basic_scan_parameters { u8 tid_trigger; u8 ssid_len; - u32 ssid[8]; + u8 ssid[32]; } __attribute__ ((packed)); -struct basic_scan_channel_parameters { +struct wl1251_scan_ch_parameters { u32 min_duration; /* in TU */ u32 max_duration; /* in TU */ u32 bssid_lsb; @@ -213,11 +218,11 @@ struct basic_scan_channel_parameters { /* SCAN parameters */ #define SCAN_MAX_NUM_OF_CHANNELS 16 -struct cmd_scan { +struct wl1251_cmd_scan { struct wl1251_cmd_header header; - struct basic_scan_parameters params; - struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; + struct wl1251_scan_parameters params; + struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; } __attribute__ ((packed)); enum { diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 6cce86462fac..e038707294a5 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -903,111 +903,13 @@ static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len) size); } -static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 num_channels, - u8 probe_requests) -{ - struct wl1251_cmd_trigger_scan_to *trigger = NULL; - struct cmd_scan *params = NULL; - int i, ret; - u16 scan_options = 0; - - if (wl->scanning) - return -EINVAL; - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); - params->params.rx_filter_options = - cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); - - /* High priority scan */ - if (!active_scan) - scan_options |= SCAN_PASSIVE; - if (high_prio) - scan_options |= SCAN_PRIORITY_HIGH; - params->params.scan_options = scan_options; - - params->params.num_channels = num_channels; - params->params.num_probe_requests = probe_requests; - params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ - params->params.tid_trigger = 0; - - for (i = 0; i < num_channels; i++) { - params->channels[i].min_duration = cpu_to_le32(30000); - params->channels[i].max_duration = cpu_to_le32(60000); - memset(¶ms->channels[i].bssid_lsb, 0xff, 4); - memset(¶ms->channels[i].bssid_msb, 0xff, 2); - params->channels[i].early_termination = 0; - params->channels[i].tx_power_att = 0; - params->channels[i].channel = i + 1; - memset(params->channels[i].pad, 0, 3); - } - - for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) - memset(¶ms->channels[i], 0, - sizeof(struct basic_scan_channel_parameters)); - - if (len && ssid) { - params->params.ssid_len = len; - memcpy(params->params.ssid, ssid, len); - } else { - params->params.ssid_len = 0; - memset(params->params.ssid, 0, 32); - } - - ret = wl1251_build_probe_req(wl, ssid, len); - if (ret < 0) { - wl1251_error("PROBE request template failed"); - goto out; - } - - trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); - if (!trigger) - goto out; - - trigger->timeout = 0; - - ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, - sizeof(*trigger)); - if (ret < 0) { - wl1251_error("trigger scan to failed for hw scan"); - goto out; - } - - wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); - - wl->scanning = true; - - ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); - if (ret < 0) - wl1251_error("SCAN failed"); - - wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); - - if (params->header.status != CMD_STATUS_SUCCESS) { - wl1251_error("TEST command answer error: %d", - params->header.status); - wl->scanning = false; - ret = -EIO; - goto out; - } - -out: - kfree(params); - return ret; - -} - static int wl1251_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { struct wl1251 *wl = hw->priv; - int ret; - u8 *ssid = NULL; size_t ssid_len = 0; + u8 *ssid = NULL; + int ret; wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); @@ -1018,12 +920,33 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); + if (wl->scanning) { + wl1251_debug(DEBUG_SCAN, "scan already in progress"); + ret = -EINVAL; + goto out; + } + ret = wl1251_ps_elp_wakeup(wl); if (ret < 0) goto out; - ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); + ret = wl1251_build_probe_req(wl, ssid, ssid_len); + if (ret < 0) + wl1251_error("probe request template build failed"); + + ret = wl1251_cmd_trigger_scan_to(wl, 0); + if (ret < 0) + goto out_sleep; + + wl->scanning = true; + ret = wl1251_cmd_scan(wl, ssid, ssid_len, 13, 3); + if (ret < 0) { + wl->scanning = false; + goto out_sleep; + } + +out_sleep: wl1251_ps_elp_sleep(wl); out: -- cgit v1.2.3 From e477c56e852c4c6db1f7665c642c9f45f76616a9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:16:57 +0200 Subject: wl1251: get probe request template from mac80211 Instead of creating the template in driver, get it from mac80211 instead. Thanks to this, three functions can be now removed. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 86 +++++-------------------------- 1 file changed, 12 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index e038707294a5..1db97229af47 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -831,82 +831,11 @@ out: return ret; } -static int wl1251_build_basic_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - - return index; -} - -static int wl1251_build_extended_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_OFDM_RATE_6MB; - rates[index++] = IEEE80211_OFDM_RATE_9MB; - rates[index++] = IEEE80211_OFDM_RATE_12MB; - rates[index++] = IEEE80211_OFDM_RATE_18MB; - rates[index++] = IEEE80211_OFDM_RATE_24MB; - rates[index++] = IEEE80211_OFDM_RATE_36MB; - rates[index++] = IEEE80211_OFDM_RATE_48MB; - rates[index++] = IEEE80211_OFDM_RATE_54MB; - - return index; -} - - -static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len) -{ - struct wl12xx_probe_req_template template; - struct wl12xx_ie_rates *rates; - char *ptr; - u16 size; - - ptr = (char *)&template; - size = sizeof(struct ieee80211_header); - - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - - /* IEs */ - /* SSID */ - template.ssid.header.id = WLAN_EID_SSID; - template.ssid.header.len = ssid_len; - if (ssid_len && ssid) - memcpy(template.ssid.ssid, ssid, ssid_len); - size += sizeof(struct wl12xx_ie_header) + ssid_len; - ptr += size; - - /* Basic Rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_SUPP_RATES; - rates->header.len = wl1251_build_basic_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; - - /* Extended rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_EXT_SUPP_RATES; - rates->header.len = wl1251_build_extended_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - - wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); - - return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template, - size); -} - static int wl1251_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { struct wl1251 *wl = hw->priv; + struct sk_buff *skb; size_t ssid_len = 0; u8 *ssid = NULL; int ret; @@ -930,9 +859,18 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl1251_build_probe_req(wl, ssid, ssid_len); + skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, + req->ie, req->ie_len); + if (!skb) { + ret = -ENOMEM; + goto out; + } + + ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, skb->data, + skb->len); + dev_kfree_skb(skb); if (ret < 0) - wl1251_error("probe request template build failed"); + goto out_sleep; ret = wl1251_cmd_trigger_scan_to(wl, 0); if (ret < 0) -- cgit v1.2.3 From dc52f0a8e50303eb67ff8856cd8d1b461462ceec Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:17:03 +0200 Subject: wl1251: use mac80211 provided channel parameters in scanning The number of channels to be used in scan was hard coded in wl1251. The proper way is to use the channels array provided by mac80211. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_cmd.c | 3 ++- drivers/net/wireless/wl12xx/wl1251_cmd.h | 5 +++++ drivers/net/wireless/wl12xx/wl1251_main.c | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index fcbfbd7585f8..0320b478bb3f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c @@ -412,6 +412,7 @@ out: } int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, + struct ieee80211_channel *channels[], unsigned int n_channels, unsigned int n_probes) { struct wl1251_cmd_scan *cmd; @@ -442,7 +443,7 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, memset(&cmd->channels[i].bssid_msb, 0xff, 2); cmd->channels[i].early_termination = 0; cmd->channels[i].tx_power_att = 0; - cmd->channels[i].channel = i + 1; + cmd->channels[i].channel = channels[i]->hw_value; } cmd->params.ssid_len = ssid_len; diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index 63ae3193f7c6..4ad67cae94d2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h @@ -27,6 +27,8 @@ #include "wl1251.h" +#include + struct acx_header; int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); @@ -44,6 +46,7 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, void *buf, size_t buf_len); int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, + struct ieee80211_channel *channels[], unsigned int n_channels, unsigned int n_probes); int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout); @@ -169,6 +172,8 @@ struct cmd_read_write_memory { #define WL1251_SCAN_MIN_DURATION 30000 #define WL1251_SCAN_MAX_DURATION 60000 +#define WL1251_SCAN_NUM_PROBES 3 + struct wl1251_scan_parameters { u32 rx_config_options; u32 rx_filter_options; diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 1db97229af47..4728983b4383 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -878,7 +878,8 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, wl->scanning = true; - ret = wl1251_cmd_scan(wl, ssid, ssid_len, 13, 3); + ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels, + req->n_channels, WL1251_SCAN_NUM_PROBES); if (ret < 0) { wl->scanning = false; goto out_sleep; -- cgit v1.2.3 From 80a112ffe8dbada25f3780ecc4beebf23451d755 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 5 Jan 2010 20:17:10 +0200 Subject: wl1251: fix sleep related error paths in wl1251_op_bss_info_changed() In various cases wl1251_op_bss_info_changed() did not call elp_sleep() after an error was noticed. Fix it by using correct goto label. The bug was a theoretical one, in practise it doesn't matter because if commands start returning errors there will be lots of other problems. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4728983b4383..f17ce06b6c24 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -946,7 +946,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, skb->data, skb->len); dev_kfree_skb(skb); if (ret < 0) - goto out; + goto out_sleep; if (wl->bss_type != BSS_TYPE_IBSS) { ret = wl1251_join(wl, wl->bss_type, wl->channel, @@ -1018,7 +1018,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); if (ret < 0) { wl1251_warning("Set ctsprotect failed %d", ret); - goto out; + goto out_sleep; } } @@ -1029,7 +1029,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) { dev_kfree_skb(beacon); - goto out; + goto out_sleep; } ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, @@ -1038,13 +1038,13 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, dev_kfree_skb(beacon); if (ret < 0) - goto out; + goto out_sleep; ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, wl->channel, wl->dtim_period); if (ret < 0) - goto out; + goto out_sleep; } out_sleep: -- cgit v1.2.3 From 34a6eddbabd704b3c7dae9362234552267573be2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 Jan 2010 16:19:24 +0200 Subject: cfg80211: Store IEs from both Beacon and Probe Response frames Store information elements from Beacon and Probe Response frames in separate buffers to allow both sets to be made available through nl80211. This allows user space applications to get access to IEs from Beacon frames even if we have received Probe Response frames from the BSS. Previously, the IEs from Probe Response frames would have overridden the IEs from Beacon frames. This feature is of somewhat limited use since most protocols include the same (or extended) information in Probe Response frames. However, there are couple of exceptions where the IEs from Beacon frames could be of some use: TIM IE is only included in Beacon frames (and it would be needed to figure out the DTIM period used in the BSS) and at least some implementations of Wireless Provisioning Services seem to include the full IE only in Beacon frames). The new BSS attribute for scan results is added to allow both the IE sets to be delivered. This is done in a way that maintains the previously used behavior for applications that are not aware of the new NL80211_BSS_BEACON_IES attribute. Signed-off-by: Jouni Malinen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 10 +++- include/net/cfg80211.h | 12 ++++- net/wireless/core.h | 3 +- net/wireless/nl80211.c | 4 ++ net/wireless/scan.c | 120 ++++++++++++++++++++++++++++++++++++------------ 5 files changed, 116 insertions(+), 33 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 7a1c8c145b22..127a73015760 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1378,13 +1378,20 @@ enum nl80211_channel_type { * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the - * raw information elements from the probe response/beacon (bin) + * raw information elements from the probe response/beacon (bin); + * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are + * from a Probe Response frame; otherwise they are from a Beacon frame. + * However, if the driver does not indicate the source of the IEs, these + * IEs may be from either frame subtype. * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon * in mBm (100 * dBm) (s32) * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon * in unspecified units, scaled to 0..100 (u8) * @NL80211_BSS_STATUS: status, if this BSS is "used" * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms + * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information + * elements from a Beacon frame (bin); not present if no Beacon frame has + * yet been received * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -1400,6 +1407,7 @@ enum nl80211_bss { NL80211_BSS_SIGNAL_UNSPEC, NL80211_BSS_STATUS, NL80211_BSS_SEEN_MS_AGO, + NL80211_BSS_BEACON_IES, /* keep last */ __NL80211_BSS_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0d734413b5fb..2af52704e670 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -626,8 +626,14 @@ enum cfg80211_signal_type { * @beacon_interval: the beacon interval as from the frame * @capability: the capability field in host byte order * @information_elements: the information elements (Note that there - * is no guarantee that these are well-formed!) + * is no guarantee that these are well-formed!); this is a pointer to + * either the beacon_ies or proberesp_ies depending on whether Probe + * Response frame has been received * @len_information_elements: total length of the information elements + * @beacon_ies: the information elements from the last Beacon frame + * @len_beacon_ies: total length of the beacon_ies + * @proberesp_ies: the information elements from the last Probe Response frame + * @len_proberesp_ies: total length of the proberesp_ies * @signal: signal strength value (type depends on the wiphy's signal_type) * @free_priv: function pointer to free private data * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes @@ -641,6 +647,10 @@ struct cfg80211_bss { u16 capability; u8 *information_elements; size_t len_information_elements; + u8 *beacon_ies; + size_t len_beacon_ies; + u8 *proberesp_ies; + size_t len_proberesp_ies; s32 signal; diff --git a/net/wireless/core.h b/net/wireless/core.h index 30ec95f05b52..2d6a6b9c0c43 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -111,7 +111,8 @@ struct cfg80211_internal_bss { unsigned long ts; struct kref ref; atomic_t hold; - bool ies_allocated; + bool beacon_ies_allocated; + bool proberesp_ies_allocated; /* must be last because of priv member */ struct cfg80211_bss pub; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b804062e0179..4af7991a9ec8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3163,6 +3163,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS, res->len_information_elements, res->information_elements); + if (res->beacon_ies && res->len_beacon_ies && + res->beacon_ies != res->information_elements) + NLA_PUT(msg, NL80211_BSS_BEACON_IES, + res->len_beacon_ies, res->beacon_ies); if (res->tsf) NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf); if (res->beacon_interval) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 0c2cbbebca95..06b0231ee5e3 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -100,8 +100,10 @@ static void bss_release(struct kref *ref) if (bss->pub.free_priv) bss->pub.free_priv(&bss->pub); - if (bss->ies_allocated) - kfree(bss->pub.information_elements); + if (bss->beacon_ies_allocated) + kfree(bss->pub.beacon_ies); + if (bss->proberesp_ies_allocated) + kfree(bss->pub.proberesp_ies); BUG_ON(atomic_read(&bss->hold)); @@ -375,8 +377,7 @@ rb_find_bss(struct cfg80211_registered_device *dev, static struct cfg80211_internal_bss * cfg80211_bss_update(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *res, - bool overwrite) + struct cfg80211_internal_bss *res) { struct cfg80211_internal_bss *found = NULL; const u8 *meshid, *meshcfg; @@ -418,28 +419,64 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, found->pub.capability = res->pub.capability; found->ts = res->ts; - /* overwrite IEs */ - if (overwrite) { + /* Update IEs */ + if (res->pub.proberesp_ies) { size_t used = dev->wiphy.bss_priv_size + sizeof(*res); - size_t ielen = res->pub.len_information_elements; + size_t ielen = res->pub.len_proberesp_ies; + + if (found->pub.proberesp_ies && + !found->proberesp_ies_allocated && + ksize(found) >= used + ielen) { + memcpy(found->pub.proberesp_ies, + res->pub.proberesp_ies, ielen); + found->pub.len_proberesp_ies = ielen; + } else { + u8 *ies = found->pub.proberesp_ies; + + if (found->proberesp_ies_allocated) + ies = krealloc(ies, ielen, GFP_ATOMIC); + else + ies = kmalloc(ielen, GFP_ATOMIC); + + if (ies) { + memcpy(ies, res->pub.proberesp_ies, + ielen); + found->proberesp_ies_allocated = true; + found->pub.proberesp_ies = ies; + found->pub.len_proberesp_ies = ielen; + } + } - if (!found->ies_allocated && ksize(found) >= used + ielen) { - memcpy(found->pub.information_elements, - res->pub.information_elements, ielen); - found->pub.len_information_elements = ielen; + /* Override possible earlier Beacon frame IEs */ + found->pub.information_elements = + found->pub.proberesp_ies; + found->pub.len_information_elements = + found->pub.len_proberesp_ies; + } + if (res->pub.beacon_ies) { + size_t used = dev->wiphy.bss_priv_size + sizeof(*res); + size_t ielen = res->pub.len_beacon_ies; + + if (found->pub.beacon_ies && + !found->beacon_ies_allocated && + ksize(found) >= used + ielen) { + memcpy(found->pub.beacon_ies, + res->pub.beacon_ies, ielen); + found->pub.len_beacon_ies = ielen; } else { - u8 *ies = found->pub.information_elements; + u8 *ies = found->pub.beacon_ies; - if (found->ies_allocated) + if (found->beacon_ies_allocated) ies = krealloc(ies, ielen, GFP_ATOMIC); else ies = kmalloc(ielen, GFP_ATOMIC); if (ies) { - memcpy(ies, res->pub.information_elements, ielen); - found->ies_allocated = true; - found->pub.information_elements = ies; - found->pub.len_information_elements = ielen; + memcpy(ies, res->pub.beacon_ies, + ielen); + found->beacon_ies_allocated = true; + found->pub.beacon_ies = ies; + found->pub.len_beacon_ies = ielen; } } } @@ -489,14 +526,26 @@ cfg80211_inform_bss(struct wiphy *wiphy, res->pub.tsf = timestamp; res->pub.beacon_interval = beacon_interval; res->pub.capability = capability; - /* point to after the private area */ - res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; - memcpy(res->pub.information_elements, ie, ielen); - res->pub.len_information_elements = ielen; + /* + * Since we do not know here whether the IEs are from a Beacon or Probe + * Response frame, we need to pick one of the options and only use it + * with the driver that does not provide the full Beacon/Probe Response + * frame. Use Beacon frame pointer to avoid indicating that this should + * override the information_elements pointer should we have received an + * earlier indication of Probe Response data. + * + * The initial buffer for the IEs is allocated with the BSS entry and + * is located after the private area. + */ + res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz; + memcpy(res->pub.beacon_ies, ie, ielen); + res->pub.len_beacon_ies = ielen; + res->pub.information_elements = res->pub.beacon_ies; + res->pub.len_information_elements = res->pub.len_beacon_ies; kref_init(&res->ref); - res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0); + res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); if (!res) return NULL; @@ -517,7 +566,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, struct cfg80211_internal_bss *res; size_t ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - bool overwrite; size_t privsz = wiphy->bss_priv_size; if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && @@ -538,16 +586,28 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); - /* point to after the private area */ - res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; - memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen); - res->pub.len_information_elements = ielen; + /* + * The initial buffer for the IEs is allocated with the BSS entry and + * is located after the private area. + */ + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz; + memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable, + ielen); + res->pub.len_proberesp_ies = ielen; + res->pub.information_elements = res->pub.proberesp_ies; + res->pub.len_information_elements = res->pub.len_proberesp_ies; + } else { + res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz; + memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen); + res->pub.len_beacon_ies = ielen; + res->pub.information_elements = res->pub.beacon_ies; + res->pub.len_information_elements = res->pub.len_beacon_ies; + } kref_init(&res->ref); - overwrite = ieee80211_is_probe_resp(mgmt->frame_control); - - res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite); + res = cfg80211_bss_update(wiphy_to_dev(wiphy), res); if (!res) return NULL; -- cgit v1.2.3 From 81ac3462d346ee7aaf037a35156b0a7a354e98cf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Jan 2010 15:30:58 +0100 Subject: mac80211: fix a few work bugs Kalle and Lennert reported problems with the new work code, and at least Kalle's problem I was able to trace to a missing jiffies initialisation. I also ran into a problem where occasionally I couldn't connect, which seems fixed with kicking the work items after scanning. Finally, also add some sanity checking code to verify that we're not adding work items while an interface is down -- that case could lead to something similar to what Lennert was seeing. There still seems to be a race condition that we're trying to figure out separately. Signed-off-by: Johannes Berg Tested-by: Lennert Buytenhek Tested-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/scan.c | 1 + net/mac80211/work.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a4c63d4e6845..30cb62bb45b3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -284,6 +284,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); ieee80211_mesh_notify_scan_completed(local); + ieee80211_queue_work(&local->hw, &local->work_work); } EXPORT_SYMBOL(ieee80211_scan_completed); diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 5ba75990c9fd..7c5d95b1bc04 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -818,6 +818,7 @@ static void ieee80211_work_work(struct work_struct *work) wk->chan == local->tmp_channel && wk->chan_type == local->tmp_channel_type) { wk->started = true; + wk->timeout = jiffies; } if (!wk->started && !local->tmp_channel) { @@ -935,6 +936,9 @@ void ieee80211_add_work(struct ieee80211_work *wk) if (WARN_ON(!wk->done)) return; + if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) + return; + wk->started = false; local = wk->sdata->local; -- cgit v1.2.3 From 81f14df0b3909875902b0253d7059e8a73dd0c7f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 7 Jan 2010 14:09:27 +0100 Subject: b43: LP-PHY: note and explain specs inconsistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 3e046ec1ff86..eb4fb4581edb 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -80,6 +80,7 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) dev->phy.lp = NULL; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */ static void lpphy_read_band_sprom(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; @@ -101,6 +102,12 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) maxpwr = bus->sprom.maxpwr_bg; lpphy->max_tx_pwr_med_band = maxpwr; cckpo = bus->sprom.cck2gpo; + /* + * We don't read SPROM's opo as specs say. On rev8 SPROMs + * opo == ofdm2gpo and we don't know any SSB with LP-PHY + * and SPROM rev below 8. + */ + B43_WARN_ON(bus->sprom.revision < 8); ofdmpo = bus->sprom.ofdm2gpo; if (cckpo) { for (i = 0; i < 4; i++) { -- cgit v1.2.3 From b74d12e116528fadc35f305eb6e9525a3a2b62b1 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 7 Jan 2010 17:24:54 -0500 Subject: cfg80211: add debug print when we drop a bogus country IE Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f79d6613c5ff..389247cb7059 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1806,8 +1806,10 @@ void regulatory_hint_11d(struct wiphy *wiphy, goto out; rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); - if (!rd) + if (!rd) { + REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n"); goto out; + } /* * This will not happen right now but we leave it here for the -- cgit v1.2.3 From 08030db6e5275dda19ea1b3ab8a41c992799db4a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 7 Jan 2010 17:24:56 -0500 Subject: cfg80211: process the max power on a country IE The max power from each country IE triplet was being ignored. This fix isn't critical as CRDA was always being used for the lower limit, but we should process it in case the AP still wants to decrease power output even more for whatever reason. Reported-by: Benoit PAPILLAULT Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 389247cb7059..77d0bb6f6e7a 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -680,7 +680,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( */ freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); power_rule->max_antenna_gain = DBI_TO_MBI(100); - power_rule->max_eirp = DBM_TO_MBM(100); + power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power); country_ie += 3; country_ie_len -= 3; -- cgit v1.2.3 From cc5d8a3772ee4e2ed29558ba548b4747959ba971 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 7 Jan 2010 17:24:57 -0500 Subject: cfg80211: Fix country IE parsing for single channel triplets This enhances the way we parse country IEs to minimize the number of regulatory rules that we create. It also fixes our current implementation which treated country IE triplets with only one channel as one independed regulatory rule even though adjecent rules were also being provided. Without this patch APs which send country IE information with a channel triplet for each individual channel will force cfg80211 to deny HT40 operation as a regulatory rule would have been created independently for each channel and as such configured only for 20 MHz operation. Although 802.11n APs which send country IEs triplets in this fassion are likely rare Benoit reports this against the Ubiquity NanoStation M5, with Country "FR" and HT40 enabled. Since we now have a helper which parses the triplets in intermediate steps we now take care extra care to process padding. Reported-by: Benoit PAPILLAULT Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 4 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 77d0bb6f6e7a..a5c2d3a6cbb2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -484,6 +484,178 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, #undef ONE_GHZ_IN_KHZ } +/* + * Some APs may send a country IE triplet for each channel they + * support and while this is completely overkill and silly we still + * need to support it. We avoid making a single rule for each channel + * though and to help us with this we use this helper to find the + * actual subband end channel. These type of country IE triplet + * scenerios are handled then, all yielding two regulaotry rules from + * parsing a country IE: + * + * [1] + * [2] + * [36] + * [40] + * + * [1] + * [2-4] + * [5-12] + * [36] + * [40-44] + * + * [1-4] + * [5-7] + * [36-44] + * [48-64] + * + * [36-36] + * [40-40] + * [44-44] + * [48-48] + * [52-52] + * [56-56] + * [60-60] + * [64-64] + * [100-100] + * [104-104] + * [108-108] + * [112-112] + * [116-116] + * [120-120] + * [124-124] + * [128-128] + * [132-132] + * [136-136] + * [140-140] + * + * Returns 0 if the IE has been found to be invalid in the middle + * somewhere. + */ +static int max_subband_chan(int orig_cur_chan, + int orig_end_channel, + s8 orig_max_power, + u8 **country_ie, + u8 *country_ie_len) +{ + u8 *triplets_start = *country_ie; + u8 len_at_triplet = *country_ie_len; + int end_subband_chan = orig_end_channel; + enum ieee80211_band band; + + /* + * We'll deal with padding for the caller unless + * its not immediate and we don't process any channels + */ + if (*country_ie_len == 1) { + *country_ie += 1; + *country_ie_len -= 1; + return orig_end_channel; + } + + /* Move to the next triplet and then start search */ + *country_ie += 3; + *country_ie_len -= 3; + + if (orig_cur_chan <= 14) + band = IEEE80211_BAND_2GHZ; + else + band = IEEE80211_BAND_5GHZ; + + while (*country_ie_len >= 3) { + int end_channel = 0; + struct ieee80211_country_ie_triplet *triplet = + (struct ieee80211_country_ie_triplet *) *country_ie; + int cur_channel = 0, next_expected_chan; + enum ieee80211_band next_band = IEEE80211_BAND_2GHZ; + + /* means last triplet is completely unrelated to this one */ + if (triplet->ext.reg_extension_id >= + IEEE80211_COUNTRY_EXTENSION_ID) { + *country_ie -= 3; + *country_ie_len += 3; + break; + } + + if (triplet->chans.first_channel == 0) { + *country_ie += 1; + *country_ie_len -= 1; + if (*country_ie_len != 0) + return 0; + break; + } + + /* Monitonically increasing channel order */ + if (triplet->chans.first_channel <= end_subband_chan) + return 0; + + /* 2 GHz */ + if (triplet->chans.first_channel <= 14) { + end_channel = triplet->chans.first_channel + + triplet->chans.num_channels - 1; + } + else { + end_channel = triplet->chans.first_channel + + (4 * (triplet->chans.num_channels - 1)); + next_band = IEEE80211_BAND_5GHZ; + } + + if (band != next_band) { + *country_ie -= 3; + *country_ie_len += 3; + break; + } + + if (orig_max_power != triplet->chans.max_power) { + *country_ie -= 3; + *country_ie_len += 3; + break; + } + + cur_channel = triplet->chans.first_channel; + + /* The key is finding the right next expected channel */ + if (band == IEEE80211_BAND_2GHZ) + next_expected_chan = end_subband_chan + 1; + else + next_expected_chan = end_subband_chan + 4; + + if (cur_channel != next_expected_chan) { + *country_ie -= 3; + *country_ie_len += 3; + break; + } + + end_subband_chan = end_channel; + + /* Move to the next one */ + *country_ie += 3; + *country_ie_len -= 3; + + /* + * Padding needs to be dealt with if we processed + * some channels. + */ + if (*country_ie_len == 1) { + *country_ie += 1; + *country_ie_len -= 1; + break; + } + + /* If seen, the IE is invalid */ + if (*country_ie_len == 2) + return 0; + } + + if (end_subband_chan == orig_end_channel) { + *country_ie = triplets_start; + *country_ie_len = len_at_triplet; + return orig_end_channel; + } + + return end_subband_chan; +} + /* * Converts a country IE to a regulatory domain. A regulatory domain * structure has a lot of information which the IE doesn't yet have, @@ -552,6 +724,19 @@ static struct ieee80211_regdomain *country_ie_2_rd( continue; } + /* + * APs can add padding to make length divisible + * by two, required by the spec. + */ + if (triplet->chans.first_channel == 0) { + country_ie++; + country_ie_len--; + /* This is expected to be at the very end only */ + if (country_ie_len != 0) + return NULL; + break; + } + /* 2 GHz */ if (triplet->chans.first_channel <= 14) end_channel = triplet->chans.first_channel + @@ -570,6 +755,20 @@ static struct ieee80211_regdomain *country_ie_2_rd( (4 * (triplet->chans.num_channels - 1)); cur_channel = triplet->chans.first_channel; + + /* + * Enhancement for APs that send a triplet for every channel + * or for whatever reason sends triplets with multiple channels + * separated when in fact they should be together. + */ + end_channel = max_subband_chan(cur_channel, + end_channel, + triplet->chans.max_power, + &country_ie, + &country_ie_len); + if (!end_channel) + return NULL; + cur_sub_max_channel = end_channel; /* Basic sanity check */ @@ -600,10 +799,13 @@ static struct ieee80211_regdomain *country_ie_2_rd( last_sub_max_channel = cur_sub_max_channel; - country_ie += 3; - country_ie_len -= 3; num_rules++; + if (country_ie_len >= 3) { + country_ie += 3; + country_ie_len -= 3; + } + /* * Note: this is not a IEEE requirement but * simply a memory requirement @@ -646,6 +848,12 @@ static struct ieee80211_regdomain *country_ie_2_rd( continue; } + if (triplet->chans.first_channel == 0) { + country_ie++; + country_ie_len--; + break; + } + reg_rule = &rd->reg_rules[i]; freq_range = ®_rule->freq_range; power_rule = ®_rule->power_rule; @@ -660,6 +868,12 @@ static struct ieee80211_regdomain *country_ie_2_rd( end_channel = triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1)); + end_channel = max_subband_chan(triplet->chans.first_channel, + end_channel, + triplet->chans.max_power, + &country_ie, + &country_ie_len); + /* * The +10 is since the regulatory domain expects * the actual band edge, not the center of freq for @@ -682,10 +896,13 @@ static struct ieee80211_regdomain *country_ie_2_rd( power_rule->max_antenna_gain = DBI_TO_MBI(100); power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power); - country_ie += 3; - country_ie_len -= 3; i++; + if (country_ie_len >= 3) { + country_ie += 3; + country_ie_len -= 3; + } + BUG_ON(i > NL80211_MAX_SUPP_REG_RULES); } -- cgit v1.2.3 From 0fca65c1c0569d6a143e978b6f4974c519033e63 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:00 +0530 Subject: ath9k: Add a new file for GPIO Move all LED/RFKILL/BTCOEX related code to gpio.c Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 1 + drivers/net/wireless/ath/ath9k/ath9k.h | 15 ++ drivers/net/wireless/ath/ath9k/gpio.c | 428 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/main.c | 406 ------------------------------ 4 files changed, 444 insertions(+), 406 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/gpio.c diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 4985b2b1b0a9..332d6f20c6b6 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -1,4 +1,5 @@ ath9k-y += beacon.o \ + gpio.o \ main.o \ recv.o \ xmit.o \ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 9efebac5ed0e..bbdca5edcfbf 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -341,6 +341,10 @@ int ath_beaconq_config(struct ath_softc *sc); #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ +/**********/ +/* BTCOEX */ +/**********/ + /* Defines the BT AR_BT_COEX_WGHT used */ enum ath_stomp_type { ATH_BTCOEX_NO_STOMP, @@ -361,6 +365,10 @@ struct ath_btcoex { struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ }; +int ath_init_btcoex_timer(struct ath_softc *sc); +void ath9k_btcoex_timer_resume(struct ath_softc *sc); +void ath9k_btcoex_timer_pause(struct ath_softc *sc); + /********************/ /* LED Control */ /********************/ @@ -385,6 +393,9 @@ struct ath_led { bool registered; }; +void ath_init_leds(struct ath_softc *sc); +void ath_deinit_leds(struct ath_softc *sc); + /********************/ /* Main driver core */ /********************/ @@ -582,4 +593,8 @@ void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); + +void ath_start_rfkill_poll(struct ath_softc *sc); +extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); + #endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c new file mode 100644 index 000000000000..e204bd25ff65 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ath9k.h" + +/********************************/ +/* LED functions */ +/********************************/ + +static void ath_led_blink_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + ath_led_blink_work.work); + + if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) + return; + + if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || + (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); + else + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, + (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); + + ieee80211_queue_delayed_work(sc->hw, + &sc->ath_led_blink_work, + (sc->sc_flags & SC_OP_LED_ON) ? + msecs_to_jiffies(sc->led_off_duration) : + msecs_to_jiffies(sc->led_on_duration)); + + sc->led_on_duration = sc->led_on_cnt ? + max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : + ATH_LED_ON_DURATION_IDLE; + sc->led_off_duration = sc->led_off_cnt ? + max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : + ATH_LED_OFF_DURATION_IDLE; + sc->led_on_cnt = sc->led_off_cnt = 0; + if (sc->sc_flags & SC_OP_LED_ON) + sc->sc_flags &= ~SC_OP_LED_ON; + else + sc->sc_flags |= SC_OP_LED_ON; +} + +static void ath_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); + struct ath_softc *sc = led->sc; + + switch (brightness) { + case LED_OFF: + if (led->led_type == ATH_LED_ASSOC || + led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, + (led->led_type == ATH_LED_RADIO)); + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + if (led->led_type == ATH_LED_RADIO) + sc->sc_flags &= ~SC_OP_LED_ON; + } else { + sc->led_off_cnt++; + } + break; + case LED_FULL: + if (led->led_type == ATH_LED_ASSOC) { + sc->sc_flags |= SC_OP_LED_ASSOCIATED; + ieee80211_queue_delayed_work(sc->hw, + &sc->ath_led_blink_work, 0); + } else if (led->led_type == ATH_LED_RADIO) { + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); + sc->sc_flags |= SC_OP_LED_ON; + } else { + sc->led_on_cnt++; + } + break; + default: + break; + } +} + +static int ath_register_led(struct ath_softc *sc, struct ath_led *led, + char *trigger) +{ + int ret; + + led->sc = sc; + led->led_cdev.name = led->name; + led->led_cdev.default_trigger = trigger; + led->led_cdev.brightness_set = ath_led_brightness; + + ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); + if (ret) + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, + "Failed to register led:%s", led->name); + else + led->registered = 1; + return ret; +} + +static void ath_unregister_led(struct ath_led *led) +{ + if (led->registered) { + led_classdev_unregister(&led->led_cdev); + led->registered = 0; + } +} + +void ath_deinit_leds(struct ath_softc *sc) +{ + ath_unregister_led(&sc->assoc_led); + sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; + ath_unregister_led(&sc->tx_led); + ath_unregister_led(&sc->rx_led); + ath_unregister_led(&sc->radio_led); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); +} + +void ath_init_leds(struct ath_softc *sc) +{ + char *trigger; + int ret; + + if (AR_SREV_9287(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + + /* Configure gpio 1 for output */ + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + /* LED off, active low */ + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); + + INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); + + trigger = ieee80211_get_radio_led_name(sc->hw); + snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), + "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->radio_led, trigger); + sc->radio_led.led_type = ATH_LED_RADIO; + if (ret) + goto fail; + + trigger = ieee80211_get_assoc_led_name(sc->hw); + snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), + "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->assoc_led, trigger); + sc->assoc_led.led_type = ATH_LED_ASSOC; + if (ret) + goto fail; + + trigger = ieee80211_get_tx_led_name(sc->hw); + snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), + "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->tx_led, trigger); + sc->tx_led.led_type = ATH_LED_TX; + if (ret) + goto fail; + + trigger = ieee80211_get_rx_led_name(sc->hw); + snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), + "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); + ret = ath_register_led(sc, &sc->rx_led, trigger); + sc->rx_led.led_type = ATH_LED_RX; + if (ret) + goto fail; + + return; + +fail: + cancel_delayed_work_sync(&sc->ath_led_blink_work); + ath_deinit_leds(sc); +} + +/*******************/ +/* Rfkill */ +/*******************/ + +static bool ath_is_rfkill_set(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == + ah->rfkill_polarity; +} + +void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + bool blocked = !!ath_is_rfkill_set(sc); + + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); +} + +void ath_start_rfkill_poll(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) + wiphy_rfkill_start_polling(sc->hw->wiphy); +} + +/******************/ +/* BTCOEX */ +/******************/ + +/* + * Detects if there is any priority bt traffic + */ +static void ath_detect_bt_priority(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) + btcoex->bt_priority_cnt++; + + if (time_after(jiffies, btcoex->bt_priority_time + + msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { + if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, + "BT priority traffic detected"); + sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; + } else { + sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + } + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + } +} + +/* + * Configures appropriate weight based on stomp type. + */ +static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, + enum ath_stomp_type stomp_type) +{ + struct ath_hw *ah = sc->sc_ah; + + switch (stomp_type) { + case ATH_BTCOEX_STOMP_ALL: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_ALL_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_LOW: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_LOW_WLAN_WGHT); + break; + case ATH_BTCOEX_STOMP_NONE: + ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, + AR_STOMP_NONE_WLAN_WGHT); + break; + default: + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Invalid Stomptype\n"); + break; + } + + ath9k_hw_btcoex_enable(ah); +} + +static void ath9k_gen_timer_start(struct ath_hw *ah, + struct ath_gen_timer *timer, + u32 timer_next, + u32 timer_period) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); + + if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { + ath9k_hw_set_interrupts(ah, 0); + sc->imask |= ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, sc->imask); + } +} + +static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) +{ + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; + + ath9k_hw_gen_timer_stop(ah, timer); + + /* if no timer is enabled, turn off interrupt mask */ + if (timer_table->timer_mask.val == 0) { + ath9k_hw_set_interrupts(ah, 0); + sc->imask &= ~ATH9K_INT_GENTIMER; + ath9k_hw_set_interrupts(ah, sc->imask); + } +} + +/* + * This is the master bt coex timer which runs for every + * 45ms, bt traffic will be given priority during 55% of this + * period while wlan gets remaining 45% + */ +static void ath_btcoex_period_timer(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *) data; + struct ath_hw *ah = sc->sc_ah; + struct ath_btcoex *btcoex = &sc->btcoex; + + ath_detect_bt_priority(sc); + + spin_lock_bh(&btcoex->btcoex_lock); + + ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); + + spin_unlock_bh(&btcoex->btcoex_lock); + + if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); + + ath9k_gen_timer_start(ah, + btcoex->no_stomp_timer, + (ath9k_hw_gettsf32(ah) + + btcoex->btcoex_no_stomp), + btcoex->btcoex_no_stomp * 10); + btcoex->hw_timer_enabled = true; + } + + mod_timer(&btcoex->period_timer, jiffies + + msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); +} + +/* + * Generic tsf based hw timer which configures weight + * registers to time slice between wlan and bt traffic + */ +static void ath_btcoex_no_stomp_timer(void *arg) +{ + struct ath_softc *sc = (struct ath_softc *)arg; + struct ath_hw *ah = sc->sc_ah; + struct ath_btcoex *btcoex = &sc->btcoex; + + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "no stomp timer running \n"); + + spin_lock_bh(&btcoex->btcoex_lock); + + if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) + ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); + else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) + ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); + + spin_unlock_bh(&btcoex->btcoex_lock); +} + +int ath_init_btcoex_timer(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + + btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; + btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * + btcoex->btcoex_period / 100; + + setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, + (unsigned long) sc); + + spin_lock_init(&btcoex->btcoex_lock); + + btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, + ath_btcoex_no_stomp_timer, + ath_btcoex_no_stomp_timer, + (void *) sc, AR_FIRST_NDP_TIMER); + + if (!btcoex->no_stomp_timer) + return -ENOMEM; + + return 0; +} + +/* + * (Re)start btcoex timers + */ +void ath9k_btcoex_timer_resume(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, + "Starting btcoex timers"); + + /* make sure duty cycle timer is also stopped when resuming */ + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); + + btcoex->bt_priority_cnt = 0; + btcoex->bt_priority_time = jiffies; + sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + + mod_timer(&btcoex->period_timer, jiffies); +} + + +/* + * Pause btcoex timer and bt duty cycle timer + */ +void ath9k_btcoex_timer_pause(struct ath_softc *sc) +{ + struct ath_btcoex *btcoex = &sc->btcoex; + struct ath_hw *ah = sc->sc_ah; + + del_timer_sync(&btcoex->period_timer); + + if (btcoex->hw_timer_enabled) + ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); + + btcoex->hw_timer_enabled = false; +} diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3777b8449789..31a33cf762da 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1000,174 +1000,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, } } -/********************************/ -/* LED functions */ -/********************************/ - -static void ath_led_blink_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - ath_led_blink_work.work); - - if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) - return; - - if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); - else - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, - (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); - - ieee80211_queue_delayed_work(sc->hw, - &sc->ath_led_blink_work, - (sc->sc_flags & SC_OP_LED_ON) ? - msecs_to_jiffies(sc->led_off_duration) : - msecs_to_jiffies(sc->led_on_duration)); - - sc->led_on_duration = sc->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - sc->led_off_duration = sc->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - sc->led_on_cnt = sc->led_off_cnt = 0; - if (sc->sc_flags & SC_OP_LED_ON) - sc->sc_flags &= ~SC_OP_LED_ON; - else - sc->sc_flags |= SC_OP_LED_ON; -} - -static void ath_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath_softc *sc = led->sc; - - switch (brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, - (led->led_type == ATH_LED_RADIO)); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - sc->sc_flags &= ~SC_OP_LED_ON; - } else { - sc->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - sc->sc_flags |= SC_OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(sc->hw, - &sc->ath_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); - sc->sc_flags |= SC_OP_LED_ON; - } else { - sc->led_on_cnt++; - } - break; - default: - break; - } -} - -static int ath_register_led(struct ath_softc *sc, struct ath_led *led, - char *trigger) -{ - int ret; - - led->sc = sc; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath_led_brightness; - - ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); - if (ret) - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Failed to register led:%s", led->name); - else - led->registered = 1; - return ret; -} - -static void ath_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } -} - -static void ath_deinit_leds(struct ath_softc *sc) -{ - ath_unregister_led(&sc->assoc_led); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - ath_unregister_led(&sc->tx_led); - ath_unregister_led(&sc->rx_led); - ath_unregister_led(&sc->radio_led); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); -} - -static void ath_init_leds(struct ath_softc *sc) -{ - char *trigger; - int ret; - - if (AR_SREV_9287(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9287; - else - sc->sc_ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - /* LED off, active low */ - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - - INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); - - trigger = ieee80211_get_radio_led_name(sc->hw); - snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), - "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->radio_led, trigger); - sc->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(sc->hw); - snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->assoc_led, trigger); - sc->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(sc->hw); - snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), - "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->tx_led, trigger); - sc->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(sc->hw); - snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), - "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->rx_led, trigger); - sc->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - return; - -fail: - cancel_delayed_work_sync(&sc->ath_led_blink_work); - ath_deinit_leds(sc); -} - void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) { struct ath_hw *ah = sc->sc_ah; @@ -1252,35 +1084,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } -/*******************/ -/* Rfkill */ -/*******************/ - -static bool ath_is_rfkill_set(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == - ah->rfkill_polarity; -} - -static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - bool blocked = !!ath_is_rfkill_set(sc); - - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); -} - -static void ath_start_rfkill_poll(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - wiphy_rfkill_start_polling(sc->hw->wiphy); -} - static void ath9k_uninit_hw(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; @@ -1364,177 +1167,6 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, return ath_reg_notifier_apply(wiphy, request, reg); } -/* - * Detects if there is any priority bt traffic - */ -static void ath_detect_bt_priority(struct ath_softc *sc) -{ - struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_hw *ah = sc->sc_ah; - - if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) - btcoex->bt_priority_cnt++; - - if (time_after(jiffies, btcoex->bt_priority_time + - msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { - if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, - "BT priority traffic detected"); - sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; - } else { - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; - } - - btcoex->bt_priority_cnt = 0; - btcoex->bt_priority_time = jiffies; - } -} - -/* - * Configures appropriate weight based on stomp type. - */ -static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, - enum ath_stomp_type stomp_type) -{ - struct ath_hw *ah = sc->sc_ah; - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_LOW: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_NONE: - ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(ah); -} - -static void ath9k_gen_timer_start(struct ath_hw *ah, - struct ath_gen_timer *timer, - u32 timer_next, - u32 timer_period) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - - ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); - - if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_set_interrupts(ah, 0); - sc->imask |= ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, sc->imask); - } -} - -static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - - ath9k_hw_gen_timer_stop(ah, timer); - - /* if no timer is enabled, turn off interrupt mask */ - if (timer_table->timer_mask.val == 0) { - ath9k_hw_set_interrupts(ah, 0); - sc->imask &= ~ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, sc->imask); - } -} - -/* - * This is the master bt coex timer which runs for every - * 45ms, bt traffic will be given priority during 55% of this - * period while wlan gets remaining 45% - */ -static void ath_btcoex_period_timer(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *) data; - struct ath_hw *ah = sc->sc_ah; - struct ath_btcoex *btcoex = &sc->btcoex; - - ath_detect_bt_priority(sc); - - spin_lock_bh(&btcoex->btcoex_lock); - - ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); - - spin_unlock_bh(&btcoex->btcoex_lock); - - if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { - if (btcoex->hw_timer_enabled) - ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); - - ath9k_gen_timer_start(ah, - btcoex->no_stomp_timer, - (ath9k_hw_gettsf32(ah) + - btcoex->btcoex_no_stomp), - btcoex->btcoex_no_stomp * 10); - btcoex->hw_timer_enabled = true; - } - - mod_timer(&btcoex->period_timer, jiffies + - msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); -} - -/* - * Generic tsf based hw timer which configures weight - * registers to time slice between wlan and bt traffic - */ -static void ath_btcoex_no_stomp_timer(void *arg) -{ - struct ath_softc *sc = (struct ath_softc *)arg; - struct ath_hw *ah = sc->sc_ah; - struct ath_btcoex *btcoex = &sc->btcoex; - - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "no stomp timer running \n"); - - spin_lock_bh(&btcoex->btcoex_lock); - - if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) - ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); - else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); - - spin_unlock_bh(&btcoex->btcoex_lock); -} - -static int ath_init_btcoex_timer(struct ath_softc *sc) -{ - struct ath_btcoex *btcoex = &sc->btcoex; - - btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; - btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * - btcoex->btcoex_period / 100; - - setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, - (unsigned long) sc); - - spin_lock_init(&btcoex->btcoex_lock); - - btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, - ath_btcoex_no_stomp_timer, - ath_btcoex_no_stomp_timer, - (void *) sc, AR_FIRST_NDP_TIMER); - - if (!btcoex->no_stomp_timer) - return -ENOMEM; - - return 0; -} - /* * Read and write, they both share the same lock. We do this to serialize * reads and writes on Atheros 802.11n PCI devices only. This is required @@ -2213,28 +1845,6 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, /* mac80211 callbacks */ /**********************/ -/* - * (Re)start btcoex timers - */ -static void ath9k_btcoex_timer_resume(struct ath_softc *sc) -{ - struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_hw *ah = sc->sc_ah; - - ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, - "Starting btcoex timers"); - - /* make sure duty cycle timer is also stopped when resuming */ - if (btcoex->hw_timer_enabled) - ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); - - btcoex->bt_priority_cnt = 0; - btcoex->bt_priority_time = jiffies; - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; - - mod_timer(&btcoex->period_timer, jiffies); -} - static int ath9k_start(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; @@ -2461,22 +2071,6 @@ exit: return 0; } -/* - * Pause btcoex timer and bt duty cycle timer - */ -static void ath9k_btcoex_timer_pause(struct ath_softc *sc) -{ - struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_hw *ah = sc->sc_ah; - - del_timer_sync(&btcoex->period_timer); - - if (btcoex->hw_timer_enabled) - ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); - - btcoex->hw_timer_enabled = false; -} - static void ath9k_stop(struct ieee80211_hw *hw) { struct ath_wiphy *aphy = hw->priv; -- cgit v1.2.3 From 556242049cc3992d0ee625e9f15c4b00ea4baac8 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:02 +0530 Subject: ath9k: Add new file init.c Move initialization/de-initialization related code to this file. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/Makefile | 1 + drivers/net/wireless/ath/ath9k/ath9k.h | 5 + drivers/net/wireless/ath/ath9k/init.c | 856 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/main.c | 842 +------------------------------ 4 files changed, 865 insertions(+), 839 deletions(-) create mode 100644 drivers/net/wireless/ath/ath9k/init.c diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 332d6f20c6b6..6b50d5eb9ec3 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -1,5 +1,6 @@ ath9k-y += beacon.o \ gpio.o \ + init.o \ main.o \ recv.o \ xmit.o \ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bbdca5edcfbf..68a423054e6c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -341,6 +341,8 @@ int ath_beaconq_config(struct ath_softc *sc); #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ +void ath_ani_calibrate(unsigned long data); + /**********/ /* BTCOEX */ /**********/ @@ -519,6 +521,7 @@ struct ath_wiphy { int chan_is_ht; }; +void ath9k_tasklet(unsigned long data); int ath_reset(struct ath_softc *sc, bool retry_tx); int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); @@ -535,6 +538,7 @@ static inline void ath_bus_cleanup(struct ath_common *common) } extern struct ieee80211_ops ath9k_ops; +extern int modparam_nohwcrypt; irqreturn_t ath_isr(int irq, void *dev); void ath_cleanup(struct ath_softc *sc); @@ -552,6 +556,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); +bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); #ifdef CONFIG_PCI int ath_pci_init(void); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c new file mode 100644 index 000000000000..2bea0892918e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -0,0 +1,856 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ath9k.h" + +static char *dev_info = "ath9k"; + +MODULE_AUTHOR("Atheros Communications"); +MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); +MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); +MODULE_LICENSE("Dual BSD/GPL"); + +static unsigned int ath9k_debug = ATH_DBG_DEFAULT; +module_param_named(debug, ath9k_debug, uint, 0); +MODULE_PARM_DESC(debug, "Debugging mask"); + +int modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +/* We use the hw_value as an index into our private channel structure */ + +#define CHAN2G(_freq, _idx) { \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 20, \ +} + +#define CHAN5G(_freq, _idx) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_idx), \ + .max_power = 20, \ +} + +/* Some 2 GHz radios are actually tunable on 2312-2732 + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_2ghz_chantable[] = { + CHAN2G(2412, 0), /* Channel 1 */ + CHAN2G(2417, 1), /* Channel 2 */ + CHAN2G(2422, 2), /* Channel 3 */ + CHAN2G(2427, 3), /* Channel 4 */ + CHAN2G(2432, 4), /* Channel 5 */ + CHAN2G(2437, 5), /* Channel 6 */ + CHAN2G(2442, 6), /* Channel 7 */ + CHAN2G(2447, 7), /* Channel 8 */ + CHAN2G(2452, 8), /* Channel 9 */ + CHAN2G(2457, 9), /* Channel 10 */ + CHAN2G(2462, 10), /* Channel 11 */ + CHAN2G(2467, 11), /* Channel 12 */ + CHAN2G(2472, 12), /* Channel 13 */ + CHAN2G(2484, 13), /* Channel 14 */ +}; + +/* Some 5 GHz radios are actually tunable on XXXX-YYYY + * on 5 MHz steps, we support the channels which we know + * we have calibration data for all cards though to make + * this static */ +static struct ieee80211_channel ath9k_5ghz_chantable[] = { + /* _We_ call this UNII 1 */ + CHAN5G(5180, 14), /* Channel 36 */ + CHAN5G(5200, 15), /* Channel 40 */ + CHAN5G(5220, 16), /* Channel 44 */ + CHAN5G(5240, 17), /* Channel 48 */ + /* _We_ call this UNII 2 */ + CHAN5G(5260, 18), /* Channel 52 */ + CHAN5G(5280, 19), /* Channel 56 */ + CHAN5G(5300, 20), /* Channel 60 */ + CHAN5G(5320, 21), /* Channel 64 */ + /* _We_ call this "Middle band" */ + CHAN5G(5500, 22), /* Channel 100 */ + CHAN5G(5520, 23), /* Channel 104 */ + CHAN5G(5540, 24), /* Channel 108 */ + CHAN5G(5560, 25), /* Channel 112 */ + CHAN5G(5580, 26), /* Channel 116 */ + CHAN5G(5600, 27), /* Channel 120 */ + CHAN5G(5620, 28), /* Channel 124 */ + CHAN5G(5640, 29), /* Channel 128 */ + CHAN5G(5660, 30), /* Channel 132 */ + CHAN5G(5680, 31), /* Channel 136 */ + CHAN5G(5700, 32), /* Channel 140 */ + /* _We_ call this UNII 3 */ + CHAN5G(5745, 33), /* Channel 149 */ + CHAN5G(5765, 34), /* Channel 153 */ + CHAN5G(5785, 35), /* Channel 157 */ + CHAN5G(5805, 36), /* Channel 161 */ + CHAN5G(5825, 37), /* Channel 165 */ +}; + +/* Atheros hardware rate code addition for short premble */ +#define SHPCHECK(__hw_rate, __flags) \ + ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) + +#define RATE(_bitrate, _hw_rate, _flags) { \ + .bitrate = (_bitrate), \ + .flags = (_flags), \ + .hw_value = (_hw_rate), \ + .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ +} + +static struct ieee80211_rate ath9k_legacy_rates[] = { + RATE(10, 0x1b, 0), + RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), + RATE(60, 0x0b, 0), + RATE(90, 0x0f, 0), + RATE(120, 0x0a, 0), + RATE(180, 0x0e, 0), + RATE(240, 0x09, 0), + RATE(360, 0x0d, 0), + RATE(480, 0x08, 0), + RATE(540, 0x0c, 0), +}; + +static void ath9k_uninit_hw(struct ath_softc *sc); + +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. + */ + +static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&sc->sc_serial_rw, flags); + iowrite32(val, sc->mem + reg_offset); + spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + } else + iowrite32(val, sc->mem + reg_offset); +} + +static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) +{ + struct ath_hw *ah = (struct ath_hw *) hw_priv; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_softc *sc = (struct ath_softc *) common->priv; + u32 val; + + if (ah->config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&sc->sc_serial_rw, flags); + val = ioread32(sc->mem + reg_offset); + spin_unlock_irqrestore(&sc->sc_serial_rw, flags); + } else + val = ioread32(sc->mem + reg_offset); + return val; +} + +static const struct ath_ops ath9k_common_ops = { + .read = ath9k_ioread32, + .write = ath9k_iowrite32, +}; + +/**************************/ +/* Initialization */ +/**************************/ + +static void setup_ht_cap(struct ath_softc *sc, + struct ieee80211_sta_ht_cap *ht_info) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + u8 tx_streams, rx_streams; + + ht_info->ht_supported = true; + ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + + ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + + /* set up supported mcs set */ + memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); + tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? + 1 : 2; + rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? + 1 : 2; + + if (tx_streams != rx_streams) { + ath_print(common, ATH_DBG_CONFIG, + "TX streams %d, RX streams: %d\n", + tx_streams, rx_streams); + ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; + ht_info->mcs.tx_params |= ((tx_streams - 1) << + IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); + } + + ht_info->mcs.rx_mask[0] = 0xff; + if (rx_streams >= 2) + ht_info->mcs.rx_mask[1] = 0xff; + + ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; +} + +static int ath9k_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); + + return ath_reg_notifier_apply(wiphy, request, reg); +} + +/* + * This function will allocate both the DMA descriptor structure, and the + * buffers it contains. These are used to contain the descriptors used + * by the system. +*/ +int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, + struct list_head *head, const char *name, + int nbuf, int ndesc) +{ +#define DS2PHYS(_dd, _ds) \ + ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) +#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) +#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_desc *ds; + struct ath_buf *bf; + int i, bsize, error; + + ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", + name, nbuf, ndesc); + + INIT_LIST_HEAD(head); + /* ath_desc must be a multiple of DWORDs */ + if ((sizeof(struct ath_desc) % 4) != 0) { + ath_print(common, ATH_DBG_FATAL, + "ath_desc not DWORD aligned\n"); + BUG_ON((sizeof(struct ath_desc) % 4) != 0); + error = -ENOMEM; + goto fail; + } + + dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; + + /* + * Need additional DMA memory because we can't use + * descriptors that cross the 4K page boundary. Assume + * one skipped descriptor per 4K page. + */ + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { + u32 ndesc_skipped = + ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); + u32 dma_len; + + while (ndesc_skipped) { + dma_len = ndesc_skipped * sizeof(struct ath_desc); + dd->dd_desc_len += dma_len; + + ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); + }; + } + + /* allocate descriptors */ + dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, + &dd->dd_desc_paddr, GFP_KERNEL); + if (dd->dd_desc == NULL) { + error = -ENOMEM; + goto fail; + } + ds = dd->dd_desc; + ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", + name, ds, (u32) dd->dd_desc_len, + ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); + + /* allocate buffers */ + bsize = sizeof(struct ath_buf) * nbuf; + bf = kzalloc(bsize, GFP_KERNEL); + if (bf == NULL) { + error = -ENOMEM; + goto fail2; + } + dd->dd_bufptr = bf; + + for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { + bf->bf_desc = ds; + bf->bf_daddr = DS2PHYS(dd, ds); + + if (!(sc->sc_ah->caps.hw_caps & + ATH9K_HW_CAP_4KB_SPLITTRANS)) { + /* + * Skip descriptor addresses which can cause 4KB + * boundary crossing (addr + length) with a 32 dword + * descriptor fetch. + */ + while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { + BUG_ON((caddr_t) bf->bf_desc >= + ((caddr_t) dd->dd_desc + + dd->dd_desc_len)); + + ds += ndesc; + bf->bf_desc = ds; + bf->bf_daddr = DS2PHYS(dd, ds); + } + } + list_add_tail(&bf->list, head); + } + return 0; +fail2: + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); +fail: + memset(dd, 0, sizeof(*dd)); + return error; +#undef ATH_DESC_4KB_BOUND_CHECK +#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED +#undef DS2PHYS +} + +static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, + const struct ath_bus_ops *bus_ops) +{ + struct ath_hw *ah = NULL; + struct ath_common *common; + int r = 0, i; + int csz = 0; + int qnum; + + /* XXX: hardware will not be ready until ath_open() being called */ + sc->sc_flags |= SC_OP_INVALID; + + spin_lock_init(&sc->wiphy_lock); + spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); + spin_lock_init(&sc->sc_pm_lock); + mutex_init(&sc->mutex); + tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); + tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, + (unsigned long)sc); + + ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); + if (!ah) + return -ENOMEM; + + ah->hw_version.devid = devid; + ah->hw_version.subsysid = subsysid; + sc->sc_ah = ah; + + common = ath9k_hw_common(ah); + common->ops = &ath9k_common_ops; + common->bus_ops = bus_ops; + common->ah = ah; + common->hw = sc->hw; + common->priv = sc; + common->debug_mask = ath9k_debug; + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath_read_cachesize(common, &csz); + /* XXX assert csz is non-zero */ + common->cachelsz = csz << 2; /* convert to bytes */ + + r = ath9k_hw_init(ah); + if (r) { + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize hardware; " + "initialization status: %d\n", r); + goto bad_free_hw; + } + + if (ath9k_init_debug(ah) < 0) { + ath_print(common, ATH_DBG_FATAL, + "Unable to create debugfs files\n"); + goto bad_free_hw; + } + + /* Get the hardware key cache size. */ + common->keymax = ah->caps.keycache_size; + if (common->keymax > ATH_KEYMAX) { + ath_print(common, ATH_DBG_ANY, + "Warning, using only %u entries in %u key cache\n", + ATH_KEYMAX, common->keymax); + common->keymax = ATH_KEYMAX; + } + + /* + * Reset the key cache since some parts do not + * reset the contents on initial power up. + */ + for (i = 0; i < common->keymax; i++) + ath9k_hw_keyreset(ah, (u16) i); + + /* default to MONITOR mode */ + sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; + + /* + * Allocate hardware transmit queues: one queue for + * beacon frames and one data queue for each QoS + * priority. Note that the hal handles reseting + * these queues at the needed time. + */ + sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); + if (sc->beacon.beaconq == -1) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup a beacon xmit queue\n"); + r = -EIO; + goto bad2; + } + sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); + if (sc->beacon.cabq == NULL) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup CAB xmit queue\n"); + r = -EIO; + goto bad2; + } + + sc->config.cabqReadytime = ATH_CABQ_READY_TIME; + ath_cabq_update(sc); + + for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) + sc->tx.hwq_map[i] = -1; + + /* Setup data queues */ + /* NB: ensure BK queue is the lowest priority h/w queue */ + if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BK traffic\n"); + r = -EIO; + goto bad2; + } + + if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for BE traffic\n"); + r = -EIO; + goto bad2; + } + if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VI traffic\n"); + r = -EIO; + goto bad2; + } + if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { + ath_print(common, ATH_DBG_FATAL, + "Unable to setup xmit queue for VO traffic\n"); + r = -EIO; + goto bad2; + } + + /* Initializes the noise floor to a reasonable default value. + * Later on this will be updated during ANI processing. */ + + common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; + setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); + + if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL)) { + /* + * Whether we should enable h/w TKIP MIC. + * XXX: if we don't support WME TKIP MIC, then we wouldn't + * report WMM capable, so it's always safe to turn on + * TKIP MIC in this case. + */ + ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, + 0, 1, NULL); + } + + /* + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. + */ + if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL) + && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_MIC, NULL) + && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, + 0, NULL)) + common->splitmic = 1; + + /* turn on mcast key search if possible */ + if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) + (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, + 1, NULL); + + sc->config.txpowlimit = ATH_TXPOWER_MAX; + + /* 11n Capabilities */ + if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + sc->sc_flags |= SC_OP_TXAGGR; + sc->sc_flags |= SC_OP_RXAGGR; + } + + common->tx_chainmask = ah->caps.tx_chainmask; + common->rx_chainmask = ah->caps.rx_chainmask; + + ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); + sc->rx.defant = ath9k_hw_getdefantenna(ah); + + if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); + + sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ + + /* initialize beacon slots */ + for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { + sc->beacon.bslot[i] = NULL; + sc->beacon.bslot_aphy[i] = NULL; + } + + /* setup channels and rates */ + + if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; + sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + sc->sbands[IEEE80211_BAND_2GHZ].n_channels = + ARRAY_SIZE(ath9k_2ghz_chantable); + sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; + sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates); + } + + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; + sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; + sc->sbands[IEEE80211_BAND_5GHZ].n_channels = + ARRAY_SIZE(ath9k_5ghz_chantable); + sc->sbands[IEEE80211_BAND_5GHZ].bitrates = + ath9k_legacy_rates + 4; + sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates) - 4; + } + + switch (ah->btcoex_hw.scheme) { + case ATH_BTCOEX_CFG_NONE: + break; + case ATH_BTCOEX_CFG_2WIRE: + ath9k_hw_btcoex_init_2wire(ah); + break; + case ATH_BTCOEX_CFG_3WIRE: + ath9k_hw_btcoex_init_3wire(ah); + r = ath_init_btcoex_timer(sc); + if (r) + goto bad2; + qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); + ath9k_hw_init_btcoex_hw(ah, qnum); + sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; + break; + default: + WARN_ON(1); + break; + } + + return 0; +bad2: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + +bad_free_hw: + ath9k_uninit_hw(sc); + return r; +} + +void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) +{ + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_AMPDU_AGGREGATION | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_SPECTRUM_MGMT; + + if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) + hw->flags |= IEEE80211_HW_MFP_CAPABLE; + + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT); + + hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + + hw->queues = 4; + hw->max_rates = 4; + hw->channel_change_time = 5000; + hw->max_listen_interval = 10; + /* Hardware supports 10 but we use 4 */ + hw->max_rate_tries = 4; + hw->sta_data_size = sizeof(struct ath_node); + hw->vif_data_size = sizeof(struct ath_vif); + + hw->rate_control_algorithm = "ath9k_rate_control"; + + if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &sc->sbands[IEEE80211_BAND_2GHZ]; + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &sc->sbands[IEEE80211_BAND_5GHZ]; +} + +/* Device driver core initialization */ +int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, + const struct ath_bus_ops *bus_ops) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_common *common; + struct ath_hw *ah; + int error = 0, i; + struct ath_regulatory *reg; + + dev_dbg(sc->dev, "Attach ATH hw\n"); + + error = ath_init_softc(devid, sc, subsysid, bus_ops); + if (error != 0) + return error; + + ah = sc->sc_ah; + common = ath9k_hw_common(ah); + + /* get mac address from hardware and set in mac80211 */ + + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); + + ath_set_hw_capab(sc, hw); + + error = ath_regd_init(&common->regulatory, sc->hw->wiphy, + ath9k_reg_notifier); + if (error) + return error; + + reg = &common->regulatory; + + if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) + setup_ht_cap(sc, + &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); + if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) + setup_ht_cap(sc, + &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); + } + + /* initialize tx/rx engine */ + error = ath_tx_init(sc, ATH_TXBUF); + if (error != 0) + goto error_attach; + + error = ath_rx_init(sc, ATH_RXBUF); + if (error != 0) + goto error_attach; + + INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); + INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); + sc->wiphy_scheduler_int = msecs_to_jiffies(500); + + error = ieee80211_register_hw(hw); + + if (!ath_is_world_regd(reg)) { + error = regulatory_hint(hw->wiphy, reg->alpha2); + if (error) + goto error_attach; + } + + /* Initialize LED control */ + ath_init_leds(sc); + + ath_start_rfkill_poll(sc); + + return 0; + +error_attach: + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_uninit_hw(sc); + + return error; +} + +/*****************************/ +/* De-Initialization */ +/*****************************/ + +static void ath9k_uninit_hw(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + + BUG_ON(!ah); + + ath9k_exit_debug(ah); + ath9k_hw_detach(ah); + sc->sc_ah = NULL; +} + +static void ath_clean_core(struct ath_softc *sc) +{ + struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; + int i = 0; + + ath9k_ps_wakeup(sc); + + dev_dbg(sc->dev, "Detach ATH hw\n"); + + ath_deinit_leds(sc); + wiphy_rfkill_stop_polling(sc->hw->wiphy); + + for (i = 0; i < sc->num_sec_wiphy; i++) { + struct ath_wiphy *aphy = sc->sec_wiphy[i]; + if (aphy == NULL) + continue; + sc->sec_wiphy[i] = NULL; + ieee80211_unregister_hw(aphy->hw); + ieee80211_free_hw(aphy->hw); + } + ieee80211_unregister_hw(hw); + ath_rx_cleanup(sc); + ath_tx_cleanup(sc); + + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + + if (!(sc->sc_flags & SC_OP_INVALID)) + ath9k_setpower(sc, ATH9K_PM_AWAKE); + + /* cleanup tx queues */ + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + if ((sc->btcoex.no_stomp_timer) && + ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); +} + +void ath_descdma_cleanup(struct ath_softc *sc, + struct ath_descdma *dd, + struct list_head *head) +{ + dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, + dd->dd_desc_paddr); + + INIT_LIST_HEAD(head); + kfree(dd->dd_bufptr); + memset(dd, 0, sizeof(*dd)); +} + +void ath_detach(struct ath_softc *sc) +{ + ath_clean_core(sc); + ath9k_uninit_hw(sc); +} + +void ath_cleanup(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + + ath_clean_core(sc); + free_irq(sc->irq, sc); + ath_bus_cleanup(common); + kfree(sc->sec_wiphy); + ieee80211_free_hw(sc->hw); + + ath9k_uninit_hw(sc); +} + +/************************/ +/* Module Hooks */ +/************************/ + +static int __init ath9k_init(void) +{ + int error; + + /* Register rate control algorithm */ + error = ath_rate_control_register(); + if (error != 0) { + printk(KERN_ERR + "ath9k: Unable to register rate control " + "algorithm: %d\n", + error); + goto err_out; + } + + error = ath9k_debug_create_root(); + if (error) { + printk(KERN_ERR + "ath9k: Unable to create debugfs root: %d\n", + error); + goto err_rate_unregister; + } + + error = ath_pci_init(); + if (error < 0) { + printk(KERN_ERR + "ath9k: No PCI devices found, driver not installed.\n"); + error = -ENODEV; + goto err_remove_root; + } + + error = ath_ahb_init(); + if (error < 0) { + error = -ENODEV; + goto err_pci_exit; + } + + return 0; + + err_pci_exit: + ath_pci_exit(); + + err_remove_root: + ath9k_debug_remove_root(); + err_rate_unregister: + ath_rate_control_unregister(); + err_out: + return error; +} +module_init(ath9k_init); + +static void __exit ath9k_exit(void) +{ + ath_ahb_exit(); + ath_pci_exit(); + ath9k_debug_remove_root(); + ath_rate_control_unregister(); + printk(KERN_INFO "%s: Driver unloaded\n", dev_info); +} +module_exit(ath9k_exit); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 31a33cf762da..48bd5d50f4d6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -18,118 +18,6 @@ #include "ath9k.h" #include "btcoex.h" -static char *dev_info = "ath9k"; - -MODULE_AUTHOR("Atheros Communications"); -MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); -MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); -MODULE_LICENSE("Dual BSD/GPL"); - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); - -static unsigned int ath9k_debug = ATH_DBG_DEFAULT; -module_param_named(debug, ath9k_debug, uint, 0); -MODULE_PARM_DESC(debug, "Debugging mask"); - -/* We use the hw_value as an index into our private channel structure */ - -#define CHAN2G(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 20, \ -} - -#define CHAN5G(_freq, _idx) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 20, \ -} - -/* Some 2 GHz radios are actually tunable on 2312-2732 - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_2ghz_chantable[] = { - CHAN2G(2412, 0), /* Channel 1 */ - CHAN2G(2417, 1), /* Channel 2 */ - CHAN2G(2422, 2), /* Channel 3 */ - CHAN2G(2427, 3), /* Channel 4 */ - CHAN2G(2432, 4), /* Channel 5 */ - CHAN2G(2437, 5), /* Channel 6 */ - CHAN2G(2442, 6), /* Channel 7 */ - CHAN2G(2447, 7), /* Channel 8 */ - CHAN2G(2452, 8), /* Channel 9 */ - CHAN2G(2457, 9), /* Channel 10 */ - CHAN2G(2462, 10), /* Channel 11 */ - CHAN2G(2467, 11), /* Channel 12 */ - CHAN2G(2472, 12), /* Channel 13 */ - CHAN2G(2484, 13), /* Channel 14 */ -}; - -/* Some 5 GHz radios are actually tunable on XXXX-YYYY - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_5ghz_chantable[] = { - /* _We_ call this UNII 1 */ - CHAN5G(5180, 14), /* Channel 36 */ - CHAN5G(5200, 15), /* Channel 40 */ - CHAN5G(5220, 16), /* Channel 44 */ - CHAN5G(5240, 17), /* Channel 48 */ - /* _We_ call this UNII 2 */ - CHAN5G(5260, 18), /* Channel 52 */ - CHAN5G(5280, 19), /* Channel 56 */ - CHAN5G(5300, 20), /* Channel 60 */ - CHAN5G(5320, 21), /* Channel 64 */ - /* _We_ call this "Middle band" */ - CHAN5G(5500, 22), /* Channel 100 */ - CHAN5G(5520, 23), /* Channel 104 */ - CHAN5G(5540, 24), /* Channel 108 */ - CHAN5G(5560, 25), /* Channel 112 */ - CHAN5G(5580, 26), /* Channel 116 */ - CHAN5G(5600, 27), /* Channel 120 */ - CHAN5G(5620, 28), /* Channel 124 */ - CHAN5G(5640, 29), /* Channel 128 */ - CHAN5G(5660, 30), /* Channel 132 */ - CHAN5G(5680, 31), /* Channel 136 */ - CHAN5G(5700, 32), /* Channel 140 */ - /* _We_ call this UNII 3 */ - CHAN5G(5745, 33), /* Channel 149 */ - CHAN5G(5765, 34), /* Channel 153 */ - CHAN5G(5785, 35), /* Channel 157 */ - CHAN5G(5805, 36), /* Channel 161 */ - CHAN5G(5825, 37), /* Channel 165 */ -}; - -/* Atheros hardware rate code addition for short premble */ -#define SHPCHECK(__hw_rate, __flags) \ - ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) - -#define RATE(_bitrate, _hw_rate, _flags) { \ - .bitrate = (_bitrate), \ - .flags = (_flags), \ - .hw_value = (_hw_rate), \ - .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ -} - -static struct ieee80211_rate ath9k_legacy_rates[] = { - RATE(10, 0x1b, 0), - RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(60, 0x0b, 0), - RATE(90, 0x0f, 0), - RATE(120, 0x0a, 0), - RATE(180, 0x0e, 0), - RATE(240, 0x09, 0), - RATE(360, 0x0d, 0), - RATE(480, 0x08, 0), - RATE(540, 0x0c, 0), -}; - static void ath_cache_conf_rate(struct ath_softc *sc, struct ieee80211_conf *conf) { @@ -221,7 +109,7 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, return channel; } -static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) +bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) { unsigned long flags; bool ret; @@ -349,7 +237,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, * When the task is complete, it reschedules itself depending on the * appropriate interval that was calculated. */ -static void ath_ani_calibrate(unsigned long data) +void ath_ani_calibrate(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; struct ath_hw *ah = sc->sc_ah; @@ -504,7 +392,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) ath_tx_node_cleanup(sc, an); } -static void ath9k_tasklet(unsigned long data) +void ath9k_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; struct ath_hw *ah = sc->sc_ah; @@ -924,44 +812,6 @@ static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf } } -static void setup_ht_cap(struct ath_softc *sc, - struct ieee80211_sta_ht_cap *ht_info) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - u8 tx_streams, rx_streams; - - ht_info->ht_supported = true; - ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SM_PS | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - - ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - - /* set up supported mcs set */ - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? - 1 : 2; - rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? - 1 : 2; - - if (tx_streams != rx_streams) { - ath_print(common, ATH_DBG_CONFIG, - "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; - ht_info->mcs.tx_params |= ((tx_streams - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - } - - ht_info->mcs.rx_mask[0] = 0xff; - if (rx_streams >= 2) - ht_info->mcs.rx_mask[1] = 0xff; - - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; -} - static void ath9k_bss_assoc_info(struct ath_softc *sc, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf) @@ -1084,513 +934,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); } -static void ath9k_uninit_hw(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - BUG_ON(!ah); - - ath9k_exit_debug(ah); - ath9k_hw_detach(ah); - sc->sc_ah = NULL; -} - -static void ath_clean_core(struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - struct ath_hw *ah = sc->sc_ah; - int i = 0; - - ath9k_ps_wakeup(sc); - - dev_dbg(sc->dev, "Detach ATH hw\n"); - - ath_deinit_leds(sc); - wiphy_rfkill_stop_polling(sc->hw->wiphy); - - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - sc->sec_wiphy[i] = NULL; - ieee80211_unregister_hw(aphy->hw); - ieee80211_free_hw(aphy->hw); - } - ieee80211_unregister_hw(hw); - ath_rx_cleanup(sc); - ath_tx_cleanup(sc); - - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - - if (!(sc->sc_flags & SC_OP_INVALID)) - ath9k_setpower(sc, ATH9K_PM_AWAKE); - - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - if ((sc->btcoex.no_stomp_timer) && - ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) - ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); -} - -void ath_detach(struct ath_softc *sc) -{ - ath_clean_core(sc); - ath9k_uninit_hw(sc); -} - -void ath_cleanup(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - ath_clean_core(sc); - free_irq(sc->irq, sc); - ath_bus_cleanup(common); - kfree(sc->sec_wiphy); - ieee80211_free_hw(sc->hw); - - ath9k_uninit_hw(sc); -} - -static int ath9k_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); - - return ath_reg_notifier_apply(wiphy, request, reg); -} - -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) -{ - struct ath_hw *ah = (struct ath_hw *) hw_priv; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&sc->sc_serial_rw, flags); - iowrite32(val, sc->mem + reg_offset); - spin_unlock_irqrestore(&sc->sc_serial_rw, flags); - } else - iowrite32(val, sc->mem + reg_offset); -} - -static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) -{ - struct ath_hw *ah = (struct ath_hw *) hw_priv; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_softc *sc = (struct ath_softc *) common->priv; - u32 val; - - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&sc->sc_serial_rw, flags); - val = ioread32(sc->mem + reg_offset); - spin_unlock_irqrestore(&sc->sc_serial_rw, flags); - } else - val = ioread32(sc->mem + reg_offset); - return val; -} - -static const struct ath_ops ath9k_common_ops = { - .read = ath9k_ioread32, - .write = ath9k_iowrite32, -}; - -/* - * Initialize and fill ath_softc, ath_sofct is the - * "Software Carrier" struct. Historically it has existed - * to allow the separation between hardware specific - * variables (now in ath_hw) and driver specific variables. - */ -static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, - const struct ath_bus_ops *bus_ops) -{ - struct ath_hw *ah = NULL; - struct ath_common *common; - int r = 0, i; - int csz = 0; - int qnum; - - /* XXX: hardware will not be ready until ath_open() being called */ - sc->sc_flags |= SC_OP_INVALID; - - spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); - spin_lock_init(&sc->sc_serial_rw); - spin_lock_init(&sc->sc_pm_lock); - mutex_init(&sc->mutex); - tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); - tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, - (unsigned long)sc); - - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (!ah) - return -ENOMEM; - - ah->hw_version.devid = devid; - ah->hw_version.subsysid = subsysid; - sc->sc_ah = ah; - - common = ath9k_hw_common(ah); - common->ops = &ath9k_common_ops; - common->bus_ops = bus_ops; - common->ah = ah; - common->hw = sc->hw; - common->priv = sc; - common->debug_mask = ath9k_debug; - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(common, &csz); - /* XXX assert csz is non-zero */ - common->cachelsz = csz << 2; /* convert to bytes */ - - r = ath9k_hw_init(ah); - if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", r); - goto bad_free_hw; - } - - if (ath9k_init_debug(ah) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); - goto bad_free_hw; - } - - /* Get the hardware key cache size. */ - common->keymax = ah->caps.keycache_size; - if (common->keymax > ATH_KEYMAX) { - ath_print(common, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, common->keymax); - common->keymax = ATH_KEYMAX; - } - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < common->keymax; i++) - ath9k_hw_keyreset(ah, (u16) i); - - /* default to MONITOR mode */ - sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; - - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that the hal handles reseting - * these queues at the needed time. - */ - sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); - if (sc->beacon.beaconq == -1) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); - r = -EIO; - goto bad2; - } - sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); - if (sc->beacon.cabq == NULL) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); - r = -EIO; - goto bad2; - } - - sc->config.cabqReadytime = ATH_CABQ_READY_TIME; - ath_cabq_update(sc); - - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - - /* Setup data queues */ - /* NB: ensure BK queue is the lowest priority h/w queue */ - if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - r = -EIO; - goto bad2; - } - - if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - r = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - r = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { - ath_print(common, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - r = -EIO; - goto bad2; - } - - /* Initializes the noise floor to a reasonable default value. - * Later on this will be updated during ANI processing. */ - - common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; - setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); - - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, - 0, 1, NULL); - } - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - common->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, - 1, NULL); - - sc->config.txpowlimit = ATH_TXPOWER_MAX; - - /* 11n Capabilities */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - sc->sc_flags |= SC_OP_TXAGGR; - sc->sc_flags |= SC_OP_RXAGGR; - } - - common->tx_chainmask = ah->caps.tx_chainmask; - common->rx_chainmask = ah->caps.rx_chainmask; - - ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); - sc->rx.defant = ath9k_hw_getdefantenna(ah); - - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); - - sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ - - /* initialize beacon slots */ - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } - - /* setup channels and rates */ - - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_chantable); - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; - sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = - ARRAY_SIZE(ath9k_legacy_rates); - } - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; - sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels = - ARRAY_SIZE(ath9k_5ghz_chantable); - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - ath9k_legacy_rates + 4; - sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = - ARRAY_SIZE(ath9k_legacy_rates) - 4; - } - - switch (ah->btcoex_hw.scheme) { - case ATH_BTCOEX_CFG_NONE: - break; - case ATH_BTCOEX_CFG_2WIRE: - ath9k_hw_btcoex_init_2wire(ah); - break; - case ATH_BTCOEX_CFG_3WIRE: - ath9k_hw_btcoex_init_3wire(ah); - r = ath_init_btcoex_timer(sc); - if (r) - goto bad2; - qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - ath9k_hw_init_btcoex_hw(ah, qnum); - sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; - break; - default: - WARN_ON(1); - break; - } - - return 0; -bad2: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - -bad_free_hw: - ath9k_uninit_hw(sc); - return r; -} - -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) -{ - struct ath_hw *ah = sc->sc_ah; - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_SPECTRUM_MGMT; - - if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) - hw->flags |= IEEE80211_HW_MFP_CAPABLE; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - if (AR_SREV_5416(ah)) - hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - - hw->queues = 4; - hw->max_rates = 4; - hw->channel_change_time = 5000; - hw->max_listen_interval = 10; - /* Hardware supports 10 but we use 4 */ - hw->max_rate_tries = 4; - hw->sta_data_size = sizeof(struct ath_node); - hw->vif_data_size = sizeof(struct ath_vif); - - hw->rate_control_algorithm = "ath9k_rate_control"; - - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; -} - -/* Device driver core initialization */ -int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, - const struct ath_bus_ops *bus_ops) -{ - struct ieee80211_hw *hw = sc->hw; - struct ath_common *common; - struct ath_hw *ah; - int error = 0, i; - struct ath_regulatory *reg; - - dev_dbg(sc->dev, "Attach ATH hw\n"); - - error = ath_init_softc(devid, sc, subsysid, bus_ops); - if (error != 0) - return error; - - ah = sc->sc_ah; - common = ath9k_hw_common(ah); - - /* get mac address from hardware and set in mac80211 */ - - SET_IEEE80211_PERM_ADDR(hw, common->macaddr); - - ath_set_hw_capab(sc, hw); - - error = ath_regd_init(&common->regulatory, sc->hw->wiphy, - ath9k_reg_notifier); - if (error) - return error; - - reg = &common->regulatory; - - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) - setup_ht_cap(sc, - &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) - setup_ht_cap(sc, - &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - } - - /* initialize tx/rx engine */ - error = ath_tx_init(sc, ATH_TXBUF); - if (error != 0) - goto error_attach; - - error = ath_rx_init(sc, ATH_RXBUF); - if (error != 0) - goto error_attach; - - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); - INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(500); - - error = ieee80211_register_hw(hw); - - if (!ath_is_world_regd(reg)) { - error = regulatory_hint(hw->wiphy, reg->alpha2); - if (error) - goto error_attach; - } - - /* Initialize LED control */ - ath_init_leds(sc); - - ath_start_rfkill_poll(sc); - - return 0; - -error_attach: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - ath9k_uninit_hw(sc); - - return error; -} - int ath_reset(struct ath_softc *sc, bool retry_tx) { struct ath_hw *ah = sc->sc_ah; @@ -1648,125 +991,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) return r; } -/* - * This function will allocate both the DMA descriptor structure, and the - * buffers it contains. These are used to contain the descriptors used - * by the system. -*/ -int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head, const char *name, - int nbuf, int ndesc) -{ -#define DS2PHYS(_dd, _ds) \ - ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) -#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) -#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_desc *ds; - struct ath_buf *bf; - int i, bsize, error; - - ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", - name, nbuf, ndesc); - - INIT_LIST_HEAD(head); - /* ath_desc must be a multiple of DWORDs */ - if ((sizeof(struct ath_desc) % 4) != 0) { - ath_print(common, ATH_DBG_FATAL, - "ath_desc not DWORD aligned\n"); - BUG_ON((sizeof(struct ath_desc) % 4) != 0); - error = -ENOMEM; - goto fail; - } - - dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; - - /* - * Need additional DMA memory because we can't use - * descriptors that cross the 4K page boundary. Assume - * one skipped descriptor per 4K page. - */ - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { - u32 ndesc_skipped = - ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); - u32 dma_len; - - while (ndesc_skipped) { - dma_len = ndesc_skipped * sizeof(struct ath_desc); - dd->dd_desc_len += dma_len; - - ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); - }; - } - - /* allocate descriptors */ - dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, - &dd->dd_desc_paddr, GFP_KERNEL); - if (dd->dd_desc == NULL) { - error = -ENOMEM; - goto fail; - } - ds = dd->dd_desc; - ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - name, ds, (u32) dd->dd_desc_len, - ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); - - /* allocate buffers */ - bsize = sizeof(struct ath_buf) * nbuf; - bf = kzalloc(bsize, GFP_KERNEL); - if (bf == NULL) { - error = -ENOMEM; - goto fail2; - } - dd->dd_bufptr = bf; - - for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - - if (!(sc->sc_ah->caps.hw_caps & - ATH9K_HW_CAP_4KB_SPLITTRANS)) { - /* - * Skip descriptor addresses which can cause 4KB - * boundary crossing (addr + length) with a 32 dword - * descriptor fetch. - */ - while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { - BUG_ON((caddr_t) bf->bf_desc >= - ((caddr_t) dd->dd_desc + - dd->dd_desc_len)); - - ds += ndesc; - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - } - } - list_add_tail(&bf->list, head); - } - return 0; -fail2: - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); -fail: - memset(dd, 0, sizeof(*dd)); - return error; -#undef ATH_DESC_4KB_BOUND_CHECK -#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED -#undef DS2PHYS -} - -void ath_descdma_cleanup(struct ath_softc *sc, - struct ath_descdma *dd, - struct list_head *head) -{ - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); - - INIT_LIST_HEAD(head); - kfree(dd->dd_bufptr); - memset(dd, 0, sizeof(*dd)); -} - int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) { int qnum; @@ -2778,63 +2002,3 @@ struct ieee80211_ops ath9k_ops = { .sw_scan_complete = ath9k_sw_scan_complete, .rfkill_poll = ath9k_rfkill_poll_state, }; - -static int __init ath9k_init(void) -{ - int error; - - /* Register rate control algorithm */ - error = ath_rate_control_register(); - if (error != 0) { - printk(KERN_ERR - "ath9k: Unable to register rate control " - "algorithm: %d\n", - error); - goto err_out; - } - - error = ath9k_debug_create_root(); - if (error) { - printk(KERN_ERR - "ath9k: Unable to create debugfs root: %d\n", - error); - goto err_rate_unregister; - } - - error = ath_pci_init(); - if (error < 0) { - printk(KERN_ERR - "ath9k: No PCI devices found, driver not installed.\n"); - error = -ENODEV; - goto err_remove_root; - } - - error = ath_ahb_init(); - if (error < 0) { - error = -ENODEV; - goto err_pci_exit; - } - - return 0; - - err_pci_exit: - ath_pci_exit(); - - err_remove_root: - ath9k_debug_remove_root(); - err_rate_unregister: - ath_rate_control_unregister(); - err_out: - return error; -} -module_init(ath9k_init); - -static void __exit ath9k_exit(void) -{ - ath_ahb_exit(); - ath_pci_exit(); - ath9k_debug_remove_root(); - ath_rate_control_unregister(); - printk(KERN_INFO "%s: Driver unloaded\n", dev_info); -} -module_exit(ath9k_exit); -- cgit v1.2.3 From 1b04b9308ebc7f6accb319cf51c9b8ec29f79707 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:05 +0530 Subject: ath9k: Cleanup Powersave flags sc_flags has slowly become a kitchen sink over time. Move powersave related flags to a separate variable. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 43 ++++++++++++++++++---------------- drivers/net/wireless/ath/ath9k/main.c | 36 ++++++++++++++-------------- drivers/net/wireless/ath/ath9k/recv.c | 36 ++++++++++++++-------------- drivers/net/wireless/ath/ath9k/xmit.c | 18 +++++++------- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 68a423054e6c..f4645a45ef3c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -416,26 +416,28 @@ void ath_deinit_leds(struct ath_softc *sc); #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ #define ATH_RATE_DUMMY_MARKER 0 -#define SC_OP_INVALID BIT(0) -#define SC_OP_BEACONS BIT(1) -#define SC_OP_RXAGGR BIT(2) -#define SC_OP_TXAGGR BIT(3) -#define SC_OP_FULL_RESET BIT(4) -#define SC_OP_PREAMBLE_SHORT BIT(5) -#define SC_OP_PROTECT_ENABLE BIT(6) -#define SC_OP_RXFLUSH BIT(7) -#define SC_OP_LED_ASSOCIATED BIT(8) -#define SC_OP_WAIT_FOR_BEACON BIT(12) -#define SC_OP_LED_ON BIT(13) -#define SC_OP_SCANNING BIT(14) -#define SC_OP_TSF_RESET BIT(15) -#define SC_OP_WAIT_FOR_CAB BIT(16) -#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) -#define SC_OP_WAIT_FOR_TX_ACK BIT(18) -#define SC_OP_BEACON_SYNC BIT(19) -#define SC_OP_BT_PRIORITY_DETECTED BIT(21) -#define SC_OP_NULLFUNC_COMPLETED BIT(22) -#define SC_OP_PS_ENABLED BIT(23) +#define SC_OP_INVALID BIT(0) +#define SC_OP_BEACONS BIT(1) +#define SC_OP_RXAGGR BIT(2) +#define SC_OP_TXAGGR BIT(3) +#define SC_OP_FULL_RESET BIT(4) +#define SC_OP_PREAMBLE_SHORT BIT(5) +#define SC_OP_PROTECT_ENABLE BIT(6) +#define SC_OP_RXFLUSH BIT(7) +#define SC_OP_LED_ASSOCIATED BIT(8) +#define SC_OP_LED_ON BIT(9) +#define SC_OP_SCANNING BIT(10) +#define SC_OP_TSF_RESET BIT(11) +#define SC_OP_BT_PRIORITY_DETECTED BIT(12) + +/* Powersave flags */ +#define PS_WAIT_FOR_BEACON BIT(0) +#define PS_WAIT_FOR_CAB BIT(1) +#define PS_WAIT_FOR_PSPOLL_DATA BIT(2) +#define PS_WAIT_FOR_TX_ACK BIT(3) +#define PS_BEACON_SYNC BIT(4) +#define PS_NULLFUNC_COMPLETED BIT(5) +#define PS_ENABLED BIT(6) struct ath_wiphy; struct ath_rate_table; @@ -471,6 +473,7 @@ struct ath_softc { u32 intrstatus; u32 sc_flags; /* SC_OP_* */ + u16 ps_flags; /* PS_* */ u16 curtxpow; u8 nbcnvifs; u16 nvifs; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 48bd5d50f4d6..974de2056b4a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -144,10 +144,10 @@ void ath9k_ps_restore(struct ath_softc *sc) goto unlock; if (sc->ps_enabled && - !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK))) + !(sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK))) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); unlock: @@ -424,7 +424,7 @@ void ath9k_tasklet(unsigned long data) */ ath_print(common, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; + sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; } if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) @@ -525,7 +525,7 @@ irqreturn_t ath_isr(int irq, void *dev) * receive frames */ ath9k_setpower(sc, ATH9K_PM_AWAKE); ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; + sc->ps_flags |= PS_WAIT_FOR_BEACON; } chip_reset: @@ -833,7 +833,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, * on the receipt of the first Beacon frame (i.e., * after time sync with the AP). */ - sc->sc_flags |= SC_OP_BEACON_SYNC; + sc->ps_flags |= PS_BEACON_SYNC; /* Configure the beacon */ ath_beacon_config(sc, vif); @@ -1238,11 +1238,11 @@ static int ath9k_tx(struct ieee80211_hw *hw, if (ieee80211_is_pspoll(hdr->frame_control)) { ath_print(common, ATH_DBG_PS, "Sending PS-Poll to pick a buffered frame\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; + sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; } else { ath_print(common, ATH_DBG_PS, "Wake up to complete TX\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; + sc->ps_flags |= PS_WAIT_FOR_TX_ACK; } /* * The actual restore operation will happen only after @@ -1538,7 +1538,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) */ if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { - sc->sc_flags |= SC_OP_PS_ENABLED; + sc->ps_flags |= PS_ENABLED; if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { @@ -1551,23 +1551,23 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * At this point we know hardware has received an ACK * of a previously sent null data frame. */ - if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) { - sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) { + sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; sc->ps_enabled = true; ath9k_hw_setrxabort(sc->sc_ah, 1); } } else { sc->ps_enabled = false; - sc->sc_flags &= ~(SC_OP_PS_ENABLED | - SC_OP_NULLFUNC_COMPLETED); + sc->ps_flags &= ~(PS_ENABLED | + PS_NULLFUNC_COMPLETED); ath9k_setpower(sc, ATH9K_PM_AWAKE); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK); + sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK); if (sc->imask & ATH9K_INT_TIM_TIMER) { sc->imask &= ~ATH9K_INT_TIM_TIMER; ath9k_hw_set_interrupts(sc->sc_ah, diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 477365e5ae69..17b0a6dd8caf 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -364,10 +364,10 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) return; /* not from our current AP */ - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; + sc->ps_flags &= ~PS_WAIT_FOR_BEACON; - if (sc->sc_flags & SC_OP_BEACON_SYNC) { - sc->sc_flags &= ~SC_OP_BEACON_SYNC; + if (sc->ps_flags & PS_BEACON_SYNC) { + sc->ps_flags &= ~PS_BEACON_SYNC; ath_print(common, ATH_DBG_PS, "Reconfigure Beacon timers based on " "timestamp from the AP\n"); @@ -384,17 +384,17 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) */ ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " "buffered broadcast/multicast frame(s)\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; + sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; return; } - if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) { + if (sc->ps_flags & PS_WAIT_FOR_CAB) { /* * This can happen if a broadcast frame is dropped or the AP * fails to send a frame indicating that all CAB frames have * been delivered. */ - sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; + sc->ps_flags &= ~PS_WAIT_FOR_CAB; ath_print(common, ATH_DBG_PS, "PS wait for CAB frames timed out\n"); } @@ -408,10 +408,10 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) hdr = (struct ieee80211_hdr *)skb->data; /* Process Beacon and CAB receive in PS state */ - if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) && + if ((sc->ps_flags & PS_WAIT_FOR_BEACON) && ieee80211_is_beacon(hdr->frame_control)) ath_rx_ps_beacon(sc, skb); - else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) && + else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && (ieee80211_is_data(hdr->frame_control) || ieee80211_is_action(hdr->frame_control)) && is_multicast_ether_addr(hdr->addr1) && @@ -420,20 +420,20 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) * No more broadcast/multicast frames to be received at this * point. */ - sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; + sc->ps_flags &= ~PS_WAIT_FOR_CAB; ath_print(common, ATH_DBG_PS, "All PS CAB frames received, back to sleep\n"); - } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && + } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && !is_multicast_ether_addr(hdr->addr1) && !ieee80211_has_morefrags(hdr->frame_control)) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA; + sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; ath_print(common, ATH_DBG_PS, "Going back to sleep after having received " "PS-Poll data (0x%x)\n", - sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK)); + sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK)); } } @@ -631,9 +631,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) sc->rx.rxotherant = 0; } - if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA))) + if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA))) ath_rx_ps(sc, skb); ath_rx_send_to_mac80211(hw, sc, skb, rxs); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index fa12b9060b0b..a821bb687b3b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1648,7 +1648,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, /* tag if this is a nullfunc frame to enable PS when AP acks it */ if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { bf->bf_isnullfunc = true; - sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; + sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; } else bf->bf_isnullfunc = false; @@ -1858,15 +1858,15 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, skb_pull(skb, padsize); } - if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK; + if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { + sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; ath_print(common, ATH_DBG_PS, "Going back to sleep after having " "received TX status (0x%x)\n", - sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK)); + sc->ps_flags & (PS_WAIT_FOR_BEACON | + PS_WAIT_FOR_CAB | + PS_WAIT_FOR_PSPOLL_DATA | + PS_WAIT_FOR_TX_ACK)); } if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) @@ -2053,11 +2053,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ if (bf->bf_isnullfunc && (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { - if ((sc->sc_flags & SC_OP_PS_ENABLED)) { + if ((sc->ps_flags & PS_ENABLED)) { sc->ps_enabled = true; ath9k_hw_setrxabort(sc->sc_ah, 1); } else - sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED; + sc->ps_flags |= PS_NULLFUNC_COMPLETED; } /* -- cgit v1.2.3 From 285f2ddae03ca207877262f5a9dbd9cddd8b3913 Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:07 +0530 Subject: ath9k: Cleanup init/deinit routines The device initialization and termination functions were messy and convoluted. Introduce helper functions to clarify init_softc() and simplify things in general. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ahb.c | 20 +- drivers/net/wireless/ath/ath9k/ath9k.h | 7 +- drivers/net/wireless/ath/ath9k/hw.c | 4 +- drivers/net/wireless/ath/ath9k/hw.h | 2 +- drivers/net/wireless/ath/ath9k/init.c | 515 ++++++++++++++++--------------- drivers/net/wireless/ath/ath9k/pci.c | 57 ++-- drivers/net/wireless/ath/ath9k/virtual.c | 2 +- 7 files changed, 309 insertions(+), 298 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 329e6bc137ab..f24b1f4c3e29 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -121,16 +121,16 @@ static int ath_ahb_probe(struct platform_device *pdev) sc->mem = mem; sc->irq = irq; - ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { - dev_err(&pdev->dev, "failed to initialize device\n"); + dev_err(&pdev->dev, "request_irq failed\n"); goto err_free_hw; } - ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); + ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); if (ret) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto err_detach; + dev_err(&pdev->dev, "failed to initialize device\n"); + goto err_irq; } ah = sc->sc_ah; @@ -143,8 +143,8 @@ static int ath_ahb_probe(struct platform_device *pdev) return 0; - err_detach: - ath_detach(sc); + err_irq: + free_irq(irq, sc); err_free_hw: ieee80211_free_hw(hw); platform_set_drvdata(pdev, NULL); @@ -161,8 +161,12 @@ static int ath_ahb_remove(struct platform_device *pdev) if (hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); - ath_cleanup(sc); + ath9k_deinit_device(sc); + free_irq(sc->irq, sc); + ieee80211_free_hw(sc->hw); + ath_bus_cleanup(common); platform_set_drvdata(pdev, NULL); } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f4645a45ef3c..bf3d4c4bfa52 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -544,13 +544,12 @@ extern struct ieee80211_ops ath9k_ops; extern int modparam_nohwcrypt; irqreturn_t ath_isr(int irq, void *dev); -void ath_cleanup(struct ath_softc *sc); -int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, +int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops); -void ath_detach(struct ath_softc *sc); +void ath9k_deinit_device(struct ath_softc *sc); const char *ath_mac_bb_name(u32 mac_bb_version); const char *ath_rf_name(u16 rf_version); -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); +void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, struct ath9k_channel *ichan); void ath_update_chainmask(struct ath_softc *sc, int is_ht); diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9474f9f6d400..2311fe7a0bf2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1242,7 +1242,7 @@ static void ath9k_hw_init_user_settings(struct ath_hw *ah) ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); } -void ath9k_hw_detach(struct ath_hw *ah) +void ath9k_hw_deinit(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -1260,7 +1260,7 @@ free_hw: kfree(ah); ah = NULL; } -EXPORT_SYMBOL(ath9k_hw_detach); +EXPORT_SYMBOL(ath9k_hw_deinit); /*******/ /* INI */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 8849450dc591..3f0f055ea39b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -616,7 +616,7 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) /* Initialization, Detach, Reset */ const char *ath9k_hw_probe(u16 vendorid, u16 devid); -void ath9k_hw_detach(struct ath_hw *ah); +void ath9k_hw_deinit(struct ath_hw *ah); int ath9k_hw_init(struct ath_hw *ah); int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, bool bChannelChange); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 2bea0892918e..16d1efb4b8b2 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -128,7 +128,7 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { RATE(540, 0x0c, 0), }; -static void ath9k_uninit_hw(struct ath_softc *sc); +static void ath9k_deinit_softc(struct ath_softc *sc); /* * Read and write, they both share the same lock. We do this to serialize @@ -333,67 +333,13 @@ fail: #undef DS2PHYS } -static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, - const struct ath_bus_ops *bus_ops) +static void ath9k_init_crypto(struct ath_softc *sc) { - struct ath_hw *ah = NULL; - struct ath_common *common; - int r = 0, i; - int csz = 0; - int qnum; - - /* XXX: hardware will not be ready until ath_open() being called */ - sc->sc_flags |= SC_OP_INVALID; - - spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); - spin_lock_init(&sc->sc_serial_rw); - spin_lock_init(&sc->sc_pm_lock); - mutex_init(&sc->mutex); - tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); - tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, - (unsigned long)sc); - - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (!ah) - return -ENOMEM; - - ah->hw_version.devid = devid; - ah->hw_version.subsysid = subsysid; - sc->sc_ah = ah; - - common = ath9k_hw_common(ah); - common->ops = &ath9k_common_ops; - common->bus_ops = bus_ops; - common->ah = ah; - common->hw = sc->hw; - common->priv = sc; - common->debug_mask = ath9k_debug; - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(common, &csz); - /* XXX assert csz is non-zero */ - common->cachelsz = csz << 2; /* convert to bytes */ - - r = ath9k_hw_init(ah); - if (r) { - ath_print(common, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", r); - goto bad_free_hw; - } - - if (ath9k_init_debug(ah) < 0) { - ath_print(common, ATH_DBG_FATAL, - "Unable to create debugfs files\n"); - goto bad_free_hw; - } + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int i = 0; /* Get the hardware key cache size. */ - common->keymax = ah->caps.keycache_size; + common->keymax = sc->sc_ah->caps.keycache_size; if (common->keymax > ATH_KEYMAX) { ath_print(common, ATH_DBG_ANY, "Warning, using only %u entries in %u key cache\n", @@ -406,185 +352,273 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, * reset the contents on initial power up. */ for (i = 0; i < common->keymax; i++) - ath9k_hw_keyreset(ah, (u16) i); + ath9k_hw_keyreset(sc->sc_ah, (u16) i); - /* default to MONITOR mode */ - sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; + if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL)) { + /* + * Whether we should enable h/w TKIP MIC. + * XXX: if we don't support WME TKIP MIC, then we wouldn't + * report WMM capable, so it's always safe to turn on + * TKIP MIC in this case. + */ + ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, 0, 1, NULL); + } /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that the hal handles reseting - * these queues at the needed time. + * Check whether the separate key cache entries + * are required to handle both tx+rx MIC keys. + * With split mic keys the number of stations is limited + * to 27 otherwise 59. */ - sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); + if (ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_TKIP, NULL) + && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_CIPHER, + ATH9K_CIPHER_MIC, NULL) + && ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_TKIP_SPLIT, + 0, NULL)) + common->splitmic = 1; + + /* turn on mcast key search if possible */ + if (!ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) + (void)ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_MCAST_KEYSRCH, + 1, 1, NULL); + +} + +static int ath9k_init_btcoex(struct ath_softc *sc) +{ + int r, qnum; + + switch (sc->sc_ah->btcoex_hw.scheme) { + case ATH_BTCOEX_CFG_NONE: + break; + case ATH_BTCOEX_CFG_2WIRE: + ath9k_hw_btcoex_init_2wire(sc->sc_ah); + break; + case ATH_BTCOEX_CFG_3WIRE: + ath9k_hw_btcoex_init_3wire(sc->sc_ah); + r = ath_init_btcoex_timer(sc); + if (r) + return -1; + qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); + ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); + sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; + break; + default: + WARN_ON(1); + break; + } + + return 0; +} + +static int ath9k_init_queues(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int i = 0; + + for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) + sc->tx.hwq_map[i] = -1; + + sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); if (sc->beacon.beaconq == -1) { ath_print(common, ATH_DBG_FATAL, "Unable to setup a beacon xmit queue\n"); - r = -EIO; - goto bad2; + goto err; } + sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); if (sc->beacon.cabq == NULL) { ath_print(common, ATH_DBG_FATAL, "Unable to setup CAB xmit queue\n"); - r = -EIO; - goto bad2; + goto err; } sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - - /* Setup data queues */ - /* NB: ensure BK queue is the lowest priority h/w queue */ if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BK traffic\n"); - r = -EIO; - goto bad2; + goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BE traffic\n"); - r = -EIO; - goto bad2; + goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VI traffic\n"); - r = -EIO; - goto bad2; + goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VO traffic\n"); - r = -EIO; - goto bad2; + goto err; } - /* Initializes the noise floor to a reasonable default value. - * Later on this will be updated during ANI processing. */ + return 0; - common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; - setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); +err: + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, - 0, 1, NULL); + return -EIO; +} + +static void ath9k_init_channels_rates(struct ath_softc *sc) +{ + if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; + sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + sc->sbands[IEEE80211_BAND_2GHZ].n_channels = + ARRAY_SIZE(ath9k_2ghz_chantable); + sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; + sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates); } - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - common->splitmic = 1; + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { + sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; + sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; + sc->sbands[IEEE80211_BAND_5GHZ].n_channels = + ARRAY_SIZE(ath9k_5ghz_chantable); + sc->sbands[IEEE80211_BAND_5GHZ].bitrates = + ath9k_legacy_rates + 4; + sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = + ARRAY_SIZE(ath9k_legacy_rates) - 4; + } +} - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, - 1, NULL); +static void ath9k_init_misc(struct ath_softc *sc) +{ + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + int i = 0; + + common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; + setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); sc->config.txpowlimit = ATH_TXPOWER_MAX; - /* 11n Capabilities */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { sc->sc_flags |= SC_OP_TXAGGR; sc->sc_flags |= SC_OP_RXAGGR; } - common->tx_chainmask = ah->caps.tx_chainmask; - common->rx_chainmask = ah->caps.rx_chainmask; + common->tx_chainmask = sc->sc_ah->caps.tx_chainmask; + common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; - ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); - sc->rx.defant = ath9k_hw_getdefantenna(ah); + ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); + sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); - sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ + sc->beacon.slottime = ATH9K_SLOT_TIME_9; - /* initialize beacon slots */ for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { sc->beacon.bslot[i] = NULL; sc->beacon.bslot_aphy[i] = NULL; } +} - /* setup channels and rates */ +static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, + const struct ath_bus_ops *bus_ops) +{ + struct ath_hw *ah = NULL; + struct ath_common *common; + int ret = 0, i; + int csz = 0; - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_chantable); - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; - sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = - ARRAY_SIZE(ath9k_legacy_rates); - } + sc->sc_flags |= SC_OP_INVALID; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; - sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels = - ARRAY_SIZE(ath9k_5ghz_chantable); - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - ath9k_legacy_rates + 4; - sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = - ARRAY_SIZE(ath9k_legacy_rates) - 4; + ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); + if (!ah) + return -ENOMEM; + + ah->hw_version.devid = devid; + ah->hw_version.subsysid = subsysid; + sc->sc_ah = ah; + + common = ath9k_hw_common(ah); + common->ops = &ath9k_common_ops; + common->bus_ops = bus_ops; + common->ah = ah; + common->hw = sc->hw; + common->priv = sc; + common->debug_mask = ath9k_debug; + + spin_lock_init(&sc->wiphy_lock); + spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); + spin_lock_init(&sc->sc_pm_lock); + mutex_init(&sc->mutex); + tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); + tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, + (unsigned long)sc); + + /* + * Cache line size is used to size and align various + * structures used to communicate with the hardware. + */ + ath_read_cachesize(common, &csz); + common->cachelsz = csz << 2; /* convert to bytes */ + + ret = ath9k_hw_init(ah); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to initialize hardware; " + "initialization status: %d\n", ret); + goto err_hw; } - switch (ah->btcoex_hw.scheme) { - case ATH_BTCOEX_CFG_NONE: - break; - case ATH_BTCOEX_CFG_2WIRE: - ath9k_hw_btcoex_init_2wire(ah); - break; - case ATH_BTCOEX_CFG_3WIRE: - ath9k_hw_btcoex_init_3wire(ah); - r = ath_init_btcoex_timer(sc); - if (r) - goto bad2; - qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - ath9k_hw_init_btcoex_hw(ah, qnum); - sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; - break; - default: - WARN_ON(1); - break; + ret = ath9k_init_debug(ah); + if (ret) { + ath_print(common, ATH_DBG_FATAL, + "Unable to create debugfs files\n"); + goto err_debug; } + ret = ath9k_init_queues(sc); + if (ret) + goto err_queues; + + ret = ath9k_init_btcoex(sc); + if (ret) + goto err_btcoex; + + ath9k_init_crypto(sc); + ath9k_init_channels_rates(sc); + ath9k_init_misc(sc); + return 0; -bad2: - /* cleanup tx queues */ + +err_btcoex: for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); +err_queues: + ath9k_exit_debug(ah); +err_debug: + ath9k_hw_deinit(ah); +err_hw: + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); -bad_free_hw: - ath9k_uninit_hw(sc); - return r; + kfree(ah); + sc->sc_ah = NULL; + + return ret; } -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) +void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | @@ -621,85 +655,85 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); + if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); + } + + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); } -/* Device driver core initialization */ -int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, +int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; struct ath_common *common; struct ath_hw *ah; - int error = 0, i; + int error = 0; struct ath_regulatory *reg; - dev_dbg(sc->dev, "Attach ATH hw\n"); - - error = ath_init_softc(devid, sc, subsysid, bus_ops); + /* Bring up device */ + error = ath9k_init_softc(devid, sc, subsysid, bus_ops); if (error != 0) - return error; + goto error_init; ah = sc->sc_ah; common = ath9k_hw_common(ah); + ath9k_set_hw_capab(sc, hw); - /* get mac address from hardware and set in mac80211 */ - - SET_IEEE80211_PERM_ADDR(hw, common->macaddr); - - ath_set_hw_capab(sc, hw); - + /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); if (error) - return error; + goto error_regd; reg = &common->regulatory; - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) - setup_ht_cap(sc, - &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) - setup_ht_cap(sc, - &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - } - - /* initialize tx/rx engine */ + /* Setup TX DMA */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) - goto error_attach; + goto error_tx; + /* Setup RX DMA */ error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) - goto error_attach; - - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); - INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(500); + goto error_rx; + /* Register with mac80211 */ error = ieee80211_register_hw(hw); + if (error) + goto error_register; + /* Handle world regulatory */ if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) - goto error_attach; + goto error_world; } - /* Initialize LED control */ - ath_init_leds(sc); + INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); + INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); + sc->wiphy_scheduler_int = msecs_to_jiffies(500); + ath_init_leds(sc); ath_start_rfkill_poll(sc); return 0; -error_attach: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - ath9k_uninit_hw(sc); - +error_world: + ieee80211_unregister_hw(hw); +error_register: + ath_rx_cleanup(sc); +error_rx: + ath_tx_cleanup(sc); +error_tx: + /* Nothing */ +error_regd: + ath9k_deinit_softc(sc); +error_init: return error; } @@ -707,29 +741,34 @@ error_attach: /* De-Initialization */ /*****************************/ -static void ath9k_uninit_hw(struct ath_softc *sc) +static void ath9k_deinit_softc(struct ath_softc *sc) { - struct ath_hw *ah = sc->sc_ah; + int i = 0; - BUG_ON(!ah); + if ((sc->btcoex.no_stomp_timer) && + sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) + ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); - ath9k_exit_debug(ah); - ath9k_hw_detach(ah); - sc->sc_ah = NULL; + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) + ath_tx_cleanupq(sc, &sc->tx.txq[i]); + + ath9k_exit_debug(sc->sc_ah); + ath9k_hw_deinit(sc->sc_ah); + + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); } -static void ath_clean_core(struct ath_softc *sc) +void ath9k_deinit_device(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; - struct ath_hw *ah = sc->sc_ah; int i = 0; ath9k_ps_wakeup(sc); - dev_dbg(sc->dev, "Detach ATH hw\n"); - - ath_deinit_leds(sc); wiphy_rfkill_stop_polling(sc->hw->wiphy); + ath_deinit_leds(sc); for (i = 0; i < sc->num_sec_wiphy; i++) { struct ath_wiphy *aphy = sc->sec_wiphy[i]; @@ -739,24 +778,12 @@ static void ath_clean_core(struct ath_softc *sc) ieee80211_unregister_hw(aphy->hw); ieee80211_free_hw(aphy->hw); } + kfree(sc->sec_wiphy); + ieee80211_unregister_hw(hw); ath_rx_cleanup(sc); ath_tx_cleanup(sc); - - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - - if (!(sc->sc_flags & SC_OP_INVALID)) - ath9k_setpower(sc, ATH9K_PM_AWAKE); - - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - if ((sc->btcoex.no_stomp_timer) && - ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) - ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); + ath9k_deinit_softc(sc); } void ath_descdma_cleanup(struct ath_softc *sc, @@ -771,26 +798,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, memset(dd, 0, sizeof(*dd)); } -void ath_detach(struct ath_softc *sc) -{ - ath_clean_core(sc); - ath9k_uninit_hw(sc); -} - -void ath_cleanup(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - - ath_clean_core(sc); - free_irq(sc->irq, sc); - ath_bus_cleanup(common); - kfree(sc->sec_wiphy); - ieee80211_free_hw(sc->hw); - - ath9k_uninit_hw(sc); -} - /************************/ /* Module Hooks */ /************************/ diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index f7af5ea54753..95b9a07597ef 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -113,25 +113,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) u16 subsysid; u32 val; int ret = 0; - struct ath_hw *ah; char hw_name[64]; if (pci_enable_device(pdev)) return -EIO; ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); - goto bad; + goto err_dma; } ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { printk(KERN_ERR "ath9k: 32-bit DMA consistent " "DMA enable failed\n"); - goto bad; + goto err_dma; } /* @@ -171,22 +168,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) { dev_err(&pdev->dev, "PCI memory region reserve error\n"); ret = -ENODEV; - goto bad; + goto err_region; } mem = pci_iomap(pdev, 0, 0); if (!mem) { printk(KERN_ERR "PCI memory map error\n") ; ret = -EIO; - goto bad1; + goto err_iomap; } hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + sizeof(struct ath_softc), &ath9k_ops); if (!hw) { - dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); + dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); ret = -ENOMEM; - goto bad2; + goto err_alloc_hw; } SET_IEEE80211_DEV(hw, &pdev->dev); @@ -201,25 +198,22 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->dev = &pdev->dev; sc->mem = mem; - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); - ret = ath_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); - if (ret) { - dev_err(&pdev->dev, "failed to initialize device\n"); - goto bad3; - } - - /* setup interrupt service routine */ - ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { dev_err(&pdev->dev, "request_irq failed\n"); - goto bad4; + goto err_irq; } sc->irq = pdev->irq; - ah = sc->sc_ah; - ath9k_hw_name(ah, hw_name, sizeof(hw_name)); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); + ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); + if (ret) { + dev_err(&pdev->dev, "Failed to initialize device\n"); + goto err_init; + } + + ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name)); printk(KERN_INFO "%s: %s mem=0x%lx, irq=%d\n", wiphy_name(hw->wiphy), @@ -227,15 +221,18 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) (unsigned long)mem, pdev->irq); return 0; -bad4: - ath_detach(sc); -bad3: + +err_init: + free_irq(sc->irq, sc); +err_irq: ieee80211_free_hw(hw); -bad2: +err_alloc_hw: pci_iounmap(pdev, mem); -bad1: +err_iomap: pci_release_region(pdev, 0); -bad: +err_region: + /* Nothing */ +err_dma: pci_disable_device(pdev); return ret; } @@ -245,8 +242,12 @@ static void ath_pci_remove(struct pci_dev *pdev) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); - ath_cleanup(sc); + ath9k_deinit_device(sc); + free_irq(sc->irq, sc); + ieee80211_free_hw(sc->hw); + ath_bus_cleanup(common); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index cd26caaf44e7..a43fbf84dab9 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c @@ -152,7 +152,7 @@ int ath9k_wiphy_add(struct ath_softc *sc) SET_IEEE80211_PERM_ADDR(hw, addr); - ath_set_hw_capab(sc, hw); + ath9k_set_hw_capab(sc, hw); error = ieee80211_register_hw(hw); -- cgit v1.2.3 From cc9c378aa57817003a094e4bb9a953337ebf035a Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:09 +0530 Subject: ath9k: Fix queue handling The TX queues have to be stopped during an internal reset. Not handling this would result in packet loss - fix this. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 974de2056b4a..1f7222aef89f 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -944,6 +944,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Stop ANI */ del_timer_sync(&common->ani.timer); + ieee80211_stop_queues(hw); + ath9k_hw_set_interrupts(ah, 0); ath_drain_all_txq(sc, retry_tx); ath_stoprecv(sc); @@ -985,6 +987,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) } } + ieee80211_wake_queues(hw); + /* Start ANI */ ath_start_ani(common); -- cgit v1.2.3 From 1395d3f00a4164caae168b041855d48e0fa9ea4c Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:11 +0530 Subject: ath9k: Add debugfs file for RX errors This file can be used to track frame reception errors. PHY error counts are also added. Location: ath9k/phy#/recv Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 118 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath9k/debug.h | 32 +++++++++ drivers/net/wireless/ath/ath9k/mac.h | 34 ++++++++++ drivers/net/wireless/ath/ath9k/recv.c | 2 + 4 files changed, 186 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 592f1b70f55a..9489b6b25b5f 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -580,6 +580,116 @@ static const struct file_operations fops_xmit = { .owner = THIS_MODULE }; +static ssize_t read_file_recv(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PHY_ERR(s, p) \ + len += snprintf(buf + len, size - len, "%18s : %10u\n", s, \ + sc->debug.stats.rxstats.phy_err_stats[p]); + + struct ath_softc *sc = file->private_data; + char *buf; + unsigned int len = 0, size = 1152; + ssize_t retval = 0; + + buf = kzalloc(size, GFP_KERNEL); + if (buf == NULL) + return 0; + + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "CRC ERR", + sc->debug.stats.rxstats.crc_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "DECRYPT CRC ERR", + sc->debug.stats.rxstats.decrypt_crc_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "PHY ERR", + sc->debug.stats.rxstats.phy_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "MIC ERR", + sc->debug.stats.rxstats.mic_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "PRE-DELIM CRC ERR", + sc->debug.stats.rxstats.pre_delim_crc_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "POST-DELIM CRC ERR", + sc->debug.stats.rxstats.post_delim_crc_err); + len += snprintf(buf + len, size - len, + "%18s : %10u\n", "DECRYPT BUSY ERR", + sc->debug.stats.rxstats.decrypt_busy_err); + + PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); + PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); + PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); + PHY_ERR("RATE", ATH9K_PHYERR_RATE); + PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); + PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); + PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); + PHY_ERR("TOR", ATH9K_PHYERR_TOR); + PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); + PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); + PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); + PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); + PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); + PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); + PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); + PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); + PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); + PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); + PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); + PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); + PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); + PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); + PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); + PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); + PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); + PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; + +#undef PHY_ERR +} + +void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) +{ +#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ +#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ + + struct ath_desc *ds = bf->bf_desc; + u32 phyerr; + + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) + RX_STAT_INC(crc_err); + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) + RX_STAT_INC(decrypt_crc_err); + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) + RX_STAT_INC(mic_err); + if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) + RX_STAT_INC(pre_delim_crc_err); + if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) + RX_STAT_INC(post_delim_crc_err); + if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) + RX_STAT_INC(decrypt_busy_err); + + if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { + RX_STAT_INC(phy_err); + phyerr = ds->ds_rxstat.rs_phyerr & 0x24; + RX_PHY_ERR_INC(phyerr); + } + +#undef RX_STAT_INC +#undef RX_PHY_ERR_INC +} + +static const struct file_operations fops_recv = { + .read = read_file_recv, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); @@ -632,6 +742,13 @@ int ath9k_init_debug(struct ath_hw *ah) if (!sc->debug.debugfs_xmit) goto err; + sc->debug.debugfs_recv = debugfs_create_file("recv", + S_IRUSR, + sc->debug.debugfs_phy, + sc, &fops_recv); + if (!sc->debug.debugfs_recv) + goto err; + return 0; err: ath9k_exit_debug(ah); @@ -643,6 +760,7 @@ void ath9k_exit_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; + debugfs_remove(sc->debug.debugfs_recv); debugfs_remove(sc->debug.debugfs_xmit); debugfs_remove(sc->debug.debugfs_wiphy); debugfs_remove(sc->debug.debugfs_rcstat); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 536663e3ee11..86780e68b31e 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -116,10 +116,35 @@ struct ath_tx_stats { u32 delim_underrun; }; +/** + * struct ath_rx_stats - RX Statistics + * @crc_err: No. of frames with incorrect CRC value + * @decrypt_crc_err: No. of frames whose CRC check failed after + decryption process completed + * @phy_err: No. of frames whose reception failed because the PHY + encountered an error + * @mic_err: No. of frames with incorrect TKIP MIC verification failure + * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections + * @post_delim_crc_err: Post-Frame delimiter CRC error detections + * @decrypt_busy_err: Decryption interruptions counter + * @phy_err_stats: Individual PHY error statistics + */ +struct ath_rx_stats { + u32 crc_err; + u32 decrypt_crc_err; + u32 phy_err; + u32 mic_err; + u32 pre_delim_crc_err; + u32 post_delim_crc_err; + u32 decrypt_busy_err; + u32 phy_err_stats[ATH9K_PHYERR_MAX]; +}; + struct ath_stats { struct ath_interrupt_stats istats; struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; + struct ath_rx_stats rxstats; }; struct ath9k_debug { @@ -130,6 +155,7 @@ struct ath9k_debug { struct dentry *debugfs_rcstat; struct dentry *debugfs_wiphy; struct dentry *debugfs_xmit; + struct dentry *debugfs_recv; struct ath_stats stats; }; @@ -142,6 +168,7 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf); +void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); void ath_debug_stat_retries(struct ath_softc *sc, int rix, int xretries, int retries, u8 per); @@ -181,6 +208,11 @@ static inline void ath_debug_stat_tx(struct ath_softc *sc, { } +static inline void ath_debug_stat_rx(struct ath_softc *sc, + struct ath_buf *bf) +{ +} + static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, int xretries, int retries, u8 per) { diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e185479e295e..29851e6376a9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -167,6 +167,40 @@ struct ath_rx_status { #define ATH9K_RXKEYIX_INVALID ((u8)-1) #define ATH9K_TXKEYIX_INVALID ((u32)-1) +enum ath9k_phyerr { + ATH9K_PHYERR_UNDERRUN = 0, /* Transmit underrun */ + ATH9K_PHYERR_TIMING = 1, /* Timing error */ + ATH9K_PHYERR_PARITY = 2, /* Illegal parity */ + ATH9K_PHYERR_RATE = 3, /* Illegal rate */ + ATH9K_PHYERR_LENGTH = 4, /* Illegal length */ + ATH9K_PHYERR_RADAR = 5, /* Radar detect */ + ATH9K_PHYERR_SERVICE = 6, /* Illegal service */ + ATH9K_PHYERR_TOR = 7, /* Transmit override receive */ + + ATH9K_PHYERR_OFDM_TIMING = 17, + ATH9K_PHYERR_OFDM_SIGNAL_PARITY = 18, + ATH9K_PHYERR_OFDM_RATE_ILLEGAL = 19, + ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL = 20, + ATH9K_PHYERR_OFDM_POWER_DROP = 21, + ATH9K_PHYERR_OFDM_SERVICE = 22, + ATH9K_PHYERR_OFDM_RESTART = 23, + ATH9K_PHYERR_FALSE_RADAR_EXT = 24, + + ATH9K_PHYERR_CCK_TIMING = 25, + ATH9K_PHYERR_CCK_HEADER_CRC = 26, + ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, + ATH9K_PHYERR_CCK_SERVICE = 30, + ATH9K_PHYERR_CCK_RESTART = 31, + ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, + ATH9K_PHYERR_CCK_POWER_DROP = 33, + + ATH9K_PHYERR_HT_CRC_ERROR = 34, + ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, + ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, + + ATH9K_PHYERR_MAX = 37, +}; + struct ath_desc { u32 ds_link; u32 ds_data; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 17b0a6dd8caf..40b5d05edcce 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -571,6 +571,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) hw = ath_get_virt_hw(sc, hdr); rx_stats = &ds->ds_rxstat; + ath_debug_stat_rx(sc, bf); + /* * If we're asked to flush receive queue, directly * chain it back at the queue without processing it. -- cgit v1.2.3 From 199afd9d89b18e8b530734ed73788518e19bed9b Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 8 Jan 2010 10:36:13 +0530 Subject: ath9k: Fix monitor mode handling mac80211 passes appropriate flags indicating whether monitor mode is being used. Use this to set the HW opmode. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1f7222aef89f..b39c7bc41143 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1581,6 +1581,14 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) } } + if (changed & IEEE80211_CONF_CHANGE_MONITOR) { + if (conf->flags & IEEE80211_CONF_MONITOR) { + ath_print(common, ATH_DBG_CONFIG, + "HW opmode set to Monitor mode\n"); + sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; + } + } + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; -- cgit v1.2.3 From d524215f6cad245249df8def19125ae6fd0bcc9b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Jan 2010 18:06:26 +0100 Subject: mac80211: use nullfunc frames for 4-addr sta detection To detect incoming 4-addr stations, hostapd needs to receive a 4-addr data frame from the remote station, so that it can create the AP VLAN for it. With this patch, the mlme code emits a 4-addr nullfunc frame immediately after assoc. On the AP side it also drops 4-addr nullfunc frames to the cooked monitor mode interface, if the interface hasn't been fully set up to receive 4-addr data frames yet. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 39 +++++++++++++++++++++++++++++++++++++++ net/mac80211/rx.c | 12 ++++++++++++ 2 files changed, 51 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5484cf930a87..0336dbb45ac5 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -282,6 +282,38 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, ieee80211_tx_skb(sdata, skb); } +static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + struct sk_buff *skb; + struct ieee80211_hdr *nullfunc; + __le16 fc; + + if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) + return; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr " + "nullfunc frame\n", sdata->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); + memset(nullfunc, 0, 30); + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); + nullfunc->frame_control = fc; + memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); + memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); + memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN); + + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + ieee80211_tx_skb(sdata, skb); +} + /* spectrum management related things */ static void ieee80211_chswitch_work(struct work_struct *work) { @@ -1089,6 +1121,13 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, bss_conf->assoc_capability = capab_info; ieee80211_set_associated(sdata, cbss, changed); + /* + * If we're using 4-addr mode, let the AP know that we're + * doing so, so that it can create the STA VLAN on its side + */ + if (ifmgd->use_4addr) + ieee80211_send_4addr_nullfunc(local, sdata); + /* * Start timer to probe the connection to the AP now. * Also start the timer that will detect beacon loss. diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e12f39a96460..efa6d3689c5e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1111,6 +1111,18 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) if (ieee80211_is_nullfunc(hdr->frame_control) || ieee80211_is_qos_nullfunc(hdr->frame_control)) { I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); + + /* + * If we receive a 4-addr nullfunc frame from a STA + * that was not moved to a 4-addr STA vlan yet, drop + * the frame to the monitor interface, to make sure + * that hostapd sees it + */ + if (ieee80211_has_a4(hdr->frame_control) && + (rx->sdata->vif.type == NL80211_IFTYPE_AP || + (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !rx->sdata->u.vlan.sta))) + return RX_DROP_MONITOR; /* * Update counter and free packet here to avoid * counting this as a dropped packed. -- cgit v1.2.3 From 0e5ded5a87c097760abd68521b86f1025dedc7d7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Jan 2010 18:10:58 +0100 Subject: mac80211: allow station updates on ap interfaces for vlan stations Since the per-vif station changes, sta_info_get on the ap sdata no longer returns entries for stations on ap vlans. This causes issues with hostapd, which currently always passes the ap interface name to nl80211 calls. This patch provides bug compatibility with the earlier versions until hostapd is fixed. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 12 ++++++------ net/mac80211/sta_info.c | 21 +++++++++++++++++++++ net/mac80211/sta_info.h | 3 +++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e5dda6fb8dff..dc12e9466ffd 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -148,7 +148,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); if (mac_addr) { - sta = sta_info_get(sdata, mac_addr); + sta = sta_info_get_bss(sdata, mac_addr); if (!sta) { ieee80211_key_free(key); err = -ENOENT; @@ -179,7 +179,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, if (mac_addr) { ret = -ENOENT; - sta = sta_info_get(sdata, mac_addr); + sta = sta_info_get_bss(sdata, mac_addr); if (!sta) goto out_unlock; @@ -226,7 +226,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); if (mac_addr) { - sta = sta_info_get(sdata, mac_addr); + sta = sta_info_get_bss(sdata, mac_addr); if (!sta) goto out; @@ -419,7 +419,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, rcu_read_lock(); - sta = sta_info_get(sdata, mac); + sta = sta_info_get_bss(sdata, mac); if (sta) { ret = 0; sta_set_sinfo(sta, sinfo); @@ -775,7 +775,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, if (mac) { rcu_read_lock(); - sta = sta_info_get(sdata, mac); + sta = sta_info_get_bss(sdata, mac); if (!sta) { rcu_read_unlock(); return -ENOENT; @@ -803,7 +803,7 @@ static int ieee80211_change_station(struct wiphy *wiphy, rcu_read_lock(); - sta = sta_info_get(sdata, mac); + sta = sta_info_get_bss(sdata, mac); if (!sta) { rcu_read_unlock(); return -ENOENT; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 47da552ce8a6..f735826f055c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -119,6 +119,27 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, return sta; } +/* + * Get sta info either from the specified interface + * or from one of its vlans + */ +struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr) +{ + struct ieee80211_local *local = sdata->local; + struct sta_info *sta; + + sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); + while (sta) { + if ((sta->sdata == sdata || + sta->sdata->bss == sdata->bss) && + memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) + break; + sta = rcu_dereference(sta->hnext); + } + return sta; +} + struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, int idx) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index c8208236e896..6f79bba5706e 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -408,6 +408,9 @@ static inline u32 get_sta_flags(struct sta_info *sta) struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); +struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr); + static inline void for_each_sta_info_type_check(struct ieee80211_local *local, const u8 *addr, -- cgit v1.2.3 From 3f0e0b220f80075ce15483b20458192c0ac27426 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Jan 2010 18:15:13 +0100 Subject: mac80211: do not transmit frames on unconfigured 4-addr vlan interfaces If frames are transmitted on 4-addr ap vlan interfaces with no station, they end up being transmitted unencrypted, even if the ap interface uses WPA. This patch add some sanity checking to make sure that this does not happen. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0661e696a1dd..47ca59e52e71 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1056,8 +1056,11 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, hdr = (struct ieee80211_hdr *) skb->data; - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { tx->sta = rcu_dereference(sdata->u.vlan.sta); + if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) + return TX_DROP; + } if (!tx->sta) tx->sta = sta_info_get(sdata, hdr->addr1); -- cgit v1.2.3 From c2c2b12a8b6cd23d4abbc086642647c656bf406c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:27:59 +0100 Subject: mwl8k: minor cleanups Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a04863633d1a..cc160418e6c5 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -208,10 +208,7 @@ struct mwl8k_priv { /* Per interface specific private data */ struct mwl8k_vif { - /* Local MAC address. */ - u8 mac_addr[ETH_ALEN]; - - /* Non AMPDU sequence number assigned by driver */ + /* Non AMPDU sequence number assigned by driver. */ u16 seqno; }; #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) @@ -2287,8 +2284,8 @@ struct mwl8k_cmd_set_rts_threshold { __le16 threshold; } __attribute__((packed)); -static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, - u16 action, u16 threshold) +static int +mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh) { struct mwl8k_cmd_set_rts_threshold *cmd; int rc; @@ -2299,8 +2296,8 @@ static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(action); - cmd->threshold = cpu_to_le16(threshold); + cmd->action = cpu_to_le16(MWL8K_CMD_SET); + cmd->threshold = cpu_to_le16(rts_thresh); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -2955,14 +2952,13 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, return -EINVAL; } + /* Set the mac address. */ + mwl8k_cmd_set_mac_addr(hw, vif->addr); + /* Clean out driver private area */ mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); - /* Set and save the mac address */ - mwl8k_cmd_set_mac_addr(hw, vif->addr); - memcpy(mwl8k_vif->mac_addr, vif->addr, ETH_ALEN); - /* Set Initial sequence number to zero */ mwl8k_vif->seqno = 0; @@ -2977,9 +2973,6 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, { struct mwl8k_priv *priv = hw->priv; - if (priv->vif == NULL) - return; - mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); priv->vif = NULL; @@ -3252,7 +3245,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { - return mwl8k_cmd_set_rts_threshold(hw, MWL8K_CMD_SET, value); + return mwl8k_cmd_set_rts_threshold(hw, value); } struct mwl8k_sta_notify_item @@ -3669,7 +3662,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* * Temporarily enable interrupts. Initial firmware host - * commands use interrupts and avoids polling. Disable + * commands use interrupts and avoid polling. Disable * interrupts when done. */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); -- cgit v1.2.3 From b569e924a9ea7c6f03dcf9b8a98d78d341925b87 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:28:14 +0100 Subject: mwl8k: undo transmit queue 0/1 swapping in mwl8k_cmd_set_edca_params() The comment and code in mwl8k_cmd_set_edca_params() suggest that the mapping between SET_EDCA_PARAMS queue numbers and transmit rings isn't actually 1:1, while tests show that the mapping is in fact 1:1. So, get rid of the transmit queue 0/1 swapping. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index cc160418e6c5..3f5fdb69a2be 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2397,12 +2397,6 @@ mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, if (cmd == NULL) return -ENOMEM; - /* - * Queues 0 (BE) and 1 (BK) are swapped in hardware for - * this call. - */ - qnum ^= !(qnum >> 1); - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); -- cgit v1.2.3 From 62abd3cfb2f1a0ab1963ac4c4087c477da6b1f2a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:28:34 +0100 Subject: mwl8k: bump the transmit wait timeout to 5 seconds While it is reasonable to expect that at least one transmit ring entry will be processed per second while we are waiting for the transmit rings to drain, the firmware can end up doing batching of transmit ring status writeback, which means that the transmit rings can appear stuck for more than a second at a time. Bump the TX drain wait timeout up from 1 to 5 seconds to account for this. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 3f5fdb69a2be..8f5f7c9f75f7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1173,7 +1173,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) /* * Must be called with priv->fw_mutex held and tx queues stopped. */ -#define MWL8K_TX_WAIT_TIMEOUT_MS 1000 +#define MWL8K_TX_WAIT_TIMEOUT_MS 5000 static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) { -- cgit v1.2.3 From b71ed2c6ce8b5c3782ed70d67dc9adbd7ed07684 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:30:16 +0100 Subject: mwl8k: simplify mwl8k_cmd_use_fixed_rate() As we always use the auto rate adaptation feature and never pass in a rate table, USE_FIXED_RATE can be simplified somewhat. While we're at it, rename it to *_sta, as this is the STA version of the command. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 88 +++++++++++--------------------------------- 1 file changed, 22 insertions(+), 66 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8f5f7c9f75f7..20e7cf2e266c 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2482,49 +2482,30 @@ static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) } /* - * CMD_USE_FIXED_RATE. + * CMD_USE_FIXED_RATE (STA version). */ -#define MWL8K_RATE_TABLE_SIZE 8 -#define MWL8K_UCAST_RATE 0 -#define MWL8K_USE_AUTO_RATE 0x0002 - -struct mwl8k_rate_entry { - /* Set to 1 if HT rate, 0 if legacy. */ - __le32 is_ht_rate; - - /* Set to 1 to use retry_count field. */ - __le32 enable_retry; - - /* Specified legacy rate or MCS. */ - __le32 rate; - - /* Number of allowed retries. */ - __le32 retry_count; -} __attribute__((packed)); - -struct mwl8k_rate_table { - /* 1 to allow specified rate and below */ - __le32 allow_rate_drop; - __le32 num_rates; - struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE]; +struct mwl8k_cmd_use_fixed_rate_sta { + struct mwl8k_cmd_pkt header; + __le32 action; + __le32 allow_rate_drop; + __le32 num_rates; + struct { + __le32 is_ht_rate; + __le32 enable_retry; + __le32 rate; + __le32 retry_count; + } rate_entry[8]; + __le32 rate_type; + __le32 reserved1; + __le32 reserved2; } __attribute__((packed)); -struct mwl8k_cmd_use_fixed_rate { - struct mwl8k_cmd_pkt header; - __le32 action; - struct mwl8k_rate_table rate_table; - - /* Unicast, Broadcast or Multicast */ - __le32 rate_type; - __le32 reserved1; - __le32 reserved2; -} __attribute__((packed)); +#define MWL8K_USE_AUTO_RATE 0x0002 +#define MWL8K_UCAST_RATE 0 -static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, - u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table) +static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw) { - struct mwl8k_cmd_use_fixed_rate *cmd; - int count; + struct mwl8k_cmd_use_fixed_rate_sta *cmd; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2533,32 +2514,8 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(action); - cmd->rate_type = cpu_to_le32(rate_type); - - if (rate_table != NULL) { - /* - * Copy over each field manually so that endian - * conversion can be done. - */ - cmd->rate_table.allow_rate_drop = - cpu_to_le32(rate_table->allow_rate_drop); - cmd->rate_table.num_rates = - cpu_to_le32(rate_table->num_rates); - - for (count = 0; count < rate_table->num_rates; count++) { - struct mwl8k_rate_entry *dst = - &cmd->rate_table.rate_entry[count]; - struct mwl8k_rate_entry *src = - &rate_table->rate_entry[count]; - - dst->is_ht_rate = cpu_to_le32(src->is_ht_rate); - dst->enable_retry = cpu_to_le32(src->enable_retry); - dst->rate = cpu_to_le32(src->rate); - dst->retry_count = cpu_to_le32(src->retry_count); - } - } + cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); + cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE); rc = mwl8k_post_cmd(hw, &cmd->header); kfree(cmd); @@ -3062,8 +3019,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, if (rc) goto out; - rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, - MWL8K_UCAST_RATE, NULL); + rc = mwl8k_cmd_use_fixed_rate_sta(hw); if (rc) goto out; } -- cgit v1.2.3 From 088aab8b62666a002907c912cd346ae6dc9f42b7 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:30:36 +0100 Subject: mwl8k: add the AP version of USE_FIXED_RATE As with the STA version, unicast will use auto rate adaptation, but the AP version allows setting the rates to be used for management and multicast transmissions, which can be set based on the BSS basic rate set. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 20e7cf2e266c..ec79033801ab 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2523,6 +2523,47 @@ static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw) return rc; } +/* + * CMD_USE_FIXED_RATE (AP version). + */ +struct mwl8k_cmd_use_fixed_rate_ap { + struct mwl8k_cmd_pkt header; + __le32 action; + __le32 allow_rate_drop; + __le32 num_rates; + struct mwl8k_rate_entry_ap { + __le32 is_ht_rate; + __le32 enable_retry; + __le32 rate; + __le32 retry_count; + } rate_entry[4]; + u8 multicast_rate; + u8 multicast_rate_type; + u8 management_rate; +} __attribute__((packed)); + +static int +mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt) +{ + struct mwl8k_cmd_use_fixed_rate_ap *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE); + cmd->multicast_rate = mcast; + cmd->management_rate = mgmt; + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + /* * CMD_ENABLE_SNIFFER. */ -- cgit v1.2.3 From 3f5610ff560aeaccf051a6f93f25535c219599a0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:30:58 +0100 Subject: mwl8k: implement AP firmware station database maintenance STA firmware uses UPDATE_STADB to manipulate the hardware station database, whereas AP firmware uses SET_NEW_STN -- this implements the latter, and hooks it into mwl8k_sta_notify(), to be used if we're running on AP firmware. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 134 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ec79033801ab..f0026f33232d 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -281,6 +281,7 @@ static const struct ieee80211_rate mwl8k_rates[] = { #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 #define MWL8K_CMD_SET_MAC_ADDR 0x0202 #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 +#define MWL8K_CMD_SET_NEW_STN 0x1111 #define MWL8K_CMD_UPDATE_STADB 0x1123 static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) @@ -313,6 +314,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(ENABLE_SNIFFER); MWL8K_CMDNAME(SET_MAC_ADDR); MWL8K_CMDNAME(SET_RATEADAPT_MODE); + MWL8K_CMDNAME(SET_NEW_STN); MWL8K_CMDNAME(UPDATE_STADB); default: snprintf(buf, bufsize, "0x%x", cmd); @@ -2659,6 +2661,90 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) return rc; } +/* + * CMD_SET_NEW_STN. + */ +struct mwl8k_cmd_set_new_stn { + struct mwl8k_cmd_pkt header; + __le16 aid; + __u8 mac_addr[6]; + __le16 stn_id; + __le16 action; + __le16 rsvd; + __le32 legacy_rates; + __u8 ht_rates[4]; + __le16 cap_info; + __le16 ht_capabilities_info; + __u8 mac_ht_param_info; + __u8 rev; + __u8 control_channel; + __u8 add_channel; + __le16 op_mode; + __le16 stbc; + __u8 add_qos_info; + __u8 is_qos_sta; + __le32 fw_sta_ptr; +} __attribute__((packed)); + +#define MWL8K_STA_ACTION_ADD 0 +#define MWL8K_STA_ACTION_REMOVE 2 + +static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct mwl8k_cmd_set_new_stn *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->aid = cpu_to_le16(sta->aid); + memcpy(cmd->mac_addr, sta->addr, ETH_ALEN); + cmd->stn_id = cpu_to_le16(sta->aid); + cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD); + cmd->legacy_rates = cpu_to_le32(sta->supp_rates[IEEE80211_BAND_2GHZ]); + if (sta->ht_cap.ht_supported) { + cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; + cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; + cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2]; + cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3]; + cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap); + cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) | + ((sta->ht_cap.ampdu_density & 7) << 2); + cmd->is_qos_sta = 1; + } + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + +static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *addr) +{ + struct mwl8k_cmd_set_new_stn *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + memcpy(cmd->mac_addr, addr, ETH_ALEN); + cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + /* * CMD_UPDATE_STADB. */ @@ -3247,6 +3333,36 @@ struct mwl8k_sta_notify_item struct ieee80211_sta sta; }; +static void +mwl8k_do_sta_notify(struct ieee80211_hw *hw, struct mwl8k_sta_notify_item *s) +{ + struct mwl8k_priv *priv = hw->priv; + + /* + * STA firmware uses UPDATE_STADB, AP firmware uses SET_NEW_STN. + */ + if (!priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { + int rc; + + rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); + if (rc >= 0) { + struct ieee80211_sta *sta; + + rcu_read_lock(); + sta = ieee80211_find_sta(s->vif, s->sta.addr); + if (sta != NULL) + MWL8K_STA(sta)->peer_id = rc; + rcu_read_unlock(); + } + } else if (!priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { + mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); + } else if (priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { + mwl8k_cmd_set_new_stn_add(hw, s->vif, &s->sta); + } else if (priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { + mwl8k_cmd_set_new_stn_del(hw, s->vif, s->sta.addr); + } +} + static void mwl8k_sta_notify_worker(struct work_struct *work) { struct mwl8k_priv *priv = @@ -3263,23 +3379,7 @@ static void mwl8k_sta_notify_worker(struct work_struct *work) spin_unlock_bh(&priv->sta_notify_list_lock); - if (s->cmd == STA_NOTIFY_ADD) { - int rc; - - rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); - if (rc >= 0) { - struct ieee80211_sta *sta; - - rcu_read_lock(); - sta = ieee80211_find_sta(s->vif, s->sta.addr); - if (sta != NULL) - MWL8K_STA(sta)->peer_id = rc; - rcu_read_unlock(); - } - } else { - mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); - } - + mwl8k_do_sta_notify(hw, s); kfree(s); spin_lock_bh(&priv->sta_notify_list_lock); -- cgit v1.2.3 From a9e00b151ec2121b7ae09d84a2b5a68b6461e98a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:31:30 +0100 Subject: mwl8k: correctly set the mac_type field for AP SET_MAC_ADDR Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f0026f33232d..428575beb8d0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2607,6 +2607,9 @@ struct mwl8k_cmd_set_mac_addr { }; } __attribute__((packed)); +#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 +#define MWL8K_MAC_TYPE_PRIMARY_AP 2 + static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) { struct mwl8k_priv *priv = hw->priv; @@ -2620,7 +2623,7 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); cmd->header.length = cpu_to_le16(sizeof(*cmd)); if (priv->ap_fw) { - cmd->mbss.mac_type = 0; + cmd->mbss.mac_type = cpu_to_le16(MWL8K_MAC_TYPE_PRIMARY_AP); memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); } else { memcpy(cmd->mac_addr, mac, ETH_ALEN); -- cgit v1.2.3 From b64fe619e371fc17d8d686d6d44aef1b41317880 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:31:39 +0100 Subject: mwl8k: basic AP interface support Add support for creating AP interfaces, and enabling beaconing. This allows running a basic AP (11b/g mode only for now). Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 171 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 428575beb8d0..759c94fb8e77 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -266,6 +266,7 @@ static const struct ieee80211_rate mwl8k_rates[] = { #define MWL8K_CMD_RADIO_CONTROL 0x001c #define MWL8K_CMD_RF_TX_POWER 0x001e #define MWL8K_CMD_RF_ANTENNA 0x0020 +#define MWL8K_CMD_SET_BEACON 0x0100 #define MWL8K_CMD_SET_PRE_SCAN 0x0107 #define MWL8K_CMD_SET_POST_SCAN 0x0108 #define MWL8K_CMD_SET_RF_CHANNEL 0x010a @@ -281,6 +282,7 @@ static const struct ieee80211_rate mwl8k_rates[] = { #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 #define MWL8K_CMD_SET_MAC_ADDR 0x0202 #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 +#define MWL8K_CMD_BSS_START 0x1100 #define MWL8K_CMD_SET_NEW_STN 0x1111 #define MWL8K_CMD_UPDATE_STADB 0x1123 @@ -299,6 +301,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(RADIO_CONTROL); MWL8K_CMDNAME(RF_TX_POWER); MWL8K_CMDNAME(RF_ANTENNA); + MWL8K_CMDNAME(SET_BEACON); MWL8K_CMDNAME(SET_PRE_SCAN); MWL8K_CMDNAME(SET_POST_SCAN); MWL8K_CMDNAME(SET_RF_CHANNEL); @@ -314,6 +317,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) MWL8K_CMDNAME(ENABLE_SNIFFER); MWL8K_CMDNAME(SET_MAC_ADDR); MWL8K_CMDNAME(SET_RATEADAPT_MODE); + MWL8K_CMDNAME(BSS_START); MWL8K_CMDNAME(SET_NEW_STN); MWL8K_CMDNAME(UPDATE_STADB); default: @@ -1769,7 +1773,9 @@ struct mwl8k_cmd_set_hw_spec { __le32 total_rxd; } __attribute__((packed)); -#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 +#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 +#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 +#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) { @@ -1790,7 +1796,9 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); for (i = 0; i < MWL8K_TX_QUEUES; i++) cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); - cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT); + cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT | + MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP | + MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON); cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); @@ -2027,6 +2035,35 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask) return rc; } +/* + * CMD_SET_BEACON. + */ +struct mwl8k_cmd_set_beacon { + struct mwl8k_cmd_pkt header; + __le16 beacon_len; + __u8 beacon[0]; +}; + +static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, u8 *beacon, int len) +{ + struct mwl8k_cmd_set_beacon *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON); + cmd->header.length = cpu_to_le16(sizeof(*cmd) + len); + cmd->beacon_len = cpu_to_le16(len); + memcpy(cmd->beacon, beacon, len); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + /* * CMD_SET_PRE_SCAN. */ @@ -2664,6 +2701,33 @@ static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) return rc; } +/* + * CMD_BSS_START. + */ +struct mwl8k_cmd_bss_start { + struct mwl8k_cmd_pkt header; + __le32 enable; +} __attribute__((packed)); + +static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, int enable) +{ + struct mwl8k_cmd_bss_start *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + cmd->enable = cpu_to_le32(enable); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + /* * CMD_SET_NEW_STN. */ @@ -2727,6 +2791,26 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, return rc; } +static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mwl8k_cmd_set_new_stn *cmd; + int rc; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (cmd == NULL) + return -ENOMEM; + + cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN); + cmd->header.length = cpu_to_le16(sizeof(*cmd)); + memcpy(cmd->mac_addr, vif->addr, ETH_ALEN); + + rc = mwl8k_post_cmd(hw, &cmd->header); + kfree(cmd); + + return rc; +} + static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *addr) { @@ -3015,16 +3099,10 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, if (priv->vif != NULL) return -EBUSY; - /* - * We only support managed interfaces for now. - */ - if (vif->type != NL80211_IFTYPE_STATION) - return -EINVAL; - /* * Reject interface creation if sniffer mode is active, as * STA operation is mutually exclusive with hardware sniffer - * mode. + * mode. (Sniffer mode is only used on STA firmware.) */ if (priv->sniffer_enabled) { printk(KERN_INFO "%s: unable to create STA " @@ -3036,6 +3114,9 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* Set the mac address. */ mwl8k_cmd_set_mac_addr(hw, vif->addr); + if (priv->ap_fw) + mwl8k_cmd_set_new_stn_add_self(hw, vif); + /* Clean out driver private area */ mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); @@ -3054,6 +3135,9 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, { struct mwl8k_priv *priv = hw->priv; + if (priv->ap_fw) + mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); + mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); priv->vif = NULL; @@ -3105,10 +3189,9 @@ out: return rc; } -static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) +static void +mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed) { struct mwl8k_priv *priv = hw->priv; u32 ap_legacy_rates; @@ -3188,6 +3271,66 @@ out: mwl8k_fw_unlock(hw); } +static void +mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed) +{ + int rc; + + if (mwl8k_fw_lock(hw)) + return; + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + rc = mwl8k_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); + if (rc) + goto out; + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + int idx; + int rate; + + /* + * Use lowest supported basic rate for multicasts + * and management frames (such as probe responses -- + * beacons will always go out at 1 Mb/s). + */ + idx = ffs(vif->bss_conf.basic_rates); + rate = idx ? mwl8k_rates[idx - 1].hw_value : 2; + + mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate); + } + + if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { + struct sk_buff *skb; + + skb = ieee80211_beacon_get(hw, vif); + if (skb != NULL) { + mwl8k_cmd_set_beacon(hw, skb->data, skb->len); + kfree_skb(skb); + } + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + mwl8k_cmd_bss_start(hw, info->enable_beacon); + +out: + mwl8k_fw_unlock(hw); +} + +static void +mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, u32 changed) +{ + struct mwl8k_priv *priv = hw->priv; + + if (!priv->ap_fw) + mwl8k_bss_info_changed_sta(hw, vif, info, changed); + else + mwl8k_bss_info_changed_ap(hw, vif, info, changed); +} + static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, int mc_count, struct dev_addr_list *mclist) { @@ -3766,6 +3909,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_get_hw_spec_ap(hw); if (!rc) rc = mwl8k_cmd_set_hw_spec(hw); + + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP); } else { rc = mwl8k_cmd_get_hw_spec_sta(hw); -- cgit v1.2.3 From efb7c49a68cf206f35793d7799608e1d69a209f9 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:31:47 +0100 Subject: mwl8k: allow limiting the amount of transmit reclaim done Add a limit argument to mwl8k_txq_reclaim(), to allow limiting the number of packets that it will reclaim, and make it return the number of packets that it reclaimed. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 759c94fb8e77..6598efcda5cc 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1249,13 +1249,15 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) MWL8K_TXD_STATUS_OK_RETRY | \ MWL8K_TXD_STATUS_OK_MORE_RETRY)) -static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) +static int +mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_tx_queue *txq = priv->txq + index; - int wake = 0; + int processed; - while (txq->stats.len > 0) { + processed = 0; + while (txq->stats.len > 0 && limit--) { int tx; struct mwl8k_tx_desc *tx_desc; unsigned long addr; @@ -1302,11 +1304,13 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) ieee80211_tx_status_irqsafe(hw, skb); - wake = 1; + processed++; } - if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) + if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) ieee80211_wake_queue(hw, index); + + return processed; } /* must be called only when the card's transmit is completely halted */ @@ -1315,7 +1319,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) struct mwl8k_priv *priv = hw->priv; struct mwl8k_tx_queue *txq = priv->txq + index; - mwl8k_txq_reclaim(hw, index, 1); + mwl8k_txq_reclaim(hw, index, INT_MAX, 1); kfree(txq->skb); txq->skb = NULL; @@ -3084,7 +3088,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) /* Return all skbs to mac80211 */ for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 1); + mwl8k_txq_reclaim(hw, i, INT_MAX, 1); } static int mwl8k_add_interface(struct ieee80211_hw *hw, @@ -3647,7 +3651,7 @@ static void mwl8k_tx_reclaim_handler(unsigned long data) spin_lock_bh(&priv->tx_lock); for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 0); + mwl8k_txq_reclaim(hw, i, INT_MAX, 0); if (priv->tx_wait != NULL && !priv->pending_tx_pkts) { complete(priv->tx_wait); @@ -4021,7 +4025,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) /* Return all skbs to mac80211 */ for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 1); + mwl8k_txq_reclaim(hw, i, INT_MAX, 1); for (i = 0; i < MWL8K_TX_QUEUES; i++) mwl8k_txq_deinit(hw, i); -- cgit v1.2.3 From 1e9f9de3b17db3aa358f39d6932662324178350d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:32:01 +0100 Subject: mwl8k: keep TX_DONE interrupt masked while transmit reclaim is running By making use of the CLEAR_SEL feature of the mwl8k host interface interrupt controller, we can keep the TX_DONE interrupt source masked while the transmit reclaim tasklet is running (NAPI style) without having to touch the interrupt controller's interrupt mask register when entering or exiting polling mode, and without having to do any more register reads/writes than we do now. When CLEAR_SEL is enabled on the TX_DONE interrupt source, reading the interrupt status register will clear the TX_DONE status bit if it was set, allowing it to be set again if a new TX_DONE event arrives while we are running the TX reclaim tasklet, but such a new event will then not trigger another PCI interrupt until a zero is written to the TX_DONE interrupt status register bit. I.e., if we write a zero to the TX_DONE interrupt source bit in the interrupt status register when the TX reclaim tasklet thinks it's done, a PCI interrupt will be triggered if a new TX_DONE event arrived from the hardware between us deciding that there is no more work to do and re-enabling the TX_DONE interrupt source, thereby avoiding the classic NAPI poll mode exit race that would otherwise occur. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 77 ++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6598efcda5cc..3f55aa0c8db3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -202,8 +202,8 @@ struct mwl8k_priv { */ struct work_struct finalize_join_worker; - /* Tasklet to reclaim TX descriptors and buffers after tx */ - struct tasklet_struct tx_reclaim_task; + /* Tasklet to perform TX reclaim. */ + struct tasklet_struct poll_tx_task; }; /* Per interface specific private data */ @@ -2963,13 +2963,16 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) u32 status; status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - if (!status) return IRQ_NONE; - if (status & MWL8K_A2H_INT_TX_DONE) - tasklet_schedule(&priv->tx_reclaim_task); + if (status & MWL8K_A2H_INT_TX_DONE) { + status &= ~MWL8K_A2H_INT_TX_DONE; + tasklet_schedule(&priv->poll_tx_task); + } + + if (status) + iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); if (status & MWL8K_A2H_INT_RX_READY) { while (rxq_process(hw, 0, 1)) @@ -2990,6 +2993,35 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +static void mwl8k_tx_poll(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct mwl8k_priv *priv = hw->priv; + int limit; + int i; + + limit = 32; + + spin_lock_bh(&priv->tx_lock); + + for (i = 0; i < MWL8K_TX_QUEUES; i++) + limit -= mwl8k_txq_reclaim(hw, i, limit, 0); + + if (!priv->pending_tx_pkts && priv->tx_wait != NULL) { + complete(priv->tx_wait); + priv->tx_wait = NULL; + } + + spin_unlock_bh(&priv->tx_lock); + + if (limit) { + writel(~MWL8K_A2H_INT_TX_DONE, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + } else { + tasklet_schedule(&priv->poll_tx_task); + } +} + /* * Core driver operations. @@ -3026,7 +3058,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) } /* Enable tx reclaim tasklet */ - tasklet_enable(&priv->tx_reclaim_task); + tasklet_enable(&priv->poll_tx_task); /* Enable interrupts */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); @@ -3059,7 +3091,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) if (rc) { iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); - tasklet_disable(&priv->tx_reclaim_task); + tasklet_disable(&priv->poll_tx_task); } return rc; @@ -3084,7 +3116,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) dev_kfree_skb(priv->beacon_skb); /* Stop tx reclaim tasklet */ - tasklet_disable(&priv->tx_reclaim_task); + tasklet_disable(&priv->poll_tx_task); /* Return all skbs to mac80211 */ for (i = 0; i < MWL8K_TX_QUEUES; i++) @@ -3643,23 +3675,6 @@ static const struct ieee80211_ops mwl8k_ops = { .ampdu_action = mwl8k_ampdu_action, }; -static void mwl8k_tx_reclaim_handler(unsigned long data) -{ - int i; - struct ieee80211_hw *hw = (struct ieee80211_hw *) data; - struct mwl8k_priv *priv = hw->priv; - - spin_lock_bh(&priv->tx_lock); - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, INT_MAX, 0); - - if (priv->tx_wait != NULL && !priv->pending_tx_pkts) { - complete(priv->tx_wait); - priv->tx_wait = NULL; - } - spin_unlock_bh(&priv->tx_lock); -} - static void mwl8k_finalize_join_worker(struct work_struct *work) { struct mwl8k_priv *priv = @@ -3859,9 +3874,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); /* TX reclaim tasklet */ - tasklet_init(&priv->tx_reclaim_task, - mwl8k_tx_reclaim_handler, (unsigned long)hw); - tasklet_disable(&priv->tx_reclaim_task); + tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_tx_task); /* Power management cookie */ priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); @@ -3890,7 +3904,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); + iowrite32(MWL8K_A2H_INT_TX_DONE, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); rc = request_irq(priv->pdev->irq, mwl8k_interrupt, @@ -4018,7 +4033,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) ieee80211_unregister_hw(hw); /* Remove tx reclaim tasklet */ - tasklet_kill(&priv->tx_reclaim_task); + tasklet_kill(&priv->poll_tx_task); /* Stop hardware */ mwl8k_hw_reset(priv); -- cgit v1.2.3 From 67e2eb27958cae758ccbc86443c360ec285acc3e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 8 Jan 2010 18:32:18 +0100 Subject: mwl8k: move receive processing to tasklet Like how TX reclaim is done in a tasklet, move receive processing to tasklet context as well. This can have nice benefits for CPU utilisation and throughput, especially at 3-stream rates. (Use the same CLEAR_SEL trick as the TX reclaim tasklet does, to avoid having to touch the interrupt mask registers.) Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 47 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 3f55aa0c8db3..13b0e32b051a 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -204,6 +204,9 @@ struct mwl8k_priv { /* Tasklet to perform TX reclaim. */ struct tasklet_struct poll_tx_task; + + /* Tasklet to perform RX. */ + struct tasklet_struct poll_rx_task; }; /* Per interface specific private data */ @@ -2971,14 +2974,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) tasklet_schedule(&priv->poll_tx_task); } - if (status) - iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - if (status & MWL8K_A2H_INT_RX_READY) { - while (rxq_process(hw, 0, 1)) - rxq_refill(hw, 0, 1); + status &= ~MWL8K_A2H_INT_RX_READY; + tasklet_schedule(&priv->poll_rx_task); } + if (status) + iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + if (status & MWL8K_A2H_INT_OPC_DONE) { if (priv->hostcmd_wait != NULL) complete(priv->hostcmd_wait); @@ -3022,6 +3025,24 @@ static void mwl8k_tx_poll(unsigned long data) } } +static void mwl8k_rx_poll(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct mwl8k_priv *priv = hw->priv; + int limit; + + limit = 32; + limit -= rxq_process(hw, 0, limit); + limit -= rxq_refill(hw, 0, limit); + + if (limit) { + writel(~MWL8K_A2H_INT_RX_READY, + priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); + } else { + tasklet_schedule(&priv->poll_rx_task); + } +} + /* * Core driver operations. @@ -3057,8 +3078,9 @@ static int mwl8k_start(struct ieee80211_hw *hw) return -EIO; } - /* Enable tx reclaim tasklet */ + /* Enable TX reclaim and RX tasklets. */ tasklet_enable(&priv->poll_tx_task); + tasklet_enable(&priv->poll_rx_task); /* Enable interrupts */ iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); @@ -3092,6 +3114,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); free_irq(priv->pdev->irq, hw); tasklet_disable(&priv->poll_tx_task); + tasklet_disable(&priv->poll_rx_task); } return rc; @@ -3115,8 +3138,9 @@ static void mwl8k_stop(struct ieee80211_hw *hw) if (priv->beacon_skb != NULL) dev_kfree_skb(priv->beacon_skb); - /* Stop tx reclaim tasklet */ + /* Stop TX reclaim and RX tasklets. */ tasklet_disable(&priv->poll_tx_task); + tasklet_disable(&priv->poll_rx_task); /* Return all skbs to mac80211 */ for (i = 0; i < MWL8K_TX_QUEUES; i++) @@ -3873,9 +3897,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); - /* TX reclaim tasklet */ + /* TX reclaim and RX tasklets. */ tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw); tasklet_disable(&priv->poll_tx_task); + tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw); + tasklet_disable(&priv->poll_rx_task); /* Power management cookie */ priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); @@ -3904,7 +3930,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(MWL8K_A2H_INT_TX_DONE, + iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); @@ -4032,8 +4058,9 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev) ieee80211_unregister_hw(hw); - /* Remove tx reclaim tasklet */ + /* Remove TX reclaim and RX tasklets. */ tasklet_kill(&priv->poll_tx_task); + tasklet_kill(&priv->poll_rx_task); /* Stop hardware */ mwl8k_hw_reset(priv); -- cgit v1.2.3 From 90be561b119a9e5439733f09cc70bd4ce9ec8022 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 8 Jan 2010 19:01:07 +0100 Subject: mac80211: fix return from ieee80211_assoc_success sparse pointed out that I made a mistake converting the return value of ieee80211_assoc_success to bool, this place should return false instead of one of the enum values (which would be true). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0336dbb45ac5..8045fd63616b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1098,7 +1098,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" " the AP (error %d)\n", sdata->name, err); - return RX_MGMT_CFG80211_ASSOC_ERROR; + return false; } if (elems.wmm_param) -- cgit v1.2.3 From f05279711b9a59ac10e0b6e5f3a7447886c72704 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Jan 2010 10:04:41 -0800 Subject: iwlwifi: add IEEE80211_AMPDU_TX_OPERATIONAL mac80211 do not check the return code now, what if mac80211 does start using the return code? IEEE80211_AMPDU_TX_OPERATIONAL is a valid action, just iwlwifi driver do not need to take any action for it; so instead of return "-EINVAL", it is a good program practice to return "-EOPNOTSUPP" to make sure mac80211 will not get wrong impression. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 771b03c1c7c5..c78063312ea9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2955,6 +2955,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return 0; else return ret; + case IEEE80211_AMPDU_TX_OPERATIONAL: + /* do nothing */ + return -EOPNOTSUPP; default: IWL_DEBUG_HT(priv, "unknown\n"); return -EINVAL; -- cgit v1.2.3 From f0118a4575d45ce3074c830660de938bc6e17bda Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Jan 2010 10:04:42 -0800 Subject: iwlwifi: ucode statistics data structure update Update data structure to match latest statistics report from uCode. Signed-off-by: Wey-Yi Guy Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 28f3800c560e..6bfc63f54b5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2984,7 +2984,7 @@ struct statistics_rx_ht_phy { __le32 agg_crc32_good; __le32 agg_mpdu_cnt; __le32 agg_cnt; - __le32 reserved2; + __le32 unsupport_mcs; } __attribute__ ((packed)); #define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) @@ -3087,8 +3087,8 @@ struct statistics_div { } __attribute__ ((packed)); struct statistics_general { - __le32 temperature; - __le32 temperature_m; + __le32 temperature; /* radio temperature */ + __le32 temperature_m; /* for 5000 and up, this is radio voltage */ struct statistics_dbg dbg; __le32 sleep_time; __le32 slots_out; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ee5aed12a4b1..510bad918f20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1387,6 +1387,9 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, accum_ht->agg_mpdu_cnt); pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n", le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt); + pos += scnprintf(buf + pos, bufsz - pos, "unsupport_mcs:\t\t%u\t\t\t%u\n", + le32_to_cpu(ht->unsupport_mcs), + accum_ht->unsupport_mcs); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); -- cgit v1.2.3 From c15867f15f98e5ecbdbee5993db7f6f4b7100481 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Jan 2010 10:04:43 -0800 Subject: iwlwifi: remove obsoleted host command "RADAR_NOTIFICATION" host command is not used and not supported by uCode, remove it from driver code. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 - drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6bfc63f54b5e..3320cce3d57b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -120,7 +120,6 @@ enum { CALIBRATION_COMPLETE_NOTIFICATION = 0x67, /* 802.11h related */ - RADAR_NOTIFICATION = 0x70, /* not used */ REPLY_QUIET_CMD = 0x71, /* not used */ REPLY_CHANNEL_SWITCH = 0x72, CHANNEL_SWITCH_NOTIFICATION = 0x73, diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 30e9ea6d54ec..87d684efe110 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -58,7 +58,6 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(COEX_PRIORITY_TABLE_CMD); IWL_CMD(COEX_MEDIUM_NOTIFICATION); IWL_CMD(COEX_EVENT_CMD); - IWL_CMD(RADAR_NOTIFICATION); IWL_CMD(REPLY_QUIET_CMD); IWL_CMD(REPLY_CHANNEL_SWITCH); IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); -- cgit v1.2.3 From 8ce1ef4a914aef8b9b90a2a2c670494168a2cca9 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Jan 2010 10:04:44 -0800 Subject: iwlwifi: fix bug in tx byte count table When setting invalid byte count in txq byte count table, read pointer should be used instead of write pointer. Reported-by: Guo, Chaohong Signed-off-by: Wey-Yi Guy Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ec6b27689fa8..c3f8ec0a38b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -781,7 +781,7 @@ void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) + if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) scd_bc_tbl[txq_id]. tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; } @@ -800,12 +800,12 @@ void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, if (txq_id != IWL_CMD_QUEUE_NUM) sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; - bc_ent = cpu_to_le16(1 | (sta_id << 12)); + bc_ent = cpu_to_le16(1 | (sta_id << 12)); scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) + if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; + tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; } static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, -- cgit v1.2.3 From 28f63a4bb744ea81030219aba2337fddb10b380b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 8 Jan 2010 16:14:10 -0700 Subject: iwl-debugfs.c: remove unnecessary casts of void * void pointers do not need to be cast to other pointer types. Signed-off-by: H Hartley Sweeten Acked-by: Zhu Yi Cc: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 46 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 510bad918f20..4a2ac9311ba8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -125,7 +125,7 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char *buf; int pos = 0; @@ -184,7 +184,7 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char *buf; int pos = 0; int cnt; @@ -232,7 +232,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, ssize_t ret; int i; int pos = 0; - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; size_t bufsz; /* default is to dump the entire data segment */ @@ -306,7 +306,7 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; struct iwl_station_entry *station; int max_sta = priv->hw_params.max_stations; char *buf; @@ -376,7 +376,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, loff_t *ppos) { ssize_t ret; - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0, ofs = 0, buf_size = 0; const u8 *ptr; char *buf; @@ -464,7 +464,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; struct ieee80211_channel *channels = NULL; const struct ieee80211_supported_band *supp_band = NULL; int pos = 0, i, bufsz = PAGE_SIZE; @@ -537,7 +537,7 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[512]; int pos = 0; const size_t bufsz = sizeof(buf); @@ -585,7 +585,7 @@ static ssize_t iwl_dbgfs_interrupt_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; int cnt = 0; char *buf; @@ -672,7 +672,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0, i; char buf[256]; const size_t bufsz = sizeof(buf); @@ -695,7 +695,7 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char buf[256]; const size_t bufsz = sizeof(buf); @@ -721,7 +721,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; struct iwl_tt_restriction *restriction; char buf[100]; @@ -781,7 +781,7 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[100]; int pos = 0; const size_t bufsz = sizeof(buf); @@ -838,7 +838,7 @@ static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[10]; int pos, value; const size_t bufsz = sizeof(buf); @@ -856,7 +856,7 @@ static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[200]; int pos = 0, i; const size_t bufsz = sizeof(buf); @@ -994,7 +994,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; struct iwl_tx_queue *txq; struct iwl_queue *q; char *buf; @@ -1040,7 +1040,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; struct iwl_rx_queue *rxq = &priv->rxq; char buf[256]; int pos = 0; @@ -1086,7 +1086,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; int bufsz = sizeof(struct statistics_rx_phy) * 20 + @@ -1400,7 +1400,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; int bufsz = (sizeof(struct statistics_tx) * 24) + 250; @@ -1542,7 +1542,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; int bufsz = sizeof(struct statistics_general) * 4 + 250; @@ -1633,7 +1633,7 @@ static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; int cnt = 0; char *buf; @@ -1714,7 +1714,7 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; int pos = 0; int cnt = 0; char *buf; @@ -1772,7 +1772,7 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[128]; int pos = 0; ssize_t ret; @@ -1823,7 +1823,7 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl_priv *priv = file->private_data; char buf[60]; int pos = 0; const size_t bufsz = sizeof(buf); -- cgit v1.2.3 From 5e124bd5e00fcf54df555b368c2dafe6886f1df2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 8 Jan 2010 22:33:38 -0800 Subject: net/mac80211/mlme.c: Remove unnecessary semicolons Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8045fd63616b..86f025bc9456 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1783,7 +1783,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, if (!wk) return -ENOMEM; - memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);; + memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); if (req->ie && req->ie_len) { memcpy(wk->ie, req->ie, req->ie_len); -- cgit v1.2.3 From 678f415fdc534c0a806fce992e4c62df0eff19d2 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 10 Jan 2010 14:07:53 +0100 Subject: mac80211: flush workqueue before calling driver ->stop() method Since commit "mwl8k: handle station database update for AP's sta entry via ->sta_notify()", mwl8k every now and then gets a command timeout when ifconfig'ing a STA interface down. This turns out to be due to mwl8k_stop() being called while the work queue item that was scheduled by mwl8k_sta_notify() to remove the STA entry for the associated AP is still queued, and the former disables interrupts so that when the latter eventually runs, a command completion interrupt is never seen. Fix this by changing ieee80211_stop_device() so that the workqueue is flushed before drv_stop() is called, instead of doing it the other way around as is done now. (As ->stop() is allowed to sleep, there isn't any reason for drivers to queue work from within it.) Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- net/mac80211/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 72a98e844718..a2ba6e29bd9a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1069,9 +1069,9 @@ void ieee80211_stop_device(struct ieee80211_local *local) ieee80211_led_radio(local, false); cancel_work_sync(&local->reconfig_filter); - drv_stop(local); flush_workqueue(local->workqueue); + drv_stop(local); } int ieee80211_reconfig(struct ieee80211_local *local) -- cgit v1.2.3 From 2d46d7c121436f1dafe91b0a8d9b99e534cfa5f8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 10 Jan 2010 17:12:41 +0100 Subject: mac80211: remove unused type argument The type argument to DEBUGFS_ADD() isn't used and can be removed, it's around from before the conversion to debugfs_remove_recursive(). Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_netdev.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 1481049f0f71..9affe2cd185f 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -255,7 +255,7 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, #endif -#define DEBUGFS_ADD(name, type) \ +#define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ sdata, &name##_ops); @@ -265,40 +265,40 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode, static void add_sta_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted, sta); - DEBUGFS_ADD(rc_rateidx_mask_2ghz, sta); - DEBUGFS_ADD(rc_rateidx_mask_5ghz, sta); + DEBUGFS_ADD(drop_unencrypted); + DEBUGFS_ADD(rc_rateidx_mask_2ghz); + DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(bssid, sta); - DEBUGFS_ADD(aid, sta); + DEBUGFS_ADD(bssid); + DEBUGFS_ADD(aid); DEBUGFS_ADD_MODE(smps, 0600); } static void add_ap_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted, ap); - DEBUGFS_ADD(rc_rateidx_mask_2ghz, ap); - DEBUGFS_ADD(rc_rateidx_mask_5ghz, ap); + DEBUGFS_ADD(drop_unencrypted); + DEBUGFS_ADD(rc_rateidx_mask_2ghz); + DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(num_sta_ps, ap); - DEBUGFS_ADD(dtim_count, ap); - DEBUGFS_ADD(num_buffered_multicast, ap); + DEBUGFS_ADD(num_sta_ps); + DEBUGFS_ADD(dtim_count); + DEBUGFS_ADD(num_buffered_multicast); } static void add_wds_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted, wds); - DEBUGFS_ADD(rc_rateidx_mask_2ghz, wds); - DEBUGFS_ADD(rc_rateidx_mask_5ghz, wds); + DEBUGFS_ADD(drop_unencrypted); + DEBUGFS_ADD(rc_rateidx_mask_2ghz); + DEBUGFS_ADD(rc_rateidx_mask_5ghz); - DEBUGFS_ADD(peer, wds); + DEBUGFS_ADD(peer); } static void add_vlan_files(struct ieee80211_sub_if_data *sdata) { - DEBUGFS_ADD(drop_unencrypted, vlan); - DEBUGFS_ADD(rc_rateidx_mask_2ghz, vlan); - DEBUGFS_ADD(rc_rateidx_mask_5ghz, vlan); + DEBUGFS_ADD(drop_unencrypted); + DEBUGFS_ADD(rc_rateidx_mask_2ghz); + DEBUGFS_ADD(rc_rateidx_mask_5ghz); } static void add_monitor_files(struct ieee80211_sub_if_data *sdata) -- cgit v1.2.3 From ab13315af97919fae0e014748105fdc2e30afb2d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:42:31 +0200 Subject: mac80211: add U-APSD client support Add Unscheduled Automatic Power-Save Delivery (U-APSD) client support. The idea is that the data frames from the client trigger AP to send the buffered frames with ACs which have U-APSD enabled. This decreases latency and makes it possible to save even more power. Driver needs to use IEEE80211_HW_UAPSD to enable the feature. The current implementation assumes that firmware takes care of the wakeup and hardware needing IEEE80211_HW_PS_NULLFUNC_STACK is not yet supported. Tested with wl1251 on a Nokia N900 and Cisco Aironet 1231G AP and running various test traffic with ping. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 18 ++++++++++++++++++ include/net/mac80211.h | 7 +++++++ net/mac80211/cfg.c | 7 +++++++ net/mac80211/ieee80211_i.h | 13 ++++++++++++- net/mac80211/main.c | 4 ++++ net/mac80211/mlme.c | 31 ++++++++++++++++++++++++++++--- net/mac80211/scan.c | 18 ++++++++++++++++++ net/mac80211/util.c | 2 ++ net/mac80211/work.c | 12 ++++++++++-- 9 files changed, 106 insertions(+), 6 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 602c0692c3fc..a8c6069a0d9f 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -120,6 +120,24 @@ #define IEEE80211_QOS_CTL_TID_MASK 0x000F #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 +/* U-APSD queue for WMM IEs sent by AP */ +#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) + +/* U-APSD queues for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO (1<<0) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI (1<<1) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK (1<<2) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE (1<<3) +#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f + +/* U-APSD max SP length for WMM IEs sent by STA */ +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x01 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x02 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 +#define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 + struct ieee80211_hdr { __le16 frame_control; __le16 duration_id; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index e1e73c6abeff..f313a3cbabda 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -113,6 +113,7 @@ struct ieee80211_tx_queue_params { u16 cw_min; u16 cw_max; u8 aifs; + bool uapsd; }; /** @@ -929,6 +930,11 @@ enum ieee80211_tkip_key_type { * Hardware supports dynamic spatial multiplexing powersave, * ie. can turn off all but one chain and then wake the rest * up as required after, for example, rts/cts handshake. + * + * @IEEE80211_HW_SUPPORTS_UAPSD: + * Hardware supports Unscheduled Automatic Power Save Delivery + * (U-APSD) in managed mode. The mode is configured with + * conf_tx() operation. */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -948,6 +954,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_BEACON_FILTER = 1<<14, IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, + IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index dc12e9466ffd..8286df5822d5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1128,6 +1128,13 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, p.cw_max = params->cwmax; p.cw_min = params->cwmin; p.txop = params->txop; + + /* + * Setting tx queue params disables u-apsd because it's only + * called in master mode. + */ + p.uapsd = false; + if (drv_conf_tx(local, params->queue, &p)) { printk(KERN_DEBUG "%s: failed to set TX queue " "parameters for queue %d\n", diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3e4ac3f30857..3468e378509a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -58,6 +58,15 @@ struct ieee80211_local; #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) +#define IEEE80211_DEFAULT_UAPSD_QUEUES \ + (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ + IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \ + IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \ + IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + +#define IEEE80211_DEFAULT_MAX_SP_LEN \ + IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL + struct ieee80211_fragment_entry { unsigned long first_frag_time; unsigned int seq; @@ -78,6 +87,7 @@ struct ieee80211_bss { u8 dtim_period; bool wmm_used; + bool uapsd_supported; unsigned long last_probe_resp; @@ -285,7 +295,7 @@ struct ieee80211_work { u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid_len; u8 supp_rates_len; - bool wmm_used, use_11n; + bool wmm_used, use_11n, uapsd_used; } assoc; struct { u32 duration; @@ -306,6 +316,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_DISABLE_11N = BIT(4), IEEE80211_STA_CSA_RECEIVED = BIT(5), IEEE80211_STA_MFP_ENABLED = BIT(6), + IEEE80211_STA_UAPSD_ENABLED = BIT(7), }; struct ieee80211_if_managed { diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 468829143991..0054bba08ce1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -491,6 +491,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; + WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) + && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), + "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); + /* * Calculate scan IE length -- we need this to alloc * memory and to subtract from the driver limit. It diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86f025bc9456..39c27d83a4f2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -569,7 +569,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_tx_queue_params params; size_t left; int count; - u8 *pos; + u8 *pos, uapsd_queues = 0; if (local->hw.queues < 4) return; @@ -579,6 +579,10 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) return; + + if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) + uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; + count = wmm_param[6] & 0x0f; if (count == ifmgd->wmm_last_param_set) return; @@ -593,6 +597,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, for (; left >= 4; left -= 4, pos += 4) { int aci = (pos[0] >> 5) & 0x03; int acm = (pos[0] >> 4) & 0x01; + bool uapsd = false; int queue; switch (aci) { @@ -600,22 +605,30 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, queue = 3; if (acm) local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ + if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) + uapsd = true; break; case 2: /* AC_VI */ queue = 1; if (acm) local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ + if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) + uapsd = true; break; case 3: /* AC_VO */ queue = 0; if (acm) local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ + if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + uapsd = true; break; case 0: /* AC_BE */ default: queue = 2; if (acm) local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ + if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) + uapsd = true; break; } @@ -623,11 +636,14 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); params.cw_min = ecw2cw(pos[1] & 0x0f); params.txop = get_unaligned_le16(pos + 2); + params.uapsd = uapsd; + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " - "cWmin=%d cWmax=%d txop=%d\n", + "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", wiphy_name(local->hw.wiphy), queue, aci, acm, - params.aifs, params.cw_min, params.cw_max, params.txop); + params.aifs, params.cw_min, params.cw_max, params.txop, + params.uapsd); #endif if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) printk(KERN_DEBUG "%s: failed to set TX queue " @@ -1906,6 +1922,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, wk->assoc.ht_information_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); + if (bss->wmm_used && bss->uapsd_supported && + (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { + wk->assoc.uapsd_used = true; + ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; + } else { + wk->assoc.uapsd_used = false; + ifmgd->flags &= ~IEEE80211_STA_UAPSD_ENABLED; + } + ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); wk->assoc.ssid_len = ssid[1]; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 30cb62bb45b3..9afe2f9885dc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -54,6 +54,23 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); } +static bool is_uapsd_supported(struct ieee802_11_elems *elems) +{ + u8 qos_info; + + if (elems->wmm_info && elems->wmm_info_len == 7 + && elems->wmm_info[5] == 1) + qos_info = elems->wmm_info[6]; + else if (elems->wmm_param && elems->wmm_param_len == 24 + && elems->wmm_param[5] == 1) + qos_info = elems->wmm_param[6]; + else + /* no valid wmm information or parameter element found */ + return false; + + return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD; +} + struct ieee80211_bss * ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee80211_rx_status *rx_status, @@ -117,6 +134,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, } bss->wmm_used = elems->wmm_param || elems->wmm_info; + bss->uapsd_supported = is_uapsd_supported(elems); if (!beacon) bss->last_probe_resp = jiffies; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a2ba6e29bd9a..e278f97c8305 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -792,6 +792,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) break; } + qparam.uapsd = false; + drv_conf_tx(local, queue, &qparam); } } diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 7c5d95b1bc04..a74fd6ee0083 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -202,7 +202,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos; + u8 *pos, qos_info; const u8 *ies; size_t offset = 0, noffset; int i, len, count, rates_len, supp_rates_len; @@ -375,6 +375,14 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, } if (wk->assoc.wmm_used && local->hw.queues >= 4) { + if (wk->assoc.uapsd_used) { + qos_info = IEEE80211_DEFAULT_UAPSD_QUEUES; + qos_info |= (IEEE80211_DEFAULT_MAX_SP_LEN << + IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); + } else { + qos_info = 0; + } + pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; *pos++ = 7; /* len */ @@ -384,7 +392,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, *pos++ = 2; /* WME */ *pos++ = 0; /* WME info */ *pos++ = 1; /* WME ver */ - *pos++ = 0; + *pos++ = qos_info; } /* add any remaining custom (i.e. vendor specific here) IEs */ -- cgit v1.2.3 From 50ae0cf15c3da2f6a8e4558de5010923e84736b2 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:42:39 +0200 Subject: mac80211: add debugfs interface for U-APSD queue configuration Because it's not yet decided how to configure which queues are U-APSD enabled, add a debugfs interface for testing purposes. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ net/mac80211/ieee80211_i.h | 14 +++++++ net/mac80211/main.c | 2 + net/mac80211/mlme.c | 2 +- net/mac80211/work.c | 4 +- 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index e4b54093d41b..b3bc32b62a5a 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -158,6 +158,98 @@ static const struct file_operations noack_ops = { .open = mac80211_open_file_generic }; +static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + int res; + char buf[10]; + + res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static ssize_t uapsd_queues_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + unsigned long val; + char buf[10]; + size_t len; + int ret; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &val); + + if (ret) + return -EINVAL; + + if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) + return -ERANGE; + + local->uapsd_queues = val; + + return count; +} + +static const struct file_operations uapsd_queues_ops = { + .read = uapsd_queues_read, + .write = uapsd_queues_write, + .open = mac80211_open_file_generic +}; + +static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + int res; + char buf[10]; + + res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len); + + return simple_read_from_buffer(user_buf, count, ppos, buf, res); +} + +static ssize_t uapsd_max_sp_len_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + unsigned long val; + char buf[10]; + size_t len; + int ret; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + ret = strict_strtoul(buf, 0, &val); + + if (ret) + return -EINVAL; + + if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) + return -ERANGE; + + local->uapsd_max_sp_len = val; + + return count; +} + +static const struct file_operations uapsd_max_sp_len_ops = { + .read = uapsd_max_sp_len_read, + .write = uapsd_max_sp_len_write, + .open = mac80211_open_file_generic +}; + static ssize_t queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -314,6 +406,8 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(queues); DEBUGFS_ADD_MODE(reset, 0200); DEBUGFS_ADD(noack); + DEBUGFS_ADD(uapsd_queues); + DEBUGFS_ADD(uapsd_max_sp_len); statsd = debugfs_create_dir("statistics", phyd); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3468e378509a..c18f576f1848 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -808,6 +808,20 @@ struct ieee80211_local { int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ + /* + * Bitmask of enabled u-apsd queues, + * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association + * to take effect. + */ + unsigned int uapsd_queues; + + /* + * Maximum number of buffered frames AP can deliver during a + * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar. + * Needs a new association to take effect. + */ + unsigned int uapsd_max_sp_len; + bool pspolling; bool offchannel_ps_enabled; /* diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0054bba08ce1..ec8f767ba95b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -384,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; local->user_power_level = -1; + local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; + local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; INIT_LIST_HEAD(&local->interfaces); mutex_init(&local->iflist_mtx); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 39c27d83a4f2..2746391248d3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -581,7 +581,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, return; if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) - uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; + uapsd_queues = local->uapsd_queues; count = wmm_param[6] & 0x0f; if (count == ifmgd->wmm_last_param_set) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index a74fd6ee0083..81bd5d592bb4 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -376,8 +376,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, if (wk->assoc.wmm_used && local->hw.queues >= 4) { if (wk->assoc.uapsd_used) { - qos_info = IEEE80211_DEFAULT_UAPSD_QUEUES; - qos_info |= (IEEE80211_DEFAULT_MAX_SP_LEN << + qos_info = local->uapsd_queues; + qos_info |= (local->uapsd_max_sp_len << IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT); } else { qos_info = 0; -- cgit v1.2.3 From 5c1b98a52c3af1044c2d3842af8bae9a89502ca9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:42:46 +0200 Subject: mac80211: create tx handler for dynamic ps Currently dynamic ps check is in ieee80211_xmit(), but it's cleaner to have a separate tx handler for this. Also this is a prerequisite for U-APSD client mode which needs to know the queue frame is in. Also need_dynamic_ps() function is embedded to the tx handler. No functional changes expect that the code is run in a later phase than originally. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/tx.c | 81 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 47ca59e52e71..6fcc85a2806a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -180,6 +180,46 @@ static int inline is_ieee80211_device(struct ieee80211_local *local, } /* tx handlers */ +static ieee80211_tx_result debug_noinline +ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) +{ + struct ieee80211_local *local = tx->local; + + /* driver doesn't support power save */ + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) + return TX_CONTINUE; + + /* hardware does dynamic power save */ + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) + return TX_CONTINUE; + + /* dynamic power save disabled */ + if (local->hw.conf.dynamic_ps_timeout <= 0) + return TX_CONTINUE; + + /* we are scanning, don't enable power save */ + if (local->scanning) + return TX_CONTINUE; + + if (!local->ps_sdata) + return TX_CONTINUE; + + /* No point if we're going to suspend */ + if (local->quiescing) + return TX_CONTINUE; + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + ieee80211_stop_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); + ieee80211_queue_work(&local->hw, + &local->dynamic_ps_disable_work); + } + + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); + + return TX_CONTINUE; +} static ieee80211_tx_result debug_noinline ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) @@ -1223,6 +1263,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) goto txh_done; \ } while (0) + CALL_TXH(ieee80211_tx_h_dynamic_ps); CALL_TXH(ieee80211_tx_h_check_assoc); CALL_TXH(ieee80211_tx_h_ps_buf); CALL_TXH(ieee80211_tx_h_select_key); @@ -1405,34 +1446,6 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, return 0; } -static bool need_dynamic_ps(struct ieee80211_local *local) -{ - /* driver doesn't support power save */ - if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) - return false; - - /* hardware does dynamic power save */ - if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - return false; - - /* dynamic power save disabled */ - if (local->hw.conf.dynamic_ps_timeout <= 0) - return false; - - /* we are scanning, don't enable power save */ - if (local->scanning) - return false; - - if (!local->ps_sdata) - return false; - - /* No point if we're going to suspend */ - if (local->quiescing) - return false; - - return true; -} - static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { @@ -1443,18 +1456,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, int headroom; bool may_encrypt; - if (need_dynamic_ps(local)) { - if (local->hw.conf.flags & IEEE80211_CONF_PS) { - ieee80211_stop_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_PS); - ieee80211_queue_work(&local->hw, - &local->dynamic_ps_disable_work); - } - - mod_timer(&local->dynamic_ps_timer, jiffies + - msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); - } - rcu_read_lock(); if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { -- cgit v1.2.3 From 0c74211d19d83729c209ddcd4dc026c2aedeb29e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:42:53 +0200 Subject: mac80211: check uapsd state for dynamic power save To make U-APSD client mode effective, we must not wake up from dynamic power save when transmitting frames. So if dynamic power save is enabled, it needs check the queue the transmitted packet is in and decide if we need to wake up or not. In a perfect world, where all packets would have correct QoS tags, U-APSD enabled queues should not trigger wakeup from power save. But in the real world, where very few packets have correct QoS tags, this won't work. For example, if only voip class has U-APSD enabled and we send a packet in voip class, but the packets we receive are in best effort class, we would receive the packets with the legacy power save method. And that would increase latencies too much from a voip application point of view. The workaround is to enable U-APSD for all qeueus and still use dynamic ps wakeup for all other queues except voip. That way we can still save power with a voip application and not sacrifice latency. Normal traffic (in background, best effort or video class) would still trigger wakeup from dynamic power save. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/tx.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6fcc85a2806a..daf81048c1f7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -184,6 +184,7 @@ static ieee80211_tx_result debug_noinline ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) { struct ieee80211_local *local = tx->local; + struct ieee80211_if_managed *ifmgd; /* driver doesn't support power save */ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) @@ -208,6 +209,30 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) if (local->quiescing) return TX_CONTINUE; + /* dynamic ps is supported only in managed mode */ + if (tx->sdata->vif.type != NL80211_IFTYPE_STATION) + return TX_CONTINUE; + + ifmgd = &tx->sdata->u.mgd; + + /* + * Don't wakeup from power save if u-apsd is enabled, voip ac has + * u-apsd enabled and the frame is in voip class. This effectively + * means that even if all access categories have u-apsd enabled, in + * practise u-apsd is only used with the voip ac. This is a + * workaround for the case when received voip class packets do not + * have correct qos tag for some reason, due the network or the + * peer application. + * + * Note: local->uapsd_queues access is racy here. If the value is + * changed via debugfs, user needs to reassociate manually to have + * everything in sync. + */ + if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) + && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) + && skb_get_queue_mapping(tx->skb) == 0) + return TX_CONTINUE; + if (local->hw.conf.flags & IEEE80211_CONF_PS) { ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_QUEUE_STOP_REASON_PS); -- cgit v1.2.3 From 558a6669d7cb407fbb0b5aec184b5c3b9a893d30 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:43:00 +0200 Subject: ieee80211: add struct ieee80211_hdr_qos The header can be used to create qos nullfunc frames, for example. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a8c6069a0d9f..842701906ae9 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -157,6 +157,16 @@ struct ieee80211_hdr_3addr { __le16 seq_ctrl; } __attribute__ ((packed)); +struct ieee80211_qos_hdr { + __le16 frame_control; + __le16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + __le16 seq_ctrl; + __le16 qos_ctrl; +} __attribute__ ((packed)); + /** * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set * @fc: frame control bytes in little-endian byteorder -- cgit v1.2.3 From 8f8ff91652fcf62b9fced5387956b4b269fde634 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:43:07 +0200 Subject: wl1251: create qos null data template The qos null data template is needed for U-APSD. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index f17ce06b6c24..d469d3dcd054 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -563,6 +563,27 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&wl->mutex); } +static int wl1251_build_qos_null_data(struct wl1251 *wl) +{ + struct ieee80211_qos_hdr template; + + memset(&template, 0, sizeof(template)); + + memcpy(template.addr1, wl->bssid, ETH_ALEN); + memcpy(template.addr2, wl->mac_addr, ETH_ALEN); + memcpy(template.addr3, wl->bssid, ETH_ALEN); + + template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_QOS_NULLFUNC | + IEEE80211_FCTL_TODS); + + /* FIXME: not sure what priority to use here */ + template.qos_ctrl = cpu_to_le16(0); + + return wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, &template, + sizeof(template)); +} + static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1251 *wl = hw->priv; @@ -948,6 +969,10 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; + ret = wl1251_build_qos_null_data(wl); + if (ret < 0) + goto out; + if (wl->bss_type != BSS_TYPE_IBSS) { ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, wl->dtim_period); -- cgit v1.2.3 From 4ff6ffa107ba1c6ba9a1cc75a1f304eaa79e8bf4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 12 Jan 2010 10:43:15 +0200 Subject: wl1251: add U-APSD support wl1251 firmware supports U-APSD just with a simple queue configuration change so enable it. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index d469d3dcd054..595f0f94d16e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1143,6 +1143,7 @@ static struct ieee80211_channel wl1251_channels[] = { static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params) { + enum wl1251_acx_ps_scheme ps_scheme; struct wl1251 *wl = hw->priv; int ret; @@ -1160,10 +1161,14 @@ static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, if (ret < 0) goto out_sleep; + if (params->uapsd) + ps_scheme = WL1251_ACX_PS_SCHEME_UPSD_TRIGGER; + else + ps_scheme = WL1251_ACX_PS_SCHEME_LEGACY; + ret = wl1251_acx_tid_cfg(wl, wl1251_tx_get_queue(queue), CHANNEL_TYPE_EDCF, - wl1251_tx_get_queue(queue), - WL1251_ACX_PS_SCHEME_LEGACY, + wl1251_tx_get_queue(queue), ps_scheme, WL1251_ACX_ACK_POLICY_LEGACY); if (ret < 0) goto out_sleep; @@ -1237,7 +1242,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl) wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_BEACON_FILTER; + IEEE80211_HW_BEACON_FILTER | + IEEE80211_HW_SUPPORTS_UAPSD; wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); wl->hw->wiphy->max_scan_ssids = 1; -- cgit v1.2.3 From c92d4edecf489dbcbb2e5dd3c513790e57e2ea0e Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:47:22 +0100 Subject: mwl8k: update MODULE_FIRMWARE tags Add MODULE_FIRMWARE tags for the mwl8k firmware images that don't have them yet, and move them to where the firmware image names are declared. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 13b0e32b051a..01cababfefa8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -394,9 +394,6 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) return 0; } -MODULE_FIRMWARE("mwl8k/helper_8687.fw"); -MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); - struct mwl8k_cmd_pkt { __le16 code; __le16 length; @@ -3737,6 +3734,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { }, }; +MODULE_FIRMWARE("mwl8k/helper_8363.fw"); +MODULE_FIRMWARE("mwl8k/fmimage_8363.fw"); +MODULE_FIRMWARE("mwl8k/helper_8687.fw"); +MODULE_FIRMWARE("mwl8k/fmimage_8687.fw"); +MODULE_FIRMWARE("mwl8k/helper_8366.fw"); +MODULE_FIRMWARE("mwl8k/fmimage_8366.fw"); + static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, -- cgit v1.2.3 From 9189c10087a738c764046fa27651d332594cd8e6 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:47:32 +0100 Subject: mwl8k: remove (mostly) write-only variable priv->current_channel Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 01cababfefa8..f2c4524888a8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -156,8 +156,6 @@ struct mwl8k_priv { struct ieee80211_vif *vif; - struct ieee80211_channel *current_channel; - /* power management status cookie from firmware */ u32 *cookie; dma_addr_t cookie_dma; @@ -3050,7 +3048,7 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) int index = skb_get_queue_mapping(skb); int rc; - if (priv->current_channel == NULL) { + if (!priv->radio_on) { printk(KERN_DEBUG "%s: dropped TX frame since radio " "disabled\n", wiphy_name(hw->wiphy)); dev_kfree_skb(skb); @@ -3182,7 +3180,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, mwl8k_vif->seqno = 0; priv->vif = vif; - priv->current_channel = NULL; return 0; } @@ -3208,7 +3205,6 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (conf->flags & IEEE80211_CONF_IDLE) { mwl8k_cmd_radio_disable(hw); - priv->current_channel = NULL; return 0; } @@ -3224,8 +3220,6 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) if (rc) goto out; - priv->current_channel = conf->channel; - if (conf->power_level > 18) conf->power_level = 18; rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); -- cgit v1.2.3 From c97470dd253831e880c72ea5d022ed7f3aee45c3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:47:37 +0100 Subject: mwl8k: don't call SET_AID if we're not associated Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f2c4524888a8..67ee3da33264 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3261,9 +3261,9 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* * Get the AP's legacy and MCS rates. */ - ap_legacy_rates = 0; if (vif->bss_conf.assoc) { struct ieee80211_sta *ap; + rcu_read_lock(); ap = ieee80211_find_sta(vif, vif->bss_conf.bssid); @@ -3301,8 +3301,9 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } - if (((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) || - (changed & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT))) { + if (vif->bss_conf.assoc && + (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT | + BSS_CHANGED_HT))) { rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates); if (rc) goto out; -- cgit v1.2.3 From 657232b625890f202867ede0ed67ecf15827ff80 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:47:47 +0100 Subject: mwl8k: simplify sequence number assignment By storing the sequence counter in << 4 format, like other drivers do. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 67ee3da33264..7d165befb0d7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1355,11 +1355,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) mwl8k_vif = MWL8K_VIF(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - u16 seqno = mwl8k_vif->seqno; - wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - wh->seq_ctrl |= cpu_to_le16(seqno << 4); - mwl8k_vif->seqno = seqno++ % 4096; + wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno); + mwl8k_vif->seqno += 0x10; } /* Setup firmware control bit fields for each frame type. */ -- cgit v1.2.3 From ca66527c60385dcec878ebd90749d1fdc43bc870 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:47:53 +0100 Subject: mwl8k: add another 88w8366 PCI ID 0x2a43 is a single-band (2.4GHz only) 88w8366 mini-PCIe card. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 7d165befb0d7..76da583df321 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3740,6 +3740,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, + { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, { }, }; MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table); -- cgit v1.2.3 From 777ad375d5960e0d2a945a34032b182eb2952d45 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:48:04 +0100 Subject: mwl8k: rename 2.4 GHz band/channels/rates related variables from FOO to FOO_24 To prepare for adding 5 GHz band/channels/rates. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 76 +++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 76da583df321..37cbfbf21567 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -141,6 +141,9 @@ struct mwl8k_priv { /* hardware/firmware parameters */ bool ap_fw; struct rxd_ops *rxd_ops; + struct ieee80211_supported_band band_24; + struct ieee80211_channel channels_24[14]; + struct ieee80211_rate rates_24[14]; /* firmware access */ struct mutex fw_mutex; @@ -173,11 +176,6 @@ struct mwl8k_priv { struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; - /* PHY parameters */ - struct ieee80211_supported_band band; - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[14]; - bool radio_on; bool radio_short_preamble; bool sniffer_enabled; @@ -220,7 +218,7 @@ struct mwl8k_sta { }; #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) -static const struct ieee80211_channel mwl8k_channels[] = { +static const struct ieee80211_channel mwl8k_channels_24[] = { { .center_freq = 2412, .hw_value = 1, }, { .center_freq = 2417, .hw_value = 2, }, { .center_freq = 2422, .hw_value = 3, }, @@ -237,7 +235,7 @@ static const struct ieee80211_channel mwl8k_channels[] = { { .center_freq = 2484, .hw_value = 14, }, }; -static const struct ieee80211_rate mwl8k_rates[] = { +static const struct ieee80211_rate mwl8k_rates_24[] = { { .bitrate = 10, .hw_value = 2, }, { .bitrate = 20, .hw_value = 4, }, { .bitrate = 55, .hw_value = 11, }, @@ -731,8 +729,8 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, } else { int i; - for (i = 0; i < ARRAY_SIZE(mwl8k_rates); i++) { - if (mwl8k_rates[i].hw_value == rxd->rate) { + for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) { + if (mwl8k_rates_24[i].hw_value == rxd->rate) { status->rate_idx = i; break; } @@ -1597,48 +1595,48 @@ struct mwl8k_cmd_get_hw_spec_sta { static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) { struct mwl8k_priv *priv = hw->priv; + struct ieee80211_supported_band *band = &priv->band_24; int rx_streams; int tx_streams; - priv->band.ht_cap.ht_supported = 1; + band->ht_cap.ht_supported = 1; if (cap & MWL8K_CAP_MAX_AMSDU) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; if (cap & MWL8K_CAP_GREENFIELD) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; + band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD; if (cap & MWL8K_CAP_AMPDU) { hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; - priv->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - priv->band.ht_cap.ampdu_density = - IEEE80211_HT_MPDU_DENSITY_NONE; + band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; } if (cap & MWL8K_CAP_RX_STBC) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; + band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC; if (cap & MWL8K_CAP_TX_STBC) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; + band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; if (cap & MWL8K_CAP_SHORTGI_40MHZ) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; if (cap & MWL8K_CAP_SHORTGI_20MHZ) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; if (cap & MWL8K_CAP_DELAY_BA) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; + band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA; if (cap & MWL8K_CAP_40MHZ) - priv->band.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK); tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK); - priv->band.ht_cap.mcs.rx_mask[0] = 0xff; + band->ht_cap.mcs.rx_mask[0] = 0xff; if (rx_streams >= 2) - priv->band.ht_cap.mcs.rx_mask[1] = 0xff; + band->ht_cap.mcs.rx_mask[1] = 0xff; if (rx_streams >= 3) - priv->band.ht_cap.mcs.rx_mask[2] = 0xff; - priv->band.ht_cap.mcs.rx_mask[4] = 0x01; - priv->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + band->ht_cap.mcs.rx_mask[2] = 0xff; + band->ht_cap.mcs.rx_mask[4] = 0x01; + band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; if (rx_streams != tx_streams) { - priv->band.ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; - priv->band.ht_cap.mcs.tx_params |= (tx_streams - 1) << + band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; + band->ht_cap.mcs.tx_params |= (tx_streams - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; } } @@ -2192,7 +2190,7 @@ static void legacy_rate_mask_to_array(u8 *rates, u32 mask) for (i = 0, j = 0; i < 14; i++) { if (mask & (1 << i)) - rates[j++] = mwl8k_rates[i].hw_value; + rates[j++] = mwl8k_rates_24[i].hw_value; } } @@ -3347,7 +3345,7 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * beacons will always go out at 1 Mb/s). */ idx = ffs(vif->bss_conf.basic_rates); - rate = idx ? mwl8k_rates[idx - 1].hw_value : 2; + rate = idx ? mwl8k_rates_24[idx - 1].hw_value : 2; mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate); } @@ -3855,16 +3853,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->pending_tx_pkts = 0; - memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(mwl8k_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24)); + priv->band_24.band = IEEE80211_BAND_2GHZ; + priv->band_24.channels = priv->channels_24; + priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); + priv->band_24.bitrates = priv->rates_24; + priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates)); - memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates)); + BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); + memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); /* * Extra headroom is the size of the required DMA header -- cgit v1.2.3 From 1349ad2f06f86f41415cf7ffa9e068fd4f89be87 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:48:17 +0100 Subject: mwl8k: move responsibility for initialising wiphy bands to GET_HW_SPEC So that we can make 2.4 GHz and 5 GHz band registration conditional on the capability bitmask returned by the firmware. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 37cbfbf21567..a17111f40266 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1557,6 +1557,28 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) return rc; } +/* + * Setup code shared between STA and AP firmware images. + */ +static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + + BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24)); + memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24)); + + BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); + memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); + + priv->band_24.band = IEEE80211_BAND_2GHZ; + priv->band_24.channels = priv->channels_24; + priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); + priv->band_24.bitrates = priv->rates_24; + priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; +} + /* * CMD_GET_HW_SPEC (STA version). */ @@ -1671,6 +1693,7 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; + mwl8k_setup_2ghz_band(hw); if (cmd->caps & cpu_to_le32(MWL8K_CAP_MIMO)) mwl8k_set_ht_caps(hw, le32_to_cpu(cmd->caps)); } @@ -1726,6 +1749,7 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; + mwl8k_setup_2ghz_band(hw); off = le32_to_cpu(cmd->wcbbase0) & 0xffff; iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); @@ -3853,17 +3877,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->pending_tx_pkts = 0; - memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24)); - priv->band_24.band = IEEE80211_BAND_2GHZ; - priv->band_24.channels = priv->channels_24; - priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24); - priv->band_24.bitrates = priv->rates_24; - priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; - - BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24)); - memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24)); - /* * Extra headroom is the size of the required DMA header * minus the size of the smallest 802.11 frame (CTS frame). -- cgit v1.2.3 From 4eae9edd38c0a9ce34e39100ccc69ff520bc1224 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:48:32 +0100 Subject: mwl8k: add 5 GHz band channels and rates Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index a17111f40266..13dded49323e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -144,6 +144,9 @@ struct mwl8k_priv { struct ieee80211_supported_band band_24; struct ieee80211_channel channels_24[14]; struct ieee80211_rate rates_24[14]; + struct ieee80211_supported_band band_50; + struct ieee80211_channel channels_50[4]; + struct ieee80211_rate rates_50[9]; /* firmware access */ struct mutex fw_mutex; @@ -252,6 +255,25 @@ static const struct ieee80211_rate mwl8k_rates_24[] = { { .bitrate = 720, .hw_value = 144, }, }; +static const struct ieee80211_channel mwl8k_channels_50[] = { + { .center_freq = 5180, .hw_value = 36, }, + { .center_freq = 5200, .hw_value = 40, }, + { .center_freq = 5220, .hw_value = 44, }, + { .center_freq = 5240, .hw_value = 48, }, +}; + +static const struct ieee80211_rate mwl8k_rates_50[] = { + { .bitrate = 60, .hw_value = 12, }, + { .bitrate = 90, .hw_value = 18, }, + { .bitrate = 120, .hw_value = 24, }, + { .bitrate = 180, .hw_value = 36, }, + { .bitrate = 240, .hw_value = 48, }, + { .bitrate = 360, .hw_value = 72, }, + { .bitrate = 480, .hw_value = 96, }, + { .bitrate = 540, .hw_value = 108, }, + { .bitrate = 720, .hw_value = 144, }, +}; + /* Set or get info from Firmware */ #define MWL8K_CMD_SET 0x0001 #define MWL8K_CMD_GET 0x0000 @@ -1579,6 +1601,25 @@ static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; } +static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw) +{ + struct mwl8k_priv *priv = hw->priv; + + BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50)); + memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50)); + + BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50)); + memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50)); + + priv->band_50.band = IEEE80211_BAND_5GHZ; + priv->band_50.channels = priv->channels_50; + priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50); + priv->band_50.bitrates = priv->rates_50; + priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50); + + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; +} + /* * CMD_GET_HW_SPEC (STA version). */ -- cgit v1.2.3 From 854783444bab0024556c0aefdb0a860f2f1da286 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:48:56 +0100 Subject: mwl8k: properly set receive status rate index on 5 GHz receive The mwl8k firmware uses indices into the 2.4 GHz band rate table for the receive descriptor channel field even if the packet was received on a 5 GHz channel, while mac80211 expects an index into the 5 GHz band rate table when packets are received on the 5 GHz band, which presents a mismatch as the 5 GHz band rate table lacks the five non-OFDM rates that the 2.4 GHz rate table starts with. To handle this properly, we need to substract 5 from the rate index field if the packet was received on a 5 GHz channel (and was not received at an MCS rate). Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 13dded49323e..cc2ce61b7992 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -759,7 +759,13 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, } } - status->band = IEEE80211_BAND_2GHZ; + if (rxd->channel > 14) { + status->band = IEEE80211_BAND_5GHZ; + if (!(status->flag & RX_FLAG_HT)) + status->rate_idx -= 5; + } else { + status->band = IEEE80211_BAND_2GHZ; + } status->freq = ieee80211_channel_to_frequency(rxd->channel); *qos = rxd->qos_control; @@ -850,7 +856,13 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) status->flag |= RX_FLAG_HT; - status->band = IEEE80211_BAND_2GHZ; + if (rxd->channel > 14) { + status->band = IEEE80211_BAND_5GHZ; + if (!(status->flag & RX_FLAG_HT)) + status->rate_idx -= 5; + } else { + status->band = IEEE80211_BAND_2GHZ; + } status->freq = ieee80211_channel_to_frequency(rxd->channel); *qos = rxd->qos_control; -- cgit v1.2.3 From 8707d0262585423cdc053bf8db0912e53915e5e4 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:49:15 +0100 Subject: mwl8k: handle 5 GHz legacy rate bitmaps in firmware commands Whenever mac80211 gives us a legacy rate bitmap in the context of the 5 GHz band, we need to remember to shift the bitmap left by 5 positions before giving it to the firmware, as the firmware follows the bitmap bit assignment of the 2.4 GHz rate table even if we're on the 5 GHz band, and the 2.4 GHz rate table includes five non-OFDM rates at the start that are not valid in the 5 GHz band. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index cc2ce61b7992..e370245b3901 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2836,6 +2836,7 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct mwl8k_cmd_set_new_stn *cmd; + u32 rates; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2848,7 +2849,11 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, memcpy(cmd->mac_addr, sta->addr, ETH_ALEN); cmd->stn_id = cpu_to_le16(sta->aid); cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD); - cmd->legacy_rates = cpu_to_le32(sta->supp_rates[IEEE80211_BAND_2GHZ]); + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) + rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; + else + rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; + cmd->legacy_rates = cpu_to_le32(rates); if (sta->ht_cap.ht_supported) { cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; @@ -2972,6 +2977,7 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, { struct mwl8k_cmd_update_stadb *cmd; struct peer_capability_info *p; + u32 rates; int rc; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -2990,8 +2996,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p->ht_caps = sta->ht_cap.cap; p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) | ((sta->ht_cap.ampdu_density & 7) << 2); - legacy_rate_mask_to_array(p->legacy_rates, - sta->supp_rates[IEEE80211_BAND_2GHZ]); + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) + rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; + else + rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; + legacy_rate_mask_to_array(p->legacy_rates, rates); memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16); p->interop = 1; p->amsdu_enabled = 0; @@ -3345,7 +3354,12 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif, goto out; } - ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) { + ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ]; + } else { + ap_legacy_rates = + ap->supp_rates[IEEE80211_BAND_5GHZ] << 5; + } memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16); rcu_read_unlock(); @@ -3422,7 +3436,13 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * beacons will always go out at 1 Mb/s). */ idx = ffs(vif->bss_conf.basic_rates); - rate = idx ? mwl8k_rates_24[idx - 1].hw_value : 2; + if (idx) + idx--; + + if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) + rate = mwl8k_rates_24[idx].hw_value; + else + rate = mwl8k_rates_50[idx].hw_value; mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate); } -- cgit v1.2.3 From 42574ea2274ec0a2a9c58ab01be91b65e60a2291 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:49:18 +0100 Subject: mwl8k: allow selecting 5 GHz channels Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index e370245b3901..6e8c126aa5e0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2222,6 +2222,8 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, if (channel->band == IEEE80211_BAND_2GHZ) cmd->channel_flags |= cpu_to_le32(0x00000001); + else if (channel->band == IEEE80211_BAND_5GHZ) + cmd->channel_flags |= cpu_to_le32(0x00000004); if (conf->channel_type == NL80211_CHAN_NO_HT || conf->channel_type == NL80211_CHAN_HT20) -- cgit v1.2.3 From 06953235f48c696b22c5ed45570680fb070f7277 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:49:41 +0100 Subject: mwl8k: use firmware capability field to decide which bands to register Make the decision about whether to register the 2.4 and 5 GHz bands with mac80211 by looking at the capability field in GET_HW_SPEC (STA firmware only for now). This enables 5 GHz STA operation. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6e8c126aa5e0..382ef4305a3e 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1666,11 +1666,14 @@ struct mwl8k_cmd_get_hw_spec_sta { #define MWL8K_CAP_DELAY_BA 0x00003000 #define MWL8K_CAP_MIMO 0x00000200 #define MWL8K_CAP_40MHZ 0x00000100 +#define MWL8K_CAP_BAND_MASK 0x00000007 +#define MWL8K_CAP_5GHZ 0x00000004 +#define MWL8K_CAP_2GHZ4 0x00000001 -static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) +static void +mwl8k_set_ht_caps(struct ieee80211_hw *hw, + struct ieee80211_supported_band *band, u32 cap) { - struct mwl8k_priv *priv = hw->priv; - struct ieee80211_supported_band *band = &priv->band_24; int rx_streams; int tx_streams; @@ -1716,6 +1719,24 @@ static void mwl8k_set_ht_caps(struct ieee80211_hw *hw, u32 cap) } } +static void +mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps) +{ + struct mwl8k_priv *priv = hw->priv; + + if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) { + mwl8k_setup_2ghz_band(hw); + if (caps & MWL8K_CAP_MIMO) + mwl8k_set_ht_caps(hw, &priv->band_24, caps); + } + + if (caps & MWL8K_CAP_5GHZ) { + mwl8k_setup_5ghz_band(hw); + if (caps & MWL8K_CAP_MIMO) + mwl8k_set_ht_caps(hw, &priv->band_50, caps); + } +} + static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) { struct mwl8k_priv *priv = hw->priv; @@ -1746,9 +1767,7 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; - mwl8k_setup_2ghz_band(hw); - if (cmd->caps & cpu_to_le32(MWL8K_CAP_MIMO)) - mwl8k_set_ht_caps(hw, le32_to_cpu(cmd->caps)); + mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); } kfree(cmd); -- cgit v1.2.3 From f5bb87cfba5ae9dd3724b846ac2fa7e033425c1c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:49:51 +0100 Subject: mwl8k: convert the priv->vif pointer to a list of vifs To prepare for adding multi-BSS support. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 51 ++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 382ef4305a3e..ee7d8a6329f8 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -160,7 +160,8 @@ struct mwl8k_priv { /* TX quiesce completion, protected by fw_mutex and tx_lock */ struct completion *tx_wait; - struct ieee80211_vif *vif; + /* List of interfaces. */ + struct list_head vif_list; /* power management status cookie from firmware */ u32 *cookie; @@ -210,6 +211,9 @@ struct mwl8k_priv { /* Per interface specific private data */ struct mwl8k_vif { + struct list_head list; + struct ieee80211_vif *vif; + /* Non AMPDU sequence number assigned by driver. */ u16 seqno; }; @@ -3246,7 +3250,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) } static int mwl8k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; @@ -3254,7 +3258,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, /* * We only support one active interface at a time. */ - if (priv->vif != NULL) + if (!list_empty(&priv->vif_list)) return -EBUSY; /* @@ -3275,14 +3279,13 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, if (priv->ap_fw) mwl8k_cmd_set_new_stn_add_self(hw, vif); - /* Clean out driver private area */ + /* Setup driver private area. */ mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); - - /* Set Initial sequence number to zero */ + mwl8k_vif->vif = vif; mwl8k_vif->seqno = 0; - priv->vif = vif; + list_add_tail(&mwl8k_vif->list, &priv->vif_list); return 0; } @@ -3291,13 +3294,14 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); if (priv->ap_fw) mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); - priv->vif = NULL; + list_del(&mwl8k_vif->list); } static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) @@ -3526,7 +3530,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, * operation, so refuse to enable sniffer mode if a STA * interface is active. */ - if (priv->vif != NULL) { + if (!list_empty(&priv->vif_list)) { if (net_ratelimit()) printk(KERN_INFO "%s: not enabling sniffer " "mode because STA interface is active\n", @@ -3547,6 +3551,14 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, return 1; } +static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv) +{ + if (!list_empty(&priv->vif_list)) + return list_entry(priv->vif_list.next, struct mwl8k_vif, list); + + return NULL; +} + static void mwl8k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *total_flags, @@ -3595,6 +3607,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, */ mwl8k_cmd_set_pre_scan(hw); } else { + struct mwl8k_vif *mwl8k_vif; const u8 *bssid; /* @@ -3605,9 +3618,11 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, * (where the OUI part needs to be nonzero for * the BSSID to be accepted by POST_SCAN). */ - bssid = "\x01\x00\x00\x00\x00\x00"; - if (priv->vif != NULL) - bssid = priv->vif->bss_conf.bssid; + mwl8k_vif = mwl8k_first_vif(priv); + if (mwl8k_vif != NULL) + bssid = mwl8k_vif->vif->bss_conf.bssid; + else + bssid = "\x01\x00\x00\x00\x00\x00"; mwl8k_cmd_set_post_scan(hw, bssid); } @@ -3810,11 +3825,14 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) struct mwl8k_priv *priv = container_of(work, struct mwl8k_priv, finalize_join_worker); struct sk_buff *skb = priv->beacon_skb; + struct mwl8k_vif *mwl8k_vif; - mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, - priv->vif->bss_conf.dtim_period); - dev_kfree_skb(skb); + mwl8k_vif = mwl8k_first_vif(priv); + if (mwl8k_vif != NULL) + mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, + mwl8k_vif->vif->bss_conf.dtim_period); + dev_kfree_skb(skb); priv->beacon_skb = NULL; } @@ -3986,7 +4004,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; hw->vif_data_size = sizeof(struct mwl8k_vif); hw->sta_data_size = sizeof(struct mwl8k_sta); - priv->vif = NULL; + + INIT_LIST_HEAD(&priv->vif_list); /* Set default radio state and preamble */ priv->radio_on = 0; -- cgit v1.2.3 From f57ca9c1af3c1e30a40ad99d75940176d8c3ff3a Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:50:14 +0100 Subject: mwl8k: prepare for posting per-vif firmware commands One of the bytes in the mwl8k firmware command header is the 'macid' byte, which for per-vif commands indicates which of the BSSes this command is intended for. (For commands that are not per-vif commands, this byte can just be 0.) This patch adds mwl8k_post_pervif_cmd(), which will take the macid assigned to this interface (to be done in ->add_interface()), copy it into the command packet macid field, and post the command as usual. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ee7d8a6329f8..ea39ef64defe 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -214,6 +214,9 @@ struct mwl8k_vif { struct list_head list; struct ieee80211_vif *vif; + /* Firmware macid for this vif. */ + int macid; + /* Non AMPDU sequence number assigned by driver. */ u16 seqno; }; @@ -419,7 +422,8 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) struct mwl8k_cmd_pkt { __le16 code; __le16 length; - __le16 seq_num; + __u8 seq_num; + __u8 macid; __le16 result; char payload[0]; } __attribute__((packed)); @@ -477,6 +481,7 @@ static int mwl8k_load_fw_image(struct mwl8k_priv *priv, cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); cmd->seq_num = 0; + cmd->macid = 0; cmd->result = 0; done = 0; @@ -1595,6 +1600,15 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) return rc; } +static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct mwl8k_cmd_pkt *cmd) +{ + if (vif != NULL) + cmd->macid = MWL8K_VIF(vif)->macid; + return mwl8k_post_cmd(hw, cmd); +} + /* * Setup code shared between STA and AP firmware images. */ @@ -3283,6 +3297,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); mwl8k_vif->vif = vif; + mwl8k_vif->macid = 0; mwl8k_vif->seqno = 0; list_add_tail(&mwl8k_vif->list, &priv->vif_list); -- cgit v1.2.3 From aa21d0f69a5ca28d33f584b8952cca154115fd26 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:50:36 +0100 Subject: mwl8k: post per-vif firmware commands as per-vif commands SET_BEACON, SET_MAC_ADDR, BSS_START and SET_NEW_STN are the currently supported firmware commands that are actually per-vif commands. Use mwl8k_post_pervif_cmd() for these commands, so that the macid of the vif they operate on gets passed down into the firmware. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 49 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ea39ef64defe..d8cf43853de1 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -294,7 +294,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_RADIO_CONTROL 0x001c #define MWL8K_CMD_RF_TX_POWER 0x001e #define MWL8K_CMD_RF_ANTENNA 0x0020 -#define MWL8K_CMD_SET_BEACON 0x0100 +#define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */ #define MWL8K_CMD_SET_PRE_SCAN 0x0107 #define MWL8K_CMD_SET_POST_SCAN 0x0108 #define MWL8K_CMD_SET_RF_CHANNEL 0x010a @@ -308,10 +308,10 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { #define MWL8K_CMD_MIMO_CONFIG 0x0125 #define MWL8K_CMD_USE_FIXED_RATE 0x0126 #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 -#define MWL8K_CMD_SET_MAC_ADDR 0x0202 +#define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 -#define MWL8K_CMD_BSS_START 0x1100 -#define MWL8K_CMD_SET_NEW_STN 0x1111 +#define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ +#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define MWL8K_CMD_UPDATE_STADB 0x1123 static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) @@ -2156,7 +2156,8 @@ struct mwl8k_cmd_set_beacon { __u8 beacon[0]; }; -static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, u8 *beacon, int len) +static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *beacon, int len) { struct mwl8k_cmd_set_beacon *cmd; int rc; @@ -2170,7 +2171,7 @@ static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw, u8 *beacon, int len) cmd->beacon_len = cpu_to_le16(len); memcpy(cmd->beacon, beacon, len); - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -2761,7 +2762,8 @@ struct mwl8k_cmd_set_mac_addr { #define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 #define MWL8K_MAC_TYPE_PRIMARY_AP 2 -static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) +static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac) { struct mwl8k_priv *priv = hw->priv; struct mwl8k_cmd_set_mac_addr *cmd; @@ -2780,7 +2782,7 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) memcpy(cmd->mac_addr, mac, ETH_ALEN); } - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -2823,7 +2825,8 @@ struct mwl8k_cmd_bss_start { __le32 enable; } __attribute__((packed)); -static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, int enable) +static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int enable) { struct mwl8k_cmd_bss_start *cmd; int rc; @@ -2836,7 +2839,7 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw, int enable) cmd->header.length = cpu_to_le16(sizeof(*cmd)); cmd->enable = cpu_to_le32(enable); - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -2904,7 +2907,7 @@ static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw, cmd->is_qos_sta = 1; } - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -2924,7 +2927,7 @@ static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw, cmd->header.length = cpu_to_le16(sizeof(*cmd)); memcpy(cmd->mac_addr, vif->addr, ETH_ALEN); - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -2945,7 +2948,7 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, memcpy(cmd->mac_addr, addr, ETH_ALEN); cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE); - rc = mwl8k_post_cmd(hw, &cmd->header); + rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); kfree(cmd); return rc; @@ -3287,12 +3290,6 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, return -EINVAL; } - /* Set the mac address. */ - mwl8k_cmd_set_mac_addr(hw, vif->addr); - - if (priv->ap_fw) - mwl8k_cmd_set_new_stn_add_self(hw, vif); - /* Setup driver private area. */ mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); @@ -3300,6 +3297,12 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, mwl8k_vif->macid = 0; mwl8k_vif->seqno = 0; + /* Set the mac address. */ + mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); + + if (priv->ap_fw) + mwl8k_cmd_set_new_stn_add_self(hw, vif); + list_add_tail(&mwl8k_vif->list, &priv->vif_list); return 0; @@ -3314,7 +3317,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, if (priv->ap_fw) mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr); - mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); + mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); list_del(&mwl8k_vif->list); } @@ -3492,13 +3495,13 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, skb = ieee80211_beacon_get(hw, vif); if (skb != NULL) { - mwl8k_cmd_set_beacon(hw, skb->data, skb->len); + mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len); kfree_skb(skb); } } if (changed & BSS_CHANGED_BEACON_ENABLED) - mwl8k_cmd_bss_start(hw, info->enable_beacon); + mwl8k_cmd_bss_start(hw, vif, info->enable_beacon); out: mwl8k_fw_unlock(hw); @@ -4112,7 +4115,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, } /* Clear MAC address */ - rc = mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); + rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); if (rc) { printk(KERN_ERR "%s: Cannot clear MAC address\n", wiphy_name(hw->wiphy)); -- cgit v1.2.3 From ee0ddf1865954f44ee929d963e2c968eb377f447 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:51:30 +0100 Subject: mwl8k: enable multi-BSS AP operation As follows: - GET_HW_SPEC is now responsible for setting priv->{ap,sta}_macids_supported, which are bitmasks of supported macids for AP and STA mode. (Typically, STA firmware images will support only one macid, #0, in STA mode, and AP firmware images will support macids #0-7, in AP mode.) - Our wiphy ->interfaces_modes is now set based on the non-zero-ness of these two bitmasks. - We main priv->macids_used, a bitmask of which macids are currently in use. ->add_interface() will assign the lowest free macid for this interface type as it is created, or bail out if there are no more free macids to assign. ->delete_interface() will mark the macid as being free again. This enables the multi-BSS code added in the previous commits. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 70 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d8cf43853de1..06dc7a0978a0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -147,6 +147,8 @@ struct mwl8k_priv { struct ieee80211_supported_band band_50; struct ieee80211_channel channels_50[4]; struct ieee80211_rate rates_50[9]; + u32 ap_macids_supported; + u32 sta_macids_supported; /* firmware access */ struct mutex fw_mutex; @@ -161,6 +163,7 @@ struct mwl8k_priv { struct completion *tx_wait; /* List of interfaces. */ + u32 macids_used; struct list_head vif_list; /* power management status cookie from firmware */ @@ -1786,6 +1789,8 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); + priv->ap_macids_supported = 0x00000000; + priv->sta_macids_supported = 0x00000001; } kfree(cmd); @@ -1840,6 +1845,8 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->hw_rev = cmd->hw_rev; mwl8k_setup_2ghz_band(hw); + priv->ap_macids_supported = 0x000000ff; + priv->sta_macids_supported = 0x00000000; off = le32_to_cpu(cmd->wcbbase0) & 0xffff; iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); @@ -2759,16 +2766,33 @@ struct mwl8k_cmd_set_mac_addr { }; } __attribute__((packed)); -#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 -#define MWL8K_MAC_TYPE_PRIMARY_AP 2 +#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0 +#define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1 +#define MWL8K_MAC_TYPE_PRIMARY_AP 2 +#define MWL8K_MAC_TYPE_SECONDARY_AP 3 static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *mac) { struct mwl8k_priv *priv = hw->priv; + struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); struct mwl8k_cmd_set_mac_addr *cmd; + int mac_type; int rc; + mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; + if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) { + if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported)) + mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT; + else + mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT; + } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) { + if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported)) + mac_type = MWL8K_MAC_TYPE_PRIMARY_AP; + else + mac_type = MWL8K_MAC_TYPE_SECONDARY_AP; + } + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -2776,7 +2800,7 @@ static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); cmd->header.length = cpu_to_le16(sizeof(*cmd)); if (priv->ap_fw) { - cmd->mbss.mac_type = cpu_to_le16(MWL8K_MAC_TYPE_PRIMARY_AP); + cmd->mbss.mac_type = cpu_to_le16(mac_type); memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); } else { memcpy(cmd->mac_addr, mac, ETH_ALEN); @@ -3271,12 +3295,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, { struct mwl8k_priv *priv = hw->priv; struct mwl8k_vif *mwl8k_vif; - - /* - * We only support one active interface at a time. - */ - if (!list_empty(&priv->vif_list)) - return -EBUSY; + u32 macids_supported; + int macid; /* * Reject interface creation if sniffer mode is active, as @@ -3290,11 +3310,27 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, return -EINVAL; } + + switch (vif->type) { + case NL80211_IFTYPE_AP: + macids_supported = priv->ap_macids_supported; + break; + case NL80211_IFTYPE_STATION: + macids_supported = priv->sta_macids_supported; + break; + default: + return -EINVAL; + } + + macid = ffs(macids_supported & ~priv->macids_used); + if (!macid--) + return -EBUSY; + /* Setup driver private area. */ mwl8k_vif = MWL8K_VIF(vif); memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); mwl8k_vif->vif = vif; - mwl8k_vif->macid = 0; + mwl8k_vif->macid = macid; mwl8k_vif->seqno = 0; /* Set the mac address. */ @@ -3303,6 +3339,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, if (priv->ap_fw) mwl8k_cmd_set_new_stn_add_self(hw, vif); + priv->macids_used |= 1 << mwl8k_vif->macid; list_add_tail(&mwl8k_vif->list, &priv->vif_list); return 0; @@ -3319,6 +3356,7 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00"); + priv->macids_used &= ~(1 << mwl8k_vif->macid); list_del(&mwl8k_vif->list); } @@ -4023,6 +4061,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, hw->vif_data_size = sizeof(struct mwl8k_vif); hw->sta_data_size = sizeof(struct mwl8k_sta); + priv->macids_used = 0; INIT_LIST_HEAD(&priv->vif_list); /* Set default radio state and preamble */ @@ -4094,12 +4133,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_get_hw_spec_ap(hw); if (!rc) rc = mwl8k_cmd_set_hw_spec(hw); - - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP); } else { rc = mwl8k_cmd_get_hw_spec_sta(hw); - - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } if (rc) { printk(KERN_ERR "%s: Cannot initialise firmware\n", @@ -4107,6 +4142,13 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, goto err_free_irq; } + hw->wiphy->interface_modes = 0; + if (priv->ap_macids_supported) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); + if (priv->sta_macids_supported) + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); + + /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { -- cgit v1.2.3 From a5fb297d634ba20bd53a7d6fecd611bbfd342e78 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 12 Jan 2010 13:51:38 +0100 Subject: mwl8k: update version number (to 0.12) and copyright Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 06dc7a0978a0..68546ca0ba37 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -2,7 +2,7 @@ * drivers/net/wireless/mwl8k.c * Driver for Marvell TOPDOG 802.11 Wireless cards * - * Copyright (C) 2008-2009 Marvell Semiconductor Inc. + * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -26,7 +26,7 @@ #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" #define MWL8K_NAME KBUILD_MODNAME -#define MWL8K_VERSION "0.11" +#define MWL8K_VERSION "0.12" /* Register definitions */ #define MWL8K_HIU_GEN_PTR 0x00000c10 -- cgit v1.2.3 From cd8c20b650f49354722b8cc1f03320b004815a0a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 13 Jan 2010 16:02:14 +0100 Subject: netfilter: nfnetlink: netns support Make nfnl socket per-petns. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter/nfnetlink.h | 8 ++--- include/net/net_namespace.h | 2 ++ net/netfilter/nf_conntrack_netlink.c | 13 ++++---- net/netfilter/nfnetlink.c | 65 +++++++++++++++++++++++------------- net/netfilter/nfnetlink_log.c | 3 +- net/netfilter/nfnetlink_queue.c | 2 +- 6 files changed, 58 insertions(+), 35 deletions(-) diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 49d321f3ccd2..53923868c9bd 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -73,11 +73,11 @@ struct nfnetlink_subsystem { extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); -extern int nfnetlink_has_listeners(unsigned int group); -extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, +extern int nfnetlink_has_listeners(struct net *net, unsigned int group); +extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo, gfp_t flags); -extern void nfnetlink_set_err(u32 pid, u32 group, int error); -extern int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags); +extern void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); +extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); extern void nfnl_lock(void); extern void nfnl_unlock(void); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index f307e133d14c..82b7be4db89a 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -81,6 +81,8 @@ struct net { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct netns_ct ct; #endif + struct sock *nfnl; + struct sock *nfnl_stash; #endif #ifdef CONFIG_XFRM struct netns_xfrm xfrm; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 59d8064eb522..d4c5d06677f9 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -482,7 +482,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) } else return 0; - if (!item->report && !nfnetlink_has_listeners(group)) + if (!item->report && !nfnetlink_has_listeners(&init_net, group)) return 0; skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); @@ -559,7 +559,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) rcu_read_unlock(); nlmsg_end(skb, nlh); - err = nfnetlink_send(skb, item->pid, group, item->report, GFP_ATOMIC); + err = nfnetlink_send(skb, &init_net, item->pid, group, item->report, + GFP_ATOMIC); if (err == -ENOBUFS || err == -EAGAIN) return -ENOBUFS; @@ -571,7 +572,7 @@ nla_put_failure: nlmsg_failure: kfree_skb(skb); errout: - nfnetlink_set_err(0, group, -ENOBUFS); + nfnetlink_set_err(&init_net, 0, group, -ENOBUFS); return 0; } #endif /* CONFIG_NF_CONNTRACK_EVENTS */ @@ -1539,7 +1540,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) return 0; if (!item->report && - !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) + !nfnetlink_has_listeners(&init_net, NFNLGRP_CONNTRACK_EXP_NEW)) return 0; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); @@ -1562,7 +1563,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) rcu_read_unlock(); nlmsg_end(skb, nlh); - nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, + nfnetlink_send(skb, &init_net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report, GFP_ATOMIC); return 0; @@ -1572,7 +1573,7 @@ nla_put_failure: nlmsg_failure: kfree_skb(skb); errout: - nfnetlink_set_err(0, 0, -ENOBUFS); + nfnetlink_set_err(&init_net, 0, 0, -ENOBUFS); return 0; } #endif diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index eedc0c1ac7a4..8eb0cc23ada3 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -40,7 +40,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); static char __initdata nfversion[] = "0.30"; -static struct sock *nfnl = NULL; static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; static DEFINE_MUTEX(nfnl_mutex); @@ -101,34 +100,35 @@ nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss) return &ss->cb[cb_id]; } -int nfnetlink_has_listeners(unsigned int group) +int nfnetlink_has_listeners(struct net *net, unsigned int group) { - return netlink_has_listeners(nfnl, group); + return netlink_has_listeners(net->nfnl, group); } EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); -int nfnetlink_send(struct sk_buff *skb, u32 pid, +int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo, gfp_t flags) { - return nlmsg_notify(nfnl, skb, pid, group, echo, flags); + return nlmsg_notify(net->nfnl, skb, pid, group, echo, flags); } EXPORT_SYMBOL_GPL(nfnetlink_send); -void nfnetlink_set_err(u32 pid, u32 group, int error) +void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) { - netlink_set_err(nfnl, pid, group, error); + netlink_set_err(net->nfnl, pid, group, error); } EXPORT_SYMBOL_GPL(nfnetlink_set_err); -int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) +int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags) { - return netlink_unicast(nfnl, skb, pid, flags); + return netlink_unicast(net->nfnl, skb, pid, flags); } EXPORT_SYMBOL_GPL(nfnetlink_unicast); /* Process one complete nfnetlink message. */ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { + struct net *net = sock_net(skb->sk); const struct nfnl_callback *nc; const struct nfnetlink_subsystem *ss; int type, err; @@ -170,7 +170,7 @@ replay: if (err < 0) return err; - err = nc->call(nfnl, skb, nlh, (const struct nlattr **)cda); + err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda); if (err == -EAGAIN) goto replay; return err; @@ -184,26 +184,45 @@ static void nfnetlink_rcv(struct sk_buff *skb) nfnl_unlock(); } -static void __exit nfnetlink_exit(void) +static int __net_init nfnetlink_net_init(struct net *net) { - printk("Removing netfilter NETLINK layer.\n"); - netlink_kernel_release(nfnl); - return; + struct sock *nfnl; + + nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX, + nfnetlink_rcv, NULL, THIS_MODULE); + if (!nfnl) + return -ENOMEM; + net->nfnl_stash = nfnl; + rcu_assign_pointer(net->nfnl, nfnl); + return 0; } -static int __init nfnetlink_init(void) +static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list) { - printk("Netfilter messages via NETLINK v%s.\n", nfversion); + struct net *net; - nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX, - nfnetlink_rcv, NULL, THIS_MODULE); - if (!nfnl) { - printk(KERN_ERR "cannot initialize nfnetlink!\n"); - return -ENOMEM; - } + list_for_each_entry(net, net_exit_list, exit_list) + rcu_assign_pointer(net->nfnl, NULL); + synchronize_net(); + list_for_each_entry(net, net_exit_list, exit_list) + netlink_kernel_release(net->nfnl_stash); +} - return 0; +static struct pernet_operations nfnetlink_net_ops = { + .init = nfnetlink_net_init, + .exit_batch = nfnetlink_net_exit_batch, +}; + +static int __init nfnetlink_init(void) +{ + printk("Netfilter messages via NETLINK v%s.\n", nfversion); + return register_pernet_subsys(&nfnetlink_net_ops); } +static void __exit nfnetlink_exit(void) +{ + printk("Removing netfilter NETLINK layer.\n"); + unregister_pernet_subsys(&nfnetlink_net_ops); +} module_init(nfnetlink_init); module_exit(nfnetlink_exit); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 9de0470d557e..285e9029a9ff 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -323,7 +323,8 @@ __nfulnl_send(struct nfulnl_instance *inst) NLMSG_DONE, sizeof(struct nfgenmsg)); - status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); + status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_pid, + MSG_DONTWAIT); inst->qlen = 0; inst->skb = NULL; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7e3fa410641e..5c589b27d6eb 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -420,7 +420,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) } /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; -- cgit v1.2.3 From 9592a5c01e79dbc59eb56fa26b124e94ffcd0962 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 13 Jan 2010 16:04:18 +0100 Subject: netfilter: ctnetlink: netns support Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 65 +++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index d4c5d06677f9..79478dfba27e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -456,6 +457,7 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct) static int ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) { + struct net *net; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; struct nlattr *nest_parms; @@ -482,7 +484,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) } else return 0; - if (!item->report && !nfnetlink_has_listeners(&init_net, group)) + net = nf_ct_net(ct); + if (!item->report && !nfnetlink_has_listeners(net, group)) return 0; skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); @@ -559,7 +562,7 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) rcu_read_unlock(); nlmsg_end(skb, nlh); - err = nfnetlink_send(skb, &init_net, item->pid, group, item->report, + err = nfnetlink_send(skb, net, item->pid, group, item->report, GFP_ATOMIC); if (err == -ENOBUFS || err == -EAGAIN) return -ENOBUFS; @@ -572,7 +575,7 @@ nla_put_failure: nlmsg_failure: kfree_skb(skb); errout: - nfnetlink_set_err(&init_net, 0, group, -ENOBUFS); + nfnetlink_set_err(net, 0, group, -ENOBUFS); return 0; } #endif /* CONFIG_NF_CONNTRACK_EVENTS */ @@ -587,6 +590,7 @@ static int ctnetlink_done(struct netlink_callback *cb) static int ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { + struct net *net = sock_net(skb->sk); struct nf_conn *ct, *last; struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; @@ -597,7 +601,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: - hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], + hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[cb->args[0]], hnnode) { if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; @@ -769,6 +773,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; struct nf_conn *ct; @@ -782,7 +787,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); else { /* Flush the whole table */ - nf_conntrack_flush_report(&init_net, + nf_conntrack_flush_report(net, NETLINK_CB(skb).pid, nlmsg_report(nlh)); return 0; @@ -791,7 +796,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(&init_net, &tuple); + h = nf_conntrack_find_get(net, &tuple); if (!h) return -ENOENT; @@ -829,6 +834,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; struct nf_conn *ct; @@ -851,7 +857,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(&init_net, &tuple); + h = nf_conntrack_find_get(net, &tuple); if (!h) return -ENOENT; @@ -1176,7 +1182,8 @@ ctnetlink_change_conntrack(struct nf_conn *ct, } static struct nf_conn * -ctnetlink_create_conntrack(const struct nlattr * const cda[], +ctnetlink_create_conntrack(struct net *net, + const struct nlattr * const cda[], struct nf_conntrack_tuple *otuple, struct nf_conntrack_tuple *rtuple, u8 u3) @@ -1185,7 +1192,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[], int err = -EINVAL; struct nf_conntrack_helper *helper; - ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC); + ct = nf_conntrack_alloc(net, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) return ERR_PTR(-ENOMEM); @@ -1286,7 +1293,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[], if (err < 0) goto err2; - master_h = nf_conntrack_find_get(&init_net, &master); + master_h = nf_conntrack_find_get(net, &master); if (master_h == NULL) { err = -ENOENT; goto err2; @@ -1314,6 +1321,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_tuple otuple, rtuple; struct nf_conntrack_tuple_hash *h = NULL; struct nfgenmsg *nfmsg = nlmsg_data(nlh); @@ -1334,9 +1342,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, spin_lock_bh(&nf_conntrack_lock); if (cda[CTA_TUPLE_ORIG]) - h = __nf_conntrack_find(&init_net, &otuple); + h = __nf_conntrack_find(net, &otuple); else if (cda[CTA_TUPLE_REPLY]) - h = __nf_conntrack_find(&init_net, &rtuple); + h = __nf_conntrack_find(net, &rtuple); if (h == NULL) { err = -ENOENT; @@ -1344,7 +1352,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conn *ct; enum ip_conntrack_events events; - ct = ctnetlink_create_conntrack(cda, &otuple, + ct = ctnetlink_create_conntrack(net, cda, &otuple, &rtuple, u3); if (IS_ERR(ct)) { err = PTR_ERR(ct); @@ -1526,9 +1534,10 @@ nla_put_failure: static int ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) { + struct nf_conntrack_expect *exp = item->exp; + struct net *net = nf_ct_exp_net(exp); struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; - struct nf_conntrack_expect *exp = item->exp; struct sk_buff *skb; unsigned int type; int flags = 0; @@ -1540,7 +1549,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) return 0; if (!item->report && - !nfnetlink_has_listeners(&init_net, NFNLGRP_CONNTRACK_EXP_NEW)) + !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW)) return 0; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); @@ -1563,7 +1572,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) rcu_read_unlock(); nlmsg_end(skb, nlh); - nfnetlink_send(skb, &init_net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, + nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, item->report, GFP_ATOMIC); return 0; @@ -1573,7 +1582,7 @@ nla_put_failure: nlmsg_failure: kfree_skb(skb); errout: - nfnetlink_set_err(&init_net, 0, 0, -ENOBUFS); + nfnetlink_set_err(net, 0, 0, -ENOBUFS); return 0; } #endif @@ -1587,7 +1596,7 @@ static int ctnetlink_exp_done(struct netlink_callback *cb) static int ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = &init_net; + struct net *net = sock_net(skb->sk); struct nf_conntrack_expect *exp, *last; struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); struct hlist_node *n; @@ -1640,6 +1649,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; struct sk_buff *skb2; @@ -1661,7 +1671,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = nf_ct_expect_find_get(&init_net, &tuple); + exp = nf_ct_expect_find_get(net, &tuple); if (!exp) return -ENOENT; @@ -1701,6 +1711,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_expect *exp; struct nf_conntrack_tuple tuple; struct nf_conntrack_helper *h; @@ -1717,7 +1728,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = nf_ct_expect_find_get(&init_net, &tuple); + exp = nf_ct_expect_find_get(net, &tuple); if (!exp) return -ENOENT; @@ -1747,7 +1758,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, } for (i = 0; i < nf_ct_expect_hsize; i++) { hlist_for_each_entry_safe(exp, n, next, - &init_net.ct.expect_hash[i], + &net->ct.expect_hash[i], hnode) { m_help = nfct_help(exp->master); if (m_help->helper == h @@ -1763,7 +1774,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, spin_lock_bh(&nf_conntrack_lock); for (i = 0; i < nf_ct_expect_hsize; i++) { hlist_for_each_entry_safe(exp, n, next, - &init_net.ct.expect_hash[i], + &net->ct.expect_hash[i], hnode) { if (del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); @@ -1784,7 +1795,8 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, } static int -ctnetlink_create_expect(const struct nlattr * const cda[], u_int8_t u3, +ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], + u_int8_t u3, u32 pid, int report) { struct nf_conntrack_tuple tuple, mask, master_tuple; @@ -1806,7 +1818,7 @@ ctnetlink_create_expect(const struct nlattr * const cda[], u_int8_t u3, return err; /* Look for master conntrack of this expectation */ - h = nf_conntrack_find_get(&init_net, &master_tuple); + h = nf_conntrack_find_get(net, &master_tuple); if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); @@ -1846,6 +1858,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const cda[]) { + struct net *net = sock_net(ctnl); struct nf_conntrack_tuple tuple; struct nf_conntrack_expect *exp; struct nfgenmsg *nfmsg = nlmsg_data(nlh); @@ -1862,13 +1875,13 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, return err; spin_lock_bh(&nf_conntrack_lock); - exp = __nf_ct_expect_find(&init_net, &tuple); + exp = __nf_ct_expect_find(net, &tuple); if (!exp) { spin_unlock_bh(&nf_conntrack_lock); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) { - err = ctnetlink_create_expect(cda, + err = ctnetlink_create_expect(net, cda, u3, NETLINK_CB(skb).pid, nlmsg_report(nlh)); -- cgit v1.2.3 From 0159f24ee764927bf44c1a25473bd4517febd21c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 13 Jan 2010 20:23:30 -0800 Subject: lib/vsprintf.c: Add IPV4 options %pI4[hnbl] for host, network, big and little endian This should allow the removal of the #defines and uses of NIPQUAD and NIPQUAD_FMT Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- lib/vsprintf.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index e83e3e79a989..add0446dd921 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -699,13 +699,37 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, return string(buf, end, mac_addr, spec); } -static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) +static char *ip4_string(char *p, const u8 *addr, const char *fmt) { int i; - + bool leading_zeros = (fmt[0] == 'i'); + int index; + int step; + + switch (fmt[2]) { + case 'h': +#ifdef __BIG_ENDIAN + index = 0; + step = 1; +#else + index = 3; + step = -1; +#endif + break; + case 'l': + index = 3; + step = -1; + break; + case 'n': + case 'b': + default: + index = 0; + step = 1; + break; + } for (i = 0; i < 4; i++) { char temp[3]; /* hold each IP quad in reverse order */ - int digits = put_dec_trunc(temp, addr[i]) - temp; + int digits = put_dec_trunc(temp, addr[index]) - temp; if (leading_zeros) { if (digits < 3) *p++ = '0'; @@ -717,6 +741,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) *p++ = temp[digits]; if (i < 3) *p++ = '.'; + index += step; } *p = '\0'; @@ -796,7 +821,7 @@ static char *ip6_compressed_string(char *p, const char *addr) if (useIPv4) { if (needcolon) *p++ = ':'; - p = ip4_string(p, &in6.s6_addr[12], false); + p = ip4_string(p, &in6.s6_addr[12], "I4"); } *p = '\0'; @@ -836,7 +861,7 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, { char ip4_addr[sizeof("255.255.255.255")]; - ip4_string(ip4_addr, addr, fmt[0] == 'i'); + ip4_string(ip4_addr, addr, fmt); return string(buf, end, ip4_addr, spec); } @@ -911,6 +936,7 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, * - 'i' [46] for 'raw' IPv4/IPv6 addresses * IPv6 omits the colons (01020304...0f) * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) + * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order * - 'I6c' for IPv6 addresses printed as specified by * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form -- cgit v1.2.3 From 608f8a0d014db6cd18d4f535934d4b5d556e3013 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 02:04:58 +0000 Subject: e1000e: use alternate MAC address on ESB2 if available Similar to 82571/2/3 parts that already do this, if ESB2/80003es2lan parts have an alternate MAC address provided in the EEPROM use it instead of the default MAC address. This patch makes the the actual code that does this generic so that it can be better used by both MAC families. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 33 ++++++++++-- drivers/net/e1000e/defines.h | 2 + drivers/net/e1000e/e1000.h | 11 +++- drivers/net/e1000e/es2lan.c | 28 +++++++++- drivers/net/e1000e/hw.h | 5 +- drivers/net/e1000e/lib.c | 124 +++++++++++++++++++++++++------------------ drivers/net/e1000e/netdev.c | 2 +- 7 files changed, 147 insertions(+), 58 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 02d67d047d96..d1a45143c2aa 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -922,9 +922,12 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); icr = er32(ICR); - if (hw->mac.type == e1000_82571 && - hw->dev_spec.e82571.alt_mac_addr_is_present) - e1000e_set_laa_state_82571(hw, true); + /* Install any alternate MAC address into RAR0 */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + return ret_val; + + e1000e_set_laa_state_82571(hw, true); /* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes) @@ -1620,6 +1623,29 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) return 0; } +/** + * e1000_read_mac_addr_82571 - Read device MAC address + * @hw: pointer to the HW structure + **/ +static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) +{ + s32 ret_val = 0; + + /* + * If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + goto out; + + ret_val = e1000_read_mac_addr_generic(hw); + +out: + return ret_val; +} + /** * e1000_power_down_phy_copper_82571 - Remove link during PHY power down * @hw: pointer to the HW structure @@ -1706,6 +1732,7 @@ static struct e1000_mac_operations e82571_mac_ops = { .setup_link = e1000_setup_link_82571, /* .setup_physical_interface: media type dependent */ .setup_led = e1000e_setup_led_generic, + .read_mac_addr = e1000_read_mac_addr_82571, }; static struct e1000_phy_operations e82_phy_ops_igp = { diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index e02e38221ed4..db05ec355749 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -460,6 +460,8 @@ */ #define E1000_RAR_ENTRIES 15 #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ +#define E1000_RAL_MAC_ADDR_LEN 4 +#define E1000_RAH_MAC_ADDR_LEN 2 /* Error Codes */ #define E1000_ERR_NVM 1 diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cebbd9079d53..7c91e4bdd361 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -529,6 +529,7 @@ extern s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); extern s32 e1000e_force_mac_fc(struct e1000_hw *hw); extern s32 e1000e_blink_led(struct e1000_hw *hw); extern void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); +extern s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); extern void e1000e_reset_adaptive(struct e1000_hw *hw); extern void e1000e_update_adaptive(struct e1000_hw *hw); @@ -629,7 +630,15 @@ extern s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 extern s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); extern void e1000e_release_nvm(struct e1000_hw *hw); extern void e1000e_reload_nvm(struct e1000_hw *hw); -extern s32 e1000e_read_mac_addr(struct e1000_hw *hw); +extern s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); + +static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) +{ + if (hw->mac.ops.read_mac_addr) + return hw->mac.ops.read_mac_addr(hw); + + return e1000_read_mac_addr_generic(hw); +} static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) { diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index e2aa3b788564..4bb9d88ad976 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -814,7 +814,9 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) ew32(IMC, 0xffffffff); icr = er32(ICR); - return 0; + ret_val = e1000_check_alt_mac_addr_generic(hw); + + return ret_val; } /** @@ -1339,6 +1341,29 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, return ret_val; } +/** + * e1000_read_mac_addr_80003es2lan - Read device MAC address + * @hw: pointer to the HW structure + **/ +static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) +{ + s32 ret_val = 0; + + /* + * If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + goto out; + + ret_val = e1000_read_mac_addr_generic(hw); + +out: + return ret_val; +} + /** * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down * @hw: pointer to the HW structure @@ -1403,6 +1428,7 @@ static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) } static struct e1000_mac_operations es2_mac_ops = { + .read_mac_addr = e1000_read_mac_addr_80003es2lan, .id_led_init = e1000e_id_led_init, .check_mng_mode = e1000e_check_mng_mode_generic, /* check_for_link dependent on media type */ diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index eccf29b75c41..127e6a226da1 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -389,6 +389,9 @@ enum e1e_registers { #define E1000_FUNC_1 1 +#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 +#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 + enum e1000_mac_type { e1000_82571, e1000_82572, @@ -756,6 +759,7 @@ struct e1000_mac_operations { s32 (*setup_physical_interface)(struct e1000_hw *); s32 (*setup_led)(struct e1000_hw *); void (*write_vfta)(struct e1000_hw *, u32, u32); + s32 (*read_mac_addr)(struct e1000_hw *); }; /* Function pointers for the PHY. */ @@ -897,7 +901,6 @@ struct e1000_fc_info { struct e1000_dev_spec_82571 { bool laa_is_present; - bool alt_mac_addr_is_present; u32 smb_counter; }; diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 2fa9b36a2c5a..547542428edc 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -138,6 +138,68 @@ void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) e1000e_rar_set(hw, mac_addr, i); } +/** + * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr + * @hw: pointer to the HW structure + * + * Checks the nvm for an alternate MAC address. An alternate MAC address + * can be setup by pre-boot software and must be treated like a permanent + * address and must override the actual permanent MAC address. If an + * alternate MAC address is found it is programmed into RAR0, replacing + * the permanent address that was installed into RAR0 by the Si on reset. + * This function will return SUCCESS unless it encounters an error while + * reading the EEPROM. + **/ +s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) +{ + u32 i; + s32 ret_val = 0; + u16 offset, nvm_alt_mac_addr_offset, nvm_data; + u8 alt_mac_addr[ETH_ALEN]; + + ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, + &nvm_alt_mac_addr_offset); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + + if (nvm_alt_mac_addr_offset == 0xFFFF) { + /* There is no Alternate MAC Address */ + goto out; + } + + if (hw->bus.func == E1000_FUNC_1) + nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; + for (i = 0; i < ETH_ALEN; i += 2) { + offset = nvm_alt_mac_addr_offset + (i >> 1); + ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); + if (ret_val) { + e_dbg("NVM Read Error\n"); + goto out; + } + + alt_mac_addr[i] = (u8)(nvm_data & 0xFF); + alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); + } + + /* if multicast bit is set, the alternate address will not be used */ + if (alt_mac_addr[0] & 0x01) { + e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); + goto out; + } + + /* + * We have a valid alternate MAC address, and we want to treat it the + * same as the normal permanent MAC address stored by the HW into the + * RAR. Do this by mapping this address into RAR0. + */ + e1000e_rar_set(hw, alt_mac_addr, 0); + +out: + return ret_val; +} + /** * e1000e_rar_set - Set receive address register * @hw: pointer to the HW structure @@ -2072,67 +2134,27 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) } /** - * e1000e_read_mac_addr - Read device MAC address + * e1000_read_mac_addr_generic - Read device MAC address * @hw: pointer to the HW structure * * Reads the device MAC address from the EEPROM and stores the value. * Since devices with two ports use the same EEPROM, we increment the * last bit in the MAC address for the second port. **/ -s32 e1000e_read_mac_addr(struct e1000_hw *hw) +s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) { - s32 ret_val; - u16 offset, nvm_data, i; - u16 mac_addr_offset = 0; - - if (hw->mac.type == e1000_82571) { - /* Check for an alternate MAC address. An alternate MAC - * address can be setup by pre-boot software and must be - * treated like a permanent address and must override the - * actual permanent MAC address.*/ - ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &mac_addr_offset); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - if (mac_addr_offset == 0xFFFF) - mac_addr_offset = 0; - - if (mac_addr_offset) { - if (hw->bus.func == E1000_FUNC_1) - mac_addr_offset += ETH_ALEN/sizeof(u16); - - /* make sure we have a valid mac address here - * before using it */ - ret_val = e1000_read_nvm(hw, mac_addr_offset, 1, - &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - if (nvm_data & 0x0001) - mac_addr_offset = 0; - } + u32 rar_high; + u32 rar_low; + u16 i; - if (mac_addr_offset) - hw->dev_spec.e82571.alt_mac_addr_is_present = 1; - } + rar_high = er32(RAH(0)); + rar_low = er32(RAL(0)); - for (i = 0; i < ETH_ALEN; i += 2) { - offset = mac_addr_offset + (i >> 1); - ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); - hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); - } + for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8)); - /* Flip last bit of mac address if we're on second port */ - if (!mac_addr_offset && hw->bus.func == E1000_FUNC_1) - hw->mac.perm_addr[5] ^= 1; + for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) + hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8)); for (i = 0; i < ETH_ALEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c3745c9d21aa..0d5ef4c5c6db 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5135,7 +5135,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, e1000_eeprom_checks(adapter); - /* copy the MAC address out of the NVM */ + /* copy the MAC address */ if (e1000e_read_mac_addr(&adapter->hw)) e_err("NVM Read Error while reading MAC address\n"); -- cgit v1.2.3 From f4d2dd4cd4d001f5dc20fc76c780c0c20c000c23 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 02:05:18 +0000 Subject: e1000e: provide MAC-family-specific function to set LAN ID Provide MAC-specific function pointer to determine the LAN ID (PCI func). The LAN ID is used internally by the driver to determine which h/w lock to use to protect accessing the PHY on ESB2 as well as help to determine the alternate MAC address on some parts. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 7 +++++++ drivers/net/e1000e/e1000.h | 2 ++ drivers/net/e1000e/es2lan.c | 4 ++++ drivers/net/e1000e/hw.h | 1 + drivers/net/e1000e/ich8lan.c | 1 + drivers/net/e1000e/lib.c | 48 ++++++++++++++++++++++++++++++++++---------- 6 files changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index d1a45143c2aa..7674a91824bc 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -267,8 +267,14 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) } switch (hw->mac.type) { + case e1000_82573: + func->set_lan_id = e1000_set_lan_id_single_port; + func->check_mng_mode = e1000e_check_mng_mode_generic; + func->led_on = e1000e_led_on_generic; + break; case e1000_82574: case e1000_82583: + func->set_lan_id = e1000_set_lan_id_single_port; func->check_mng_mode = e1000_check_mng_mode_82574; func->led_on = e1000_led_on_82574; break; @@ -1721,6 +1727,7 @@ static struct e1000_mac_operations e82571_mac_ops = { .cleanup_led = e1000e_cleanup_led_generic, .clear_hw_cntrs = e1000_clear_hw_cntrs_82571, .get_bus_info = e1000e_get_bus_info_pcie, + .set_lan_id = e1000_set_lan_id_multi_port_pcie, /* .get_link_up_info: media type dependent */ /* .led_on: mac type dependent */ .led_off = e1000e_led_off_generic, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 7c91e4bdd361..8b311ce0400e 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -502,6 +502,8 @@ extern s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); extern s32 e1000e_led_on_generic(struct e1000_hw *hw); extern s32 e1000e_led_off_generic(struct e1000_hw *hw); extern s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); +extern void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); +extern void e1000_set_lan_id_single_port(struct e1000_hw *hw); extern s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex); extern s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex); extern s32 e1000e_disable_pcie_master(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index 4bb9d88ad976..27d21589a69a 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c @@ -246,6 +246,9 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_adapter *adapter) break; } + /* set lan id for port to determine which phy lock to use */ + hw->mac.ops.set_lan_id(hw); + return 0; } @@ -1435,6 +1438,7 @@ static struct e1000_mac_operations es2_mac_ops = { .cleanup_led = e1000e_cleanup_led_generic, .clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan, .get_bus_info = e1000e_get_bus_info_pcie, + .set_lan_id = e1000_set_lan_id_multi_port_pcie, .get_link_up_info = e1000_get_link_up_info_80003es2lan, .led_on = e1000e_led_on_generic, .led_off = e1000e_led_off_generic, diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 127e6a226da1..9cac5d9b94b8 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -749,6 +749,7 @@ struct e1000_mac_operations { void (*clear_hw_cntrs)(struct e1000_hw *); void (*clear_vfta)(struct e1000_hw *); s32 (*get_bus_info)(struct e1000_hw *); + void (*set_lan_id)(struct e1000_hw *); s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); s32 (*led_on)(struct e1000_hw *); s32 (*led_off)(struct e1000_hw *); diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index ad08cf3f40c0..061cd100aac2 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -3302,6 +3302,7 @@ static struct e1000_mac_operations ich8_mac_ops = { /* cleanup_led dependent on mac type */ .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, .get_bus_info = e1000_get_bus_info_ich8lan, + .set_lan_id = e1000_set_lan_id_single_port, .get_link_up_info = e1000_get_link_up_info_ich8lan, /* led_on dependent on mac type */ /* led_off dependent on mac type */ diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 547542428edc..5f6b17148d34 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -51,10 +51,10 @@ enum e1000_mng_mode { **/ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) { + struct e1000_mac_info *mac = &hw->mac; struct e1000_bus_info *bus = &hw->bus; struct e1000_adapter *adapter = hw->adapter; - u32 status; - u16 pcie_link_status, pci_header_type, cap_offset; + u16 pcie_link_status, cap_offset; cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP); if (!cap_offset) { @@ -68,19 +68,45 @@ s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) PCIE_LINK_WIDTH_SHIFT); } - pci_read_config_word(adapter->pdev, PCI_HEADER_TYPE_REGISTER, - &pci_header_type); - if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) { - status = er32(STATUS); - bus->func = (status & E1000_STATUS_FUNC_MASK) - >> E1000_STATUS_FUNC_SHIFT; - } else { - bus->func = 0; - } + mac->ops.set_lan_id(hw); return 0; } +/** + * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices + * + * @hw: pointer to the HW structure + * + * Determines the LAN function id by reading memory-mapped registers + * and swaps the port value if requested. + **/ +void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + u32 reg; + + /* + * The status register reports the correct function number + * for the device regardless of function swap state. + */ + reg = er32(STATUS); + bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; +} + +/** + * e1000_set_lan_id_single_port - Set LAN id for a single port device + * @hw: pointer to the HW structure + * + * Sets the LAN function id to zero for a single port device. + **/ +void e1000_set_lan_id_single_port(struct e1000_hw *hw) +{ + struct e1000_bus_info *bus = &hw->bus; + + bus->func = 0; +} + /** * e1000_clear_vfta_generic - Clear VLAN filter table * @hw: pointer to the HW structure -- cgit v1.2.3 From ab8932f3e8e07df92d6ce3fa41f5af0dda865429 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 02:05:38 +0000 Subject: e1000e: genericize the update multicast address list Make updating the multicast address list generic for all families and enforce the requirement to update the entire multicast table array all at once instead of piecemeal which causes problems on some parts. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 28 +--------------------- drivers/net/e1000e/e1000.h | 4 +--- drivers/net/e1000e/hw.h | 6 ++++- drivers/net/e1000e/lib.c | 58 ++++++++++++--------------------------------- drivers/net/e1000e/netdev.c | 20 ++++------------ 5 files changed, 27 insertions(+), 89 deletions(-) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 7674a91824bc..3c95acb3a87d 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1233,32 +1233,6 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw) return 0; } -/** - * e1000_update_mc_addr_list_82571 - Update Multicast addresses - * @hw: pointer to the HW structure - * @mc_addr_list: array of multicast addresses to program - * @mc_addr_count: number of multicast addresses to program - * @rar_used_count: the first RAR register free to program - * @rar_count: total number of supported Receive Address Registers - * - * Updates the Receive Address Registers and Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - * The parameter rar_count will usually be hw->mac.rar_entry_count - * unless there are workarounds that change this. - **/ -static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw, - u8 *mc_addr_list, - u32 mc_addr_count, - u32 rar_used_count, - u32 rar_count) -{ - if (e1000e_get_laa_state_82571(hw)) - rar_count--; - - e1000e_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count, - rar_used_count, rar_count); -} - /** * e1000_setup_link_82571 - Setup flow control and link settings * @hw: pointer to the HW structure @@ -1731,7 +1705,7 @@ static struct e1000_mac_operations e82571_mac_ops = { /* .get_link_up_info: media type dependent */ /* .led_on: mac type dependent */ .led_off = e1000e_led_off_generic, - .update_mc_addr_list = e1000_update_mc_addr_list_82571, + .update_mc_addr_list = e1000e_update_mc_addr_list_generic, .write_vfta = e1000_write_vfta_generic, .clear_vfta = e1000_clear_vfta_82571, .reset_hw = e1000_reset_hw_82571, diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 8b311ce0400e..aec378e7441d 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -518,9 +518,7 @@ extern void e1000_clear_vfta_generic(struct e1000_hw *hw); extern void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); extern void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count, - u32 rar_used_count, - u32 rar_count); + u32 mc_addr_count); extern void e1000e_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); extern s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); extern void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 9cac5d9b94b8..8bdcd5f24eff 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -753,7 +753,7 @@ struct e1000_mac_operations { s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); s32 (*led_on)(struct e1000_hw *); s32 (*led_off)(struct e1000_hw *); - void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32); + void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); s32 (*reset_hw)(struct e1000_hw *); s32 (*init_hw)(struct e1000_hw *); s32 (*setup_link)(struct e1000_hw *); @@ -819,6 +819,10 @@ struct e1000_mac_info { u16 ifs_ratio; u16 ifs_step_size; u16 mta_reg_count; + + /* Maximum size of the MTA register table in all supported adapters */ + #define MAX_MTA_REG 128 + u32 mta_shadow[MAX_MTA_REG]; u16 rar_entry_count; u8 forced_speed_duplex; diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index 5f6b17148d34..2425ed11d5cc 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -340,62 +340,34 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program - * @rar_used_count: the first RAR register free to program - * @rar_count: total number of supported Receive Address Registers * - * Updates the Receive Address Registers and Multicast Table Array. + * Updates entire Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. - * The parameter rar_count will usually be hw->mac.rar_entry_count - * unless there are workarounds that change this. **/ void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count, - u32 rar_used_count, u32 rar_count) + u8 *mc_addr_list, u32 mc_addr_count) { - u32 i; - u32 *mcarray = kzalloc(hw->mac.mta_reg_count * sizeof(u32), GFP_ATOMIC); + u32 hash_value, hash_bit, hash_reg; + int i; - if (!mcarray) { - printk(KERN_ERR "multicast array memory allocation failed\n"); - return; - } + /* clear mta_shadow */ + memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - /* - * Load the first set of multicast addresses into the exact - * filters (RAR). If there are not enough to fill the RAR - * array, clear the filters. - */ - for (i = rar_used_count; i < rar_count; i++) { - if (mc_addr_count) { - e1000e_rar_set(hw, mc_addr_list, i); - mc_addr_count--; - mc_addr_list += ETH_ALEN; - } else { - E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0); - e1e_flush(); - E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0); - e1e_flush(); - } - } - - /* Load any remaining multicast addresses into the hash table. */ - for (; mc_addr_count > 0; mc_addr_count--) { - u32 hash_value, hash_reg, hash_bit, mta; + /* update mta_shadow from mc_addr_list */ + for (i = 0; (u32) i < mc_addr_count; i++) { hash_value = e1000_hash_mc_addr(hw, mc_addr_list); - e_dbg("Hash value = 0x%03X\n", hash_value); + hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); hash_bit = hash_value & 0x1F; - mta = (1 << hash_bit); - mcarray[hash_reg] |= mta; - mc_addr_list += ETH_ALEN; - } - /* write the hash table completely */ - for (i = 0; i < hw->mac.mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, mcarray[i]); + hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); + mc_addr_list += (ETH_ALEN); + } + /* replace the entire MTA table */ + for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) + E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); e1e_flush(); - kfree(mcarray); } /** diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 0d5ef4c5c6db..3d57ca5482f4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2536,22 +2536,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) * @hw: pointer to the HW structure * @mc_addr_list: array of multicast addresses to program * @mc_addr_count: number of multicast addresses to program - * @rar_used_count: the first RAR register free to program - * @rar_count: total number of supported Receive Address Registers * - * Updates the Receive Address Registers and Multicast Table Array. + * Updates the Multicast Table Array. * The caller must have a packed mc_addr_list of multicast addresses. - * The parameter rar_count will usually be hw->mac.rar_entry_count - * unless there are workarounds that change this. Currently no func pointer - * exists and all implementations are handled in the generic version of this - * function. **/ static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list, - u32 mc_addr_count, u32 rar_used_count, - u32 rar_count) + u32 mc_addr_count) { - hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count, - rar_used_count, rar_count); + hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count); } /** @@ -2567,7 +2559,6 @@ static void e1000_set_multi(struct net_device *netdev) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct e1000_mac_info *mac = &hw->mac; struct dev_mc_list *mc_ptr; u8 *mta_list; u32 rctl; @@ -2609,15 +2600,14 @@ static void e1000_set_multi(struct net_device *netdev) mc_ptr = mc_ptr->next; } - e1000_update_mc_addr_list(hw, mta_list, i, 1, - mac->rar_entry_count); + e1000_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); } else { /* * if we're called from probe, we might not have * anything to do here, so clear out the list */ - e1000_update_mc_addr_list(hw, NULL, 0, 1, mac->rar_entry_count); + e1000_update_mc_addr_list(hw, NULL, 0); } } -- cgit v1.2.3 From 76b11f8e270f04851774ff64b16e29e5a43d3a1a Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 11 Jan 2010 02:50:50 +0000 Subject: qeth: HiperSockets Network Traffic Analyzer New feature to trace HiperSockets network traffic for debugging purposes. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 5 +- drivers/s390/net/qeth_core_main.c | 130 ++++++++++++++++------------ drivers/s390/net/qeth_core_mpc.h | 44 +++++++++- drivers/s390/net/qeth_core_sys.c | 8 +- drivers/s390/net/qeth_l2_main.c | 3 +- drivers/s390/net/qeth_l3.h | 2 + drivers/s390/net/qeth_l3_main.c | 174 ++++++++++++++++++++++++++++++++------ drivers/s390/net/qeth_l3_sys.c | 56 ++++++++++++ 8 files changed, 336 insertions(+), 86 deletions(-) diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index b232693378cd..a3ac4456e0b1 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -649,6 +649,7 @@ struct qeth_card_options { int performance_stats; int rx_sg_cb; enum qeth_ipa_isolation_modes isolation; + int sniffer; }; /* @@ -737,6 +738,7 @@ struct qeth_card { struct qeth_discipline discipline; atomic_t force_alloc_skb; struct service_level qeth_service_level; + struct qdio_ssqd_desc ssqd; }; struct qeth_card_list_struct { @@ -811,7 +813,8 @@ int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *, enum qeth_ipa_cmds, enum qeth_prot_versions); int qeth_query_setadapterparms(struct qeth_card *); -int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int, const char *); +int qeth_check_qdio_errors(struct qeth_card *, struct qdio_buffer *, + unsigned int, const char *); void qeth_queue_input_buffer(struct qeth_card *, int); struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, struct qdio_buffer *, struct qdio_buffer_element **, int *, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d34804d5ece1..2c8e9da8753f 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -269,6 +269,7 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) card->qdio.init_pool.buf_count = bufcnt; return qeth_alloc_buffer_pool(card); } +EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool); static int qeth_issue_next_read(struct qeth_card *card) { @@ -350,8 +351,10 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, if (IS_IPA(iob->data)) { cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data); if (IS_IPA_REPLY(cmd)) { - if (cmd->hdr.command < IPA_CMD_SETCCID || - cmd->hdr.command > IPA_CMD_MODCCID) + if (cmd->hdr.command != IPA_CMD_SETCCID && + cmd->hdr.command != IPA_CMD_DELCCID && + cmd->hdr.command != IPA_CMD_MODCCID && + cmd->hdr.command != IPA_CMD_SET_DIAG_ASS) qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card); return cmd; @@ -1100,11 +1103,6 @@ static int qeth_setup_card(struct qeth_card *card) card->thread_running_mask = 0; INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread); INIT_LIST_HEAD(&card->ip_list); - card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); - if (!card->ip_tbd_list) { - QETH_DBF_TEXT(SETUP, 0, "iptbdnom"); - return -ENOMEM; - } INIT_LIST_HEAD(card->ip_tbd_list); INIT_LIST_HEAD(&card->cmd_waiter_list); init_waitqueue_head(&card->wait_q); @@ -1138,21 +1136,30 @@ static struct qeth_card *qeth_alloc_card(void) QETH_DBF_TEXT(SETUP, 2, "alloccrd"); card = kzalloc(sizeof(struct qeth_card), GFP_DMA|GFP_KERNEL); if (!card) - return NULL; + goto out; QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); - if (qeth_setup_channel(&card->read)) { - kfree(card); - return NULL; - } - if (qeth_setup_channel(&card->write)) { - qeth_clean_channel(&card->read); - kfree(card); - return NULL; + card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); + if (!card->ip_tbd_list) { + QETH_DBF_TEXT(SETUP, 0, "iptbdnom"); + goto out_card; } + if (qeth_setup_channel(&card->read)) + goto out_ip; + if (qeth_setup_channel(&card->write)) + goto out_channel; card->options.layer2 = -1; card->qeth_service_level.seq_print = qeth_core_sl_print; register_service_level(&card->qeth_service_level); return card; + +out_channel: + qeth_clean_channel(&card->read); +out_ip: + kfree(card->ip_tbd_list); +out_card: + kfree(card); +out: + return NULL; } static int qeth_determine_card_type(struct qeth_card *card) @@ -2573,8 +2580,8 @@ int qeth_query_setadapterparms(struct qeth_card *card) } EXPORT_SYMBOL_GPL(qeth_query_setadapterparms); -int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, - const char *dbftext) +int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, + unsigned int qdio_error, const char *dbftext) { if (qdio_error) { QETH_DBF_TEXT(TRACE, 2, dbftext); @@ -2584,7 +2591,11 @@ int qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, QETH_DBF_TEXT_(QERR, 2, " F14=%02X", buf->element[14].flags & 0xff); QETH_DBF_TEXT_(QERR, 2, " qerr=%X", qdio_error); - return 1; + if ((buf->element[15].flags & 0xff) == 0x12) { + card->stats.rx_dropped++; + return 0; + } else + return 1; } return 0; } @@ -2667,7 +2678,7 @@ static int qeth_handle_send_error(struct qeth_card *card, qdio_err = 1; } } - qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); + qeth_check_qdio_errors(card, buffer->buffer, qdio_err, "qouterr"); if (!qdio_err) return QETH_SEND_ERROR_NONE; @@ -3509,6 +3520,7 @@ void qeth_tx_timeout(struct net_device *dev) { struct qeth_card *card; + QETH_DBF_TEXT(TRACE, 4, "txtimeo"); card = dev->ml_priv; card->stats.tx_errors++; qeth_schedule_recovery(card); @@ -3847,9 +3859,7 @@ static int qeth_core_driver_group(const char *buf, struct device *root_dev, int qeth_core_hardsetup_card(struct qeth_card *card) { - struct qdio_ssqd_desc *ssqd; int retries = 0; - int mpno = 0; int rc; QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); @@ -3882,31 +3892,6 @@ retriable: else goto retry; } - - rc = qeth_get_unitaddr(card); - if (rc) { - QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); - return rc; - } - - ssqd = kmalloc(sizeof(struct qdio_ssqd_desc), GFP_KERNEL); - if (!ssqd) { - rc = -ENOMEM; - goto out; - } - rc = qdio_get_ssqd_desc(CARD_DDEV(card), ssqd); - if (rc == 0) - mpno = ssqd->pcnt; - kfree(ssqd); - - if (mpno) - mpno = min(mpno - 1, QETH_MAX_PORTNO); - if (card->info.portno > mpno) { - QETH_DBF_MESSAGE(2, "Device %s does not offer port number %d" - "\n.", CARD_BUS_ID(card), card->info.portno); - rc = -ENODEV; - goto out; - } qeth_init_tokens(card); qeth_init_func_level(card); rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb); @@ -3990,7 +3975,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, struct qdio_buffer_element *element = *__element; int offset = *__offset; struct sk_buff *skb = NULL; - int skb_len; + int skb_len = 0; void *data_ptr; int data_len; int headroom = 0; @@ -4009,20 +3994,24 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, *hdr = element->addr + offset; offset += sizeof(struct qeth_hdr); - if (card->options.layer2) { - if (card->info.type == QETH_CARD_TYPE_OSN) { - skb_len = (*hdr)->hdr.osn.pdu_length; - headroom = sizeof(struct qeth_hdr); - } else { - skb_len = (*hdr)->hdr.l2.pkt_length; - } - } else { + switch ((*hdr)->hdr.l2.id) { + case QETH_HEADER_TYPE_LAYER2: + skb_len = (*hdr)->hdr.l2.pkt_length; + break; + case QETH_HEADER_TYPE_LAYER3: skb_len = (*hdr)->hdr.l3.length; if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || (card->info.link_type == QETH_LINK_TYPE_HSTR)) headroom = TR_HLEN; else headroom = ETH_HLEN; + break; + case QETH_HEADER_TYPE_OSN: + skb_len = (*hdr)->hdr.osn.pdu_length; + headroom = sizeof(struct qeth_hdr); + break; + default: + break; } if (!skb_len) @@ -4177,6 +4166,33 @@ void qeth_core_free_discipline(struct qeth_card *card) card->discipline.ccwgdriver = NULL; } +static void qeth_determine_capabilities(struct qeth_card *card) +{ + int rc; + + QETH_DBF_TEXT(SETUP, 2, "detcapab"); + rc = ccw_device_set_online(CARD_DDEV(card)); + if (rc) { + QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); + goto out; + } + + rc = qeth_get_unitaddr(card); + if (rc) { + QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); + goto out_offline; + } + + rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); + if (rc) + QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); + +out_offline: + ccw_device_set_offline(CARD_DDEV(card)); +out: + return; +} + static int qeth_core_probe_device(struct ccwgroup_device *gdev) { struct qeth_card *card; @@ -4242,6 +4258,8 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) write_lock_irqsave(&qeth_core_card_list.rwlock, flags); list_add_tail(&card->list, &qeth_core_card_list.list); write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags); + + qeth_determine_capabilities(card); return 0; err_card: diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 1ba51152f667..104a3351e02b 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -156,6 +156,8 @@ enum qeth_ipa_return_codes { IPA_RC_IP_TABLE_FULL = 0x0002, IPA_RC_UNKNOWN_ERROR = 0x0003, IPA_RC_UNSUPPORTED_COMMAND = 0x0004, + IPA_RC_TRACE_ALREADY_ACTIVE = 0x0005, + IPA_RC_INVALID_FORMAT = 0x0006, IPA_RC_DUP_IPV6_REMOTE = 0x0008, IPA_RC_DUP_IPV6_HOME = 0x0010, IPA_RC_UNREGISTERED_ADDR = 0x0011, @@ -196,6 +198,11 @@ enum qeth_ipa_return_codes { IPA_RC_INVALID_IP_VERSION2 = 0xf001, IPA_RC_FFFF = 0xffff }; +/* for DELIP */ +#define IPA_RC_IP_ADDRESS_NOT_DEFINED IPA_RC_PRIMARY_ALREADY_DEFINED +/* for SET_DIAGNOSTIC_ASSIST */ +#define IPA_RC_INVALID_SUBCMD IPA_RC_IP_TABLE_FULL +#define IPA_RC_HARDWARE_AUTH_ERROR IPA_RC_UNKNOWN_ERROR /* IPA function flags; each flag marks availability of respective function */ enum qeth_ipa_funcs { @@ -246,6 +253,7 @@ enum qeth_ipa_setadp_cmd { IPA_SETADP_SET_SNMP_CONTROL = 0x00000200L, IPA_SETADP_QUERY_CARD_INFO = 0x00000400L, IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, + IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, }; enum qeth_ipa_mac_ops { @@ -424,6 +432,40 @@ struct qeth_create_destroy_address { __u8 unique_id[8]; } __attribute__ ((packed)); +/* SET DIAGNOSTIC ASSIST IPA Command: *************************************/ + +enum qeth_diags_cmds { + QETH_DIAGS_CMD_QUERY = 0x0001, + QETH_DIAGS_CMD_TRAP = 0x0002, + QETH_DIAGS_CMD_TRACE = 0x0004, + QETH_DIAGS_CMD_NOLOG = 0x0008, + QETH_DIAGS_CMD_DUMP = 0x0010, +}; + +enum qeth_diags_trace_types { + QETH_DIAGS_TYPE_HIPERSOCKET = 0x02, +}; + +enum qeth_diags_trace_cmds { + QETH_DIAGS_CMD_TRACE_ENABLE = 0x0001, + QETH_DIAGS_CMD_TRACE_DISABLE = 0x0002, + QETH_DIAGS_CMD_TRACE_MODIFY = 0x0004, + QETH_DIAGS_CMD_TRACE_REPLACE = 0x0008, + QETH_DIAGS_CMD_TRACE_QUERY = 0x0010, +}; + +struct qeth_ipacmd_diagass { + __u32 host_tod2; + __u32:32; + __u16 subcmd_len; + __u16:16; + __u32 subcmd; + __u8 type; + __u8 action; + __u16 options; + __u32:32; +} __attribute__ ((packed)); + /* Header for each IPA command */ struct qeth_ipacmd_hdr { __u8 command; @@ -452,6 +494,7 @@ struct qeth_ipa_cmd { struct qeth_create_destroy_address create_destroy_addr; struct qeth_ipacmd_setadpparms setadapterparms; struct qeth_set_routing setrtg; + struct qeth_ipacmd_diagass diagass; } data; } __attribute__ ((packed)); @@ -469,7 +512,6 @@ enum qeth_ipa_arp_return_codes { QETH_IPA_ARP_RC_Q_NO_DATA = 0x0008, }; - extern char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc); extern char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 9ff2b36fdc43..ac2239a4f133 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -118,7 +118,7 @@ static ssize_t qeth_dev_portno_store(struct device *dev, { struct qeth_card *card = dev_get_drvdata(dev); char *tmp; - unsigned int portno; + unsigned int portno, limit; if (!card) return -EINVAL; @@ -128,9 +128,11 @@ static ssize_t qeth_dev_portno_store(struct device *dev, return -EPERM; portno = simple_strtoul(buf, &tmp, 16); - if (portno > QETH_MAX_PORTNO) { + if (portno > QETH_MAX_PORTNO) + return -EINVAL; + limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt); + if (portno > limit) return -EINVAL; - } card->info.portno = portno; return count; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 038299ae3feb..74ba388a159f 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -769,7 +769,8 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev, index = i % QDIO_MAX_BUFFERS_PER_Q; buffer = &card->qdio.in_q->bufs[index]; if (!(qdio_err && - qeth_check_qdio_errors(buffer->buffer, qdio_err, "qinerr"))) + qeth_check_qdio_errors(card, buffer->buffer, qdio_err, + "qinerr"))) qeth_l2_process_inbound_buffer(card, buffer, index); /* clear buffer and give back to hardware */ qeth_put_buffer_pool_entry(card, buffer->pool_entry); diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 321988fa9f7d..8447d233d0b3 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h @@ -13,6 +13,8 @@ #include "qeth_core.h" +#define QETH_SNIFF_AVAIL 0x0008 + struct qeth_ipaddr { struct list_head entry; enum qeth_ip_types type; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fd1b6ed3721f..337d03fb045d 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -242,6 +242,8 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *tmp, *t; int found = 0; + if (card->options.sniffer) + return 0; list_for_each_entry_safe(tmp, t, card->ip_tbd_list, entry) { if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) @@ -457,6 +459,8 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) QETH_DBF_TEXT(TRACE, 2, "sdiplist"); QETH_DBF_HEX(TRACE, 2, &card, sizeof(void *)); + if (card->options.sniffer) + return; spin_lock_irqsave(&card->ip_lock, flags); tbd_list = card->ip_tbd_list; card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); @@ -495,7 +499,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) spin_unlock_irqrestore(&card->ip_lock, flags); rc = qeth_l3_deregister_addr_entry(card, addr); spin_lock_irqsave(&card->ip_lock, flags); - if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED)) + if (!rc || (rc == IPA_RC_IP_ADDRESS_NOT_DEFINED)) kfree(addr); else list_add_tail(&addr->entry, &card->ip_list); @@ -513,6 +517,8 @@ static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean, unsigned long flags; QETH_DBF_TEXT(TRACE, 4, "clearip"); + if (recover && card->options.sniffer) + return; spin_lock_irqsave(&card->ip_lock, flags); /* clear todo list */ list_for_each_entry_safe(addr, tmp, card->ip_tbd_list, entry) { @@ -1674,6 +1680,76 @@ static int qeth_l3_get_unique_id(struct qeth_card *card) return rc; } +static int +qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd; + __u16 rc; + + QETH_DBF_TEXT(SETUP, 2, "diastrcb"); + + cmd = (struct qeth_ipa_cmd *)data; + rc = cmd->hdr.return_code; + if (rc) { + QETH_DBF_TEXT_(TRACE, 2, "dxter%x", rc); + if (cmd->data.diagass.action == QETH_DIAGS_CMD_TRACE_ENABLE) { + switch (rc) { + case IPA_RC_HARDWARE_AUTH_ERROR: + dev_warn(&card->gdev->dev, "The device is not " + "authorized to run as a HiperSockets " + "network traffic analyzer\n"); + break; + case IPA_RC_TRACE_ALREADY_ACTIVE: + dev_warn(&card->gdev->dev, "A HiperSockets " + "network traffic analyzer is already " + "active in the HiperSockets LAN\n"); + break; + default: + break; + } + } + return 0; + } + + switch (cmd->data.diagass.action) { + case QETH_DIAGS_CMD_TRACE_QUERY: + break; + case QETH_DIAGS_CMD_TRACE_DISABLE: + card->info.promisc_mode = SET_PROMISC_MODE_OFF; + dev_info(&card->gdev->dev, "The HiperSockets network traffic " + "analyzer is deactivated\n"); + break; + case QETH_DIAGS_CMD_TRACE_ENABLE: + card->info.promisc_mode = SET_PROMISC_MODE_ON; + dev_info(&card->gdev->dev, "The HiperSockets network traffic " + "analyzer is activated\n"); + break; + default: + QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", + cmd->data.diagass.action, QETH_CARD_IFNAME(card)); + } + + return 0; +} + +static int +qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd) +{ + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; + + QETH_DBF_TEXT(SETUP, 2, "diagtrac"); + + iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0); + cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); + cmd->data.diagass.subcmd_len = 16; + cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE; + cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET; + cmd->data.diagass.action = diags_cmd; + return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL); +} + static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev) { @@ -1951,7 +2027,10 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, case QETH_CAST_ANYCAST: case QETH_CAST_NOCAST: default: - skb->pkt_type = PACKET_HOST; + if (card->options.sniffer) + skb->pkt_type = PACKET_OTHERHOST; + else + skb->pkt_type = PACKET_HOST; memcpy(tg_addr, card->dev->dev_addr, card->dev->addr_len); } @@ -2007,7 +2086,6 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, int offset; __u16 vlan_tag = 0; unsigned int len; - /* get first element of current buffer */ element = (struct qdio_buffer_element *)&buf->buffer->element[0]; offset = 0; @@ -2026,7 +2104,7 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, case QETH_HEADER_TYPE_LAYER3: vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); len = skb->len; - if (vlan_tag) + if (vlan_tag && !card->options.sniffer) if (card->vlangrp) vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); @@ -2037,6 +2115,16 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, else netif_rx(skb); break; + case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ + skb->pkt_type = PACKET_HOST; + skb->protocol = eth_type_trans(skb, skb->dev); + if (card->options.checksum_type == NO_CHECKSUMMING) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; + netif_receive_skb(skb); + break; default: dev_kfree_skb_any(skb); QETH_DBF_TEXT(TRACE, 3, "inbunkno"); @@ -2118,6 +2206,9 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, 0, 1); + if (card->options.sniffer && + (card->info.promisc_mode == SET_PROMISC_MODE_ON)) + qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE); if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { @@ -2162,6 +2253,36 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) return rc; } +/* + * test for and Switch promiscuous mode (on or off) + * either for guestlan or HiperSocket Sniffer + */ +static void +qeth_l3_handle_promisc_mode(struct qeth_card *card) +{ + struct net_device *dev = card->dev; + + if (((dev->flags & IFF_PROMISC) && + (card->info.promisc_mode == SET_PROMISC_MODE_ON)) || + (!(dev->flags & IFF_PROMISC) && + (card->info.promisc_mode == SET_PROMISC_MODE_OFF))) + return; + + if (card->info.guestlan) { /* Guestlan trace */ + if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) + qeth_setadp_promisc_mode(card); + } else if (card->options.sniffer && /* HiperSockets trace */ + qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) { + if (dev->flags & IFF_PROMISC) { + QETH_DBF_TEXT(TRACE, 3, "+promisc"); + qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_ENABLE); + } else { + QETH_DBF_TEXT(TRACE, 3, "-promisc"); + qeth_diags_trace(card, QETH_DIAGS_CMD_TRACE_DISABLE); + } + } +} + static void qeth_l3_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; @@ -2170,15 +2291,17 @@ static void qeth_l3_set_multicast_list(struct net_device *dev) if (qeth_threads_running(card, QETH_RECOVER_THREAD) && (card->state != CARD_STATE_UP)) return; - qeth_l3_delete_mc_addresses(card); - qeth_l3_add_multicast_ipv4(card); + if (!card->options.sniffer) { + qeth_l3_delete_mc_addresses(card); + qeth_l3_add_multicast_ipv4(card); #ifdef CONFIG_QETH_IPV6 - qeth_l3_add_multicast_ipv6(card); + qeth_l3_add_multicast_ipv6(card); #endif - qeth_l3_set_ip_addr_list(card); - if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) - return; - qeth_setadp_promisc_mode(card); + qeth_l3_set_ip_addr_list(card); + if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) + return; + } + qeth_l3_handle_promisc_mode(card); } static const char *qeth_l3_arp_get_error_cause(int *rc) @@ -2778,8 +2901,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) int nr_frags; if ((card->info.type == QETH_CARD_TYPE_IQD) && - (skb->protocol != htons(ETH_P_IPV6)) && - (skb->protocol != htons(ETH_P_IP))) + (((skb->protocol != htons(ETH_P_IPV6)) && + (skb->protocol != htons(ETH_P_IP))) || + card->options.sniffer)) goto tx_drop; if ((card->state != CARD_STATE_UP) || !card->lan_online) { @@ -3155,7 +3279,7 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev, index = i % QDIO_MAX_BUFFERS_PER_Q; buffer = &card->qdio.in_q->bufs[index]; if (!(qdio_err && - qeth_check_qdio_errors(buffer->buffer, + qeth_check_qdio_errors(card, buffer->buffer, qdio_err, "qinerr"))) qeth_l3_process_inbound_buffer(card, buffer, index); /* clear buffer and give back to hardware */ @@ -3250,20 +3374,22 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) goto out_remove; } else card->lan_online = 1; - qeth_l3_set_large_send(card, card->options.large_send); rc = qeth_l3_setadapter_parms(card); if (rc) QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); - rc = qeth_l3_start_ipassists(card); - if (rc) - QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); - rc = qeth_l3_setrouting_v4(card); - if (rc) - QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); - rc = qeth_l3_setrouting_v6(card); - if (rc) - QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); + if (!card->options.sniffer) { + rc = qeth_l3_start_ipassists(card); + if (rc) + QETH_DBF_TEXT_(SETUP, 2, "3err%d", rc); + qeth_l3_set_large_send(card, card->options.large_send); + rc = qeth_l3_setrouting_v4(card); + if (rc) + QETH_DBF_TEXT_(SETUP, 2, "4err%d", rc); + rc = qeth_l3_setrouting_v6(card); + if (rc) + QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); + } netif_tx_disable(card->dev); rc = qeth_init_qdio_queues(card); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 3360b0941aa1..3f08b11274ae 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -319,6 +319,61 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev, static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show, qeth_l3_dev_checksum_store); +static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qeth_card *card = dev_get_drvdata(dev); + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0); +} + +static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct qeth_card *card = dev_get_drvdata(dev); + int ret; + unsigned long i; + + if (!card) + return -EINVAL; + + if (card->info.type != QETH_CARD_TYPE_IQD) + return -EPERM; + + if ((card->state != CARD_STATE_DOWN) && + (card->state != CARD_STATE_RECOVER)) + return -EPERM; + + ret = strict_strtoul(buf, 16, &i); + if (ret) + return -EINVAL; + switch (i) { + case 0: + card->options.sniffer = i; + break; + case 1: + ret = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); + if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) { + card->options.sniffer = i; + if (card->qdio.init_pool.buf_count != + QETH_IN_BUF_COUNT_MAX) + qeth_realloc_buffer_pool(card, + QETH_IN_BUF_COUNT_MAX); + break; + } else + return -EPERM; + default: /* fall through */ + return -EINVAL; + } + return count; +} + +static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, + qeth_l3_dev_sniffer_store); + static ssize_t qeth_l3_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -373,6 +428,7 @@ static struct attribute *qeth_l3_device_attrs[] = { &dev_attr_broadcast_mode.attr, &dev_attr_canonical_macaddr.attr, &dev_attr_checksumming.attr, + &dev_attr_sniffer.attr, &dev_attr_large_send.attr, NULL, }; -- cgit v1.2.3 From 84b66683dba002f4cce2aaf78bf45debfaf22795 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Mon, 11 Jan 2010 02:50:51 +0000 Subject: qeth: avoid recovery during device online setting If a qeth device is set online, several initialisation steps are performed. If a failure in one of these steps occurs, the qeth device is reset into DOWN state. If due to the failure a qeth recovery is scheduled and started in another thread, this might cause all kinds of conflicts, even a kernel panic. The patch forbids scheduling of a qeth recovery while online processing is performed till the card is in state SOFTSETUP. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 1 - drivers/s390/net/qeth_l3_main.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 74ba388a159f..c3258b0dd649 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -927,7 +927,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); - qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); recover_flag = card->state; rc = qeth_core_hardsetup_card(card); if (rc) { diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 337d03fb045d..5475834ab916 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3338,8 +3338,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT(SETUP, 2, "setonlin"); QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); - qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); - recover_flag = card->state; rc = qeth_core_hardsetup_card(card); if (rc) { -- cgit v1.2.3 From a60389abaab92213c79790e074ff6bc36ac0ebe5 Mon Sep 17 00:00:00 2001 From: Einar Lueck Date: Mon, 11 Jan 2010 02:50:52 +0000 Subject: qeth: default BLKT values for new OSA/3 hardware Set default BLKT values for new OSA/3 hardware. Signed-off-by: Einar Lueck Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core_main.c | 41 +++++++++++++++++++++++++-------------- drivers/s390/net/qeth_core_sys.c | 6 +++--- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 2c8e9da8753f..fa8a519218ac 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1362,26 +1362,29 @@ static int qeth_read_conf_data(struct qeth_card *card, void **buffer, return ret; } -static int qeth_get_unitaddr(struct qeth_card *card) +static void qeth_configure_unitaddr(struct qeth_card *card, char *prcd) { - int length; - char *prcd; - int rc; - - QETH_DBF_TEXT(SETUP, 2, "getunit"); - rc = qeth_read_conf_data(card, (void **) &prcd, &length); - if (rc) { - QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", - dev_name(&card->gdev->dev), rc); - return rc; - } + QETH_DBF_TEXT(SETUP, 2, "cfgunit"); card->info.chpid = prcd[30]; card->info.unit_addr2 = prcd[31]; card->info.cula = prcd[63]; card->info.guestlan = ((prcd[0x10] == _ascebc['V']) && (prcd[0x11] == _ascebc['M'])); - kfree(prcd); - return 0; +} + +static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd) +{ + QETH_DBF_TEXT(SETUP, 2, "cfgblkt"); + + if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && prcd[76] == 0xF5) { + card->info.blkt.time_total = 250; + card->info.blkt.inter_packet = 5; + card->info.blkt.inter_packet_jumbo = 15; + } else { + card->info.blkt.time_total = 0; + card->info.blkt.inter_packet = 0; + card->info.blkt.inter_packet_jumbo = 0; + } } static void qeth_init_tokens(struct qeth_card *card) @@ -4169,6 +4172,8 @@ void qeth_core_free_discipline(struct qeth_card *card) static void qeth_determine_capabilities(struct qeth_card *card) { int rc; + int length; + char *prcd; QETH_DBF_TEXT(SETUP, 2, "detcapab"); rc = ccw_device_set_online(CARD_DDEV(card)); @@ -4177,11 +4182,17 @@ static void qeth_determine_capabilities(struct qeth_card *card) goto out; } - rc = qeth_get_unitaddr(card); + + rc = qeth_read_conf_data(card, (void **) &prcd, &length); if (rc) { + QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", + dev_name(&card->gdev->dev), rc); QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); goto out_offline; } + qeth_configure_unitaddr(card, prcd); + qeth_configure_blkt_default(card, prcd); + kfree(prcd); rc = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); if (rc) diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index ac2239a4f133..88ae4357136a 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -539,7 +539,7 @@ static ssize_t qeth_dev_blkt_total_store(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); return qeth_dev_blkt_store(card, buf, count, - &card->info.blkt.time_total, 1000); + &card->info.blkt.time_total, 5000); } @@ -561,7 +561,7 @@ static ssize_t qeth_dev_blkt_inter_store(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); return qeth_dev_blkt_store(card, buf, count, - &card->info.blkt.inter_packet, 100); + &card->info.blkt.inter_packet, 1000); } static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show, @@ -582,7 +582,7 @@ static ssize_t qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct qeth_card *card = dev_get_drvdata(dev); return qeth_dev_blkt_store(card, buf, count, - &card->info.blkt.inter_packet_jumbo, 100); + &card->info.blkt.inter_packet_jumbo, 1000); } static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show, -- cgit v1.2.3 From 37fce430dd66a6251bde6ef0004a1da69b26c028 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 12 Jan 2010 20:59:13 +0000 Subject: drivers/net/tlan: Remove TRUE/FALSE defines, use bool Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tlan.c | 28 ++++++++++++++-------------- drivers/net/tlan.h | 3 --- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 613943eb6e75..3ec31dce99f9 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -338,7 +338,7 @@ static int TLan_PhyInternalService( struct net_device * ); static int TLan_PhyDp83840aCheck( struct net_device * ); */ -static int TLan_MiiReadReg( struct net_device *, u16, u16, u16 * ); +static bool TLan_MiiReadReg( struct net_device *, u16, u16, u16 * ); static void TLan_MiiSendData( u16, u32, unsigned ); static void TLan_MiiSync( u16 ); static void TLan_MiiWriteReg( struct net_device *, u16, u16, u16 ); @@ -2204,7 +2204,7 @@ TLan_ResetAdapter( struct net_device *dev ) u32 data; u8 data8; - priv->tlanFullDuplex = FALSE; + priv->tlanFullDuplex = false; priv->phyOnline=0; netif_carrier_off(dev); @@ -2259,7 +2259,7 @@ TLan_ResetAdapter( struct net_device *dev ) TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a ); } else if ( priv->duplex == TLAN_DUPLEX_FULL ) { TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 ); - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; } else { TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 ); } @@ -2651,14 +2651,14 @@ static void TLan_PhyStartLink( struct net_device *dev ) TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000); } else if ( priv->speed == TLAN_SPEED_10 && priv->duplex == TLAN_DUPLEX_FULL) { - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100); } else if ( priv->speed == TLAN_SPEED_100 && priv->duplex == TLAN_DUPLEX_HALF) { TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000); } else if ( priv->speed == TLAN_SPEED_100 && priv->duplex == TLAN_DUPLEX_FULL) { - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100); } else { @@ -2695,7 +2695,7 @@ static void TLan_PhyStartLink( struct net_device *dev ) tctl &= ~TLAN_TC_AUISEL; if ( priv->duplex == TLAN_DUPLEX_FULL ) { control |= MII_GC_DUPLEX; - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; } if ( priv->speed == TLAN_SPEED_100 ) { control |= MII_GC_SPEEDSEL; @@ -2750,9 +2750,9 @@ static void TLan_PhyFinishAutoNeg( struct net_device *dev ) TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa ); mode = an_adv & an_lpa & 0x03E0; if ( mode & 0x0100 ) { - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; } else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) { - priv->tlanFullDuplex = TRUE; + priv->tlanFullDuplex = true; } if ( ( ! ( mode & 0x0180 ) ) && @@ -2855,8 +2855,8 @@ void TLan_PhyMonitor( struct net_device *dev ) * TLan_MiiReadReg * * Returns: - * 0 if ack received ok - * 1 otherwise. + * false if ack received ok + * true if no ack received or other error * * Parms: * dev The device structure containing @@ -2875,17 +2875,17 @@ void TLan_PhyMonitor( struct net_device *dev ) * **************************************************************/ -static int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) +static bool TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) { u8 nack; u16 sio, tmp; u32 i; - int err; + bool err; int minten; TLanPrivateInfo *priv = netdev_priv(dev); unsigned long flags = 0; - err = FALSE; + err = false; outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO; @@ -2918,7 +2918,7 @@ static int TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val ) TLan_SetBit(TLAN_NET_SIO_MCLK, sio); } tmp = 0xffff; - err = TRUE; + err = true; } else { /* ACK, so read data */ for (tmp = 0, i = 0x8000; i; i >>= 1) { TLan_ClearBit(TLAN_NET_SIO_MCLK, sio); diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h index 4b82f283e985..d13ff12d7500 100644 --- a/drivers/net/tlan.h +++ b/drivers/net/tlan.h @@ -31,9 +31,6 @@ * ****************************************************************/ -#define FALSE 0 -#define TRUE 1 - #define TLAN_MIN_FRAME_SIZE 64 #define TLAN_MAX_FRAME_SIZE 1600 -- cgit v1.2.3 From e1d5a010729a7a495a8a8de85727f3f0d62f06a0 Mon Sep 17 00:00:00 2001 From: Samir Bellabes Date: Thu, 7 Jan 2010 22:10:56 +0000 Subject: genetlink: optimize ctrl_dumpfamily() there is a unnecessary test which can be replaced by a good initialization in the 'for' statement Noticed by Serge E. Hallyn Signed-off-by: Samir Bellabes Signed-off-by: David S. Miller --- net/netlink/genetlink.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index d07ecda0a92d..a4b6e148c5de 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -681,9 +681,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) int chains_to_skip = cb->args[0]; int fams_to_skip = cb->args[1]; - for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { - if (i < chains_to_skip) - continue; + for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) { n = 0; list_for_each_entry(rt, genl_family_chain(i), family_list) { if (!rt->netnsok && !net_eq(net, &init_net)) -- cgit v1.2.3 From 508e14b4a4fb1a824a14f2c5b8d7df67b313f8e4 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 12 Jan 2010 14:27:30 +0000 Subject: netpoll: allow execution of multiple rx_hooks per interface Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller --- include/linux/netpoll.h | 11 +++- net/core/netpoll.c | 169 ++++++++++++++++++++++++++++++------------------ 2 files changed, 114 insertions(+), 66 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 2524267210d3..a765ea898549 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -21,15 +21,20 @@ struct netpoll { __be32 local_ip, remote_ip; u16 local_port, remote_port; u8 remote_mac[ETH_ALEN]; + + struct list_head rx; /* rx_np list element */ }; struct netpoll_info { atomic_t refcnt; + int rx_flags; spinlock_t rx_lock; - struct netpoll *rx_np; /* netpoll that registered an rx_hook */ + struct list_head rx_np; /* netpolls that registered an rx_hook */ + struct sk_buff_head arp_tx; /* list of arp requests to reply to */ struct sk_buff_head txq; + struct delayed_work tx_work; }; @@ -51,7 +56,7 @@ static inline int netpoll_rx(struct sk_buff *skb) unsigned long flags; int ret = 0; - if (!npinfo || (!npinfo->rx_np && !npinfo->rx_flags)) + if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) return 0; spin_lock_irqsave(&npinfo->rx_lock, flags); @@ -67,7 +72,7 @@ static inline int netpoll_rx_on(struct sk_buff *skb) { struct netpoll_info *npinfo = skb->dev->npinfo; - return npinfo && (npinfo->rx_np || npinfo->rx_flags); + return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); } static inline int netpoll_receive_skb(struct sk_buff *skb) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 0b4d0d35ef40..7aa697253765 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -407,11 +407,24 @@ static void arp_reply(struct sk_buff *skb) __be32 sip, tip; unsigned char *sha; struct sk_buff *send_skb; - struct netpoll *np = NULL; + struct netpoll *np, *tmp; + unsigned long flags; + int hits = 0; + + if (list_empty(&npinfo->rx_np)) + return; + + /* Before checking the packet, we do some early + inspection whether this is interesting at all */ + spin_lock_irqsave(&npinfo->rx_lock, flags); + list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { + if (np->dev == skb->dev) + hits++; + } + spin_unlock_irqrestore(&npinfo->rx_lock, flags); - if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) - np = npinfo->rx_np; - if (!np) + /* No netpoll struct is using this dev */ + if (!hits) return; /* No arp on this interface */ @@ -437,77 +450,91 @@ static void arp_reply(struct sk_buff *skb) arp_ptr += skb->dev->addr_len; memcpy(&sip, arp_ptr, 4); arp_ptr += 4; - /* if we actually cared about dst hw addr, it would get copied here */ + /* If we actually cared about dst hw addr, + it would get copied here */ arp_ptr += skb->dev->addr_len; memcpy(&tip, arp_ptr, 4); /* Should we ignore arp? */ - if (tip != np->local_ip || - ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) + if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) return; size = arp_hdr_len(skb->dev); - send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev), - LL_RESERVED_SPACE(np->dev)); - if (!send_skb) - return; - - skb_reset_network_header(send_skb); - arp = (struct arphdr *) skb_put(send_skb, size); - send_skb->dev = skb->dev; - send_skb->protocol = htons(ETH_P_ARP); + spin_lock_irqsave(&npinfo->rx_lock, flags); + list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { + if (tip != np->local_ip) + continue; - /* Fill the device header for the ARP frame */ - if (dev_hard_header(send_skb, skb->dev, ptype, - sha, np->dev->dev_addr, - send_skb->len) < 0) { - kfree_skb(send_skb); - return; - } + send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev), + LL_RESERVED_SPACE(np->dev)); + if (!send_skb) + continue; - /* - * Fill out the arp protocol part. - * - * we only support ethernet device type, - * which (according to RFC 1390) should always equal 1 (Ethernet). - */ + skb_reset_network_header(send_skb); + arp = (struct arphdr *) skb_put(send_skb, size); + send_skb->dev = skb->dev; + send_skb->protocol = htons(ETH_P_ARP); - arp->ar_hrd = htons(np->dev->type); - arp->ar_pro = htons(ETH_P_IP); - arp->ar_hln = np->dev->addr_len; - arp->ar_pln = 4; - arp->ar_op = htons(type); + /* Fill the device header for the ARP frame */ + if (dev_hard_header(send_skb, skb->dev, ptype, + sha, np->dev->dev_addr, + send_skb->len) < 0) { + kfree_skb(send_skb); + continue; + } - arp_ptr=(unsigned char *)(arp + 1); - memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); - arp_ptr += np->dev->addr_len; - memcpy(arp_ptr, &tip, 4); - arp_ptr += 4; - memcpy(arp_ptr, sha, np->dev->addr_len); - arp_ptr += np->dev->addr_len; - memcpy(arp_ptr, &sip, 4); + /* + * Fill out the arp protocol part. + * + * we only support ethernet device type, + * which (according to RFC 1390) should + * always equal 1 (Ethernet). + */ - netpoll_send_skb(np, send_skb); + arp->ar_hrd = htons(np->dev->type); + arp->ar_pro = htons(ETH_P_IP); + arp->ar_hln = np->dev->addr_len; + arp->ar_pln = 4; + arp->ar_op = htons(type); + + arp_ptr = (unsigned char *)(arp + 1); + memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); + arp_ptr += np->dev->addr_len; + memcpy(arp_ptr, &tip, 4); + arp_ptr += 4; + memcpy(arp_ptr, sha, np->dev->addr_len); + arp_ptr += np->dev->addr_len; + memcpy(arp_ptr, &sip, 4); + + netpoll_send_skb(np, send_skb); + + /* If there are several rx_hooks for the same address, + we're fine by sending a single reply */ + break; + } + spin_unlock_irqrestore(&npinfo->rx_lock, flags); } int __netpoll_rx(struct sk_buff *skb) { int proto, len, ulen; + int hits = 0; struct iphdr *iph; struct udphdr *uh; - struct netpoll_info *npi = skb->dev->npinfo; - struct netpoll *np = npi->rx_np; + struct netpoll_info *npinfo = skb->dev->npinfo; + struct netpoll *np, *tmp; - if (!np) + if (list_empty(&npinfo->rx_np)) goto out; + if (skb->dev->type != ARPHRD_ETHER) goto out; /* check if netpoll clients need ARP */ if (skb->protocol == htons(ETH_P_ARP) && atomic_read(&trapped)) { - skb_queue_tail(&npi->arp_tx, skb); + skb_queue_tail(&npinfo->arp_tx, skb); return 1; } @@ -551,16 +578,23 @@ int __netpoll_rx(struct sk_buff *skb) goto out; if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) goto out; - if (np->local_ip && np->local_ip != iph->daddr) - goto out; - if (np->remote_ip && np->remote_ip != iph->saddr) - goto out; - if (np->local_port && np->local_port != ntohs(uh->dest)) - goto out; - np->rx_hook(np, ntohs(uh->source), - (char *)(uh+1), - ulen - sizeof(struct udphdr)); + list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { + if (np->local_ip && np->local_ip != iph->daddr) + continue; + if (np->remote_ip && np->remote_ip != iph->saddr) + continue; + if (np->local_port && np->local_port != ntohs(uh->dest)) + continue; + + np->rx_hook(np, ntohs(uh->source), + (char *)(uh+1), + ulen - sizeof(struct udphdr)); + hits++; + } + + if (!hits) + goto out; kfree_skb(skb); return 1; @@ -684,6 +718,7 @@ int netpoll_setup(struct netpoll *np) struct net_device *ndev = NULL; struct in_device *in_dev; struct netpoll_info *npinfo; + struct netpoll *npe, *tmp; unsigned long flags; int err; @@ -704,7 +739,7 @@ int netpoll_setup(struct netpoll *np) } npinfo->rx_flags = 0; - npinfo->rx_np = NULL; + INIT_LIST_HEAD(&npinfo->rx_np); spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); @@ -785,7 +820,7 @@ int netpoll_setup(struct netpoll *np) if (np->rx_hook) { spin_lock_irqsave(&npinfo->rx_lock, flags); npinfo->rx_flags |= NETPOLL_RX_ENABLED; - npinfo->rx_np = np; + list_add_tail(&np->rx, &npinfo->rx_np); spin_unlock_irqrestore(&npinfo->rx_lock, flags); } @@ -801,9 +836,16 @@ int netpoll_setup(struct netpoll *np) return 0; release: - if (!ndev->npinfo) + if (!ndev->npinfo) { + spin_lock_irqsave(&npinfo->rx_lock, flags); + list_for_each_entry_safe(npe, tmp, &npinfo->rx_np, rx) { + npe->dev = NULL; + } + spin_unlock_irqrestore(&npinfo->rx_lock, flags); + kfree(npinfo); - np->dev = NULL; + } + dev_put(ndev); return err; } @@ -823,10 +865,11 @@ void netpoll_cleanup(struct netpoll *np) if (np->dev) { npinfo = np->dev->npinfo; if (npinfo) { - if (npinfo->rx_np == np) { + if (!list_empty(&npinfo->rx_np)) { spin_lock_irqsave(&npinfo->rx_lock, flags); - npinfo->rx_np = NULL; - npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; + list_del(&np->rx); + if (list_empty(&npinfo->rx_np)) + npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } -- cgit v1.2.3 From 9a58a80a701bdb2d220cdab4914218df5b48d781 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 14 Jan 2010 03:10:54 -0800 Subject: proc_fops: convert drivers/isdn/ to seq_file Convert code away from ->read_proc/->write_proc interfaces. Switch to proc_create()/proc_create_data() which make addition of proc entries reliable wrt NULL ->proc_fops, NULL ->data and so on. Problem with ->read_proc et al is described here commit 786d7e1612f0b0adb6046f19b906609e4fe8b1ba "Fix rmmod/read/write races in /proc entries" [akpm@linux-foundation.org: CONFIG_PROC_FS=n build fix] Signed-off-by: Alexey Dobriyan Signed-off-by: Tilman Schmidt Signed-off-by: Karsten Keil Signed-off-by: David S. Miller --- Documentation/isdn/INTERFACE.CAPI | 9 +- drivers/isdn/capi/capi.c | 99 ++++++---------- drivers/isdn/capi/capidrv.c | 55 +++------ drivers/isdn/capi/kcapi.c | 8 +- drivers/isdn/gigaset/capi.c | 75 ++++++------ drivers/isdn/hardware/avm/avmcard.h | 6 +- drivers/isdn/hardware/avm/b1.c | 54 +++++---- drivers/isdn/hardware/avm/b1dma.c | 71 ++++++------ drivers/isdn/hardware/avm/b1isa.c | 2 +- drivers/isdn/hardware/avm/b1pci.c | 4 +- drivers/isdn/hardware/avm/b1pcmcia.c | 2 +- drivers/isdn/hardware/avm/c4.c | 53 +++++---- drivers/isdn/hardware/avm/t1isa.c | 2 +- drivers/isdn/hardware/avm/t1pci.c | 2 +- drivers/isdn/hardware/eicon/capimain.c | 40 ++++--- drivers/isdn/hardware/eicon/diva_didd.c | 45 ++++---- drivers/isdn/hardware/eicon/divasi.c | 48 ++++---- drivers/isdn/hardware/eicon/divasproc.c | 198 ++++++++++++++------------------ drivers/isdn/hysdn/hycapi.c | 56 ++++----- include/linux/isdn/capilli.h | 3 +- net/bluetooth/cmtp/capi.c | 37 +++--- 21 files changed, 411 insertions(+), 458 deletions(-) diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI index 5fe8de5cc727..f172091fb7cd 100644 --- a/Documentation/isdn/INTERFACE.CAPI +++ b/Documentation/isdn/INTERFACE.CAPI @@ -149,10 +149,11 @@ char *(*procinfo)(struct capi_ctr *ctrlr) pointer to a callback function returning the entry for the device in the CAPI controller info table, /proc/capi/controller -read_proc_t *ctr_read_proc - pointer to the read_proc callback function for the device's proc file - system entry, /proc/capi/controllers/; will be called with a - pointer to the device's capi_ctr structure as the last (data) argument +const struct file_operations *proc_fops + pointers to callback functions for the device's proc file + system entry, /proc/capi/controllers/; pointer to the device's + capi_ctr structure is available from struct proc_dir_entry::data + which is available from struct inode. Note: Callback functions except send_message() are never called in interrupt context. diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 65bf91e16a42..79f9364aded6 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -33,6 +33,7 @@ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include #include +#include #include #include #include @@ -1407,114 +1408,84 @@ static void capinc_tty_exit(void) * /proc/capi/capi20: * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */ -static int proc_capidev_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capi20_proc_show(struct seq_file *m, void *v) { struct capidev *cdev; struct list_head *l; - int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); - len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n", + seq_printf(m, "0 %d %lu %lu %lu %lu\n", cdev->ap.applid, cdev->ap.nrecvctlpkt, cdev->ap.nrecvdatapkt, cdev->ap.nsentctlpkt, cdev->ap.nsentdatapkt); - if (len <= off) { - off -= len; - len = 0; - } else { - if (len-off > count) - goto endloop; - } } - -endloop: read_unlock(&capidev_list_lock); - if (len < count) - *eof = 1; - if (len > count) len = count; - if (len < 0) len = 0; - return len; + return 0; } +static int capi20_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capi20_proc_show, NULL); +} + +static const struct file_operations capi20_proc_fops = { + .owner = THIS_MODULE, + .open = capi20_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * /proc/capi/capi20ncci: * applid ncci */ -static int proc_capincci_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capi20ncci_proc_show(struct seq_file *m, void *v) { struct capidev *cdev; struct capincci *np; struct list_head *l; - int len = 0; read_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); for (np=cdev->nccis; np; np = np->next) { - len += sprintf(page+len, "%d 0x%x\n", + seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); - if (len <= off) { - off -= len; - len = 0; - } else { - if (len-off > count) - goto endloop; - } } } -endloop: read_unlock(&capidev_list_lock); - *start = page+off; - if (len < count) - *eof = 1; - if (len>count) len = count; - if (len<0) len = 0; - return len; + return 0; } -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capi20", 0 , proc_capidev_read_proc }, - { "capi/capi20ncci", 0 , proc_capincci_read_proc }, +static int capi20ncci_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capi20ncci_proc_show, NULL); +} + +static const struct file_operations capi20ncci_proc_fops = { + .owner = THIS_MODULE, + .open = capi20ncci_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static void __init proc_init(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, NULL); - if (p->procent) p->procent->read_proc = p->read_proc; - } + proc_create("capi/capi20", 0, NULL, &capi20_proc_fops); + proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops); } static void __exit proc_exit(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, NULL); - p->procent = NULL; - } - } + remove_proc_entry("capi/capi20", NULL); + remove_proc_entry("capi/capi20ncci", NULL); } /* -------- init function and module interface ---------------------- */ diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 66b7d7a86474..bb450152fb74 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2229,59 +2230,37 @@ static void lower_callback(unsigned int cmd, u32 contr, void *data) * /proc/capi/capidrv: * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt */ -static int proc_capidrv_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int capidrv_proc_show(struct seq_file *m, void *v) { - int len = 0; - - len += sprintf(page+len, "%lu %lu %lu %lu\n", + seq_printf(m, "%lu %lu %lu %lu\n", global.ap.nrecvctlpkt, global.ap.nrecvdatapkt, global.ap.nsentctlpkt, global.ap.nsentdatapkt); - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + return 0; +} + +static int capidrv_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, capidrv_proc_show, NULL); } -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capidrv", 0 , proc_capidrv_read_proc }, +static const struct file_operations capidrv_proc_fops = { + .owner = THIS_MODULE, + .open = capidrv_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static void __init proc_init(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, NULL); - if (p->procent) p->procent->read_proc = p->read_proc; - } + proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops); } static void __exit proc_exit(void) { - int nelem = ARRAY_SIZE(procfsentries); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, NULL); - p->procent = NULL; - } - } + remove_proc_entry("capi/capidrv", NULL); } static int __init capidrv_init(void) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index dc506ab99cac..b0bacf377c18 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -490,13 +490,7 @@ attach_capi_ctr(struct capi_ctr *card) card->traceflag = showcapimsgs; sprintf(card->procfn, "capi/controllers/%d", card->cnr); - card->procent = create_proc_entry(card->procfn, 0, NULL); - if (card->procent) { - card->procent->read_proc = - (int (*)(char *,char **,off_t,int,int *,void *)) - card->ctr_read_proc; - card->procent->data = card; - } + card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card); ncards++; printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 3f5cd06af104..6f0ae32906bf 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -13,6 +13,8 @@ #include "gigaset.h" #include +#include +#include #include #include #include @@ -2106,35 +2108,22 @@ static char *gigaset_procinfo(struct capi_ctr *ctr) return ctr->name; /* ToDo: more? */ } -/** - * gigaset_ctr_read_proc() - build controller proc file entry - * @page: buffer of PAGE_SIZE bytes for receiving the entry. - * @start: unused. - * @off: unused. - * @count: unused. - * @eof: unused. - * @ctr: controller descriptor structure. - * - * Return value: length of generated entry - */ -static int gigaset_ctr_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctr) +static int gigaset_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctr = m->private; struct cardstate *cs = ctr->driverdata; char *s; int i; - int len = 0; - len += sprintf(page+len, "%-16s %s\n", "name", ctr->name); - len += sprintf(page+len, "%-16s %s %s\n", "dev", + + seq_printf(m, "%-16s %s\n", "name", ctr->name); + seq_printf(m, "%-16s %s %s\n", "dev", dev_driver_string(cs->dev), dev_name(cs->dev)); - len += sprintf(page+len, "%-16s %d\n", "id", cs->myid); + seq_printf(m, "%-16s %d\n", "id", cs->myid); if (cs->gotfwver) - len += sprintf(page+len, "%-16s %d.%d.%d.%d\n", "firmware", + seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware", cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); - len += sprintf(page+len, "%-16s %d\n", "channels", - cs->channels); - len += sprintf(page+len, "%-16s %s\n", "onechannel", - cs->onechannel ? "yes" : "no"); + seq_printf(m, "%-16s %d\n", "channels", cs->channels); + seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no"); switch (cs->mode) { case M_UNKNOWN: @@ -2152,7 +2141,7 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "%-16s %s\n", "mode", s); + seq_printf(m, "%-16s %s\n", "mode", s); switch (cs->mstate) { case MS_UNINITIALIZED: @@ -2176,25 +2165,21 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "%-16s %s\n", "mstate", s); + seq_printf(m, "%-16s %s\n", "mstate", s); - len += sprintf(page+len, "%-16s %s\n", "running", - cs->running ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "connected", - cs->connected ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "isdn_up", - cs->isdn_up ? "yes" : "no"); - len += sprintf(page+len, "%-16s %s\n", "cidmode", - cs->cidmode ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no"); + seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no"); for (i = 0; i < cs->channels; i++) { - len += sprintf(page+len, "[%d]%-13s %d\n", i, "corrupted", + seq_printf(m, "[%d]%-13s %d\n", i, "corrupted", cs->bcs[i].corrupted); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_down", + seq_printf(m, "[%d]%-13s %d\n", i, "trans_down", cs->bcs[i].trans_down); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "trans_up", + seq_printf(m, "[%d]%-13s %d\n", i, "trans_up", cs->bcs[i].trans_up); - len += sprintf(page+len, "[%d]%-13s %d\n", i, "chstate", + seq_printf(m, "[%d]%-13s %d\n", i, "chstate", cs->bcs[i].chstate); switch (cs->bcs[i].proto2) { case L2_BITSYNC: @@ -2209,11 +2194,23 @@ static int gigaset_ctr_read_proc(char *page, char **start, off_t off, default: s = "??"; } - len += sprintf(page+len, "[%d]%-13s %s\n", i, "proto2", s); + seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s); } - return len; + return 0; } +static int gigaset_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, gigaset_proc_show, PDE(inode)->data); +} + +static const struct file_operations gigaset_proc_fops = { + .owner = THIS_MODULE, + .open = gigaset_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; static struct capi_driver capi_driver_gigaset = { .name = "gigaset", @@ -2256,7 +2253,7 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid) iif->ctr.release_appl = gigaset_release_appl; iif->ctr.send_message = gigaset_send_message; iif->ctr.procinfo = gigaset_procinfo; - iif->ctr.ctr_read_proc = gigaset_ctr_read_proc; + iif->ctr.proc_fops = &gigaset_proc_fops; INIT_LIST_HEAD(&iif->appls); skb_queue_head_init(&iif->sendqueue); atomic_set(&iif->sendqlen, 0); diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h index d964f07e4a56..a70e8854461d 100644 --- a/drivers/isdn/hardware/avm/avmcard.h +++ b/drivers/isdn/hardware/avm/avmcard.h @@ -556,8 +556,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); void b1_parse_version(avmctrl_info *card); irqreturn_t b1_interrupt(int interrupt, void *devptr); -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); +extern const struct file_operations b1ctl_proc_fops; avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, long rsize, long ssize); @@ -577,7 +576,6 @@ void b1dma_register_appl(struct capi_ctr *ctrl, capi_register_params *rp); void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); +extern const struct file_operations b1dmactl_proc_fops; #endif /* _AVMCARD_H_ */ diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index a7c0083e78a7..c38fa0f4c729 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -634,18 +636,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr) } /* ------------------------------------------------------------- */ -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int b1ctl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -658,20 +659,20 @@ int b1ctl_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if (card->cardtype == avm_t1isa) - len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); + seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -685,7 +686,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -693,16 +694,25 @@ int b1ctl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); + + return 0; +} + +static int b1ctl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, b1ctl_proc_show, PDE(inode)->data); } +const struct file_operations b1ctl_proc_fops = { + .owner = THIS_MODULE, + .open = b1ctl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +EXPORT_SYMBOL(b1ctl_proc_fops); + /* ------------------------------------------------------------- */ #ifdef CONFIG_PCI @@ -781,8 +791,6 @@ EXPORT_SYMBOL(b1_send_message); EXPORT_SYMBOL(b1_parse_version); EXPORT_SYMBOL(b1_interrupt); -EXPORT_SYMBOL(b1ctl_read_proc); - static int __init b1_init(void) { char *p; diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index 0e84aaae43fd..124550d0dbf3 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -855,21 +857,20 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) /* ------------------------------------------------------------- */ -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int b1dmactl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; u32 txoff, txlen, rxoff, rxlen, csr; unsigned long flags; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -882,18 +883,18 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -907,7 +908,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -915,7 +916,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); spin_lock_irqsave(&card->lock, flags); @@ -930,27 +931,30 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, spin_unlock_irqrestore(&card->lock, flags); - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr (cached)", (unsigned long)card->csr); - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr", (unsigned long)csr); - len += sprintf(page+len, "%-16s %lu\n", - "txoff", (unsigned long)txoff); - len += sprintf(page+len, "%-16s %lu\n", - "txlen", (unsigned long)txlen); - len += sprintf(page+len, "%-16s %lu\n", - "rxoff", (unsigned long)rxoff); - len += sprintf(page+len, "%-16s %lu\n", - "rxlen", (unsigned long)rxlen); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); + seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr); + seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff); + seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen); + seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff); + seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen); + + return 0; +} + +static int b1dmactl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, b1dmactl_proc_show, PDE(inode)->data); } +const struct file_operations b1dmactl_proc_fops = { + .owner = THIS_MODULE, + .open = b1dmactl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +EXPORT_SYMBOL(b1dmactl_proc_fops); + /* ------------------------------------------------------------- */ EXPORT_SYMBOL(b1dma_reset); @@ -963,7 +967,6 @@ EXPORT_SYMBOL(b1dma_reset_ctr); EXPORT_SYMBOL(b1dma_register_appl); EXPORT_SYMBOL(b1dma_release_appl); EXPORT_SYMBOL(b1dma_send_message); -EXPORT_SYMBOL(b1dmactl_read_proc); static int __init b1dma_init(void) { diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c index 6461a32bc838..ff5390546f92 100644 --- a/drivers/isdn/hardware/avm/b1isa.c +++ b/drivers/isdn/hardware/avm/b1isa.c @@ -121,7 +121,7 @@ static int b1isa_probe(struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1isa_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c index 5b314a2c4049..c97e4315079d 100644 --- a/drivers/isdn/hardware/avm/b1pci.c +++ b/drivers/isdn/hardware/avm/b1pci.c @@ -112,7 +112,7 @@ static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1pci_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); cinfo->capi_ctrl.owner = THIS_MODULE; @@ -251,7 +251,7 @@ static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c index 7740403b40e1..d6391e0afeea 100644 --- a/drivers/isdn/hardware/avm/b1pcmcia.c +++ b/drivers/isdn/hardware/avm/b1pcmcia.c @@ -108,7 +108,7 @@ static int b1pcmcia_add_card(unsigned int port, unsigned irq, cinfo->capi_ctrl.load_firmware = b1_load_firmware; cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 6833301a45fc..de6e6b311819 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -1062,19 +1064,18 @@ static char *c4_procinfo(struct capi_ctr *ctrl) return cinfo->infobuf; } -static int c4_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int c4_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u8 flag; - int len = 0; char *s; - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + seq_printf(m, "%-16s %s\n", "name", card->name); + seq_printf(m, "%-16s 0x%x\n", "io", card->port); + seq_printf(m, "%-16s %d\n", "irq", card->irq); + seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); switch (card->cardtype) { case avm_b1isa: s = "B1 ISA"; break; case avm_b1pci: s = "B1 PCI"; break; @@ -1087,18 +1088,18 @@ static int c4_read_proc(char *page, char **start, off_t off, case avm_c2: s = "C2"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[3]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", "protocol", (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -1112,7 +1113,7 @@ static int c4_read_proc(char *page, char **start, off_t off, if (card->cardtype != avm_m1) { flag = ((u8 *)(ctrl->profile.manu))[5]; if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", + seq_printf(m, "%-16s%s%s%s%s\n", "linetype", (flag & 0x01) ? " point to point" : "", (flag & 0x02) ? " point to multipoint" : "", @@ -1120,16 +1121,24 @@ static int c4_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); + + return 0; } +static int c4_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, c4_proc_show, PDE(inode)->data); +} + +static const struct file_operations c4_proc_fops = { + .owner = THIS_MODULE, + .open = c4_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* ------------------------------------------------------------- */ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, @@ -1201,7 +1210,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, cinfo->capi_ctrl.load_firmware = c4_load_firmware; cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; cinfo->capi_ctrl.procinfo = c4_procinfo; - cinfo->capi_ctrl.ctr_read_proc = c4_read_proc; + cinfo->capi_ctrl.proc_fops = &c4_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index 1c53fd49adb6..baeeb3c2a3ee 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c @@ -429,7 +429,7 @@ static int t1isa_probe(struct pci_dev *pdev, int cardnr) cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; cinfo->capi_ctrl.procinfo = t1isa_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c index e6d298d75146..5a3f83098018 100644 --- a/drivers/isdn/hardware/avm/t1pci.c +++ b/drivers/isdn/hardware/avm/t1pci.c @@ -119,7 +119,7 @@ static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev) cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; cinfo->capi_ctrl.procinfo = t1pci_procinfo; - cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; + cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; strcpy(cinfo->capi_ctrl.name, card->name); retval = attach_capi_ctr(&cinfo->capi_ctrl); diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c index 98fcdfc7ca55..0f073cd73763 100644 --- a/drivers/isdn/hardware/eicon/capimain.c +++ b/drivers/isdn/hardware/eicon/capimain.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "os_capi.h" @@ -75,25 +76,32 @@ void diva_os_free_message_buffer(diva_os_message_buffer_s * dmb) /* * proc function for controller info */ -static int diva_ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int diva_ctl_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; diva_card *card = (diva_card *) ctrl->driverdata; - int len = 0; - - len += sprintf(page + len, "%s\n", ctrl->name); - len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial); - len += sprintf(page + len, "Id : %d\n", card->Id); - len += sprintf(page + len, "Channels : %d\n", card->d.channels); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + + seq_printf(m, "%s\n", ctrl->name); + seq_printf(m, "Serial No. : %s\n", ctrl->serial); + seq_printf(m, "Id : %d\n", card->Id); + seq_printf(m, "Channels : %d\n", card->d.channels); + + return 0; +} + +static int diva_ctl_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, diva_ctl_proc_show, NULL); } +static const struct file_operations diva_ctl_proc_fops = { + .owner = THIS_MODULE, + .open = diva_ctl_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * set additional os settings in capi_ctr struct */ @@ -102,7 +110,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl) ctrl->driver_name = DRIVERLNAME; ctrl->load_firmware = NULL; ctrl->reset_ctr = NULL; - ctrl->ctr_read_proc = diva_ctl_read_proc; + ctrl->proc_fops = &diva_ctl_proc_fops; ctrl->owner = THIS_MODULE; } diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c index 993b14cf1778..5d06a7437824 100644 --- a/drivers/isdn/hardware/eicon/diva_didd.c +++ b/drivers/isdn/hardware/eicon/diva_didd.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "platform.h" @@ -62,39 +63,41 @@ static char *getrev(const char *revision) return rev; } -static int -proc_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int divadidd_proc_show(struct seq_file *m, void *v) { - int len = 0; char tmprev[32]; strcpy(tmprev, main_revision); - len += sprintf(page + len, "%s\n", DRIVERNAME); - len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD); - len += sprintf(page + len, "build : %s(%s)\n", + seq_printf(m, "%s\n", DRIVERNAME); + seq_printf(m, "name : %s\n", DRIVERLNAME); + seq_printf(m, "release : %s\n", DRIVERRELEASE_DIDD); + seq_printf(m, "build : %s(%s)\n", diva_didd_common_code_build, DIVA_BUILD); - len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + seq_printf(m, "revision : %s\n", getrev(tmprev)); + + return 0; } +static int divadidd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, divadidd_proc_show, NULL); +} + +static const struct file_operations divadidd_proc_fops = { + .owner = THIS_MODULE, + .open = divadidd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int DIVA_INIT_FUNCTION create_proc(void) { proc_net_eicon = proc_mkdir("eicon", init_net.proc_net); if (proc_net_eicon) { - if ((proc_didd = - create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO, - proc_net_eicon))) { - proc_didd->read_proc = proc_read; - } + proc_didd = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, + &divadidd_proc_fops); return (1); } return (0); diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c index 69e71ebe7841..f577719ab3fa 100644 --- a/drivers/isdn/hardware/eicon/divasi.c +++ b/drivers/isdn/hardware/eicon/divasi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -86,39 +87,40 @@ static void diva_um_timer_function(unsigned long data); extern struct proc_dir_entry *proc_net_eicon; static struct proc_dir_entry *um_idi_proc_entry = NULL; -static int -um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int um_idi_proc_show(struct seq_file *m, void *v) { - int len = 0; char tmprev[32]; - len += sprintf(page + len, "%s\n", DRIVERNAME); - len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI); + seq_printf(m, "%s\n", DRIVERNAME); + seq_printf(m, "name : %s\n", DRIVERLNAME); + seq_printf(m, "release : %s\n", DRIVERRELEASE_IDI); strcpy(tmprev, main_revision); - len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); - len += sprintf(page + len, "build : %s\n", DIVA_BUILD); - len += sprintf(page + len, "major : %d\n", major); - - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + seq_printf(m, "revision : %s\n", getrev(tmprev)); + seq_printf(m, "build : %s\n", DIVA_BUILD); + seq_printf(m, "major : %d\n", major); + + return 0; +} + +static int um_idi_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, um_idi_proc_show, NULL); } +static const struct file_operations um_idi_proc_fops = { + .owner = THIS_MODULE, + .open = um_idi_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int DIVA_INIT_FUNCTION create_um_idi_proc(void) { - um_idi_proc_entry = create_proc_entry(DRIVERLNAME, - S_IFREG | S_IRUGO | S_IWUSR, - proc_net_eicon); + um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, + &um_idi_proc_fops); if (!um_idi_proc_entry) return (0); - - um_idi_proc_entry->read_proc = um_idi_proc_read; - return (1); } diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index 040827288ec9..46d44a942624 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -141,14 +142,10 @@ void remove_divas_proc(void) } } -/* -** write group_optimization -*/ -static int -write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; if ((count == 1) || (count == 2)) { @@ -172,14 +169,10 @@ write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, return (-EINVAL); } -/* -** write dynamic_l1_down -*/ -static int -write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; if ((count == 1) || (count == 2)) { @@ -203,63 +196,62 @@ write_d_l1_down(struct file *file, const char __user *buffer, unsigned long coun return (-EINVAL); } - -/* -** read dynamic_l1_down -*/ -static int -read_d_l1_down(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int d_l1_down_proc_show(struct seq_file *m, void *v) { - int len = 0; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += sprintf(page + len, "%s\n", + seq_printf(m, "%s\n", (IoAdapter->capi_cfg. cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" : "0"); + return 0; +} - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); +static int d_l1_down_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, d_l1_down_proc_show, PDE(inode)->data); } -/* -** read group_optimization -*/ -static int -read_grp_opt(char *page, char **start, off_t off, int count, int *eof, - void *data) +static const struct file_operations d_l1_down_proc_fops = { + .owner = THIS_MODULE, + .open = d_l1_down_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = d_l1_down_proc_write, +}; + +static int grp_opt_proc_show(struct seq_file *m, void *v) { - int len = 0; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += sprintf(page + len, "%s\n", + seq_printf(m, "%s\n", (IoAdapter->capi_cfg. cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) ? "1" : "0"); + return 0; +} - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); +static int grp_opt_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, grp_opt_proc_show, PDE(inode)->data); } -/* -** info write -*/ -static int -info_write(struct file *file, const char __user *buffer, unsigned long count, - void *data) +static const struct file_operations grp_opt_proc_fops = { + .owner = THIS_MODULE, + .open = grp_opt_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = grp_opt_proc_write, +}; + +static ssize_t info_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; char c[4]; @@ -277,63 +269,46 @@ info_write(struct file *file, const char __user *buffer, unsigned long count, return (-EINVAL); } -/* -** info read -*/ -static int -info_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int info_proc_show(struct seq_file *m, void *v) { int i = 0; - int len = 0; char *p; char tmpser[16]; - diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; + diva_os_xdi_adapter_t *a = m->private; PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; - len += - sprintf(page + len, "Name : %s\n", - IoAdapter->Properties.Name); - len += sprintf(page + len, "DSP state : %08x\n", a->dsp_mask); - len += sprintf(page + len, "Channels : %02d\n", - IoAdapter->Properties.Channels); - len += sprintf(page + len, "E. max/used : %03d/%03d\n", + seq_printf(m, "Name : %s\n", IoAdapter->Properties.Name); + seq_printf(m, "DSP state : %08x\n", a->dsp_mask); + seq_printf(m, "Channels : %02d\n", IoAdapter->Properties.Channels); + seq_printf(m, "E. max/used : %03d/%03d\n", IoAdapter->e_max, IoAdapter->e_count); diva_get_vserial_number(IoAdapter, tmpser); - len += sprintf(page + len, "Serial : %s\n", tmpser); - len += - sprintf(page + len, "IRQ : %d\n", - IoAdapter->irq_info.irq_nr); - len += sprintf(page + len, "CardIndex : %d\n", a->CardIndex); - len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal); - len += sprintf(page + len, "Controller : %d\n", a->controller); - len += sprintf(page + len, "Bus-Type : %s\n", + seq_printf(m, "Serial : %s\n", tmpser); + seq_printf(m, "IRQ : %d\n", IoAdapter->irq_info.irq_nr); + seq_printf(m, "CardIndex : %d\n", a->CardIndex); + seq_printf(m, "CardOrdinal : %d\n", a->CardOrdinal); + seq_printf(m, "Controller : %d\n", a->controller); + seq_printf(m, "Bus-Type : %s\n", (a->Bus == DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI"); - len += sprintf(page + len, "Port-Name : %s\n", a->port_name); + seq_printf(m, "Port-Name : %s\n", a->port_name); if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) { - len += - sprintf(page + len, "PCI-bus : %d\n", - a->resources.pci.bus); - len += - sprintf(page + len, "PCI-func : %d\n", - a->resources.pci.func); + seq_printf(m, "PCI-bus : %d\n", a->resources.pci.bus); + seq_printf(m, "PCI-func : %d\n", a->resources.pci.func); for (i = 0; i < 8; i++) { if (a->resources.pci.bar[i]) { - len += - sprintf(page + len, + seq_printf(m, "Mem / I/O %d : 0x%x / mapped : 0x%lx", i, a->resources.pci.bar[i], (unsigned long) a->resources. pci.addr[i]); if (a->resources.pci.length[i]) { - len += - sprintf(page + len, + seq_printf(m, " / length : %d", a->resources.pci. length[i]); } - len += sprintf(page + len, "\n"); + seq_putc(m, '\n'); } } } @@ -353,16 +328,25 @@ info_read(char *page, char **start, off_t off, int count, int *eof, } else { p = "ready"; } - len += sprintf(page + len, "State : %s\n", p); + seq_printf(m, "State : %s\n", p); - if (off + count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len - off) ? count : len - off); + return 0; +} + +static int info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, info_proc_show, PDE(inode)->data); } +static const struct file_operations info_proc_fops = { + .owner = THIS_MODULE, + .open = info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = info_proc_write, +}; + /* ** adapter proc init/de-init */ @@ -380,28 +364,20 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a) return (0); a->proc_adapter_dir = (void *) de; - if (!(pe = - create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) + pe = proc_create_data(info_proc_name, S_IRUGO | S_IWUSR, de, + &info_proc_fops, a); + if (!pe) return (0); a->proc_info = (void *) pe; - pe->write_proc = info_write; - pe->read_proc = info_read; - pe->data = a; - if ((pe = create_proc_entry(grp_opt_proc_name, - S_IFREG | S_IRUGO | S_IWUSR, de))) { + pe = proc_create_data(grp_opt_proc_name, S_IRUGO | S_IWUSR, de, + &grp_opt_proc_fops, a); + if (pe) a->proc_grp_opt = (void *) pe; - pe->write_proc = write_grp_opt; - pe->read_proc = read_grp_opt; - pe->data = a; - } - if ((pe = create_proc_entry(d_l1_down_proc_name, - S_IFREG | S_IRUGO | S_IWUSR, de))) { + pe = proc_create_data(d_l1_down_proc_name, S_IRUGO | S_IWUSR, de, + &d_l1_down_proc_fops, a); + if (pe) a->proc_d_l1_down = (void *) pe; - pe->write_proc = write_d_l1_down; - pe->read_proc = read_d_l1_down; - pe->data = a; - } DBG_TRC(("proc entry %s created", tmp)); diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 4ffaa14b9fc4..fe874afa4f81 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -11,6 +11,8 @@ */ #include +#include +#include #include #include #include @@ -432,26 +434,16 @@ static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) return retval; } -/********************************************************************* -hycapi_read_proc - -Informations provided in the /proc/capi-entries. - -*********************************************************************/ - -static int hycapi_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) +static int hycapi_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); hysdn_card *card = cinfo->card; - int len = 0; char *s; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_read_proc\n"); -#endif - len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + + seq_printf(m, "%-16s %s\n", "name", cinfo->cardname); + seq_printf(m, "%-16s 0x%x\n", "io", card->iobase); + seq_printf(m, "%-16s %d\n", "irq", card->irq); switch (card->brdtype) { case BD_PCCARD: s = "HYSDN Hycard"; break; @@ -461,24 +453,32 @@ static int hycapi_read_proc(char *page, char **start, off_t off, case BD_PLEXUS: s = "HYSDN Plexus30"; break; default: s = "???"; break; } - len += sprintf(page+len, "%-16s %s\n", "type", s); + seq_printf(m, "%-16s %s\n", "type", s); if ((s = cinfo->version[VER_DRIVER]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + seq_printf(m, "%-16s %s\n", "ver_driver", s); if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + seq_printf(m, "%-16s %s\n", "ver_cardtype", s); if ((s = cinfo->version[VER_SERIAL]) != NULL) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + seq_printf(m, "%-16s %s\n", "ver_serial", s); - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); + return 0; +} + +static int hycapi_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, hycapi_proc_show, PDE(inode)->data); } +static const struct file_operations hycapi_proc_fops = { + .owner = THIS_MODULE, + .open = hycapi_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /************************************************************** hycapi_load_firmware @@ -774,7 +774,7 @@ hycapi_capi_create(hysdn_card *card) ctrl->load_firmware = hycapi_load_firmware; ctrl->reset_ctr = hycapi_reset_ctr; ctrl->procinfo = hycapi_procinfo; - ctrl->ctr_read_proc = hycapi_read_proc; + ctrl->proc_fops = &hycapi_proc_fops; strcpy(ctrl->name, cinfo->cardname); ctrl->owner = THIS_MODULE; diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index 7acb87a44872..d3e5e9da0c82 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -50,8 +50,7 @@ struct capi_ctr { u16 (*send_message)(struct capi_ctr *, struct sk_buff *skb); char *(*procinfo)(struct capi_ctr *); - int (*ctr_read_proc)(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *card); + const struct file_operations *proc_fops; /* filled in before calling ready callback */ u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */ diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 97f8d68d574d..3487cfe74aec 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c @@ -21,7 +21,8 @@ */ #include - +#include +#include #include #include #include @@ -516,33 +517,37 @@ static char *cmtp_procinfo(struct capi_ctr *ctrl) return "CAPI Message Transport Protocol"; } -static int cmtp_ctr_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl) +static int cmtp_proc_show(struct seq_file *m, void *v) { + struct capi_ctr *ctrl = m->private; struct cmtp_session *session = ctrl->driverdata; struct cmtp_application *app; struct list_head *p, *n; - int len = 0; - len += sprintf(page + len, "%s\n\n", cmtp_procinfo(ctrl)); - len += sprintf(page + len, "addr %s\n", session->name); - len += sprintf(page + len, "ctrl %d\n", session->num); + seq_printf(m, "%s\n\n", cmtp_procinfo(ctrl)); + seq_printf(m, "addr %s\n", session->name); + seq_printf(m, "ctrl %d\n", session->num); list_for_each_safe(p, n, &session->applications) { app = list_entry(p, struct cmtp_application, list); - len += sprintf(page + len, "appl %d -> %d\n", app->appl, app->mapping); + seq_printf(m, "appl %d -> %d\n", app->appl, app->mapping); } - if (off + count >= len) - *eof = 1; - - if (len < off) - return 0; - - *start = page + off; + return 0; +} - return ((count < len - off) ? count : len - off); +static int cmtp_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, cmtp_proc_show, PDE(inode)->data); } +static const struct file_operations cmtp_proc_fops = { + .owner = THIS_MODULE, + .open = cmtp_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; int cmtp_attach_device(struct cmtp_session *session) { @@ -582,7 +587,7 @@ int cmtp_attach_device(struct cmtp_session *session) session->ctrl.send_message = cmtp_send_message; session->ctrl.procinfo = cmtp_procinfo; - session->ctrl.ctr_read_proc = cmtp_ctr_read_proc; + session->ctrl.proc_fops = &cmtp_proc_fops; if (attach_capi_ctr(&session->ctrl) < 0) { BT_ERR("Can't attach new controller"); -- cgit v1.2.3 From 79b6a5110abf6fd4454ba34e0960783a4a2c801a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 14 Jan 2010 17:00:54 -0500 Subject: Revert "iwmc3200wifi: fix array out-of-boundary access" This reverts commit 6c853da3f30c93eae847ecbcd9fdf10ba0da04c2. From Message-ID: <1262663293.551.117.camel@debian> On Sat, 2010-01-02 at 22:09 +0800, Dan Carpenter wrote: > It don't think 6c853da3f30c93 is right. That's the patch > titled "iwmc3200wifi: fix array out-of-boundary access" > > Allocate priv->rx_packets[IWM_RX_ID_HASH + 1] because the max array > index is IWM_RX_ID_HASH according to IWM_RX_ID_GET_HASH(). > > In 2.6.33-rc2 IWM_RX_ID_GET_HASH() doesn't go as high as IWM_RX_ID_HASH > and I don't see any array out-of-bounds. > > #define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH) Ah, you are right. I took '%' for '&'. John, would you revert it? Sorry for the false alarm. Thanks, -yi Reported-by: Dan Carpenter Reviewed-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 842811142bef..79ffa3b98d73 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -268,7 +268,7 @@ struct iwm_priv { struct sk_buff_head rx_list; struct list_head rx_tickets; - struct list_head rx_packets[IWM_RX_ID_HASH + 1]; + struct list_head rx_packets[IWM_RX_ID_HASH]; struct workqueue_struct *rx_wq; struct work_struct rx_worker; -- cgit v1.2.3 From 6021e08db47386507108a475e6c820a7006a4632 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Thu, 7 Jan 2010 11:10:38 -0700 Subject: b43: Declare at least one real firmware file using MODULE_FIRMWARE. BugLink: http://bugs.launchpad.net/bugs/488636 Enhances module information with the names of the firmware files that could be used by this driver. This helps tools like Jockey to correctly detect and/or install the firmware files relevant to this driver. Signed-off-by: Tim Gardner Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6634a77fc766..881afff86bd3 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -67,7 +67,12 @@ MODULE_AUTHOR("Gábor Stefanik"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); - +MODULE_FIRMWARE("b43/ucode11.fw"); +MODULE_FIRMWARE("b43/ucode13.fw"); +MODULE_FIRMWARE("b43/ucode14.fw"); +MODULE_FIRMWARE("b43/ucode15.fw"); +MODULE_FIRMWARE("b43/ucode5.fw"); +MODULE_FIRMWARE("b43/ucode9.fw"); static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); -- cgit v1.2.3 From e99c7cd57b2481ee36b2338040e3ce1cd17e0763 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 7 Jan 2010 17:24:55 -0500 Subject: cfg80211: fix 2 GHz subband calculation for country IEs Country IEs triplets are getting an extra channel with the current count. This does not affect regulatory because we always took the intersection between what the AP gave and what CRDA believed is correct. This however does fix processing some Country IEs with multiple sequential 2 GHz triplets. Since our parser and the spec mandates all channels be monitonically increasing we would drop the IE after noticing the second triplet begins on a channel already processed. APs that send these type of country IEs seems rare though. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a5c2d3a6cbb2..f0859eada758 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -740,7 +740,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( /* 2 GHz */ if (triplet->chans.first_channel <= 14) end_channel = triplet->chans.first_channel + - triplet->chans.num_channels; + triplet->chans.num_channels - 1; else /* * 5 GHz -- For example in country IEs if the first @@ -863,7 +863,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( /* 2 GHz */ if (triplet->chans.first_channel <= 14) end_channel = triplet->chans.first_channel + - triplet->chans.num_channels; + triplet->chans.num_channels -1; else end_channel = triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1)); -- cgit v1.2.3 From c2f4f527edab37f2f2130bd7813cd41db907ab6b Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Tue, 12 Jan 2010 12:58:17 -0600 Subject: b43legacy: Declare all possible ucodeX.fw files Enhance module information with the names of the firmware files that could be used by this driver. This helps tools like Jockey to correctly detect and/or install the firmware files relevant to this driver. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 494017e4fcc9..9e268b6240fb 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -61,6 +61,8 @@ MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); +MODULE_FIRMWARE("b43legacy/ucode2.fw"); +MODULE_FIRMWARE("b43legacy/ucode4.fw"); #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) static int modparam_pio; -- cgit v1.2.3 From ececeecee8c60be96368bcc416057f38822012df Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 12 Jan 2010 18:23:04 -0500 Subject: wl1271: remove unused flags These are unused and as with a previous patch 5ef5da for wl1251 this removes some other unused flags. the IRQ_MASK specifically conflicts with include/pcmcia/cs.h when using compat-wireless. Cc: Kalle Valo Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_reg.h | 99 -------------------------------- 1 file changed, 99 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h index 1f237389d1c7..990960771528 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/wl1271_reg.h @@ -62,73 +62,10 @@ #define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) #define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) #define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) -/* - * Interrupt registers. - * 64 bit interrupt sources registers ws ced. - * sme interupts were removed and new ones were added. - * Order was changed. - */ -#define FIQ_MASK (REGISTERS_BASE + 0x0400) -#define FIQ_MASK_L (REGISTERS_BASE + 0x0400) -#define FIQ_MASK_H (REGISTERS_BASE + 0x0404) -#define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) -#define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) -#define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) -#define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) -#define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) -#define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) -#define IRQ_MASK (REGISTERS_BASE + 0x0418) -#define IRQ_MASK_L (REGISTERS_BASE + 0x0418) -#define IRQ_MASK_H (REGISTERS_BASE + 0x041C) -#define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) -#define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) -#define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) -#define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) -#define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) -#define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) -#define ECPU_MASK (REGISTERS_BASE + 0x0448) -#define FIQ_STS_L (REGISTERS_BASE + 0x044C) -#define FIQ_STS_H (REGISTERS_BASE + 0x0450) -#define IRQ_STS_L (REGISTERS_BASE + 0x0454) -#define IRQ_STS_H (REGISTERS_BASE + 0x0458) -#define INT_STS_ND (REGISTERS_BASE + 0x0464) -#define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) -#define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) -#define INT_STS_CLR (REGISTERS_BASE + 0x04B4) -#define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) -#define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) -#define INT_ACK (REGISTERS_BASE + 0x046C) -#define INT_ACK_L (REGISTERS_BASE + 0x046C) -#define INT_ACK_H (REGISTERS_BASE + 0x0470) -#define INT_TRIG (REGISTERS_BASE + 0x0474) -#define INT_TRIG_L (REGISTERS_BASE + 0x0474) -#define INT_TRIG_H (REGISTERS_BASE + 0x0478) -#define HOST_STS_L (REGISTERS_BASE + 0x045C) -#define HOST_STS_H (REGISTERS_BASE + 0x0460) -#define HOST_MASK (REGISTERS_BASE + 0x0430) -#define HOST_MASK_L (REGISTERS_BASE + 0x0430) -#define HOST_MASK_H (REGISTERS_BASE + 0x0434) -#define HOST_MASK_SET (REGISTERS_BASE + 0x0438) -#define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) -#define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) -#define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) -#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) -#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) #define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) #define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) -/* Host Interrupts*/ -#define HINT_MASK (REGISTERS_BASE + 0x0494) -#define HINT_MASK_SET (REGISTERS_BASE + 0x0498) -#define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) -#define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) -/*1150 spec calls this HINT_STS_RAW*/ -#define HINT_STS_ND (REGISTERS_BASE + 0x04B0) -#define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) -#define HINT_ACK (REGISTERS_BASE + 0x04A8) -#define HINT_TRIG (REGISTERS_BASE + 0x04AC) - /*============================================= Host Interrupt Mask Register - 32bit (RW) ------------------------------------------ @@ -432,16 +369,6 @@ | CFG_RX_PRSP_EN) -/*=============================================== - Phy regs - ===============================================*/ -#define ACX_PHY_ADDR_REG SBB_ADDR -#define ACX_PHY_DATA_REG SBB_DATA -#define ACX_PHY_CTRL_REG SBB_CTL -#define ACX_PHY_REG_WR_MASK 0x00000001ul -#define ACX_PHY_REG_RD_MASK 0x00000002ul - - /*=============================================== EEPROM Read/Write Request 32bit RW ------------------------------------------ @@ -511,28 +438,6 @@ #define ACX_CONT_WIND_MIN_MASK 0x0000007f #define ACX_CONT_WIND_MAX 0x03ff0000 -/* - * Indirect slave register/memory registers - * ---------------------------------------- - */ -#define HW_SLAVE_REG_ADDR_REG 0x00000004 -#define HW_SLAVE_REG_DATA_REG 0x00000008 -#define HW_SLAVE_REG_CTRL_REG 0x0000000c - -#define SLAVE_AUTO_INC 0x00010000 -#define SLAVE_NO_AUTO_INC 0x00000000 -#define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 - -#define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR -#define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA -#define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL -#define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL - -#define HW_FUNC_EVENT_INT_EN 0x8000 -#define HW_FUNC_EVENT_MASK_REG 0x00000034 - -#define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) - /*=============================================== HI_CFG Interface Configuration Register Values ------------------------------------------ @@ -647,10 +552,6 @@ b12-b0 - Supported Rate indicator bits as defined below. ******************************************************************************/ -#define TNETW1251_CHIP_ID_PG1_0 0x07010101 -#define TNETW1251_CHIP_ID_PG1_1 0x07020101 -#define TNETW1251_CHIP_ID_PG1_2 0x07030101 - /************************************************************************* Interrupt Trigger Register (Host -> WiLink) -- cgit v1.2.3 From 2f1f00fc9b477481ad5c63976385c345851fee3d Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 13 Jan 2010 14:36:24 +0100 Subject: Remove config option B43_LEGACY_RFKILL completely In f41f3f373dd72344c65d801d6381fe83ef3a2c54 the B43 driver was ported to use the cfg80211 API for rfkill and consequently the config option was dropped (RFKILL is now unconditionally enabled). However in the Kernel Info the feature is still checked and reported missing. This patch just removes the conditional and the relevant code blocks while still reporting that feature unconditionally would be another option (it's always there). Signed-off-by: Christoph Egger Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 9e268b6240fb..174ac6bde2b1 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3962,7 +3962,7 @@ static struct ssb_driver b43legacy_ssb_driver = { static void b43legacy_print_driverinfo(void) { - const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "", + const char *feat_pci = "", *feat_leds = "", *feat_pio = "", *feat_dma = ""; #ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT @@ -3971,9 +3971,6 @@ static void b43legacy_print_driverinfo(void) #ifdef CONFIG_B43LEGACY_LEDS feat_leds = "L"; #endif -#ifdef CONFIG_B43LEGACY_RFKILL - feat_rfkill = "R"; -#endif #ifdef CONFIG_B43LEGACY_PIO feat_pio = "I"; #endif @@ -3981,9 +3978,9 @@ static void b43legacy_print_driverinfo(void) feat_dma = "D"; #endif printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " + "[ Features: %s%s%s%s, Firmware-ID: " B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", - feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); + feat_pci, feat_leds, feat_pio, feat_dma); } static int __init b43legacy_init(void) -- cgit v1.2.3 From 5e4ea1f0ed256382d6d839fbd7a5c7f1b99b6cb0 Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 14 Jan 2010 10:20:57 +0530 Subject: ath9k: Fix panic on driver load The device has to be marked as invalid before registering the ISR. HW initialization takes place after the ISR has been registered, and the invalid flag is eventually cleared in the ->stop() callback. Reported-by: Pavel Roskin Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ahb.c | 3 +++ drivers/net/wireless/ath/ath9k/init.c | 2 -- drivers/net/wireless/ath/ath9k/pci.c | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index f24b1f4c3e29..9e62a569e816 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -121,6 +121,9 @@ static int ath_ahb_probe(struct platform_device *pdev) sc->mem = mem; sc->irq = irq; + /* Will be cleared in ath9k_start() */ + sc->sc_flags |= SC_OP_INVALID; + ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { dev_err(&pdev->dev, "request_irq failed\n"); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 16d1efb4b8b2..5f78d7a5ff22 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -534,8 +534,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, int ret = 0, i; int csz = 0; - sc->sc_flags |= SC_OP_INVALID; - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); if (!ah) return -ENOMEM; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 95b9a07597ef..4ae7b5f12029 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -198,6 +198,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->dev = &pdev->dev; sc->mem = mem; + /* Will be cleared in ath9k_start() */ + sc->sc_flags |= SC_OP_INVALID; + ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { dev_err(&pdev->dev, "request_irq failed\n"); -- cgit v1.2.3 From 9d173fc5dfa8c1b4578b331ac7ff3ce8af27006e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 14 Jan 2010 13:09:14 +0200 Subject: mac80211: fix mac80211.h documentation warnings There were some warnings about missing documentation and a missing reference. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- Documentation/DocBook/mac80211.tmpl | 2 +- include/net/mac80211.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index f3f37f141dbd..971d1c0c83e5 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -144,7 +144,7 @@ usage should require reading the full document. this though and the recommendation to allow only a single interface in STA mode at first! -!Finclude/net/mac80211.h ieee80211_if_init_conf +!Finclude/net/mac80211.h ieee80211_vif diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f313a3cbabda..bbfa4750092e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -107,6 +107,7 @@ enum ieee80211_max_queues { * 2^n-1 in the range 1..32767] * @cw_max: maximum contention window [like @cw_min] * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled + * @uapsd: is U-APSD mode enabled for the queue */ struct ieee80211_tx_queue_params { u16 txop; @@ -608,7 +609,11 @@ enum ieee80211_conf_changed { /** * enum ieee80211_smps_mode - spatial multiplexing power save mode * - * @ + * @IEEE80211_SMPS_AUTOMATIC: automatic + * @IEEE80211_SMPS_OFF: off + * @IEEE80211_SMPS_STATIC: static + * @IEEE80211_SMPS_DYNAMIC: dynamic + * @IEEE80211_SMPS_NUM_MODES: internal, don't use */ enum ieee80211_smps_mode { IEEE80211_SMPS_AUTOMATIC, -- cgit v1.2.3 From c99445b14054e0c4ed4715df1dad1fc608cbab46 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 14 Jan 2010 13:09:21 +0200 Subject: mac80211: improve powersave documentation There has been some confusion how drivers should implement powersave support. Improve the documentation a bit to make it more clear what drivers need to do. Also mention about U-APSD. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 75 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bbfa4750092e..c90047de4428 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -569,7 +569,13 @@ struct ieee80211_rx_status { * @IEEE80211_CONF_MONITOR: there's a monitor interface present -- use this * to determine for example whether to calculate timestamps for packets * or not, do not use instead of filter flags! - * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only) + * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only). + * This is the power save mode defined by IEEE 802.11-2007 section 11.2, + * meaning that the hardware still wakes up for beacons, is able to + * transmit frames and receive the possible acknowledgment frames. + * Not to be confused with hardware specific wakeup/sleep states, + * driver is responsible for that. See the section "Powersave support" + * for more. * @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set * the driver should be prepared to handle configuration requests but * may turn the device off as much as possible. Typically, this flag will @@ -1138,18 +1144,24 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * * mac80211 has support for various powersave implementations. * - * First, it can support hardware that handles all powersaving by - * itself, such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS - * hardware flag. In that case, it will be told about the desired - * powersave mode depending on the association status, and the driver - * must take care of sending nullfunc frames when necessary, i.e. when - * entering and leaving powersave mode. The driver is required to look at - * the AID in beacons and signal to the AP that it woke up when it finds - * traffic directed to it. This mode supports dynamic PS by simply - * enabling/disabling PS. - * - * Additionally, such hardware may set the %IEEE80211_HW_SUPPORTS_DYNAMIC_PS - * flag to indicate that it can support dynamic PS mode itself (see below). + * First, it can support hardware that handles all powersaving by itself, + * such hardware should simply set the %IEEE80211_HW_SUPPORTS_PS hardware + * flag. In that case, it will be told about the desired powersave mode + * with the %IEEE80211_CONF_PS flag depending on the association status. + * The hardware must take care of sending nullfunc frames when necessary, + * i.e. when entering and leaving powersave mode. The hardware is required + * to look at the AID in beacons and signal to the AP that it woke up when + * it finds traffic directed to it. + * + * %IEEE80211_CONF_PS flag enabled means that the powersave mode defined in + * IEEE 802.11-2007 section 11.2 is enabled. This is not to be confused + * with hardware wakeup and sleep states. Driver is responsible for waking + * up the hardware before issueing commands to the hardware and putting it + * back to sleep at approriate times. + * + * When PS is enabled, hardware needs to wakeup for beacons and receive the + * buffered multicast/broadcast frames after the beacon. Also it must be + * possible to send frames and receive the acknowledment frame. * * Other hardware designs cannot send nullfunc frames by themselves and also * need software support for parsing the TIM bitmap. This is also supported @@ -1157,14 +1169,35 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * %IEEE80211_HW_PS_NULLFUNC_STACK flags. The hardware is of course still * required to pass up beacons. The hardware is still required to handle * waking up for multicast traffic; if it cannot the driver must handle that - * as best as it can, mac80211 is too slow. - * - * Dynamic powersave mode is an extension to normal powersave mode in which - * the hardware stays awake for a user-specified period of time after sending - * a frame so that reply frames need not be buffered and therefore delayed - * to the next wakeup. This can either be supported by hardware, in which case - * the driver needs to look at the @dynamic_ps_timeout hardware configuration - * value, or by the stack if all nullfunc handling is in the stack. + * as best as it can, mac80211 is too slow to do that. + * + * Dynamic powersave is an extension to normal powersave in which the + * hardware stays awake for a user-specified period of time after sending a + * frame so that reply frames need not be buffered and therefore delayed to + * the next wakeup. It's compromise of getting good enough latency when + * there's data traffic and still saving significantly power in idle + * periods. + * + * Dynamic powersave is supported by simply mac80211 enabling and disabling + * PS based on traffic. Driver needs to only set %IEEE80211_HW_SUPPORTS_PS + * flag and mac80211 will handle everything automatically. Additionally, + * hardware having support for the dynamic PS feature may set the + * %IEEE80211_HW_SUPPORTS_DYNAMIC_PS flag to indicate that it can support + * dynamic PS mode itself. The driver needs to look at the + * @dynamic_ps_timeout hardware configuration value and use it that value + * whenever %IEEE80211_CONF_PS is set. In this case mac80211 will disable + * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS + * enabled whenever user has enabled powersave. + * + * Driver informs U-APSD client support by enabling + * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the + * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS + * Nullfunc frames and stay awake until the service period has ended. To + * utilize U-APSD, dynamic powersave is disabled for voip AC and all frames + * from that AC are transmitted with powersave enabled. + * + * Note: U-APSD client mode is not yet supported with + * %IEEE80211_HW_PS_NULLFUNC_STACK. */ /** -- cgit v1.2.3 From a0f2e0fca1e72c1de07e834be05b61d33842253e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 14 Jan 2010 13:27:46 -0500 Subject: cfg80211: Ingore country IEs with a zero set of number of channels Previous to this and the last patch, titled, "cfg80211: Fix 2 GHz subband calculation for country IEs" we would end up treating these IEs as single channel units. These are in fact just bogus IE triplets so ignore the entire IE if these are found. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f0859eada758..f3b77f7b8e3d 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -585,6 +585,9 @@ static int max_subband_chan(int orig_cur_chan, break; } + if (triplet->chans.num_channels == 0) + return 0; + /* Monitonically increasing channel order */ if (triplet->chans.first_channel <= end_subband_chan) return 0; @@ -737,6 +740,9 @@ static struct ieee80211_regdomain *country_ie_2_rd( break; } + if (triplet->chans.num_channels == 0) + return NULL; + /* 2 GHz */ if (triplet->chans.first_channel <= 14) end_channel = triplet->chans.first_channel + -- cgit v1.2.3 From b6b1ac69372da996f40863358df41ca77075b249 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Jan 2010 13:13:47 -0600 Subject: Staging: r8187se: Fix compile error from wireless-testing commit 7044cc56 In wireless-testing, commit 7044cc56 added struct ieee80211_hdr_3addr to include/linux/ieee80211.h. This definition collides with one that is in the r8187se driver in staging. The conflict is resolved by changing r8187se to use the definition from include/linuc/ieee80211.h. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 9 -------- .../rtl8187se/ieee80211/ieee80211_softmac.c | 24 +++++++++++----------- drivers/staging/rtl8187se/r8180_core.c | 4 ++-- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 3222c22152fb..462578703d07 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -482,15 +482,6 @@ struct ieee80211_header_data { u16 seq_ctrl; }; -struct ieee80211_hdr_3addr { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; -} __attribute__ ((packed)); - struct ieee80211_hdr_4addr { u16 frame_ctl; u16 duration_id; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 334e4c7ec61b..cc9da3713526 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -203,7 +203,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee enqueue_mgmt(ieee,skb); }else{ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -220,7 +220,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee spin_unlock_irqrestore(&ieee->lock, flags); spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -246,7 +246,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i if(single){ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -259,7 +259,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i }else{ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -287,7 +287,7 @@ inline struct sk_buff *ieee80211_disassociate_skb( return NULL; disass = (struct ieee80211_disassoc_frame *) skb_put(skb,sizeof(struct ieee80211_disassoc_frame)); - disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC); + disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); disass->header.duration_id = 0; memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); @@ -905,7 +905,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) assoc = (struct ieee80211_assoc_response_frame *) skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); - assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); + assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); memcpy(assoc->header.addr1, dest,ETH_ALEN); memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); @@ -981,7 +981,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); - hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | (pwr ? IEEE80211_FCTL_PM:0)); @@ -1084,7 +1084,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)); - hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; + hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ; hdr->header.duration_id= 37; //FIXME memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); @@ -1786,11 +1786,11 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, tasklet_schedule(&ieee->ps_task); - if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP && - WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON) + if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP && + WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON) ieee->last_rx_ps_time = jiffies; - switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + switch (WLAN_FC_GET_STYPE(header->frame_control)) { case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: @@ -2064,7 +2064,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee) header = (struct ieee80211_hdr_3addr *) skb->data; - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 53e654d0d4fa..7788bc42e9b4 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -1909,7 +1909,7 @@ rate) struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); int mode; struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data; - short morefrag = (h->frame_ctl) & IEEE80211_FCTL_MOREFRAGS; + short morefrag = (h->frame_control) & IEEE80211_FCTL_MOREFRAGS; unsigned long flags; int priority; @@ -2177,7 +2177,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority, TxDescDuration = ThisFrameTime + aSifsTime + AckTime; } - if(!(frag_hdr->frame_ctl & IEEE80211_FCTL_MOREFRAGS)) { //no more fragment + if (!(frag_hdr->frame_control & IEEE80211_FCTL_MOREFRAGS)) { // ThisFrame-ACK. Duration = aSifsTime + AckTime; } else { // One or more fragments remained. -- cgit v1.2.3 From 4d0392be21d4710121f855c0caf57d32ffd1ced0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 15 Jan 2010 01:08:58 -0800 Subject: net/core/sock.c: quiet sparse noise In sock_getsockopt the symbol 'lv' is declared as an unsigned int type, probably due to sizeof returning a size_t which is really an unsigned int. This produces a sparse warning for SO_PEERNAME due to the sock->ops->getname() call: warning: incorrect type in argument 3 (different signedness) expected int *sockaddr_len got unsigned int * Quiet the warning by changing the type of 'lv' to an int. Signed-off-by: H Hartley Sweeten Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index e1f6f225f012..10b1d3243a72 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -741,7 +741,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, struct timeval tm; } v; - unsigned int lv = sizeof(int); + int lv = sizeof(int); int len; if (get_user(len, optlen)) -- cgit v1.2.3 From 71fceff0ea36d5a6cffecb272b8b3970535fe905 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 15 Jan 2010 01:16:40 -0800 Subject: ipv4: Use less conflicting local var name in change_nexthops() loop macro. As noticed by H Hartley Sweeten, since change_nexthops() uses 'nh' as it's iterator variable, it can conflict with other existing local vars. Use "nexthop_nh" to avoid the conflict and make it easier to figure out where this magic variable comes from. Signed-off-by: David S. Miller --- net/ipv4/fib_semantics.c | 76 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ed19aa6919c2..96b21011a3e4 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -62,8 +62,8 @@ static DEFINE_SPINLOCK(fib_multipath_lock); #define for_nexthops(fi) { int nhsel; const struct fib_nh * nh; \ for (nhsel=0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++) -#define change_nexthops(fi) { int nhsel; struct fib_nh * nh; \ -for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++) +#define change_nexthops(fi) { int nhsel; struct fib_nh *nexthop_nh; \ +for (nhsel=0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nexthop_nh++, nhsel++) #else /* CONFIG_IP_ROUTE_MULTIPATH */ @@ -72,7 +72,7 @@ for (nhsel=0, nh = (struct fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, #define for_nexthops(fi) { int nhsel = 0; const struct fib_nh * nh = (fi)->fib_nh; \ for (nhsel=0; nhsel < 1; nhsel++) -#define change_nexthops(fi) { int nhsel = 0; struct fib_nh * nh = (struct fib_nh *)((fi)->fib_nh); \ +#define change_nexthops(fi) { int nhsel = 0; struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \ for (nhsel=0; nhsel < 1; nhsel++) #endif /* CONFIG_IP_ROUTE_MULTIPATH */ @@ -145,9 +145,9 @@ void free_fib_info(struct fib_info *fi) return; } change_nexthops(fi) { - if (nh->nh_dev) - dev_put(nh->nh_dev); - nh->nh_dev = NULL; + if (nexthop_nh->nh_dev) + dev_put(nexthop_nh->nh_dev); + nexthop_nh->nh_dev = NULL; } endfor_nexthops(fi); fib_info_cnt--; release_net(fi->fib_net); @@ -162,9 +162,9 @@ void fib_release_info(struct fib_info *fi) if (fi->fib_prefsrc) hlist_del(&fi->fib_lhash); change_nexthops(fi) { - if (!nh->nh_dev) + if (!nexthop_nh->nh_dev) continue; - hlist_del(&nh->nh_hash); + hlist_del(&nexthop_nh->nh_hash); } endfor_nexthops(fi) fi->fib_dead = 1; fib_info_put(fi); @@ -395,19 +395,20 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, if (!rtnh_ok(rtnh, remaining)) return -EINVAL; - nh->nh_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; - nh->nh_oif = rtnh->rtnh_ifindex; - nh->nh_weight = rtnh->rtnh_hops + 1; + nexthop_nh->nh_flags = + (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; + nexthop_nh->nh_oif = rtnh->rtnh_ifindex; + nexthop_nh->nh_weight = rtnh->rtnh_hops + 1; attrlen = rtnh_attrlen(rtnh); if (attrlen > 0) { struct nlattr *nla, *attrs = rtnh_attrs(rtnh); nla = nla_find(attrs, attrlen, RTA_GATEWAY); - nh->nh_gw = nla ? nla_get_be32(nla) : 0; + nexthop_nh->nh_gw = nla ? nla_get_be32(nla) : 0; #ifdef CONFIG_NET_CLS_ROUTE nla = nla_find(attrs, attrlen, RTA_FLOW); - nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; + nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; #endif } @@ -738,7 +739,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi->fib_nhs = nhs; change_nexthops(fi) { - nh->nh_parent = fi; + nexthop_nh->nh_parent = fi; } endfor_nexthops(fi) if (cfg->fc_mx) { @@ -808,7 +809,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto failure; } else { change_nexthops(fi) { - if ((err = fib_check_nh(cfg, fi, nh)) != 0) + if ((err = fib_check_nh(cfg, fi, nexthop_nh)) != 0) goto failure; } endfor_nexthops(fi) } @@ -843,11 +844,11 @@ link_it: struct hlist_head *head; unsigned int hash; - if (!nh->nh_dev) + if (!nexthop_nh->nh_dev) continue; - hash = fib_devindex_hashfn(nh->nh_dev->ifindex); + hash = fib_devindex_hashfn(nexthop_nh->nh_dev->ifindex); head = &fib_info_devhash[hash]; - hlist_add_head(&nh->nh_hash, head); + hlist_add_head(&nexthop_nh->nh_hash, head); } endfor_nexthops(fi) spin_unlock_bh(&fib_info_lock); return fi; @@ -1080,21 +1081,21 @@ int fib_sync_down_dev(struct net_device *dev, int force) prev_fi = fi; dead = 0; change_nexthops(fi) { - if (nh->nh_flags&RTNH_F_DEAD) + if (nexthop_nh->nh_flags&RTNH_F_DEAD) dead++; - else if (nh->nh_dev == dev && - nh->nh_scope != scope) { - nh->nh_flags |= RTNH_F_DEAD; + else if (nexthop_nh->nh_dev == dev && + nexthop_nh->nh_scope != scope) { + nexthop_nh->nh_flags |= RTNH_F_DEAD; #ifdef CONFIG_IP_ROUTE_MULTIPATH spin_lock_bh(&fib_multipath_lock); - fi->fib_power -= nh->nh_power; - nh->nh_power = 0; + fi->fib_power -= nexthop_nh->nh_power; + nexthop_nh->nh_power = 0; spin_unlock_bh(&fib_multipath_lock); #endif dead++; } #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (force > 1 && nh->nh_dev == dev) { + if (force > 1 && nexthop_nh->nh_dev == dev) { dead = fi->fib_nhs; break; } @@ -1144,18 +1145,20 @@ int fib_sync_up(struct net_device *dev) prev_fi = fi; alive = 0; change_nexthops(fi) { - if (!(nh->nh_flags&RTNH_F_DEAD)) { + if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { alive++; continue; } - if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP)) + if (nexthop_nh->nh_dev == NULL || + !(nexthop_nh->nh_dev->flags&IFF_UP)) continue; - if (nh->nh_dev != dev || !__in_dev_get_rtnl(dev)) + if (nexthop_nh->nh_dev != dev || + !__in_dev_get_rtnl(dev)) continue; alive++; spin_lock_bh(&fib_multipath_lock); - nh->nh_power = 0; - nh->nh_flags &= ~RTNH_F_DEAD; + nexthop_nh->nh_power = 0; + nexthop_nh->nh_flags &= ~RTNH_F_DEAD; spin_unlock_bh(&fib_multipath_lock); } endfor_nexthops(fi) @@ -1182,9 +1185,9 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) if (fi->fib_power <= 0) { int power = 0; change_nexthops(fi) { - if (!(nh->nh_flags&RTNH_F_DEAD)) { - power += nh->nh_weight; - nh->nh_power = nh->nh_weight; + if (!(nexthop_nh->nh_flags&RTNH_F_DEAD)) { + power += nexthop_nh->nh_weight; + nexthop_nh->nh_power = nexthop_nh->nh_weight; } } endfor_nexthops(fi); fi->fib_power = power; @@ -1204,9 +1207,10 @@ void fib_select_multipath(const struct flowi *flp, struct fib_result *res) w = jiffies % fi->fib_power; change_nexthops(fi) { - if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) { - if ((w -= nh->nh_power) <= 0) { - nh->nh_power--; + if (!(nexthop_nh->nh_flags&RTNH_F_DEAD) && + nexthop_nh->nh_power) { + if ((w -= nexthop_nh->nh_power) <= 0) { + nexthop_nh->nh_power--; fi->fib_power--; res->nh_sel = nhsel; spin_unlock_bh(&fib_multipath_lock); -- cgit v1.2.3 From a03d2451998e09e87eb573a9e04cc41fde2bb77f Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 14 Jan 2010 01:53:21 +0000 Subject: netxen: fix endianness read mac address In netxen_read_mac_addr, mac_addr should be declared u64 instead of __le64, used by host only. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 4 ++-- drivers/net/netxen/netxen_nic_hw.c | 4 ++-- drivers/net/netxen/netxen_nic_main.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 8264ae0cbf1d..1e9c8fa46c71 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1427,8 +1427,8 @@ static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring) } -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); -int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac); +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 85e28e60ecf1..0db36f190ba2 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1033,7 +1033,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, return 0; } -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac) { __le32 *pmac = (__le32 *) mac; u32 offset; @@ -1058,7 +1058,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) return 0; } -int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac) { uint32_t crbaddr, mac_hi, mac_lo; int pci_func = adapter->ahw.pci_func; diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index def4a07357d6..b69cb3c7dfb6 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -432,7 +432,7 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) { int i; unsigned char *p; - __le64 mac_addr; + u64 mac_addr; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; -- cgit v1.2.3 From c070395009e1e153395837cd256dffc931dd6f98 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 14 Jan 2010 01:53:22 +0000 Subject: netxen: fix endianness intr coalesce Before sending Interrupt coalesce parameters to device, convert them in little endian. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_hw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 0db36f190ba2..9548e5967399 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -777,17 +777,20 @@ int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) int netxen_config_intr_coalesce(struct netxen_adapter *adapter) { nx_nic_req_t req; - u64 word; - int rv; + u64 word[6]; + int rv, i; memset(&req, 0, sizeof(nx_nic_req_t)); + memset(word, 0, sizeof(word)); req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); - word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); - req.req_hdr = cpu_to_le64(word); + word[0] = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word[0]); - memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal)); + memcpy(&word[0], &adapter->coal, sizeof(adapter->coal)); + for (i = 0; i < 6; i++) + req.words[i] = cpu_to_le64(word[i]); rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) { -- cgit v1.2.3 From 4d21fef426c5cbbdf6da607de4c0adcaa3d4bbb0 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 14 Jan 2010 01:53:23 +0000 Subject: netxen: fix license header GNU General Public License is in file "COPYING". Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/Makefile | 2 +- drivers/net/netxen/netxen_nic.h | 2 +- drivers/net/netxen/netxen_nic_ctx.c | 2 +- drivers/net/netxen/netxen_nic_ethtool.c | 2 +- drivers/net/netxen/netxen_nic_hdr.h | 2 +- drivers/net/netxen/netxen_nic_hw.c | 2 +- drivers/net/netxen/netxen_nic_hw.h | 2 +- drivers/net/netxen/netxen_nic_init.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile index 11d94e2434e4..861a0590b1f4 100644 --- a/drivers/net/netxen/Makefile +++ b/drivers/net/netxen/Makefile @@ -18,7 +18,7 @@ # MA 02111-1307, USA. # # The full GNU General Public License is included in this distribution -# in the file called LICENSE. +# in the file called "COPYING". # # diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 1e9c8fa46c71..144d2e880422 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 9cb8f6878047..2a8ef5fc9663 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 542f408333ff..f8499e56cbee 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 638369024908..622e4c8be937 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9548e5967399..dd45c7a9122e 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index 3fd1dcb3583a..e2c5b6f2df03 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 333bd325f58e..1c63610ead42 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index b69cb3c7dfb6..e5bdd4de7731 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -19,7 +19,7 @@ * MA 02111-1307, USA. * * The full GNU General Public License is included in this distribution - * in the file called LICENSE. + * in the file called "COPYING". * */ -- cgit v1.2.3 From 1954dc11776ef8c06263ba4cd21bf4d25c79a19c Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Thu, 14 Jan 2010 01:53:24 +0000 Subject: netxen: fix sparse warning Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index e5bdd4de7731..076f826d5a50 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2596,7 +2596,7 @@ netxen_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, return size; } -ssize_t netxen_sysfs_write_mem(struct kobject *kobj, +static ssize_t netxen_sysfs_write_mem(struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { -- cgit v1.2.3 From ad72c347e56bf3a0231b9d686e17764157d2961c Mon Sep 17 00:00:00 2001 From: Christian Pellegrin Date: Thu, 14 Jan 2010 07:08:34 +0000 Subject: can: Proper ctrlmode handling for CAN devices This patch adds error checking of ctrlmode values for CAN devices. As an example all availabe bits are implemented in the mcp251x driver. Signed-off-by: Christian Pellegrin Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/at91_can.c | 1 + drivers/net/can/bfin_can.c | 1 + drivers/net/can/dev.c | 2 ++ drivers/net/can/mcp251x.c | 11 ++++++++++- drivers/net/can/mscan/mscan.c | 1 + drivers/net/can/sja1000/sja1000.c | 1 + drivers/net/can/ti_hecc.c | 1 + drivers/net/can/usb/ems_usb.c | 1 + include/linux/can/dev.h | 1 + 9 files changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index f7287497ba6e..a2f29a38798a 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1073,6 +1073,7 @@ static int __init at91_can_probe(struct platform_device *pdev) priv->can.bittiming_const = &at91_bittiming_const; priv->can.do_set_bittiming = at91_set_bittiming; priv->can.do_set_mode = at91_set_mode; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; priv->reg_base = addr; priv->dev = dev; priv->clk = clk; diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index 7e1926e79e98..bf7f9ba2d903 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -603,6 +603,7 @@ struct net_device *alloc_bfin_candev(void) priv->can.bittiming_const = &bfin_can_bittiming_const; priv->can.do_set_bittiming = bfin_can_set_bittiming; priv->can.do_set_mode = bfin_can_set_mode; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; return dev; } diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index c1bb29f0322b..f08f1202ff00 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -592,6 +592,8 @@ static int can_changelink(struct net_device *dev, if (dev->flags & IFF_UP) return -EBUSY; cm = nla_data(data[IFLA_CAN_CTRLMODE]); + if (cm->flags & ~priv->ctrlmode_supported) + return -EOPNOTSUPP; priv->ctrlmode &= ~cm->mask; priv->ctrlmode |= cm->flags; } diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index afa2fa45fed9..bbe186b5a0ed 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -539,9 +539,14 @@ static void mcp251x_set_normal_mode(struct spi_device *spi) if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { /* Put device into loopback mode */ mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK); + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { + /* Put device into listen-only mode */ + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY); } else { /* Put device into normal mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | + (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT ? + CANCTRL_OSM : 0)); /* Wait for the device to enter normal mode */ timeout = jiffies + HZ; @@ -948,6 +953,10 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) priv->can.bittiming_const = &mcp251x_bittiming_const; priv->can.do_set_mode = mcp251x_do_set_mode; priv->can.clock.freq = pdata->oscillator_frequency / 2; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; + if (pdata->model == CAN_MCP251X_MCP2515) + priv->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; priv->net = net; dev_set_drvdata(&spi->dev, priv); diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 40827c128b65..6b7dd578d417 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -686,6 +686,7 @@ struct net_device *alloc_mscandev(void) priv->can.bittiming_const = &mscan_bittiming_const; priv->can.do_set_bittiming = mscan_do_set_bittiming; priv->can.do_set_mode = mscan_do_set_mode; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; for (i = 0; i < TX_QUEUE_SIZE; i++) { priv->tx_queue[i].id = i; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 345304d779b9..ace103a44833 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -567,6 +567,7 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) priv->can.bittiming_const = &sja1000_bittiming_const; priv->can.do_set_bittiming = sja1000_set_bittiming; priv->can.do_set_mode = sja1000_set_mode; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; if (sizeof_priv) priv->priv = (void *)priv + sizeof(struct sja1000_priv); diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 7d370e32a7a8..8332e242b0be 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -909,6 +909,7 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->can.bittiming_const = &ti_hecc_bittiming_const; priv->can.do_set_mode = ti_hecc_do_set_mode; priv->can.do_get_state = ti_hecc_get_state; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; ndev->irq = irq->start; ndev->flags |= IFF_ECHO; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index ddb17e256656..bfab283ba9b1 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -1022,6 +1022,7 @@ static int ems_usb_probe(struct usb_interface *intf, dev->can.bittiming_const = &ems_usb_bittiming_const; dev->can.do_set_bittiming = ems_usb_set_bittiming; dev->can.do_set_mode = ems_usb_set_mode; + dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; netdev->flags |= IFF_ECHO; /* we support local echo */ diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 7e7c98a3e908..c8c660a79f90 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -38,6 +38,7 @@ struct can_priv { enum can_state state; u32 ctrlmode; + u32 ctrlmode_supported; int restart_ms; struct timer_list restart_timer; -- cgit v1.2.3 From 05c2828c72c4eabf62376adfe27bd24797621f62 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 14 Jan 2010 06:17:09 +0000 Subject: tun: export underlying socket Tun device looks similar to a packet socket in that both pass complete frames from/to userspace. This patch fills in enough fields in the socket underlying tun driver to support sendmsg/recvmsg operations, and message flags MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket to modules. Regular read/write behaviour is unchanged. This way, code using raw sockets to inject packets into a physical device, can support injecting packets into host network stack almost without modification. First user of this interface will be vhost virtualization accelerator. Signed-off-by: Michael S. Tsirkin Acked-by: Herbert Xu Acked-by: David S. Miller Signed-off-by: David S. Miller --- drivers/net/tun.c | 101 +++++++++++++++++++++++++++++++++++++++---------- include/linux/if_tun.h | 14 +++++++ 2 files changed, 96 insertions(+), 19 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2834a01bae24..5adb3d150552 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -144,6 +144,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) err = 0; tfile->tun = tun; tun->tfile = tfile; + tun->socket.file = file; dev_hold(tun->dev); sock_hold(tun->socket.sk); atomic_inc(&tfile->count); @@ -158,6 +159,7 @@ static void __tun_detach(struct tun_struct *tun) /* Detach from net device */ netif_tx_lock_bh(tun->dev); tun->tfile = NULL; + tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); /* Drop read queue */ @@ -387,7 +389,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) /* Notify and wake up reader process */ if (tun->flags & TUN_FASYNC) kill_fasync(&tun->fasync, SIGIO, POLL_IN); - wake_up_interruptible(&tun->socket.wait); + wake_up_interruptible_poll(&tun->socket.wait, POLLIN | + POLLRDNORM | POLLRDBAND); return NETDEV_TX_OK; drop: @@ -743,7 +746,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, len = min_t(int, skb->len, len); skb_copy_datagram_const_iovec(skb, 0, iv, total, len); - total += len; + total += skb->len; tun->dev->stats.tx_packets++; tun->dev->stats.tx_bytes += len; @@ -751,34 +754,23 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, return total; } -static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t tun_do_read(struct tun_struct *tun, + struct kiocb *iocb, const struct iovec *iv, + ssize_t len, int noblock) { - struct file *file = iocb->ki_filp; - struct tun_file *tfile = file->private_data; - struct tun_struct *tun = __tun_get(tfile); DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; - ssize_t len, ret = 0; - - if (!tun) - return -EBADFD; + ssize_t ret = 0; DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name); - len = iov_length(iv, count); - if (len < 0) { - ret = -EINVAL; - goto out; - } - add_wait_queue(&tun->socket.wait, &wait); while (len) { current->state = TASK_INTERRUPTIBLE; /* Read frames from the queue */ if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) { - if (file->f_flags & O_NONBLOCK) { + if (noblock) { ret = -EAGAIN; break; } @@ -805,6 +797,27 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, current->state = TASK_RUNNING; remove_wait_queue(&tun->socket.wait, &wait); + return ret; +} + +static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct tun_file *tfile = file->private_data; + struct tun_struct *tun = __tun_get(tfile); + ssize_t len, ret; + + if (!tun) + return -EBADFD; + len = iov_length(iv, count); + if (len < 0) { + ret = -EINVAL; + goto out; + } + + ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); out: tun_put(tun); return ret; @@ -847,7 +860,8 @@ static void tun_sock_write_space(struct sock *sk) return; if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible_sync(sk->sk_sleep); + wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | + POLLWRNORM | POLLWRBAND); tun = tun_sk(sk)->tun; kill_fasync(&tun->fasync, SIGIO, POLL_OUT); @@ -858,6 +872,37 @@ static void tun_sock_destruct(struct sock *sk) free_netdev(tun_sk(sk)->tun->dev); } +static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct tun_struct *tun = container_of(sock, struct tun_struct, socket); + return tun_get_user(tun, m->msg_iov, total_len, + m->msg_flags & MSG_DONTWAIT); +} + +static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags) +{ + struct tun_struct *tun = container_of(sock, struct tun_struct, socket); + int ret; + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) + return -EINVAL; + ret = tun_do_read(tun, iocb, m->msg_iov, total_len, + flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } + return ret; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops tun_socket_ops = { + .sendmsg = tun_sendmsg, + .recvmsg = tun_recvmsg, +}; + static struct proto tun_proto = { .name = "tun", .owner = THIS_MODULE, @@ -986,6 +1031,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) goto err_free_dev; init_waitqueue_head(&tun->socket.wait); + tun->socket.ops = &tun_socket_ops; sock_init_data(&tun->socket, sk); sk->sk_write_space = tun_sock_write_space; sk->sk_sndbuf = INT_MAX; @@ -1525,6 +1571,23 @@ static void tun_cleanup(void) rtnl_link_unregister(&tun_link_ops); } +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *tun_get_socket(struct file *file) +{ + struct tun_struct *tun; + if (file->f_op != &tun_fops) + return ERR_PTR(-EINVAL); + tun = tun_get(file); + if (!tun) + return ERR_PTR(-EBADFD); + tun_put(tun); + return &tun->socket; +} +EXPORT_SYMBOL_GPL(tun_get_socket); + module_init(tun_init); module_exit(tun_cleanup); MODULE_DESCRIPTION(DRV_DESCRIPTION); diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 3f5fd523b49d..404abe00162c 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -86,4 +86,18 @@ struct tun_filter { __u8 addr[0][ETH_ALEN]; }; +#ifdef __KERNEL__ +#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE) +struct socket *tun_get_socket(struct file *); +#else +#include +#include +struct file; +struct socket; +static inline struct socket *tun_get_socket(struct file *f) +{ + return ERR_PTR(-EINVAL); +} +#endif /* CONFIG_TUN */ +#endif /* __KERNEL__ */ #endif /* __IF_TUN_H */ -- cgit v1.2.3 From 5da779c34ccff5e1e617892b6c8bd8260fb1f04c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 14 Jan 2010 06:17:18 +0000 Subject: mm: export use_mm/unuse_mm to modules vhost net module wants to do copy to/from user from a kernel thread, which needs use_mm. Export it to modules. Acked-by: Andrea Arcangeli Acked-by: Andrew Morton Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- mm/mmu_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/mmu_context.c b/mm/mmu_context.c index ded9081f4021..0777654147c9 100644 --- a/mm/mmu_context.c +++ b/mm/mmu_context.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ void use_mm(struct mm_struct *mm) if (active_mm != mm) mmdrop(active_mm); } +EXPORT_SYMBOL_GPL(use_mm); /* * unuse_mm @@ -56,3 +58,4 @@ void unuse_mm(struct mm_struct *mm) enter_lazy_tlb(mm, tsk); task_unlock(tsk); } +EXPORT_SYMBOL_GPL(unuse_mm); -- cgit v1.2.3 From 3a4d5c94e959359ece6d6b55045c3f046677f55c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 14 Jan 2010 06:17:27 +0000 Subject: vhost_net: a kernel-level virtio server What it is: vhost net is a character device that can be used to reduce the number of system calls involved in virtio networking. Existing virtio net code is used in the guest without modification. There's similarity with vringfd, with some differences and reduced scope - uses eventfd for signalling - structures can be moved around in memory at any time (good for migration, bug work-arounds in userspace) - write logging is supported (good for migration) - support memory table and not just an offset (needed for kvm) common virtio related code has been put in a separate file vhost.c and can be made into a separate module if/when more backends appear. I used Rusty's lguest.c as the source for developing this part : this supplied me with witty comments I wouldn't be able to write myself. What it is not: vhost net is not a bus, and not a generic new system call. No assumptions are made on how guest performs hypercalls. Userspace hypervisors are supported as well as kvm. How it works: Basically, we connect virtio frontend (configured by userspace) to a backend. The backend could be a network device, or a tap device. Backend is also configured by userspace, including vlan/mac etc. Status: This works for me, and I haven't see any crashes. Compared to userspace, people reported improved latency (as I save up to 4 system calls per packet), as well as better bandwidth and CPU utilization. Features that I plan to look at in the future: - mergeable buffers - zero copy - scalability tuning: figure out the best threading model to use Note on RCU usage (this is also documented in vhost.h, near private_pointer which is the value protected by this variant of RCU): what is happening is that the rcu_dereference() is being used in a workqueue item. The role of rcu_read_lock() is taken on by the start of execution of the workqueue item, of rcu_read_unlock() by the end of execution of the workqueue item, and of synchronize_rcu() by flush_workqueue()/flush_work(). In the future we might need to apply some gcc attribute or sparse annotation to the function passed to INIT_WORK(). Paul's ack below is for this RCU usage. (Includes fixes by Alan Cox , David L Stevens , Chris Wright ) Acked-by: Rusty Russell Acked-by: Arnd Bergmann Acked-by: "Paul E. McKenney" Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- MAINTAINERS | 9 + arch/ia64/kvm/Kconfig | 1 + arch/powerpc/kvm/Kconfig | 1 + arch/s390/kvm/Kconfig | 1 + arch/x86/kvm/Kconfig | 1 + drivers/Makefile | 1 + drivers/vhost/Kconfig | 11 + drivers/vhost/Makefile | 2 + drivers/vhost/net.c | 661 ++++++++++++++++++++++++++ drivers/vhost/vhost.c | 1098 ++++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 161 +++++++ include/linux/Kbuild | 1 + include/linux/miscdevice.h | 1 + include/linux/vhost.h | 130 ++++++ 14 files changed, 2079 insertions(+) create mode 100644 drivers/vhost/Kconfig create mode 100644 drivers/vhost/Makefile create mode 100644 drivers/vhost/net.c create mode 100644 drivers/vhost/vhost.c create mode 100644 drivers/vhost/vhost.h create mode 100644 include/linux/vhost.h diff --git a/MAINTAINERS b/MAINTAINERS index 745643b8c344..337dffbe9a47 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5803,6 +5803,15 @@ S: Maintained F: Documentation/filesystems/vfat.txt F: fs/fat/ +VIRTIO HOST (VHOST) +M: "Michael S. Tsirkin" +L: kvm@vger.kernel.org +L: virtualization@lists.osdl.org +L: netdev@vger.kernel.org +S: Maintained +F: drivers/vhost/ +F: include/linux/vhost.h + VIA RHINE NETWORK DRIVER M: Roger Luethi S: Maintained diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index ef3e7be29caf..01c75797119c 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -47,6 +47,7 @@ config KVM_INTEL Provides support for KVM on Itanium 2 processors equipped with the VT extensions. +source drivers/vhost/Kconfig source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 07703f72330e..e28841fbfb8d 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -75,6 +75,7 @@ config KVM_E500 If unsure, say N. +source drivers/vhost/Kconfig source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 6ee55ae84ce2..a7251580891c 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -35,6 +35,7 @@ config KVM # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. +source drivers/vhost/Kconfig source drivers/virtio/Kconfig endif # VIRTUALIZATION diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 4cd498332466..3c4d0109ad20 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -65,6 +65,7 @@ config KVM_AMD # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. +source drivers/vhost/Kconfig source drivers/lguest/Kconfig source drivers/virtio/Kconfig diff --git a/drivers/Makefile b/drivers/Makefile index 6ee53c7a57a1..81e36596b1e9 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ obj-$(CONFIG_SSB) += ssb/ +obj-$(CONFIG_VHOST_NET) += vhost/ obj-$(CONFIG_VIRTIO) += virtio/ obj-$(CONFIG_VLYNQ) += vlynq/ obj-$(CONFIG_STAGING) += staging/ diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig new file mode 100644 index 000000000000..9f409f447aea --- /dev/null +++ b/drivers/vhost/Kconfig @@ -0,0 +1,11 @@ +config VHOST_NET + tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)" + depends on NET && EVENTFD && EXPERIMENTAL + ---help--- + This kernel module can be loaded in host kernel to accelerate + guest networking with virtio_net. Not to be confused with virtio_net + module itself which needs to be loaded in guest kernel. + + To compile this driver as a module, choose M here: the module will + be called vhost_net. + diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile new file mode 100644 index 000000000000..72dd02050bb9 --- /dev/null +++ b/drivers/vhost/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_VHOST_NET) += vhost_net.o +vhost_net-y := vhost.o net.o diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c new file mode 100644 index 000000000000..4c8928319e1d --- /dev/null +++ b/drivers/vhost/net.c @@ -0,0 +1,661 @@ +/* Copyright (C) 2009 Red Hat, Inc. + * Author: Michael S. Tsirkin + * + * This work is licensed under the terms of the GNU GPL, version 2. + * + * virtio-net server in host kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "vhost.h" + +/* Max number of bytes transferred before requeueing the job. + * Using this limit prevents one virtqueue from starving others. */ +#define VHOST_NET_WEIGHT 0x80000 + +enum { + VHOST_NET_VQ_RX = 0, + VHOST_NET_VQ_TX = 1, + VHOST_NET_VQ_MAX = 2, +}; + +enum vhost_net_poll_state { + VHOST_NET_POLL_DISABLED = 0, + VHOST_NET_POLL_STARTED = 1, + VHOST_NET_POLL_STOPPED = 2, +}; + +struct vhost_net { + struct vhost_dev dev; + struct vhost_virtqueue vqs[VHOST_NET_VQ_MAX]; + struct vhost_poll poll[VHOST_NET_VQ_MAX]; + /* Tells us whether we are polling a socket for TX. + * We only do this when socket buffer fills up. + * Protected by tx vq lock. */ + enum vhost_net_poll_state tx_poll_state; +}; + +/* Pop first len bytes from iovec. Return number of segments used. */ +static int move_iovec_hdr(struct iovec *from, struct iovec *to, + size_t len, int iov_count) +{ + int seg = 0; + size_t size; + while (len && seg < iov_count) { + size = min(from->iov_len, len); + to->iov_base = from->iov_base; + to->iov_len = size; + from->iov_len -= size; + from->iov_base += size; + len -= size; + ++from; + ++to; + ++seg; + } + return seg; +} + +/* Caller must have TX VQ lock */ +static void tx_poll_stop(struct vhost_net *net) +{ + if (likely(net->tx_poll_state != VHOST_NET_POLL_STARTED)) + return; + vhost_poll_stop(net->poll + VHOST_NET_VQ_TX); + net->tx_poll_state = VHOST_NET_POLL_STOPPED; +} + +/* Caller must have TX VQ lock */ +static void tx_poll_start(struct vhost_net *net, struct socket *sock) +{ + if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED)) + return; + vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file); + net->tx_poll_state = VHOST_NET_POLL_STARTED; +} + +/* Expects to be always run from workqueue - which acts as + * read-size critical section for our kind of RCU. */ +static void handle_tx(struct vhost_net *net) +{ + struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX]; + unsigned head, out, in, s; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_control = NULL, + .msg_controllen = 0, + .msg_iov = vq->iov, + .msg_flags = MSG_DONTWAIT, + }; + size_t len, total_len = 0; + int err, wmem; + size_t hdr_size; + struct socket *sock = rcu_dereference(vq->private_data); + if (!sock) + return; + + wmem = atomic_read(&sock->sk->sk_wmem_alloc); + if (wmem >= sock->sk->sk_sndbuf) + return; + + use_mm(net->dev.mm); + mutex_lock(&vq->mutex); + vhost_disable_notify(vq); + + if (wmem < sock->sk->sk_sndbuf * 2) + tx_poll_stop(net); + hdr_size = vq->hdr_size; + + for (;;) { + head = vhost_get_vq_desc(&net->dev, vq, vq->iov, + ARRAY_SIZE(vq->iov), + &out, &in, + NULL, NULL); + /* Nothing new? Wait for eventfd to tell us they refilled. */ + if (head == vq->num) { + wmem = atomic_read(&sock->sk->sk_wmem_alloc); + if (wmem >= sock->sk->sk_sndbuf * 3 / 4) { + tx_poll_start(net, sock); + set_bit(SOCK_ASYNC_NOSPACE, &sock->flags); + break; + } + if (unlikely(vhost_enable_notify(vq))) { + vhost_disable_notify(vq); + continue; + } + break; + } + if (in) { + vq_err(vq, "Unexpected descriptor format for TX: " + "out %d, int %d\n", out, in); + break; + } + /* Skip header. TODO: support TSO. */ + s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out); + msg.msg_iovlen = out; + len = iov_length(vq->iov, out); + /* Sanity check */ + if (!len) { + vq_err(vq, "Unexpected header len for TX: " + "%zd expected %zd\n", + iov_length(vq->hdr, s), hdr_size); + break; + } + /* TODO: Check specific error and bomb out unless ENOBUFS? */ + err = sock->ops->sendmsg(NULL, sock, &msg, len); + if (unlikely(err < 0)) { + vhost_discard_vq_desc(vq); + tx_poll_start(net, sock); + break; + } + if (err != len) + pr_err("Truncated TX packet: " + " len %d != %zd\n", err, len); + vhost_add_used_and_signal(&net->dev, vq, head, 0); + total_len += len; + if (unlikely(total_len >= VHOST_NET_WEIGHT)) { + vhost_poll_queue(&vq->poll); + break; + } + } + + mutex_unlock(&vq->mutex); + unuse_mm(net->dev.mm); +} + +/* Expects to be always run from workqueue - which acts as + * read-size critical section for our kind of RCU. */ +static void handle_rx(struct vhost_net *net) +{ + struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX]; + unsigned head, out, in, log, s; + struct vhost_log *vq_log; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_control = NULL, /* FIXME: get and handle RX aux data. */ + .msg_controllen = 0, + .msg_iov = vq->iov, + .msg_flags = MSG_DONTWAIT, + }; + + struct virtio_net_hdr hdr = { + .flags = 0, + .gso_type = VIRTIO_NET_HDR_GSO_NONE + }; + + size_t len, total_len = 0; + int err; + size_t hdr_size; + struct socket *sock = rcu_dereference(vq->private_data); + if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue)) + return; + + use_mm(net->dev.mm); + mutex_lock(&vq->mutex); + vhost_disable_notify(vq); + hdr_size = vq->hdr_size; + + vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ? + vq->log : NULL; + + for (;;) { + head = vhost_get_vq_desc(&net->dev, vq, vq->iov, + ARRAY_SIZE(vq->iov), + &out, &in, + vq_log, &log); + /* OK, now we need to know about added descriptors. */ + if (head == vq->num) { + if (unlikely(vhost_enable_notify(vq))) { + /* They have slipped one in as we were + * doing that: check again. */ + vhost_disable_notify(vq); + continue; + } + /* Nothing new? Wait for eventfd to tell us + * they refilled. */ + break; + } + /* We don't need to be notified again. */ + if (out) { + vq_err(vq, "Unexpected descriptor format for RX: " + "out %d, int %d\n", + out, in); + break; + } + /* Skip header. TODO: support TSO/mergeable rx buffers. */ + s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in); + msg.msg_iovlen = in; + len = iov_length(vq->iov, in); + /* Sanity check */ + if (!len) { + vq_err(vq, "Unexpected header len for RX: " + "%zd expected %zd\n", + iov_length(vq->hdr, s), hdr_size); + break; + } + err = sock->ops->recvmsg(NULL, sock, &msg, + len, MSG_DONTWAIT | MSG_TRUNC); + /* TODO: Check specific error and bomb out unless EAGAIN? */ + if (err < 0) { + vhost_discard_vq_desc(vq); + break; + } + /* TODO: Should check and handle checksum. */ + if (err > len) { + pr_err("Discarded truncated rx packet: " + " len %d > %zd\n", err, len); + vhost_discard_vq_desc(vq); + continue; + } + len = err; + err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size); + if (err) { + vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n", + vq->iov->iov_base, err); + break; + } + len += hdr_size; + vhost_add_used_and_signal(&net->dev, vq, head, len); + if (unlikely(vq_log)) + vhost_log_write(vq, vq_log, log, len); + total_len += len; + if (unlikely(total_len >= VHOST_NET_WEIGHT)) { + vhost_poll_queue(&vq->poll); + break; + } + } + + mutex_unlock(&vq->mutex); + unuse_mm(net->dev.mm); +} + +static void handle_tx_kick(struct work_struct *work) +{ + struct vhost_virtqueue *vq; + struct vhost_net *net; + vq = container_of(work, struct vhost_virtqueue, poll.work); + net = container_of(vq->dev, struct vhost_net, dev); + handle_tx(net); +} + +static void handle_rx_kick(struct work_struct *work) +{ + struct vhost_virtqueue *vq; + struct vhost_net *net; + vq = container_of(work, struct vhost_virtqueue, poll.work); + net = container_of(vq->dev, struct vhost_net, dev); + handle_rx(net); +} + +static void handle_tx_net(struct work_struct *work) +{ + struct vhost_net *net; + net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_TX].work); + handle_tx(net); +} + +static void handle_rx_net(struct work_struct *work) +{ + struct vhost_net *net; + net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_RX].work); + handle_rx(net); +} + +static int vhost_net_open(struct inode *inode, struct file *f) +{ + struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL); + int r; + if (!n) + return -ENOMEM; + n->vqs[VHOST_NET_VQ_TX].handle_kick = handle_tx_kick; + n->vqs[VHOST_NET_VQ_RX].handle_kick = handle_rx_kick; + r = vhost_dev_init(&n->dev, n->vqs, VHOST_NET_VQ_MAX); + if (r < 0) { + kfree(n); + return r; + } + + vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT); + vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN); + n->tx_poll_state = VHOST_NET_POLL_DISABLED; + + f->private_data = n; + + return 0; +} + +static void vhost_net_disable_vq(struct vhost_net *n, + struct vhost_virtqueue *vq) +{ + if (!vq->private_data) + return; + if (vq == n->vqs + VHOST_NET_VQ_TX) { + tx_poll_stop(n); + n->tx_poll_state = VHOST_NET_POLL_DISABLED; + } else + vhost_poll_stop(n->poll + VHOST_NET_VQ_RX); +} + +static void vhost_net_enable_vq(struct vhost_net *n, + struct vhost_virtqueue *vq) +{ + struct socket *sock = vq->private_data; + if (!sock) + return; + if (vq == n->vqs + VHOST_NET_VQ_TX) { + n->tx_poll_state = VHOST_NET_POLL_STOPPED; + tx_poll_start(n, sock); + } else + vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file); +} + +static struct socket *vhost_net_stop_vq(struct vhost_net *n, + struct vhost_virtqueue *vq) +{ + struct socket *sock; + + mutex_lock(&vq->mutex); + sock = vq->private_data; + vhost_net_disable_vq(n, vq); + rcu_assign_pointer(vq->private_data, NULL); + mutex_unlock(&vq->mutex); + return sock; +} + +static void vhost_net_stop(struct vhost_net *n, struct socket **tx_sock, + struct socket **rx_sock) +{ + *tx_sock = vhost_net_stop_vq(n, n->vqs + VHOST_NET_VQ_TX); + *rx_sock = vhost_net_stop_vq(n, n->vqs + VHOST_NET_VQ_RX); +} + +static void vhost_net_flush_vq(struct vhost_net *n, int index) +{ + vhost_poll_flush(n->poll + index); + vhost_poll_flush(&n->dev.vqs[index].poll); +} + +static void vhost_net_flush(struct vhost_net *n) +{ + vhost_net_flush_vq(n, VHOST_NET_VQ_TX); + vhost_net_flush_vq(n, VHOST_NET_VQ_RX); +} + +static int vhost_net_release(struct inode *inode, struct file *f) +{ + struct vhost_net *n = f->private_data; + struct socket *tx_sock; + struct socket *rx_sock; + + vhost_net_stop(n, &tx_sock, &rx_sock); + vhost_net_flush(n); + vhost_dev_cleanup(&n->dev); + if (tx_sock) + fput(tx_sock->file); + if (rx_sock) + fput(rx_sock->file); + /* We do an extra flush before freeing memory, + * since jobs can re-queue themselves. */ + vhost_net_flush(n); + kfree(n); + return 0; +} + +static struct socket *get_raw_socket(int fd) +{ + struct { + struct sockaddr_ll sa; + char buf[MAX_ADDR_LEN]; + } uaddr; + int uaddr_len = sizeof uaddr, r; + struct socket *sock = sockfd_lookup(fd, &r); + if (!sock) + return ERR_PTR(-ENOTSOCK); + + /* Parameter checking */ + if (sock->sk->sk_type != SOCK_RAW) { + r = -ESOCKTNOSUPPORT; + goto err; + } + + r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa, + &uaddr_len, 0); + if (r) + goto err; + + if (uaddr.sa.sll_family != AF_PACKET) { + r = -EPFNOSUPPORT; + goto err; + } + return sock; +err: + fput(sock->file); + return ERR_PTR(r); +} + +static struct socket *get_tun_socket(int fd) +{ + struct file *file = fget(fd); + struct socket *sock; + if (!file) + return ERR_PTR(-EBADF); + sock = tun_get_socket(file); + if (IS_ERR(sock)) + fput(file); + return sock; +} + +static struct socket *get_socket(int fd) +{ + struct socket *sock; + /* special case to disable backend */ + if (fd == -1) + return NULL; + sock = get_raw_socket(fd); + if (!IS_ERR(sock)) + return sock; + sock = get_tun_socket(fd); + if (!IS_ERR(sock)) + return sock; + return ERR_PTR(-ENOTSOCK); +} + +static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) +{ + struct socket *sock, *oldsock; + struct vhost_virtqueue *vq; + int r; + + mutex_lock(&n->dev.mutex); + r = vhost_dev_check_owner(&n->dev); + if (r) + goto err; + + if (index >= VHOST_NET_VQ_MAX) { + r = -ENOBUFS; + goto err; + } + vq = n->vqs + index; + mutex_lock(&vq->mutex); + + /* Verify that ring has been setup correctly. */ + if (!vhost_vq_access_ok(vq)) { + r = -EFAULT; + goto err; + } + sock = get_socket(fd); + if (IS_ERR(sock)) { + r = PTR_ERR(sock); + goto err; + } + + /* start polling new socket */ + oldsock = vq->private_data; + if (sock == oldsock) + goto done; + + vhost_net_disable_vq(n, vq); + rcu_assign_pointer(vq->private_data, sock); + vhost_net_enable_vq(n, vq); + mutex_unlock(&vq->mutex); +done: + if (oldsock) { + vhost_net_flush_vq(n, index); + fput(oldsock->file); + } +err: + mutex_unlock(&n->dev.mutex); + return r; +} + +static long vhost_net_reset_owner(struct vhost_net *n) +{ + struct socket *tx_sock = NULL; + struct socket *rx_sock = NULL; + long err; + mutex_lock(&n->dev.mutex); + err = vhost_dev_check_owner(&n->dev); + if (err) + goto done; + vhost_net_stop(n, &tx_sock, &rx_sock); + vhost_net_flush(n); + err = vhost_dev_reset_owner(&n->dev); +done: + mutex_unlock(&n->dev.mutex); + if (tx_sock) + fput(tx_sock->file); + if (rx_sock) + fput(rx_sock->file); + return err; +} + +static int vhost_net_set_features(struct vhost_net *n, u64 features) +{ + size_t hdr_size = features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ? + sizeof(struct virtio_net_hdr) : 0; + int i; + mutex_lock(&n->dev.mutex); + if ((features & (1 << VHOST_F_LOG_ALL)) && + !vhost_log_access_ok(&n->dev)) { + mutex_unlock(&n->dev.mutex); + return -EFAULT; + } + n->dev.acked_features = features; + smp_wmb(); + for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { + mutex_lock(&n->vqs[i].mutex); + n->vqs[i].hdr_size = hdr_size; + mutex_unlock(&n->vqs[i].mutex); + } + vhost_net_flush(n); + mutex_unlock(&n->dev.mutex); + return 0; +} + +static long vhost_net_ioctl(struct file *f, unsigned int ioctl, + unsigned long arg) +{ + struct vhost_net *n = f->private_data; + void __user *argp = (void __user *)arg; + u64 __user *featurep = argp; + struct vhost_vring_file backend; + u64 features; + int r; + switch (ioctl) { + case VHOST_NET_SET_BACKEND: + r = copy_from_user(&backend, argp, sizeof backend); + if (r < 0) + return r; + return vhost_net_set_backend(n, backend.index, backend.fd); + case VHOST_GET_FEATURES: + features = VHOST_FEATURES; + return copy_to_user(featurep, &features, sizeof features); + case VHOST_SET_FEATURES: + r = copy_from_user(&features, featurep, sizeof features); + if (r < 0) + return r; + if (features & ~VHOST_FEATURES) + return -EOPNOTSUPP; + return vhost_net_set_features(n, features); + case VHOST_RESET_OWNER: + return vhost_net_reset_owner(n); + default: + mutex_lock(&n->dev.mutex); + r = vhost_dev_ioctl(&n->dev, ioctl, arg); + vhost_net_flush(n); + mutex_unlock(&n->dev.mutex); + return r; + } +} + +#ifdef CONFIG_COMPAT +static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl, + unsigned long arg) +{ + return vhost_net_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); +} +#endif + +const static struct file_operations vhost_net_fops = { + .owner = THIS_MODULE, + .release = vhost_net_release, + .unlocked_ioctl = vhost_net_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = vhost_net_compat_ioctl, +#endif + .open = vhost_net_open, +}; + +static struct miscdevice vhost_net_misc = { + VHOST_NET_MINOR, + "vhost-net", + &vhost_net_fops, +}; + +int vhost_net_init(void) +{ + int r = vhost_init(); + if (r) + goto err_init; + r = misc_register(&vhost_net_misc); + if (r) + goto err_reg; + return 0; +err_reg: + vhost_cleanup(); +err_init: + return r; + +} +module_init(vhost_net_init); + +void vhost_net_exit(void) +{ + misc_deregister(&vhost_net_misc); + vhost_cleanup(); +} +module_exit(vhost_net_exit); + +MODULE_VERSION("0.0.1"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Michael S. Tsirkin"); +MODULE_DESCRIPTION("Host kernel accelerator for virtio net"); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c new file mode 100644 index 000000000000..c8c25dbc5857 --- /dev/null +++ b/drivers/vhost/vhost.c @@ -0,0 +1,1098 @@ +/* Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2006 Rusty Russell IBM Corporation + * + * Author: Michael S. Tsirkin + * + * Inspiration, some code, and most witty comments come from + * Documentation/lguest/lguest.c, by Rusty Russell + * + * This work is licensed under the terms of the GNU GPL, version 2. + * + * Generic code for virtio server in host kernel. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "vhost.h" + +enum { + VHOST_MEMORY_MAX_NREGIONS = 64, + VHOST_MEMORY_F_LOG = 0x1, +}; + +static struct workqueue_struct *vhost_workqueue; + +static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh, + poll_table *pt) +{ + struct vhost_poll *poll; + poll = container_of(pt, struct vhost_poll, table); + + poll->wqh = wqh; + add_wait_queue(wqh, &poll->wait); +} + +static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync, + void *key) +{ + struct vhost_poll *poll; + poll = container_of(wait, struct vhost_poll, wait); + if (!((unsigned long)key & poll->mask)) + return 0; + + queue_work(vhost_workqueue, &poll->work); + return 0; +} + +/* Init poll structure */ +void vhost_poll_init(struct vhost_poll *poll, work_func_t func, + unsigned long mask) +{ + INIT_WORK(&poll->work, func); + init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); + init_poll_funcptr(&poll->table, vhost_poll_func); + poll->mask = mask; +} + +/* Start polling a file. We add ourselves to file's wait queue. The caller must + * keep a reference to a file until after vhost_poll_stop is called. */ +void vhost_poll_start(struct vhost_poll *poll, struct file *file) +{ + unsigned long mask; + mask = file->f_op->poll(file, &poll->table); + if (mask) + vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); +} + +/* Stop polling a file. After this function returns, it becomes safe to drop the + * file reference. You must also flush afterwards. */ +void vhost_poll_stop(struct vhost_poll *poll) +{ + remove_wait_queue(poll->wqh, &poll->wait); +} + +/* Flush any work that has been scheduled. When calling this, don't hold any + * locks that are also used by the callback. */ +void vhost_poll_flush(struct vhost_poll *poll) +{ + flush_work(&poll->work); +} + +void vhost_poll_queue(struct vhost_poll *poll) +{ + queue_work(vhost_workqueue, &poll->work); +} + +static void vhost_vq_reset(struct vhost_dev *dev, + struct vhost_virtqueue *vq) +{ + vq->num = 1; + vq->desc = NULL; + vq->avail = NULL; + vq->used = NULL; + vq->last_avail_idx = 0; + vq->avail_idx = 0; + vq->last_used_idx = 0; + vq->used_flags = 0; + vq->used_flags = 0; + vq->log_used = false; + vq->log_addr = -1ull; + vq->hdr_size = 0; + vq->private_data = NULL; + vq->log_base = NULL; + vq->error_ctx = NULL; + vq->error = NULL; + vq->kick = NULL; + vq->call_ctx = NULL; + vq->call = NULL; +} + +long vhost_dev_init(struct vhost_dev *dev, + struct vhost_virtqueue *vqs, int nvqs) +{ + int i; + dev->vqs = vqs; + dev->nvqs = nvqs; + mutex_init(&dev->mutex); + dev->log_ctx = NULL; + dev->log_file = NULL; + dev->memory = NULL; + dev->mm = NULL; + + for (i = 0; i < dev->nvqs; ++i) { + dev->vqs[i].dev = dev; + mutex_init(&dev->vqs[i].mutex); + vhost_vq_reset(dev, dev->vqs + i); + if (dev->vqs[i].handle_kick) + vhost_poll_init(&dev->vqs[i].poll, + dev->vqs[i].handle_kick, + POLLIN); + } + return 0; +} + +/* Caller should have device mutex */ +long vhost_dev_check_owner(struct vhost_dev *dev) +{ + /* Are you the owner? If not, I don't think you mean to do that */ + return dev->mm == current->mm ? 0 : -EPERM; +} + +/* Caller should have device mutex */ +static long vhost_dev_set_owner(struct vhost_dev *dev) +{ + /* Is there an owner already? */ + if (dev->mm) + return -EBUSY; + /* No owner, become one */ + dev->mm = get_task_mm(current); + return 0; +} + +/* Caller should have device mutex */ +long vhost_dev_reset_owner(struct vhost_dev *dev) +{ + struct vhost_memory *memory; + + /* Restore memory to default empty mapping. */ + memory = kmalloc(offsetof(struct vhost_memory, regions), GFP_KERNEL); + if (!memory) + return -ENOMEM; + + vhost_dev_cleanup(dev); + + memory->nregions = 0; + dev->memory = memory; + return 0; +} + +/* Caller should have device mutex */ +void vhost_dev_cleanup(struct vhost_dev *dev) +{ + int i; + for (i = 0; i < dev->nvqs; ++i) { + if (dev->vqs[i].kick && dev->vqs[i].handle_kick) { + vhost_poll_stop(&dev->vqs[i].poll); + vhost_poll_flush(&dev->vqs[i].poll); + } + if (dev->vqs[i].error_ctx) + eventfd_ctx_put(dev->vqs[i].error_ctx); + if (dev->vqs[i].error) + fput(dev->vqs[i].error); + if (dev->vqs[i].kick) + fput(dev->vqs[i].kick); + if (dev->vqs[i].call_ctx) + eventfd_ctx_put(dev->vqs[i].call_ctx); + if (dev->vqs[i].call) + fput(dev->vqs[i].call); + vhost_vq_reset(dev, dev->vqs + i); + } + if (dev->log_ctx) + eventfd_ctx_put(dev->log_ctx); + dev->log_ctx = NULL; + if (dev->log_file) + fput(dev->log_file); + dev->log_file = NULL; + /* No one will access memory at this point */ + kfree(dev->memory); + dev->memory = NULL; + if (dev->mm) + mmput(dev->mm); + dev->mm = NULL; +} + +static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) +{ + u64 a = addr / VHOST_PAGE_SIZE / 8; + /* Make sure 64 bit math will not overflow. */ + if (a > ULONG_MAX - (unsigned long)log_base || + a + (unsigned long)log_base > ULONG_MAX) + return -EFAULT; + + return access_ok(VERIFY_WRITE, log_base + a, + (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8); +} + +/* Caller should have vq mutex and device mutex. */ +static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem, + int log_all) +{ + int i; + for (i = 0; i < mem->nregions; ++i) { + struct vhost_memory_region *m = mem->regions + i; + unsigned long a = m->userspace_addr; + if (m->memory_size > ULONG_MAX) + return 0; + else if (!access_ok(VERIFY_WRITE, (void __user *)a, + m->memory_size)) + return 0; + else if (log_all && !log_access_ok(log_base, + m->guest_phys_addr, + m->memory_size)) + return 0; + } + return 1; +} + +/* Can we switch to this memory table? */ +/* Caller should have device mutex but not vq mutex */ +static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem, + int log_all) +{ + int i; + for (i = 0; i < d->nvqs; ++i) { + int ok; + mutex_lock(&d->vqs[i].mutex); + /* If ring is inactive, will check when it's enabled. */ + if (d->vqs[i].private_data) + ok = vq_memory_access_ok(d->vqs[i].log_base, mem, + log_all); + else + ok = 1; + mutex_unlock(&d->vqs[i].mutex); + if (!ok) + return 0; + } + return 1; +} + +static int vq_access_ok(unsigned int num, + struct vring_desc __user *desc, + struct vring_avail __user *avail, + struct vring_used __user *used) +{ + return access_ok(VERIFY_READ, desc, num * sizeof *desc) && + access_ok(VERIFY_READ, avail, + sizeof *avail + num * sizeof *avail->ring) && + access_ok(VERIFY_WRITE, used, + sizeof *used + num * sizeof *used->ring); +} + +/* Can we log writes? */ +/* Caller should have device mutex but not vq mutex */ +int vhost_log_access_ok(struct vhost_dev *dev) +{ + return memory_access_ok(dev, dev->memory, 1); +} + +/* Verify access for write logging. */ +/* Caller should have vq mutex and device mutex */ +static int vq_log_access_ok(struct vhost_virtqueue *vq, void __user *log_base) +{ + return vq_memory_access_ok(log_base, vq->dev->memory, + vhost_has_feature(vq->dev, VHOST_F_LOG_ALL)) && + (!vq->log_used || log_access_ok(log_base, vq->log_addr, + sizeof *vq->used + + vq->num * sizeof *vq->used->ring)); +} + +/* Can we start vq? */ +/* Caller should have vq mutex and device mutex */ +int vhost_vq_access_ok(struct vhost_virtqueue *vq) +{ + return vq_access_ok(vq->num, vq->desc, vq->avail, vq->used) && + vq_log_access_ok(vq, vq->log_base); +} + +static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) +{ + struct vhost_memory mem, *newmem, *oldmem; + unsigned long size = offsetof(struct vhost_memory, regions); + long r; + r = copy_from_user(&mem, m, size); + if (r) + return r; + if (mem.padding) + return -EOPNOTSUPP; + if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) + return -E2BIG; + newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL); + if (!newmem) + return -ENOMEM; + + memcpy(newmem, &mem, size); + r = copy_from_user(newmem->regions, m->regions, + mem.nregions * sizeof *m->regions); + if (r) { + kfree(newmem); + return r; + } + + if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) + return -EFAULT; + oldmem = d->memory; + rcu_assign_pointer(d->memory, newmem); + synchronize_rcu(); + kfree(oldmem); + return 0; +} + +static int init_used(struct vhost_virtqueue *vq, + struct vring_used __user *used) +{ + int r = put_user(vq->used_flags, &used->flags); + if (r) + return r; + return get_user(vq->last_used_idx, &used->idx); +} + +static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) +{ + struct file *eventfp, *filep = NULL, + *pollstart = NULL, *pollstop = NULL; + struct eventfd_ctx *ctx = NULL; + u32 __user *idxp = argp; + struct vhost_virtqueue *vq; + struct vhost_vring_state s; + struct vhost_vring_file f; + struct vhost_vring_addr a; + u32 idx; + long r; + + r = get_user(idx, idxp); + if (r < 0) + return r; + if (idx > d->nvqs) + return -ENOBUFS; + + vq = d->vqs + idx; + + mutex_lock(&vq->mutex); + + switch (ioctl) { + case VHOST_SET_VRING_NUM: + /* Resizing ring with an active backend? + * You don't want to do that. */ + if (vq->private_data) { + r = -EBUSY; + break; + } + r = copy_from_user(&s, argp, sizeof s); + if (r < 0) + break; + if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { + r = -EINVAL; + break; + } + vq->num = s.num; + break; + case VHOST_SET_VRING_BASE: + /* Moving base with an active backend? + * You don't want to do that. */ + if (vq->private_data) { + r = -EBUSY; + break; + } + r = copy_from_user(&s, argp, sizeof s); + if (r < 0) + break; + if (s.num > 0xffff) { + r = -EINVAL; + break; + } + vq->last_avail_idx = s.num; + /* Forget the cached index value. */ + vq->avail_idx = vq->last_avail_idx; + break; + case VHOST_GET_VRING_BASE: + s.index = idx; + s.num = vq->last_avail_idx; + r = copy_to_user(argp, &s, sizeof s); + break; + case VHOST_SET_VRING_ADDR: + r = copy_from_user(&a, argp, sizeof a); + if (r < 0) + break; + if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { + r = -EOPNOTSUPP; + break; + } + /* For 32bit, verify that the top 32bits of the user + data are set to zero. */ + if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr || + (u64)(unsigned long)a.used_user_addr != a.used_user_addr || + (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) { + r = -EFAULT; + break; + } + if ((a.avail_user_addr & (sizeof *vq->avail->ring - 1)) || + (a.used_user_addr & (sizeof *vq->used->ring - 1)) || + (a.log_guest_addr & (sizeof *vq->used->ring - 1))) { + r = -EINVAL; + break; + } + + /* We only verify access here if backend is configured. + * If it is not, we don't as size might not have been setup. + * We will verify when backend is configured. */ + if (vq->private_data) { + if (!vq_access_ok(vq->num, + (void __user *)(unsigned long)a.desc_user_addr, + (void __user *)(unsigned long)a.avail_user_addr, + (void __user *)(unsigned long)a.used_user_addr)) { + r = -EINVAL; + break; + } + + /* Also validate log access for used ring if enabled. */ + if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) && + !log_access_ok(vq->log_base, a.log_guest_addr, + sizeof *vq->used + + vq->num * sizeof *vq->used->ring)) { + r = -EINVAL; + break; + } + } + + r = init_used(vq, (struct vring_used __user *)(unsigned long) + a.used_user_addr); + if (r) + break; + vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); + vq->desc = (void __user *)(unsigned long)a.desc_user_addr; + vq->avail = (void __user *)(unsigned long)a.avail_user_addr; + vq->log_addr = a.log_guest_addr; + vq->used = (void __user *)(unsigned long)a.used_user_addr; + break; + case VHOST_SET_VRING_KICK: + r = copy_from_user(&f, argp, sizeof f); + if (r < 0) + break; + eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); + if (IS_ERR(eventfp)) + return PTR_ERR(eventfp); + if (eventfp != vq->kick) { + pollstop = filep = vq->kick; + pollstart = vq->kick = eventfp; + } else + filep = eventfp; + break; + case VHOST_SET_VRING_CALL: + r = copy_from_user(&f, argp, sizeof f); + if (r < 0) + break; + eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); + if (IS_ERR(eventfp)) + return PTR_ERR(eventfp); + if (eventfp != vq->call) { + filep = vq->call; + ctx = vq->call_ctx; + vq->call = eventfp; + vq->call_ctx = eventfp ? + eventfd_ctx_fileget(eventfp) : NULL; + } else + filep = eventfp; + break; + case VHOST_SET_VRING_ERR: + r = copy_from_user(&f, argp, sizeof f); + if (r < 0) + break; + eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); + if (IS_ERR(eventfp)) + return PTR_ERR(eventfp); + if (eventfp != vq->error) { + filep = vq->error; + vq->error = eventfp; + ctx = vq->error_ctx; + vq->error_ctx = eventfp ? + eventfd_ctx_fileget(eventfp) : NULL; + } else + filep = eventfp; + break; + default: + r = -ENOIOCTLCMD; + } + + if (pollstop && vq->handle_kick) + vhost_poll_stop(&vq->poll); + + if (ctx) + eventfd_ctx_put(ctx); + if (filep) + fput(filep); + + if (pollstart && vq->handle_kick) + vhost_poll_start(&vq->poll, vq->kick); + + mutex_unlock(&vq->mutex); + + if (pollstop && vq->handle_kick) + vhost_poll_flush(&vq->poll); + return r; +} + +/* Caller must have device mutex */ +long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + struct file *eventfp, *filep = NULL; + struct eventfd_ctx *ctx = NULL; + u64 p; + long r; + int i, fd; + + /* If you are not the owner, you can become one */ + if (ioctl == VHOST_SET_OWNER) { + r = vhost_dev_set_owner(d); + goto done; + } + + /* You must be the owner to do anything else */ + r = vhost_dev_check_owner(d); + if (r) + goto done; + + switch (ioctl) { + case VHOST_SET_MEM_TABLE: + r = vhost_set_memory(d, argp); + break; + case VHOST_SET_LOG_BASE: + r = copy_from_user(&p, argp, sizeof p); + if (r < 0) + break; + if ((u64)(unsigned long)p != p) { + r = -EFAULT; + break; + } + for (i = 0; i < d->nvqs; ++i) { + struct vhost_virtqueue *vq; + void __user *base = (void __user *)(unsigned long)p; + vq = d->vqs + i; + mutex_lock(&vq->mutex); + /* If ring is inactive, will check when it's enabled. */ + if (vq->private_data && !vq_log_access_ok(vq, base)) + r = -EFAULT; + else + vq->log_base = base; + mutex_unlock(&vq->mutex); + } + break; + case VHOST_SET_LOG_FD: + r = get_user(fd, (int __user *)argp); + if (r < 0) + break; + eventfp = fd == -1 ? NULL : eventfd_fget(fd); + if (IS_ERR(eventfp)) { + r = PTR_ERR(eventfp); + break; + } + if (eventfp != d->log_file) { + filep = d->log_file; + ctx = d->log_ctx; + d->log_ctx = eventfp ? + eventfd_ctx_fileget(eventfp) : NULL; + } else + filep = eventfp; + for (i = 0; i < d->nvqs; ++i) { + mutex_lock(&d->vqs[i].mutex); + d->vqs[i].log_ctx = d->log_ctx; + mutex_unlock(&d->vqs[i].mutex); + } + if (ctx) + eventfd_ctx_put(ctx); + if (filep) + fput(filep); + break; + default: + r = vhost_set_vring(d, ioctl, argp); + break; + } +done: + return r; +} + +static const struct vhost_memory_region *find_region(struct vhost_memory *mem, + __u64 addr, __u32 len) +{ + struct vhost_memory_region *reg; + int i; + /* linear search is not brilliant, but we really have on the order of 6 + * regions in practice */ + for (i = 0; i < mem->nregions; ++i) { + reg = mem->regions + i; + if (reg->guest_phys_addr <= addr && + reg->guest_phys_addr + reg->memory_size - 1 >= addr) + return reg; + } + return NULL; +} + +/* TODO: This is really inefficient. We need something like get_user() + * (instruction directly accesses the data, with an exception table entry + * returning -EFAULT). See Documentation/x86/exception-tables.txt. + */ +static int set_bit_to_user(int nr, void __user *addr) +{ + unsigned long log = (unsigned long)addr; + struct page *page; + void *base; + int bit = nr + (log % PAGE_SIZE) * 8; + int r; + r = get_user_pages_fast(log, 1, 1, &page); + if (r) + return r; + base = kmap_atomic(page, KM_USER0); + set_bit(bit, base); + kunmap_atomic(base, KM_USER0); + set_page_dirty_lock(page); + put_page(page); + return 0; +} + +static int log_write(void __user *log_base, + u64 write_address, u64 write_length) +{ + int r; + if (!write_length) + return 0; + write_address /= VHOST_PAGE_SIZE; + for (;;) { + u64 base = (u64)(unsigned long)log_base; + u64 log = base + write_address / 8; + int bit = write_address % 8; + if ((u64)(unsigned long)log != log) + return -EFAULT; + r = set_bit_to_user(bit, (void __user *)(unsigned long)log); + if (r < 0) + return r; + if (write_length <= VHOST_PAGE_SIZE) + break; + write_length -= VHOST_PAGE_SIZE; + write_address += VHOST_PAGE_SIZE; + } + return r; +} + +int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, + unsigned int log_num, u64 len) +{ + int i, r; + + /* Make sure data written is seen before log. */ + wmb(); + for (i = 0; i < log_num; ++i) { + u64 l = min(log[i].len, len); + r = log_write(vq->log_base, log[i].addr, l); + if (r < 0) + return r; + len -= l; + if (!len) + return 0; + } + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + /* Length written exceeds what we have stored. This is a bug. */ + BUG(); + return 0; +} + +int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, + struct iovec iov[], int iov_size) +{ + const struct vhost_memory_region *reg; + struct vhost_memory *mem; + struct iovec *_iov; + u64 s = 0; + int ret = 0; + + rcu_read_lock(); + + mem = rcu_dereference(dev->memory); + while ((u64)len > s) { + u64 size; + if (ret >= iov_size) { + ret = -ENOBUFS; + break; + } + reg = find_region(mem, addr, len); + if (!reg) { + ret = -EFAULT; + break; + } + _iov = iov + ret; + size = reg->memory_size - addr + reg->guest_phys_addr; + _iov->iov_len = min((u64)len, size); + _iov->iov_base = (void *)(unsigned long) + (reg->userspace_addr + addr - reg->guest_phys_addr); + s += size; + addr += size; + ++ret; + } + + rcu_read_unlock(); + return ret; +} + +/* Each buffer in the virtqueues is actually a chain of descriptors. This + * function returns the next descriptor in the chain, + * or -1U if we're at the end. */ +static unsigned next_desc(struct vring_desc *desc) +{ + unsigned int next; + + /* If this descriptor says it doesn't chain, we're done. */ + if (!(desc->flags & VRING_DESC_F_NEXT)) + return -1U; + + /* Check they're not leading us off end of descriptors. */ + next = desc->next; + /* Make sure compiler knows to grab that: we don't want it changing! */ + /* We will use the result as an index in an array, so most + * architectures only need a compiler barrier here. */ + read_barrier_depends(); + + return next; +} + +static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num, + struct vring_desc *indirect) +{ + struct vring_desc desc; + unsigned int i = 0, count, found = 0; + int ret; + + /* Sanity check */ + if (indirect->len % sizeof desc) { + vq_err(vq, "Invalid length in indirect descriptor: " + "len 0x%llx not multiple of 0x%zx\n", + (unsigned long long)indirect->len, + sizeof desc); + return -EINVAL; + } + + ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect, + ARRAY_SIZE(vq->indirect)); + if (ret < 0) { + vq_err(vq, "Translation failure %d in indirect.\n", ret); + return ret; + } + + /* We will use the result as an address to read from, so most + * architectures only need a compiler barrier here. */ + read_barrier_depends(); + + count = indirect->len / sizeof desc; + /* Buffers are chained via a 16 bit next field, so + * we can have at most 2^16 of these. */ + if (count > USHORT_MAX + 1) { + vq_err(vq, "Indirect buffer length too big: %d\n", + indirect->len); + return -E2BIG; + } + + do { + unsigned iov_count = *in_num + *out_num; + if (++found > count) { + vq_err(vq, "Loop detected: last one at %u " + "indirect size %u\n", + i, count); + return -EINVAL; + } + if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect, + sizeof desc)) { + vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", + i, (size_t)indirect->addr + i * sizeof desc); + return -EINVAL; + } + if (desc.flags & VRING_DESC_F_INDIRECT) { + vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n", + i, (size_t)indirect->addr + i * sizeof desc); + return -EINVAL; + } + + ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count, + iov_size - iov_count); + if (ret < 0) { + vq_err(vq, "Translation failure %d indirect idx %d\n", + ret, i); + return ret; + } + /* If this is an input descriptor, increment that count. */ + if (desc.flags & VRING_DESC_F_WRITE) { + *in_num += ret; + if (unlikely(log)) { + log[*log_num].addr = desc.addr; + log[*log_num].len = desc.len; + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (*in_num) { + vq_err(vq, "Indirect descriptor " + "has out after in: idx %d\n", i); + return -EINVAL; + } + *out_num += ret; + } + } while ((i = next_desc(&desc)) != -1); + return 0; +} + +/* This looks in the virtqueue and for the first available buffer, and converts + * it to an iovec for convenient access. Since descriptors consist of some + * number of output then some number of input descriptors, it's actually two + * iovecs, but we pack them into one and note how many of each there were. + * + * This function returns the descriptor number found, or vq->num (which + * is never a valid descriptor number) if none was found. */ +unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num) +{ + struct vring_desc desc; + unsigned int i, head, found = 0; + u16 last_avail_idx; + int ret; + + /* Check it isn't doing very strange things with descriptor numbers. */ + last_avail_idx = vq->last_avail_idx; + if (get_user(vq->avail_idx, &vq->avail->idx)) { + vq_err(vq, "Failed to access avail idx at %p\n", + &vq->avail->idx); + return vq->num; + } + + if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) { + vq_err(vq, "Guest moved used index from %u to %u", + last_avail_idx, vq->avail_idx); + return vq->num; + } + + /* If there's nothing new since last we looked, return invalid. */ + if (vq->avail_idx == last_avail_idx) + return vq->num; + + /* Only get avail ring entries after they have been exposed by guest. */ + rmb(); + + /* Grab the next descriptor number they're advertising, and increment + * the index we've seen. */ + if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) { + vq_err(vq, "Failed to read head: idx %d address %p\n", + last_avail_idx, + &vq->avail->ring[last_avail_idx % vq->num]); + return vq->num; + } + + /* If their number is silly, that's an error. */ + if (head >= vq->num) { + vq_err(vq, "Guest says index %u > %u is available", + head, vq->num); + return vq->num; + } + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + if (unlikely(log)) + *log_num = 0; + + i = head; + do { + unsigned iov_count = *in_num + *out_num; + if (i >= vq->num) { + vq_err(vq, "Desc index is %u > %u, head = %u", + i, vq->num, head); + return vq->num; + } + if (++found > vq->num) { + vq_err(vq, "Loop detected: last one at %u " + "vq size %u head %u\n", + i, vq->num, head); + return vq->num; + } + ret = copy_from_user(&desc, vq->desc + i, sizeof desc); + if (ret) { + vq_err(vq, "Failed to get descriptor: idx %d addr %p\n", + i, vq->desc + i); + return vq->num; + } + if (desc.flags & VRING_DESC_F_INDIRECT) { + ret = get_indirect(dev, vq, iov, iov_size, + out_num, in_num, + log, log_num, &desc); + if (ret < 0) { + vq_err(vq, "Failure detected " + "in indirect descriptor at idx %d\n", i); + return vq->num; + } + continue; + } + + ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count, + iov_size - iov_count); + if (ret < 0) { + vq_err(vq, "Translation failure %d descriptor idx %d\n", + ret, i); + return vq->num; + } + if (desc.flags & VRING_DESC_F_WRITE) { + /* If this is an input descriptor, + * increment that count. */ + *in_num += ret; + if (unlikely(log)) { + log[*log_num].addr = desc.addr; + log[*log_num].len = desc.len; + ++*log_num; + } + } else { + /* If it's an output descriptor, they're all supposed + * to come before any input descriptors. */ + if (*in_num) { + vq_err(vq, "Descriptor has out after in: " + "idx %d\n", i); + return vq->num; + } + *out_num += ret; + } + } while ((i = next_desc(&desc)) != -1); + + /* On success, increment avail index. */ + vq->last_avail_idx++; + return head; +} + +/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */ +void vhost_discard_vq_desc(struct vhost_virtqueue *vq) +{ + vq->last_avail_idx--; +} + +/* After we've used one of their buffers, we tell them about it. We'll then + * want to notify the guest, using eventfd. */ +int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) +{ + struct vring_used_elem *used; + + /* The virtqueue contains a ring of used buffers. Get a pointer to the + * next entry in that used ring. */ + used = &vq->used->ring[vq->last_used_idx % vq->num]; + if (put_user(head, &used->id)) { + vq_err(vq, "Failed to write used id"); + return -EFAULT; + } + if (put_user(len, &used->len)) { + vq_err(vq, "Failed to write used len"); + return -EFAULT; + } + /* Make sure buffer is written before we update index. */ + wmb(); + if (put_user(vq->last_used_idx + 1, &vq->used->idx)) { + vq_err(vq, "Failed to increment used idx"); + return -EFAULT; + } + if (unlikely(vq->log_used)) { + /* Make sure data is seen before log. */ + wmb(); + log_write(vq->log_base, vq->log_addr + sizeof *vq->used->ring * + (vq->last_used_idx % vq->num), + sizeof *vq->used->ring); + log_write(vq->log_base, vq->log_addr, sizeof *vq->used->ring); + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); + } + vq->last_used_idx++; + return 0; +} + +/* This actually signals the guest, using eventfd. */ +void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) +{ + __u16 flags = 0; + if (get_user(flags, &vq->avail->flags)) { + vq_err(vq, "Failed to get flags"); + return; + } + + /* If they don't want an interrupt, don't signal, unless empty. */ + if ((flags & VRING_AVAIL_F_NO_INTERRUPT) && + (vq->avail_idx != vq->last_avail_idx || + !vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY))) + return; + + /* Signal the Guest tell them we used something up. */ + if (vq->call_ctx) + eventfd_signal(vq->call_ctx, 1); +} + +/* And here's the combo meal deal. Supersize me! */ +void vhost_add_used_and_signal(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + unsigned int head, int len) +{ + vhost_add_used(vq, head, len); + vhost_signal(dev, vq); +} + +/* OK, now we need to know about added descriptors. */ +bool vhost_enable_notify(struct vhost_virtqueue *vq) +{ + u16 avail_idx; + int r; + if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY)) + return false; + vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; + r = put_user(vq->used_flags, &vq->used->flags); + if (r) { + vq_err(vq, "Failed to enable notification at %p: %d\n", + &vq->used->flags, r); + return false; + } + /* They could have slipped one in as we were doing that: make + * sure it's written, then check again. */ + mb(); + r = get_user(avail_idx, &vq->avail->idx); + if (r) { + vq_err(vq, "Failed to check avail idx at %p: %d\n", + &vq->avail->idx, r); + return false; + } + + return avail_idx != vq->last_avail_idx; +} + +/* We don't need to be notified again. */ +void vhost_disable_notify(struct vhost_virtqueue *vq) +{ + int r; + if (vq->used_flags & VRING_USED_F_NO_NOTIFY) + return; + vq->used_flags |= VRING_USED_F_NO_NOTIFY; + r = put_user(vq->used_flags, &vq->used->flags); + if (r) + vq_err(vq, "Failed to enable notification at %p: %d\n", + &vq->used->flags, r); +} + +int vhost_init(void) +{ + vhost_workqueue = create_singlethread_workqueue("vhost"); + if (!vhost_workqueue) + return -ENOMEM; + return 0; +} + +void vhost_cleanup(void) +{ + destroy_workqueue(vhost_workqueue); +} diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h new file mode 100644 index 000000000000..44591ba9b07a --- /dev/null +++ b/drivers/vhost/vhost.h @@ -0,0 +1,161 @@ +#ifndef _VHOST_H +#define _VHOST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct vhost_device; + +enum { + /* Enough place for all fragments, head, and virtio net header. */ + VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2, +}; + +/* Poll a file (eventfd or socket) */ +/* Note: there's nothing vhost specific about this structure. */ +struct vhost_poll { + poll_table table; + wait_queue_head_t *wqh; + wait_queue_t wait; + /* struct which will handle all actual work. */ + struct work_struct work; + unsigned long mask; +}; + +void vhost_poll_init(struct vhost_poll *poll, work_func_t func, + unsigned long mask); +void vhost_poll_start(struct vhost_poll *poll, struct file *file); +void vhost_poll_stop(struct vhost_poll *poll); +void vhost_poll_flush(struct vhost_poll *poll); +void vhost_poll_queue(struct vhost_poll *poll); + +struct vhost_log { + u64 addr; + u64 len; +}; + +/* The virtqueue structure describes a queue attached to a device. */ +struct vhost_virtqueue { + struct vhost_dev *dev; + + /* The actual ring of buffers. */ + struct mutex mutex; + unsigned int num; + struct vring_desc __user *desc; + struct vring_avail __user *avail; + struct vring_used __user *used; + struct file *kick; + struct file *call; + struct file *error; + struct eventfd_ctx *call_ctx; + struct eventfd_ctx *error_ctx; + struct eventfd_ctx *log_ctx; + + struct vhost_poll poll; + + /* The routine to call when the Guest pings us, or timeout. */ + work_func_t handle_kick; + + /* Last available index we saw. */ + u16 last_avail_idx; + + /* Caches available index value from user. */ + u16 avail_idx; + + /* Last index we used. */ + u16 last_used_idx; + + /* Used flags */ + u16 used_flags; + + /* Log writes to used structure. */ + bool log_used; + u64 log_addr; + + struct iovec indirect[VHOST_NET_MAX_SG]; + struct iovec iov[VHOST_NET_MAX_SG]; + struct iovec hdr[VHOST_NET_MAX_SG]; + size_t hdr_size; + /* We use a kind of RCU to access private pointer. + * All readers access it from workqueue, which makes it possible to + * flush the workqueue instead of synchronize_rcu. Therefore readers do + * not need to call rcu_read_lock/rcu_read_unlock: the beginning of + * work item execution acts instead of rcu_read_lock() and the end of + * work item execution acts instead of rcu_read_lock(). + * Writers use virtqueue mutex. */ + void *private_data; + /* Log write descriptors */ + void __user *log_base; + struct vhost_log log[VHOST_NET_MAX_SG]; +}; + +struct vhost_dev { + /* Readers use RCU to access memory table pointer + * log base pointer and features. + * Writers use mutex below.*/ + struct vhost_memory *memory; + struct mm_struct *mm; + struct mutex mutex; + unsigned acked_features; + struct vhost_virtqueue *vqs; + int nvqs; + struct file *log_file; + struct eventfd_ctx *log_ctx; +}; + +long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs); +long vhost_dev_check_owner(struct vhost_dev *); +long vhost_dev_reset_owner(struct vhost_dev *); +void vhost_dev_cleanup(struct vhost_dev *); +long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg); +int vhost_vq_access_ok(struct vhost_virtqueue *vq); +int vhost_log_access_ok(struct vhost_dev *); + +unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, + struct iovec iov[], unsigned int iov_count, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, unsigned int *log_num); +void vhost_discard_vq_desc(struct vhost_virtqueue *); + +int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); +void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *); +void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *, + unsigned int head, int len); +void vhost_disable_notify(struct vhost_virtqueue *); +bool vhost_enable_notify(struct vhost_virtqueue *); + +int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, + unsigned int log_num, u64 len); + +int vhost_init(void); +void vhost_cleanup(void); + +#define vq_err(vq, fmt, ...) do { \ + pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \ + if ((vq)->error_ctx) \ + eventfd_signal((vq)->error_ctx, 1);\ + } while (0) + +enum { + VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) | + (1 << VIRTIO_RING_F_INDIRECT_DESC) | + (1 << VHOST_F_LOG_ALL) | + (1 << VHOST_NET_F_VIRTIO_NET_HDR), +}; + +static inline int vhost_has_feature(struct vhost_dev *dev, int bit) +{ + unsigned acked_features = rcu_dereference(dev->acked_features); + return acked_features & (1 << bit); +} + +#endif diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 756f831cbdd5..d93080748a91 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -362,6 +362,7 @@ unifdef-y += uio.h unifdef-y += unistd.h unifdef-y += usbdevice_fs.h unifdef-y += utsname.h +unifdef-y += vhost.h unifdef-y += videodev2.h unifdef-y += videodev.h unifdef-y += virtio_config.h diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index adaf3c15e449..8b5f7cc0fba6 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -30,6 +30,7 @@ #define HPET_MINOR 228 #define FUSE_MINOR 229 #define KVM_MINOR 232 +#define VHOST_NET_MINOR 233 #define MISC_DYNAMIC_MINOR 255 struct device; diff --git a/include/linux/vhost.h b/include/linux/vhost.h new file mode 100644 index 000000000000..e847f1e30756 --- /dev/null +++ b/include/linux/vhost.h @@ -0,0 +1,130 @@ +#ifndef _LINUX_VHOST_H +#define _LINUX_VHOST_H +/* Userspace interface for in-kernel virtio accelerators. */ + +/* vhost is used to reduce the number of system calls involved in virtio. + * + * Existing virtio net code is used in the guest without modification. + * + * This header includes interface used by userspace hypervisor for + * device configuration. + */ + +#include +#include +#include +#include +#include + +struct vhost_vring_state { + unsigned int index; + unsigned int num; +}; + +struct vhost_vring_file { + unsigned int index; + int fd; /* Pass -1 to unbind from file. */ + +}; + +struct vhost_vring_addr { + unsigned int index; + /* Option flags. */ + unsigned int flags; + /* Flag values: */ + /* Whether log address is valid. If set enables logging. */ +#define VHOST_VRING_F_LOG 0 + + /* Start of array of descriptors (virtually contiguous) */ + __u64 desc_user_addr; + /* Used structure address. Must be 32 bit aligned */ + __u64 used_user_addr; + /* Available structure address. Must be 16 bit aligned */ + __u64 avail_user_addr; + /* Logging support. */ + /* Log writes to used structure, at offset calculated from specified + * address. Address must be 32 bit aligned. */ + __u64 log_guest_addr; +}; + +struct vhost_memory_region { + __u64 guest_phys_addr; + __u64 memory_size; /* bytes */ + __u64 userspace_addr; + __u64 flags_padding; /* No flags are currently specified. */ +}; + +/* All region addresses and sizes must be 4K aligned. */ +#define VHOST_PAGE_SIZE 0x1000 + +struct vhost_memory { + __u32 nregions; + __u32 padding; + struct vhost_memory_region regions[0]; +}; + +/* ioctls */ + +#define VHOST_VIRTIO 0xAF + +/* Features bitmask for forward compatibility. Transport bits are used for + * vhost specific features. */ +#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64) +#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64) + +/* Set current process as the (exclusive) owner of this file descriptor. This + * must be called before any other vhost command. Further calls to + * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */ +#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01) +/* Give up ownership, and reset the device to default values. + * Allows subsequent call to VHOST_OWNER_SET to succeed. */ +#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02) + +/* Set up/modify memory layout */ +#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory) + +/* Write logging setup. */ +/* Memory writes can optionally be logged by setting bit at an offset + * (calculated from the physical address) from specified log base. + * The bit is set using an atomic 32 bit operation. */ +/* Set base address for logging. */ +#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64) +/* Specify an eventfd file descriptor to signal on log write. */ +#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int) + +/* Ring setup. */ +/* Set number of descriptors in ring. This parameter can not + * be modified while ring is running (bound to a device). */ +#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state) +/* Set addresses for the ring. */ +#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr) +/* Base value where queue looks for available descriptors */ +#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state) +/* Get accessor: reads index, writes value in num */ +#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state) + +/* The following ioctls use eventfd file descriptors to signal and poll + * for events. */ + +/* Set eventfd to poll for added buffers */ +#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file) +/* Set eventfd to signal when buffers have beed used */ +#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file) +/* Set eventfd to signal an error */ +#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file) + +/* VHOST_NET specific defines */ + +/* Attach virtio net ring to a raw socket, or tap device. + * The socket must be already bound to an ethernet device, this device will be + * used for transmit. Pass fd -1 to unbind from the socket and the transmit + * device. This can be used to stop the ring (e.g. for migration). */ +#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file) + +/* Feature bits */ +/* Log all write descriptors. Can be changed while device is active. */ +#define VHOST_F_LOG_ALL 26 +/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ +#define VHOST_NET_F_VIRTIO_NET_HDR 27 + +#endif -- cgit v1.2.3 From c5bab5e94d148aee2c852450374143c89aa56511 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 14 Jan 2010 01:05:48 +0000 Subject: can: mscan-mpc5xxx: fix broken support for the MPC5200 Due to an invalid "#ifdef CONFIG_PPC_MPC5200", the real clock setup function was not called for the MPC5200. Signed-off-by: Wolfgang Grandegger Acked-by: Wolfram Sang Signed-off-by: David S. Miller --- drivers/net/can/mscan/mpc5xxx_can.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index f73487f723b8..03e7c48465a2 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -43,7 +43,7 @@ struct mpc5xxx_can_data { int *mscan_clksrc); }; -#ifdef CONFIG_PPC_MPC5200 +#ifdef CONFIG_PPC_MPC52xx static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = { { .compatible = "fsl,mpc5200-cdm", }, {} @@ -84,7 +84,7 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, /* Determine SYS_XTAL_IN frequency from the clock domain settings */ np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids); if (!np_cdm) { - dev_err(&of->dev, "can't get clock node!\n"); + dev_err(&ofdev->dev, "can't get clock node!\n"); return 0; } cdm = of_iomap(np_cdm, 0); @@ -101,14 +101,14 @@ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, return freq; } -#else /* !CONFIG_PPC_MPC5200 */ +#else /* !CONFIG_PPC_MPC52xx */ static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev, const char *clock_name, int *mscan_clksrc) { return 0; } -#endif /* CONFIG_PPC_MPC5200 */ +#endif /* CONFIG_PPC_MPC52xx */ #ifdef CONFIG_PPC_MPC512x struct mpc512x_clockctl { -- cgit v1.2.3 From d86458471aadffe93b741024b5a879ea5dc8df35 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 15 Jan 2010 01:48:22 -0800 Subject: ethoc: Use resource_size Use the resource_size function instead of manually calculating the resource size. Signed-off-by: Tobias Klauser Signed-off-by: David S. Miller --- drivers/net/ethoc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index bd1db92aec1b..f9d5ca078743 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -904,7 +904,7 @@ static int ethoc_probe(struct platform_device *pdev) } mmio = devm_request_mem_region(&pdev->dev, res->start, - res->end - res->start + 1, res->name); + resource_size(res), res->name); if (!mmio) { dev_err(&pdev->dev, "cannot request I/O memory space\n"); ret = -ENXIO; @@ -917,7 +917,7 @@ static int ethoc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (res) { mem = devm_request_mem_region(&pdev->dev, res->start, - res->end - res->start + 1, res->name); + resource_size(res), res->name); if (!mem) { dev_err(&pdev->dev, "cannot request memory space\n"); ret = -ENXIO; @@ -945,7 +945,7 @@ static int ethoc_probe(struct platform_device *pdev) priv->dma_alloc = 0; priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, - mmio->end - mmio->start + 1); + resource_size(mmio)); if (!priv->iobase) { dev_err(&pdev->dev, "cannot remap I/O memory space\n"); ret = -ENXIO; @@ -954,7 +954,7 @@ static int ethoc_probe(struct platform_device *pdev) if (netdev->mem_end) { priv->membase = devm_ioremap_nocache(&pdev->dev, - netdev->mem_start, mem->end - mem->start + 1); + netdev->mem_start, resource_size(mem)); if (!priv->membase) { dev_err(&pdev->dev, "cannot remap memory space\n"); ret = -ENXIO; -- cgit v1.2.3 From 93895757df4ebe22c98b9128b98ebf8cec972c60 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Thu, 14 Jan 2010 23:20:31 +0100 Subject: mac80211: Fixed netif_tx_wake_all_queues in IBSS mode When ieee80211_offchannel_return is called, it needs to re-enabled TX queues that have been stopped in ieee80211_offchannel_stop_beaconing or ieee80211_offchannel_stop_station. It happens if we are doing a scan with an IBSS interface. In this case, the interface stopped transmitting. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/offchannel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 1facfeb1f79b..c36b1911987a 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -153,9 +153,11 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.associated) ieee80211_offchannel_ps_disable(sdata); - netif_tx_wake_all_queues(sdata->dev); } + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) + netif_tx_wake_all_queues(sdata->dev); + /* re-enable beaconing */ if (enable_beaconing && (sdata->vif.type == NL80211_IFTYPE_AP || -- cgit v1.2.3 From 84920e3e47f654a22b540606fb8c1ab90b870942 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 14 Jan 2010 20:08:20 -0500 Subject: cfg80211: make regulatory_hint_11d() band specific In practice APs do not send country IE channel triplets for channels the AP is not operating on and if they were to do so they would have to use the regulatory extension which we currently do not process. No AP has been seen in practice that does this though so just drop those country IEs. Additionally it has been noted the first series of country IE channels triplets are specific to the band the AP sends. Propagate the band on which the country IE was found on reject the country IE then if the triplets are ever oustide of the band. Although we now won't process country IE information with multiple band information we leave the intersection work as is as it is technically possible for someone to want to eventually process these type of country IEs with regulatory extensions. Cc: Jouni Malinen Cc: Johannes Berg Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 74 +++++++++++++++++++++++++++++++++++++++--------------- net/wireless/reg.h | 11 ++++++++ net/wireless/sme.c | 1 + 3 files changed, 66 insertions(+), 20 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f3b77f7b8e3d..5f8071de7950 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -484,6 +484,34 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, #undef ONE_GHZ_IN_KHZ } +/* + * This is a work around for sanity checking ieee80211_channel_to_frequency()'s + * work. ieee80211_channel_to_frequency() can for example currently provide a + * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be + * an AP providing channel 8 on a country IE triplet when it sent this on the + * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz + * channel. + * + * This can be removed once ieee80211_channel_to_frequency() takes in a band. + */ +static bool chan_in_band(int chan, enum ieee80211_band band) +{ + int center_freq = ieee80211_channel_to_frequency(chan); + + switch (band) { + case IEEE80211_BAND_2GHZ: + if (center_freq <= 2484) + return true; + return false; + case IEEE80211_BAND_5GHZ: + if (center_freq >= 5005) + return true; + return false; + default: + return false; + } +} + /* * Some APs may send a country IE triplet for each channel they * support and while this is completely overkill and silly we still @@ -532,7 +560,8 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range, * Returns 0 if the IE has been found to be invalid in the middle * somewhere. */ -static int max_subband_chan(int orig_cur_chan, +static int max_subband_chan(enum ieee80211_band band, + int orig_cur_chan, int orig_end_channel, s8 orig_max_power, u8 **country_ie, @@ -541,7 +570,6 @@ static int max_subband_chan(int orig_cur_chan, u8 *triplets_start = *country_ie; u8 len_at_triplet = *country_ie_len; int end_subband_chan = orig_end_channel; - enum ieee80211_band band; /* * We'll deal with padding for the caller unless @@ -557,17 +585,14 @@ static int max_subband_chan(int orig_cur_chan, *country_ie += 3; *country_ie_len -= 3; - if (orig_cur_chan <= 14) - band = IEEE80211_BAND_2GHZ; - else - band = IEEE80211_BAND_5GHZ; + if (!chan_in_band(orig_cur_chan, band)) + return 0; while (*country_ie_len >= 3) { int end_channel = 0; struct ieee80211_country_ie_triplet *triplet = (struct ieee80211_country_ie_triplet *) *country_ie; int cur_channel = 0, next_expected_chan; - enum ieee80211_band next_band = IEEE80211_BAND_2GHZ; /* means last triplet is completely unrelated to this one */ if (triplet->ext.reg_extension_id >= @@ -592,6 +617,9 @@ static int max_subband_chan(int orig_cur_chan, if (triplet->chans.first_channel <= end_subband_chan) return 0; + if (!chan_in_band(triplet->chans.first_channel, band)) + return 0; + /* 2 GHz */ if (triplet->chans.first_channel <= 14) { end_channel = triplet->chans.first_channel + @@ -600,14 +628,10 @@ static int max_subband_chan(int orig_cur_chan, else { end_channel = triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1)); - next_band = IEEE80211_BAND_5GHZ; } - if (band != next_band) { - *country_ie -= 3; - *country_ie_len += 3; - break; - } + if (!chan_in_band(end_channel, band)) + return 0; if (orig_max_power != triplet->chans.max_power) { *country_ie -= 3; @@ -666,6 +690,7 @@ static int max_subband_chan(int orig_cur_chan, * with our userspace regulatory agent to get lower bounds. */ static struct ieee80211_regdomain *country_ie_2_rd( + enum ieee80211_band band, u8 *country_ie, u8 country_ie_len, u32 *checksum) @@ -743,8 +768,11 @@ static struct ieee80211_regdomain *country_ie_2_rd( if (triplet->chans.num_channels == 0) return NULL; + if (!chan_in_band(triplet->chans.first_channel, band)) + return NULL; + /* 2 GHz */ - if (triplet->chans.first_channel <= 14) + if (band == IEEE80211_BAND_2GHZ) end_channel = triplet->chans.first_channel + triplet->chans.num_channels - 1; else @@ -767,7 +795,8 @@ static struct ieee80211_regdomain *country_ie_2_rd( * or for whatever reason sends triplets with multiple channels * separated when in fact they should be together. */ - end_channel = max_subband_chan(cur_channel, + end_channel = max_subband_chan(band, + cur_channel, end_channel, triplet->chans.max_power, &country_ie, @@ -775,6 +804,9 @@ static struct ieee80211_regdomain *country_ie_2_rd( if (!end_channel) return NULL; + if (!chan_in_band(end_channel, band)) + return NULL; + cur_sub_max_channel = end_channel; /* Basic sanity check */ @@ -867,14 +899,15 @@ static struct ieee80211_regdomain *country_ie_2_rd( reg_rule->flags = flags; /* 2 GHz */ - if (triplet->chans.first_channel <= 14) + if (band == IEEE80211_BAND_2GHZ) end_channel = triplet->chans.first_channel + triplet->chans.num_channels -1; else end_channel = triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1)); - end_channel = max_subband_chan(triplet->chans.first_channel, + end_channel = max_subband_chan(band, + triplet->chans.first_channel, end_channel, triplet->chans.max_power, &country_ie, @@ -1981,8 +2014,9 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy, * therefore cannot iterate over the rdev list here. */ void regulatory_hint_11d(struct wiphy *wiphy, - u8 *country_ie, - u8 country_ie_len) + enum ieee80211_band band, + u8 *country_ie, + u8 country_ie_len) { struct ieee80211_regdomain *rd = NULL; char alpha2[2]; @@ -2028,7 +2062,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, wiphy_idx_valid(last_request->wiphy_idx))) goto out; - rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); + rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum); if (!rd) { REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n"); goto out; diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 3362c7c069b2..3018508226ab 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -41,14 +41,25 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, * regulatory_hint_11d - hints a country IE as a regulatory domain * @wiphy: the wireless device giving the hint (used only for reporting * conflicts) + * @band: the band on which the country IE was received on. This determines + * the band we'll process the country IE channel triplets for. * @country_ie: pointer to the country IE * @country_ie_len: length of the country IE * * We will intersect the rd with the what CRDA tells us should apply * for the alpha2 this country IE belongs to, this prevents APs from * sending us incorrect or outdated information against a country. + * + * The AP is expected to provide Country IE channel triplets for the + * band it is on. It is technically possible for APs to send channel + * country IE triplets even for channels outside of the band they are + * in but for that they would have to use the regulatory extension + * in combination with a triplet but this behaviour is currently + * not observed. For this reason if a triplet is seen with channel + * information for a band the BSS is not present in it will be ignored. */ void regulatory_hint_11d(struct wiphy *wiphy, + enum ieee80211_band band, u8 *country_ie, u8 country_ie_len); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 2333d78187e4..2ce5e1609a3d 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -454,6 +454,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * - and country_ie[1] which is the IE length */ regulatory_hint_11d(wdev->wiphy, + bss->channel->band, country_ie + 2, country_ie[1]); } -- cgit v1.2.3 From 43d3534344bbdcfa9c61a6b38490cd4cbb2f6bb6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 15 Jan 2010 03:00:48 +0100 Subject: mac80211: force use_short_slot=true for 5GHz Normally 5GHz does not have a concept of long vs short slot time, however the slot time that it ends up using is the same as for 2.4 GHZ and use_short_slot == true Because of that, it makes more sense to force use_short_slot = true whenever 5 GHz is being used, so that this particular check does not have to be in every single driver that uses this flag. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 7 +++++++ net/mac80211/mlme.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8286df5822d5..b0102c538b30 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1085,6 +1085,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, params->use_short_preamble; changed |= BSS_CHANGED_ERP_PREAMBLE; } + + if (!sdata->vif.bss_conf.use_short_slot && + sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { + sdata->vif.bss_conf.use_short_slot = true; + changed |= BSS_CHANGED_ERP_SLOT; + } + if (params->use_short_slot_time >= 0) { sdata->vif.bss_conf.use_short_slot = params->use_short_slot_time; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2746391248d3..a82564e73d91 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -670,6 +670,8 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, } use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); + if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + use_short_slot = true; if (use_protection != bss_conf->use_cts_prot) { bss_conf->use_cts_prot = use_protection; -- cgit v1.2.3 From 145b6d1a56f224d15c61aa7ecfda9a1171b47b6a Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 15 Jan 2010 21:44:21 +0800 Subject: mac80211: fix memory leak in ieee80211_send_probe_req This patch fixes memory leak in ieee80211_send_probe_req, which is introduced in 7c12ce8b854df346388ea56d684784e3484012cf: mac80211: use Probe Request template when sending a direct scan The patch is against the latest wireless-test tree. Signed-off-by: Ming Lei Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- net/mac80211/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e278f97c8305..ca170b417da6 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1028,6 +1028,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); + kfree(buf); } u32 ieee80211_sta_get_rates(struct ieee80211_local *local, -- cgit v1.2.3 From 0005baf4a31efe6de6f922f73ccbd3762a110062 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 15 Jan 2010 02:33:40 +0100 Subject: ath9k: cleanup slot time and ack/cts timeout handling Previously ath9k left the initialization of slot timing and ACK/CTS timeout to the mode specific initvals. This does not handle short vs long slot in 2.4 GHz and uses a rather strange value for the 2.4 GHz ACK timeout (64 usec). This patch uses the proper ath9k_hw functions for setting slot time and timeouts and also implements the switch between short and long slot time in 2.4 GHz Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 3 +- drivers/net/wireless/ath/ath9k/hw.c | 103 ++++++++++---------------------- drivers/net/wireless/ath/ath9k/hw.h | 4 +- drivers/net/wireless/ath/ath9k/main.c | 20 +++++++ 4 files changed, 55 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 1660ef17aaf5..422454fe4ff0 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -480,7 +480,8 @@ void ath_beacon_tasklet(unsigned long data) sc->beacon.updateslot = COMMIT; /* commit next beacon */ sc->beacon.slotupdate = slot; } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { - ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); + ah->slottime = sc->beacon.slottime; + ath9k_hw_init_global_settings(ah); sc->beacon.updateslot = OK; } if (bfaddr != 0) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2311fe7a0bf2..e1fd4cc9fae2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -52,28 +52,6 @@ module_exit(ath9k_exit); /* Helper Functions */ /********************/ -static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - - if (!ah->curchan) /* should really check for CCK instead */ - return clks / ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; - - return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; -} - -static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - - if (conf_is_ht40(conf)) - return ath9k_hw_mac_usec(ah, clks) / 2; - else - return ath9k_hw_mac_usec(ah, clks); -} - static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; @@ -413,8 +391,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) ah->beacon_interval = 100; ah->enable_32kHz_clock = DONT_USE_32KHZ; ah->slottime = (u32) -1; - ah->acktimeout = (u32) -1; - ah->ctstimeout = (u32) -1; ah->globaltxtimeout = (u32) -1; ah->power_mode = ATH9K_PM_UNDEFINED; } @@ -1180,34 +1156,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, } } -static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) +static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) { - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "bad ack timeout %u\n", us); - ah->acktimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); - ah->acktimeout = us; - return true; - } + u32 val = ath9k_hw_mac_to_clks(ah, us); + val = min(val, (u32) 0xFFFF); + REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val); } -static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) +static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) { - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "bad cts timeout %u\n", us); - ah->ctstimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); - ah->ctstimeout = us; - return true; - } + u32 val = ath9k_hw_mac_to_clks(ah, us); + val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK)); + REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val); +} + +static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) +{ + u32 val = ath9k_hw_mac_to_clks(ah, us); + val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS)); + REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val); } static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) @@ -1224,23 +1191,32 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) } } -static void ath9k_hw_init_user_settings(struct ath_hw *ah) +void ath9k_hw_init_global_settings(struct ath_hw *ah) { + struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + int acktimeout; + int sifstime; + ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", ah->misc_mode); if (ah->misc_mode != 0) REG_WRITE(ah, AR_PCU_MISC, REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); - if (ah->slottime != (u32) -1) - ath9k_hw_setslottime(ah, ah->slottime); - if (ah->acktimeout != (u32) -1) - ath9k_hw_set_ack_timeout(ah, ah->acktimeout); - if (ah->ctstimeout != (u32) -1) - ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); + + if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) + sifstime = 16; + else + sifstime = 10; + + acktimeout = ah->slottime + sifstime; + ath9k_hw_setslottime(ah, ah->slottime); + ath9k_hw_set_ack_timeout(ah, acktimeout); + ath9k_hw_set_cts_timeout(ah, acktimeout); if (ah->globaltxtimeout != (u32) -1) ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); } +EXPORT_SYMBOL(ath9k_hw_init_global_settings); void ath9k_hw_deinit(struct ath_hw *ah) { @@ -2061,7 +2037,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) ath9k_enable_rfkill(ah); - ath9k_hw_init_user_settings(ah); + ath9k_hw_init_global_settings(ah); if (AR_SREV_9287_12_OR_LATER(ah)) { REG_WRITE(ah, AR_D_GBL_IFS_SIFS, @@ -3658,21 +3634,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) } EXPORT_SYMBOL(ath9k_hw_extend_tsf); -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) -{ - if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { - ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, - "bad slot time %u\n", us); - ah->slottime = (u32) -1; - return false; - } else { - REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); - ah->slottime = us; - return true; - } -} -EXPORT_SYMBOL(ath9k_hw_setslottime); - void ath9k_hw_set11nmac2040(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 3f0f055ea39b..a7ff07537bc4 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -553,8 +553,6 @@ struct ath_hw { int16_t txpower_indexoffset; u32 beacon_interval; u32 slottime; - u32 acktimeout; - u32 ctstimeout; u32 globaltxtimeout; /* ANI */ @@ -668,7 +666,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); void ath9k_hw_reset_tsf(struct ath_hw *ah); void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp); -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); +void ath9k_hw_init_global_settings(struct ath_hw *ah); void ath9k_hw_set11nmac2040(struct ath_hw *ah); void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index b39c7bc41143..580ecca0182c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1789,6 +1789,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_vif *avp = (void *)vif->drv_priv; + int slottime; int error; mutex_lock(&sc->mutex); @@ -1824,6 +1825,25 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath_beacon_config(sc, vif); } + if (changed & BSS_CHANGED_ERP_SLOT) { + if (bss_conf->use_short_slot) + slottime = 9; + else + slottime = 20; + if (vif->type == NL80211_IFTYPE_AP) { + /* + * Defer update, so that connected stations can adjust + * their settings at the same time. + * See beacon.c for more details + */ + sc->beacon.slottime = slottime; + sc->beacon.updateslot = UPDATE; + } else { + ah->slottime = slottime; + ath9k_hw_init_global_settings(ah); + } + } + /* Disable transmission of beacons */ if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); -- cgit v1.2.3 From e239d8591843945630521ec85edca08289f1a751 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 15 Jan 2010 02:34:58 +0100 Subject: ath9k: implement coverage class support Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 +++++-- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 13 +++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e1fd4cc9fae2..0b1dd10f1d84 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1195,6 +1195,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; int acktimeout; + int slottime; int sifstime; ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", @@ -1209,8 +1210,10 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) else sifstime = 10; - acktimeout = ah->slottime + sifstime; - ath9k_hw_setslottime(ah, ah->slottime); + /* As defined by IEEE 802.11-2007 17.3.8.6 */ + slottime = ah->slottime + 3 * ah->coverage_class; + acktimeout = slottime + sifstime; + ath9k_hw_setslottime(ah, slottime); ath9k_hw_set_ack_timeout(ah, acktimeout); ath9k_hw_set_cts_timeout(ah, acktimeout); if (ah->globaltxtimeout != (u32) -1) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index a7ff07537bc4..ab1f1981d857 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -551,6 +551,7 @@ struct ath_hw { u32 *bank6Temp; int16_t txpower_indexoffset; + int coverage_class; u32 beacon_interval; u32 slottime; u32 globaltxtimeout; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 580ecca0182c..c0c571c2e8c4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2014,6 +2014,18 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) mutex_unlock(&sc->mutex); } +static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + struct ath_hw *ah = sc->sc_ah; + + mutex_lock(&sc->mutex); + ah->coverage_class = coverage_class; + ath9k_hw_init_global_settings(ah); + mutex_unlock(&sc->mutex); +} + struct ieee80211_ops ath9k_ops = { .tx = ath9k_tx, .start = ath9k_start, @@ -2033,4 +2045,5 @@ struct ieee80211_ops ath9k_ops = { .sw_scan_start = ath9k_sw_scan_start, .sw_scan_complete = ath9k_sw_scan_complete, .rfkill_poll = ath9k_rfkill_poll_state, + .set_coverage_class = ath9k_set_coverage_class, }; -- cgit v1.2.3 From 857c0fc490d8474d1a232d9b6568a4b229634bcd Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:01:49 +0100 Subject: b43: use standard fls for finding the most significant bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_lp.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index eb4fb4581edb..b58d6cf26580 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1710,19 +1710,6 @@ static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = { .c0 = 0, }; -static u8 lpphy_nbits(s32 val) -{ - u32 tmp = abs(val); - u8 nbits = 0; - - while (tmp != 0) { - nbits++; - tmp >>= 1; - } - - return nbits; -} - static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) { struct lpphy_iq_est iq_est; @@ -1749,8 +1736,8 @@ static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples) goto out; } - prod_msb = lpphy_nbits(prod); - q_msb = lpphy_nbits(qpwr); + prod_msb = fls(abs(prod)); + q_msb = fls(abs(qpwr)); tmp1 = prod_msb - 20; if (tmp1 >= 0) { -- cgit v1.2.3 From 003d6d2792bebb2b66966ce5f1da11849e855180 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:10:53 +0100 Subject: b43: add new SSB's core id for BCM4328 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following line shows my BCM4328 detected on SSB. We didn't include 0x0C rev. ssb: Core 1 found: IEEE 802.11 (cc 0x812, rev 0x0C, vendor 0x4243) Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 881afff86bd3..c238468bca7f 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -118,6 +118,7 @@ static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), + SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 12), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), -- cgit v1.2.3 From 4772ae107c42cdce1d3864d8d540ea0401eb09d6 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:18:21 +0100 Subject: b43: N-PHY: clean table init, check PHY rev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move table init to tables_nphy.c, detect newer PHY which use different init. We don't init newer PHYs yet but this at least shows what more is needed. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 38 +++---------- drivers/net/wireless/b43/tables_nphy.c | 100 ++++++++++++++++++++++++--------- drivers/net/wireless/b43/tables_nphy.h | 29 +--------- 3 files changed, 84 insertions(+), 83 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 992318a78077..6b995b92af7a 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -203,38 +203,16 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev) b43_ntab_write(dev, (offset) + i, (data)[i]); \ } while (0) -/* Upload the N-PHY tables. */ +/* + * Upload the N-PHY tables. + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables + */ static void b43_nphy_tables_init(struct b43_wldev *dev) { - /* Static tables */ - ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); - ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); - ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); - ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); - ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); - ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); - ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); - ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); - ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); - ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); - ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); - ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); - ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); - ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); - - /* Volatile tables */ - ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); - ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); - ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); - ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); - ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); - ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); - ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); - ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); - ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); - ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); - ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); - ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); + if (dev->phy.rev < 3) + b43_nphy_rev0_1_2_tables_init(dev); + else + b43_nphy_rev3plus_tables_init(dev); } static void b43_nphy_workarounds(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 4e2336315545..d0b91b561fb8 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -1336,7 +1336,7 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) } -const u8 b43_ntab_adjustpower0[] = { +static const u8 b43_ntab_adjustpower0[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, @@ -1355,7 +1355,7 @@ const u8 b43_ntab_adjustpower0[] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, }; -const u8 b43_ntab_adjustpower1[] = { +static const u8 b43_ntab_adjustpower1[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, @@ -1374,11 +1374,11 @@ const u8 b43_ntab_adjustpower1[] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, }; -const u16 b43_ntab_bdi[] = { +static const u16 b43_ntab_bdi[] = { 0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2, }; -const u32 b43_ntab_channelest[] = { +static const u32 b43_ntab_channelest[] = { 0x44444444, 0x44444444, 0x44444444, 0x44444444, 0x44444444, 0x44444444, 0x44444444, 0x44444444, 0x10101010, 0x10101010, 0x10101010, 0x10101010, @@ -1405,7 +1405,7 @@ const u32 b43_ntab_channelest[] = { 0x10101010, 0x10101010, 0x10101010, 0x10101010, }; -const u8 b43_ntab_estimatepowerlt0[] = { +static const u8 b43_ntab_estimatepowerlt0[] = { 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, @@ -1416,7 +1416,7 @@ const u8 b43_ntab_estimatepowerlt0[] = { 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, }; -const u8 b43_ntab_estimatepowerlt1[] = { +static const u8 b43_ntab_estimatepowerlt1[] = { 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, @@ -1427,14 +1427,14 @@ const u8 b43_ntab_estimatepowerlt1[] = { 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, }; -const u8 b43_ntab_framelookup[] = { +static const u8 b43_ntab_framelookup[] = { 0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16, 0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E, 0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A, 0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A, }; -const u32 b43_ntab_framestruct[] = { +static const u32 b43_ntab_framestruct[] = { 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, 0x09804506, 0x00100030, 0x09804507, 0x00100030, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -1645,7 +1645,7 @@ const u32 b43_ntab_framestruct[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; -const u32 b43_ntab_gainctl0[] = { +static const u32 b43_ntab_gainctl0[] = { 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, @@ -1680,7 +1680,7 @@ const u32 b43_ntab_gainctl0[] = { 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, }; -const u32 b43_ntab_gainctl1[] = { +static const u32 b43_ntab_gainctl1[] = { 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, @@ -1715,12 +1715,12 @@ const u32 b43_ntab_gainctl1[] = { 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, }; -const u32 b43_ntab_intlevel[] = { +static const u32 b43_ntab_intlevel[] = { 0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46, 0x00C1188D, 0x080024D2, 0x00000070, }; -const u32 b43_ntab_iqlt0[] = { +static const u32 b43_ntab_iqlt0[] = { 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, @@ -1755,7 +1755,7 @@ const u32 b43_ntab_iqlt0[] = { 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, }; -const u32 b43_ntab_iqlt1[] = { +static const u32 b43_ntab_iqlt1[] = { 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, @@ -1790,7 +1790,7 @@ const u32 b43_ntab_iqlt1[] = { 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, }; -const u16 b43_ntab_loftlt0[] = { +static const u16 b43_ntab_loftlt0[] = { 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, @@ -1815,7 +1815,7 @@ const u16 b43_ntab_loftlt0[] = { 0x0002, 0x0103, }; -const u16 b43_ntab_loftlt1[] = { +static const u16 b43_ntab_loftlt1[] = { 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, @@ -1840,7 +1840,7 @@ const u16 b43_ntab_loftlt1[] = { 0x0002, 0x0103, }; -const u8 b43_ntab_mcs[] = { +static const u8 b43_ntab_mcs[] = { 0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C, 0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C, 0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C, @@ -1859,7 +1859,7 @@ const u8 b43_ntab_mcs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -const u32 b43_ntab_noisevar10[] = { +static const u32 b43_ntab_noisevar10[] = { 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, @@ -1926,7 +1926,7 @@ const u32 b43_ntab_noisevar10[] = { 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, }; -const u32 b43_ntab_noisevar11[] = { +static const u32 b43_ntab_noisevar11[] = { 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, @@ -1993,7 +1993,7 @@ const u32 b43_ntab_noisevar11[] = { 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, }; -const u16 b43_ntab_pilot[] = { +static const u16 b43_ntab_pilot[] = { 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82, @@ -2011,12 +2011,12 @@ const u16 b43_ntab_pilot[] = { 0xF0A0, 0xF028, 0xFFFF, 0xFFFF, }; -const u32 b43_ntab_pilotlt[] = { +static const u32 b43_ntab_pilotlt[] = { 0x76540123, 0x62407351, 0x76543201, 0x76540213, 0x76540123, 0x76430521, }; -const u32 b43_ntab_tdi20a0[] = { +static const u32 b43_ntab_tdi20a0[] = { 0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0, 0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D, 0x00020301, 0x00030504, 0x00040708, 0x0005090B, @@ -2033,7 +2033,7 @@ const u32 b43_ntab_tdi20a0[] = { 0x00000000, 0x00000000, 0x00000000, }; -const u32 b43_ntab_tdi20a1[] = { +static const u32 b43_ntab_tdi20a1[] = { 0x00014B26, 0x00028D29, 0x000393AD, 0x00049630, 0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D, 0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B, @@ -2050,7 +2050,7 @@ const u32 b43_ntab_tdi20a1[] = { 0x00000000, 0x00000000, 0x00000000, }; -const u32 b43_ntab_tdi40a0[] = { +static const u32 b43_ntab_tdi40a0[] = { 0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2, 0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C, 0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2, @@ -2081,7 +2081,7 @@ const u32 b43_ntab_tdi40a0[] = { 0x00000000, 0x00000000, }; -const u32 b43_ntab_tdi40a1[] = { +static const u32 b43_ntab_tdi40a1[] = { 0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD, 0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07, 0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D, @@ -2112,7 +2112,7 @@ const u32 b43_ntab_tdi40a1[] = { 0x00000000, 0x00000000, }; -const u32 b43_ntab_tdtrn[] = { +static const u32 b43_ntab_tdtrn[] = { 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6, 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68, 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52, @@ -2291,7 +2291,7 @@ const u32 b43_ntab_tdtrn[] = { 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE, }; -const u32 b43_ntab_tmap[] = { +static const u32 b43_ntab_tmap[] = { 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, 0xF1111110, 0x11111111, 0x11F11111, 0x00000111, @@ -2474,3 +2474,51 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) /* Some compiletime assertions... */ assert_ntab_array_sizes(); } + +#define ntab_upload(dev, offset, data) do { \ + unsigned int i; \ + for (i = 0; i < (offset##_SIZE); i++) \ + b43_ntab_write(dev, (offset) + i, (data)[i]); \ + } while (0) + +void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev) +{ + /* Static tables */ + ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); + ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); + ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); + ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); + ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); + ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); + ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); + ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); + ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); + ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); + ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); + ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); + ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); + ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); + + /* Volatile tables */ + ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); + ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); + ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); + ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); + ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); + ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); + ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); + ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); + ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); + ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); + ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); + ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); +} + +void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev) +{ + /* Static tables */ + /* TODO */ + + /* Volatile tables */ + /* TODO */ +} diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 4d498b053ec7..1f0a602fd247 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -128,32 +128,7 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); -extern const u8 b43_ntab_adjustpower0[]; -extern const u8 b43_ntab_adjustpower1[]; -extern const u16 b43_ntab_bdi[]; -extern const u32 b43_ntab_channelest[]; -extern const u8 b43_ntab_estimatepowerlt0[]; -extern const u8 b43_ntab_estimatepowerlt1[]; -extern const u8 b43_ntab_framelookup[]; -extern const u32 b43_ntab_framestruct[]; -extern const u32 b43_ntab_gainctl0[]; -extern const u32 b43_ntab_gainctl1[]; -extern const u32 b43_ntab_intlevel[]; -extern const u32 b43_ntab_iqlt0[]; -extern const u32 b43_ntab_iqlt1[]; -extern const u16 b43_ntab_loftlt0[]; -extern const u16 b43_ntab_loftlt1[]; -extern const u8 b43_ntab_mcs[]; -extern const u32 b43_ntab_noisevar10[]; -extern const u32 b43_ntab_noisevar11[]; -extern const u16 b43_ntab_pilot[]; -extern const u32 b43_ntab_pilotlt[]; -extern const u32 b43_ntab_tdi20a0[]; -extern const u32 b43_ntab_tdi20a1[]; -extern const u32 b43_ntab_tdi40a0[]; -extern const u32 b43_ntab_tdi40a1[]; -extern const u32 b43_ntab_tdtrn[]; -extern const u32 b43_ntab_tmap[]; - +void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); +void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); #endif /* B43_TABLES_NPHY_H_ */ -- cgit v1.2.3 From 76a4db303d06066792bbc0e886def2cf99b232ef Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:27:46 +0100 Subject: b43: N-PHY: add shared memory offsets definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 2f12a750bc98..54d6085a887b 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -253,6 +253,14 @@ enum { #define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */ #define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ #define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ +/* SHM_SHARED tx iq workarounds */ +#define B43_SHM_SH_NPHY_TXIQW0 0x0700 +#define B43_SHM_SH_NPHY_TXIQW1 0x0702 +#define B43_SHM_SH_NPHY_TXIQW2 0x0704 +#define B43_SHM_SH_NPHY_TXIQW3 0x0706 +/* SHM_SHARED tx pwr ctrl */ +#define B43_SHM_SH_NPHY_TXPWR_INDX0 0x0708 +#define B43_SHM_SH_NPHY_TXPWR_INDX1 0x070E /* SHM_SCRATCH offsets */ #define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */ -- cgit v1.2.3 From f8187b5b9780a9ac3c12c70413615a0fdf321cd5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:34:21 +0100 Subject: b43: N-PHY: add needed struct definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 24 +++++++++++++++++++++ drivers/net/wireless/b43/phy_n.h | 38 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 5 +++++ 3 files changed, 67 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6b995b92af7a..cb784a2504a6 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -29,6 +29,30 @@ #include "phy_n.h" #include "tables_nphy.h" +struct nphy_txgains { + u16 txgm[2]; + u16 pga[2]; + u16 pad[2]; + u16 ipa[2]; +}; + +struct nphy_iqcal_params { + u16 txgm; + u16 pga; + u16 pad; + u16 ipa; + u16 cal_gain; + u16 ncorr[5]; +}; + +struct nphy_iq_est { + s32 iq0_prod; + u32 i0_pwr; + u32 q0_pwr; + s32 iq1_prod; + u32 i1_pwr; + u32 q1_pwr; +}; void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 1749aef4147d..f829e4e397e8 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -919,6 +919,44 @@ struct b43_wldev; +struct b43_phy_n_iq_comp { + s16 a0; + s16 b0; + s16 a1; + s16 b1; +}; + +struct b43_phy_n_rssical_cache { + u16 rssical_radio_regs_2G[2]; + u16 rssical_phy_regs_2G[12]; + + u16 rssical_radio_regs_5G[2]; + u16 rssical_phy_regs_5G[12]; +}; + +struct b43_phy_n_cal_cache { + u16 txcal_radio_regs_2G[8]; + u16 txcal_coeffs_2G[8]; + struct b43_phy_n_iq_comp rxcal_coeffs_2G; + + u16 txcal_radio_regs_5G[8]; + u16 txcal_coeffs_5G[8]; + struct b43_phy_n_iq_comp rxcal_coeffs_5G; +}; + +struct b43_phy_n_txpwrindex { + s8 index; + s8 index_internal; + s8 index_internal_save; + u16 AfectrlOverride; + u16 AfeCtrlDacGain; + u16 rad_gain; + u8 bbmult; + u16 iqcomp_a; + u16 iqcomp_b; + u16 locomp; +}; + struct b43_phy_n { //TODO lots of missing stuff }; diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 1f0a602fd247..f6753c4b96b2 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -46,6 +46,11 @@ struct b43_nphy_channeltab_entry { struct b43_wldev; +struct nphy_txiqcal_ladder { + u8 percent; + u8 g_env; +}; + /* Upload the default register value table. * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz * table is uploaded. If "ignore_uploadflag" is true, we upload any value -- cgit v1.2.3 From 5b0ade3377b91da14410612b2051d66d26d31069 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:40:03 +0100 Subject: b43: N-PHY: add missing register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index f829e4e397e8..c5084a4e30cd 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -231,6 +231,7 @@ #define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */ #define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */ #define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */ +#define B43_NPHY_AFECTL_OVER1 B43_PHY_N(0x08F) /* AFE control override 1 */ #define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */ #define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */ #define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0 @@ -705,6 +706,10 @@ #define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */ #define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */ #define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0 +#define B43_NPHY_PAPD_EN0 B43_PHY_N(0x297) /* PAPD Enable0 TBD */ +#define B43_NPHY_EPS_TABLE_ADJ0 B43_PHY_N(0x298) /* EPS Table Adj0 TBD */ +#define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ +#define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ -- cgit v1.2.3 From 2a448bfc70f4fd4a54996d1c7a371ba28ec0568f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 12:54:30 +0100 Subject: b43: N-PHY: add global variables to b43_phy_n struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.h | 44 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index c5084a4e30cd..4572866756fc 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -963,7 +963,49 @@ struct b43_phy_n_txpwrindex { }; struct b43_phy_n { - //TODO lots of missing stuff + u8 antsel_type; + u8 cal_orig_pwr_idx[2]; + u8 measure_hold; + u8 phyrxchain; + u8 perical; + u32 deaf_count; + u32 rxcalparams; + bool hang_avoid; + bool mute; + u16 papd_epsilon_offset[2]; + + u8 mphase_cal_phase_id; + u16 mphase_txcal_cmdidx; + u16 mphase_txcal_numcmds; + u16 mphase_txcal_bestcoeffs[11]; + + u8 txpwrctrl; + u16 txcal_bbmult; + u16 txiqlocal_bestc[11]; + bool txiqlocal_coeffsvalid; + struct b43_phy_n_txpwrindex txpwrindex[2]; + + u16 tx_rx_cal_phy_saveregs[11]; + u16 tx_rx_cal_radio_saveregs[22]; + + u16 rfctrl_intc1_save; + u16 rfctrl_intc2_save; + + u16 classifier_state; + u16 clip_state[2]; + + bool ipa2g_on; + u8 iqcal_chanspec_2G; + u8 rssical_chanspec_2G; + + bool ipa5g_on; + u8 iqcal_chanspec_5G; + u8 rssical_chanspec_5G; + + struct b43_phy_n_rssical_cache rssical_cache; + struct b43_phy_n_cal_cache cal_cache; + bool crsminpwr_adjusted; + bool noisevars_adjusted; }; -- cgit v1.2.3 From 088e56b44a52bbd58a790627148cf75ed71ae34b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 13:02:45 +0100 Subject: b43: N-PHY: add various tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/tables_nphy.c | 477 +++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 37 +++ 2 files changed, 514 insertions(+) diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index d0b91b561fb8..7dff853ab962 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2406,6 +2406,483 @@ static const u32 b43_ntab_tmap[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; +const u32 b43_ntab_tx_gain_rev0_1_2[] = { + 0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42, + 0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44, + 0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844, + 0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44, + 0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844, + 0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644, + 0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444, + 0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44, + 0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844, + 0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44, + 0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944, + 0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744, + 0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544, + 0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44, + 0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844, + 0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44, + 0x03902b42, 0x03902a44, 0x03902a42, 0x03902944, + 0x03902942, 0x03902844, 0x03902842, 0x03902744, + 0x03902742, 0x03902644, 0x03902642, 0x03902544, + 0x03902542, 0x03802b44, 0x03802b42, 0x03802a44, + 0x03802a42, 0x03802944, 0x03802942, 0x03802844, + 0x03802842, 0x03802744, 0x03802742, 0x03802644, + 0x03802642, 0x03802544, 0x03802542, 0x03802444, + 0x03802442, 0x03802344, 0x03802342, 0x03802244, + 0x03802242, 0x03802144, 0x03802142, 0x03802044, + 0x03802042, 0x03801f44, 0x03801f42, 0x03801e44, + 0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44, + 0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44, + 0x03801a42, 0x03801944, 0x03801942, 0x03801844, + 0x03801842, 0x03801744, 0x03801742, 0x03801644, + 0x03801642, 0x03801544, 0x03801542, 0x03801444, + 0x03801442, 0x03801344, 0x03801342, 0x00002b00, +}; + +const u32 b43_ntab_tx_gain_rev3plus_2ghz[] = { + 0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e, + 0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037, + 0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e, + 0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037, + 0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e, + 0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037, + 0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e, + 0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037, + 0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e, + 0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037, + 0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e, + 0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037, + 0x19410044, 0x19410042, 0x19410040, 0x1941003e, + 0x1941003c, 0x1941003b, 0x19410039, 0x19410037, + 0x18410044, 0x18410042, 0x18410040, 0x1841003e, + 0x1841003c, 0x1841003b, 0x18410039, 0x18410037, + 0x17410044, 0x17410042, 0x17410040, 0x1741003e, + 0x1741003c, 0x1741003b, 0x17410039, 0x17410037, + 0x16410044, 0x16410042, 0x16410040, 0x1641003e, + 0x1641003c, 0x1641003b, 0x16410039, 0x16410037, + 0x15410044, 0x15410042, 0x15410040, 0x1541003e, + 0x1541003c, 0x1541003b, 0x15410039, 0x15410037, + 0x14410044, 0x14410042, 0x14410040, 0x1441003e, + 0x1441003c, 0x1441003b, 0x14410039, 0x14410037, + 0x13410044, 0x13410042, 0x13410040, 0x1341003e, + 0x1341003c, 0x1341003b, 0x13410039, 0x13410037, + 0x12410044, 0x12410042, 0x12410040, 0x1241003e, + 0x1241003c, 0x1241003b, 0x12410039, 0x12410037, + 0x11410044, 0x11410042, 0x11410040, 0x1141003e, + 0x1141003c, 0x1141003b, 0x11410039, 0x11410037, + 0x10410044, 0x10410042, 0x10410040, 0x1041003e, + 0x1041003c, 0x1041003b, 0x10410039, 0x10410037, +}; + +const u32 b43_ntab_tx_gain_rev3_5ghz[] = { + 0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e, + 0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037, + 0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e, + 0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037, + 0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e, + 0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037, + 0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e, + 0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037, + 0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e, + 0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037, + 0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e, + 0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037, + 0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e, + 0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037, + 0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e, + 0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037, + 0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e, + 0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037, + 0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e, + 0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037, + 0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e, + 0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037, + 0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e, + 0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037, + 0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e, + 0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037, + 0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e, + 0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037, + 0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e, + 0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037, + 0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e, + 0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037, +}; + +const u32 b43_ntab_tx_gain_rev4_5ghz[] = { + 0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e, + 0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037, + 0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e, + 0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037, + 0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e, + 0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037, + 0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e, + 0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037, + 0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e, + 0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037, + 0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e, + 0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037, + 0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e, + 0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037, + 0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e, + 0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037, + 0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e, + 0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037, + 0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e, + 0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037, + 0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e, + 0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037, + 0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e, + 0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038, + 0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e, + 0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037, + 0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e, + 0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037, + 0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e, + 0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037, + 0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c, + 0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034, +}; + +const u32 b43_ntab_tx_gain_rev5plus_5ghz[] = { + 0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044, + 0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c, + 0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e, + 0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a, + 0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e, + 0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a, + 0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e, + 0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037, + 0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040, + 0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a, + 0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c, + 0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038, + 0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b, + 0x09620039, 0x09620037, 0x09620035, 0x09620033, + 0x08620044, 0x08620042, 0x08620040, 0x0862003e, + 0x0862003c, 0x0862003b, 0x0862003a, 0x08620039, + 0x07620043, 0x07620042, 0x07620040, 0x0762003f, + 0x0762003d, 0x0762003b, 0x0762003a, 0x07620039, + 0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b, + 0x06620039, 0x06620037, 0x06620035, 0x06620033, + 0x05620046, 0x05620044, 0x05620042, 0x05620040, + 0x0562003e, 0x0562003c, 0x0562003b, 0x05620039, + 0x04620044, 0x04620042, 0x04620040, 0x0462003e, + 0x0462003c, 0x0462003b, 0x04620039, 0x04620038, + 0x0362003c, 0x0362003b, 0x0362003a, 0x03620039, + 0x03620038, 0x03620037, 0x03620035, 0x03620033, + 0x0262004c, 0x0262004a, 0x02620048, 0x02620047, + 0x02620046, 0x02620044, 0x02620043, 0x02620042, + 0x0162004a, 0x01620048, 0x01620046, 0x01620044, + 0x01620043, 0x01620042, 0x01620041, 0x01620040, + 0x00620042, 0x00620040, 0x0062003e, 0x0062003c, + 0x0062003b, 0x00620039, 0x00620037, 0x00620035, +}; + +const u32 txpwrctrl_tx_gain_ipa[] = { + 0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029, + 0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025, + 0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029, + 0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025, + 0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029, + 0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025, + 0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029, + 0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025, + 0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029, + 0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025, + 0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029, + 0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025, + 0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029, + 0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025, + 0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029, + 0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025, + 0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029, + 0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025, + 0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029, + 0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025, + 0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029, + 0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025, + 0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029, + 0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025, + 0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029, + 0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025, + 0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029, + 0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025, + 0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029, + 0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025, + 0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029, + 0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025, +}; + +const u32 txpwrctrl_tx_gain_ipa_rev5[] = { + 0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029, + 0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025, + 0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029, + 0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025, + 0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029, + 0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025, + 0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029, + 0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025, + 0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029, + 0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025, + 0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029, + 0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025, + 0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029, + 0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025, + 0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029, + 0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025, + 0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029, + 0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025, + 0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029, + 0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025, + 0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029, + 0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025, + 0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029, + 0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025, + 0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029, + 0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025, + 0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029, + 0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025, + 0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029, + 0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025, + 0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029, + 0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025, +}; + +const u32 txpwrctrl_tx_gain_ipa_rev6[] = { + 0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029, + 0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025, + 0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029, + 0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025, + 0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029, + 0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025, + 0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029, + 0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025, + 0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029, + 0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025, + 0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029, + 0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025, + 0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029, + 0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025, + 0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029, + 0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025, + 0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029, + 0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025, + 0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029, + 0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025, + 0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029, + 0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025, + 0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029, + 0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025, + 0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029, + 0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025, + 0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029, + 0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025, + 0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029, + 0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025, + 0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029, + 0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025, +}; + +const u32 txpwrctrl_tx_gain_ipa_5g[] = { + 0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031, + 0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b, + 0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027, + 0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022, + 0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025, + 0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027, + 0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023, + 0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027, + 0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022, + 0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025, + 0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021, + 0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026, + 0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022, + 0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026, + 0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022, + 0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026, + 0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022, + 0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026, + 0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022, + 0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026, + 0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021, + 0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026, + 0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029, + 0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024, + 0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027, + 0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023, + 0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026, + 0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022, + 0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025, + 0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027, + 0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022, + 0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f, +}; + +const u16 tbl_iqcal_gainparams[2][9][8] = { + { + { 0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69 }, + { 0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69 }, + { 0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68 }, + { 0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67 }, + { 0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66 }, + { 0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65 }, + { 0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65 }, + { 0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65 }, + { 0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65 } + }, + { + { 0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 }, + { 0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79 }, + { 0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79 }, + { 0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78 }, + { 0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78 }, + { 0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78 }, + { 0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78 }, + { 0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78 }, + { 0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78 } + } +}; + +const struct nphy_txiqcal_ladder ladder_lo[] = { + { 3, 0 }, + { 4, 0 }, + { 6, 0 }, + { 9, 0 }, + { 13, 0 }, + { 18, 0 }, + { 25, 0 }, + { 25, 1 }, + { 25, 2 }, + { 25, 3 }, + { 25, 4 }, + { 25, 5 }, + { 25, 6 }, + { 25, 7 }, + { 35, 7 }, + { 50, 7 }, + { 71, 7 }, + { 100, 7 } +}; + +const struct nphy_txiqcal_ladder ladder_iq[] = { + { 3, 0 }, + { 4, 0 }, + { 6, 0 }, + { 9, 0 }, + { 13, 0 }, + { 18, 0 }, + { 25, 0 }, + { 35, 0 }, + { 50, 0 }, + { 71, 0 }, + { 100, 0 }, + { 100, 1 }, + { 100, 2 }, + { 100, 3 }, + { 100, 4 }, + { 100, 5 }, + { 100, 6 }, + { 100, 7 } +}; + +const u16 loscale[] = { + 256, 256, 271, 271, + 287, 256, 256, 271, + 271, 287, 287, 304, + 304, 256, 256, 271, + 271, 287, 287, 304, + 304, 322, 322, 341, + 341, 362, 362, 383, + 383, 256, 256, 271, + 271, 287, 287, 304, + 304, 322, 322, 256, + 256, 271, 271, 287, + 287, 304, 304, 322, + 322, 341, 341, 362, + 362, 256, 256, 271, + 271, 287, 287, 304, + 304, 322, 322, 256, + 256, 271, 271, 287, + 287, 304, 304, 322, + 322, 341, 341, 362, + 362, 256, 256, 271, + 271, 287, 287, 304, + 304, 322, 322, 341, + 341, 362, 362, 383, + 383, 406, 406, 430, + 430, 455, 455, 482, + 482, 511, 511, 541, + 541, 573, 573, 607, + 607, 643, 643, 681, + 681, 722, 722, 764, + 764, 810, 810, 858, + 858, 908, 908, 962, + 962, 1019, 1019, 256 +}; + +const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { + 0x0200, 0x0300, 0x0400, 0x0700, + 0x0900, 0x0c00, 0x1200, 0x1201, + 0x1202, 0x1203, 0x1204, 0x1205, + 0x1206, 0x1207, 0x1907, 0x2307, + 0x3207, 0x4707 +}; + +const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { + 0x0300, 0x0500, 0x0700, 0x0900, + 0x0d00, 0x1100, 0x1900, 0x1901, + 0x1902, 0x1903, 0x1904, 0x1905, + 0x1906, 0x1907, 0x2407, 0x3207, + 0x4607, 0x6407 +}; + +const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { + 0x0100, 0x0200, 0x0400, 0x0700, + 0x0900, 0x0c00, 0x1200, 0x1900, + 0x2300, 0x3200, 0x4700, 0x4701, + 0x4702, 0x4703, 0x4704, 0x4705, + 0x4706, 0x4707 +}; + +const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { + 0x0200, 0x0300, 0x0600, 0x0900, + 0x0d00, 0x1100, 0x1900, 0x2400, + 0x3200, 0x4600, 0x6400, 0x6401, + 0x6402, 0x6403, 0x6404, 0x6405, + 0x6406, 0x6407 +}; + +const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3] = { }; + +const u16 tbl_tx_iqlo_cal_startcoefs[B43_NTAB_TX_IQLO_CAL_STARTCOEFS] = { }; + +const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { + 0x8423, 0x8323, 0x8073, 0x8256, + 0x8045, 0x8223, 0x9423, 0x9323, + 0x9073, 0x9256, 0x9045, 0x9223 +}; + +const u16 tbl_tx_iqlo_cal_cmds_recal[] = { + 0x8101, 0x8253, 0x8053, 0x8234, + 0x8034, 0x9101, 0x9253, 0x9053, + 0x9234, 0x9034 +}; + +const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { + 0x8123, 0x8264, 0x8086, 0x8245, + 0x8056, 0x9123, 0x9264, 0x9086, + 0x9245, 0x9056 +}; + +const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { + 0x8434, 0x8334, 0x8084, 0x8267, + 0x8056, 0x8234, 0x9434, 0x9334, + 0x9084, 0x9267, 0x9056, 0x9234 +}; + static inline void assert_ntab_array_sizes(void) { #undef check diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index f6753c4b96b2..51636d02f8b1 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -131,9 +131,46 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); #define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ #define B43_NTAB_C1_LOFEEDTH_SIZE 128 +#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18 +#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18 +#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18 +#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_20_SIZE 18 +#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3 11 +#define B43_NTAB_TX_IQLO_CAL_STARTCOEFS 9 +#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3 12 +#define B43_NTAB_TX_IQLO_CAL_CMDS_RECAL 10 +#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10 +#define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 + void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); +extern const u32 b43_ntab_tx_gain_rev0_1_2[]; +extern const u32 b43_ntab_tx_gain_rev3plus_2ghz[]; +extern const u32 b43_ntab_tx_gain_rev3_5ghz[]; +extern const u32 b43_ntab_tx_gain_rev4_5ghz[]; +extern const u32 b43_ntab_tx_gain_rev5plus_5ghz[]; + +extern const u32 txpwrctrl_tx_gain_ipa[]; +extern const u32 txpwrctrl_tx_gain_ipa_rev5[]; +extern const u32 txpwrctrl_tx_gain_ipa_rev6[]; +extern const u32 txpwrctrl_tx_gain_ipa_5g[]; +extern const u16 tbl_iqcal_gainparams[2][9][8]; +extern const struct nphy_txiqcal_ladder ladder_lo[]; +extern const struct nphy_txiqcal_ladder ladder_iq[]; +extern const u16 loscale[]; + +extern const u16 tbl_tx_iqlo_cal_loft_ladder_40[]; +extern const u16 tbl_tx_iqlo_cal_loft_ladder_20[]; +extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[]; +extern const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[]; +extern const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[]; +extern const u16 tbl_tx_iqlo_cal_startcoefs[]; +extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[]; +extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; +extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; +extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; + #endif /* B43_TABLES_NPHY_H_ */ -- cgit v1.2.3 From 0988a7a1a98300e90a6613b33738e07cdf8ce786 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 13:27:29 +0100 Subject: b43: N-PHY: update init code to match current specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous init path was based on old specs from old driver. Update it as much as possible leaving some TODOs for not implemented functions. Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 201 +++++++++++++++++++++++++++++++-------- 1 file changed, 161 insertions(+), 40 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index cb784a2504a6..c16c98538f65 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -419,75 +419,196 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) //TODO } +/* + * Init N-PHY + * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N + */ int b43_phy_initn(struct b43_wldev *dev) { + struct ssb_bus *bus = dev->dev->bus; struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = phy->n; + u8 tx_pwr_state; + struct nphy_txgains target; u16 tmp; + enum ieee80211_band tmp2; + bool do_rssi_cal; + + u16 clip[2]; + bool do_cal = false; - //TODO: Spectral management + if ((dev->phy.rev >= 3) && + (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && + (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { + chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); + } + nphy->deaf_count = 0; b43_nphy_tables_init(dev); + nphy->crsminpwr_adjusted = false; + nphy->noisevars_adjusted = false; /* Clear all overrides */ - b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); + if (dev->phy.rev >= 3) { + b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); + b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); + b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); + b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); + } else { + b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); + } b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); + if (dev->phy.rev < 6) { + b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); + } b43_phy_mask(dev, B43_NPHY_RFSEQMODE, ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); + if (dev->phy.rev >= 3) + b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0); b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); - tmp = (phy->rev < 2) ? 64 : 59; - b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, - ~B43_NPHY_BPHY_CTL3_SCALE, - tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); - + if (dev->phy.rev <= 2) { + tmp = (dev->phy.rev == 2) ? 0x3B : 0x40; + b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, + ~B43_NPHY_BPHY_CTL3_SCALE, + tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); + } b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); - b43_phy_write(dev, B43_NPHY_TXREALFD, 184); - b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); - b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); - b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); + if (bus->sprom.boardflags2_lo & 0x100 || + (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && + bus->boardinfo.type == 0x8B)) + b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); + else + b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); + b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8); + b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); + b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); - //TODO MIMO-Config - //TODO Update TX/RX chain + /* TODO MIMO-Config */ + /* TODO Update TX/RX chain */ if (phy->rev < 2) { b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); } + + tmp2 = b43_current_band(dev->wl); + if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) { + b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); + b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, + nphy->papd_epsilon_offset[0] << 7); + b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); + b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, + nphy->papd_epsilon_offset[1] << 7); + /* TODO N PHY IPA Set TX Dig Filters */ + } else if (phy->rev >= 5) { + /* TODO N PHY Ext PA Set TX Dig Filters */ + } + b43_nphy_workarounds(dev); - b43_nphy_reset_cca(dev); - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); + /* Reset CCA, in init code it differs a little from standard way */ + /* b43_nphy_bmac_clock_fgc(dev, 1); */ + tmp = b43_phy_read(dev, B43_NPHY_BBCFG); + b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); + b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); + /* b43_nphy_bmac_clock_fgc(dev, 0); */ + + /* TODO N PHY MAC PHY Clock Set with argument 1 */ + + /* b43_nphy_pa_override(dev, false); */ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); + /* b43_nphy_pa_override(dev, true); */ + + /* b43_nphy_classifier(dev, 0, 0); */ + /* b43_nphy_read_clip_detection(dev, clip); */ + tx_pwr_state = nphy->txpwrctrl; + /* TODO N PHY TX power control with argument 0 + (turning off power control) */ + /* TODO Fix the TX Power Settings */ + /* TODO N PHY TX Power Control Idle TSSI */ + /* TODO N PHY TX Power Control Setup */ + + if (phy->rev >= 3) { + /* TODO */ + } else { + /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ + /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ + } - b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ - //TODO read core1/2 clip1 thres regs - - if (1 /* FIXME Band is 2.4GHz */) - b43_nphy_bphy_init(dev); - //TODO disable TX power control - //TODO Fix the TX power settings - //TODO Init periodic calibration with reason 3 - b43_nphy_rssi_cal(dev, 2); - b43_nphy_rssi_cal(dev, 0); - b43_nphy_rssi_cal(dev, 1); - //TODO get TX gain - //TODO init superswitch - //TODO calibrate LO - //TODO idle TSSI TX pctl - //TODO TX power control power setup - //TODO table writes - //TODO TX power control coefficients - //TODO enable TX power control - //TODO control antenna selection - //TODO init radar detection - //TODO reset channel if changed + if (nphy->phyrxchain != 3) + ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ + if (nphy->mphase_cal_phase_id > 0) + ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ + + do_rssi_cal = false; + if (phy->rev >= 3) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + do_rssi_cal = (nphy->rssical_chanspec_2G == 0); + else + do_rssi_cal = (nphy->rssical_chanspec_5G == 0); + + if (do_rssi_cal) + ;/* b43_nphy_rssi_cal(dev); */ + else + ;/* b43_nphy_restore_rssi_cal(dev); */ + } else { + /* b43_nphy_rssi_cal(dev); */ + } + + if (!((nphy->measure_hold & 0x6) != 0)) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + do_cal = (nphy->iqcal_chanspec_2G == 0); + else + do_cal = (nphy->iqcal_chanspec_5G == 0); + + if (nphy->mute) + do_cal = false; + + if (do_cal) { + /* target = b43_nphy_get_tx_gains(dev); */ + + if (nphy->antsel_type == 2) + ;/*TODO NPHY Superswitch Init with argument 1*/ + if (nphy->perical != 2) { + /* b43_nphy_rssi_cal(dev); */ + if (phy->rev >= 3) { + nphy->cal_orig_pwr_idx[0] = + nphy->txpwrindex[0].index_internal; + nphy->cal_orig_pwr_idx[1] = + nphy->txpwrindex[1].index_internal; + /* TODO N PHY Pre Calibrate TX Gain */ + /*target = b43_nphy_get_tx_gains(dev)*/ + } + } + } + } + + /* + if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { + if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) + Call N PHY Save Cal + else if (nphy->mphase_cal_phase_id == 0) + N PHY Periodic Calibration with argument 3 + } else { + b43_nphy_restore_cal(dev); + } + */ + + /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */ + /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ + b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); + b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); + if (phy->rev >= 3 && phy->rev <= 6) + b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); + /* b43_nphy_tx_lp_fbw(dev); */ + /* TODO N PHY Spur Workaround */ b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); return 0; -- cgit v1.2.3 From 4a933c8566da3e2b164ea74b1632bf2f43c8ee9b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 13:36:43 +0100 Subject: b43: N-PHY: update CCA reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index c16c98538f65..c9d2b7738aef 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -343,18 +343,34 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ +static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) +{ + u32 tmslow; + + if (dev->phy.type != B43_PHYTYPE_N) + return; + + tmslow = ssb_read32(dev->dev, SSB_TMSLOW); + if (force) + tmslow |= SSB_TMSLOW_FGC; + else + tmslow &= ~SSB_TMSLOW_FGC; + ssb_write32(dev->dev, SSB_TMSLOW, tmslow); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ static void b43_nphy_reset_cca(struct b43_wldev *dev) { u16 bbcfg; - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC); + b43_nphy_bmac_clock_fgc(dev, 1); bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); - b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); - b43_phy_write(dev, B43_NPHY_BBCFG, - bbcfg & ~B43_NPHY_BBCFG_RSTCCA); - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); + b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); + udelay(1); + b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); + b43_nphy_bmac_clock_fgc(dev, 0); + /* TODO: N PHY Force RF Seq with argument 2 */ } enum b43_nphy_rf_sequence { -- cgit v1.2.3 From 4cb9977516d0f52a779d12a430ccf263d35802fc Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 13:40:58 +0100 Subject: b43: N-PHY: split RSSI calibration into 2 functions (rev2, rev3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index c9d2b7738aef..30b9dacb666c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -429,10 +429,31 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); } -/* RSSI Calibration */ -static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ +static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) { - //TODO + /* TODO */ +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ +static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) +{ + /* TODO */ +} + +/* + * RSSI Calibration + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal + */ +static void b43_nphy_rssi_cal(struct b43_wldev *dev) +{ + if (dev->phy.rev >= 3) { + b43_nphy_rev3_rssi_cal(dev); + } else { + b43_nphy_rev2_rssi_cal(dev, 2); + b43_nphy_rev2_rssi_cal(dev, 0); + b43_nphy_rev2_rssi_cal(dev, 1); + } } /* @@ -571,11 +592,11 @@ int b43_phy_initn(struct b43_wldev *dev) do_rssi_cal = (nphy->rssical_chanspec_5G == 0); if (do_rssi_cal) - ;/* b43_nphy_rssi_cal(dev); */ + b43_nphy_rssi_cal(dev); else ;/* b43_nphy_restore_rssi_cal(dev); */ } else { - /* b43_nphy_rssi_cal(dev); */ + b43_nphy_rssi_cal(dev); } if (!((nphy->measure_hold & 0x6) != 0)) { -- cgit v1.2.3 From bbec398c1b7baa1dbde1e49446d1cbf4c6c20fa1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 14:31:39 +0100 Subject: b43: N-PHY: add clip detection reading/writing and some classifier function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 30b9dacb666c..72b1c410b7ff 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -28,6 +28,7 @@ #include "b43.h" #include "phy_n.h" #include "tables_nphy.h" +#include "main.h" struct nphy_txgains { u16 txgm[2]; @@ -373,6 +374,41 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev) /* TODO: N PHY Force RF Seq with argument 2 */ } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ +static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) +{ + b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); + b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ +static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) +{ + clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES); + clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ +static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) +{ + u16 tmp; + + if (dev->dev->id.revision == 16) + b43_mac_suspend(dev); + + tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); + tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN | + B43_NPHY_CLASSCTL_WAITEDEN); + tmp &= ~mask; + tmp |= (val & mask); + b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); + + if (dev->dev->id.revision == 16) + b43_mac_enable(dev); + + return tmp; +} + enum b43_nphy_rf_sequence { B43_RFSEQ_RX2TX, B43_RFSEQ_TX2RX, @@ -563,8 +599,8 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); /* b43_nphy_pa_override(dev, true); */ - /* b43_nphy_classifier(dev, 0, 0); */ - /* b43_nphy_read_clip_detection(dev, clip); */ + b43_nphy_classifier(dev, 0, 0); + b43_nphy_read_clip_detection(dev, clip); tx_pwr_state = nphy->txpwrctrl; /* TODO N PHY TX power control with argument 0 (turning off power control) */ -- cgit v1.2.3 From 3c95627d404e1094313f2dcb87424e2ae462e814 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 14:38:32 +0100 Subject: b43: N-PHY: implement RSSI selection and offset scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 121 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 72b1c410b7ff..494c95246954 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -465,6 +465,127 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev) b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ +static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, + s8 offset, u8 core, u8 rail, u8 type) +{ + u16 tmp; + bool core1or5 = (core == 1) || (core == 5); + bool core2or5 = (core == 2) || (core == 5); + + offset = clamp_val(offset, -32, 31); + tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); + + if (core1or5 && (rail == 0) && (type == 2)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); + if (core1or5 && (rail == 1) && (type == 2)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); + if (core2or5 && (rail == 0) && (type == 2)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); + if (core2or5 && (rail == 1) && (type == 2)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); + if (core1or5 && (rail == 0) && (type == 0)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); + if (core1or5 && (rail == 1) && (type == 0)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); + if (core2or5 && (rail == 0) && (type == 0)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); + if (core2or5 && (rail == 1) && (type == 0)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); + if (core1or5 && (rail == 0) && (type == 1)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); + if (core1or5 && (rail == 1) && (type == 1)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); + if (core2or5 && (rail == 0) && (type == 1)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); + if (core2or5 && (rail == 1) && (type == 1)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); + if (core1or5 && (rail == 0) && (type == 6)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); + if (core1or5 && (rail == 1) && (type == 6)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); + if (core2or5 && (rail == 0) && (type == 6)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); + if (core2or5 && (rail == 1) && (type == 6)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); + if (core1or5 && (rail == 0) && (type == 3)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); + if (core1or5 && (rail == 1) && (type == 3)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); + if (core2or5 && (rail == 0) && (type == 3)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); + if (core2or5 && (rail == 1) && (type == 3)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); + if (core1or5 && (type == 4)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); + if (core2or5 && (type == 4)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); + if (core1or5 && (type == 5)) + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); + if (core2or5 && (type == 5)) + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ +static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) +{ + u16 val; + + if (dev->phy.rev >= 3) { + /* TODO */ + } else { + if (type < 3) + val = 0; + else if (type == 6) + val = 1; + else if (type == 3) + val = 2; + else + val = 3; + + val = (val << 12) | (val << 14); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); + + if (type < 3) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, + (type + 1) << 4); + b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, + (type + 1) << 4); + } + + /* TODO use some definitions */ + if (code == 0) { + b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); + if (type < 3) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, + 0xFEC7, 0); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xEFDC, 0); + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, + 0xFFFE, 0); + udelay(20); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xFFFE, 0); + } + } else { + b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, + 0x3000); + if (type < 3) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, + 0xFEC7, 0x0180); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xEFDC, (code << 1 | 0x1021)); + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, + 0xFFFE, 0x0001); + udelay(20); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xFFFE, 0); + } + } + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) { -- cgit v1.2.3 From dfb4aa5dd0a9b61a6eaa64e9209b2f8839c0a256 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 14:45:13 +0100 Subject: b43: N-PHY: add RSSI polling and setting 2055 (radio) VCM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 494c95246954..a0e84c428e79 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -586,6 +586,102 @@ static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ +static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) +{ + int i; + for (i = 0; i < 2; i++) { + if (type == 2) { + if (i == 0) { + b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, + 0xFC, buf[0]); + b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, + 0xFC, buf[1]); + } else { + b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, + 0xFC, buf[2 * i]); + b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, + 0xFC, buf[2 * i + 1]); + } + } else { + if (i == 0) + b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, + 0xF3, buf[0] << 2); + else + b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, + 0xF3, buf[2 * i + 1] << 2); + } + } +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ +static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, + u8 nsamp) +{ + int i; + int out; + u16 save_regs_phy[9]; + u16 s[2]; + + if (dev->phy.rev >= 3) { + save_regs_phy[0] = b43_phy_read(dev, + B43_NPHY_RFCTL_LUT_TRSW_UP1); + save_regs_phy[1] = b43_phy_read(dev, + B43_NPHY_RFCTL_LUT_TRSW_UP2); + save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); + save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); + save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); + } + + b43_nphy_rssi_select(dev, 5, type); + + if (dev->phy.rev < 2) { + save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); + b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); + } + + for (i = 0; i < 4; i++) + buf[i] = 0; + + for (i = 0; i < nsamp; i++) { + if (dev->phy.rev < 2) { + s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); + s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); + } else { + s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); + s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); + } + + buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; + buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; + buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; + buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; + } + out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | + (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); + + if (dev->phy.rev < 2) + b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); + + if (dev->phy.rev >= 3) { + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, + save_regs_phy[0]); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, + save_regs_phy[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); + b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); + b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); + b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); + } + + return out; +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) { -- cgit v1.2.3 From 90b9738d85395d46ffdc961e1a0c80a17e8f4d32 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 14:48:21 +0100 Subject: b43: N-PHY: RSSI calibration for rev < 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 157 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index a0e84c428e79..126c0afa5da2 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -685,7 +685,160 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) { - /* TODO */ + int i, j; + u8 state[4]; + u8 code, val; + u16 class, override; + u8 regs_save_radio[2]; + u16 regs_save_phy[2]; + s8 offset[4]; + + u16 clip_state[2]; + u16 clip_off[2] = { 0xFFFF, 0xFFFF }; + s32 results_min[4] = { }; + u8 vcm_final[4] = { }; + s32 results[4][4] = { }; + s32 miniq[4][2] = { }; + + if (type == 2) { + code = 0; + val = 6; + } else if (type < 2) { + code = 25; + val = 4; + } else { + B43_WARN_ON(1); + return; + } + + class = b43_nphy_classifier(dev, 0, 0); + b43_nphy_classifier(dev, 7, 4); + b43_nphy_read_clip_detection(dev, clip_state); + b43_nphy_write_clip_detection(dev, clip_off); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + override = 0x140; + else + override = 0x110; + + regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); + regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); + b43_radio_write16(dev, B2055_C1_PD_RXTX, val); + + regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); + regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); + b43_radio_write16(dev, B2055_C2_PD_RXTX, val); + + state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; + state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; + b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); + b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); + state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; + state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; + + b43_nphy_rssi_select(dev, 5, type); + b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); + b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); + + for (i = 0; i < 4; i++) { + u8 tmp[4]; + for (j = 0; j < 4; j++) + tmp[j] = i; + if (type != 1) + b43_nphy_set_rssi_2055_vcm(dev, type, tmp); + b43_nphy_poll_rssi(dev, type, results[i], 8); + if (type < 2) + for (j = 0; j < 2; j++) + miniq[i][j] = min(results[i][2 * j], + results[i][2 * j + 1]); + } + + for (i = 0; i < 4; i++) { + s32 mind = 40; + u8 minvcm = 0; + s32 minpoll = 249; + s32 curr; + for (j = 0; j < 4; j++) { + if (type == 2) + curr = abs(results[j][i]); + else + curr = abs(miniq[j][i / 2] - code * 8); + + if (curr < mind) { + mind = curr; + minvcm = j; + } + + if (results[j][i] < minpoll) + minpoll = results[j][i]; + } + results_min[i] = minpoll; + vcm_final[i] = minvcm; + } + + if (type != 1) + b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); + + for (i = 0; i < 4; i++) { + offset[i] = (code * 8) - results[vcm_final[i]][i]; + + if (offset[i] < 0) + offset[i] = -((abs(offset[i]) + 4) / 8); + else + offset[i] = (offset[i] + 4) / 8; + + if (results_min[i] == 248) + offset[i] = code - 32; + + if (i % 2 == 0) + b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0, + type); + else + b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1, + type); + } + + b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); + b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]); + + switch (state[2]) { + case 1: + b43_nphy_rssi_select(dev, 1, 2); + break; + case 4: + b43_nphy_rssi_select(dev, 1, 0); + break; + case 2: + b43_nphy_rssi_select(dev, 1, 1); + break; + default: + b43_nphy_rssi_select(dev, 1, 1); + break; + } + + switch (state[3]) { + case 1: + b43_nphy_rssi_select(dev, 2, 2); + break; + case 4: + b43_nphy_rssi_select(dev, 2, 0); + break; + default: + b43_nphy_rssi_select(dev, 2, 1); + break; + } + + b43_nphy_rssi_select(dev, 0, type); + + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); + b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); + b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); + + b43_nphy_classifier(dev, 7, class); + b43_nphy_write_clip_detection(dev, clip_state); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ @@ -867,7 +1020,7 @@ int b43_phy_initn(struct b43_wldev *dev) if (nphy->antsel_type == 2) ;/*TODO NPHY Superswitch Init with argument 1*/ if (nphy->perical != 2) { - /* b43_nphy_rssi_cal(dev); */ + b43_nphy_rssi_cal(dev); if (phy->rev >= 3) { nphy->cal_orig_pwr_idx[0] = nphy->txpwrindex[0].index_internal; -- cgit v1.2.3 From e50cbcf6741684753da401722f337efacfa4a98f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:02:38 +0100 Subject: b43: N-PHY: implement PA overriding (RF control related) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 126c0afa5da2..0e379427270a 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -344,6 +344,40 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ +static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) +{ + struct b43_phy_n *nphy = dev->phy.n; + enum ieee80211_band band; + u16 tmp; + + if (!enable) { + nphy->rfctrl_intc1_save = b43_phy_read(dev, + B43_NPHY_RFCTL_INTC1); + nphy->rfctrl_intc2_save = b43_phy_read(dev, + B43_NPHY_RFCTL_INTC2); + band = b43_current_band(dev->wl); + if (dev->phy.rev >= 3) { + if (band == IEEE80211_BAND_5GHZ) + tmp = 0x600; + else + tmp = 0x480; + } else { + if (band == IEEE80211_BAND_5GHZ) + tmp = 0x180; + else + tmp = 0x120; + } + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); + } else { + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, + nphy->rfctrl_intc1_save); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, + nphy->rfctrl_intc2_save); + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) { @@ -964,10 +998,10 @@ int b43_phy_initn(struct b43_wldev *dev) /* TODO N PHY MAC PHY Clock Set with argument 1 */ - /* b43_nphy_pa_override(dev, false); */ + b43_nphy_pa_override(dev, false); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); - /* b43_nphy_pa_override(dev, true); */ + b43_nphy_pa_override(dev, true); b43_nphy_classifier(dev, 0, 0); b43_nphy_read_clip_detection(dev, clip); -- cgit v1.2.3 From 42e1547e5199ebfd41e3fb63db69dac8c4ed8d1c Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:06:47 +0100 Subject: b43: N-PHY: add RSSI calibration restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki ` Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 45 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 0e379427270a..b0ff3a3aaa7b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -896,6 +896,49 @@ static void b43_nphy_rssi_cal(struct b43_wldev *dev) } } +/* + * Restore RSSI Calibration + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal + */ +static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + u16 *rssical_radio_regs = NULL; + u16 *rssical_phy_regs = NULL; + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (!nphy->rssical_chanspec_2G) + return; + rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; + rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; + } else { + if (!nphy->rssical_chanspec_5G) + return; + rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; + rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; + } + + /* TODO use some definitions */ + b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]); + b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]); + + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); + + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); + + b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); + b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); + b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N @@ -1034,7 +1077,7 @@ int b43_phy_initn(struct b43_wldev *dev) if (do_rssi_cal) b43_nphy_rssi_cal(dev); else - ;/* b43_nphy_restore_rssi_cal(dev); */ + b43_nphy_restore_rssi_cal(dev); } else { b43_nphy_rssi_cal(dev); } -- cgit v1.2.3 From 5c1a140afbd3abeec92b74c91ad495cf69af4de3 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:10:54 +0100 Subject: b43: N-PHY: add function than forces (not) staying in carrier search MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b0ff3a3aaa7b..62ed7b7f6452 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -443,6 +443,29 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) return tmp; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ +static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) +{ + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = phy->n; + + if (enable) { + u16 clip[] = { 0xFFFF, 0xFFFF }; + if (nphy->deaf_count++ == 0) { + nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); + b43_nphy_classifier(dev, 0x7, 0); + b43_nphy_read_clip_detection(dev, nphy->clip_state); + b43_nphy_write_clip_detection(dev, clip); + } + b43_nphy_reset_cca(dev); + } else { + if (--nphy->deaf_count == 0) { + b43_nphy_classifier(dev, 0x7, nphy->classifier_state); + b43_nphy_write_clip_detection(dev, nphy->clip_state); + } + } +} + enum b43_nphy_rf_sequence { B43_RFSEQ_RX2TX, B43_RFSEQ_TX2RX, -- cgit v1.2.3 From a67162ab00d5f0d28f58a62ccd48e6a9cab07645 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:16:25 +0100 Subject: b43: N-PHY: implement RX IQ coeffs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 62ed7b7f6452..3232a465e0a5 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -408,6 +408,23 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev) /* TODO: N PHY Force RF Seq with argument 2 */ } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ +static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, + struct b43_phy_n_iq_comp *pcomp) +{ + if (write) { + b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0); + b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0); + b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1); + b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1); + } else { + pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0); + pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0); + pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1); + pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1); + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) { -- cgit v1.2.3 From 0914640072570f5867818884b8b78c0468b9747f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:17:10 +0100 Subject: b43: N-PHY: implement workaround for TX IQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3232a465e0a5..d67ba207783a 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -425,6 +425,22 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ +static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) +{ + u16 array[4]; + int i; + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50); + for (i = 0; i < 4; i++) + array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) { -- cgit v1.2.3 From 2f258b74d13c200944ef018c71ed9d9a7d4da0b0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:18:35 +0100 Subject: b43: N-PHY: implement restoring general configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki a Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d67ba207783a..68c1582db712 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -995,6 +995,96 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ +static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) +{ + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (dev->phy.rev >= 6) { + /* TODO If the chip is 47162 + return txpwrctrl_tx_gain_ipa_rev5 */ + return txpwrctrl_tx_gain_ipa_rev6; + } else if (dev->phy.rev >= 5) { + return txpwrctrl_tx_gain_ipa_rev5; + } else { + return txpwrctrl_tx_gain_ipa; + } + } else { + return txpwrctrl_tx_gain_ipa_5g; + } +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ +static void b43_nphy_restore_cal(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + u16 coef[4]; + u16 *loft = NULL; + u16 *table = NULL; + + int i; + u16 *txcal_radio_regs = NULL; + struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + if (nphy->iqcal_chanspec_2G == 0) + return; + table = nphy->cal_cache.txcal_coeffs_2G; + loft = &nphy->cal_cache.txcal_coeffs_2G[5]; + } else { + if (nphy->iqcal_chanspec_5G == 0) + return; + table = nphy->cal_cache.txcal_coeffs_5G; + loft = &nphy->cal_cache.txcal_coeffs_5G[5]; + } + + /* TODO: Write an N PHY table with ID 15, length 4, offset 80, + width 16, and data from table */ + + for (i = 0; i < 4; i++) { + if (dev->phy.rev >= 3) + table[i] = coef[i]; + else + coef[i] = 0; + } + + /* TODO: Write an N PHY table with ID 15, length 4, offset 88, + width 16, and data from coef */ + /* TODO: Write an N PHY table with ID 15, length 2, offset 85, + width 16 and data from loft */ + /* TODO: Write an N PHY table with ID 15, length 2, offset 93, + width 16 and data from loft */ + + if (dev->phy.rev < 2) + b43_nphy_tx_iq_workaround(dev); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; + rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; + } else { + txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; + rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; + } + + /* TODO use some definitions */ + if (dev->phy.rev >= 3) { + b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); + b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); + b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); + b43_radio_write(dev, 0x3022, txcal_radio_regs[3]); + b43_radio_write(dev, 0x2023, txcal_radio_regs[4]); + b43_radio_write(dev, 0x2024, txcal_radio_regs[5]); + b43_radio_write(dev, 0x3023, txcal_radio_regs[6]); + b43_radio_write(dev, 0x3024, txcal_radio_regs[7]); + } else { + b43_radio_write(dev, 0x8B, txcal_radio_regs[0]); + b43_radio_write(dev, 0xBA, txcal_radio_regs[1]); + b43_radio_write(dev, 0x8D, txcal_radio_regs[2]); + b43_radio_write(dev, 0xBC, txcal_radio_regs[3]); + } + b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N -- cgit v1.2.3 From 2faa6b832fb44b1910fe668a4ae127a69e998936 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:26:12 +0100 Subject: b43: N-PHY: implement RX IQ estimation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 68c1582db712..776d0082ef1c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -408,6 +408,45 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev) /* TODO: N PHY Force RF Seq with argument 2 */ } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ +static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, + u16 samps, u8 time, bool wait) +{ + int i; + u16 tmp; + + b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps); + b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time); + if (wait) + b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE); + else + b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE); + + b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START); + + for (i = 1000; i; i--) { + tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD); + if (!(tmp & B43_NPHY_IQEST_CMD_START)) { + est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0); + est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0); + est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0); + + est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1); + est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1); + est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) | + b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1); + return; + } + udelay(10); + } + memset(est, 0, sizeof(*est)); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, struct b43_phy_n_iq_comp *pcomp) -- cgit v1.2.3 From 34a56f2cae865224829d3fa7b8d7ddeee139191f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:29:05 +0100 Subject: b43: N-PHY: implement calculating RX IQ comp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 776d0082ef1c..d08feffdce68 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -464,6 +464,105 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ +static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) +{ + int i; + s32 iq; + u32 ii; + u32 qq; + int iq_nbits, qq_nbits; + int arsh, brsh; + u16 tmp, a, b; + + struct nphy_iq_est est; + struct b43_phy_n_iq_comp old; + struct b43_phy_n_iq_comp new = { }; + bool error = false; + + if (mask == 0) + return; + + b43_nphy_rx_iq_coeffs(dev, false, &old); + b43_nphy_rx_iq_coeffs(dev, true, &new); + b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); + new = old; + + for (i = 0; i < 2; i++) { + if (i == 0 && (mask & 1)) { + iq = est.iq0_prod; + ii = est.i0_pwr; + qq = est.q0_pwr; + } else if (i == 1 && (mask & 2)) { + iq = est.iq1_prod; + ii = est.i1_pwr; + qq = est.q1_pwr; + } else { + B43_WARN_ON(1); + continue; + } + + if (ii + qq < 2) { + error = true; + break; + } + + iq_nbits = fls(abs(iq)); + qq_nbits = fls(qq); + + arsh = iq_nbits - 20; + if (arsh >= 0) { + a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); + tmp = ii >> arsh; + } else { + a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); + tmp = ii << -arsh; + } + if (tmp == 0) { + error = true; + break; + } + a /= tmp; + + brsh = qq_nbits - 11; + if (brsh >= 0) { + b = (qq << (31 - qq_nbits)); + tmp = ii >> brsh; + } else { + b = (qq << (31 - qq_nbits)); + tmp = ii << -brsh; + } + if (tmp == 0) { + error = true; + break; + } + b = int_sqrt(b / tmp - a * a) - (1 << 10); + + if (i == 0 && (mask & 0x1)) { + if (dev->phy.rev >= 3) { + new.a0 = a & 0x3FF; + new.b0 = b & 0x3FF; + } else { + new.a0 = b & 0x3FF; + new.b0 = a & 0x3FF; + } + } else if (i == 1 && (mask & 0x2)) { + if (dev->phy.rev >= 3) { + new.a1 = a & 0x3FF; + new.b1 = b & 0x3FF; + } else { + new.a1 = b & 0x3FF; + new.b1 = a & 0x3FF; + } + } + } + + if (error) + new = old; + + b43_nphy_rx_iq_coeffs(dev, true, &new); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) { -- cgit v1.2.3 From b0022e15cc39abebd997fefa18cf3b6e141f76bd Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:40:50 +0100 Subject: b43: N-PHY: implement getting TX gains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 87 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d08feffdce68..e21526f2f24c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1151,6 +1151,89 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ +static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + u16 curr_gain[2]; + struct nphy_txgains target; + const u32 *table = NULL; + + if (nphy->txpwrctrl == 0) { + int i; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + /* TODO: Read an N PHY Table with ID 7, length 2, + offset 0x110, width 16, and curr_gain */ + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); + + for (i = 0; i < 2; ++i) { + if (dev->phy.rev >= 3) { + target.ipa[i] = curr_gain[i] & 0x000F; + target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; + target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; + target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; + } else { + target.ipa[i] = curr_gain[i] & 0x0003; + target.pad[i] = (curr_gain[i] & 0x000C) >> 2; + target.pga[i] = (curr_gain[i] & 0x0070) >> 4; + target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; + } + } + } else { + int i; + u16 index[2]; + index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) & + B43_NPHY_TXPCTL_STAT_BIDX) >> + B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; + index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) & + B43_NPHY_TXPCTL_STAT_BIDX) >> + B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; + + for (i = 0; i < 2; ++i) { + if (dev->phy.rev >= 3) { + enum ieee80211_band band = + b43_current_band(dev->wl); + + if ((nphy->ipa2g_on && + band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && + band == IEEE80211_BAND_5GHZ)) { + table = b43_nphy_get_ipa_gain_table(dev); + } else { + if (band == IEEE80211_BAND_5GHZ) { + if (dev->phy.rev == 3) + table = b43_ntab_tx_gain_rev3_5ghz; + else if (dev->phy.rev == 4) + table = b43_ntab_tx_gain_rev4_5ghz; + else + table = b43_ntab_tx_gain_rev5plus_5ghz; + } else { + table = b43_ntab_tx_gain_rev3plus_2ghz; + } + } + + target.ipa[i] = (table[index[i]] >> 16) & 0xF; + target.pad[i] = (table[index[i]] >> 20) & 0xF; + target.pga[i] = (table[index[i]] >> 24) & 0xF; + target.txgm[i] = (table[index[i]] >> 28) & 0xF; + } else { + table = b43_ntab_tx_gain_rev0_1_2; + + target.ipa[i] = (table[index[i]] >> 16) & 0x3; + target.pad[i] = (table[index[i]] >> 18) & 0x3; + target.pga[i] = (table[index[i]] >> 20) & 0x7; + target.txgm[i] = (table[index[i]] >> 23) & 0x7; + } + } + } + + return target; +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ static void b43_nphy_restore_cal(struct b43_wldev *dev) { @@ -1376,7 +1459,7 @@ int b43_phy_initn(struct b43_wldev *dev) do_cal = false; if (do_cal) { - /* target = b43_nphy_get_tx_gains(dev); */ + target = b43_nphy_get_tx_gains(dev); if (nphy->antsel_type == 2) ;/*TODO NPHY Superswitch Init with argument 1*/ @@ -1388,7 +1471,7 @@ int b43_phy_initn(struct b43_wldev *dev) nphy->cal_orig_pwr_idx[1] = nphy->txpwrindex[1].index_internal; /* TODO N PHY Pre Calibrate TX Gain */ - /*target = b43_nphy_get_tx_gains(dev)*/ + target = b43_nphy_get_tx_gains(dev); } } } -- cgit v1.2.3 From fe3e46e881daad2c7e3886e767bda90871d5f4d6 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:51:55 +0100 Subject: b43: N-PHY: add TX LP FBW (TX filter 40 related) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e21526f2f24c..242f16d489fa 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -378,6 +378,28 @@ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ +static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u16 tmp; + enum ieee80211_band band = b43_current_band(dev->wl); + bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ); + + if (dev->phy.rev >= 3) { + if (ipa) { + tmp = 4; + b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, + (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); + } + + tmp = 1; + b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2, + (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) { @@ -1494,7 +1516,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); if (phy->rev >= 3 && phy->rev <= 6) b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); - /* b43_nphy_tx_lp_fbw(dev); */ + b43_nphy_tx_lp_fbw(dev); /* TODO N PHY Spur Workaround */ b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); -- cgit v1.2.3 From c4a92003b0d02367bb1be94867a79651897e91ed Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 15:55:18 +0100 Subject: b43: N-PHY: add RX radio cores calibration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 242f16d489fa..3e587d73619e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1173,6 +1173,49 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ +static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u16 *save = nphy->tx_rx_cal_radio_saveregs; + + if (dev->phy.rev >= 3) { + /* TODO */ + } else { + save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); + b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); + + save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2); + b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54); + + save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1); + b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29); + + save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2); + b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54); + + save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX); + save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX); + + if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) & + B43_NPHY_BANDCTL_5GHZ)) { + b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04); + b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04); + } else { + b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20); + b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20); + } + + if (dev->phy.rev < 2) { + b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20); + b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20); + } else { + b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20); + b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20); + } + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) { -- cgit v1.2.3 From de7ed0c6245276eaa62523ffb36512d88bf1efb3 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:06:35 +0100 Subject: b43: N-PHY: update TX calibration ladder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3e587d73619e..d09a16f76007 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1216,6 +1216,31 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ +static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) +{ + struct b43_phy_n *nphy = dev->phy.n; + int i; + u16 scale, entry; + + u16 tmp = nphy->txcal_bbmult; + if (core == 0) + tmp >>= 8; + tmp &= 0xff; + + for (i = 0; i < 18; i++) { + scale = (ladder_lo[i].percent * tmp) / 100; + entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; + /* TODO: Write an N PHY Table with ID 15, length 1, + offset i, width 16, and data entry */ + + scale = (ladder_iq[i].percent * tmp) / 100; + entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; + /* TODO: Write an N PHY Table with ID 15, length 1, + offset i + 32, width 16, and data entry */ + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) { -- cgit v1.2.3 From e9762492f5c7176660ed030e9dd816b3208def12 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:08:25 +0100 Subject: b43: N-PHY: implement calculating IQ gain params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d09a16f76007..8a3bc2c58a81 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1216,6 +1216,44 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ +static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, + struct nphy_txgains target, + struct nphy_iqcal_params *params) +{ + int i, j, indx; + u16 gain; + + if (dev->phy.rev >= 3) { + params->txgm = target.txgm[core]; + params->pga = target.pga[core]; + params->pad = target.pad[core]; + params->ipa = target.ipa[core]; + params->cal_gain = (params->txgm << 12) | (params->pga << 8) | + (params->pad << 4) | (params->ipa); + for (j = 0; j < 5; j++) + params->ncorr[j] = 0x79; + } else { + gain = (target.pad[core]) | (target.pga[core] << 4) | + (target.txgm[core] << 8); + + indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? + 1 : 0; + for (i = 0; i < 9; i++) + if (tbl_iqcal_gainparams[indx][i][0] == gain) + break; + i = min(i, 8); + + params->txgm = tbl_iqcal_gainparams[indx][i][1]; + params->pga = tbl_iqcal_gainparams[indx][i][2]; + params->pad = tbl_iqcal_gainparams[indx][i][3]; + params->cal_gain = (params->txgm << 7) | (params->pga << 4) | + (params->pad << 2); + for (j = 0; j < 4; j++) + params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) { -- cgit v1.2.3 From fb43b8e23519f853f142202bb341c21382f39070 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:10:48 +0100 Subject: b43: N-PHY: add huge calculating TX IQ LO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 226 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8a3bc2c58a81..4111a4626001 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1434,6 +1434,232 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ +static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, + struct nphy_txgains target, + bool full, bool mphase) +{ + struct b43_phy_n *nphy = dev->phy.n; + int i; + int error = 0; + int freq; + bool avoid = false; + u8 length; + u16 tmp, core, type, count, max, numb, last, cmd; + const u16 *table; + bool phy6or5x; + + u16 buffer[11]; + u16 diq_start = 0; + u16 save[2]; + u16 gain[2]; + struct nphy_iqcal_params params[2]; + bool updated[2] = { }; + + b43_nphy_stay_in_carrier_search(dev, true); + + if (dev->phy.rev >= 4) { + avoid = nphy->hang_avoid; + nphy->hang_avoid = 0; + } + + /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data pointer save */ + + for (i = 0; i < 2; i++) { + b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); + gain[i] = params[i].cal_gain; + } + /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data pointer gain */ + + b43_nphy_tx_cal_radio_setup(dev); + /* TODO: Call N PHY TX Cal PHY Setup */ + + phy6or5x = dev->phy.rev >= 6 || + (dev->phy.rev == 5 && nphy->ipa2g_on && + b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); + if (phy6or5x) { + /* TODO */ + } + + b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); + + if (1 /* FIXME: the band width is 20 MHz */) + freq = 2500; + else + freq = 5000; + + if (nphy->mphase_cal_phase_id > 2) + ;/* TODO: Call N PHY Run Samples with (band width * 8), + 0xFFFF, 0, 1, 0 as arguments */ + else + ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments + and save result as error */ + + if (error == 0) { + if (nphy->mphase_cal_phase_id > 2) { + table = nphy->mphase_txcal_bestcoeffs; + length = 11; + if (dev->phy.rev < 3) + length -= 2; + } else { + if (!full && nphy->txiqlocal_coeffsvalid) { + table = nphy->txiqlocal_bestc; + length = 11; + if (dev->phy.rev < 3) + length -= 2; + } else { + full = true; + if (dev->phy.rev >= 3) { + table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; + length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; + } else { + table = tbl_tx_iqlo_cal_startcoefs; + length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS; + } + } + } + + /* TODO: Write an N PHY Table with ID 15, length from above, + offset 64, width 16, and the data pointer from above */ + + if (full) { + if (dev->phy.rev >= 3) + max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; + else + max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; + } else { + if (dev->phy.rev >= 3) + max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; + else + max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL; + } + + if (mphase) { + count = nphy->mphase_txcal_cmdidx; + numb = min(max, + (u16)(count + nphy->mphase_txcal_numcmds)); + } else { + count = 0; + numb = max; + } + + for (; count < numb; count++) { + if (full) { + if (dev->phy.rev >= 3) + cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; + else + cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; + } else { + if (dev->phy.rev >= 3) + cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; + else + cmd = tbl_tx_iqlo_cal_cmds_recal[count]; + } + + core = (cmd & 0x3000) >> 12; + type = (cmd & 0x0F00) >> 8; + + if (phy6or5x && updated[core] == 0) { + b43_nphy_update_tx_cal_ladder(dev, core); + updated[core] = 1; + } + + tmp = (params[core].ncorr[type] << 8) | 0x66; + b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); + + if (type == 1 || type == 3 || type == 4) { + /* TODO: Read an N PHY Table with ID 15, + length 1, offset 69 + core, + width 16, and data pointer buffer */ + diq_start = buffer[0]; + buffer[0] = 0; + /* TODO: Write an N PHY Table with ID 15, + length 1, offset 69 + core, width 16, + and data of 0 */ + } + + b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); + for (i = 0; i < 2000; i++) { + tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD); + if (tmp & 0xC000) + break; + udelay(10); + } + + /* TODO: Read an N PHY Table with ID 15, + length table_length, offset 96, width 16, + and data pointer buffer */ + /* TODO: Write an N PHY Table with ID 15, + length table_length, offset 64, width 16, + and data pointer buffer */ + + if (type == 1 || type == 3 || type == 4) + buffer[0] = diq_start; + } + + if (mphase) + nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; + + last = (dev->phy.rev < 3) ? 6 : 7; + + if (!mphase || nphy->mphase_cal_phase_id == last) { + /* TODO: Write an N PHY Table with ID 15, length 4, + offset 96, width 16, and data pointer buffer */ + /* TODO: Read an N PHY Table with ID 15, length 4, + offset 80, width 16, and data pointer buffer */ + if (dev->phy.rev < 3) { + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + buffer[3] = 0; + } + /* TODO: Write an N PHY Table with ID 15, length 4, + offset 88, width 16, and data pointer buffer */ + /* TODO: Read an N PHY Table with ID 15, length 2, + offset 101, width 16, and data pointer buffer*/ + /* TODO: Write an N PHY Table with ID 15, length 2, + offset 85, width 16, and data pointer buffer */ + /* TODO: Write an N PHY Table with ID 15, length 2, + offset 93, width 16, and data pointer buffer */ + length = 11; + if (dev->phy.rev < 3) + length -= 2; + /* TODO: Read an N PHY Table with ID 15, length length, + offset 96, width 16, and data pointer + nphy->txiqlocal_bestc */ + nphy->txiqlocal_coeffsvalid = true; + /* TODO: Set nphy->txiqlocal_chanspec to + the current channel */ + } else { + length = 11; + if (dev->phy.rev < 3) + length -= 2; + /* TODO: Read an N PHY Table with ID 5, length length, + offset 96, width 16, and data pointer + nphy->mphase_txcal_bestcoeffs */ + } + + /* TODO: Call N PHY Stop Playback */ + b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); + } + + /* TODO: Call N PHY TX Cal PHY Cleanup */ + /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data from save */ + + if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) + b43_nphy_tx_iq_workaround(dev); + + if (dev->phy.rev >= 4) + nphy->hang_avoid = avoid; + + b43_nphy_stay_in_carrier_search(dev, false); + + return error; +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N -- cgit v1.2.3 From 15931e318b27e85ea06f44d53abc3d3e6a3fc9ff Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:20:56 +0100 Subject: b43: N-PHY: add RX IQ calibrationi for rev < 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 206 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 4111a4626001..f982f56d5bf3 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1660,6 +1660,206 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, return error; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ +static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, + struct nphy_txgains target, u8 type, bool debug) +{ + struct b43_phy_n *nphy = dev->phy.n; + int i, j, index; + u8 rfctl[2]; + u8 afectl_core; + u16 tmp[6]; + u16 cur_hpf1, cur_hpf2, cur_lna; + u32 real, imag; + enum ieee80211_band band; + + u8 use; + u16 cur_hpf; + u16 lna[3] = { 3, 3, 1 }; + u16 hpf1[3] = { 7, 2, 0 }; + u16 hpf2[3] = { 2, 0, 0 }; + u32 power[3]; + u16 gain_save[2]; + u16 cal_gain[2]; + struct nphy_iqcal_params cal_params[2]; + struct nphy_iq_est est; + int ret = 0; + bool playtone = true; + int desired = 13; + + b43_nphy_stay_in_carrier_search(dev, 1); + + if (dev->phy.rev < 2) + ;/* TODO: Call N PHY Reapply TX Cal Coeffs */ + /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data gain_save */ + for (i = 0; i < 2; i++) { + b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); + cal_gain[i] = cal_params[i].cal_gain; + } + /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data from cal_gain */ + + for (i = 0; i < 2; i++) { + if (i == 0) { + rfctl[0] = B43_NPHY_RFCTL_INTC1; + rfctl[1] = B43_NPHY_RFCTL_INTC2; + afectl_core = B43_NPHY_AFECTL_C1; + } else { + rfctl[0] = B43_NPHY_RFCTL_INTC2; + rfctl[1] = B43_NPHY_RFCTL_INTC1; + afectl_core = B43_NPHY_AFECTL_C2; + } + + tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA); + tmp[2] = b43_phy_read(dev, afectl_core); + tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + tmp[4] = b43_phy_read(dev, rfctl[0]); + tmp[5] = b43_phy_read(dev, rfctl[1]); + + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, + (u16)~B43_NPHY_RFSEQCA_RXDIS, + ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, + (1 - i)); + b43_phy_set(dev, afectl_core, 0x0006); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006); + + band = b43_current_band(dev->wl); + + if (nphy->rxcalparams & 0xFF000000) { + if (band == IEEE80211_BAND_5GHZ) + b43_phy_write(dev, rfctl[0], 0x140); + else + b43_phy_write(dev, rfctl[0], 0x110); + } else { + if (band == IEEE80211_BAND_5GHZ) + b43_phy_write(dev, rfctl[0], 0x180); + else + b43_phy_write(dev, rfctl[0], 0x120); + } + + if (band == IEEE80211_BAND_5GHZ) + b43_phy_write(dev, rfctl[1], 0x148); + else + b43_phy_write(dev, rfctl[1], 0x114); + + if (nphy->rxcalparams & 0x10000) { + b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC, + (i + 1)); + b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC, + (2 - i)); + } + + for (j = 0; i < 4; j++) { + if (j < 3) { + cur_lna = lna[j]; + cur_hpf1 = hpf1[j]; + cur_hpf2 = hpf2[j]; + } else { + if (power[1] > 10000) { + use = 1; + cur_hpf = cur_hpf1; + index = 2; + } else { + if (power[0] > 10000) { + use = 1; + cur_hpf = cur_hpf1; + index = 1; + } else { + index = 0; + use = 2; + cur_hpf = cur_hpf2; + } + } + cur_lna = lna[index]; + cur_hpf1 = hpf1[index]; + cur_hpf2 = hpf2[index]; + cur_hpf += desired - hweight32(power[index]); + cur_hpf = clamp_val(cur_hpf, 0, 10); + if (use == 1) + cur_hpf1 = cur_hpf; + else + cur_hpf2 = cur_hpf; + } + + tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | + (cur_lna << 2)); + /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], + 3, 0 as arguments */ + /* TODO: Call N PHY Force RF Seq with 2 as argument */ + /* TODO: Call N PHT Stop Playback */ + + if (playtone) { + /* TODO: Call N PHY TX Tone with 4000, + (nphy_rxcalparams & 0xffff), 0, 0 + as arguments and save result as ret */ + playtone = false; + } else { + /* TODO: Call N PHY Run Samples with 160, + 0xFFFF, 0, 0, 0 as arguments */ + } + + if (ret == 0) { + if (j < 3) { + b43_nphy_rx_iq_est(dev, &est, 1024, 32, + false); + if (i == 0) { + real = est.i0_pwr; + imag = est.q0_pwr; + } else { + real = est.i1_pwr; + imag = est.q1_pwr; + } + power[i] = ((real + imag) / 1024) + 1; + } else { + b43_nphy_calc_rx_iq_comp(dev, 1 << i); + } + /* TODO: Call N PHY Stop Playback */ + } + + if (ret != 0) + break; + } + + b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC); + b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC); + b43_phy_write(dev, rfctl[1], tmp[5]); + b43_phy_write(dev, rfctl[0], tmp[4]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]); + b43_phy_write(dev, afectl_core, tmp[2]); + b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]); + + if (ret != 0) + break; + } + + /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ + /* TODO: Call N PHY Force RF Seq with 2 as argument */ + /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, + width 16, and data from gain_save */ + + b43_nphy_stay_in_carrier_search(dev, 0); + + return ret; +} + +static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, + struct nphy_txgains target, u8 type, bool debug) +{ + return -1; +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ +static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, + struct nphy_txgains target, u8 type, bool debug) +{ + if (dev->phy.rev >= 3) + return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); + else + return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); +} + /* * Init N-PHY * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N @@ -1831,16 +2031,14 @@ int b43_phy_initn(struct b43_wldev *dev) } } - /* if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) - Call N PHY Save Cal + ;/* Call N PHY Save Cal */ else if (nphy->mphase_cal_phase_id == 0) - N PHY Periodic Calibration with argument 3 + ;/* N PHY Periodic Calibration with argument 3 */ } else { b43_nphy_restore_cal(dev); } - */ /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */ /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ -- cgit v1.2.3 From 6dcd9d911cace479ff5612dab3896c8fceb60773 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:24:57 +0100 Subject: b43: N-PHY: implement TX power control coef setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 69 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index f982f56d5bf3..a0e8283519fd 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -659,6 +659,73 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ +static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + int i, j; + u32 tmp; + u32 cur_real, cur_imag, real_part, imag_part; + + u16 buffer[7]; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + + /* TODO: Read an N PHY Table with ID 15, length 7, offset 80, + width 16, and data pointer buffer */ + + for (i = 0; i < 2; i++) { + tmp = ((buffer[i * 2] & 0x3FF) << 10) | + (buffer[i * 2 + 1] & 0x3FF); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, + (((i + 26) << 10) | 320)); + for (j = 0; j < 128; j++) { + b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, + ((tmp >> 16) & 0xFFFF)); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (tmp & 0xFFFF)); + } + } + + for (i = 0; i < 2; i++) { + tmp = buffer[5 + i]; + real_part = (tmp >> 8) & 0xFF; + imag_part = (tmp & 0xFF); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, + (((i + 26) << 10) | 448)); + + if (dev->phy.rev >= 3) { + cur_real = real_part; + cur_imag = imag_part; + tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); + } + + for (j = 0; j < 128; j++) { + if (dev->phy.rev < 3) { + cur_real = (real_part * loscale[j] + 128) >> 8; + cur_imag = (imag_part * loscale[j] + 128) >> 8; + tmp = ((cur_real & 0xFF) << 8) | + (cur_imag & 0xFF); + } + b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, + ((tmp >> 16) & 0xFFFF)); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (tmp & 0xFFFF)); + } + } + + if (dev->phy.rev >= 3) { + b43_shm_write16(dev, B43_SHM_SHARED, + B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); + b43_shm_write16(dev, B43_SHM_SHARED, + B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); +} + enum b43_nphy_rf_sequence { B43_RFSEQ_RX2TX, B43_RFSEQ_TX2RX, @@ -2040,7 +2107,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_restore_cal(dev); } - /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */ + b43_nphy_tx_pwr_ctrl_coef_setup(dev); /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); -- cgit v1.2.3 From 730dd70549e0ec755dd55615ba5cfc38a482a947 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 15 Jan 2010 16:38:07 +0100 Subject: b43: N-PHY: drop unused definition, uncomment needed call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index a0e8283519fd..4a817e3da163 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -222,12 +222,6 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev) ~B43_NPHY_RFCTL_CMD_EN); } -#define ntab_upload(dev, offset, data) do { \ - unsigned int i; \ - for (i = 0; i < (offset##_SIZE); i++) \ - b43_ntab_write(dev, (offset) + i, (data)[i]); \ - } while (0) - /* * Upload the N-PHY tables. * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables @@ -2021,11 +2015,11 @@ int b43_phy_initn(struct b43_wldev *dev) b43_nphy_workarounds(dev); /* Reset CCA, in init code it differs a little from standard way */ - /* b43_nphy_bmac_clock_fgc(dev, 1); */ + b43_nphy_bmac_clock_fgc(dev, 1); tmp = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); - /* b43_nphy_bmac_clock_fgc(dev, 0); */ + b43_nphy_bmac_clock_fgc(dev, 0); /* TODO N PHY MAC PHY Clock Set with argument 1 */ -- cgit v1.2.3 From b87babeb40aaf879d20268792390ce831805a557 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:27 +0000 Subject: qlge: Add data for firmware dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 403 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 398 insertions(+), 5 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index ee0e2bd4842f..a265325abb15 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -75,15 +75,43 @@ #define TX_DESC_PER_OAL 0 #endif +/* Word shifting for converting 64-bit + * address to a series of 16-bit words. + * This is used for some MPI firmware + * mailbox commands. + */ +#define LSW(x) ((u16)(x)) +#define MSW(x) ((u16)((u32)(x) >> 16)) +#define LSD(x) ((u32)((u64)(x))) +#define MSD(x) ((u32)((((u64)(x)) >> 32))) + /* MPI test register definitions. This register * is used for determining alternate NIC function's * PCI->func number. */ enum { MPI_TEST_FUNC_PORT_CFG = 0x1002, + MPI_TEST_FUNC_PRB_CTL = 0x100e, + MPI_TEST_FUNC_PRB_EN = 0x18a20000, + MPI_TEST_FUNC_RST_STS = 0x100a, + MPI_TEST_FUNC_RST_FRC = 0x00000003, + MPI_TEST_NIC_FUNC_MASK = 0x00000007, + MPI_TEST_NIC1_FUNCTION_ENABLE = (1 << 0), + MPI_TEST_NIC1_FUNCTION_MASK = 0x0000000e, MPI_TEST_NIC1_FUNC_SHIFT = 1, + MPI_TEST_NIC2_FUNCTION_ENABLE = (1 << 4), + MPI_TEST_NIC2_FUNCTION_MASK = 0x000000e0, MPI_TEST_NIC2_FUNC_SHIFT = 5, - MPI_TEST_NIC_FUNC_MASK = 0x00000007, + MPI_TEST_FC1_FUNCTION_ENABLE = (1 << 8), + MPI_TEST_FC1_FUNCTION_MASK = 0x00000e00, + MPI_TEST_FC1_FUNCTION_SHIFT = 9, + MPI_TEST_FC2_FUNCTION_ENABLE = (1 << 12), + MPI_TEST_FC2_FUNCTION_MASK = 0x0000e000, + MPI_TEST_FC2_FUNCTION_SHIFT = 13, + + MPI_NIC_READ = 0x00000000, + MPI_NIC_REG_BLOCK = 0x00020000, + MPI_NIC_FUNCTION_SHIFT = 6, }; /* @@ -464,7 +492,7 @@ enum { MDIO_PORT = 0x00000440, MDIO_STATUS = 0x00000450, - /* XGMAC AUX statistics registers */ + XGMAC_REGISTER_END = 0x00000740, }; /* @@ -505,6 +533,7 @@ enum { enum { MAC_ADDR_IDX_SHIFT = 4, MAC_ADDR_TYPE_SHIFT = 16, + MAC_ADDR_TYPE_COUNT = 10, MAC_ADDR_TYPE_MASK = 0x000f0000, MAC_ADDR_TYPE_CAM_MAC = 0x00000000, MAC_ADDR_TYPE_MULTI_MAC = 0x00010000, @@ -522,6 +551,30 @@ enum { MAC_ADDR_MR = (1 << 30), MAC_ADDR_MW = (1 << 31), MAX_MULTICAST_ENTRIES = 32, + + /* Entry count and words per entry + * for each address type in the filter. + */ + MAC_ADDR_MAX_CAM_ENTRIES = 512, + MAC_ADDR_MAX_CAM_WCOUNT = 3, + MAC_ADDR_MAX_MULTICAST_ENTRIES = 32, + MAC_ADDR_MAX_MULTICAST_WCOUNT = 2, + MAC_ADDR_MAX_VLAN_ENTRIES = 4096, + MAC_ADDR_MAX_VLAN_WCOUNT = 1, + MAC_ADDR_MAX_MCAST_FLTR_ENTRIES = 4096, + MAC_ADDR_MAX_MCAST_FLTR_WCOUNT = 1, + MAC_ADDR_MAX_FC_MAC_ENTRIES = 4, + MAC_ADDR_MAX_FC_MAC_WCOUNT = 2, + MAC_ADDR_MAX_MGMT_MAC_ENTRIES = 8, + MAC_ADDR_MAX_MGMT_MAC_WCOUNT = 2, + MAC_ADDR_MAX_MGMT_VLAN_ENTRIES = 16, + MAC_ADDR_MAX_MGMT_VLAN_WCOUNT = 1, + MAC_ADDR_MAX_MGMT_V4_ENTRIES = 4, + MAC_ADDR_MAX_MGMT_V4_WCOUNT = 1, + MAC_ADDR_MAX_MGMT_V6_ENTRIES = 4, + MAC_ADDR_MAX_MGMT_V6_WCOUNT = 4, + MAC_ADDR_MAX_MGMT_TU_DP_ENTRIES = 4, + MAC_ADDR_MAX_MGMT_TU_DP_WCOUNT = 1, }; /* @@ -592,6 +645,7 @@ enum { enum { RT_IDX_IDX_SHIFT = 8, RT_IDX_TYPE_MASK = 0x000f0000, + RT_IDX_TYPE_SHIFT = 16, RT_IDX_TYPE_RT = 0x00000000, RT_IDX_TYPE_RT_INV = 0x00010000, RT_IDX_TYPE_NICQ = 0x00020000, @@ -660,7 +714,89 @@ enum { RT_IDX_UNUSED013 = 13, RT_IDX_UNUSED014 = 14, RT_IDX_PROMISCUOUS_SLOT = 15, - RT_IDX_MAX_SLOTS = 16, + RT_IDX_MAX_RT_SLOTS = 8, + RT_IDX_MAX_NIC_SLOTS = 16, +}; + +/* + * Serdes Address Register (XG_SERDES_ADDR) bit definitions. + */ +enum { + XG_SERDES_ADDR_RDY = (1 << 31), + XG_SERDES_ADDR_R = (1 << 30), + + XG_SERDES_ADDR_STS = 0x00001E06, + XG_SERDES_ADDR_XFI1_PWR_UP = 0x00000005, + XG_SERDES_ADDR_XFI2_PWR_UP = 0x0000000a, + XG_SERDES_ADDR_XAUI_PWR_DOWN = 0x00000001, + + /* Serdes coredump definitions. */ + XG_SERDES_XAUI_AN_START = 0x00000000, + XG_SERDES_XAUI_AN_END = 0x00000034, + XG_SERDES_XAUI_HSS_PCS_START = 0x00000800, + XG_SERDES_XAUI_HSS_PCS_END = 0x0000880, + XG_SERDES_XFI_AN_START = 0x00001000, + XG_SERDES_XFI_AN_END = 0x00001034, + XG_SERDES_XFI_TRAIN_START = 0x10001050, + XG_SERDES_XFI_TRAIN_END = 0x1000107C, + XG_SERDES_XFI_HSS_PCS_START = 0x00001800, + XG_SERDES_XFI_HSS_PCS_END = 0x00001838, + XG_SERDES_XFI_HSS_TX_START = 0x00001c00, + XG_SERDES_XFI_HSS_TX_END = 0x00001c1f, + XG_SERDES_XFI_HSS_RX_START = 0x00001c40, + XG_SERDES_XFI_HSS_RX_END = 0x00001c5f, + XG_SERDES_XFI_HSS_PLL_START = 0x00001e00, + XG_SERDES_XFI_HSS_PLL_END = 0x00001e1f, +}; + +/* + * NIC Probe Mux Address Register (PRB_MX_ADDR) bit definitions. + */ +enum { + PRB_MX_ADDR_ARE = (1 << 16), + PRB_MX_ADDR_UP = (1 << 15), + PRB_MX_ADDR_SWP = (1 << 14), + + /* Module select values. */ + PRB_MX_ADDR_MAX_MODS = 21, + PRB_MX_ADDR_MOD_SEL_SHIFT = 9, + PRB_MX_ADDR_MOD_SEL_TBD = 0, + PRB_MX_ADDR_MOD_SEL_IDE1 = 1, + PRB_MX_ADDR_MOD_SEL_IDE2 = 2, + PRB_MX_ADDR_MOD_SEL_FRB = 3, + PRB_MX_ADDR_MOD_SEL_ODE1 = 4, + PRB_MX_ADDR_MOD_SEL_ODE2 = 5, + PRB_MX_ADDR_MOD_SEL_DA1 = 6, + PRB_MX_ADDR_MOD_SEL_DA2 = 7, + PRB_MX_ADDR_MOD_SEL_IMP1 = 8, + PRB_MX_ADDR_MOD_SEL_IMP2 = 9, + PRB_MX_ADDR_MOD_SEL_OMP1 = 10, + PRB_MX_ADDR_MOD_SEL_OMP2 = 11, + PRB_MX_ADDR_MOD_SEL_ORS1 = 12, + PRB_MX_ADDR_MOD_SEL_ORS2 = 13, + PRB_MX_ADDR_MOD_SEL_REG = 14, + PRB_MX_ADDR_MOD_SEL_MAC1 = 16, + PRB_MX_ADDR_MOD_SEL_MAC2 = 17, + PRB_MX_ADDR_MOD_SEL_VQM1 = 18, + PRB_MX_ADDR_MOD_SEL_VQM2 = 19, + PRB_MX_ADDR_MOD_SEL_MOP = 20, + /* Bit fields indicating which modules + * are valid for each clock domain. + */ + PRB_MX_ADDR_VALID_SYS_MOD = 0x000f7ff7, + PRB_MX_ADDR_VALID_PCI_MOD = 0x000040c1, + PRB_MX_ADDR_VALID_XGM_MOD = 0x00037309, + PRB_MX_ADDR_VALID_FC_MOD = 0x00003001, + PRB_MX_ADDR_VALID_TOTAL = 34, + + /* Clock domain values. */ + PRB_MX_ADDR_CLOCK_SHIFT = 6, + PRB_MX_ADDR_SYS_CLOCK = 0, + PRB_MX_ADDR_PCI_CLOCK = 2, + PRB_MX_ADDR_FC_CLOCK = 5, + PRB_MX_ADDR_XGM_CLOCK = 6, + + PRB_MX_ADDR_MAX_MUX = 64, }; /* @@ -1432,7 +1568,7 @@ struct nic_stats { u64 rx_nic_fifo_drop; }; -/* Address/Length pairs for the coredump. */ +/* Firmware coredump internal register address/length pairs. */ enum { MPI_CORE_REGS_ADDR = 0x00030000, MPI_CORE_REGS_CNT = 127, @@ -1487,7 +1623,7 @@ struct mpi_coredump_segment_header { u8 description[16]; }; -/* Reg dump segment numbers. */ +/* Firmware coredump header segment numbers. */ enum { CORE_SEG_NUM = 1, TEST_LOGIC_SEG_NUM = 2, @@ -1538,6 +1674,67 @@ enum { }; +/* There are 64 generic NIC registers. */ +#define NIC_REGS_DUMP_WORD_COUNT 64 +/* XGMAC word count. */ +#define XGMAC_DUMP_WORD_COUNT (XGMAC_REGISTER_END / 4) +/* Word counts for the SERDES blocks. */ +#define XG_SERDES_XAUI_AN_COUNT 14 +#define XG_SERDES_XAUI_HSS_PCS_COUNT 33 +#define XG_SERDES_XFI_AN_COUNT 14 +#define XG_SERDES_XFI_TRAIN_COUNT 12 +#define XG_SERDES_XFI_HSS_PCS_COUNT 15 +#define XG_SERDES_XFI_HSS_TX_COUNT 32 +#define XG_SERDES_XFI_HSS_RX_COUNT 32 +#define XG_SERDES_XFI_HSS_PLL_COUNT 32 + +/* There are 2 CNA ETS and 8 NIC ETS registers. */ +#define ETS_REGS_DUMP_WORD_COUNT 10 + +/* Each probe mux entry stores the probe type plus 64 entries + * that are each each 64-bits in length. There are a total of + * 34 (PRB_MX_ADDR_VALID_TOTAL) valid probes. + */ +#define PRB_MX_ADDR_PRB_WORD_COUNT (1 + (PRB_MX_ADDR_MAX_MUX * 2)) +#define PRB_MX_DUMP_TOT_COUNT (PRB_MX_ADDR_PRB_WORD_COUNT * \ + PRB_MX_ADDR_VALID_TOTAL) +/* Each routing entry consists of 4 32-bit words. + * They are route type, index, index word, and result. + * There are 2 route blocks with 8 entries each and + * 2 NIC blocks with 16 entries each. + * The totol entries is 48 with 4 words each. + */ +#define RT_IDX_DUMP_ENTRIES 48 +#define RT_IDX_DUMP_WORDS_PER_ENTRY 4 +#define RT_IDX_DUMP_TOT_WORDS (RT_IDX_DUMP_ENTRIES * \ + RT_IDX_DUMP_WORDS_PER_ENTRY) +/* There are 10 address blocks in filter, each with + * different entry counts and different word-count-per-entry. + */ +#define MAC_ADDR_DUMP_ENTRIES \ + ((MAC_ADDR_MAX_CAM_ENTRIES * MAC_ADDR_MAX_CAM_WCOUNT) + \ + (MAC_ADDR_MAX_MULTICAST_ENTRIES * MAC_ADDR_MAX_MULTICAST_WCOUNT) + \ + (MAC_ADDR_MAX_VLAN_ENTRIES * MAC_ADDR_MAX_VLAN_WCOUNT) + \ + (MAC_ADDR_MAX_MCAST_FLTR_ENTRIES * MAC_ADDR_MAX_MCAST_FLTR_WCOUNT) + \ + (MAC_ADDR_MAX_FC_MAC_ENTRIES * MAC_ADDR_MAX_FC_MAC_WCOUNT) + \ + (MAC_ADDR_MAX_MGMT_MAC_ENTRIES * MAC_ADDR_MAX_MGMT_MAC_WCOUNT) + \ + (MAC_ADDR_MAX_MGMT_VLAN_ENTRIES * MAC_ADDR_MAX_MGMT_VLAN_WCOUNT) + \ + (MAC_ADDR_MAX_MGMT_V4_ENTRIES * MAC_ADDR_MAX_MGMT_V4_WCOUNT) + \ + (MAC_ADDR_MAX_MGMT_V6_ENTRIES * MAC_ADDR_MAX_MGMT_V6_WCOUNT) + \ + (MAC_ADDR_MAX_MGMT_TU_DP_ENTRIES * MAC_ADDR_MAX_MGMT_TU_DP_WCOUNT)) +#define MAC_ADDR_DUMP_WORDS_PER_ENTRY 2 +#define MAC_ADDR_DUMP_TOT_WORDS (MAC_ADDR_DUMP_ENTRIES * \ + MAC_ADDR_DUMP_WORDS_PER_ENTRY) +/* Maximum of 4 functions whose semaphore registeres are + * in the coredump. + */ +#define MAX_SEMAPHORE_FUNCTIONS 4 +/* Defines for access the MPI shadow registers. */ +#define RISC_124 0x0003007c +#define RISC_127 0x0003007f +#define SHADOW_OFFSET 0xb0000000 +#define SHADOW_REG_SHIFT 20 + struct ql_nic_misc { u32 rx_ring_count; u32 tx_ring_count; @@ -1579,6 +1776,199 @@ struct ql_reg_dump { u32 ets[8+2]; }; +struct ql_mpi_coredump { + /* segment 0 */ + struct mpi_coredump_global_header mpi_global_header; + + /* segment 1 */ + struct mpi_coredump_segment_header core_regs_seg_hdr; + u32 mpi_core_regs[MPI_CORE_REGS_CNT]; + u32 mpi_core_sh_regs[MPI_CORE_SH_REGS_CNT]; + + /* segment 2 */ + struct mpi_coredump_segment_header test_logic_regs_seg_hdr; + u32 test_logic_regs[TEST_REGS_CNT]; + + /* segment 3 */ + struct mpi_coredump_segment_header rmii_regs_seg_hdr; + u32 rmii_regs[RMII_REGS_CNT]; + + /* segment 4 */ + struct mpi_coredump_segment_header fcmac1_regs_seg_hdr; + u32 fcmac1_regs[FCMAC_REGS_CNT]; + + /* segment 5 */ + struct mpi_coredump_segment_header fcmac2_regs_seg_hdr; + u32 fcmac2_regs[FCMAC_REGS_CNT]; + + /* segment 6 */ + struct mpi_coredump_segment_header fc1_mbx_regs_seg_hdr; + u32 fc1_mbx_regs[FC_MBX_REGS_CNT]; + + /* segment 7 */ + struct mpi_coredump_segment_header ide_regs_seg_hdr; + u32 ide_regs[IDE_REGS_CNT]; + + /* segment 8 */ + struct mpi_coredump_segment_header nic1_mbx_regs_seg_hdr; + u32 nic1_mbx_regs[NIC_MBX_REGS_CNT]; + + /* segment 9 */ + struct mpi_coredump_segment_header smbus_regs_seg_hdr; + u32 smbus_regs[SMBUS_REGS_CNT]; + + /* segment 10 */ + struct mpi_coredump_segment_header fc2_mbx_regs_seg_hdr; + u32 fc2_mbx_regs[FC_MBX_REGS_CNT]; + + /* segment 11 */ + struct mpi_coredump_segment_header nic2_mbx_regs_seg_hdr; + u32 nic2_mbx_regs[NIC_MBX_REGS_CNT]; + + /* segment 12 */ + struct mpi_coredump_segment_header i2c_regs_seg_hdr; + u32 i2c_regs[I2C_REGS_CNT]; + /* segment 13 */ + struct mpi_coredump_segment_header memc_regs_seg_hdr; + u32 memc_regs[MEMC_REGS_CNT]; + + /* segment 14 */ + struct mpi_coredump_segment_header pbus_regs_seg_hdr; + u32 pbus_regs[PBUS_REGS_CNT]; + + /* segment 15 */ + struct mpi_coredump_segment_header mde_regs_seg_hdr; + u32 mde_regs[MDE_REGS_CNT]; + + /* segment 16 */ + struct mpi_coredump_segment_header nic_regs_seg_hdr; + u32 nic_regs[NIC_REGS_DUMP_WORD_COUNT]; + + /* segment 17 */ + struct mpi_coredump_segment_header nic2_regs_seg_hdr; + u32 nic2_regs[NIC_REGS_DUMP_WORD_COUNT]; + + /* segment 18 */ + struct mpi_coredump_segment_header xgmac1_seg_hdr; + u32 xgmac1[XGMAC_DUMP_WORD_COUNT]; + + /* segment 19 */ + struct mpi_coredump_segment_header xgmac2_seg_hdr; + u32 xgmac2[XGMAC_DUMP_WORD_COUNT]; + + /* segment 20 */ + struct mpi_coredump_segment_header code_ram_seg_hdr; + u32 code_ram[CODE_RAM_CNT]; + + /* segment 21 */ + struct mpi_coredump_segment_header memc_ram_seg_hdr; + u32 memc_ram[MEMC_RAM_CNT]; + + /* segment 22 */ + struct mpi_coredump_segment_header xaui_an_hdr; + u32 serdes_xaui_an[XG_SERDES_XAUI_AN_COUNT]; + + /* segment 23 */ + struct mpi_coredump_segment_header xaui_hss_pcs_hdr; + u32 serdes_xaui_hss_pcs[XG_SERDES_XAUI_HSS_PCS_COUNT]; + + /* segment 24 */ + struct mpi_coredump_segment_header xfi_an_hdr; + u32 serdes_xfi_an[XG_SERDES_XFI_AN_COUNT]; + + /* segment 25 */ + struct mpi_coredump_segment_header xfi_train_hdr; + u32 serdes_xfi_train[XG_SERDES_XFI_TRAIN_COUNT]; + + /* segment 26 */ + struct mpi_coredump_segment_header xfi_hss_pcs_hdr; + u32 serdes_xfi_hss_pcs[XG_SERDES_XFI_HSS_PCS_COUNT]; + + /* segment 27 */ + struct mpi_coredump_segment_header xfi_hss_tx_hdr; + u32 serdes_xfi_hss_tx[XG_SERDES_XFI_HSS_TX_COUNT]; + + /* segment 28 */ + struct mpi_coredump_segment_header xfi_hss_rx_hdr; + u32 serdes_xfi_hss_rx[XG_SERDES_XFI_HSS_RX_COUNT]; + + /* segment 29 */ + struct mpi_coredump_segment_header xfi_hss_pll_hdr; + u32 serdes_xfi_hss_pll[XG_SERDES_XFI_HSS_PLL_COUNT]; + + /* segment 30 */ + struct mpi_coredump_segment_header misc_nic_seg_hdr; + struct ql_nic_misc misc_nic_info; + + /* segment 31 */ + /* one interrupt state for each CQ */ + struct mpi_coredump_segment_header intr_states_seg_hdr; + u32 intr_states[MAX_RX_RINGS]; + + /* segment 32 */ + /* 3 cam words each for 16 unicast, + * 2 cam words for each of 32 multicast. + */ + struct mpi_coredump_segment_header cam_entries_seg_hdr; + u32 cam_entries[(16 * 3) + (32 * 3)]; + + /* segment 33 */ + struct mpi_coredump_segment_header nic_routing_words_seg_hdr; + u32 nic_routing_words[16]; + /* segment 34 */ + struct mpi_coredump_segment_header ets_seg_hdr; + u32 ets[ETS_REGS_DUMP_WORD_COUNT]; + + /* segment 35 */ + struct mpi_coredump_segment_header probe_dump_seg_hdr; + u32 probe_dump[PRB_MX_DUMP_TOT_COUNT]; + + /* segment 36 */ + struct mpi_coredump_segment_header routing_reg_seg_hdr; + u32 routing_regs[RT_IDX_DUMP_TOT_WORDS]; + + /* segment 37 */ + struct mpi_coredump_segment_header mac_prot_reg_seg_hdr; + u32 mac_prot_regs[MAC_ADDR_DUMP_TOT_WORDS]; + + /* segment 38 */ + struct mpi_coredump_segment_header xaui2_an_hdr; + u32 serdes2_xaui_an[XG_SERDES_XAUI_AN_COUNT]; + + /* segment 39 */ + struct mpi_coredump_segment_header xaui2_hss_pcs_hdr; + u32 serdes2_xaui_hss_pcs[XG_SERDES_XAUI_HSS_PCS_COUNT]; + + /* segment 40 */ + struct mpi_coredump_segment_header xfi2_an_hdr; + u32 serdes2_xfi_an[XG_SERDES_XFI_AN_COUNT]; + + /* segment 41 */ + struct mpi_coredump_segment_header xfi2_train_hdr; + u32 serdes2_xfi_train[XG_SERDES_XFI_TRAIN_COUNT]; + + /* segment 42 */ + struct mpi_coredump_segment_header xfi2_hss_pcs_hdr; + u32 serdes2_xfi_hss_pcs[XG_SERDES_XFI_HSS_PCS_COUNT]; + + /* segment 43 */ + struct mpi_coredump_segment_header xfi2_hss_tx_hdr; + u32 serdes2_xfi_hss_tx[XG_SERDES_XFI_HSS_TX_COUNT]; + + /* segment 44 */ + struct mpi_coredump_segment_header xfi2_hss_rx_hdr; + u32 serdes2_xfi_hss_rx[XG_SERDES_XFI_HSS_RX_COUNT]; + + /* segment 45 */ + struct mpi_coredump_segment_header xfi2_hss_pll_hdr; + u32 serdes2_xfi_hss_pll[XG_SERDES_XFI_HSS_PLL_COUNT]; + + /* segment 50 */ + /* semaphore register for all 5 functions */ + struct mpi_coredump_segment_header sem_regs_seg_hdr; + u32 sem_regs[MAX_SEMAPHORE_FUNCTIONS]; +}; + /* * intr_context structure is used during initialization * to hook the interrupts. It is also used in a single @@ -1735,6 +2125,8 @@ struct ql_adapter { u32 port_link_up; u32 port_init; u32 link_status; + struct ql_mpi_coredump *mpi_coredump; + u32 core_is_dumped; u32 link_config; u32 led_config; u32 max_frame_size; @@ -1747,6 +2139,7 @@ struct ql_adapter { struct delayed_work mpi_work; struct delayed_work mpi_port_cfg_work; struct delayed_work mpi_idc_work; + struct delayed_work mpi_core_to_log; struct completion ide_completion; struct nic_operations *nic_ops; u16 device_id; -- cgit v1.2.3 From 8aae2600030f54494f9061d2cde141802d774be9 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:28 +0000 Subject: qlge: Add basic firmware dump. Adding the infrstructure and basic data for the firmware core dump. The firmware coredump is turned OFF by default. There will be no memory allocations for data dumps to the log. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 6 + drivers/net/qlge/qlge_dbg.c | 523 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/qlge/qlge_main.c | 20 ++ drivers/net/qlge/qlge_mpi.c | 73 ++++++ 4 files changed, 622 insertions(+) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index a265325abb15..bbdd388aa9b7 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2211,6 +2211,7 @@ extern int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, void ql_queue_fw_error(struct ql_adapter *qdev); void ql_mpi_work(struct work_struct *work); void ql_mpi_reset_work(struct work_struct *work); +void ql_mpi_core_to_log(struct work_struct *work); int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 ebit); void ql_queue_asic_error(struct ql_adapter *qdev); u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); @@ -2221,6 +2222,11 @@ void ql_mpi_port_cfg_work(struct work_struct *work); int ql_mb_get_fw_state(struct ql_adapter *qdev); int ql_cam_route_initialize(struct ql_adapter *qdev); int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); +int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data); +int ql_unpause_mpi_risc(struct ql_adapter *qdev); +int ql_pause_mpi_risc(struct ql_adapter *qdev); +int ql_core_dump(struct ql_adapter *qdev, + struct ql_mpi_coredump *mpi_coredump); int ql_mb_about_fw(struct ql_adapter *qdev); int ql_wol(struct ql_adapter *qdev); int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol); diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 9f58c4710761..1d026141b78d 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -91,6 +91,179 @@ err: return status; } +/* Read the MPI Processor shadow registers */ +static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf) +{ + u32 i; + int status; + + for (i = 0; i < MPI_CORE_SH_REGS_CNT; i++, buf++) { + status = ql_write_mpi_reg(qdev, RISC_124, + (SHADOW_OFFSET | i << SHADOW_REG_SHIFT)); + if (status) + goto end; + status = ql_read_mpi_reg(qdev, RISC_127, buf); + if (status) + goto end; + } +end: + return status; +} + +/* Read the MPI Processor core registers */ +static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf, + u32 offset, u32 count) +{ + int i, status = 0; + for (i = 0; i < count; i++, buf++) { + status = ql_read_mpi_reg(qdev, offset + i, buf); + if (status) + return status; + } + return status; +} + + +/* Read out the routing index registers */ +static int ql_get_routing_index_registers(struct ql_adapter *qdev, u32 *buf) +{ + int status; + u32 type, index, index_max; + u32 result_index; + u32 result_data; + u32 val; + + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return status; + + for (type = 0; type < 4; type++) { + if (type < 2) + index_max = 8; + else + index_max = 16; + for (index = 0; index < index_max; index++) { + val = RT_IDX_RS + | (type << RT_IDX_TYPE_SHIFT) + | (index << RT_IDX_IDX_SHIFT); + ql_write32(qdev, RT_IDX, val); + result_index = 0; + while ((result_index & RT_IDX_MR) == 0) + result_index = ql_read32(qdev, RT_IDX); + result_data = ql_read32(qdev, RT_DATA); + *buf = type; + buf++; + *buf = index; + buf++; + *buf = result_index; + buf++; + *buf = result_data; + buf++; + } + } + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); + return status; +} + +/* Read out the MAC protocol registers */ +static void ql_get_mac_protocol_registers(struct ql_adapter *qdev, u32 *buf) +{ + u32 result_index, result_data; + u32 type; + u32 index; + u32 offset; + u32 val; + u32 initial_val = MAC_ADDR_RS; + u32 max_index; + u32 max_offset; + + for (type = 0; type < MAC_ADDR_TYPE_COUNT; type++) { + switch (type) { + + case 0: /* CAM */ + initial_val |= MAC_ADDR_ADR; + max_index = MAC_ADDR_MAX_CAM_ENTRIES; + max_offset = MAC_ADDR_MAX_CAM_WCOUNT; + break; + case 1: /* Multicast MAC Address */ + max_index = MAC_ADDR_MAX_CAM_WCOUNT; + max_offset = MAC_ADDR_MAX_CAM_WCOUNT; + break; + case 2: /* VLAN filter mask */ + case 3: /* MC filter mask */ + max_index = MAC_ADDR_MAX_CAM_WCOUNT; + max_offset = MAC_ADDR_MAX_CAM_WCOUNT; + break; + case 4: /* FC MAC addresses */ + max_index = MAC_ADDR_MAX_FC_MAC_ENTRIES; + max_offset = MAC_ADDR_MAX_FC_MAC_WCOUNT; + break; + case 5: /* Mgmt MAC addresses */ + max_index = MAC_ADDR_MAX_MGMT_MAC_ENTRIES; + max_offset = MAC_ADDR_MAX_MGMT_MAC_WCOUNT; + break; + case 6: /* Mgmt VLAN addresses */ + max_index = MAC_ADDR_MAX_MGMT_VLAN_ENTRIES; + max_offset = MAC_ADDR_MAX_MGMT_VLAN_WCOUNT; + break; + case 7: /* Mgmt IPv4 address */ + max_index = MAC_ADDR_MAX_MGMT_V4_ENTRIES; + max_offset = MAC_ADDR_MAX_MGMT_V4_WCOUNT; + break; + case 8: /* Mgmt IPv6 address */ + max_index = MAC_ADDR_MAX_MGMT_V6_ENTRIES; + max_offset = MAC_ADDR_MAX_MGMT_V6_WCOUNT; + break; + case 9: /* Mgmt TCP/UDP Dest port */ + max_index = MAC_ADDR_MAX_MGMT_TU_DP_ENTRIES; + max_offset = MAC_ADDR_MAX_MGMT_TU_DP_WCOUNT; + break; + default: + printk(KERN_ERR"Bad type!!! 0x%08x\n", type); + max_index = 0; + max_offset = 0; + break; + } + for (index = 0; index < max_index; index++) { + for (offset = 0; offset < max_offset; offset++) { + val = initial_val + | (type << MAC_ADDR_TYPE_SHIFT) + | (index << MAC_ADDR_IDX_SHIFT) + | (offset); + ql_write32(qdev, MAC_ADDR_IDX, val); + result_index = 0; + while ((result_index & MAC_ADDR_MR) == 0) { + result_index = ql_read32(qdev, + MAC_ADDR_IDX); + } + result_data = ql_read32(qdev, MAC_ADDR_DATA); + *buf = result_index; + buf++; + *buf = result_data; + buf++; + } + } + } +} + +static void ql_get_sem_registers(struct ql_adapter *qdev, u32 *buf) +{ + u32 func_num, reg, reg_val; + int status; + + for (func_num = 0; func_num < MAX_SEMAPHORE_FUNCTIONS ; func_num++) { + reg = MPI_NIC_REG_BLOCK + | (func_num << MPI_NIC_FUNCTION_SHIFT) + | (SEM / 4); + status = ql_read_mpi_reg(qdev, reg, ®_val); + *buf = reg_val; + /* if the read failed then dead fill the element. */ + if (!status) + *buf = 0xdeadbeef; + buf++; + } +} + /* Create a coredump segment header */ static void ql_build_coredump_seg_header( struct mpi_coredump_segment_header *seg_hdr, @@ -103,6 +276,329 @@ static void ql_build_coredump_seg_header( memcpy(seg_hdr->description, desc, (sizeof(seg_hdr->description)) - 1); } +/* + * This function should be called when a coredump / probedump + * is to be extracted from the HBA. It is assumed there is a + * qdev structure that contains the base address of the register + * space for this function as well as a coredump structure that + * will contain the dump. + */ +int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) +{ + int status; + int i; + + if (!mpi_coredump) { + QPRINTK(qdev, DRV, ERR, + "No memory available.\n"); + return -ENOMEM; + } + + /* Try to get the spinlock, but dont worry if + * it isn't available. If the firmware died it + * might be holding the sem. + */ + ql_sem_spinlock(qdev, SEM_PROC_REG_MASK); + + status = ql_pause_mpi_risc(qdev); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed RISC pause. Status = 0x%.08x\n", status); + goto err; + } + + /* Insert the global header */ + memset(&(mpi_coredump->mpi_global_header), 0, + sizeof(struct mpi_coredump_global_header)); + mpi_coredump->mpi_global_header.cookie = MPI_COREDUMP_COOKIE; + mpi_coredump->mpi_global_header.headerSize = + sizeof(struct mpi_coredump_global_header); + mpi_coredump->mpi_global_header.imageSize = + sizeof(struct ql_mpi_coredump); + memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump", + sizeof(mpi_coredump->mpi_global_header.idString)); + + /* Get generic NIC reg dump */ + ql_build_coredump_seg_header(&mpi_coredump->nic_regs_seg_hdr, + NIC1_CONTROL_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->nic_regs), "NIC1 Registers"); + + if (qdev->func & 1) { + /* Odd means our function is NIC 2 */ + for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) + mpi_coredump->nic2_regs[i] = + ql_read32(qdev, i * sizeof(u32)); + } else { + /* Even means our function is NIC 1 */ + for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) + mpi_coredump->nic_regs[i] = + ql_read32(qdev, i * sizeof(u32)); + } + + ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr, + CORE_SEG_NUM, + sizeof(mpi_coredump->core_regs_seg_hdr) + + sizeof(mpi_coredump->mpi_core_regs) + + sizeof(mpi_coredump->mpi_core_sh_regs), + "Core Registers"); + + /* Get the MPI Core Registers */ + status = ql_get_mpi_regs(qdev, &mpi_coredump->mpi_core_regs[0], + MPI_CORE_REGS_ADDR, MPI_CORE_REGS_CNT); + if (status) + goto err; + /* Get the 16 MPI shadow registers */ + status = ql_get_mpi_shadow_regs(qdev, + &mpi_coredump->mpi_core_sh_regs[0]); + if (status) + goto err; + + /* Get the Test Logic Registers */ + ql_build_coredump_seg_header(&mpi_coredump->test_logic_regs_seg_hdr, + TEST_LOGIC_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->test_logic_regs), + "Test Logic Regs"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->test_logic_regs[0], + TEST_REGS_ADDR, TEST_REGS_CNT); + if (status) + goto err; + + /* Get the RMII Registers */ + ql_build_coredump_seg_header(&mpi_coredump->rmii_regs_seg_hdr, + RMII_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->rmii_regs), + "RMII Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->rmii_regs[0], + RMII_REGS_ADDR, RMII_REGS_CNT); + if (status) + goto err; + + /* Get the FCMAC1 Registers */ + ql_build_coredump_seg_header(&mpi_coredump->fcmac1_regs_seg_hdr, + FCMAC1_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->fcmac1_regs), + "FCMAC1 Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->fcmac1_regs[0], + FCMAC1_REGS_ADDR, FCMAC_REGS_CNT); + if (status) + goto err; + + /* Get the FCMAC2 Registers */ + + ql_build_coredump_seg_header(&mpi_coredump->fcmac2_regs_seg_hdr, + FCMAC2_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->fcmac2_regs), + "FCMAC2 Registers"); + + status = ql_get_mpi_regs(qdev, &mpi_coredump->fcmac2_regs[0], + FCMAC2_REGS_ADDR, FCMAC_REGS_CNT); + if (status) + goto err; + + /* Get the FC1 MBX Registers */ + ql_build_coredump_seg_header(&mpi_coredump->fc1_mbx_regs_seg_hdr, + FC1_MBOX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->fc1_mbx_regs), + "FC1 MBox Regs"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->fc1_mbx_regs[0], + FC1_MBX_REGS_ADDR, FC_MBX_REGS_CNT); + if (status) + goto err; + + /* Get the IDE Registers */ + ql_build_coredump_seg_header(&mpi_coredump->ide_regs_seg_hdr, + IDE_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->ide_regs), + "IDE Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->ide_regs[0], + IDE_REGS_ADDR, IDE_REGS_CNT); + if (status) + goto err; + + /* Get the NIC1 MBX Registers */ + ql_build_coredump_seg_header(&mpi_coredump->nic1_mbx_regs_seg_hdr, + NIC1_MBOX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->nic1_mbx_regs), + "NIC1 MBox Regs"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->nic1_mbx_regs[0], + NIC1_MBX_REGS_ADDR, NIC_MBX_REGS_CNT); + if (status) + goto err; + + /* Get the SMBus Registers */ + ql_build_coredump_seg_header(&mpi_coredump->smbus_regs_seg_hdr, + SMBUS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->smbus_regs), + "SMBus Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->smbus_regs[0], + SMBUS_REGS_ADDR, SMBUS_REGS_CNT); + if (status) + goto err; + + /* Get the FC2 MBX Registers */ + ql_build_coredump_seg_header(&mpi_coredump->fc2_mbx_regs_seg_hdr, + FC2_MBOX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->fc2_mbx_regs), + "FC2 MBox Regs"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->fc2_mbx_regs[0], + FC2_MBX_REGS_ADDR, FC_MBX_REGS_CNT); + if (status) + goto err; + + /* Get the NIC2 MBX Registers */ + ql_build_coredump_seg_header(&mpi_coredump->nic2_mbx_regs_seg_hdr, + NIC2_MBOX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->nic2_mbx_regs), + "NIC2 MBox Regs"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->nic2_mbx_regs[0], + NIC2_MBX_REGS_ADDR, NIC_MBX_REGS_CNT); + if (status) + goto err; + + /* Get the I2C Registers */ + ql_build_coredump_seg_header(&mpi_coredump->i2c_regs_seg_hdr, + I2C_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->i2c_regs), + "I2C Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->i2c_regs[0], + I2C_REGS_ADDR, I2C_REGS_CNT); + if (status) + goto err; + + /* Get the MEMC Registers */ + ql_build_coredump_seg_header(&mpi_coredump->memc_regs_seg_hdr, + MEMC_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->memc_regs), + "MEMC Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->memc_regs[0], + MEMC_REGS_ADDR, MEMC_REGS_CNT); + if (status) + goto err; + + /* Get the PBus Registers */ + ql_build_coredump_seg_header(&mpi_coredump->pbus_regs_seg_hdr, + PBUS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->pbus_regs), + "PBUS Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->pbus_regs[0], + PBUS_REGS_ADDR, PBUS_REGS_CNT); + if (status) + goto err; + + /* Get the MDE Registers */ + ql_build_coredump_seg_header(&mpi_coredump->mde_regs_seg_hdr, + MDE_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->mde_regs), + "MDE Registers"); + status = ql_get_mpi_regs(qdev, &mpi_coredump->mde_regs[0], + MDE_REGS_ADDR, MDE_REGS_CNT); + if (status) + goto err; + + ql_build_coredump_seg_header(&mpi_coredump->misc_nic_seg_hdr, + MISC_NIC_INFO_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->misc_nic_info), + "MISC NIC INFO"); + mpi_coredump->misc_nic_info.rx_ring_count = qdev->rx_ring_count; + mpi_coredump->misc_nic_info.tx_ring_count = qdev->tx_ring_count; + mpi_coredump->misc_nic_info.intr_count = qdev->intr_count; + mpi_coredump->misc_nic_info.function = qdev->func; + + /* Segment 31 */ + /* Get indexed register values. */ + ql_build_coredump_seg_header(&mpi_coredump->intr_states_seg_hdr, + INTR_STATES_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->intr_states), + "INTR States"); + ql_get_intr_states(qdev, &mpi_coredump->intr_states[0]); + + ql_build_coredump_seg_header(&mpi_coredump->cam_entries_seg_hdr, + CAM_ENTRIES_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->cam_entries), + "CAM Entries"); + status = ql_get_cam_entries(qdev, &mpi_coredump->cam_entries[0]); + if (status) + goto err; + + ql_build_coredump_seg_header(&mpi_coredump->nic_routing_words_seg_hdr, + ROUTING_WORDS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->nic_routing_words), + "Routing Words"); + status = ql_get_routing_entries(qdev, + &mpi_coredump->nic_routing_words[0]); + if (status) + goto err; + + /* Segment 34 (Rev C. step 23) */ + ql_build_coredump_seg_header(&mpi_coredump->ets_seg_hdr, + ETS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->ets), + "ETS Registers"); + status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]); + if (status) + goto err; + + ql_build_coredump_seg_header(&mpi_coredump->routing_reg_seg_hdr, + ROUTING_INDEX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->routing_regs), + "Routing Regs"); + status = ql_get_routing_index_registers(qdev, + &mpi_coredump->routing_regs[0]); + if (status) + goto err; + + ql_build_coredump_seg_header(&mpi_coredump->mac_prot_reg_seg_hdr, + MAC_PROTOCOL_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->mac_prot_regs), + "MAC Prot Regs"); + ql_get_mac_protocol_registers(qdev, &mpi_coredump->mac_prot_regs[0]); + + /* Get the semaphore registers for all 5 functions */ + ql_build_coredump_seg_header(&mpi_coredump->sem_regs_seg_hdr, + SEM_REGS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->sem_regs), "Sem Registers"); + + ql_get_sem_registers(qdev, &mpi_coredump->sem_regs[0]); + + /* Prevent the mpi restarting while we dump the memory.*/ + ql_write_mpi_reg(qdev, MPI_TEST_FUNC_RST_STS, MPI_TEST_FUNC_RST_FRC); + + /* clear the pause */ + status = ql_unpause_mpi_risc(qdev); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed RISC unpause. Status = 0x%.08x\n", status); + goto err; + } +err: + ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ + return status; + +} + void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump) { @@ -180,6 +676,33 @@ void ql_gen_reg_dump(struct ql_adapter *qdev, return; } +/* Coredump to messages log file using separate worker thread */ +void ql_mpi_core_to_log(struct work_struct *work) +{ + struct ql_adapter *qdev = + container_of(work, struct ql_adapter, mpi_core_to_log.work); + u32 *tmp, count; + int i; + + count = sizeof(struct ql_mpi_coredump) / sizeof(u32); + tmp = (u32 *)qdev->mpi_coredump; + QPRINTK(qdev, DRV, DEBUG, "Core is dumping to log file!\n"); + + for (i = 0; i < count; i += 8) { + printk(KERN_ERR "%.08x: %.08x %.08x %.08x %.08x %.08x " + "%.08x %.08x %.08x \n", i, + tmp[i + 0], + tmp[i + 1], + tmp[i + 2], + tmp[i + 3], + tmp[i + 4], + tmp[i + 5], + tmp[i + 6], + tmp[i + 7]); + msleep(5); + } +} + #ifdef QL_REG_DUMP static void ql_dump_intr_states(struct ql_adapter *qdev) { diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 167a3dab2f18..e58892304e19 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -73,6 +73,13 @@ static int qlge_irq_type = MSIX_IRQ; module_param(qlge_irq_type, int, MSIX_IRQ); MODULE_PARM_DESC(qlge_irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); +static int qlge_mpi_coredump; +module_param(qlge_mpi_coredump, int, 0); +MODULE_PARM_DESC(qlge_mpi_coredump, + "Option to enable MPI firmware dump. " + "Default is OFF - Do Not allocate memory. " + "Do not perform firmware coredump."); + static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, @@ -3842,6 +3849,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) cancel_delayed_work_sync(&qdev->mpi_reset_work); cancel_delayed_work_sync(&qdev->mpi_work); cancel_delayed_work_sync(&qdev->mpi_idc_work); + cancel_delayed_work_sync(&qdev->mpi_core_to_log); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); for (i = 0; i < qdev->rss_ring_count; i++) @@ -4398,6 +4406,7 @@ static void ql_release_all(struct pci_dev *pdev) iounmap(qdev->reg_base); if (qdev->doorbell_area) iounmap(qdev->doorbell_area); + vfree(qdev->mpi_coredump); pci_release_regions(pdev); pci_set_drvdata(pdev, NULL); } @@ -4479,6 +4488,15 @@ static int __devinit ql_init_device(struct pci_dev *pdev, spin_lock_init(&qdev->hw_lock); spin_lock_init(&qdev->stats_lock); + if (qlge_mpi_coredump) { + qdev->mpi_coredump = + vmalloc(sizeof(struct ql_mpi_coredump)); + if (qdev->mpi_coredump == NULL) { + dev_err(&pdev->dev, "Coredump alloc failed.\n"); + err = -ENOMEM; + goto err_out; + } + } /* make sure the EEPROM is good */ err = qdev->nic_ops->get_flash(qdev); if (err) { @@ -4508,6 +4526,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); + INIT_DELAYED_WORK(&qdev->mpi_core_to_log, ql_mpi_core_to_log); init_completion(&qdev->ide_completion); if (!cards_found) { @@ -4630,6 +4649,7 @@ static void ql_eeh_close(struct net_device *ndev) cancel_delayed_work_sync(&qdev->mpi_reset_work); cancel_delayed_work_sync(&qdev->mpi_work); cancel_delayed_work_sync(&qdev->mpi_idc_work); + cancel_delayed_work_sync(&qdev->mpi_core_to_log); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); for (i = 0; i < qdev->rss_ring_count; i++) diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index e2b2286102d4..242b1ea955e4 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -1,5 +1,35 @@ #include "qlge.h" +int ql_unpause_mpi_risc(struct ql_adapter *qdev) +{ + u32 tmp; + + /* Un-pause the RISC */ + tmp = ql_read32(qdev, CSR); + if (!(tmp & CSR_RP)) + return -EIO; + + ql_write32(qdev, CSR, CSR_CMD_CLR_PAUSE); + return 0; +} + +int ql_pause_mpi_risc(struct ql_adapter *qdev) +{ + u32 tmp; + int count = UDELAY_COUNT; + + /* Pause the RISC */ + ql_write32(qdev, CSR, CSR_CMD_SET_PAUSE); + do { + tmp = ql_read32(qdev, CSR); + if (tmp & CSR_RP) + break; + mdelay(UDELAY_DELAY); + count--; + } while (count); + return (count == 0) ? -ETIMEDOUT : 0; +} + int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) { int status; @@ -45,6 +75,35 @@ int ql_soft_reset_mpi_risc(struct ql_adapter *qdev) return status; } +/* Determine if we are in charge of the firwmare. If + * we are the lower of the 2 NIC pcie functions, or if + * we are the higher function and the lower function + * is not enabled. + */ +int ql_own_firmware(struct ql_adapter *qdev) +{ + u32 temp; + + /* If we are the lower of the 2 NIC functions + * on the chip the we are responsible for + * core dump and firmware reset after an error. + */ + if (qdev->func < qdev->alt_func) + return 1; + + /* If we are the higher of the 2 NIC functions + * on the chip and the lower function is not + * enabled, then we are responsible for + * core dump and firmware reset after an error. + */ + temp = ql_read32(qdev, STS); + if (!(temp & (1 << (8 + qdev->alt_func)))) + return 1; + + return 0; + +} + static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) { int i, status; @@ -1143,5 +1202,19 @@ void ql_mpi_reset_work(struct work_struct *work) cancel_delayed_work_sync(&qdev->mpi_work); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); cancel_delayed_work_sync(&qdev->mpi_idc_work); + /* If we're not the dominant NIC function, + * then there is nothing to do. + */ + if (!ql_own_firmware(qdev)) { + QPRINTK(qdev, DRV, ERR, "Don't own firmware!\n"); + return; + } + + if (!ql_core_dump(qdev, qdev->mpi_coredump)) { + QPRINTK(qdev, DRV, ERR, "Core is dumped!\n"); + qdev->core_is_dumped = 1; + queue_delayed_work(qdev->workqueue, + &qdev->mpi_core_to_log, 5 * HZ); + } ql_soft_reset_mpi_risc(qdev); } -- cgit v1.2.3 From c89ec8b9de887cda0879d27036fce8d2a2fd6400 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:29 +0000 Subject: qlge: Add probe regs to firmware dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_dbg.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 1d026141b78d..913ca1e10e3e 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -123,6 +123,53 @@ static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf, return status; } +/* Read the ASIC probe dump */ +static unsigned int *ql_get_probe(struct ql_adapter *qdev, u32 clock, + u32 valid, u32 *buf) +{ + u32 module, mux_sel, probe, lo_val, hi_val; + + for (module = 0; module < PRB_MX_ADDR_MAX_MODS; module++) { + if (!((valid >> module) & 1)) + continue; + for (mux_sel = 0; mux_sel < PRB_MX_ADDR_MAX_MUX; mux_sel++) { + probe = clock + | PRB_MX_ADDR_ARE + | mux_sel + | (module << PRB_MX_ADDR_MOD_SEL_SHIFT); + ql_write32(qdev, PRB_MX_ADDR, probe); + lo_val = ql_read32(qdev, PRB_MX_DATA); + if (mux_sel == 0) { + *buf = probe; + buf++; + } + probe |= PRB_MX_ADDR_UP; + ql_write32(qdev, PRB_MX_ADDR, probe); + hi_val = ql_read32(qdev, PRB_MX_DATA); + *buf = lo_val; + buf++; + *buf = hi_val; + buf++; + } + } + return buf; +} + +static int ql_get_probe_dump(struct ql_adapter *qdev, unsigned int *buf) +{ + /* First we have to enable the probe mux */ + ql_write_mpi_reg(qdev, MPI_TEST_FUNC_PRB_CTL, MPI_TEST_FUNC_PRB_EN); + buf = ql_get_probe(qdev, PRB_MX_ADDR_SYS_CLOCK, + PRB_MX_ADDR_VALID_SYS_MOD, buf); + buf = ql_get_probe(qdev, PRB_MX_ADDR_PCI_CLOCK, + PRB_MX_ADDR_VALID_PCI_MOD, buf); + buf = ql_get_probe(qdev, PRB_MX_ADDR_XGM_CLOCK, + PRB_MX_ADDR_VALID_XGM_MOD, buf); + buf = ql_get_probe(qdev, PRB_MX_ADDR_FC_CLOCK, + PRB_MX_ADDR_VALID_FC_MOD, buf); + return 0; + +} /* Read out the routing index registers */ static int ql_get_routing_index_registers(struct ql_adapter *qdev, u32 *buf) @@ -558,6 +605,13 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) if (status) goto err; + ql_build_coredump_seg_header(&mpi_coredump->probe_dump_seg_hdr, + PROBE_DUMP_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->probe_dump), + "Probe Dump"); + ql_get_probe_dump(qdev, &mpi_coredump->probe_dump[0]); + ql_build_coredump_seg_header(&mpi_coredump->routing_reg_seg_hdr, ROUTING_INDEX_SEG_NUM, sizeof(struct mpi_coredump_segment_header) -- cgit v1.2.3 From 2c1f73c3ddfd526750b003bc49a255641ac1f0ca Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:30 +0000 Subject: qlge: Add RAM dump to firmware dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 3 ++ drivers/net/qlge/qlge_dbg.c | 35 +++++++++++++++++++++ drivers/net/qlge/qlge_mpi.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index bbdd388aa9b7..05feb03e9da6 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2225,6 +2225,9 @@ int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data); int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data); int ql_unpause_mpi_risc(struct ql_adapter *qdev); int ql_pause_mpi_risc(struct ql_adapter *qdev); +int ql_hard_reset_mpi_risc(struct ql_adapter *qdev); +int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, + u32 ram_addr, int word_count); int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump); int ql_mb_about_fw(struct ql_adapter *qdev); diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 913ca1e10e3e..833cfd7a22c1 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -647,6 +647,41 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) "Failed RISC unpause. Status = 0x%.08x\n", status); goto err; } + + /* Reset the RISC so we can dump RAM */ + status = ql_hard_reset_mpi_risc(qdev); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed RISC reset. Status = 0x%.08x\n", status); + goto err; + } + + ql_build_coredump_seg_header(&mpi_coredump->code_ram_seg_hdr, + WCS_RAM_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->code_ram), + "WCS RAM"); + status = ql_dump_risc_ram_area(qdev, &mpi_coredump->code_ram[0], + CODE_RAM_ADDR, CODE_RAM_CNT); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed Dump of CODE RAM. Status = 0x%.08x\n", status); + goto err; + } + + /* Insert the segment header */ + ql_build_coredump_seg_header(&mpi_coredump->memc_ram_seg_hdr, + MEMC_RAM_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->memc_ram), + "MEMC RAM"); + status = ql_dump_risc_ram_area(qdev, &mpi_coredump->memc_ram[0], + MEMC_RAM_ADDR, MEMC_RAM_CNT); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed Dump of MEMC RAM. Status = 0x%.08x\n", status); + goto err; + } err: ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */ return status; diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 242b1ea955e4..3304eb7df581 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -30,6 +30,25 @@ int ql_pause_mpi_risc(struct ql_adapter *qdev) return (count == 0) ? -ETIMEDOUT : 0; } +int ql_hard_reset_mpi_risc(struct ql_adapter *qdev) +{ + u32 tmp; + int count = UDELAY_COUNT; + + /* Reset the RISC */ + ql_write32(qdev, CSR, CSR_CMD_SET_RST); + do { + tmp = ql_read32(qdev, CSR); + if (tmp & CSR_RR) { + ql_write32(qdev, CSR, CSR_CMD_CLR_RST); + break; + } + mdelay(UDELAY_DELAY); + count--; + } while (count); + return (count == 0) ? -ETIMEDOUT : 0; +} + int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data) { int status; @@ -728,6 +747,63 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev) return status; } +int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, + u32 size) +{ + int status = 0; + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 9; + mbcp->out_count = 1; + + mbcp->mbox_in[0] = MB_CMD_DUMP_RISC_RAM; + mbcp->mbox_in[1] = LSW(addr); + mbcp->mbox_in[2] = MSW(req_dma); + mbcp->mbox_in[3] = LSW(req_dma); + mbcp->mbox_in[4] = MSW(size); + mbcp->mbox_in[5] = LSW(size); + mbcp->mbox_in[6] = MSW(MSD(req_dma)); + mbcp->mbox_in[7] = LSW(MSD(req_dma)); + mbcp->mbox_in[8] = MSW(addr); + + + status = ql_mailbox_command(qdev, mbcp); + if (status) + return status; + + if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { + QPRINTK(qdev, DRV, ERR, + "Failed to dump risc RAM.\n"); + status = -EIO; + } + return status; +} + +/* Issue a mailbox command to dump RISC RAM. */ +int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, + u32 ram_addr, int word_count) +{ + int status; + char *my_buf; + dma_addr_t buf_dma; + + my_buf = pci_alloc_consistent(qdev->pdev, word_count * sizeof(u32), + &buf_dma); + if (!my_buf) + return -EIO; + + status = ql_mb_dump_ram(qdev, buf_dma, ram_addr, word_count); + if (!status) + memcpy(buf, my_buf, word_count * sizeof(u32)); + + pci_free_consistent(qdev->pdev, word_count * sizeof(u32), my_buf, + buf_dma); + return status; +} + /* Get link settings and maximum frame size settings * for the current port. * Most likely will block. -- cgit v1.2.3 From 24bb55b480f16f4cd8d64c2d46e28f0c82df0409 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:31 +0000 Subject: qlge: Add alternate function's reg dump to fw dump. Get the 2nd (other) nic function register values. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_dbg.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 833cfd7a22c1..181281390129 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -1,5 +1,23 @@ #include "qlge.h" +/* Read a NIC register from the alternate function. */ +static u32 ql_read_other_func_reg(struct ql_adapter *qdev, + u32 reg) +{ + u32 register_to_read; + u32 reg_val; + unsigned int status = 0; + + register_to_read = MPI_NIC_REG_BLOCK + | MPI_NIC_READ + | (qdev->alt_func << MPI_NIC_FUNCTION_SHIFT) + | reg; + status = ql_read_mpi_reg(qdev, register_to_read, ®_val); + if (status != 0) + return 0xffffffff; + + return reg_val; +} static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) { @@ -371,16 +389,28 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) sizeof(struct mpi_coredump_segment_header) + sizeof(mpi_coredump->nic_regs), "NIC1 Registers"); + ql_build_coredump_seg_header(&mpi_coredump->nic2_regs_seg_hdr, + NIC2_CONTROL_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->nic2_regs), "NIC2 Registers"); + if (qdev->func & 1) { /* Odd means our function is NIC 2 */ for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) mpi_coredump->nic2_regs[i] = ql_read32(qdev, i * sizeof(u32)); + + for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) + mpi_coredump->nic_regs[i] = + ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); } else { /* Even means our function is NIC 1 */ for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) mpi_coredump->nic_regs[i] = ql_read32(qdev, i * sizeof(u32)); + for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) + mpi_coredump->nic2_regs[i] = + ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); } ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr, -- cgit v1.2.3 From a48c86fdb1253f36167bab1fc30a51211d49a901 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:32 +0000 Subject: qlge: Add serdes reg blocks dump to firmware dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_dbg.c | 417 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 181281390129..87e50d9c3350 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -19,6 +19,318 @@ static u32 ql_read_other_func_reg(struct ql_adapter *qdev, return reg_val; } +/* Write a NIC register from the alternate function. */ +static int ql_write_other_func_reg(struct ql_adapter *qdev, + u32 reg, u32 reg_val) +{ + u32 register_to_read; + int status = 0; + + register_to_read = MPI_NIC_REG_BLOCK + | MPI_NIC_READ + | (qdev->alt_func << MPI_NIC_FUNCTION_SHIFT) + | reg; + status = ql_write_mpi_reg(qdev, register_to_read, reg_val); + + return status; +} + +static int ql_wait_other_func_reg_rdy(struct ql_adapter *qdev, u32 reg, + u32 bit, u32 err_bit) +{ + u32 temp; + int count = 10; + + while (count) { + temp = ql_read_other_func_reg(qdev, reg); + + /* check for errors */ + if (temp & err_bit) + return -1; + else if (temp & bit) + return 0; + mdelay(10); + count--; + } + return -1; +} + +static int ql_read_other_func_serdes_reg(struct ql_adapter *qdev, u32 reg, + u32 *data) +{ + int status; + + /* wait for reg to come ready */ + status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4, + XG_SERDES_ADDR_RDY, 0); + if (status) + goto exit; + + /* set up for reg read */ + ql_write_other_func_reg(qdev, XG_SERDES_ADDR/4, reg | PROC_ADDR_R); + + /* wait for reg to come ready */ + status = ql_wait_other_func_reg_rdy(qdev, XG_SERDES_ADDR / 4, + XG_SERDES_ADDR_RDY, 0); + if (status) + goto exit; + + /* get the data */ + *data = ql_read_other_func_reg(qdev, (XG_SERDES_DATA / 4)); +exit: + return status; +} + +/* Read out the SERDES registers */ +static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data) +{ + int status; + + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, XG_SERDES_ADDR, XG_SERDES_ADDR_RDY, 0); + if (status) + goto exit; + + /* set up for reg read */ + ql_write32(qdev, XG_SERDES_ADDR, reg | PROC_ADDR_R); + + /* wait for reg to come ready */ + status = ql_wait_reg_rdy(qdev, XG_SERDES_ADDR, XG_SERDES_ADDR_RDY, 0); + if (status) + goto exit; + + /* get the data */ + *data = ql_read32(qdev, XG_SERDES_DATA); +exit: + return status; +} + +static void ql_get_both_serdes(struct ql_adapter *qdev, u32 addr, + u32 *direct_ptr, u32 *indirect_ptr, + unsigned int direct_valid, unsigned int indirect_valid) +{ + unsigned int status; + + status = 1; + if (direct_valid) + status = ql_read_serdes_reg(qdev, addr, direct_ptr); + /* Dead fill any failures or invalids. */ + if (status) + *direct_ptr = 0xDEADBEEF; + + status = 1; + if (indirect_valid) + status = ql_read_other_func_serdes_reg( + qdev, addr, indirect_ptr); + /* Dead fill any failures or invalids. */ + if (status) + *indirect_ptr = 0xDEADBEEF; +} + +static int ql_get_serdes_regs(struct ql_adapter *qdev, + struct ql_mpi_coredump *mpi_coredump) +{ + int status; + unsigned int xfi_direct_valid, xfi_indirect_valid, xaui_direct_valid; + unsigned int xaui_indirect_valid, i; + u32 *direct_ptr, temp; + u32 *indirect_ptr; + + xfi_direct_valid = xfi_indirect_valid = 0; + xaui_direct_valid = xaui_indirect_valid = 1; + + /* The XAUI needs to be read out per port */ + if (qdev->func & 1) { + /* We are NIC 2 */ + status = ql_read_other_func_serdes_reg(qdev, + XG_SERDES_XAUI_HSS_PCS_START, &temp); + if (status) + temp = XG_SERDES_ADDR_XAUI_PWR_DOWN; + if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) == + XG_SERDES_ADDR_XAUI_PWR_DOWN) + xaui_indirect_valid = 0; + + status = ql_read_serdes_reg(qdev, + XG_SERDES_XAUI_HSS_PCS_START, &temp); + if (status) + temp = XG_SERDES_ADDR_XAUI_PWR_DOWN; + + if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) == + XG_SERDES_ADDR_XAUI_PWR_DOWN) + xaui_direct_valid = 0; + } else { + /* We are NIC 1 */ + status = ql_read_other_func_serdes_reg(qdev, + XG_SERDES_XAUI_HSS_PCS_START, &temp); + if (status) + temp = XG_SERDES_ADDR_XAUI_PWR_DOWN; + if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) == + XG_SERDES_ADDR_XAUI_PWR_DOWN) + xaui_indirect_valid = 0; + + status = ql_read_serdes_reg(qdev, + XG_SERDES_XAUI_HSS_PCS_START, &temp); + if (status) + temp = XG_SERDES_ADDR_XAUI_PWR_DOWN; + if ((temp & XG_SERDES_ADDR_XAUI_PWR_DOWN) == + XG_SERDES_ADDR_XAUI_PWR_DOWN) + xaui_direct_valid = 0; + } + + /* + * XFI register is shared so only need to read one + * functions and then check the bits. + */ + status = ql_read_serdes_reg(qdev, XG_SERDES_ADDR_STS, &temp); + if (status) + temp = 0; + + if ((temp & XG_SERDES_ADDR_XFI1_PWR_UP) == + XG_SERDES_ADDR_XFI1_PWR_UP) { + /* now see if i'm NIC 1 or NIC 2 */ + if (qdev->func & 1) + /* I'm NIC 2, so the indirect (NIC1) xfi is up. */ + xfi_indirect_valid = 1; + else + xfi_direct_valid = 1; + } + if ((temp & XG_SERDES_ADDR_XFI2_PWR_UP) == + XG_SERDES_ADDR_XFI2_PWR_UP) { + /* now see if i'm NIC 1 or NIC 2 */ + if (qdev->func & 1) + /* I'm NIC 2, so the indirect (NIC1) xfi is up. */ + xfi_direct_valid = 1; + else + xfi_indirect_valid = 1; + } + + /* Get XAUI_AN register block. */ + if (qdev->func & 1) { + /* Function 2 is direct */ + direct_ptr = mpi_coredump->serdes2_xaui_an; + indirect_ptr = mpi_coredump->serdes_xaui_an; + } else { + /* Function 1 is direct */ + direct_ptr = mpi_coredump->serdes_xaui_an; + indirect_ptr = mpi_coredump->serdes2_xaui_an; + } + + for (i = 0; i <= 0x000000034; i += 4, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xaui_direct_valid, xaui_indirect_valid); + + /* Get XAUI_HSS_PCS register block. */ + if (qdev->func & 1) { + direct_ptr = + mpi_coredump->serdes2_xaui_hss_pcs; + indirect_ptr = + mpi_coredump->serdes_xaui_hss_pcs; + } else { + direct_ptr = + mpi_coredump->serdes_xaui_hss_pcs; + indirect_ptr = + mpi_coredump->serdes2_xaui_hss_pcs; + } + + for (i = 0x800; i <= 0x880; i += 4, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xaui_direct_valid, xaui_indirect_valid); + + /* Get XAUI_XFI_AN register block. */ + if (qdev->func & 1) { + direct_ptr = mpi_coredump->serdes2_xfi_an; + indirect_ptr = mpi_coredump->serdes_xfi_an; + } else { + direct_ptr = mpi_coredump->serdes_xfi_an; + indirect_ptr = mpi_coredump->serdes2_xfi_an; + } + + for (i = 0x1000; i <= 0x1034; i += 4, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + + /* Get XAUI_XFI_TRAIN register block. */ + if (qdev->func & 1) { + direct_ptr = mpi_coredump->serdes2_xfi_train; + indirect_ptr = + mpi_coredump->serdes_xfi_train; + } else { + direct_ptr = mpi_coredump->serdes_xfi_train; + indirect_ptr = + mpi_coredump->serdes2_xfi_train; + } + + for (i = 0x1050; i <= 0x107c; i += 4, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + + /* Get XAUI_XFI_HSS_PCS register block. */ + if (qdev->func & 1) { + direct_ptr = + mpi_coredump->serdes2_xfi_hss_pcs; + indirect_ptr = + mpi_coredump->serdes_xfi_hss_pcs; + } else { + direct_ptr = + mpi_coredump->serdes_xfi_hss_pcs; + indirect_ptr = + mpi_coredump->serdes2_xfi_hss_pcs; + } + + for (i = 0x1800; i <= 0x1838; i += 4, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + + /* Get XAUI_XFI_HSS_TX register block. */ + if (qdev->func & 1) { + direct_ptr = + mpi_coredump->serdes2_xfi_hss_tx; + indirect_ptr = + mpi_coredump->serdes_xfi_hss_tx; + } else { + direct_ptr = mpi_coredump->serdes_xfi_hss_tx; + indirect_ptr = + mpi_coredump->serdes2_xfi_hss_tx; + } + for (i = 0x1c00; i <= 0x1c1f; i++, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + + /* Get XAUI_XFI_HSS_RX register block. */ + if (qdev->func & 1) { + direct_ptr = + mpi_coredump->serdes2_xfi_hss_rx; + indirect_ptr = + mpi_coredump->serdes_xfi_hss_rx; + } else { + direct_ptr = mpi_coredump->serdes_xfi_hss_rx; + indirect_ptr = + mpi_coredump->serdes2_xfi_hss_rx; + } + + for (i = 0x1c40; i <= 0x1c5f; i++, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + + + /* Get XAUI_XFI_HSS_PLL register block. */ + if (qdev->func & 1) { + direct_ptr = + mpi_coredump->serdes2_xfi_hss_pll; + indirect_ptr = + mpi_coredump->serdes_xfi_hss_pll; + } else { + direct_ptr = + mpi_coredump->serdes_xfi_hss_pll; + indirect_ptr = + mpi_coredump->serdes2_xfi_hss_pll; + } + for (i = 0x1e00; i <= 0x1e1f; i++, direct_ptr++, indirect_ptr++) + ql_get_both_serdes(qdev, i, direct_ptr, indirect_ptr, + xfi_direct_valid, xfi_indirect_valid); + return 0; +} + static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) { int status = 0; @@ -413,6 +725,111 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); } + /* Rev C. Step 20a */ + ql_build_coredump_seg_header(&mpi_coredump->xaui_an_hdr, + XAUI_AN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xaui_an), + "XAUI AN Registers"); + + /* Rev C. Step 20b */ + ql_build_coredump_seg_header(&mpi_coredump->xaui_hss_pcs_hdr, + XAUI_HSS_PCS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xaui_hss_pcs), + "XAUI HSS PCS Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_an_hdr, XFI_AN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_an), + "XFI AN Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_train_hdr, + XFI_TRAIN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_train), + "XFI TRAIN Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pcs_hdr, + XFI_HSS_PCS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_hss_pcs), + "XFI HSS PCS Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_tx_hdr, + XFI_HSS_TX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_hss_tx), + "XFI HSS TX Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_rx_hdr, + XFI_HSS_RX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_hss_rx), + "XFI HSS RX Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi_hss_pll_hdr, + XFI_HSS_PLL_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes_xfi_hss_pll), + "XFI HSS PLL Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xaui2_an_hdr, + XAUI2_AN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xaui_an), + "XAUI2 AN Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xaui2_hss_pcs_hdr, + XAUI2_HSS_PCS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xaui_hss_pcs), + "XAUI2 HSS PCS Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_an_hdr, + XFI2_AN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_an), + "XFI2 AN Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_train_hdr, + XFI2_TRAIN_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_train), + "XFI2 TRAIN Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pcs_hdr, + XFI2_HSS_PCS_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_hss_pcs), + "XFI2 HSS PCS Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_tx_hdr, + XFI2_HSS_TX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_hss_tx), + "XFI2 HSS TX Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_rx_hdr, + XFI2_HSS_RX_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_hss_rx), + "XFI2 HSS RX Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xfi2_hss_pll_hdr, + XFI2_HSS_PLL_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->serdes2_xfi_hss_pll), + "XFI2 HSS PLL Registers"); + + status = ql_get_serdes_regs(qdev, mpi_coredump); + if (status) { + QPRINTK(qdev, DRV, ERR, + "Failed Dump of Serdes Registers. Status = 0x%.08x\n", + status); + goto err; + } + ql_build_coredump_seg_header(&mpi_coredump->core_regs_seg_hdr, CORE_SEG_NUM, sizeof(mpi_coredump->core_regs_seg_hdr) + -- cgit v1.2.3 From a2f982328427157eaa819c02986a65b9b168733a Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:33 +0000 Subject: qlge: Add xgmac reg blocks to firwmare dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_dbg.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 87e50d9c3350..ec4349a254cc 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -331,6 +331,76 @@ static int ql_get_serdes_regs(struct ql_adapter *qdev, return 0; } +static int ql_read_other_func_xgmac_reg(struct ql_adapter *qdev, u32 reg, + u32 *data) +{ + int status = 0; + + /* wait for reg to come ready */ + status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4, + XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + if (status) + goto exit; + + /* set up for reg read */ + ql_write_other_func_reg(qdev, XGMAC_ADDR / 4, reg | XGMAC_ADDR_R); + + /* wait for reg to come ready */ + status = ql_wait_other_func_reg_rdy(qdev, XGMAC_ADDR / 4, + XGMAC_ADDR_RDY, XGMAC_ADDR_XME); + if (status) + goto exit; + + /* get the data */ + *data = ql_read_other_func_reg(qdev, XGMAC_DATA / 4); +exit: + return status; +} + +/* Read the 400 xgmac control/statistics registers + * skipping unused locations. + */ +static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf, + unsigned int other_function) +{ + int status = 0; + int i; + + for (i = PAUSE_SRC_LO; i < XGMAC_REGISTER_END; i += 4, buf++) { + /* We're reading 400 xgmac registers, but we filter out + * serveral locations that are non-responsive to reads. + */ + if ((i == 0x00000114) || + (i == 0x00000118) || + (i == 0x0000013c) || + (i == 0x00000140) || + (i > 0x00000150 && i < 0x000001fc) || + (i > 0x00000278 && i < 0x000002a0) || + (i > 0x000002c0 && i < 0x000002cf) || + (i > 0x000002dc && i < 0x000002f0) || + (i > 0x000003c8 && i < 0x00000400) || + (i > 0x00000400 && i < 0x00000410) || + (i > 0x00000410 && i < 0x00000420) || + (i > 0x00000420 && i < 0x00000430) || + (i > 0x00000430 && i < 0x00000440) || + (i > 0x00000440 && i < 0x00000450) || + (i > 0x00000450 && i < 0x00000500) || + (i > 0x0000054c && i < 0x00000568) || + (i > 0x000005c8 && i < 0x00000600)) { + if (other_function) + status = + ql_read_other_func_xgmac_reg(qdev, i, buf); + else + status = ql_read_xgmac_reg(qdev, i, buf); + + if (status) + *buf = 0xdeadbeef; + break; + } + } + return status; +} + static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf) { int status = 0; @@ -706,6 +776,17 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) sizeof(struct mpi_coredump_segment_header) + sizeof(mpi_coredump->nic2_regs), "NIC2 Registers"); + /* Get XGMac registers. (Segment 18, Rev C. step 21) */ + ql_build_coredump_seg_header(&mpi_coredump->xgmac1_seg_hdr, + NIC1_XGMAC_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->xgmac1), "NIC1 XGMac Registers"); + + ql_build_coredump_seg_header(&mpi_coredump->xgmac2_seg_hdr, + NIC2_XGMAC_SEG_NUM, + sizeof(struct mpi_coredump_segment_header) + + sizeof(mpi_coredump->xgmac2), "NIC2 XGMac Registers"); + if (qdev->func & 1) { /* Odd means our function is NIC 2 */ for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) @@ -715,6 +796,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) mpi_coredump->nic_regs[i] = ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); + + ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac2[0], 0); + ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac1[0], 1); } else { /* Even means our function is NIC 1 */ for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) @@ -723,6 +807,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) for (i = 0; i < NIC_REGS_DUMP_WORD_COUNT; i++) mpi_coredump->nic2_regs[i] = ql_read_other_func_reg(qdev, (i * sizeof(u32)) / 4); + + ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac1[0], 0); + ql_get_xgmac_regs(qdev, &mpi_coredump->xgmac2[0], 1); } /* Rev C. Step 20a */ -- cgit v1.2.3 From d5c1da56afb8a6b232393fb3fdef4909389d05fe Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Fri, 15 Jan 2010 13:31:34 +0000 Subject: qlge: Add module param to force firmware core dump. Default setting is 'off', don't allow force firmware dump. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 3 +++ drivers/net/qlge/qlge_dbg.c | 25 +++++++++++++++++++++++++ drivers/net/qlge/qlge_main.c | 11 +++++++++-- drivers/net/qlge/qlge_mpi.c | 16 ++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 05feb03e9da6..9169c4cf413a 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2004,6 +2004,7 @@ enum { QL_CAM_RT_SET = 8, QL_SELFTEST = 9, QL_LB_LINK_UP = 10, + QL_FRC_COREDUMP = 11, }; /* link_status bit definitions */ @@ -2230,6 +2231,7 @@ int ql_dump_risc_ram_area(struct ql_adapter *qdev, void *buf, u32 ram_addr, int word_count); int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump); +int ql_mb_sys_err(struct ql_adapter *qdev); int ql_mb_about_fw(struct ql_adapter *qdev); int ql_wol(struct ql_adapter *qdev); int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol); @@ -2246,6 +2248,7 @@ void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump); netdev_tx_t ql_lb_send(struct sk_buff *skb, struct net_device *ndev); void ql_check_lb_frame(struct ql_adapter *, struct sk_buff *); +int ql_own_firmware(struct ql_adapter *qdev); int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget); #if 1 diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index ec4349a254cc..57df835147eb 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -1222,6 +1222,28 @@ err: } +static void ql_get_core_dump(struct ql_adapter *qdev) +{ + if (!ql_own_firmware(qdev)) { + QPRINTK(qdev, DRV, ERR, "%s: Don't own firmware!\n", + qdev->ndev->name); + return; + } + + if (!netif_running(qdev->ndev)) { + QPRINTK(qdev, IFUP, ERR, + "Force Coredump can only be done from interface " + "that is up.\n"); + return; + } + + if (ql_mb_sys_err(qdev)) { + QPRINTK(qdev, IFUP, ERR, + "Fail force coredump with ql_mb_sys_err().\n"); + return; + } +} + void ql_gen_reg_dump(struct ql_adapter *qdev, struct ql_reg_dump *mpi_coredump) { @@ -1297,6 +1319,9 @@ void ql_gen_reg_dump(struct ql_adapter *qdev, status = ql_get_ets_regs(qdev, &mpi_coredump->ets[0]); if (status) return; + + if (test_bit(QL_FRC_COREDUMP, &qdev->flags)) + ql_get_core_dump(qdev); } /* Coredump to messages log file using separate worker thread */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index e58892304e19..95fb63dcd9e4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -77,8 +77,13 @@ static int qlge_mpi_coredump; module_param(qlge_mpi_coredump, int, 0); MODULE_PARM_DESC(qlge_mpi_coredump, "Option to enable MPI firmware dump. " - "Default is OFF - Do Not allocate memory. " - "Do not perform firmware coredump."); + "Default is OFF - Do Not allocate memory. "); + +static int qlge_force_coredump; +module_param(qlge_force_coredump, int, 0); +MODULE_PARM_DESC(qlge_force_coredump, + "Option to allow force of firmware core dump. " + "Default is OFF - Do not allow."); static DEFINE_PCI_DEVICE_TABLE(qlge_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, @@ -4496,6 +4501,8 @@ static int __devinit ql_init_device(struct pci_dev *pdev, err = -ENOMEM; goto err_out; } + if (qlge_force_coredump) + set_bit(QL_FRC_COREDUMP, &qdev->flags); } /* make sure the EEPROM is good */ err = qdev->nic_ops->get_flash(qdev); diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 3304eb7df581..e2c846f17fc7 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -607,6 +607,22 @@ end: return status; } +int ql_mb_sys_err(struct ql_adapter *qdev) +{ + struct mbox_params mbc; + struct mbox_params *mbcp = &mbc; + int status; + + memset(mbcp, 0, sizeof(struct mbox_params)); + + mbcp->in_count = 1; + mbcp->out_count = 0; + + mbcp->mbox_in[0] = MB_CMD_MAKE_SYS_ERR; + + status = ql_mailbox_command(qdev, mbcp); + return status; +} /* Get MPI firmware version. This will be used for * driver banner and for ethtool info. -- cgit v1.2.3 From 6eb3a8553345ba2b4efd5390709e158289b9ece4 Mon Sep 17 00:00:00 2001 From: Patrick Mullaney Date: Sat, 16 Jan 2010 01:05:38 -0800 Subject: macvlan: add GRO bit to features mask Allow macvlan devices to support GRO. Signed-off-by: Patrick Mullaney Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 21a9c9ab4b34..fa0dc514dbaf 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -418,7 +418,7 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ - NETIF_F_TSO_ECN | NETIF_F_TSO6) + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO) #define MACVLAN_STATE_MASK \ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) -- cgit v1.2.3 From af19b49152bdb68fda894183e88096d6d1aa5c3d Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Wed, 13 Jan 2010 00:37:25 +0000 Subject: qlcnic: Qlogic ethernet driver for CNA devices o 1G/10G Ethernet Driver for Qlgic QLE8240 and QLE8242 CNA devices. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/Makefile | 8 + drivers/net/qlcnic/qlcnic.h | 1106 +++++++++++++++ drivers/net/qlcnic/qlcnic_ctx.c | 536 +++++++ drivers/net/qlcnic/qlcnic_ethtool.c | 870 ++++++++++++ drivers/net/qlcnic/qlcnic_hdr.h | 937 +++++++++++++ drivers/net/qlcnic/qlcnic_hw.c | 1201 ++++++++++++++++ drivers/net/qlcnic/qlcnic_init.c | 1466 ++++++++++++++++++++ drivers/net/qlcnic/qlcnic_main.c | 2604 +++++++++++++++++++++++++++++++++++ 8 files changed, 8728 insertions(+) create mode 100644 drivers/net/qlcnic/Makefile create mode 100644 drivers/net/qlcnic/qlcnic.h create mode 100644 drivers/net/qlcnic/qlcnic_ctx.c create mode 100644 drivers/net/qlcnic/qlcnic_ethtool.c create mode 100644 drivers/net/qlcnic/qlcnic_hdr.h create mode 100644 drivers/net/qlcnic/qlcnic_hw.c create mode 100644 drivers/net/qlcnic/qlcnic_init.c create mode 100644 drivers/net/qlcnic/qlcnic_main.c diff --git a/drivers/net/qlcnic/Makefile b/drivers/net/qlcnic/Makefile new file mode 100644 index 000000000000..ddba83ef3f44 --- /dev/null +++ b/drivers/net/qlcnic/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for Qlogic 1G/10G Ethernet Driver for CNA devices +# + +obj-$(CONFIG_QLCNIC) := qlcnic.o + +qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ + qlcnic_ethtool.o qlcnic_ctx.o diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h new file mode 100644 index 000000000000..abec46846539 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic.h @@ -0,0 +1,1106 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#ifndef _QLCNIC_H_ +#define _QLCNIC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include "qlcnic_hdr.h" + +#define _QLCNIC_LINUX_MAJOR 5 +#define _QLCNIC_LINUX_MINOR 0 +#define _QLCNIC_LINUX_SUBVERSION 0 +#define QLCNIC_LINUX_VERSIONID "5.0.0" + +#define QLCNIC_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) +#define _major(v) (((v) >> 24) & 0xff) +#define _minor(v) (((v) >> 16) & 0xff) +#define _build(v) ((v) & 0xffff) + +/* version in image has weird encoding: + * 7:0 - major + * 15:8 - minor + * 31:16 - build (little endian) + */ +#define QLCNIC_DECODE_VERSION(v) \ + QLCNIC_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16)) + +#define QLCNIC_NUM_FLASH_SECTORS (64) +#define QLCNIC_FLASH_SECTOR_SIZE (64 * 1024) +#define QLCNIC_FLASH_TOTAL_SIZE (QLCNIC_NUM_FLASH_SECTORS \ + * QLCNIC_FLASH_SECTOR_SIZE) + +#define RCV_DESC_RINGSIZE(rds_ring) \ + (sizeof(struct rcv_desc) * (rds_ring)->num_desc) +#define RCV_BUFF_RINGSIZE(rds_ring) \ + (sizeof(struct qlcnic_rx_buffer) * rds_ring->num_desc) +#define STATUS_DESC_RINGSIZE(sds_ring) \ + (sizeof(struct status_desc) * (sds_ring)->num_desc) +#define TX_BUFF_RINGSIZE(tx_ring) \ + (sizeof(struct qlcnic_cmd_buffer) * tx_ring->num_desc) +#define TX_DESC_RINGSIZE(tx_ring) \ + (sizeof(struct cmd_desc_type0) * tx_ring->num_desc) + +#define QLCNIC_P3P_A0 0x50 + +#define QLCNIC_IS_REVISION_P3P(REVISION) (REVISION >= QLCNIC_P3P_A0) + +#define FIRST_PAGE_GROUP_START 0 +#define FIRST_PAGE_GROUP_END 0x100000 + +#define P3_MAX_MTU (9600) +#define QLCNIC_MAX_ETHERHDR 32 /* This contains some padding */ + +#define QLCNIC_P3_RX_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + ETH_DATA_LEN) +#define QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN (QLCNIC_MAX_ETHERHDR + P3_MAX_MTU) +#define QLCNIC_CT_DEFAULT_RX_BUF_LEN 2048 +#define QLCNIC_LRO_BUFFER_EXTRA 2048 + +#define QLCNIC_RX_LRO_BUFFER_LENGTH (8060) + +/* Opcodes to be used with the commands */ +#define TX_ETHER_PKT 0x01 +#define TX_TCP_PKT 0x02 +#define TX_UDP_PKT 0x03 +#define TX_IP_PKT 0x04 +#define TX_TCP_LSO 0x05 +#define TX_TCP_LSO6 0x06 +#define TX_IPSEC 0x07 +#define TX_IPSEC_CMD 0x0a +#define TX_TCPV6_PKT 0x0b +#define TX_UDPV6_PKT 0x0c + +/* Tx defines */ +#define MAX_BUFFERS_PER_CMD 32 +#define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) +#define QLCNIC_MAX_TX_TIMEOUTS 2 + +/* + * Following are the states of the Phantom. Phantom will set them and + * Host will read to check if the fields are correct. + */ +#define PHAN_INITIALIZE_FAILED 0xffff +#define PHAN_INITIALIZE_COMPLETE 0xff01 + +/* Host writes the following to notify that it has done the init-handshake */ +#define PHAN_INITIALIZE_ACK 0xf00f +#define PHAN_PEG_RCV_INITIALIZED 0xff01 + +#define NUM_RCV_DESC_RINGS 3 +#define NUM_STS_DESC_RINGS 4 + +#define RCV_RING_NORMAL 0 +#define RCV_RING_JUMBO 1 +#define RCV_RING_LRO 2 + +#define MIN_CMD_DESCRIPTORS 64 +#define MIN_RCV_DESCRIPTORS 64 +#define MIN_JUMBO_DESCRIPTORS 32 + +#define MAX_CMD_DESCRIPTORS 1024 +#define MAX_RCV_DESCRIPTORS_1G 4096 +#define MAX_RCV_DESCRIPTORS_10G 8192 +#define MAX_JUMBO_RCV_DESCRIPTORS_1G 512 +#define MAX_JUMBO_RCV_DESCRIPTORS_10G 1024 +#define MAX_LRO_RCV_DESCRIPTORS 8 + +#define DEFAULT_RCV_DESCRIPTORS_1G 2048 +#define DEFAULT_RCV_DESCRIPTORS_10G 4096 + +#define get_next_index(index, length) \ + (((index) + 1) & ((length) - 1)) + +#define MPORT_MULTI_FUNCTION_MODE 0x2222 + +/* + * Following data structures describe the descriptors that will be used. + * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when + * we are doing LSO (above the 1500 size packet) only. + */ + +#define FLAGS_VLAN_TAGGED 0x10 +#define FLAGS_VLAN_OOB 0x40 + +#define qlcnic_set_tx_vlan_tci(cmd_desc, v) \ + (cmd_desc)->vlan_TCI = cpu_to_le16(v); +#define qlcnic_set_cmd_desc_port(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) +#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) + +#define qlcnic_set_tx_port(_desc, _port) \ + ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)) + +#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \ + ((_desc)->flags_opcode = \ + cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))) + +#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \ + ((_desc)->nfrags__length = \ + cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))) + +struct cmd_desc_type0 { + u8 tcp_hdr_offset; /* For LSO only */ + u8 ip_hdr_offset; /* For LSO only */ + __le16 flags_opcode; /* 15:13 unused, 12:7 opcode, 6:0 flags */ + __le32 nfrags__length; /* 31:8 total len, 7:0 frag count */ + + __le64 addr_buffer2; + + __le16 reference_handle; + __le16 mss; + u8 port_ctxid; /* 7:4 ctxid 3:0 port */ + u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */ + __le16 conn_id; /* IPSec offoad only */ + + __le64 addr_buffer3; + __le64 addr_buffer1; + + __le16 buffer_length[4]; + + __le64 addr_buffer4; + + __le32 reserved2; + __le16 reserved; + __le16 vlan_TCI; + +} __attribute__ ((aligned(64))); + +/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */ +struct rcv_desc { + __le16 reference_handle; + __le16 reserved; + __le32 buffer_length; /* allocated buffer length (usually 2K) */ + __le64 addr_buffer; +}; + +/* opcode field in status_desc */ +#define QLCNIC_SYN_OFFLOAD 0x03 +#define QLCNIC_RXPKT_DESC 0x04 +#define QLCNIC_OLD_RXPKT_DESC 0x3f +#define QLCNIC_RESPONSE_DESC 0x05 +#define QLCNIC_LRO_DESC 0x12 + +/* for status field in status_desc */ +#define STATUS_CKSUM_OK (2) + +/* owner bits of status_desc */ +#define STATUS_OWNER_HOST (0x1ULL << 56) +#define STATUS_OWNER_PHANTOM (0x2ULL << 56) + +/* Status descriptor: + 0-3 port, 4-7 status, 8-11 type, 12-27 total_length + 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset + 53-55 desc_cnt, 56-57 owner, 58-63 opcode + */ +#define qlcnic_get_sts_port(sts_data) \ + ((sts_data) & 0x0F) +#define qlcnic_get_sts_status(sts_data) \ + (((sts_data) >> 4) & 0x0F) +#define qlcnic_get_sts_type(sts_data) \ + (((sts_data) >> 8) & 0x0F) +#define qlcnic_get_sts_totallength(sts_data) \ + (((sts_data) >> 12) & 0xFFFF) +#define qlcnic_get_sts_refhandle(sts_data) \ + (((sts_data) >> 28) & 0xFFFF) +#define qlcnic_get_sts_prot(sts_data) \ + (((sts_data) >> 44) & 0x0F) +#define qlcnic_get_sts_pkt_offset(sts_data) \ + (((sts_data) >> 48) & 0x1F) +#define qlcnic_get_sts_desc_cnt(sts_data) \ + (((sts_data) >> 53) & 0x7) +#define qlcnic_get_sts_opcode(sts_data) \ + (((sts_data) >> 58) & 0x03F) + +#define qlcnic_get_lro_sts_refhandle(sts_data) \ + ((sts_data) & 0x0FFFF) +#define qlcnic_get_lro_sts_length(sts_data) \ + (((sts_data) >> 16) & 0x0FFFF) +#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data) \ + (((sts_data) >> 32) & 0x0FF) +#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data) \ + (((sts_data) >> 40) & 0x0FF) +#define qlcnic_get_lro_sts_timestamp(sts_data) \ + (((sts_data) >> 48) & 0x1) +#define qlcnic_get_lro_sts_type(sts_data) \ + (((sts_data) >> 49) & 0x7) +#define qlcnic_get_lro_sts_push_flag(sts_data) \ + (((sts_data) >> 52) & 0x1) +#define qlcnic_get_lro_sts_seq_number(sts_data) \ + ((sts_data) & 0x0FFFFFFFF) + + +struct status_desc { + __le64 status_desc_data[2]; +} __attribute__ ((aligned(16))); + +/* UNIFIED ROMIMAGE */ +#define QLCNIC_UNI_FW_MIN_SIZE 0xc8000 +#define QLCNIC_UNI_DIR_SECT_PRODUCT_TBL 0x0 +#define QLCNIC_UNI_DIR_SECT_BOOTLD 0x6 +#define QLCNIC_UNI_DIR_SECT_FW 0x7 + +/*Offsets */ +#define QLCNIC_UNI_CHIP_REV_OFF 10 +#define QLCNIC_UNI_FLAGS_OFF 11 +#define QLCNIC_UNI_BIOS_VERSION_OFF 12 +#define QLCNIC_UNI_BOOTLD_IDX_OFF 27 +#define QLCNIC_UNI_FIRMWARE_IDX_OFF 29 + +struct uni_table_desc{ + u32 findex; + u32 num_entries; + u32 entry_size; + u32 reserved[5]; +}; + +struct uni_data_desc{ + u32 findex; + u32 size; + u32 reserved[5]; +}; + +/* Magic number to let user know flash is programmed */ +#define QLCNIC_BDINFO_MAGIC 0x12345678 + +#define QLCNIC_BRDTYPE_P3_REF_QG 0x0021 +#define QLCNIC_BRDTYPE_P3_HMEZ 0x0022 +#define QLCNIC_BRDTYPE_P3_10G_CX4_LP 0x0023 +#define QLCNIC_BRDTYPE_P3_4_GB 0x0024 +#define QLCNIC_BRDTYPE_P3_IMEZ 0x0025 +#define QLCNIC_BRDTYPE_P3_10G_SFP_PLUS 0x0026 +#define QLCNIC_BRDTYPE_P3_10000_BASE_T 0x0027 +#define QLCNIC_BRDTYPE_P3_XG_LOM 0x0028 +#define QLCNIC_BRDTYPE_P3_4_GB_MM 0x0029 +#define QLCNIC_BRDTYPE_P3_10G_SFP_CT 0x002a +#define QLCNIC_BRDTYPE_P3_10G_SFP_QT 0x002b +#define QLCNIC_BRDTYPE_P3_10G_CX4 0x0031 +#define QLCNIC_BRDTYPE_P3_10G_XFP 0x0032 +#define QLCNIC_BRDTYPE_P3_10G_TP 0x0080 + +/* Flash memory map */ +#define QLCNIC_BRDCFG_START 0x4000 /* board config */ +#define QLCNIC_BOOTLD_START 0x10000 /* bootld */ +#define QLCNIC_IMAGE_START 0x43000 /* compressed image */ +#define QLCNIC_USER_START 0x3E8000 /* Firmare info */ + +#define QLCNIC_FW_VERSION_OFFSET (QLCNIC_USER_START+0x408) +#define QLCNIC_FW_SIZE_OFFSET (QLCNIC_USER_START+0x40c) +#define QLCNIC_FW_SERIAL_NUM_OFFSET (QLCNIC_USER_START+0x81c) +#define QLCNIC_BIOS_VERSION_OFFSET (QLCNIC_USER_START+0x83c) + +#define QLCNIC_BRDTYPE_OFFSET (QLCNIC_BRDCFG_START+0x8) +#define QLCNIC_FW_MAGIC_OFFSET (QLCNIC_BRDCFG_START+0x128) + +#define QLCNIC_FW_MIN_SIZE (0x3fffff) +#define QLCNIC_UNIFIED_ROMIMAGE 0 +#define QLCNIC_FLASH_ROMIMAGE 1 +#define QLCNIC_UNKNOWN_ROMIMAGE 0xff + +#define QLCNIC_UNIFIED_ROMIMAGE_NAME "phanfw.bin" +#define QLCNIC_FLASH_ROMIMAGE_NAME "flash" + +extern char qlcnic_driver_name[]; + +/* Number of status descriptors to handle per interrupt */ +#define MAX_STATUS_HANDLE (64) + +/* + * qlcnic_skb_frag{} is to contain mapping info for each SG list. This + * has to be freed when DMA is complete. This is part of qlcnic_tx_buffer{}. + */ +struct qlcnic_skb_frag { + u64 dma; + u64 length; +}; + +struct qlcnic_recv_crb { + u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; + u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; + u32 sw_int_mask[NUM_STS_DESC_RINGS]; +}; + +/* Following defines are for the state of the buffers */ +#define QLCNIC_BUFFER_FREE 0 +#define QLCNIC_BUFFER_BUSY 1 + +/* + * There will be one qlcnic_buffer per skb packet. These will be + * used to save the dma info for pci_unmap_page() + */ +struct qlcnic_cmd_buffer { + struct sk_buff *skb; + struct qlcnic_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; + u32 frag_count; +}; + +/* In rx_buffer, we do not need multiple fragments as is a single buffer */ +struct qlcnic_rx_buffer { + struct list_head list; + struct sk_buff *skb; + u64 dma; + u16 ref_handle; + u16 state; +}; + +/* Board types */ +#define QLCNIC_GBE 0x01 +#define QLCNIC_XGBE 0x02 + +/* + * One hardware_context{} per adapter + * contains interrupt info as well shared hardware info. + */ +struct qlcnic_hardware_context { + void __iomem *pci_base0; + void __iomem *ocm_win_crb; + + unsigned long pci_len0; + + u32 ocm_win; + u32 crb_win; + + rwlock_t crb_lock; + struct mutex mem_lock; + + u8 cut_through; + u8 revision_id; + u8 pci_func; + u8 linkup; + u16 port_type; + u16 board_type; +}; + +struct qlcnic_adapter_stats { + u64 xmitcalled; + u64 xmitfinished; + u64 rxdropped; + u64 txdropped; + u64 csummed; + u64 rx_pkts; + u64 lro_pkts; + u64 rxbytes; + u64 txbytes; +}; + +/* + * Rcv Descriptor Context. One such per Rcv Descriptor. There may + * be one Rcv Descriptor for normal packets, one for jumbo and may be others. + */ +struct qlcnic_host_rds_ring { + u32 producer; + u32 num_desc; + u32 dma_size; + u32 skb_size; + u32 flags; + void __iomem *crb_rcv_producer; + struct rcv_desc *desc_head; + struct qlcnic_rx_buffer *rx_buf_arr; + struct list_head free_list; + spinlock_t lock; + dma_addr_t phys_addr; +}; + +struct qlcnic_host_sds_ring { + u32 consumer; + u32 num_desc; + void __iomem *crb_sts_consumer; + void __iomem *crb_intr_mask; + + struct status_desc *desc_head; + struct qlcnic_adapter *adapter; + struct napi_struct napi; + struct list_head free_list[NUM_RCV_DESC_RINGS]; + + int irq; + + dma_addr_t phys_addr; + char name[IFNAMSIZ+4]; +}; + +struct qlcnic_host_tx_ring { + u32 producer; + __le32 *hw_consumer; + u32 sw_consumer; + void __iomem *crb_cmd_producer; + u32 num_desc; + + struct netdev_queue *txq; + + struct qlcnic_cmd_buffer *cmd_buf_arr; + struct cmd_desc_type0 *desc_head; + dma_addr_t phys_addr; + dma_addr_t hw_cons_phys_addr; +}; + +/* + * Receive context. There is one such structure per instance of the + * receive processing. Any state information that is relevant to + * the receive, and is must be in this structure. The global data may be + * present elsewhere. + */ +struct qlcnic_recv_context { + u32 state; + u16 context_id; + u16 virt_port; + + struct qlcnic_host_rds_ring *rds_rings; + struct qlcnic_host_sds_ring *sds_rings; +}; + +/* HW context creation */ + +#define QLCNIC_OS_CRB_RETRY_COUNT 4000 +#define QLCNIC_CDRP_SIGNATURE_MAKE(pcifn, version) \ + (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16)) + +#define QLCNIC_CDRP_CMD_BIT 0x80000000 + +/* + * All responses must have the QLCNIC_CDRP_CMD_BIT cleared + * in the crb QLCNIC_CDRP_CRB_OFFSET. + */ +#define QLCNIC_CDRP_FORM_RSP(rsp) (rsp) +#define QLCNIC_CDRP_IS_RSP(rsp) (((rsp) & QLCNIC_CDRP_CMD_BIT) == 0) + +#define QLCNIC_CDRP_RSP_OK 0x00000001 +#define QLCNIC_CDRP_RSP_FAIL 0x00000002 +#define QLCNIC_CDRP_RSP_TIMEOUT 0x00000003 + +/* + * All commands must have the QLCNIC_CDRP_CMD_BIT set in + * the crb QLCNIC_CDRP_CRB_OFFSET. + */ +#define QLCNIC_CDRP_FORM_CMD(cmd) (QLCNIC_CDRP_CMD_BIT | (cmd)) +#define QLCNIC_CDRP_IS_CMD(cmd) (((cmd) & QLCNIC_CDRP_CMD_BIT) != 0) + +#define QLCNIC_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001 +#define QLCNIC_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002 +#define QLCNIC_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003 +#define QLCNIC_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004 +#define QLCNIC_CDRP_CMD_READ_MAX_RX_CTX 0x00000005 +#define QLCNIC_CDRP_CMD_READ_MAX_TX_CTX 0x00000006 +#define QLCNIC_CDRP_CMD_CREATE_RX_CTX 0x00000007 +#define QLCNIC_CDRP_CMD_DESTROY_RX_CTX 0x00000008 +#define QLCNIC_CDRP_CMD_CREATE_TX_CTX 0x00000009 +#define QLCNIC_CDRP_CMD_DESTROY_TX_CTX 0x0000000a +#define QLCNIC_CDRP_CMD_SETUP_STATISTICS 0x0000000e +#define QLCNIC_CDRP_CMD_GET_STATISTICS 0x0000000f +#define QLCNIC_CDRP_CMD_DELETE_STATISTICS 0x00000010 +#define QLCNIC_CDRP_CMD_SET_MTU 0x00000012 +#define QLCNIC_CDRP_CMD_READ_PHY 0x00000013 +#define QLCNIC_CDRP_CMD_WRITE_PHY 0x00000014 +#define QLCNIC_CDRP_CMD_READ_HW_REG 0x00000015 +#define QLCNIC_CDRP_CMD_GET_FLOW_CTL 0x00000016 +#define QLCNIC_CDRP_CMD_SET_FLOW_CTL 0x00000017 +#define QLCNIC_CDRP_CMD_READ_MAX_MTU 0x00000018 +#define QLCNIC_CDRP_CMD_READ_MAX_LRO 0x00000019 +#define QLCNIC_CDRP_CMD_CONFIGURE_TOE 0x0000001a +#define QLCNIC_CDRP_CMD_FUNC_ATTRIB 0x0000001b +#define QLCNIC_CDRP_CMD_READ_PEXQ_PARAMETERS 0x0000001c +#define QLCNIC_CDRP_CMD_GET_LIC_CAPABILITIES 0x0000001d +#define QLCNIC_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e +#define QLCNIC_CDRP_CMD_MAX 0x0000001f + +#define QLCNIC_RCODE_SUCCESS 0 +#define QLCNIC_RCODE_TIMEOUT 17 +#define QLCNIC_DESTROY_CTX_RESET 0 + +/* + * Capabilities Announced + */ +#define QLCNIC_CAP0_LEGACY_CONTEXT (1) +#define QLCNIC_CAP0_LEGACY_MN (1 << 2) +#define QLCNIC_CAP0_LSO (1 << 6) +#define QLCNIC_CAP0_JUMBO_CONTIGUOUS (1 << 7) +#define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) + +/* + * Context state + */ +#define QLCNIC_HOST_CTX_STATE_ACTIVE 2 + +/* + * Rx context + */ + +struct qlcnic_hostrq_sds_ring { + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le16 msi_index; + __le16 rsvd; /* Padding */ +}; + +struct qlcnic_hostrq_rds_ring { + __le64 host_phys_addr; /* Ring base addr */ + __le64 buff_size; /* Packet buffer size */ + __le32 ring_size; /* Ring entries */ + __le32 ring_kind; /* Class of ring */ +}; + +struct qlcnic_hostrq_rx_ctx { + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 host_rds_crb_mode; /* RDS crb usage */ + /* These ring offsets are relative to data[0] below */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ + u8 reserved[128]; /* reserve space for future expansion*/ + /* MUST BE 64-bit aligned. + The following is packed: + - N hostrq_rds_rings + - N hostrq_sds_rings */ + char data[0]; +}; + +struct qlcnic_cardrsp_rds_ring{ + __le32 host_producer_crb; /* Crb to use */ + __le32 rsvd1; /* Padding */ +}; + +struct qlcnic_cardrsp_sds_ring { + __le32 host_consumer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ +}; + +struct qlcnic_cardrsp_rx_ctx { + /* These ring offsets are relative to data[0] below */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le32 host_ctx_state; /* Starting State */ + __le32 num_fn_per_port; /* How many PCI fn share the port */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 context_id; /* Handle for context */ + u8 phys_port; /* Physical id of port */ + u8 virt_port; /* Virtual/Logical id of port */ + u8 reserved[128]; /* save space for future expansion */ + /* MUST BE 64-bit aligned. + The following is packed: + - N cardrsp_rds_rings + - N cardrs_sds_rings */ + char data[0]; +}; + +#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \ + (sizeof(HOSTRQ_RX) + \ + (rds_rings)*(sizeof(struct qlcnic_hostrq_rds_ring)) + \ + (sds_rings)*(sizeof(struct qlcnic_hostrq_sds_ring))) + +#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \ + (sizeof(CARDRSP_RX) + \ + (rds_rings)*(sizeof(struct qlcnic_cardrsp_rds_ring)) + \ + (sds_rings)*(sizeof(struct qlcnic_cardrsp_sds_ring))) + +/* + * Tx context + */ + +struct qlcnic_hostrq_cds_ring { + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le32 rsvd; /* Padding */ +}; + +struct qlcnic_hostrq_tx_ctx { + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le64 cmd_cons_dma_addr; /* */ + __le64 dummy_dma_addr; /* */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ + __le16 interrupt_ctl; + __le16 msi_index; + __le16 rsvd3; /* Padding */ + struct qlcnic_hostrq_cds_ring cds_ring; /* Desc of cds ring */ + u8 reserved[128]; /* future expansion */ +}; + +struct qlcnic_cardrsp_cds_ring { + __le32 host_producer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ +}; + +struct qlcnic_cardrsp_tx_ctx { + __le32 host_ctx_state; /* Starting state */ + __le16 context_id; /* Handle for context */ + u8 phys_port; /* Physical id of port */ + u8 virt_port; /* Virtual/Logical id of port */ + struct qlcnic_cardrsp_cds_ring cds_ring; /* Card cds settings */ + u8 reserved[128]; /* future expansion */ +}; + +#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) (sizeof(HOSTRQ_TX)) +#define SIZEOF_CARDRSP_TX(CARDRSP_TX) (sizeof(CARDRSP_TX)) + +/* CRB */ + +#define QLCNIC_HOST_RDS_CRB_MODE_UNIQUE 0 +#define QLCNIC_HOST_RDS_CRB_MODE_SHARED 1 +#define QLCNIC_HOST_RDS_CRB_MODE_CUSTOM 2 +#define QLCNIC_HOST_RDS_CRB_MODE_MAX 3 + +#define QLCNIC_HOST_INT_CRB_MODE_UNIQUE 0 +#define QLCNIC_HOST_INT_CRB_MODE_SHARED 1 +#define QLCNIC_HOST_INT_CRB_MODE_NORX 2 +#define QLCNIC_HOST_INT_CRB_MODE_NOTX 3 +#define QLCNIC_HOST_INT_CRB_MODE_NORXTX 4 + + +/* MAC */ + +#define MC_COUNT_P3 38 + +#define QLCNIC_MAC_NOOP 0 +#define QLCNIC_MAC_ADD 1 +#define QLCNIC_MAC_DEL 2 + +struct qlcnic_mac_list_s { + struct list_head list; + uint8_t mac_addr[ETH_ALEN+2]; +}; + +/* + * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is + * adjusted based on configured MTU. + */ +#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US 3 +#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS 256 +#define QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS 64 +#define QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US 4 + +#define QLCNIC_INTR_DEFAULT 0x04 + +union qlcnic_nic_intr_coalesce_data { + struct { + u16 rx_packets; + u16 rx_time_us; + u16 tx_packets; + u16 tx_time_us; + } data; + u64 word; +}; + +struct qlcnic_nic_intr_coalesce { + u16 stats_time_us; + u16 rate_sample_time; + u16 flags; + u16 rsvd_1; + u32 low_threshold; + u32 high_threshold; + union qlcnic_nic_intr_coalesce_data normal; + union qlcnic_nic_intr_coalesce_data low; + union qlcnic_nic_intr_coalesce_data high; + union qlcnic_nic_intr_coalesce_data irq; +}; + +#define QLCNIC_HOST_REQUEST 0x13 +#define QLCNIC_REQUEST 0x14 + +#define QLCNIC_MAC_EVENT 0x1 + +#define QLCNIC_IP_UP 2 +#define QLCNIC_IP_DOWN 3 + +/* + * Driver --> Firmware + */ +#define QLCNIC_H2C_OPCODE_START 0 +#define QLCNIC_H2C_OPCODE_CONFIG_RSS 1 +#define QLCNIC_H2C_OPCODE_CONFIG_RSS_TBL 2 +#define QLCNIC_H2C_OPCODE_CONFIG_INTR_COALESCE 3 +#define QLCNIC_H2C_OPCODE_CONFIG_LED 4 +#define QLCNIC_H2C_OPCODE_CONFIG_PROMISCUOUS 5 +#define QLCNIC_H2C_OPCODE_CONFIG_L2_MAC 6 +#define QLCNIC_H2C_OPCODE_LRO_REQUEST 7 +#define QLCNIC_H2C_OPCODE_GET_SNMP_STATS 8 +#define QLCNIC_H2C_OPCODE_PROXY_START_REQUEST 9 +#define QLCNIC_H2C_OPCODE_PROXY_STOP_REQUEST 10 +#define QLCNIC_H2C_OPCODE_PROXY_SET_MTU 11 +#define QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE 12 +#define QLCNIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST 13 +#define QLCNIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST 14 +#define QLCNIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST 15 +#define QLCNIC_H2C_OPCODE_GET_NET_STATS 16 +#define QLCNIC_H2C_OPCODE_PROXY_UPDATE_P2V 17 +#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR 18 +#define QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK 19 +#define QLCNIC_H2C_OPCODE_PROXY_STOP_DONE 20 +#define QLCNIC_H2C_OPCODE_GET_LINKEVENT 21 +#define QLCNIC_C2C_OPCODE 22 +#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING 23 +#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO 24 +#define QLCNIC_H2C_OPCODE_LAST 25 +/* + * Firmware --> Driver + */ + +#define QLCNIC_C2H_OPCODE_START 128 +#define QLCNIC_C2H_OPCODE_CONFIG_RSS_RESPONSE 129 +#define QLCNIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE 130 +#define QLCNIC_C2H_OPCODE_CONFIG_MAC_RESPONSE 131 +#define QLCNIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE 132 +#define QLCNIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE 133 +#define QLCNIC_C2H_OPCODE_LRO_DELETE_RESPONSE 134 +#define QLCNIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE 135 +#define QLCNIC_C2H_OPCODE_GET_SNMP_STATS 136 +#define QLCNIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY 137 +#define QLCNIC_C2H_OPCODE_INSTALL_LICENSE_REPLY 138 +#define QLCNIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139 +#define QLCNIC_C2H_OPCODE_GET_NET_STATS_RESPONSE 140 +#define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 +#define QLCNIC_C2H_OPCODE_LAST 142 + +#define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ +#define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ +#define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ + +#define QLCNIC_LRO_REQUEST_CLEANUP 4 + +/* Capabilites received */ +#define QLCNIC_FW_CAPABILITY_BDG (1 << 8) +#define QLCNIC_FW_CAPABILITY_FVLANTX (1 << 9) +#define QLCNIC_FW_CAPABILITY_HW_LRO (1 << 10) + +/* module types */ +#define LINKEVENT_MODULE_NOT_PRESENT 1 +#define LINKEVENT_MODULE_OPTICAL_UNKNOWN 2 +#define LINKEVENT_MODULE_OPTICAL_SRLR 3 +#define LINKEVENT_MODULE_OPTICAL_LRM 4 +#define LINKEVENT_MODULE_OPTICAL_SFP_1G 5 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE 6 +#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7 +#define LINKEVENT_MODULE_TWINAX 8 + +#define LINKSPEED_10GBPS 10000 +#define LINKSPEED_1GBPS 1000 +#define LINKSPEED_100MBPS 100 +#define LINKSPEED_10MBPS 10 + +#define LINKSPEED_ENCODED_10MBPS 0 +#define LINKSPEED_ENCODED_100MBPS 1 +#define LINKSPEED_ENCODED_1GBPS 2 + +#define LINKEVENT_AUTONEG_DISABLED 0 +#define LINKEVENT_AUTONEG_ENABLED 1 + +#define LINKEVENT_HALF_DUPLEX 0 +#define LINKEVENT_FULL_DUPLEX 1 + +#define LINKEVENT_LINKSPEED_MBPS 0 +#define LINKEVENT_LINKSPEED_ENCODED 1 + +#define AUTO_FW_RESET_ENABLED 0x01 +/* firmware response header: + * 63:58 - message type + * 57:56 - owner + * 55:53 - desc count + * 52:48 - reserved + * 47:40 - completion id + * 39:32 - opcode + * 31:16 - error code + * 15:00 - reserved + */ +#define qlcnic_get_nic_msg_opcode(msg_hdr) \ + ((msg_hdr >> 32) & 0xFF) + +struct qlcnic_fw_msg { + union { + struct { + u64 hdr; + u64 body[7]; + }; + u64 words[8]; + }; +}; + +struct qlcnic_nic_req { + __le64 qhdr; + __le64 req_hdr; + __le64 words[6]; +}; + +struct qlcnic_mac_req { + u8 op; + u8 tag; + u8 mac_addr[6]; +}; + +#define QLCNIC_MSI_ENABLED 0x02 +#define QLCNIC_MSIX_ENABLED 0x04 +#define QLCNIC_LRO_ENABLED 0x08 +#define QLCNIC_BRIDGE_ENABLED 0X10 +#define QLCNIC_DIAG_ENABLED 0x20 +#define QLCNIC_IS_MSI_FAMILY(adapter) \ + ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) + +#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS +#define QLCNIC_MSIX_TBL_SPACE 8192 +#define QLCNIC_PCI_REG_MSIX_TBL 0x44 + +#define QLCNIC_NETDEV_WEIGHT 128 +#define QLCNIC_ADAPTER_UP_MAGIC 777 + +#define __QLCNIC_FW_ATTACHED 0 +#define __QLCNIC_DEV_UP 1 +#define __QLCNIC_RESETTING 2 +#define __QLCNIC_START_FW 4 + +struct qlcnic_adapter { + struct qlcnic_hardware_context ahw; + + struct net_device *netdev; + struct pci_dev *pdev; + struct list_head mac_list; + + spinlock_t tx_clean_lock; + + u16 num_txd; + u16 num_rxd; + u16 num_jumbo_rxd; + u16 num_lro_rxd; + + u8 max_rds_rings; + u8 max_sds_rings; + u8 driver_mismatch; + u8 msix_supported; + u8 rx_csum; + u8 pci_using_dac; + u8 portnum; + u8 physical_port; + + u8 mc_enabled; + u8 max_mc_count; + u8 rss_supported; + u8 rsrvd1; + u8 fw_wait_cnt; + u8 fw_fail_cnt; + u8 tx_timeo_cnt; + u8 need_fw_reset; + + u8 has_link_events; + u8 fw_type; + u16 tx_context_id; + u16 mtu; + u16 is_up; + + u16 link_speed; + u16 link_duplex; + u16 link_autoneg; + u16 module_type; + + u32 capabilities; + u32 flags; + u32 irq; + u32 temp; + + u32 int_vec_bit; + u32 heartbit; + + u8 dev_state; + u8 rsrd1; + u32 rsrd2; + + + u8 mac_addr[ETH_ALEN]; + + struct qlcnic_adapter_stats stats; + + struct qlcnic_recv_context recv_ctx; + struct qlcnic_host_tx_ring *tx_ring; + + void __iomem *tgt_mask_reg; + void __iomem *tgt_status_reg; + void __iomem *crb_int_state_reg; + void __iomem *isr_int_vec; + + struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; + + struct delayed_work fw_work; + + struct work_struct tx_timeout_task; + + struct qlcnic_nic_intr_coalesce coal; + + unsigned long state; + __le32 file_prd_off; /*File fw product offset*/ + u32 fw_version; + const struct firmware *fw; +}; + +int qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val); +int qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val); + +u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); +int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data); +int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data); +int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data); + +#define QLCRD32(adapter, off) \ + (qlcnic_hw_read_wx_2M(adapter, off)) +#define QLCWR32(adapter, off, val) \ + (qlcnic_hw_write_wx_2M(adapter, off, val)) + +int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32); +void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); + +#define qlcnic_rom_lock(a) \ + qlcnic_pcie_sem_lock((a), 2, QLCNIC_ROM_LOCK_ID) +#define qlcnic_rom_unlock(a) \ + qlcnic_pcie_sem_unlock((a), 2) +#define qlcnic_phy_lock(a) \ + qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID) +#define qlcnic_phy_unlock(a) \ + qlcnic_pcie_sem_unlock((a), 3) +#define qlcnic_api_lock(a) \ + qlcnic_pcie_sem_lock((a), 5, 0) +#define qlcnic_api_unlock(a) \ + qlcnic_pcie_sem_unlock((a), 5) +#define qlcnic_sw_lock(a) \ + qlcnic_pcie_sem_lock((a), 6, 0) +#define qlcnic_sw_unlock(a) \ + qlcnic_pcie_sem_unlock((a), 6) +#define crb_win_lock(a) \ + qlcnic_pcie_sem_lock((a), 7, QLCNIC_CRB_WIN_LOCK_ID) +#define crb_win_unlock(a) \ + qlcnic_pcie_sem_unlock((a), 7) + +int qlcnic_get_board_info(struct qlcnic_adapter *adapter); +int qlcnic_wol_supported(struct qlcnic_adapter *adapter); + +/* Functions from qlcnic_init.c */ +int qlcnic_phantom_init(struct qlcnic_adapter *adapter); +int qlcnic_load_firmware(struct qlcnic_adapter *adapter); +int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter); +void qlcnic_request_firmware(struct qlcnic_adapter *adapter); +void qlcnic_release_firmware(struct qlcnic_adapter *adapter); +int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter); + +int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp); +int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, + u8 *bytes, size_t size); +int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter); +void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter); + +void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32); + +int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter); +void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter); + +void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter); +void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); + +int qlcnic_init_firmware(struct qlcnic_adapter *adapter); +void qlcnic_watchdog_task(struct work_struct *work); +void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, + struct qlcnic_host_rds_ring *rds_ring); +int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); +void qlcnic_set_multi(struct net_device *netdev); +void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); +int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32); +int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter); +int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable); +int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd); +int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable); +void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup); + +int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); +int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); +int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable); +int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable); +int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); +void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, + struct qlcnic_host_tx_ring *tx_ring); +int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac); + +/* Functions from qlcnic_main.c */ +int qlcnic_reset_context(struct qlcnic_adapter *); + +/* + * QLOGIC Board information + */ + +#define QLCNIC_MAX_BOARD_NAME_LEN 64 +struct qlcnic_brdinfo { + unsigned short vendor; + unsigned short device; + unsigned short sub_vendor; + unsigned short sub_device; + char short_name[QLCNIC_MAX_BOARD_NAME_LEN]; +}; + +static const struct qlcnic_brdinfo qlcnic_boards[] = { + {0x1077, 0x8020, 0x1077, 0x203, "8200 Series Single Port 10GbE CNA"}, + {0x1077, 0x8020, 0x1077, 0x207, "8200 Series Dual Port 10GbE CNA"}, + {0x1077, 0x8020, 0x1077, 0x20b, + "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x1077, 0x20c, + "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x1077, 0x20f, + "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"}, + {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"}, +}; + +#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) + +static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) +{ + smp_mb(); + if (tx_ring->producer < tx_ring->sw_consumer) + return tx_ring->sw_consumer - tx_ring->producer; + else + return tx_ring->sw_consumer + tx_ring->num_desc - + tx_ring->producer; +} + +extern const struct ethtool_ops qlcnic_ethtool_ops; + +#endif /* __QLCNIC_H_ */ diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c new file mode 100644 index 000000000000..71c16a183458 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -0,0 +1,536 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#include "qlcnic.h" + +#define QLCHAL_VERSION 1 + +static u32 +qlcnic_poll_rsp(struct qlcnic_adapter *adapter) +{ + u32 rsp; + int timeout = 0; + + do { + /* give atleast 1ms for firmware to respond */ + msleep(1); + + if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT) + return QLCNIC_CDRP_RSP_TIMEOUT; + + rsp = QLCRD32(adapter, QLCNIC_CDRP_CRB_OFFSET); + } while (!QLCNIC_CDRP_IS_RSP(rsp)); + + return rsp; +} + +static u32 +qlcnic_issue_cmd(struct qlcnic_adapter *adapter, + u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd) +{ + u32 rsp; + u32 signature; + u32 rcode = QLCNIC_RCODE_SUCCESS; + struct pci_dev *pdev = adapter->pdev; + + signature = QLCNIC_CDRP_SIGNATURE_MAKE(pci_fn, version); + + /* Acquire semaphore before accessing CRB */ + if (qlcnic_api_lock(adapter)) + return QLCNIC_RCODE_TIMEOUT; + + QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature); + QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, arg1); + QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, arg2); + QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, arg3); + QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, QLCNIC_CDRP_FORM_CMD(cmd)); + + rsp = qlcnic_poll_rsp(adapter); + + if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) { + dev_err(&pdev->dev, "card response timeout.\n"); + rcode = QLCNIC_RCODE_TIMEOUT; + } else if (rsp == QLCNIC_CDRP_RSP_FAIL) { + rcode = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); + dev_err(&pdev->dev, "failed card response code:0x%x\n", + rcode); + } + + /* Release semaphore */ + qlcnic_api_unlock(adapter); + + return rcode; +} + +int +qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) +{ + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { + if (qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + recv_ctx->context_id, + mtu, + 0, + QLCNIC_CDRP_CMD_SET_MTU)) { + + dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); + return -EIO; + } + } + + return 0; +} + +static int +qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) +{ + void *addr; + struct qlcnic_hostrq_rx_ctx *prq; + struct qlcnic_cardrsp_rx_ctx *prsp; + struct qlcnic_hostrq_rds_ring *prq_rds; + struct qlcnic_hostrq_sds_ring *prq_sds; + struct qlcnic_cardrsp_rds_ring *prsp_rds; + struct qlcnic_cardrsp_sds_ring *prsp_sds; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_sds_ring *sds_ring; + + dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; + u64 phys_addr; + + int i, nrds_rings, nsds_rings; + size_t rq_size, rsp_size; + u32 cap, reg, val; + int err; + + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + nrds_rings = adapter->max_rds_rings; + nsds_rings = adapter->max_sds_rings; + + rq_size = + SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings, + nsds_rings); + rsp_size = + SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, + nsds_rings); + + addr = pci_alloc_consistent(adapter->pdev, + rq_size, &hostrq_phys_addr); + if (addr == NULL) + return -ENOMEM; + prq = (struct qlcnic_hostrq_rx_ctx *)addr; + + addr = pci_alloc_consistent(adapter->pdev, + rsp_size, &cardrsp_phys_addr); + if (addr == NULL) { + err = -ENOMEM; + goto out_free_rq; + } + prsp = (struct qlcnic_cardrsp_rx_ctx *)addr; + + prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr); + + cap = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN); + cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); + + prq->capabilities[0] = cpu_to_le32(cap); + prq->host_int_crb_mode = + cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); + prq->host_rds_crb_mode = + cpu_to_le32(QLCNIC_HOST_RDS_CRB_MODE_UNIQUE); + + prq->num_rds_rings = cpu_to_le16(nrds_rings); + prq->num_sds_rings = cpu_to_le16(nsds_rings); + prq->rds_ring_offset = cpu_to_le32(0); + + val = le32_to_cpu(prq->rds_ring_offset) + + (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings); + prq->sds_ring_offset = cpu_to_le32(val); + + prq_rds = (struct qlcnic_hostrq_rds_ring *)(prq->data + + le32_to_cpu(prq->rds_ring_offset)); + + for (i = 0; i < nrds_rings; i++) { + + rds_ring = &recv_ctx->rds_rings[i]; + + prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); + prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); + prq_rds[i].ring_kind = cpu_to_le32(i); + prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); + } + + prq_sds = (struct qlcnic_hostrq_sds_ring *)(prq->data + + le32_to_cpu(prq->sds_ring_offset)); + + for (i = 0; i < nsds_rings; i++) { + + sds_ring = &recv_ctx->sds_rings[i]; + + prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); + prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); + prq_sds[i].msi_index = cpu_to_le16(i); + } + + phys_addr = hostrq_phys_addr; + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + (u32)(phys_addr >> 32), + (u32)(phys_addr & 0xffffffff), + rq_size, + QLCNIC_CDRP_CMD_CREATE_RX_CTX); + if (err) { + dev_err(&adapter->pdev->dev, + "Failed to create rx ctx in firmware%d\n", err); + goto out_free_rsp; + } + + + prsp_rds = ((struct qlcnic_cardrsp_rds_ring *) + &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); + + for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { + rds_ring = &recv_ctx->rds_rings[i]; + + reg = le32_to_cpu(prsp_rds[i].host_producer_crb); + rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter, + QLCNIC_REG(reg - 0x200)); + } + + prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) + &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); + + for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { + sds_ring = &recv_ctx->sds_rings[i]; + + reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); + sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter, + QLCNIC_REG(reg - 0x200)); + + reg = le32_to_cpu(prsp_sds[i].interrupt_crb); + sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter, + QLCNIC_REG(reg - 0x200)); + } + + recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); + recv_ctx->context_id = le16_to_cpu(prsp->context_id); + recv_ctx->virt_port = prsp->virt_port; + +out_free_rsp: + pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); +out_free_rq: + pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); + return err; +} + +static void +qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + if (qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + recv_ctx->context_id, + QLCNIC_DESTROY_CTX_RESET, + 0, + QLCNIC_CDRP_CMD_DESTROY_RX_CTX)) { + + dev_err(&adapter->pdev->dev, + "Failed to destroy rx ctx in firmware\n"); + } +} + +static int +qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) +{ + struct qlcnic_hostrq_tx_ctx *prq; + struct qlcnic_hostrq_cds_ring *prq_cds; + struct qlcnic_cardrsp_tx_ctx *prsp; + void *rq_addr, *rsp_addr; + size_t rq_size, rsp_size; + u32 temp; + int err; + u64 phys_addr; + dma_addr_t rq_phys_addr, rsp_phys_addr; + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + + rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); + rq_addr = pci_alloc_consistent(adapter->pdev, + rq_size, &rq_phys_addr); + if (!rq_addr) + return -ENOMEM; + + rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); + rsp_addr = pci_alloc_consistent(adapter->pdev, + rsp_size, &rsp_phys_addr); + if (!rsp_addr) { + err = -ENOMEM; + goto out_free_rq; + } + + memset(rq_addr, 0, rq_size); + prq = (struct qlcnic_hostrq_tx_ctx *)rq_addr; + + memset(rsp_addr, 0, rsp_size); + prsp = (struct qlcnic_cardrsp_tx_ctx *)rsp_addr; + + prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); + + temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN | + QLCNIC_CAP0_LSO); + prq->capabilities[0] = cpu_to_le32(temp); + + prq->host_int_crb_mode = + cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); + + prq->interrupt_ctl = 0; + prq->msi_index = 0; + prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); + + prq_cds = &prq->cds_ring; + + prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); + prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); + + phys_addr = rq_phys_addr; + err = qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + (u32)(phys_addr >> 32), + ((u32)phys_addr & 0xffffffff), + rq_size, + QLCNIC_CDRP_CMD_CREATE_TX_CTX); + + if (err == QLCNIC_RCODE_SUCCESS) { + temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); + tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter, + QLCNIC_REG(temp - 0x200)); + + adapter->tx_context_id = + le16_to_cpu(prsp->context_id); + } else { + dev_err(&adapter->pdev->dev, + "Failed to create tx ctx in firmware%d\n", err); + err = -EIO; + } + + pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); + +out_free_rq: + pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); + + return err; +} + +static void +qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) +{ + if (qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + adapter->tx_context_id, + QLCNIC_DESTROY_CTX_RESET, + 0, + QLCNIC_CDRP_CMD_DESTROY_TX_CTX)) { + + dev_err(&adapter->pdev->dev, + "Failed to destroy tx ctx in firmware\n"); + } +} + +int +qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) +{ + + if (qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + reg, + 0, + 0, + QLCNIC_CDRP_CMD_READ_PHY)) { + + return -EIO; + } + + return QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); +} + +int +qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) +{ + return qlcnic_issue_cmd(adapter, + adapter->ahw.pci_func, + QLCHAL_VERSION, + reg, + val, + 0, + QLCNIC_CDRP_CMD_WRITE_PHY); +} + +int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) +{ + void *addr; + int err; + int ring; + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_host_tx_ring *tx_ring; + + struct pci_dev *pdev = adapter->pdev; + + recv_ctx = &adapter->recv_ctx; + tx_ring = adapter->tx_ring; + + tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32), + &tx_ring->hw_cons_phys_addr); + if (tx_ring->hw_consumer == NULL) { + dev_err(&pdev->dev, "failed to allocate tx consumer\n"); + return -ENOMEM; + } + *(tx_ring->hw_consumer) = 0; + + /* cmd desc ring */ + addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), + &tx_ring->phys_addr); + + if (addr == NULL) { + dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); + return -ENOMEM; + } + + tx_ring->desc_head = (struct cmd_desc_type0 *)addr; + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + addr = pci_alloc_consistent(adapter->pdev, + RCV_DESC_RINGSIZE(rds_ring), + &rds_ring->phys_addr); + if (addr == NULL) { + dev_err(&pdev->dev, + "failed to allocate rds ring [%d]\n", ring); + err = -ENOMEM; + goto err_out_free; + } + rds_ring->desc_head = (struct rcv_desc *)addr; + + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + addr = pci_alloc_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE(sds_ring), + &sds_ring->phys_addr); + if (addr == NULL) { + dev_err(&pdev->dev, + "failed to allocate sds ring [%d]\n", ring); + err = -ENOMEM; + goto err_out_free; + } + sds_ring->desc_head = (struct status_desc *)addr; + } + + + err = qlcnic_fw_cmd_create_rx_ctx(adapter); + if (err) + goto err_out_free; + err = qlcnic_fw_cmd_create_tx_ctx(adapter); + if (err) + goto err_out_free; + + set_bit(__QLCNIC_FW_ATTACHED, &adapter->state); + return 0; + +err_out_free: + qlcnic_free_hw_resources(adapter); + return err; +} + +void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_host_tx_ring *tx_ring; + int ring; + + + if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { + qlcnic_fw_cmd_destroy_rx_ctx(adapter); + qlcnic_fw_cmd_destroy_tx_ctx(adapter); + + /* Allow dma queues to drain after context reset */ + msleep(20); + } + + recv_ctx = &adapter->recv_ctx; + + tx_ring = adapter->tx_ring; + if (tx_ring->hw_consumer != NULL) { + pci_free_consistent(adapter->pdev, + sizeof(u32), + tx_ring->hw_consumer, + tx_ring->hw_cons_phys_addr); + tx_ring->hw_consumer = NULL; + } + + if (tx_ring->desc_head != NULL) { + pci_free_consistent(adapter->pdev, + TX_DESC_RINGSIZE(tx_ring), + tx_ring->desc_head, tx_ring->phys_addr); + tx_ring->desc_head = NULL; + } + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + + if (rds_ring->desc_head != NULL) { + pci_free_consistent(adapter->pdev, + RCV_DESC_RINGSIZE(rds_ring), + rds_ring->desc_head, + rds_ring->phys_addr); + rds_ring->desc_head = NULL; + } + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + if (sds_ring->desc_head != NULL) { + pci_free_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE(sds_ring), + sds_ring->desc_head, + sds_ring->phys_addr); + sds_ring->desc_head = NULL; + } + } +} + diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c new file mode 100644 index 000000000000..65e9620e28f1 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -0,0 +1,870 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#include +#include +#include +#include +#include +#include + +#include "qlcnic.h" + +struct qlcnic_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m) +#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m) + +static const struct qlcnic_stats qlcnic_gstrings_stats[] = { + {"xmit_called", + QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)}, + {"xmit_finished", + QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)}, + {"rx_dropped", + QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, + {"tx_dropped", + QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, + {"csummed", + QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, + {"rx_pkts", + QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, + {"lro_pkts", + QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)}, + {"rx_bytes", + QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, + {"tx_bytes", + QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, +}; + +#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) + +static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { + "Register_Test_on_offline", + "Link_Test_on_offline" +}; + +#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) + +#define QLCNIC_RING_REGS_COUNT 20 +#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32)) +#define QLCNIC_MAX_EEPROM_LEN 1024 + +static const u32 diag_registers[] = { + CRB_CMDPEG_STATE, + CRB_RCVPEG_STATE, + CRB_XG_STATE_P3, + CRB_FW_CAPABILITIES_1, + ISR_INT_STATE_REG, + QLCNIC_CRB_DEV_REF_COUNT, + QLCNIC_CRB_DEV_STATE, + QLCNIC_CRB_DRV_STATE, + QLCNIC_CRB_DRV_SCRATCH, + QLCNIC_CRB_DEV_PARTITION_INFO, + QLCNIC_CRB_DRV_IDC_VER, + QLCNIC_PEG_ALIVE_COUNTER, + QLCNIC_PEG_HALT_STATUS1, + QLCNIC_PEG_HALT_STATUS2, + QLCNIC_CRB_PEG_NET_0+0x3c, + QLCNIC_CRB_PEG_NET_1+0x3c, + QLCNIC_CRB_PEG_NET_2+0x3c, + QLCNIC_CRB_PEG_NET_4+0x3c, + -1 +}; + +static int qlcnic_get_regs_len(struct net_device *dev) +{ + return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN; +} + +static int qlcnic_get_eeprom_len(struct net_device *dev) +{ + return QLCNIC_FLASH_TOTAL_SIZE; +} + +static void +qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u32 fw_major, fw_minor, fw_build; + + fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); + fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); + fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB); + sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); + + strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); + strlcpy(drvinfo->driver, qlcnic_driver_name, 32); + strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID, 32); +} + +static int +qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + int check_sfp_module = 0; + u16 pcifn = adapter->ahw.pci_func; + + /* read which mode */ + if (adapter->ahw.port_type == QLCNIC_GBE) { + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full); + + ecmd->advertising = (ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full); + + ecmd->speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex; + ecmd->autoneg = adapter->link_autoneg; + + } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + u32 val; + + val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); + if (val == QLCNIC_PORT_MODE_802_3_AP) { + ecmd->supported = SUPPORTED_1000baseT_Full; + ecmd->advertising = ADVERTISED_1000baseT_Full; + } else { + ecmd->supported = SUPPORTED_10000baseT_Full; + ecmd->advertising = ADVERTISED_10000baseT_Full; + } + + if (netif_running(dev) && adapter->has_link_events) { + ecmd->speed = adapter->link_speed; + ecmd->autoneg = adapter->link_autoneg; + ecmd->duplex = adapter->link_duplex; + goto skip; + } + + val = QLCRD32(adapter, P3_LINK_SPEED_REG(pcifn)); + ecmd->speed = P3_LINK_SPEED_MHZ * + P3_LINK_SPEED_VAL(pcifn, val); + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_DISABLE; + } else + return -EIO; + +skip: + ecmd->phy_address = adapter->physical_port; + ecmd->transceiver = XCVR_EXTERNAL; + + switch (adapter->ahw.board_type) { + case QLCNIC_BRDTYPE_P3_REF_QG: + case QLCNIC_BRDTYPE_P3_4_GB: + case QLCNIC_BRDTYPE_P3_4_GB_MM: + + ecmd->supported |= SUPPORTED_Autoneg; + ecmd->advertising |= ADVERTISED_Autoneg; + case QLCNIC_BRDTYPE_P3_10G_CX4: + case QLCNIC_BRDTYPE_P3_10G_CX4_LP: + case QLCNIC_BRDTYPE_P3_10000_BASE_T: + ecmd->supported |= SUPPORTED_TP; + ecmd->advertising |= ADVERTISED_TP; + ecmd->port = PORT_TP; + ecmd->autoneg = adapter->link_autoneg; + break; + case QLCNIC_BRDTYPE_P3_IMEZ: + case QLCNIC_BRDTYPE_P3_XG_LOM: + case QLCNIC_BRDTYPE_P3_HMEZ: + ecmd->supported |= SUPPORTED_MII; + ecmd->advertising |= ADVERTISED_MII; + ecmd->port = PORT_MII; + ecmd->autoneg = AUTONEG_DISABLE; + break; + case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS: + case QLCNIC_BRDTYPE_P3_10G_SFP_CT: + case QLCNIC_BRDTYPE_P3_10G_SFP_QT: + ecmd->advertising |= ADVERTISED_TP; + ecmd->supported |= SUPPORTED_TP; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; + case QLCNIC_BRDTYPE_P3_10G_XFP: + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_FIBRE; + ecmd->port = PORT_FIBRE; + ecmd->autoneg = AUTONEG_DISABLE; + break; + case QLCNIC_BRDTYPE_P3_10G_TP: + if (adapter->ahw.port_type == QLCNIC_XGBE) { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); + ecmd->advertising |= + (ADVERTISED_FIBRE | ADVERTISED_TP); + ecmd->port = PORT_FIBRE; + check_sfp_module = netif_running(dev) && + adapter->has_link_events; + } else { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); + ecmd->advertising |= + (ADVERTISED_TP | ADVERTISED_Autoneg); + ecmd->port = PORT_TP; + } + break; + default: + dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", + adapter->ahw.board_type); + return -EIO; + } + + if (check_sfp_module) { + switch (adapter->module_type) { + case LINKEVENT_MODULE_OPTICAL_UNKNOWN: + case LINKEVENT_MODULE_OPTICAL_SRLR: + case LINKEVENT_MODULE_OPTICAL_LRM: + case LINKEVENT_MODULE_OPTICAL_SFP_1G: + ecmd->port = PORT_FIBRE; + break; + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: + case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: + case LINKEVENT_MODULE_TWINAX: + ecmd->port = PORT_TP; + break; + default: + ecmd->port = PORT_OTHER; + } + } + + return 0; +} + +static int +qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + __u32 status; + + /* read which mode */ + if (adapter->ahw.port_type == QLCNIC_GBE) { + /* autonegotiation */ + if (qlcnic_fw_cmd_set_phy(adapter, + QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG, + ecmd->autoneg) != 0) + return -EIO; + else + adapter->link_autoneg = ecmd->autoneg; + + if (qlcnic_fw_cmd_query_phy(adapter, + QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) != 0) + return -EIO; + + switch (ecmd->speed) { + case SPEED_10: + qlcnic_set_phy_speed(status, 0); + break; + case SPEED_100: + qlcnic_set_phy_speed(status, 1); + break; + case SPEED_1000: + qlcnic_set_phy_speed(status, 2); + break; + } + + if (ecmd->duplex == DUPLEX_HALF) + qlcnic_clear_phy_duplex(status); + if (ecmd->duplex == DUPLEX_FULL) + qlcnic_set_phy_duplex(status); + if (qlcnic_fw_cmd_set_phy(adapter, + QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + *((int *)&status)) != 0) + return -EIO; + else { + adapter->link_speed = ecmd->speed; + adapter->link_duplex = ecmd->duplex; + } + } else + return -EOPNOTSUPP; + + if (!netif_running(dev)) + return 0; + + dev->netdev_ops->ndo_stop(dev); + return dev->netdev_ops->ndo_open(dev); +} + +static void +qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_host_sds_ring *sds_ring; + u32 *regs_buff = p; + int ring, i = 0; + + memset(p, 0, qlcnic_get_regs_len(dev)); + regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | + (adapter->pdev)->device; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + + for (i = 0; diag_registers[i] != -1; i++) + regs_buff[i] = QLCRD32(adapter, diag_registers[i]); + + regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/ + + regs_buff[i++] = 1; /* No. of tx ring */ + regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer)); + regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer); + + regs_buff[i++] = 2; /* No. of rx ring */ + regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer); + regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer); + + regs_buff[i++] = adapter->max_sds_rings; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &(recv_ctx->sds_rings[ring]); + regs_buff[i++] = readl(sds_ring->crb_sts_consumer); + } +} + +static u32 qlcnic_test_link(struct net_device *dev) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u32 val; + + val = QLCRD32(adapter, CRB_XG_STATE_P3); + val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); + return (val == XG_LINK_UP_P3) ? 0 : 1; +} + +static int +qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 *bytes) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + int offset; + int ret; + + if (eeprom->len == 0) + return -EINVAL; + + eeprom->magic = (adapter->pdev)->vendor | + ((adapter->pdev)->device << 16); + offset = eeprom->offset; + + ret = qlcnic_rom_fast_read_words(adapter, offset, bytes, + eeprom->len); + if (ret < 0) + return ret; + + return 0; +} + +static void +qlcnic_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + + ring->rx_pending = adapter->num_rxd; + ring->rx_jumbo_pending = adapter->num_jumbo_rxd; + ring->rx_jumbo_pending += adapter->num_lro_rxd; + ring->tx_pending = adapter->num_txd; + + if (adapter->ahw.port_type == QLCNIC_GBE) { + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } else { + ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + ring->tx_max_pending = MAX_CMD_DESCRIPTORS; + + ring->rx_mini_max_pending = 0; + ring->rx_mini_pending = 0; +} + +static u32 +qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name) +{ + u32 num_desc; + num_desc = max(val, min); + num_desc = min(num_desc, max); + num_desc = roundup_pow_of_two(num_desc); + + if (val != num_desc) { + printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n", + qlcnic_driver_name, r_name, num_desc, val); + } + + return num_desc; +} + +static int +qlcnic_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G; + u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + u16 num_rxd, num_jumbo_rxd, num_txd; + + + if (ring->rx_mini_pending) + return -EOPNOTSUPP; + + if (adapter->ahw.port_type == QLCNIC_GBE) { + max_rcv_desc = MAX_RCV_DESCRIPTORS_1G; + max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + num_rxd = qlcnic_validate_ringparam(ring->rx_pending, + MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx"); + + num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending, + MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo"); + + num_txd = qlcnic_validate_ringparam(ring->tx_pending, + MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx"); + + if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd && + num_jumbo_rxd == adapter->num_jumbo_rxd) + return 0; + + adapter->num_rxd = num_rxd; + adapter->num_jumbo_rxd = num_jumbo_rxd; + adapter->num_txd = num_txd; + + return qlcnic_reset_context(adapter); +} + +static void +qlcnic_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int port = adapter->physical_port; + __u32 val; + + if (adapter->ahw.port_type == QLCNIC_GBE) { + if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) + return; + /* get flow control settings */ + val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port)); + pause->rx_pause = qlcnic_gb_get_rx_flowctl(val); + val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL); + switch (port) { + case 0: + pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val)); + break; + case 1: + pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val)); + break; + case 2: + pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val)); + break; + case 3: + default: + pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val)); + break; + } + } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS)) + return; + pause->rx_pause = 1; + val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL); + if (port == 0) + pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val)); + else + pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val)); + } else { + dev_err(&netdev->dev, "Unknown board type: %x\n", + adapter->ahw.port_type); + } +} + +static int +qlcnic_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int port = adapter->physical_port; + __u32 val; + + /* read mode */ + if (adapter->ahw.port_type == QLCNIC_GBE) { + if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) + return -EIO; + /* set flow control */ + val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port)); + + if (pause->rx_pause) + qlcnic_gb_rx_flowctl(val); + else + qlcnic_gb_unset_rx_flowctl(val); + + QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), + val); + /* set autoneg */ + val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL); + switch (port) { + case 0: + if (pause->tx_pause) + qlcnic_gb_unset_gb0_mask(val); + else + qlcnic_gb_set_gb0_mask(val); + break; + case 1: + if (pause->tx_pause) + qlcnic_gb_unset_gb1_mask(val); + else + qlcnic_gb_set_gb1_mask(val); + break; + case 2: + if (pause->tx_pause) + qlcnic_gb_unset_gb2_mask(val); + else + qlcnic_gb_set_gb2_mask(val); + break; + case 3: + default: + if (pause->tx_pause) + qlcnic_gb_unset_gb3_mask(val); + else + qlcnic_gb_set_gb3_mask(val); + break; + } + QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val); + } else if (adapter->ahw.port_type == QLCNIC_XGBE) { + if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS)) + return -EIO; + val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL); + if (port == 0) { + if (pause->tx_pause) + qlcnic_xg_unset_xg0_mask(val); + else + qlcnic_xg_set_xg0_mask(val); + } else { + if (pause->tx_pause) + qlcnic_xg_unset_xg1_mask(val); + else + qlcnic_xg_set_xg1_mask(val); + } + QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val); + } else { + dev_err(&netdev->dev, "Unknown board type: %x\n", + adapter->ahw.port_type); + } + return 0; +} + +static int qlcnic_reg_test(struct net_device *dev) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u32 data_read, data_written; + + data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0)); + if ((data_read & 0xffff) != adapter->pdev->vendor) + return 1; + + data_written = (u32)0xa5a5a5a5; + + QLCWR32(adapter, CRB_SCRATCHPAD_TEST, data_written); + data_read = QLCRD32(adapter, CRB_SCRATCHPAD_TEST); + if (data_written != data_read) + return 1; + + return 0; +} + +static int qlcnic_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_TEST: + return QLCNIC_TEST_LEN; + case ETH_SS_STATS: + return QLCNIC_STATS_LEN; + default: + return -EOPNOTSUPP; + } +} + +static void +qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, + u64 *data) +{ + memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN); + data[0] = qlcnic_reg_test(dev); + if (data[0]) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* link test */ + data[1] = (u64) qlcnic_test_link(dev); + if (data[1]) + eth_test->flags |= ETH_TEST_FL_FAILED; +} + +static void +qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) +{ + int index; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *qlcnic_gstrings_test, + QLCNIC_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + for (index = 0; index < QLCNIC_STATS_LEN; index++) { + memcpy(data + index * ETH_GSTRING_LEN, + qlcnic_gstrings_stats[index].stat_string, + ETH_GSTRING_LEN); + } + break; + } +} + +static void +qlcnic_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 * data) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + int index; + + for (index = 0; index < QLCNIC_STATS_LEN; index++) { + char *p = + (char *)adapter + + qlcnic_gstrings_stats[index].stat_offset; + data[index] = + (qlcnic_gstrings_stats[index].sizeof_stat == + sizeof(u64)) ? *(u64 *)p:(*(u32 *)p); + } +} + +static u32 qlcnic_get_rx_csum(struct net_device *dev) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + return adapter->rx_csum; +} + +static int qlcnic_set_rx_csum(struct net_device *dev, u32 data) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + adapter->rx_csum = !!data; + return 0; +} + +static u32 qlcnic_get_tso(struct net_device *dev) +{ + return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0; +} + +static int qlcnic_set_tso(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); + else + dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); + + return 0; +} + +static void +qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u32 wol_cfg; + + wol->supported = 0; + wol->wolopts = 0; + + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV); + if (wol_cfg & (1UL << adapter->portnum)) + wol->supported |= WAKE_MAGIC; + + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG); + if (wol_cfg & (1UL << adapter->portnum)) + wol->wolopts |= WAKE_MAGIC; +} + +static int +qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + u32 wol_cfg; + + if (wol->wolopts & ~WAKE_MAGIC) + return -EOPNOTSUPP; + + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV); + if (!(wol_cfg & (1 << adapter->portnum))) + return -EOPNOTSUPP; + + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG); + if (wol->wolopts & WAKE_MAGIC) + wol_cfg |= 1UL << adapter->portnum; + else + wol_cfg &= ~(1UL << adapter->portnum); + + QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg); + + return 0; +} + +/* + * Set the coalescing parameters. Currently only normal is supported. + * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the + * firmware coalescing to default. + */ +static int qlcnic_set_intr_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ethcoal) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return -EINVAL; + + /* + * Return Error if unsupported values or + * unsupported parameters are set. + */ + if (ethcoal->rx_coalesce_usecs > 0xffff || + ethcoal->rx_max_coalesced_frames > 0xffff || + ethcoal->tx_coalesce_usecs > 0xffff || + ethcoal->tx_max_coalesced_frames > 0xffff || + ethcoal->rx_coalesce_usecs_irq || + ethcoal->rx_max_coalesced_frames_irq || + ethcoal->tx_coalesce_usecs_irq || + ethcoal->tx_max_coalesced_frames_irq || + ethcoal->stats_block_coalesce_usecs || + ethcoal->use_adaptive_rx_coalesce || + ethcoal->use_adaptive_tx_coalesce || + ethcoal->pkt_rate_low || + ethcoal->rx_coalesce_usecs_low || + ethcoal->rx_max_coalesced_frames_low || + ethcoal->tx_coalesce_usecs_low || + ethcoal->tx_max_coalesced_frames_low || + ethcoal->pkt_rate_high || + ethcoal->rx_coalesce_usecs_high || + ethcoal->rx_max_coalesced_frames_high || + ethcoal->tx_coalesce_usecs_high || + ethcoal->tx_max_coalesced_frames_high) + return -EINVAL; + + if (!ethcoal->rx_coalesce_usecs || + !ethcoal->rx_max_coalesced_frames) { + adapter->coal.flags = QLCNIC_INTR_DEFAULT; + adapter->coal.normal.data.rx_time_us = + QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; + adapter->coal.normal.data.rx_packets = + QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; + } else { + adapter->coal.flags = 0; + adapter->coal.normal.data.rx_time_us = + ethcoal->rx_coalesce_usecs; + adapter->coal.normal.data.rx_packets = + ethcoal->rx_max_coalesced_frames; + } + adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs; + adapter->coal.normal.data.tx_packets = + ethcoal->tx_max_coalesced_frames; + + qlcnic_config_intr_coalesce(adapter); + + return 0; +} + +static int qlcnic_get_intr_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ethcoal) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return -EINVAL; + + ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us; + ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us; + ethcoal->rx_max_coalesced_frames = + adapter->coal.normal.data.rx_packets; + ethcoal->tx_max_coalesced_frames = + adapter->coal.normal.data.tx_packets; + + return 0; +} + +static int qlcnic_set_flags(struct net_device *netdev, u32 data) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int hw_lro; + + if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)) + return -EINVAL; + + ethtool_op_set_flags(netdev, data); + + hw_lro = (data & ETH_FLAG_LRO) ? QLCNIC_LRO_ENABLED : 0; + + if (qlcnic_config_hw_lro(adapter, hw_lro)) + return -EIO; + + if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter)) + return -EIO; + + + return 0; +} + +const struct ethtool_ops qlcnic_ethtool_ops = { + .get_settings = qlcnic_get_settings, + .set_settings = qlcnic_set_settings, + .get_drvinfo = qlcnic_get_drvinfo, + .get_regs_len = qlcnic_get_regs_len, + .get_regs = qlcnic_get_regs, + .get_link = ethtool_op_get_link, + .get_eeprom_len = qlcnic_get_eeprom_len, + .get_eeprom = qlcnic_get_eeprom, + .get_ringparam = qlcnic_get_ringparam, + .set_ringparam = qlcnic_set_ringparam, + .get_pauseparam = qlcnic_get_pauseparam, + .set_pauseparam = qlcnic_set_pauseparam, + .set_tx_csum = ethtool_op_set_tx_csum, + .set_sg = ethtool_op_set_sg, + .get_tso = qlcnic_get_tso, + .set_tso = qlcnic_set_tso, + .get_wol = qlcnic_get_wol, + .set_wol = qlcnic_set_wol, + .self_test = qlcnic_diag_test, + .get_strings = qlcnic_get_strings, + .get_ethtool_stats = qlcnic_get_ethtool_stats, + .get_sset_count = qlcnic_get_sset_count, + .get_rx_csum = qlcnic_get_rx_csum, + .set_rx_csum = qlcnic_set_rx_csum, + .get_coalesce = qlcnic_get_intr_coalesce, + .set_coalesce = qlcnic_set_intr_coalesce, + .get_flags = ethtool_op_get_flags, + .set_flags = qlcnic_set_flags, +}; diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h new file mode 100644 index 000000000000..0469f84360a4 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_hdr.h @@ -0,0 +1,937 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#ifndef __QLCNIC_HDR_H_ +#define __QLCNIC_HDR_H_ + +#include +#include + +/* + * The basic unit of access when reading/writing control registers. + */ + +enum { + QLCNIC_HW_H0_CH_HUB_ADR = 0x05, + QLCNIC_HW_H1_CH_HUB_ADR = 0x0E, + QLCNIC_HW_H2_CH_HUB_ADR = 0x03, + QLCNIC_HW_H3_CH_HUB_ADR = 0x01, + QLCNIC_HW_H4_CH_HUB_ADR = 0x06, + QLCNIC_HW_H5_CH_HUB_ADR = 0x07, + QLCNIC_HW_H6_CH_HUB_ADR = 0x08 +}; + +/* Hub 0 */ +enum { + QLCNIC_HW_MN_CRB_AGT_ADR = 0x15, + QLCNIC_HW_MS_CRB_AGT_ADR = 0x25 +}; + +/* Hub 1 */ +enum { + QLCNIC_HW_PS_CRB_AGT_ADR = 0x73, + QLCNIC_HW_SS_CRB_AGT_ADR = 0x20, + QLCNIC_HW_RPMX3_CRB_AGT_ADR = 0x0b, + QLCNIC_HW_QMS_CRB_AGT_ADR = 0x00, + QLCNIC_HW_SQGS0_CRB_AGT_ADR = 0x01, + QLCNIC_HW_SQGS1_CRB_AGT_ADR = 0x02, + QLCNIC_HW_SQGS2_CRB_AGT_ADR = 0x03, + QLCNIC_HW_SQGS3_CRB_AGT_ADR = 0x04, + QLCNIC_HW_C2C0_CRB_AGT_ADR = 0x58, + QLCNIC_HW_C2C1_CRB_AGT_ADR = 0x59, + QLCNIC_HW_C2C2_CRB_AGT_ADR = 0x5a, + QLCNIC_HW_RPMX2_CRB_AGT_ADR = 0x0a, + QLCNIC_HW_RPMX4_CRB_AGT_ADR = 0x0c, + QLCNIC_HW_RPMX7_CRB_AGT_ADR = 0x0f, + QLCNIC_HW_RPMX9_CRB_AGT_ADR = 0x12, + QLCNIC_HW_SMB_CRB_AGT_ADR = 0x18 +}; + +/* Hub 2 */ +enum { + QLCNIC_HW_NIU_CRB_AGT_ADR = 0x31, + QLCNIC_HW_I2C0_CRB_AGT_ADR = 0x19, + QLCNIC_HW_I2C1_CRB_AGT_ADR = 0x29, + + QLCNIC_HW_SN_CRB_AGT_ADR = 0x10, + QLCNIC_HW_I2Q_CRB_AGT_ADR = 0x20, + QLCNIC_HW_LPC_CRB_AGT_ADR = 0x22, + QLCNIC_HW_ROMUSB_CRB_AGT_ADR = 0x21, + QLCNIC_HW_QM_CRB_AGT_ADR = 0x66, + QLCNIC_HW_SQG0_CRB_AGT_ADR = 0x60, + QLCNIC_HW_SQG1_CRB_AGT_ADR = 0x61, + QLCNIC_HW_SQG2_CRB_AGT_ADR = 0x62, + QLCNIC_HW_SQG3_CRB_AGT_ADR = 0x63, + QLCNIC_HW_RPMX1_CRB_AGT_ADR = 0x09, + QLCNIC_HW_RPMX5_CRB_AGT_ADR = 0x0d, + QLCNIC_HW_RPMX6_CRB_AGT_ADR = 0x0e, + QLCNIC_HW_RPMX8_CRB_AGT_ADR = 0x11 +}; + +/* Hub 3 */ +enum { + QLCNIC_HW_PH_CRB_AGT_ADR = 0x1A, + QLCNIC_HW_SRE_CRB_AGT_ADR = 0x50, + QLCNIC_HW_EG_CRB_AGT_ADR = 0x51, + QLCNIC_HW_RPMX0_CRB_AGT_ADR = 0x08 +}; + +/* Hub 4 */ +enum { + QLCNIC_HW_PEGN0_CRB_AGT_ADR = 0x40, + QLCNIC_HW_PEGN1_CRB_AGT_ADR, + QLCNIC_HW_PEGN2_CRB_AGT_ADR, + QLCNIC_HW_PEGN3_CRB_AGT_ADR, + QLCNIC_HW_PEGNI_CRB_AGT_ADR, + QLCNIC_HW_PEGND_CRB_AGT_ADR, + QLCNIC_HW_PEGNC_CRB_AGT_ADR, + QLCNIC_HW_PEGR0_CRB_AGT_ADR, + QLCNIC_HW_PEGR1_CRB_AGT_ADR, + QLCNIC_HW_PEGR2_CRB_AGT_ADR, + QLCNIC_HW_PEGR3_CRB_AGT_ADR, + QLCNIC_HW_PEGN4_CRB_AGT_ADR +}; + +/* Hub 5 */ +enum { + QLCNIC_HW_PEGS0_CRB_AGT_ADR = 0x40, + QLCNIC_HW_PEGS1_CRB_AGT_ADR, + QLCNIC_HW_PEGS2_CRB_AGT_ADR, + QLCNIC_HW_PEGS3_CRB_AGT_ADR, + QLCNIC_HW_PEGSI_CRB_AGT_ADR, + QLCNIC_HW_PEGSD_CRB_AGT_ADR, + QLCNIC_HW_PEGSC_CRB_AGT_ADR +}; + +/* Hub 6 */ +enum { + QLCNIC_HW_CAS0_CRB_AGT_ADR = 0x46, + QLCNIC_HW_CAS1_CRB_AGT_ADR = 0x47, + QLCNIC_HW_CAS2_CRB_AGT_ADR = 0x48, + QLCNIC_HW_CAS3_CRB_AGT_ADR = 0x49, + QLCNIC_HW_NCM_CRB_AGT_ADR = 0x16, + QLCNIC_HW_TMR_CRB_AGT_ADR = 0x17, + QLCNIC_HW_XDMA_CRB_AGT_ADR = 0x05, + QLCNIC_HW_OCM0_CRB_AGT_ADR = 0x06, + QLCNIC_HW_OCM1_CRB_AGT_ADR = 0x07 +}; + +/* Floaters - non existent modules */ +#define QLCNIC_HW_EFC_RPMX0_CRB_AGT_ADR 0x67 + +/* This field defines PCI/X adr [25:20] of agents on the CRB */ +enum { + QLCNIC_HW_PX_MAP_CRB_PH = 0, + QLCNIC_HW_PX_MAP_CRB_PS, + QLCNIC_HW_PX_MAP_CRB_MN, + QLCNIC_HW_PX_MAP_CRB_MS, + QLCNIC_HW_PX_MAP_CRB_PGR1, + QLCNIC_HW_PX_MAP_CRB_SRE, + QLCNIC_HW_PX_MAP_CRB_NIU, + QLCNIC_HW_PX_MAP_CRB_QMN, + QLCNIC_HW_PX_MAP_CRB_SQN0, + QLCNIC_HW_PX_MAP_CRB_SQN1, + QLCNIC_HW_PX_MAP_CRB_SQN2, + QLCNIC_HW_PX_MAP_CRB_SQN3, + QLCNIC_HW_PX_MAP_CRB_QMS, + QLCNIC_HW_PX_MAP_CRB_SQS0, + QLCNIC_HW_PX_MAP_CRB_SQS1, + QLCNIC_HW_PX_MAP_CRB_SQS2, + QLCNIC_HW_PX_MAP_CRB_SQS3, + QLCNIC_HW_PX_MAP_CRB_PGN0, + QLCNIC_HW_PX_MAP_CRB_PGN1, + QLCNIC_HW_PX_MAP_CRB_PGN2, + QLCNIC_HW_PX_MAP_CRB_PGN3, + QLCNIC_HW_PX_MAP_CRB_PGND, + QLCNIC_HW_PX_MAP_CRB_PGNI, + QLCNIC_HW_PX_MAP_CRB_PGS0, + QLCNIC_HW_PX_MAP_CRB_PGS1, + QLCNIC_HW_PX_MAP_CRB_PGS2, + QLCNIC_HW_PX_MAP_CRB_PGS3, + QLCNIC_HW_PX_MAP_CRB_PGSD, + QLCNIC_HW_PX_MAP_CRB_PGSI, + QLCNIC_HW_PX_MAP_CRB_SN, + QLCNIC_HW_PX_MAP_CRB_PGR2, + QLCNIC_HW_PX_MAP_CRB_EG, + QLCNIC_HW_PX_MAP_CRB_PH2, + QLCNIC_HW_PX_MAP_CRB_PS2, + QLCNIC_HW_PX_MAP_CRB_CAM, + QLCNIC_HW_PX_MAP_CRB_CAS0, + QLCNIC_HW_PX_MAP_CRB_CAS1, + QLCNIC_HW_PX_MAP_CRB_CAS2, + QLCNIC_HW_PX_MAP_CRB_C2C0, + QLCNIC_HW_PX_MAP_CRB_C2C1, + QLCNIC_HW_PX_MAP_CRB_TIMR, + QLCNIC_HW_PX_MAP_CRB_PGR3, + QLCNIC_HW_PX_MAP_CRB_RPMX1, + QLCNIC_HW_PX_MAP_CRB_RPMX2, + QLCNIC_HW_PX_MAP_CRB_RPMX3, + QLCNIC_HW_PX_MAP_CRB_RPMX4, + QLCNIC_HW_PX_MAP_CRB_RPMX5, + QLCNIC_HW_PX_MAP_CRB_RPMX6, + QLCNIC_HW_PX_MAP_CRB_RPMX7, + QLCNIC_HW_PX_MAP_CRB_XDMA, + QLCNIC_HW_PX_MAP_CRB_I2Q, + QLCNIC_HW_PX_MAP_CRB_ROMUSB, + QLCNIC_HW_PX_MAP_CRB_CAS3, + QLCNIC_HW_PX_MAP_CRB_RPMX0, + QLCNIC_HW_PX_MAP_CRB_RPMX8, + QLCNIC_HW_PX_MAP_CRB_RPMX9, + QLCNIC_HW_PX_MAP_CRB_OCM0, + QLCNIC_HW_PX_MAP_CRB_OCM1, + QLCNIC_HW_PX_MAP_CRB_SMB, + QLCNIC_HW_PX_MAP_CRB_I2C0, + QLCNIC_HW_PX_MAP_CRB_I2C1, + QLCNIC_HW_PX_MAP_CRB_LPC, + QLCNIC_HW_PX_MAP_CRB_PGNC, + QLCNIC_HW_PX_MAP_CRB_PGR0 +}; + +/* This field defines CRB adr [31:20] of the agents */ + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_MN \ + ((QLCNIC_HW_H0_CH_HUB_ADR << 7) | QLCNIC_HW_MN_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PH \ + ((QLCNIC_HW_H0_CH_HUB_ADR << 7) | QLCNIC_HW_PH_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_MS \ + ((QLCNIC_HW_H0_CH_HUB_ADR << 7) | QLCNIC_HW_MS_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PS \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_PS_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SS \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SS_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX3 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX3_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_QMS \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_QMS_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQS0 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SQGS0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQS1 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SQGS1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQS2 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SQGS2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQS3 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SQGS3_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_C2C0 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_C2C0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_C2C1 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_C2C1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX2 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX4 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX4_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX7 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX7_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX9 \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX9_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SMB \ + ((QLCNIC_HW_H1_CH_HUB_ADR << 7) | QLCNIC_HW_SMB_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_NIU \ + ((QLCNIC_HW_H2_CH_HUB_ADR << 7) | QLCNIC_HW_NIU_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_I2C0 \ + ((QLCNIC_HW_H2_CH_HUB_ADR << 7) | QLCNIC_HW_I2C0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_I2C1 \ + ((QLCNIC_HW_H2_CH_HUB_ADR << 7) | QLCNIC_HW_I2C1_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SRE \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_SRE_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_EG \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_EG_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX0 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_QMN \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_QM_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQN0 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_SQG0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQN1 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_SQG1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQN2 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_SQG2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SQN3 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_SQG3_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX1 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX5 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX5_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX6 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX6_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX8 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_RPMX8_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_CAS0 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_CAS0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_CAS1 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_CAS1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_CAS2 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_CAS2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_CAS3 \ + ((QLCNIC_HW_H3_CH_HUB_ADR << 7) | QLCNIC_HW_CAS3_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGNI \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGNI_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGND \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGND_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGN0 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGN0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGN1 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGN1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGN2 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGN2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGN3 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGN3_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGN4 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGN4_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGNC \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGNC_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGR0 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGR0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGR1 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGR1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGR2 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGR2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGR3 \ + ((QLCNIC_HW_H4_CH_HUB_ADR << 7) | QLCNIC_HW_PEGR3_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGSI \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGSI_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGSD \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGSD_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGS0 \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGS0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGS1 \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGS1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGS2 \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGS2_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGS3 \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGS3_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_PGSC \ + ((QLCNIC_HW_H5_CH_HUB_ADR << 7) | QLCNIC_HW_PEGSC_CRB_AGT_ADR) + +#define QLCNIC_HW_CRB_HUB_AGT_ADR_CAM \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_NCM_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_TMR_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_XDMA_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_SN \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_SN_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_I2Q_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_ROMUSB_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_OCM0 \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_OCM0_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_OCM1 \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_OCM1_CRB_AGT_ADR) +#define QLCNIC_HW_CRB_HUB_AGT_ADR_LPC \ + ((QLCNIC_HW_H6_CH_HUB_ADR << 7) | QLCNIC_HW_LPC_CRB_AGT_ADR) + +#define QLCNIC_SRE_MISC (QLCNIC_CRB_SRE + 0x0002c) + +#define QLCNIC_I2Q_CLR_PCI_HI (QLCNIC_CRB_I2Q + 0x00034) + +#define ROMUSB_GLB (QLCNIC_CRB_ROMUSB + 0x00000) +#define ROMUSB_ROM (QLCNIC_CRB_ROMUSB + 0x10000) + +#define QLCNIC_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004) +#define QLCNIC_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008) +#define QLCNIC_ROMUSB_GLB_PAD_GPIO_I (ROMUSB_GLB + 0x000c) +#define QLCNIC_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038) +#define QLCNIC_ROMUSB_GLB_TEST_MUX_SEL (ROMUSB_GLB + 0x0044) +#define QLCNIC_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c) +#define QLCNIC_ROMUSB_GLB_CHIP_CLK_CTRL (ROMUSB_GLB + 0x00A8) + +#define QLCNIC_ROMUSB_GPIO(n) (ROMUSB_GLB + 0x60 + (4 * (n))) + +#define QLCNIC_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) +#define QLCNIC_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) +#define QLCNIC_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c) +#define QLCNIC_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) +#define QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) +#define QLCNIC_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) + +/* Lock IDs for ROM lock */ +#define ROM_LOCK_DRIVER 0x0d417340 + +/****************************************************************************** +* +* Definitions specific to M25P flash +* +******************************************************************************* +*/ + +/* all are 1MB windows */ + +#define QLCNIC_PCI_CRB_WINDOWSIZE 0x00100000 +#define QLCNIC_PCI_CRB_WINDOW(A) \ + (QLCNIC_PCI_CRBSPACE + (A)*QLCNIC_PCI_CRB_WINDOWSIZE) + +#define QLCNIC_CRB_NIU QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_NIU) +#define QLCNIC_CRB_SRE QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SRE) +#define QLCNIC_CRB_ROMUSB \ + QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_ROMUSB) +#define QLCNIC_CRB_I2Q QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_I2Q) +#define QLCNIC_CRB_I2C0 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_I2C0) +#define QLCNIC_CRB_SMB QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SMB) +#define QLCNIC_CRB_MAX QLCNIC_PCI_CRB_WINDOW(64) + +#define QLCNIC_CRB_PCIX_HOST QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PH) +#define QLCNIC_CRB_PCIX_HOST2 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PH2) +#define QLCNIC_CRB_PEG_NET_0 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGN0) +#define QLCNIC_CRB_PEG_NET_1 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGN1) +#define QLCNIC_CRB_PEG_NET_2 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGN2) +#define QLCNIC_CRB_PEG_NET_3 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGN3) +#define QLCNIC_CRB_PEG_NET_4 QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SQS2) +#define QLCNIC_CRB_PEG_NET_D QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGND) +#define QLCNIC_CRB_PEG_NET_I QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PGNI) +#define QLCNIC_CRB_DDR_NET QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_MN) +#define QLCNIC_CRB_QDR_NET QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_SN) + +#define QLCNIC_CRB_PCIX_MD QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_PS) +#define QLCNIC_CRB_PCIE QLCNIC_CRB_PCIX_MD + +#define ISR_INT_VECTOR (QLCNIC_PCIX_PS_REG(PCIX_INT_VECTOR)) +#define ISR_INT_MASK (QLCNIC_PCIX_PS_REG(PCIX_INT_MASK)) +#define ISR_INT_MASK_SLOW (QLCNIC_PCIX_PS_REG(PCIX_INT_MASK)) +#define ISR_INT_TARGET_STATUS (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS)) +#define ISR_INT_TARGET_MASK (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK)) +#define ISR_INT_TARGET_STATUS_F1 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F1)) +#define ISR_INT_TARGET_MASK_F1 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F1)) +#define ISR_INT_TARGET_STATUS_F2 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F2)) +#define ISR_INT_TARGET_MASK_F2 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F2)) +#define ISR_INT_TARGET_STATUS_F3 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F3)) +#define ISR_INT_TARGET_MASK_F3 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F3)) +#define ISR_INT_TARGET_STATUS_F4 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F4)) +#define ISR_INT_TARGET_MASK_F4 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F4)) +#define ISR_INT_TARGET_STATUS_F5 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F5)) +#define ISR_INT_TARGET_MASK_F5 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F5)) +#define ISR_INT_TARGET_STATUS_F6 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F6)) +#define ISR_INT_TARGET_MASK_F6 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F6)) +#define ISR_INT_TARGET_STATUS_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) +#define ISR_INT_TARGET_MASK_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) + +#define QLCNIC_PCI_MN_2M (0) +#define QLCNIC_PCI_MS_2M (0x80000) +#define QLCNIC_PCI_OCM0_2M (0x000c0000UL) +#define QLCNIC_PCI_CRBSPACE (0x06000000UL) +#define QLCNIC_PCI_2MB_SIZE (0x00200000UL) +#define QLCNIC_PCI_CAMQM_2M_BASE (0x000ff800UL) +#define QLCNIC_PCI_CAMQM_2M_END (0x04800800UL) + +#define QLCNIC_CRB_CAM QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_CAM) + +#define QLCNIC_ADDR_DDR_NET (0x0000000000000000ULL) +#define QLCNIC_ADDR_DDR_NET_MAX (0x000000000fffffffULL) +#define QLCNIC_ADDR_OCM0 (0x0000000200000000ULL) +#define QLCNIC_ADDR_OCM0_MAX (0x00000002000fffffULL) +#define QLCNIC_ADDR_OCM1 (0x0000000200400000ULL) +#define QLCNIC_ADDR_OCM1_MAX (0x00000002004fffffULL) +#define QLCNIC_ADDR_QDR_NET (0x0000000300000000ULL) +#define QLCNIC_ADDR_QDR_NET_MAX_P3 (0x0000000303ffffffULL) + +/* + * Register offsets for MN + */ +#define QLCNIC_MIU_CONTROL (0x000) +#define QLCNIC_MIU_MN_CONTROL (QLCNIC_CRB_DDR_NET+QLCNIC_MIU_CONTROL) + +/* 200ms delay in each loop */ +#define QLCNIC_NIU_PHY_WAITLEN 200000 +/* 10 seconds before we give up */ +#define QLCNIC_NIU_PHY_WAITMAX 50 +#define QLCNIC_NIU_MAX_GBE_PORTS 4 +#define QLCNIC_NIU_MAX_XG_PORTS 2 + +#define QLCNIC_NIU_MODE (QLCNIC_CRB_NIU + 0x00000) +#define QLCNIC_NIU_GB_PAUSE_CTL (QLCNIC_CRB_NIU + 0x0030c) +#define QLCNIC_NIU_XG_PAUSE_CTL (QLCNIC_CRB_NIU + 0x00098) + +#define QLCNIC_NIU_GB_MAC_CONFIG_0(I) \ + (QLCNIC_CRB_NIU + 0x30000 + (I)*0x10000) +#define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \ + (QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000) + + +#define TEST_AGT_CTRL (0x00) + +#define TA_CTL_START 1 +#define TA_CTL_ENABLE 2 +#define TA_CTL_WRITE 4 +#define TA_CTL_BUSY 8 + +/* + * Register offsets for MN + */ +#define MIU_TEST_AGT_BASE (0x90) + +#define MIU_TEST_AGT_ADDR_LO (0x04) +#define MIU_TEST_AGT_ADDR_HI (0x08) +#define MIU_TEST_AGT_WRDATA_LO (0x10) +#define MIU_TEST_AGT_WRDATA_HI (0x14) +#define MIU_TEST_AGT_WRDATA_UPPER_LO (0x20) +#define MIU_TEST_AGT_WRDATA_UPPER_HI (0x24) +#define MIU_TEST_AGT_WRDATA(i) (0x10+(0x10*((i)>>1))+(4*((i)&1))) +#define MIU_TEST_AGT_RDDATA_LO (0x18) +#define MIU_TEST_AGT_RDDATA_HI (0x1c) +#define MIU_TEST_AGT_RDDATA_UPPER_LO (0x28) +#define MIU_TEST_AGT_RDDATA_UPPER_HI (0x2c) +#define MIU_TEST_AGT_RDDATA(i) (0x18+(0x10*((i)>>1))+(4*((i)&1))) + +#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 +#define MIU_TEST_AGT_UPPER_ADDR(off) (0) + +/* + * Register offsets for MS + */ +#define SIU_TEST_AGT_BASE (0x60) + +#define SIU_TEST_AGT_ADDR_LO (0x04) +#define SIU_TEST_AGT_ADDR_HI (0x18) +#define SIU_TEST_AGT_WRDATA_LO (0x08) +#define SIU_TEST_AGT_WRDATA_HI (0x0c) +#define SIU_TEST_AGT_WRDATA(i) (0x08+(4*(i))) +#define SIU_TEST_AGT_RDDATA_LO (0x10) +#define SIU_TEST_AGT_RDDATA_HI (0x14) +#define SIU_TEST_AGT_RDDATA(i) (0x10+(4*(i))) + +#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8 +#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22) + +/* XG Link status */ +#define XG_LINK_UP 0x10 +#define XG_LINK_DOWN 0x20 + +#define XG_LINK_UP_P3 0x01 +#define XG_LINK_DOWN_P3 0x02 +#define XG_LINK_STATE_P3_MASK 0xf +#define XG_LINK_STATE_P3(pcifn, val) \ + (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK) + +#define P3_LINK_SPEED_MHZ 100 +#define P3_LINK_SPEED_MASK 0xff +#define P3_LINK_SPEED_REG(pcifn) \ + (CRB_PF_LINK_SPEED_1 + (((pcifn) / 4) * 4)) +#define P3_LINK_SPEED_VAL(pcifn, reg) \ + (((reg) >> (8 * ((pcifn) & 0x3))) & P3_LINK_SPEED_MASK) + +#define QLCNIC_CAM_RAM_BASE (QLCNIC_CRB_CAM + 0x02000) +#define QLCNIC_CAM_RAM(reg) (QLCNIC_CAM_RAM_BASE + (reg)) +#define QLCNIC_FW_VERSION_MAJOR (QLCNIC_CAM_RAM(0x150)) +#define QLCNIC_FW_VERSION_MINOR (QLCNIC_CAM_RAM(0x154)) +#define QLCNIC_FW_VERSION_SUB (QLCNIC_CAM_RAM(0x158)) +#define QLCNIC_ROM_LOCK_ID (QLCNIC_CAM_RAM(0x100)) +#define QLCNIC_PHY_LOCK_ID (QLCNIC_CAM_RAM(0x120)) +#define QLCNIC_CRB_WIN_LOCK_ID (QLCNIC_CAM_RAM(0x124)) + +#define NIC_CRB_BASE (QLCNIC_CAM_RAM(0x200)) +#define NIC_CRB_BASE_2 (QLCNIC_CAM_RAM(0x700)) +#define QLCNIC_REG(X) (NIC_CRB_BASE+(X)) +#define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X)) + +#define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18)) +#define QLCNIC_ARG1_CRB_OFFSET (QLCNIC_REG(0x1c)) +#define QLCNIC_ARG2_CRB_OFFSET (QLCNIC_REG(0x20)) +#define QLCNIC_ARG3_CRB_OFFSET (QLCNIC_REG(0x24)) +#define QLCNIC_SIGN_CRB_OFFSET (QLCNIC_REG(0x28)) + +#define CRB_CMDPEG_STATE (QLCNIC_REG(0x50)) +#define CRB_RCVPEG_STATE (QLCNIC_REG(0x13c)) + +#define CRB_XG_STATE_P3 (QLCNIC_REG(0x98)) +#define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8)) +#define CRB_PF_LINK_SPEED_2 (QLCNIC_REG(0xec)) + +#define CRB_MPORT_MODE (QLCNIC_REG(0xc4)) +#define CRB_DMA_SHIFT (QLCNIC_REG(0xcc)) + +#define CRB_TEMP_STATE (QLCNIC_REG(0x1b4)) + +#define CRB_V2P_0 (QLCNIC_REG(0x290)) +#define CRB_V2P(port) (CRB_V2P_0+((port)*4)) +#define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0)) + +#define CRB_SW_INT_MASK_0 (QLCNIC_REG(0x1d8)) +#define CRB_SW_INT_MASK_1 (QLCNIC_REG(0x1e0)) +#define CRB_SW_INT_MASK_2 (QLCNIC_REG(0x1e4)) +#define CRB_SW_INT_MASK_3 (QLCNIC_REG(0x1e8)) + +#define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128)) +#define CRB_MAC_BLOCK_START (QLCNIC_CAM_RAM(0x1c0)) + +/* + * capabilities register, can be used to selectively enable/disable features + * for backward compability + */ +#define CRB_NIC_CAPABILITIES_HOST QLCNIC_REG(0x1a8) +#define CRB_NIC_CAPABILITIES_FW QLCNIC_REG(0x1dc) +#define CRB_NIC_MSI_MODE_HOST QLCNIC_REG(0x270) +#define CRB_NIC_MSI_MODE_FW QLCNIC_REG(0x274) + +#define INTR_SCHEME_PERPORT 0x1 +#define MSI_MODE_MULTIFUNC 0x1 + +/* used for ethtool tests */ +#define CRB_SCRATCHPAD_TEST QLCNIC_REG(0x280) + +/* + * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address + * which can be read by the Phantom host to get producer/consumer indexes from + * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following + * registers will be used for the addresses of the ring's shared memory + * on the Phantom. + */ + +#define qlcnic_get_temp_val(x) ((x) >> 16) +#define qlcnic_get_temp_state(x) ((x) & 0xffff) +#define qlcnic_encode_temp(val, state) (((val) << 16) | (state)) + +/* + * Temperature control. + */ +enum { + QLCNIC_TEMP_NORMAL = 0x1, /* Normal operating range */ + QLCNIC_TEMP_WARN, /* Sound alert, temperature getting high */ + QLCNIC_TEMP_PANIC /* Fatal error, hardware has shut down. */ +}; + +/* Lock IDs for PHY lock */ +#define PHY_LOCK_DRIVER 0x44524956 + +/* Used for PS PCI Memory access */ +#define PCIX_PS_OP_ADDR_LO (0x10000) +/* via CRB (PS side only) */ +#define PCIX_PS_OP_ADDR_HI (0x10004) + +#define PCIX_INT_VECTOR (0x10100) +#define PCIX_INT_MASK (0x10104) + +#define PCIX_OCM_WINDOW (0x10800) +#define PCIX_OCM_WINDOW_REG(func) (PCIX_OCM_WINDOW + 0x20 * (func)) + +#define PCIX_TARGET_STATUS (0x10118) +#define PCIX_TARGET_STATUS_F1 (0x10160) +#define PCIX_TARGET_STATUS_F2 (0x10164) +#define PCIX_TARGET_STATUS_F3 (0x10168) +#define PCIX_TARGET_STATUS_F4 (0x10360) +#define PCIX_TARGET_STATUS_F5 (0x10364) +#define PCIX_TARGET_STATUS_F6 (0x10368) +#define PCIX_TARGET_STATUS_F7 (0x1036c) + +#define PCIX_TARGET_MASK (0x10128) +#define PCIX_TARGET_MASK_F1 (0x10170) +#define PCIX_TARGET_MASK_F2 (0x10174) +#define PCIX_TARGET_MASK_F3 (0x10178) +#define PCIX_TARGET_MASK_F4 (0x10370) +#define PCIX_TARGET_MASK_F5 (0x10374) +#define PCIX_TARGET_MASK_F6 (0x10378) +#define PCIX_TARGET_MASK_F7 (0x1037c) + +#define PCIX_MSI_F(i) (0x13000+((i)*4)) + +#define QLCNIC_PCIX_PH_REG(reg) (QLCNIC_CRB_PCIE + (reg)) +#define QLCNIC_PCIX_PS_REG(reg) (QLCNIC_CRB_PCIX_MD + (reg)) +#define QLCNIC_PCIE_REG(reg) (QLCNIC_CRB_PCIE + (reg)) + +#define PCIE_SEM0_LOCK (0x1c000) +#define PCIE_SEM0_UNLOCK (0x1c004) +#define PCIE_SEM_LOCK(N) (PCIE_SEM0_LOCK + 8*(N)) +#define PCIE_SEM_UNLOCK(N) (PCIE_SEM0_UNLOCK + 8*(N)) + +#define PCIE_SETUP_FUNCTION (0x12040) +#define PCIE_SETUP_FUNCTION2 (0x12048) +#define PCIE_MISCCFG_RC (0x1206c) +#define PCIE_TGT_SPLIT_CHICKEN (0x12080) +#define PCIE_CHICKEN3 (0x120c8) + +#define ISR_INT_STATE_REG (QLCNIC_PCIX_PS_REG(PCIE_MISCCFG_RC)) +#define PCIE_MAX_MASTER_SPLIT (0x14048) + +#define QLCNIC_PORT_MODE_NONE 0 +#define QLCNIC_PORT_MODE_XG 1 +#define QLCNIC_PORT_MODE_GB 2 +#define QLCNIC_PORT_MODE_802_3_AP 3 +#define QLCNIC_PORT_MODE_AUTO_NEG 4 +#define QLCNIC_PORT_MODE_AUTO_NEG_1G 5 +#define QLCNIC_PORT_MODE_AUTO_NEG_XG 6 +#define QLCNIC_PORT_MODE_ADDR (QLCNIC_CAM_RAM(0x24)) +#define QLCNIC_WOL_PORT_MODE (QLCNIC_CAM_RAM(0x198)) + +#define QLCNIC_WOL_CONFIG_NV (QLCNIC_CAM_RAM(0x184)) +#define QLCNIC_WOL_CONFIG (QLCNIC_CAM_RAM(0x188)) + +#define QLCNIC_PEG_TUNE_MN_PRESENT 0x1 +#define QLCNIC_PEG_TUNE_CAPABILITY (QLCNIC_CAM_RAM(0x02c)) + +#define QLCNIC_DMA_WATCHDOG_CTRL (QLCNIC_CAM_RAM(0x14)) +#define QLCNIC_PEG_ALIVE_COUNTER (QLCNIC_CAM_RAM(0xb0)) +#define QLCNIC_PEG_HALT_STATUS1 (QLCNIC_CAM_RAM(0xa8)) +#define QLCNIC_PEG_HALT_STATUS2 (QLCNIC_CAM_RAM(0xac)) +#define QLCNIC_CRB_DEV_REF_COUNT (QLCNIC_CAM_RAM(0x138)) +#define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140)) + +#define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144)) +#define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148)) +#define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c)) +#define QLCNIC_CRB_DRV_IDC_VER (QLCNIC_CAM_RAM(0x14c)) + + /* Device State */ +#define QLCNIC_DEV_COLD 1 +#define QLCNIC_DEV_INITALIZING 2 +#define QLCNIC_DEV_READY 3 +#define QLCNIC_DEV_NEED_RESET 4 +#define QLCNIC_DEV_NEED_QUISCENT 5 +#define QLCNIC_DEV_FAILED 6 + +#define QLCNIC_RCODE_DRIVER_INFO 0x20000000 +#define QLCNIC_RCODE_DRIVER_CAN_RELOAD 0x40000000 +#define QLCNIC_RCODE_FATAL_ERROR 0x80000000 +#define QLCNIC_FWERROR_PEGNUM(code) ((code) & 0xff) +#define QLCNIC_FWERROR_CODE(code) ((code >> 8) & 0xfffff) + +#define FW_POLL_DELAY (2 * HZ) +#define FW_FAIL_THRESH 3 +#define FW_POLL_THRESH 10 + +#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) +#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) + +/* + * PCI Interrupt Vector Values. + */ +#define PCIX_INT_VECTOR_BIT_F0 0x0080 +#define PCIX_INT_VECTOR_BIT_F1 0x0100 +#define PCIX_INT_VECTOR_BIT_F2 0x0200 +#define PCIX_INT_VECTOR_BIT_F3 0x0400 +#define PCIX_INT_VECTOR_BIT_F4 0x0800 +#define PCIX_INT_VECTOR_BIT_F5 0x1000 +#define PCIX_INT_VECTOR_BIT_F6 0x2000 +#define PCIX_INT_VECTOR_BIT_F7 0x4000 + +struct qlcnic_legacy_intr_set { + u32 int_vec_bit; + u32 tgt_status_reg; + u32 tgt_mask_reg; + u32 pci_int_reg; +}; + +#define QLCNIC_LEGACY_INTR_CONFIG \ +{ \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \ + \ + { \ + .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \ + .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \ + .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \ + .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \ +} + +/* NIU REGS */ + +#define _qlcnic_crb_get_bit(var, bit) ((var >> bit) & 0x1) + +/* + * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3) + * + * Bit 0 : enable_tx => 1:enable frame xmit, 0:disable + * Bit 1 : tx_synced => R/O: xmit enable synched to xmit stream + * Bit 2 : enable_rx => 1:enable frame recv, 0:disable + * Bit 3 : rx_synced => R/O: recv enable synched to recv stream + * Bit 4 : tx_flowctl => 1:enable pause frame generation, 0:disable + * Bit 5 : rx_flowctl => 1:act on recv'd pause frames, 0:ignore + * Bit 8 : loopback => 1:loop MAC xmits to MAC recvs, 0:normal + * Bit 16: tx_reset_pb => 1:reset frame xmit protocol blk, 0:no-op + * Bit 17: rx_reset_pb => 1:reset frame recv protocol blk, 0:no-op + * Bit 18: tx_reset_mac => 1:reset data/ctl multiplexer blk, 0:no-op + * Bit 19: rx_reset_mac => 1:reset ctl frames & timers blk, 0:no-op + * Bit 31: soft_reset => 1:reset the MAC and the SERDES, 0:no-op + */ +#define qlcnic_gb_rx_flowctl(config_word) \ + ((config_word) |= 1 << 5) +#define qlcnic_gb_get_rx_flowctl(config_word) \ + _qlcnic_crb_get_bit((config_word), 5) +#define qlcnic_gb_unset_rx_flowctl(config_word) \ + ((config_word) &= ~(1 << 5)) + +/* + * NIU GB Pause Ctl Register + */ + +#define qlcnic_gb_set_gb0_mask(config_word) \ + ((config_word) |= 1 << 0) +#define qlcnic_gb_set_gb1_mask(config_word) \ + ((config_word) |= 1 << 2) +#define qlcnic_gb_set_gb2_mask(config_word) \ + ((config_word) |= 1 << 4) +#define qlcnic_gb_set_gb3_mask(config_word) \ + ((config_word) |= 1 << 6) + +#define qlcnic_gb_get_gb0_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 0) +#define qlcnic_gb_get_gb1_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 2) +#define qlcnic_gb_get_gb2_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 4) +#define qlcnic_gb_get_gb3_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 6) + +#define qlcnic_gb_unset_gb0_mask(config_word) \ + ((config_word) &= ~(1 << 0)) +#define qlcnic_gb_unset_gb1_mask(config_word) \ + ((config_word) &= ~(1 << 2)) +#define qlcnic_gb_unset_gb2_mask(config_word) \ + ((config_word) &= ~(1 << 4)) +#define qlcnic_gb_unset_gb3_mask(config_word) \ + ((config_word) &= ~(1 << 6)) + +/* + * NIU XG Pause Ctl Register + * + * Bit 0 : xg0_mask => 1:disable tx pause frames + * Bit 1 : xg0_request => 1:request single pause frame + * Bit 2 : xg0_on_off => 1:request is pause on, 0:off + * Bit 3 : xg1_mask => 1:disable tx pause frames + * Bit 4 : xg1_request => 1:request single pause frame + * Bit 5 : xg1_on_off => 1:request is pause on, 0:off + */ + +#define qlcnic_xg_set_xg0_mask(config_word) \ + ((config_word) |= 1 << 0) +#define qlcnic_xg_set_xg1_mask(config_word) \ + ((config_word) |= 1 << 3) + +#define qlcnic_xg_get_xg0_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 0) +#define qlcnic_xg_get_xg1_mask(config_word) \ + _qlcnic_crb_get_bit((config_word), 3) + +#define qlcnic_xg_unset_xg0_mask(config_word) \ + ((config_word) &= ~(1 << 0)) +#define qlcnic_xg_unset_xg1_mask(config_word) \ + ((config_word) &= ~(1 << 3)) + +/* + * NIU XG Pause Ctl Register + * + * Bit 0 : xg0_mask => 1:disable tx pause frames + * Bit 1 : xg0_request => 1:request single pause frame + * Bit 2 : xg0_on_off => 1:request is pause on, 0:off + * Bit 3 : xg1_mask => 1:disable tx pause frames + * Bit 4 : xg1_request => 1:request single pause frame + * Bit 5 : xg1_on_off => 1:request is pause on, 0:off + */ + +/* + * PHY-Specific MII control/status registers. + */ +#define QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG 4 +#define QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS 17 + +/* + * PHY-Specific Status Register (reg 17). + * + * Bit 0 : jabber => 1:jabber detected, 0:not + * Bit 1 : polarity => 1:polarity reversed, 0:normal + * Bit 2 : recvpause => 1:receive pause enabled, 0:disabled + * Bit 3 : xmitpause => 1:transmit pause enabled, 0:disabled + * Bit 4 : energydetect => 1:sleep, 0:active + * Bit 5 : downshift => 1:downshift, 0:no downshift + * Bit 6 : crossover => 1:MDIX (crossover), 0:MDI (no crossover) + * Bits 7-9 : cablelen => not valid in 10Mb/s mode + * 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m + * Bit 10 : link => 1:link up, 0:link down + * Bit 11 : resolved => 1:speed and duplex resolved, 0:not yet + * Bit 12 : pagercvd => 1:page received, 0:page not received + * Bit 13 : duplex => 1:full duplex, 0:half duplex + * Bits 14-15 : speed => 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd + */ + +#define qlcnic_get_phy_speed(config_word) (((config_word) >> 14) & 0x03) + +#define qlcnic_set_phy_speed(config_word, val) \ + ((config_word) |= ((val & 0x03) << 14)) +#define qlcnic_set_phy_duplex(config_word) \ + ((config_word) |= 1 << 13) +#define qlcnic_clear_phy_duplex(config_word) \ + ((config_word) &= ~(1 << 13)) + +#define qlcnic_get_phy_link(config_word) \ + _qlcnic_crb_get_bit(config_word, 10) +#define qlcnic_get_phy_duplex(config_word) \ + _qlcnic_crb_get_bit(config_word, 13) + +#define QLCNIC_NIU_NON_PROMISC_MODE 0 +#define QLCNIC_NIU_PROMISC_MODE 1 +#define QLCNIC_NIU_ALLMULTI_MODE 2 + +struct crb_128M_2M_sub_block_map { + unsigned valid; + unsigned start_128M; + unsigned end_128M; + unsigned start_2M; +}; + +struct crb_128M_2M_block_map{ + struct crb_128M_2M_sub_block_map sub_block[16]; +}; +#endif /* __QLCNIC_HDR_H_ */ diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c new file mode 100644 index 000000000000..91234e7b39e4 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -0,0 +1,1201 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#include "qlcnic.h" + +#include + +#define MASK(n) ((1ULL<<(n))-1) +#define OCM_WIN_P3P(addr) (addr & 0xffc0000) + +#define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) + +#define CRB_BLK(off) ((off >> 20) & 0x3f) +#define CRB_SUBBLK(off) ((off >> 16) & 0xf) +#define CRB_WINDOW_2M (0x130060) +#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) +#define CRB_INDIRECT_2M (0x1e0000UL) + + +#ifndef readq +static inline u64 readq(void __iomem *addr) +{ + return readl(addr) | (((u64) readl(addr + 4)) << 32LL); +} +#endif + +#ifndef writeq +static inline void writeq(u64 val, void __iomem *addr) +{ + writel(((u32) (val)), (addr)); + writel(((u32) (val >> 32)), (addr + 4)); +} +#endif + +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) < (high)) && ((addr) >= (low))) + +#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base0 + (off)) + +static void __iomem *pci_base_offset(struct qlcnic_adapter *adapter, + unsigned long off) +{ + if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END)) + return PCI_OFFSET_FIRST_RANGE(adapter, off); + + return NULL; +} + +static const struct crb_128M_2M_block_map +crb_128M_2M_map[64] __cacheline_aligned_in_smp = { + {{{0, 0, 0, 0} } }, /* 0: PCI */ + {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ + {1, 0x0110000, 0x0120000, 0x130000}, + {1, 0x0120000, 0x0122000, 0x124000}, + {1, 0x0130000, 0x0132000, 0x126000}, + {1, 0x0140000, 0x0142000, 0x128000}, + {1, 0x0150000, 0x0152000, 0x12a000}, + {1, 0x0160000, 0x0170000, 0x110000}, + {1, 0x0170000, 0x0172000, 0x12e000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x01e0000, 0x01e0800, 0x122000}, + {0, 0x0000000, 0x0000000, 0x000000} } }, + {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ + {{{0, 0, 0, 0} } }, /* 3: */ + {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ + {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ + {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ + {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ + {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x08f0000, 0x08f2000, 0x172000} } }, + {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x09f0000, 0x09f2000, 0x176000} } }, + {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x0af0000, 0x0af2000, 0x17a000} } }, + {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, + {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ + {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ + {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ + {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ + {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ + {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ + {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ + {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ + {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ + {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ + {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ + {{{0, 0, 0, 0} } }, /* 23: */ + {{{0, 0, 0, 0} } }, /* 24: */ + {{{0, 0, 0, 0} } }, /* 25: */ + {{{0, 0, 0, 0} } }, /* 26: */ + {{{0, 0, 0, 0} } }, /* 27: */ + {{{0, 0, 0, 0} } }, /* 28: */ + {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ + {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ + {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ + {{{0} } }, /* 32: PCI */ + {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ + {1, 0x2110000, 0x2120000, 0x130000}, + {1, 0x2120000, 0x2122000, 0x124000}, + {1, 0x2130000, 0x2132000, 0x126000}, + {1, 0x2140000, 0x2142000, 0x128000}, + {1, 0x2150000, 0x2152000, 0x12a000}, + {1, 0x2160000, 0x2170000, 0x110000}, + {1, 0x2170000, 0x2172000, 0x12e000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000}, + {0, 0x0000000, 0x0000000, 0x000000} } }, + {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ + {{{0} } }, /* 35: */ + {{{0} } }, /* 36: */ + {{{0} } }, /* 37: */ + {{{0} } }, /* 38: */ + {{{0} } }, /* 39: */ + {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ + {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ + {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ + {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ + {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ + {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ + {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ + {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ + {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ + {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ + {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ + {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ + {{{0} } }, /* 52: */ + {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ + {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ + {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ + {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ + {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ + {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ + {{{0} } }, /* 59: I2C0 */ + {{{0} } }, /* 60: I2C1 */ + {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */ + {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ + {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ +}; + +/* + * top 12 bits of crb internal address (hub, agent) + */ +static const unsigned crb_hub_agt[64] = { + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PS, + QLCNIC_HW_CRB_HUB_AGT_ADR_MN, + QLCNIC_HW_CRB_HUB_AGT_ADR_MS, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_SRE, + QLCNIC_HW_CRB_HUB_AGT_ADR_NIU, + QLCNIC_HW_CRB_HUB_AGT_ADR_QMN, + QLCNIC_HW_CRB_HUB_AGT_ADR_SQN0, + QLCNIC_HW_CRB_HUB_AGT_ADR_SQN1, + QLCNIC_HW_CRB_HUB_AGT_ADR_SQN2, + QLCNIC_HW_CRB_HUB_AGT_ADR_SQN3, + QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q, + QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR, + QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGN4, + QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGN0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGN1, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGN2, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGN3, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGND, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGNI, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGS0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGS1, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGS2, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGS3, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGSI, + QLCNIC_HW_CRB_HUB_AGT_ADR_SN, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_EG, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PS, + QLCNIC_HW_CRB_HUB_AGT_ADR_CAM, + 0, + 0, + 0, + 0, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_TIMR, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX1, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX2, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX3, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX4, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX5, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX6, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX7, + QLCNIC_HW_CRB_HUB_AGT_ADR_XDMA, + QLCNIC_HW_CRB_HUB_AGT_ADR_I2Q, + QLCNIC_HW_CRB_HUB_AGT_ADR_ROMUSB, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX0, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX8, + QLCNIC_HW_CRB_HUB_AGT_ADR_RPMX9, + QLCNIC_HW_CRB_HUB_AGT_ADR_OCM0, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_SMB, + QLCNIC_HW_CRB_HUB_AGT_ADR_I2C0, + QLCNIC_HW_CRB_HUB_AGT_ADR_I2C1, + 0, + QLCNIC_HW_CRB_HUB_AGT_ADR_PGNC, + 0, +}; + +/* PCI Windowing for DDR regions. */ + +#define QLCNIC_PCIE_SEM_TIMEOUT 10000 + +int +qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) +{ + int done = 0, timeout = 0; + + while (!done) { + done = QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem))); + if (done == 1) + break; + if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) + return -EIO; + msleep(1); + } + + if (id_reg) + QLCWR32(adapter, id_reg, adapter->portnum); + + return 0; +} + +void +qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem) +{ + QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem))); +} + +static int +qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, + struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) +{ + u32 i, producer, consumer; + struct qlcnic_cmd_buffer *pbuf; + struct cmd_desc_type0 *cmd_desc; + struct qlcnic_host_tx_ring *tx_ring; + + i = 0; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return -EIO; + + tx_ring = adapter->tx_ring; + __netif_tx_lock_bh(tx_ring->txq); + + producer = tx_ring->producer; + consumer = tx_ring->sw_consumer; + + if (nr_desc >= qlcnic_tx_avail(tx_ring)) { + netif_tx_stop_queue(tx_ring->txq); + __netif_tx_unlock_bh(tx_ring->txq); + return -EBUSY; + } + + do { + cmd_desc = &cmd_desc_arr[i]; + + pbuf = &tx_ring->cmd_buf_arr[producer]; + pbuf->skb = NULL; + pbuf->frag_count = 0; + + memcpy(&tx_ring->desc_head[producer], + &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); + + producer = get_next_index(producer, tx_ring->num_desc); + i++; + + } while (i != nr_desc); + + tx_ring->producer = producer; + + qlcnic_update_cmd_producer(adapter, tx_ring); + + __netif_tx_unlock_bh(tx_ring->txq); + + return 0; +} + +static int +qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, + unsigned op) +{ + struct qlcnic_nic_req req; + struct qlcnic_mac_req *mac_req; + u64 word; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_REQUEST << 23); + + word = QLCNIC_MAC_EVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + mac_req = (struct qlcnic_mac_req *)&req.words[0]; + mac_req->op = op; + memcpy(mac_req->mac_addr, addr, 6); + + return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); +} + +static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, + u8 *addr, struct list_head *del_list) +{ + struct list_head *head; + struct qlcnic_mac_list_s *cur; + + /* look up if already exists */ + list_for_each(head, del_list) { + cur = list_entry(head, struct qlcnic_mac_list_s, list); + + if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { + list_move_tail(head, &adapter->mac_list); + return 0; + } + } + + cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); + if (cur == NULL) { + dev_err(&adapter->netdev->dev, + "failed to add mac address filter\n"); + return -ENOMEM; + } + memcpy(cur->mac_addr, addr, ETH_ALEN); + list_add_tail(&cur->list, &adapter->mac_list); + + return qlcnic_sre_macaddr_change(adapter, + cur->mac_addr, QLCNIC_MAC_ADD); +} + +void qlcnic_set_multi(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct dev_mc_list *mc_ptr; + u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + u32 mode = VPORT_MISS_MODE_DROP; + LIST_HEAD(del_list); + struct list_head *head; + struct qlcnic_mac_list_s *cur; + + list_splice_tail_init(&adapter->mac_list, &del_list); + + qlcnic_nic_add_mac(adapter, adapter->mac_addr, &del_list); + qlcnic_nic_add_mac(adapter, bcast_addr, &del_list); + + if (netdev->flags & IFF_PROMISC) { + mode = VPORT_MISS_MODE_ACCEPT_ALL; + goto send_fw_cmd; + } + + if ((netdev->flags & IFF_ALLMULTI) || + (netdev->mc_count > adapter->max_mc_count)) { + mode = VPORT_MISS_MODE_ACCEPT_MULTI; + goto send_fw_cmd; + } + + if (netdev->mc_count > 0) { + for (mc_ptr = netdev->mc_list; mc_ptr; + mc_ptr = mc_ptr->next) { + qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr, + &del_list); + } + } + +send_fw_cmd: + qlcnic_nic_set_promisc(adapter, mode); + head = &del_list; + while (!list_empty(head)) { + cur = list_entry(head->next, struct qlcnic_mac_list_s, list); + + qlcnic_sre_macaddr_change(adapter, + cur->mac_addr, QLCNIC_MAC_DEL); + list_del(&cur->list); + kfree(cur); + } +} + +int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) +{ + struct qlcnic_nic_req req; + u64 word; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(mode); + + return qlcnic_send_cmd_descs(adapter, + (struct cmd_desc_type0 *)&req, 1); +} + +void qlcnic_free_mac_list(struct qlcnic_adapter *adapter) +{ + struct qlcnic_mac_list_s *cur; + struct list_head *head = &adapter->mac_list; + + while (!list_empty(head)) { + cur = list_entry(head->next, struct qlcnic_mac_list_s, list); + qlcnic_sre_macaddr_change(adapter, + cur->mac_addr, QLCNIC_MAC_DEL); + list_del(&cur->list); + kfree(cur); + } +} + +#define QLCNIC_CONFIG_INTR_COALESCE 3 + +/* + * Send the interrupt coalescing parameter set by ethtool to the card. + */ +int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) +{ + struct qlcnic_nic_req req; + u64 word[6]; + int rv, i; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word[0] = QLCNIC_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word[0]); + + memcpy(&word[0], &adapter->coal, sizeof(adapter->coal)); + for (i = 0; i < 6; i++) + req.words[i] = cpu_to_le64(word[i]); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "Could not send interrupt coalescing parameters\n"); + + return rv; +} + +int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) +{ + struct qlcnic_nic_req req; + u64 word; + int rv; + + if ((adapter->flags & QLCNIC_LRO_ENABLED) == enable) + return 0; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(enable); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "Could not send configure hw lro request\n"); + + adapter->flags ^= QLCNIC_LRO_ENABLED; + + return rv; +} + +int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, int enable) +{ + struct qlcnic_nic_req req; + u64 word; + int rv; + + if (!!(adapter->flags & QLCNIC_BRIDGE_ENABLED) == enable) + return 0; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_BRIDGING | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(enable); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "Could not send configure bridge mode request\n"); + + adapter->flags ^= QLCNIC_BRIDGE_ENABLED; + + return rv; +} + + +#define RSS_HASHTYPE_IP_TCP 0x3 + +int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) +{ + struct qlcnic_nic_req req; + u64 word; + int i, rv; + + const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, + 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, + 0x255b0ec26d5a56daULL }; + + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + /* + * RSS request: + * bits 3-0: hash_method + * 5-4: hash_type_ipv4 + * 7-6: hash_type_ipv6 + * 8: enable + * 9: use indirection table + * 47-10: reserved + * 63-48: indirection table mask + */ + word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | + ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | + ((u64)(enable & 0x1) << 8) | + ((0x7ULL) << 48); + req.words[0] = cpu_to_le64(word); + for (i = 0; i < 5; i++) + req.words[i+1] = cpu_to_le64(key[i]); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, "could not configure RSS\n"); + + return rv; +} + +int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, u32 ip, int cmd) +{ + struct qlcnic_nic_req req; + u64 word; + int rv; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(cmd); + req.words[1] = cpu_to_le64(ip); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "could not notify %s IP 0x%x reuqest\n", + (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip); + + return rv; +} + +int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable) +{ + struct qlcnic_nic_req req; + u64 word; + int rv; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(enable | (enable << 8)); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "could not configure link notification\n"); + + return rv; +} + +int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter) +{ + struct qlcnic_nic_req req; + u64 word; + int rv; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_LRO_REQUEST | + ((u64)adapter->portnum << 16) | + ((u64)QLCNIC_LRO_REQUEST_CLEANUP << 56) ; + + req.req_hdr = cpu_to_le64(word); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) + dev_err(&adapter->netdev->dev, + "could not cleanup lro flows\n"); + + return rv; +} + +/* + * qlcnic_change_mtu - Change the Maximum Transfer Unit + * @returns 0 on success, negative on failure + */ + +int qlcnic_change_mtu(struct net_device *netdev, int mtu) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int rc = 0; + + if (mtu > P3_MAX_MTU) { + dev_err(&adapter->netdev->dev, "mtu > %d bytes unsupported\n", + P3_MAX_MTU); + return -EINVAL; + } + + rc = qlcnic_fw_cmd_set_mtu(adapter, mtu); + + if (!rc) + netdev->mtu = mtu; + + return rc; +} + +int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac) +{ + u32 crbaddr, mac_hi, mac_lo; + int pci_func = adapter->ahw.pci_func; + + crbaddr = CRB_MAC_BLOCK_START + + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); + + mac_lo = QLCRD32(adapter, crbaddr); + mac_hi = QLCRD32(adapter, crbaddr+4); + + if (pci_func & 1) + *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); + else + *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32)); + + return 0; +} + +/* + * Changes the CRB window to the specified window. + */ + /* Returns < 0 if off is not valid, + * 1 if window access is needed. 'off' is set to offset from + * CRB space in 128M pci map + * 0 if no window access is needed. 'off' is set to 2M addr + * In: 'off' is offset from base in 128M pci map + */ +static int +qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter, + ulong off, void __iomem **addr) +{ + const struct crb_128M_2M_sub_block_map *m; + + if ((off >= QLCNIC_CRB_MAX) || (off < QLCNIC_PCI_CRBSPACE)) + return -EINVAL; + + off -= QLCNIC_PCI_CRBSPACE; + + /* + * Try direct map + */ + m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; + + if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { + *addr = adapter->ahw.pci_base0 + m->start_2M + + (off - m->start_128M); + return 0; + } + + /* + * Not in direct map, use crb window + */ + *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + (off & MASK(16)); + return 1; +} + +/* + * In: 'off' is offset from CRB space in 128M pci map + * Out: 'off' is 2M pci map addr + * side effect: lock crb window + */ +static void +qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) +{ + u32 window; + void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M; + + off -= QLCNIC_PCI_CRBSPACE; + + window = CRB_HI(off); + + if (adapter->ahw.crb_win == window) + return; + + writel(window, addr); + if (readl(addr) != window) { + if (printk_ratelimit()) + dev_warn(&adapter->pdev->dev, + "failed to set CRB window to %d off 0x%lx\n", + window, off); + } + adapter->ahw.crb_win = window; +} + +int +qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) +{ + unsigned long flags; + int rv; + void __iomem *addr = NULL; + + rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr); + + if (rv == 0) { + writel(data, addr); + return 0; + } + + if (rv > 0) { + /* indirect access */ + write_lock_irqsave(&adapter->ahw.crb_lock, flags); + crb_win_lock(adapter); + qlcnic_pci_set_crbwindow_2M(adapter, off); + writel(data, addr); + crb_win_unlock(adapter); + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + return 0; + } + + dev_err(&adapter->pdev->dev, + "%s: invalid offset: 0x%016lx\n", __func__, off); + dump_stack(); + return -EIO; +} + +u32 +qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) +{ + unsigned long flags; + int rv; + u32 data; + void __iomem *addr = NULL; + + rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr); + + if (rv == 0) + return readl(addr); + + if (rv > 0) { + /* indirect access */ + write_lock_irqsave(&adapter->ahw.crb_lock, flags); + crb_win_lock(adapter); + qlcnic_pci_set_crbwindow_2M(adapter, off); + data = readl(addr); + crb_win_unlock(adapter); + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + return data; + } + + dev_err(&adapter->pdev->dev, + "%s: invalid offset: 0x%016lx\n", __func__, off); + dump_stack(); + return -1; +} + + +void __iomem * +qlcnic_get_ioaddr(struct qlcnic_adapter *adapter, u32 offset) +{ + void __iomem *addr = NULL; + + WARN_ON(qlcnic_pci_get_crb_addr_2M(adapter, offset, &addr)); + + return addr; +} + + +static int +qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter, + u64 addr, u32 *start) +{ + u32 window; + struct pci_dev *pdev = adapter->pdev; + + if ((addr & 0x00ff800) == 0xff800) { + if (printk_ratelimit()) + dev_warn(&pdev->dev, "QM access not handled\n"); + return -EIO; + } + + window = OCM_WIN_P3P(addr); + + writel(window, adapter->ahw.ocm_win_crb); + /* read back to flush */ + readl(adapter->ahw.ocm_win_crb); + + adapter->ahw.ocm_win = window; + *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); + return 0; +} + +static int +qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off, + u64 *data, int op) +{ + void __iomem *addr, *mem_ptr = NULL; + resource_size_t mem_base; + int ret; + u32 start; + + mutex_lock(&adapter->ahw.mem_lock); + + ret = qlcnic_pci_set_window_2M(adapter, off, &start); + if (ret != 0) + goto unlock; + + addr = pci_base_offset(adapter, start); + if (addr) + goto noremap; + + mem_base = pci_resource_start(adapter->pdev, 0) + (start & PAGE_MASK); + + mem_ptr = ioremap(mem_base, PAGE_SIZE); + if (mem_ptr == NULL) { + ret = -EIO; + goto unlock; + } + + addr = mem_ptr + (start & (PAGE_SIZE - 1)); + +noremap: + if (op == 0) /* read */ + *data = readq(addr); + else /* write */ + writeq(*data, addr); + +unlock: + mutex_unlock(&adapter->ahw.mem_lock); + + if (mem_ptr) + iounmap(mem_ptr); + return ret; +} + +#define MAX_CTL_CHECK 1000 + +int +qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, + u64 off, u64 data) +{ + int i, j, ret; + u32 temp, off8; + u64 stride; + void __iomem *mem_crb; + + /* Only 64-bit aligned access */ + if (off & 7) + return -EIO; + + /* P3 onward, test agent base for MIU and SIU is same */ + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, + QLCNIC_ADDR_QDR_NET_MAX_P3)) { + mem_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE); + goto correct; + } + + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) { + mem_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE); + goto correct; + } + + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) + return qlcnic_pci_mem_access_direct(adapter, off, &data, 1); + + return -EIO; + +correct: + stride = QLCNIC_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; + + off8 = off & ~(stride-1); + + mutex_lock(&adapter->ahw.mem_lock); + + writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); + + i = 0; + if (stride == 16) { + writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); + writel((TA_CTL_START | TA_CTL_ENABLE), + (mem_crb + TEST_AGT_CTRL)); + + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = readl(mem_crb + TEST_AGT_CTRL); + if ((temp & TA_CTL_BUSY) == 0) + break; + } + + if (j >= MAX_CTL_CHECK) { + ret = -EIO; + goto done; + } + + i = (off & 0xf) ? 0 : 2; + writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)), + mem_crb + MIU_TEST_AGT_WRDATA(i)); + writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)), + mem_crb + MIU_TEST_AGT_WRDATA(i+1)); + i = (off & 0xf) ? 2 : 0; + } + + writel(data & 0xffffffff, + mem_crb + MIU_TEST_AGT_WRDATA(i)); + writel((data >> 32) & 0xffffffff, + mem_crb + MIU_TEST_AGT_WRDATA(i+1)); + + writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); + writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), + (mem_crb + TEST_AGT_CTRL)); + + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = readl(mem_crb + TEST_AGT_CTRL); + if ((temp & TA_CTL_BUSY) == 0) + break; + } + + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to write through agent\n"); + ret = -EIO; + } else + ret = 0; + +done: + mutex_unlock(&adapter->ahw.mem_lock); + + return ret; +} + +int +qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, + u64 off, u64 *data) +{ + int j, ret; + u32 temp, off8; + u64 val, stride; + void __iomem *mem_crb; + + /* Only 64-bit aligned access */ + if (off & 7) + return -EIO; + + /* P3 onward, test agent base for MIU and SIU is same */ + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET, + QLCNIC_ADDR_QDR_NET_MAX_P3)) { + mem_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE); + goto correct; + } + + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) { + mem_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE); + goto correct; + } + + if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) { + return qlcnic_pci_mem_access_direct(adapter, + off, data, 0); + } + + return -EIO; + +correct: + stride = QLCNIC_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; + + off8 = off & ~(stride-1); + + mutex_lock(&adapter->ahw.mem_lock); + + writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); + writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); + writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); + + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = readl(mem_crb + TEST_AGT_CTRL); + if ((temp & TA_CTL_BUSY) == 0) + break; + } + + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); + ret = -EIO; + } else { + off8 = MIU_TEST_AGT_RDDATA_LO; + if ((stride == 16) && (off & 0xf)) + off8 = MIU_TEST_AGT_RDDATA_UPPER_LO; + + temp = readl(mem_crb + off8 + 4); + val = (u64)temp << 32; + val |= readl(mem_crb + off8); + *data = val; + ret = 0; + } + + mutex_unlock(&adapter->ahw.mem_lock); + + return ret; +} + +int qlcnic_get_board_info(struct qlcnic_adapter *adapter) +{ + int offset, board_type, magic; + struct pci_dev *pdev = adapter->pdev; + + offset = QLCNIC_FW_MAGIC_OFFSET; + if (qlcnic_rom_fast_read(adapter, offset, &magic)) + return -EIO; + + if (magic != QLCNIC_BDINFO_MAGIC) { + dev_err(&pdev->dev, "invalid board config, magic=%08x\n", + magic); + return -EIO; + } + + offset = QLCNIC_BRDTYPE_OFFSET; + if (qlcnic_rom_fast_read(adapter, offset, &board_type)) + return -EIO; + + adapter->ahw.board_type = board_type; + + if (board_type == QLCNIC_BRDTYPE_P3_4_GB_MM) { + u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I); + if ((gpio & 0x8000) == 0) + board_type = QLCNIC_BRDTYPE_P3_10G_TP; + } + + switch (board_type) { + case QLCNIC_BRDTYPE_P3_HMEZ: + case QLCNIC_BRDTYPE_P3_XG_LOM: + case QLCNIC_BRDTYPE_P3_10G_CX4: + case QLCNIC_BRDTYPE_P3_10G_CX4_LP: + case QLCNIC_BRDTYPE_P3_IMEZ: + case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS: + case QLCNIC_BRDTYPE_P3_10G_SFP_CT: + case QLCNIC_BRDTYPE_P3_10G_SFP_QT: + case QLCNIC_BRDTYPE_P3_10G_XFP: + case QLCNIC_BRDTYPE_P3_10000_BASE_T: + adapter->ahw.port_type = QLCNIC_XGBE; + break; + case QLCNIC_BRDTYPE_P3_REF_QG: + case QLCNIC_BRDTYPE_P3_4_GB: + case QLCNIC_BRDTYPE_P3_4_GB_MM: + adapter->ahw.port_type = QLCNIC_GBE; + break; + case QLCNIC_BRDTYPE_P3_10G_TP: + adapter->ahw.port_type = (adapter->portnum < 2) ? + QLCNIC_XGBE : QLCNIC_GBE; + break; + default: + dev_err(&pdev->dev, "unknown board type %x\n", board_type); + adapter->ahw.port_type = QLCNIC_XGBE; + break; + } + + return 0; +} + +int +qlcnic_wol_supported(struct qlcnic_adapter *adapter) +{ + u32 wol_cfg; + + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV); + if (wol_cfg & (1UL << adapter->portnum)) { + wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG); + if (wol_cfg & (1 << adapter->portnum)) + return 1; + } + + return 0; +} diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c new file mode 100644 index 000000000000..7ae8bcc1e439 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -0,0 +1,1466 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#include +#include +#include "qlcnic.h" + +struct crb_addr_pair { + u32 addr; + u32 data; +}; + +#define QLCNIC_MAX_CRB_XFORM 60 +static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM]; + +#define crb_addr_transform(name) \ + (crb_addr_xform[QLCNIC_HW_PX_MAP_CRB_##name] = \ + QLCNIC_HW_CRB_HUB_AGT_ADR_##name << 20) + +#define QLCNIC_ADDR_ERROR (0xffffffff) + +static void +qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring); + +static void crb_addr_transform_setup(void) +{ + crb_addr_transform(XDMA); + crb_addr_transform(TIMR); + crb_addr_transform(SRE); + crb_addr_transform(SQN3); + crb_addr_transform(SQN2); + crb_addr_transform(SQN1); + crb_addr_transform(SQN0); + crb_addr_transform(SQS3); + crb_addr_transform(SQS2); + crb_addr_transform(SQS1); + crb_addr_transform(SQS0); + crb_addr_transform(RPMX7); + crb_addr_transform(RPMX6); + crb_addr_transform(RPMX5); + crb_addr_transform(RPMX4); + crb_addr_transform(RPMX3); + crb_addr_transform(RPMX2); + crb_addr_transform(RPMX1); + crb_addr_transform(RPMX0); + crb_addr_transform(ROMUSB); + crb_addr_transform(SN); + crb_addr_transform(QMN); + crb_addr_transform(QMS); + crb_addr_transform(PGNI); + crb_addr_transform(PGND); + crb_addr_transform(PGN3); + crb_addr_transform(PGN2); + crb_addr_transform(PGN1); + crb_addr_transform(PGN0); + crb_addr_transform(PGSI); + crb_addr_transform(PGSD); + crb_addr_transform(PGS3); + crb_addr_transform(PGS2); + crb_addr_transform(PGS1); + crb_addr_transform(PGS0); + crb_addr_transform(PS); + crb_addr_transform(PH); + crb_addr_transform(NIU); + crb_addr_transform(I2Q); + crb_addr_transform(EG); + crb_addr_transform(MN); + crb_addr_transform(MS); + crb_addr_transform(CAS2); + crb_addr_transform(CAS1); + crb_addr_transform(CAS0); + crb_addr_transform(CAM); + crb_addr_transform(C2C1); + crb_addr_transform(C2C0); + crb_addr_transform(SMB); + crb_addr_transform(OCM0); + crb_addr_transform(I2C0); +} + +void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_rx_buffer *rx_buf; + int i, ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + for (i = 0; i < rds_ring->num_desc; ++i) { + rx_buf = &(rds_ring->rx_buf_arr[i]); + if (rx_buf->state == QLCNIC_BUFFER_FREE) + continue; + pci_unmap_single(adapter->pdev, + rx_buf->dma, + rds_ring->dma_size, + PCI_DMA_FROMDEVICE); + if (rx_buf->skb != NULL) + dev_kfree_skb_any(rx_buf->skb); + } + } +} + +void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter) +{ + struct qlcnic_cmd_buffer *cmd_buf; + struct qlcnic_skb_frag *buffrag; + int i, j; + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + + cmd_buf = tx_ring->cmd_buf_arr; + for (i = 0; i < tx_ring->num_desc; i++) { + buffrag = cmd_buf->frag_array; + if (buffrag->dma) { + pci_unmap_single(adapter->pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + buffrag->dma = 0ULL; + } + for (j = 0; j < cmd_buf->frag_count; j++) { + buffrag++; + if (buffrag->dma) { + pci_unmap_page(adapter->pdev, buffrag->dma, + buffrag->length, + PCI_DMA_TODEVICE); + buffrag->dma = 0ULL; + } + } + if (cmd_buf->skb) { + dev_kfree_skb_any(cmd_buf->skb); + cmd_buf->skb = NULL; + } + cmd_buf++; + } +} + +void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_tx_ring *tx_ring; + int ring; + + recv_ctx = &adapter->recv_ctx; + + if (recv_ctx->rds_rings == NULL) + goto skip_rds; + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + vfree(rds_ring->rx_buf_arr); + rds_ring->rx_buf_arr = NULL; + } + kfree(recv_ctx->rds_rings); + +skip_rds: + if (adapter->tx_ring == NULL) + return; + + tx_ring = adapter->tx_ring; + vfree(tx_ring->cmd_buf_arr); + kfree(adapter->tx_ring); +} + +int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx; + struct qlcnic_host_rds_ring *rds_ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_host_tx_ring *tx_ring; + struct qlcnic_rx_buffer *rx_buf; + int ring, i, size; + + struct qlcnic_cmd_buffer *cmd_buf_arr; + struct net_device *netdev = adapter->netdev; + + size = sizeof(struct qlcnic_host_tx_ring); + tx_ring = kzalloc(size, GFP_KERNEL); + if (tx_ring == NULL) { + dev_err(&netdev->dev, "failed to allocate tx ring struct\n"); + return -ENOMEM; + } + adapter->tx_ring = tx_ring; + + tx_ring->num_desc = adapter->num_txd; + tx_ring->txq = netdev_get_tx_queue(netdev, 0); + + cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring)); + if (cmd_buf_arr == NULL) { + dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n"); + return -ENOMEM; + } + memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); + tx_ring->cmd_buf_arr = cmd_buf_arr; + + recv_ctx = &adapter->recv_ctx; + + size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring); + rds_ring = kzalloc(size, GFP_KERNEL); + if (rds_ring == NULL) { + dev_err(&netdev->dev, "failed to allocate rds ring struct\n"); + return -ENOMEM; + } + recv_ctx->rds_rings = rds_ring; + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + switch (ring) { + case RCV_RING_NORMAL: + rds_ring->num_desc = adapter->num_rxd; + if (adapter->ahw.cut_through) { + rds_ring->dma_size = + QLCNIC_CT_DEFAULT_RX_BUF_LEN; + rds_ring->skb_size = + QLCNIC_CT_DEFAULT_RX_BUF_LEN; + } else { + rds_ring->dma_size = + QLCNIC_P3_RX_BUF_MAX_LEN; + rds_ring->skb_size = + rds_ring->dma_size + NET_IP_ALIGN; + } + break; + + case RCV_RING_JUMBO: + rds_ring->num_desc = adapter->num_jumbo_rxd; + rds_ring->dma_size = + QLCNIC_P3_RX_JUMBO_BUF_MAX_LEN; + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA; + + rds_ring->skb_size = + rds_ring->dma_size + NET_IP_ALIGN; + break; + + case RCV_RING_LRO: + rds_ring->num_desc = adapter->num_lro_rxd; + rds_ring->dma_size = QLCNIC_RX_LRO_BUFFER_LENGTH; + rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; + break; + + } + rds_ring->rx_buf_arr = (struct qlcnic_rx_buffer *) + vmalloc(RCV_BUFF_RINGSIZE(rds_ring)); + if (rds_ring->rx_buf_arr == NULL) { + dev_err(&netdev->dev, "Failed to allocate " + "rx buffer ring %d\n", ring); + goto err_out; + } + memset(rds_ring->rx_buf_arr, 0, RCV_BUFF_RINGSIZE(rds_ring)); + INIT_LIST_HEAD(&rds_ring->free_list); + /* + * Now go through all of them, set reference handles + * and put them in the queues. + */ + rx_buf = rds_ring->rx_buf_arr; + for (i = 0; i < rds_ring->num_desc; i++) { + list_add_tail(&rx_buf->list, + &rds_ring->free_list); + rx_buf->ref_handle = i; + rx_buf->state = QLCNIC_BUFFER_FREE; + rx_buf++; + } + spin_lock_init(&rds_ring->lock); + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sds_ring->irq = adapter->msix_entries[ring].vector; + sds_ring->adapter = adapter; + sds_ring->num_desc = adapter->num_rxd; + + for (i = 0; i < NUM_RCV_DESC_RINGS; i++) + INIT_LIST_HEAD(&sds_ring->free_list[i]); + } + + return 0; + +err_out: + qlcnic_free_sw_resources(adapter); + return -ENOMEM; +} + +/* + * Utility to translate from internal Phantom CRB address + * to external PCI CRB address. + */ +static u32 qlcnic_decode_crb_addr(u32 addr) +{ + int i; + u32 base_addr, offset, pci_base; + + crb_addr_transform_setup(); + + pci_base = QLCNIC_ADDR_ERROR; + base_addr = addr & 0xfff00000; + offset = addr & 0x000fffff; + + for (i = 0; i < QLCNIC_MAX_CRB_XFORM; i++) { + if (crb_addr_xform[i] == base_addr) { + pci_base = i << 20; + break; + } + } + if (pci_base == QLCNIC_ADDR_ERROR) + return pci_base; + else + return pci_base + offset; +} + +#define QLCNIC_MAX_ROM_WAIT_USEC 100 + +static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter) +{ + long timeout = 0; + long done = 0; + + cond_resched(); + + while (done == 0) { + done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS); + done &= 2; + if (++timeout >= QLCNIC_MAX_ROM_WAIT_USEC) { + dev_err(&adapter->pdev->dev, + "Timeout reached waiting for rom done"); + return -EIO; + } + udelay(1); + } + return 0; +} + +static int do_rom_fast_read(struct qlcnic_adapter *adapter, + int addr, int *valp) +{ + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr); + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 3); + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_INSTR_OPCODE, 0xb); + if (qlcnic_wait_rom_done(adapter)) { + dev_err(&adapter->pdev->dev, "Error waiting for rom done\n"); + return -EIO; + } + /* reset abyte_cnt and dummy_byte_cnt */ + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 0); + udelay(10); + QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + + *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA); + return 0; +} + +static int do_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, + u8 *bytes, size_t size) +{ + int addridx; + int ret = 0; + + for (addridx = addr; addridx < (addr + size); addridx += 4) { + int v; + ret = do_rom_fast_read(adapter, addridx, &v); + if (ret != 0) + break; + *(__le32 *)bytes = cpu_to_le32(v); + bytes += 4; + } + + return ret; +} + +int +qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr, + u8 *bytes, size_t size) +{ + int ret; + + ret = qlcnic_rom_lock(adapter); + if (ret < 0) + return ret; + + ret = do_rom_fast_read_words(adapter, addr, bytes, size); + + qlcnic_rom_unlock(adapter); + return ret; +} + +int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp) +{ + int ret; + + if (qlcnic_rom_lock(adapter) != 0) + return -EIO; + + ret = do_rom_fast_read(adapter, addr, valp); + qlcnic_rom_unlock(adapter); + return ret; +} + +int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) +{ + int addr, val; + int i, n, init_delay; + struct crb_addr_pair *buf; + unsigned offset; + u32 off; + struct pci_dev *pdev = adapter->pdev; + + /* resetall */ + qlcnic_rom_lock(adapter); + QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xffffffff); + qlcnic_rom_unlock(adapter); + + if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) || + qlcnic_rom_fast_read(adapter, 4, &n) != 0) { + dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n); + return -EIO; + } + offset = n & 0xffffU; + n = (n >> 16) & 0xffffU; + + if (n >= 1024) { + dev_err(&pdev->dev, "QLOGIC card flash not initialized.\n"); + return -EIO; + } + + buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); + if (buf == NULL) { + dev_err(&pdev->dev, "Unable to calloc memory for rom read.\n"); + return -ENOMEM; + } + + for (i = 0; i < n; i++) { + if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || + qlcnic_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) { + kfree(buf); + return -EIO; + } + + buf[i].addr = addr; + buf[i].data = val; + } + + for (i = 0; i < n; i++) { + + off = qlcnic_decode_crb_addr(buf[i].addr); + if (off == QLCNIC_ADDR_ERROR) { + dev_err(&pdev->dev, "CRB init value out of range %x\n", + buf[i].addr); + continue; + } + off += QLCNIC_PCI_CRBSPACE; + + if (off & 1) + continue; + + /* skipping cold reboot MAGIC */ + if (off == QLCNIC_CAM_RAM(0x1fc)) + continue; + if (off == (QLCNIC_CRB_I2C0 + 0x1c)) + continue; + if (off == (ROMUSB_GLB + 0xbc)) /* do not reset PCI */ + continue; + if (off == (ROMUSB_GLB + 0xa8)) + continue; + if (off == (ROMUSB_GLB + 0xc8)) /* core clock */ + continue; + if (off == (ROMUSB_GLB + 0x24)) /* MN clock */ + continue; + if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */ + continue; + if ((off & 0x0ff00000) == QLCNIC_CRB_DDR_NET) + continue; + /* skip the function enable register */ + if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION)) + continue; + if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION2)) + continue; + if ((off & 0x0ff00000) == QLCNIC_CRB_SMB) + continue; + + init_delay = 1; + /* After writing this register, HW needs time for CRB */ + /* to quiet down (else crb_window returns 0xffffffff) */ + if (off == QLCNIC_ROMUSB_GLB_SW_RESET) + init_delay = 1000; + + QLCWR32(adapter, off, buf[i].data); + + msleep(init_delay); + } + kfree(buf); + + /* p2dn replyCount */ + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e); + /* disable_peg_cache 0 & 1*/ + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8); + + /* peg_clr_all */ + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0xc, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x8, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0); + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0); + return 0; +} + +static int +qlcnic_has_mn(struct qlcnic_adapter *adapter) +{ + u32 capability, flashed_ver; + capability = 0; + + qlcnic_rom_fast_read(adapter, + QLCNIC_FW_VERSION_OFFSET, (int *)&flashed_ver); + flashed_ver = QLCNIC_DECODE_VERSION(flashed_ver); + + if (flashed_ver >= QLCNIC_VERSION_CODE(4, 0, 220)) { + + capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY); + if (capability & QLCNIC_PEG_TUNE_MN_PRESENT) + return 1; + } + return 0; +} + +static +struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) +{ + u32 i; + struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; + __le32 entries = cpu_to_le32(directory->num_entries); + + for (i = 0; i < entries; i++) { + + __le32 offs = cpu_to_le32(directory->findex) + + (i * cpu_to_le32(directory->entry_size)); + __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8)); + + if (tab_type == section) + return (struct uni_table_desc *) &unirom[offs]; + } + + return NULL; +} + +static int +qlcnic_set_product_offs(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *ptab_descr; + const u8 *unirom = adapter->fw->data; + u32 i; + __le32 entries; + int mn_present = qlcnic_has_mn(adapter); + + ptab_descr = qlcnic_get_table_desc(unirom, + QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); + if (ptab_descr == NULL) + return -1; + + entries = cpu_to_le32(ptab_descr->num_entries); +nomn: + for (i = 0; i < entries; i++) { + + __le32 flags, file_chiprev, offs; + u8 chiprev = adapter->ahw.revision_id; + u32 flagbit; + + offs = cpu_to_le32(ptab_descr->findex) + + (i * cpu_to_le32(ptab_descr->entry_size)); + flags = cpu_to_le32(*((int *)&unirom[offs] + + QLCNIC_UNI_FLAGS_OFF)); + file_chiprev = cpu_to_le32(*((int *)&unirom[offs] + + QLCNIC_UNI_CHIP_REV_OFF)); + + flagbit = mn_present ? 1 : 2; + + if ((chiprev == file_chiprev) && + ((1ULL << flagbit) & flags)) { + adapter->file_prd_off = offs; + return 0; + } + } + if (mn_present) { + mn_present = 0; + goto nomn; + } + return -1; +} + +static +struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter, + u32 section, u32 idx_offset) +{ + const u8 *unirom = adapter->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + idx_offset)); + struct uni_table_desc *tab_desc; + __le32 offs; + + tab_desc = qlcnic_get_table_desc(unirom, section); + + if (tab_desc == NULL) + return NULL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * idx); + + return (struct uni_data_desc *)&unirom[offs]; +} + +static u8 * +qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter) +{ + u32 offs = QLCNIC_BOOTLD_START; + + if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + offs = cpu_to_le32((qlcnic_get_data_desc(adapter, + QLCNIC_UNI_DIR_SECT_BOOTLD, + QLCNIC_UNI_BOOTLD_IDX_OFF))->findex); + + return (u8 *)&adapter->fw->data[offs]; +} + +static u8 * +qlcnic_get_fw_offs(struct qlcnic_adapter *adapter) +{ + u32 offs = QLCNIC_IMAGE_START; + + if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + offs = cpu_to_le32((qlcnic_get_data_desc(adapter, + QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex); + + return (u8 *)&adapter->fw->data[offs]; +} + +static __le32 +qlcnic_get_fw_size(struct qlcnic_adapter *adapter) +{ + if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE) + return cpu_to_le32((qlcnic_get_data_desc(adapter, + QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF))->size); + else + return cpu_to_le32( + *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]); +} + +static __le32 +qlcnic_get_fw_version(struct qlcnic_adapter *adapter) +{ + struct uni_data_desc *fw_data_desc; + const struct firmware *fw = adapter->fw; + __le32 major, minor, sub; + const u8 *ver_str; + int i, ret; + + if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) + return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]); + + fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW, + QLCNIC_UNI_FIRMWARE_IDX_OFF); + ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) + + cpu_to_le32(fw_data_desc->size) - 17; + + for (i = 0; i < 12; i++) { + if (!strncmp(&ver_str[i], "REV=", 4)) { + ret = sscanf(&ver_str[i+4], "%u.%u.%u ", + &major, &minor, &sub); + if (ret != 3) + return 0; + else + return major + (minor << 8) + (sub << 16); + } + } + + return 0; +} + +static __le32 +qlcnic_get_bios_version(struct qlcnic_adapter *adapter) +{ + const struct firmware *fw = adapter->fw; + __le32 bios_ver, prd_off = adapter->file_prd_off; + + if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE) + return cpu_to_le32( + *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]); + + bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) + + QLCNIC_UNI_BIOS_VERSION_OFF)); + + return (bios_ver << 24) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); +} + +int +qlcnic_need_fw_reset(struct qlcnic_adapter *adapter) +{ + u32 count, old_count; + u32 val, version, major, minor, build; + int i, timeout; + + if (adapter->need_fw_reset) + return 1; + + /* last attempt had failed */ + if (QLCRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) + return 1; + + old_count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); + + for (i = 0; i < 10; i++) { + + timeout = msleep_interruptible(200); + if (timeout) { + QLCWR32(adapter, CRB_CMDPEG_STATE, + PHAN_INITIALIZE_FAILED); + return -EINTR; + } + + count = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); + if (count != old_count) + break; + } + + /* firmware is dead */ + if (count == old_count) + return 1; + + /* check if we have got newer or different file firmware */ + if (adapter->fw) { + + val = qlcnic_get_fw_version(adapter); + + version = QLCNIC_DECODE_VERSION(val); + + major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); + minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); + build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB); + + if (version > QLCNIC_VERSION_CODE(major, minor, build)) + return 1; + } + + return 0; +} + +static const char *fw_name[] = { + QLCNIC_UNIFIED_ROMIMAGE_NAME, + QLCNIC_FLASH_ROMIMAGE_NAME, +}; + +int +qlcnic_load_firmware(struct qlcnic_adapter *adapter) +{ + u64 *ptr64; + u32 i, flashaddr, size; + const struct firmware *fw = adapter->fw; + struct pci_dev *pdev = adapter->pdev; + + dev_info(&pdev->dev, "loading firmware from %s\n", + fw_name[adapter->fw_type]); + + if (fw) { + __le64 data; + + size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; + + ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter); + flashaddr = QLCNIC_BOOTLD_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + + if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data)) + return -EIO; + + flashaddr += 8; + } + + size = (__force u32)qlcnic_get_fw_size(adapter) / 8; + + ptr64 = (u64 *)qlcnic_get_fw_offs(adapter); + flashaddr = QLCNIC_IMAGE_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + + if (qlcnic_pci_mem_write_2M(adapter, + flashaddr, data)) + return -EIO; + + flashaddr += 8; + } + } else { + u64 data; + u32 hi, lo; + + size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8; + flashaddr = QLCNIC_BOOTLD_START; + + for (i = 0; i < size; i++) { + if (qlcnic_rom_fast_read(adapter, + flashaddr, (int *)&lo) != 0) + return -EIO; + if (qlcnic_rom_fast_read(adapter, + flashaddr + 4, (int *)&hi) != 0) + return -EIO; + + data = (((u64)hi << 32) | lo); + + if (qlcnic_pci_mem_write_2M(adapter, + flashaddr, data)) + return -EIO; + + flashaddr += 8; + } + } + msleep(1); + + QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x18, 0x1020); + QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0x80001e); + return 0; +} + +static int +qlcnic_validate_firmware(struct qlcnic_adapter *adapter) +{ + __le32 val; + u32 ver, min_ver, bios, min_size; + struct pci_dev *pdev = adapter->pdev; + const struct firmware *fw = adapter->fw; + u8 fw_type = adapter->fw_type; + + if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { + if (qlcnic_set_product_offs(adapter)) + return -EINVAL; + + min_size = QLCNIC_UNI_FW_MIN_SIZE; + } else { + val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]); + if ((__force u32)val != QLCNIC_BDINFO_MAGIC) + return -EINVAL; + + min_size = QLCNIC_FW_MIN_SIZE; + } + + if (fw->size < min_size) + return -EINVAL; + + val = qlcnic_get_fw_version(adapter); + + min_ver = QLCNIC_VERSION_CODE(4, 0, 216); + + ver = QLCNIC_DECODE_VERSION(val); + + if ((_major(ver) > _QLCNIC_LINUX_MAJOR) || (ver < min_ver)) { + dev_err(&pdev->dev, + "%s: firmware version %d.%d.%d unsupported\n", + fw_name[fw_type], _major(ver), _minor(ver), _build(ver)); + return -EINVAL; + } + + val = qlcnic_get_bios_version(adapter); + qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios); + if ((__force u32)val != bios) { + dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", + fw_name[fw_type]); + return -EINVAL; + } + + /* check if flashed firmware is newer */ + if (qlcnic_rom_fast_read(adapter, + QLCNIC_FW_VERSION_OFFSET, (int *)&val)) + return -EIO; + + val = QLCNIC_DECODE_VERSION(val); + if (val > ver) { + dev_info(&pdev->dev, "%s: firmware is older than flash\n", + fw_name[fw_type]); + return -EINVAL; + } + + QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC); + return 0; +} + +static void +qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter) +{ + u8 fw_type; + + switch (adapter->fw_type) { + case QLCNIC_UNKNOWN_ROMIMAGE: + fw_type = QLCNIC_UNIFIED_ROMIMAGE; + break; + + case QLCNIC_UNIFIED_ROMIMAGE: + default: + fw_type = QLCNIC_FLASH_ROMIMAGE; + break; + } + + adapter->fw_type = fw_type; +} + + + +void qlcnic_request_firmware(struct qlcnic_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + int rc; + + adapter->fw_type = QLCNIC_UNKNOWN_ROMIMAGE; + +next: + qlcnic_get_next_fwtype(adapter); + + if (adapter->fw_type == QLCNIC_FLASH_ROMIMAGE) { + adapter->fw = NULL; + } else { + rc = request_firmware(&adapter->fw, + fw_name[adapter->fw_type], &pdev->dev); + if (rc != 0) + goto next; + + rc = qlcnic_validate_firmware(adapter); + if (rc != 0) { + release_firmware(adapter->fw); + msleep(1); + goto next; + } + } +} + + +void +qlcnic_release_firmware(struct qlcnic_adapter *adapter) +{ + if (adapter->fw) + release_firmware(adapter->fw); + adapter->fw = NULL; +} + +int qlcnic_phantom_init(struct qlcnic_adapter *adapter) +{ + u32 val; + int retries = 60; + + do { + val = QLCRD32(adapter, CRB_CMDPEG_STATE); + + switch (val) { + case PHAN_INITIALIZE_COMPLETE: + case PHAN_INITIALIZE_ACK: + return 0; + case PHAN_INITIALIZE_FAILED: + goto out_err; + default: + break; + } + + msleep(500); + + } while (--retries); + + QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); + +out_err: + dev_err(&adapter->pdev->dev, "firmware init failed\n"); + return -EIO; +} + +static int +qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter) +{ + u32 val; + int retries = 2000; + + do { + val = QLCRD32(adapter, CRB_RCVPEG_STATE); + + if (val == PHAN_PEG_RCV_INITIALIZED) + return 0; + + msleep(10); + + } while (--retries); + + if (!retries) { + dev_err(&adapter->pdev->dev, "Receive Peg initialization not " + "complete, state: 0x%x.\n", val); + return -EIO; + } + + return 0; +} + +int qlcnic_init_firmware(struct qlcnic_adapter *adapter) +{ + int err; + + err = qlcnic_receive_peg_ready(adapter); + if (err) + return err; + + QLCWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); + QLCWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); + QLCWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); + QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + + return err; +} + +static void +qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, + struct qlcnic_fw_msg *msg) +{ + u32 cable_OUI; + u16 cable_len; + u16 link_speed; + u8 link_status, module, duplex, autoneg; + struct net_device *netdev = adapter->netdev; + + adapter->has_link_events = 1; + + cable_OUI = msg->body[1] & 0xffffffff; + cable_len = (msg->body[1] >> 32) & 0xffff; + link_speed = (msg->body[1] >> 48) & 0xffff; + + link_status = msg->body[2] & 0xff; + duplex = (msg->body[2] >> 16) & 0xff; + autoneg = (msg->body[2] >> 24) & 0xff; + + module = (msg->body[2] >> 8) & 0xff; + if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) + dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, " + "length %d\n", cable_OUI, cable_len); + else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) + dev_info(&netdev->dev, "unsupported cable length %d\n", + cable_len); + + qlcnic_advert_link_change(adapter, link_status); + + if (duplex == LINKEVENT_FULL_DUPLEX) + adapter->link_duplex = DUPLEX_FULL; + else + adapter->link_duplex = DUPLEX_HALF; + + adapter->module_type = module; + adapter->link_autoneg = autoneg; + adapter->link_speed = link_speed; +} + +static void +qlcnic_handle_fw_message(int desc_cnt, int index, + struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_fw_msg msg; + struct status_desc *desc; + int i = 0, opcode; + + while (desc_cnt > 0 && i < 8) { + desc = &sds_ring->desc_head[index]; + msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); + msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); + + index = get_next_index(index, sds_ring->num_desc); + desc_cnt--; + } + + opcode = qlcnic_get_nic_msg_opcode(msg.body[0]); + switch (opcode) { + case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: + qlcnic_handle_linkevent(sds_ring->adapter, &msg); + break; + default: + break; + } +} + +static int +qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring, + struct qlcnic_rx_buffer *buffer) +{ + struct sk_buff *skb; + dma_addr_t dma; + struct pci_dev *pdev = adapter->pdev; + + buffer->skb = dev_alloc_skb(rds_ring->skb_size); + if (!buffer->skb) + return -ENOMEM; + + skb = buffer->skb; + + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + buffer->skb = NULL; + return -ENOMEM; + } + + buffer->skb = skb; + buffer->dma = dma; + buffer->state = QLCNIC_BUFFER_BUSY; + + return 0; +} + +static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum) +{ + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + + buffer = &rds_ring->rx_buf_arr[index]; + + pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, + PCI_DMA_FROMDEVICE); + + skb = buffer->skb; + if (!skb) + goto no_skb; + + if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) { + adapter->stats.csummed++; + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; + } + + skb->dev = adapter->netdev; + + buffer->skb = NULL; +no_skb: + buffer->state = QLCNIC_BUFFER_FREE; + return skb; +} + +static struct qlcnic_rx_buffer * +qlcnic_process_rcv(struct qlcnic_adapter *adapter, + struct qlcnic_host_sds_ring *sds_ring, + int ring, u64 sts_data0) +{ + struct net_device *netdev = adapter->netdev; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + int index, length, cksum, pkt_offset; + + if (unlikely(ring >= adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_sts_refhandle(sts_data0); + if (unlikely(index >= rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + + length = qlcnic_get_sts_totallength(sts_data0); + cksum = qlcnic_get_sts_status(sts_data0); + pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); + if (!skb) + return buffer; + + if (length > rds_ring->skb_size) + skb_put(skb, rds_ring->skb_size); + else + skb_put(skb, length); + + if (pkt_offset) + skb_pull(skb, pkt_offset); + + skb->truesize = skb->len + sizeof(struct sk_buff); + skb->protocol = eth_type_trans(skb, netdev); + + napi_gro_receive(&sds_ring->napi, skb); + + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; + + return buffer; +} + +#define QLC_TCP_HDR_SIZE 20 +#define QLC_TCP_TS_OPTION_SIZE 12 +#define QLC_TCP_TS_HDR_SIZE (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE) + +static struct qlcnic_rx_buffer * +qlcnic_process_lro(struct qlcnic_adapter *adapter, + struct qlcnic_host_sds_ring *sds_ring, + int ring, u64 sts_data0, u64 sts_data1) +{ + struct net_device *netdev = adapter->netdev; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + struct iphdr *iph; + struct tcphdr *th; + bool push, timestamp; + int l2_hdr_offset, l4_hdr_offset; + int index; + u16 lro_length, length, data_offset; + u32 seq_number; + + if (unlikely(ring > adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_lro_sts_refhandle(sts_data0); + if (unlikely(index > rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + + timestamp = qlcnic_get_lro_sts_timestamp(sts_data0); + lro_length = qlcnic_get_lro_sts_length(sts_data0); + l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0); + l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0); + push = qlcnic_get_lro_sts_push_flag(sts_data0); + seq_number = qlcnic_get_lro_sts_seq_number(sts_data1); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); + if (!skb) + return buffer; + + if (timestamp) + data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; + else + data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE; + + skb_put(skb, lro_length + data_offset); + + skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); + + skb_pull(skb, l2_hdr_offset); + skb->protocol = eth_type_trans(skb, netdev); + + iph = (struct iphdr *)skb->data; + th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); + + length = (iph->ihl << 2) + (th->doff << 2) + lro_length; + iph->tot_len = htons(length); + iph->check = 0; + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + th->psh = push; + th->seq = htonl(seq_number); + + length = skb->len; + + netif_receive_skb(skb); + + adapter->stats.lro_pkts++; + adapter->stats.rxbytes += length; + + return buffer; +} + +int +qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) +{ + struct qlcnic_adapter *adapter = sds_ring->adapter; + struct list_head *cur; + struct status_desc *desc; + struct qlcnic_rx_buffer *rxbuf; + u64 sts_data0, sts_data1; + + int count = 0; + int opcode, ring, desc_cnt; + u32 consumer = sds_ring->consumer; + + while (count < max) { + desc = &sds_ring->desc_head[consumer]; + sts_data0 = le64_to_cpu(desc->status_desc_data[0]); + + if (!(sts_data0 & STATUS_OWNER_HOST)) + break; + + desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); + opcode = qlcnic_get_sts_opcode(sts_data0); + + switch (opcode) { + case QLCNIC_RXPKT_DESC: + case QLCNIC_OLD_RXPKT_DESC: + case QLCNIC_SYN_OFFLOAD: + ring = qlcnic_get_sts_type(sts_data0); + rxbuf = qlcnic_process_rcv(adapter, sds_ring, + ring, sts_data0); + break; + case QLCNIC_LRO_DESC: + ring = qlcnic_get_lro_sts_type(sts_data0); + sts_data1 = le64_to_cpu(desc->status_desc_data[1]); + rxbuf = qlcnic_process_lro(adapter, sds_ring, + ring, sts_data0, sts_data1); + break; + case QLCNIC_RESPONSE_DESC: + qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring); + default: + goto skip; + } + + WARN_ON(desc_cnt > 1); + + if (rxbuf) + list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); + +skip: + for (; desc_cnt > 0; desc_cnt--) { + desc = &sds_ring->desc_head[consumer]; + desc->status_desc_data[0] = + cpu_to_le64(STATUS_OWNER_PHANTOM); + consumer = get_next_index(consumer, sds_ring->num_desc); + } + count++; + } + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + struct qlcnic_host_rds_ring *rds_ring = + &adapter->recv_ctx.rds_rings[ring]; + + if (!list_empty(&sds_ring->free_list[ring])) { + list_for_each(cur, &sds_ring->free_list[ring]) { + rxbuf = list_entry(cur, + struct qlcnic_rx_buffer, list); + qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); + } + spin_lock(&rds_ring->lock); + list_splice_tail_init(&sds_ring->free_list[ring], + &rds_ring->free_list); + spin_unlock(&rds_ring->lock); + } + + qlcnic_post_rx_buffers_nodb(adapter, rds_ring); + } + + if (count) { + sds_ring->consumer = consumer; + writel(consumer, sds_ring->crb_sts_consumer); + } + + return count; +} + +void +qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid, + struct qlcnic_host_rds_ring *rds_ring) +{ + struct rcv_desc *pdesc; + struct qlcnic_rx_buffer *buffer; + int producer, count = 0; + struct list_head *head; + + producer = rds_ring->producer; + + spin_lock(&rds_ring->lock); + head = &rds_ring->free_list; + while (!list_empty(head)) { + + buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); + + if (!buffer->skb) { + if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) + break; + } + + count++; + list_del(&buffer->list); + + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->addr_buffer = cpu_to_le64(buffer->dma); + pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); + pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); + + producer = get_next_index(producer, rds_ring->num_desc); + } + spin_unlock(&rds_ring->lock); + + if (count) { + rds_ring->producer = producer; + writel((producer-1) & (rds_ring->num_desc-1), + rds_ring->crb_rcv_producer); + } +} + +static void +qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, + struct qlcnic_host_rds_ring *rds_ring) +{ + struct rcv_desc *pdesc; + struct qlcnic_rx_buffer *buffer; + int producer, count = 0; + struct list_head *head; + + producer = rds_ring->producer; + if (!spin_trylock(&rds_ring->lock)) + return; + + head = &rds_ring->free_list; + while (!list_empty(head)) { + + buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); + + if (!buffer->skb) { + if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) + break; + } + + count++; + list_del(&buffer->list); + + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); + pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); + pdesc->addr_buffer = cpu_to_le64(buffer->dma); + + producer = get_next_index(producer, rds_ring->num_desc); + } + + if (count) { + rds_ring->producer = producer; + writel((producer - 1) & (rds_ring->num_desc - 1), + rds_ring->crb_rcv_producer); + } + spin_unlock(&rds_ring->lock); +} + diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c new file mode 100644 index 000000000000..1698b6a68ed1 --- /dev/null +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -0,0 +1,2604 @@ +/* + * Copyright (C) 2009 - QLogic Corporation. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution + * in the file called "COPYING". + * + */ + +#include +#include + +#include "qlcnic.h" + +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("QLogic 10 GbE Converged Ethernet Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(QLCNIC_LINUX_VERSIONID); +MODULE_FIRMWARE(QLCNIC_UNIFIED_ROMIMAGE_NAME); + +char qlcnic_driver_name[] = "qlcnic"; +static const char qlcnic_driver_string[] = "QLogic Converged Ethernet Driver v" + QLCNIC_LINUX_VERSIONID; + +static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG; + +/* Default to restricted 1G auto-neg mode */ +static int wol_port_mode = 5; + +static int use_msi = 1; +module_param(use_msi, int, 0644); +MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); + +static int use_msi_x = 1; +module_param(use_msi_x, int, 0644); +MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled"); + +static int auto_fw_reset = AUTO_FW_RESET_ENABLED; +module_param(auto_fw_reset, int, 0644); +MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled"); + +static int __devinit qlcnic_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void __devexit qlcnic_remove(struct pci_dev *pdev); +static int qlcnic_open(struct net_device *netdev); +static int qlcnic_close(struct net_device *netdev); +static netdev_tx_t qlcnic_xmit_frame(struct sk_buff *, + struct net_device *); +static void qlcnic_tx_timeout(struct net_device *netdev); +static void qlcnic_tx_timeout_task(struct work_struct *work); +static void qlcnic_attach_work(struct work_struct *work); +static void qlcnic_fwinit_work(struct work_struct *work); +static void qlcnic_fw_poll_work(struct work_struct *work); +static void qlcnic_schedule_work(struct qlcnic_adapter *adapter, + work_func_t func, int delay); +static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter); +static int qlcnic_poll(struct napi_struct *napi, int budget); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void qlcnic_poll_controller(struct net_device *netdev); +#endif + +static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); +static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); +static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); +static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); + +static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter); +static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); + +static irqreturn_t qlcnic_intr(int irq, void *data); +static irqreturn_t qlcnic_msi_intr(int irq, void *data); +static irqreturn_t qlcnic_msix_intr(int irq, void *data); + +static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev); +static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long); + +/* PCI Device ID Table */ +#define ENTRY(device) \ + {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ + .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} + +#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 + +static const struct pci_device_id qlcnic_pci_tbl[] __devinitdata = { + ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), + {0,} +}; + +MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl); + + +void +qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, + struct qlcnic_host_tx_ring *tx_ring) +{ + writel(tx_ring->producer, tx_ring->crb_cmd_producer); + + if (qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH) { + netif_stop_queue(adapter->netdev); + smp_mb(); + } +} + +static const u32 msi_tgt_status[8] = { + ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1, + ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3, + ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5, + ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 +}; + +static const +struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; + +static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) +{ + writel(0, sds_ring->crb_intr_mask); +} + +static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_adapter *adapter = sds_ring->adapter; + + writel(0x1, sds_ring->crb_intr_mask); + + if (!QLCNIC_IS_MSI_FAMILY(adapter)) + writel(0xfbff, adapter->tgt_mask_reg); +} + +static int +qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count) +{ + int size = sizeof(struct qlcnic_host_sds_ring) * count; + + recv_ctx->sds_rings = kzalloc(size, GFP_KERNEL); + + return (recv_ctx->sds_rings == NULL); +} + +static void +qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) +{ + if (recv_ctx->sds_rings != NULL) + kfree(recv_ctx->sds_rings); + + recv_ctx->sds_rings = NULL; +} + +static int +qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) + return -ENOMEM; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_add(netdev, &sds_ring->napi, + qlcnic_poll, QLCNIC_NETDEV_WEIGHT); + } + + return 0; +} + +static void +qlcnic_napi_del(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_del(&sds_ring->napi); + } + + qlcnic_free_sds_rings(&adapter->recv_ctx); +} + +static void +qlcnic_napi_enable(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + napi_enable(&sds_ring->napi); + qlcnic_enable_int(sds_ring); + } +} + +static void +qlcnic_napi_disable(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + qlcnic_disable_int(sds_ring); + napi_synchronize(&sds_ring->napi); + napi_disable(&sds_ring->napi); + } +} + +static void qlcnic_clear_stats(struct qlcnic_adapter *adapter) +{ + memset(&adapter->stats, 0, sizeof(adapter->stats)); + return; +} + +static int qlcnic_set_dma_mask(struct qlcnic_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + u64 mask, cmask; + + adapter->pci_using_dac = 0; + + mask = DMA_BIT_MASK(39); + cmask = mask; + + if (pci_set_dma_mask(pdev, mask) == 0 && + pci_set_consistent_dma_mask(pdev, cmask) == 0) { + adapter->pci_using_dac = 1; + return 0; + } + + return -EIO; +} + +/* Update addressable range if firmware supports it */ +static int +qlcnic_update_dma_mask(struct qlcnic_adapter *adapter) +{ + int change, shift, err; + u64 mask, old_mask, old_cmask; + struct pci_dev *pdev = adapter->pdev; + + change = 0; + + shift = QLCRD32(adapter, CRB_DMA_SHIFT); + if (shift > 32) + return 0; + + if (shift > 9) + change = 1; + + if (change) { + old_mask = pdev->dma_mask; + old_cmask = pdev->dev.coherent_dma_mask; + + mask = DMA_BIT_MASK(32+shift); + + err = pci_set_dma_mask(pdev, mask); + if (err) + goto err_out; + + err = pci_set_consistent_dma_mask(pdev, mask); + if (err) + goto err_out; + dev_info(&pdev->dev, "using %d-bit dma mask\n", 32+shift); + } + + return 0; + +err_out: + pci_set_dma_mask(pdev, old_mask); + pci_set_consistent_dma_mask(pdev, old_cmask); + return err; +} + +static void qlcnic_set_port_mode(struct qlcnic_adapter *adapter) +{ + u32 val, data; + + val = adapter->ahw.board_type; + if ((val == QLCNIC_BRDTYPE_P3_HMEZ) || + (val == QLCNIC_BRDTYPE_P3_XG_LOM)) { + if (port_mode == QLCNIC_PORT_MODE_802_3_AP) { + data = QLCNIC_PORT_MODE_802_3_AP; + QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data); + } else if (port_mode == QLCNIC_PORT_MODE_XG) { + data = QLCNIC_PORT_MODE_XG; + QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data); + } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_1G) { + data = QLCNIC_PORT_MODE_AUTO_NEG_1G; + QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data); + } else if (port_mode == QLCNIC_PORT_MODE_AUTO_NEG_XG) { + data = QLCNIC_PORT_MODE_AUTO_NEG_XG; + QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data); + } else { + data = QLCNIC_PORT_MODE_AUTO_NEG; + QLCWR32(adapter, QLCNIC_PORT_MODE_ADDR, data); + } + + if ((wol_port_mode != QLCNIC_PORT_MODE_802_3_AP) && + (wol_port_mode != QLCNIC_PORT_MODE_XG) && + (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_1G) && + (wol_port_mode != QLCNIC_PORT_MODE_AUTO_NEG_XG)) { + wol_port_mode = QLCNIC_PORT_MODE_AUTO_NEG; + } + QLCWR32(adapter, QLCNIC_WOL_PORT_MODE, wol_port_mode); + } +} + +static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable) +{ + u32 control; + int pos; + + pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + if (pos) { + pci_read_config_dword(pdev, pos, &control); + if (enable) + control |= PCI_MSIX_FLAGS_ENABLE; + else + control = 0; + pci_write_config_dword(pdev, pos, control); + } +} + +static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count) +{ + int i; + + for (i = 0; i < count; i++) + adapter->msix_entries[i].entry = i; +} + +static int +qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) +{ + int i; + unsigned char *p; + u64 mac_addr; + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + + if (qlcnic_get_mac_addr(adapter, &mac_addr) != 0) + return -EIO; + + p = (unsigned char *)&mac_addr; + for (i = 0; i < 6; i++) + netdev->dev_addr[i] = *(p + 5 - i); + + memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); + memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); + + /* set station address */ + + if (!is_valid_ether_addr(netdev->perm_addr)) + dev_warn(&pdev->dev, "Bad MAC address %pM.\n", + netdev->dev_addr); + + return 0; +} + +static int qlcnic_set_mac(struct net_device *netdev, void *p) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + if (netif_running(netdev)) { + netif_device_detach(netdev); + qlcnic_napi_disable(adapter); + } + + memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len); + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + qlcnic_set_multi(adapter->netdev); + + if (netif_running(netdev)) { + netif_device_attach(netdev); + qlcnic_napi_enable(adapter); + } + return 0; +} + +static const struct net_device_ops qlcnic_netdev_ops = { + .ndo_open = qlcnic_open, + .ndo_stop = qlcnic_close, + .ndo_start_xmit = qlcnic_xmit_frame, + .ndo_get_stats = qlcnic_get_stats, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_multicast_list = qlcnic_set_multi, + .ndo_set_mac_address = qlcnic_set_mac, + .ndo_change_mtu = qlcnic_change_mtu, + .ndo_tx_timeout = qlcnic_tx_timeout, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = qlcnic_poll_controller, +#endif +}; + +static void +qlcnic_setup_intr(struct qlcnic_adapter *adapter) +{ + const struct qlcnic_legacy_intr_set *legacy_intrp; + struct pci_dev *pdev = adapter->pdev; + int err, num_msix; + + if (adapter->rss_supported) { + num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ? + MSIX_ENTRIES_PER_ADAPTER : 2; + } else + num_msix = 1; + + adapter->max_sds_rings = 1; + + adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); + + legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; + + adapter->int_vec_bit = legacy_intrp->int_vec_bit; + adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, + legacy_intrp->tgt_status_reg); + adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter, + legacy_intrp->tgt_mask_reg); + adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR); + + adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter, + ISR_INT_STATE_REG); + + qlcnic_set_msix_bit(pdev, 0); + + if (adapter->msix_supported) { + + qlcnic_init_msix_entries(adapter, num_msix); + err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); + if (err == 0) { + adapter->flags |= QLCNIC_MSIX_ENABLED; + qlcnic_set_msix_bit(pdev, 1); + + if (adapter->rss_supported) + adapter->max_sds_rings = num_msix; + + dev_info(&pdev->dev, "using msi-x interrupts\n"); + return; + } + + if (err > 0) + pci_disable_msix(pdev); + + /* fall through for msi */ + } + + if (use_msi && !pci_enable_msi(pdev)) { + adapter->flags |= QLCNIC_MSI_ENABLED; + adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter, + msi_tgt_status[adapter->ahw.pci_func]); + dev_info(&pdev->dev, "using msi interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; + return; + } + + dev_info(&pdev->dev, "using legacy interrupts\n"); + adapter->msix_entries[0].vector = pdev->irq; +} + +static void +qlcnic_teardown_intr(struct qlcnic_adapter *adapter) +{ + if (adapter->flags & QLCNIC_MSIX_ENABLED) + pci_disable_msix(adapter->pdev); + if (adapter->flags & QLCNIC_MSI_ENABLED) + pci_disable_msi(adapter->pdev); +} + +static void +qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) +{ + if (adapter->ahw.pci_base0 != NULL) + iounmap(adapter->ahw.pci_base0); +} + +static int +qlcnic_setup_pci_map(struct qlcnic_adapter *adapter) +{ + void __iomem *mem_ptr0 = NULL; + resource_size_t mem_base; + unsigned long mem_len, pci_len0 = 0; + + struct pci_dev *pdev = adapter->pdev; + int pci_func = adapter->ahw.pci_func; + + /* + * Set the CRB window to invalid. If any register in window 0 is + * accessed it should set the window to 0 and then reset it to 1. + */ + adapter->ahw.crb_win = -1; + adapter->ahw.ocm_win = -1; + + /* remap phys address */ + mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ + mem_len = pci_resource_len(pdev, 0); + + if (mem_len == QLCNIC_PCI_2MB_SIZE) { + + mem_ptr0 = pci_ioremap_bar(pdev, 0); + if (mem_ptr0 == NULL) { + dev_err(&pdev->dev, "failed to map PCI bar 0\n"); + return -EIO; + } + pci_len0 = mem_len; + } else { + return -EIO; + } + + dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); + + adapter->ahw.pci_base0 = mem_ptr0; + adapter->ahw.pci_len0 = pci_len0; + + adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter, + QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func))); + + return 0; +} + +static void get_brd_name(struct qlcnic_adapter *adapter, char *name) +{ + struct pci_dev *pdev = adapter->pdev; + int i, found = 0; + + for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { + if (qlcnic_boards[i].vendor == pdev->vendor && + qlcnic_boards[i].device == pdev->device && + qlcnic_boards[i].sub_vendor == pdev->subsystem_vendor && + qlcnic_boards[i].sub_device == pdev->subsystem_device) { + strcpy(name, qlcnic_boards[i].short_name); + found = 1; + break; + } + + } + + if (!found) + name = "Unknown"; +} + +static void +qlcnic_check_options(struct qlcnic_adapter *adapter) +{ + u32 fw_major, fw_minor, fw_build; + char brd_name[QLCNIC_MAX_BOARD_NAME_LEN]; + char serial_num[32]; + int i, offset, val; + int *ptr32; + struct pci_dev *pdev = adapter->pdev; + + adapter->driver_mismatch = 0; + + ptr32 = (int *)&serial_num; + offset = QLCNIC_FW_SERIAL_NUM_OFFSET; + for (i = 0; i < 8; i++) { + if (qlcnic_rom_fast_read(adapter, offset, &val) == -1) { + dev_err(&pdev->dev, "error reading board info\n"); + adapter->driver_mismatch = 1; + return; + } + ptr32[i] = cpu_to_le32(val); + offset += sizeof(u32); + } + + fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); + fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); + fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB); + + adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); + + if (adapter->portnum == 0) { + get_brd_name(adapter, brd_name); + + pr_info("%s: %s Board Chip rev 0x%x\n", + module_name(THIS_MODULE), + brd_name, adapter->ahw.revision_id); + } + + if (adapter->fw_version < QLCNIC_VERSION_CODE(3, 4, 216)) { + adapter->driver_mismatch = 1; + dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n", + fw_major, fw_minor, fw_build); + return; + } + + i = QLCRD32(adapter, QLCNIC_SRE_MISC); + adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0; + + dev_info(&pdev->dev, "firmware v%d.%d.%d [%s]\n", + fw_major, fw_minor, fw_build, + adapter->ahw.cut_through ? "cut-through" : "legacy"); + + if (adapter->fw_version >= QLCNIC_VERSION_CODE(4, 0, 222)) + adapter->capabilities = QLCRD32(adapter, CRB_FW_CAPABILITIES_1); + + adapter->flags &= ~QLCNIC_LRO_ENABLED; + + if (adapter->ahw.port_type == QLCNIC_XGBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } else if (adapter->ahw.port_type == QLCNIC_GBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } + + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + + adapter->num_txd = MAX_CMD_DESCRIPTORS; + + adapter->num_lro_rxd = 0; + adapter->max_rds_rings = 2; +} + +static int +qlcnic_start_firmware(struct qlcnic_adapter *adapter) +{ + int val, err, first_boot; + + err = qlcnic_set_dma_mask(adapter); + if (err) + return err; + + if (!qlcnic_can_start_firmware(adapter)) + goto wait_init; + + first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc)); + if (first_boot == 0x55555555) + /* This is the first boot after power up */ + QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC); + + qlcnic_request_firmware(adapter); + + err = qlcnic_need_fw_reset(adapter); + if (err < 0) + goto err_out; + if (err == 0) + goto wait_init; + + if (first_boot != 0x55555555) { + QLCWR32(adapter, CRB_CMDPEG_STATE, 0); + qlcnic_pinit_from_rom(adapter); + msleep(1); + } + + QLCWR32(adapter, CRB_DMA_SHIFT, 0x55555555); + QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0); + QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0); + + qlcnic_set_port_mode(adapter); + + err = qlcnic_load_firmware(adapter); + if (err) + goto err_out; + + qlcnic_release_firmware(adapter); + + val = (_QLCNIC_LINUX_MAJOR << 16) + | ((_QLCNIC_LINUX_MINOR << 8)) + | (_QLCNIC_LINUX_SUBVERSION); + QLCWR32(adapter, CRB_DRIVER_VERSION, val); + +wait_init: + /* Handshake with the card before we register the devices. */ + err = qlcnic_phantom_init(adapter); + if (err) + goto err_out; + + QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); + + qlcnic_update_dma_mask(adapter); + + qlcnic_check_options(adapter); + + adapter->need_fw_reset = 0; + + /* fall through and release firmware */ + +err_out: + qlcnic_release_firmware(adapter); + return err; +} + +static int +qlcnic_request_irq(struct qlcnic_adapter *adapter) +{ + irq_handler_t handler; + struct qlcnic_host_sds_ring *sds_ring; + int err, ring; + + unsigned long flags = 0; + struct net_device *netdev = adapter->netdev; + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + if (adapter->flags & QLCNIC_MSIX_ENABLED) + handler = qlcnic_msix_intr; + else if (adapter->flags & QLCNIC_MSI_ENABLED) + handler = qlcnic_msi_intr; + else { + flags |= IRQF_SHARED; + handler = qlcnic_intr; + } + adapter->irq = netdev->irq; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sprintf(sds_ring->name, "%s[%d]", netdev->name, ring); + err = request_irq(sds_ring->irq, handler, + flags, sds_ring->name, sds_ring); + if (err) + return err; + } + + return 0; +} + +static void +qlcnic_free_irq(struct qlcnic_adapter *adapter) +{ + int ring; + struct qlcnic_host_sds_ring *sds_ring; + + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + free_irq(sds_ring->irq, sds_ring); + } +} + +static void +qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter) +{ + adapter->coal.flags = QLCNIC_INTR_DEFAULT; + adapter->coal.normal.data.rx_time_us = + QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; + adapter->coal.normal.data.rx_packets = + QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; + adapter->coal.normal.data.tx_time_us = + QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US; + adapter->coal.normal.data.tx_packets = + QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS; +} + +static int +__qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return -EIO; + + qlcnic_set_multi(netdev); + qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu); + + adapter->ahw.linkup = 0; + + if (adapter->max_sds_rings > 1) + qlcnic_config_rss(adapter, 1); + + qlcnic_config_intr_coalesce(adapter); + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + qlcnic_config_hw_lro(adapter, QLCNIC_LRO_ENABLED); + + qlcnic_napi_enable(adapter); + + qlcnic_linkevent_request(adapter, 1); + + set_bit(__QLCNIC_DEV_UP, &adapter->state); + return 0; +} + +/* Usage: During resume and firmware recovery module.*/ + +static int +qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + int err = 0; + + rtnl_lock(); + if (netif_running(netdev)) + err = __qlcnic_up(adapter, netdev); + rtnl_unlock(); + + return err; +} + +static void +__qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + + if (!test_and_clear_bit(__QLCNIC_DEV_UP, &adapter->state)) + return; + + smp_mb(); + spin_lock(&adapter->tx_clean_lock); + netif_carrier_off(netdev); + netif_tx_disable(netdev); + + qlcnic_free_mac_list(adapter); + + qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE); + + qlcnic_napi_disable(adapter); + + qlcnic_release_tx_buffers(adapter); + spin_unlock(&adapter->tx_clean_lock); +} + +/* Usage: During suspend and firmware recovery module */ + +static void +qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) +{ + rtnl_lock(); + if (netif_running(netdev)) + __qlcnic_down(adapter, netdev); + rtnl_unlock(); + +} + +static int +qlcnic_attach(struct qlcnic_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err, ring; + struct qlcnic_host_rds_ring *rds_ring; + + if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) + return 0; + + err = qlcnic_init_firmware(adapter); + if (err) + return err; + + err = qlcnic_napi_add(adapter, netdev); + if (err) + return err; + + err = qlcnic_alloc_sw_resources(adapter); + if (err) { + dev_err(&pdev->dev, "Error in setting sw resources\n"); + return err; + } + + err = qlcnic_alloc_hw_resources(adapter); + if (err) { + dev_err(&pdev->dev, "Error in setting hw resources\n"); + goto err_out_free_sw; + } + + + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx.rds_rings[ring]; + qlcnic_post_rx_buffers(adapter, ring, rds_ring); + } + + err = qlcnic_request_irq(adapter); + if (err) { + dev_err(&pdev->dev, "failed to setup interrupt\n"); + goto err_out_free_rxbuf; + } + + qlcnic_init_coalesce_defaults(adapter); + + qlcnic_create_sysfs_entries(adapter); + + adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC; + return 0; + +err_out_free_rxbuf: + qlcnic_release_rx_buffers(adapter); + qlcnic_free_hw_resources(adapter); +err_out_free_sw: + qlcnic_free_sw_resources(adapter); + return err; +} + +static void +qlcnic_detach(struct qlcnic_adapter *adapter) +{ + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + + qlcnic_remove_sysfs_entries(adapter); + + qlcnic_free_hw_resources(adapter); + qlcnic_release_rx_buffers(adapter); + qlcnic_free_irq(adapter); + qlcnic_napi_del(adapter); + qlcnic_free_sw_resources(adapter); + + adapter->is_up = 0; +} + +int +qlcnic_reset_context(struct qlcnic_adapter *adapter) +{ + int err = 0; + struct net_device *netdev = adapter->netdev; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EBUSY; + + if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) { + + netif_device_detach(netdev); + + if (netif_running(netdev)) + __qlcnic_down(adapter, netdev); + + qlcnic_detach(adapter); + + if (netif_running(netdev)) { + err = qlcnic_attach(adapter); + if (!err) + err = __qlcnic_up(adapter, netdev); + + if (err) + goto done; + } + + netif_device_attach(netdev); + } + +done: + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return err; +} + +static int +qlcnic_setup_netdev(struct qlcnic_adapter *adapter, + struct net_device *netdev) +{ + int err; + struct pci_dev *pdev = adapter->pdev; + + adapter->rx_csum = 1; + adapter->mc_enabled = 0; + adapter->max_mc_count = 38; + + netdev->netdev_ops = &qlcnic_netdev_ops; + netdev->watchdog_timeo = 2*HZ; + + qlcnic_change_mtu(netdev, netdev->mtu); + + SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); + + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->features |= (NETIF_F_GRO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + + if (adapter->pci_using_dac) { + netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) + netdev->features |= (NETIF_F_HW_VLAN_TX); + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) + netdev->features |= NETIF_F_LRO; + + netdev->irq = adapter->msix_entries[0].vector; + + INIT_WORK(&adapter->tx_timeout_task, qlcnic_tx_timeout_task); + + if (qlcnic_read_mac_addr(adapter)) + dev_warn(&pdev->dev, "failed to read mac addr\n"); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "failed to register net device\n"); + return err; + } + + return 0; +} + +static int __devinit +qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev = NULL; + struct qlcnic_adapter *adapter = NULL; + int err; + int pci_func_id = PCI_FUNC(pdev->devfn); + uint8_t revision_id; + + err = pci_enable_device(pdev); + if (err) + return err; + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + err = -ENODEV; + goto err_out_disable_pdev; + } + + err = pci_request_regions(pdev, qlcnic_driver_name); + if (err) + goto err_out_disable_pdev; + + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); + if (!netdev) { + dev_err(&pdev->dev, "failed to allocate net_device\n"); + err = -ENOMEM; + goto err_out_free_res; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; + adapter->ahw.pci_func = pci_func_id; + + revision_id = pdev->revision; + adapter->ahw.revision_id = revision_id; + + rwlock_init(&adapter->ahw.crb_lock); + mutex_init(&adapter->ahw.mem_lock); + + spin_lock_init(&adapter->tx_clean_lock); + INIT_LIST_HEAD(&adapter->mac_list); + + err = qlcnic_setup_pci_map(adapter); + if (err) + goto err_out_free_netdev; + + /* This will be reset for mezz cards */ + adapter->portnum = pci_func_id; + + err = qlcnic_get_board_info(adapter); + if (err) { + dev_err(&pdev->dev, "Error getting board config info.\n"); + goto err_out_iounmap; + } + + + err = qlcnic_start_firmware(adapter); + if (err) + goto err_out_decr_ref; + + /* + * See if the firmware gave us a virtual-physical port mapping. + */ + adapter->physical_port = adapter->portnum; + + qlcnic_clear_stats(adapter); + + qlcnic_setup_intr(adapter); + + err = qlcnic_setup_netdev(adapter, netdev); + if (err) + goto err_out_disable_msi; + + pci_set_drvdata(pdev, adapter); + + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); + + switch (adapter->ahw.port_type) { + case QLCNIC_GBE: + dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", + adapter->netdev->name); + break; + case QLCNIC_XGBE: + dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n", + adapter->netdev->name); + break; + } + + qlcnic_create_diag_entries(adapter); + + return 0; + +err_out_disable_msi: + qlcnic_teardown_intr(adapter); + +err_out_decr_ref: + qlcnic_clr_all_drv_state(adapter); + +err_out_iounmap: + qlcnic_cleanup_pci_map(adapter); + +err_out_free_netdev: + free_netdev(netdev); + +err_out_free_res: + pci_release_regions(pdev); + +err_out_disable_pdev: + pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); + return err; +} + +static void __devexit qlcnic_remove(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter; + struct net_device *netdev; + + adapter = pci_get_drvdata(pdev); + if (adapter == NULL) + return; + + netdev = adapter->netdev; + + qlcnic_cancel_fw_work(adapter); + + unregister_netdev(netdev); + + cancel_work_sync(&adapter->tx_timeout_task); + + qlcnic_detach(adapter); + + qlcnic_clr_all_drv_state(adapter); + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + + qlcnic_teardown_intr(adapter); + + qlcnic_remove_diag_entries(adapter); + + qlcnic_cleanup_pci_map(adapter); + + qlcnic_release_firmware(adapter); + + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + + free_netdev(netdev); +} +static int __qlcnic_shutdown(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int retval; + + netif_device_detach(netdev); + + qlcnic_cancel_fw_work(adapter); + + if (netif_running(netdev)) + qlcnic_down(adapter, netdev); + + cancel_work_sync(&adapter->tx_timeout_task); + + qlcnic_detach(adapter); + + qlcnic_clr_all_drv_state(adapter); + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + + retval = pci_save_state(pdev); + if (retval) + return retval; + + if (qlcnic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } + + return 0; +} + +static void qlcnic_shutdown(struct pci_dev *pdev) +{ + if (__qlcnic_shutdown(pdev)) + return; + + pci_disable_device(pdev); +} + +#ifdef CONFIG_PM +static int +qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int retval; + + retval = __qlcnic_shutdown(pdev); + if (retval) + return retval; + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int +qlcnic_resume(struct pci_dev *pdev) +{ + struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int err; + + err = pci_enable_device(pdev); + if (err) + return err; + + pci_set_power_state(pdev, PCI_D0); + pci_set_master(pdev); + pci_restore_state(pdev); + + adapter->ahw.crb_win = -1; + adapter->ahw.ocm_win = -1; + + err = qlcnic_start_firmware(adapter); + if (err) { + dev_err(&pdev->dev, "failed to start firmware\n"); + return err; + } + + if (netif_running(netdev)) { + err = qlcnic_attach(adapter); + if (err) + goto err_out; + + err = qlcnic_up(adapter, netdev); + if (err) + goto err_out_detach; + + + qlcnic_config_indev_addr(netdev, NETDEV_UP); + } + + netif_device_attach(netdev); + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); + return 0; + +err_out_detach: + qlcnic_detach(adapter); +err_out: + qlcnic_clr_all_drv_state(adapter); + return err; +} +#endif + +static int qlcnic_open(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int err; + + if (adapter->driver_mismatch) + return -EIO; + + err = qlcnic_attach(adapter); + if (err) + return err; + + err = __qlcnic_up(adapter, netdev); + if (err) + goto err_out; + + netif_start_queue(netdev); + + return 0; + +err_out: + qlcnic_detach(adapter); + return err; +} + +/* + * qlcnic_close - Disables a network interface entry point + */ +static int qlcnic_close(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + __qlcnic_down(adapter, netdev); + return 0; +} + +static void +qlcnic_tso_check(struct net_device *netdev, + struct qlcnic_host_tx_ring *tx_ring, + struct cmd_desc_type0 *first_desc, + struct sk_buff *skb) +{ + u8 opcode = TX_ETHER_PKT; + __be16 protocol = skb->protocol; + u16 flags = 0, vid = 0; + u32 producer; + int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; + struct cmd_desc_type0 *hwdesc; + struct vlan_ethhdr *vh; + + if (protocol == cpu_to_be16(ETH_P_8021Q)) { + + vh = (struct vlan_ethhdr *)skb->data; + protocol = vh->h_vlan_encapsulated_proto; + flags = FLAGS_VLAN_TAGGED; + + } else if (vlan_tx_tag_present(skb)) { + + flags = FLAGS_VLAN_OOB; + vid = vlan_tx_tag_get(skb); + qlcnic_set_tx_vlan_tci(first_desc, vid); + vlan_oob = 1; + } + + if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + skb_shinfo(skb)->gso_size > 0) { + + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + + first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + first_desc->total_hdr_length = hdr_len; + if (vlan_oob) { + first_desc->total_hdr_length += VLAN_HLEN; + first_desc->tcp_hdr_offset = VLAN_HLEN; + first_desc->ip_hdr_offset = VLAN_HLEN; + /* Only in case of TSO on vlan device */ + flags |= FLAGS_VLAN_TAGGED; + } + + opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? + TX_TCP_LSO6 : TX_TCP_LSO; + tso = 1; + + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + u8 l4proto; + + if (protocol == cpu_to_be16(ETH_P_IP)) { + l4proto = ip_hdr(skb)->protocol; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCP_PKT; + else if (l4proto == IPPROTO_UDP) + opcode = TX_UDP_PKT; + } else if (protocol == cpu_to_be16(ETH_P_IPV6)) { + l4proto = ipv6_hdr(skb)->nexthdr; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCPV6_PKT; + else if (l4proto == IPPROTO_UDP) + opcode = TX_UDPV6_PKT; + } + } + + first_desc->tcp_hdr_offset += skb_transport_offset(skb); + first_desc->ip_hdr_offset += skb_network_offset(skb); + qlcnic_set_tx_flags_opcode(first_desc, flags, opcode); + + if (!tso) + return; + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring + */ + producer = tx_ring->producer; + copied = 0; + offset = 2; + + if (vlan_oob) { + /* Create a TSO vlan header template for firmware */ + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + hdr_len + VLAN_HLEN); + + vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); + skb_copy_from_linear_data(skb, vh, 12); + vh->h_vlan_proto = htons(ETH_P_8021Q); + vh->h_vlan_TCI = htons(vid); + skb_copy_from_linear_data_offset(skb, 12, + (char *)vh + 16, copy_len - 16); + + copied = copy_len - VLAN_HLEN; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + while (copied < hdr_len) { + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + (hdr_len - copied)); + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + skb_copy_from_linear_data_offset(skb, copied, + (char *)hwdesc + offset, copy_len); + + copied += copy_len; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + tx_ring->producer = producer; + barrier(); +} + +static int +qlcnic_map_tx_skb(struct pci_dev *pdev, + struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf) +{ + struct qlcnic_skb_frag *nf; + struct skb_frag_struct *frag; + int i, nr_frags; + dma_addr_t map; + + nr_frags = skb_shinfo(skb)->nr_frags; + nf = &pbuf->frag_array[0]; + + map = pci_map_single(pdev, skb->data, + skb_headlen(skb), PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto out_err; + + nf->dma = map; + nf->length = skb_headlen(skb); + + for (i = 0; i < nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nf = &pbuf->frag_array[i+1]; + + map = pci_map_page(pdev, frag->page, frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto unwind; + + nf->dma = map; + nf->length = frag->size; + } + + return 0; + +unwind: + while (--i >= 0) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + } + + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + +out_err: + return -ENOMEM; +} + +static inline void +qlcnic_clear_cmddesc(u64 *desc) +{ + desc[0] = 0ULL; + desc[2] = 0ULL; +} + +static netdev_tx_t +qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + struct qlcnic_cmd_buffer *pbuf; + struct qlcnic_skb_frag *buffrag; + struct cmd_desc_type0 *hwdesc, *first_desc; + struct pci_dev *pdev; + int i, k; + + u32 producer; + int frag_count, no_of_desc; + u32 num_txd = tx_ring->num_desc; + + frag_count = skb_shinfo(skb)->nr_frags + 1; + + /* 4 fragments per cmd des */ + no_of_desc = (frag_count + 3) >> 2; + + if (unlikely(no_of_desc + 2 > qlcnic_tx_avail(tx_ring))) { + netif_stop_queue(netdev); + return NETDEV_TX_BUSY; + } + + producer = tx_ring->producer; + pbuf = &tx_ring->cmd_buf_arr[producer]; + + pdev = adapter->pdev; + + if (qlcnic_map_tx_skb(pdev, skb, pbuf)) + goto drop_packet; + + pbuf->skb = skb; + pbuf->frag_count = frag_count; + + first_desc = hwdesc = &tx_ring->desc_head[producer]; + qlcnic_clear_cmddesc((u64 *)hwdesc); + + qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len); + qlcnic_set_tx_port(first_desc, adapter->portnum); + + for (i = 0; i < frag_count; i++) { + + k = i % 4; + + if ((k == 0) && (i > 0)) { + /* move to next desc.*/ + producer = get_next_index(producer, num_txd); + hwdesc = &tx_ring->desc_head[producer]; + qlcnic_clear_cmddesc((u64 *)hwdesc); + tx_ring->cmd_buf_arr[producer].skb = NULL; + } + + buffrag = &pbuf->frag_array[i]; + + hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length); + switch (k) { + case 0: + hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); + break; + case 1: + hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma); + break; + case 2: + hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma); + break; + case 3: + hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma); + break; + } + } + + tx_ring->producer = get_next_index(producer, num_txd); + + qlcnic_tso_check(netdev, tx_ring, first_desc, skb); + + qlcnic_update_cmd_producer(adapter, tx_ring); + + adapter->stats.txbytes += skb->len; + adapter->stats.xmitcalled++; + + return NETDEV_TX_OK; + +drop_packet: + adapter->stats.txdropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static int qlcnic_check_temp(struct qlcnic_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + u32 temp, temp_state, temp_val; + int rv = 0; + + temp = QLCRD32(adapter, CRB_TEMP_STATE); + + temp_state = qlcnic_get_temp_state(temp); + temp_val = qlcnic_get_temp_val(temp); + + if (temp_state == QLCNIC_TEMP_PANIC) { + dev_err(&netdev->dev, + "Device temperature %d degrees C exceeds" + " maximum allowed. Hardware has been shut down.\n", + temp_val); + rv = 1; + } else if (temp_state == QLCNIC_TEMP_WARN) { + if (adapter->temp == QLCNIC_TEMP_NORMAL) { + dev_err(&netdev->dev, + "Device temperature %d degrees C " + "exceeds operating range." + " Immediate action needed.\n", + temp_val); + } + } else { + if (adapter->temp == QLCNIC_TEMP_WARN) { + dev_info(&netdev->dev, + "Device temperature is now %d degrees C" + " in normal range.\n", temp_val); + } + } + adapter->temp = temp_state; + return rv; +} + +void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) +{ + struct net_device *netdev = adapter->netdev; + + if (adapter->ahw.linkup && !linkup) { + dev_info(&netdev->dev, "NIC Link is down\n"); + adapter->ahw.linkup = 0; + if (netif_running(netdev)) { + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } else if (!adapter->ahw.linkup && linkup) { + dev_info(&netdev->dev, "NIC Link is up\n"); + adapter->ahw.linkup = 1; + if (netif_running(netdev)) { + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + } +} + +static void qlcnic_tx_timeout(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) + return; + + dev_err(&netdev->dev, "transmit timeout, resetting.\n"); + schedule_work(&adapter->tx_timeout_task); +} + +static void qlcnic_tx_timeout_task(struct work_struct *work) +{ + struct qlcnic_adapter *adapter = + container_of(work, struct qlcnic_adapter, tx_timeout_task); + + if (!netif_running(adapter->netdev)) + return; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return; + + if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) + goto request_reset; + + clear_bit(__QLCNIC_RESETTING, &adapter->state); + if (!qlcnic_reset_context(adapter)) { + adapter->netdev->trans_start = jiffies; + return; + + /* context reset failed, fall through for fw reset */ + } + +request_reset: + adapter->need_fw_reset = 1; + clear_bit(__QLCNIC_RESETTING, &adapter->state); +} + +static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct net_device_stats *stats = &netdev->stats; + + memset(stats, 0, sizeof(*stats)); + + stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; + stats->tx_packets = adapter->stats.xmitfinished; + stats->rx_bytes = adapter->stats.rxbytes; + stats->tx_bytes = adapter->stats.txbytes; + stats->rx_dropped = adapter->stats.rxdropped; + stats->tx_dropped = adapter->stats.txdropped; + + return stats; +} + +static irqreturn_t qlcnic_intr(int irq, void *data) +{ + struct qlcnic_host_sds_ring *sds_ring = data; + struct qlcnic_adapter *adapter = sds_ring->adapter; + u32 status; + + status = readl(adapter->isr_int_vec); + + if (!(status & adapter->int_vec_bit)) + return IRQ_NONE; + + /* check interrupt state machine, to be sure */ + status = readl(adapter->crb_int_state_reg); + if (!ISR_LEGACY_INT_TRIGGERED(status)) + return IRQ_NONE; + + writel(0xffffffff, adapter->tgt_status_reg); + /* read twice to ensure write is flushed */ + readl(adapter->isr_int_vec); + readl(adapter->isr_int_vec); + + napi_schedule(&sds_ring->napi); + + return IRQ_HANDLED; +} + +static irqreturn_t qlcnic_msi_intr(int irq, void *data) +{ + struct qlcnic_host_sds_ring *sds_ring = data; + struct qlcnic_adapter *adapter = sds_ring->adapter; + + /* clear interrupt */ + writel(0xffffffff, adapter->tgt_status_reg); + + napi_schedule(&sds_ring->napi); + return IRQ_HANDLED; +} + +static irqreturn_t qlcnic_msix_intr(int irq, void *data) +{ + struct qlcnic_host_sds_ring *sds_ring = data; + + napi_schedule(&sds_ring->napi); + return IRQ_HANDLED; +} + +static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) +{ + u32 sw_consumer, hw_consumer; + int count = 0, i; + struct qlcnic_cmd_buffer *buffer; + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; + struct qlcnic_skb_frag *frag; + int done; + struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; + + if (!spin_trylock(&adapter->tx_clean_lock)) + return 1; + + sw_consumer = tx_ring->sw_consumer; + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + + while (sw_consumer != hw_consumer) { + buffer = &tx_ring->cmd_buf_arr[sw_consumer]; + if (buffer->skb) { + frag = &buffer->frag_array[0]; + pci_unmap_single(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + frag->dma = 0ULL; + for (i = 1; i < buffer->frag_count; i++) { + frag++; + pci_unmap_page(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + frag->dma = 0ULL; + } + + adapter->stats.xmitfinished++; + dev_kfree_skb_any(buffer->skb); + buffer->skb = NULL; + } + + sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); + if (++count >= MAX_STATUS_HANDLE) + break; + } + + if (count && netif_running(netdev)) { + tx_ring->sw_consumer = sw_consumer; + + smp_mb(); + + if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { + __netif_tx_lock(tx_ring->txq, smp_processor_id()); + if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { + netif_wake_queue(netdev); + adapter->tx_timeo_cnt = 0; + } + __netif_tx_unlock(tx_ring->txq); + } + } + /* + * If everything is freed up to consumer then check if the ring is full + * If the ring is full then check if more needs to be freed and + * schedule the call back again. + * + * This happens when there are 2 CPUs. One could be freeing and the + * other filling it. If the ring is full when we get out of here and + * the card has already interrupted the host then the host can miss the + * interrupt. + * + * There is still a possible race condition and the host could miss an + * interrupt. The card has to take care of this. + */ + hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); + done = (sw_consumer == hw_consumer); + spin_unlock(&adapter->tx_clean_lock); + + return done; +} + +static int qlcnic_poll(struct napi_struct *napi, int budget) +{ + struct qlcnic_host_sds_ring *sds_ring = + container_of(napi, struct qlcnic_host_sds_ring, napi); + + struct qlcnic_adapter *adapter = sds_ring->adapter; + + int tx_complete; + int work_done; + + tx_complete = qlcnic_process_cmd_ring(adapter); + + work_done = qlcnic_process_rcv_ring(sds_ring, budget); + + if ((work_done < budget) && tx_complete) { + napi_complete(&sds_ring->napi); + if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) + qlcnic_enable_int(sds_ring); + } + + return work_done; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void qlcnic_poll_controller(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + disable_irq(adapter->irq); + qlcnic_intr(adapter->irq, adapter); + enable_irq(adapter->irq); +} +#endif + +static void +qlcnic_set_drv_state(struct qlcnic_adapter *adapter, int state) +{ + u32 val; + + WARN_ON(state != QLCNIC_DEV_NEED_RESET && + state != QLCNIC_DEV_NEED_QUISCENT); + + if (qlcnic_api_lock(adapter)) + return ; + + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + + if (state == QLCNIC_DEV_NEED_RESET) + val |= ((u32)0x1 << (adapter->portnum * 4)); + else if (state == QLCNIC_DEV_NEED_QUISCENT) + val |= ((u32)0x1 << ((adapter->portnum * 4) + 1)); + + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + + qlcnic_api_unlock(adapter); +} + +static void +qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter) +{ + u32 val; + + if (qlcnic_api_lock(adapter)) + goto err; + + val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + val &= ~((u32)0x1 << (adapter->portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); + + if (!(val & 0x11111111)) + QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD); + + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + val &= ~((u32)0x3 << (adapter->portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + + qlcnic_api_unlock(adapter); +err: + adapter->fw_fail_cnt = 0; + clear_bit(__QLCNIC_START_FW, &adapter->state); + clear_bit(__QLCNIC_RESETTING, &adapter->state); +} + +static int +qlcnic_check_drv_state(struct qlcnic_adapter *adapter) +{ + int act, state; + + state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + act = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + + if (((state & 0x11111111) == (act & 0x11111111)) || + ((act & 0x11111111) == ((state >> 1) & 0x11111111))) + return 0; + else + return 1; +} + +static int +qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) +{ + u32 val, prev_state; + int cnt = 0; + int portnum = adapter->portnum; + + if (qlcnic_api_lock(adapter)) + return -1; + + val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); + if (!(val & ((int)0x1 << (portnum * 4)))) { + val |= ((u32)0x1 << (portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); + } else if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state)) { + goto start_fw; + } + + prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + + switch (prev_state) { + case QLCNIC_DEV_COLD: +start_fw: + QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITALIZING); + qlcnic_api_unlock(adapter); + return 1; + + case QLCNIC_DEV_READY: + qlcnic_api_unlock(adapter); + return 0; + + case QLCNIC_DEV_NEED_RESET: + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + val |= ((u32)0x1 << (portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + break; + + case QLCNIC_DEV_NEED_QUISCENT: + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + val |= ((u32)0x1 << ((portnum * 4) + 1)); + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + break; + + case QLCNIC_DEV_FAILED: + qlcnic_api_unlock(adapter); + return -1; + } + + qlcnic_api_unlock(adapter); + msleep(1000); + while ((QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) != QLCNIC_DEV_READY) && + ++cnt < 20) + msleep(1000); + + if (cnt >= 20) + return -1; + + if (qlcnic_api_lock(adapter)) + return -1; + + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + val &= ~((u32)0x3 << (portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + + qlcnic_api_unlock(adapter); + + return 0; +} + +static void +qlcnic_fwinit_work(struct work_struct *work) +{ + struct qlcnic_adapter *adapter = container_of(work, + struct qlcnic_adapter, fw_work.work); + int dev_state; + + if (++adapter->fw_wait_cnt > FW_POLL_THRESH) + goto err_ret; + + if (test_bit(__QLCNIC_START_FW, &adapter->state)) { + + if (qlcnic_check_drv_state(adapter)) { + qlcnic_schedule_work(adapter, + qlcnic_fwinit_work, FW_POLL_DELAY); + return; + } + + if (!qlcnic_start_firmware(adapter)) { + qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); + return; + } + + goto err_ret; + } + + dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + switch (dev_state) { + case QLCNIC_DEV_READY: + if (!qlcnic_start_firmware(adapter)) { + qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); + return; + } + case QLCNIC_DEV_FAILED: + break; + + default: + qlcnic_schedule_work(adapter, + qlcnic_fwinit_work, 2 * FW_POLL_DELAY); + return; + } + +err_ret: + qlcnic_clr_all_drv_state(adapter); +} + +static void +qlcnic_detach_work(struct work_struct *work) +{ + struct qlcnic_adapter *adapter = container_of(work, + struct qlcnic_adapter, fw_work.work); + struct net_device *netdev = adapter->netdev; + u32 status; + + netif_device_detach(netdev); + + qlcnic_down(adapter, netdev); + + qlcnic_detach(adapter); + + status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); + + if (status & QLCNIC_RCODE_FATAL_ERROR) + goto err_ret; + + if (adapter->temp == QLCNIC_TEMP_PANIC) + goto err_ret; + + qlcnic_set_drv_state(adapter, adapter->dev_state); + + adapter->fw_wait_cnt = 0; + + qlcnic_schedule_work(adapter, qlcnic_fwinit_work, FW_POLL_DELAY); + + return; + +err_ret: + qlcnic_clr_all_drv_state(adapter); + +} + +static void +qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) +{ + u32 state; + + if (qlcnic_api_lock(adapter)) + return; + + state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + + if (state != QLCNIC_DEV_INITALIZING && state != QLCNIC_DEV_NEED_RESET) { + QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET); + set_bit(__QLCNIC_START_FW, &adapter->state); + } + + qlcnic_api_unlock(adapter); +} + +static void +qlcnic_schedule_work(struct qlcnic_adapter *adapter, + work_func_t func, int delay) +{ + INIT_DELAYED_WORK(&adapter->fw_work, func); + schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay)); +} + +static void +qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter) +{ + while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + msleep(10); + + cancel_delayed_work_sync(&adapter->fw_work); +} + +static void +qlcnic_attach_work(struct work_struct *work) +{ + struct qlcnic_adapter *adapter = container_of(work, + struct qlcnic_adapter, fw_work.work); + struct net_device *netdev = adapter->netdev; + int err; + + if (netif_running(netdev)) { + err = qlcnic_attach(adapter); + if (err) + goto done; + + err = qlcnic_up(adapter, netdev); + if (err) { + qlcnic_detach(adapter); + goto done; + } + + qlcnic_config_indev_addr(netdev, NETDEV_UP); + } + + netif_device_attach(netdev); + +done: + adapter->fw_fail_cnt = 0; + clear_bit(__QLCNIC_RESETTING, &adapter->state); + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); +} + +static int +qlcnic_check_health(struct qlcnic_adapter *adapter) +{ + u32 state = 0, heartbit; + struct net_device *netdev = adapter->netdev; + + if (qlcnic_check_temp(adapter)) + goto detach; + + if (adapter->need_fw_reset) { + qlcnic_dev_request_reset(adapter); + goto detach; + } + + state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); + if (state == QLCNIC_DEV_NEED_RESET || state == QLCNIC_DEV_NEED_QUISCENT) + adapter->need_fw_reset = 1; + + heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); + if (heartbit != adapter->heartbit) { + adapter->heartbit = heartbit; + adapter->fw_fail_cnt = 0; + if (adapter->need_fw_reset) + goto detach; + return 0; + } + + if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) + return 0; + + qlcnic_dev_request_reset(adapter); + + clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state); + + dev_info(&netdev->dev, "firmware hang detected\n"); + +detach: + adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state : + QLCNIC_DEV_NEED_RESET; + + if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && + !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + qlcnic_schedule_work(adapter, qlcnic_detach_work, 0); + + return 1; +} + +static void +qlcnic_fw_poll_work(struct work_struct *work) +{ + struct qlcnic_adapter *adapter = container_of(work, + struct qlcnic_adapter, fw_work.work); + + if (test_bit(__QLCNIC_RESETTING, &adapter->state)) + goto reschedule; + + + if (qlcnic_check_health(adapter)) + return; + +reschedule: + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); +} + +static ssize_t +qlcnic_store_bridged_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + unsigned long new; + int ret = -EINVAL; + + if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)) + goto err_out; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + goto err_out; + + if (strict_strtoul(buf, 2, &new)) + goto err_out; + + if (!qlcnic_config_bridged_mode(adapter, !!new)) + ret = len; + +err_out: + return ret; +} + +static ssize_t +qlcnic_show_bridged_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + int bridged_mode = 0; + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) + bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED); + + return sprintf(buf, "%d\n", bridged_mode); +} + +static struct device_attribute dev_attr_bridged_mode = { + .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, + .show = qlcnic_show_bridged_mode, + .store = qlcnic_store_bridged_mode, +}; + +static ssize_t +qlcnic_store_diag_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + unsigned long new; + + if (strict_strtoul(buf, 2, &new)) + return -EINVAL; + + if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED)) + adapter->flags ^= QLCNIC_DIAG_ENABLED; + + return len; +} + +static ssize_t +qlcnic_show_diag_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", + !!(adapter->flags & QLCNIC_DIAG_ENABLED)); +} + +static struct device_attribute dev_attr_diag_mode = { + .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, + .show = qlcnic_show_diag_mode, + .store = qlcnic_store_diag_mode, +}; + +static int +qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, + loff_t offset, size_t size) +{ + if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) + return -EIO; + + if ((size != 4) || (offset & 0x3)) + return -EINVAL; + + if (offset < QLCNIC_PCI_CRBSPACE) + return -EINVAL; + + return 0; +} + +static ssize_t +qlcnic_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u32 data; + int ret; + + ret = qlcnic_sysfs_validate_crb(adapter, offset, size); + if (ret != 0) + return ret; + + data = QLCRD32(adapter, offset); + memcpy(buf, &data, size); + return size; +} + +static ssize_t +qlcnic_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u32 data; + int ret; + + ret = qlcnic_sysfs_validate_crb(adapter, offset, size); + if (ret != 0) + return ret; + + memcpy(&data, buf, size); + QLCWR32(adapter, offset, data); + return size; +} + +static int +qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, + loff_t offset, size_t size) +{ + if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) + return -EIO; + + if ((size != 8) || (offset & 0x7)) + return -EIO; + + return 0; +} + +static ssize_t +qlcnic_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u64 data; + int ret; + + ret = qlcnic_sysfs_validate_mem(adapter, offset, size); + if (ret != 0) + return ret; + + if (qlcnic_pci_mem_read_2M(adapter, offset, &data)) + return -EIO; + + memcpy(buf, &data, size); + + return size; +} + +static ssize_t +qlcnic_sysfs_write_mem(struct kobject *kobj, struct bin_attribute *attr, + char *buf, loff_t offset, size_t size) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + u64 data; + int ret; + + ret = qlcnic_sysfs_validate_mem(adapter, offset, size); + if (ret != 0) + return ret; + + memcpy(&data, buf, size); + + if (qlcnic_pci_mem_write_2M(adapter, offset, data)) + return -EIO; + + return size; +} + + +static struct bin_attribute bin_attr_crb = { + .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_crb, + .write = qlcnic_sysfs_write_crb, +}; + +static struct bin_attribute bin_attr_mem = { + .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, + .size = 0, + .read = qlcnic_sysfs_read_mem, + .write = qlcnic_sysfs_write_mem, +}; + +static void +qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) + if (device_create_file(dev, &dev_attr_bridged_mode)) + dev_warn(dev, + "failed to create bridged_mode sysfs entry\n"); +} + +static void +qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG) + device_remove_file(dev, &dev_attr_bridged_mode); +} + +static void +qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + if (device_create_file(dev, &dev_attr_diag_mode)) + dev_info(dev, "failed to create diag_mode sysfs entry\n"); + if (device_create_bin_file(dev, &bin_attr_crb)) + dev_info(dev, "failed to create crb sysfs entry\n"); + if (device_create_bin_file(dev, &bin_attr_mem)) + dev_info(dev, "failed to create mem sysfs entry\n"); +} + + +static void +qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) +{ + struct device *dev = &adapter->pdev->dev; + + device_remove_file(dev, &dev_attr_diag_mode); + device_remove_bin_file(dev, &bin_attr_crb); + device_remove_bin_file(dev, &bin_attr_mem); +} + +#ifdef CONFIG_INET + +#define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops) + +static int +qlcnic_destip_supported(struct qlcnic_adapter *adapter) +{ + if (adapter->ahw.cut_through) + return 0; + + return 1; +} + +static void +qlcnic_config_indev_addr(struct net_device *dev, unsigned long event) +{ + struct in_device *indev; + struct qlcnic_adapter *adapter = netdev_priv(dev); + + if (!qlcnic_destip_supported(adapter)) + return; + + indev = in_dev_get(dev); + if (!indev) + return; + + for_ifa(indev) { + switch (event) { + case NETDEV_UP: + qlcnic_config_ipaddr(adapter, + ifa->ifa_address, QLCNIC_IP_UP); + break; + case NETDEV_DOWN: + qlcnic_config_ipaddr(adapter, + ifa->ifa_address, QLCNIC_IP_DOWN); + break; + default: + break; + } + } endfor_ifa(indev); + + in_dev_put(indev); + return; +} + +static int qlcnic_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct qlcnic_adapter *adapter; + struct net_device *dev = (struct net_device *)ptr; + +recheck: + if (dev == NULL) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_qlcnic_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter) + goto done; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + goto done; + + qlcnic_config_indev_addr(dev, event); +done: + return NOTIFY_DONE; +} + +static int +qlcnic_inetaddr_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct qlcnic_adapter *adapter; + struct net_device *dev; + + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + + dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; + +recheck: + if (dev == NULL || !netif_running(dev)) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_qlcnic_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter || !qlcnic_destip_supported(adapter)) + goto done; + + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + goto done; + + switch (event) { + case NETDEV_UP: + qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP); + break; + case NETDEV_DOWN: + qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN); + break; + default: + break; + } + +done: + return NOTIFY_DONE; +} + +static struct notifier_block qlcnic_netdev_cb = { + .notifier_call = qlcnic_netdev_event, +}; + +static struct notifier_block qlcnic_inetaddr_cb = { + .notifier_call = qlcnic_inetaddr_event, +}; +#else +static void +qlcnic_config_indev_addr(struct net_device *dev, unsigned long event) +{ } +#endif + +static struct pci_driver qlcnic_driver = { + .name = qlcnic_driver_name, + .id_table = qlcnic_pci_tbl, + .probe = qlcnic_probe, + .remove = __devexit_p(qlcnic_remove), +#ifdef CONFIG_PM + .suspend = qlcnic_suspend, + .resume = qlcnic_resume, +#endif + .shutdown = qlcnic_shutdown +}; + +static int __init qlcnic_init_module(void) +{ + + printk(KERN_INFO "%s\n", qlcnic_driver_string); + +#ifdef CONFIG_INET + register_netdevice_notifier(&qlcnic_netdev_cb); + register_inetaddr_notifier(&qlcnic_inetaddr_cb); +#endif + + + return pci_register_driver(&qlcnic_driver); +} + +module_init(qlcnic_init_module); + +static void __exit qlcnic_exit_module(void) +{ + + pci_unregister_driver(&qlcnic_driver); + +#ifdef CONFIG_INET + unregister_inetaddr_notifier(&qlcnic_inetaddr_cb); + unregister_netdevice_notifier(&qlcnic_netdev_cb); +#endif +} + +module_exit(qlcnic_exit_module); -- cgit v1.2.3 From 0ec00f0392b807d57a2281576a96552d7694b6bb Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Wed, 13 Jan 2010 00:37:26 +0000 Subject: NET: Add Qlogic ethernet driver for CNA devices o Separate Ethernet driver for Qlogic CNA devices Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- MAINTAINERS | 7 +++++++ drivers/net/Kconfig | 7 +++++++ drivers/net/Makefile | 1 + 3 files changed, 15 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 337dffbe9a47..61367ec865cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4452,6 +4452,13 @@ S: Supported F: Documentation/networking/LICENSE.qla3xxx F: drivers/net/qla3xxx.* +QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER +M: Amit Kumar Salecha +M: linux-driver@qlogic.com +L: netdev@vger.kernel.org +S: Supported +F: drivers/net/qlcnic/ + QLOGIC QLGE 10Gb ETHERNET DRIVER M: Ron Mercer M: linux-driver@qlogic.com diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5be6a2376f4f..cb0e534418e3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2778,6 +2778,13 @@ config BNX2X To compile this driver as a module, choose M here: the module will be called bnx2x. This is recommended. +config QLCNIC + tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support" + depends on PCI + help + This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet + devices. + config QLGE tristate "QLogic QLGE 10Gb Ethernet Driver Support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6746e8b8bdfc..0b763cbe9b1f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -149,6 +149,7 @@ ll_temac-objs := ll_temac_main.o ll_temac_mdio.o obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o +obj-$(CONFIG_QLCNIC) += qlcnic/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_PPP) += ppp_generic.o -- cgit v1.2.3 From 72659ecce68588b74f6c46862c2b4cec137d7a5a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 17 Jan 2010 19:09:39 -0800 Subject: tcp: account SYN-ACK timeouts & retransmissions Currently we don't increment SYN-ACK timeouts & retransmissions although we do increment the same stats for SYN. We seem to have lost the SYN-ACK accounting with the introduction of tcp_syn_recv_timer (commit 2248761e in the netdev-vger-cvs tree). This patch fixes this issue. In the process we also rename the v4/v6 syn/ack retransmit functions for clarity. We also add a new request_socket operations (syn_ack_timeout) so we can keep code in inet_connection_sock.c protocol agnostic. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- include/net/request_sock.h | 2 ++ include/net/tcp.h | 2 ++ net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/tcp_ipv4.c | 18 ++++++++++-------- net/ipv4/tcp_timer.c | 6 ++++++ net/ipv6/tcp_ipv6.c | 12 ++++++++++-- 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/include/net/request_sock.h b/include/net/request_sock.h index c9b50ebd9ce9..99e6e19b57c2 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -45,6 +45,8 @@ struct request_sock_ops { void (*send_reset)(struct sock *sk, struct sk_buff *skb); void (*destructor)(struct request_sock *req); + void (*syn_ack_timeout)(struct sock *sk, + struct request_sock *req); }; /* struct request_sock - mini sock to represent a connection request diff --git a/include/net/tcp.h b/include/net/tcp.h index 788c99f98597..87d164b9bd8f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -400,6 +400,8 @@ extern int compat_tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); extern void tcp_set_keepalive(struct sock *sk, int val); +extern void tcp_syn_ack_timeout(struct sock *sk, + struct request_sock *req); extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int nonblock, diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ee16475f8fc3..8da6429269dd 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -529,6 +529,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, syn_ack_recalc(req, thresh, max_retries, queue->rskq_defer_accept, &expire, &resend); + if (req->rsk_ops->syn_ack_timeout) + req->rsk_ops->syn_ack_timeout(parent, req); if (!expire && (!resend || !req->rsk_ops->rtx_syn_ack(parent, req, NULL) || diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 382f667238ec..356f544c4c10 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -742,9 +742,9 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, * This still operates on a request_sock only, not on a big * socket. */ -static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, - struct request_sock *req, - struct request_values *rvp) +static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, + struct request_sock *req, + struct request_values *rvp) { const struct inet_request_sock *ireq = inet_rsk(req); int err = -1; @@ -775,10 +775,11 @@ static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, return err; } -static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, +static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req, struct request_values *rvp) { - return __tcp_v4_send_synack(sk, NULL, req, rvp); + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); + return tcp_v4_send_synack(sk, NULL, req, rvp); } /* @@ -1192,10 +1193,11 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), - .rtx_syn_ack = tcp_v4_send_synack, + .rtx_syn_ack = tcp_v4_rtx_synack, .send_ack = tcp_v4_reqsk_send_ack, .destructor = tcp_v4_reqsk_destructor, .send_reset = tcp_v4_send_reset, + .syn_ack_timeout = tcp_syn_ack_timeout, }; #ifdef CONFIG_TCP_MD5SIG @@ -1373,8 +1375,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) } tcp_rsk(req)->snt_isn = isn; - if (__tcp_v4_send_synack(sk, dst, req, - (struct request_values *)&tmp_ext) || + if (tcp_v4_send_synack(sk, dst, req, + (struct request_values *)&tmp_ext) || want_cookie) goto drop_and_free; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8816a20c2597..de7d1bf9114f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -474,6 +474,12 @@ static void tcp_synack_timer(struct sock *sk) TCP_TIMEOUT_INIT, TCP_RTO_MAX); } +void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req) +{ + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEOUTS); +} +EXPORT_SYMBOL(tcp_syn_ack_timeout); + void tcp_set_keepalive(struct sock *sk, int val) { if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1c832bf198b3..82f2dea0e39e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -520,6 +520,13 @@ done: return err; } +static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, + struct request_values *rvp) +{ + TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); + return tcp_v6_send_synack(sk, req, rvp); +} + static inline void syn_flood_warning(struct sk_buff *skb) { #ifdef CONFIG_SYN_COOKIES @@ -890,10 +897,11 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), - .rtx_syn_ack = tcp_v6_send_synack, + .rtx_syn_ack = tcp_v6_rtx_synack, .send_ack = tcp_v6_reqsk_send_ack, .destructor = tcp_v6_reqsk_destructor, - .send_reset = tcp_v6_send_reset + .send_reset = tcp_v6_send_reset, + .syn_ack_timeout = tcp_syn_ack_timeout, }; #ifdef CONFIG_TCP_MD5SIG -- cgit v1.2.3 From 2c8c1e7297e19bdef3c178c3ea41d898a7716e3e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 17 Jan 2010 03:35:32 +0000 Subject: net: spread __net_init, __net_exit __net_init/__net_exit are apparently not going away, so use them to full extent. In some cases __net_init was removed, because it was called from __net_exit code. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 12 ++++++------ net/8021q/vlan.c | 4 ++-- net/8021q/vlanproc.c | 2 +- net/bridge/br_if.c | 2 +- net/core/fib_rules.c | 2 +- net/core/rtnetlink.c | 4 ++-- net/core/sock.c | 4 ++-- net/dccp/ipv4.c | 4 ++-- net/dccp/ipv6.c | 4 ++-- net/ipv4/fib_frontend.c | 4 ++-- net/ipv4/igmp.c | 4 ++-- net/ipv4/ip_fragment.c | 8 ++++---- net/ipv4/ip_gre.c | 4 ++-- net/ipv4/ipip.c | 7 +++---- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/udp.c | 4 ++-- net/ipv4/udplite.c | 4 ++-- net/ipv6/addrconf.c | 8 ++++---- net/ipv6/af_inet6.c | 4 ++-- net/ipv6/anycast.c | 2 +- net/ipv6/fib6_rules.c | 4 ++-- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_fib.c | 6 +++--- net/ipv6/ip6_flowlabel.c | 9 ++++----- net/ipv6/ip6_tunnel.c | 9 ++++----- net/ipv6/mcast.c | 13 ++++++------- net/ipv6/ndisc.c | 4 ++-- net/ipv6/proc.c | 4 ++-- net/ipv6/raw.c | 4 ++-- net/ipv6/reassembly.c | 8 ++++---- net/ipv6/route.c | 6 +++--- net/ipv6/sit.c | 9 ++++----- net/ipv6/sysctl_net_ipv6.c | 4 ++-- net/ipv6/tcp_ipv6.c | 8 ++++---- net/ipv6/udp.c | 2 +- net/ipv6/udplite.c | 4 ++-- net/key/af_key.c | 6 +++--- net/packet/af_packet.c | 4 ++-- net/phonet/pn_dev.c | 4 ++-- net/sysctl_net.c | 4 ++-- net/unix/af_unix.c | 4 ++-- net/unix/sysctl_net_unix.c | 2 +- net/wireless/wext-proc.c | 4 ++-- net/xfrm/xfrm_sysctl.c | 4 ++-- 44 files changed, 107 insertions(+), 112 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6a42a1453afa..99a0ff3889ee 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3307,7 +3307,7 @@ static void bond_remove_proc_entry(struct bonding *bond) /* Create the bonding directory under /proc/net, if doesn't exist yet. * Caller must hold rtnl_lock. */ -static void bond_create_proc_dir(struct bond_net *bn) +static void __net_init bond_create_proc_dir(struct bond_net *bn) { if (!bn->proc_dir) { bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net); @@ -3320,7 +3320,7 @@ static void bond_create_proc_dir(struct bond_net *bn) /* Destroy the bonding directory under /proc/net, if empty. * Caller must hold rtnl_lock. */ -static void bond_destroy_proc_dir(struct bond_net *bn) +static void __net_exit bond_destroy_proc_dir(struct bond_net *bn) { if (bn->proc_dir) { remove_proc_entry(DRV_NAME, bn->net->proc_net); @@ -3338,11 +3338,11 @@ static void bond_remove_proc_entry(struct bonding *bond) { } -static void bond_create_proc_dir(struct bond_net *bn) +static inline void bond_create_proc_dir(struct bond_net *bn) { } -static void bond_destroy_proc_dir(struct bond_net *bn) +static inline void bond_destroy_proc_dir(struct bond_net *bn) { } @@ -4955,7 +4955,7 @@ out_netdev: goto out; } -static int bond_net_init(struct net *net) +static int __net_init bond_net_init(struct net *net) { struct bond_net *bn = net_generic(net, bond_net_id); @@ -4967,7 +4967,7 @@ static int bond_net_init(struct net *net) return 0; } -static void bond_net_exit(struct net *net) +static void __net_exit bond_net_exit(struct net *net) { struct bond_net *bn = net_generic(net, bond_net_id); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 33f90e7362cc..453512266ea1 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -663,7 +663,7 @@ out: return err; } -static int vlan_init_net(struct net *net) +static int __net_init vlan_init_net(struct net *net) { struct vlan_net *vn = net_generic(net, vlan_net_id); int err; @@ -675,7 +675,7 @@ static int vlan_init_net(struct net *net) return err; } -static void vlan_exit_net(struct net *net) +static void __net_exit vlan_exit_net(struct net *net) { vlan_proc_cleanup(net); } diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 9ec1f057c03a..afead353e215 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -140,7 +140,7 @@ void vlan_proc_cleanup(struct net *net) * Create /proc/net/vlan entries */ -int vlan_proc_init(struct net *net) +int __net_init vlan_proc_init(struct net *net) { struct vlan_net *vn = net_generic(net, vlan_net_id); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index a2cbe61f6e65..7bc0604069c7 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -467,7 +467,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) return 0; } -void br_net_exit(struct net *net) +void __net_exit br_net_exit(struct net *net) { struct net_device *dev; LIST_HEAD(list); diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 02a3b2c69c1e..9a24377146bf 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -708,7 +708,7 @@ static struct notifier_block fib_rules_notifier = { .notifier_call = fib_rules_event, }; -static int fib_rules_net_init(struct net *net) +static int __net_init fib_rules_net_init(struct net *net) { INIT_LIST_HEAD(&net->rules_ops); spin_lock_init(&net->rules_mod_lock); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 794bcb897ff0..62f3878a6010 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1386,7 +1386,7 @@ static struct notifier_block rtnetlink_dev_notifier = { }; -static int rtnetlink_net_init(struct net *net) +static int __net_init rtnetlink_net_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, @@ -1397,7 +1397,7 @@ static int rtnetlink_net_init(struct net *net) return 0; } -static void rtnetlink_net_exit(struct net *net) +static void __net_exit rtnetlink_net_exit(struct net *net) { netlink_kernel_release(net->rtnl); net->rtnl = NULL; diff --git a/net/core/sock.c b/net/core/sock.c index 10b1d3243a72..ceef50bd131b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2140,13 +2140,13 @@ int sock_prot_inuse_get(struct net *net, struct proto *prot) } EXPORT_SYMBOL_GPL(sock_prot_inuse_get); -static int sock_inuse_init_net(struct net *net) +static int __net_init sock_inuse_init_net(struct net *net) { net->core.inuse = alloc_percpu(struct prot_inuse); return net->core.inuse ? 0 : -ENOMEM; } -static void sock_inuse_exit_net(struct net *net) +static void __net_exit sock_inuse_exit_net(struct net *net) { free_percpu(net->core.inuse); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index dad7bc4878e0..b195c4feaa0a 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -996,7 +996,7 @@ static struct inet_protosw dccp_v4_protosw = { .flags = INET_PROTOSW_ICSK, }; -static int dccp_v4_init_net(struct net *net) +static int __net_init dccp_v4_init_net(struct net *net) { int err; @@ -1005,7 +1005,7 @@ static int dccp_v4_init_net(struct net *net) return err; } -static void dccp_v4_exit_net(struct net *net) +static void __net_exit dccp_v4_exit_net(struct net *net) { inet_ctl_sock_destroy(net->dccp.v4_ctl_sk); } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index baf05cf43c28..1aec6349e858 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -1189,7 +1189,7 @@ static struct inet_protosw dccp_v6_protosw = { .flags = INET_PROTOSW_ICSK, }; -static int dccp_v6_init_net(struct net *net) +static int __net_init dccp_v6_init_net(struct net *net) { int err; @@ -1198,7 +1198,7 @@ static int dccp_v6_init_net(struct net *net) return err; } -static void dccp_v6_exit_net(struct net *net) +static void __net_exit dccp_v6_exit_net(struct net *net) { inet_ctl_sock_destroy(net->dccp.v6_ctl_sk); } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 82dbf711d6d0..9b3e28ed5240 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -883,7 +883,7 @@ static void nl_fib_input(struct sk_buff *skb) netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT); } -static int nl_fib_lookup_init(struct net *net) +static int __net_init nl_fib_lookup_init(struct net *net) { struct sock *sk; sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0, @@ -1004,7 +1004,7 @@ fail: return err; } -static void __net_exit ip_fib_net_exit(struct net *net) +static void ip_fib_net_exit(struct net *net) { unsigned int i; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 76c08402c933..8f5468393f01 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -2603,7 +2603,7 @@ static const struct file_operations igmp_mcf_seq_fops = { .release = seq_release_net, }; -static int igmp_net_init(struct net *net) +static int __net_init igmp_net_init(struct net *net) { struct proc_dir_entry *pde; @@ -2621,7 +2621,7 @@ out_igmp: return -ENOMEM; } -static void igmp_net_exit(struct net *net) +static void __net_exit igmp_net_exit(struct net *net) { proc_net_remove(net, "mcfilter"); proc_net_remove(net, "igmp"); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 86964b353c31..891c72aea520 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -646,7 +646,7 @@ static struct ctl_table ip4_frags_ctl_table[] = { { } }; -static int ip4_frags_ns_ctl_register(struct net *net) +static int __net_init ip4_frags_ns_ctl_register(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; @@ -676,7 +676,7 @@ err_alloc: return -ENOMEM; } -static void ip4_frags_ns_ctl_unregister(struct net *net) +static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net) { struct ctl_table *table; @@ -704,7 +704,7 @@ static inline void ip4_frags_ctl_register(void) } #endif -static int ipv4_frags_init_net(struct net *net) +static int __net_init ipv4_frags_init_net(struct net *net) { /* * Fragment cache limits. We will commit 256K at one time. Should we @@ -726,7 +726,7 @@ static int ipv4_frags_init_net(struct net *net) return ip4_frags_ns_ctl_register(net); } -static void ipv4_frags_exit_net(struct net *net) +static void __net_exit ipv4_frags_exit_net(struct net *net) { ip4_frags_ns_ctl_unregister(net); inet_frags_exit_net(&net->ipv4.frags, &ip4_frags); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index f36ce156cac6..7631b20490f5 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1307,7 +1307,7 @@ static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head) } } -static int ipgre_init_net(struct net *net) +static int __net_init ipgre_init_net(struct net *net) { struct ipgre_net *ign = net_generic(net, ipgre_net_id); int err; @@ -1334,7 +1334,7 @@ err_alloc_dev: return err; } -static void ipgre_exit_net(struct net *net) +static void __net_exit ipgre_exit_net(struct net *net) { struct ipgre_net *ign; LIST_HEAD(list); diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index eda04fed3379..95db732e542b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -130,7 +130,6 @@ struct ipip_net { struct net_device *fb_tunnel_dev; }; -static void ipip_fb_tunnel_init(struct net_device *dev); static void ipip_tunnel_init(struct net_device *dev); static void ipip_tunnel_setup(struct net_device *dev); @@ -730,7 +729,7 @@ static void ipip_tunnel_init(struct net_device *dev) ipip_tunnel_bind_dev(dev); } -static void ipip_fb_tunnel_init(struct net_device *dev) +static void __net_init ipip_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -773,7 +772,7 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head) } } -static int ipip_init_net(struct net *net) +static int __net_init ipip_init_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); int err; @@ -806,7 +805,7 @@ err_alloc_dev: return err; } -static void ipip_exit_net(struct net *net) +static void __net_exit ipip_exit_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); LIST_HEAD(list); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 356f544c4c10..c3588b4fd979 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2430,12 +2430,12 @@ static struct tcp_seq_afinfo tcp4_seq_afinfo = { }, }; -static int tcp4_proc_init_net(struct net *net) +static int __net_init tcp4_proc_init_net(struct net *net) { return tcp_proc_register(net, &tcp4_seq_afinfo); } -static void tcp4_proc_exit_net(struct net *net) +static void __net_exit tcp4_proc_exit_net(struct net *net) { tcp_proc_unregister(net, &tcp4_seq_afinfo); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index f0126fdd7e04..4f7d2122d818 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2027,12 +2027,12 @@ static struct udp_seq_afinfo udp4_seq_afinfo = { }, }; -static int udp4_proc_init_net(struct net *net) +static int __net_init udp4_proc_init_net(struct net *net) { return udp_proc_register(net, &udp4_seq_afinfo); } -static void udp4_proc_exit_net(struct net *net) +static void __net_exit udp4_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udp4_seq_afinfo); } diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 66f79513f4a5..6610bf76369f 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -81,12 +81,12 @@ static struct udp_seq_afinfo udplite4_seq_afinfo = { }, }; -static int udplite4_proc_init_net(struct net *net) +static int __net_init udplite4_proc_init_net(struct net *net) { return udp_proc_register(net, &udplite4_seq_afinfo); } -static void udplite4_proc_exit_net(struct net *net) +static void __net_exit udplite4_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udplite4_seq_afinfo); } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index de7a194a64ab..1593289155ff 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3027,14 +3027,14 @@ static const struct file_operations if6_fops = { .release = seq_release_net, }; -static int if6_proc_net_init(struct net *net) +static int __net_init if6_proc_net_init(struct net *net) { if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) return -ENOMEM; return 0; } -static void if6_proc_net_exit(struct net *net) +static void __net_exit if6_proc_net_exit(struct net *net) { proc_net_remove(net, "if_inet6"); } @@ -4418,7 +4418,7 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) #endif -static int addrconf_init_net(struct net *net) +static int __net_init addrconf_init_net(struct net *net) { int err; struct ipv6_devconf *all, *dflt; @@ -4467,7 +4467,7 @@ err_alloc_all: return err; } -static void addrconf_exit_net(struct net *net) +static void __net_exit addrconf_exit_net(struct net *net) { #ifdef CONFIG_SYSCTL __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 12e69d364dd5..e29160ff4a0f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -999,7 +999,7 @@ err_udplite_mib: return -ENOMEM; } -static void __net_exit ipv6_cleanup_mibs(struct net *net) +static void ipv6_cleanup_mibs(struct net *net) { snmp_mib_free((void **)net->mib.udp_stats_in6); snmp_mib_free((void **)net->mib.udplite_stats_in6); @@ -1042,7 +1042,7 @@ out: #endif } -static void inet6_net_exit(struct net *net) +static void __net_exit inet6_net_exit(struct net *net) { #ifdef CONFIG_PROC_FS udp6_proc_exit(net); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index f1c74c8ef9de..c4f6ca32fa74 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -538,7 +538,7 @@ static const struct file_operations ac6_seq_fops = { .release = seq_release_net, }; -int ac6_proc_init(struct net *net) +int __net_init ac6_proc_init(struct net *net) { if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) return -ENOMEM; diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index b7aa7c64cc4a..551882b9dfd6 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -262,7 +262,7 @@ static struct fib_rules_ops fib6_rules_ops_template = { .fro_net = &init_net, }; -static int fib6_rules_net_init(struct net *net) +static int __net_init fib6_rules_net_init(struct net *net) { struct fib_rules_ops *ops; int err = -ENOMEM; @@ -291,7 +291,7 @@ out_fib6_rules_ops: goto out; } -static void fib6_rules_net_exit(struct net *net) +static void __net_exit fib6_rules_net_exit(struct net *net) { fib_rules_unregister(net->ipv6.fib6_rules_ops); } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4ae661bc3677..217dbc2e28d4 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -951,7 +951,7 @@ ctl_table ipv6_icmp_table_template[] = { { }, }; -struct ctl_table *ipv6_icmp_sysctl_init(struct net *net) +struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net) { struct ctl_table *table; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 0e93ca56eb69..f626ea2b304f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -239,7 +239,7 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id) return NULL; } -static void fib6_tables_init(struct net *net) +static void __net_init fib6_tables_init(struct net *net) { fib6_link_table(net, net->ipv6.fib6_main_tbl); fib6_link_table(net, net->ipv6.fib6_local_tbl); @@ -262,7 +262,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl, return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags); } -static void fib6_tables_init(struct net *net) +static void __net_init fib6_tables_init(struct net *net) { fib6_link_table(net, net->ipv6.fib6_main_tbl); } @@ -1469,7 +1469,7 @@ static void fib6_gc_timer_cb(unsigned long arg) fib6_run_gc(0, (struct net *)arg); } -static int fib6_net_init(struct net *net) +static int __net_init fib6_net_init(struct net *net) { setup_timer(&net->ipv6.ip6_fib_timer, fib6_gc_timer_cb, (unsigned long)net); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 6e7bffa2205e..e41eba8aacf1 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -154,7 +154,7 @@ static void ip6_fl_gc(unsigned long dummy) write_unlock(&ip6_fl_lock); } -static void ip6_fl_purge(struct net *net) +static void __net_exit ip6_fl_purge(struct net *net) { int i; @@ -735,7 +735,7 @@ static const struct file_operations ip6fl_seq_fops = { .release = seq_release_net, }; -static int ip6_flowlabel_proc_init(struct net *net) +static int __net_init ip6_flowlabel_proc_init(struct net *net) { if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops)) @@ -743,7 +743,7 @@ static int ip6_flowlabel_proc_init(struct net *net) return 0; } -static void ip6_flowlabel_proc_fini(struct net *net) +static void __net_exit ip6_flowlabel_proc_fini(struct net *net) { proc_net_remove(net, "ip6_flowlabel"); } @@ -754,11 +754,10 @@ static inline int ip6_flowlabel_proc_init(struct net *net) } static inline void ip6_flowlabel_proc_fini(struct net *net) { - return ; } #endif -static inline void ip6_flowlabel_net_exit(struct net *net) +static void __net_exit ip6_flowlabel_net_exit(struct net *net) { ip6_fl_purge(net); ip6_flowlabel_proc_fini(net); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index d453d07b0dfe..fbd786981aa9 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -74,7 +74,6 @@ MODULE_LICENSE("GPL"); (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ (HASH_SIZE - 1)) -static void ip6_fb_tnl_dev_init(struct net_device *dev); static void ip6_tnl_dev_init(struct net_device *dev); static void ip6_tnl_dev_setup(struct net_device *dev); @@ -1364,7 +1363,7 @@ static void ip6_tnl_dev_init(struct net_device *dev) * Return: 0 **/ -static void ip6_fb_tnl_dev_init(struct net_device *dev) +static void __net_init ip6_fb_tnl_dev_init(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); struct net *net = dev_net(dev); @@ -1388,7 +1387,7 @@ static struct xfrm6_tunnel ip6ip6_handler = { .priority = 1, }; -static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) +static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) { int h; struct ip6_tnl *t; @@ -1407,7 +1406,7 @@ static void ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) unregister_netdevice_many(&list); } -static int ip6_tnl_init_net(struct net *net) +static int __net_init ip6_tnl_init_net(struct net *net) { struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); int err; @@ -1436,7 +1435,7 @@ err_alloc_dev: return err; } -static void ip6_tnl_exit_net(struct net *net) +static void __net_exit ip6_tnl_exit_net(struct net *net) { struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 1f9c44442e65..25f6cca79e6b 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2646,7 +2646,7 @@ static const struct file_operations igmp6_mcf_seq_fops = { .release = seq_release_net, }; -static int igmp6_proc_init(struct net *net) +static int __net_init igmp6_proc_init(struct net *net) { int err; @@ -2666,23 +2666,22 @@ out_proc_net_igmp6: goto out; } -static void igmp6_proc_exit(struct net *net) +static void __net_exit igmp6_proc_exit(struct net *net) { proc_net_remove(net, "mcfilter6"); proc_net_remove(net, "igmp6"); } #else -static int igmp6_proc_init(struct net *net) +static inline int igmp6_proc_init(struct net *net) { return 0; } -static void igmp6_proc_exit(struct net *net) +static inline void igmp6_proc_exit(struct net *net) { - ; } #endif -static int igmp6_net_init(struct net *net) +static int __net_init igmp6_net_init(struct net *net) { int err; @@ -2708,7 +2707,7 @@ out_sock_create: goto out; } -static void igmp6_net_exit(struct net *net) +static void __net_exit igmp6_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.igmp_sk); igmp6_proc_exit(net); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index c45852798092..2dfec6bb8ada 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1772,7 +1772,7 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, void __user *bu #endif -static int ndisc_net_init(struct net *net) +static int __net_init ndisc_net_init(struct net *net) { struct ipv6_pinfo *np; struct sock *sk; @@ -1797,7 +1797,7 @@ static int ndisc_net_init(struct net *net) return 0; } -static void ndisc_net_exit(struct net *net) +static void __net_exit ndisc_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.ndisc_sk); } diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 7b197b7132e0..02f20016b4c9 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -267,7 +267,7 @@ int snmp6_unregister_dev(struct inet6_dev *idev) return 0; } -static int ipv6_proc_init_net(struct net *net) +static int __net_init ipv6_proc_init_net(struct net *net) { if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, &sockstat6_seq_fops)) @@ -288,7 +288,7 @@ proc_dev_snmp6_fail: return -ENOMEM; } -static void ipv6_proc_exit_net(struct net *net) +static void __net_exit ipv6_proc_exit_net(struct net *net) { proc_net_remove(net, "sockstat6"); proc_net_remove(net, "dev_snmp6"); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 926ce8eeffaf..ed31c37c6e39 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -1275,7 +1275,7 @@ static const struct file_operations raw6_seq_fops = { .release = seq_release_net, }; -static int raw6_init_net(struct net *net) +static int __net_init raw6_init_net(struct net *net) { if (!proc_net_fops_create(net, "raw6", S_IRUGO, &raw6_seq_fops)) return -ENOMEM; @@ -1283,7 +1283,7 @@ static int raw6_init_net(struct net *net) return 0; } -static void raw6_exit_net(struct net *net) +static void __net_exit raw6_exit_net(struct net *net) { proc_net_remove(net, "raw6"); } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 2cddea3bd6be..fa38fc7cc6e9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -672,7 +672,7 @@ static struct ctl_table ip6_frags_ctl_table[] = { { } }; -static int ip6_frags_ns_sysctl_register(struct net *net) +static int __net_init ip6_frags_ns_sysctl_register(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; @@ -702,7 +702,7 @@ err_alloc: return -ENOMEM; } -static void ip6_frags_ns_sysctl_unregister(struct net *net) +static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net) { struct ctl_table *table; @@ -745,7 +745,7 @@ static inline void ip6_frags_sysctl_unregister(void) } #endif -static int ipv6_frags_init_net(struct net *net) +static int __net_init ipv6_frags_init_net(struct net *net) { net->ipv6.frags.high_thresh = 256 * 1024; net->ipv6.frags.low_thresh = 192 * 1024; @@ -756,7 +756,7 @@ static int ipv6_frags_init_net(struct net *net) return ip6_frags_ns_sysctl_register(net); } -static void ipv6_frags_exit_net(struct net *net) +static void __net_exit ipv6_frags_exit_net(struct net *net) { ip6_frags_ns_sysctl_unregister(net); inet_frags_exit_net(&net->ipv6.frags, &ip6_frags); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2bd74c5f8d9..8500156f2637 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2612,7 +2612,7 @@ ctl_table ipv6_route_table_template[] = { { } }; -struct ctl_table *ipv6_route_sysctl_init(struct net *net) +struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) { struct ctl_table *table; @@ -2637,7 +2637,7 @@ struct ctl_table *ipv6_route_sysctl_init(struct net *net) } #endif -static int ip6_route_net_init(struct net *net) +static int __net_init ip6_route_net_init(struct net *net) { int ret = -ENOMEM; @@ -2702,7 +2702,7 @@ out_ip6_dst_ops: goto out; } -static void ip6_route_net_exit(struct net *net) +static void __net_exit ip6_route_net_exit(struct net *net) { #ifdef CONFIG_PROC_FS proc_net_remove(net, "ipv6_route"); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 976e68244b99..10207cc8cc0e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -62,7 +62,6 @@ #define HASH_SIZE 16 #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) -static void ipip6_fb_tunnel_init(struct net_device *dev); static void ipip6_tunnel_init(struct net_device *dev); static void ipip6_tunnel_setup(struct net_device *dev); @@ -1120,7 +1119,7 @@ static void ipip6_tunnel_init(struct net_device *dev) ipip6_tunnel_bind_dev(dev); } -static void ipip6_fb_tunnel_init(struct net_device *dev) +static void __net_init ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -1145,7 +1144,7 @@ static struct xfrm_tunnel sit_handler = { .priority = 1, }; -static void sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) +static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) { int prio; @@ -1162,7 +1161,7 @@ static void sit_destroy_tunnels(struct sit_net *sitn, struct list_head *head) } } -static int sit_init_net(struct net *net) +static int __net_init sit_init_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); int err; @@ -1195,7 +1194,7 @@ err_alloc_dev: return err; } -static void sit_exit_net(struct net *net) +static void __net_exit sit_exit_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); LIST_HEAD(list); diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index c690736885b4..f841d93bf987 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -55,7 +55,7 @@ struct ctl_path net_ipv6_ctl_path[] = { }; EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); -static int ipv6_sysctl_net_init(struct net *net) +static int __net_init ipv6_sysctl_net_init(struct net *net) { struct ctl_table *ipv6_table; struct ctl_table *ipv6_route_table; @@ -98,7 +98,7 @@ out_ipv6_table: goto out; } -static void ipv6_sysctl_net_exit(struct net *net) +static void __net_exit ipv6_sysctl_net_exit(struct net *net) { struct ctl_table *ipv6_table; struct ctl_table *ipv6_route_table; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 82f2dea0e39e..6963a6b6763e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2113,7 +2113,7 @@ static struct tcp_seq_afinfo tcp6_seq_afinfo = { }, }; -int tcp6_proc_init(struct net *net) +int __net_init tcp6_proc_init(struct net *net) { return tcp_proc_register(net, &tcp6_seq_afinfo); } @@ -2182,18 +2182,18 @@ static struct inet_protosw tcpv6_protosw = { INET_PROTOSW_ICSK, }; -static int tcpv6_net_init(struct net *net) +static int __net_init tcpv6_net_init(struct net *net) { return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, SOCK_RAW, IPPROTO_TCP, net); } -static void tcpv6_net_exit(struct net *net) +static void __net_exit tcpv6_net_exit(struct net *net) { inet_ctl_sock_destroy(net->ipv6.tcp_sk); } -static void tcpv6_net_exit_batch(struct list_head *net_exit_list) +static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list) { inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6); } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69ebdbe78c47..34efb3589ffa 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1396,7 +1396,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { }, }; -int udp6_proc_init(struct net *net) +int __net_init udp6_proc_init(struct net *net) { return udp_proc_register(net, &udp6_seq_afinfo); } diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 6ea6938919e6..5f48fadc27f7 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -104,12 +104,12 @@ static struct udp_seq_afinfo udplite6_seq_afinfo = { }, }; -static int udplite6_proc_init_net(struct net *net) +static int __net_init udplite6_proc_init_net(struct net *net) { return udp_proc_register(net, &udplite6_seq_afinfo); } -static void udplite6_proc_exit_net(struct net *net) +static void __net_exit udplite6_proc_exit_net(struct net *net) { udp_proc_unregister(net, &udplite6_seq_afinfo); } diff --git a/net/key/af_key.c b/net/key/af_key.c index 76fa6fef6473..4744b1f6372f 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3738,17 +3738,17 @@ static int __net_init pfkey_init_proc(struct net *net) return 0; } -static void pfkey_exit_proc(struct net *net) +static void __net_exit pfkey_exit_proc(struct net *net) { proc_net_remove(net, "pfkey"); } #else -static int __net_init pfkey_init_proc(struct net *net) +static inline int pfkey_init_proc(struct net *net) { return 0; } -static void pfkey_exit_proc(struct net *net) +static inline void pfkey_exit_proc(struct net *net) { } #endif diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e0516a22be2e..a97acfe7e770 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2448,7 +2448,7 @@ static const struct file_operations packet_seq_fops = { #endif -static int packet_net_init(struct net *net) +static int __net_init packet_net_init(struct net *net) { rwlock_init(&net->packet.sklist_lock); INIT_HLIST_HEAD(&net->packet.sklist); @@ -2459,7 +2459,7 @@ static int packet_net_init(struct net *net) return 0; } -static void packet_net_exit(struct net *net) +static void __net_exit packet_net_exit(struct net *net) { proc_net_remove(net, "packet"); } diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index bc4a33bf2d3d..c597cc53a6fb 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -311,7 +311,7 @@ static struct notifier_block phonet_device_notifier = { }; /* Per-namespace Phonet devices handling */ -static int phonet_init_net(struct net *net) +static int __net_init phonet_init_net(struct net *net) { struct phonet_net *pnn = net_generic(net, phonet_net_id); @@ -324,7 +324,7 @@ static int phonet_init_net(struct net *net) return 0; } -static void phonet_exit_net(struct net *net) +static void __net_exit phonet_exit_net(struct net *net) { struct phonet_net *pnn = net_generic(net, phonet_net_id); struct net_device *dev; diff --git a/net/sysctl_net.c b/net/sysctl_net.c index 0b15d7250c40..53196009160a 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -71,7 +71,7 @@ static struct ctl_table_root net_sysctl_ro_root = { .permissions = net_ctl_ro_header_perms, }; -static int sysctl_net_init(struct net *net) +static int __net_init sysctl_net_init(struct net *net) { setup_sysctl_set(&net->sysctls, &net_sysctl_ro_root.default_set, @@ -79,7 +79,7 @@ static int sysctl_net_init(struct net *net) return 0; } -static void sysctl_net_exit(struct net *net) +static void __net_exit sysctl_net_exit(struct net *net) { WARN_ON(!list_empty(&net->sysctls.list)); return; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f25511903115..9bc9b92bc099 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2224,7 +2224,7 @@ static const struct net_proto_family unix_family_ops = { }; -static int unix_net_init(struct net *net) +static int __net_init unix_net_init(struct net *net) { int error = -ENOMEM; @@ -2243,7 +2243,7 @@ out: return error; } -static void unix_net_exit(struct net *net) +static void __net_exit unix_net_exit(struct net *net) { unix_sysctl_unregister(net); proc_net_remove(net, "unix"); diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c index 708f5df6b7f0..d095c7be10d0 100644 --- a/net/unix/sysctl_net_unix.c +++ b/net/unix/sysctl_net_unix.c @@ -31,7 +31,7 @@ static struct ctl_path unix_path[] = { { }, }; -int unix_sysctl_register(struct net *net) +int __net_init unix_sysctl_register(struct net *net) { struct ctl_table *table; diff --git a/net/wireless/wext-proc.c b/net/wireless/wext-proc.c index 273a7f77c834..8bafa31fa9f8 100644 --- a/net/wireless/wext-proc.c +++ b/net/wireless/wext-proc.c @@ -140,7 +140,7 @@ static const struct file_operations wireless_seq_fops = { .release = seq_release_net, }; -int wext_proc_init(struct net *net) +int __net_init wext_proc_init(struct net *net) { /* Create /proc/net/wireless entry */ if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops)) @@ -149,7 +149,7 @@ int wext_proc_init(struct net *net) return 0; } -void wext_proc_exit(struct net *net) +void __net_exit wext_proc_exit(struct net *net) { proc_net_remove(net, "wireless"); } diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c index 2e221f2cad7e..2c4d6cdcba49 100644 --- a/net/xfrm/xfrm_sysctl.c +++ b/net/xfrm/xfrm_sysctl.c @@ -2,7 +2,7 @@ #include #include -static void __xfrm_sysctl_init(struct net *net) +static void __net_init __xfrm_sysctl_init(struct net *net) { net->xfrm.sysctl_aevent_etime = XFRM_AE_ETIME; net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE; @@ -64,7 +64,7 @@ out_kmemdup: return -ENOMEM; } -void xfrm_sysctl_fini(struct net *net) +void __net_exit xfrm_sysctl_fini(struct net *net) { struct ctl_table *table; -- cgit v1.2.3 From a47430583dab67b23161b0e75226781deed50138 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 17 Jan 2010 07:30:43 +0000 Subject: bnx2: Refine statistics code. Refine the statistics macros by passing in just the name of the counter field. This makes it a lot easier and cleaner to add counters saved before the last reset in the next patch. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 62 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b1c20e5f7de8..47fb5086cf56 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6542,92 +6542,94 @@ bnx2_close(struct net_device *dev) return 0; } -#define GET_NET_STATS64(ctr) \ +#define GET_64BIT_NET_STATS64(ctr) \ (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ (unsigned long) (ctr##_lo) -#define GET_NET_STATS32(ctr) \ +#define GET_64BIT_NET_STATS32(ctr) \ (ctr##_lo) #if (BITS_PER_LONG == 64) -#define GET_NET_STATS GET_NET_STATS64 +#define GET_64BIT_NET_STATS(ctr) \ + GET_64BIT_NET_STATS64(bp->stats_blk->ctr) #else -#define GET_NET_STATS GET_NET_STATS32 +#define GET_64BIT_NET_STATS(ctr) \ + GET_64BIT_NET_STATS32(bp->stats_blk->ctr) #endif +#define GET_32BIT_NET_STATS(ctr) \ + (unsigned long) (bp->stats_blk->ctr) + static struct net_device_stats * bnx2_get_stats(struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); - struct statistics_block *stats_blk = bp->stats_blk; struct net_device_stats *net_stats = &dev->stats; if (bp->stats_blk == NULL) { return net_stats; } net_stats->rx_packets = - GET_NET_STATS(stats_blk->stat_IfHCInUcastPkts) + - GET_NET_STATS(stats_blk->stat_IfHCInMulticastPkts) + - GET_NET_STATS(stats_blk->stat_IfHCInBroadcastPkts); + GET_64BIT_NET_STATS(stat_IfHCInUcastPkts) + + GET_64BIT_NET_STATS(stat_IfHCInMulticastPkts) + + GET_64BIT_NET_STATS(stat_IfHCInBroadcastPkts); net_stats->tx_packets = - GET_NET_STATS(stats_blk->stat_IfHCOutUcastPkts) + - GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts) + - GET_NET_STATS(stats_blk->stat_IfHCOutBroadcastPkts); + GET_64BIT_NET_STATS(stat_IfHCOutUcastPkts) + + GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts) + + GET_64BIT_NET_STATS(stat_IfHCOutBroadcastPkts); net_stats->rx_bytes = - GET_NET_STATS(stats_blk->stat_IfHCInOctets); + GET_64BIT_NET_STATS(stat_IfHCInOctets); net_stats->tx_bytes = - GET_NET_STATS(stats_blk->stat_IfHCOutOctets); + GET_64BIT_NET_STATS(stat_IfHCOutOctets); net_stats->multicast = - GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts); + GET_64BIT_NET_STATS(stat_IfHCOutMulticastPkts); net_stats->collisions = - (unsigned long) stats_blk->stat_EtherStatsCollisions; + GET_32BIT_NET_STATS(stat_EtherStatsCollisions); net_stats->rx_length_errors = - (unsigned long) (stats_blk->stat_EtherStatsUndersizePkts + - stats_blk->stat_EtherStatsOverrsizePkts); + GET_32BIT_NET_STATS(stat_EtherStatsUndersizePkts) + + GET_32BIT_NET_STATS(stat_EtherStatsOverrsizePkts); net_stats->rx_over_errors = - (unsigned long) (stats_blk->stat_IfInFTQDiscards + - stats_blk->stat_IfInMBUFDiscards); + GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + + GET_32BIT_NET_STATS(stat_IfInMBUFDiscards); net_stats->rx_frame_errors = - (unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors; + GET_32BIT_NET_STATS(stat_Dot3StatsAlignmentErrors); net_stats->rx_crc_errors = - (unsigned long) stats_blk->stat_Dot3StatsFCSErrors; + GET_32BIT_NET_STATS(stat_Dot3StatsFCSErrors); net_stats->rx_errors = net_stats->rx_length_errors + net_stats->rx_over_errors + net_stats->rx_frame_errors + net_stats->rx_crc_errors; net_stats->tx_aborted_errors = - (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + - stats_blk->stat_Dot3StatsLateCollisions); + GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) + + GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions); if ((CHIP_NUM(bp) == CHIP_NUM_5706) || (CHIP_ID(bp) == CHIP_ID_5708_A0)) net_stats->tx_carrier_errors = 0; else { net_stats->tx_carrier_errors = - (unsigned long) - stats_blk->stat_Dot3StatsCarrierSenseErrors; + GET_32BIT_NET_STATS(stat_Dot3StatsCarrierSenseErrors); } net_stats->tx_errors = - (unsigned long) - stats_blk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors - + + GET_32BIT_NET_STATS(stat_emac_tx_stat_dot3statsinternalmactransmiterrors) + net_stats->tx_aborted_errors + net_stats->tx_carrier_errors; net_stats->rx_missed_errors = - (unsigned long) (stats_blk->stat_IfInFTQDiscards + - stats_blk->stat_IfInMBUFDiscards + stats_blk->stat_FwRxDrop); + GET_32BIT_NET_STATS(stat_IfInFTQDiscards) + + GET_32BIT_NET_STATS(stat_IfInMBUFDiscards) + + GET_32BIT_NET_STATS(stat_FwRxDrop); return net_stats; } -- cgit v1.2.3 From 354fcd7774a00809ebefdba75e747364cb22a940 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 17 Jan 2010 07:30:44 +0000 Subject: bnx2: Save statistics during reset. MTU changes, ring size changes, etc cause the chip to be reset and the statisctics flushed. To keep track of the accumulated statistics, we add code to save the whole statistics block before reset. We also modify the macros and statistics functions to return the sum of the saved and current counters. Based on original patch by Breno Leitao Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++------- drivers/net/bnx2.h | 1 + 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 47fb5086cf56..d83512d3e02f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6231,6 +6231,8 @@ bnx2_open(struct net_device *dev) atomic_set(&bp->intr_sem, 0); + memset(bp->temp_stats_blk, 0, sizeof(struct statistics_block)); + bnx2_enable_int(bp); if (bp->flags & BNX2_FLAG_USING_MSI) { @@ -6542,6 +6544,30 @@ bnx2_close(struct net_device *dev) return 0; } +static void +bnx2_save_stats(struct bnx2 *bp) +{ + u32 *hw_stats = (u32 *) bp->stats_blk; + u32 *temp_stats = (u32 *) bp->temp_stats_blk; + int i; + + /* The 1st 10 counters are 64-bit counters */ + for (i = 0; i < 20; i += 2) { + u32 hi; + u64 lo; + + hi = *(temp_stats + i) + *(hw_stats + i); + lo = *(temp_stats + i + 1) + *(hw_stats + i + 1); + if (lo > 0xffffffff) + hi++; + *(temp_stats + i) = hi; + *(temp_stats + i + 1) = lo & 0xffffffff; + } + + for ( ; i < sizeof(struct statistics_block) / 4; i++) + *(temp_stats + i) = *(temp_stats + i) + *(hw_stats + i); +} + #define GET_64BIT_NET_STATS64(ctr) \ (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \ (unsigned long) (ctr##_lo) @@ -6551,14 +6577,17 @@ bnx2_close(struct net_device *dev) #if (BITS_PER_LONG == 64) #define GET_64BIT_NET_STATS(ctr) \ - GET_64BIT_NET_STATS64(bp->stats_blk->ctr) + GET_64BIT_NET_STATS64(bp->stats_blk->ctr) + \ + GET_64BIT_NET_STATS64(bp->temp_stats_blk->ctr) #else #define GET_64BIT_NET_STATS(ctr) \ - GET_64BIT_NET_STATS32(bp->stats_blk->ctr) + GET_64BIT_NET_STATS32(bp->stats_blk->ctr) + \ + GET_64BIT_NET_STATS32(bp->temp_stats_blk->ctr) #endif #define GET_32BIT_NET_STATS(ctr) \ - (unsigned long) (bp->stats_blk->ctr) + (unsigned long) (bp->stats_blk->ctr + \ + bp->temp_stats_blk->ctr) static struct net_device_stats * bnx2_get_stats(struct net_device *dev) @@ -7089,6 +7118,9 @@ static int bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) { if (netif_running(bp->dev)) { + /* Reset will erase chipset stats; save them */ + bnx2_save_stats(bp); + bnx2_netif_stop(bp); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); bnx2_free_skbs(bp); @@ -7433,6 +7465,7 @@ bnx2_get_ethtool_stats(struct net_device *dev, struct bnx2 *bp = netdev_priv(dev); int i; u32 *hw_stats = (u32 *) bp->stats_blk; + u32 *temp_stats = (u32 *) bp->temp_stats_blk; u8 *stats_len_arr = NULL; if (hw_stats == NULL) { @@ -7449,21 +7482,26 @@ bnx2_get_ethtool_stats(struct net_device *dev, stats_len_arr = bnx2_5708_stats_len_arr; for (i = 0; i < BNX2_NUM_STATS; i++) { + unsigned long offset; + if (stats_len_arr[i] == 0) { /* skip this counter */ buf[i] = 0; continue; } + + offset = bnx2_stats_offset_arr[i]; if (stats_len_arr[i] == 4) { /* 4-byte counter */ - buf[i] = (u64) - *(hw_stats + bnx2_stats_offset_arr[i]); + buf[i] = (u64) *(hw_stats + offset) + + *(temp_stats + offset); continue; } /* 8-byte counter */ - buf[i] = (((u64) *(hw_stats + - bnx2_stats_offset_arr[i])) << 32) + - *(hw_stats + bnx2_stats_offset_arr[i] + 1); + buf[i] = (((u64) *(hw_stats + offset)) << 32) + + *(hw_stats + offset + 1) + + (((u64) *(temp_stats + offset)) << 32) + + *(temp_stats + offset + 1); } } @@ -7831,6 +7869,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags = 0; bp->phy_flags = 0; + bp->temp_stats_blk = + kzalloc(sizeof(struct statistics_block), GFP_KERNEL); + + if (bp->temp_stats_blk == NULL) { + rc = -ENOMEM; + goto err_out; + } + /* enable device (incl. PCI PM wakeup), and bus-mastering */ rc = pci_enable_device(pdev); if (rc) { @@ -8352,6 +8398,8 @@ bnx2_remove_one(struct pci_dev *pdev) if (bp->regview) iounmap(bp->regview); + kfree(bp->temp_stats_blk); + free_netdev(dev); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 939dc44d50a0..b860fbbff355 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6851,6 +6851,7 @@ struct bnx2 { dma_addr_t status_blk_mapping; struct statistics_block *stats_blk; + struct statistics_block *temp_stats_blk; dma_addr_t stats_blk_mapping; int ctx_pages; -- cgit v1.2.3 From 83fc81024bd8572f31db784f8c0079e999a4fa44 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:07:50 +0100 Subject: netfilter: xt_connlimit: netns support Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/xt_connlimit.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 8103bef78e44..0d9d18ea2b09 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -90,7 +90,8 @@ same_source_net(const union nf_inet_addr *addr, } } -static int count_them(struct xt_connlimit_data *data, +static int count_them(struct net *net, + struct xt_connlimit_data *data, const struct nf_conntrack_tuple *tuple, const union nf_inet_addr *addr, const union nf_inet_addr *mask, @@ -113,7 +114,7 @@ static int count_them(struct xt_connlimit_data *data, /* check the saved connections */ list_for_each_entry_safe(conn, tmp, hash, list) { - found = nf_conntrack_find_get(&init_net, &conn->tuple); + found = nf_conntrack_find_get(net, &conn->tuple); found_ct = NULL; if (found != NULL) @@ -171,6 +172,7 @@ static int count_them(struct xt_connlimit_data *data, static bool connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) { + struct net *net = dev_net(par->in ? par->in : par->out); const struct xt_connlimit_info *info = par->matchinfo; union nf_inet_addr addr; struct nf_conntrack_tuple tuple; @@ -195,7 +197,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) } spin_lock_bh(&info->data->lock); - connections = count_them(info->data, tuple_ptr, &addr, + connections = count_them(net, info->data, tuple_ptr, &addr, &info->mask, par->family); spin_unlock_bh(&info->data->lock); -- cgit v1.2.3 From e9d3897cc2205eec8b7afcc022e4730914b4f48c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:08:37 +0100 Subject: netfilter: netns: #ifdef ->iptable_security, ->ip6table_security 'security' tables depend on SECURITY, so ifdef them. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/net/netns/ipv4.h | 2 ++ include/net/netns/ipv6.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2eb3814d6258..8098f6b8319d 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -37,7 +37,9 @@ struct netns_ipv4 { struct xt_table *iptable_mangle; struct xt_table *iptable_raw; struct xt_table *arptable_filter; +#ifdef CONFIG_SECURITY struct xt_table *iptable_security; +#endif struct xt_table *nat_table; struct hlist_head *nat_bysource; int nat_vmalloced; diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index dfeb2d7c425b..1f11ebc22151 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -36,7 +36,9 @@ struct netns_ipv6 { struct xt_table *ip6table_filter; struct xt_table *ip6table_mangle; struct xt_table *ip6table_raw; +#ifdef CONFIG_SECURITY struct xt_table *ip6table_security; +#endif #endif struct rt6_info *ip6_null_entry; struct rt6_statistics *rt6_stats; -- cgit v1.2.3 From a1004d8e3d463012f231bab104325ecb15637f78 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:14:50 +0100 Subject: netfilter: xt_hashlimit: simplify seqfile code Simply pass hashtable to seqfile iterators, proc entry itself is not needed. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/xt_hashlimit.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 5bdc1fbf3ad7..944fd11c8989 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -841,8 +841,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = { static void *dl_seq_start(struct seq_file *s, loff_t *pos) __acquires(htable->lock) { - struct proc_dir_entry *pde = s->private; - struct xt_hashlimit_htable *htable = pde->data; + struct xt_hashlimit_htable *htable = s->private; unsigned int *bucket; spin_lock_bh(&htable->lock); @@ -859,8 +858,7 @@ static void *dl_seq_start(struct seq_file *s, loff_t *pos) static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) { - struct proc_dir_entry *pde = s->private; - struct xt_hashlimit_htable *htable = pde->data; + struct xt_hashlimit_htable *htable = s->private; unsigned int *bucket = (unsigned int *)v; *pos = ++(*bucket); @@ -874,8 +872,7 @@ static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) static void dl_seq_stop(struct seq_file *s, void *v) __releases(htable->lock) { - struct proc_dir_entry *pde = s->private; - struct xt_hashlimit_htable *htable = pde->data; + struct xt_hashlimit_htable *htable = s->private; unsigned int *bucket = (unsigned int *)v; kfree(bucket); @@ -917,8 +914,7 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family, static int dl_seq_show(struct seq_file *s, void *v) { - struct proc_dir_entry *pde = s->private; - struct xt_hashlimit_htable *htable = pde->data; + struct xt_hashlimit_htable *htable = s->private; unsigned int *bucket = (unsigned int *)v; struct dsthash_ent *ent; struct hlist_node *pos; @@ -944,7 +940,7 @@ static int dl_proc_open(struct inode *inode, struct file *file) if (!ret) { struct seq_file *sf = file->private_data; - sf->private = PDE(inode); + sf->private = PDE(inode)->data; } return ret; } -- cgit v1.2.3 From a83d8e8d099fc373a5ca7112ad08c553bb2c180f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:21:13 +0100 Subject: netfilter: xtables: add struct xt_mtchk_param::net Some complex match modules (like xt_hashlimit/xt_recent) want netns information at constructor and destructor time. We propably can play games at match destruction time, because netns can be passed in object, but I think it's cleaner to explicitly pass netns. Add ->net, make sure it's set from ebtables/iptables/ip6tables code. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 1 + net/bridge/netfilter/ebtables.c | 14 +++++++++----- net/ipv4/netfilter/ip_tables.c | 24 ++++++++++++++---------- net/ipv6/netfilter/ip6_tables.c | 14 ++++++++------ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 378f27ae7772..88261b9829a7 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -205,6 +205,7 @@ struct xt_match_param { * @hook_mask: via which hooks the new rule is reachable */ struct xt_mtchk_param { + struct net *net; const char *table; const void *entryinfo; const struct xt_match *match; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index bd1c65425d4f..c77bab986696 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -619,7 +619,9 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) } static inline int -ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, +ebt_check_entry(struct ebt_entry *e, + struct net *net, + struct ebt_table_info *newinfo, const char *name, unsigned int *cnt, struct ebt_cl_stack *cl_s, unsigned int udc_cnt) { @@ -671,6 +673,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, } i = 0; + mtpar.net = net; mtpar.table = tgpar.table = name; mtpar.entryinfo = tgpar.entryinfo = e; mtpar.hook_mask = tgpar.hook_mask = hookmask; @@ -808,7 +811,8 @@ letscontinue: } /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ -static int translate_table(char *name, struct ebt_table_info *newinfo) +static int translate_table(struct net *net, char *name, + struct ebt_table_info *newinfo) { unsigned int i, j, k, udc_cnt; int ret; @@ -917,7 +921,7 @@ static int translate_table(char *name, struct ebt_table_info *newinfo) /* used to know what we need to clean up if something goes wrong */ i = 0; ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt); + ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt); if (ret != 0) { EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, ebt_cleanup_entry, &i); @@ -1017,7 +1021,7 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) if (ret != 0) goto free_counterstmp; - ret = translate_table(tmp.name, newinfo); + ret = translate_table(net, tmp.name, newinfo); if (ret != 0) goto free_counterstmp; @@ -1154,7 +1158,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table) newinfo->hook_entry[i] = p + ((char *)repl->hook_entry[i] - repl->entries); } - ret = translate_table(repl->name, newinfo); + ret = translate_table(net, repl->name, newinfo); if (ret != 0) { BUGPRINT("Translate_table failed\n"); goto free_chainstack; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 572330a552ef..a069d72d9482 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -661,8 +661,8 @@ static int check_target(struct ipt_entry *e, const char *name) } static int -find_check_entry(struct ipt_entry *e, const char *name, unsigned int size, - unsigned int *i) +find_check_entry(struct ipt_entry *e, struct net *net, const char *name, + unsigned int size, unsigned int *i) { struct ipt_entry_target *t; struct xt_target *target; @@ -675,6 +675,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size, return ret; j = 0; + mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ip; mtpar.hook_mask = e->comefrom; @@ -798,7 +799,8 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) /* Checks and translates the user-supplied table segment (held in newinfo) */ static int -translate_table(const char *name, +translate_table(struct net *net, + const char *name, unsigned int valid_hooks, struct xt_table_info *newinfo, void *entry0, @@ -860,7 +862,7 @@ translate_table(const char *name, /* Finally, each sanity check must pass */ i = 0; ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, - find_check_entry, name, size, &i); + find_check_entry, net, name, size, &i); if (ret != 0) { IPT_ENTRY_ITERATE(entry0, newinfo->size, @@ -1303,7 +1305,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_table(tmp.name, tmp.valid_hooks, + ret = translate_table(net, tmp.name, tmp.valid_hooks, newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, tmp.hook_entry, tmp.underflow); if (ret != 0) @@ -1655,7 +1657,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, } static int -compat_check_entry(struct ipt_entry *e, const char *name, +compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, unsigned int *i) { struct xt_mtchk_param mtpar; @@ -1663,6 +1665,7 @@ compat_check_entry(struct ipt_entry *e, const char *name, int ret; j = 0; + mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ip; mtpar.hook_mask = e->comefrom; @@ -1684,7 +1687,8 @@ compat_check_entry(struct ipt_entry *e, const char *name, } static int -translate_compat_table(const char *name, +translate_compat_table(struct net *net, + const char *name, unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, @@ -1773,7 +1777,7 @@ translate_compat_table(const char *name, i = 0; ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, - name, &i); + net, name, &i); if (ret) { j -= i; COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, @@ -1833,7 +1837,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(tmp.name, tmp.valid_hooks, + ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, &newinfo, &loc_cpu_entry, tmp.size, tmp.num_entries, tmp.hook_entry, tmp.underflow); @@ -2086,7 +2090,7 @@ struct xt_table *ipt_register_table(struct net *net, loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(table->name, table->valid_hooks, + ret = translate_table(net, table->name, table->valid_hooks, newinfo, loc_cpu_entry, repl->size, repl->num_entries, repl->hook_entry, diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 480d7f8c9802..a825940a92ef 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -693,8 +693,8 @@ static int check_target(struct ip6t_entry *e, const char *name) } static int -find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, - unsigned int *i) +find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, + unsigned int size, unsigned int *i) { struct ip6t_entry_target *t; struct xt_target *target; @@ -707,6 +707,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, return ret; j = 0; + mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ipv6; mtpar.hook_mask = e->comefrom; @@ -830,7 +831,8 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) /* Checks and translates the user-supplied table segment (held in newinfo) */ static int -translate_table(const char *name, +translate_table(struct net *net, + const char *name, unsigned int valid_hooks, struct xt_table_info *newinfo, void *entry0, @@ -892,7 +894,7 @@ translate_table(const char *name, /* Finally, each sanity check must pass */ i = 0; ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, - find_check_entry, name, size, &i); + find_check_entry, net, name, size, &i); if (ret != 0) { IP6T_ENTRY_ITERATE(entry0, newinfo->size, @@ -1336,7 +1338,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_table(tmp.name, tmp.valid_hooks, + ret = translate_table(net, tmp.name, tmp.valid_hooks, newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, tmp.hook_entry, tmp.underflow); if (ret != 0) @@ -2121,7 +2123,7 @@ struct xt_table *ip6t_register_table(struct net *net, loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(table->name, table->valid_hooks, + ret = translate_table(net, table->name, table->valid_hooks, newinfo, loc_cpu_entry, repl->size, repl->num_entries, repl->hook_entry, -- cgit v1.2.3 From f54e9367f8499a9bf6b2afbc0dce63e1d53c525a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:25:47 +0100 Subject: netfilter: xtables: add struct xt_mtdtor_param::net Add ->net to match destructor list like ->net in constructor list. Make sure it's set in ebtables/iptables/ip6tables, this requires to propagate netns up to *_unregister_table(). Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 1 + include/linux/netfilter_bridge/ebtables.h | 2 +- include/linux/netfilter_ipv4/ip_tables.h | 2 +- include/linux/netfilter_ipv6/ip6_tables.h | 2 +- net/bridge/netfilter/ebtable_broute.c | 2 +- net/bridge/netfilter/ebtable_filter.c | 2 +- net/bridge/netfilter/ebtable_nat.c | 2 +- net/bridge/netfilter/ebtables.c | 19 ++++++++-------- net/ipv4/netfilter/ip_tables.c | 25 +++++++++++---------- net/ipv4/netfilter/iptable_filter.c | 2 +- net/ipv4/netfilter/iptable_mangle.c | 2 +- net/ipv4/netfilter/iptable_raw.c | 2 +- net/ipv4/netfilter/iptable_security.c | 2 +- net/ipv4/netfilter/nf_nat_rule.c | 2 +- net/ipv6/netfilter/ip6_tables.c | 37 +++++++++++++++++-------------- net/ipv6/netfilter/ip6table_filter.c | 2 +- net/ipv6/netfilter/ip6table_mangle.c | 2 +- net/ipv6/netfilter/ip6table_raw.c | 2 +- net/ipv6/netfilter/ip6table_security.c | 2 +- 19 files changed, 59 insertions(+), 53 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 88261b9829a7..3caf5e151102 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -216,6 +216,7 @@ struct xt_mtchk_param { /* Match destructor parameters */ struct xt_mtdtor_param { + struct net *net; const struct xt_match *match; void *matchinfo; u_int8_t family; diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 3cc40c131cc3..1c6f0c5f530e 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -289,7 +289,7 @@ struct ebt_table { ~(__alignof__(struct ebt_replace)-1)) extern struct ebt_table *ebt_register_table(struct net *net, const struct ebt_table *table); -extern void ebt_unregister_table(struct ebt_table *table); +extern void ebt_unregister_table(struct net *net, struct ebt_table *table); extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, struct ebt_table *table); diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 27b3f5807305..8d1f273d350b 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -242,7 +242,7 @@ extern void ipt_init(void) __init; extern struct xt_table *ipt_register_table(struct net *net, const struct xt_table *table, const struct ipt_replace *repl); -extern void ipt_unregister_table(struct xt_table *table); +extern void ipt_unregister_table(struct net *net, struct xt_table *table); /* Standard entry. */ struct ipt_standard { diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index b31050d20ae4..d2952d2fa658 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -300,7 +300,7 @@ extern void ip6t_init(void) __init; extern struct xt_table *ip6t_register_table(struct net *net, const struct xt_table *table, const struct ip6t_replace *repl); -extern void ip6t_unregister_table(struct xt_table *table); +extern void ip6t_unregister_table(struct net *net, struct xt_table *table); extern unsigned int ip6t_do_table(struct sk_buff *skb, unsigned int hook, const struct net_device *in, diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index d32ab13e728c..ae3f106c3908 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -71,7 +71,7 @@ static int __net_init broute_net_init(struct net *net) static void __net_exit broute_net_exit(struct net *net) { - ebt_unregister_table(net->xt.broute_table); + ebt_unregister_table(net, net->xt.broute_table); } static struct pernet_operations broute_net_ops = { diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 60b1a6ca7185..42e6bd094574 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -107,7 +107,7 @@ static int __net_init frame_filter_net_init(struct net *net) static void __net_exit frame_filter_net_exit(struct net *net) { - ebt_unregister_table(net->xt.frame_filter); + ebt_unregister_table(net, net->xt.frame_filter); } static struct pernet_operations frame_filter_net_ops = { diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 4a98804203b0..6dc2f878ae05 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -107,7 +107,7 @@ static int __net_init frame_nat_net_init(struct net *net) static void __net_exit frame_nat_net_exit(struct net *net) { - ebt_unregister_table(net->xt.frame_nat); + ebt_unregister_table(net, net->xt.frame_nat); } static struct pernet_operations frame_nat_net_ops = { diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index c77bab986696..1aa0e4c1f52d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -561,13 +561,14 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo, } static inline int -ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i) +ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i) { struct xt_mtdtor_param par; if (i && (*i)-- == 0) return 1; + par.net = net; par.match = m->u.match; par.matchinfo = m->data; par.family = NFPROTO_BRIDGE; @@ -595,7 +596,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) } static inline int -ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) +ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt) { struct xt_tgdtor_param par; struct ebt_entry_target *t; @@ -606,7 +607,7 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) if (cnt && (*cnt)-- == 0) return 1; EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL); - EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL); + EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL); t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); par.target = t->u.target; @@ -731,7 +732,7 @@ ebt_check_entry(struct ebt_entry *e, cleanup_watchers: EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j); cleanup_matches: - EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i); + EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i); return ret; } @@ -924,7 +925,7 @@ static int translate_table(struct net *net, char *name, ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt); if (ret != 0) { EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_cleanup_entry, &i); + ebt_cleanup_entry, net, &i); } vfree(cl_s); return ret; @@ -1074,7 +1075,7 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) /* decrease module count and free resources */ EBT_ENTRY_ITERATE(table->entries, table->entries_size, - ebt_cleanup_entry, NULL); + ebt_cleanup_entry, net, NULL); vfree(table->entries); if (table->chainstack) { @@ -1091,7 +1092,7 @@ free_unlock: mutex_unlock(&ebt_mutex); free_iterate: EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, - ebt_cleanup_entry, NULL); + ebt_cleanup_entry, net, NULL); free_counterstmp: vfree(counterstmp); /* can be initialized in translate_table() */ @@ -1208,7 +1209,7 @@ out: return ERR_PTR(ret); } -void ebt_unregister_table(struct ebt_table *table) +void ebt_unregister_table(struct net *net, struct ebt_table *table) { int i; @@ -1220,7 +1221,7 @@ void ebt_unregister_table(struct ebt_table *table) list_del(&table->list); mutex_unlock(&ebt_mutex); EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size, - ebt_cleanup_entry, NULL); + ebt_cleanup_entry, net, NULL); if (table->private->nentries) module_put(table->me); vfree(table->private->entries); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index a069d72d9482..cfaba0e2e6fc 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -553,13 +553,14 @@ mark_source_chains(struct xt_table_info *newinfo, } static int -cleanup_match(struct ipt_entry_match *m, unsigned int *i) +cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) { struct xt_mtdtor_param par; if (i && (*i)-- == 0) return 1; + par.net = net; par.match = m->u.kernel.match; par.matchinfo = m->data; par.family = NFPROTO_IPV4; @@ -705,7 +706,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, &j); + IPT_MATCH_ITERATE(e, cleanup_match, net, &j); return ret; } @@ -775,7 +776,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, } static int -cleanup_entry(struct ipt_entry *e, unsigned int *i) +cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i) { struct xt_tgdtor_param par; struct ipt_entry_target *t; @@ -784,7 +785,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) return 1; /* Cleanup all matches */ - IPT_MATCH_ITERATE(e, cleanup_match, NULL); + IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ipt_get_target(e); par.target = t->u.kernel.target; @@ -866,7 +867,7 @@ translate_table(struct net *net, if (ret != 0) { IPT_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); + cleanup_entry, net, &i); return ret; } @@ -1260,7 +1261,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, - NULL); + net, NULL); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, sizeof(struct xt_counters) * num_counters) != 0) @@ -1320,7 +1321,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1682,7 +1683,7 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, return 0; cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, &j); + IPT_MATCH_ITERATE(e, cleanup_match, net, &j); return ret; } @@ -1782,7 +1783,7 @@ translate_compat_table(struct net *net, j -= i; COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, compat_release_entry, &j); - IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); + IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); xt_free_table_info(newinfo); return ret; } @@ -1853,7 +1854,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -2112,7 +2113,7 @@ out: return ERR_PTR(ret); } -void ipt_unregister_table(struct xt_table *table) +void ipt_unregister_table(struct net *net, struct xt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; @@ -2122,7 +2123,7 @@ void ipt_unregister_table(struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index df566cbd68e5..dee90eb8aa47 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -138,7 +138,7 @@ static int __net_init iptable_filter_net_init(struct net *net) static void __net_exit iptable_filter_net_exit(struct net *net) { - ipt_unregister_table(net->ipv4.iptable_filter); + ipt_unregister_table(net, net->ipv4.iptable_filter); } static struct pernet_operations iptable_filter_net_ops = { diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index fae78c3076c4..e07bf242343a 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -208,7 +208,7 @@ static int __net_init iptable_mangle_net_init(struct net *net) static void __net_exit iptable_mangle_net_exit(struct net *net) { - ipt_unregister_table(net->ipv4.iptable_mangle); + ipt_unregister_table(net, net->ipv4.iptable_mangle); } static struct pernet_operations iptable_mangle_net_ops = { diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 993edc23be09..40f2b9f611a2 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -100,7 +100,7 @@ static int __net_init iptable_raw_net_init(struct net *net) static void __net_exit iptable_raw_net_exit(struct net *net) { - ipt_unregister_table(net->ipv4.iptable_raw); + ipt_unregister_table(net, net->ipv4.iptable_raw); } static struct pernet_operations iptable_raw_net_ops = { diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 3bd3d6388da5..7ce2366e4305 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -138,7 +138,7 @@ static int __net_init iptable_security_net_init(struct net *net) static void __net_exit iptable_security_net_exit(struct net *net) { - ipt_unregister_table(net->ipv4.iptable_security); + ipt_unregister_table(net, net->ipv4.iptable_security); } static struct pernet_operations iptable_security_net_ops = { diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 9e81e0dfb4ec..85da34fdc755 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -195,7 +195,7 @@ static int __net_init nf_nat_rule_net_init(struct net *net) static void __net_exit nf_nat_rule_net_exit(struct net *net) { - ipt_unregister_table(net->ipv4.nat_table); + ipt_unregister_table(net, net->ipv4.nat_table); } static struct pernet_operations nf_nat_rule_net_ops = { diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index a825940a92ef..9f1d45f2ba8f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -585,13 +585,14 @@ mark_source_chains(struct xt_table_info *newinfo, } static int -cleanup_match(struct ip6t_entry_match *m, unsigned int *i) +cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) { struct xt_mtdtor_param par; if (i && (*i)-- == 0) return 1; + par.net = net; par.match = m->u.kernel.match; par.matchinfo = m->data; par.family = NFPROTO_IPV6; @@ -737,7 +738,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - IP6T_MATCH_ITERATE(e, cleanup_match, &j); + IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); return ret; } @@ -807,7 +808,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, } static int -cleanup_entry(struct ip6t_entry *e, unsigned int *i) +cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) { struct xt_tgdtor_param par; struct ip6t_entry_target *t; @@ -816,7 +817,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) return 1; /* Cleanup all matches */ - IP6T_MATCH_ITERATE(e, cleanup_match, NULL); + IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ip6t_get_target(e); par.target = t->u.kernel.target; @@ -898,7 +899,7 @@ translate_table(struct net *net, if (ret != 0) { IP6T_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); + cleanup_entry, net, &i); return ret; } @@ -1293,7 +1294,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, - NULL); + net, NULL); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, sizeof(struct xt_counters) * num_counters) != 0) @@ -1353,7 +1354,7 @@ do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1692,14 +1693,15 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, return ret; } -static int compat_check_entry(struct ip6t_entry *e, const char *name, - unsigned int *i) +static int compat_check_entry(struct ip6t_entry *e, struct net *net, + const char *name, unsigned int *i) { unsigned int j; int ret; struct xt_mtchk_param mtpar; j = 0; + mtpar.net = net; mtpar.table = name; mtpar.entryinfo = &e->ipv6; mtpar.hook_mask = e->comefrom; @@ -1716,12 +1718,13 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name, return 0; cleanup_matches: - IP6T_MATCH_ITERATE(e, cleanup_match, &j); + IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); return ret; } static int -translate_compat_table(const char *name, +translate_compat_table(struct net *net, + const char *name, unsigned int valid_hooks, struct xt_table_info **pinfo, void **pentry0, @@ -1810,12 +1813,12 @@ translate_compat_table(const char *name, i = 0; ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, - name, &i); + net, name, &i); if (ret) { j -= i; COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, compat_release_entry, &j); - IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); + IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); xt_free_table_info(newinfo); return ret; } @@ -1870,7 +1873,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_compat_table(tmp.name, tmp.valid_hooks, + ret = translate_compat_table(net, tmp.name, tmp.valid_hooks, &newinfo, &loc_cpu_entry, tmp.size, tmp.num_entries, tmp.hook_entry, tmp.underflow); @@ -1886,7 +1889,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -2144,7 +2147,7 @@ out: return ERR_PTR(ret); } -void ip6t_unregister_table(struct xt_table *table) +void ip6t_unregister_table(struct net *net, struct xt_table *table) { struct xt_table_info *private; void *loc_cpu_entry; @@ -2154,7 +2157,7 @@ void ip6t_unregister_table(struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; - IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); + IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index ad378efd0eb8..33ddfe53e18d 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -131,7 +131,7 @@ static int __net_init ip6table_filter_net_init(struct net *net) static void __net_exit ip6table_filter_net_exit(struct net *net) { - ip6t_unregister_table(net->ipv6.ip6table_filter); + ip6t_unregister_table(net, net->ipv6.ip6table_filter); } static struct pernet_operations ip6table_filter_net_ops = { diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index a929c19d30e3..9bc483f000e5 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -182,7 +182,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net) static void __net_exit ip6table_mangle_net_exit(struct net *net) { - ip6t_unregister_table(net->ipv6.ip6table_mangle); + ip6t_unregister_table(net, net->ipv6.ip6table_mangle); } static struct pernet_operations ip6table_mangle_net_ops = { diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index ed1a1180f3b3..4c90b552e433 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -94,7 +94,7 @@ static int __net_init ip6table_raw_net_init(struct net *net) static void __net_exit ip6table_raw_net_exit(struct net *net) { - ip6t_unregister_table(net->ipv6.ip6table_raw); + ip6t_unregister_table(net, net->ipv6.ip6table_raw); } static struct pernet_operations ip6table_raw_net_ops = { diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 41b444c60934..baa8d4ef3b0a 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -134,7 +134,7 @@ static int __net_init ip6table_security_net_init(struct net *net) static void __net_exit ip6table_security_net_exit(struct net *net) { - ip6t_unregister_table(net->ipv6.ip6table_security); + ip6t_unregister_table(net, net->ipv6.ip6table_security); } static struct pernet_operations ip6table_security_net_ops = { -- cgit v1.2.3 From 7d07d5632b672c892a65882c2a119345fd9596c9 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:31:00 +0100 Subject: netfilter: xt_recent: netns support Make recent table list per-netns. Make proc files per-netns. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/xt_recent.c | 136 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 41 deletions(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 768d01ff1fea..203333107367 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -78,15 +79,26 @@ struct recent_table { struct list_head iphash[0]; }; -static LIST_HEAD(tables); +struct recent_net { + struct list_head tables; +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *xt_recent; +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + struct proc_dir_entry *ipt_recent; +#endif +#endif +}; + +static int recent_net_id; +static inline struct recent_net *recent_pernet(struct net *net) +{ + return net_generic(net, recent_net_id); +} + static DEFINE_SPINLOCK(recent_lock); static DEFINE_MUTEX(recent_mutex); #ifdef CONFIG_PROC_FS -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT -static struct proc_dir_entry *proc_old_dir; -#endif -static struct proc_dir_entry *recent_proc_dir; static const struct file_operations recent_old_fops, recent_mt_fops; #endif @@ -172,11 +184,12 @@ static void recent_entry_update(struct recent_table *t, struct recent_entry *e) list_move_tail(&e->lru_list, &t->lru_list); } -static struct recent_table *recent_table_lookup(const char *name) +static struct recent_table *recent_table_lookup(struct recent_net *recent_net, + const char *name) { struct recent_table *t; - list_for_each_entry(t, &tables, list) + list_for_each_entry(t, &recent_net->tables, list) if (!strcmp(t->name, name)) return t; return NULL; @@ -195,6 +208,8 @@ static void recent_table_flush(struct recent_table *t) static bool recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) { + struct net *net = dev_net(par->in ? par->in : par->out); + struct recent_net *recent_net = recent_pernet(net); const struct xt_recent_mtinfo *info = par->matchinfo; struct recent_table *t; struct recent_entry *e; @@ -227,7 +242,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) ttl++; spin_lock_bh(&recent_lock); - t = recent_table_lookup(info->name); + t = recent_table_lookup(recent_net, info->name); e = recent_entry_lookup(t, &addr, par->match->family, (info->check_set & XT_RECENT_TTL) ? ttl : 0); if (e == NULL) { @@ -271,6 +286,7 @@ out: static bool recent_mt_check(const struct xt_mtchk_param *par) { + struct recent_net *recent_net = recent_pernet(par->net); const struct xt_recent_mtinfo *info = par->matchinfo; struct recent_table *t; #ifdef CONFIG_PROC_FS @@ -297,7 +313,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) return false; mutex_lock(&recent_mutex); - t = recent_table_lookup(info->name); + t = recent_table_lookup(recent_net, info->name); if (t != NULL) { t->refcnt++; ret = true; @@ -314,7 +330,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) for (i = 0; i < ip_list_hash_size; i++) INIT_LIST_HEAD(&t->iphash[i]); #ifdef CONFIG_PROC_FS - pde = proc_create_data(t->name, ip_list_perms, recent_proc_dir, + pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, &recent_mt_fops, t); if (pde == NULL) { kfree(t); @@ -323,10 +339,10 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) pde->uid = ip_list_uid; pde->gid = ip_list_gid; #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT - pde = proc_create_data(t->name, ip_list_perms, proc_old_dir, + pde = proc_create_data(t->name, ip_list_perms, recent_net->ipt_recent, &recent_old_fops, t); if (pde == NULL) { - remove_proc_entry(t->name, proc_old_dir); + remove_proc_entry(t->name, recent_net->xt_recent); kfree(t); goto out; } @@ -335,7 +351,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) #endif #endif spin_lock_bh(&recent_lock); - list_add_tail(&t->list, &tables); + list_add_tail(&t->list, &recent_net->tables); spin_unlock_bh(&recent_lock); ret = true; out: @@ -345,20 +361,21 @@ out: static void recent_mt_destroy(const struct xt_mtdtor_param *par) { + struct recent_net *recent_net = recent_pernet(par->net); const struct xt_recent_mtinfo *info = par->matchinfo; struct recent_table *t; mutex_lock(&recent_mutex); - t = recent_table_lookup(info->name); + t = recent_table_lookup(recent_net, info->name); if (--t->refcnt == 0) { spin_lock_bh(&recent_lock); list_del(&t->list); spin_unlock_bh(&recent_lock); #ifdef CONFIG_PROC_FS #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT - remove_proc_entry(t->name, proc_old_dir); + remove_proc_entry(t->name, recent_net->ipt_recent); #endif - remove_proc_entry(t->name, recent_proc_dir); + remove_proc_entry(t->name, recent_net->xt_recent); #endif recent_table_flush(t); kfree(t); @@ -607,8 +624,65 @@ static const struct file_operations recent_mt_fops = { .release = seq_release_private, .owner = THIS_MODULE, }; + +static int __net_init recent_proc_net_init(struct net *net) +{ + struct recent_net *recent_net = recent_pernet(net); + + recent_net->xt_recent = proc_mkdir("xt_recent", net->proc_net); + if (!recent_net->xt_recent) + return -ENOMEM; +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + recent_net->ipt_recent = proc_mkdir("ipt_recent", net->proc_net); + if (!recent_net->ipt_recent) { + proc_net_remove(net, "xt_recent"); + return -ENOMEM; + } +#endif + return 0; +} + +static void __net_exit recent_proc_net_exit(struct net *net) +{ +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + proc_net_remove(net, "ipt_recent"); +#endif + proc_net_remove(net, "xt_recent"); +} +#else +static inline int recent_proc_net_init(struct net *net) +{ + return 0; +} + +static inline void recent_proc_net_exit(struct net *net) +{ +} #endif /* CONFIG_PROC_FS */ +static int __net_init recent_net_init(struct net *net) +{ + struct recent_net *recent_net = recent_pernet(net); + + INIT_LIST_HEAD(&recent_net->tables); + return recent_proc_net_init(net); +} + +static void __net_exit recent_net_exit(struct net *net) +{ + struct recent_net *recent_net = recent_pernet(net); + + BUG_ON(!list_empty(&recent_net->tables)); + recent_proc_net_exit(net); +} + +static struct pernet_operations recent_net_ops = { + .init = recent_net_init, + .exit = recent_net_exit, + .id = &recent_net_id, + .size = sizeof(struct recent_net), +}; + static struct xt_match recent_mt_reg[] __read_mostly = { { .name = "recent", @@ -640,39 +714,19 @@ static int __init recent_mt_init(void) return -EINVAL; ip_list_hash_size = 1 << fls(ip_list_tot); - err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); -#ifdef CONFIG_PROC_FS + err = register_pernet_subsys(&recent_net_ops); if (err) return err; - recent_proc_dir = proc_mkdir("xt_recent", init_net.proc_net); - if (recent_proc_dir == NULL) { - xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); - err = -ENOMEM; - } -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT - if (err < 0) - return err; - proc_old_dir = proc_mkdir("ipt_recent", init_net.proc_net); - if (proc_old_dir == NULL) { - remove_proc_entry("xt_recent", init_net.proc_net); - xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); - err = -ENOMEM; - } -#endif -#endif + err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); + if (err) + unregister_pernet_subsys(&recent_net_ops); return err; } static void __exit recent_mt_exit(void) { - BUG_ON(!list_empty(&tables)); xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); -#ifdef CONFIG_PROC_FS -#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT - remove_proc_entry("ipt_recent", init_net.proc_net); -#endif - remove_proc_entry("xt_recent", init_net.proc_net); -#endif + unregister_pernet_subsys(&recent_net_ops); } module_init(recent_mt_init); -- cgit v1.2.3 From e89fc3f1b06d9241f65e580b002789abaa6d11ac Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 18 Jan 2010 08:33:28 +0100 Subject: netfilter: xt_hashlimit: netns support Make hashtable per-netns. Make proc files per-netns. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/xt_hashlimit.c | 141 ++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 43 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 944fd11c8989..fb7fcb773a3f 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include @@ -40,9 +41,19 @@ MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match"); MODULE_ALIAS("ipt_hashlimit"); MODULE_ALIAS("ip6t_hashlimit"); +struct hashlimit_net { + struct hlist_head htables; + struct proc_dir_entry *ipt_hashlimit; + struct proc_dir_entry *ip6t_hashlimit; +}; + +static int hashlimit_net_id; +static inline struct hashlimit_net *hashlimit_pernet(struct net *net) +{ + return net_generic(net, hashlimit_net_id); +} + /* need to declare this at the top */ -static struct proc_dir_entry *hashlimit_procdir4; -static struct proc_dir_entry *hashlimit_procdir6; static const struct file_operations dl_file_ops; /* hash table crap */ @@ -93,13 +104,13 @@ struct xt_hashlimit_htable { /* seq_file stuff */ struct proc_dir_entry *pde; + struct net *net; struct hlist_head hash[0]; /* hashtable itself */ }; static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ -static HLIST_HEAD(hashlimit_htables); static struct kmem_cache *hashlimit_cachep __read_mostly; static inline bool dst_cmp(const struct dsthash_ent *ent, @@ -185,8 +196,9 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) } static void htable_gc(unsigned long htlong); -static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family) +static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_int8_t family) { + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); struct xt_hashlimit_htable *hinfo; unsigned int size; unsigned int i; @@ -239,26 +251,29 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family) spin_lock_init(&hinfo->lock); hinfo->pde = proc_create_data(minfo->name, 0, (family == NFPROTO_IPV4) ? - hashlimit_procdir4 : hashlimit_procdir6, + hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit, &dl_file_ops, hinfo); if (!hinfo->pde) { vfree(hinfo); return -1; } + hinfo->net = net; setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); spin_lock_bh(&hashlimit_lock); - hlist_add_head(&hinfo->node, &hashlimit_htables); + hlist_add_head(&hinfo->node, &hashlimit_net->htables); spin_unlock_bh(&hashlimit_lock); return 0; } -static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family) +static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, + u_int8_t family) { + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); struct xt_hashlimit_htable *hinfo; unsigned int size; unsigned int i; @@ -301,19 +316,20 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family) hinfo->pde = proc_create_data(minfo->name, 0, (family == NFPROTO_IPV4) ? - hashlimit_procdir4 : hashlimit_procdir6, + hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit, &dl_file_ops, hinfo); if (hinfo->pde == NULL) { vfree(hinfo); return -1; } + hinfo->net = net; setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); spin_lock_bh(&hashlimit_lock); - hlist_add_head(&hinfo->node, &hashlimit_htables); + hlist_add_head(&hinfo->node, &hashlimit_net->htables); spin_unlock_bh(&hashlimit_lock); return 0; @@ -364,24 +380,30 @@ static void htable_gc(unsigned long htlong) static void htable_destroy(struct xt_hashlimit_htable *hinfo) { + struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net); + struct proc_dir_entry *parent; + del_timer_sync(&hinfo->timer); - /* remove proc entry */ - remove_proc_entry(hinfo->pde->name, - hinfo->family == NFPROTO_IPV4 ? hashlimit_procdir4 : - hashlimit_procdir6); + if (hinfo->family == NFPROTO_IPV4) + parent = hashlimit_net->ipt_hashlimit; + else + parent = hashlimit_net->ip6t_hashlimit; + remove_proc_entry(hinfo->pde->name, parent); htable_selective_cleanup(hinfo, select_all); vfree(hinfo); } -static struct xt_hashlimit_htable *htable_find_get(const char *name, +static struct xt_hashlimit_htable *htable_find_get(struct net *net, + const char *name, u_int8_t family) { + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); struct xt_hashlimit_htable *hinfo; struct hlist_node *pos; spin_lock_bh(&hashlimit_lock); - hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) { + hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node) { if (!strcmp(name, hinfo->pde->name) && hinfo->family == family) { atomic_inc(&hinfo->use); @@ -665,6 +687,7 @@ hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) { + struct net *net = par->net; struct xt_hashlimit_info *r = par->matchinfo; /* Check for overflow. */ @@ -694,8 +717,8 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) * the list of htable's in htable_create(), since then we would * create duplicate proc files. -HW */ mutex_lock(&hlimit_mutex); - r->hinfo = htable_find_get(r->name, par->match->family); - if (!r->hinfo && htable_create_v0(r, par->match->family) != 0) { + r->hinfo = htable_find_get(net, r->name, par->match->family); + if (!r->hinfo && htable_create_v0(net, r, par->match->family) != 0) { mutex_unlock(&hlimit_mutex); return false; } @@ -706,6 +729,7 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) static bool hashlimit_mt_check(const struct xt_mtchk_param *par) { + struct net *net = par->net; struct xt_hashlimit_mtinfo1 *info = par->matchinfo; /* Check for overflow. */ @@ -735,8 +759,8 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par) * the list of htable's in htable_create(), since then we would * create duplicate proc files. -HW */ mutex_lock(&hlimit_mutex); - info->hinfo = htable_find_get(info->name, par->match->family); - if (!info->hinfo && htable_create(info, par->match->family) != 0) { + info->hinfo = htable_find_get(net, info->name, par->match->family); + if (!info->hinfo && htable_create(net, info, par->match->family) != 0) { mutex_unlock(&hlimit_mutex); return false; } @@ -953,10 +977,61 @@ static const struct file_operations dl_file_ops = { .release = seq_release }; +static int __net_init hashlimit_proc_net_init(struct net *net) +{ + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); + + hashlimit_net->ipt_hashlimit = proc_mkdir("ipt_hashlimit", net->proc_net); + if (!hashlimit_net->ipt_hashlimit) + return -ENOMEM; +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) + hashlimit_net->ip6t_hashlimit = proc_mkdir("ip6t_hashlimit", net->proc_net); + if (!hashlimit_net->ip6t_hashlimit) { + proc_net_remove(net, "ipt_hashlimit"); + return -ENOMEM; + } +#endif + return 0; +} + +static void __net_exit hashlimit_proc_net_exit(struct net *net) +{ + proc_net_remove(net, "ipt_hashlimit"); +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) + proc_net_remove(net, "ip6t_hashlimit"); +#endif +} + +static int __net_init hashlimit_net_init(struct net *net) +{ + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); + + INIT_HLIST_HEAD(&hashlimit_net->htables); + return hashlimit_proc_net_init(net); +} + +static void __net_exit hashlimit_net_exit(struct net *net) +{ + struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); + + BUG_ON(!hlist_empty(&hashlimit_net->htables)); + hashlimit_proc_net_exit(net); +} + +static struct pernet_operations hashlimit_net_ops = { + .init = hashlimit_net_init, + .exit = hashlimit_net_exit, + .id = &hashlimit_net_id, + .size = sizeof(struct hashlimit_net), +}; + static int __init hashlimit_mt_init(void) { int err; + err = register_pernet_subsys(&hashlimit_net_ops); + if (err < 0) + return err; err = xt_register_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); if (err < 0) @@ -970,41 +1045,21 @@ static int __init hashlimit_mt_init(void) printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n"); goto err2; } - hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net); - if (!hashlimit_procdir4) { - printk(KERN_ERR "xt_hashlimit: unable to create proc dir " - "entry\n"); - goto err3; - } - err = 0; -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) - hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net); - if (!hashlimit_procdir6) { - printk(KERN_ERR "xt_hashlimit: unable to create proc dir " - "entry\n"); - err = -ENOMEM; - } -#endif - if (!err) - return 0; - remove_proc_entry("ipt_hashlimit", init_net.proc_net); -err3: - kmem_cache_destroy(hashlimit_cachep); + return 0; + err2: xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); err1: + unregister_pernet_subsys(&hashlimit_net_ops); return err; } static void __exit hashlimit_mt_exit(void) { - remove_proc_entry("ipt_hashlimit", init_net.proc_net); -#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) - remove_proc_entry("ip6t_hashlimit", init_net.proc_net); -#endif kmem_cache_destroy(hashlimit_cachep); xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); + unregister_pernet_subsys(&hashlimit_net_ops); } module_init(hashlimit_mt_init); -- cgit v1.2.3 From 2ae3111eafd797e24cc390bb5ce6a8fa0deacdb2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 18 Jan 2010 00:29:19 -0800 Subject: drivers/net: Eliminate useless code The variable qdev is initialized twice to the same (side effect-free) expression. Drop one initialization. A simplified version of the semantic match that finds this problem is: (http://coccinelle.lip6.fr/) // @forall@ idexpression *x; identifier f!=ERR_PTR; @@ x = f(...) ... when != x ( x = f(...,<+...x...+>,...) | * x = f(...) ) // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/qla3xxx.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index f922294fd349..4ef0afbcbe1b 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -4087,7 +4087,6 @@ static void __devexit ql3xxx_remove(struct pci_dev *pdev) struct ql3_adapter *qdev = netdev_priv(ndev); unregister_netdev(ndev); - qdev = netdev_priv(ndev); ql_disable_interrupts(qdev); -- cgit v1.2.3 From a5d896adf019143adf72d08826fe5359b6a8762c Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 18 Jan 2010 09:44:39 +0100 Subject: netfilter: nfnetlink_queue: simplify warning message This patch remove variable part from a debug message to have message concatenation from syslog. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- net/netfilter/nfnetlink_queue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 5c589b27d6eb..90cf36decea3 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -414,8 +414,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) queue->queue_dropped++; if (net_ratelimit()) printk(KERN_WARNING "nf_queue: full at %d entries, " - "dropping packets(s). Dropped: %d\n", - queue->queue_total, queue->queue_dropped); + "dropping packets(s).\n", + queue->queue_total); goto err_out_free_nskb; } -- cgit v1.2.3 From fa44a73cc766c7f3bac71a66d564e0049b800325 Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Mon, 18 Jan 2010 12:59:55 +0000 Subject: ppp_generic.c severly whitespace damanged by 9c705260feea6ae329bc6b6d5f6d2ef0227eda0a I was just looking at ppp_generic, and noticed that it fairly recently (as in the last year) got rather mangled with many spaces turned into tabs in places they very much shouldn't have been. I tracked it down to commit 9c705260feea6ae329bc6b6d5f6d2ef0227eda0a (ppp: ppp_mp_explode() redesign). I am amazed if that patch passed the patch checking script. I have no idea what kind of weird editor setting did this, but it has to have been a weird editor setting or a very unfortunate search and replace gone wrong. I only found it trying to apply a patch I was playing with and wondering why it wouldn't apply. Then I found there were tabs in the middle of comments that used to be spaces. Well here is a patch that should fix it up as far as I can tell. Purely whitespace repair. No actual code changes. Signed-off-by: Len Sorensen Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 122 +++++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 2282e729edbe..6d61602208c1 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -167,7 +167,7 @@ struct channel { u8 avail; /* flag used in multilink stuff */ u8 had_frag; /* >= 1 fragments have been sent */ u32 lastseq; /* MP: last sequence # received */ - int speed; /* speed of the corresponding ppp channel*/ + int speed; /* speed of the corresponding ppp channel*/ #endif /* CONFIG_PPP_MULTILINK */ }; @@ -1293,13 +1293,13 @@ ppp_push(struct ppp *ppp) */ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) { - int len, totlen; - int i, bits, hdrlen, mtu; - int flen; - int navail, nfree, nzero; - int nbigger; - int totspeed; - int totfree; + int len, totlen; + int i, bits, hdrlen, mtu; + int flen; + int navail, nfree, nzero; + int nbigger; + int totspeed; + int totfree; unsigned char *p, *q; struct list_head *list; struct channel *pch; @@ -1307,21 +1307,21 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) struct ppp_channel *chan; totspeed = 0; /*total bitrate of the bundle*/ - nfree = 0; /* # channels which have no packet already queued */ - navail = 0; /* total # of usable channels (not deregistered) */ - nzero = 0; /* number of channels with zero speed associated*/ - totfree = 0; /*total # of channels available and + nfree = 0; /* # channels which have no packet already queued */ + navail = 0; /* total # of usable channels (not deregistered) */ + nzero = 0; /* number of channels with zero speed associated*/ + totfree = 0; /*total # of channels available and *having no queued packets before *starting the fragmentation*/ hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - i = 0; - list_for_each_entry(pch, &ppp->channels, clist) { + i = 0; + list_for_each_entry(pch, &ppp->channels, clist) { navail += pch->avail = (pch->chan != NULL); pch->speed = pch->chan->speed; - if (pch->avail) { + if (pch->avail) { if (skb_queue_empty(&pch->file.xq) || - !pch->had_frag) { + !pch->had_frag) { if (pch->speed == 0) nzero++; else @@ -1331,60 +1331,60 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) ++nfree; ++totfree; } - if (!pch->had_frag && i < ppp->nxchan) - ppp->nxchan = i; + if (!pch->had_frag && i < ppp->nxchan) + ppp->nxchan = i; } ++i; } /* - * Don't start sending this packet unless at least half of - * the channels are free. This gives much better TCP - * performance if we have a lot of channels. + * Don't start sending this packet unless at least half of + * the channels are free. This gives much better TCP + * performance if we have a lot of channels. */ - if (nfree == 0 || nfree < navail / 2) - return 0; /* can't take now, leave it in xmit_pending */ + if (nfree == 0 || nfree < navail / 2) + return 0; /* can't take now, leave it in xmit_pending */ /* Do protocol field compression (XXX this should be optional) */ - p = skb->data; - len = skb->len; + p = skb->data; + len = skb->len; if (*p == 0) { ++p; --len; } totlen = len; - nbigger = len % nfree; + nbigger = len % nfree; - /* skip to the channel after the one we last used - and start at that one */ + /* skip to the channel after the one we last used + and start at that one */ list = &ppp->channels; - for (i = 0; i < ppp->nxchan; ++i) { + for (i = 0; i < ppp->nxchan; ++i) { list = list->next; - if (list == &ppp->channels) { - i = 0; + if (list == &ppp->channels) { + i = 0; break; } } - /* create a fragment for each channel */ + /* create a fragment for each channel */ bits = B; - while (len > 0) { + while (len > 0) { list = list->next; - if (list == &ppp->channels) { - i = 0; + if (list == &ppp->channels) { + i = 0; continue; } - pch = list_entry(list, struct channel, clist); + pch = list_entry(list, struct channel, clist); ++i; if (!pch->avail) continue; /* - * Skip this channel if it has a fragment pending already and - * we haven't given a fragment to all of the free channels. + * Skip this channel if it has a fragment pending already and + * we haven't given a fragment to all of the free channels. */ if (pch->avail == 1) { - if (nfree > 0) + if (nfree > 0) continue; } else { pch->avail = 1; @@ -1393,32 +1393,32 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) /* check the channel's mtu and whether it is still attached. */ spin_lock_bh(&pch->downl); if (pch->chan == NULL) { - /* can't use this channel, it's being deregistered */ + /* can't use this channel, it's being deregistered */ if (pch->speed == 0) nzero--; else - totspeed -= pch->speed; + totspeed -= pch->speed; spin_unlock_bh(&pch->downl); pch->avail = 0; totlen = len; totfree--; nfree--; - if (--navail == 0) + if (--navail == 0) break; continue; } /* *if the channel speed is not set divide - *the packet evenly among the free channels; + *the packet evenly among the free channels; *otherwise divide it according to the speed *of the channel we are going to transmit on */ flen = len; if (nfree > 0) { if (pch->speed == 0) { - flen = totlen/nfree ; + flen = totlen/nfree; if (nbigger > 0) { flen++; nbigger--; @@ -1436,8 +1436,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) } /* - *check if we are on the last channel or - *we exceded the lenght of the data to + *check if we are on the last channel or + *we exceded the lenght of the data to *fragment */ if ((nfree <= 0) || (flen > len)) @@ -1448,29 +1448,29 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) *above formula will be equal or less than zero. *Skip the channel in this case */ - if (flen <= 0) { + if (flen <= 0) { pch->avail = 2; spin_unlock_bh(&pch->downl); continue; } - mtu = pch->chan->mtu - hdrlen; - if (mtu < 4) - mtu = 4; + mtu = pch->chan->mtu - hdrlen; + if (mtu < 4) + mtu = 4; if (flen > mtu) flen = mtu; - if (flen == len) - bits |= E; - frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); + if (flen == len) + bits |= E; + frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC); if (!frag) goto noskb; - q = skb_put(frag, flen + hdrlen); + q = skb_put(frag, flen + hdrlen); - /* make the MP header */ + /* make the MP header */ q[0] = PPP_MP >> 8; q[1] = PPP_MP; if (ppp->flags & SC_MP_XSHORTSEQ) { - q[2] = bits + ((ppp->nxseq >> 8) & 0xf); + q[2] = bits + ((ppp->nxseq >> 8) & 0xf); q[3] = ppp->nxseq; } else { q[2] = bits; @@ -1483,24 +1483,24 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) /* try to send it down the channel */ chan = pch->chan; - if (!skb_queue_empty(&pch->file.xq) || + if (!skb_queue_empty(&pch->file.xq) || !chan->ops->start_xmit(chan, frag)) skb_queue_tail(&pch->file.xq, frag); - pch->had_frag = 1; + pch->had_frag = 1; p += flen; - len -= flen; + len -= flen; ++ppp->nxseq; bits = 0; spin_unlock_bh(&pch->downl); } - ppp->nxchan = i; + ppp->nxchan = i; return 1; noskb: spin_unlock_bh(&pch->downl); if (ppp->debug & 1) - printk(KERN_ERR "PPP: no memory (fragment)\n"); + printk(KERN_ERR "PPP: no memory (fragment)\n"); ++ppp->dev->stats.tx_errors; ++ppp->nxseq; return 1; /* abandon the frame */ -- cgit v1.2.3 From 6d955180b2f9ccff444df06265160868cabb289a Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Mon, 18 Jan 2010 12:58:44 +0000 Subject: ipv4: allow warming up the ARP cache with request type gratuitous ARP If the per device ARP_ACCEPT option is enable, currently we only allow creating new ARP cache entries for response type gratuitous ARP. Allowing gratuitous ARP to create new ARP entries (not only to update existing ones) is useful when we want to avoid unnecessary delays for the first packet of a stream. This patch allows request type gratuitous ARP to create new ARP cache entries as well. This is useful when we want to populate the ARP cache entries for a large number of hosts on the same LAN. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 15 ++++++++++++--- net/ipv4/arp.c | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index c532884f4fec..2dc7a1d97686 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -852,9 +852,18 @@ arp_notify - BOOLEAN or hardware address changes. arp_accept - BOOLEAN - Define behavior when gratuitous arp replies are received: - 0 - drop gratuitous arp frames - 1 - accept gratuitous arp frames + Define behavior for gratuitous ARP frames who's IP is not + already present in the ARP table: + 0 - don't create new entries in the ARP table + 1 - create new entries in the ARP table + + Both replies and requests type gratuitous arp will trigger the + ARP table to be updated, if this setting is on. + + If the ARP table already contains the IP address of the + gratuitous arp frame, the arp table will be updated regardless + if this setting is on or off. + app_solicit - INTEGER The maximum number of probes to send to the user space ARP daemon diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 078709233bc4..1940b4df7699 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -907,7 +907,8 @@ static int arp_process(struct sk_buff *skb) devices (strip is candidate) */ if (n == NULL && - arp->ar_op == htons(ARPOP_REPLY) && + (arp->ar_op == htons(ARPOP_REPLY) || + (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) && inet_addr_type(net, sip) == RTN_UNICAST) n = __neigh_lookup(&arp_tbl, &sip, dev, 1); } -- cgit v1.2.3 From 861a57cd01f97e984320b5aeeee019ede48c714d Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Jan 2010 04:08:26 +0100 Subject: mac80211: fix WMM AC default for non-QoS data frames The WMM AC selection added to the monitor mode selection function accidentally assigns non-QoS data frames to the same AC as mgmt frames (VO). This is not serious, but should be fixed anyway. This patch assigns them to the BE AC instead. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/iface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index edf21cebeee8..09fff4662e80 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -695,10 +695,14 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); - if (!ieee80211_is_data_qos(hdr->frame_control)) { + if (!ieee80211_is_data(hdr->frame_control)) { skb->priority = 7; return ieee802_1d_to_ac[skb->priority]; } + if (!ieee80211_is_data_qos(hdr->frame_control)) { + skb->priority = 0; + return ieee802_1d_to_ac[skb->priority]; + } p = ieee80211_get_qos_ctl(hdr); skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; -- cgit v1.2.3 From 9ed333e0298c8f12cf7f3b4aec4258e81ef588a0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:33 -0800 Subject: iwlwifi: fix clear statistics counter command When receive reply statistics command with "clear" mask, just reset the accumulated statistics counters, but not the current statistics counters, so the accumulated statistics counter can provide the correct information. Signed-off-by: Wey-Yi Guy Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 6f36b6e79f5e..10db97327452 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -638,8 +638,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { - memset(&priv->statistics, 0, - sizeof(struct iwl_notif_statistics)); #ifdef CONFIG_IWLWIFI_DEBUG memset(&priv->accum_statistics, 0, sizeof(struct iwl_notif_statistics)); -- cgit v1.2.3 From e3ef2164386a13a37714ec033e30811d052c7999 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:34 -0800 Subject: iwlwifi: format and show statistics counter from uCode To help debug uCode related problem, adding "delta" and "max" information in debugfs statistics counters display. Those information show the delta between two statistics report from uCode, user can monitor the counters for any "un-normal" behavior. Signed-off-by: Wey-Yi Guy Signed-off-by: Jay Sternberg Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 850 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl-rx.c | 19 +- 3 files changed, 545 insertions(+), 326 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 4a2ac9311ba8..2264cbd95a00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1081,6 +1081,12 @@ static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, return p; } +static const char ucode_stats_header[] = + "%-32s current acumulative delta max\n"; +static const char ucode_stats_short_format[] = + " %-30s %10u\n"; +static const char ucode_stats_format[] = + " %-30s %10u %10u %10u %10u\n"; static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, @@ -1089,14 +1095,15 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; - int bufsz = sizeof(struct statistics_rx_phy) * 20 + - sizeof(struct statistics_rx_non_phy) * 20 + - sizeof(struct statistics_rx_ht_phy) * 20 + 400; + int bufsz = sizeof(struct statistics_rx_phy) * 40 + + sizeof(struct statistics_rx_non_phy) * 40 + + sizeof(struct statistics_rx_ht_phy) * 40 + 400; ssize_t ret; - struct statistics_rx_phy *ofdm, *accum_ofdm; - struct statistics_rx_phy *cck, *accum_cck; + struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; + struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; struct statistics_rx_non_phy *general, *accum_general; - struct statistics_rx_ht_phy *ht, *accum_ht; + struct statistics_rx_non_phy *delta_general, *max_general; + struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; if (!iwl_is_alive(priv)) return -EAGAIN; @@ -1129,267 +1136,401 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, accum_cck = &priv->accum_statistics.rx.cck; accum_general = &priv->accum_statistics.rx.general; accum_ht = &priv->accum_statistics.rx.ofdm_ht; + delta_ofdm = &priv->delta_statistics.rx.ofdm; + delta_cck = &priv->delta_statistics.rx.cck; + delta_general = &priv->delta_statistics.rx.general; + delta_ht = &priv->delta_statistics.rx.ofdm_ht; + max_ofdm = &priv->max_delta.rx.ofdm; + max_cck = &priv->max_delta.rx.cck; + max_general = &priv->max_delta.rx.general; + max_ht = &priv->max_delta.rx.ofdm_ht; + pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - "overrun_err:\t\t%u\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_Rx - OFDM:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), + accum_ofdm->ina_cnt, + delta_ofdm->ina_cnt, max_ofdm->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_cnt:", + le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, + delta_ofdm->fina_cnt, max_ofdm->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "plcp_err:", + le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, + delta_ofdm->plcp_err, max_ofdm->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_err:", + le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, + delta_ofdm->crc32_err, max_ofdm->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "overrun_err:", le32_to_cpu(ofdm->overrun_err), - accum_ofdm->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - "early_overrun_err:\t%u\t\t\t%u\n", + accum_ofdm->overrun_err, + delta_ofdm->overrun_err, max_ofdm->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "early_overrun_err:", le32_to_cpu(ofdm->early_overrun_err), - accum_ofdm->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", + accum_ofdm->early_overrun_err, + delta_ofdm->early_overrun_err, + max_ofdm->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_good:", le32_to_cpu(ofdm->crc32_good), - accum_ofdm->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - "false_alarm_cnt:\t%u\t\t\t%u\n", + accum_ofdm->crc32_good, + delta_ofdm->crc32_good, max_ofdm->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "false_alarm_cnt:", le32_to_cpu(ofdm->false_alarm_cnt), - accum_ofdm->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "fina_sync_err_cnt:\t%u\t\t\t%u\n", + accum_ofdm->false_alarm_cnt, + delta_ofdm->false_alarm_cnt, + max_ofdm->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_sync_err_cnt:", le32_to_cpu(ofdm->fina_sync_err_cnt), - accum_ofdm->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sfd_timeout:\t\t%u\t\t\t%u\n", + accum_ofdm->fina_sync_err_cnt, + delta_ofdm->fina_sync_err_cnt, + max_ofdm->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sfd_timeout:", le32_to_cpu(ofdm->sfd_timeout), - accum_ofdm->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "fina_timeout:\t\t%u\t\t\t%u\n", + accum_ofdm->sfd_timeout, + delta_ofdm->sfd_timeout, + max_ofdm->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_timeout:", le32_to_cpu(ofdm->fina_timeout), - accum_ofdm->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "unresponded_rts:\t%u\t\t\t%u\n", + accum_ofdm->fina_timeout, + delta_ofdm->fina_timeout, + max_ofdm->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "unresponded_rts:", le32_to_cpu(ofdm->unresponded_rts), - accum_ofdm->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, - "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", + accum_ofdm->unresponded_rts, + delta_ofdm->unresponded_rts, + max_ofdm->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "rxe_frame_lmt_ovrun:", le32_to_cpu(ofdm->rxe_frame_limit_overrun), - accum_ofdm->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_ack_cnt:\t\t%u\t\t\t%u\n", + accum_ofdm->rxe_frame_limit_overrun, + delta_ofdm->rxe_frame_limit_overrun, + max_ofdm->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_ack_cnt:", le32_to_cpu(ofdm->sent_ack_cnt), - accum_ofdm->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_cts_cnt:\t\t%u\t\t\t%u\n", + accum_ofdm->sent_ack_cnt, + delta_ofdm->sent_ack_cnt, + max_ofdm->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_cts_cnt:", le32_to_cpu(ofdm->sent_cts_cnt), - accum_ofdm->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", + accum_ofdm->sent_cts_cnt, + delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_ba_rsp_cnt:", le32_to_cpu(ofdm->sent_ba_rsp_cnt), - accum_ofdm->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "dsp_self_kill:\t\t%u\t\t\t%u\n", + accum_ofdm->sent_ba_rsp_cnt, + delta_ofdm->sent_ba_rsp_cnt, + max_ofdm->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "dsp_self_kill:", le32_to_cpu(ofdm->dsp_self_kill), - accum_ofdm->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, - "mh_format_err:\t\t%u\t\t\t%u\n", + accum_ofdm->dsp_self_kill, + delta_ofdm->dsp_self_kill, + max_ofdm->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "mh_format_err:", le32_to_cpu(ofdm->mh_format_err), - accum_ofdm->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", + accum_ofdm->mh_format_err, + delta_ofdm->mh_format_err, + max_ofdm->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "re_acq_main_rssi_sum:", le32_to_cpu(ofdm->re_acq_main_rssi_sum), - accum_ofdm->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(cck->plcp_err), accum_cck->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(cck->crc32_err), accum_cck->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - "overrun_err:\t\t%u\t\t\t%u\n", + accum_ofdm->re_acq_main_rssi_sum, + delta_ofdm->re_acq_main_rssi_sum, + max_ofdm->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_Rx - CCK:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "ina_cnt:", + le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, + delta_cck->ina_cnt, max_cck->ina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_cnt:", + le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, + delta_cck->fina_cnt, max_cck->fina_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "plcp_err:", + le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, + delta_cck->plcp_err, max_cck->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_err:", + le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, + delta_cck->crc32_err, max_cck->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "overrun_err:", le32_to_cpu(cck->overrun_err), - accum_cck->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - "early_overrun_err:\t%u\t\t\t%u\n", + accum_cck->overrun_err, + delta_cck->overrun_err, max_cck->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "early_overrun_err:", le32_to_cpu(cck->early_overrun_err), - accum_cck->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", - le32_to_cpu(cck->crc32_good), accum_cck->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - "false_alarm_cnt:\t%u\t\t\t%u\n", + accum_cck->early_overrun_err, + delta_cck->early_overrun_err, + max_cck->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_good:", + le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, + delta_cck->crc32_good, + max_cck->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "false_alarm_cnt:", le32_to_cpu(cck->false_alarm_cnt), - accum_cck->false_alarm_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "fina_sync_err_cnt:\t%u\t\t\t%u\n", + accum_cck->false_alarm_cnt, + delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_sync_err_cnt:", le32_to_cpu(cck->fina_sync_err_cnt), - accum_cck->fina_sync_err_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sfd_timeout:\t\t%u\t\t\t%u\n", + accum_cck->fina_sync_err_cnt, + delta_cck->fina_sync_err_cnt, + max_cck->fina_sync_err_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sfd_timeout:", le32_to_cpu(cck->sfd_timeout), - accum_cck->sfd_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "fina_timeout:\t\t%u\t\t\t%u\n", + accum_cck->sfd_timeout, + delta_cck->sfd_timeout, max_cck->sfd_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "fina_timeout:", le32_to_cpu(cck->fina_timeout), - accum_cck->fina_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "unresponded_rts:\t%u\t\t\t%u\n", + accum_cck->fina_timeout, + delta_cck->fina_timeout, max_cck->fina_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "unresponded_rts:", le32_to_cpu(cck->unresponded_rts), - accum_cck->unresponded_rts); - pos += scnprintf(buf + pos, bufsz - pos, - "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", + accum_cck->unresponded_rts, + delta_cck->unresponded_rts, + max_cck->unresponded_rts); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "rxe_frame_lmt_ovrun:", le32_to_cpu(cck->rxe_frame_limit_overrun), - accum_cck->rxe_frame_limit_overrun); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_ack_cnt:\t\t%u\t\t\t%u\n", + accum_cck->rxe_frame_limit_overrun, + delta_cck->rxe_frame_limit_overrun, + max_cck->rxe_frame_limit_overrun); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_ack_cnt:", le32_to_cpu(cck->sent_ack_cnt), - accum_cck->sent_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_cts_cnt:\t\t%u\t\t\t%u\n", + accum_cck->sent_ack_cnt, + delta_cck->sent_ack_cnt, + max_cck->sent_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_cts_cnt:", le32_to_cpu(cck->sent_cts_cnt), - accum_cck->sent_cts_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", + accum_cck->sent_cts_cnt, + delta_cck->sent_cts_cnt, + max_cck->sent_cts_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sent_ba_rsp_cnt:", le32_to_cpu(cck->sent_ba_rsp_cnt), - accum_cck->sent_ba_rsp_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "dsp_self_kill:\t\t%u\t\t\t%u\n", + accum_cck->sent_ba_rsp_cnt, + delta_cck->sent_ba_rsp_cnt, + max_cck->sent_ba_rsp_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "dsp_self_kill:", le32_to_cpu(cck->dsp_self_kill), - accum_cck->dsp_self_kill); - pos += scnprintf(buf + pos, bufsz - pos, - "mh_format_err:\t\t%u\t\t\t%u\n", + accum_cck->dsp_self_kill, + delta_cck->dsp_self_kill, + max_cck->dsp_self_kill); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "mh_format_err:", le32_to_cpu(cck->mh_format_err), - accum_cck->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", + accum_cck->mh_format_err, + delta_cck->mh_format_err, max_cck->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "re_acq_main_rssi_sum:", le32_to_cpu(cck->re_acq_main_rssi_sum), - accum_cck->re_acq_main_rssi_sum); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n", + accum_cck->re_acq_main_rssi_sum, + delta_cck->re_acq_main_rssi_sum, + max_cck->re_acq_main_rssi_sum); + + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_Rx - GENERAL:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "bogus_cts:", le32_to_cpu(general->bogus_cts), - accum_general->bogus_cts); - pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n", + accum_general->bogus_cts, + delta_general->bogus_cts, max_general->bogus_cts); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "bogus_ack:", le32_to_cpu(general->bogus_ack), - accum_general->bogus_ack); - pos += scnprintf(buf + pos, bufsz - pos, - "non_bssid_frames:\t%u\t\t\t%u\n", + accum_general->bogus_ack, + delta_general->bogus_ack, max_general->bogus_ack); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "non_bssid_frames:", le32_to_cpu(general->non_bssid_frames), - accum_general->non_bssid_frames); - pos += scnprintf(buf + pos, bufsz - pos, - "filtered_frames:\t%u\t\t\t%u\n", + accum_general->non_bssid_frames, + delta_general->non_bssid_frames, + max_general->non_bssid_frames); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "filtered_frames:", le32_to_cpu(general->filtered_frames), - accum_general->filtered_frames); - pos += scnprintf(buf + pos, bufsz - pos, - "non_channel_beacons:\t%u\t\t\t%u\n", + accum_general->filtered_frames, + delta_general->filtered_frames, + max_general->filtered_frames); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "non_channel_beacons:", le32_to_cpu(general->non_channel_beacons), - accum_general->non_channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, - "channel_beacons:\t%u\t\t\t%u\n", + accum_general->non_channel_beacons, + delta_general->non_channel_beacons, + max_general->non_channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "channel_beacons:", le32_to_cpu(general->channel_beacons), - accum_general->channel_beacons); - pos += scnprintf(buf + pos, bufsz - pos, - "num_missed_bcon:\t%u\t\t\t%u\n", + accum_general->channel_beacons, + delta_general->channel_beacons, + max_general->channel_beacons); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "num_missed_bcon:", le32_to_cpu(general->num_missed_bcon), - accum_general->num_missed_bcon); - pos += scnprintf(buf + pos, bufsz - pos, - "adc_rx_saturation_time:\t%u\t\t\t%u\n", + accum_general->num_missed_bcon, + delta_general->num_missed_bcon, + max_general->num_missed_bcon); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "adc_rx_saturation_time:", le32_to_cpu(general->adc_rx_saturation_time), - accum_general->adc_rx_saturation_time); - pos += scnprintf(buf + pos, bufsz - pos, - "ina_detect_search_tm:\t%u\t\t\t%u\n", + accum_general->adc_rx_saturation_time, + delta_general->adc_rx_saturation_time, + max_general->adc_rx_saturation_time); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "ina_detect_search_tm:", le32_to_cpu(general->ina_detection_search_time), - accum_general->ina_detection_search_time); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_silence_rssi_a:\t%u\t\t\t%u\n", + accum_general->ina_detection_search_time, + delta_general->ina_detection_search_time, + max_general->ina_detection_search_time); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_silence_rssi_a:", le32_to_cpu(general->beacon_silence_rssi_a), - accum_general->beacon_silence_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_silence_rssi_b:\t%u\t\t\t%u\n", + accum_general->beacon_silence_rssi_a, + delta_general->beacon_silence_rssi_a, + max_general->beacon_silence_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_silence_rssi_b:", le32_to_cpu(general->beacon_silence_rssi_b), - accum_general->beacon_silence_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_silence_rssi_c:\t%u\t\t\t%u\n", + accum_general->beacon_silence_rssi_b, + delta_general->beacon_silence_rssi_b, + max_general->beacon_silence_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_silence_rssi_c:", le32_to_cpu(general->beacon_silence_rssi_c), - accum_general->beacon_silence_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, - "interference_data_flag:\t%u\t\t\t%u\n", + accum_general->beacon_silence_rssi_c, + delta_general->beacon_silence_rssi_c, + max_general->beacon_silence_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "interference_data_flag:", le32_to_cpu(general->interference_data_flag), - accum_general->interference_data_flag); - pos += scnprintf(buf + pos, bufsz - pos, - "channel_load:\t\t%u\t\t\t%u\n", + accum_general->interference_data_flag, + delta_general->interference_data_flag, + max_general->interference_data_flag); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "channel_load:", le32_to_cpu(general->channel_load), - accum_general->channel_load); - pos += scnprintf(buf + pos, bufsz - pos, - "dsp_false_alarms:\t%u\t\t\t%u\n", + accum_general->channel_load, + delta_general->channel_load, + max_general->channel_load); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "dsp_false_alarms:", le32_to_cpu(general->dsp_false_alarms), - accum_general->dsp_false_alarms); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_rssi_a:\t\t%u\t\t\t%u\n", + accum_general->dsp_false_alarms, + delta_general->dsp_false_alarms, + max_general->dsp_false_alarms); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_rssi_a:", le32_to_cpu(general->beacon_rssi_a), - accum_general->beacon_rssi_a); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_rssi_b:\t\t%u\t\t\t%u\n", + accum_general->beacon_rssi_a, + delta_general->beacon_rssi_a, + max_general->beacon_rssi_a); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_rssi_b:", le32_to_cpu(general->beacon_rssi_b), - accum_general->beacon_rssi_b); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_rssi_c:\t\t%u\t\t\t%u\n", + accum_general->beacon_rssi_b, + delta_general->beacon_rssi_b, + max_general->beacon_rssi_b); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_rssi_c:", le32_to_cpu(general->beacon_rssi_c), - accum_general->beacon_rssi_c); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_energy_a:\t%u\t\t\t%u\n", + accum_general->beacon_rssi_c, + delta_general->beacon_rssi_c, + max_general->beacon_rssi_c); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_energy_a:", le32_to_cpu(general->beacon_energy_a), - accum_general->beacon_energy_a); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_energy_b:\t%u\t\t\t%u\n", + accum_general->beacon_energy_a, + delta_general->beacon_energy_a, + max_general->beacon_energy_a); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_energy_b:", le32_to_cpu(general->beacon_energy_b), - accum_general->beacon_energy_b); - pos += scnprintf(buf + pos, bufsz - pos, - "beacon_energy_c:\t%u\t\t\t%u\n", + accum_general->beacon_energy_b, + delta_general->beacon_energy_b, + max_general->beacon_energy_b); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "beacon_energy_c:", le32_to_cpu(general->beacon_energy_c), - accum_general->beacon_energy_c); + accum_general->beacon_energy_c, + delta_general->beacon_energy_c, + max_general->beacon_energy_c); pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(ht->plcp_err), accum_ht->plcp_err); - pos += scnprintf(buf + pos, bufsz - pos, - "overrun_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(ht->overrun_err), accum_ht->overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, - "early_overrun_err:\t%u\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_Rx - OFDM_HT:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "plcp_err:", + le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, + delta_ht->plcp_err, max_ht->plcp_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "overrun_err:", + le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, + delta_ht->overrun_err, max_ht->overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "early_overrun_err:", le32_to_cpu(ht->early_overrun_err), - accum_ht->early_overrun_err); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", - le32_to_cpu(ht->crc32_good), accum_ht->crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", - le32_to_cpu(ht->crc32_err), accum_ht->crc32_err); - pos += scnprintf(buf + pos, bufsz - pos, - "mh_format_err:\t\t%u\t\t\t%u\n", + accum_ht->early_overrun_err, + delta_ht->early_overrun_err, + max_ht->early_overrun_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_good:", + le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, + delta_ht->crc32_good, max_ht->crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "crc32_err:", + le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, + delta_ht->crc32_err, max_ht->crc32_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "mh_format_err:", le32_to_cpu(ht->mh_format_err), - accum_ht->mh_format_err); - pos += scnprintf(buf + pos, bufsz - pos, - "agg_crc32_good:\t\t%u\t\t\t%u\n", + accum_ht->mh_format_err, + delta_ht->mh_format_err, max_ht->mh_format_err); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg_crc32_good:", le32_to_cpu(ht->agg_crc32_good), - accum_ht->agg_crc32_good); - pos += scnprintf(buf + pos, bufsz - pos, - "agg_mpdu_cnt:\t\t%u\t\t\t%u\n", + accum_ht->agg_crc32_good, + delta_ht->agg_crc32_good, max_ht->agg_crc32_good); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg_mpdu_cnt:", le32_to_cpu(ht->agg_mpdu_cnt), - accum_ht->agg_mpdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n", - le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "unsupport_mcs:\t\t%u\t\t\t%u\n", + accum_ht->agg_mpdu_cnt, + delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg_cnt:", + le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, + delta_ht->agg_cnt, max_ht->agg_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "unsupport_mcs:", le32_to_cpu(ht->unsupport_mcs), - accum_ht->unsupport_mcs); + accum_ht->unsupport_mcs, + delta_ht->unsupport_mcs, max_ht->unsupport_mcs); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -1403,9 +1544,9 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; - int bufsz = (sizeof(struct statistics_tx) * 24) + 250; + int bufsz = (sizeof(struct statistics_tx) * 48) + 250; ssize_t ret; - struct statistics_tx *tx, *accum_tx; + struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; if (!iwl_is_alive(priv)) return -EAGAIN; @@ -1432,106 +1573,148 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, */ tx = &priv->statistics.tx; accum_tx = &priv->accum_statistics.tx; + delta_tx = &priv->delta_statistics.tx; + max_tx = &priv->max_delta.tx; pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_Tx:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "preamble:", le32_to_cpu(tx->preamble_cnt), - accum_tx->preamble_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "rx_detected_cnt:\t\t%u\t\t\t%u\n", + accum_tx->preamble_cnt, + delta_tx->preamble_cnt, max_tx->preamble_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "rx_detected_cnt:", le32_to_cpu(tx->rx_detected_cnt), - accum_tx->rx_detected_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n", + accum_tx->rx_detected_cnt, + delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "bt_prio_defer_cnt:", le32_to_cpu(tx->bt_prio_defer_cnt), - accum_tx->bt_prio_defer_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n", + accum_tx->bt_prio_defer_cnt, + delta_tx->bt_prio_defer_cnt, + max_tx->bt_prio_defer_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "bt_prio_kill_cnt:", le32_to_cpu(tx->bt_prio_kill_cnt), - accum_tx->bt_prio_kill_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "few_bytes_cnt:\t\t\t%u\t\t\t%u\n", + accum_tx->bt_prio_kill_cnt, + delta_tx->bt_prio_kill_cnt, + max_tx->bt_prio_kill_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "few_bytes_cnt:", le32_to_cpu(tx->few_bytes_cnt), - accum_tx->few_bytes_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "cts_timeout:\t\t\t%u\t\t\t%u\n", - le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "ack_timeout:\t\t\t%u\t\t\t%u\n", + accum_tx->few_bytes_cnt, + delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "cts_timeout:", + le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, + delta_tx->cts_timeout, max_tx->cts_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "ack_timeout:", le32_to_cpu(tx->ack_timeout), - accum_tx->ack_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "expected_ack_cnt:\t\t%u\t\t\t%u\n", + accum_tx->ack_timeout, + delta_tx->ack_timeout, max_tx->ack_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "expected_ack_cnt:", le32_to_cpu(tx->expected_ack_cnt), - accum_tx->expected_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "actual_ack_cnt:\t\t\t%u\t\t\t%u\n", + accum_tx->expected_ack_cnt, + delta_tx->expected_ack_cnt, + max_tx->expected_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "actual_ack_cnt:", le32_to_cpu(tx->actual_ack_cnt), - accum_tx->actual_ack_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n", + accum_tx->actual_ack_cnt, + delta_tx->actual_ack_cnt, + max_tx->actual_ack_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "dump_msdu_cnt:", le32_to_cpu(tx->dump_msdu_cnt), - accum_tx->dump_msdu_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "abort_nxt_frame_mismatch:" - "\t%u\t\t\t%u\n", + accum_tx->dump_msdu_cnt, + delta_tx->dump_msdu_cnt, + max_tx->dump_msdu_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "abort_nxt_frame_mismatch:", le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), - accum_tx->burst_abort_next_frame_mismatch_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "abort_missing_nxt_frame:" - "\t%u\t\t\t%u\n", + accum_tx->burst_abort_next_frame_mismatch_cnt, + delta_tx->burst_abort_next_frame_mismatch_cnt, + max_tx->burst_abort_next_frame_mismatch_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "abort_missing_nxt_frame:", le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), - accum_tx->burst_abort_missing_next_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "cts_timeout_collision:\t\t%u\t\t\t%u\n", + accum_tx->burst_abort_missing_next_frame_cnt, + delta_tx->burst_abort_missing_next_frame_cnt, + max_tx->burst_abort_missing_next_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "cts_timeout_collision:", le32_to_cpu(tx->cts_timeout_collision), - accum_tx->cts_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, - "ack_ba_timeout_collision:\t%u\t\t\t%u\n", + accum_tx->cts_timeout_collision, + delta_tx->cts_timeout_collision, + max_tx->cts_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "ack_ba_timeout_collision:", le32_to_cpu(tx->ack_or_ba_timeout_collision), - accum_tx->ack_or_ba_timeout_collision); - pos += scnprintf(buf + pos, bufsz - pos, - "agg ba_timeout:\t\t\t%u\t\t\t%u\n", + accum_tx->ack_or_ba_timeout_collision, + delta_tx->ack_or_ba_timeout_collision, + max_tx->ack_or_ba_timeout_collision); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg ba_timeout:", le32_to_cpu(tx->agg.ba_timeout), - accum_tx->agg.ba_timeout); - pos += scnprintf(buf + pos, bufsz - pos, - "agg ba_resched_frames:\t\t%u\t\t\t%u\n", + accum_tx->agg.ba_timeout, + delta_tx->agg.ba_timeout, + max_tx->agg.ba_timeout); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg ba_resched_frames:", le32_to_cpu(tx->agg.ba_reschedule_frames), - accum_tx->agg.ba_reschedule_frames); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_agg_frame:\t%u\t\t\t%u\n", + accum_tx->agg.ba_reschedule_frames, + delta_tx->agg.ba_reschedule_frames, + max_tx->agg.ba_reschedule_frames); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg scd_query_agg_frame:", le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), - accum_tx->agg.scd_query_agg_frame_cnt); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_no_agg:\t\t%u\t\t\t%u\n", + accum_tx->agg.scd_query_agg_frame_cnt, + delta_tx->agg.scd_query_agg_frame_cnt, + max_tx->agg.scd_query_agg_frame_cnt); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg scd_query_no_agg:", le32_to_cpu(tx->agg.scd_query_no_agg), - accum_tx->agg.scd_query_no_agg); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_agg:\t\t%u\t\t\t%u\n", + accum_tx->agg.scd_query_no_agg, + delta_tx->agg.scd_query_no_agg, + max_tx->agg.scd_query_no_agg); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg scd_query_agg:", le32_to_cpu(tx->agg.scd_query_agg), - accum_tx->agg.scd_query_agg); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_mismatch:\t\t%u\t\t\t%u\n", + accum_tx->agg.scd_query_agg, + delta_tx->agg.scd_query_agg, + max_tx->agg.scd_query_agg); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg scd_query_mismatch:", le32_to_cpu(tx->agg.scd_query_mismatch), - accum_tx->agg.scd_query_mismatch); - pos += scnprintf(buf + pos, bufsz - pos, - "agg frame_not_ready:\t\t%u\t\t\t%u\n", + accum_tx->agg.scd_query_mismatch, + delta_tx->agg.scd_query_mismatch, + max_tx->agg.scd_query_mismatch); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg frame_not_ready:", le32_to_cpu(tx->agg.frame_not_ready), - accum_tx->agg.frame_not_ready); - pos += scnprintf(buf + pos, bufsz - pos, - "agg underrun:\t\t\t%u\t\t\t%u\n", + accum_tx->agg.frame_not_ready, + delta_tx->agg.frame_not_ready, + max_tx->agg.frame_not_ready); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg underrun:", le32_to_cpu(tx->agg.underrun), - accum_tx->agg.underrun); - pos += scnprintf(buf + pos, bufsz - pos, - "agg bt_prio_kill:\t\t%u\t\t\t%u\n", + accum_tx->agg.underrun, + delta_tx->agg.underrun, max_tx->agg.underrun); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg bt_prio_kill:", le32_to_cpu(tx->agg.bt_prio_kill), - accum_tx->agg.bt_prio_kill); - pos += scnprintf(buf + pos, bufsz - pos, - "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n", + accum_tx->agg.bt_prio_kill, + delta_tx->agg.bt_prio_kill, + max_tx->agg.bt_prio_kill); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "agg rx_ba_rsp_cnt:", le32_to_cpu(tx->agg.rx_ba_rsp_cnt), - accum_tx->agg.rx_ba_rsp_cnt); + accum_tx->agg.rx_ba_rsp_cnt, + delta_tx->agg.rx_ba_rsp_cnt, + max_tx->agg.rx_ba_rsp_cnt); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); @@ -1545,11 +1728,12 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; - int bufsz = sizeof(struct statistics_general) * 4 + 250; + int bufsz = sizeof(struct statistics_general) * 8 + 250; ssize_t ret; struct statistics_general *general, *accum_general; - struct statistics_dbg *dbg, *accum_dbg; - struct statistics_div *div, *accum_div; + struct statistics_general *delta_general, *max_general; + struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; + struct statistics_div *div, *accum_div, *delta_div, *max_div; if (!iwl_is_alive(priv)) return -EAGAIN; @@ -1578,52 +1762,72 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, dbg = &priv->statistics.general.dbg; div = &priv->statistics.general.div; accum_general = &priv->accum_statistics.general; + delta_general = &priv->delta_statistics.general; + max_general = &priv->max_delta.general; accum_dbg = &priv->accum_statistics.general.dbg; + delta_dbg = &priv->delta_statistics.general.dbg; + max_dbg = &priv->max_delta.general.dbg; accum_div = &priv->accum_statistics.general.div; + delta_div = &priv->delta_statistics.general.div; + max_div = &priv->max_delta.general.div; pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "\t\t\tcurrent\t\t\taccumulative\n"); - pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, + "Statistics_General:"); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, + "temperature:", le32_to_cpu(general->temperature)); - pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, + "temperature_m:", le32_to_cpu(general->temperature_m)); - pos += scnprintf(buf + pos, bufsz - pos, - "burst_check:\t\t\t%u\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "burst_check:", le32_to_cpu(dbg->burst_check), - accum_dbg->burst_check); - pos += scnprintf(buf + pos, bufsz - pos, - "burst_count:\t\t\t%u\t\t\t%u\n", + accum_dbg->burst_check, + delta_dbg->burst_check, max_dbg->burst_check); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "burst_count:", le32_to_cpu(dbg->burst_count), - accum_dbg->burst_count); - pos += scnprintf(buf + pos, bufsz - pos, - "sleep_time:\t\t\t%u\t\t\t%u\n", + accum_dbg->burst_count, + delta_dbg->burst_count, max_dbg->burst_count); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "sleep_time:", le32_to_cpu(general->sleep_time), - accum_general->sleep_time); - pos += scnprintf(buf + pos, bufsz - pos, - "slots_out:\t\t\t%u\t\t\t%u\n", + accum_general->sleep_time, + delta_general->sleep_time, max_general->sleep_time); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "slots_out:", le32_to_cpu(general->slots_out), - accum_general->slots_out); - pos += scnprintf(buf + pos, bufsz - pos, - "slots_idle:\t\t\t%u\t\t\t%u\n", + accum_general->slots_out, + delta_general->slots_out, max_general->slots_out); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "slots_idle:", le32_to_cpu(general->slots_idle), - accum_general->slots_idle); + accum_general->slots_idle, + delta_general->slots_idle, max_general->slots_idle); pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", le32_to_cpu(general->ttl_timestamp)); - pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n", - le32_to_cpu(div->tx_on_a), accum_div->tx_on_a); - pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n", - le32_to_cpu(div->tx_on_b), accum_div->tx_on_b); - pos += scnprintf(buf + pos, bufsz - pos, - "exec_time:\t\t\t%u\t\t\t%u\n", - le32_to_cpu(div->exec_time), accum_div->exec_time); - pos += scnprintf(buf + pos, bufsz - pos, - "probe_time:\t\t\t%u\t\t\t%u\n", - le32_to_cpu(div->probe_time), accum_div->probe_time); - pos += scnprintf(buf + pos, bufsz - pos, - "rx_enable_counter:\t\t%u\t\t\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "tx_on_a:", + le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, + delta_div->tx_on_a, max_div->tx_on_a); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "tx_on_b:", + le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, + delta_div->tx_on_b, max_div->tx_on_b); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "exec_time:", + le32_to_cpu(div->exec_time), accum_div->exec_time, + delta_div->exec_time, max_div->exec_time); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "probe_time:", + le32_to_cpu(div->probe_time), accum_div->probe_time, + delta_div->probe_time, max_div->probe_time); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "rx_enable_counter:", le32_to_cpu(general->rx_enable_counter), - accum_general->rx_enable_counter); + accum_general->rx_enable_counter, + delta_general->rx_enable_counter, + max_general->rx_enable_counter); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 70f0e79c8e4a..63e45cd3f634 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1162,6 +1162,8 @@ struct iwl_priv { struct iwl_notif_statistics statistics; #ifdef CONFIG_IWLWIFI_DEBUG struct iwl_notif_statistics accum_statistics; + struct iwl_notif_statistics delta_statistics; + struct iwl_notif_statistics max_delta; #endif /* context information */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 10db97327452..5bbe5f1f749c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -564,15 +564,24 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, int i; __le32 *prev_stats; u32 *accum_stats; + u32 *delta, *max_delta; prev_stats = (__le32 *)&priv->statistics; accum_stats = (u32 *)&priv->accum_statistics; + delta = (u32 *)&priv->delta_statistics; + max_delta = (u32 *)&priv->max_delta; for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); - i += sizeof(__le32), stats++, prev_stats++, accum_stats++) - if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) - *accum_stats += (le32_to_cpu(*stats) - + i += sizeof(__le32), stats++, prev_stats++, delta++, + max_delta++, accum_stats++) { + if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { + *delta = (le32_to_cpu(*stats) - le32_to_cpu(*prev_stats)); + *accum_stats += *delta; + if (*delta > *max_delta) + *max_delta = *delta; + } + } /* reset accumulative statistics for "no-counter" type statistics */ priv->accum_statistics.general.temperature = @@ -641,6 +650,10 @@ void iwl_reply_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG memset(&priv->accum_statistics, 0, sizeof(struct iwl_notif_statistics)); + memset(&priv->delta_statistics, 0, + sizeof(struct iwl_notif_statistics)); + memset(&priv->max_delta, 0, + sizeof(struct iwl_notif_statistics)); #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } -- cgit v1.2.3 From 11fc524941248dc717f1af5dfa844eceb7c0217f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:35 -0800 Subject: iwlwifi: add num_of_sos_stats to statistics counter When uCode detects number of beacon missed consecutively above the internal missed beacon threshold (set by uCode), it will reset and re-tune the radio in order to get out of bad PHY state. This "num_of_sos_states" counter monitors number of time uCode encounters this bad condition and has to re-tune the radio. Signed-off-by: Wey-Yi Guy Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 7 ++++++- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 3320cce3d57b..8dc34a3d4f7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3095,7 +3095,12 @@ struct statistics_general { __le32 ttl_timestamp; struct statistics_div div; __le32 rx_enable_counter; - __le32 reserved1; + /* + * num_of_sos_states: + * count the number of times we have to re-tune + * in order to get out of bad PHY status + */ + __le32 num_of_sos_states; __le32 reserved2; __le32 reserved3; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2264cbd95a00..19c7fab47939 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1728,7 +1728,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, struct iwl_priv *priv = file->private_data; int pos = 0; char *buf; - int bufsz = sizeof(struct statistics_general) * 8 + 250; + int bufsz = sizeof(struct statistics_general) * 10 + 300; ssize_t ret; struct statistics_general *general, *accum_general; struct statistics_general *delta_general, *max_general; @@ -1828,6 +1828,12 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, accum_general->rx_enable_counter, delta_general->rx_enable_counter, max_general->rx_enable_counter); + pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, + "num_of_sos_states:", + le32_to_cpu(general->num_of_sos_states), + accum_general->num_of_sos_states, + delta_general->num_of_sos_states, + max_general->num_of_sos_states); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); return ret; -- cgit v1.2.3 From 937c397eb633b804d9a806d08c395ecfc42b1fec Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:36 -0800 Subject: iwlwifi: correct return code for log_event When dumping event log in debugfs, iwl_dump_nic_event_log() should return the correct error code instead of let the calling function makes it own assumption. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c78063312ea9..eaa309d8bee1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1965,7 +1965,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, IWL_ERR(priv, "Invalid event log pointer 0x%08X for %s uCode\n", base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); - return pos; + return -EINVAL; } /* event log header */ @@ -2013,7 +2013,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, bufsz = size * 48; *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) - return pos; + return -ENOMEM; } if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { /* diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 19c7fab47939..a7ca06d21d59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -429,8 +429,9 @@ static ssize_t iwl_dbgfs_log_event_read(struct file *file, int pos = 0; ssize_t ret = -ENOMEM; - pos = priv->cfg->ops->lib->dump_nic_event_log(priv, true, &buf, true); - if (pos && buf) { + ret = pos = priv->cfg->ops->lib->dump_nic_event_log( + priv, true, &buf, true); + if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); kfree(buf); } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 10b0aa8024c4..8bbcc5487aa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1644,7 +1644,7 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, base = le32_to_cpu(priv->card_alive.log_event_table_ptr); if (!iwl3945_hw_valid_rtc_data_addr(base)) { IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return pos; + return -EINVAL; } /* event log header */ @@ -1693,7 +1693,7 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, bufsz = size * 48; *buf = kmalloc(bufsz, GFP_KERNEL); if (!*buf) - return pos; + return -ENOMEM; } if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { /* if uCode has wrapped back to top of log, -- cgit v1.2.3 From 2be76703a3afb281155894ac52d34f7f5d736633 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:37 -0800 Subject: iwlwifi: set interrupt coalescing timer range and default For interrupt coalescing timer, the CSR_INT_COALESCING is an 8 bit register in 32-usec unit, the range can go from 0x00 - 0xFF. set the range and default timeout value for both calibration mode and operation mode. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 15 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-rx.c | 4 ++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5b56307a3812..29eb7b4dc7d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -257,8 +257,8 @@ int iwl_hw_nic_init(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); priv->cfg->ops->lib->apm_ops.init(priv); - /* Set interrupt coalescing timer to 512 usecs */ - iwl_write8(priv, CSR_INT_COALESCING, 512 / 32); + /* Set interrupt coalescing calibration timer to default (512 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 63e45cd3f634..251eb737860c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1011,6 +1011,21 @@ struct iwl_event_log { int wraps_more_count; }; +/* + * host interrupt timeout value + * used with setting interrupt coalescing timer + * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit + * + * default interrupt coalescing timer is 64 x 32 = 2048 usecs + * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs + */ +#define IWL_HOST_INT_TIMEOUT_MAX (0xFF) +#define IWL_HOST_INT_TIMEOUT_DEF (0x40) +#define IWL_HOST_INT_TIMEOUT_MIN (0x0) +#define IWL_HOST_INT_CALIB_TIMEOUT_MAX (0xFF) +#define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) +#define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) + struct iwl_priv { /* ieee device used by generic ieee processing code */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 5bbe5f1f749c..07bdba93c179 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -473,8 +473,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ - iwl_write8(priv, CSR_INT_COALESCING, 0x40); + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); return 0; } -- cgit v1.2.3 From 2a11df6ee58d1b1fc7e5ecd7593a04d7555dc522 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:38 -0800 Subject: iwlwifi: software w/a for h/w bug cause Rx bit get clear This is a w/a for a hardware bug. the h/w bug may cause the Rx bit (bit 15 before shifting it to 31) to clear when using interrupt coalescing. This does not mean frames are lost - their processing is just delayed until next interrupt arrives. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 29eb7b4dc7d4..9d6c144d0701 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1803,6 +1803,16 @@ irqreturn_t iwl_isr_ict(int irq, void *data) if (val == 0xffffffff) val = 0; + /* + * this is a w/a for a h/w bug. the h/w bug may cause the Rx bit + * (bit 15 before shifting it to 31) to clear when using interrupt + * coalescing. fortunately, bits 18 and 19 stay set when this happens + * so we use them to decide on the real state of the Rx bit. + * In order words, bit 15 is set if bit 18 or bit 19 are set. + */ + if (val & 0xC0000) + val |= 0x8000; + inta = (0xff & val) | ((0xff00 & val) << 16); IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", inta, inta_mask, val); -- cgit v1.2.3 From 1b3eb8236ad9369ae519216b61a3d22806370115 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:39 -0800 Subject: iwlwifi: display flowhandler register when sw error or on-demand Flowhandler handle the communication between driver and uCode, when any uCode error happen, we also like to know what is the status of the flowhandler; it can help to debug flowhandler related problem. Also adding debugfs file to dump current value of flowhandler registers. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 65 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 24 +++++++++++ drivers/net/wireless/iwlwifi/iwl-fh.h | 19 +++++++++ 8 files changed, 114 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0db1fda94a65..506429f00c12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -106,6 +106,7 @@ static struct iwl_lib_ops iwl1000_lib = { .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c6120f0b8f98..500c410f5242 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1467,6 +1467,7 @@ struct iwl_lib_ops iwl5000_lib = { .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, .load_ucode = iwl5000_load_ucode, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a5a0ed4817a4..c5f244f3d747 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -216,6 +216,7 @@ static struct iwl_lib_ops iwl6000_lib = { .dump_nic_event_log = iwl_dump_nic_event_log, .dump_nic_error_log = iwl_dump_nic_error_log, .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, .init_alive_start = iwl5000_init_alive_start, .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9d6c144d0701..28d97f5f8ccf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1353,6 +1353,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv) priv->cfg->ops->lib->dump_nic_error_log(priv); if (priv->cfg->ops->lib->dump_csr) priv->cfg->ops->lib->dump_csr(priv); + if (priv->cfg->ops->lib->dump_fh) + priv->cfg->ops->lib->dump_fh(priv, NULL, false); priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) @@ -3278,6 +3280,69 @@ void iwl_dump_csr(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_dump_csr); +const static char *get_fh_string(int cmd) +{ + switch (cmd) { + IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); + IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); + IWL_CMD(FH_RSCSR_CHNL0_WPTR); + IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); + IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); + IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); + IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); + IWL_CMD(FH_TSSR_TX_STATUS_REG); + IWL_CMD(FH_TSSR_TX_ERROR_REG); + default: + return "UNKNOWN"; + + } +} + +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) +{ + int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif + u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, + FH_RSCSR_CHNL0_WPTR, + FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_MEM_RSSR_SHARED_CTRL_REG, + FH_MEM_RSSR_RX_STATUS_REG, + FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return pos; + } +#endif + IWL_ERR(priv, "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + IWL_ERR(priv, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return 0; +} +EXPORT_SYMBOL(iwl_dump_fh); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8deb83bfe182..666b0e0728b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -171,6 +171,7 @@ struct iwl_lib_ops { bool full_log, char **buf, bool display); void (*dump_nic_error_log)(struct iwl_priv *priv); void (*dump_csr)(struct iwl_priv *priv); + int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display); int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); /* power management */ struct iwl_apm_ops apm_ops; @@ -582,6 +583,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv); int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv); #else diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 58e0462cafa3..1d1e655317a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -111,6 +111,7 @@ struct iwl_debugfs { struct dentry *file_clear_traffic_statistics; struct dentry *file_csr; struct dentry *file_ucode_tracing; + struct dentry *file_fh_reg; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a7ca06d21d59..a3d461ff4a9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2151,6 +2151,27 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + char *buf; + int pos = 0; + ssize_t ret = -EFAULT; + + if (priv->cfg->ops->lib->dump_fh) { + ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true); + if (buf) { + ret = simple_read_from_buffer(user_buf, + count, ppos, buf, pos); + kfree(buf); + } + } + + return ret; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -2167,6 +2188,7 @@ DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); +DEBUGFS_READ_FILE_OPS(fh_reg); /* * Create the debugfs files and directories @@ -2218,6 +2240,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); @@ -2277,6 +2300,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_clear_traffic_statistics); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_ucode_rx_stats); diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 65fa8a69fd5a..1342cf40297a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -379,6 +379,25 @@ #define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) +/** + * Bit fields for TSSR(Tx Shared Status & Control) error status register: + * 31: Indicates an address error when accessed to internal memory + * uCode/driver must write "1" in order to clear this flag + * 30: Indicates that Host did not send the expected number of dwords to FH + * uCode/driver must write "1" in order to clear this flag + * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA + * command was received from the scheduler while the TRB was already full + * with previous command + * uCode/driver must write "1" in order to clear this flag + * 7-0: Each status bit indicates a channel's TxCredit error. When an error + * bit is set, it indicates that the FH has received a full indication + * from the RTC TxFIFO and the current value of the TxCredit counter was + * not equal to zero. This mean that the credit mechanism was not + * synchronized to the TxFIFO status + * uCode/driver must write "1" in order to clear this flag + */ +#define FH_TSSR_TX_ERROR_REG (FH_TSSR_LOWER_BOUND + 0x018) + #define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) #define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) -- cgit v1.2.3 From 4e9772b0a94c7d3a5f7062ba94afdbb9e692275d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:43:40 -0800 Subject: iwlwifi: remove extra statistics request from debugfs When reading current ucode statistics information from debugfs, in current implementation, it will always send a new "statistics request" to uCode. In normal operation, uCode should report the statistics per beacon interval. Remove this extra request to reduce the additional command exchanges between driver and uCode. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 41 ------------------------------ 1 file changed, 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a3d461ff4a9c..38e2f9f9f1dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1109,16 +1109,6 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, if (!iwl_is_alive(priv)) return -EAGAIN; - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { IWL_ERR(priv, "Can not allocate Buffer\n"); @@ -1552,16 +1542,6 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, if (!iwl_is_alive(priv)) return -EAGAIN; - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { IWL_ERR(priv, "Can not allocate Buffer\n"); @@ -1739,16 +1719,6 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, if (!iwl_is_alive(priv)) return -EAGAIN; - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } buf = kzalloc(bufsz, GFP_KERNEL); if (!buf) { IWL_ERR(priv, "Can not allocate Buffer\n"); @@ -1986,23 +1956,12 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, struct iwl_priv *priv = file->private_data; char buf[128]; int pos = 0; - ssize_t ret; const size_t bufsz = sizeof(buf); struct statistics_tx *tx; if (!iwl_is_alive(priv)) pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); else { - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, CMD_SYNC, false); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, "Error sending statistics request: %zd\n", - ret); - return -EAGAIN; - } tx = &priv->statistics.tx; if (tx->tx_power.ant_a || tx->tx_power.ant_b || -- cgit v1.2.3 From 1f44780827c6bbbcd1f12d5c6b6ce84f49a96bc0 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 15 Jan 2010 13:43:41 -0800 Subject: iwlwifi: update copyright year to 2010 Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-calib.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-calib.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-csr.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-spectrum.c | 2 +- drivers/net/wireless/iwlwifi/iwl-spectrum.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 47 files changed, 63 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 506429f00c12..d5c6edbbc95a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h index 08ce259a0e60..042f6bc0df13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 6fd10d443ba3..3a876a8ece38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index a871d09d598f..abe2b739c4dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 5a1033ca7aaa..ce990adc51e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index d4b49883b30e..47909f94271e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 28ffe4c826d8..6472910b72d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3ec2fe370b58..db4137d9a3ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index c606366b582c..67ef562e8db1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6a004abb5973..8159a0fcf5a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index bc056e9ab85f..714e032f6217 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 500c410f5242..aab6cf23c2bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h index 90185777d98b..ddba39999997 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c5f244f3d747..4dab7f12e725 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c index 3bccba20f6da..1a24946bc203 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h index ab55f92a161d..a594e4fdc6b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index b93e49158196..6aebcedaca8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index affc0c5a2f2c..2f0094a43261 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index eaa309d8bee1..8db86239bd6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index dc61906290e8..845831ac053e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index b6cef989a796..2b7b1df83ba0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8dc34a3d4f7e..cee5fb2187c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 28d97f5f8ccf..bb3ed25f8438 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 666b0e0728b3..785331a98aa5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,7 +71,7 @@ struct iwl_cmd; #define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" #define DRV_AUTHOR "" #define IWL_PCI_DEVICE(dev, subdev, cfg) \ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 1ec8cb4d5eae..1e00720bf8b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 1d1e655317a2..0facaca9b40b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 38e2f9f9f1dc..af00ad2afa14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 251eb737860c..c6310b0b2f12 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 4a30969689ff..fd37152abae3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 0cd9c02ee044..4e1ba824dc50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 1342cf40297a..113c3669b9ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 87d684efe110..86783c27d97c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index bd0b12efb5c7..45af5bbc1c56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index e552d4c4bdbe..c719baf2585a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 46c7a95b88f0..a6f9c918aabc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index f47f053f02ea..49a70baa3fb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 8ccc0bb1d9ed..8599444bef01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 310c32e8f698..5db91c10dcc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 6d95832db06d..d2d2a9174900 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 07bdba93c179..eb45f8be0746 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fa1c89ba6459..ceb91f969e45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c index 1ea5cd345fe8..da166d1d1b13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index a77c1e619062..af6babee2891 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ieee80211 subsystem header files. * diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index cde09a890b73..8afa39b4b488 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 8d052de2d405..8c6850d03e47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 87ce2bd292c7..d365d13e3291 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8bbcc5487aa0..c46f988d0a5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -77,7 +77,7 @@ #endif #define DRV_VERSION IWLWIFI_VERSION VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" #define DRV_AUTHOR "" MODULE_DESCRIPTION(DRV_DESCRIPTION); -- cgit v1.2.3 From 8e9310c1790566ea2de2e8b6e1c04bacbbee648c Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 16 Jan 2010 14:36:53 -0500 Subject: mac80211: pid: replace open-coded msecs_to_jiffies Code directly scaling by HZ and rounding can be more efficiently and clearly performed with msecs_to_jiffies. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_algo.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 29bc4c516238..2652a374974e 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -157,9 +157,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, /* In case nothing happened during the previous control interval, turn * the sharpening factor on. */ - period = (HZ * pinfo->sampling_period + 500) / 1000; - if (!period) - period = 1; + period = msecs_to_jiffies(pinfo->sampling_period); if (jiffies - spinfo->last_sample > 2 * period) spinfo->sharp_cnt = pinfo->sharpen_duration; @@ -252,9 +250,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba } /* Update PID controller state. */ - period = (HZ * pinfo->sampling_period + 500) / 1000; - if (!period) - period = 1; + period = msecs_to_jiffies(pinfo->sampling_period); if (time_after(jiffies, spinfo->last_sample + period)) rate_control_pid_sample(pinfo, sband, sta, spinfo); } -- cgit v1.2.3 From edc6ccb7b992bd9ea5db4555c8f0bf74c656f964 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 01:47:55 +0100 Subject: mac80211: move and rename misc tx handler This TX handler is used only for assigning the station pointer in the control information, so give it a better name. Also move it before rate control. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index daf81048c1f7..a74ab797fed9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -559,6 +559,17 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) return TX_CONTINUE; } +static ieee80211_tx_result debug_noinline +ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + + if (tx->sta) + info->control.sta = &tx->sta->sta; + + return TX_CONTINUE; +} + static ieee80211_tx_result debug_noinline ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) { @@ -733,17 +744,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) return TX_CONTINUE; } -static ieee80211_tx_result debug_noinline -ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - - if (tx->sta) - info->control.sta = &tx->sta->sta; - - return TX_CONTINUE; -} - static ieee80211_tx_result debug_noinline ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) { @@ -1292,10 +1292,10 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) CALL_TXH(ieee80211_tx_h_check_assoc); CALL_TXH(ieee80211_tx_h_ps_buf); CALL_TXH(ieee80211_tx_h_select_key); + CALL_TXH(ieee80211_tx_h_sta); CALL_TXH(ieee80211_tx_h_michael_mic_add); if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) CALL_TXH(ieee80211_tx_h_rate_ctrl); - CALL_TXH(ieee80211_tx_h_misc); CALL_TXH(ieee80211_tx_h_sequence); CALL_TXH(ieee80211_tx_h_fragment); /* handlers after fragment must be aware of tx info fragmentation! */ -- cgit v1.2.3 From 697e6a0fb0c8783695d4b4a5d7131476b296d623 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 01:47:56 +0100 Subject: mac80211: clear TX control on filtered frames When an skb survived a round-trip through the driver and needs to be re-used, its control information is definitely not valid any more, the driver will have overwritten it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/status.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 0ebcdda24200..9e171b178276 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -69,6 +69,14 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, */ goto drop; + /* + * This skb 'survived' a round-trip through the driver, and + * hopefully the driver didn't mangle it too badly. However, + * we can definitely not rely on the the control information + * being correct. Clear it so we don't get junk there. + */ + memset(&info->control, 0, sizeof(info->control)); + sta->tx_filtered_count++; /* -- cgit v1.2.3 From a6bae9e7ab19876a157c91019852395539e4f20e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 01:47:57 +0100 Subject: mac80211: remove useless setting of IEEE80211_TX_INTFL_DONT_ENCRYPT There's no value in setting a flag that will never be checked after this point, this seems to be legacy code -- I think previously the flag was used to check whether to encrypt the frame or not. Now, however, the flag need not be set, and setting it actually interferes if the frame will be processed again later. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a74ab797fed9..9afbee0d53c0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -553,9 +553,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) } } - if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) - info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - return TX_CONTINUE; } -- cgit v1.2.3 From 813d76694043d00b59475baa1fbfaf54a2eb7fad Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 01:47:58 +0100 Subject: mac80211: move control.hw_key assignment When mac80211 asks a driver to encrypt a frame, it must assign the control.hw_key pointer for it to know which key to use etc. Currently, mac80211 does this whenever it would software-encrypt a frame. Change the logic of this code to assign the hw_key pointer when selecting the key, and later check it when deciding whether to encrypt the frame or let it be encrypted by the hardware. This allows us to later simply skip the encryption function since it no longer modifies the TX control. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tkip.c | 11 ++++++----- net/mac80211/tx.c | 9 +++++++++ net/mac80211/wep.c | 18 ++++++++--------- net/mac80211/wpa.c | 57 +++++++++++++++++++++-------------------------------- 4 files changed, 46 insertions(+), 49 deletions(-) diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index b73454a507f9..14fe49332c02 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -195,11 +195,13 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, } EXPORT_SYMBOL(ieee80211_get_tkip_key); -/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the +/* + * Encrypt packet payload with TKIP using @key. @pos is a pointer to the * beginning of the buffer containing payload. This payload must include - * headroom of eight octets for IV and Ext. IV and taildroom of four octets - * for ICV. @payload_len is the length of payload (_not_ including extra - * headroom and tailroom). @ta is the transmitter addresses. */ + * the IV/Ext.IV and space for (taildroom) four octets for ICV. + * @payload_len is the length of payload (_not_ including IV/ICV length). + * @ta is the transmitter addresses. + */ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, struct ieee80211_key *key, u8 *pos, size_t payload_len, u8 *ta) @@ -214,7 +216,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key); - pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9afbee0d53c0..e3d8ff533ee6 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -529,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) tx->key = NULL; if (tx->key) { + bool skip_hw = false; + tx->key->tx_rx_count++; /* TODO: add threshold stuff again */ @@ -545,12 +547,19 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) !ieee80211_use_mfp(hdr->frame_control, tx->sta, tx->skb)) tx->key = NULL; + skip_hw = (tx->key->conf.flags & + IEEE80211_KEY_FLAG_SW_MGMT) && + ieee80211_is_mgmt(hdr->frame_control); break; case ALG_AES_CMAC: if (!ieee80211_is_mgmt(hdr->frame_control)) tx->key = NULL; break; } + + if (!skip_hw && + tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + info->control.hw_key = &tx->key->conf; } return TX_CONTINUE; diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 247123fe1a7a..0a4c641c9605 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -305,20 +305,20 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { + if (!info->control.hw_key) { if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, tx->key->conf.keylen, tx->key->conf.keyidx)) return -1; - } else { - info->control.hw_key = &tx->key->conf; - if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) { - if (!ieee80211_wep_add_iv(tx->local, skb, - tx->key->conf.keylen, - tx->key->conf.keyidx)) - return -1; - } } + + if (info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) { + if (!ieee80211_wep_add_iv(tx->local, skb, + tx->key->conf.keylen, + tx->key->conf.keyidx)) + return -1; + } + return 0; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 5332014cb229..f4971cd45c64 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) unsigned int hdrlen; struct ieee80211_hdr *hdr; struct sk_buff *skb = tx->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int authenticator; - int wpa_test = 0; int tail; hdr = (struct ieee80211_hdr *)skb->data; @@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) data = skb->data + hdrlen; data_len = skb->len - hdrlen; - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && + if (info->control.hw_key && !(tx->flags & IEEE80211_TX_FRAGMENTED) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && - !wpa_test) { - /* hwaccel - with no need for preallocated room for MMIC */ + !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { + /* hwaccel - with no need for SW-generated MMIC */ return TX_CONTINUE; } tail = MICHAEL_MIC_LEN; - if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) + if (!info->control.hw_key) tail += TKIP_ICV_LEN; if (WARN_ON(skb_tailroom(skb) < tail || @@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) int len, tail; u8 *pos; - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { - /* hwaccel - with no need for preallocated room for IV/ICV */ - info->control.hw_key = &tx->key->conf; + if (info->control.hw_key && + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { + /* hwaccel - with no need for software-generated IV */ return 0; } hdrlen = ieee80211_hdrlen(hdr->frame_control); len = skb->len - hdrlen; - if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + if (info->control.hw_key) tail = 0; else tail = TKIP_ICV_LEN; @@ -175,13 +173,11 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) if (key->u.tkip.tx.iv16 == 0) key->u.tkip.tx.iv32++; - if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { - /* hwaccel - with preallocated room for IV */ - ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); + pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16); - info->control.hw_key = &tx->key->conf; + /* hwaccel - with software IV */ + if (info->control.hw_key) return 0; - } /* Add room for ICV */ skb_put(skb, TKIP_ICV_LEN); @@ -363,24 +359,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) int hdrlen, len, tail; u8 *pos, *pn; int i; - bool skip_hw; - - skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) && - ieee80211_is_mgmt(hdr->frame_control); - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) && - !skip_hw) { - /* hwaccel - with no need for preallocated room for CCMP - * header or MIC fields */ - info->control.hw_key = &tx->key->conf; + if (info->control.hw_key && + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { + /* + * hwaccel has no need for preallocated room for CCMP + * header or MIC fields + */ return 0; } hdrlen = ieee80211_hdrlen(hdr->frame_control); len = skb->len - hdrlen; - if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + if (info->control.hw_key) tail = 0; else tail = CCMP_MIC_LEN; @@ -405,11 +397,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ccmp_pn2hdr(pos, pn, key->conf.keyidx); - if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) { - /* hwaccel - with preallocated room for CCMP header */ - info->control.hw_key = &tx->key->conf; + /* hwaccel - with software CCMP header */ + if (info->control.hw_key) return 0; - } pos += CCMP_HDR_LEN; ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); @@ -525,11 +515,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx) u8 *pn, aad[20]; int i; - if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { - /* hwaccel */ - info->control.hw_key = &tx->key->conf; + if (info->control.hw_key) return 0; - } if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) return TX_DROP; -- cgit v1.2.3 From c6fcf6bcfc3cfc1c00cc7fd9610cfa2b1a18041f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 01:47:59 +0100 Subject: mac80211: re-enable re-transmission of filtered frames In an earlier commit, mac80211: disable software retry for now Pavel Roskin reported a problem that seems to be due to software retry of already transmitted frames. It turns out that we've never done that correctly, but due to some recent changes it now crashes in the TX code. I've added a comment in the patch that explains the problem better and also points to possible solutions -- which I can't implement right now. I disabled software retry of failed/filtered frames because it was broken. With the work of the previous patches, it now becomes fairly easy to re-enable it by adding a flag indicating that the frame shouldn't be modified, but still running it through the transmit handlers to populate the control information. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 4 ++++ net/mac80211/status.c | 32 +++++--------------------------- net/mac80211/tx.c | 7 ++++++- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index c90047de4428..f03f97b627fe 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -271,6 +271,9 @@ struct ieee80211_bss_conf { * transmit function after the current frame, this can be used * by drivers to kick the DMA queue only if unset or when the * queue gets full. + * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted + * after TX status because the destination was asleep, it must not + * be modified again (no seqno assignment, crypto, etc.) */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -291,6 +294,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17), IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), + IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), }; /** diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 9e171b178276..800b6777e0ed 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -44,38 +44,17 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - /* - * XXX: This is temporary! - * - * The problem here is that when we get here, the driver will - * quite likely have pretty much overwritten info->control by - * using info->driver_data or info->rate_driver_data. Thus, - * when passing out the frame to the driver again, we would be - * passing completely bogus data since the driver would then - * expect a properly filled info->control. In mac80211 itself - * the same problem occurs, since we need info->control.vif - * internally. - * - * To fix this, we should send the frame through TX processing - * again. However, it's not that simple, since the frame will - * have been software-encrypted (if applicable) already, and - * encrypting it again doesn't do much good. So to properly do - * that, we not only have to skip the actual 'raw' encryption - * (key selection etc. still has to be done!) but also the - * sequence number assignment since that impacts the crypto - * encapsulation, of course. - * - * Hence, for now, fix the bug by just dropping the frame. - */ - goto drop; - /* * This skb 'survived' a round-trip through the driver, and * hopefully the driver didn't mangle it too badly. However, * we can definitely not rely on the the control information - * being correct. Clear it so we don't get junk there. + * being correct. Clear it so we don't get junk there, and + * indicate that it needs new processing, but must not be + * modified/encrypted again. */ memset(&info->control, 0, sizeof(info->control)); + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | + IEEE80211_TX_INTFL_RETRANSMISSION; sta->tx_filtered_count++; @@ -130,7 +109,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, return; } - drop: #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (net_ratelimit()) printk(KERN_DEBUG "%s: dropped TX filtered frame, " diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e3d8ff533ee6..da557b0d0114 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1285,6 +1285,7 @@ static int __ieee80211_tx(struct ieee80211_local *local, static int invoke_tx_handlers(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ieee80211_tx_result res = TX_DROP; #define CALL_TXH(txh) \ @@ -1299,9 +1300,13 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) CALL_TXH(ieee80211_tx_h_ps_buf); CALL_TXH(ieee80211_tx_h_select_key); CALL_TXH(ieee80211_tx_h_sta); - CALL_TXH(ieee80211_tx_h_michael_mic_add); if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) CALL_TXH(ieee80211_tx_h_rate_ctrl); + + if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) + goto txh_done; + + CALL_TXH(ieee80211_tx_h_michael_mic_add); CALL_TXH(ieee80211_tx_h_sequence); CALL_TXH(ieee80211_tx_h_fragment); /* handlers after fragment must be aware of tx info fragmentation! */ -- cgit v1.2.3 From 026816fce48390807859508cd5172e9c79901ef7 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:03:28 +0100 Subject: b43: N-PHY: implement RX PHY cleanup and setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 82 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 4a817e3da163..a1dd381c6c6e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -480,6 +480,88 @@ static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ +static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core) +{ + u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; + + b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]); + if (core == 0) { + b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); + } else { + b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); + } + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]); + b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]); + b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]); + b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]); + b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); + b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ +static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) +{ + u8 rxval, txval; + u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; + + regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA); + if (core == 0) { + regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); + } else { + regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + } + regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); + regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); + regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); + regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); + regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1); + regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); + regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); + regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); + + b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); + b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); + + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, (u16)~B43_NPHY_RFSEQCA_RXDIS, + ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, + ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT)); + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, + (core << B43_NPHY_RFSEQCA_RXEN_SHIFT)); + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS, + (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT)); + + if (core == 0) { + b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007); + } else { + b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007); + b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007); + } + + /* TODO: Call N PHY RF Ctrl Intc Override with 2, 0, 3 as arguments */ + /* TODO: Call N PHY RF Intc Override with 8, 0, 3, 0 as arguments */ + /* TODO: Call N PHY RF Seq with 0 as argument */ + + if (core == 0) { + rxval = 1; + txval = 8; + } else { + rxval = 4; + txval = 2; + } + + /* TODO: Call N PHY RF Ctrl Intc Override with 1, rxval, (core + 1) */ + /* TODO: Call N PHY RF Ctrl Intc Override with 1, txval, (2 - core) */ +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) { -- cgit v1.2.3 From e53de67449bbcaf5551f54e506a4dff62fc6a49c Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:03:32 +0100 Subject: b43: N-PHY: implement TX PHY cleanup and setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 112 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index a1dd381c6c6e..fd93b2a6b494 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1505,6 +1505,114 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) return target; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ +static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) +{ + u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; + + if (dev->phy.rev >= 3) { + b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]); + b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]); + b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]); + /* TODO: Write an N PHY Table with ID 8, length 1, offset 3, + width 16, and data from regs[5] */ + /* TODO: Write an N PHY Table with ID 8, length 1, offset 19, + width 16, and data from regs[6] */ + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]); + b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); + b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); + b43_nphy_reset_cca(dev); + } else { + b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]); + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); + /* TODO: Write an N PHY Table with ID 8, length 1, offset 2, + width 16, and data from regs[3] */ + /* TODO: Write an N PHY Table with ID 8, length 1, offset 18, + width 16, and data from regs[4] */ + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]); + } +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ +static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) +{ + u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; + u16 tmp; + + regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); + regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); + if (dev->phy.rev >= 3) { + b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); + + tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); + regs[2] = tmp; + b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600); + + tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + regs[3] = tmp; + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); + + regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); + b43_phy_mask(dev, B43_NPHY_BBCFG, ~B43_NPHY_BBCFG_RSTRX); + + /* TODO: Read an N PHY Table with ID 8, length 1, offset 3, + width 16, and data pointing to tmp */ + regs[5] = tmp; + + /* TODO: Write an N PHY Table with ID 8, length 1, offset 3, + width 16, and data 0 */ + /* TODO: Read an N PHY Table with ID 8, length 1, offset 19, + width 16, and data pointing to tmp */ + regs[6] = tmp; + + /* TODO: Write an N PHY Table with ID 8, length 1, offset 19, + width 16, and data 0 */ + regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); + regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); + + /* TODO: Call N PHY RF Ctrl Intc Override with 2, 1, 3 */ + /* TODO: Call N PHY RF Ctrl Intc Override with 1, 2, 1 */ + /* TODO: Call N PHY RF Ctrl Intc Override with 1, 8, 2 */ + + regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); + regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); + b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); + b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); + } else { + b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); + tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); + regs[2] = tmp; + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000); + /* TODO: Read an N PHY Table with ID 8, length 1, offset 2, + width 16, and data pointing to tmp */ + regs[3] = tmp; + tmp |= 0x2000; + /* TODO: Write an N PHY Table with ID 8, length 1, offset 2, + width 16, and data pointer tmp */ + /* TODO: Read an N PHY Table with ID 8, length 1, offset 18, + width 16, and data pointer tmp */ + regs[4] = tmp; + tmp |= 0x2000; + /* TODO: Write an N PHY Table with ID 8, length 1, offset 18, + width 16, and data pointer tmp */ + regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); + regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) + tmp = 0x0180; + else + tmp = 0x0120; + b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); + b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ static void b43_nphy_restore_cal(struct b43_wldev *dev) { @@ -1617,7 +1725,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, width 16, and data pointer gain */ b43_nphy_tx_cal_radio_setup(dev); - /* TODO: Call N PHY TX Cal PHY Setup */ + b43_nphy_tx_cal_phy_setup(dev); phy6or5x = dev->phy.rev >= 6 || (dev->phy.rev == 5 && nphy->ipa2g_on && @@ -1788,7 +1896,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); } - /* TODO: Call N PHY TX Cal PHY Cleanup */ + b43_nphy_tx_cal_phy_cleanup(dev); /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, width 16, and data from save */ -- cgit v1.2.3 From ad9716e8e8bc39664a0d41ec94f9bffbf748b45b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:03:40 +0100 Subject: b43: N-PHY: implement MIMO config update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 16 +++++++++++++++- drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index fd93b2a6b494..1996843eac11 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -424,6 +424,20 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev) /* TODO: N PHY Force RF Seq with argument 2 */ } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ +static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble) +{ + u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG); + + mimocfg |= B43_NPHY_MIMOCFG_AUTO; + if (preamble == 1) + mimocfg |= B43_NPHY_MIMOCFG_GFMIX; + else + mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX; + + b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, u16 samps, u8 time, bool wait) @@ -2180,7 +2194,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); - /* TODO MIMO-Config */ + b43_nphy_update_mimo_config(dev, nphy->preamble_override); /* TODO Update TX/RX chain */ if (phy->rev < 2) { diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 4572866756fc..ae00e3f2d613 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -973,6 +973,7 @@ struct b43_phy_n { bool hang_avoid; bool mute; u16 papd_epsilon_offset[2]; + s32 preamble_override; u8 mphase_cal_phase_id; u16 mphase_txcal_cmdidx; -- cgit v1.2.3 From 53ae8e8c92b2715f27c95e8e7169bca9a8909856 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:03:48 +0100 Subject: b43: N-PHY: implement stopping playback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 34 +++++++++++++++++++++++++++++++--- drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1996843eac11..229f2d0364f2 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -749,6 +749,34 @@ static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ +static void b43_nphy_stop_playback(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u16 tmp; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); + if (tmp & 0x1) + b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); + else if (tmp & 0x2) + b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, (u16)~0x8000); + + b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); + + if (nphy->bb_mult_save & 0x80000000) { + tmp = nphy->bb_mult_save & 0xFFFF; + /* TODO: Write an N PHY Table with ID 15, length 1, offset 87, + width 16 and data from tmp */ + nphy->bb_mult_save = 0; + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) { @@ -1906,7 +1934,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, nphy->mphase_txcal_bestcoeffs */ } - /* TODO: Call N PHY Stop Playback */ + b43_nphy_stop_playback(dev); b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); } @@ -2053,7 +2081,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], 3, 0 as arguments */ /* TODO: Call N PHY Force RF Seq with 2 as argument */ - /* TODO: Call N PHT Stop Playback */ + b43_nphy_stop_playback(dev); if (playtone) { /* TODO: Call N PHY TX Tone with 4000, @@ -2080,7 +2108,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, } else { b43_nphy_calc_rx_iq_comp(dev, 1 << i); } - /* TODO: Call N PHY Stop Playback */ + b43_nphy_stop_playback(dev); } if (ret != 0) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index ae00e3f2d613..d6c92a81d3c0 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -974,6 +974,7 @@ struct b43_phy_n { bool mute; u16 papd_epsilon_offset[2]; s32 preamble_override; + u32 bb_mult_save; u8 mphase_cal_phase_id; u16 mphase_txcal_cmdidx; -- cgit v1.2.3 From 4f4ab6cd1486fcb0ab8d689d625ac7691198f36b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:03:55 +0100 Subject: b43: N-PHY: implement chain selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 30 +++++++++++++++++++++++++++++- drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 229f2d0364f2..90a49cfaa965 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -438,6 +438,34 @@ static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble) b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ +static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + bool override = false; + u16 chain = 0x33; + + if (nphy->txrx_chain == 0) { + chain = 0x11; + override = true; + } else if (nphy->txrx_chain == 1) { + chain = 0x22; + override = true; + } + + b43_phy_maskset(dev, B43_NPHY_RFSEQCA, + ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), + chain); + + if (override) + b43_phy_set(dev, B43_NPHY_RFSEQMODE, + B43_NPHY_RFSEQMODE_CAOVER); + else + b43_phy_mask(dev, B43_NPHY_RFSEQMODE, + ~B43_NPHY_RFSEQMODE_CAOVER); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, u16 samps, u8 time, bool wait) @@ -2223,7 +2251,7 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); b43_nphy_update_mimo_config(dev, nphy->preamble_override); - /* TODO Update TX/RX chain */ + b43_nphy_update_txrx_chain(dev); if (phy->rev < 2) { b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index d6c92a81d3c0..f5a27661f659 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -987,6 +987,7 @@ struct b43_phy_n { bool txiqlocal_coeffsvalid; struct b43_phy_n_txpwrindex txpwrindex[2]; + u8 txrx_chain; u16 tx_rx_cal_phy_saveregs[11]; u16 tx_rx_cal_radio_saveregs[22]; -- cgit v1.2.3 From 67c0d6e2d1abb9cbff9235143a8faaef89119628 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:04:02 +0100 Subject: b43: N-PHY: move RF sequence declarations top, add missing calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 90a49cfaa965..99024b02bdbd 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -55,6 +55,18 @@ struct nphy_iq_est { u32 q1_pwr; }; +enum b43_nphy_rf_sequence { + B43_RFSEQ_RX2TX, + B43_RFSEQ_TX2RX, + B43_RFSEQ_RESET2RX, + B43_RFSEQ_UPDATE_GAINH, + B43_RFSEQ_UPDATE_GAINL, + B43_RFSEQ_UPDATE_GAINU, +}; + +static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, + enum b43_nphy_rf_sequence seq); + void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO } @@ -421,7 +433,7 @@ static void b43_nphy_reset_cca(struct b43_wldev *dev) udelay(1); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); b43_nphy_bmac_clock_fgc(dev, 0); - /* TODO: N PHY Force RF Seq with argument 2 */ + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ @@ -590,7 +602,7 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) /* TODO: Call N PHY RF Ctrl Intc Override with 2, 0, 3 as arguments */ /* TODO: Call N PHY RF Intc Override with 8, 0, 3, 0 as arguments */ - /* TODO: Call N PHY RF Seq with 0 as argument */ + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); if (core == 0) { rxval = 1; @@ -872,15 +884,7 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, false); } -enum b43_nphy_rf_sequence { - B43_RFSEQ_RX2TX, - B43_RFSEQ_TX2RX, - B43_RFSEQ_RESET2RX, - B43_RFSEQ_UPDATE_GAINH, - B43_RFSEQ_UPDATE_GAINL, - B43_RFSEQ_UPDATE_GAINU, -}; - +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, enum b43_nphy_rf_sequence seq) { @@ -2156,7 +2160,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, } /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ - /* TODO: Call N PHY Force RF Seq with 2 as argument */ + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, width 16, and data from gain_save */ -- cgit v1.2.3 From c57199bc32ebcd914253496486d2e09b1c9a3de0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 17 Jan 2010 13:04:08 +0100 Subject: b43: N-PHY: store seq mode for proper restoring (follow specs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 99024b02bdbd..95190d42372c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -897,6 +897,7 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, }; int i; + u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); @@ -910,8 +911,7 @@ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, } b43err(dev->wl, "RF sequence status timeout\n"); ok: - b43_phy_mask(dev, B43_NPHY_RFSEQMODE, - ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); + b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); } static void b43_nphy_bphy_init(struct b43_wldev *dev) -- cgit v1.2.3 From 5f2aa25e0e5b221a176ab3d1c51d51da265cb4a7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 17 Jan 2010 15:49:02 +0100 Subject: cfg80211: rcu-ify rdev and wdev Future code will need to look up rdev and wdev within atomic sections, but currently we need to lock a mutex for such lookups. Change the list handling for both to be RCU-safe so that we can look them up in rcu sections instead in the future. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/core.c | 26 +++++++++++++++----------- net/wireless/core.h | 3 ++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 20db90246de5..d07f57c906db 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1,7 +1,7 @@ /* * This is the linux wireless configuration interface. * - * Copyright 2006-2009 Johannes Berg + * Copyright 2006-2010 Johannes Berg */ #include @@ -31,15 +31,10 @@ MODULE_AUTHOR("Johannes Berg"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); -/* RCU might be appropriate here since we usually - * only read the list, and that can happen quite - * often because we need to do it for each command */ +/* RCU-protected (and cfg80211_mutex for writers) */ LIST_HEAD(cfg80211_rdev_list); int cfg80211_rdev_list_generation; -/* - * This is used to protect the cfg80211_rdev_list - */ DEFINE_MUTEX(cfg80211_mutex); /* for debugfs */ @@ -477,7 +472,7 @@ int wiphy_register(struct wiphy *wiphy) /* set up regulatory info */ wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); - list_add(&rdev->list, &cfg80211_rdev_list); + list_add_rcu(&rdev->list, &cfg80211_rdev_list); cfg80211_rdev_list_generation++; mutex_unlock(&cfg80211_mutex); @@ -554,7 +549,8 @@ void wiphy_unregister(struct wiphy *wiphy) * it impossible to find from userspace. */ debugfs_remove_recursive(rdev->wiphy.debugfsdir); - list_del(&rdev->list); + list_del_rcu(&rdev->list); + synchronize_rcu(); /* * Try to grab rdev->mtx. If a command is still in progress, @@ -670,7 +666,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, INIT_LIST_HEAD(&wdev->event_list); spin_lock_init(&wdev->event_lock); mutex_lock(&rdev->devlist_mtx); - list_add(&wdev->list, &rdev->netdev_list); + list_add_rcu(&wdev->list, &rdev->netdev_list); rdev->devlist_generation++; /* can only change netns with wiphy */ dev->features |= NETIF_F_NETNS_LOCAL; @@ -782,13 +778,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, */ if (!list_empty(&wdev->list)) { sysfs_remove_link(&dev->dev.kobj, "phy80211"); - list_del_init(&wdev->list); + list_del_rcu(&wdev->list); rdev->devlist_generation++; #ifdef CONFIG_CFG80211_WEXT kfree(wdev->wext.keys); #endif } mutex_unlock(&rdev->devlist_mtx); + /* + * synchronise (so that we won't find this netdev + * from other code any more) and then clear the list + * head so that the above code can safely check for + * !list_empty() to avoid double-cleanup. + */ + synchronize_rcu(); + INIT_LIST_HEAD(&wdev->list); break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/net/wireless/core.h b/net/wireless/core.h index 2d6a6b9c0c43..c326a667022a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -1,7 +1,7 @@ /* * Wireless configuration interface internals. * - * Copyright 2006-2009 Johannes Berg + * Copyright 2006-2010 Johannes Berg */ #ifndef __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H @@ -48,6 +48,7 @@ struct cfg80211_registered_device { /* associate netdev list */ struct mutex devlist_mtx; + /* protected by devlist_mtx or RCU */ struct list_head netdev_list; int devlist_generation; int opencount; /* also protected by devlist_mtx */ -- cgit v1.2.3 From 27032059677b98f33634ceb90488812db432cbc9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 17 Jan 2010 21:08:50 +0100 Subject: ath9k: fix RTS/CTS handling The Tx DMA descriptor has two kinds of flags that select RTS/CTS usage. The first one (global for the frame) selects whether RTS/CTS or CTS-to-self should be used, the second one enables RTS/CTS or CTS-to-self usage for an individual multi-rate-retry entry. Previously the code preparing the descriptor only enabled the global flag, if the first MRR series selected the local one. Fix this by enabling the global flag if any of the MRR entries need it. With this patch, rate control can properly select the use of RTS/CTS for all MRR entries except the first one, which is the default behavior. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 37 +++++++++++++++-------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a821bb687b3b..a6893cf0c43b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1498,26 +1498,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ctsrate |= rate->hw_value_short; - /* - * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. - * Check the first rate in the series to decide whether RTS/CTS - * or CTS-to-self has to be used. - */ - if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - flags = ATH9K_TXDESC_CTSENA; - else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - flags = ATH9K_TXDESC_RTSENA; - - /* FIXME: Handle aggregation protection */ - if (sc->config.ath_aggr_prot && - (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { - flags = ATH9K_TXDESC_RTSENA; - } - - /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) - flags &= ~(ATH9K_TXDESC_RTSENA); - for (i = 0; i < 4; i++) { bool is_40, is_sgi, is_sp; int phy; @@ -1529,8 +1509,15 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) series[i].Tries = rates[i].count; series[i].ChSel = common->tx_chainmask; - if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) + if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || + (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + flags |= ATH9K_TXDESC_RTSENA; + } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; + flags |= ATH9K_TXDESC_CTSENA; + } + if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) series[i].RateFlags |= ATH9K_RATESERIES_2040; if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) @@ -1568,6 +1555,14 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); } + /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ + if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) + flags &= ~ATH9K_TXDESC_RTSENA; + + /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ + if (flags & ATH9K_TXDESC_RTSENA) + flags &= ~ATH9K_TXDESC_CTSENA; + /* set dur_update_en for l-sig computation except for PS-Poll frames */ ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, bf->bf_lastbf->bf_desc, -- cgit v1.2.3 From ce9058aedd75f14785400dcc49a2bc352ca38871 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Sun, 17 Jan 2010 22:45:23 +0100 Subject: mac80211: removed useless code in IBSS management ieee82011_sta_find_ibss() and ieee80211_sta_merge_ibss() are always called with a defined state. So it's useless to check it or set it in those function. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5bcde4c3fba1..c2a708e3a18c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -454,6 +454,9 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) return active; } +/* + * This function is called with state == IEEE80211_IBSS_MLME_JOINED + */ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) { @@ -519,6 +522,10 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) capability, 0); } +/* + * This function is called with state == IEEE80211_IBSS_MLME_SEARCH + */ + static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; @@ -575,18 +582,14 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) #endif /* CONFIG_MAC80211_IBSS_DEBUG */ /* Selected IBSS not found in current scan results - try to scan */ - if (ifibss->state == IEEE80211_IBSS_MLME_JOINED && - !ieee80211_sta_active_ibss(sdata)) { - mod_timer(&ifibss->timer, - round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); - } else if (time_after(jiffies, ifibss->last_scan_completed + + if (time_after(jiffies, ifibss->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->name); ieee80211_request_internal_scan(sdata, ifibss->ssid, ifibss->ssid_len); - } else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) { + } else { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifibss->ibss_join_req + @@ -604,7 +607,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) interval = IEEE80211_SCAN_INTERVAL_SLOW; } - ifibss->state = IEEE80211_IBSS_MLME_SEARCH; mod_timer(&ifibss->timer, round_jiffies(jiffies + interval)); } -- cgit v1.2.3 From a98bfec2985221d8e0904a526cbe88590eaad2a6 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Sun, 17 Jan 2010 22:45:24 +0100 Subject: mac80211: Fixed a bug in IBSS merge First, both beacons and probe responses can be used for IBSS merge. Next, sdata->u.ibss.bssid was always true (and thus IBSS merge was disabled). We should use sdata->u.ibss.fixed_bssid instead. Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/ibss.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c2a708e3a18c..f95750b423e3 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -293,12 +293,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, /* check if we need to merge IBSS */ - /* merge only on beacons (???) */ - if (!beacon) - goto put_bss; - /* we use a fixed BSSID */ - if (sdata->u.ibss.bssid) + if (sdata->u.ibss.fixed_bssid) goto put_bss; /* not an IBSS */ -- cgit v1.2.3 From 288c8ce8047695fd8872dd5db3ef21a9679c402f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 17 Jan 2010 23:17:29 +0100 Subject: p54pci: handle dma mapping errors This patch adds error-paths to handle pci_dma_mapping errors. Cc: Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a72f7c2577de..4bf4c213baec 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -157,6 +157,14 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev, skb_tail_pointer(skb), priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(priv->pdev, mapping)) { + dev_kfree_skb_any(skb); + dev_err(&priv->pdev->dev, + "RX DMA Mapping error\n"); + break; + } + desc->host_addr = cpu_to_le32(mapping); desc->device_addr = 0; // FIXME: necessary? desc->len = cpu_to_le16(priv->common.rx_mtu + 32); @@ -325,14 +333,20 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) u32 device_idx, idx, i; spin_lock_irqsave(&priv->lock, flags); - device_idx = le32_to_cpu(ring_control->device_idx[1]); idx = le32_to_cpu(ring_control->host_idx[1]); i = idx % ARRAY_SIZE(ring_control->tx_data); - priv->tx_buf_data[i] = skb; mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(priv->pdev, mapping)) { + spin_unlock_irqrestore(&priv->lock, flags); + p54_free_skb(dev, skb); + dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); + return ; + } + priv->tx_buf_data[i] = skb; + desc = &ring_control->tx_data[i]; desc->host_addr = cpu_to_le32(mapping); desc->device_addr = ((struct p54_hdr *)skb->data)->req_id; -- cgit v1.2.3 From d713804c6032b95cd3035014e16fadebb9655c6f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 17 Jan 2010 23:19:25 +0100 Subject: p54pci: move tx cleanup into tasklet This patch moves the tx cleanup routines out of the critical interrupt context and into the (previously known as rx) tasklet. The main goal of this operation is to remove the extensive usage of spin_lock_irqsaves in the generic p54common library. The next step would be to modify p54usb to do the rx processing inside a tasklet (just like usbnet). Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 56 ++++++++++++++++++++------------------- drivers/net/wireless/p54/p54pci.h | 6 ++--- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 4bf4c213baec..48cae48ed6eb 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -234,25 +234,26 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); } -/* caller must hold priv->lock */ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, int ring_index, struct p54p_desc *ring, u32 ring_limit, - void **tx_buf) + struct sk_buff **tx_buf) { + unsigned long flags; struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; struct p54p_desc *desc; + struct sk_buff *skb; u32 idx, i; i = (*index) % ring_limit; (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); idx %= ring_limit; + spin_lock_irqsave(&priv->lock, flags); while (i != idx) { desc = &ring[i]; - if (tx_buf[i]) - if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) - p54_free_skb(dev, tx_buf[i]); + + skb = tx_buf[i]; tx_buf[i] = NULL; pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), @@ -263,17 +264,32 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, desc->len = 0; desc->flags = 0; + if (skb && FREE_AFTER_TX(skb)) { + spin_unlock_irqrestore(&priv->lock, flags); + p54_free_skb(dev, skb); + spin_lock_irqsave(&priv->lock, flags); + } + i++; i %= ring_limit; } + spin_unlock_irqrestore(&priv->lock, flags); } -static void p54p_rx_tasklet(unsigned long dev_id) +static void p54p_tasklet(unsigned long dev_id) { struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; + p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, + ARRAY_SIZE(ring_control->tx_mgmt), + priv->tx_buf_mgmt); + + p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, + ARRAY_SIZE(ring_control->tx_data), + priv->tx_buf_data); + p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); @@ -288,38 +304,24 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) { struct ieee80211_hw *dev = dev_id; struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; __le32 reg; spin_lock(&priv->lock); reg = P54P_READ(int_ident); if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { - spin_unlock(&priv->lock); - return IRQ_HANDLED; + goto out; } - P54P_WRITE(int_ack, reg); reg &= P54P_READ(int_enable); - if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { - p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, - 3, ring_control->tx_mgmt, - ARRAY_SIZE(ring_control->tx_mgmt), - priv->tx_buf_mgmt); - - p54p_check_tx_ring(dev, &priv->tx_idx_data, - 1, ring_control->tx_data, - ARRAY_SIZE(ring_control->tx_data), - priv->tx_buf_data); - - tasklet_schedule(&priv->rx_tasklet); - - } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) + if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) + tasklet_schedule(&priv->tasklet); + else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) complete(&priv->boot_comp); +out: spin_unlock(&priv->lock); - return reg ? IRQ_HANDLED : IRQ_NONE; } @@ -368,7 +370,7 @@ static void p54p_stop(struct ieee80211_hw *dev) unsigned int i; struct p54p_desc *desc; - tasklet_kill(&priv->rx_tasklet); + tasklet_kill(&priv->tasklet); P54P_WRITE(int_enable, cpu_to_le32(0)); P54P_READ(int_enable); @@ -559,7 +561,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, priv->common.tx = p54p_tx; spin_lock_init(&priv->lock); - tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); + tasklet_init(&priv->tasklet, p54p_tasklet, (unsigned long)dev); err = request_firmware(&priv->firmware, "isl3886pci", &priv->pdev->dev); diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index fbb683953fb2..2feead617a3b 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h @@ -92,7 +92,7 @@ struct p54p_priv { struct p54_common common; struct pci_dev *pdev; struct p54p_csr __iomem *map; - struct tasklet_struct rx_tasklet; + struct tasklet_struct tasklet; const struct firmware *firmware; spinlock_t lock; struct p54p_ring_control *ring_control; @@ -101,8 +101,8 @@ struct p54p_priv { u32 rx_idx_mgmt, tx_idx_mgmt; struct sk_buff *rx_buf_data[8]; struct sk_buff *rx_buf_mgmt[4]; - void *tx_buf_data[32]; - void *tx_buf_mgmt[4]; + struct sk_buff *tx_buf_data[32]; + struct sk_buff *tx_buf_mgmt[4]; struct completion boot_comp; }; -- cgit v1.2.3 From d41a3552f96673480d7913c170cab31fa00b7697 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 18 Jan 2010 00:21:17 +0100 Subject: b43: N-PHY: add writing one element tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 95190d42372c..32f837049ef9 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -808,8 +808,7 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) if (nphy->bb_mult_save & 0x80000000) { tmp = nphy->bb_mult_save & 0xFFFF; - /* TODO: Write an N PHY Table with ID 15, length 1, offset 87, - width 16 and data from tmp */ + b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); nphy->bb_mult_save = 0; } @@ -1486,13 +1485,11 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) for (i = 0; i < 18; i++) { scale = (ladder_lo[i].percent * tmp) / 100; entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; - /* TODO: Write an N PHY Table with ID 15, length 1, - offset i, width 16, and data entry */ + b43_ntab_write(dev, B43_NTAB16(15, i), entry); scale = (ladder_iq[i].percent * tmp) / 100; entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; - /* TODO: Write an N PHY Table with ID 15, length 1, - offset i + 32, width 16, and data entry */ + b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry); } } @@ -1590,10 +1587,8 @@ static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]); b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]); - /* TODO: Write an N PHY Table with ID 8, length 1, offset 3, - width 16, and data from regs[5] */ - /* TODO: Write an N PHY Table with ID 8, length 1, offset 19, - width 16, and data from regs[6] */ + b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]); + b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]); b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]); b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]); b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); @@ -1603,10 +1598,8 @@ static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]); b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]); b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); - /* TODO: Write an N PHY Table with ID 8, length 1, offset 2, - width 16, and data from regs[3] */ - /* TODO: Write an N PHY Table with ID 8, length 1, offset 18, - width 16, and data from regs[4] */ + b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]); + b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]); b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]); b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]); } @@ -1638,15 +1631,11 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) /* TODO: Read an N PHY Table with ID 8, length 1, offset 3, width 16, and data pointing to tmp */ regs[5] = tmp; - - /* TODO: Write an N PHY Table with ID 8, length 1, offset 3, - width 16, and data 0 */ + b43_ntab_write(dev, B43_NTAB16(8, 3), 0); /* TODO: Read an N PHY Table with ID 8, length 1, offset 19, width 16, and data pointing to tmp */ regs[6] = tmp; - - /* TODO: Write an N PHY Table with ID 8, length 1, offset 19, - width 16, and data 0 */ + b43_ntab_write(dev, B43_NTAB16(8, 19), 0); regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); @@ -1668,14 +1657,12 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) width 16, and data pointing to tmp */ regs[3] = tmp; tmp |= 0x2000; - /* TODO: Write an N PHY Table with ID 8, length 1, offset 2, - width 16, and data pointer tmp */ + b43_ntab_write(dev, B43_NTAB16(8, 2), tmp); /* TODO: Read an N PHY Table with ID 8, length 1, offset 18, width 16, and data pointer tmp */ regs[4] = tmp; tmp |= 0x2000; - /* TODO: Write an N PHY Table with ID 8, length 1, offset 18, - width 16, and data pointer tmp */ + b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) @@ -1900,9 +1887,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, width 16, and data pointer buffer */ diq_start = buffer[0]; buffer[0] = 0; - /* TODO: Write an N PHY Table with ID 15, - length 1, offset 69 + core, width 16, - and data of 0 */ + b43_ntab_write(dev, B43_NTAB16(15, 69 + core), + 0); } b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); -- cgit v1.2.3 From 2581b1434ccba6960e0b671927d87c83b5152c9d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 18 Jan 2010 00:21:21 +0100 Subject: b43: N-PHY: implement and add multi-dimensional table writing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 58 +++++++++++++++------------------- drivers/net/wireless/b43/tables_nphy.c | 40 +++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 2 ++ 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 32f837049ef9..671fbcfdc0ec 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1699,8 +1699,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) loft = &nphy->cal_cache.txcal_coeffs_5G[5]; } - /* TODO: Write an N PHY table with ID 15, length 4, offset 80, - width 16, and data from table */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table); for (i = 0; i < 4; i++) { if (dev->phy.rev >= 3) @@ -1709,12 +1708,9 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) coef[i] = 0; } - /* TODO: Write an N PHY table with ID 15, length 4, offset 88, - width 16, and data from coef */ - /* TODO: Write an N PHY table with ID 15, length 2, offset 85, - width 16 and data from loft */ - /* TODO: Write an N PHY table with ID 15, length 2, offset 93, - width 16 and data from loft */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft); if (dev->phy.rev < 2) b43_nphy_tx_iq_workaround(dev); @@ -1782,8 +1778,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); gain[i] = params[i].cal_gain; } - /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data pointer gain */ + + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain); b43_nphy_tx_cal_radio_setup(dev); b43_nphy_tx_cal_phy_setup(dev); @@ -1833,8 +1829,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, } } - /* TODO: Write an N PHY Table with ID 15, length from above, - offset 64, width 16, and the data pointer from above */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table); if (full) { if (dev->phy.rev >= 3) @@ -1902,9 +1897,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, /* TODO: Read an N PHY Table with ID 15, length table_length, offset 96, width 16, and data pointer buffer */ - /* TODO: Write an N PHY Table with ID 15, - length table_length, offset 64, width 16, - and data pointer buffer */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, + buffer); if (type == 1 || type == 3 || type == 4) buffer[0] = diq_start; @@ -1916,8 +1910,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, last = (dev->phy.rev < 3) ? 6 : 7; if (!mphase || nphy->mphase_cal_phase_id == last) { - /* TODO: Write an N PHY Table with ID 15, length 4, - offset 96, width 16, and data pointer buffer */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer); /* TODO: Read an N PHY Table with ID 15, length 4, offset 80, width 16, and data pointer buffer */ if (dev->phy.rev < 3) { @@ -1926,14 +1919,14 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, buffer[2] = 0; buffer[3] = 0; } - /* TODO: Write an N PHY Table with ID 15, length 4, - offset 88, width 16, and data pointer buffer */ - /* TODO: Read an N PHY Table with ID 15, length 2, - offset 101, width 16, and data pointer buffer*/ - /* TODO: Write an N PHY Table with ID 15, length 2, - offset 85, width 16, and data pointer buffer */ - /* TODO: Write an N PHY Table with ID 15, length 2, - offset 93, width 16, and data pointer buffer */ + b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, + buffer); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, + buffer); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, + buffer); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, + buffer); length = 11; if (dev->phy.rev < 3) length -= 2; @@ -1957,8 +1950,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, } b43_nphy_tx_cal_phy_cleanup(dev); - /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data from save */ + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save); if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) b43_nphy_tx_iq_workaround(dev); @@ -2008,8 +2000,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); cal_gain[i] = cal_params[i].cal_gain; } - /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data from cal_gain */ + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain); for (i = 0; i < 2; i++) { if (i == 0) { @@ -2147,8 +2138,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); - /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data from gain_save */ + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); b43_nphy_stay_in_carrier_search(dev, 0); @@ -2290,8 +2280,10 @@ int b43_phy_initn(struct b43_wldev *dev) if (phy->rev >= 3) { /* TODO */ } else { - /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ - /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ + b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, + b43_ntab_tx_gain_rev0_1_2); + b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, + b43_ntab_tx_gain_rev0_1_2); } if (nphy->phyrxchain != 3) diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index 7dff853ab962..fc08be0b976e 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2952,6 +2952,46 @@ void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) assert_ntab_array_sizes(); } +void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, const void *_data) +{ + u32 type, value; + const u8 *data = _data; + unsigned int i; + + type = offset & B43_NTAB_TYPEMASK; + offset &= ~B43_NTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); + + for (i = 0; i < nr_elements; i++) { + switch (type) { + case B43_NTAB_8BIT: + value = *data; + data++; + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value); + break; + case B43_NTAB_16BIT: + value = *((u16 *)data); + data += 2; + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value); + break; + case B43_NTAB_32BIT: + value = *((u32 *)data); + data += 4; + b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + value & 0xFFFF); + break; + default: + B43_WARN_ON(1); + } + } +} + #define ntab_upload(dev, offset, data) do { \ unsigned int i; \ for (i = 0; i < (offset##_SIZE); i++) \ diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 51636d02f8b1..d5605df5d6b8 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -143,6 +143,8 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, const void *_data); void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev); void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev); -- cgit v1.2.3 From 11380a4b2d86fae9a6bce75c9373668cc323fe57 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 19 Jan 2010 13:46:10 -0800 Subject: net: Unexport napi_gro_flush(). Nothing outside of net/core/dev.c uses it. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 - net/core/dev.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a3fccc85b1a0..468a11dea58c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1527,7 +1527,6 @@ extern int netif_rx(struct sk_buff *skb); extern int netif_rx_ni(struct sk_buff *skb); #define HAVE_NETIF_RECEIVE_SKB 1 extern int netif_receive_skb(struct sk_buff *skb); -extern void napi_gro_flush(struct napi_struct *napi); extern gro_result_t dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb); extern gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb); diff --git a/net/core/dev.c b/net/core/dev.c index a008f6987a95..5747b9edc1bb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2582,7 +2582,7 @@ out: return netif_receive_skb(skb); } -void napi_gro_flush(struct napi_struct *napi) +static void napi_gro_flush(struct napi_struct *napi) { struct sk_buff *skb, *next; @@ -2595,7 +2595,6 @@ void napi_gro_flush(struct napi_struct *napi) napi->gro_count = 0; napi->gro_list = NULL; } -EXPORT_SYMBOL(napi_gro_flush); enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { -- cgit v1.2.3 From c643a66ef5ccfd4d359327fb8afa9949f1abbfdd Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 18 Jan 2010 00:21:27 +0100 Subject: b43: N-PHY: implement and add reading one element tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 18 +++++++----------- drivers/net/wireless/b43/tables_nphy.c | 31 +++++++++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 1 + 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 671fbcfdc0ec..7eac0ae2b15e 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1628,12 +1628,11 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_mask(dev, B43_NPHY_BBCFG, ~B43_NPHY_BBCFG_RSTRX); - /* TODO: Read an N PHY Table with ID 8, length 1, offset 3, - width 16, and data pointing to tmp */ + tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); regs[5] = tmp; b43_ntab_write(dev, B43_NTAB16(8, 3), 0); - /* TODO: Read an N PHY Table with ID 8, length 1, offset 19, - width 16, and data pointing to tmp */ + + tmp = b43_ntab_read(dev, B43_NTAB16(8, 19)); regs[6] = tmp; b43_ntab_write(dev, B43_NTAB16(8, 19), 0); regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); @@ -1653,13 +1652,11 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); regs[2] = tmp; b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000); - /* TODO: Read an N PHY Table with ID 8, length 1, offset 2, - width 16, and data pointing to tmp */ + tmp = b43_ntab_read(dev, B43_NTAB16(8, 2)); regs[3] = tmp; tmp |= 0x2000; b43_ntab_write(dev, B43_NTAB16(8, 2), tmp); - /* TODO: Read an N PHY Table with ID 8, length 1, offset 18, - width 16, and data pointer tmp */ + tmp = b43_ntab_read(dev, B43_NTAB16(8, 18)); regs[4] = tmp; tmp |= 0x2000; b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); @@ -1877,9 +1874,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); if (type == 1 || type == 3 || type == 4) { - /* TODO: Read an N PHY Table with ID 15, - length 1, offset 69 + core, - width 16, and data pointer buffer */ + buffer[0] = b43_ntab_read(dev, + B43_NTAB16(15, 69 + core)); diq_start = buffer[0]; buffer[0] = 0; b43_ntab_write(dev, B43_NTAB16(15, 69 + core), diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index fc08be0b976e..b8aed456da1f 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2919,6 +2919,37 @@ static inline void assert_ntab_array_sizes(void) #undef check } +u32 b43_ntab_read(struct b43_wldev *dev, u32 offset) +{ + u32 type, value; + + type = offset & B43_NTAB_TYPEMASK; + offset &= ~B43_NTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + switch (type) { + case B43_NTAB_8BIT: + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF; + break; + case B43_NTAB_16BIT: + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + break; + case B43_NTAB_32BIT: + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); + value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI); + value <<= 16; + value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + break; + default: + B43_WARN_ON(1); + value = 0; + } + + return value; +} + void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) { u32 type; diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index d5605df5d6b8..64e990a14de3 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -142,6 +142,7 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL 10 #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 +u32 b43_ntab_read(struct b43_wldev *dev, u32 offset); void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data); -- cgit v1.2.3 From 9145834e84805f5efcca4706edfd641047af1d55 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 18 Jan 2010 00:21:35 +0100 Subject: b43: N-PHY: implement and add multi-dimensional table reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 30 +++++++++++------------------ drivers/net/wireless/b43/tables_nphy.c | 35 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 2 ++ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 7eac0ae2b15e..1359267a35ff 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -829,8 +829,7 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, true); - /* TODO: Read an N PHY Table with ID 15, length 7, offset 80, - width 16, and data pointer buffer */ + b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); for (i = 0; i < 2; i++) { tmp = ((buffer[i * 2] & 0x3FF) << 10) | @@ -1507,8 +1506,7 @@ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, true); - /* TODO: Read an N PHY Table with ID 7, length 2, - offset 0x110, width 16, and curr_gain */ + b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain); if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, false); @@ -1768,8 +1766,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, nphy->hang_avoid = 0; } - /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data pointer save */ + b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save); for (i = 0; i < 2; i++) { b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); @@ -1890,9 +1887,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, udelay(10); } - /* TODO: Read an N PHY Table with ID 15, - length table_length, offset 96, width 16, - and data pointer buffer */ + b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, + buffer); b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, buffer); @@ -1907,8 +1903,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, if (!mphase || nphy->mphase_cal_phase_id == last) { b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer); - /* TODO: Read an N PHY Table with ID 15, length 4, - offset 80, width 16, and data pointer buffer */ + b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer); if (dev->phy.rev < 3) { buffer[0] = 0; buffer[1] = 0; @@ -1926,9 +1921,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, length = 11; if (dev->phy.rev < 3) length -= 2; - /* TODO: Read an N PHY Table with ID 15, length length, - offset 96, width 16, and data pointer - nphy->txiqlocal_bestc */ + b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, + nphy->txiqlocal_bestc); nphy->txiqlocal_coeffsvalid = true; /* TODO: Set nphy->txiqlocal_chanspec to the current channel */ @@ -1936,9 +1930,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, length = 11; if (dev->phy.rev < 3) length -= 2; - /* TODO: Read an N PHY Table with ID 5, length length, - offset 96, width 16, and data pointer - nphy->mphase_txcal_bestcoeffs */ + b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, + nphy->mphase_txcal_bestcoeffs); } b43_nphy_stop_playback(dev); @@ -1990,8 +1983,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, if (dev->phy.rev < 2) ;/* TODO: Call N PHY Reapply TX Cal Coeffs */ - /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, - width 16, and data gain_save */ + b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); for (i = 0; i < 2; i++) { b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); cal_gain[i] = cal_params[i].cal_gain; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index b8aed456da1f..b8c9fc619ab1 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2950,6 +2950,41 @@ u32 b43_ntab_read(struct b43_wldev *dev, u32 offset) return value; } +void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, void *_data) +{ + u32 type; + u8 *data = _data; + unsigned int i; + + type = offset & B43_NTAB_TYPEMASK; + offset &= ~B43_NTAB_TYPEMASK; + B43_WARN_ON(offset > 0xFFFF); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); + + for (i = 0; i < nr_elements; i++) { + switch (type) { + case B43_NTAB_8BIT: + *data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF; + data++; + break; + case B43_NTAB_16BIT: + *((u16 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + data += 2; + break; + case B43_NTAB_32BIT: + *((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI); + *((u32 *)data) <<= 16; + *((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO); + data += 4; + break; + default: + B43_WARN_ON(1); + } + } +} + void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) { u32 type; diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 64e990a14de3..6bbef894010c 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -143,6 +143,8 @@ b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); #define B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3 12 u32 b43_ntab_read(struct b43_wldev *dev, u32 offset); +void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset, + unsigned int nr_elements, void *_data); void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data); -- cgit v1.2.3 From de9a47f92795f697964f662415cb27816c2d9b76 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 18 Jan 2010 00:21:49 +0100 Subject: b43: N-PHY: silence warnings, add missing call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1359267a35ff..e77f1f24d101 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1624,7 +1624,7 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); - b43_phy_mask(dev, B43_NPHY_BBCFG, ~B43_NPHY_BBCFG_RSTRX); + b43_phy_mask(dev, B43_NPHY_BBCFG, (u16)~B43_NPHY_BBCFG_RSTRX); tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); regs[5] = tmp; @@ -1970,7 +1970,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, u16 lna[3] = { 3, 3, 1 }; u16 hpf1[3] = { 7, 2, 0 }; u16 hpf2[3] = { 2, 0, 0 }; - u32 power[3]; + u32 power[3] = { }; u16 gain_save[2]; u16 cal_gain[2]; struct nphy_iqcal_params cal_params[2]; @@ -2077,7 +2077,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, (cur_lna << 2)); /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], 3, 0 as arguments */ - /* TODO: Call N PHY Force RF Seq with 2 as argument */ + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); b43_nphy_stop_playback(dev); if (playtone) { -- cgit v1.2.3 From 1625c148cde23a8b4180e171ed4a17e17521b995 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 19 Jan 2010 00:19:21 +0100 Subject: libertas: Set/clear WPA keys before the WEP ones With the v10 firmware running on 8688 HW, clearing WPA keys after setting the WEP key prevents us from being able to associate with WEP APs. Swapping the calling order for assoc_helper_wpa_keys() and assoc_helper_wep_keys fixes that issue. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 5e650f358415..fb3dff0fdfa8 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -2052,13 +2052,6 @@ void lbs_association_worker(struct work_struct *work) goto out; } - if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { - ret = assoc_helper_wep_keys(priv, assoc_req); - if (ret) - goto out; - } - if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { ret = assoc_helper_secinfo(priv, assoc_req); if (ret) @@ -2078,6 +2071,14 @@ void lbs_association_worker(struct work_struct *work) goto out; } + if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) + || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { + ret = assoc_helper_wep_keys(priv, assoc_req); + if (ret) + goto out; + } + + /* SSID/BSSID should be the _last_ config option set, because they * trigger the association attempt. */ -- cgit v1.2.3 From 27e310c91c3433ab9997b925b3fd65e660634c76 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 19 Jan 2010 10:53:30 -0800 Subject: nl80211: Allow association to change channels during reassociation nl80211_associate() was rejecting (re)association attempts with EBUSY in some cases where we are currently associated with an AP that uses different channel from the destination AP. Fix this by passing the current wdev to rdev_fixed_channel() in the same way that was already done for join-IBSS and connect commands. This allows the fixedchan check to skipped for the current wdev and allows the reassociation to proceed. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4af7991a9ec8..5b79ecf17bea 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3571,6 +3571,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; struct net_device *dev; + struct wireless_dev *wdev; struct cfg80211_crypto_settings crypto; struct ieee80211_channel *chan, *fixedchan; const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; @@ -3616,7 +3617,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) } mutex_lock(&rdev->devlist_mtx); - fixedchan = rdev_fixed_channel(rdev, NULL); + wdev = dev->ieee80211_ptr; + fixedchan = rdev_fixed_channel(rdev, wdev); if (fixedchan && chan != fixedchan) { err = -EBUSY; mutex_unlock(&rdev->devlist_mtx); -- cgit v1.2.3 From c9f6a6567f3e8dd69dd3f80a67e73d7d10884bea Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 19 Jan 2010 14:04:19 -0500 Subject: ath9k: make tx power config changes take effect immediatley Users wishing to tweak tx power want it to happen immediately, try to respect that. This was tested by Lorenzo by measuring the received signal strength from an AP with ath9k and the patch. Changing the tx power on the AP produced these results: 1) iwconfig wlan0 txpower 20 ---> Rx power -37dbm 2) iwconfig wlan0 txpower 15 ---> Rx power -41dbm 3) iwconfig wlan0 txpower 10 ---> Rx power -45dbm 4) iwconfig wlan0 txpower 5 ---> Rx power -51dbm 5) iwconfig wlan0 txpower 0 ---> Rx power -37dbm The result with 0 is an anomoly and would need to be addressed through a separate patch. Signed-off-by: Luis R. Rodriguez Tested-by: Lorenzo Bianconi Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c0c571c2e8c4..6f3e71c5071e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1624,8 +1624,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) } skip_chan_change: - if (changed & IEEE80211_CONF_CHANGE_POWER) + if (changed & IEEE80211_CONF_CHANGE_POWER) { sc->config.txpowlimit = 2 * conf->power_level; + ath_update_txpow(sc); + } spin_lock_bh(&sc->wiphy_lock); disable_radio = ath9k_all_wiphys_idle(sc); -- cgit v1.2.3 From 64147c729732ba9c9e50966971bdfbd503c888bb Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 19 Jan 2010 17:07:41 -0500 Subject: libertas/assoc.c: rearrange some strange line breaks Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 62 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index fb3dff0fdfa8..0979b07799a0 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -1160,11 +1160,11 @@ int lbs_adhoc_stop(struct lbs_private *priv) static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, struct bss_descriptor *match_bss) { - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && match_bss->wpa_ie[0] != WLAN_EID_GENERIC - && match_bss->rsn_ie[0] != WLAN_EID_RSN - && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + if (!secinfo->wep_enabled && + !secinfo->WPAenabled && !secinfo->WPA2enabled && + match_bss->wpa_ie[0] != WLAN_EID_GENERIC && + match_bss->rsn_ie[0] != WLAN_EID_RSN && + !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; else return 0; @@ -1173,9 +1173,9 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, struct bss_descriptor *match_bss) { - if (secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + if (secinfo->wep_enabled && + !secinfo->WPAenabled && !secinfo->WPA2enabled && + (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; else return 0; @@ -1184,8 +1184,8 @@ static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, struct bss_descriptor *match_bss) { - if (!secinfo->wep_enabled && secinfo->WPAenabled - && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) + if (!secinfo->wep_enabled && secinfo->WPAenabled && + (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) /* privacy bit may NOT be set in some APs like LinkSys WRT54G && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ ) @@ -1210,11 +1210,11 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, struct bss_descriptor *match_bss) { - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) - && (match_bss->rsn_ie[0] != WLAN_EID_RSN) - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + if (!secinfo->wep_enabled && + !secinfo->WPAenabled && !secinfo->WPA2enabled && + (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) && + (match_bss->rsn_ie[0] != WLAN_EID_RSN) && + (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; else return 0; @@ -1525,8 +1525,8 @@ static int assoc_helper_associate(struct lbs_private *priv, /* If we're given and 'any' BSSID, try associating based on SSID */ if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(bssid_any, assoc_req->bssid) - && compare_ether_addr(bssid_off, assoc_req->bssid)) { + if (compare_ether_addr(bssid_any, assoc_req->bssid) && + compare_ether_addr(bssid_off, assoc_req->bssid)) { ret = assoc_helper_bssid(priv, assoc_req); done = 1; } @@ -1612,11 +1612,9 @@ static int assoc_helper_channel(struct lbs_private *priv, goto restore_mesh; } - if ( assoc_req->secinfo.wep_enabled - && (assoc_req->wep_keys[0].len - || assoc_req->wep_keys[1].len - || assoc_req->wep_keys[2].len - || assoc_req->wep_keys[3].len)) { + if (assoc_req->secinfo.wep_enabled && + (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || + assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) { /* Make sure WEP keys are re-sent to firmware */ set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); } @@ -1983,14 +1981,14 @@ void lbs_association_worker(struct work_struct *work) assoc_req->secinfo.auth_mode); /* If 'any' SSID was specified, find an SSID to associate with */ - if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) - && !assoc_req->ssid_len) + if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) && + !assoc_req->ssid_len) find_any_ssid = 1; /* But don't use 'any' SSID if there's a valid locked BSSID to use */ if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(assoc_req->bssid, bssid_any) - && compare_ether_addr(assoc_req->bssid, bssid_off)) + if (compare_ether_addr(assoc_req->bssid, bssid_any) && + compare_ether_addr(assoc_req->bssid, bssid_off)) find_any_ssid = 0; } @@ -2064,15 +2062,15 @@ void lbs_association_worker(struct work_struct *work) goto out; } - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { + if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) || + test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { ret = assoc_helper_wpa_keys(priv, assoc_req); if (ret) goto out; } - if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { + if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) || + test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { ret = assoc_helper_wep_keys(priv, assoc_req); if (ret) goto out; @@ -2082,8 +2080,8 @@ void lbs_association_worker(struct work_struct *work) /* SSID/BSSID should be the _last_ config option set, because they * trigger the association attempt. */ - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) - || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { + if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) || + test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { int success = 1; ret = assoc_helper_associate(priv, assoc_req); -- cgit v1.2.3 From 7981d6f6b280d28779343cff4a88029fe53d1b47 Mon Sep 17 00:00:00 2001 From: Allan Stephens Date: Tue, 19 Jan 2010 14:23:57 -0800 Subject: tipc: Clean up configuration file This patch addresses a number of minor (mostly cosmetic) issues relating to the configuration of TIPC, including the following: - Corrects range limits for maximum number of ports per node - Adds missing range limits for size of log buffer - Removes configuration setting relating to unsupported slave node capability - Standardizes description and help text wording for configuration settings - Removes unneeded blank spaces Signed-off-by: Allan Stephens Signed-off-by: David S. Miller --- net/tipc/Kconfig | 73 +++++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig index dafbd533067c..b74f78d0c033 100644 --- a/net/tipc/Kconfig +++ b/net/tipc/Kconfig @@ -10,7 +10,7 @@ menuconfig TIPC specially designed for intra cluster communication. This protocol originates from Ericsson where it has been used in carrier grade cluster applications for many years. - + For more information about TIPC, see http://tipc.sourceforge.net. This protocol support is also available as a module ( = code which @@ -23,24 +23,23 @@ menuconfig TIPC if TIPC config TIPC_ADVANCED - bool "TIPC: Advanced configuration" + bool "Advanced TIPC configuration" default n help - Saying Y here will open some advanced configuration - for TIPC. Most users do not need to bother, so if - unsure, just say N. + Saying Y here will open some advanced configuration for TIPC. + Most users do not need to bother; if unsure, just say N. config TIPC_ZONES - int "Maximum number of zones in network" + int "Maximum number of zones in a network" depends on TIPC_ADVANCED range 1 255 default "3" help - Max number of zones inside TIPC network. Max supported value - is 255 zones, minimum is 1 + Specifies how many zones can be supported in a TIPC network. + Can range from 1 to 255 zones; default is 3. - Default is 3 zones in a network; setting this to higher - allows more zones but might use more memory. + Setting this to a smaller value saves some memory; + setting it to a higher value allows for more zones. config TIPC_CLUSTERS int "Maximum number of clusters in a zone" @@ -48,70 +47,52 @@ config TIPC_CLUSTERS range 1 1 default "1" help - ***Only 1 (one cluster in a zone) is supported by current code.*** - - (Max number of clusters inside TIPC zone. Max supported - value is 4095 clusters, minimum is 1. + Specifies how many clusters can be supported in a TIPC zone. - Default is 1; setting this to smaller value might save - some memory, setting it to higher - allows more clusters and might consume more memory.) + *** Currently TIPC only supports a single cluster per zone. *** config TIPC_NODES - int "Maximum number of nodes in cluster" + int "Maximum number of nodes in a cluster" depends on TIPC_ADVANCED range 8 2047 default "255" help - Maximum number of nodes inside a TIPC cluster. Maximum - supported value is 2047 nodes, minimum is 8. - - Setting this to a smaller value saves some memory, - setting it to higher allows more nodes. - -config TIPC_SLAVE_NODES - int "Maximum number of slave nodes in cluster" - depends on TIPC_ADVANCED - range 0 2047 - default "0" - help - ***This capability is not supported by current code.*** - - Maximum number of slave nodes inside a TIPC cluster. Maximum - supported value is 2047 nodes, minimum is 0. + Specifies how many nodes can be supported in a TIPC cluster. + Can range from 8 to 2047 nodes; default is 255. - Setting this to a smaller value saves some memory, - setting it to higher allows more nodes. + Setting this to a smaller value saves some memory; + setting it to higher allows for more nodes. config TIPC_PORTS int "Maximum number of ports in a node" depends on TIPC_ADVANCED - range 217 65536 + range 127 65535 default "8191" help - Maximum number of ports within a node. Maximum - supported value is 64535 nodes, minimum is 127. + Specifies how many ports can be supported by a node. + Can range from 127 to 65535 ports; default is 8191. Setting this to a smaller value saves some memory, - setting it to higher allows more ports. + setting it to higher allows for more ports. config TIPC_LOG int "Size of log buffer" depends on TIPC_ADVANCED - default 0 + range 0 32768 + default "0" help - Size (in bytes) of TIPC's internal log buffer, which records the - occurrence of significant events. Maximum supported value - is 32768 bytes, minimum is 0. + Size (in bytes) of TIPC's internal log buffer, which records the + occurrence of significant events. Can range from 0 to 32768 bytes; + default is 0. There is no need to enable the log buffer unless the node will be managed remotely via TIPC. config TIPC_DEBUG - bool "Enable debugging support" + bool "Enable debug messages" default n help - This will enable debugging of TIPC. + This enables debugging of TIPC. Only say Y here if you are having trouble with TIPC. It will enable the display of detailed information about what is going on. -- cgit v1.2.3 From b38f6eddeee510ce8178c2d2db54ed25f1d7cb63 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Wed, 20 Jan 2010 10:39:14 +0100 Subject: netfilter: nf_conntrack_ipv6: delete the redundant macro definitions The following three macro definitions are never used, so delete them. Signed-off-by: Shan Wei Acked-by: David S. Miller Signed-off-by: Patrick McHardy --- net/ipv6/netfilter/nf_conntrack_reasm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 312c20adc83f..1030ce1e6c79 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -45,9 +45,6 @@ #include #include -#define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */ -#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ -#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT struct nf_ct_frag6_skb_cb { -- cgit v1.2.3 From 7c070aa947d1a4105742378579c267f6e7fd08a1 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Wed, 20 Jan 2010 10:42:41 +0100 Subject: IPv6: reassembly: replace magic number with macro definitions Use macro to define high/low thresh value, refer to IPV6_FRAG_TIMEOUT. Signed-off-by: Shan Wei Acked-by: David S. Miller Signed-off-by: Patrick McHardy --- include/net/ipv6.h | 2 ++ net/ipv6/netfilter/nf_conntrack_reasm.c | 4 ++-- net/ipv6/reassembly.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index ccab5946c830..299bbf5adfb6 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -246,6 +246,8 @@ extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); int ip6_frag_nqueues(struct net *net); int ip6_frag_mem(struct net *net); +#define IPV6_FRAG_HIGH_THRESH 262144 /* == 256*1024 */ +#define IPV6_FRAG_LOW_THRESH 196608 /* == 192*1024 */ #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ extern int __ipv6_addr_type(const struct in6_addr *addr); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 1030ce1e6c79..744ea49de356 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -666,8 +666,8 @@ int nf_ct_frag6_init(void) nf_frags.frag_expire = nf_ct_frag6_expire; nf_frags.secret_interval = 10 * 60 * HZ; nf_init_frags.timeout = IPV6_FRAG_TIMEOUT; - nf_init_frags.high_thresh = 256 * 1024; - nf_init_frags.low_thresh = 192 * 1024; + nf_init_frags.high_thresh = IPV6_FRAG_HIGH_THRESH; + nf_init_frags.low_thresh = IPV6_FRAG_LOW_THRESH; inet_frags_init_net(&nf_init_frags); inet_frags_init(&nf_frags); diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 2cddea3bd6be..15bb122e1ce4 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -747,8 +747,8 @@ static inline void ip6_frags_sysctl_unregister(void) static int ipv6_frags_init_net(struct net *net) { - net->ipv6.frags.high_thresh = 256 * 1024; - net->ipv6.frags.low_thresh = 192 * 1024; + net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; + net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH; net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; inet_frags_init_net(&net->ipv6.frags); -- cgit v1.2.3 From 614b05900ec3516b835cd06f848ef6bc915beeea Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:02 +0000 Subject: tg3: Enable PLL PD when CLKREQ disabled for 5717A0 PCIe PLL power down cannot be used if CLKREQ is enabled because data corruption will occur. If CLKREQ is disabled though, enabling PCIE P1 PLL power-down saves some power. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 16 ++++++++++++++++ drivers/net/tg3.h | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b0630cd093a3..b80e7eef8af9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7569,6 +7569,20 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(TG3_PCIE_LNKCTL, val | TG3_PCIE_LNKCTL_L1_PLL_PD_DIS); } + if (tp->tg3_flags3 & TG3_FLG3_L1PLLPD_EN) { + u32 grc_mode = tr32(GRC_MODE); + + /* Access the lower 1K of PL PCIE block registers. */ + val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK; + tw32(GRC_MODE, val | GRC_MODE_PCIE_PL_SEL); + + val = tr32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1); + tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_PL_LO_PHYCTL1, + val | TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN); + + tw32(GRC_MODE, grc_mode); + } + /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. But do not set this on PCI Express @@ -13096,6 +13110,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 || tp->pci_chip_rev_id == CHIPREV_ID_57780_A1) tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG; + } else if (tp->pci_chip_rev_id == CHIPREV_ID_5717_A0) { + tp->tg3_flags3 |= TG3_FLG3_L1PLLPD_EN; } } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) { tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cd30889650f8..44a505d07e20 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1540,6 +1540,8 @@ #define GRC_MODE_HOST_SENDBDS 0x00020000 #define GRC_MODE_NO_TX_PHDR_CSUM 0x00100000 #define GRC_MODE_NVRAM_WR_ENABLE 0x00200000 +#define GRC_MODE_PCIE_TL_SEL 0x00000000 +#define GRC_MODE_PCIE_PL_SEL 0x00400000 #define GRC_MODE_NO_RX_PHDR_CSUM 0x00800000 #define GRC_MODE_IRQ_ON_TX_CPU_ATTN 0x01000000 #define GRC_MODE_IRQ_ON_RX_CPU_ATTN 0x02000000 @@ -1547,7 +1549,13 @@ #define GRC_MODE_IRQ_ON_DMA_ATTN 0x08000000 #define GRC_MODE_IRQ_ON_FLOW_ATTN 0x10000000 #define GRC_MODE_4X_NIC_SEND_RINGS 0x20000000 +#define GRC_MODE_PCIE_DL_SEL 0x20000000 #define GRC_MODE_MCAST_FRM_ENABLE 0x40000000 +#define GRC_MODE_PCIE_HI_1K_EN 0x80000000 +#define GRC_MODE_PCIE_PORT_MASK (GRC_MODE_PCIE_TL_SEL | \ + GRC_MODE_PCIE_PL_SEL | \ + GRC_MODE_PCIE_DL_SEL | \ + GRC_MODE_PCIE_HI_1K_EN) #define GRC_MISC_CFG 0x00006804 #define GRC_MISC_CFG_CORECLK_RESET 0x00000001 #define GRC_MISC_CFG_PRESCALAR_MASK 0x000000fe @@ -1801,6 +1809,11 @@ /* 0x7e74 --> 0x8000 unused */ +/* Alternate PCIE definitions */ +#define TG3_PCIE_TLDLPL_PORT 0x00007c00 +#define TG3_PCIE_PL_LO_PHYCTL1 0x00000004 +#define TG3_PCIE_PL_LO_PHYCTL1_L1PLLPD_EN 0x00001000 + /* OTP bit definitions */ #define TG3_OTP_AGCTGT_MASK 0x000000e0 #define TG3_OTP_AGCTGT_SHIFT 1 @@ -2809,6 +2822,7 @@ struct tg3 { #define TG3_FLG3_40BIT_DMA_LIMIT_BUG 0x00100000 #define TG3_FLG3_SHORT_DMA_BUG 0x00200000 #define TG3_FLG3_USE_JUMBO_BDFLAG 0x00400000 +#define TG3_FLG3_L1PLLPD_EN 0x00800000 struct timer_list timer; u16 timer_counter; -- cgit v1.2.3 From 666bc831cf820e16cbd0c2d5be780c512b1afe15 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:03 +0000 Subject: tg3: Improve internal resource allocations The 5717 and the 57765 have more resources at their disposal internally. This patch tunes the driver to get better performance. The adjustments made here only apply to the 57765 and 5717 asic revs. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 25 +++++++++++++++++++++---- drivers/net/tg3.h | 4 ++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b80e7eef8af9..adb579f0d75d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8152,7 +8152,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Prevent chip from dropping frames when flow control * is enabled. */ - tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + val = 1; + else + val = 2; + tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, val); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 && (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { @@ -14091,9 +14095,22 @@ static void __devinit tg3_init_link_config(struct tg3 *tp) static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) { - if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { + tp->bufmgr_config.mbuf_read_dma_low_water = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water = + DEFAULT_MB_MACRX_LOW_WATER_57765; + tp->bufmgr_config.mbuf_high_water = + DEFAULT_MB_HIGH_WATER_57765; + + tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = + DEFAULT_MB_RDMA_LOW_WATER_5705; + tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = + DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765; + tp->bufmgr_config.mbuf_high_water_jumbo = + DEFAULT_MB_HIGH_WATER_JUMBO_57765; + } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 44a505d07e20..91139fdf7f43 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1203,14 +1203,18 @@ #define DEFAULT_MB_MACRX_LOW_WATER 0x00000020 #define DEFAULT_MB_MACRX_LOW_WATER_5705 0x00000010 #define DEFAULT_MB_MACRX_LOW_WATER_5906 0x00000004 +#define DEFAULT_MB_MACRX_LOW_WATER_57765 0x0000002a #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO 0x00000098 #define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780 0x0000004b +#define DEFAULT_MB_MACRX_LOW_WATER_JUMBO_57765 0x0000007e #define BUFMGR_MB_HIGH_WATER 0x00004418 #define DEFAULT_MB_HIGH_WATER 0x00000060 #define DEFAULT_MB_HIGH_WATER_5705 0x00000060 #define DEFAULT_MB_HIGH_WATER_5906 0x00000010 +#define DEFAULT_MB_HIGH_WATER_57765 0x000000a0 #define DEFAULT_MB_HIGH_WATER_JUMBO 0x0000017c #define DEFAULT_MB_HIGH_WATER_JUMBO_5780 0x00000096 +#define DEFAULT_MB_HIGH_WATER_JUMBO_57765 0x000000ea #define BUFMGR_RX_MB_ALLOC_REQ 0x0000441c #define BUFMGR_MB_ALLOC_BIT 0x10000000 #define BUFMGR_RX_MB_ALLOC_RESP 0x00004420 -- cgit v1.2.3 From 9b952f51d019db37276bdb2924e776ca09132fc1 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:04 +0000 Subject: tg3: Add 5717 serdes phy ID The serdes and copper phys of the 5717 asic rev have different phy IDs. This patch adds the serdes phy ID. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 ++- drivers/net/tg3.h | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index adb579f0d75d..4a653478edd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -14170,7 +14170,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5756: return "5722/5756"; case PHY_ID_BCM5906: return "5906"; case PHY_ID_BCM5761: return "5761"; - case PHY_ID_BCM5717: return "5717"; + case PHY_ID_BCM5718C: return "5718C"; + case PHY_ID_BCM5718S: return "5718S"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 91139fdf7f43..edb7a14cf58f 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2893,7 +2893,8 @@ struct tg3 { #define PHY_ID_BCM5756 0xbc050ed0 #define PHY_ID_BCM5784 0xbc050fa0 #define PHY_ID_BCM5761 0xbc050fd0 -#define PHY_ID_BCM5717 0x5c0d8a00 +#define PHY_ID_BCM5718C 0x5c0d8a00 +#define PHY_ID_BCM5718S 0xbc050ff0 #define PHY_ID_BCM5906 0xdc00ac40 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2936,7 +2937,8 @@ struct tg3 { (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \ - (X) == PHY_ID_BCM5717 || (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM5718C || (X) == PHY_ID_BCM5718S || \ + (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; -- cgit v1.2.3 From ecf1410b9d70b3034e5955e92bb0c3e02ff21e9c Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:05 +0000 Subject: tg3: Abort phy init for 5717 serdes devices The 5717 serdes devices have a different phy register layout than all other previous serdes devices. This patch aborts the phy init sequence in tg3_phy_reset() if the device is a 5717 serdes. It also aborts the tg3_phy_toggle_apd() operation. Most other operations in the MII_SERDES path are O.K. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4a653478edd6..7a36bf4dc968 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1560,7 +1560,9 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable) { u32 reg; - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) || + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) return; if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { @@ -1935,6 +1937,10 @@ static int tg3_phy_reset(struct tg3 *tp) } } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)) + return 0; + tg3_phy_apply_otp(tp); if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD) -- cgit v1.2.3 From 8b5a6c42e1f2277433aeefa9ee5a0c1a2473b7d8 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:06 +0000 Subject: tg3: Fix 5717 and 57765 memory selftests Both the 5717 and the 57765 will fail 'ethtool -t' selftests at the memory selftest portion. The memory map for these two devices differs from the rest of the asic revs and each other. This patch adds a new memory map to use for memory selftests. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7a36bf4dc968..44ac9e233bef 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10659,12 +10659,27 @@ static int tg3_test_memory(struct tg3 *tp) { 0x00008000, 0x01000}, { 0x00010000, 0x01000}, { 0xffffffff, 0x00000} + }, mem_tbl_5717[] = { + { 0x00000200, 0x00008}, + { 0x00010000, 0x0a000}, + { 0x00020000, 0x13c00}, + { 0xffffffff, 0x00000} + }, mem_tbl_57765[] = { + { 0x00000200, 0x00008}, + { 0x00004000, 0x00800}, + { 0x00006000, 0x09800}, + { 0x00010000, 0x0a000}, + { 0xffffffff, 0x00000} }; struct mem_entry *mem_tbl; int err = 0; int i; - if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + mem_tbl = mem_tbl_5717; + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + mem_tbl = mem_tbl_57765; + else if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) mem_tbl = mem_tbl_5755; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) mem_tbl = mem_tbl_5906; -- cgit v1.2.3 From 5fd68fbdaf75505a2400826c7f314a1f3121a5f7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:07 +0000 Subject: tg3: Supply a nicaddr for 57765 jumbo RCB The 57765 needs the driver to supply a nic address to the jumbo RCB, just like all other devices except the 5717. This patch changes the test to single out the 5717 rather than maintain a lengthy whitelist of asic revs. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 44ac9e233bef..72d1e18a152c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7787,7 +7787,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) | BDINFO_FLAGS_USE_EXT_RECV); - if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_JUMBO_BUFFER_DESC); } else { -- cgit v1.2.3 From c2353a3214ff5813c4b719b3cdacbe939b1c63a0 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:08 +0000 Subject: tg3: Fix tx mailbox initialization If a device supports MSI-X interrupts, the driver assumes TSS will be available. This is not true for the 57765. This patch changes the code so that only the default tx mailbox is initialized if TSS is not available. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 72d1e18a152c..dffa51a4aafb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7440,10 +7440,13 @@ static void tg3_rings_reset(struct tg3 *tp) for (i = 1; i < TG3_IRQ_MAX_VECS; i++) { tp->napi[i].tx_prod = 0; tp->napi[i].tx_cons = 0; - tw32_mailbox(tp->napi[i].prodmbox, 0); + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + tw32_mailbox(tp->napi[i].prodmbox, 0); tw32_rx_mbox(tp->napi[i].consmbox, 0); tw32_mailbox_f(tp->napi[i].int_mbox, 1); } + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)) + tw32_mailbox(tp->napi[0].prodmbox, 0); } else { tp->napi[0].tx_prod = 0; tp->napi[0].tx_cons = 0; -- cgit v1.2.3 From cb4ed1fd8af963101a59c8c5fef97cbbf5f3fb88 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:09 +0000 Subject: tg3: Turn off the debug UART for 57765 If the debug UART is left enabled, the LEDs will not work properly. This patch disables the debug UART. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index dffa51a4aafb..075d21a6b55a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13328,7 +13328,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || -- cgit v1.2.3 From 334355aa590c4b58750015c2f5710cd5074f45dd Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:10 +0000 Subject: tg3: Bypass power source switching for 57765 The 57765 repurposes all the GPIOs normally used to switch power sources when configured as a NIC device. This patch changes the code to avoid touching the GPIOs for this asic rev. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 075d21a6b55a..78102023aa93 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2021,7 +2021,9 @@ static void tg3_frob_aux_power(struct tg3 *tp) { struct tg3 *tp_peer = tp; - if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0) + /* The GPIOs do something completely different on 57765. */ + if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) return; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 || -- cgit v1.2.3 From b0f752210c0aa5e3d9ece4cbfefdc43092a68b83 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 20 Jan 2010 16:58:11 +0000 Subject: tg3: Add 57765 phy ID and enable devices. This patch rounds out the 57765 asic rev support by adding the 57765 phy ID and entering the 57765 device IDs in the pci table. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 +++++++ drivers/net/tg3.h | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 78102023aa93..eaed2aa09e1f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -244,6 +244,12 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, @@ -14199,6 +14205,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) case PHY_ID_BCM5761: return "5761"; case PHY_ID_BCM5718C: return "5718C"; case PHY_ID_BCM5718S: return "5718S"; + case PHY_ID_BCM57765: return "57765"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index edb7a14cf58f..34c9ef4b74a3 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2895,6 +2895,7 @@ struct tg3 { #define PHY_ID_BCM5761 0xbc050fd0 #define PHY_ID_BCM5718C 0x5c0d8a00 #define PHY_ID_BCM5718S 0xbc050ff0 +#define PHY_ID_BCM57765 0x5c0d8a40 #define PHY_ID_BCM5906 0xdc00ac40 #define PHY_ID_BCM8002 0x60010140 #define PHY_ID_INVALID 0xffffffff @@ -2938,7 +2939,7 @@ struct tg3 { (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \ (X) == PHY_ID_BCM5718C || (X) == PHY_ID_BCM5718S || \ - (X) == PHY_ID_BCM8002) + (X) == PHY_ID_BCM57765 || (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; -- cgit v1.2.3 From d03e067778104911cc02cb92dd152df2f3b988a5 Mon Sep 17 00:00:00 2001 From: Liu Yu-B13201 Date: Wed, 13 Jan 2010 22:13:16 +0000 Subject: dts/mpc8569mds: Cleanup tbi phy to support rtbi After these change, when need to work in rtbi mode, just change phy-connection-type to "rtbi". Also, this work can be done by u-boot. Signed-off-by: Liu Yu Signed-off-by: David S. Miller --- arch/powerpc/boot/dts/mpc8569mds.dts | 47 ++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index 795eb362fcf9..8b72eaff5b03 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts @@ -535,6 +535,7 @@ rx-clock-name = "none"; tx-clock-name = "clk12"; pio-handle = <&pio1>; + tbi-handle = <&tbi1>; phy-handle = <&qe_phy0>; phy-connection-type = "rgmii-id"; }; @@ -579,7 +580,7 @@ reg = <0x6>; device_type = "ethernet-phy"; }; - tbi-phy@11 { + tbi1: tbi-phy@11 { reg = <0x11>; device_type = "tbi-phy"; }; @@ -590,7 +591,7 @@ reg = <0x3520 0x18>; compatible = "fsl,ucc-mdio"; - tbi0: tbi-phy@15 { + tbi6: tbi-phy@15 { reg = <0x15>; device_type = "tbi-phy"; }; @@ -600,7 +601,7 @@ #size-cells = <0>; reg = <0x3720 0x38>; compatible = "fsl,ucc-mdio"; - tbi1: tbi-phy@17 { + tbi8: tbi-phy@17 { reg = <0x17>; device_type = "tbi-phy"; }; @@ -617,10 +618,22 @@ rx-clock-name = "none"; tx-clock-name = "clk12"; pio-handle = <&pio3>; + tbi-handle = <&tbi3>; phy-handle = <&qe_phy2>; phy-connection-type = "rgmii-id"; }; + mdio@2320 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2320 0x18>; + compatible = "fsl,ucc-mdio"; + tbi3: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + enet1: ucc@3000 { device_type = "network"; compatible = "ucc_geth"; @@ -632,10 +645,22 @@ rx-clock-name = "none"; tx-clock-name = "clk17"; pio-handle = <&pio2>; + tbi-handle = <&tbi2>; phy-handle = <&qe_phy1>; phy-connection-type = "rgmii-id"; }; + mdio@3120 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3120 0x18>; + compatible = "fsl,ucc-mdio"; + tbi2: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + enet3: ucc@3200 { device_type = "network"; compatible = "ucc_geth"; @@ -647,10 +672,22 @@ rx-clock-name = "none"; tx-clock-name = "clk17"; pio-handle = <&pio4>; + tbi-handle = <&tbi4>; phy-handle = <&qe_phy3>; phy-connection-type = "rgmii-id"; }; + mdio@3320 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3320 0x18>; + compatible = "fsl,ucc-mdio"; + tbi4: tbi-phy@11 { + reg = <0x11>; + device_type = "tbi-phy"; + }; + }; + enet5: ucc@3400 { device_type = "network"; compatible = "ucc_geth"; @@ -661,7 +698,7 @@ local-mac-address = [ 00 00 00 00 00 00 ]; rx-clock-name = "none"; tx-clock-name = "none"; - tbi-handle = <&tbi0>; + tbi-handle = <&tbi6>; phy-handle = <&qe_phy5>; phy-connection-type = "sgmii"; }; @@ -676,7 +713,7 @@ local-mac-address = [ 00 00 00 00 00 00 ]; rx-clock-name = "none"; tx-clock-name = "none"; - tbi-handle = <&tbi1>; + tbi-handle = <&tbi8>; phy-handle = <&qe_phy7>; phy-connection-type = "sgmii"; }; -- cgit v1.2.3 From c1fb8340d7a39346c08ec4b1db4fb432f02acd4c Mon Sep 17 00:00:00 2001 From: Liu Yu-B13201 Date: Wed, 13 Jan 2010 22:13:17 +0000 Subject: mpc8569mds: Add bscr setting for rtbi mode Signed-off-by: Liu Yu Signed-off-by: David S. Miller --- arch/powerpc/platforms/85xx/mpc85xx_mds.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 21f61b8c445b..04ed2156db1c 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -237,6 +237,8 @@ static void __init mpc85xx_mds_setup_arch(void) } else if (machine_is(mpc8569_mds)) { #define BCSR7_UCC12_GETHnRST (0x1 << 2) #define BCSR8_UEM_MARVELL_RST (0x1 << 1) +#define BCSR_UCC_RGMII (0x1 << 6) +#define BCSR_UCC_RTBI (0x1 << 5) /* * U-Boot mangles interrupt polarity for Marvell PHYs, * so reset built-in and UEM Marvell PHYs, this puts @@ -247,6 +249,28 @@ static void __init mpc85xx_mds_setup_arch(void) setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST); clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST); + + for (np = NULL; (np = of_find_compatible_node(np, + "network", + "ucc_geth")) != NULL;) { + const unsigned int *prop; + int ucc_num; + + prop = of_get_property(np, "cell-index", NULL); + if (prop == NULL) + continue; + + ucc_num = *prop - 1; + + prop = of_get_property(np, "phy-connection-type", NULL); + if (prop == NULL) + continue; + + if (strcmp("rtbi", (const char *)prop) == 0) + clrsetbits_8(&bcsr_regs[7 + ucc_num], + BCSR_UCC_RGMII, BCSR_UCC_RTBI); + } + } iounmap(bcsr_regs); } -- cgit v1.2.3 From 81abb43a243b6d74b6f7201a7a22aa5355cd3a8a Mon Sep 17 00:00:00 2001 From: Liu Yu-B13201 Date: Wed, 13 Jan 2010 22:13:18 +0000 Subject: ucc_geth: update the tbi-phy setting Old method only set tbi-phy for eth0. Signed-off-by: Liu Yu Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 96bdc0b43889..6750de10a087 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "ucc_geth.h" #include "fsl_pq_mdio.h" @@ -1334,7 +1335,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) struct ucc_geth __iomem *ug_regs; struct ucc_fast __iomem *uf_regs; int ret_val; - u32 upsmr, maccfg2, tbiBaseAddress; + u32 upsmr, maccfg2; u16 value; ugeth_vdbg("%s: IN", __func__); @@ -1389,14 +1390,20 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) /* Note that this depends on proper setting in utbipar register. */ if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { - tbiBaseAddress = in_be32(&ug_regs->utbipar); - tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; - tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; - value = ugeth->phydev->bus->read(ugeth->phydev->bus, - (u8) tbiBaseAddress, ENET_TBI_MII_CR); + struct ucc_geth_info *ug_info = ugeth->ug_info; + struct phy_device *tbiphy; + + if (!ug_info->tbi_node) + ugeth_warn("TBI mode requires that the device " + "tree specify a tbi-handle\n"); + + tbiphy = of_phy_find_device(ug_info->tbi_node); + if (!tbiphy) + ugeth_warn("Could not get TBI device\n"); + + value = phy_read(tbiphy, ENET_TBI_MII_CR); value &= ~0x1000; /* Turn off autonegotiation */ - ugeth->phydev->bus->write(ugeth->phydev->bus, - (u8) tbiBaseAddress, ENET_TBI_MII_CR, value); + phy_write(tbiphy, ENET_TBI_MII_CR, value); } init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); -- cgit v1.2.3 From 5f8cbc13225eadd981c817f7d14b8deab61ebfaa Mon Sep 17 00:00:00 2001 From: Liu Yu-B13201 Date: Wed, 13 Jan 2010 22:13:19 +0000 Subject: phy: add RTBI mode for m88e1111 Signed-off-by: Liu Yu Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 6f69b9ba0df8..65ed385c2ceb 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -63,6 +63,7 @@ #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 +#define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9 #define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 @@ -269,6 +270,43 @@ static int m88e1111_config_init(struct phy_device *phydev) return err; } + if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { + temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); + if (temp < 0) + return temp; + temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); + err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); + if (err < 0) + return err; + + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + if (temp < 0) + return temp; + temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); + temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; + err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + if (err < 0) + return err; + + /* soft reset */ + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + if (err < 0) + return err; + do + temp = phy_read(phydev, MII_BMCR); + while (temp & BMCR_RESET); + + temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); + if (temp < 0) + return temp; + temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); + temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; + err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); + if (err < 0) + return err; + } + + err = phy_write(phydev, MII_BMCR, BMCR_RESET); if (err < 0) return err; -- cgit v1.2.3 From 4b258461c0b31ded170a1a56b944b0fded1c887b Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 21 Jan 2010 01:26:29 -0800 Subject: net: Optimize non-gso test checks Avoid checking twice whether skb needs to be linearized, if one skb_linearize was already done. Signed-off-by: Krishna Kumar Signed-off-by: David S. Miller --- net/core/dev.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 5747b9edc1bb..4fad9db417b1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1982,6 +1982,21 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, return rc; } +/* + * Returns true if either: + * 1. skb has frag_list and the device doesn't support FRAGLIST, or + * 2. skb is fragmented and the device does not support SG, or if + * at least one of fragments is in highmem and device does not + * support DMA from it. + */ +static inline int skb_needs_linearize(struct sk_buff *skb, + struct net_device *dev) +{ + return (skb_has_frags(skb) && !(dev->features & NETIF_F_FRAGLIST)) || + (skb_shinfo(skb)->nr_frags && (!(dev->features & NETIF_F_SG) || + illegal_highdma(dev, skb))); +} + /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit @@ -2018,18 +2033,8 @@ int dev_queue_xmit(struct sk_buff *skb) if (netif_needs_gso(dev, skb)) goto gso; - if (skb_has_frags(skb) && - !(dev->features & NETIF_F_FRAGLIST) && - __skb_linearize(skb)) - goto out_kfree_skb; - - /* Fragmented skb is linearized if device does not support SG, - * or if at least one of fragments is in highmem and device - * does not support DMA from it. - */ - if (skb_shinfo(skb)->nr_frags && - (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && - __skb_linearize(skb)) + /* Convert a paged skb to linear, if required */ + if (skb_needs_linearize(skb, dev) && __skb_linearize(skb)) goto out_kfree_skb; /* If packet is not checksummed and device does not support -- cgit v1.2.3 From 17660f81243e998f36257881ac3ae61685bf91c1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 21 Jan 2010 01:28:45 -0800 Subject: vhost: fix TUN=m VHOST_NET=y drivers/built-in.o: In function `get_tun_socket': net.c:(.text+0x15436e): undefined reference to `tun_get_socket' If tun is a module, vhost must be a module, too. If tun is built-in or disabled, vhost can be built-in. Note: TUN || !TUN might look a bit strange until you realize that boolean logic rules do not apply for tristate variables. Reported-by: Randy Dunlap Signed-off-by: Michael S. Tsirkin Acked-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/vhost/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 9f409f447aea..9e9355367bb3 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -1,6 +1,6 @@ config VHOST_NET tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)" - depends on NET && EVENTFD && EXPERIMENTAL + depends on NET && EVENTFD && (TUN || !TUN) && EXPERIMENTAL ---help--- This kernel module can be loaded in host kernel to accelerate guest networking with virtio_net. Not to be confused with virtio_net -- cgit v1.2.3 From 09cb47a2c68f9596927bc05dab0453edb35cd32d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 21 Jan 2010 02:43:20 -0800 Subject: net/sctp: Eliminate useless code The variable newinet is initialized twice to the same (side effect-free) expression. Drop one initialization. A simplified version of the semantic match that finds this problem is: (http://coccinelle.lip6.fr/) // @forall@ idexpression *x; identifier f!=ERR_PTR; @@ x = f(...) ... when != x ( x = f(...,<+...x...+>,...) | * x = f(...) ) // Signed-off-by: Julia Lawall Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 67fdac9d2d33..f6d1e59c4151 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6359,7 +6359,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk, struct sctp_association *asoc) { struct inet_sock *inet = inet_sk(sk); - struct inet_sock *newinet = inet_sk(newsk); + struct inet_sock *newinet; newsk->sk_type = sk->sk_type; newsk->sk_bound_dev_if = sk->sk_bound_dev_if; -- cgit v1.2.3 From 8f47afe080df450eedda7b29873512c2a9a9adcb Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Tue, 19 Jan 2010 05:15:00 +0000 Subject: be2net: ethtool self test reorganization. The ddr dma ethtool self test needs to be performed even when ETH_TEST_FL_OFFLINE is not set. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index f18c02f3a5e4..2f2ebbd678f2 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -545,10 +545,11 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) &data[2]) != 0) { test->flags |= ETH_TEST_FL_FAILED; } + } - data[3] = be_test_ddr_dma(adapter); - if (data[3] != 0) - test->flags |= ETH_TEST_FL_FAILED; + if (be_test_ddr_dma(adapter) != 0) { + data[3] = 1; + test->flags |= ETH_TEST_FL_FAILED; } } -- cgit v1.2.3 From 4276e47e2d1c85a2477caf0d22b91c4f2377fba8 Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Tue, 19 Jan 2010 05:15:36 +0000 Subject: be2net: Add link test to list of ethtool self tests. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 2f2ebbd678f2..09d8899b2de9 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -112,6 +112,7 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = { "PHY Loopback test", "External Loopback test", "DDR DMA test" + "Link test" }; #define ETHTOOL_TESTS_NUM ARRAY_SIZE(et_self_tests) @@ -529,6 +530,9 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) { struct be_adapter *adapter = netdev_priv(netdev); + bool link_up; + u8 mac_speed = 0; + u16 qos_link_speed = 0; memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); @@ -552,6 +556,13 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) test->flags |= ETH_TEST_FL_FAILED; } + if (be_cmd_link_status_query(adapter, &link_up, &mac_speed, + &qos_link_speed) != 0) { + test->flags |= ETH_TEST_FL_FAILED; + data[4] = -1; + } else if (mac_speed) { + data[4] = 1; + } } static int -- cgit v1.2.3 From e4fca007b06165900d0e44e8d5e251376819bf5d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 22 Jan 2010 12:33:09 -0500 Subject: mac80211: avoid NULL ptr deref when using WEP "mac80211: move control.hw_key assignment" changed an if-else into two separate if statments, but the if-else is needed to prevent dereferencing a null info->control.hw_key. This fixes avoids a lock-up during association on my machine when using WEP. Signed-off-by: John W. Linville --- net/mac80211/wep.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 0a4c641c9605..5d745f2d7236 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -310,9 +310,8 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) tx->key->conf.keylen, tx->key->conf.keyidx)) return -1; - } - - if (info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) { + } else if (info->control.hw_key->flags & + IEEE80211_KEY_FLAG_GENERATE_IV) { if (!ieee80211_wep_add_iv(tx->local, skb, tx->key->conf.keylen, tx->key->conf.keyidx)) -- cgit v1.2.3 From b3fbdcf49f940d0703c356441e0daf045e64e076 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 11:40:47 +0100 Subject: mac80211: pass vif and station to update_tkip_key When a TKIP key is updated, we should pass the station pointer instead of just the address, since drivers can use that to store their own data. We also need to pass the virtual interface pointer. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 11 ++++++++--- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 +++++++--- include/net/mac80211.h | 6 ++++-- net/mac80211/driver-ops.h | 14 ++++++++++---- net/mac80211/driver-trace.h | 15 +++++++++------ net/mac80211/tkip.c | 12 +++++------- 6 files changed, 43 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c238468bca7f..c699e46534dc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -844,8 +844,10 @@ static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32, } static void b43_op_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_key_conf *keyconf, const u8 *addr, - u32 iv32, u16 *phase1key) + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { struct b43_wl *wl = hw_to_b43_wl(hw); struct b43_wldev *dev; @@ -863,7 +865,10 @@ static void b43_op_update_tkip_key(struct ieee80211_hw *hw, keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ rx_tkip_phase1_write(dev, index, iv32, phase1key); - keymac_write(dev, index, addr); + /* only pairwise TKIP keys are supported right now */ + if (WARN_ON(!sta)) + goto out_unlock; + keymac_write(dev, index, sta->addr); out_unlock: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8db86239bd6a..62b6939df52e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2839,14 +2839,18 @@ void iwl_config_ap(struct iwl_priv *priv) } static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_key_conf *keyconf, const u8 *addr, - u32 iv32, u16 *phase1key) + struct ieee80211_vif *vif, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key) { struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211(priv, "enter\n"); - iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); + iwl_update_tkip_key(priv, keyconf, + sta ? sta->addr : iwl_bcast_addr, + iv32, phase1key); IWL_DEBUG_MAC80211(priv, "leave\n"); } diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f03f97b627fe..f56d6f479532 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1614,8 +1614,10 @@ struct ieee80211_ops { struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); void (*update_tkip_key)(struct ieee80211_hw *hw, - struct ieee80211_key_conf *conf, const u8 *address, - u32 iv32, u16 *phase1key); + struct ieee80211_vif *vif, + struct ieee80211_key_conf *conf, + struct ieee80211_sta *sta, + u32 iv32, u16 *phase1key); int (*hw_scan)(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); void (*sw_scan_start)(struct ieee80211_hw *hw); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index de91d39e0276..40c6e9a89864 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -137,16 +137,22 @@ static inline int drv_set_key(struct ieee80211_local *local, } static inline void drv_update_tkip_key(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct ieee80211_key_conf *conf, - const u8 *address, u32 iv32, + struct sta_info *sta, u32 iv32, u16 *phase1key) { + struct ieee80211_sta *ista = NULL; + might_sleep(); + if (sta) + ista = &sta->sta; + if (local->ops->update_tkip_key) - local->ops->update_tkip_key(&local->hw, conf, address, - iv32, phase1key); - trace_drv_update_tkip_key(local, conf, address, iv32); + local->ops->update_tkip_key(&local->hw, &sdata->vif, conf, + ista, iv32, phase1key); + trace_drv_update_tkip_key(local, sdata, conf, ista, iv32); } static inline int drv_hw_scan(struct ieee80211_local *local, diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 0ea258123b8e..fefa6e6b01bc 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -331,26 +331,29 @@ TRACE_EVENT(drv_set_key, TRACE_EVENT(drv_update_tkip_key, TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct ieee80211_key_conf *conf, - const u8 *address, u32 iv32), + struct ieee80211_sta *sta, u32 iv32), - TP_ARGS(local, conf, address, iv32), + TP_ARGS(local, sdata, conf, sta, iv32), TP_STRUCT__entry( LOCAL_ENTRY - __array(u8, addr, 6) + VIF_ENTRY + STA_ENTRY __field(u32, iv32) ), TP_fast_assign( LOCAL_ASSIGN; - memcpy(__entry->addr, address, 6); + VIF_ASSIGN; + STA_ASSIGN; __entry->iv32 = iv32; ), TP_printk( - LOCAL_PR_FMT " addr:%pM iv32:%#x", - LOCAL_PR_ARG, __entry->addr, __entry->iv32 + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x", + LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32 ) ); diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 14fe49332c02..7ef491e9d66d 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -304,14 +304,12 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, if (key->local->ops->update_tkip_key && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { - static const u8 bcast[ETH_ALEN] = - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *sta_addr = key->sta->sta.addr; + struct ieee80211_sub_if_data *sdata = key->sdata; - if (is_multicast_ether_addr(ra)) - sta_addr = bcast; - - drv_update_tkip_key(key->local, &key->conf, sta_addr, + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(key->sdata->bss, + struct ieee80211_sub_if_data, u.ap); + drv_update_tkip_key(key->local, sdata, &key->conf, key->sta, iv32, key->u.tkip.rx[queue].p1k); key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; } -- cgit v1.2.3 From ef15aac6073b27fd4f70007784d2d52ed394bf43 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 20 Jan 2010 12:02:33 +0100 Subject: cfg80211: export multiple MAC addresses in sysfs If a device has multiple MAC addresses, userspace will need to know about that. Similarly, if it allows the MAC addresses to vary by a bitmask. If a driver exports multiple addresses, it is assumed that it will be able to deal with that many different addresses, which need not necessarily match the ones programmed into the device; if a mask is set then the device should deal addresses within that mask based on an arbitrary "base address". To test it all and show how it is used, add support to hwsim even though it can't actually deal with addresses different from the default. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 8 +++++++- include/net/cfg80211.h | 22 +++++++++++++++++++++- net/wireless/core.c | 12 ++++++++++++ net/wireless/sysfs.c | 20 ++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 84df3fcf37b3..0dbda8dfbd99 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -281,6 +281,8 @@ struct mac80211_hwsim_data { struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; + struct mac_address addresses[2]; + struct ieee80211_channel *channel; unsigned long beacon_int; /* in jiffies unit */ unsigned int rx_filter; @@ -1154,7 +1156,11 @@ static int __init init_mac80211_hwsim(void) SET_IEEE80211_DEV(hw, data->dev); addr[3] = i >> 8; addr[4] = i; - SET_IEEE80211_PERM_ADDR(hw, addr); + memcpy(data->addresses[0].addr, addr, ETH_ALEN); + memcpy(data->addresses[1].addr, addr, ETH_ALEN); + data->addresses[1].addr[0] |= 0x40; + hw->wiphy->n_addresses = 2; + hw->wiphy->addresses = data->addresses; hw->channel_change_time = 1; hw->queues = 4; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 2af52704e670..c5d16f299d6f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1195,6 +1195,10 @@ enum wiphy_flags { WIPHY_FLAG_4ADDR_STATION = BIT(6), }; +struct mac_address { + u8 addr[ETH_ALEN]; +}; + /** * struct wiphy - wireless hardware description * @idx: the wiphy index assigned to this item @@ -1213,12 +1217,28 @@ enum wiphy_flags { * -1 = fragmentation disabled, only odd values >= 256 used * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled * @net: the network namespace this wiphy currently lives in + * @perm_addr: permanent MAC address of this device + * @addr_mask: If the device supports multiple MAC addresses by masking, + * set this to a mask with variable bits set to 1, e.g. if the last + * four bits are variable then set it to 00:...:00:0f. The actual + * variable bits shall be determined by the interfaces added, with + * interfaces not matching the mask being rejected to be brought up. + * @n_addresses: number of addresses in @addresses. + * @addresses: If the device has more than one address, set this pointer + * to a list of addresses (6 bytes each). The first one will be used + * by default for perm_addr. In this case, the mask should be set to + * all-zeroes. In this case it is assumed that the device can handle + * the same number of arbitrary MAC addresses. */ struct wiphy { /* assign these fields before you register the wiphy */ - /* permanent MAC address */ + /* permanent MAC address(es) */ u8 perm_addr[ETH_ALEN]; + u8 addr_mask[ETH_ALEN]; + + u16 n_addresses; + struct mac_address *addresses; /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; diff --git a/net/wireless/core.c b/net/wireless/core.c index d07f57c906db..71b6b3a9cf1f 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -413,6 +413,18 @@ int wiphy_register(struct wiphy *wiphy) int i; u16 ifmodes = wiphy->interface_modes; + if (WARN_ON(wiphy->addresses && !wiphy->n_addresses)) + return -EINVAL; + + if (WARN_ON(wiphy->addresses && + !is_zero_ether_addr(wiphy->perm_addr) && + memcmp(wiphy->perm_addr, wiphy->addresses[0].addr, + ETH_ALEN))) + return -EINVAL; + + if (wiphy->addresses) + memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); + /* sanity check ifmodes */ WARN_ON(!ifmodes); ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index efe3c5c92b2d..9f2cef3e0ca0 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -33,10 +33,30 @@ static ssize_t name ## _show(struct device *dev, \ SHOW_FMT(index, "%d", wiphy_idx); SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); +SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); + +static ssize_t addresses_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; + char *start = buf; + int i; + + if (!wiphy->addresses) + return sprintf(buf, "%pM\n", wiphy->perm_addr); + + for (i = 0; i < wiphy->n_addresses; i++) + buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr); + + return buf - start; +} static struct device_attribute ieee80211_dev_attrs[] = { __ATTR_RO(index), __ATTR_RO(macaddress), + __ATTR_RO(address_mask), + __ATTR_RO(addresses), {} }; -- cgit v1.2.3 From d0dd2de0d055f0ffb1e2ecdc21380de9d12a85e2 Mon Sep 17 00:00:00 2001 From: Andriy Tkachuk Date: Wed, 20 Jan 2010 13:55:06 +0200 Subject: mac80211: Account HT Control field in Data frame hdrlen according to 802.11n-2009 ieee80211_hdrlen() should account account new HT Control field in 802.11 data frame header introduced by IEEE 802.11n standard. According to 802.11n-2009 HT Control field is present in data frames when both of following are met: 1. It is QoS data frame. 2. Order bit is set in Frame Control field. The change might be totally compatible with legacy non-11n aware frames, because 802.11-2007 standard states that "all QoS STAs set this subfield to 0". Signed-off-by: Andriy V. Tkachuk Acked-by : Benoit Papillault Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 2 ++ net/wireless/util.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 842701906ae9..19984958ab7b 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -138,6 +138,8 @@ #define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x03 #define IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT 5 +#define IEEE80211_HT_CTL_LEN 4 + struct ieee80211_hdr { __le16 frame_control; __le16 duration_id; diff --git a/net/wireless/util.c b/net/wireless/util.c index 23557c1d0a9c..be2ab8c59e3a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -227,8 +227,11 @@ unsigned int ieee80211_hdrlen(__le16 fc) if (ieee80211_is_data(fc)) { if (ieee80211_has_a4(fc)) hdrlen = 30; - if (ieee80211_is_data_qos(fc)) + if (ieee80211_is_data_qos(fc)) { hdrlen += IEEE80211_QOS_CTL_LEN; + if (ieee80211_has_order(fc)) + hdrlen += IEEE80211_HT_CTL_LEN; + } goto out; } -- cgit v1.2.3 From 5d6ce628f986d1a3c523cbb0a5a52095c48cc332 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 20 Jan 2010 23:51:03 -0500 Subject: ath5k: dont use external sleep clock in AP mode When using the external sleep clock in AP mode, the TSF increments too quickly, causing beacon interval to be much lower than it is supposed to be, resulting in lots of beacon-not-ready interrupts. This fixes http://bugzilla.kernel.org/show_bug.cgi?id=14802. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/reset.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 6690923fd78c..a35a7db0fc4c 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -1374,8 +1374,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, * Set clocks to 32KHz operation and use an * external 32KHz crystal when sleeping if one * exists */ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_set_sleep_clock(ah, true); + if (ah->ah_version == AR5K_AR5212 && + ah->ah_op_mode != NL80211_IFTYPE_AP) + ath5k_hw_set_sleep_clock(ah, true); /* * Disable beacons and reset the register -- cgit v1.2.3 From a951ae2176b982574ffa197455db6c89359fd5eb Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 20 Jan 2010 23:51:04 -0500 Subject: ath5k: fix setup for CAB queue The beacon sent gating doesn't seem to work with any combination of flags. Thus, buffered frames tend to stay buffered forever, using up tx descriptors. Instead, use the DBA gating and hold transmission of the buffered frames until 80% of the beacon interval has elapsed using the ready time. This fixes the following error in AP mode: ath5k phy0: no further txbuf available, dropping packet Add a comment to acknowledge that this isn't the best solution. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/base.c | 22 +++++++++++++++++++--- drivers/net/wireless/ath/ath5k/qcu.c | 5 +++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 66bcb506a112..ad4d446f0264 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -535,7 +535,7 @@ struct ath5k_txq_info { u32 tqi_cbr_period; /* Constant bit rate period */ u32 tqi_cbr_overflow_limit; u32 tqi_burst_time; - u32 tqi_ready_time; /* Not used */ + u32 tqi_ready_time; /* Time queue waits after an event */ }; /* diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b5015376d4ba..535a6afb94e3 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1516,7 +1516,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc) ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); if (ret) - return ret; + goto err; + if (sc->opmode == NL80211_IFTYPE_AP || sc->opmode == NL80211_IFTYPE_MESH_POINT) { /* @@ -1543,10 +1544,25 @@ ath5k_beaconq_config(struct ath5k_softc *sc) if (ret) { ATH5K_ERR(sc, "%s: unable to update parameters for beacon " "hardware queue!\n", __func__); - return ret; + goto err; } + ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */ + if (ret) + goto err; - return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; + /* reconfigure cabq with ready time to 80% of beacon_interval */ + ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); + if (ret) + goto err; + + qi.tqi_ready_time = (sc->bintval * 80) / 100; + ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); + if (ret) + goto err; + + ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB); +err: + return ret; } static void diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index abe36c0d139c..9122a8556f45 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c @@ -408,12 +408,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) break; case AR5K_TX_QUEUE_CAB: + /* XXX: use BCN_SENT_GT, if we can figure out how */ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | + AR5K_QCU_MISC_FRSHED_DBA_GT | AR5K_QCU_MISC_CBREXP_DIS | AR5K_QCU_MISC_CBREXP_BCN_DIS); - ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - + ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - (AR5K_TUNE_SW_BEACON_RESP - AR5K_TUNE_DMA_BEACON_RESP) - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | -- cgit v1.2.3 From 58da1318ee92ad3fe7917278d596768bbe441850 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 21 Jan 2010 11:17:27 +0530 Subject: ath9k: Fix wifi disconnection when collocated bt scan is active As all bt packets are priority traffic during bt scan, wifi will get disconnected when bt scan lasts for few seconds. Fix this by allocating 10% of bt period time (4.5ms) to wifi fully. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/btcoex.h | 2 ++ drivers/net/wireless/ath/ath9k/gpio.c | 30 ++++++++++++++++++++++-------- drivers/net/wireless/ath/ath9k/reg.h | 6 +++--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bf3d4c4bfa52..bdbcc70df075 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -364,6 +364,7 @@ struct ath_btcoex { int bt_stomp_type; /* Types of BT stomping */ u32 btcoex_no_stomp; /* in usec */ u32 btcoex_period; /* in usec */ + u32 btscan_no_stomp; /* in usec */ struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ }; @@ -429,6 +430,7 @@ void ath_deinit_leds(struct ath_softc *sc); #define SC_OP_SCANNING BIT(10) #define SC_OP_TSF_RESET BIT(11) #define SC_OP_BT_PRIORITY_DETECTED BIT(12) +#define SC_OP_BT_SCAN BIT(13) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 1ba31a73317c..1ee5a15ccbb1 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -25,10 +25,12 @@ #define ATH_BTCOEX_DEF_BT_PERIOD 45 #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 +#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90 #define ATH_BTCOEX_BMISS_THRESH 50 #define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */ #define ATH_BT_CNT_THRESHOLD 3 +#define ATH_BT_CNT_SCAN_THRESHOLD 15 enum ath_btcoex_scheme { ATH_BTCOEX_CFG_NONE, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index e204bd25ff65..deab8beb0680 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -230,12 +230,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc) if (time_after(jiffies, btcoex->bt_priority_time + msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { - if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { + sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); + /* Detect if colocated bt started scanning */ + if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { + ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, + "BT scan detected"); + sc->sc_flags |= (SC_OP_BT_SCAN | + SC_OP_BT_PRIORITY_DETECTED); + } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, "BT priority traffic detected"); sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; - } else { - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; } btcoex->bt_priority_cnt = 0; @@ -316,12 +321,17 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_softc *sc = (struct ath_softc *) data; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; + u32 timer_period; + bool is_btscan; ath_detect_bt_priority(sc); + is_btscan = sc->sc_flags & SC_OP_BT_SCAN; + spin_lock_bh(&btcoex->btcoex_lock); - ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); + ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : + btcoex->bt_stomp_type); spin_unlock_bh(&btcoex->btcoex_lock); @@ -329,11 +339,12 @@ static void ath_btcoex_period_timer(unsigned long data) if (btcoex->hw_timer_enabled) ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); + timer_period = is_btscan ? btcoex->btscan_no_stomp : + btcoex->btcoex_no_stomp; ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, (ath9k_hw_gettsf32(ah) + - btcoex->btcoex_no_stomp), - btcoex->btcoex_no_stomp * 10); + timer_period), timer_period * 10); btcoex->hw_timer_enabled = true; } @@ -350,13 +361,14 @@ static void ath_btcoex_no_stomp_timer(void *arg) struct ath_softc *sc = (struct ath_softc *)arg; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; + bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "no stomp timer running \n"); spin_lock_bh(&btcoex->btcoex_lock); - if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) + if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); @@ -371,6 +383,8 @@ int ath_init_btcoex_timer(struct ath_softc *sc) btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * btcoex->btcoex_period / 100; + btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * + btcoex->btcoex_period / 100; setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, (unsigned long) sc); @@ -405,7 +419,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; + sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); mod_timer(&btcoex->period_timer, jiffies); } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 8e653fb937a1..72cfa8ebd9ae 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -1547,9 +1547,9 @@ enum { #define AR_BT_COEX_WEIGHT 0x8174 #define AR_BT_COEX_WGHT 0xff55 -#define AR_STOMP_ALL_WLAN_WGHT 0xffcc -#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8 -#define AR_STOMP_NONE_WLAN_WGHT 0xaa00 +#define AR_STOMP_ALL_WLAN_WGHT 0xfcfc +#define AR_STOMP_LOW_WLAN_WGHT 0xa8a8 +#define AR_STOMP_NONE_WLAN_WGHT 0x0000 #define AR_BTCOEX_BT_WGHT 0x0000ffff #define AR_BTCOEX_BT_WGHT_S 0 #define AR_BTCOEX_WL_WGHT 0xffff0000 -- cgit v1.2.3 From 4bb29f8c390fb7be207ec3f11b9d30ccdf1cb6ac Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 22 Jan 2010 00:36:39 +0100 Subject: mac80211: fix rx data handling for non-data frames on multiple vifs The loop that passes non-data frames to all relevant vifs inside the __ieee80211_rx_handle_packet keeps a pointer to the previous sdata to avoid having to make unnecessary copies of the frame it's handling. This led to a bug that caused it to apply the ieee80211_rx_data state to the wrong interface, thereby either missing the rx.sta pointer or having it assigned where it shouldn't be. This breaks (among other things) aggregation on some vifs, as action frame exchages are dropped to the cooked monitor interface due to rx->sta being NULL. Fix this by restructuring the loop so that it prepares the rx data just before making the skb copy and calling the rx handlers. Cc: stable@kernel.org Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rx.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a8e15b84c05b..7e0b3e340389 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2348,22 +2348,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, sdata->vif.type == NL80211_IFTYPE_AP_VLAN) continue; - rx.sta = sta_info_get(sdata, hdr->addr2); - - rx.flags |= IEEE80211_RX_RA_MATCH; - prepares = prepare_for_handlers(sdata, &rx, hdr); - - if (!prepares) - continue; - - if (status->flag & RX_FLAG_MMIC_ERROR) { - rx.sdata = sdata; - if (rx.flags & IEEE80211_RX_RA_MATCH) - ieee80211_rx_michael_mic_report(hdr, - &rx); - continue; - } - /* * frame is destined for this interface, but if it's * not also for the previous one we handle that after @@ -2375,6 +2359,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } + rx.sta = sta_info_get(prev, hdr->addr2); + + rx.flags |= IEEE80211_RX_RA_MATCH; + prepares = prepare_for_handlers(prev, &rx, hdr); + + if (!prepares) + goto next; + + if (status->flag & RX_FLAG_MMIC_ERROR) { + rx.sdata = prev; + if (rx.flags & IEEE80211_RX_RA_MATCH) + ieee80211_rx_michael_mic_report(hdr, + &rx); + goto next; + } + /* * frame was destined for the previous interface * so invoke RX handlers for it @@ -2387,11 +2387,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, "multicast frame for %s\n", wiphy_name(local->hw.wiphy), prev->name); - continue; + goto next; } ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); +next: prev = sdata; } + + if (prev) { + rx.sta = sta_info_get(prev, hdr->addr2); + + rx.flags |= IEEE80211_RX_RA_MATCH; + prepares = prepare_for_handlers(prev, &rx, hdr); + + if (!prepares) + prev = NULL; + } } if (prev) ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); -- cgit v1.2.3 From aa4c7b2a2547db95388f795f092ea286fbdd98a1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2010 01:53:12 +0100 Subject: b43: check band width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 6 ++++++ drivers/net/wireless/b43/phy_common.h | 3 +++ drivers/net/wireless/b43/phy_n.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c699e46534dc..6d7cf3c2f7bf 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3576,6 +3576,12 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) dev = wl->current_dev; phy = &dev->phy; + if (conf_is_ht(conf)) + phy->is_40mhz = + (conf_is_ht40_minus(conf) || conf_is_ht40_plus(conf)); + else + phy->is_40mhz = false; + b43_mac_suspend(dev); if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 9edd4e8e0c85..f635f9e4f83d 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -212,6 +212,9 @@ struct b43_phy { bool supports_2ghz; bool supports_5ghz; + /* HT info */ + bool is_40mhz; + /* GMODE bit enabled? */ bool gmode; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e77f1f24d101..2cdf32e5fd9b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1787,7 +1787,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); - if (1 /* FIXME: the band width is 20 MHz */) + if (!dev->phy.is_40mhz) freq = 2500; else freq = 5000; -- cgit v1.2.3 From 75377b2476d85d90c0db07e780ee95741cff3a2d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2010 01:53:13 +0100 Subject: b43: N-PHY: implement overriding RF control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 82 ++++++++++++++++++++++++++++++++-- drivers/net/wireless/b43/tables_nphy.c | 37 +++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 21 +++++++++ 3 files changed, 137 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 2cdf32e5fd9b..d3c9783b76ba 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -912,6 +912,82 @@ ok: b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ +static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, + u16 value, u8 core, bool off) +{ + int i; + u8 index = fls(field); + u8 addr, en_addr, val_addr; + /* we expect only one bit set */ + B43_WARN_ON(field & (~(1 << index))); + + if (dev->phy.rev >= 3) { + const struct nphy_rf_control_override_rev3 *rf_ctrl; + for (i = 0; i < 2; i++) { + if (index == 0 || index == 16) { + b43err(dev->wl, + "Unsupported RF Ctrl Override call\n"); + return; + } + + rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; + en_addr = B43_PHY_N((i == 0) ? + rf_ctrl->en_addr0 : rf_ctrl->en_addr1); + val_addr = B43_PHY_N((i == 0) ? + rf_ctrl->val_addr0 : rf_ctrl->val_addr1); + + if (off) { + b43_phy_mask(dev, en_addr, ~(field)); + b43_phy_mask(dev, val_addr, + ~(rf_ctrl->val_mask)); + } else { + if (core == 0 || ((1 << core) & i) != 0) { + b43_phy_set(dev, en_addr, field); + b43_phy_maskset(dev, val_addr, + ~(rf_ctrl->val_mask), + (value << rf_ctrl->val_shift)); + } + } + } + } else { + const struct nphy_rf_control_override_rev2 *rf_ctrl; + if (off) { + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field)); + value = 0; + } else { + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field); + } + + for (i = 0; i < 2; i++) { + if (index <= 1 || index == 16) { + b43err(dev->wl, + "Unsupported RF Ctrl Override call\n"); + return; + } + + if (index == 2 || index == 10 || + (index >= 13 && index <= 15)) { + core = 1; + } + + rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; + addr = B43_PHY_N((i == 0) ? + rf_ctrl->addr0 : rf_ctrl->addr1); + + if ((core & (1 << i)) != 0) + b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask), + (value << rf_ctrl->shift)); + + b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_START); + udelay(1); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE); + } + } +} + static void b43_nphy_bphy_init(struct b43_wldev *dev) { unsigned int i; @@ -2075,8 +2151,8 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | (cur_lna << 2)); - /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], - 3, 0 as arguments */ + b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3, + false); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); b43_nphy_stop_playback(dev); @@ -2124,7 +2200,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, break; } - /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ + b43_nphy_rf_control_override(dev, 0x400, 0, 3, true); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index b8c9fc619ab1..dd9687d611d7 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2883,6 +2883,43 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x9084, 0x9267, 0x9056, 0x9234 }; +/* addr0, addr1, bmask, shift */ +const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[] = { + { 0x78, 0x78, 0x0038, 3 }, /* for field == 0x0002 (fls == 2) */ + { 0x7A, 0x7D, 0x0001, 0 }, /* for field == 0x0004 (fls == 3) */ + { 0x7A, 0x7D, 0x0002, 1 }, /* for field == 0x0008 (fls == 4) */ + { 0x7A, 0x7D, 0x0004, 2 }, /* for field == 0x0010 (fls == 5) */ + { 0x7A, 0x7D, 0x0030, 4 }, /* for field == 0x0020 (fls == 6) */ + { 0x7A, 0x7D, 0x00C0, 6 }, /* for field == 0x0040 (fls == 7) */ + { 0x7A, 0x7D, 0x0100, 8 }, /* for field == 0x0080 (fls == 8) */ + { 0x7A, 0x7D, 0x0200, 9 }, /* for field == 0x0100 (fls == 9) */ + { 0x78, 0x78, 0x0004, 2 }, /* for field == 0x0200 (fls == 10) */ + { 0x7B, 0x7E, 0x01FF, 0 }, /* for field == 0x0400 (fls == 11) */ + { 0x7C, 0x7F, 0x01FF, 0 }, /* for field == 0x0800 (fls == 12) */ + { 0x78, 0x78, 0x0100, 8 }, /* for field == 0x1000 (fls == 13) */ + { 0x78, 0x78, 0x0200, 9 }, /* for field == 0x2000 (fls == 14) */ + { 0x78, 0x78, 0xF000, 12 } /* for field == 0x4000 (fls == 15) */ +}; + +/* val_mask, val_shift, en_addr0, val_addr0, en_addr1, val_addr1 */ +const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = { + { 0x8000, 15, 0xE5, 0xF9, 0xE6, 0xFB }, /* field == 0x0001 (fls 1) */ + { 0x0001, 0, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0002 (fls 2) */ + { 0x0002, 1, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0004 (fls 3) */ + { 0x0004, 2, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0008 (fls 4) */ + { 0x0016, 4, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0010 (fls 5) */ + { 0x0020, 5, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0020 (fls 6) */ + { 0x0040, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0040 (fls 7) */ + { 0x0080, 6, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0080 (fls 8) */ + { 0x0100, 7, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0100 (fls 9) */ + { 0x0007, 0, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0200 (fls 10) */ + { 0x0070, 4, 0xE7, 0xF8, 0xEC, 0xFA }, /* field == 0x0400 (fls 11) */ + { 0xE000, 13, 0xE7, 0x7A, 0xEC, 0x7D }, /* field == 0x0800 (fls 12) */ + { 0xFFFF, 0, 0xE7, 0x7B, 0xEC, 0x7E }, /* field == 0x1000 (fls 13) */ + { 0xFFFF, 0, 0xE7, 0x7C, 0xEC, 0x7F }, /* field == 0x2000 (fls 14) */ + { 0x00C0, 6, 0xE7, 0xF9, 0xEC, 0xFB } /* field == 0x4000 (fls 15) */ +}; + static inline void assert_ntab_array_sizes(void) { #undef check diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 6bbef894010c..5d38172a152d 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -51,6 +51,22 @@ struct nphy_txiqcal_ladder { u8 g_env; }; +struct nphy_rf_control_override_rev2 { + u8 addr0; + u8 addr1; + u16 bmask; + u8 shift; +}; + +struct nphy_rf_control_override_rev3 { + u16 val_mask; + u8 val_shift; + u8 en_addr0; + u8 val_addr0; + u8 en_addr1; + u8 val_addr1; +}; + /* Upload the default register value table. * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz * table is uploaded. If "ignore_uploadflag" is true, we upload any value @@ -178,4 +194,9 @@ extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; +extern const struct nphy_rf_control_override_rev2 + tbl_rf_control_override_rev2[]; +extern const struct nphy_rf_control_override_rev3 + tbl_rf_control_override_rev3[]; + #endif /* B43_TABLES_NPHY_H_ */ -- cgit v1.2.3 From 10a798733e0f47923a1050231d8d39609c62be70 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2010 01:53:14 +0100 Subject: b43: N-PHY: add running samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 68 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d3c9783b76ba..f5900f04ff5c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -816,6 +816,66 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ +static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, + u16 wait, bool iqmode, bool dac_test) +{ + struct b43_phy_n *nphy = dev->phy.n; + int i; + u16 seq_mode; + u32 tmp; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + + if ((nphy->bb_mult_save & 0x80000000) == 0) { + tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); + nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; + } + + if (!dev->phy.is_40mhz) + tmp = 0x6464; + else + tmp = 0x4747; + b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); + + b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1)); + + if (loops != 0xFFFF) + b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1)); + else + b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops); + + b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait); + + seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); + + b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER); + if (iqmode) { + b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); + b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000); + } else { + if (dac_test) + b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5); + else + b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1); + } + for (i = 0; i < 100; i++) { + if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) { + i = 0; + break; + } + udelay(10); + } + if (i) + b43err(dev->wl, "run samples timeout\n"); + + b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) { @@ -1869,8 +1929,8 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, freq = 5000; if (nphy->mphase_cal_phase_id > 2) - ;/* TODO: Call N PHY Run Samples with (band width * 8), - 0xFFFF, 0, 1, 0 as arguments */ + b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8, + 0xFFFF, 0, true, false); else ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments and save result as error */ @@ -2162,8 +2222,8 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, as arguments and save result as ret */ playtone = false; } else { - /* TODO: Call N PHY Run Samples with 160, - 0xFFFF, 0, 0, 0 as arguments */ + b43_nphy_run_samples(dev, 160, 0xFFFF, 0, + false, false); } if (ret == 0) { -- cgit v1.2.3 From 45ca697e60eb5d3cac4530ae3a88f96c297efb09 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2010 01:53:15 +0100 Subject: b43: N-PHY: add setting power amplifier filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 41 ++++++++++++++++++++++++++++++++-- drivers/net/wireless/b43/tables_nphy.c | 24 ++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.h | 1 + 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index f5900f04ff5c..97a44e43d057 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1628,6 +1628,43 @@ static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ +static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) +{ + int i; + for (i = 0; i < 15; i++) + b43_phy_write(dev, B43_PHY_N(0x2C5 + i), + tbl_tx_filter_coef_rev4[2][i]); +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ +static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) +{ + int i, j; + /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ + u16 offset[] = { 0x186, 0x195, 0x2C5 }; + + for (i = 0; i < 3; i++) + for (j = 0; j < 15; j++) + b43_phy_write(dev, B43_PHY_N(offset[i] + j), + tbl_tx_filter_coef_rev4[i][j]); + + if (dev->phy.is_40mhz) { + for (j = 0; j < 15; j++) + b43_phy_write(dev, B43_PHY_N(offset[0] + j), + tbl_tx_filter_coef_rev4[3][j]); + } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + for (j = 0; j < 15; j++) + b43_phy_write(dev, B43_PHY_N(offset[0] + j), + tbl_tx_filter_coef_rev4[5][j]); + } + + if (dev->phy.channel == 14) + for (j = 0; j < 15; j++) + b43_phy_write(dev, B43_PHY_N(offset[0] + j), + tbl_tx_filter_coef_rev4[6][j]); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) { @@ -2371,9 +2408,9 @@ int b43_phy_initn(struct b43_wldev *dev) b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, nphy->papd_epsilon_offset[1] << 7); - /* TODO N PHY IPA Set TX Dig Filters */ + b43_nphy_int_pa_set_tx_dig_filters(dev); } else if (phy->rev >= 5) { - /* TODO N PHY Ext PA Set TX Dig Filters */ + b43_nphy_ext_pa_set_tx_dig_filters(dev); } b43_nphy_workarounds(dev); diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index dd9687d611d7..a00d509150f7 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -2883,6 +2883,30 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x9084, 0x9267, 0x9056, 0x9234 }; +const s16 tbl_tx_filter_coef_rev4[7][15] = { + { -377, 137, -407, 208, -1527, + 956, 93, 186, 93, 230, + -44, 230, 20, -191, 201 }, + { -77, 20, -98, 49, -93, + 60, 56, 111, 56, 26, + -5, 26, 34, -32, 34 }, + { -360, 164, -376, 164, -1533, + 576, 308, -314, 308, 121, + -73, 121, 91, 124, 91 }, + { -295, 200, -363, 142, -1391, + 826, 151, 301, 151, 151, + 301, 151, 602, -752, 602 }, + { -92, 58, -96, 49, -104, + 44, 17, 35, 17, 12, + 25, 12, 13, 27, 13 }, + { -375, 136, -399, 209, -1479, + 949, 130, 260, 130, 230, + -44, 230, 201, -191, 201 }, + { 0xed9, 0xc8, 0xe95, 0x8e, 0xa91, + 0x33a, 0x97, 0x12d, 0x97, 0x97, + 0x12d, 0x97, 0x25a, 0xd10, 0x25a } +}; + /* addr0, addr1, bmask, shift */ const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[] = { { 0x78, 0x78, 0x0038, 3 }, /* for field == 0x0002 (fls == 2) */ diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 5d38172a152d..9c1c6ecd3672 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -193,6 +193,7 @@ extern const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[]; extern const u16 tbl_tx_iqlo_cal_cmds_recal[]; extern const u16 tbl_tx_iqlo_cal_cmds_fullcal[]; extern const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[]; +extern const s16 tbl_tx_filter_coef_rev4[7][15]; extern const struct nphy_rf_control_override_rev2 tbl_rf_control_override_rev2[]; -- cgit v1.2.3 From 59af099b1956086b06c0d0f32ea99ce136b415b7 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2010 01:53:16 +0100 Subject: b43: N-PHY: add TX tone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 60 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 97a44e43d057..a45a1f3ced42 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -816,6 +816,43 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ +static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, + bool test) +{ + int i; + u16 bw, len, num, rot, angle; + /* TODO: *buffer; */ + + bw = (dev->phy.is_40mhz) ? 40 : 20; + len = bw << 3; + + if (test) { + if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX) + bw = 82; + else + bw = 80; + + if (dev->phy.is_40mhz) + bw <<= 1; + + len = bw << 1; + } + + /* TODO: buffer = kzalloc(len * sizeof(u32), GFP_KERNEL); */ + num = len; + rot = (((freq * 36) / bw) << 16) / 100; + angle = 0; + + for (i = 0; i < num; i++) { + /* TODO */ + } + + /* TODO: Call N PHY Load Sample Table with buffer, num as arguments */ + /* TODO: kfree(buffer); */ + return num; +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, u16 wait, bool iqmode, bool dac_test) @@ -876,6 +913,20 @@ static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); } +/* + * Transmits a known value for LO calibration + * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone + */ +static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, + bool iqmode, bool dac_test) +{ + u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); + if (samp == 0) + return -1; + b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test); + return 0; +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) { @@ -1969,8 +2020,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8, 0xFFFF, 0, true, false); else - ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments - and save result as error */ + error = b43_nphy_tx_tone(dev, freq, 250, true, false); if (error == 0) { if (nphy->mphase_cal_phase_id > 2) { @@ -2254,9 +2304,9 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, b43_nphy_stop_playback(dev); if (playtone) { - /* TODO: Call N PHY TX Tone with 4000, - (nphy_rxcalparams & 0xffff), 0, 0 - as arguments and save result as ret */ + ret = b43_nphy_tx_tone(dev, 4000, + (nphy->rxcalparams & 0xFFFF), + false, false); playtone = false; } else { b43_nphy_run_samples(dev, 160, 0xFFFF, 0, -- cgit v1.2.3 From b92f7d30830a319148df2943b7565989494e5ad1 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 22 Jan 2010 08:01:11 +0100 Subject: p54pci: revise tx locking This patch continues the effort which began with: "[PATCH] p54pci: move tx cleanup into tasklet". Thanks to these changes, p54pci's interrupt & tx cleanup routines can be made lock-less. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 48cae48ed6eb..bda29c00f3ef 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -238,7 +238,6 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, int ring_index, struct p54p_desc *ring, u32 ring_limit, struct sk_buff **tx_buf) { - unsigned long flags; struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; struct p54p_desc *desc; @@ -249,7 +248,6 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); idx %= ring_limit; - spin_lock_irqsave(&priv->lock, flags); while (i != idx) { desc = &ring[i]; @@ -264,16 +262,12 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, desc->len = 0; desc->flags = 0; - if (skb && FREE_AFTER_TX(skb)) { - spin_unlock_irqrestore(&priv->lock, flags); + if (skb && FREE_AFTER_TX(skb)) p54_free_skb(dev, skb); - spin_lock_irqsave(&priv->lock, flags); - } i++; i %= ring_limit; } - spin_unlock_irqrestore(&priv->lock, flags); } static void p54p_tasklet(unsigned long dev_id) @@ -306,7 +300,6 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) struct p54p_priv *priv = dev->priv; __le32 reg; - spin_lock(&priv->lock); reg = P54P_READ(int_ident); if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { goto out; @@ -321,15 +314,14 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) complete(&priv->boot_comp); out: - spin_unlock(&priv->lock); return reg ? IRQ_HANDLED : IRQ_NONE; } static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { + unsigned long flags; struct p54p_priv *priv = dev->priv; struct p54p_ring_control *ring_control = priv->ring_control; - unsigned long flags; struct p54p_desc *desc; dma_addr_t mapping; u32 device_idx, idx, i; @@ -370,14 +362,14 @@ static void p54p_stop(struct ieee80211_hw *dev) unsigned int i; struct p54p_desc *desc; - tasklet_kill(&priv->tasklet); - P54P_WRITE(int_enable, cpu_to_le32(0)); P54P_READ(int_enable); udelay(10); free_irq(priv->pdev->irq, dev); + tasklet_kill(&priv->tasklet); + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { -- cgit v1.2.3 From 477781477a88f60c89003c852def4aedc6f78101 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 22:21:18 +0100 Subject: netfiltr: ipt_CLUSTERIP: simplify seq_file codeA Pass "struct clusterip_config" itself to seq_file iterators and save one dereference. Proc entry itself isn't interesting. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ipt_CLUSTERIP.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 40ca2d240abb..0886f96c736b 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -560,8 +560,7 @@ struct clusterip_seq_position { static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) { - const struct proc_dir_entry *pde = s->private; - struct clusterip_config *c = pde->data; + struct clusterip_config *c = s->private; unsigned int weight; u_int32_t local_nodes; struct clusterip_seq_position *idx; @@ -632,10 +631,9 @@ static int clusterip_proc_open(struct inode *inode, struct file *file) if (!ret) { struct seq_file *sf = file->private_data; - struct proc_dir_entry *pde = PDE(inode); - struct clusterip_config *c = pde->data; + struct clusterip_config *c = PDE(inode)->data; - sf->private = pde; + sf->private = c; clusterip_config_get(c); } @@ -645,8 +643,7 @@ static int clusterip_proc_open(struct inode *inode, struct file *file) static int clusterip_proc_release(struct inode *inode, struct file *file) { - struct proc_dir_entry *pde = PDE(inode); - struct clusterip_config *c = pde->data; + struct clusterip_config *c = PDE(inode)->data; int ret; ret = seq_release(inode, file); @@ -660,10 +657,9 @@ static int clusterip_proc_release(struct inode *inode, struct file *file) static ssize_t clusterip_proc_write(struct file *file, const char __user *input, size_t size, loff_t *ofs) { + struct clusterip_config *c = PDE(file->f_path.dentry->d_inode)->data; #define PROC_WRITELEN 10 char buffer[PROC_WRITELEN+1]; - const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); - struct clusterip_config *c = pde->data; unsigned long nodenum; if (copy_from_user(buffer, input, PROC_WRITELEN)) -- cgit v1.2.3 From f12553ebe045a8a40ab33fa500fb57d10706e226 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 22:07:59 +0100 Subject: mac80211: add missing key check ieee80211_tx_h_select_key might decide that a frame need not be encrypted at all, in which case it will clear tx->key. In that case it may crash if a key was previously selected, e.g. as the default key. This is also due to my patch "mac80211: move control.hw_key assignment". Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index da557b0d0114..fcfa988a37a3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -557,7 +557,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) break; } - if (!skip_hw && + if (!skip_hw && tx->key && tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE) info->control.hw_key = &tx->key->conf; } -- cgit v1.2.3 From 1ada1b1b41b0e54291aca67eed4bd42e61e7e529 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:45:43 +0000 Subject: ixgbe: Set the correct pool when VLANs are added in SR-IOV mode. When VFs are allocated (as indicated by adapter->num_vfs is non-zero) then the PF pool is no longer zero. Instead it will be the same as the number of VFs allocated. When setting the VLVF entry for the PF we need to use the correct pool otherwise the PF will get VLAN packets from the wire because the packet will pass VFTA filtering and the PF has the default pool, but it will not get VLAN packets from the VFs because it has not set the correct pool bit in the VLVF entry. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index c46252520d7a..b8fd81748602 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2432,15 +2432,17 @@ static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + int pool_ndx = adapter->num_vfs; /* add VID to filter table */ - hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true); + hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, true); } static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + int pool_ndx = adapter->num_vfs; if (!test_bit(__IXGBE_DOWN, &adapter->state)) ixgbe_irq_disable(adapter); @@ -2451,7 +2453,7 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) ixgbe_irq_enable(adapter); /* remove VID from filter table */ - hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false); + hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false); } static void ixgbe_vlan_rx_register(struct net_device *netdev, -- cgit v1.2.3 From ef291b8c71ee934d077676b891494c50e17ccc28 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:46:02 +0000 Subject: ixgbe: Remove unused emulation MAC storage from the per VF data structure. This data storage for SW emulated MAC addresses is unlikely to ever be used so pull it. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index db64f139f173..e576fb4740bc 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -110,7 +110,6 @@ struct vf_data_storage { u16 num_vf_mc_hashes; u16 default_vf_vlan_id; u16 vlans_enabled; - unsigned char em_mac_addresses[MAX_EMULATION_MAC_ADDRS * ETH_ALEN]; bool clear_to_send; int rar; }; -- cgit v1.2.3 From c9205697c7527173c8f8bfa9f8c9dabdbced3c49 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:46:22 +0000 Subject: ixgbe: Allow the VF driver to be loaded before the PF driver The PF Reset Done bit should not be set in the extended control register until the PF has actually completed the bring up process. It is a mis- interpretation of the purpose of this bit to assume it should be set when the physical reset of the device is done. Instead it should be used to indicate to the VFs when the PF is ready to provide them with required services. This is not until after the PF is finished coming up and ready to process mailbox events. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 6 +----- drivers/net/ixgbe/ixgbe_main.c | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index c92b5b8b3181..d4ed6adb7975 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -890,7 +890,7 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) { s32 status = 0; - u32 ctrl, ctrl_ext; + u32 ctrl; u32 i; u32 autoc; u32 autoc2; @@ -945,10 +945,6 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) status = IXGBE_ERR_RESET_FAILED; hw_dbg(hw, "Reset polling failed to complete.\n"); } - /* Clear PF Reset Done bit so PF/VF Mail Ops can work */ - ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); - ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; - IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); msleep(50); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b8fd81748602..b96afd98fa3d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2826,6 +2826,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) u32 txdctl, rxdctl, mhadd; u32 dmatxctl; u32 gpie; + u32 ctrl_ext; ixgbe_get_hw_control(adapter); @@ -3015,6 +3016,12 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; adapter->link_check_timeout = jiffies; mod_timer(&adapter->watchdog_timer, jiffies); + + /* Set PF Reset Done bit so PF/VF Mail Ops can work */ + ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); + ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; + IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext); + return 0; } -- cgit v1.2.3 From 767081adbd920ce93e3f1cbe797d0631637f92b3 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:46:40 +0000 Subject: ixgbe: Improve reset coordination between the PF and the VF Inadequate coordination between the PF driver and the VF driver results in tx hangs in the VF driver when you perform certain actions that will lead to a re-init of the PF. Add feature to notify active VFs when the PF is about to re-initialize so that the VFs can take appropriate action. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 11 +++++++++++ drivers/net/ixgbe/ixgbe_sriov.c | 26 ++++++++++++++++++++++++++ drivers/net/ixgbe/ixgbe_sriov.h | 2 ++ 3 files changed, 39 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index b96afd98fa3d..ee41d331a35f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3203,6 +3203,17 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* signal that we are down to the interrupt handler */ set_bit(__IXGBE_DOWN, &adapter->state); + /* disable receive for all VFs and wait one second */ + if (adapter->num_vfs) { + for (i = 0 ; i < adapter->num_vfs; i++) + adapter->vfinfo[i].clear_to_send = 0; + + /* ping all the active vfs to let them know we are going down */ + ixgbe_ping_all_vfs(adapter); + /* Disable all VFTE/VFRE TX/RX */ + ixgbe_disable_tx_rx(adapter); + } + /* disable receives */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 74bca74d57c1..d4cd20f30199 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c @@ -334,3 +334,29 @@ void ixgbe_msg_task(struct ixgbe_adapter *adapter) } } +void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + + /* disable transmit and receive for all vfs */ + IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0); + + IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0); + IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0); +} + +void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 ping; + int i; + + for (i = 0 ; i < adapter->num_vfs; i++) { + ping = IXGBE_PF_CONTROL_MSG; + if (adapter->vfinfo[i].clear_to_send) + ping |= IXGBE_VT_MSGTYPE_CTS; + ixgbe_write_mbx(hw, &ping, 1, i); + } +} + diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ixgbe/ixgbe_sriov.h index 664b237eacb9..51d1106c45a1 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ixgbe/ixgbe_sriov.h @@ -39,6 +39,8 @@ void ixgbe_msg_task(struct ixgbe_adapter *adapter); int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, int vf, unsigned char *mac_addr); int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); +void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter); +void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); void ixgbe_dump_registers(struct ixgbe_adapter *adapter); #endif /* _IXGBE_SRIOV_H_ */ -- cgit v1.2.3 From a9ee25a2b87c8077042ce23d3231f67f026719b0 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:47:00 +0000 Subject: ixgbevf: Take action when the PF notifies the VF it is resetting. When the VF driver gets a control message from the PF that indicates the PF is about to reset or go down we schedule the watchdog timer so that it will detect the PF has gone offline and take appropriate action. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/ixgbevf_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 39544afdc57f..bd2fd4608ed7 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -956,10 +956,17 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data) struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; u32 eicr; + u32 msg; eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS); IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr); + hw->mbx.ops.read(hw, &msg, 1); + + if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG) + mod_timer(&adapter->watchdog_timer, + round_jiffies(jiffies + 10)); + return IRQ_HANDLED; } -- cgit v1.2.3 From c0456c231a8b2981128cc29e211b7bad1bd997df Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:47:18 +0000 Subject: ixgbevf: Fix panics in the VF driver Fix panics in the VF driver that occur when you bring it down after having already brought the PF down. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/ixgbevf_main.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index bd2fd4608ed7..0a27fa17e7ff 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1693,8 +1693,10 @@ static void ixgbevf_clean_rx_ring(struct ixgbevf_adapter *adapter, unsigned long size; unsigned int i; - /* Free all the Rx ring sk_buffs */ + if (!rx_ring->rx_buffer_info) + return; + /* Free all the Rx ring sk_buffs */ for (i = 0; i < rx_ring->count; i++) { struct ixgbevf_rx_buffer *rx_buffer_info; @@ -1751,6 +1753,9 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter, unsigned long size; unsigned int i; + if (!tx_ring->tx_buffer_info) + return; + /* Free all the Tx ring sk_buffs */ for (i = 0; i < tx_ring->count; i++) { @@ -1843,12 +1848,24 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter) void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) { + struct ixgbe_hw *hw = &adapter->hw; + WARN_ON(in_interrupt()); + while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) msleep(1); - ixgbevf_down(adapter); - ixgbevf_up(adapter); + /* + * Check if PF is up before re-init. If not then skip until + * later when the PF is up and ready to service requests from + * the VF via mailbox. If the VF is up and running then the + * watchdog task will continue to schedule reset tasks until + * the PF is up and running. + */ + if (!hw->mac.ops.reset_hw(hw)) { + ixgbevf_down(adapter); + ixgbevf_up(adapter); + } clear_bit(__IXGBEVF_RESETTING, &adapter->state); } @@ -2423,7 +2440,6 @@ void ixgbevf_free_tx_resources(struct ixgbevf_adapter *adapter, { struct pci_dev *pdev = adapter->pdev; - ixgbevf_clean_tx_ring(adapter, tx_ring); vfree(tx_ring->tx_buffer_info); -- cgit v1.2.3 From da6b33306801af7ee6479c177051e70842974932 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Fri, 22 Jan 2010 22:47:37 +0000 Subject: ixgbevf: Tell network stack to stop tx when the VF detects PF reset When the VF detects that the PF has reset turn off carrier and stop all tx queues. Signed-off-by: Greg Rose Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/ixgbevf_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 0a27fa17e7ff..623353db11ba 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -2381,6 +2381,8 @@ static void ixgbevf_watchdog_task(struct work_struct *work) &link_up, false)) != 0) { adapter->link_up = link_up; adapter->link_speed = link_speed; + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); schedule_work(&adapter->reset_task); goto pf_has_reset; } -- cgit v1.2.3 From a271623f871dda970319ca15dfad3a8c8c36249f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 10:13:10 +0000 Subject: netdev: remove certain HAVE_ macros After netdev_ops compat code HAVE_* macros aren't needed, in fact they _will_ result in compile breakage for out of tree drivers. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/netdevice.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 468a11dea58c..b5fb51d0b8b1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -621,30 +621,21 @@ struct net_device_ops { struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb); -#define HAVE_CHANGE_RX_FLAGS void (*ndo_change_rx_flags)(struct net_device *dev, int flags); -#define HAVE_SET_RX_MODE void (*ndo_set_rx_mode)(struct net_device *dev); -#define HAVE_MULTICAST void (*ndo_set_multicast_list)(struct net_device *dev); -#define HAVE_SET_MAC_ADDR int (*ndo_set_mac_address)(struct net_device *dev, void *addr); -#define HAVE_VALIDATE_ADDR int (*ndo_validate_addr)(struct net_device *dev); -#define HAVE_PRIVATE_IOCTL int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); -#define HAVE_SET_CONFIG int (*ndo_set_config)(struct net_device *dev, struct ifmap *map); -#define HAVE_CHANGE_MTU int (*ndo_change_mtu)(struct net_device *dev, int new_mtu); int (*ndo_neigh_setup)(struct net_device *dev, struct neigh_parms *); -#define HAVE_TX_TIMEOUT void (*ndo_tx_timeout) (struct net_device *dev); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); @@ -656,7 +647,6 @@ struct net_device_ops { void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); #ifdef CONFIG_NET_POLL_CONTROLLER -#define HAVE_NETDEV_POLL void (*ndo_poll_controller)(struct net_device *dev); #endif #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) -- cgit v1.2.3 From 81c1ebfc4379f529b001e23164dd5c2282bdc0ec Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 10:16:05 +0000 Subject: neigh: simplify seq_file code Simpily pass 'struct neigh_table' with seq_file private pointer, and save one dereference. Proc entry itself isn't interesting. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/core/neighbour.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f35377b643e4..f2efd72da799 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2417,8 +2417,7 @@ EXPORT_SYMBOL(neigh_seq_stop); static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos) { - struct proc_dir_entry *pde = seq->private; - struct neigh_table *tbl = pde->data; + struct neigh_table *tbl = seq->private; int cpu; if (*pos == 0) @@ -2435,8 +2434,7 @@ static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos) static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct proc_dir_entry *pde = seq->private; - struct neigh_table *tbl = pde->data; + struct neigh_table *tbl = seq->private; int cpu; for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) { @@ -2455,8 +2453,7 @@ static void neigh_stat_seq_stop(struct seq_file *seq, void *v) static int neigh_stat_seq_show(struct seq_file *seq, void *v) { - struct proc_dir_entry *pde = seq->private; - struct neigh_table *tbl = pde->data; + struct neigh_table *tbl = seq->private; struct neigh_statistics *st = v; if (v == SEQ_START_TOKEN) { @@ -2501,7 +2498,7 @@ static int neigh_stat_seq_open(struct inode *inode, struct file *file) if (!ret) { struct seq_file *sf = file->private_data; - sf->private = PDE(inode); + sf->private = PDE(inode)->data; } return ret; }; -- cgit v1.2.3 From 5833929cc2ad2b3064b4fac8c44e293972d240d8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 10:17:26 +0000 Subject: net: constify MIB name tables Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/snmp.h | 2 +- net/ipv4/proc.c | 4 ++-- net/ipv6/proc.c | 12 ++++++------ net/sctp/proc.c | 2 +- net/xfrm/xfrm_proc.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/net/snmp.h b/include/net/snmp.h index f0d756f2ac99..da02ee027d69 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -32,7 +32,7 @@ * - name of entries. */ struct snmp_mib { - char *name; + const char *name; int entry; }; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index f25542c48b7d..1b09a6dde7c0 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -127,8 +127,8 @@ static const struct snmp_mib snmp4_ipextstats_list[] = { SNMP_MIB_SENTINEL }; -static struct { - char *name; +static const struct { + const char *name; int index; } icmpmibmap[] = { { "DestUnreachs", ICMP_DEST_UNREACH }, diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 02f20016b4c9..bfe2598dd563 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -59,7 +59,7 @@ static const struct file_operations sockstat6_seq_fops = { .release = single_release_net, }; -static struct snmp_mib snmp6_ipstats_list[] = { +static const struct snmp_mib snmp6_ipstats_list[] = { /* ipv6 mib according to RFC 2465 */ SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INPKTS), SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS), @@ -92,7 +92,7 @@ static struct snmp_mib snmp6_ipstats_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp6_icmp6_list[] = { +static const struct snmp_mib snmp6_icmp6_list[] = { /* icmpv6 mib according to RFC 2466 */ SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), @@ -120,7 +120,7 @@ static const char *const icmp6type2name[256] = { }; -static struct snmp_mib snmp6_udp6_list[] = { +static const struct snmp_mib snmp6_udp6_list[] = { SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS), SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS), @@ -128,7 +128,7 @@ static struct snmp_mib snmp6_udp6_list[] = { SNMP_MIB_SENTINEL }; -static struct snmp_mib snmp6_udplite6_list[] = { +static const struct snmp_mib snmp6_udplite6_list[] = { SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS), SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), @@ -170,8 +170,8 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) return; } -static inline void -snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) +static void snmp6_seq_show_item(struct seq_file *seq, void **mib, + const struct snmp_mib *itemlist) { int i; for (i=0; itemlist[i].name; i++) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index d093cbfeaac4..a5ac6e0a8d9c 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -40,7 +40,7 @@ #include #include /* for snmp_fold_field */ -static struct snmp_mib sctp_snmp_list[] = { +static const struct snmp_mib sctp_snmp_list[] = { SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB), SNMP_MIB_ITEM("SctpActiveEstabs", SCTP_MIB_ACTIVEESTABS), SNMP_MIB_ITEM("SctpPassiveEstabs", SCTP_MIB_PASSIVEESTABS), diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index fef8db553e8d..c083a4e4e796 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -15,7 +15,7 @@ #include #include -static struct snmp_mib xfrm_mib_list[] = { +static const struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmInError", LINUX_MIB_XFRMINERROR), SNMP_MIB_ITEM("XfrmInBufferError", LINUX_MIB_XFRMINBUFFERERROR), SNMP_MIB_ITEM("XfrmInHdrError", LINUX_MIB_XFRMINHDRERROR), -- cgit v1.2.3 From e754834e65220b2b674c55c3b6dfb2fb1a2804d0 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 22 Jan 2010 10:18:25 +0000 Subject: icmp: move icmp_err_convert[] to .rodata Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/icmp.h | 2 +- net/ipv4/icmp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/icmp.h b/include/net/icmp.h index dfa72d4e8907..15b3dfe9fce8 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -28,7 +28,7 @@ struct icmp_err { unsigned fatal:1; }; -extern struct icmp_err icmp_err_convert[]; +extern const struct icmp_err icmp_err_convert[]; #define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field) #define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field) #define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmpmsg_statistics, field+256) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index fe11f60ce41b..4b4c2bcd15db 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -114,7 +114,7 @@ struct icmp_bxm { /* An array of errno for error messages from dest unreach. */ /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOST_UNREACH and SR_FAILED MUST be considered 'transient errs'. */ -struct icmp_err icmp_err_convert[] = { +const struct icmp_err icmp_err_convert[] = { { .errno = ENETUNREACH, /* ICMP_NET_UNREACH */ .fatal = 0, -- cgit v1.2.3 From e9017b55189355e9e6569990a18919e83f35bccb Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Sat, 23 Jan 2010 01:57:42 -0800 Subject: IP: Send an ICMP "Fragment Reassembly Timeout" message when enabling connection track No matter whether connection track is enabled, an end host should send an ICMPv4 "Fragment Reassembly Timeout" message when defrag timeout. The reasons are following two points: 1. RFC 792 says: >>>> >> > > If a host reassembling a fragmented datagram cannot complete the >>>> >> > > reassembly due to missing fragments within its time limit it >>>> >> > > discards the datagram, and it may send a time exceeded message. >>>> >> > > >>>> >> > > If fragment zero is not available then no time exceeded need be >>>> >> > > sent at all. >>>> >> > > >>>> >> > > Read more: http://www.faqs.org/rfcs/rfc792.html#ixzz0aOXRD7Wp 2. Patrick McHardy also agrees with this opinion. :-) About the discussion of this opinion, refer to http://patchwork.ozlabs.org/patch/41649 The patch fixed the problem like this: When enabling connection track, fragments are received at PRE_ROUTING HOOK. If they are failed to reassemble, ip_expire() will be called. Before sending an ICMP "Fragment Reassembly Timeout" message, the patch searches router table to get the destination entry only for host type. The patch has been tested on both host type and route type. Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 891c72aea520..9f41bd311754 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -205,13 +207,37 @@ static void ip_expire(unsigned long arg) if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { struct sk_buff *head = qp->q.fragments; - /* Send an ICMP "Fragment Reassembly Timeout" message. */ rcu_read_lock(); head->dev = dev_get_by_index_rcu(net, qp->iif); - if (head->dev) - icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); - rcu_read_unlock(); + if (!head->dev) + goto out_rcu_unlock; + + /* + * Only search router table for the head fragment, + * when defraging timeout at PRE_ROUTING HOOK. + */ + if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) { + const struct iphdr *iph = ip_hdr(head); + int err = ip_route_input(head, iph->daddr, iph->saddr, + iph->tos, head->dev); + if (unlikely(err)) + goto out_rcu_unlock; + + /* + * Only an end host needs to send an ICMP + * "Fragment Reassembly Timeout" message, per RFC792. + */ + if (skb_rtable(head)->rt_type != RTN_LOCAL) + goto out_rcu_unlock; + + } + + /* Send an ICMP "Fragment Reassembly Timeout" message. */ + icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); } + +out_rcu_unlock: + rcu_read_unlock(); out: spin_unlock(&qp->q.lock); ipq_put(qp); -- cgit v1.2.3 From 9010bc3364db56dd88a1851e0797e597e322ce08 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Sat, 23 Jan 2010 02:06:26 -0800 Subject: ixgbevf: Fix IPv6 GSO type checks Based on patch from Sridhar Samudrala The following patch fixes the check for IPv6 GSO packet in ixgbevf driver to use skb_is_gso_v6(). SKB_GSO_DODGY is also set when packets are forwarded from a guest. CC: Sridhar Samudrala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbevf/ixgbevf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 623353db11ba..7b3af107ca84 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -2781,7 +2781,7 @@ static int ixgbevf_tso(struct ixgbevf_adapter *adapter, IPPROTO_TCP, 0); adapter->hw_tso_ctxt++; - } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) { + } else if (skb_is_gso_v6(skb)) { ipv6_hdr(skb)->payload_len = 0; tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, -- cgit v1.2.3 From 3b43a18743421cccd33902e29016fa49b2d52dbb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sat, 23 Jan 2010 20:27:14 +0200 Subject: mac80211: fix tx select key null pointer crash with hostapd Pavel Roskin reported a crash in ieee80211_tx_h_select_key(): http://marc.info/?l=linux-wireless&m=126419655108528&w=2 This is a regression from patch "mac80211: move control.hw_key assignment". Fix it as suggested by Johannes, adding an else statement to make sure that tx->key is not accessed when it's null. Compile-tested only. Reported-by: Pavel Roskin Cc: Johannes Berg Signed-off-by: Kalle Valo Tested-by: Bob Copeland Signed-off-by: John W. Linville --- net/mac80211/tx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index fcfa988a37a3..d017b3530d4d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -547,9 +547,10 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) !ieee80211_use_mfp(hdr->frame_control, tx->sta, tx->skb)) tx->key = NULL; - skip_hw = (tx->key->conf.flags & - IEEE80211_KEY_FLAG_SW_MGMT) && - ieee80211_is_mgmt(hdr->frame_control); + else + skip_hw = (tx->key->conf.flags & + IEEE80211_KEY_FLAG_SW_MGMT) && + ieee80211_is_mgmt(hdr->frame_control); break; case ALG_AES_CMAC: if (!ieee80211_is_mgmt(hdr->frame_control)) -- cgit v1.2.3 From 32e7bfc41110bc8f29ec0f293c3bcee6645fef34 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 25 Jan 2010 13:36:10 -0800 Subject: net: use helpers to access uc list V2 This patch introduces three macros to work with uc list from net drivers. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 5 ++--- drivers/net/e1000/e1000_main.c | 4 ++-- drivers/net/igb/igb_main.c | 7 ++++--- drivers/net/ixgbe/ixgbe_common.c | 7 +++---- drivers/net/ixgbe/ixgbe_common.h | 2 +- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbe/ixgbe_type.h | 4 ++-- drivers/net/mv643xx_eth.c | 3 +-- drivers/net/niu.c | 4 ++-- drivers/net/stmmac/dwmac1000_core.c | 10 +++++----- drivers/net/virtio_net.c | 12 +++++++----- drivers/s390/net/qeth_l2_main.c | 2 +- include/linux/netdevice.h | 5 +++++ net/core/dev.c | 4 ++-- 14 files changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d83512d3e02f..a7b6b12c1c05 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -48,7 +48,6 @@ #include #include #include -#include #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) #define BCM_CNIC 1 @@ -3579,14 +3578,14 @@ bnx2_set_rx_mode(struct net_device *dev) sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN; } - if (dev->uc.count > BNX2_MAX_UNICAST_ADDRESSES) { + if (netdev_uc_count(dev) > BNX2_MAX_UNICAST_ADDRESSES) { rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN | BNX2_RPM_SORT_USER0_PROM_VLAN; } else if (!(dev->flags & IFF_PROMISC)) { /* Add all entries into to the match filter list */ i = 0; - list_for_each_entry(ha, &dev->uc.list, list) { + netdev_for_each_uc_addr(ha, dev) { bnx2_set_mac_addr(bp, ha->addr, i + BNX2_START_UNICAST_ADDRESS_INDEX); sort_mode |= (1 << diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 87f575ca427d..2ce88c5f75c5 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2139,7 +2139,7 @@ static void e1000_set_rx_mode(struct net_device *netdev) rctl |= E1000_RCTL_VFE; } - if (netdev->uc.count > rar_entries - 1) { + if (netdev_uc_count(netdev) > rar_entries - 1) { rctl |= E1000_RCTL_UPE; } else if (!(netdev->flags & IFF_PROMISC)) { rctl &= ~E1000_RCTL_UPE; @@ -2162,7 +2162,7 @@ static void e1000_set_rx_mode(struct net_device *netdev) */ i = 1; if (use_uc) - list_for_each_entry(ha, &netdev->uc.list, list) { + netdev_for_each_uc_addr(ha, netdev) { if (i == rar_entries) break; e1000_rar_set(hw, ha->addr, i++); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d9679493c635..01cc29483e2f 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2905,12 +2905,13 @@ static int igb_write_uc_addr_list(struct net_device *netdev) int count = 0; /* return ENOMEM indicating insufficient memory for addresses */ - if (netdev->uc.count > rar_entries) + if (netdev_uc_count(netdev) > rar_entries) return -ENOMEM; - if (netdev->uc.count && rar_entries) { + if (!netdev_uc_empty(netdev) && rar_entries) { struct netdev_hw_addr *ha; - list_for_each_entry(ha, &netdev->uc.list, list) { + + netdev_for_each_uc_addr(ha, netdev) { if (!rar_entries) break; igb_rar_set_qsel(adapter, ha->addr, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 276c2aaa800b..eb49020903c1 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "ixgbe.h" @@ -1347,7 +1346,7 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) /** * ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses * @hw: pointer to hardware structure - * @uc_list: the list of new addresses + * @netdev: pointer to net device structure * * The given list replaces any existing list. Clears the secondary addrs from * receive address registers. Uses unused receive address registers for the @@ -1357,7 +1356,7 @@ static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq) * manually putting the device into promiscuous mode. **/ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, - struct list_head *uc_list) + struct net_device *netdev) { u32 i; u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc; @@ -1381,7 +1380,7 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, } /* Add the new addresses */ - list_for_each_entry(ha, uc_list, list) { + netdev_for_each_uc_addr(ha, netdev) { hw_dbg(hw, " Adding the secondary addresses:\n"); ixgbe_add_uc_addr(hw, ha->addr, 0); } diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index dfff0ffaa502..13606d4809c9 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -60,7 +60,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr func); s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, - struct list_head *uc_list); + struct net_device *netdev); s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw); s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ee41d331a35f..439645d2aeef 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2568,7 +2568,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); /* reprogram secondary unicast list */ - hw->mac.ops.update_uc_addr_list(hw, &netdev->uc.list); + hw->mac.ops.update_uc_addr_list(hw, netdev); /* reprogram multicast list */ addr_count = netdev->mc_count; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index b4caa7011a2b..0db67c19b2c4 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -30,7 +30,7 @@ #include #include -#include +#include /* Vendor ID */ #define IXGBE_INTEL_VENDOR_ID 0x8086 @@ -2405,7 +2405,7 @@ struct ixgbe_mac_operations { s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32); s32 (*init_rx_addrs)(struct ixgbe_hw *); - s32 (*update_uc_addr_list)(struct ixgbe_hw *, struct list_head *); + s32 (*update_uc_addr_list)(struct ixgbe_hw *, struct net_device *); s32 (*update_mc_addr_list)(struct ixgbe_hw *, u8 *, u32, ixgbe_mc_addr_itr); s32 (*enable_mc)(struct ixgbe_hw *); diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index af67af55efe7..e24072a9a979 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -55,7 +55,6 @@ #include #include #include -#include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; static char mv643xx_eth_driver_version[] = "1.4"; @@ -1697,7 +1696,7 @@ static u32 uc_addr_filter_mask(struct net_device *dev) return 0; nibbles = 1 << (dev->dev_addr[5] & 0x0f); - list_for_each_entry(ha, &dev->uc.list, list) { + netdev_for_each_uc_addr(ha, dev) { if (memcmp(dev->dev_addr, ha->addr, 5)) return 0; if ((dev->dev_addr[5] ^ ha->addr[5]) & 0xf0) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 0e260cfbff7b..af9a8647c7e8 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6372,7 +6372,7 @@ static void niu_set_rx_mode(struct net_device *dev) if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 0)) np->flags |= NIU_FLAGS_MCAST; - alt_cnt = dev->uc.count; + alt_cnt = netdev_uc_count(dev); if (alt_cnt > niu_num_alt_addr(np)) { alt_cnt = 0; np->flags |= NIU_FLAGS_PROMISC; @@ -6381,7 +6381,7 @@ static void niu_set_rx_mode(struct net_device *dev) if (alt_cnt) { int index = 0; - list_for_each_entry(ha, &dev->uc.list, list) { + netdev_for_each_uc_addr(ha, dev) { err = niu_set_alt_mac(np, index, ha->addr); if (err) printk(KERN_WARNING PFX "%s: Error %d " diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 928eac05b912..d812e9cdb3db 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -83,7 +83,7 @@ static void dwmac1000_set_filter(struct net_device *dev) unsigned int value = 0; DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", - __func__, dev->mc_count, dev->uc.count); + __func__, dev->mc_count, netdev_uc_count(dev)); if (dev->flags & IFF_PROMISC) value = GMAC_FRAME_FILTER_PR; @@ -117,7 +117,7 @@ static void dwmac1000_set_filter(struct net_device *dev) } /* Handle multiple unicast addresses (perfect filtering)*/ - if (dev->uc.count > GMAC_MAX_UNICAST_ADDRESSES) + if (netdev_uc_count(dev) > GMAC_MAX_UNICAST_ADDRESSES) /* Switch to promiscuous mode is more than 16 addrs are required */ value |= GMAC_FRAME_FILTER_PR; @@ -125,9 +125,9 @@ static void dwmac1000_set_filter(struct net_device *dev) int reg = 1; struct netdev_hw_addr *ha; - list_for_each_entry(ha, &dev->uc.list, list) { - dwmac1000_set_umac_addr(ioaddr, ha->addr, reg); - reg++; + netdev_for_each_uc_addr(ha, dev) { + dwmac1000_set_umac_addr(ioaddr, ha->addr, reg); + reg++; } } diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c708ecc3cb2e..088332a943f7 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -675,6 +675,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) struct virtio_net_ctrl_mac *mac_data; struct dev_addr_list *addr; struct netdev_hw_addr *ha; + int uc_count; void *buf; int i; @@ -701,8 +702,9 @@ static void virtnet_set_rx_mode(struct net_device *dev) dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", allmulti ? "en" : "dis"); + uc_count = netdev_uc_count(dev); /* MAC filter - use one buffer for both lists */ - mac_data = buf = kzalloc(((dev->uc.count + dev->mc_count) * ETH_ALEN) + + mac_data = buf = kzalloc(((uc_count + dev->mc_count) * ETH_ALEN) + (2 * sizeof(mac_data->entries)), GFP_ATOMIC); if (!buf) { dev_warn(&dev->dev, "No memory for MAC address buffer\n"); @@ -712,16 +714,16 @@ static void virtnet_set_rx_mode(struct net_device *dev) sg_init_table(sg, 2); /* Store the unicast list and count in the front of the buffer */ - mac_data->entries = dev->uc.count; + mac_data->entries = uc_count; i = 0; - list_for_each_entry(ha, &dev->uc.list, list) + netdev_for_each_uc_addr(ha, dev) memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); sg_set_buf(&sg[0], mac_data, - sizeof(mac_data->entries) + (dev->uc.count * ETH_ALEN)); + sizeof(mac_data->entries) + (uc_count * ETH_ALEN)); /* multicast list and count fill the end */ - mac_data = (void *)&mac_data->macs[dev->uc.count][0]; + mac_data = (void *)&mac_data->macs[uc_count][0]; mac_data->entries = dev->mc_count; addr = dev->mc_list; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index c3258b0dd649..51fde6f2e0b8 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -622,7 +622,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) for (dm = dev->mc_list; dm; dm = dm->next) qeth_l2_add_mc(card, dm->da_addr, 0); - list_for_each_entry(ha, &dev->uc.list, list) + netdev_for_each_uc_addr(ha, dev) qeth_l2_add_mc(card, ha->addr, 1); spin_unlock_bh(&card->mclock); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index b5fb51d0b8b1..93a32a5ca74f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -263,6 +263,11 @@ struct netdev_hw_addr_list { int count; }; +#define netdev_uc_count(dev) ((dev)->uc.count) +#define netdev_uc_empty(dev) ((dev)->uc.count == 0) +#define netdev_for_each_uc_addr(ha, dev) \ + list_for_each_entry(ha, &dev->uc.list, list) + struct hh_cache { struct hh_cache *hh_next; /* Next entry */ atomic_t hh_refcnt; /* number of users */ diff --git a/net/core/dev.c b/net/core/dev.c index 4fad9db417b1..2cba5c521e56 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3665,10 +3665,10 @@ void __dev_set_rx_mode(struct net_device *dev) /* Unicast addresses changes may only happen under the rtnl, * therefore calling __dev_set_promiscuity here is safe. */ - if (dev->uc.count > 0 && !dev->uc_promisc) { + if (!netdev_uc_empty(dev) && !dev->uc_promisc) { __dev_set_promiscuity(dev, 1); dev->uc_promisc = 1; - } else if (dev->uc.count == 0 && dev->uc_promisc) { + } else if (netdev_uc_empty(dev) && dev->uc_promisc) { __dev_set_promiscuity(dev, -1); dev->uc_promisc = 0; } -- cgit v1.2.3 From a13d276f1e49ae0bc4ad18ce8ea3c90656c9e8d4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 22 Jan 2010 14:22:42 -0800 Subject: iwlwifi: configure missed beacon threshold Add support to configure missed beacon threshold, by default, if receive "missed beacon" notification from uCode and has more than 5 consecutive beacon missed, then perform sensitivity calibration; with this change, allow user to adjust the missed beacon threshold from debugfs in case more sensitivity calibration required for better performance in noisy environment The default value (=5) should be good enough for the normal condition, but for very noisy environment, more sensitivity calibration could help improve the throughput, so by setting the missed beacon threshold to lower number, user might experience better performance result. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-commands.h | 25 +++++++++++++--- drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 46 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-rx.c | 5 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 7 files changed, 74 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 62b6939df52e..e9f786443d1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3372,6 +3372,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; + priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; /* Choose which receivers/antennas to use */ if (priv->cfg->ops->hcmd->set_rxon_chain) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index cee5fb2187c8..8823d18b9f43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3165,13 +3165,30 @@ struct iwl_notif_statistics { /* * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) + * + * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed + * in regardless of how many missed beacons, which mean when driver receive the + * notification, inside the command, it can find all the beacons information + * which include number of total missed beacons, number of consecutive missed + * beacons, number of beacons received and number of beacons expected to + * receive. + * + * If uCode detected consecutive_missed_beacons > 5, it will reset the radio + * in order to bring the radio/PHY back to working state; which has no relation + * to when driver will perform sensitivity calibration. + * + * Driver should set it own missed_beacon_threshold to decide when to perform + * sensitivity calibration based on number of consecutive missed beacons in + * order to improve overall performance, especially in noisy environment. + * */ -/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, - * then this notification will be sent. */ -#define CONSECUTIVE_MISSED_BCONS_TH 20 + +#define IWL_MISSED_BEACON_THRESHOLD_MIN (1) +#define IWL_MISSED_BEACON_THRESHOLD_DEF (5) +#define IWL_MISSED_BEACON_THRESHOLD_MAX IWL_MISSED_BEACON_THRESHOLD_DEF struct iwl_missed_beacon_notif { - __le32 consequtive_missed_beacons; + __le32 consecutive_missed_beacons; __le32 total_missed_becons; __le32 num_expected_beacons; __le32 num_recvd_beacons; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 0facaca9b40b..36b558f23325 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -112,6 +112,7 @@ struct iwl_debugfs { struct dentry *file_csr; struct dentry *file_ucode_tracing; struct dentry *file_fh_reg; + struct dentry *file_missed_beacon; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index af00ad2afa14..02f80bc21307 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2131,6 +2131,49 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, return ret; } +static ssize_t iwl_dbgfs_missed_beacon_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + int pos = 0; + char buf[12]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + pos += scnprintf(buf + pos, bufsz - pos, "%d\n", + priv->missed_beacon_threshold); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} + +static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int missed; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &missed) != 1) + return -EINVAL; + + if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN || + missed > IWL_MISSED_BEACON_THRESHOLD_MAX) + priv->missed_beacon_threshold = + IWL_MISSED_BEACON_THRESHOLD_DEF; + else + priv->missed_beacon_threshold = missed; + + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -2148,6 +2191,7 @@ DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); DEBUGFS_READ_FILE_OPS(fh_reg); +DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); /* * Create the debugfs files and directories @@ -2200,6 +2244,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); + DEBUGFS_ADD_FILE(missed_beacon, debug, S_IWUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); @@ -2260,6 +2305,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) file_clear_traffic_statistics); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_missed_beacon); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_ucode_rx_stats); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c6310b0b2f12..5e06e666f176 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1053,6 +1053,7 @@ struct iwl_priv { #endif /* ucode beacon time */ u32 ucode_beacon_time; + int missed_beacon_threshold; /* we allocate array of iwl4965_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index eb45f8be0746..dc06c7bb0f5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -499,9 +499,10 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_missed_beacon_notif *missed_beacon; missed_beacon = &pkt->u.missed_beacon; - if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { + if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) > + priv->missed_beacon_threshold) { IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", - le32_to_cpu(missed_beacon->consequtive_missed_beacons), + le32_to_cpu(missed_beacon->consecutive_missed_beacons), le32_to_cpu(missed_beacon->total_missed_becons), le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_expected_beacons)); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c46f988d0a5b..9c0b6ebbdc59 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3881,6 +3881,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) priv->band = IEEE80211_BAND_2GHZ; priv->iw_mode = NL80211_IFTYPE_STATION; + priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; iwl_reset_qos(priv); -- cgit v1.2.3 From afbdd69af0e6a0c40676d4d4b94a0a4414708eaa Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 22 Jan 2010 14:22:43 -0800 Subject: iwlwifi: add function to reset/tune radio if needed Adding "radio reset" function to help reset and stabilize the radio. During normal operation, sometime for unknown reason, radio encounter problem and can not recover by itself; the best way to recover from it is to reset and re-tune the radio. Currently, there is no RF reset command available, but since radio will get reset when switching channel, use internal hw scan request to force radio reset and get back to normal operation state. The internal hw scan will only perform passive scan on the first available channel (not the channel being used) in associated state. The request should be ignored if already performing scan operation or STA is not in associated state. Also include an "internal_scan" debugfs file to help trigger the internal scan from user mode. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 24 +++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 24 +++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 155 ++++++++++++++++++++++++++--- 6 files changed, 193 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bb3ed25f8438..645bc133577a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -3343,6 +3343,30 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) } EXPORT_SYMBOL(iwl_dump_fh); +void iwl_force_rf_reset(struct iwl_priv *priv) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + if (!iwl_is_associated(priv)) { + IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); + return; + } + /* + * There is no easy and better way to force reset the radio, + * the only known method is switching channel which will force to + * reset and tune the radio. + * Use internal short scan (single channel) operation to should + * achieve this objective. + * Driver should reset the radio when number of consecutive missed + * beacon, or any other uCode error condition detected. + */ + IWL_DEBUG_INFO(priv, "perform radio reset.\n"); + iwl_internal_short_hw_scan(priv); + return; +} +EXPORT_SYMBOL(iwl_force_rf_reset); + #ifdef CONFIG_PM int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 785331a98aa5..6de83d1e1eb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -494,6 +494,8 @@ void iwl_init_scan_params(struct iwl_priv *priv); int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); +int iwl_internal_short_hw_scan(struct iwl_priv *priv); +void iwl_force_rf_reset(struct iwl_priv *priv); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 36b558f23325..d81b4f39bb1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -113,6 +113,7 @@ struct iwl_debugfs { struct dentry *file_ucode_tracing; struct dentry *file_fh_reg; struct dentry *file_missed_beacon; + struct dentry *file_internal_scan; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 02f80bc21307..4944fdb31ba8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2174,6 +2174,27 @@ static ssize_t iwl_dbgfs_missed_beacon_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int scan; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &scan) != 1) + return -EINVAL; + + iwl_internal_short_hw_scan(priv); + + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -2192,6 +2213,7 @@ DEBUGFS_WRITE_FILE_OPS(csr); DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); +DEBUGFS_WRITE_FILE_OPS(internal_scan); /* * Create the debugfs files and directories @@ -2245,6 +2267,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, debug, S_IWUSR); + DEBUGFS_ADD_FILE(internal_scan, debug, S_IWUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); @@ -2306,6 +2329,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_missed_beacon); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_internal_scan); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_ucode_rx_stats); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 5e06e666f176..502d7a6b0904 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1080,6 +1080,7 @@ struct iwl_priv { void *scan; int scan_bands; struct cfg80211_scan_request *scan_request; + bool is_internal_short_scan; u8 scan_tx_ant[IEEE80211_NUM_BANDS]; u8 mgmt_tx_ant; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index ceb91f969e45..fd6bafbddfca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -314,6 +314,72 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_get_passive_dwell_time); +static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, + enum ieee80211_band band, + struct iwl_scan_channel *scan_ch) +{ + const struct ieee80211_supported_band *sband; + const struct iwl_channel_info *ch_info; + u16 passive_dwell = 0; + u16 active_dwell = 0; + int i, added = 0; + u16 channel = 0; + + sband = iwl_get_hw_mode(priv, band); + if (!sband) { + IWL_ERR(priv, "invalid band\n"); + return added; + } + + active_dwell = iwl_get_active_dwell_time(priv, band, 0); + passive_dwell = iwl_get_passive_dwell_time(priv, band); + + if (passive_dwell <= active_dwell) + passive_dwell = active_dwell + 1; + + /* only scan single channel, good enough to reset the RF */ + /* pick the first valid not in-use channel */ + if (band == IEEE80211_BAND_5GHZ) { + for (i = 14; i < priv->channel_count; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } else { + for (i = 0; i < 14; i++) { + if (priv->channel_info[i].channel != + le16_to_cpu(priv->staging_rxon.channel)) { + channel = + priv->channel_info[i].channel; + ch_info = iwl_get_channel_info(priv, + band, channel); + if (is_channel_valid(ch_info)) + break; + } + } + } + if (channel) { + scan_ch->channel = cpu_to_le16(channel); + scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; + scan_ch->active_dwell = cpu_to_le16(active_dwell); + scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + /* Set txpower levels to defaults */ + scan_ch->dsp_atten = 110; + if (band == IEEE80211_BAND_5GHZ) + scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; + else + scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + added++; + } else + IWL_ERR(priv, "no valid channel found\n"); + return added; +} + static int iwl_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 n_probes, @@ -421,6 +487,7 @@ static int iwl_scan_initiate(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Starting scan...\n"); set_bit(STATUS_SCANNING, &priv->status); + priv->is_internal_short_scan = false; priv->scan_start = jiffies; priv->scan_pass_start = priv->scan_start; @@ -488,6 +555,45 @@ out_unlock: } EXPORT_SYMBOL(iwl_mac_hw_scan); +/* + * internal short scan, this function should only been called while associated. + * It will reset and tune the radio to prevent possible RF related problem + */ +int iwl_internal_short_hw_scan(struct iwl_priv *priv) +{ + int ret = 0; + + if (!iwl_is_ready_rf(priv)) { + ret = -EIO; + IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); + goto out; + } + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); + ret = -EAGAIN; + goto out; + } + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); + ret = -EAGAIN; + goto out; + } + priv->scan_bands = 0; + if (priv->band == IEEE80211_BAND_5GHZ) + priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); + else + priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); + + IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); + set_bit(STATUS_SCANNING, &priv->status); + priv->is_internal_short_scan = true; + queue_work(priv->workqueue, &priv->request_scan); + +out: + return ret; +} +EXPORT_SYMBOL(iwl_internal_short_hw_scan); + #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) void iwl_bg_scan_check(struct work_struct *data) @@ -551,7 +657,8 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, if (WARN_ON(left < ie_len)) return len; - memcpy(pos, ies, ie_len); + if (ies) + memcpy(pos, ies, ie_len); len += ie_len; left -= ie_len; @@ -654,7 +761,6 @@ static void iwl_bg_request_scan(struct work_struct *data) unsigned long flags; IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); - spin_lock_irqsave(&priv->lock, flags); interval = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); @@ -672,7 +778,9 @@ static void iwl_bg_request_scan(struct work_struct *data) scan_suspend_time, interval); } - if (priv->scan_request->n_ssids) { + if (priv->is_internal_short_scan) { + IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); + } else if (priv->scan_request->n_ssids) { int i, p = 0; IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); for (i = 0; i < priv->scan_request->n_ssids; i++) { @@ -753,24 +861,38 @@ static void iwl_bg_request_scan(struct work_struct *data) rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; scan->rx_chain = cpu_to_le16(rx_chain); - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - priv->scan_request->ie, - priv->scan_request->ie_len, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); + if (!priv->is_internal_short_scan) { + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + priv->scan_request->ie, + priv->scan_request->ie_len, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + } else { + cmd_len = iwl_fill_probe_req(priv, + (struct ieee80211_mgmt *)scan->data, + NULL, 0, + IWL_MAX_SCAN_SIZE - sizeof(*scan)); + } scan->tx_cmd.len = cpu_to_le16(cmd_len); - if (iwl_is_monitor_mode(priv)) scan->filter_flags = RXON_FILTER_PROMISC_MSK; scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | RXON_FILTER_BCON_AWARE_MSK); - scan->channel_count = - iwl_get_channels_for_scan(priv, band, is_active, n_probes, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - + if (priv->is_internal_short_scan) { + scan->channel_count = + iwl_get_single_channel_for_scan(priv, band, + (void *)&scan->data[le16_to_cpu( + scan->tx_cmd.len)]); + } else { + scan->channel_count = + iwl_get_channels_for_scan(priv, band, + is_active, n_probes, + (void *)&scan->data[le16_to_cpu( + scan->tx_cmd.len)]); + } if (scan->channel_count == 0) { IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); goto done; @@ -831,7 +953,12 @@ void iwl_bg_scan_completed(struct work_struct *work) cancel_delayed_work(&priv->scan_check); - ieee80211_scan_completed(priv->hw, false); + if (!priv->is_internal_short_scan) + ieee80211_scan_completed(priv->hw, false); + else { + priv->is_internal_short_scan = false; + IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); + } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; -- cgit v1.2.3 From 220575f78fb0b8d2a1c41cd28115d52ae8d132ee Mon Sep 17 00:00:00 2001 From: Henry Zhangh Date: Fri, 22 Jan 2010 14:22:44 -0800 Subject: iwlwifi: Fix A band scanning when associated This patch allows A band to be scanned when driver is associated to AP. Scan mechanism is that mac80211/cfg80211 requests driver to scan G band first and then immediately to scan A band. Original code require driver to wait for 2 seconds after any scan before another scan will be performed. This caused driver to service G band scan request from mac80211/cfg80211 but deny the A band scan request. Signed-off-by: Henry Zhangh Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 17 ++--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 502d7a6b0904..42cf1810b451 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1072,7 +1072,6 @@ struct iwl_priv { struct iwl_calib_result calib_results[IWL_CALIB_MAX]; /* Scan related variables */ - unsigned long last_scan_jiffies; unsigned long next_scan_jiffies; unsigned long scan_start; unsigned long scan_pass_start; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index fd6bafbddfca..07fabbbfd567 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -192,18 +192,15 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, IWL_DEBUG_SCAN(priv, "Scan ch.res: " "%d [802.11%s] " "(TSF: 0x%08X:%08X) - %d " - "elapsed=%lu usec (%dms since last)\n", + "elapsed=%lu usec\n", notif->channel, notif->band ? "bg" : "a", le32_to_cpu(notif->tsf_high), le32_to_cpu(notif->tsf_low), le32_to_cpu(notif->statistics[0]), - le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, - jiffies_to_msecs(elapsed_jiffies - (priv->last_scan_jiffies, jiffies))); + le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); #endif - priv->last_scan_jiffies = jiffies; priv->next_scan_jiffies = 0; } @@ -250,7 +247,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, goto reschedule; } - priv->last_scan_jiffies = jiffies; priv->next_scan_jiffies = 0; IWL_DEBUG_INFO(priv, "Setting scan to off\n"); @@ -528,15 +524,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } - /* if we just finished scan ask for delay */ - if (iwl_is_associated(priv) && priv->last_scan_jiffies && - time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { - IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n"); - queue_work(priv->workqueue, &priv->scan_completed); - ret = 0; - goto out_unlock; - } - priv->scan_bands = 0; for (i = 0; i < req->n_channels; i++) priv->scan_bands |= BIT(req->channels[i]->band); -- cgit v1.2.3 From d4d59e88cb746165c6fe33eacb6f582d525c6ef1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 22 Jan 2010 14:22:45 -0800 Subject: iwlwifi: Logic to control how frequent radio should be reset if needed Add additional logic for internal scan routine to control how frequent this function should be performed. The intent of this function is to reset/re-tune the radio and bring the RF/PHY back to normal state, it does not make sense calling it too frequent, if reset the radio can not bring it back to normal state, it indicate there are other reason to cause the radio not operate correctly. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 42cf1810b451..86d38ae2ec7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1076,6 +1076,7 @@ struct iwl_priv { unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; + unsigned long last_internal_scan_jiffies; void *scan; int scan_bands; struct cfg80211_scan_request *scan_request; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 07fabbbfd567..08faafae8497 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -201,7 +201,8 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf); #endif - priv->next_scan_jiffies = 0; + if (!priv->is_internal_short_scan) + priv->next_scan_jiffies = 0; } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ @@ -247,7 +248,11 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, goto reschedule; } - priv->next_scan_jiffies = 0; + if (!priv->is_internal_short_scan) + priv->next_scan_jiffies = 0; + else + priv->last_internal_scan_jiffies = jiffies; + IWL_DEBUG_INFO(priv, "Setting scan to off\n"); clear_bit(STATUS_SCANNING, &priv->status); @@ -546,6 +551,8 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); * internal short scan, this function should only been called while associated. * It will reset and tune the radio to prevent possible RF related problem */ +#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1) + int iwl_internal_short_hw_scan(struct iwl_priv *priv) { int ret = 0; @@ -565,6 +572,13 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) ret = -EAGAIN; goto out; } + if (priv->last_internal_scan_jiffies && + time_after(priv->last_internal_scan_jiffies + + IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) { + IWL_DEBUG_SCAN(priv, "internal scan rejected\n"); + goto out; + } + priv->scan_bands = 0; if (priv->band == IEEE80211_BAND_5GHZ) priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); -- cgit v1.2.3 From 3e4fb5faefb57824f2e42305b3d5907845af978c Mon Sep 17 00:00:00 2001 From: Trieu 'Andrew' Nguyen Date: Fri, 22 Jan 2010 14:22:46 -0800 Subject: iwlwifi: Tune radio to prevent unexpected behavior We have seen the throughput dropped due to external noisy environment and the radio is out of tune. There are lot of plcp errors indicating this condition. Eventually the station can get de-authenticated by the Access Point. By resetting and tuning the radio, the plcp errors are reduced or eliminated and the throughput starts to rise. To prevent unexpected behavior such as drop in throughput or deauthentication, - The change provides the driver feature to monitor and tune the radio base on the statistics notification from the uCode. - It also allows the setting of the plcp error rate threshold via the plcp_delta under debugfs interface. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 7 ++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++ drivers/net/wireless/iwlwifi/iwl-core.h | 3 ++ drivers/net/wireless/iwlwifi/iwl-debug.h | 1 + drivers/net/wireless/iwlwifi/iwl-debugfs.c | 44 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-dev.h | 12 +++++++ drivers/net/wireless/iwlwifi/iwl-rx.c | 54 ++++++++++++++++++++++++++++++ 10 files changed, 132 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index d5c6edbbc95a..85162e2c35d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -175,6 +175,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -201,6 +202,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6472910b72d4..764479f74c8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2830,6 +2830,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .ht_greenfield_support = false, .led_compensation = 64, .broken_powersave = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2847,6 +2848,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .ht_greenfield_support = false, .led_compensation = 64, .broken_powersave = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct pci_device_id iwl3945_hw_card_ids[] = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8159a0fcf5a8..c36fef99b4b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2239,6 +2239,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .broken_powersave = true, .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aab6cf23c2bd..cbbc0e4f2c76 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1603,6 +1603,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .led_compensation = 51, .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -1627,6 +1628,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .led_compensation = 51, .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1649,6 +1651,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .use_bsm = false, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1673,6 +1676,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .led_compensation = 51, .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1697,6 +1701,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .led_compensation = 51, .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1721,6 +1726,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .led_compensation = 51, .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -1743,6 +1749,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .use_bsm = false, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4dab7f12e725..b191c634ad92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -308,6 +308,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -337,6 +338,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -366,6 +368,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -396,6 +399,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -425,6 +429,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -455,6 +460,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6de83d1e1eb8..661918347d48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -232,6 +232,8 @@ struct iwl_mod_params { * @adv_thermal_throttle: support advance thermal throttle * @support_ct_kill_exit: support ct kill exit condition * @support_wimax_coexist: support wimax/wifi co-exist + * @plcp_delta_threshold: plcp error rate threshold used to trigger + * radio tuning when there is a high receiving plcp error rate * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -288,6 +290,7 @@ struct iwl_cfg { bool adv_thermal_throttle; bool support_ct_kill_exit; const bool support_wimax_coexist; + u8 plcp_delta_threshold; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d81b4f39bb1d..aff1dc0756fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -114,6 +114,7 @@ struct iwl_debugfs { struct dentry *file_fh_reg; struct dentry *file_missed_beacon; struct dentry *file_internal_scan; + struct dentry *file_plcp_delta; } dbgfs_debug_files; u32 sram_offset; u32 sram_len; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 4944fdb31ba8..3f9c03998491 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2195,6 +2195,47 @@ static ssize_t iwl_dbgfs_internal_scan_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char buf[12]; + const size_t bufsz = sizeof(buf); + ssize_t ret; + + pos += scnprintf(buf + pos, bufsz - pos, "%u\n", + priv->cfg->plcp_delta_threshold); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} + +static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int plcp; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &plcp) != 1) + return -EINVAL; + if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || + (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) + priv->cfg->plcp_delta_threshold = + IWL_MAX_PLCP_ERR_THRESHOLD_DEF; + else + priv->cfg->plcp_delta_threshold = plcp; + return count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -2214,6 +2255,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing); DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_WRITE_FILE_OPS(internal_scan); +DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); /* * Create the debugfs files and directories @@ -2268,6 +2310,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); DEBUGFS_ADD_FILE(missed_beacon, debug, S_IWUSR); DEBUGFS_ADD_FILE(internal_scan, debug, S_IWUSR); + DEBUGFS_ADD_FILE(plcp_delta, debug, S_IWUSR | S_IRUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); @@ -2330,6 +2373,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_missed_beacon); DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_internal_scan); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_plcp_delta); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. file_ucode_rx_stats); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 86d38ae2ec7e..a1f3ecb69ed0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1026,6 +1026,15 @@ struct iwl_event_log { #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10) #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0) +/* + * This is the threshold value of plcp error rate per 100mSecs. It is + * used to set and check for the validity of plcp_delta. + */ +#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) +#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) +#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) +#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1055,6 +1064,9 @@ struct iwl_priv { u32 ucode_beacon_time; int missed_beacon_threshold; + /* storing the jiffies when the plcp error rate is received */ + unsigned long plcp_jiffies; + /* we allocate array of iwl4965_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ struct iwl_channel_info *channel_info; /* channel info array */ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index dc06c7bb0f5c..ea309f42a78a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -602,11 +602,15 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) +#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { int change; struct iwl_rx_packet *pkt = rxb_addr(rxb); + int combined_plcp_delta; + unsigned int plcp_msec; + unsigned long plcp_received_jiffies; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), @@ -621,6 +625,56 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif + /* + * check for plcp_err and trigger radio reset if it exceeds + * the plcp error threshold plcp_delta. + */ + plcp_received_jiffies = jiffies; + plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - + (long) priv->plcp_jiffies); + priv->plcp_jiffies = plcp_received_jiffies; + /* + * check to make sure plcp_msec is not 0 to prevent division + * by zero. + */ + if (plcp_msec) { + combined_plcp_delta = + (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - + le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) + + (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - + le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err)); + + if ((combined_plcp_delta > 0) && + ((combined_plcp_delta * 100) / plcp_msec) > + priv->cfg->plcp_delta_threshold) { + /* + * if plcp_err exceed the threshold, the following + * data is printed in csv format: + * Text: plcp_err exceeded %d, + * Received ofdm.plcp_err, + * Current ofdm.plcp_err, + * Received ofdm_ht.plcp_err, + * Current ofdm_ht.plcp_err, + * combined_plcp_delta, + * plcp_msec + */ + IWL_DEBUG_RADIO(priv, PLCP_MSG, + priv->cfg->plcp_delta_threshold, + le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), + le32_to_cpu(priv->statistics.rx.ofdm.plcp_err), + le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), + le32_to_cpu( + priv->statistics.rx.ofdm_ht.plcp_err), + combined_plcp_delta, plcp_msec); + + /* + * Reset the RF radio due to the high plcp + * error rate + */ + iwl_force_rf_reset(priv); + } + } + memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); set_bit(STATUS_STATISTICS, &priv->status); -- cgit v1.2.3 From 07f33f92e8e1e6ed2ec9d4de048142e7a1d96856 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 22 Jan 2010 14:22:47 -0800 Subject: iwlwifi: enable DC calibration From: Abhijeet Kolekar For 6X50 DC calibration needs to be initialized else uCode will run an endless loop. Enbale DC calibration in hw config. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index b191c634ad92..f89ef4aa78fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -158,11 +158,25 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) /* Set initial sensitivity parameters */ /* Set initial calibration set */ priv->hw_params.sens = &iwl6000_sensitivity; - priv->hw_params.calib_init_cfg = + switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + case CSR_HW_REV_TYPE_6x50: + priv->hw_params.calib_init_cfg = BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_DC) | BIT(IWL_CALIB_LO) | BIT(IWL_CALIB_TX_IQ) | BIT(IWL_CALIB_BASE_BAND); + + break; + default: + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); + break; + } + return 0; } -- cgit v1.2.3 From 1fa97aaeb7fb5111f69abfdb8db656ce19e4951e Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 22 Jan 2010 14:22:48 -0800 Subject: iwlwifi: cleanup station adding code The work done when a station is added is very similar whether the station is added synchronously or asynchronously. Centralize this work. At the same time increase the status flags being checked for when the command returns with accompanying debug messages. Also increase checking when setting the "ucode active" state with accompanying debugging. This work is done in preparation for station notification support. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 114 ++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 8afa39b4b488..842f15653238 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -80,46 +80,103 @@ int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) } EXPORT_SYMBOL(iwl_get_ra_sta_id); +/* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) - IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", - sta_id); + IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u addr %pM\n", + sta_id, priv->stations[sta_id].sta.sta.addr); - priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; - IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", - priv->stations[sta_id].sta.sta.addr); - - spin_unlock_irqrestore(&priv->sta_lock, flags); + if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) { + IWL_DEBUG_ASSOC(priv, + "STA id %u addr %pM already present in uCode (according to driver)\n", + sta_id, priv->stations[sta_id].sta.sta.addr); + } else { + priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; + IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", + sta_id, priv->stations[sta_id].sta.sta.addr); + } } -static void iwl_add_sta_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct iwl_rx_packet *pkt) +static void iwl_process_add_sta_resp(struct iwl_priv *priv, + struct iwl_addsta_cmd *addsta, + struct iwl_rx_packet *pkt, + bool sync) { - struct iwl_addsta_cmd *addsta = - (struct iwl_addsta_cmd *)cmd->cmd.payload; u8 sta_id = addsta->sta.sta_id; + unsigned long flags; if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - pkt->hdr.flags); + pkt->hdr.flags); return; } + IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n", + sta_id); + + spin_lock_irqsave(&priv->sta_lock, flags); + switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: + IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); iwl_sta_ucode_activate(priv, sta_id); - /* fall through */ + break; + case ADD_STA_NO_ROOM_IN_TABLE: + IWL_ERR(priv, "Adding station %d failed, no room in table.\n", + sta_id); + break; + case ADD_STA_NO_BLOCK_ACK_RESOURCE: + IWL_ERR(priv, "Adding station %d failed, no block ack resource.\n", + sta_id); + break; + case ADD_STA_MODIFY_NON_EXIST_STA: + IWL_ERR(priv, "Attempting to modify non-existing station %d \n", + sta_id); + break; default: - IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", - pkt->u.add_sta.status); + IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", + pkt->u.add_sta.status); break; } + + IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n", + priv->stations[sta_id].sta.mode == + STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", + sta_id, priv->stations[sta_id].sta.sta.addr); + + /* + * XXX: The MAC address in the command buffer is often changed from + * the original sent to the device. That is, the MAC address + * written to the command buffer often is not the same MAC adress + * read from the command buffer when the command returns. This + * issue has not yet been resolved and this debugging is left to + * observe the problem. + */ + IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n", + priv->stations[sta_id].sta.mode == + STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", + addsta->sta.addr); + + /* + * Determine if we wanted to modify or add a station, + * if adding a station succeeded we have some more initialization + * to do when using station notification. TODO + */ + + spin_unlock_irqrestore(&priv->sta_lock, flags); +} + +static void iwl_add_sta_callback(struct iwl_priv *priv, + struct iwl_device_cmd *cmd, + struct iwl_rx_packet *pkt) +{ + struct iwl_addsta_cmd *addsta = + (struct iwl_addsta_cmd *)cmd->cmd.payload; + + iwl_process_add_sta_resp(priv, addsta, pkt, false); + } int iwl_send_add_sta(struct iwl_priv *priv, @@ -145,24 +202,9 @@ int iwl_send_add_sta(struct iwl_priv *priv, if (ret || (flags & CMD_ASYNC)) return ret; - pkt = (struct iwl_rx_packet *)cmd.reply_page; - if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - pkt->hdr.flags); - ret = -EIO; - } - if (ret == 0) { - switch (pkt->u.add_sta.status) { - case ADD_STA_SUCCESS_MSK: - iwl_sta_ucode_activate(priv, sta->sta.sta_id); - IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); - break; - default: - ret = -EIO; - IWL_WARN(priv, "REPLY_ADD_STA failed\n"); - break; - } + pkt = (struct iwl_rx_packet *)cmd.reply_page; + iwl_process_add_sta_resp(priv, sta, pkt, true); } iwl_free_pages(priv, cmd.reply_page); -- cgit v1.2.3 From 3459ab5a1c92eaf8b76e9fa1b6ca529cf83066f3 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 22 Jan 2010 14:22:49 -0800 Subject: iwlwifi: make broadcast station addition generic Add function pointer for broadcast station addition so that we can call it in from iwlcore at a later time. We only distinguish between iwlagn and iwl3945 broadcast station addition. For the iwl3945 station addition we add that function to iwlcore since that is where most station functionality resides, making it part of iwl3945 will require significant code reorganization that will dilute station management functionality. This seems to be an efficient solution. It may seem as though we are removing error checking when adding the 3945 broadcast station but this error checking was never really necessary since the function returns the station id and the broadcast station id is always set. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.c | 7 ++----- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-6000.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-sta.c | 11 +++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.h | 1 + 9 files changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 85162e2c35d9..4281999cfaaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -140,6 +140,7 @@ static struct iwl_lib_ops iwl1000_lib = { .temperature = iwl5000_temperature, .set_ct_kill = iwl1000_set_ct_threshold, }, + .add_bcast_station = iwl_add_bcast_station, }; static const struct iwl_ops iwl1000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 764479f74c8b..57194bbd2762 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1951,11 +1951,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) } /* Add the broadcast address so we can send broadcast frames */ - if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == - IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); - return -EIO; - } + priv->cfg->ops->lib->add_bcast_station(priv); /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ @@ -2796,6 +2792,7 @@ static struct iwl_lib_ops iwl3945_lib = { .post_associate = iwl3945_post_associate, .isr = iwl_isr_legacy, .config_ap = iwl3945_config_ap, + .add_bcast_station = iwl3945_add_bcast_station, }; static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c36fef99b4b0..aebe8c51d3e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2206,6 +2206,7 @@ static struct iwl_lib_ops iwl4965_lib = { .temperature = iwl4965_temperature_calib, .set_ct_kill = iwl4965_set_ct_threshold, }, + .add_bcast_station = iwl_add_bcast_station, }; static const struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index cbbc0e4f2c76..6027e2a658d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1503,6 +1503,7 @@ struct iwl_lib_ops iwl5000_lib = { .temperature = iwl5000_temperature, .set_ct_kill = iwl5000_set_ct_threshold, }, + .add_bcast_station = iwl_add_bcast_station, }; static struct iwl_lib_ops iwl5150_lib = { @@ -1556,6 +1557,7 @@ static struct iwl_lib_ops iwl5150_lib = { .temperature = iwl5150_temperature, .set_ct_kill = iwl5150_set_ct_threshold, }, + .add_bcast_station = iwl_add_bcast_station, }; static const struct iwl_ops iwl5000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f89ef4aa78fd..81e03e33ec73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -266,6 +266,7 @@ static struct iwl_lib_ops iwl6000_lib = { .temperature = iwl5000_temperature, .set_ct_kill = iwl6000_set_ct_threshold, }, + .add_bcast_station = iwl_add_bcast_station, }; static const struct iwl_ops iwl6000_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index e9f786443d1f..bed5dda8d6b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -203,7 +203,8 @@ int iwl_commit_rxon(struct iwl_priv *priv) priv->start_calib = 0; /* Add the broadcast address so we can send broadcast frames */ - iwl_add_bcast_station(priv); + priv->cfg->ops->lib->add_bcast_station(priv); + /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 661918347d48..e14e32976b80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -188,6 +188,8 @@ struct iwl_lib_ops { /* temperature */ struct iwl_temp_ops temp_ops; + /* station management */ + void (*add_bcast_station)(struct iwl_priv *priv); }; struct iwl_led_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 842f15653238..fcac73cf82bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1127,6 +1127,7 @@ static void iwl_sta_init_bcast_lq(struct iwl_priv *priv) */ void iwl_add_bcast_station(struct iwl_priv *priv) { + IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); /* Set up default rate scaling table in device's station table */ @@ -1134,6 +1135,16 @@ void iwl_add_bcast_station(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_add_bcast_station); +/** + * iwl3945_add_bcast_station - add broadcast station into station table. + */ +void iwl3945_add_bcast_station(struct iwl_priv *priv) +{ + IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); + iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL); +} +EXPORT_SYMBOL(iwl3945_add_bcast_station); + /** * iwl_get_sta_id - Find station's index within station table * diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 8c6850d03e47..2dc35fe28f56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -53,6 +53,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_add_bcast_station(struct iwl_priv *priv); +void iwl3945_add_bcast_station(struct iwl_priv *priv); int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); void iwl_clear_stations_table(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); -- cgit v1.2.3 From dab1c161fed18eb6b3472bdbfd827264caae097f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 22 Jan 2010 14:22:50 -0800 Subject: iwlwifi: bit field description for BT Config command Give better bit filed define and description for flag parameter in REPLY_BT_CONFIG command: flags: bit 0 - 1: BT channel announcement enabled 0: disable bit 1 - 1: priority of BT device enabled 0: disable bit 2 - 1: BT 2 wire support enabled 0: disable Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 15 ++++++++++++--- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 8823d18b9f43..ce538946f3ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2247,10 +2247,19 @@ struct iwl_link_quality_cmd { __le32 reserved2; } __attribute__ ((packed)); +/* + * BT configuration enable flags: + * bit 0 - 1: BT channel announcement enabled + * 0: disable + * bit 1 - 1: priority of BT device enabled + * 0: disable + * bit 2 - 1: BT 2 wire support enabled + * 0: disable + */ #define BT_COEX_DISABLE (0x0) -#define BT_COEX_MODE_2W (0x1) -#define BT_COEX_MODE_3W (0x2) -#define BT_COEX_MODE_4W (0x3) +#define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0) +#define BT_ENABLE_PRIORITY BIT(1) +#define BT_ENABLE_2_WIRE BIT(2) #define BT_LEAD_TIME_MIN (0x0) #define BT_LEAD_TIME_DEF (0x1E) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 645bc133577a..d625aa8fe7a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1977,7 +1977,7 @@ EXPORT_SYMBOL(iwl_isr_legacy); int iwl_send_bt_config(struct iwl_priv *priv) { struct iwl_bt_cmd bt_cmd = { - .flags = BT_COEX_MODE_4W, + .flags = BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY, .lead_time = BT_LEAD_TIME_DEF, .max_kill = BT_MAX_KILL_DEF, .kill_ack_mask = 0, -- cgit v1.2.3 From 06702a735eacf8679e9ff0d49eb3c989bc6b96ce Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 22 Jan 2010 14:22:51 -0800 Subject: iwlwifi: module parameter to enable/disable bt co-exist Adding "bt_coex_active" module parameter for iwlcore to enable/disable BT coexist; if bt_coex_active is true (default), uCode will do kill/defer every time the priority line is asserted (BT is sending signals on the priority line in the PCIx). By disable the bt_coex_active, uCode will ignore the BT activity and perform the normal operation. Users might experience transmit issue on some platform due to this WiFi/BT co-exist problem. The possible symptoms are: NetworkManager and other similar programs can scan and find all the available APs, but will timeout and unable to associate with any of the APs; no out-going frames can be found with wireless sniffer tools. On those platforms, WiFi communication can be restored by set "bt_coex_active" module parameter to "false" Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-core.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index ce538946f3ff..c2f31eb26bef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2261,6 +2261,9 @@ struct iwl_link_quality_cmd { #define BT_ENABLE_PRIORITY BIT(1) #define BT_ENABLE_2_WIRE BIT(2) +#define BT_COEX_DISABLE (0x0) +#define BT_COEX_ENABLE (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY) + #define BT_LEAD_TIME_MIN (0x0) #define BT_LEAD_TIME_DEF (0x1E) #define BT_LEAD_TIME_MAX (0xFF) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d625aa8fe7a2..1cfabd6be0b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -47,6 +47,26 @@ MODULE_VERSION(IWLWIFI_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); +/* + * set bt_coex_active to true, uCode will do kill/defer + * every time the priority line is asserted (BT is sending signals on the + * priority line in the PCIx). + * set bt_coex_active to false, uCode will ignore the BT activity and + * perform the normal operation + * + * User might experience transmit issue on some platform due to WiFi/BT + * co-exist problem. The possible behaviors are: + * Able to scan and finding all the available AP + * Not able to associate with any AP + * On those platforms, WiFi communication can be restored by set + * "bt_coex_active" module parameter to "false" + * + * default: bt_coex_active = true (BT_COEX_ENABLE) + */ +static bool bt_coex_active = true; +module_param(bt_coex_active, bool, S_IRUGO); +MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); + static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, 0, COEX_UNASSOC_IDLE_FLAGS}, @@ -1977,13 +1997,20 @@ EXPORT_SYMBOL(iwl_isr_legacy); int iwl_send_bt_config(struct iwl_priv *priv) { struct iwl_bt_cmd bt_cmd = { - .flags = BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY, .lead_time = BT_LEAD_TIME_DEF, .max_kill = BT_MAX_KILL_DEF, .kill_ack_mask = 0, .kill_cts_mask = 0, }; + if (!bt_coex_active) + bt_cmd.flags = BT_COEX_DISABLE; + else + bt_cmd.flags = BT_COEX_ENABLE; + + IWL_DEBUG_INFO(priv, "BT coex %s\n", + (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); + return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(struct iwl_bt_cmd), &bt_cmd); } -- cgit v1.2.3 From 1d8c4ae9169ee8d8ca7fb84a7b6bb4c7a4d49397 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 14:22:52 -0800 Subject: iwlwifi: is no longer experimental It really hasn't been for a long time, not sure why this stuck around. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b16b06c2031f..e44e572acb92 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -1,6 +1,6 @@ config IWLWIFI tristate "Intel Wireless Wifi" - depends on PCI && MAC80211 && EXPERIMENTAL + depends on PCI && MAC80211 select FW_LOADER config IWLWIFI_SPECTRUM_MEASUREMENT -- cgit v1.2.3 From 158bea07c6017fa67bc0c64815ce5c3a998083dc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 14:22:53 -0800 Subject: iwlwifi: reorder device setup It is better to first notify cfg80211 about the hw rfkill state (so the rfkill device that will be registered won't have the wrong state while being registered), and the power/tt variable init can (and probably should) also be done first. Also rename iwl_setup_mac to iwl_mac_setup_register to better describe what it really does. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index bed5dda8d6b2..1853064855cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2608,7 +2608,7 @@ void iwl_post_associate(struct iwl_priv *priv) * Not a mac80211 entry point function, but it fits in with all the * other mac80211 functions grouped here. */ -static int iwl_setup_mac(struct iwl_priv *priv) +static int iwl_mac_setup_register(struct iwl_priv *priv) { int ret; struct ieee80211_hw *hw = priv->hw; @@ -3625,9 +3625,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_setup_deferred_work(priv); iwl_setup_rx_handlers(priv); - /********************************** - * 8. Setup and register mac80211 - **********************************/ + /********************************************* + * 8. Enable interrupts and read RFKILL state + *********************************************/ /* enable interrupts if needed: hw bug w/a */ pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); @@ -3638,14 +3638,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_enable_interrupts(priv); - err = iwl_setup_mac(priv); - if (err) - goto out_remove_sysfs; - - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - /* If platform's RF_KILL switch is NOT set to KILL */ if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); @@ -3657,6 +3649,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_power_initialize(priv); iwl_tt_initialize(priv); + + /************************************************** + * 9. Setup and register with mac80211 and debugfs + **************************************************/ + err = iwl_mac_setup_register(priv); + if (err) + goto out_remove_sysfs; + + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + return 0; out_remove_sysfs: -- cgit v1.2.3 From 4c84a8f1679f754d6080e49892f5cae2c88c91a8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 14:22:54 -0800 Subject: iwlwifi: clean up debugfs code The debugfs code can be made a whole lot more efficient by using debugfs_remove_recursive(), the large chunk of variables can completely go away and by moving two variables we no longer need to allocate an extra chunk of memory. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 64 +------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 239 ++++++++++------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +- 3 files changed, 91 insertions(+), 215 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index aff1dc0756fc..1c7b53d511c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -67,63 +67,6 @@ do { \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ } while (0) -#ifdef CONFIG_IWLWIFI_DEBUGFS -struct iwl_debugfs { - const char *name; - struct dentry *dir_drv; - struct dentry *dir_data; - struct dentry *dir_debug; - struct dentry *dir_rf; - struct dir_data_files { - struct dentry *file_sram; - struct dentry *file_nvm; - struct dentry *file_stations; - struct dentry *file_log_event; - struct dentry *file_channels; - struct dentry *file_status; - struct dentry *file_interrupt; - struct dentry *file_qos; - struct dentry *file_thermal_throttling; - struct dentry *file_led; - struct dentry *file_disable_ht40; - struct dentry *file_sleep_level_override; - struct dentry *file_current_sleep_command; - } dbgfs_data_files; - struct dir_rf_files { - struct dentry *file_disable_sensitivity; - struct dentry *file_disable_chain_noise; - struct dentry *file_disable_tx_power; - } dbgfs_rf_files; - struct dir_debug_files { - struct dentry *file_rx_statistics; - struct dentry *file_tx_statistics; - struct dentry *file_traffic_log; - struct dentry *file_rx_queue; - struct dentry *file_tx_queue; - struct dentry *file_ucode_rx_stats; - struct dentry *file_ucode_tx_stats; - struct dentry *file_ucode_general_stats; - struct dentry *file_sensitivity; - struct dentry *file_chain_noise; - struct dentry *file_tx_power; - struct dentry *file_power_save_status; - struct dentry *file_clear_ucode_statistics; - struct dentry *file_clear_traffic_statistics; - struct dentry *file_csr; - struct dentry *file_ucode_tracing; - struct dentry *file_fh_reg; - struct dentry *file_missed_beacon; - struct dentry *file_internal_scan; - struct dentry *file_plcp_delta; - } dbgfs_debug_files; - u32 sram_offset; - u32 sram_len; -}; - -int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); -void iwl_dbgfs_unregister(struct iwl_priv *priv); -#endif - #else #define IWL_DEBUG(__priv, level, fmt, args...) #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) @@ -132,9 +75,10 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, {} #endif /* CONFIG_IWLWIFI_DEBUG */ - - -#ifndef CONFIG_IWLWIFI_DEBUGFS +#ifdef CONFIG_IWLWIFI_DEBUGFS +int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); +void iwl_dbgfs_unregister(struct iwl_priv *priv); +#else static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 3f9c03998491..5c8377b9ad9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -41,43 +41,28 @@ #include "iwl-calib.h" /* create and remove of files */ -#define DEBUGFS_ADD_DIR(name, parent) do { \ - dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ - if (!(dbgfs->dir_##name)) \ - goto err; \ +#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ + if (!debugfs_create_file(#name, mode, parent, priv, \ + &iwl_dbgfs_##name##_ops)) \ + goto err; \ } while (0) -#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_file(#name, mode, \ - dbgfs->dir_##parent, priv, \ - &iwl_dbgfs_##name##_ops); \ - if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ - goto err; \ +#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ } while (0) -#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ - dbgfs->dir_##parent, ptr); \ - if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ - || !dbgfs->dbgfs_##parent##_files.file_##name) \ - goto err; \ +#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ } while (0) -#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \ - if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ - || !dbgfs->dbgfs_##parent##_files.file_##name) \ - goto err; \ -} while (0) - -#define DEBUGFS_REMOVE(name) do { \ - debugfs_remove(name); \ - name = NULL; \ -} while (0); - /* file operation */ #define DEBUGFS_READ_FUNC(name) \ static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ @@ -236,24 +221,24 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, size_t bufsz; /* default is to dump the entire data segment */ - if (!priv->dbgfs->sram_offset && !priv->dbgfs->sram_len) { - priv->dbgfs->sram_offset = 0x800000; + if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { + priv->dbgfs_sram_offset = 0x800000; if (priv->ucode_type == UCODE_INIT) - priv->dbgfs->sram_len = priv->ucode_init_data.len; + priv->dbgfs_sram_len = priv->ucode_init_data.len; else - priv->dbgfs->sram_len = priv->ucode_data.len; + priv->dbgfs_sram_len = priv->ucode_data.len; } - bufsz = 30 + priv->dbgfs->sram_len * sizeof(char) * 10; + bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10; buf = kmalloc(bufsz, GFP_KERNEL); if (!buf) return -ENOMEM; pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", - priv->dbgfs->sram_len); + priv->dbgfs_sram_len); pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", - priv->dbgfs->sram_offset); - for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { - val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ - priv->dbgfs->sram_len - i); + priv->dbgfs_sram_offset); + for (i = priv->dbgfs_sram_len; i > 0; i -= 4) { + val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \ + priv->dbgfs_sram_len - i); if (i < 4) { switch (i) { case 1: @@ -293,11 +278,11 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, return -EFAULT; if (sscanf(buf, "%x,%x", &offset, &len) == 2) { - priv->dbgfs->sram_offset = offset; - priv->dbgfs->sram_len = len; + priv->dbgfs_sram_offset = offset; + priv->dbgfs_sram_len = len; } else { - priv->dbgfs->sram_offset = 0; - priv->dbgfs->sram_len = 0; + priv->dbgfs_sram_offset = 0; + priv->dbgfs_sram_len = 0; } return count; @@ -2263,75 +2248,73 @@ DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); */ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { - struct iwl_debugfs *dbgfs; struct dentry *phyd = priv->hw->wiphy->debugfsdir; - int ret = 0; + struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug; - dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); - if (!dbgfs) { - ret = -ENOMEM; - goto err; - } + dir_drv = debugfs_create_dir(name, phyd); + if (!dir_drv) + return -ENOMEM; - priv->dbgfs = dbgfs; - dbgfs->name = name; - dbgfs->dir_drv = debugfs_create_dir(name, phyd); - if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { - ret = -ENOENT; + priv->debugfs_dir = dir_drv; + + dir_data = debugfs_create_dir("data", dir_drv); + if (!dir_data) + goto err; + dir_rf = debugfs_create_dir("rf", dir_drv); + if (!dir_rf) + goto err; + dir_debug = debugfs_create_dir("debug", dir_drv); + if (!dir_debug) goto err; - } - DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); - DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); - DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); - DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); - DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(log_event, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(stations, data, S_IRUSR); - DEBUGFS_ADD_FILE(channels, data, S_IRUSR); - DEBUGFS_ADD_FILE(status, data, S_IRUSR); - DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(qos, data, S_IRUSR); - DEBUGFS_ADD_FILE(led, data, S_IRUSR); - DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR); - DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR); - DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR); - DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR); - DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR); - DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR); - DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR); - DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); - DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); - DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); - DEBUGFS_ADD_FILE(csr, debug, S_IWUSR); - DEBUGFS_ADD_FILE(fh_reg, debug, S_IRUSR); - DEBUGFS_ADD_FILE(missed_beacon, debug, S_IWUSR); - DEBUGFS_ADD_FILE(internal_scan, debug, S_IWUSR); - DEBUGFS_ADD_FILE(plcp_delta, debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR); + DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(csr, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { - DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); - DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); - DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); - DEBUGFS_ADD_FILE(ucode_tracing, debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); } - DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); - DEBUGFS_ADD_BOOL(disable_chain_noise, rf, + DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal); + DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, &priv->disable_chain_noise_cal); if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) - DEBUGFS_ADD_BOOL(disable_tx_power, rf, + DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf, &priv->disable_tx_power_cal); return 0; err: - IWL_ERR(priv, "Can't open the debugfs directory\n"); + IWL_ERR(priv, "Can't create the debugfs directory\n"); iwl_dbgfs_unregister(priv); - return ret; + return -ENOMEM; } EXPORT_SYMBOL(iwl_dbgfs_register); @@ -2341,63 +2324,11 @@ EXPORT_SYMBOL(iwl_dbgfs_register); */ void iwl_dbgfs_unregister(struct iwl_priv *priv) { - if (!priv->dbgfs) + if (!priv->debugfs_dir) return; - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); - DEBUGFS_REMOVE(priv->dbgfs->dir_data); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_clear_ucode_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_clear_traffic_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_csr); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_fh_reg); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_missed_beacon); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_internal_scan); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_plcp_delta); - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_rx_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_tx_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_general_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_sensitivity); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_chain_noise); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_tracing); - } - DEBUGFS_REMOVE(priv->dbgfs->dir_debug); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); - if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); - DEBUGFS_REMOVE(priv->dbgfs->dir_rf); - DEBUGFS_REMOVE(priv->dbgfs->dir_drv); - kfree(priv->dbgfs); - priv->dbgfs = NULL; + debugfs_remove_recursive(priv->debugfs_dir); + priv->debugfs_dir = NULL; } EXPORT_SYMBOL(iwl_dbgfs_unregister); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index a1f3ecb69ed0..d9f325bd4b69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1309,7 +1309,8 @@ struct iwl_priv { u16 rx_traffic_idx; u8 *tx_traffic; u8 *rx_traffic; - struct iwl_debugfs *dbgfs; + struct dentry *debugfs_dir; + u32 dbgfs_sram_offset, dbgfs_sram_len; #endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUG */ -- cgit v1.2.3 From 875295f183a8cb18e9fde0edae0ab88719debcbd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 14:22:55 -0800 Subject: iwlwifi: fix sparse warning sparse correctly warns about symbol not being static, make static to shut it up. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1853064855cd..d4500b5e0175 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -705,7 +705,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base, spin_unlock_irqrestore(&priv->reg_lock, reg_flags); } -void iwl_continuous_event_trace(struct iwl_priv *priv) +static void iwl_continuous_event_trace(struct iwl_priv *priv) { u32 capacity; /* event log capacity in # entries */ u32 base; /* SRAM byte address of event log header */ -- cgit v1.2.3 From 65baa90d92097ce9b7c080697e6b370d335c2efc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 Jan 2010 14:22:56 -0800 Subject: iwlwifi: check endianness annotations by default sparse won't check endianness annotations by default, but iwlwifi is and should be clean so we can make sparse check them on it. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 7f82044af242..bdaa924d2853 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -20,3 +20,5 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o # 3945 obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o + +ccflags-y += -D__CHECK_ENDIAN__ -- cgit v1.2.3 From 81963d68575d497d626ce13e42c84518a931cc12 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 22 Jan 2010 14:22:57 -0800 Subject: iwlwifi: cleanup spectrum measurement command support In iwlagn the support for spectrum measurement command has been disabled since v2.6.29 without any requests for it. In addition to this when this command is indeed enabled it has been found to trigger firmware SYSASSERT on at least 4965 and 5100 hardware (see http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=1952 ). Since then this code has been bitrotting and cannot just be enabled without porting. Remove support for spectrum measurement command from iwlagn. It can be added back if there is a future need and the firmware problem it triggers has been fixed. Support for the spectrim measurement notification remains as it has been enabled all the time. In addition to this remove the 3945 spectrum measurement command Kconfig option and make this command always supported. The code added by this enabling is minimal and only run when user triggers a spectrum measurement request via sysfs. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 12 -- drivers/net/wireless/iwlwifi/Makefile | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 11 +- drivers/net/wireless/iwlwifi/iwl-core.h | 10 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +- drivers/net/wireless/iwlwifi/iwl-rx.c | 18 +++ drivers/net/wireless/iwlwifi/iwl-spectrum.c | 198 ---------------------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 27 ++-- 8 files changed, 33 insertions(+), 247 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-spectrum.c diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index e44e572acb92..dc8ed1527666 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -3,12 +3,6 @@ config IWLWIFI depends on PCI && MAC80211 select FW_LOADER -config IWLWIFI_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwlagn driver" - depends on IWLWIFI - ---help--- - This option will enable spectrum measurement for the iwlagn driver. - config IWLWIFI_DEBUG bool "Enable full debugging output in iwlagn and iwl3945 drivers" depends on IWLWIFI @@ -120,9 +114,3 @@ config IWL3945 inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called iwl3945. - -config IWL3945_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwl3945 driver" - depends on IWL3945 - ---help--- - This option will enable spectrum measurement for the iwl3945 driver. diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index bdaa924d2853..4e378faee650 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -3,7 +3,6 @@ iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o iwlcore-objs += iwl-scan.o iwl-led.o iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o -iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o CFLAGS_iwl-devtrace.o := -I$(src) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d4500b5e0175..4a268927377b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -73,13 +73,7 @@ #define VD #endif -#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT -#define VS "s" -#else -#define VS -#endif - -#define DRV_VERSION IWLWIFI_VERSION VD VS +#define DRV_VERSION IWLWIFI_VERSION VD MODULE_DESCRIPTION(DRV_DESCRIPTION); @@ -889,6 +883,8 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; + priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = + iwl_rx_spectrum_measure_notif; priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; @@ -902,7 +898,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; - iwl_setup_spectrum_handlers(priv); iwl_setup_rx_scan_handlers(priv); /* status change handler */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e14e32976b80..ec1fe1d7cc9a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -429,6 +429,8 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); /* Handlers */ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb); void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwl_reply_statistics(struct iwl_priv *priv, @@ -531,14 +533,6 @@ int iwl_send_calib_results(struct iwl_priv *priv); int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); void iwl_calib_free_results(struct iwl_priv *priv); -/******************************************************************************* - * Spectrum Measureemtns in iwl-spectrum.c - ******************************************************************************/ -#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT -void iwl_setup_spectrum_handlers(struct iwl_priv *priv); -#else -static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {} -#endif /***************************************************** * S e n d i n g H o s t C o m m a n d s * *****************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d9f325bd4b69..9b0a5cbc20f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1055,11 +1055,10 @@ struct iwl_priv { struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; -#if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT) /* spectrum measurement report caching */ struct iwl_spectrum_notification measure_report; u8 measurement_status; -#endif + /* ucode beacon time */ u32 ucode_beacon_time; int missed_beacon_threshold; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index ea309f42a78a..5df66382d922 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -512,6 +512,24 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); +void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); + + if (!report->state) { + IWL_DEBUG_11H(priv, + "Spectrum Measure Notification: Start\n"); + return; + } + + memcpy(&priv->measure_report, report, sizeof(*report)); + priv->measurement_status |= MEASUREMENT_READY; +} +EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif); + + /* Calculate noise level, based on measurements during network silence just * before arriving beacon. This measurement can be done only if we know diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c deleted file mode 100644 index da166d1d1b13..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ /dev/null @@ -1,198 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-spectrum.h" - -#define BEACON_TIME_MASK_LOW 0x00FFFFFF -#define BEACON_TIME_MASK_HIGH 0xFF000000 -#define TIME_UNIT 1024 - -/* - * extended beacon time format - * time in usec will be changed into a 32-bit value in 8:24 format - * the high 1 byte is the beacon counts - * the lower 3 bytes is the time in usec within one beacon interval - */ - -/* TOOD: was used in sysfs debug interface need to add to mac */ -#if 0 -static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval) -{ - u32 quot; - u32 rem; - u32 interval = beacon_interval * 1024; - - if (!interval || !usec) - return 0; - - quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); - rem = (usec % interval) & BEACON_TIME_MASK_LOW; - - return (quot << 24) + rem; -} - -/* base is usually what we get from ucode with each received frame, - * the same as HW timer counter counting down - */ - -static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) -{ - u32 base_low = base & BEACON_TIME_MASK_LOW; - u32 addon_low = addon & BEACON_TIME_MASK_LOW; - u32 interval = beacon_interval * TIME_UNIT; - u32 res = (base & BEACON_TIME_MASK_HIGH) + - (addon & BEACON_TIME_MASK_HIGH); - - if (base_low > addon_low) - res += base_low - addon_low; - else if (base_low < addon_low) { - res += interval + base_low - addon_low; - res += (1 << 24); - } else - res += (1 << 24); - - return cpu_to_le32(res); -} -static int iwl_get_measurement(struct iwl_priv *priv, - struct ieee80211_measurement_params *params, - u8 type) -{ - struct iwl4965_spectrum_cmd spectrum; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SPECTRUM_MEASUREMENT_CMD, - .data = (void *)&spectrum, - .meta.flags = CMD_WANT_SKB, - }; - u32 add_time = le64_to_cpu(params->start_time); - int rc; - int spectrum_resp_status; - int duration = le16_to_cpu(params->duration); - - if (iwl_is_associated(priv)) - add_time = - iwl_usecs_to_beacons( - le64_to_cpu(params->start_time) - priv->last_tsf, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - - memset(&spectrum, 0, sizeof(spectrum)); - - spectrum.channel_count = cpu_to_le16(1); - spectrum.flags = - RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; - spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; - cmd.len = sizeof(spectrum); - spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - - if (iwl_is_associated(priv)) - spectrum.start_time = - iwl_add_beacon_time(priv->last_beacon_time, - add_time, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - else - spectrum.start_time = 0; - - spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); - spectrum.channels[0].channel = params->channel; - spectrum.channels[0].type = type; - if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) - spectrum.flags |= RXON_FLG_BAND_24G_MSK | - RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); - rc = -EIO; - } - - spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); - switch (spectrum_resp_status) { - case 0: /* Command will be handled */ - if (res->u.spectrum.id != 0xff) { - IWL_DEBUG_INFO(priv, - "Replaced existing measurement: %d\n", - res->u.spectrum.id); - priv->measurement_status &= ~MEASUREMENT_READY; - } - priv->measurement_status |= MEASUREMENT_ACTIVE; - rc = 0; - break; - - case 1: /* Command will not be handled */ - rc = -EAGAIN; - break; - } - - dev_kfree_skb_any(cmd.meta.u.skb); - - return rc; -} -#endif - -static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); - - if (!report->state) { - IWL_DEBUG_11H(priv, - "Spectrum Measure Notification: Start\n"); - return; - } - - memcpy(&priv->measure_report, report, sizeof(*report)); - priv->measurement_status |= MEASUREMENT_READY; -} - -void iwl_setup_spectrum_handlers(struct iwl_priv *priv) -{ - priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = - iwl_rx_spectrum_measure_notif; -} -EXPORT_SYMBOL(iwl_setup_spectrum_handlers); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9c0b6ebbdc59..cd42b5838b38 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -56,6 +56,7 @@ #include "iwl-helpers.h" #include "iwl-core.h" #include "iwl-dev.h" +#include "iwl-spectrum.h" /* * module name, copyright, version, etc. @@ -70,13 +71,12 @@ #define VD #endif -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT -#define VS "s" -#else -#define VS -#endif - -#define DRV_VERSION IWLWIFI_VERSION VD VS +/* + * add "s" to indicate spectrum measurement included. + * we add it here to be consistent with previous releases in which + * this was configurable. + */ +#define DRV_VERSION IWLWIFI_VERSION VD "s" #define DRV_COPYRIGHT "Copyright(c) 2003-2010 Intel Corporation" #define DRV_AUTHOR "" @@ -689,10 +689,6 @@ drop: return -1; } -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - -#include "iwl-spectrum.h" - #define BEACON_TIME_MASK_LOW 0x00FFFFFF #define BEACON_TIME_MASK_HIGH 0xFF000000 #define TIME_UNIT 1024 @@ -819,7 +815,6 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, return rc; } -#endif static void iwl3945_rx_reply_alive(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -962,6 +957,8 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; + priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = + iwl_rx_spectrum_measure_notif; priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; @@ -975,7 +972,6 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; - iwl_setup_spectrum_handlers(priv); iwl_setup_rx_scan_handlers(priv); priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; @@ -3569,8 +3565,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) { @@ -3640,7 +3634,6 @@ static ssize_t store_measurement(struct device *d, static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, show_measurement, store_measurement); -#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, @@ -3823,9 +3816,7 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_dump_errors.attr, &dev_attr_flags.attr, &dev_attr_filter_flags.attr, -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT &dev_attr_measurement.attr, -#endif &dev_attr_retry_rate.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, -- cgit v1.2.3 From ff27fabe62d288038b36f41ac6a2190ed7d15993 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Fri, 22 Jan 2010 14:22:58 -0800 Subject: iwlwifi: fix throughput degradation in aggregation mode The following commit commit e4da8c37af626001ff704fb29ea14eb58f5f7208 Author: Johannes Berg Date: Wed Dec 23 13:15:43 2009 +0100 mac80211: make off-channel work generic triggered a bug in iwlwifi where HT parameters would not be correctly set in some mac80211 pathways. The aggregation (and possibly other) station flags were not being set, which limited the size of aggregation blocks and reduced throughput at high rates. >From Johannes: """ Due to Wey-Yi's patch to use the set-channel command when the channel changes while associated, we don't get a full new RXON. Therefore, we don't re-set the rxon-station either. However, under some circumstances that apparently have gotten more likely mac80211 will first set up the BSS info, then add the station and then switch to an HT channel type. Therefore, the check for "priv->current_ht_config.is_ht" in iwl_rxon_add_station() will hit false and not fill in the HT information. However, that check can just be removed, which is the easiest fix for all this, because the HT capa struct is always there, just could possibly have the ht_supported member set to false. """ A sample good link in my 3x3 network improves by approximately 25% TCP throughput. This fixes Bug 2144 (http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2144). Signed-off-by: Daniel Halperin Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index fcac73cf82bc..e0b13fb78653 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1045,24 +1045,19 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) struct ieee80211_sta_ht_cap *cur_ht_config = NULL; u8 sta_id; - /* Add station to device's station table */ - /* - * XXX: This check is definitely not correct, if we're an AP - * it'll always be false which is not what we want, but - * it doesn't look like iwlagn is prepared to be an HT - * AP anyway. + * Set HT capabilities. It is ok to set this struct even if not using + * HT config: the priv->current_ht_config.is_ht flag will just be false */ - if (priv->current_ht_config.is_ht) { - rcu_read_lock(); - sta = ieee80211_find_sta(priv->vif, addr); - if (sta) { - memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); - cur_ht_config = &ht_config; - } - rcu_read_unlock(); + rcu_read_lock(); + sta = ieee80211_find_sta(priv->vif, addr); + if (sta) { + memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); + cur_ht_config = &ht_config; } + rcu_read_unlock(); + /* Add station to device's station table */ sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); /* Set up default rate scaling table in device's station table */ -- cgit v1.2.3 From 658965107e2a45a1a4297cb494adc55797dd9ad1 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Jan 2010 03:26:11 +0100 Subject: ath9k: improve max rate retry handling ath9k currently forces hw->max_rate_tries to 4 to work around rate control inefficiencies. This has some negative side effects, such as rate_control_send_low also using a maximum of 4 tries, which could negatively affect reliability of unicast management frames. This patch pushes the retry limit to the rate control instead, and allows it to use more tries on the last stage to prevent unnecessary packet loss. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 3 +-- drivers/net/wireless/ath/ath9k/rc.c | 12 ++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5f78d7a5ff22..c3066b553546 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -640,8 +640,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->max_rates = 4; hw->channel_change_time = 5000; hw->max_listen_interval = 10; - /* Hardware supports 10 but we use 4 */ - hw->max_rate_tries = 4; + hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index c915954d4d5b..74290137f43d 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -678,13 +678,13 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, * For Multi Rate Retry we use a different number of * retry attempt counts. This ends up looking like this: * - * MRR[0] = 2 - * MRR[1] = 2 - * MRR[2] = 2 - * MRR[3] = 4 + * MRR[0] = 4 + * MRR[1] = 4 + * MRR[2] = 4 + * MRR[3] = 8 * */ - try_per_rate = sc->hw->max_rate_tries; + try_per_rate = 4; rate_table = sc->cur_rate_table; rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); @@ -714,7 +714,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, for ( ; i < 4; i++) { /* Use twice the number of tries for the last MRR segment. */ if (i + 1 == 4) - try_per_rate = 4; + try_per_rate = 8; ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); /* All other rates in the series have RTS enabled */ -- cgit v1.2.3 From 96869a39399269a776a94812e9fff3d38b47d838 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 24 Jan 2010 13:13:32 +0100 Subject: b43: Workaround circular locking in hw-tkip key update callback The TKIP key update callback is called from the RX path, where the driver mutex is already locked. This results in a circular locking bug. Avoid this by removing the lock. Johannes noted that there is a separate bug: The callback still breaks on SDIO hardware, because SDIO hardware access needs to sleep, but we are not allowed to sleep in the callback due to mac80211's RCU locking. Signed-off-by: Michael Buesch Tested-by: Larry Finger Reported-by: kecsa@kutfo.hit.bme.hu Cc: Johannes Berg Cc: stable Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6d7cf3c2f7bf..66220cde9c49 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -856,22 +856,19 @@ static void b43_op_update_tkip_key(struct ieee80211_hw *hw, if (B43_WARN_ON(!modparam_hwtkip)) return; - mutex_lock(&wl->mutex); - + /* This is only called from the RX path through mac80211, where + * our mutex is already locked. */ + B43_WARN_ON(!mutex_is_locked(&wl->mutex)); dev = wl->current_dev; - if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) - goto out_unlock; + B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED); keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ rx_tkip_phase1_write(dev, index, iv32, phase1key); /* only pairwise TKIP keys are supported right now */ if (WARN_ON(!sta)) - goto out_unlock; + return; keymac_write(dev, index, sta->addr); - -out_unlock: - mutex_unlock(&wl->mutex); } static void do_key_write(struct b43_wldev *dev, -- cgit v1.2.3 From eb807fb23878bc319e029ed8ce3d835d239723a5 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 24 Jan 2010 14:55:12 +0200 Subject: mac80211: fix update_tkip_key() documentation about the context Johannes noticed that I had incorrectly documented the context of update_tkip_key() driver operation. It must be atomic because all RX code is run inside rcu critical section. Reported-by: Johannes Berg Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/net/mac80211.h | 2 +- net/mac80211/driver-ops.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f56d6f479532..f64402f6312b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1489,7 +1489,7 @@ enum ieee80211_ampdu_mlme_action { * @update_tkip_key: See the section "Hardware crypto acceleration" * This callback will be called in the context of Rx. Called for drivers * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. - * The callback can sleep. + * The callback must be atomic. * * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. The scan must honour the channel diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 40c6e9a89864..6c31f38ac7f5 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -144,8 +144,6 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, { struct ieee80211_sta *ista = NULL; - might_sleep(); - if (sta) ista = &sta->sta; -- cgit v1.2.3 From 1396b231b0369c4146988c2f42fb416ae19e2572 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 24 Jan 2010 20:44:35 +0100 Subject: mac80211: fix WARN_ON in the new work code ieee80211_work_rx_mgmt currently enqueues various management frames, including deauth and disassoc frames, however the function ieee80211_work_rx_queued_mgmt does not handle these, as they should only occur if the AP is buggy. It does emit a WARN_ON when this happens though, and several users have reported such instances. Fix the WARN_ON by not queueing such frames in the first place. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/work.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 81bd5d592bb4..df8277cdb4d0 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -1022,8 +1022,6 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, case IEEE80211_STYPE_PROBE_RESP: case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: - case IEEE80211_STYPE_DEAUTH: - case IEEE80211_STYPE_DISASSOC: skb_queue_tail(&local->work_skb_queue, skb); ieee80211_queue_work(&local->hw, &local->work_work); return RX_QUEUED; -- cgit v1.2.3 From 382b16559d599c4260aeb82a5ea5ba44459d1cd2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Jan 2010 11:36:16 +0100 Subject: mac80211: fix sw crypto What a stupid mistake. In commit 813d76694043d00b59475baa1fbfaf54a2eb7fad Author: Johannes Berg Date: Sun Jan 17 01:47:58 2010 +0100 mac80211: move control.hw_key assignment I inserted code testing the wrong flags field, which means that the test is almost always true (it's really testing for the peer's WMM support) and thus the later parts of the stack assume hw crypto will be done even if that's not true. Obviously, that broke software crypto. Maxim said so specifically, and Jochen probably uses some cipher that iwl3945 doesn't support in hardware, which might also explain that Maxim reports that even hw crypto is broken. Fix this to test the right flags field. Reported-by: Maxim Levitsky Reported-by: Jochen Friedrich Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d017b3530d4d..14c70452c245 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -559,7 +559,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) } if (!skip_hw && tx->key && - tx->key->conf.flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) info->control.hw_key = &tx->key->conf; } -- cgit v1.2.3 From 723bae7ee44fd79c1cd3c7531ed581d373920774 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Jan 2010 13:36:36 +0100 Subject: mac80211: track work started through callbacks Currently, the remain_on_channel work callback needs to track in its own data structure whether the work was just started or not. By reordering some code this becomes unnecessary, the generic wk->started variable can still be 'false' on the first invocation and only be 'true' on actual timeout invocations, so that the extra variable can be removed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 - net/mac80211/work.c | 17 ++++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c18f576f1848..3067fbd69d63 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -299,7 +299,6 @@ struct ieee80211_work { } assoc; struct { u32 duration; - bool started; } remain; }; diff --git a/net/mac80211/work.c b/net/mac80211/work.c index df8277cdb4d0..7e708d5c88b4 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -535,8 +535,7 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) * First time we run, do nothing -- the generic code will * have switched to the right channel etc. */ - if (!wk->remain.started) { - wk->remain.started = true; + if (!wk->started) { wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, @@ -821,15 +820,17 @@ static void ieee80211_work_work(struct work_struct *work) mutex_lock(&local->work_mtx); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + bool started = wk->started; + /* mark work as started if it's on the current off-channel */ - if (!wk->started && local->tmp_channel && + if (!started && local->tmp_channel && wk->chan == local->tmp_channel && wk->chan_type == local->tmp_channel_type) { - wk->started = true; + started = true; wk->timeout = jiffies; } - if (!wk->started && !local->tmp_channel) { + if (!started && !local->tmp_channel) { /* * TODO: could optimize this by leaving the * station vifs in awake mode if they @@ -842,12 +843,12 @@ static void ieee80211_work_work(struct work_struct *work) local->tmp_channel = wk->chan; local->tmp_channel_type = wk->chan_type; ieee80211_hw_config(local, 0); - wk->started = true; + started = true; wk->timeout = jiffies; } /* don't try to work with items that aren't started */ - if (!wk->started) + if (!started) continue; if (time_is_after_jiffies(wk->timeout)) { @@ -882,6 +883,8 @@ static void ieee80211_work_work(struct work_struct *work) break; } + wk->started = started; + switch (rma) { case WORK_ACT_NONE: /* might have changed the timeout */ -- cgit v1.2.3 From 3ed0fac3b56504aaaa3d800e7891ed4a7068b85c Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 25 Jan 2010 18:59:58 +0100 Subject: b43: N-PHY: fix one bit off in parsing RF Ctrl Override arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index a45a1f3ced42..061b01b814d1 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1031,7 +1031,7 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, u8 index = fls(field); u8 addr, en_addr, val_addr; /* we expect only one bit set */ - B43_WARN_ON(field & (~(1 << index))); + B43_WARN_ON(field & (~(1 << (index - 1)))); if (dev->phy.rev >= 3) { const struct nphy_rf_control_override_rev3 *rf_ctrl; -- cgit v1.2.3 From 986504540306137dfc90a936f9f25086d15621c5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 25 Jan 2010 18:59:59 +0100 Subject: b43: make cordic common (LP-PHY and N-PHY need it) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_common.c | 38 +++++++++++++++++++++++++++++ drivers/net/wireless/b43/phy_common.h | 3 +++ drivers/net/wireless/b43/phy_lp.c | 45 ++--------------------------------- 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 75b26e175e8f..446c41bb1e9f 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -421,3 +421,41 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) { b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); } + +struct b43_c32 b43_cordic(int theta) +{ + u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, + 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, + 229, 115, 57, 29, }; + int i, tmp, signx = 1, angle = 0; + struct b43_c32 ret = { .i = 39797, .q = 0, }; + + theta = clamp_t(int, theta, -180, 180); + + if (theta > 90) { + theta -= 180; + signx = -1; + } else if (theta < -90) { + theta += 180; + signx = -1; + } + + for (i = 0; i <= 17; i++) { + if (theta > angle) { + tmp = ret.i - (ret.q >> i); + ret.q += ret.i >> i; + ret.i = tmp; + angle += arctg[i]; + } else { + tmp = ret.i + (ret.q >> i); + ret.q -= ret.i >> i; + ret.i = tmp; + angle -= arctg[i]; + } + } + + ret.i *= signx; + ret.q *= signx; + + return ret; +} diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index f635f9e4f83d..9e4de47d0608 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -5,6 +5,8 @@ struct b43_wldev; +/* Complex number using 2 32-bit signed integers */ +struct b43_c32 { s32 i, q; }; /* PHY register routing bits */ #define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ @@ -421,5 +423,6 @@ int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset); */ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); +struct b43_c32 b43_cordic(int theta); #endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index b58d6cf26580..453585073437 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1767,47 +1767,6 @@ out: return ret; } -/* Complex number using 2 32-bit signed integers */ -typedef struct {s32 i, q;} lpphy_c32; - -static lpphy_c32 lpphy_cordic(int theta) -{ - u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, - 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, - 229, 115, 57, 29, }; - int i, tmp, signx = 1, angle = 0; - lpphy_c32 ret = { .i = 39797, .q = 0, }; - - theta = clamp_t(int, theta, -180, 180); - - if (theta > 90) { - theta -= 180; - signx = -1; - } else if (theta < -90) { - theta += 180; - signx = -1; - } - - for (i = 0; i <= 17; i++) { - if (theta > angle) { - tmp = ret.i - (ret.q >> i); - ret.q += ret.i >> i; - ret.i = tmp; - angle += arctg[i]; - } else { - tmp = ret.i + (ret.q >> i); - ret.q -= ret.i >> i; - ret.i = tmp; - angle -= arctg[i]; - } - } - - ret.i *= signx; - ret.q *= signx; - - return ret; -} - static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops, u16 wait) { @@ -1826,7 +1785,7 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) struct b43_phy_lp *lpphy = dev->phy.lp; u16 buf[64]; int i, samples = 0, angle = 0, rotation = (9 * freq) / 500; - lpphy_c32 sample; + struct b43_c32 sample; lpphy->tx_tone_freq = freq; @@ -1842,7 +1801,7 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) } for (i = 0; i < samples; i++) { - sample = lpphy_cordic(angle); + sample = b43_cordic(angle); angle += rotation; buf[i] = ((sample.i * max) & 0xFF) << 8; buf[i] |= (sample.q * max) & 0xFF; -- cgit v1.2.3 From 6f98e62a9f1bdbd83d8d1be8c2ca6f58099846ef Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 25 Jan 2010 19:00:00 +0100 Subject: b43: update cordic code to match current specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Tested-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_common.c | 19 +++++++++++++------ drivers/net/wireless/b43/phy_common.h | 4 ++++ drivers/net/wireless/b43/phy_lp.c | 7 ++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 446c41bb1e9f..8f7d7eff2d80 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -422,21 +422,28 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304, 58666, 29335, 14668, 7334, 3667, 1833, 917, 458, 229, 115, 57, 29, }; - int i, tmp, signx = 1, angle = 0; + u8 i; + s32 tmp; + s8 signx = 1; + u32 angle = 0; struct b43_c32 ret = { .i = 39797, .q = 0, }; - theta = clamp_t(int, theta, -180, 180); + while (theta > (180 << 16)) + theta -= (360 << 16); + while (theta < -(180 << 16)) + theta += (360 << 16); - if (theta > 90) { - theta -= 180; + if (theta > (90 << 16)) { + theta -= (180 << 16); signx = -1; - } else if (theta < -90) { - theta += 180; + } else if (theta < -(90 << 16)) { + theta += (180 << 16); signx = -1; } diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 9e4de47d0608..bd480b481bfc 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -8,6 +8,10 @@ struct b43_wldev; /* Complex number using 2 32-bit signed integers */ struct b43_c32 { s32 i, q; }; +#define CORDIC_CONVERT(value) (((value) >= 0) ? \ + ((((value) >> 15) + 1) >> 1) : \ + -((((-(value)) >> 15) + 1) >> 1)) + /* PHY register routing bits */ #define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ #define B43_PHYROUTE_BASE 0x0000 /* Base registers */ diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 453585073437..185219e0a552 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -1784,7 +1784,8 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) { struct b43_phy_lp *lpphy = dev->phy.lp; u16 buf[64]; - int i, samples = 0, angle = 0, rotation = (9 * freq) / 500; + int i, samples = 0, angle = 0; + int rotation = (((36 * freq) / 20) << 16) / 100; struct b43_c32 sample; lpphy->tx_tone_freq = freq; @@ -1803,8 +1804,8 @@ static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max) for (i = 0; i < samples; i++) { sample = b43_cordic(angle); angle += rotation; - buf[i] = ((sample.i * max) & 0xFF) << 8; - buf[i] |= (sample.q * max) & 0xFF; + buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8; + buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF); } b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf); -- cgit v1.2.3 From f2982181e0531c0b12752336a1578626f99e7828 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Mon, 25 Jan 2010 19:00:01 +0100 Subject: b43: N-PHY: use cordic to generate samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 061b01b814d1..df4bf435e218 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -821,8 +821,9 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, bool test) { int i; - u16 bw, len, num, rot, angle; - /* TODO: *buffer; */ + u16 bw, len, rot, angle; + b43_c32 *samples; + bw = (dev->phy.is_40mhz) ? 40 : 20; len = bw << 3; @@ -839,18 +840,20 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, len = bw << 1; } - /* TODO: buffer = kzalloc(len * sizeof(u32), GFP_KERNEL); */ - num = len; + samples = kzalloc(len * sizeof(b43_c32), GFP_KERNEL); rot = (((freq * 36) / bw) << 16) / 100; angle = 0; - for (i = 0; i < num; i++) { - /* TODO */ + for (i = 0; i < len; i++) { + samples[i] = b43_cordic(angle); + angle += rot; + samples[i].q = CORDIC_CONVERT(samples[i].q * max); + samples[i].i = CORDIC_CONVERT(samples[i].i * max); } - /* TODO: Call N PHY Load Sample Table with buffer, num as arguments */ - /* TODO: kfree(buffer); */ - return num; + /* TODO: Call N PHY Load Sample Table with buffer, len as arguments */ + kfree(samples); + return len; } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ -- cgit v1.2.3 From 18c949070b57d2cbcc0b25c5cfa003ece204e468 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Jan 2010 19:07:39 +0100 Subject: mac80211: fill jiffies/vif on filtered frames Filtered frames not only need their control information cleared to avoid wrong checks, but also need to have jiffies and vif assigned so they can be processed or expired. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/status.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 800b6777e0ed..e57ad6b1d7ea 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -53,6 +53,9 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, * modified/encrypted again. */ memset(&info->control, 0, sizeof(info->control)); + + info->control.jiffies = jiffies; + info->control.vif = &sta->sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | IEEE80211_TX_INTFL_RETRANSMISSION; -- cgit v1.2.3 From b747caf365b4121903b26d1cd65454c7bc607184 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 26 Jan 2010 05:17:00 -0800 Subject: ariadne: Fix build. References removed HAVE_MULTICAST. Reporeted-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ariadne.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index c35af3e106b1..e2c202493fa7 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -123,9 +123,7 @@ static void ariadne_reset(struct net_device *dev); static irqreturn_t ariadne_interrupt(int irq, void *data); static int ariadne_close(struct net_device *dev); static struct net_device_stats *ariadne_get_stats(struct net_device *dev); -#ifdef HAVE_MULTICAST static void set_multicast_list(struct net_device *dev); -#endif static void memcpyw(volatile u_short *dest, u_short *src, int len) -- cgit v1.2.3 From c21dbf9214bce129f92e1af05552553ff0e318ed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Jan 2010 14:15:46 +0100 Subject: cfg80211: export cfg80211_find_ie This new function (previously a static function called just "find_ie" can be used to find a specific IE in a buffer of IEs. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 16 ++++++++++++++++ net/wireless/scan.c | 38 ++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index c5d16f299d6f..a3f0a7ed31ac 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1658,6 +1658,22 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, */ unsigned int cfg80211_classify8021d(struct sk_buff *skb); +/** + * cfg80211_find_ie - find information element in data + * + * @eid: element ID + * @ies: data consisting of IEs + * @len: length of data + * + * This function will return %NULL if the element ID could + * not be found or if the element is invalid (claims to be + * longer than the given data), or a pointer to the first byte + * of the requested element, that is the byte containing the + * element ID. There are no checks on the element length + * other than having to fit into the given data. + */ +const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len); + /* * Regulatory helper functions for wiphys */ diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 06b0231ee5e3..978cac3414b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -143,9 +143,9 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev) dev->bss_generation++; } -static u8 *find_ie(u8 num, u8 *ies, int len) +const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len) { - while (len > 2 && ies[0] != num) { + while (len > 2 && ies[0] != eid) { len -= ies[1] + 2; ies += ies[1] + 2; } @@ -155,11 +155,12 @@ static u8 *find_ie(u8 num, u8 *ies, int len) return NULL; return ies; } +EXPORT_SYMBOL(cfg80211_find_ie); static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) { - const u8 *ie1 = find_ie(num, ies1, len1); - const u8 *ie2 = find_ie(num, ies2, len2); + const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); + const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); int r; if (!ie1 && !ie2) @@ -185,9 +186,9 @@ static bool is_bss(struct cfg80211_bss *a, if (!ssid) return true; - ssidie = find_ie(WLAN_EID_SSID, - a->information_elements, - a->len_information_elements); + ssidie = cfg80211_find_ie(WLAN_EID_SSID, + a->information_elements, + a->len_information_elements); if (!ssidie) return false; if (ssidie[1] != ssid_len) @@ -204,9 +205,9 @@ static bool is_mesh(struct cfg80211_bss *a, if (!is_zero_ether_addr(a->bssid)) return false; - ie = find_ie(WLAN_EID_MESH_ID, - a->information_elements, - a->len_information_elements); + ie = cfg80211_find_ie(WLAN_EID_MESH_ID, + a->information_elements, + a->len_information_elements); if (!ie) return false; if (ie[1] != meshidlen) @@ -214,9 +215,9 @@ static bool is_mesh(struct cfg80211_bss *a, if (memcmp(ie + 2, meshid, meshidlen)) return false; - ie = find_ie(WLAN_EID_MESH_CONFIG, - a->information_elements, - a->len_information_elements); + ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, + a->information_elements, + a->len_information_elements); if (!ie) return false; if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) @@ -395,11 +396,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, if (is_zero_ether_addr(res->pub.bssid)) { /* must be mesh, verify */ - meshid = find_ie(WLAN_EID_MESH_ID, res->pub.information_elements, - res->pub.len_information_elements); - meshcfg = find_ie(WLAN_EID_MESH_CONFIG, - res->pub.information_elements, - res->pub.len_information_elements); + meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, + res->pub.information_elements, + res->pub.len_information_elements); + meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, + res->pub.information_elements, + res->pub.len_information_elements); if (!meshid || !meshcfg || meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { /* bogus mesh */ -- cgit v1.2.3 From 56007a028c51cbf800a6c969d6f6431d23443b99 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Jan 2010 14:19:52 +0100 Subject: mac80211: wait for beacon before enabling powersave Because DTIM information is required for powersave but is only conveyed in beacons, wait for a beacon before enabling powersave, and change the way the information is conveyed to the driver accordingly. mwl8k doesn't currently seem to implement PS but requires the DTIM period in a different way; after talking to Lennert we agreed to just have mwl8k do the parsing itself in the finalize_join work. Signed-off-by: Johannes Berg Acked-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/mwl8k.c | 14 +++++++++----- drivers/net/wireless/wl12xx/wl1251.h | 3 --- drivers/net/wireless/wl12xx/wl1251_main.c | 25 +++++++------------------ include/net/mac80211.h | 7 ++++++- net/mac80211/mlme.c | 27 ++++++++++++++++++++++++--- net/mac80211/scan.c | 4 ---- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 8599444bef01..9e3ca0641451 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -319,7 +319,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; if (priv->vif) - dtimper = priv->vif->bss_conf.dtim_period; + dtimper = priv->hw->conf.ps_dtim_period; else dtimper = 1; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 68546ca0ba37..f0f08f3919cc 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3881,12 +3881,16 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) struct mwl8k_priv *priv = container_of(work, struct mwl8k_priv, finalize_join_worker); struct sk_buff *skb = priv->beacon_skb; - struct mwl8k_vif *mwl8k_vif; + struct ieee80211_mgmt *mgmt = (void *)skb->data; + int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable); + const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM, + mgmt->u.beacon.variable, len); + int dtim_period = 1; + + if (tim && tim[1] >= 2) + dtim_period = tim[3]; - mwl8k_vif = mwl8k_first_vif(priv); - if (mwl8k_vif != NULL) - mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, - mwl8k_vif->vif->bss_conf.dtim_period); + mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period); dev_kfree_skb(skb); priv->beacon_skb = NULL; diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 6301578d1565..37c61c19cae5 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -341,9 +341,6 @@ struct wl1251 { /* Are we currently scanning */ bool scanning; - /* Our association ID */ - u16 aid; - /* Default key (for WEP) */ u32 default_key; diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 595f0f94d16e..a717dde4822e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -617,10 +617,13 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) wl->psm_requested = true; + wl->dtim_period = conf->ps_dtim_period; + + ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int, + wl->dtim_period); + /* - * We enter PSM only if we're already associated. - * If we're not, we'll enter it when joining an SSID, - * through the bss_info_changed() hook. + * mac80211 enables PSM only if we're already associated. */ ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) @@ -943,7 +946,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changed) { - enum wl1251_cmd_ps_mode mode; struct wl1251 *wl = hw->priv; struct sk_buff *beacon, *skb; int ret; @@ -984,11 +986,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->beacon_int = bss_conf->beacon_int; - wl->dtim_period = bss_conf->dtim_period; - - ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int, - wl->dtim_period); - wl->aid = bss_conf->aid; skb = ieee80211_pspoll_get(wl->hw, wl->vif); if (!skb) @@ -1001,17 +998,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; - ret = wl1251_acx_aid(wl, wl->aid); + ret = wl1251_acx_aid(wl, bss_conf->aid); if (ret < 0) goto out_sleep; - - /* If we want to go in PSM but we're not there yet */ - if (wl->psm_requested && !wl->psm) { - mode = STATION_POWER_SAVE_MODE; - ret = wl1251_ps_set_mode(wl, mode); - if (ret < 0) - goto out_sleep; - } } else { /* use defaults when not associated */ wl->beacon_int = WL1251_DEFAULT_BEACON_INT; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f64402f6312b..1e9c93024cf2 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -186,7 +186,8 @@ enum ieee80211_bss_change { * @use_short_slot: use short slot time (only relevant for ERP); * if the hardware cannot handle this it must set the * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag - * @dtim_period: num of beacons before the next DTIM, for PSM + * @dtim_period: num of beacons before the next DTIM, for beaconing, + * not valid in station mode (cf. hw conf ps_dtim_period) * @timestamp: beacon timestamp * @beacon_int: beacon interval * @assoc_capability: capabilities taken from assoc resp @@ -648,6 +649,9 @@ enum ieee80211_smps_mode { * value will be only achievable between DTIM frames, the hardware * needs to check for the multicast traffic bit in DTIM beacons. * This variable is valid only when the CONF_PS flag is set. + * @ps_dtim_period: The DTIM period of the AP we're connected to, for use + * in power saving. Power saving will not be enabled until a beacon + * has been received and the DTIM period is known. * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the * powersave documentation below. This variable is valid only when * the CONF_PS flag is set. @@ -674,6 +678,7 @@ struct ieee80211_conf { int max_sleep_period; u16 listen_interval; + u8 ps_dtim_period; u8 long_frame_max_tx_count, short_frame_max_tx_count; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1e1d16c55ee5..86c6ad1b058d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -484,6 +484,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) if (count == 1 && found->u.mgd.powersave && found->u.mgd.associated && + found->u.mgd.associated->beacon_ies && !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL))) { s32 beaconint_us; @@ -497,14 +498,22 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) if (beaconint_us > latency) { local->ps_sdata = NULL; } else { - u8 dtimper = found->vif.bss_conf.dtim_period; + struct ieee80211_bss *bss; int maxslp = 1; + u8 dtimper; - if (dtimper > 1) + bss = (void *)found->u.mgd.associated->priv; + dtimper = bss->dtim_period; + + /* If the TIM IE is invalid, pretend the value is 1 */ + if (!dtimper) + dtimper = 1; + else if (dtimper > 1) maxslp = min_t(int, dtimper, latency / beaconint_us); local->hw.conf.max_sleep_period = maxslp; + local->hw.conf.ps_dtim_period = dtimper; local->ps_sdata = found; } } else { @@ -702,7 +711,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, /* set timing information */ sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; sdata->vif.bss_conf.timestamp = cbss->tsf; - sdata->vif.bss_conf.dtim_period = bss->dtim_period; bss_info_changed |= BSS_CHANGED_BEACON_INT; bss_info_changed |= ieee80211_handle_bss_capability(sdata, @@ -1168,6 +1176,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, int freq; struct ieee80211_bss *bss; struct ieee80211_channel *channel; + bool need_ps = false; + + if (sdata->u.mgd.associated) { + bss = (void *)sdata->u.mgd.associated->priv; + /* not previously set so we may need to recalc */ + need_ps = !bss->dtim_period; + } if (elems->ds_params && elems->ds_params_len == 1) freq = ieee80211_channel_to_frequency(elems->ds_params[0]); @@ -1187,6 +1202,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (!sdata->u.mgd.associated) return; + if (need_ps) { + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); + } + if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)) { diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 9afe2f9885dc..bc061f629674 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -111,10 +111,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->dtim_period = tim_ie->dtim_period; } - /* set default value for buggy AP/no TIM element */ - if (bss->dtim_period == 0) - bss->dtim_period = 1; - bss->supp_rates_len = 0; if (elems->supp_rates) { clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; -- cgit v1.2.3 From 99824461ea72ca0044cc6508f02c0e1cabf37ba5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:00 +0000 Subject: net/atm: Convert printk to pr_ Add #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ Remove function names from output Use single line pr_debug instead of broken multiple uses without newline Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/br2684.c | 18 ++--- net/atm/clip.c | 60 ++++++++-------- net/atm/common.c | 52 +++++++------- net/atm/ioctl.c | 7 +- net/atm/lec.c | 192 ++++++++++++++++++++++------------------------------ net/atm/mpc.c | 4 +- net/atm/mpoa_proc.c | 3 +- net/atm/pppoatm.c | 17 ++--- net/atm/raw.c | 5 +- net/atm/resources.c | 12 ++-- net/atm/signaling.c | 19 +++--- net/atm/svc.c | 13 ++-- 12 files changed, 190 insertions(+), 212 deletions(-) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index c9230c398697..d72b1a579911 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -6,6 +6,8 @@ * Eric Kinzie, 2006-2007, US Naval Research Laboratory */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -148,7 +150,7 @@ static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb) struct br2684_vcc *brvcc = BR2684_VCC(vcc); struct net_device *net_dev = skb->dev; - pr_debug("br2684_pop(vcc %p ; net_dev %p )\n", vcc, net_dev); + pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev); brvcc->old_pop(vcc, skb); if (!net_dev) @@ -244,7 +246,7 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb, struct br2684_dev *brdev = BRPRIV(dev); struct br2684_vcc *brvcc; - pr_debug("br2684_start_xmit, skb_dst(skb)=%p\n", skb_dst(skb)); + pr_debug("skb_dst(skb)=%p\n", skb_dst(skb)); read_lock(&devs_lock); brvcc = pick_outgoing_vcc(skb, brdev); if (brvcc == NULL) { @@ -352,7 +354,7 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) struct net_device *net_dev = brvcc->device; struct br2684_dev *brdev = BRPRIV(net_dev); - pr_debug("br2684_push\n"); + pr_debug("\n"); if (unlikely(skb == NULL)) { /* skb==NULL means VCC is being destroyed */ @@ -479,8 +481,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) write_lock_irq(&devs_lock); net_dev = br2684_find_dev(&be.ifspec); if (net_dev == NULL) { - printk(KERN_ERR - "br2684: tried to attach to non-existant device\n"); + pr_err("tried to attach to non-existant device\n"); err = -ENXIO; goto error; } @@ -503,8 +504,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) err = -EINVAL; goto error; } - pr_debug("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, - be.encaps, brvcc); + pr_debug("vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, brvcc); if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { unsigned char *esi = atmvcc->dev->esi; if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) @@ -595,7 +595,7 @@ static int br2684_create(void __user * arg) struct atm_newif_br2684 ni; enum br2684_payload payload; - pr_debug("br2684_create\n"); + pr_debug("\n"); if (copy_from_user(&ni, arg, sizeof ni)) { return -EFAULT; @@ -624,7 +624,7 @@ static int br2684_create(void __user * arg) /* open, stop, do_ioctl ? */ err = register_netdev(netdev); if (err < 0) { - printk(KERN_ERR "br2684_create: register_netdev failed\n"); + pr_err("register_netdev failed\n"); free_netdev(netdev); return err; } diff --git a/net/atm/clip.c b/net/atm/clip.c index 64629c354343..d7939fd58cd3 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -2,6 +2,8 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include /* for UINT_MAX */ @@ -51,7 +53,7 @@ static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip) struct atmarp_ctrl *ctrl; struct sk_buff *skb; - pr_debug("to_atmarpd(%d)\n", type); + pr_debug("(%d)\n", type); if (!atmarpd) return -EUNATCH; skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC); @@ -71,8 +73,7 @@ static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip) static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry) { - pr_debug("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry, - entry->neigh); + pr_debug("%p to entry %p (neigh %p)\n", clip_vcc, entry, entry->neigh); clip_vcc->entry = entry; clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */ clip_vcc->next = entry->vccs; @@ -86,7 +87,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) struct clip_vcc **walk; if (!entry) { - printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc); + pr_crit("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc); return; } netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */ @@ -106,12 +107,10 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) error = neigh_update(entry->neigh, NULL, NUD_NONE, NEIGH_UPDATE_F_ADMIN); if (error) - printk(KERN_CRIT "unlink_clip_vcc: " - "neigh_update failed with %d\n", error); + pr_crit("neigh_update failed with %d\n", error); goto out; } - printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc " - "0x%p)\n", entry, clip_vcc); + pr_crit("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc); out: netif_tx_unlock_bh(entry->neigh->dev); } @@ -127,7 +126,7 @@ static int neigh_check_cb(struct neighbour *n) if (cv->idle_timeout && time_after(jiffies, exp)) { pr_debug("releasing vcc %p->%p of entry %p\n", - cv, cv->vcc, entry); + cv, cv->vcc, entry); vcc_release_async(cv->vcc, -ETIMEDOUT); } } @@ -139,7 +138,7 @@ static int neigh_check_cb(struct neighbour *n) struct sk_buff *skb; pr_debug("destruction postponed with ref %d\n", - atomic_read(&n->refcnt)); + atomic_read(&n->refcnt)); while ((skb = skb_dequeue(&n->arp_queue)) != NULL) dev_kfree_skb(skb); @@ -163,7 +162,7 @@ static int clip_arp_rcv(struct sk_buff *skb) { struct atm_vcc *vcc; - pr_debug("clip_arp_rcv\n"); + pr_debug("\n"); vcc = ATM_SKB(skb)->vcc; if (!vcc || !atm_charge(vcc, skb->truesize)) { dev_kfree_skb_any(skb); @@ -188,7 +187,7 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); - pr_debug("clip push\n"); + pr_debug("\n"); if (!skb) { pr_debug("removing VCC %p\n", clip_vcc); if (clip_vcc->entry) @@ -239,7 +238,7 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb) int old; unsigned long flags; - pr_debug("clip_pop(vcc %p)\n", vcc); + pr_debug("(vcc %p)\n", vcc); clip_vcc->old_pop(vcc, skb); /* skb->dev == NULL in outbound ARP packets */ if (!dev) @@ -255,7 +254,7 @@ static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb) static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb) { - pr_debug("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb); + pr_debug("(neigh %p, skb %p)\n", neigh, skb); to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip); } @@ -284,7 +283,7 @@ static int clip_constructor(struct neighbour *neigh) struct in_device *in_dev; struct neigh_parms *parms; - pr_debug("clip_constructor (neigh %p, entry %p)\n", neigh, entry); + pr_debug("(neigh %p, entry %p)\n", neigh, entry); neigh->type = inet_addr_type(&init_net, entry->ip); if (neigh->type != RTN_UNICAST) return -EINVAL; @@ -369,9 +368,9 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, int old; unsigned long flags; - pr_debug("clip_start_xmit (skb %p)\n", skb); + pr_debug("(skb %p)\n", skb); if (!skb_dst(skb)) { - printk(KERN_ERR "clip_start_xmit: skb_dst(skb) == NULL\n"); + pr_err("skb_dst(skb) == NULL\n"); dev_kfree_skb(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; @@ -385,7 +384,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, return 0; } #endif - printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n"); + pr_err("NO NEIGHBOUR !\n"); dev_kfree_skb(skb); dev->stats.tx_dropped++; return NETDEV_TX_OK; @@ -421,7 +420,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb, pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev); old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */ if (old) { - printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); + pr_warning("XOFF->XOFF transition\n"); return NETDEV_TX_OK; } dev->stats.tx_packets++; @@ -456,7 +455,7 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL); if (!clip_vcc) return -ENOMEM; - pr_debug("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc); + pr_debug("%p vcc %p\n", clip_vcc, vcc); clip_vcc->vcc = vcc; vcc->user_back = clip_vcc; set_bit(ATM_VF_IS_CLIP, &vcc->flags); @@ -506,16 +505,16 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip) struct rtable *rt; if (vcc->push != clip_push) { - printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n"); + pr_warning("non-CLIP VCC\n"); return -EBADF; } clip_vcc = CLIP_VCC(vcc); if (!ip) { if (!clip_vcc->entry) { - printk(KERN_ERR "hiding hidden ATMARP entry\n"); + pr_err("hiding hidden ATMARP entry\n"); return 0; } - pr_debug("setentry: remove\n"); + pr_debug("remove\n"); unlink_clip_vcc(clip_vcc); return 0; } @@ -529,9 +528,9 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip) entry = NEIGH2ENTRY(neigh); if (entry != clip_vcc->entry) { if (!clip_vcc->entry) - pr_debug("setentry: add\n"); + pr_debug("add\n"); else { - pr_debug("setentry: update\n"); + pr_debug("update\n"); unlink_clip_vcc(clip_vcc); } link_vcc(clip_vcc, entry); @@ -614,16 +613,16 @@ static int clip_device_event(struct notifier_block *this, unsigned long event, switch (event) { case NETDEV_UP: - pr_debug("clip_device_event NETDEV_UP\n"); + pr_debug("NETDEV_UP\n"); to_atmarpd(act_up, PRIV(dev)->number, 0); break; case NETDEV_GOING_DOWN: - pr_debug("clip_device_event NETDEV_DOWN\n"); + pr_debug("NETDEV_DOWN\n"); to_atmarpd(act_down, PRIV(dev)->number, 0); break; case NETDEV_CHANGE: case NETDEV_CHANGEMTU: - pr_debug("clip_device_event NETDEV_CHANGE*\n"); + pr_debug("NETDEV_CHANGE*\n"); to_atmarpd(act_change, PRIV(dev)->number, 0); break; } @@ -660,7 +659,7 @@ static struct notifier_block clip_inet_notifier = { static void atmarpd_close(struct atm_vcc *vcc) { - pr_debug("atmarpd_close\n"); + pr_debug("\n"); rtnl_lock(); atmarpd = NULL; @@ -950,8 +949,7 @@ static int __init atm_clip_init(void) p = proc_create("arp", S_IRUGO, atm_proc_root, &arp_seq_fops); if (!p) { - printk(KERN_ERR "Unable to initialize " - "/proc/net/atm/arp\n"); + pr_err("Unable to initialize /proc/net/atm/arp\n"); atm_clip_exit_noproc(); return -ENOMEM; } diff --git a/net/atm/common.c b/net/atm/common.c index d61e051e0a3f..17f7e5f2131b 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -2,6 +2,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include #include @@ -64,8 +65,7 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", - sk_wmem_alloc_get(sk), size, - sk->sk_sndbuf); + sk_wmem_alloc_get(sk), size, sk->sk_sndbuf); return NULL; } while (!(skb = alloc_skb(size, GFP_KERNEL))) @@ -249,8 +249,7 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) max_sdu = ATM_MAX_AAL34_PDU; break; default: - printk(KERN_WARNING "ATM: AAL problems ... " - "(%d)\n",aal); + pr_warning("AAL problems ... (%d)\n", aal); /* fall through */ case ATM_AAL5: max_sdu = ATM_MAX_AAL5_PDU; @@ -385,11 +384,17 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); if (error) goto fail; - pr_debug("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal); - pr_debug(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, - vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); - pr_debug(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class, - vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); + pr_debug("VCC %d.%d, AAL %d\n", vpi, vci, vcc->qos.aal); + pr_debug(" TX: %d, PCR %d..%d, SDU %d\n", + vcc->qos.txtp.traffic_class, + vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr, + vcc->qos.txtp.max_sdu); + pr_debug(" RX: %d, PCR %d..%d, SDU %d\n", + vcc->qos.rxtp.traffic_class, + vcc->qos.rxtp.min_pcr, + vcc->qos.rxtp.max_pcr, + vcc->qos.rxtp.max_sdu); if (dev->ops->open) { if ((error = dev->ops->open(vcc))) @@ -413,7 +418,7 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) struct atm_vcc *vcc = ATM_SD(sock); int error; - pr_debug("vcc_connect (vpi %d, vci %d)\n",vpi,vci); + pr_debug("(vpi %d, vci %d)\n", vpi, vci); if (sock->state == SS_CONNECTED) return -EISCONN; if (sock->state != SS_UNCONNECTED) @@ -426,14 +431,15 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) else if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) return -EINVAL; - pr_debug("vcc_connect (TX: cl %d,bw %d-%d,sdu %d; " - "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", - vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, - vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, - vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr, - vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, - vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : - " ??? code ",vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); + pr_debug("(TX: cl %d,bw %d-%d,sdu %d; " + "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", + vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu, + vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr, + vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, + vcc->qos.aal == ATM_AAL5 ? "" : + vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ", + vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) return -EBADFD; if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || @@ -497,7 +503,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, if (error) return error; sock_recv_ts_and_drops(msg, sk, skb); - pr_debug("RcvM %d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize); + pr_debug("%d -= %d\n", atomic_read(&sk->sk_rmem_alloc), skb->truesize); atm_return(vcc, skb->truesize); skb_free_datagram(sk, skb); return copied; @@ -772,19 +778,19 @@ static int __init atm_init(void) goto out; if ((error = atmpvc_init()) < 0) { - printk(KERN_ERR "atmpvc_init() failed with %d\n", error); + pr_err("atmpvc_init() failed with %d\n", error); goto out_unregister_vcc_proto; } if ((error = atmsvc_init()) < 0) { - printk(KERN_ERR "atmsvc_init() failed with %d\n", error); + pr_err("atmsvc_init() failed with %d\n", error); goto out_atmpvc_exit; } if ((error = atm_proc_init()) < 0) { - printk(KERN_ERR "atm_proc_init() failed with %d\n",error); + pr_err("atm_proc_init() failed with %d\n", error); goto out_atmsvc_exit; } if ((error = atm_sysfs_init()) < 0) { - printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error); + pr_err("atm_sysfs_init() failed with %d\n", error); goto out_atmproc_exit; } out: diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 2ea40995dced..b75afba1f72b 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -3,6 +3,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ /* 2003 John Levon */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include #include @@ -97,8 +98,8 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg goto done; case ATM_SETSC: if (net_ratelimit()) - printk(KERN_WARNING "ATM_SETSC is obsolete; used by %s:%d\n", - current->comm, task_pid_nr(current)); + pr_warning("ATM_SETSC is obsolete; used by %s:%d\n", + current->comm, task_pid_nr(current)); error = 0; goto done; case ATMSIGD_CTRL: @@ -123,7 +124,7 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg to think about it at all. dwmw2. */ if (compat) { if (net_ratelimit()) - printk(KERN_WARNING "32-bit task cannot be atmsigd\n"); + pr_warning("32-bit task cannot be atmsigd\n"); error = -EINVAL; goto done; } diff --git a/net/atm/lec.c b/net/atm/lec.c index 42749b7b917c..6873813c3c99 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -4,6 +4,8 @@ * Marko Kiiskila */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -242,7 +244,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb) static void lec_tx_timeout(struct net_device *dev) { - printk(KERN_INFO "%s: tx timeout\n", dev->name); + pr_info("%s\n", dev->name); dev->trans_start = jiffies; netif_wake_queue(dev); } @@ -266,7 +268,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, int i = 0; #endif /* DUMP_PACKETS >0 */ - pr_debug("lec_start_xmit called\n"); + pr_debug("called\n"); if (!priv->lecd) { printk("%s:No lecd attached\n", dev->name); dev->stats.tx_errors++; @@ -276,8 +278,8 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, } pr_debug("skbuff head:%lx data:%lx tail:%lx end:%lx\n", - (long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb), - (long)skb_end_pointer(skb)); + (long)skb->head, (long)skb->data, (long)skb_tail_pointer(skb), + (long)skb_end_pointer(skb)); #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) if (memcmp(skb->data, bridge_ula_lec, sizeof(bridge_ula_lec)) == 0) lec_handle_bridge(skb, dev); @@ -286,7 +288,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, /* Make sure we have room for lec_id */ if (skb_headroom(skb) < 2) { - pr_debug("lec_start_xmit: reallocating skb\n"); + pr_debug("reallocating skb\n"); skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); kfree_skb(skb); if (skb2 == NULL) @@ -367,19 +369,16 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, #endif entry = NULL; vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); - pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n", dev->name, - vcc, vcc ? vcc->flags : 0, entry); + pr_debug("%s:vcc:%p vcc_flags:%lx, entry:%p\n", + dev->name, vcc, vcc ? vcc->flags : 0, entry); if (!vcc || !test_bit(ATM_VF_READY, &vcc->flags)) { if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { - pr_debug("%s:lec_start_xmit: queuing packet, ", - dev->name); - pr_debug("MAC address %pM\n", lec_h->h_dest); + pr_debug("%s:queuing packet, MAC address %pM\n", + dev->name, lec_h->h_dest); skb_queue_tail(&entry->tx_wait, skb); } else { - pr_debug - ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", - dev->name); - pr_debug("MAC address %pM\n", lec_h->h_dest); + pr_debug("%s:tx queue full or no arp entry, dropping, MAC address: %pM\n", + dev->name, lec_h->h_dest); dev->stats.tx_dropped++; dev_kfree_skb(skb); } @@ -390,8 +389,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, #endif /* DUMP_PACKETS > 0 */ while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { - pr_debug("lec.c: emptying tx queue, "); - pr_debug("MAC address %pM\n", lec_h->h_dest); + pr_debug("emptying tx queue, MAC address %pM\n", lec_h->h_dest); lec_send(vcc, skb2); } @@ -477,10 +475,10 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) mesg->content.normal.atm_addr, mesg->content.normal.flag, mesg->content.normal.targetless_le_arp); - pr_debug("lec: in l_arp_update\n"); + pr_debug("in l_arp_update\n"); if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */ - pr_debug("lec: LANE2 3.1.5, got tlvs, size %d\n", - mesg->sizeoftlvs); + pr_debug("LANE2 3.1.5, got tlvs, size %d\n", + mesg->sizeoftlvs); lane2_associate_ind(dev, mesg->content.normal.mac_addr, tmp, mesg->sizeoftlvs); } @@ -531,9 +529,8 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) struct sk_buff *skb2; struct sock *sk; - pr_debug - ("%s: entry found, responding to zeppelin\n", - dev->name); + pr_debug("%s: entry found, responding to zeppelin\n", + dev->name); skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); @@ -633,7 +630,7 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, sk->sk_data_ready(sk, skb->len); if (data != NULL) { - pr_debug("lec: about to send %d bytes of data\n", data->len); + pr_debug("about to send %d bytes of data\n", data->len); atm_force_charge(priv->lecd, data->truesize); skb_queue_tail(&sk->sk_receive_queue, data); sk->sk_data_ready(sk, skb->len); @@ -692,35 +689,27 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) struct lec_priv *priv = netdev_priv(dev); #if DUMP_PACKETS >0 - int i = 0; - char buf[300]; - - printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name, - vcc->vpi, vcc->vci); + printk(KERN_DEBUG "%s: vcc vpi:%d vci:%d\n", + dev->name, vcc->vpi, vcc->vci); #endif if (!skb) { pr_debug("%s: null skb\n", dev->name); lec_vcc_close(priv, vcc); return; } -#if DUMP_PACKETS > 0 - printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name, - skb->len, priv->lecid); #if DUMP_PACKETS >= 2 - for (i = 0; i < skb->len && i < 99; i++) { - sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); - } +#define MAX_SKB_DUMP 99 #elif DUMP_PACKETS >= 1 - for (i = 0; i < skb->len && i < 30; i++) { - sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); - } -#endif /* DUMP_PACKETS >= 1 */ - if (i == skb->len) - printk("%s\n", buf); - else - printk("%s...\n", buf); +#define MAX_SKB_DUMP 30 +#endif +#if DUMP_PACKETS > 0 + printk(KERN_DEBUG "%s: rcv datalen:%ld lecid:%4.4x\n", + dev->name, skb->len, priv->lecid); + print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1, + skb->data, min(MAX_SKB_DUMP, skb->len), true); #endif /* DUMP_PACKETS > 0 */ - if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) { /* Control frame, to daemon */ + if (memcmp(skb->data, lec_ctrl_magic, 4) == 0) { + /* Control frame, to daemon */ struct sock *sk = sk_atm(vcc); pr_debug("%s: To daemon\n", dev->name); @@ -801,7 +790,7 @@ static void lec_pop(struct atm_vcc *vcc, struct sk_buff *skb) struct net_device *dev = skb->dev; if (vpriv == NULL) { - printk("lec_pop(): vpriv = NULL!?!?!?\n"); + pr_info("vpriv = NULL!?!?!?\n"); return; } @@ -822,11 +811,8 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) /* Lecd must be up in this case */ bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); - if (bytes_left != 0) { - printk - ("lec: lec_vcc_attach, copy from user failed for %d bytes\n", - bytes_left); - } + if (bytes_left != 0) + pr_info("copy from user failed for %d bytes\n", bytes_left); if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || !dev_lec[ioc_data.dev_num]) return -EINVAL; @@ -1199,7 +1185,7 @@ static int __init lane_module_init(void) p = proc_create("lec", S_IRUGO, atm_proc_root, &lec_seq_fops); if (!p) { - printk(KERN_ERR "Unable to initialize /proc/net/atm/lec\n"); + pr_err("Unable to initialize /proc/net/atm/lec\n"); return -ENOMEM; } #endif @@ -1381,7 +1367,7 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr, #if 0 #define pr_debug(format,args...) /* -#define pr_debug printk + #define pr_debug printk */ #endif #define DEBUG_ARP_TABLE 0 @@ -1450,10 +1436,7 @@ lec_arp_add(struct lec_priv *priv, struct lec_arp_table *entry) tmp = &priv->lec_arp_tables[HASH(entry->mac_addr[ETH_ALEN - 1])]; hlist_add_head(&entry->next, tmp); - pr_debug("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", - 0xff & entry->mac_addr[0], 0xff & entry->mac_addr[1], - 0xff & entry->mac_addr[2], 0xff & entry->mac_addr[3], - 0xff & entry->mac_addr[4], 0xff & entry->mac_addr[5]); + pr_debug("Added entry:%pM\n", entry->mac_addr); } /* @@ -1492,10 +1475,7 @@ lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) } skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */ - pr_debug("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", - 0xff & to_remove->mac_addr[0], 0xff & to_remove->mac_addr[1], - 0xff & to_remove->mac_addr[2], 0xff & to_remove->mac_addr[3], - 0xff & to_remove->mac_addr[4], 0xff & to_remove->mac_addr[5]); + pr_debug("Removed entry:%pM\n", to_remove->mac_addr); return 0; } @@ -1714,9 +1694,7 @@ static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, struct hlist_head *head; struct lec_arp_table *entry; - pr_debug("LEC_ARP: lec_arp_find :%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", - mac_addr[0] & 0xff, mac_addr[1] & 0xff, mac_addr[2] & 0xff, - mac_addr[3] & 0xff, mac_addr[4] & 0xff, mac_addr[5] & 0xff); + pr_debug("%pM\n", mac_addr); head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])]; hlist_for_each_entry(entry, node, head, next) { @@ -1755,7 +1733,7 @@ static void lec_arp_expire_arp(unsigned long data) entry = (struct lec_arp_table *)data; - pr_debug("lec_arp_expire_arp\n"); + pr_debug("\n"); if (entry->status == ESI_ARP_PENDING) { if (entry->no_tries <= entry->priv->max_retry_count) { if (entry->is_rdesc) @@ -1779,10 +1757,10 @@ static void lec_arp_expire_vcc(unsigned long data) del_timer(&to_remove->timer); - pr_debug("LEC_ARP %p %p: lec_arp_expire_vcc vpi:%d vci:%d\n", - to_remove, priv, - to_remove->vcc ? to_remove->recv_vcc->vpi : 0, - to_remove->vcc ? to_remove->recv_vcc->vci : 0); + pr_debug("%p %p: vpi:%d vci:%d\n", + to_remove, priv, + to_remove->vcc ? to_remove->recv_vcc->vpi : 0, + to_remove->vcc ? to_remove->recv_vcc->vci : 0); spin_lock_irqsave(&priv->lec_arp_lock, flags); hlist_del(&to_remove->next); @@ -1819,7 +1797,7 @@ static void lec_arp_check_expire(struct work_struct *work) unsigned long time_to_check; int i; - pr_debug("lec_arp_check_expire %p\n", priv); + pr_debug("%p\n", priv); now = jiffies; restart: spin_lock_irqsave(&priv->lec_arp_lock, flags); @@ -1832,12 +1810,12 @@ restart: time_to_check = priv->aging_time; pr_debug("About to expire: %lx - %lx > %lx\n", - now, entry->last_used, time_to_check); + now, entry->last_used, time_to_check); if (time_after(now, entry->last_used + time_to_check) && !(entry->flags & LEC_PERMANENT_FLAG) && !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ /* Remove entry */ - pr_debug("LEC:Entry timed out\n"); + pr_debug("Entry timed out\n"); lec_arp_remove(priv, entry); lec_arp_put(entry); } else { @@ -1934,7 +1912,7 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, entry->packets_flooded < priv->maximum_unknown_frame_count) { entry->packets_flooded++; - pr_debug("LEC_ARP: Flooding..\n"); + pr_debug("Flooding..\n"); found = priv->mcast_vcc; goto out; } @@ -1945,13 +1923,13 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, */ lec_arp_hold(entry); *ret_entry = entry; - pr_debug("lec: entry->status %d entry->vcc %p\n", entry->status, - entry->vcc); + pr_debug("entry->status %d entry->vcc %p\n", entry->status, + entry->vcc); found = NULL; } else { /* No matching entry was found */ entry = make_entry(priv, mac_to_find); - pr_debug("LEC_ARP: Making entry\n"); + pr_debug("Making entry\n"); if (!entry) { found = priv->mcast_vcc; goto out; @@ -1988,7 +1966,7 @@ lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr, struct lec_arp_table *entry; int i; - pr_debug("lec_addr_delete\n"); + pr_debug("\n"); spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { @@ -2019,10 +1997,8 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, struct lec_arp_table *entry, *tmp; int i; - pr_debug("lec:%s", (targetless_le_arp) ? "targetless " : " "); - pr_debug("lec_arp_update mac:%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], - mac_addr[4], mac_addr[5]); + pr_debug("%smac:%pM\n", + (targetless_le_arp) ? "targetless " : "", mac_addr); spin_lock_irqsave(&priv->lec_arp_lock, flags); entry = lec_arp_find(priv, mac_addr); @@ -2149,19 +2125,17 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, * Vcc which we don't want to make default vcc, * attach it anyway. */ - pr_debug - ("LEC_ARP:Attaching data direct, not default: " - "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", - ioc_data->atm_addr[0], ioc_data->atm_addr[1], - ioc_data->atm_addr[2], ioc_data->atm_addr[3], - ioc_data->atm_addr[4], ioc_data->atm_addr[5], - ioc_data->atm_addr[6], ioc_data->atm_addr[7], - ioc_data->atm_addr[8], ioc_data->atm_addr[9], - ioc_data->atm_addr[10], ioc_data->atm_addr[11], - ioc_data->atm_addr[12], ioc_data->atm_addr[13], - ioc_data->atm_addr[14], ioc_data->atm_addr[15], - ioc_data->atm_addr[16], ioc_data->atm_addr[17], - ioc_data->atm_addr[18], ioc_data->atm_addr[19]); + pr_debug("LEC_ARP:Attaching data direct, not default: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", + ioc_data->atm_addr[0], ioc_data->atm_addr[1], + ioc_data->atm_addr[2], ioc_data->atm_addr[3], + ioc_data->atm_addr[4], ioc_data->atm_addr[5], + ioc_data->atm_addr[6], ioc_data->atm_addr[7], + ioc_data->atm_addr[8], ioc_data->atm_addr[9], + ioc_data->atm_addr[10], ioc_data->atm_addr[11], + ioc_data->atm_addr[12], ioc_data->atm_addr[13], + ioc_data->atm_addr[14], ioc_data->atm_addr[15], + ioc_data->atm_addr[16], ioc_data->atm_addr[17], + ioc_data->atm_addr[18], ioc_data->atm_addr[19]); entry = make_entry(priv, bus_mac); if (entry == NULL) goto out; @@ -2177,19 +2151,17 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, dump_arp_table(priv); goto out; } - pr_debug - ("LEC_ARP:Attaching data direct, default: " - "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", - ioc_data->atm_addr[0], ioc_data->atm_addr[1], - ioc_data->atm_addr[2], ioc_data->atm_addr[3], - ioc_data->atm_addr[4], ioc_data->atm_addr[5], - ioc_data->atm_addr[6], ioc_data->atm_addr[7], - ioc_data->atm_addr[8], ioc_data->atm_addr[9], - ioc_data->atm_addr[10], ioc_data->atm_addr[11], - ioc_data->atm_addr[12], ioc_data->atm_addr[13], - ioc_data->atm_addr[14], ioc_data->atm_addr[15], - ioc_data->atm_addr[16], ioc_data->atm_addr[17], - ioc_data->atm_addr[18], ioc_data->atm_addr[19]); + pr_debug("LEC_ARP:Attaching data direct, default: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n", + ioc_data->atm_addr[0], ioc_data->atm_addr[1], + ioc_data->atm_addr[2], ioc_data->atm_addr[3], + ioc_data->atm_addr[4], ioc_data->atm_addr[5], + ioc_data->atm_addr[6], ioc_data->atm_addr[7], + ioc_data->atm_addr[8], ioc_data->atm_addr[9], + ioc_data->atm_addr[10], ioc_data->atm_addr[11], + ioc_data->atm_addr[12], ioc_data->atm_addr[13], + ioc_data->atm_addr[14], ioc_data->atm_addr[15], + ioc_data->atm_addr[16], ioc_data->atm_addr[17], + ioc_data->atm_addr[18], ioc_data->atm_addr[19]); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { if (memcmp @@ -2197,9 +2169,9 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, ATM_ESA_LEN) == 0) { pr_debug("LEC_ARP: Attaching data direct\n"); pr_debug("Currently -> Vcc: %d, Rvcc:%d\n", - entry->vcc ? entry->vcc->vci : 0, - entry->recv_vcc ? entry->recv_vcc-> - vci : 0); + entry->vcc ? entry->vcc->vci : 0, + entry->recv_vcc ? entry->recv_vcc-> + vci : 0); found_entry = 1; del_timer(&entry->timer); entry->vcc = vcc; @@ -2271,7 +2243,7 @@ static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) struct lec_arp_table *entry; int i; - pr_debug("LEC:lec_flush_complete %lx\n", tran_id); + pr_debug("%lx\n", tran_id); restart: spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { @@ -2312,7 +2284,7 @@ lec_set_flush_tran_id(struct lec_priv *priv, if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { entry->flush_tran_id = tran_id; pr_debug("Set flush transaction id to %lx for %p\n", - tran_id, entry); + tran_id, entry); } } spin_unlock_irqrestore(&priv->lec_arp_lock, flags); diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 38a6cb0863f0..3c45aef47b7e 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -1447,7 +1449,7 @@ static __init int atm_mpoa_init(void) register_atm_ioctl(&atm_ioctl_ops); if (mpc_proc_init() != 0) - printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); + pr_info("failed to initialize /proc/mpoa\n"); printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 1a0f5ccea9c4..0603ab478cf5 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -1,3 +1,4 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #ifdef CONFIG_PROC_FS #include @@ -278,7 +279,7 @@ int mpc_proc_init(void) p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_file_operations); if (!p) { - printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME); + pr_err("Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME); return -ENOMEM; } return 0; diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index 0af84cd4f65b..62db6d71dbab 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -33,6 +33,8 @@ * These hooks are not yet available in ppp_generic */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -132,7 +134,7 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc) static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb) { struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc); - pr_debug("pppoatm push\n"); + pr_debug("\n"); if (skb == NULL) { /* VCC was closed */ pr_debug("removing ATMPPP VCC %p\n", pvcc); pppoatm_unassign_vcc(atmvcc); @@ -165,10 +167,9 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb) pvcc->chan.mtu += LLC_LEN; break; } - pr_debug("Couldn't autodetect yet " - "(skb: %02X %02X %02X %02X %02X %02X)\n", - skb->data[0], skb->data[1], skb->data[2], - skb->data[3], skb->data[4], skb->data[5]); + pr_debug("Couldn't autodetect yet (skb: %02X %02X %02X %02X %02X %02X)\n", + skb->data[0], skb->data[1], skb->data[2], + skb->data[3], skb->data[4], skb->data[5]); goto error; case e_vc: break; @@ -194,7 +195,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) { struct pppoatm_vcc *pvcc = chan_to_pvcc(chan); ATM_SKB(skb)->vcc = pvcc->atmvcc; - pr_debug("pppoatm_send (skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); + pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc); if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT)) (void) skb_pull(skb, 1); switch (pvcc->encaps) { /* LLC encapsulation needed */ @@ -226,8 +227,8 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc); ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; - pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, ATM_SKB(skb)->vcc, - ATM_SKB(skb)->vcc->dev); + pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", + skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) ? DROP_PACKET : 1; nospace: diff --git a/net/atm/raw.c b/net/atm/raw.c index cbfcc71a17b1..fb8a9497653c 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -2,6 +2,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include #include @@ -32,8 +33,8 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) { struct sock *sk = sk_atm(vcc); - pr_debug("APopR (%d) %d -= %d\n", vcc->vci, - sk_wmem_alloc_get(sk), skb->truesize); + pr_debug("(%d) %d -= %d\n", + vcc->vci, sk_wmem_alloc_get(sk), skb->truesize); atomic_sub(skb->truesize, &sk->sk_wmem_alloc); dev_kfree_skb_any(skb); sk->sk_write_space(sk); diff --git a/net/atm/resources.c b/net/atm/resources.c index 56b7322ff461..0d4c0ee090db 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -7,6 +7,7 @@ * 2002/01 - don't free the whole struct sock on sk->destruct time, * use the default destruct function initialized by sock_init_data */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include #include @@ -79,8 +80,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, dev = __alloc_atm_dev(type); if (!dev) { - printk(KERN_ERR "atm_dev_register: no space for dev %s\n", - type); + pr_err("no space for dev %s\n", type); return NULL; } mutex_lock(&atm_dev_mutex); @@ -109,16 +109,12 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, atomic_set(&dev->refcnt, 1); if (atm_proc_dev_register(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_proc_dev_register failed for dev %s\n", - type); + pr_err("atm_proc_dev_register failed for dev %s\n", type); goto out_fail; } if (atm_register_sysfs(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_register_sysfs failed for dev %s\n", - type); + pr_err("atm_register_sysfs failed for dev %s\n", type); atm_proc_dev_deregister(dev); goto out_fail; } diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 229921400522..28df4edf9ca4 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -2,6 +2,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include /* error codes */ #include /* printk */ @@ -37,14 +38,14 @@ static void sigd_put_skb(struct sk_buff *skb) add_wait_queue(&sigd_sleep,&wait); while (!sigd) { set_current_state(TASK_UNINTERRUPTIBLE); - pr_debug("atmsvc: waiting for signaling demon...\n"); + pr_debug("atmsvc: waiting for signaling daemon...\n"); schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&sigd_sleep,&wait); #else if (!sigd) { - pr_debug("atmsvc: no signaling demon\n"); + pr_debug("atmsvc: no signaling daemon\n"); kfree_skb(skb); return; } @@ -90,8 +91,7 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) msg = (struct atmsvc_msg *) skb->data; atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); vcc = *(struct atm_vcc **) &msg->vcc; - pr_debug("sigd_send %d (0x%lx)\n",(int) msg->type, - (unsigned long) vcc); + pr_debug("%d (0x%lx)\n", (int)msg->type, (unsigned long)vcc); sk = sk_atm(vcc); switch (msg->type) { @@ -150,8 +150,7 @@ as_indicate_complete: clear_bit(ATM_VF_WAITING, &vcc->flags); break; default: - printk(KERN_ALERT "sigd_send: bad message type %d\n", - (int) msg->type); + pr_alert("bad message type %d\n", (int)msg->type); return -EINVAL; } sk->sk_state_change(sk); @@ -169,7 +168,7 @@ void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type, struct atmsvc_msg *msg; static unsigned session = 0; - pr_debug("sigd_enq %d (0x%p)\n",(int) type,vcc); + pr_debug("%d (0x%p)\n", (int)type, vcc); while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL))) schedule(); msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)); @@ -219,10 +218,10 @@ static void sigd_close(struct atm_vcc *vcc) struct sock *s; int i; - pr_debug("sigd_close\n"); + pr_debug("\n"); sigd = NULL; if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) - printk(KERN_ERR "sigd_close: closing with requests pending\n"); + pr_err("closing with requests pending\n"); skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); read_lock(&vcc_sklist_lock); @@ -256,7 +255,7 @@ static struct atm_dev sigd_dev = { int sigd_attach(struct atm_vcc *vcc) { if (sigd) return -EADDRINUSE; - pr_debug("sigd_attach\n"); + pr_debug("\n"); sigd = vcc; vcc->dev = &sigd_dev; vcc_insert_socket(sk_atm(vcc)); diff --git a/net/atm/svc.c b/net/atm/svc.c index 66e1d9b3e5de..251ddbc42e4b 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -2,6 +2,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ #include #include /* struct socket, struct proto_ops */ @@ -46,7 +47,7 @@ static void svc_disconnect(struct atm_vcc *vcc) struct sk_buff *skb; struct sock *sk = sk_atm(vcc); - pr_debug("svc_disconnect %p\n",vcc); + pr_debug("%p\n",vcc); if (test_bit(ATM_VF_REGIS,&vcc->flags)) { prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); sigd_enq(vcc,as_close,NULL,NULL,NULL); @@ -76,7 +77,7 @@ static int svc_release(struct socket *sock) if (sk) { vcc = ATM_SD(sock); - pr_debug("svc_release %p\n", vcc); + pr_debug("%p\n", vcc); clear_bit(ATM_VF_READY, &vcc->flags); /* VCC pointer is used as a reference, so we must not free it (thereby subjecting it to re-use) before all pending connections @@ -153,7 +154,7 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, struct atm_vcc *vcc = ATM_SD(sock); int error; - pr_debug("svc_connect %p\n",vcc); + pr_debug("%p\n",vcc); lock_sock(sk); if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { error = -EINVAL; @@ -286,7 +287,7 @@ static int svc_listen(struct socket *sock,int backlog) struct atm_vcc *vcc = ATM_SD(sock); int error; - pr_debug("svc_listen %p\n",vcc); + pr_debug("%p\n", vcc); lock_sock(sk); /* let server handle listen on unbound sockets */ if (test_bit(ATM_VF_SESSION,&vcc->flags)) { @@ -336,7 +337,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) new_vcc = ATM_SD(newsock); - pr_debug("svc_accept %p -> %p\n",old_vcc,new_vcc); + pr_debug("%p -> %p\n", old_vcc, new_vcc); while (1) { DEFINE_WAIT(wait); @@ -540,7 +541,7 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, error = -EINPROGRESS; goto out; } - pr_debug("svc_addparty added wait queue\n"); + pr_debug("added wait queue\n"); while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); -- cgit v1.2.3 From c39f01d7883f944ae75961cc1a31d348c7970599 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:01 +0000 Subject: net/atm/addr.c: Convert include Signed-off-by: David S. Miller --- net/atm/addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/atm/addr.c b/net/atm/addr.c index 82e85abc303d..cf3ae8b47572 100644 --- a/net/atm/addr.c +++ b/net/atm/addr.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include "signaling.h" #include "addr.h" -- cgit v1.2.3 From 3356b4d41605f9b0977b0963c65f466eee213fe9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:02 +0000 Subject: net/atm/atm_misc.c: checkpatch cleanups Moved EXPORT_SYMBOL to follow definition Add space after commas Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/atm_misc.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c index 02cc7e71efea..fc63526d8695 100644 --- a/net/atm/atm_misc.c +++ b/net/atm/atm_misc.c @@ -2,37 +2,35 @@ /* Written 1995-2000 by Werner Almesberger, EPFL ICA */ - #include #include #include #include #include #include +#include #include -#include - -int atm_charge(struct atm_vcc *vcc,int truesize) +int atm_charge(struct atm_vcc *vcc, int truesize) { - atm_force_charge(vcc,truesize); + atm_force_charge(vcc, truesize); if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf) return 1; - atm_return(vcc,truesize); + atm_return(vcc, truesize); atomic_inc(&vcc->stats->rx_drop); return 0; } +EXPORT_SYMBOL(atm_charge); - -struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, - gfp_t gfp_flags) +struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc, int pdu_size, + gfp_t gfp_flags) { struct sock *sk = sk_atm(vcc); int guess = atm_guess_pdu2truesize(pdu_size); - atm_force_charge(vcc,guess); + atm_force_charge(vcc, guess); if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { - struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags); + struct sk_buff *skb = alloc_skb(pdu_size, gfp_flags); if (skb) { atomic_add(skb->truesize-guess, @@ -40,10 +38,11 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, return skb; } } - atm_return(vcc,guess); + atm_return(vcc, guess); atomic_inc(&vcc->stats->rx_drop); return NULL; } +EXPORT_SYMBOL(atm_alloc_charge); /* @@ -73,7 +72,6 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size, * else * */ - int atm_pcr_goal(const struct atm_trafprm *tp) { if (tp->pcr && tp->pcr != ATM_MAX_PCR) @@ -84,26 +82,20 @@ int atm_pcr_goal(const struct atm_trafprm *tp) return -tp->max_pcr; return 0; } +EXPORT_SYMBOL(atm_pcr_goal); - -void sonet_copy_stats(struct k_sonet_stats *from,struct sonet_stats *to) +void sonet_copy_stats(struct k_sonet_stats *from, struct sonet_stats *to) { #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) __SONET_ITEMS #undef __HANDLE_ITEM } +EXPORT_SYMBOL(sonet_copy_stats); - -void sonet_subtract_stats(struct k_sonet_stats *from,struct sonet_stats *to) +void sonet_subtract_stats(struct k_sonet_stats *from, struct sonet_stats *to) { -#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i) +#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i) __SONET_ITEMS #undef __HANDLE_ITEM } - - -EXPORT_SYMBOL(atm_charge); -EXPORT_SYMBOL(atm_alloc_charge); -EXPORT_SYMBOL(atm_pcr_goal); -EXPORT_SYMBOL(sonet_copy_stats); EXPORT_SYMBOL(sonet_subtract_stats); -- cgit v1.2.3 From f0a6cb118d7f9e72799a9c0c13f75d1b236a6546 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:03 +0000 Subject: net/atm/atm_sysfs.c: checkpatch cleanups Add space after for Indent switch/case statements 80 column wrapping Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/atm_sysfs.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c index b5674dc2083d..f693b78eb467 100644 --- a/net/atm/atm_sysfs.c +++ b/net/atm/atm_sysfs.c @@ -42,13 +42,14 @@ static ssize_t show_atmaddress(struct device *cdev, spin_lock_irqsave(&adev->lock, flags); list_for_each_entry(aaddr, &adev->local, entry) { - for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { + for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { if (j == *fmt) { pos += sprintf(pos, "."); ++fmt; j = 0; } - pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]); + pos += sprintf(pos, "%02x", + aaddr->addr.sas_addr.prv[i]); } pos += sprintf(pos, "\n"); } @@ -78,17 +79,17 @@ static ssize_t show_link_rate(struct device *cdev, /* show the link rate, not the data rate */ switch (adev->link_rate) { - case ATM_OC3_PCR: - link_rate = 155520000; - break; - case ATM_OC12_PCR: - link_rate = 622080000; - break; - case ATM_25_PCR: - link_rate = 25600000; - break; - default: - link_rate = adev->link_rate * 8 * 53; + case ATM_OC3_PCR: + link_rate = 155520000; + break; + case ATM_OC12_PCR: + link_rate = 622080000; + break; + case ATM_25_PCR: + link_rate = 25600000; + break; + default: + link_rate = adev->link_rate * 8 * 53; } pos += sprintf(pos, "%d\n", link_rate); -- cgit v1.2.3 From 641d729eb6236db0ce33e2b07a7f93193e60ea5a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:04 +0000 Subject: net/atm/br2684.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/br2684.c | 72 ++++++++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/net/atm/br2684.c b/net/atm/br2684.c index d72b1a579911..4d64d87e7578 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,20 +28,14 @@ #include "common.h" -#ifdef SKB_DEBUG static void skb_debug(const struct sk_buff *skb) { +#ifdef SKB_DEBUG #define NUM2PRINT 50 - char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ - int i = 0; - for (i = 0; i < skb->len && i < NUM2PRINT; i++) { - sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); - } - printk(KERN_DEBUG "br2684: skb: %s\n", buf); -} -#else -#define skb_debug(skb) do {} while (0) + print_hex_dump(KERN_DEBUG, "br2684: skb: ", DUMP_OFFSET, + 16, 1, skb->data, min(NUM2PRINT, skb->len), true); #endif +} #define BR2684_ETHERTYPE_LEN 2 #define BR2684_PAD_LEN 2 @@ -70,7 +64,7 @@ struct br2684_vcc { struct atm_vcc *atmvcc; struct net_device *device; /* keep old push, pop functions for chaining */ - void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb); + void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb); void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); enum br2684_encaps encaps; struct list_head brvccs; @@ -302,7 +296,8 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg) struct br2684_dev *brdev; read_lock(&devs_lock); brdev = BRPRIV(br2684_find_dev(&fs.ifspec)); - if (brdev == NULL || list_empty(&brdev->brvccs) || brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ + if (brdev == NULL || list_empty(&brdev->brvccs) || + brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ brvcc = NULL; else brvcc = list_entry_brvcc(brdev->brvccs.next); @@ -378,29 +373,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) __skb_trim(skb, skb->len - 4); /* accept packets that have "ipv[46]" in the snap header */ - if ((skb->len >= (sizeof(llc_oui_ipv4))) - && - (memcmp - (skb->data, llc_oui_ipv4, - sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { - if (memcmp - (skb->data + 6, ethertype_ipv6, - sizeof(ethertype_ipv6)) == 0) + if ((skb->len >= (sizeof(llc_oui_ipv4))) && + (memcmp(skb->data, llc_oui_ipv4, + sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { + if (memcmp(skb->data + 6, ethertype_ipv6, + sizeof(ethertype_ipv6)) == 0) skb->protocol = htons(ETH_P_IPV6); - else if (memcmp - (skb->data + 6, ethertype_ipv4, - sizeof(ethertype_ipv4)) == 0) + else if (memcmp(skb->data + 6, ethertype_ipv4, + sizeof(ethertype_ipv4)) == 0) skb->protocol = htons(ETH_P_IP); else goto error; skb_pull(skb, sizeof(llc_oui_ipv4)); skb_reset_network_header(skb); skb->pkt_type = PACKET_HOST; - /* - * Let us waste some time for checking the encapsulation. - * Note, that only 7 char is checked so frames with a valid FCS - * are also accepted (but FCS is not checked of course). - */ + /* + * Let us waste some time for checking the encapsulation. + * Note, that only 7 char is checked so frames with a valid FCS + * are also accepted (but FCS is not checked of course). + */ } else if ((skb->len >= sizeof(llc_oui_pid_pad)) && (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { skb_pull(skb, sizeof(llc_oui_pid_pad)); @@ -495,12 +486,12 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) err = -EEXIST; goto error; } - if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || - be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != - BR2684_ENCAPS_VC - && be.encaps != - BR2684_ENCAPS_LLC) - || be.min_size != 0) { + if (be.fcs_in != BR2684_FCSIN_NO || + be.fcs_out != BR2684_FCSOUT_NO || + be.fcs_auto || be.has_vpiid || be.send_padding || + (be.encaps != BR2684_ENCAPS_VC && + be.encaps != BR2684_ENCAPS_LLC) || + be.min_size != 0) { err = -EINVAL; goto error; } @@ -541,7 +532,8 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) } __module_get(THIS_MODULE); return 0; - error: + +error: write_unlock_irq(&devs_lock); kfree(brvcc); return err; @@ -587,7 +579,7 @@ static void br2684_setup_routed(struct net_device *netdev) INIT_LIST_HEAD(&brdev->brvccs); } -static int br2684_create(void __user * arg) +static int br2684_create(void __user *arg) { int err; struct net_device *netdev; @@ -597,9 +589,8 @@ static int br2684_create(void __user * arg) pr_debug("\n"); - if (copy_from_user(&ni, arg, sizeof ni)) { + if (copy_from_user(&ni, arg, sizeof ni)) return -EFAULT; - } if (ni.media & BR2684_FLAG_ROUTED) payload = p_routed; @@ -607,9 +598,8 @@ static int br2684_create(void __user * arg) payload = p_bridged; ni.media &= 0xffff; /* strip flags */ - if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { + if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) return -EINVAL; - } netdev = alloc_netdev(sizeof(struct br2684_dev), ni.ifname[0] ? ni.ifname : "nas%d", -- cgit v1.2.3 From e956ea1b7de1df5ae4d6dc3e7460ed9e140803cd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:05 +0000 Subject: net/atm/clip.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/clip.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/net/atm/clip.c b/net/atm/clip.c index d7939fd58cd3..ebfa022008f7 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -32,10 +32,10 @@ #include #include /* for struct rtable and routing */ #include /* icmp_send */ -#include /* for HZ */ +#include /* for HZ */ +#include #include /* for htons etc. */ #include /* save/restore_flags */ -#include #include #include "common.h" @@ -56,10 +56,10 @@ static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip) pr_debug("(%d)\n", type); if (!atmarpd) return -EUNATCH; - skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC); + skb = alloc_skb(sizeof(struct atmarp_ctrl), GFP_ATOMIC); if (!skb) return -ENOMEM; - ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl)); + ctrl = (struct atmarp_ctrl *)skb_put(skb, sizeof(struct atmarp_ctrl)); ctrl->type = type; ctrl->itf_num = itf; ctrl->ip = ip; @@ -111,7 +111,7 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) goto out; } pr_crit("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc); - out: +out: netif_tx_unlock_bh(entry->neigh->dev); } @@ -205,12 +205,12 @@ static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb) } ATM_SKB(skb)->vcc = vcc; skb_reset_mac_header(skb); - if (!clip_vcc->encap - || skb->len < RFC1483LLC_LEN - || memcmp(skb->data, llc_oui, sizeof (llc_oui))) + if (!clip_vcc->encap || + skb->len < RFC1483LLC_LEN || + memcmp(skb->data, llc_oui, sizeof(llc_oui))) skb->protocol = htons(ETH_P_IP); else { - skb->protocol = ((__be16 *) skb->data)[3]; + skb->protocol = ((__be16 *)skb->data)[3]; skb_pull(skb, RFC1483LLC_LEN); if (skb->protocol == htons(ETH_P_ARP)) { skb->dev->stats.rx_packets++; @@ -644,7 +644,6 @@ static int clip_inet_event(struct notifier_block *this, unsigned long event, return clip_device_event(this, NETDEV_CHANGE, in_dev->dev); } - static struct notifier_block clip_dev_notifier = { .notifier_call = clip_device_event, }; @@ -670,7 +669,6 @@ static void atmarpd_close(struct atm_vcc *vcc) module_put(THIS_MODULE); } - static struct atmdev_ops atmarpd_dev_ops = { .close = atmarpd_close }; @@ -692,11 +690,11 @@ static int atm_init_atmarp(struct atm_vcc *vcc) return -EADDRINUSE; } - mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ); + mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ); atmarpd = vcc; - set_bit(ATM_VF_META,&vcc->flags); - set_bit(ATM_VF_READY,&vcc->flags); + set_bit(ATM_VF_META, &vcc->flags); + set_bit(ATM_VF_READY, &vcc->flags); /* allow replies and avoid getting closed if signaling dies */ vcc->dev = &atmarpd_dev; vcc_insert_socket(sk_atm(vcc)); -- cgit v1.2.3 From a8147d737bd37bd51bb01737ac9c17a2cfc02a38 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:06 +0000 Subject: net/atm/common.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/common.c | 338 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 173 insertions(+), 165 deletions(-) diff --git a/net/atm/common.c b/net/atm/common.c index 17f7e5f2131b..74d095a081e3 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -19,11 +19,10 @@ #include #include #include /* struct sock */ +#include +#include -#include #include -#include - #include "resources.h" /* atm_find_dev */ #include "common.h" /* prototypes */ @@ -32,13 +31,15 @@ #include "signaling.h" /* for WAITING and sigd_attach */ struct hlist_head vcc_hash[VCC_HTABLE_SIZE]; +EXPORT_SYMBOL(vcc_hash); + DEFINE_RWLOCK(vcc_sklist_lock); +EXPORT_SYMBOL(vcc_sklist_lock); static void __vcc_insert_socket(struct sock *sk) { struct atm_vcc *vcc = atm_sk(sk); - struct hlist_head *head = &vcc_hash[vcc->vci & - (VCC_HTABLE_SIZE - 1)]; + struct hlist_head *head = &vcc_hash[vcc->vci & (VCC_HTABLE_SIZE - 1)]; sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1); sk_add_node(sk, head); } @@ -49,6 +50,7 @@ void vcc_insert_socket(struct sock *sk) __vcc_insert_socket(sk); write_unlock_irq(&vcc_sklist_lock); } +EXPORT_SYMBOL(vcc_insert_socket); static void vcc_remove_socket(struct sock *sk) { @@ -57,8 +59,7 @@ static void vcc_remove_socket(struct sock *sk) write_unlock_irq(&vcc_sklist_lock); } - -static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) +static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size) { struct sk_buff *skb; struct sock *sk = sk_atm(vcc); @@ -70,23 +71,20 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) } while (!(skb = alloc_skb(size, GFP_KERNEL))) schedule(); - pr_debug("AlTx %d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); + pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); atomic_add(skb->truesize, &sk->sk_wmem_alloc); return skb; } - -EXPORT_SYMBOL(vcc_hash); -EXPORT_SYMBOL(vcc_sklist_lock); -EXPORT_SYMBOL(vcc_insert_socket); - static void vcc_sock_destruct(struct sock *sk) { if (atomic_read(&sk->sk_rmem_alloc)) - printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_rmem_alloc)); + printk(KERN_DEBUG "%s: rmem leakage (%d bytes) detected.\n", + __func__, atomic_read(&sk->sk_rmem_alloc)); if (atomic_read(&sk->sk_wmem_alloc)) - printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_wmem_alloc)); + printk(KERN_DEBUG "%s: wmem leakage (%d bytes) detected.\n", + __func__, atomic_read(&sk->sk_wmem_alloc)); } static void vcc_def_wakeup(struct sock *sk) @@ -142,8 +140,8 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family) vcc = atm_sk(sk); vcc->dev = NULL; - memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); - memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); + memset(&vcc->local, 0, sizeof(struct sockaddr_atmsvc)); + memset(&vcc->remote, 0, sizeof(struct sockaddr_atmsvc)); vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ atomic_set(&sk->sk_wmem_alloc, 1); atomic_set(&sk->sk_rmem_alloc, 0); @@ -156,7 +154,6 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family) return 0; } - static void vcc_destroy_socket(struct sock *sk) { struct atm_vcc *vcc = atm_sk(sk); @@ -171,7 +168,7 @@ static void vcc_destroy_socket(struct sock *sk) vcc->push(vcc, NULL); /* atmarpd has no push */ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { - atm_return(vcc,skb->truesize); + atm_return(vcc, skb->truesize); kfree_skb(skb); } @@ -182,7 +179,6 @@ static void vcc_destroy_socket(struct sock *sk) vcc_remove_socket(sk); } - int vcc_release(struct socket *sock) { struct sock *sk = sock->sk; @@ -197,7 +193,6 @@ int vcc_release(struct socket *sock) return 0; } - void vcc_release_async(struct atm_vcc *vcc, int reply) { struct sock *sk = sk_atm(vcc); @@ -208,8 +203,6 @@ void vcc_release_async(struct atm_vcc *vcc, int reply) clear_bit(ATM_VF_WAITING, &vcc->flags); sk->sk_state_change(sk); } - - EXPORT_SYMBOL(vcc_release_async); @@ -235,36 +228,37 @@ void atm_dev_release_vccs(struct atm_dev *dev) write_unlock_irq(&vcc_sklist_lock); } - -static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) +static int adjust_tp(struct atm_trafprm *tp, unsigned char aal) { int max_sdu; - if (!tp->traffic_class) return 0; + if (!tp->traffic_class) + return 0; switch (aal) { - case ATM_AAL0: - max_sdu = ATM_CELL_SIZE-1; - break; - case ATM_AAL34: - max_sdu = ATM_MAX_AAL34_PDU; - break; - default: - pr_warning("AAL problems ... (%d)\n", aal); - /* fall through */ - case ATM_AAL5: - max_sdu = ATM_MAX_AAL5_PDU; + case ATM_AAL0: + max_sdu = ATM_CELL_SIZE-1; + break; + case ATM_AAL34: + max_sdu = ATM_MAX_AAL34_PDU; + break; + default: + pr_warning("AAL problems ... (%d)\n", aal); + /* fall through */ + case ATM_AAL5: + max_sdu = ATM_MAX_AAL5_PDU; } - if (!tp->max_sdu) tp->max_sdu = max_sdu; - else if (tp->max_sdu > max_sdu) return -EINVAL; - if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV; + if (!tp->max_sdu) + tp->max_sdu = max_sdu; + else if (tp->max_sdu > max_sdu) + return -EINVAL; + if (!tp->max_cdv) + tp->max_cdv = ATM_MAX_CDV; return 0; } - static int check_ci(const struct atm_vcc *vcc, short vpi, int vci) { - struct hlist_head *head = &vcc_hash[vci & - (VCC_HTABLE_SIZE - 1)]; + struct hlist_head *head = &vcc_hash[vci & (VCC_HTABLE_SIZE - 1)]; struct hlist_node *node; struct sock *s; struct atm_vcc *walk; @@ -288,7 +282,6 @@ static int check_ci(const struct atm_vcc *vcc, short vpi, int vci) return 0; } - static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci) { static short p; /* poor man's per-device cache */ @@ -326,14 +319,13 @@ static int find_ci(const struct atm_vcc *vcc, short *vpi, int *vci) if ((c == ATM_NOT_RSV_VCI || *vci != ATM_VCI_ANY) && *vpi == ATM_VPI_ANY) { p++; - if (p >= 1 << vcc->dev->ci_range.vpi_bits) p = 0; + if (p >= 1 << vcc->dev->ci_range.vpi_bits) + p = 0; } - } - while (old_p != p || old_c != c); + } while (old_p != p || old_c != c); return -EADDRINUSE; } - static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, int vci) { @@ -361,27 +353,29 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, __vcc_insert_socket(sk); write_unlock_irq(&vcc_sklist_lock); switch (vcc->qos.aal) { - case ATM_AAL0: - error = atm_init_aal0(vcc); - vcc->stats = &dev->stats.aal0; - break; - case ATM_AAL34: - error = atm_init_aal34(vcc); - vcc->stats = &dev->stats.aal34; - break; - case ATM_NO_AAL: - /* ATM_AAL5 is also used in the "0 for default" case */ - vcc->qos.aal = ATM_AAL5; - /* fall through */ - case ATM_AAL5: - error = atm_init_aal5(vcc); - vcc->stats = &dev->stats.aal5; - break; - default: - error = -EPROTOTYPE; + case ATM_AAL0: + error = atm_init_aal0(vcc); + vcc->stats = &dev->stats.aal0; + break; + case ATM_AAL34: + error = atm_init_aal34(vcc); + vcc->stats = &dev->stats.aal34; + break; + case ATM_NO_AAL: + /* ATM_AAL5 is also used in the "0 for default" case */ + vcc->qos.aal = ATM_AAL5; + /* fall through */ + case ATM_AAL5: + error = atm_init_aal5(vcc); + vcc->stats = &dev->stats.aal5; + break; + default: + error = -EPROTOTYPE; } - if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); - if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); + if (!error) + error = adjust_tp(&vcc->qos.txtp, vcc->qos.aal); + if (!error) + error = adjust_tp(&vcc->qos.rxtp, vcc->qos.aal); if (error) goto fail; pr_debug("VCC %d.%d, AAL %d\n", vpi, vci, vcc->qos.aal); @@ -397,7 +391,8 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, vcc->qos.rxtp.max_sdu); if (dev->ops->open) { - if ((error = dev->ops->open(vcc))) + error = dev->ops->open(vcc); + if (error) goto fail; } return 0; @@ -411,7 +406,6 @@ fail_module_put: return error; } - int vcc_connect(struct socket *sock, int itf, short vpi, int vci) { struct atm_dev *dev; @@ -427,16 +421,16 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) return -EINVAL; if (vpi != ATM_VPI_UNSPEC && vci != ATM_VCI_UNSPEC) - clear_bit(ATM_VF_PARTIAL,&vcc->flags); + clear_bit(ATM_VF_PARTIAL, &vcc->flags); else - if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) + if (test_bit(ATM_VF_PARTIAL, &vcc->flags)) return -EINVAL; pr_debug("(TX: cl %d,bw %d-%d,sdu %d; " "RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)\n", vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_sdu, vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr, - vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu, + vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_sdu, vcc->qos.aal == ATM_AAL5 ? "" : vcc->qos.aal == ATM_AAL0 ? "" : " ??? code ", vcc->qos.aal == ATM_AAL0 ? 0 : vcc->qos.aal); @@ -446,12 +440,14 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; if (likely(itf != ATM_ITF_ANY)) { - dev = try_then_request_module(atm_dev_lookup(itf), "atm-device-%d", itf); + dev = try_then_request_module(atm_dev_lookup(itf), + "atm-device-%d", itf); } else { dev = NULL; mutex_lock(&atm_dev_mutex); if (!list_empty(&atm_devs)) { - dev = list_entry(atm_devs.next, struct atm_dev, dev_list); + dev = list_entry(atm_devs.next, + struct atm_dev, dev_list); atm_dev_hold(dev); } mutex_unlock(&atm_dev_mutex); @@ -464,13 +460,12 @@ int vcc_connect(struct socket *sock, int itf, short vpi, int vci) return error; } if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) - set_bit(ATM_VF_PARTIAL,&vcc->flags); - if (test_bit(ATM_VF_READY,&ATM_SD(sock)->flags)) + set_bit(ATM_VF_PARTIAL, &vcc->flags); + if (test_bit(ATM_VF_READY, &ATM_SD(sock)->flags)) sock->state = SS_CONNECTED; return 0; } - int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { @@ -484,8 +479,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, if (flags & ~MSG_DONTWAIT) /* only handle MSG_DONTWAIT */ return -EOPNOTSUPP; vcc = ATM_SD(sock); - if (test_bit(ATM_VF_RELEASED,&vcc->flags) || - test_bit(ATM_VF_CLOSE,&vcc->flags) || + if (test_bit(ATM_VF_RELEASED, &vcc->flags) || + test_bit(ATM_VF_CLOSE, &vcc->flags) || !test_bit(ATM_VF_READY, &vcc->flags)) return 0; @@ -509,7 +504,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, return copied; } - int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { @@ -517,7 +511,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, DEFINE_WAIT(wait); struct atm_vcc *vcc; struct sk_buff *skb; - int eff,error; + int eff, error; const void __user *buff; int size; @@ -556,7 +550,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, eff = (size+3) & ~3; /* align to word boundary */ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); error = 0; - while (!(skb = alloc_tx(vcc,eff))) { + while (!(skb = alloc_tx(vcc, eff))) { if (m->msg_flags & MSG_DONTWAIT) { error = -EAGAIN; break; @@ -566,9 +560,9 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, error = -ERESTARTSYS; break; } - if (test_bit(ATM_VF_RELEASED,&vcc->flags) || - test_bit(ATM_VF_CLOSE,&vcc->flags) || - !test_bit(ATM_VF_READY,&vcc->flags)) { + if (test_bit(ATM_VF_RELEASED, &vcc->flags) || + test_bit(ATM_VF_CLOSE, &vcc->flags) || + !test_bit(ATM_VF_READY, &vcc->flags)) { error = -EPIPE; send_sig(SIGPIPE, current, 0); break; @@ -580,20 +574,20 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, goto out; skb->dev = NULL; /* for paths shared with net_device interfaces */ ATM_SKB(skb)->atm_options = vcc->atm_options; - if (copy_from_user(skb_put(skb,size),buff,size)) { + if (copy_from_user(skb_put(skb, size), buff, size)) { kfree_skb(skb); error = -EFAULT; goto out; } - if (eff != size) memset(skb->data+size,0,eff-size); - error = vcc->dev->ops->send(vcc,skb); + if (eff != size) + memset(skb->data + size, 0, eff-size); + error = vcc->dev->ops->send(vcc, skb); error = error ? error : size; out: release_sock(sk); return error; } - unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; @@ -629,8 +623,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) return mask; } - -static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) +static int atm_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) { int error; @@ -642,25 +635,31 @@ static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) qos->rxtp.traffic_class != vcc->qos.rxtp.traffic_class || qos->txtp.traffic_class != vcc->qos.txtp.traffic_class) return -EINVAL; - error = adjust_tp(&qos->txtp,qos->aal); - if (!error) error = adjust_tp(&qos->rxtp,qos->aal); - if (error) return error; - if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP; + error = adjust_tp(&qos->txtp, qos->aal); + if (!error) + error = adjust_tp(&qos->rxtp, qos->aal); + if (error) + return error; + if (!vcc->dev->ops->change_qos) + return -EOPNOTSUPP; if (sk_atm(vcc)->sk_family == AF_ATMPVC) - return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET); - return svc_change_qos(vcc,qos); + return vcc->dev->ops->change_qos(vcc, qos, ATM_MF_SET); + return svc_change_qos(vcc, qos); } - static int check_tp(const struct atm_trafprm *tp) { /* @@@ Should be merged with adjust_tp */ - if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) return 0; + if (!tp->traffic_class || tp->traffic_class == ATM_ANYCLASS) + return 0; if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr && - !tp->max_pcr) return -EINVAL; - if (tp->min_pcr == ATM_MAX_PCR) return -EINVAL; + !tp->max_pcr) + return -EINVAL; + if (tp->min_pcr == ATM_MAX_PCR) + return -EINVAL; if (tp->min_pcr && tp->max_pcr && tp->max_pcr != ATM_MAX_PCR && - tp->min_pcr > tp->max_pcr) return -EINVAL; + tp->min_pcr > tp->max_pcr) + return -EINVAL; /* * We allow pcr to be outside [min_pcr,max_pcr], because later * adjustment may still push it in the valid range. @@ -668,7 +667,6 @@ static int check_tp(const struct atm_trafprm *tp) return 0; } - static int check_qos(const struct atm_qos *qos) { int error; @@ -678,9 +676,11 @@ static int check_qos(const struct atm_qos *qos) if (qos->txtp.traffic_class != qos->rxtp.traffic_class && qos->txtp.traffic_class && qos->rxtp.traffic_class && qos->txtp.traffic_class != ATM_ANYCLASS && - qos->rxtp.traffic_class != ATM_ANYCLASS) return -EINVAL; + qos->rxtp.traffic_class != ATM_ANYCLASS) + return -EINVAL; error = check_tp(&qos->txtp); - if (error) return error; + if (error) + return error; return check_tp(&qos->rxtp); } @@ -696,37 +696,41 @@ int vcc_setsockopt(struct socket *sock, int level, int optname, vcc = ATM_SD(sock); switch (optname) { - case SO_ATMQOS: - { - struct atm_qos qos; - - if (copy_from_user(&qos,optval,sizeof(qos))) - return -EFAULT; - error = check_qos(&qos); - if (error) return error; - if (sock->state == SS_CONNECTED) - return atm_change_qos(vcc,&qos); - if (sock->state != SS_UNCONNECTED) - return -EBADFD; - vcc->qos = qos; - set_bit(ATM_VF_HASQOS,&vcc->flags); - return 0; - } - case SO_SETCLP: - if (get_user(value,(unsigned long __user *)optval)) - return -EFAULT; - if (value) vcc->atm_options |= ATM_ATMOPT_CLP; - else vcc->atm_options &= ~ATM_ATMOPT_CLP; - return 0; - default: - if (level == SOL_SOCKET) return -EINVAL; - break; + case SO_ATMQOS: + { + struct atm_qos qos; + + if (copy_from_user(&qos, optval, sizeof(qos))) + return -EFAULT; + error = check_qos(&qos); + if (error) + return error; + if (sock->state == SS_CONNECTED) + return atm_change_qos(vcc, &qos); + if (sock->state != SS_UNCONNECTED) + return -EBADFD; + vcc->qos = qos; + set_bit(ATM_VF_HASQOS, &vcc->flags); + return 0; } - if (!vcc->dev || !vcc->dev->ops->setsockopt) return -EINVAL; - return vcc->dev->ops->setsockopt(vcc,level,optname,optval,optlen); + case SO_SETCLP: + if (get_user(value, (unsigned long __user *)optval)) + return -EFAULT; + if (value) + vcc->atm_options |= ATM_ATMOPT_CLP; + else + vcc->atm_options &= ~ATM_ATMOPT_CLP; + return 0; + default: + if (level == SOL_SOCKET) + return -EINVAL; + break; + } + if (!vcc->dev || !vcc->dev->ops->setsockopt) + return -EINVAL; + return vcc->dev->ops->setsockopt(vcc, level, optname, optval, optlen); } - int vcc_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { @@ -740,33 +744,33 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, vcc = ATM_SD(sock); switch (optname) { - case SO_ATMQOS: - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) - return -EINVAL; - return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ? - -EFAULT : 0; - case SO_SETCLP: - return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : - 0,(unsigned long __user *)optval) ? -EFAULT : 0; - case SO_ATMPVC: - { - struct sockaddr_atmpvc pvc; - - if (!vcc->dev || - !test_bit(ATM_VF_ADDR,&vcc->flags)) - return -ENOTCONN; - pvc.sap_family = AF_ATMPVC; - pvc.sap_addr.itf = vcc->dev->number; - pvc.sap_addr.vpi = vcc->vpi; - pvc.sap_addr.vci = vcc->vci; - return copy_to_user(optval,&pvc,sizeof(pvc)) ? - -EFAULT : 0; - } - default: - if (level == SOL_SOCKET) return -EINVAL; + case SO_ATMQOS: + if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) + return -EINVAL; + return copy_to_user(optval, &vcc->qos, sizeof(vcc->qos)) + ? -EFAULT : 0; + case SO_SETCLP: + return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0, + (unsigned long __user *)optval) ? -EFAULT : 0; + case SO_ATMPVC: + { + struct sockaddr_atmpvc pvc; + + if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) + return -ENOTCONN; + pvc.sap_family = AF_ATMPVC; + pvc.sap_addr.itf = vcc->dev->number; + pvc.sap_addr.vpi = vcc->vpi; + pvc.sap_addr.vci = vcc->vci; + return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0; + } + default: + if (level == SOL_SOCKET) + return -EINVAL; break; } - if (!vcc->dev || !vcc->dev->ops->getsockopt) return -EINVAL; + if (!vcc->dev || !vcc->dev->ops->getsockopt) + return -EINVAL; return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len); } @@ -774,22 +778,26 @@ static int __init atm_init(void) { int error; - if ((error = proto_register(&vcc_proto, 0)) < 0) + error = proto_register(&vcc_proto, 0); + if (error < 0) goto out; - - if ((error = atmpvc_init()) < 0) { + error = atmpvc_init(); + if (error < 0) { pr_err("atmpvc_init() failed with %d\n", error); goto out_unregister_vcc_proto; } - if ((error = atmsvc_init()) < 0) { + error = atmsvc_init(); + if (error < 0) { pr_err("atmsvc_init() failed with %d\n", error); goto out_atmpvc_exit; } - if ((error = atm_proc_init()) < 0) { + error = atm_proc_init(); + if (error < 0) { pr_err("atm_proc_init() failed with %d\n", error); goto out_atmsvc_exit; } - if ((error = atm_sysfs_init()) < 0) { + error = atm_sysfs_init(); + if (error < 0) { pr_err("atm_sysfs_init() failed with %d\n", error); goto out_atmproc_exit; } -- cgit v1.2.3 From 5ff7ef7911d100b6568c731b1d078f819da82d03 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:07 +0000 Subject: net/atm/ioctl.c: checkpatch cleanups Spacing cleanups Moved EXPORT_SYMBOL Mostly 80 column wrapped. switch/case cleanups Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/ioctl.c | 195 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index b75afba1f72b..62dc8bfe6fe7 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -37,6 +37,7 @@ void register_atm_ioctl(struct atm_ioctl *ioctl) list_add_tail(&ioctl->list, &ioctl_list); mutex_unlock(&ioctl_mutex); } +EXPORT_SYMBOL(register_atm_ioctl); void deregister_atm_ioctl(struct atm_ioctl *ioctl) { @@ -44,129 +45,128 @@ void deregister_atm_ioctl(struct atm_ioctl *ioctl) list_del(&ioctl->list); mutex_unlock(&ioctl_mutex); } - -EXPORT_SYMBOL(register_atm_ioctl); EXPORT_SYMBOL(deregister_atm_ioctl); -static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg, int compat) +static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg, int compat) { struct sock *sk = sock->sk; struct atm_vcc *vcc; int error; - struct list_head * pos; + struct list_head *pos; void __user *argp = (void __user *)arg; vcc = ATM_SD(sock); switch (cmd) { - case SIOCOUTQ: - if (sock->state != SS_CONNECTED || - !test_bit(ATM_VF_READY, &vcc->flags)) { - error = -EINVAL; - goto done; - } - error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), - (int __user *) argp) ? -EFAULT : 0; + case SIOCOUTQ: + if (sock->state != SS_CONNECTED || + !test_bit(ATM_VF_READY, &vcc->flags)) { + error = -EINVAL; + goto done; + } + error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), + (int __user *)argp) ? -EFAULT : 0; + goto done; + case SIOCINQ: + { + struct sk_buff *skb; + + if (sock->state != SS_CONNECTED) { + error = -EINVAL; goto done; - case SIOCINQ: - { - struct sk_buff *skb; - - if (sock->state != SS_CONNECTED) { - error = -EINVAL; - goto done; - } - skb = skb_peek(&sk->sk_receive_queue); - error = put_user(skb ? skb->len : 0, - (int __user *)argp) ? -EFAULT : 0; - goto done; - } - case SIOCGSTAMP: /* borrowed from IP */ + } + skb = skb_peek(&sk->sk_receive_queue); + error = put_user(skb ? skb->len : 0, + (int __user *)argp) ? -EFAULT : 0; + goto done; + } + case SIOCGSTAMP: /* borrowed from IP */ #ifdef CONFIG_COMPAT - if (compat) - error = compat_sock_get_timestamp(sk, argp); - else + if (compat) + error = compat_sock_get_timestamp(sk, argp); + else #endif - error = sock_get_timestamp(sk, argp); - goto done; - case SIOCGSTAMPNS: /* borrowed from IP */ + error = sock_get_timestamp(sk, argp); + goto done; + case SIOCGSTAMPNS: /* borrowed from IP */ #ifdef CONFIG_COMPAT - if (compat) - error = compat_sock_get_timestampns(sk, argp); - else + if (compat) + error = compat_sock_get_timestampns(sk, argp); + else #endif - error = sock_get_timestampns(sk, argp); + error = sock_get_timestampns(sk, argp); + goto done; + case ATM_SETSC: + if (net_ratelimit()) + pr_warning("ATM_SETSC is obsolete; used by %s:%d\n", + current->comm, task_pid_nr(current)); + error = 0; + goto done; + case ATMSIGD_CTRL: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; goto done; - case ATM_SETSC: - if (net_ratelimit()) - pr_warning("ATM_SETSC is obsolete; used by %s:%d\n", - current->comm, task_pid_nr(current)); - error = 0; + } + /* + * The user/kernel protocol for exchanging signalling + * info uses kernel pointers as opaque references, + * so the holder of the file descriptor can scribble + * on the kernel... so we should make sure that we + * have the same privileges that /proc/kcore needs + */ + if (!capable(CAP_SYS_RAWIO)) { + error = -EPERM; goto done; - case ATMSIGD_CTRL: - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - /* - * The user/kernel protocol for exchanging signalling - * info uses kernel pointers as opaque references, - * so the holder of the file descriptor can scribble - * on the kernel... so we should make sure that we - * have the same privileges that /proc/kcore needs - */ - if (!capable(CAP_SYS_RAWIO)) { - error = -EPERM; - goto done; - } + } #ifdef CONFIG_COMPAT - /* WTF? I don't even want to _think_ about making this - work for 32-bit userspace. TBH I don't really want - to think about it at all. dwmw2. */ - if (compat) { - if (net_ratelimit()) - pr_warning("32-bit task cannot be atmsigd\n"); - error = -EINVAL; - goto done; - } + /* WTF? I don't even want to _think_ about making this + work for 32-bit userspace. TBH I don't really want + to think about it at all. dwmw2. */ + if (compat) { + if (net_ratelimit()) + pr_warning("32-bit task cannot be atmsigd\n"); + error = -EINVAL; + goto done; + } #endif - error = sigd_attach(vcc); - if (!error) - sock->state = SS_CONNECTED; + error = sigd_attach(vcc); + if (!error) + sock->state = SS_CONNECTED; + goto done; + case ATM_SETBACKEND: + case ATM_NEWBACKENDIF: + { + atm_backend_t backend; + error = get_user(backend, (atm_backend_t __user *)argp); + if (error) goto done; - case ATM_SETBACKEND: - case ATM_NEWBACKENDIF: - { - atm_backend_t backend; - error = get_user(backend, (atm_backend_t __user *) argp); - if (error) - goto done; - switch (backend) { - case ATM_BACKEND_PPP: - request_module("pppoatm"); - break; - case ATM_BACKEND_BR2684: - request_module("br2684"); - break; - } - } - break; - case ATMMPC_CTRL: - case ATMMPC_DATA: - request_module("mpoa"); - break; - case ATMARPD_CTRL: - request_module("clip"); + switch (backend) { + case ATM_BACKEND_PPP: + request_module("pppoatm"); break; - case ATMLEC_CTRL: - request_module("lec"); + case ATM_BACKEND_BR2684: + request_module("br2684"); break; + } + break; + } + case ATMMPC_CTRL: + case ATMMPC_DATA: + request_module("mpoa"); + break; + case ATMARPD_CTRL: + request_module("clip"); + break; + case ATMLEC_CTRL: + request_module("lec"); + break; } error = -ENOIOCTLCMD; mutex_lock(&ioctl_mutex); list_for_each(pos, &ioctl_list) { - struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); + struct atm_ioctl *ic = list_entry(pos, struct atm_ioctl, list); if (try_module_get(ic->owner)) { error = ic->ioctl(sock, cmd, arg); module_put(ic->owner); @@ -185,7 +185,6 @@ done: return error; } - int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { return do_vcc_ioctl(sock, cmd, arg, 0); @@ -288,8 +287,8 @@ static int do_atmif_sioc(struct socket *sock, unsigned int cmd, sioc = compat_alloc_user_space(sizeof(*sioc)); sioc32 = compat_ptr(arg); - if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) - || get_user(data, &sioc32->arg)) + if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) || + get_user(data, &sioc32->arg)) return -EFAULT; datap = compat_ptr(data); if (put_user(datap, &sioc->arg)) -- cgit v1.2.3 From c48192a7075fb218d92810fbe76ddd8732f2bbb8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:08 +0000 Subject: net/atm/lec.c: checkpatch cleanups Convert #include Use print_hex_dump Move embedded assigns out of tests Move trailing statements to new lines Remove unnecessary braces around single line statements switch/case cleanups Removed paren around returns Use %pM Moved leading continuation logical tests to end of previous line Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/lec.c | 284 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 136 insertions(+), 148 deletions(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index 6873813c3c99..aefd278d6af6 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -87,17 +87,19 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, int is_rdesc, struct lec_arp_table **ret_entry); static void lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, - const unsigned char *atm_addr, unsigned long remoteflag, + const unsigned char *atm_addr, + unsigned long remoteflag, unsigned int targetless_le_arp); static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id); static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc); static void lec_set_flush_tran_id(struct lec_priv *priv, const unsigned char *atm_addr, unsigned long tran_id); -static void lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, +static void lec_vcc_added(struct lec_priv *priv, + const struct atmlec_ioc *ioc_data, struct atm_vcc *vcc, - void (*old_push) (struct atm_vcc *vcc, - struct sk_buff *skb)); + void (*old_push)(struct atm_vcc *vcc, + struct sk_buff *skb)); static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc); /* must be done under lec_arp_lock */ @@ -112,7 +114,6 @@ static inline void lec_arp_put(struct lec_arp_table *entry) kfree(entry); } - static struct lane2_ops lane2_ops = { lane2_resolve, /* resolve, spec 3.1.3 */ lane2_associate_req, /* associate_req, spec 3.1.4 */ @@ -150,7 +151,8 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) mesg = (struct atmlec_msg *)skb2->data; mesg->type = l_topology_change; buff += 4; - mesg->content.normal.flag = *buff & 0x01; /* 0x01 is topology change */ + mesg->content.normal.flag = *buff & 0x01; + /* 0x01 is topology change */ priv = netdev_priv(dev); atm_force_charge(priv->lecd, skb2->truesize); @@ -263,14 +265,10 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, unsigned char rdesc[ETH_ALEN]; /* Token Ring route descriptor */ #endif int is_rdesc; -#if DUMP_PACKETS > 0 - char buf[300]; - int i = 0; -#endif /* DUMP_PACKETS >0 */ pr_debug("called\n"); if (!priv->lecd) { - printk("%s:No lecd attached\n", dev->name); + pr_info("%s:No lecd attached\n", dev->name); dev->stats.tx_errors++; netif_stop_queue(dev); kfree_skb(skb); @@ -315,23 +313,17 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, } #endif -#if DUMP_PACKETS > 0 - printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, - skb->len, priv->lecid); #if DUMP_PACKETS >= 2 - for (i = 0; i < skb->len && i < 99; i++) { - sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); - } +#define MAX_DUMP_SKB 99 #elif DUMP_PACKETS >= 1 - for (i = 0; i < skb->len && i < 30; i++) { - sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); - } +#define MAX_DUMP_SKB 30 +#endif +#if DUMP_PACKETS >= 1 + printk(KERN_DEBUG "%s: send datalen:%ld lecid:%4.4x\n", + dev->name, skb->len, priv->lecid); + print_hex_dump(KERN_DEBUG, "", DUMP_OFFSET, 16, 1, + skb->data, min(skb->len, MAX_DUMP_SKB), true); #endif /* DUMP_PACKETS >= 1 */ - if (i == skb->len) - printk("%s\n", buf); - else - printk("%s...\n", buf); -#endif /* DUMP_PACKETS > 0 */ /* Minimum ethernet-frame size */ #ifdef CONFIG_TR @@ -385,7 +377,8 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, goto out; } #if DUMP_PACKETS > 0 - printk("%s:sending to vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci); + printk(KERN_DEBUG "%s:sending to vpi:%d vci:%d\n", + dev->name, vcc->vpi, vcc->vci); #endif /* DUMP_PACKETS > 0 */ while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { @@ -442,14 +435,12 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) pr_debug("%s: msg from zeppelin:%d\n", dev->name, mesg->type); switch (mesg->type) { case l_set_mac_addr: - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) dev->dev_addr[i] = mesg->content.normal.mac_addr[i]; - } break; case l_del_mac_addr: - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) dev->dev_addr[i] = 0; - } break; case l_addr_delete: lec_addr_delete(priv, mesg->content.normal.atm_addr, @@ -497,13 +488,14 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) priv->flush_timeout = (mesg->content.config.flush_timeout * HZ); priv->path_switching_delay = (mesg->content.config.path_switching_delay * HZ); - priv->lane_version = mesg->content.config.lane_version; /* LANE2 */ + priv->lane_version = mesg->content.config.lane_version; + /* LANE2 */ priv->lane2_ops = NULL; if (priv->lane_version > 1) priv->lane2_ops = &lane2_ops; if (dev_set_mtu(dev, mesg->content.config.mtu)) - printk("%s: change_mtu to %d failed\n", dev->name, - mesg->content.config.mtu); + pr_info("%s: change_mtu to %d failed\n", + dev->name, mesg->content.config.mtu); priv->is_proxy = mesg->content.config.is_proxy; break; case l_flush_tran_id: @@ -524,16 +516,15 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) break; if (br_fdb_test_addr_hook(dev, - mesg->content.proxy.mac_addr)) { + mesg->content.proxy.mac_addr)) { /* hit from bridge table, send LE_ARP_RESPONSE */ struct sk_buff *skb2; struct sock *sk; pr_debug("%s: entry found, responding to zeppelin\n", dev->name); - skb2 = - alloc_skb(sizeof(struct atmlec_msg), - GFP_ATOMIC); + skb2 = alloc_skb(sizeof(struct atmlec_msg), + GFP_ATOMIC); if (skb2 == NULL) break; skb2->len = sizeof(struct atmlec_msg); @@ -548,7 +539,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ break; default: - printk("%s: Unknown message type %d\n", dev->name, mesg->type); + pr_info("%s: Unknown message type %d\n", dev->name, mesg->type); dev_kfree_skb(skb); return -EINVAL; } @@ -569,14 +560,13 @@ static void lec_atm_close(struct atm_vcc *vcc) lec_arp_destroy(priv); if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) - printk("%s lec_atm_close: closing with messages pending\n", - dev->name); + pr_info("%s closing with messages pending\n", dev->name); while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) { atm_return(vcc, skb->truesize); dev_kfree_skb(skb); } - printk("%s: Shut down!\n", dev->name); + pr_info("%s: Shut down!\n", dev->name); module_put(THIS_MODULE); } @@ -605,9 +595,8 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, struct sk_buff *skb; struct atmlec_msg *mesg; - if (!priv || !priv->lecd) { + if (!priv || !priv->lecd) return -1; - } skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); if (!skb) return -1; @@ -688,7 +677,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) struct net_device *dev = (struct net_device *)vcc->proto_data; struct lec_priv *priv = netdev_priv(dev); -#if DUMP_PACKETS >0 +#if DUMP_PACKETS > 0 printk(KERN_DEBUG "%s: vcc vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci); #endif @@ -767,9 +756,8 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) dev_kfree_skb(skb); return; } - if (!hlist_empty(&priv->lec_arp_empty_ones)) { + if (!hlist_empty(&priv->lec_arp_empty_ones)) lec_arp_check_empties(priv, vcc, skb); - } skb_pull(skb, 2); /* skip lec_id */ #ifdef CONFIG_TR if (priv->is_trdev) @@ -816,7 +804,8 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg) if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || !dev_lec[ioc_data.dev_num]) return -EINVAL; - if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) + vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); + if (!vpriv) return -ENOMEM; vpriv->xoff = 0; vpriv->old_pop = vcc->pop; @@ -907,9 +896,8 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) priv->flush_timeout = (4 * HZ); priv->path_switching_delay = (6 * HZ); - if (dev_lec[i]->flags & IFF_UP) { + if (dev_lec[i]->flags & IFF_UP) netif_start_queue(dev_lec[i]); - } __module_get(THIS_MODULE); return i; } @@ -1111,7 +1099,9 @@ static int lec_seq_show(struct seq_file *seq, void *v) else { struct lec_state *state = seq->private; struct net_device *dev = state->dev; - struct lec_arp_table *entry = hlist_entry(state->node, struct lec_arp_table, next); + struct lec_arp_table *entry = hlist_entry(state->node, + struct lec_arp_table, + next); seq_printf(seq, "%s ", dev->name); lec_info(seq, entry); @@ -1191,7 +1181,7 @@ static int __init lane_module_init(void) #endif register_atm_ioctl(&lane_ioctl_ops); - printk("lec.c: " __DATE__ " " __TIME__ " initialized\n"); + pr_info("lec.c: " __DATE__ " " __TIME__ " initialized\n"); return 0; } @@ -1280,13 +1270,13 @@ static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst, struct lec_priv *priv = netdev_priv(dev); if (compare_ether_addr(lan_dst, dev->dev_addr)) - return (0); /* not our mac address */ + return 0; /* not our mac address */ kfree(priv->tlvs); /* NULL if there was no previous association */ priv->tlvs = kmemdup(tlvs, sizeoftlvs, GFP_KERNEL); if (priv->tlvs == NULL) - return (0); + return 0; priv->sizeoftlvs = sizeoftlvs; skb = alloc_skb(sizeoftlvs, GFP_ATOMIC); @@ -1296,12 +1286,12 @@ static int lane2_associate_req(struct net_device *dev, const u8 *lan_dst, skb_copy_to_linear_data(skb, tlvs, sizeoftlvs); retval = send_to_lecd(priv, l_associate_req, NULL, NULL, skb); if (retval != 0) - printk("lec.c: lane2_associate_req() failed\n"); + pr_info("lec.c: lane2_associate_req() failed\n"); /* * If the previous association has changed we must * somehow notify other LANE entities about the change */ - return (1); + return 1; } /* @@ -1334,12 +1324,12 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr, entry->sizeoftlvs = sizeoftlvs; #endif #if 0 - printk("lec.c: lane2_associate_ind()\n"); - printk("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs); + pr_info("\n"); + pr_info("dump of tlvs, sizeoftlvs=%d\n", sizeoftlvs); while (i < sizeoftlvs) - printk("%02x ", tlvs[i++]); + pr_cont("%02x ", tlvs[i++]); - printk("\n"); + pr_cont("\n"); #endif /* tell MPOA about the TLVs we saw */ @@ -1359,13 +1349,13 @@ static void lane2_associate_ind(struct net_device *dev, const u8 *mac_addr, #include #include -#include +#include #include #include #include #if 0 -#define pr_debug(format,args...) +#define pr_debug(format, args...) /* #define pr_debug printk */ @@ -1381,7 +1371,7 @@ static void lec_arp_expire_arp(unsigned long data); * Arp table funcs */ -#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE -1)) +#define HASH(ch) (ch & (LEC_ARP_TABLE_SIZE - 1)) /* * Initialization of arp-cache @@ -1390,9 +1380,8 @@ static void lec_arp_init(struct lec_priv *priv) { unsigned short i; - for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { + for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); - } INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); INIT_HLIST_HEAD(&priv->lec_no_forward); INIT_HLIST_HEAD(&priv->mcast_fwds); @@ -1449,20 +1438,23 @@ lec_arp_remove(struct lec_priv *priv, struct lec_arp_table *to_remove) struct lec_arp_table *entry; int i, remove_vcc = 1; - if (!to_remove) { + if (!to_remove) return -1; - } hlist_del(&to_remove->next); del_timer(&to_remove->timer); - /* If this is the only MAC connected to this VCC, also tear down the VCC */ + /* + * If this is the only MAC connected to this VCC, + * also tear down the VCC + */ if (to_remove->status >= ESI_FLUSH_PENDING) { /* * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT */ for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry(entry, node, + &priv->lec_arp_tables[i], next) { if (memcmp(to_remove->atm_addr, entry->atm_addr, ATM_ESA_LEN) == 0) { remove_vcc = 0; @@ -1493,9 +1485,8 @@ static const char *get_status_string(unsigned char st) return "ESI_FLUSH_PENDING"; case ESI_FORWARD_DIRECT: return "ESI_FORWARD_DIRECT"; - default: - return ""; } + return ""; } static void dump_arp_table(struct lec_priv *priv) @@ -1505,18 +1496,15 @@ static void dump_arp_table(struct lec_priv *priv) char buf[256]; int i, j, offset; - printk("Dump %p:\n", priv); + pr_info("Dump %p:\n", priv); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry(rulla, node, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry(rulla, node, + &priv->lec_arp_tables[i], next) { offset = 0; offset += sprintf(buf, "%d: %p\n", i, rulla); - offset += sprintf(buf + offset, "Mac:"); - for (j = 0; j < ETH_ALEN; j++) { - offset += sprintf(buf + offset, - "%2.2x ", - rulla->mac_addr[j] & 0xff); - } - offset += sprintf(buf + offset, "Atm:"); + offset += sprintf(buf + offset, "Mac: %pM", + rulla->mac_addr); + offset += sprintf(buf + offset, " Atm:"); for (j = 0; j < ATM_ESA_LEN; j++) { offset += sprintf(buf + offset, "%2.2x ", @@ -1536,20 +1524,16 @@ static void dump_arp_table(struct lec_priv *priv) "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); - printk("%s\n", buf); + pr_info("%s\n", buf); } } if (!hlist_empty(&priv->lec_no_forward)) - printk("No forward\n"); + pr_info("No forward\n"); hlist_for_each_entry(rulla, node, &priv->lec_no_forward, next) { offset = 0; - offset += sprintf(buf + offset, "Mac:"); - for (j = 0; j < ETH_ALEN; j++) { - offset += sprintf(buf + offset, "%2.2x ", - rulla->mac_addr[j] & 0xff); - } - offset += sprintf(buf + offset, "Atm:"); + offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr); + offset += sprintf(buf + offset, " Atm:"); for (j = 0; j < ATM_ESA_LEN; j++) { offset += sprintf(buf + offset, "%2.2x ", rulla->atm_addr[j] & 0xff); @@ -1566,19 +1550,15 @@ static void dump_arp_table(struct lec_priv *priv) "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); - printk("%s\n", buf); + pr_info("%s\n", buf); } if (!hlist_empty(&priv->lec_arp_empty_ones)) - printk("Empty ones\n"); + pr_info("Empty ones\n"); hlist_for_each_entry(rulla, node, &priv->lec_arp_empty_ones, next) { offset = 0; - offset += sprintf(buf + offset, "Mac:"); - for (j = 0; j < ETH_ALEN; j++) { - offset += sprintf(buf + offset, "%2.2x ", - rulla->mac_addr[j] & 0xff); - } - offset += sprintf(buf + offset, "Atm:"); + offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr); + offset += sprintf(buf + offset, " Atm:"); for (j = 0; j < ATM_ESA_LEN; j++) { offset += sprintf(buf + offset, "%2.2x ", rulla->atm_addr[j] & 0xff); @@ -1595,19 +1575,15 @@ static void dump_arp_table(struct lec_priv *priv) "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); - printk("%s", buf); + pr_info("%s", buf); } if (!hlist_empty(&priv->mcast_fwds)) - printk("Multicast Forward VCCs\n"); + pr_info("Multicast Forward VCCs\n"); hlist_for_each_entry(rulla, node, &priv->mcast_fwds, next) { offset = 0; - offset += sprintf(buf + offset, "Mac:"); - for (j = 0; j < ETH_ALEN; j++) { - offset += sprintf(buf + offset, "%2.2x ", - rulla->mac_addr[j] & 0xff); - } - offset += sprintf(buf + offset, "Atm:"); + offset += sprintf(buf + offset, "Mac: %pM", rulla->mac_addr); + offset += sprintf(buf + offset, " Atm:"); for (j = 0; j < ATM_ESA_LEN; j++) { offset += sprintf(buf + offset, "%2.2x ", rulla->atm_addr[j] & 0xff); @@ -1624,7 +1600,7 @@ static void dump_arp_table(struct lec_priv *priv) "Flags:%x, Packets_flooded:%x, Status: %s ", rulla->flags, rulla->packets_flooded, get_status_string(rulla->status)); - printk("%s\n", buf); + pr_info("%s\n", buf); } } @@ -1650,14 +1626,16 @@ static void lec_arp_destroy(struct lec_priv *priv) spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_tables[i], next) { lec_arp_remove(priv, entry); lec_arp_put(entry); } INIT_HLIST_HEAD(&priv->lec_arp_tables[i]); } - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_empty_ones, next) { del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); hlist_del(&entry->next); @@ -1665,7 +1643,8 @@ static void lec_arp_destroy(struct lec_priv *priv) } INIT_HLIST_HEAD(&priv->lec_arp_empty_ones); - hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_no_forward, next) { del_timer_sync(&entry->timer); lec_arp_clear_vccs(entry); hlist_del(&entry->next); @@ -1698,9 +1677,8 @@ static struct lec_arp_table *lec_arp_find(struct lec_priv *priv, head = &priv->lec_arp_tables[HASH(mac_addr[ETH_ALEN - 1])]; hlist_for_each_entry(entry, node, head, next) { - if (!compare_ether_addr(mac_addr, entry->mac_addr)) { + if (!compare_ether_addr(mac_addr, entry->mac_addr)) return entry; - } } return NULL; } @@ -1712,7 +1690,7 @@ static struct lec_arp_table *make_entry(struct lec_priv *priv, to_return = kzalloc(sizeof(struct lec_arp_table), GFP_ATOMIC); if (!to_return) { - printk("LEC: Arp entry kmalloc failed\n"); + pr_info("LEC: Arp entry kmalloc failed\n"); return NULL; } memcpy(to_return->mac_addr, mac_addr, ETH_ALEN); @@ -1802,7 +1780,8 @@ static void lec_arp_check_expire(struct work_struct *work) restart: spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_tables[i], next) { if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change) time_to_check = priv->forward_delay_time; @@ -1811,9 +1790,9 @@ restart: pr_debug("About to expire: %lx - %lx > %lx\n", now, entry->last_used, time_to_check); - if (time_after(now, entry->last_used + time_to_check) - && !(entry->flags & LEC_PERMANENT_FLAG) - && !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ + if (time_after(now, entry->last_used + time_to_check) && + !(entry->flags & LEC_PERMANENT_FLAG) && + !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ /* Remove entry */ pr_debug("Entry timed out\n"); lec_arp_remove(priv, entry); @@ -1821,11 +1800,10 @@ restart: } else { /* Something else */ if ((entry->status == ESI_VC_PENDING || - entry->status == ESI_ARP_PENDING) - && time_after_eq(now, - entry->timestamp + - priv-> - max_unknown_frame_time)) { + entry->status == ESI_ARP_PENDING) && + time_after_eq(now, + entry->timestamp + + priv->max_unknown_frame_time)) { entry->timestamp = jiffies; entry->packets_flooded = 0; if (entry->status == ESI_VC_PENDING) @@ -1834,8 +1812,7 @@ restart: entry->atm_addr, NULL); } - if (entry->status == ESI_FLUSH_PENDING - && + if (entry->status == ESI_FLUSH_PENDING && time_after_eq(now, entry->timestamp + priv->path_switching_delay)) { struct sk_buff *skb; @@ -1863,7 +1840,8 @@ restart: * */ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, - const unsigned char *mac_to_find, int is_rdesc, + const unsigned char *mac_to_find, + int is_rdesc, struct lec_arp_table **ret_entry) { unsigned long flags; @@ -1899,9 +1877,8 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, * If the LE_ARP cache entry is still pending, reset count to 0 * so another LE_ARP request can be made for this frame. */ - if (entry->status == ESI_ARP_PENDING) { + if (entry->status == ESI_ARP_PENDING) entry->no_tries = 0; - } /* * Data direct VC not yet set up, check to see if the unknown * frame count is greater than the limit. If the limit has @@ -1969,10 +1946,11 @@ lec_addr_delete(struct lec_priv *priv, const unsigned char *atm_addr, pr_debug("\n"); spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { - if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) - && (permanent || - !(entry->flags & LEC_PERMANENT_FLAG))) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_tables[i], next) { + if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN) && + (permanent || + !(entry->flags & LEC_PERMANENT_FLAG))) { lec_arp_remove(priv, entry); lec_arp_put(entry); } @@ -2008,7 +1986,8 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, * we have no entry in the cache. 7.1.30 */ if (!hlist_empty(&priv->lec_arp_empty_ones)) { - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_empty_ones, next) { if (memcmp(entry->atm_addr, atm_addr, ATM_ESA_LEN) == 0) { hlist_del(&entry->next); del_timer(&entry->timer); @@ -2052,7 +2031,8 @@ lec_arp_update(struct lec_priv *priv, const unsigned char *mac_addr, memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN); del_timer(&entry->timer); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry(tmp, node, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry(tmp, node, + &priv->lec_arp_tables[i], next) { if (entry != tmp && !memcmp(tmp->atm_addr, atm_addr, ATM_ESA_LEN)) { /* Vcc to this host exists */ @@ -2097,14 +2077,13 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, int i, found_entry = 0; spin_lock_irqsave(&priv->lec_arp_lock, flags); + /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ if (ioc_data->receive == 2) { - /* Vcc for Multicast Forward. No timer, LANEv2 7.1.20 and 2.3.5.3 */ - pr_debug("LEC_ARP: Attaching mcast forward\n"); #if 0 entry = lec_arp_find(priv, bus_mac); if (!entry) { - printk("LEC_ARP: Multicast entry not found!\n"); + pr_info("LEC_ARP: Multicast entry not found!\n"); goto out; } memcpy(entry->atm_addr, ioc_data->atm_addr, ATM_ESA_LEN); @@ -2163,7 +2142,8 @@ lec_vcc_added(struct lec_priv *priv, const struct atmlec_ioc *ioc_data, ioc_data->atm_addr[16], ioc_data->atm_addr[17], ioc_data->atm_addr[18], ioc_data->atm_addr[19]); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry(entry, node, + &priv->lec_arp_tables[i], next) { if (memcmp (ioc_data->atm_addr, entry->atm_addr, ATM_ESA_LEN) == 0) { @@ -2247,14 +2227,16 @@ static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id) restart: spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { - if (entry->flush_tran_id == tran_id - && entry->status == ESI_FLUSH_PENDING) { + hlist_for_each_entry(entry, node, + &priv->lec_arp_tables[i], next) { + if (entry->flush_tran_id == tran_id && + entry->status == ESI_FLUSH_PENDING) { struct sk_buff *skb; struct atm_vcc *vcc = entry->vcc; lec_arp_hold(entry); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); + spin_unlock_irqrestore(&priv->lec_arp_lock, + flags); while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) lec_send(vcc, skb); entry->last_used = jiffies; @@ -2280,7 +2262,8 @@ lec_set_flush_tran_id(struct lec_priv *priv, spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) - hlist_for_each_entry(entry, node, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry(entry, node, + &priv->lec_arp_tables[i], next) { if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)) { entry->flush_tran_id = tran_id; pr_debug("Set flush transaction id to %lx for %p\n", @@ -2300,7 +2283,8 @@ static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc) struct lec_vcc_priv *vpriv; int err = 0; - if (!(vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL))) + vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); + if (!vpriv) return -ENOMEM; vpriv->xoff = 0; vpriv->old_pop = vcc->pop; @@ -2340,18 +2324,19 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) spin_lock_irqsave(&priv->lec_arp_lock, flags); for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_tables[i], next) { if (vcc == entry->vcc) { lec_arp_remove(priv, entry); lec_arp_put(entry); - if (priv->mcast_vcc == vcc) { + if (priv->mcast_vcc == vcc) priv->mcast_vcc = NULL; - } } } } - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_empty_ones, next) { if (entry->vcc == vcc) { lec_arp_clear_vccs(entry); del_timer(&entry->timer); @@ -2360,7 +2345,8 @@ static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc) } } - hlist_for_each_entry_safe(entry, node, next, &priv->lec_no_forward, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_no_forward, next) { if (entry->recv_vcc == vcc) { lec_arp_clear_vccs(entry); del_timer(&entry->timer); @@ -2401,14 +2387,16 @@ lec_arp_check_empties(struct lec_priv *priv, src = hdr->h_source; spin_lock_irqsave(&priv->lec_arp_lock, flags); - hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_empty_ones, next) { + hlist_for_each_entry_safe(entry, node, next, + &priv->lec_arp_empty_ones, next) { if (vcc == entry->vcc) { del_timer(&entry->timer); memcpy(entry->mac_addr, src, ETH_ALEN); entry->status = ESI_FORWARD_DIRECT; entry->last_used = jiffies; /* We might have got an entry */ - if ((tmp = lec_arp_find(priv, src))) { + tmp = lec_arp_find(priv, src); + if (tmp) { lec_arp_remove(priv, tmp); lec_arp_put(tmp); } -- cgit v1.2.3 From 5710044073ea734c0d7806d7fb9cd6308053704b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:09 +0000 Subject: net/atm/mpc.c: checkpatch cleanups Convert #include pr_info and pr_cont Moved labels to column 1 Move trailing statements to new lines switch/case cleanups remove unnecessary breaks after returns Remove unnecessary braces around single line statements Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/mpc.c | 445 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 252 insertions(+), 193 deletions(-) diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 3c45aef47b7e..55dba22e44b3 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -15,8 +15,8 @@ #include #include #include +#include #include -#include #include /* for ip_fast_csum() */ #include #include @@ -38,15 +38,17 @@ */ #if 0 -#define dprintk printk /* debug */ +#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ #else -#define dprintk(format,args...) +#define dprintk(format, args...) \ + do { if (0) printk(KERN_DEBUG format, ##args); } while (0) #endif #if 0 -#define ddprintk printk /* more debug */ +#define ddprintk printk(KERN_DEBUG format, ##args) /* more debug */ #else -#define ddprintk(format,args...) +#define ddprintk(format, args...) \ + do { if (0) printk(KERN_DEBUG format, ##args); } while (0) #endif @@ -54,15 +56,19 @@ #define MPOA_TAG_LEN 4 /* mpc_daemon -> kernel */ -static void MPOA_trigger_rcvd (struct k_message *msg, struct mpoa_client *mpc); +static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc); static void mps_death(struct k_message *msg, struct mpoa_client *mpc); -static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action); -static void MPOA_cache_impos_rcvd(struct k_message *msg, struct mpoa_client *mpc); -static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc); -static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc); +static void clean_up(struct k_message *msg, struct mpoa_client *mpc, + int action); +static void MPOA_cache_impos_rcvd(struct k_message *msg, + struct mpoa_client *mpc); +static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, + struct mpoa_client *mpc); +static void set_mps_mac_addr_rcvd(struct k_message *mesg, + struct mpoa_client *mpc); static const uint8_t *copy_macs(struct mpoa_client *mpc, const uint8_t *router_mac, @@ -76,10 +82,11 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb); static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb); static netdev_tx_t mpc_send_packet(struct sk_buff *skb, - struct net_device *dev); -static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev); + struct net_device *dev); +static int mpoa_event_listener(struct notifier_block *mpoa_notifier, + unsigned long event, void *dev); static void mpc_timer_refresh(void); -static void mpc_cache_check( unsigned long checking_time ); +static void mpc_cache_check(unsigned long checking_time); static struct llc_snap_hdr llc_snap_mpoa_ctrl = { 0xaa, 0xaa, 0x03, @@ -169,7 +176,7 @@ struct atm_mpoa_qos *atm_mpoa_add_qos(__be32 dst_ip, struct atm_qos *qos) entry = kmalloc(sizeof(struct atm_mpoa_qos), GFP_KERNEL); if (entry == NULL) { - printk("mpoa: atm_mpoa_add_qos: out of memory\n"); + pr_info("mpoa: out of memory\n"); return entry; } @@ -187,10 +194,9 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip) struct atm_mpoa_qos *qos; qos = qos_head; - while( qos != NULL ){ - if(qos->ipaddr == dst_ip) { + while (qos) { + if (qos->ipaddr == dst_ip) break; - } qos = qos->next; } @@ -202,10 +208,10 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(__be32 dst_ip) */ int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry) { - struct atm_mpoa_qos *curr; - if (entry == NULL) return 0; + if (entry == NULL) + return 0; if (entry == qos_head) { qos_head = qos_head->next; kfree(entry); @@ -236,9 +242,17 @@ void atm_mpoa_disp_qos(struct seq_file *m) while (qos != NULL) { seq_printf(m, "%pI4\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", - &qos->ipaddr, - qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, - qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); + &qos->ipaddr, + qos->qos.txtp.max_pcr, + qos->qos.txtp.pcr, + qos->qos.txtp.min_pcr, + qos->qos.txtp.max_cdv, + qos->qos.txtp.max_sdu, + qos->qos.rxtp.max_pcr, + qos->qos.rxtp.pcr, + qos->qos.rxtp.min_pcr, + qos->qos.rxtp.max_cdv, + qos->qos.rxtp.max_sdu); qos = qos->next; } } @@ -258,7 +272,7 @@ static struct mpoa_client *alloc_mpc(void) { struct mpoa_client *mpc; - mpc = kzalloc(sizeof (struct mpoa_client), GFP_KERNEL); + mpc = kzalloc(sizeof(struct mpoa_client), GFP_KERNEL); if (mpc == NULL) return NULL; rwlock_init(&mpc->ingress_lock); @@ -268,7 +282,7 @@ static struct mpoa_client *alloc_mpc(void) mpc->parameters.mpc_p1 = MPC_P1; mpc->parameters.mpc_p2 = MPC_P2; - memset(mpc->parameters.mpc_p3,0,sizeof(mpc->parameters.mpc_p3)); + memset(mpc->parameters.mpc_p3, 0, sizeof(mpc->parameters.mpc_p3)); mpc->parameters.mpc_p4 = MPC_P4; mpc->parameters.mpc_p5 = MPC_P5; mpc->parameters.mpc_p6 = MPC_P6; @@ -290,7 +304,7 @@ static void start_mpc(struct mpoa_client *mpc, struct net_device *dev) dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); if (!dev->netdev_ops) - printk("mpoa: (%s) start_mpc not starting\n", dev->name); + pr_info("(%s) not starting\n", dev->name); else { mpc->old_ops = dev->netdev_ops; mpc->new_ops = *mpc->old_ops; @@ -321,25 +335,18 @@ static const char *mpoa_device_type_string(char type) __attribute__ ((unused)); static const char *mpoa_device_type_string(char type) { - switch(type) { + switch (type) { case NON_MPOA: return "non-MPOA device"; - break; case MPS: return "MPS"; - break; case MPC: return "MPC"; - break; case MPS_AND_MPC: return "both MPS and MPC"; - break; - default: - return "unspecified (non-MPOA) device"; - break; } - return ""; /* not reached */ + return "unspecified (non-MPOA) device"; } /* @@ -368,22 +375,24 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, dprintk("total length of all TLVs %d\n", sizeoftlvs); mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */ if (mpc == NULL) { - printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name); + pr_info("(%s) no mpc\n", dev->name); return; } end_of_tlvs = tlvs + sizeoftlvs; while (end_of_tlvs - tlvs >= 5) { - type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3]; + type = ((tlvs[0] << 24) | (tlvs[1] << 16) | + (tlvs[2] << 8) | tlvs[3]); length = tlvs[4]; tlvs += 5; dprintk(" type 0x%x length %02x\n", type, length); if (tlvs + length > end_of_tlvs) { - printk("TLV value extends past its buffer, aborting parse\n"); + pr_info("TLV value extends past its buffer, aborting parse\n"); return; } if (type == 0) { - printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name); + pr_info("mpoa: (%s) TLV type was 0, returning\n", + dev->name); return; } @@ -393,39 +402,47 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, } mpoa_device_type = *tlvs++; number_of_mps_macs = *tlvs++; - dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type)); + dprintk("mpoa: (%s) MPOA device type '%s', ", + dev->name, mpoa_device_type_string(mpoa_device_type)); if (mpoa_device_type == MPS_AND_MPC && length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */ - printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", - dev->name); + pr_info("(%s) short MPOA Device Type TLV\n", + dev->name); continue; } - if ((mpoa_device_type == MPS || mpoa_device_type == MPC) - && length < 22 + number_of_mps_macs*ETH_ALEN) { - printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", - dev->name); + if ((mpoa_device_type == MPS || mpoa_device_type == MPC) && + length < 22 + number_of_mps_macs*ETH_ALEN) { + pr_info("(%s) short MPOA Device Type TLV\n", dev->name); continue; } - if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) { + if (mpoa_device_type != MPS && + mpoa_device_type != MPS_AND_MPC) { dprintk("ignoring non-MPS device\n"); - if (mpoa_device_type == MPC) tlvs += 20; + if (mpoa_device_type == MPC) + tlvs += 20; continue; /* we are only interested in MPSs */ } - if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) { - printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name); + if (number_of_mps_macs == 0 && + mpoa_device_type == MPS_AND_MPC) { + pr_info("(%s) MPS_AND_MPC has zero MACs\n", dev->name); continue; /* someone should read the spec */ } dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs); - /* ok, now we can go and tell our daemon the control address of MPS */ + /* + * ok, now we can go and tell our daemon + * the control address of MPS + */ send_set_mps_ctrl_addr(tlvs, mpc); - tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type); - if (tlvs == NULL) return; + tlvs = copy_macs(mpc, mac_addr, tlvs, + number_of_mps_macs, mpoa_device_type); + if (tlvs == NULL) + return; } if (end_of_tlvs - tlvs != 0) - printk("mpoa: (%s) lane2_assoc_ind: ignoring %Zd bytes of trailing TLV carbage\n", - dev->name, end_of_tlvs - tlvs); + pr_info("(%s) ignoring %Zd bytes of trailing TLV garbage\n", + dev->name, end_of_tlvs - tlvs); return; } @@ -443,11 +460,12 @@ static const uint8_t *copy_macs(struct mpoa_client *mpc, num_macs = (mps_macs > 1) ? mps_macs : 1; if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */ - if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs); + if (mpc->number_of_mps_macs != 0) + kfree(mpc->mps_macs); mpc->number_of_mps_macs = 0; - mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL); + mpc->mps_macs = kmalloc(num_macs * ETH_ALEN, GFP_KERNEL); if (mpc->mps_macs == NULL) { - printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name); + pr_info("(%s) out of mem\n", mpc->dev->name); return NULL; } } @@ -480,24 +498,30 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) iph = (struct iphdr *)buff; ipaddr = iph->daddr; - ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr); + ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", + mpc->dev->name, ipaddr); entry = mpc->in_ops->get(ipaddr, mpc); if (entry == NULL) { entry = mpc->in_ops->add_entry(ipaddr, mpc); - if (entry != NULL) mpc->in_ops->put(entry); + if (entry != NULL) + mpc->in_ops->put(entry); return 1; } - if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */ - ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name); + /* threshold not exceeded or VCC not ready */ + if (mpc->in_ops->cache_hit(entry, mpc) != OPEN) { + ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", + mpc->dev->name); mpc->in_ops->put(entry); return 1; } - ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name); + ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", + mpc->dev->name); /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */ if (iph->ttl <= 1) { - ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl); + ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", + mpc->dev->name, iph->ttl); mpc->in_ops->put(entry); return 1; } @@ -506,15 +530,18 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); if (entry->ctrl_info.tag != 0) { - ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag); + ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", + mpc->dev->name, entry->ctrl_info.tag); tagged_llc_snap_hdr.tag = entry->ctrl_info.tag; - skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ - skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */ + skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ + skb_push(skb, sizeof(tagged_llc_snap_hdr)); + /* add LLC/SNAP header */ skb_copy_to_linear_data(skb, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr)); } else { - skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ - skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */ + skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ + skb_push(skb, sizeof(struct llc_snap_hdr)); + /* add LLC/SNAP header + tag */ skb_copy_to_linear_data(skb, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)); } @@ -539,8 +566,8 @@ static netdev_tx_t mpc_send_packet(struct sk_buff *skb, int i = 0; mpc = find_mpc_by_lec(dev); /* this should NEVER fail */ - if(mpc == NULL) { - printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name); + if (mpc == NULL) { + pr_info("(%s) no MPC found\n", dev->name); goto non_ip; } @@ -556,14 +583,15 @@ static netdev_tx_t mpc_send_packet(struct sk_buff *skb, goto non_ip; while (i < mpc->number_of_mps_macs) { - if (!compare_ether_addr(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN))) - if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */ - return NETDEV_TX_OK; /* success! */ + if (!compare_ether_addr(eth->h_dest, + (mpc->mps_macs + i*ETH_ALEN))) + if (send_via_shortcut(skb, mpc) == 0) /* try shortcut */ + return NETDEV_TX_OK; i++; } - non_ip: - return mpc->old_ops->ndo_start_xmit(skb,dev); +non_ip: + return mpc->old_ops->ndo_start_xmit(skb, dev); } static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) @@ -576,7 +604,8 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc)); if (bytes_left != 0) { - printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left); + pr_info("mpoa:Short read (missed %d bytes) from userland\n", + bytes_left); return -EFAULT; } ipaddr = ioc_data.ipaddr; @@ -589,18 +618,20 @@ static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) if (ioc_data.type == MPC_SOCKET_INGRESS) { in_entry = mpc->in_ops->get(ipaddr, mpc); - if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) { - printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n", + if (in_entry == NULL || + in_entry->entry_state < INGRESS_RESOLVED) { + pr_info("(%s) did not find RESOLVED entry from ingress cache\n", mpc->dev->name); - if (in_entry != NULL) mpc->in_ops->put(in_entry); + if (in_entry != NULL) + mpc->in_ops->put(in_entry); return -EINVAL; } - printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %pI4\n", - mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); + pr_info("(%s) attaching ingress SVC, entry = %pI4\n", + mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); in_entry->shortcut = vcc; mpc->in_ops->put(in_entry); } else { - printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name); + pr_info("(%s) attaching egress SVC\n", mpc->dev->name); } vcc->proto_data = mpc->dev; @@ -620,7 +651,7 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev) mpc = find_mpc_by_lec(dev); if (mpc == NULL) { - printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name); + pr_info("(%s) close for unknown MPC\n", dev->name); return; } @@ -628,19 +659,21 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev) in_entry = mpc->in_ops->get_by_vcc(vcc, mpc); if (in_entry) { dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %pI4\n", - mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); + mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); in_entry->shortcut = NULL; mpc->in_ops->put(in_entry); } eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc); if (eg_entry) { - dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name); + dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", + mpc->dev->name); eg_entry->shortcut = NULL; mpc->eg_ops->put(eg_entry); } if (in_entry == NULL && eg_entry == NULL) - dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name); + dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", + dev->name); return; } @@ -656,16 +689,19 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) ddprintk("mpoa: (%s) mpc_push:\n", dev->name); if (skb == NULL) { - dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name); + dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", + dev->name); mpc_vcc_close(vcc, dev); return; } skb->dev = dev; - if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) { + if (memcmp(skb->data, &llc_snap_mpoa_ctrl, + sizeof(struct llc_snap_hdr)) == 0) { struct sock *sk = sk_atm(vcc); - dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name); + dprintk("mpoa: (%s) mpc_push: control packet arrived\n", + dev->name); /* Pass control packets to daemon */ skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); @@ -677,20 +713,23 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) mpc = find_mpc_by_lec(dev); if (mpc == NULL) { - printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name); + pr_info("(%s) unknown MPC\n", dev->name); return; } - if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */ - ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name); + if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, + sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */ + ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", + dev->name); - } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */ - printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name); - printk(" mpc_push: non-tagged data unsupported, purging\n"); + } else if (memcmp(skb->data, &llc_snap_mpoa_data, + sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */ + pr_info("(%s) Unsupported non-tagged data packet arrived. Purging\n", + dev->name); dev_kfree_skb_any(skb); return; } else { - printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name); + pr_info("(%s) garbage arrived, purging\n", dev->name); dev_kfree_skb_any(skb); return; } @@ -700,8 +739,8 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) eg = mpc->eg_ops->get_by_tag(tag, mpc); if (eg == NULL) { - printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n", - dev->name,tag); + pr_info("mpoa: (%s) Didn't find egress cache entry, tag = %u\n", + dev->name, tag); purge_egress_shortcut(vcc, NULL); dev_kfree_skb_any(skb); return; @@ -713,13 +752,15 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) */ if (eg->shortcut == NULL) { eg->shortcut = vcc; - printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name); + pr_info("(%s) egress SVC in use\n", dev->name); } - skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */ - new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */ + skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); + /* get rid of LLC/SNAP header */ + new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); + /* LLC/SNAP is shorter than MAC header :( */ dev_kfree_skb_any(skb); - if (new_skb == NULL){ + if (new_skb == NULL) { mpc->eg_ops->put(eg); return; } @@ -752,7 +793,7 @@ static struct atm_dev mpc_dev = { /* members not explicitly initialised will be 0 */ }; -static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) +static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg) { struct mpoa_client *mpc; struct lec_priv *priv; @@ -772,15 +813,17 @@ static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) mpc = find_mpc_by_itfnum(arg); if (mpc == NULL) { - dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg); + dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", + arg); mpc = alloc_mpc(); if (mpc == NULL) return -ENOMEM; mpc->dev_num = arg; - mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */ + mpc->dev = find_lec_by_itfnum(arg); + /* NULL if there was no lec */ } if (mpc->mpoad_vcc) { - printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg); + pr_info("mpoad is already present for itf %d\n", arg); return -EADDRINUSE; } @@ -796,8 +839,8 @@ static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) mpc->mpoad_vcc = vcc; vcc->dev = &mpc_dev; vcc_insert_socket(sk_atm(vcc)); - set_bit(ATM_VF_META,&vcc->flags); - set_bit(ATM_VF_READY,&vcc->flags); + set_bit(ATM_VF_META, &vcc->flags); + set_bit(ATM_VF_READY, &vcc->flags); if (mpc->dev) { char empty[ATM_ESA_LEN]; @@ -807,7 +850,7 @@ static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) /* set address if mpcd e.g. gets killed and restarted. * If we do not do it now we have to wait for the next LE_ARP */ - if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 ) + if (memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0) send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); } @@ -819,7 +862,7 @@ static void send_set_mps_ctrl_addr(const char *addr, struct mpoa_client *mpc) { struct k_message mesg; - memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN); + memcpy(mpc->mps_ctrl_addr, addr, ATM_ESA_LEN); mesg.type = SET_MPS_CTRL_ADDR; memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN); @@ -835,11 +878,11 @@ static void mpoad_close(struct atm_vcc *vcc) mpc = find_mpc_by_vcc(vcc); if (mpc == NULL) { - printk("mpoa: mpoad_close: did not find MPC\n"); + pr_info("did not find MPC\n"); return; } if (!mpc->mpoad_vcc) { - printk("mpoa: mpoad_close: close for non-present mpoad\n"); + pr_info("close for non-present mpoad\n"); return; } @@ -859,7 +902,7 @@ static void mpoad_close(struct atm_vcc *vcc) kfree_skb(skb); } - printk("mpoa: (%s) going down\n", + pr_info("(%s) going down\n", (mpc->dev) ? mpc->dev->name : ""); module_put(THIS_MODULE); @@ -873,15 +916,16 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb) { struct mpoa_client *mpc = find_mpc_by_vcc(vcc); - struct k_message *mesg = (struct k_message*)skb->data; + struct k_message *mesg = (struct k_message *)skb->data; atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); if (mpc == NULL) { - printk("mpoa: msg_from_mpoad: no mpc found\n"); + pr_info("no mpc found\n"); return 0; } - dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : ""); - switch(mesg->type) { + dprintk("mpoa: (%s) msg_from_mpoad:", + (mpc->dev) ? mpc->dev->name : ""); + switch (mesg->type) { case MPOA_RES_REPLY_RCVD: dprintk(" mpoa_res_reply_rcvd\n"); MPOA_res_reply_rcvd(mesg, mpc); @@ -942,7 +986,7 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc) struct sock *sk; if (mpc == NULL || !mpc->mpoad_vcc) { - printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type); + pr_info("mesg %d to a non-existent mpoad\n", mesg->type); return -ENXIO; } @@ -960,7 +1004,8 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc) return 0; } -static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr) +static int mpoa_event_listener(struct notifier_block *mpoa_notifier, + unsigned long event, void *dev_ptr) { struct net_device *dev; struct mpoa_client *mpc; @@ -983,10 +1028,10 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo mpc = find_mpc_by_itfnum(priv->itfnum); if (mpc == NULL) { dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n", - dev->name); + dev->name); mpc = alloc_mpc(); if (mpc == NULL) { - printk("mpoa: mpoa_event_listener: no new mpc"); + pr_info("no new mpc"); break; } } @@ -1010,9 +1055,8 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; - if (mpc->mpoad_vcc != NULL) { + if (mpc->mpoad_vcc != NULL) start_mpc(mpc, dev); - } break; case NETDEV_DOWN: /* the dev was ifconfig'ed down */ @@ -1022,9 +1066,8 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; - if (mpc->mpoad_vcc != NULL) { + if (mpc->mpoad_vcc != NULL) stop_mpc(mpc); - } break; case NETDEV_REBOOT: case NETDEV_CHANGE: @@ -1051,7 +1094,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) in_cache_entry *entry; entry = mpc->in_ops->get(dst_ip, mpc); - if(entry == NULL){ + if (entry == NULL) { entry = mpc->in_ops->add_entry(dst_ip, mpc); entry->entry_state = INGRESS_RESOLVING; msg->type = SND_MPOA_RES_RQST; @@ -1062,7 +1105,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) return; } - if(entry->entry_state == INGRESS_INVALID){ + if (entry->entry_state == INGRESS_INVALID) { entry->entry_state = INGRESS_RESOLVING; msg->type = SND_MPOA_RES_RQST; msg->content.in_info = entry->ctrl_info; @@ -1072,7 +1115,7 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) return; } - printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n", + pr_info("(%s) entry already in resolving state\n", (mpc->dev) ? mpc->dev->name : ""); mpc->in_ops->put(entry); return; @@ -1082,22 +1125,24 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) * Things get complicated because we have to check if there's an egress * shortcut with suitable traffic parameters we could use. */ -static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry) +static void check_qos_and_open_shortcut(struct k_message *msg, + struct mpoa_client *client, + in_cache_entry *entry) { __be32 dst_ip = msg->content.in_info.in_dst_ip; struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client); - if(eg_entry && eg_entry->shortcut){ - if(eg_entry->shortcut->qos.txtp.traffic_class & - msg->qos.txtp.traffic_class & - (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){ - if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR) - entry->shortcut = eg_entry->shortcut; - else if(eg_entry->shortcut->qos.txtp.max_pcr > 0) - entry->shortcut = eg_entry->shortcut; + if (eg_entry && eg_entry->shortcut) { + if (eg_entry->shortcut->qos.txtp.traffic_class & + msg->qos.txtp.traffic_class & + (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)) { + if (eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR) + entry->shortcut = eg_entry->shortcut; + else if (eg_entry->shortcut->qos.txtp.max_pcr > 0) + entry->shortcut = eg_entry->shortcut; } - if(entry->shortcut){ + if (entry->shortcut) { dprintk("mpoa: (%s) using egress SVC to reach %pI4\n", client->dev->name, &dst_ip); client->eg_ops->put(eg_entry); @@ -1109,12 +1154,13 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien /* No luck in the egress cache we must open an ingress SVC */ msg->type = OPEN_INGRESS_SVC; - if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) - { + if (qos && + (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) { msg->qos = qos->qos; - printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name); - } - else memset(&msg->qos,0,sizeof(struct atm_qos)); + pr_info("(%s) trying to get a CBR shortcut\n", + client->dev->name); + } else + memset(&msg->qos, 0, sizeof(struct atm_qos)); msg_to_mpoad(msg, client); return; } @@ -1126,15 +1172,17 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %pI4\n", mpc->dev->name, &dst_ip); - ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry); - if(entry == NULL){ - printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name); + ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", + mpc->dev->name, entry); + if (entry == NULL) { + pr_info("(%s) ARGH, received res. reply for an entry that doesn't exist.\n", + mpc->dev->name); return; } ddprintk(" entry_state = %d ", entry->entry_state); if (entry->entry_state == INGRESS_RESOLVED) { - printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name); + pr_info("(%s) RESOLVED entry!\n", mpc->dev->name); mpc->in_ops->put(entry); return; } @@ -1145,15 +1193,16 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) entry->refresh_time = 0; ddprintk("entry->shortcut = %p\n", entry->shortcut); - if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){ + if (entry->entry_state == INGRESS_RESOLVING && + entry->shortcut != NULL) { entry->entry_state = INGRESS_RESOLVED; mpc->in_ops->put(entry); return; /* Shortcut already open... */ } if (entry->shortcut != NULL) { - printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n", - mpc->dev->name); + pr_info("(%s) entry->shortcut != NULL, impossible!\n", + mpc->dev->name); mpc->in_ops->put(entry); return; } @@ -1172,9 +1221,9 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) __be32 mask = msg->ip_mask; in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); - if(entry == NULL){ - printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ip = %pI4\n", - mpc->dev->name, &dst_ip); + if (entry == NULL) { + pr_info("(%s) purge for a non-existing entry, ip = %pI4\n", + mpc->dev->name, &dst_ip); return; } @@ -1197,7 +1246,8 @@ static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc); if (entry == NULL) { - dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name); + dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", + mpc->dev->name); return; } @@ -1218,13 +1268,13 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) dprintk("mpoa: purge_egress_shortcut: entering\n"); if (vcc == NULL) { - printk("mpoa: purge_egress_shortcut: vcc == NULL\n"); + pr_info("vcc == NULL\n"); return; } skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); if (skb == NULL) { - printk("mpoa: purge_egress_shortcut: out of memory\n"); + pr_info("out of memory\n"); return; } @@ -1249,14 +1299,14 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) * Our MPS died. Tell our daemon to send NHRP data plane purge to each * of the egress shortcuts we have. */ -static void mps_death( struct k_message * msg, struct mpoa_client * mpc ) +static void mps_death(struct k_message *msg, struct mpoa_client *mpc) { eg_cache_entry *entry; dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name); - if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){ - printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name); + if (memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)) { + pr_info("(%s) wrong MPS\n", mpc->dev->name); return; } @@ -1275,20 +1325,21 @@ static void mps_death( struct k_message * msg, struct mpoa_client * mpc ) return; } -static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc) +static void MPOA_cache_impos_rcvd(struct k_message *msg, + struct mpoa_client *mpc) { uint16_t holding_time; eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc); holding_time = msg->content.eg_info.holding_time; dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n", - mpc->dev->name, entry, holding_time); - if(entry == NULL && holding_time) { + mpc->dev->name, entry, holding_time); + if (entry == NULL && holding_time) { entry = mpc->eg_ops->add_entry(msg, mpc); mpc->eg_ops->put(entry); return; } - if(holding_time){ + if (holding_time) { mpc->eg_ops->update(entry, holding_time); return; } @@ -1302,7 +1353,8 @@ static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * return; } -static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc) +static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, + struct mpoa_client *mpc) { struct lec_priv *priv; int i, retval ; @@ -1318,33 +1370,38 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *m memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN); dprintk("mpoa: (%s) setting MPC ctrl ATM address to ", - (mpc->dev) ? mpc->dev->name : ""); + (mpc->dev) ? mpc->dev->name : ""); for (i = 7; i < sizeof(tlv); i++) dprintk("%02x ", tlv[i]); dprintk("\n"); if (mpc->dev) { priv = netdev_priv(mpc->dev); - retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv)); + retval = priv->lane2_ops->associate_req(mpc->dev, + mpc->dev->dev_addr, + tlv, sizeof(tlv)); if (retval == 0) - printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name); + pr_info("(%s) MPOA device type TLV association failed\n", + mpc->dev->name); retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL); if (retval < 0) - printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name); + pr_info("(%s) targetless LE_ARP request failed\n", + mpc->dev->name); } return; } -static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client) +static void set_mps_mac_addr_rcvd(struct k_message *msg, + struct mpoa_client *client) { - if(client->number_of_mps_macs) + if (client->number_of_mps_macs) kfree(client->mps_macs); client->number_of_mps_macs = 0; client->mps_macs = kmemdup(msg->MPS_ctrl, ETH_ALEN, GFP_KERNEL); if (client->mps_macs == NULL) { - printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n"); + pr_info("out of memory\n"); return; } client->number_of_mps_macs = 1; @@ -1365,11 +1422,11 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action) /* FIXME: This knows too much of the cache structure */ read_lock_irq(&mpc->egress_lock); entry = mpc->eg_cache; - while (entry != NULL){ - msg->content.eg_info = entry->ctrl_info; - dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id); - msg_to_mpoad(msg, mpc); - entry = entry->next; + while (entry != NULL) { + msg->content.eg_info = entry->ctrl_info; + dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id); + msg_to_mpoad(msg, mpc); + entry = entry->next; } read_unlock_irq(&mpc->egress_lock); @@ -1388,20 +1445,22 @@ static void mpc_timer_refresh(void) return; } -static void mpc_cache_check( unsigned long checking_time ) +static void mpc_cache_check(unsigned long checking_time) { struct mpoa_client *mpc = mpcs; static unsigned long previous_resolving_check_time; static unsigned long previous_refresh_time; - while( mpc != NULL ){ + while (mpc != NULL) { mpc->in_ops->clear_count(mpc); mpc->eg_ops->clear_expired(mpc); - if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){ + if (checking_time - previous_resolving_check_time > + mpc->parameters.mpc_p4 * HZ) { mpc->in_ops->check_resolving(mpc); previous_resolving_check_time = checking_time; } - if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){ + if (checking_time - previous_refresh_time > + mpc->parameters.mpc_p5 * HZ) { mpc->in_ops->refresh(mpc); previous_refresh_time = checking_time; } @@ -1412,7 +1471,8 @@ static void mpc_cache_check( unsigned long checking_time ) return; } -static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) { int err = 0; struct atm_vcc *vcc = ATM_SD(sock); @@ -1424,21 +1484,20 @@ static int atm_mpoa_ioctl(struct socket *sock, unsigned int cmd, unsigned long a return -EPERM; switch (cmd) { - case ATMMPC_CTRL: - err = atm_mpoa_mpoad_attach(vcc, (int)arg); - if (err >= 0) - sock->state = SS_CONNECTED; - break; - case ATMMPC_DATA: - err = atm_mpoa_vcc_attach(vcc, (void __user *)arg); - break; - default: - break; + case ATMMPC_CTRL: + err = atm_mpoa_mpoad_attach(vcc, (int)arg); + if (err >= 0) + sock->state = SS_CONNECTED; + break; + case ATMMPC_DATA: + err = atm_mpoa_vcc_attach(vcc, (void __user *)arg); + break; + default: + break; } return err; } - static struct atm_ioctl atm_ioctl_ops = { .owner = THIS_MODULE, .ioctl = atm_mpoa_ioctl, @@ -1451,7 +1510,7 @@ static __init int atm_mpoa_init(void) if (mpc_proc_init() != 0) pr_info("failed to initialize /proc/mpoa\n"); - printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); + pr_info("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); return 0; } -- cgit v1.2.3 From bee67d34b2dd495feafb1a37b5ea2d6179b74178 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:10 +0000 Subject: net/atm/mpoa_caches.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/mpoa_caches.c | 160 +++++++++++++++++++++++++++----------------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index 4504a4b339bb..de21cc66feb4 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -11,15 +11,17 @@ */ #if 0 -#define dprintk printk /* debug */ +#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ #else -#define dprintk(format,args...) +#define dprintk(format, args...) \ + do { if (0) printk(KERN_DEBUG format, ##args); } while (0) #endif #if 0 -#define ddprintk printk /* more debug */ +#define ddprintk printk(KERN_DEBUG format, ##args) /* more debug */ #else -#define ddprintk(format,args...) +#define ddprintk(format, args...) \ + do { if (0) printk(KERN_DEBUG format, ##args); } while (0) #endif static in_cache_entry *in_cache_get(__be32 dst_ip, @@ -29,8 +31,8 @@ static in_cache_entry *in_cache_get(__be32 dst_ip, read_lock_bh(&client->ingress_lock); entry = client->in_cache; - while(entry != NULL){ - if( entry->ctrl_info.in_dst_ip == dst_ip ){ + while (entry != NULL) { + if (entry->ctrl_info.in_dst_ip == dst_ip) { atomic_inc(&entry->use); read_unlock_bh(&client->ingress_lock); return entry; @@ -50,8 +52,8 @@ static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip, read_lock_bh(&client->ingress_lock); entry = client->in_cache; - while(entry != NULL){ - if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){ + while (entry != NULL) { + if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) { atomic_inc(&entry->use); read_unlock_bh(&client->ingress_lock); return entry; @@ -65,14 +67,14 @@ static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip, } static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc, - struct mpoa_client *client ) + struct mpoa_client *client) { in_cache_entry *entry; read_lock_bh(&client->ingress_lock); entry = client->in_cache; - while(entry != NULL){ - if(entry->shortcut == vcc) { + while (entry != NULL) { + if (entry->shortcut == vcc) { atomic_inc(&entry->use); read_unlock_bh(&client->ingress_lock); return entry; @@ -90,11 +92,12 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip, in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL); if (entry == NULL) { - printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n"); + pr_info("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n"); return NULL; } - dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %pI4\n", &dst_ip); + dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %pI4\n", + &dst_ip); atomic_set(&entry->use, 1); dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n"); @@ -126,39 +129,41 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc) struct k_message msg; entry->count++; - if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL) + if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL) return OPEN; - if(entry->entry_state == INGRESS_REFRESHING){ - if(entry->count > mpc->parameters.mpc_p1){ + if (entry->entry_state == INGRESS_REFRESHING) { + if (entry->count > mpc->parameters.mpc_p1) { msg.type = SND_MPOA_RES_RQST; msg.content.in_info = entry->ctrl_info; memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN); qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; + if (qos != NULL) + msg.qos = qos->qos; msg_to_mpoad(&msg, mpc); do_gettimeofday(&(entry->reply_wait)); entry->entry_state = INGRESS_RESOLVING; } - if(entry->shortcut != NULL) + if (entry->shortcut != NULL) return OPEN; return CLOSED; } - if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) + if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) return OPEN; - if( entry->count > mpc->parameters.mpc_p1 && - entry->entry_state == INGRESS_INVALID){ + if (entry->count > mpc->parameters.mpc_p1 && + entry->entry_state == INGRESS_INVALID) { dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %pI4, sending MPOA res req\n", mpc->dev->name, &entry->ctrl_info.in_dst_ip); entry->entry_state = INGRESS_RESOLVING; - msg.type = SND_MPOA_RES_RQST; - memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN ); + msg.type = SND_MPOA_RES_RQST; + memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN); msg.content.in_info = entry->ctrl_info; qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; - msg_to_mpoad( &msg, mpc); + if (qos != NULL) + msg.qos = qos->qos; + msg_to_mpoad(&msg, mpc); do_gettimeofday(&(entry->reply_wait)); } @@ -195,14 +200,15 @@ static void in_cache_remove_entry(in_cache_entry *entry, if (entry->next != NULL) entry->next->prev = entry->prev; client->in_ops->put(entry); - if(client->in_cache == NULL && client->eg_cache == NULL){ + if (client->in_cache == NULL && client->eg_cache == NULL) { msg.type = STOP_KEEP_ALIVE_SM; - msg_to_mpoad(&msg,client); + msg_to_mpoad(&msg, client); } /* Check if the egress side still uses this VCC */ if (vcc != NULL) { - eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client); + eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, + client); if (eg_entry != NULL) { client->eg_ops->put(eg_entry); return; @@ -213,7 +219,6 @@ static void in_cache_remove_entry(in_cache_entry *entry, return; } - /* Call this every MPC-p2 seconds... Not exactly correct solution, but an easy one... */ static void clear_count_and_expired(struct mpoa_client *client) @@ -225,11 +230,11 @@ static void clear_count_and_expired(struct mpoa_client *client) write_lock_bh(&client->ingress_lock); entry = client->in_cache; - while(entry != NULL){ - entry->count=0; + while (entry != NULL) { + entry->count = 0; next_entry = entry->next; - if((now.tv_sec - entry->tv.tv_sec) - > entry->ctrl_info.holding_time){ + if ((now.tv_sec - entry->tv.tv_sec) + > entry->ctrl_info.holding_time) { dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %pI4\n", &entry->ctrl_info.in_dst_ip); client->in_ops->remove_entry(entry, client); @@ -250,33 +255,38 @@ static void check_resolving_entries(struct mpoa_client *client) struct timeval now; struct k_message msg; - do_gettimeofday( &now ); + do_gettimeofday(&now); read_lock_bh(&client->ingress_lock); entry = client->in_cache; - while( entry != NULL ){ - if(entry->entry_state == INGRESS_RESOLVING){ - if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){ - entry = entry->next; /* Entry in hold down */ + while (entry != NULL) { + if (entry->entry_state == INGRESS_RESOLVING) { + if ((now.tv_sec - entry->hold_down.tv_sec) < + client->parameters.mpc_p6) { + entry = entry->next; /* Entry in hold down */ continue; } - if( (now.tv_sec - entry->reply_wait.tv_sec) > - entry->retry_time ){ - entry->retry_time = MPC_C1*( entry->retry_time ); - if(entry->retry_time > client->parameters.mpc_p5){ - /* Retry time maximum exceeded, put entry in hold down. */ + if ((now.tv_sec - entry->reply_wait.tv_sec) > + entry->retry_time) { + entry->retry_time = MPC_C1 * (entry->retry_time); + /* + * Retry time maximum exceeded, + * put entry in hold down. + */ + if (entry->retry_time > client->parameters.mpc_p5) { do_gettimeofday(&(entry->hold_down)); entry->retry_time = client->parameters.mpc_p4; entry = entry->next; continue; } /* Ask daemon to send a resolution request. */ - memset(&(entry->hold_down),0,sizeof(struct timeval)); + memset(&(entry->hold_down), 0, sizeof(struct timeval)); msg.type = SND_MPOA_RES_RTRY; memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN); msg.content.in_info = entry->ctrl_info; qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; + if (qos != NULL) + msg.qos = qos->qos; msg_to_mpoad(&msg, client); do_gettimeofday(&(entry->reply_wait)); } @@ -296,11 +306,12 @@ static void refresh_entries(struct mpoa_client *client) do_gettimeofday(&now); read_lock_bh(&client->ingress_lock); - while( entry != NULL ){ - if( entry->entry_state == INGRESS_RESOLVED ){ - if(!(entry->refresh_time)) - entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3; - if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){ + while (entry != NULL) { + if (entry->entry_state == INGRESS_RESOLVED) { + if (!(entry->refresh_time)) + entry->refresh_time = (2 * (entry->ctrl_info.holding_time))/3; + if ((now.tv_sec - entry->reply_wait.tv_sec) > + entry->refresh_time) { dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n"); entry->entry_state = INGRESS_REFRESHING; @@ -314,21 +325,22 @@ static void refresh_entries(struct mpoa_client *client) static void in_destroy_cache(struct mpoa_client *mpc) { write_lock_irq(&mpc->ingress_lock); - while(mpc->in_cache != NULL) + while (mpc->in_cache != NULL) mpc->in_ops->remove_entry(mpc->in_cache, mpc); write_unlock_irq(&mpc->ingress_lock); return; } -static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id, + struct mpoa_client *mpc) { eg_cache_entry *entry; read_lock_irq(&mpc->egress_lock); entry = mpc->eg_cache; - while(entry != NULL){ - if(entry->ctrl_info.cache_id == cache_id){ + while (entry != NULL) { + if (entry->ctrl_info.cache_id == cache_id) { atomic_inc(&entry->use); read_unlock_irq(&mpc->egress_lock); return entry; @@ -348,7 +360,7 @@ static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc) read_lock_irqsave(&mpc->egress_lock, flags); entry = mpc->eg_cache; - while (entry != NULL){ + while (entry != NULL) { if (entry->ctrl_info.tag == tag) { atomic_inc(&entry->use); read_unlock_irqrestore(&mpc->egress_lock, flags); @@ -362,14 +374,15 @@ static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc) } /* This can be called from any context since it saves CPU flags */ -static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, + struct mpoa_client *mpc) { unsigned long flags; eg_cache_entry *entry; read_lock_irqsave(&mpc->egress_lock, flags); entry = mpc->eg_cache; - while (entry != NULL){ + while (entry != NULL) { if (entry->shortcut == vcc) { atomic_inc(&entry->use); read_unlock_irqrestore(&mpc->egress_lock, flags); @@ -382,14 +395,15 @@ static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_clie return NULL; } -static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr, + struct mpoa_client *mpc) { eg_cache_entry *entry; read_lock_irq(&mpc->egress_lock); entry = mpc->eg_cache; - while(entry != NULL){ - if(entry->latest_ip_addr == ipaddr) { + while (entry != NULL) { + if (entry->latest_ip_addr == ipaddr) { atomic_inc(&entry->use); read_unlock_irq(&mpc->egress_lock); return entry; @@ -429,9 +443,9 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, if (entry->next != NULL) entry->next->prev = entry->prev; client->eg_ops->put(entry); - if(client->in_cache == NULL && client->eg_cache == NULL){ + if (client->in_cache == NULL && client->eg_cache == NULL) { msg.type = STOP_KEEP_ALIVE_SM; - msg_to_mpoad(&msg,client); + msg_to_mpoad(&msg, client); } /* Check if the ingress side still uses this VCC */ @@ -447,12 +461,13 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, return; } -static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client) +static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, + struct mpoa_client *client) { eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL); if (entry == NULL) { - printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n"); + pr_info("out of memory\n"); return NULL; } @@ -472,7 +487,8 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli entry->ctrl_info = msg->content.eg_info; do_gettimeofday(&(entry->tv)); entry->entry_state = EGRESS_RESOLVED; - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id)); + dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %u\n", + ntohl(entry->ctrl_info.cache_id)); dprintk("mpoa: mpoa_caches.c: mps_ip = %pI4\n", &entry->ctrl_info.mps_ip); atomic_inc(&entry->use); @@ -483,7 +499,7 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_cli return entry; } -static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time) +static void update_eg_cache_entry(eg_cache_entry *entry, uint16_t holding_time) { do_gettimeofday(&(entry->tv)); entry->entry_state = EGRESS_RESOLVED; @@ -502,13 +518,14 @@ static void clear_expired(struct mpoa_client *client) write_lock_irq(&client->egress_lock); entry = client->eg_cache; - while(entry != NULL){ + while (entry != NULL) { next_entry = entry->next; - if((now.tv_sec - entry->tv.tv_sec) - > entry->ctrl_info.holding_time){ + if ((now.tv_sec - entry->tv.tv_sec) + > entry->ctrl_info.holding_time) { msg.type = SND_EGRESS_PURGE; msg.content.eg_info = entry->ctrl_info; - dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id)); + dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %u.\n", + ntohl(entry->ctrl_info.cache_id)); msg_to_mpoad(&msg, client); client->eg_ops->remove_entry(entry, client); } @@ -522,7 +539,7 @@ static void clear_expired(struct mpoa_client *client) static void eg_destroy_cache(struct mpoa_client *mpc) { write_lock_irq(&mpc->egress_lock); - while(mpc->eg_cache != NULL) + while (mpc->eg_cache != NULL) mpc->eg_ops->remove_entry(mpc->eg_cache, mpc); write_unlock_irq(&mpc->egress_lock); @@ -530,7 +547,6 @@ static void eg_destroy_cache(struct mpoa_client *mpc) } - static struct in_cache_ops ingress_ops = { in_cache_add_entry, /* add_entry */ in_cache_get, /* get */ -- cgit v1.2.3 From f1e100491e0e696b19f37f2b0cf728a5f2bc56e7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:11 +0000 Subject: net/atm/mpoa_proc.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/mpoa_proc.c | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index 0603ab478cf5..aae4a87c22ac 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include "mpc.h" @@ -21,9 +21,10 @@ */ #if 1 -#define dprintk printk /* debug */ +#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ #else -#define dprintk(format,args...) +#define dprintk(format, args...) \ + do { if (0) printk(KERN_DEBUG format, ##args); } while (0) #endif #define STAT_FILE_NAME "mpc" /* Our statistic file's name */ @@ -52,42 +53,37 @@ static const struct file_operations mpc_file_operations = { /* * Returns the state of an ingress cache entry as a string */ -static const char *ingress_state_string(int state){ - switch(state) { +static const char *ingress_state_string(int state) +{ + switch (state) { case INGRESS_RESOLVING: return "resolving "; - break; case INGRESS_RESOLVED: return "resolved "; - break; case INGRESS_INVALID: return "invalid "; - break; case INGRESS_REFRESHING: return "refreshing "; - break; - default: - return ""; } + + return ""; } /* * Returns the state of an egress cache entry as a string */ -static const char *egress_state_string(int state){ - switch(state) { +static const char *egress_state_string(int state) +{ + switch (state) { case EGRESS_RESOLVED: return "resolved "; - break; case EGRESS_PURGE: return "purge "; - break; case EGRESS_INVALID: return "invalid "; - break; - default: - return ""; } + + return ""; } /* @@ -124,7 +120,6 @@ static void mpc_stop(struct seq_file *m, void *v) static int mpc_show(struct seq_file *m, void *v) { struct mpoa_client *mpc = v; - unsigned char *temp; int i; in_cache_entry *in_entry; eg_cache_entry *eg_entry; @@ -141,15 +136,17 @@ static int mpc_show(struct seq_file *m, void *v) do_gettimeofday(&now); for (in_entry = mpc->in_cache; in_entry; in_entry = in_entry->next) { - temp = (unsigned char *)&in_entry->ctrl_info.in_dst_ip; - sprintf(ip_string,"%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); + sprintf(ip_string, "%pI4", &in_entry->ctrl_info.in_dst_ip); seq_printf(m, "%-16s%s%-14lu%-12u", - ip_string, - ingress_state_string(in_entry->entry_state), - in_entry->ctrl_info.holding_time-(now.tv_sec-in_entry->tv.tv_sec), - in_entry->packets_fwded); + ip_string, + ingress_state_string(in_entry->entry_state), + in_entry->ctrl_info.holding_time - + (now.tv_sec-in_entry->tv.tv_sec), + in_entry->packets_fwded); if (in_entry->shortcut) - seq_printf(m, " %-3d %-3d",in_entry->shortcut->vpi,in_entry->shortcut->vci); + seq_printf(m, " %-3d %-3d", + in_entry->shortcut->vpi, + in_entry->shortcut->vci); seq_printf(m, "\n"); } @@ -157,21 +154,23 @@ static int mpc_show(struct seq_file *m, void *v) seq_printf(m, "Egress Entries:\nIngress MPC ATM addr\nCache-id State Holding time Packets recvd Latest IP addr VPI VCI\n"); for (eg_entry = mpc->eg_cache; eg_entry; eg_entry = eg_entry->next) { unsigned char *p = eg_entry->ctrl_info.in_MPC_data_ATM_addr; - for(i = 0; i < ATM_ESA_LEN; i++) + for (i = 0; i < ATM_ESA_LEN; i++) seq_printf(m, "%02x", p[i]); seq_printf(m, "\n%-16lu%s%-14lu%-15u", (unsigned long)ntohl(eg_entry->ctrl_info.cache_id), egress_state_string(eg_entry->entry_state), - (eg_entry->ctrl_info.holding_time-(now.tv_sec-eg_entry->tv.tv_sec)), + (eg_entry->ctrl_info.holding_time - + (now.tv_sec-eg_entry->tv.tv_sec)), eg_entry->packets_rcvd); /* latest IP address */ - temp = (unsigned char *)&eg_entry->latest_ip_addr; - sprintf(ip_string, "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]); + sprintf(ip_string, "%pI4", &eg_entry->latest_ip_addr); seq_printf(m, "%-16s", ip_string); if (eg_entry->shortcut) - seq_printf(m, " %-3d %-3d",eg_entry->shortcut->vpi,eg_entry->shortcut->vci); + seq_printf(m, " %-3d %-3d", + eg_entry->shortcut->vpi, + eg_entry->shortcut->vci); seq_printf(m, "\n"); } seq_printf(m, "\n"); @@ -290,10 +289,9 @@ int mpc_proc_init(void) */ void mpc_proc_clean(void) { - remove_proc_entry(STAT_FILE_NAME,atm_proc_root); + remove_proc_entry(STAT_FILE_NAME, atm_proc_root); } - #endif /* CONFIG_PROC_FS */ -- cgit v1.2.3 From d81219db6add0a176c37d6fe4e1c050778de9d2f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:12 +0000 Subject: net/atm/pppoatm.c: checkpatch cleanups Move embedded assigns out of tests Move trailing statements to new lines Move labels to column 1 Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/pppoatm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index 62db6d71dbab..400839273c67 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -176,7 +176,8 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb) } ppp_input(&pvcc->chan, skb); return; - error: + +error: kfree_skb(skb); ppp_input_error(&pvcc->chan, 0); } @@ -209,7 +210,8 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) goto nospace; } kfree_skb(skb); - if ((skb = n) == NULL) + skb = n; + if (skb == NULL) return DROP_PACKET; } else if (!atm_may_send(pvcc->atmvcc, skb->truesize)) goto nospace; @@ -231,7 +233,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev); return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb) ? DROP_PACKET : 1; - nospace: +nospace: /* * We don't have space to send this SKB now, but we might have * already applied SC_COMP_PROT compression, so may need to undo @@ -290,7 +292,8 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg) (be.encaps == e_vc ? 0 : LLC_LEN); pvcc->wakeup_tasklet = tasklet_proto; pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan; - if ((err = ppp_register_channel(&pvcc->chan)) != 0) { + err = ppp_register_channel(&pvcc->chan); + if (err != 0) { kfree(pvcc); return err; } -- cgit v1.2.3 From 07367adbe5f18b6b7a7476094181ff99cd90cb7e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:13 +0000 Subject: net/atm/proc.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/proc.c | 81 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/net/atm/proc.c b/net/atm/proc.c index ab8419a324b6..476779d845eb 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -24,15 +24,15 @@ #include /* for __init */ #include #include -#include +#include +#include /* for HZ */ #include -#include /* for HZ */ #include "resources.h" #include "common.h" /* atm_proc_init prototype */ #include "signaling.h" /* to get sigd - ugly too */ -static ssize_t proc_dev_atm_read(struct file *file,char __user *buf,size_t count, - loff_t *pos); +static ssize_t proc_dev_atm_read(struct file *file, char __user *buf, + size_t count, loff_t *pos); static const struct file_operations proc_atm_dev_ops = { .owner = THIS_MODULE, @@ -43,9 +43,9 @@ static void add_stats(struct seq_file *seq, const char *aal, const struct k_atm_aal_stats *stats) { seq_printf(seq, "%s ( %d %d %d %d %d )", aal, - atomic_read(&stats->tx),atomic_read(&stats->tx_err), - atomic_read(&stats->rx),atomic_read(&stats->rx_err), - atomic_read(&stats->rx_drop)); + atomic_read(&stats->tx), atomic_read(&stats->tx_err), + atomic_read(&stats->rx), atomic_read(&stats->rx_err), + atomic_read(&stats->rx_drop)); } static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev) @@ -151,8 +151,8 @@ static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) { - static const char *const class_name[] = - {"off","UBR","CBR","VBR","ABR"}; + static const char *const class_name[] = { + "off", "UBR", "CBR", "VBR", "ABR"}; static const char *const aal_name[] = { "---", "1", "2", "3/4", /* 0- 3 */ "???", "5", "???", "???", /* 4- 7 */ @@ -160,11 +160,12 @@ static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc) "???", "0", "???", "???"}; /* 12-15 */ seq_printf(seq, "%3d %3d %5d %-3s %7d %-5s %7d %-6s", - vcc->dev->number,vcc->vpi,vcc->vci, - vcc->qos.aal >= ARRAY_SIZE(aal_name) ? "err" : - aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr, - class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr, - class_name[vcc->qos.txtp.traffic_class]); + vcc->dev->number, vcc->vpi, vcc->vci, + vcc->qos.aal >= ARRAY_SIZE(aal_name) ? "err" : + aal_name[vcc->qos.aal], vcc->qos.rxtp.min_pcr, + class_name[vcc->qos.rxtp.traffic_class], + vcc->qos.txtp.min_pcr, + class_name[vcc->qos.txtp.traffic_class]); if (test_bit(ATM_VF_IS_CLIP, &vcc->flags)) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); struct net_device *dev; @@ -195,19 +196,20 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi, vcc->vci); switch (sk->sk_family) { - case AF_ATMPVC: - seq_printf(seq, "PVC"); - break; - case AF_ATMSVC: - seq_printf(seq, "SVC"); - break; - default: - seq_printf(seq, "%3d", sk->sk_family); + case AF_ATMPVC: + seq_printf(seq, "PVC"); + break; + case AF_ATMSVC: + seq_printf(seq, "SVC"); + break; + default: + seq_printf(seq, "%3d", sk->sk_family); } - seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err, - sk_wmem_alloc_get(sk), sk->sk_sndbuf, - sk_rmem_alloc_get(sk), sk->sk_rcvbuf, - atomic_read(&sk->sk_refcnt)); + seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", + vcc->flags, sk->sk_err, + sk_wmem_alloc_get(sk), sk->sk_sndbuf, + sk_rmem_alloc_get(sk), sk->sk_rcvbuf, + atomic_read(&sk->sk_refcnt)); } static void svc_info(struct seq_file *seq, struct atm_vcc *vcc) @@ -376,32 +378,35 @@ static ssize_t proc_dev_atm_read(struct file *file, char __user *buf, unsigned long page; int length; - if (count == 0) return 0; + if (count == 0) + return 0; page = get_zeroed_page(GFP_KERNEL); - if (!page) return -ENOMEM; + if (!page) + return -ENOMEM; dev = PDE(file->f_path.dentry->d_inode)->data; if (!dev->ops->proc_read) length = -EINVAL; else { - length = dev->ops->proc_read(dev,pos,(char *) page); - if (length > count) length = -EINVAL; + length = dev->ops->proc_read(dev, pos, (char *)page); + if (length > count) + length = -EINVAL; } if (length >= 0) { - if (copy_to_user(buf,(char *) page,length)) length = -EFAULT; + if (copy_to_user(buf, (char *)page, length)) + length = -EFAULT; (*pos)++; } free_page(page); return length; } - struct proc_dir_entry *atm_proc_root; EXPORT_SYMBOL(atm_proc_root); int atm_proc_dev_register(struct atm_dev *dev) { - int digits,num; + int digits, num; int error; /* No proc info */ @@ -410,26 +415,28 @@ int atm_proc_dev_register(struct atm_dev *dev) error = -ENOMEM; digits = 0; - for (num = dev->number; num; num /= 10) digits++; - if (!digits) digits++; + for (num = dev->number; num; num /= 10) + digits++; + if (!digits) + digits++; dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL); if (!dev->proc_name) goto err_out; - sprintf(dev->proc_name,"%s:%d",dev->type, dev->number); + sprintf(dev->proc_name, "%s:%d", dev->type, dev->number); dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, &proc_atm_dev_ops, dev); if (!dev->proc_entry) goto err_free_name; return 0; + err_free_name: kfree(dev->proc_name); err_out: return error; } - void atm_proc_dev_deregister(struct atm_dev *dev) { if (!dev->ops->proc_read) -- cgit v1.2.3 From 6b6dd498f409463635c4f29a3a49585bc7e5d43e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:14 +0000 Subject: net/atm/pvc.c: checkpatch cleanups Spacing cleanups Mostly 80 column wrapped. Move trailing statements to new lines Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/pvc.c | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 8d74e62b0d79..437ee70c5e62 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -17,32 +17,35 @@ #include "common.h" /* common for PVCs and SVCs */ -static int pvc_shutdown(struct socket *sock,int how) +static int pvc_shutdown(struct socket *sock, int how) { return 0; } - -static int pvc_bind(struct socket *sock,struct sockaddr *sockaddr, - int sockaddr_len) +static int pvc_bind(struct socket *sock, struct sockaddr *sockaddr, + int sockaddr_len) { struct sock *sk = sock->sk; struct sockaddr_atmpvc *addr; struct atm_vcc *vcc; int error; - if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL; - addr = (struct sockaddr_atmpvc *) sockaddr; - if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; + if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) + return -EINVAL; + addr = (struct sockaddr_atmpvc *)sockaddr; + if (addr->sap_family != AF_ATMPVC) + return -EAFNOSUPPORT; lock_sock(sk); vcc = ATM_SD(sock); if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { error = -EBADFD; goto out; } - if (test_bit(ATM_VF_PARTIAL,&vcc->flags)) { - if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; - if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; + if (test_bit(ATM_VF_PARTIAL, &vcc->flags)) { + if (vcc->vpi != ATM_VPI_UNSPEC) + addr->sap_addr.vpi = vcc->vpi; + if (vcc->vci != ATM_VCI_UNSPEC) + addr->sap_addr.vci = vcc->vci; } error = vcc_connect(sock, addr->sap_addr.itf, addr->sap_addr.vpi, addr->sap_addr.vci); @@ -51,11 +54,10 @@ out: return error; } - -static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr, - int sockaddr_len,int flags) +static int pvc_connect(struct socket *sock, struct sockaddr *sockaddr, + int sockaddr_len, int flags) { - return pvc_bind(sock,sockaddr,sockaddr_len); + return pvc_bind(sock, sockaddr, sockaddr_len); } static int pvc_setsockopt(struct socket *sock, int level, int optname, @@ -70,7 +72,6 @@ static int pvc_setsockopt(struct socket *sock, int level, int optname, return error; } - static int pvc_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { @@ -83,16 +84,16 @@ static int pvc_getsockopt(struct socket *sock, int level, int optname, return error; } - -static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, - int *sockaddr_len,int peer) +static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, + int *sockaddr_len, int peer) { struct sockaddr_atmpvc *addr; struct atm_vcc *vcc = ATM_SD(sock); - if (!vcc->dev || !test_bit(ATM_VF_ADDR,&vcc->flags)) return -ENOTCONN; + if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) + return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); - addr = (struct sockaddr_atmpvc *) sockaddr; + addr = (struct sockaddr_atmpvc *)sockaddr; addr->sap_family = AF_ATMPVC; addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; @@ -100,7 +101,6 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, return 0; } - static const struct proto_ops pvc_proto_ops = { .family = PF_ATMPVC, .owner = THIS_MODULE, @@ -137,7 +137,6 @@ static int pvc_create(struct net *net, struct socket *sock, int protocol, return vcc_create(net, sock, protocol, PF_ATMPVC); } - static const struct net_proto_family pvc_family_ops = { .family = PF_ATMPVC, .create = pvc_create, -- cgit v1.2.3 From fa61f0cac8b91e671eb0ba27a4972c7e72a909a6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:15 +0000 Subject: net/atm/raw.c: checkpatch cleanups Spacing cleanups Mostly 80 column wrapped. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/raw.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/net/atm/raw.c b/net/atm/raw.c index fb8a9497653c..d0c4bd047dc4 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -18,7 +18,7 @@ * SKB == NULL indicates that the link is being closed */ -static void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb) +static void atm_push_raw(struct atm_vcc *vcc, struct sk_buff *skb) { if (skb) { struct sock *sk = sk_atm(vcc); @@ -28,8 +28,7 @@ static void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb) } } - -static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) +static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb) { struct sock *sk = sk_atm(vcc); @@ -40,24 +39,22 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) sk->sk_write_space(sk); } - -static int atm_send_aal0(struct atm_vcc *vcc,struct sk_buff *skb) +static int atm_send_aal0(struct atm_vcc *vcc, struct sk_buff *skb) { /* * Note that if vpi/vci are _ANY or _UNSPEC the below will * still work */ if (!capable(CAP_NET_ADMIN) && - (((u32 *) skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) != - ((vcc->vpi << ATM_HDR_VPI_SHIFT) | (vcc->vci << ATM_HDR_VCI_SHIFT))) - { + (((u32 *)skb->data)[0] & (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK)) != + ((vcc->vpi << ATM_HDR_VPI_SHIFT) | + (vcc->vci << ATM_HDR_VCI_SHIFT))) { kfree_skb(skb); return -EADDRNOTAVAIL; } - return vcc->dev->ops->send(vcc,skb); + return vcc->dev->ops->send(vcc, skb); } - int atm_init_aal0(struct atm_vcc *vcc) { vcc->push = atm_push_raw; @@ -67,7 +64,6 @@ int atm_init_aal0(struct atm_vcc *vcc) return 0; } - int atm_init_aal34(struct atm_vcc *vcc) { vcc->push = atm_push_raw; @@ -77,7 +73,6 @@ int atm_init_aal34(struct atm_vcc *vcc) return 0; } - int atm_init_aal5(struct atm_vcc *vcc) { vcc->push = atm_push_raw; @@ -86,6 +81,4 @@ int atm_init_aal5(struct atm_vcc *vcc) vcc->send = vcc->dev->ops->send; return 0; } - - EXPORT_SYMBOL(atm_init_aal5); -- cgit v1.2.3 From 07b54c9ad4804bdd546d3db0889b0db381c726e3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:16 +0000 Subject: net/atm/resources.c: checkpatch cleanups Spacing cleanups Mostly 80 column wrapped. Move embedded assigns out of tests Move trailing statements to new lines switch/case cleanups Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/resources.c | 390 ++++++++++++++++++++++++++-------------------------- 1 file changed, 192 insertions(+), 198 deletions(-) diff --git a/net/atm/resources.c b/net/atm/resources.c index 0d4c0ee090db..447ed89205d8 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -71,7 +71,7 @@ struct atm_dev *atm_dev_lookup(int number) mutex_unlock(&atm_dev_mutex); return dev; } - +EXPORT_SYMBOL(atm_dev_lookup); struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, int number, unsigned long *flags) @@ -85,7 +85,8 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, } mutex_lock(&atm_dev_mutex); if (number != -1) { - if ((inuse = __atm_dev_lookup(number))) { + inuse = __atm_dev_lookup(number); + if (inuse) { atm_dev_put(inuse); mutex_unlock(&atm_dev_mutex); kfree(dev); @@ -130,7 +131,7 @@ out_fail: dev = NULL; goto out; } - +EXPORT_SYMBOL(atm_dev_register); void atm_dev_deregister(struct atm_dev *dev) { @@ -152,7 +153,7 @@ void atm_dev_deregister(struct atm_dev *dev) atm_dev_put(dev); } - +EXPORT_SYMBOL(atm_dev_deregister); static void copy_aal_stats(struct k_atm_aal_stats *from, struct atm_aal_stats *to) @@ -162,7 +163,6 @@ static void copy_aal_stats(struct k_atm_aal_stats *from, #undef __HANDLE_ITEM } - static void subtract_aal_stats(struct k_atm_aal_stats *from, struct atm_aal_stats *to) { @@ -171,8 +171,8 @@ static void subtract_aal_stats(struct k_atm_aal_stats *from, #undef __HANDLE_ITEM } - -static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, int zero) +static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, + int zero) { struct atm_dev_stats tmp; int error = 0; @@ -190,7 +190,6 @@ static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, in return error ? -EFAULT : 0; } - int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) { void __user *buf; @@ -206,50 +205,49 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) #endif switch (cmd) { - case ATM_GETNAMES: - - if (compat) { + case ATM_GETNAMES: + if (compat) { #ifdef CONFIG_COMPAT - struct compat_atm_iobuf __user *ciobuf = arg; - compat_uptr_t cbuf; - iobuf_len = &ciobuf->length; - if (get_user(cbuf, &ciobuf->buffer)) - return -EFAULT; - buf = compat_ptr(cbuf); + struct compat_atm_iobuf __user *ciobuf = arg; + compat_uptr_t cbuf; + iobuf_len = &ciobuf->length; + if (get_user(cbuf, &ciobuf->buffer)) + return -EFAULT; + buf = compat_ptr(cbuf); #endif - } else { - struct atm_iobuf __user *iobuf = arg; - iobuf_len = &iobuf->length; - if (get_user(buf, &iobuf->buffer)) - return -EFAULT; - } - if (get_user(len, iobuf_len)) + } else { + struct atm_iobuf __user *iobuf = arg; + iobuf_len = &iobuf->length; + if (get_user(buf, &iobuf->buffer)) return -EFAULT; - mutex_lock(&atm_dev_mutex); - list_for_each(p, &atm_devs) - size += sizeof(int); - if (size > len) { - mutex_unlock(&atm_dev_mutex); - return -E2BIG; - } - tmp_buf = kmalloc(size, GFP_ATOMIC); - if (!tmp_buf) { - mutex_unlock(&atm_dev_mutex); - return -ENOMEM; - } - tmp_p = tmp_buf; - list_for_each(p, &atm_devs) { - dev = list_entry(p, struct atm_dev, dev_list); - *tmp_p++ = dev->number; - } + } + if (get_user(len, iobuf_len)) + return -EFAULT; + mutex_lock(&atm_dev_mutex); + list_for_each(p, &atm_devs) + size += sizeof(int); + if (size > len) { mutex_unlock(&atm_dev_mutex); - error = ((copy_to_user(buf, tmp_buf, size)) || - put_user(size, iobuf_len)) - ? -EFAULT : 0; - kfree(tmp_buf); - return error; - default: - break; + return -E2BIG; + } + tmp_buf = kmalloc(size, GFP_ATOMIC); + if (!tmp_buf) { + mutex_unlock(&atm_dev_mutex); + return -ENOMEM; + } + tmp_p = tmp_buf; + list_for_each(p, &atm_devs) { + dev = list_entry(p, struct atm_dev, dev_list); + *tmp_p++ = dev->number; + } + mutex_unlock(&atm_dev_mutex); + error = ((copy_to_user(buf, tmp_buf, size)) || + put_user(size, iobuf_len)) + ? -EFAULT : 0; + kfree(tmp_buf); + return error; + default: + break; } if (compat) { @@ -278,166 +276,167 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) if (get_user(number, &sioc->number)) return -EFAULT; } - if (!(dev = try_then_request_module(atm_dev_lookup(number), - "atm-device-%d", number))) + + dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d", + number); + if (!dev) return -ENODEV; switch (cmd) { - case ATM_GETTYPE: - size = strlen(dev->type) + 1; - if (copy_to_user(buf, dev->type, size)) { - error = -EFAULT; - goto done; - } - break; - case ATM_GETESI: - size = ESI_LEN; - if (copy_to_user(buf, dev->esi, size)) { - error = -EFAULT; - goto done; - } - break; - case ATM_SETESI: - { - int i; - - for (i = 0; i < ESI_LEN; i++) - if (dev->esi[i]) { - error = -EEXIST; - goto done; - } - } - /* fall through */ - case ATM_SETESIF: - { - unsigned char esi[ESI_LEN]; - - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - if (copy_from_user(esi, buf, ESI_LEN)) { - error = -EFAULT; - goto done; - } - memcpy(dev->esi, esi, ESI_LEN); - error = ESI_LEN; - goto done; - } - case ATM_GETSTATZ: - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - /* fall through */ - case ATM_GETSTAT: - size = sizeof(struct atm_dev_stats); - error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); - if (error) - goto done; - break; - case ATM_GETCIRANGE: - size = sizeof(struct atm_cirange); - if (copy_to_user(buf, &dev->ci_range, size)) { - error = -EFAULT; - goto done; - } - break; - case ATM_GETLINKRATE: - size = sizeof(int); - if (copy_to_user(buf, &dev->link_rate, size)) { - error = -EFAULT; - goto done; - } - break; - case ATM_RSTADDR: - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - atm_reset_addr(dev, ATM_ADDR_LOCAL); - break; - case ATM_ADDADDR: - case ATM_DELADDR: - case ATM_ADDLECSADDR: - case ATM_DELLECSADDR: - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - { - struct sockaddr_atmsvc addr; - - if (copy_from_user(&addr, buf, sizeof(addr))) { - error = -EFAULT; - goto done; - } - if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) - error = atm_add_addr(dev, &addr, - (cmd == ATM_ADDADDR ? - ATM_ADDR_LOCAL : ATM_ADDR_LECS)); - else - error = atm_del_addr(dev, &addr, - (cmd == ATM_DELADDR ? - ATM_ADDR_LOCAL : ATM_ADDR_LECS)); + case ATM_GETTYPE: + size = strlen(dev->type) + 1; + if (copy_to_user(buf, dev->type, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_GETESI: + size = ESI_LEN; + if (copy_to_user(buf, dev->esi, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_SETESI: + { + int i; + + for (i = 0; i < ESI_LEN; i++) + if (dev->esi[i]) { + error = -EEXIST; goto done; } - case ATM_GETADDR: - case ATM_GETLECSADDR: - error = atm_get_addr(dev, buf, len, - (cmd == ATM_GETADDR ? + } + /* fall through */ + case ATM_SETESIF: + { + unsigned char esi[ESI_LEN]; + + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + if (copy_from_user(esi, buf, ESI_LEN)) { + error = -EFAULT; + goto done; + } + memcpy(dev->esi, esi, ESI_LEN); + error = ESI_LEN; + goto done; + } + case ATM_GETSTATZ: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + /* fall through */ + case ATM_GETSTAT: + size = sizeof(struct atm_dev_stats); + error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); + if (error) + goto done; + break; + case ATM_GETCIRANGE: + size = sizeof(struct atm_cirange); + if (copy_to_user(buf, &dev->ci_range, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_GETLINKRATE: + size = sizeof(int); + if (copy_to_user(buf, &dev->link_rate, size)) { + error = -EFAULT; + goto done; + } + break; + case ATM_RSTADDR: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + atm_reset_addr(dev, ATM_ADDR_LOCAL); + break; + case ATM_ADDADDR: + case ATM_DELADDR: + case ATM_ADDLECSADDR: + case ATM_DELLECSADDR: + { + struct sockaddr_atmsvc addr; + + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + + if (copy_from_user(&addr, buf, sizeof(addr))) { + error = -EFAULT; + goto done; + } + if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) + error = atm_add_addr(dev, &addr, + (cmd == ATM_ADDADDR ? ATM_ADDR_LOCAL : ATM_ADDR_LECS)); - if (error < 0) - goto done; - size = error; - /* may return 0, but later on size == 0 means "don't - write the length" */ - error = put_user(size, sioc_len) - ? -EFAULT : 0; + else + error = atm_del_addr(dev, &addr, + (cmd == ATM_DELADDR ? + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); + goto done; + } + case ATM_GETADDR: + case ATM_GETLECSADDR: + error = atm_get_addr(dev, buf, len, + (cmd == ATM_GETADDR ? + ATM_ADDR_LOCAL : ATM_ADDR_LECS)); + if (error < 0) + goto done; + size = error; + /* may return 0, but later on size == 0 means "don't + write the length" */ + error = put_user(size, sioc_len) ? -EFAULT : 0; + goto done; + case ATM_SETLOOP: + if (__ATM_LM_XTRMT((int) (unsigned long) buf) && + __ATM_LM_XTLOC((int) (unsigned long) buf) > + __ATM_LM_XTRMT((int) (unsigned long) buf)) { + error = -EINVAL; goto done; - case ATM_SETLOOP: - if (__ATM_LM_XTRMT((int) (unsigned long) buf) && - __ATM_LM_XTLOC((int) (unsigned long) buf) > - __ATM_LM_XTRMT((int) (unsigned long) buf)) { + } + /* fall through */ + case ATM_SETCIRANGE: + case SONET_GETSTATZ: + case SONET_SETDIAG: + case SONET_CLRDIAG: + case SONET_SETFRAMING: + if (!capable(CAP_NET_ADMIN)) { + error = -EPERM; + goto done; + } + /* fall through */ + default: + if (compat) { +#ifdef CONFIG_COMPAT + if (!dev->ops->compat_ioctl) { error = -EINVAL; goto done; } - /* fall through */ - case ATM_SETCIRANGE: - case SONET_GETSTATZ: - case SONET_SETDIAG: - case SONET_CLRDIAG: - case SONET_SETFRAMING: - if (!capable(CAP_NET_ADMIN)) { - error = -EPERM; - goto done; - } - /* fall through */ - default: - if (compat) { -#ifdef CONFIG_COMPAT - if (!dev->ops->compat_ioctl) { - error = -EINVAL; - goto done; - } - size = dev->ops->compat_ioctl(dev, cmd, buf); + size = dev->ops->compat_ioctl(dev, cmd, buf); #endif - } else { - if (!dev->ops->ioctl) { - error = -EINVAL; - goto done; - } - size = dev->ops->ioctl(dev, cmd, buf); - } - if (size < 0) { - error = (size == -ENOIOCTLCMD ? -EINVAL : size); + } else { + if (!dev->ops->ioctl) { + error = -EINVAL; goto done; } + size = dev->ops->ioctl(dev, cmd, buf); + } + if (size < 0) { + error = (size == -ENOIOCTLCMD ? -EINVAL : size); + goto done; + } } if (size) - error = put_user(size, sioc_len) - ? -EFAULT : 0; + error = put_user(size, sioc_len) ? -EFAULT : 0; else error = 0; done: @@ -445,7 +444,7 @@ done: return error; } -static __inline__ void *dev_get_idx(loff_t left) +static inline void *dev_get_idx(loff_t left) { struct list_head *p; @@ -474,8 +473,3 @@ void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) ? atm_devs.next : ((struct list_head *)v)->next; return (v == &atm_devs) ? NULL : v; } - - -EXPORT_SYMBOL(atm_dev_register); -EXPORT_SYMBOL(atm_dev_deregister); -EXPORT_SYMBOL(atm_dev_lookup); -- cgit v1.2.3 From 0ec96e656fcd4a8ea8cb0e92f90ab4bb6f79cada Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:17 +0000 Subject: net/atm/signaling.c: checkpatch cleanups Mostly 80 column wrapped. Move embedded assigns out of tests Move trailing statements to new lines switch/case cleanups Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/signaling.c | 202 ++++++++++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 28df4edf9ca4..ad1d28ae512b 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -18,7 +18,6 @@ #include "resources.h" #include "signaling.h" - #undef WAIT_FOR_DEMON /* #define this if system calls on SVC sockets should block until the demon runs. Danger: may cause nasty hangs if the demon @@ -29,20 +28,19 @@ struct atm_vcc *sigd = NULL; static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep); #endif - static void sigd_put_skb(struct sk_buff *skb) { #ifdef WAIT_FOR_DEMON - DECLARE_WAITQUEUE(wait,current); + DECLARE_WAITQUEUE(wait, current); - add_wait_queue(&sigd_sleep,&wait); + add_wait_queue(&sigd_sleep, &wait); while (!sigd) { set_current_state(TASK_UNINTERRUPTIBLE); pr_debug("atmsvc: waiting for signaling daemon...\n"); schedule(); } current->state = TASK_RUNNING; - remove_wait_queue(&sigd_sleep,&wait); + remove_wait_queue(&sigd_sleep, &wait); #else if (!sigd) { pr_debug("atmsvc: no signaling daemon\n"); @@ -50,39 +48,39 @@ static void sigd_put_skb(struct sk_buff *skb) return; } #endif - atm_force_charge(sigd,skb->truesize); - skb_queue_tail(&sk_atm(sigd)->sk_receive_queue,skb); + atm_force_charge(sigd, skb->truesize); + skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb); sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len); } - -static void modify_qos(struct atm_vcc *vcc,struct atmsvc_msg *msg) +static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg) { struct sk_buff *skb; - if (test_bit(ATM_VF_RELEASED,&vcc->flags) || - !test_bit(ATM_VF_READY,&vcc->flags)) + if (test_bit(ATM_VF_RELEASED, &vcc->flags) || + !test_bit(ATM_VF_READY, &vcc->flags)) return; msg->type = as_error; - if (!vcc->dev->ops->change_qos) msg->reply = -EOPNOTSUPP; + if (!vcc->dev->ops->change_qos) + msg->reply = -EOPNOTSUPP; else { /* should lock VCC */ - msg->reply = vcc->dev->ops->change_qos(vcc,&msg->qos, - msg->reply); - if (!msg->reply) msg->type = as_okay; + msg->reply = vcc->dev->ops->change_qos(vcc, &msg->qos, + msg->reply); + if (!msg->reply) + msg->type = as_okay; } /* * Should probably just turn around the old skb. But the, the buffer * space accounting needs to follow the change too. Maybe later. */ - while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL))) + while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL))) schedule(); - *(struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)) = *msg; + *(struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)) = *msg; sigd_put_skb(skb); } - -static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) +static int sigd_send(struct atm_vcc *vcc, struct sk_buff *skb) { struct atmsvc_msg *msg; struct atm_vcc *session_vcc; @@ -95,63 +93,64 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb) sk = sk_atm(vcc); switch (msg->type) { - case as_okay: - sk->sk_err = -msg->reply; - clear_bit(ATM_VF_WAITING, &vcc->flags); - if (!*vcc->local.sas_addr.prv && - !*vcc->local.sas_addr.pub) { - vcc->local.sas_family = AF_ATMSVC; - memcpy(vcc->local.sas_addr.prv, - msg->local.sas_addr.prv,ATM_ESA_LEN); - memcpy(vcc->local.sas_addr.pub, - msg->local.sas_addr.pub,ATM_E164_LEN+1); - } - session_vcc = vcc->session ? vcc->session : vcc; - if (session_vcc->vpi || session_vcc->vci) break; - session_vcc->itf = msg->pvc.sap_addr.itf; - session_vcc->vpi = msg->pvc.sap_addr.vpi; - session_vcc->vci = msg->pvc.sap_addr.vci; - if (session_vcc->vpi || session_vcc->vci) - session_vcc->qos = msg->qos; - break; - case as_error: - clear_bit(ATM_VF_REGIS,&vcc->flags); - clear_bit(ATM_VF_READY,&vcc->flags); - sk->sk_err = -msg->reply; - clear_bit(ATM_VF_WAITING, &vcc->flags); + case as_okay: + sk->sk_err = -msg->reply; + clear_bit(ATM_VF_WAITING, &vcc->flags); + if (!*vcc->local.sas_addr.prv && !*vcc->local.sas_addr.pub) { + vcc->local.sas_family = AF_ATMSVC; + memcpy(vcc->local.sas_addr.prv, + msg->local.sas_addr.prv, ATM_ESA_LEN); + memcpy(vcc->local.sas_addr.pub, + msg->local.sas_addr.pub, ATM_E164_LEN + 1); + } + session_vcc = vcc->session ? vcc->session : vcc; + if (session_vcc->vpi || session_vcc->vci) break; - case as_indicate: - vcc = *(struct atm_vcc **) &msg->listen_vcc; - sk = sk_atm(vcc); - pr_debug("as_indicate!!!\n"); - lock_sock(sk); - if (sk_acceptq_is_full(sk)) { - sigd_enq(NULL,as_reject,vcc,NULL,NULL); - dev_kfree_skb(skb); - goto as_indicate_complete; - } - sk->sk_ack_backlog++; - skb_queue_tail(&sk->sk_receive_queue, skb); - pr_debug("waking sk->sk_sleep 0x%p\n", sk->sk_sleep); - sk->sk_state_change(sk); + session_vcc->itf = msg->pvc.sap_addr.itf; + session_vcc->vpi = msg->pvc.sap_addr.vpi; + session_vcc->vci = msg->pvc.sap_addr.vci; + if (session_vcc->vpi || session_vcc->vci) + session_vcc->qos = msg->qos; + break; + case as_error: + clear_bit(ATM_VF_REGIS, &vcc->flags); + clear_bit(ATM_VF_READY, &vcc->flags); + sk->sk_err = -msg->reply; + clear_bit(ATM_VF_WAITING, &vcc->flags); + break; + case as_indicate: + vcc = *(struct atm_vcc **)&msg->listen_vcc; + sk = sk_atm(vcc); + pr_debug("as_indicate!!!\n"); + lock_sock(sk); + if (sk_acceptq_is_full(sk)) { + sigd_enq(NULL, as_reject, vcc, NULL, NULL); + dev_kfree_skb(skb); + goto as_indicate_complete; + } + sk->sk_ack_backlog++; + skb_queue_tail(&sk->sk_receive_queue, skb); + pr_debug("waking sk->sk_sleep 0x%p\n", sk->sk_sleep); + sk->sk_state_change(sk); as_indicate_complete: - release_sock(sk); - return 0; - case as_close: - set_bit(ATM_VF_RELEASED,&vcc->flags); - vcc_release_async(vcc, msg->reply); - goto out; - case as_modify: - modify_qos(vcc,msg); - break; - case as_addparty: - case as_dropparty: - sk->sk_err_soft = msg->reply; /* < 0 failure, otherwise ep_ref */ - clear_bit(ATM_VF_WAITING, &vcc->flags); - break; - default: - pr_alert("bad message type %d\n", (int)msg->type); - return -EINVAL; + release_sock(sk); + return 0; + case as_close: + set_bit(ATM_VF_RELEASED, &vcc->flags); + vcc_release_async(vcc, msg->reply); + goto out; + case as_modify: + modify_qos(vcc, msg); + break; + case as_addparty: + case as_dropparty: + sk->sk_err_soft = msg->reply; + /* < 0 failure, otherwise ep_ref */ + clear_bit(ATM_VF_WAITING, &vcc->flags); + break; + default: + pr_alert("bad message type %d\n", (int)msg->type); + return -EINVAL; } sk->sk_state_change(sk); out: @@ -159,48 +158,52 @@ out: return 0; } - -void sigd_enq2(struct atm_vcc *vcc,enum atmsvc_msg_type type, - struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc,const struct atm_qos *qos,int reply) +void sigd_enq2(struct atm_vcc *vcc, enum atmsvc_msg_type type, + struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc, const struct atm_qos *qos, + int reply) { struct sk_buff *skb; struct atmsvc_msg *msg; static unsigned session = 0; pr_debug("%d (0x%p)\n", (int)type, vcc); - while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL))) + while (!(skb = alloc_skb(sizeof(struct atmsvc_msg), GFP_KERNEL))) schedule(); - msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg)); - memset(msg,0,sizeof(*msg)); + msg = (struct atmsvc_msg *)skb_put(skb, sizeof(struct atmsvc_msg)); + memset(msg, 0, sizeof(*msg)); msg->type = type; *(struct atm_vcc **) &msg->vcc = vcc; *(struct atm_vcc **) &msg->listen_vcc = listen_vcc; msg->reply = reply; - if (qos) msg->qos = *qos; - if (vcc) msg->sap = vcc->sap; - if (svc) msg->svc = *svc; - if (vcc) msg->local = vcc->local; - if (pvc) msg->pvc = *pvc; + if (qos) + msg->qos = *qos; + if (vcc) + msg->sap = vcc->sap; + if (svc) + msg->svc = *svc; + if (vcc) + msg->local = vcc->local; + if (pvc) + msg->pvc = *pvc; if (vcc) { if (type == as_connect && test_bit(ATM_VF_SESSION, &vcc->flags)) msg->session = ++session; /* every new pmp connect gets the next session number */ } sigd_put_skb(skb); - if (vcc) set_bit(ATM_VF_REGIS,&vcc->flags); + if (vcc) + set_bit(ATM_VF_REGIS, &vcc->flags); } - -void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, - struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc) +void sigd_enq(struct atm_vcc *vcc, enum atmsvc_msg_type type, + struct atm_vcc *listen_vcc, const struct sockaddr_atmpvc *pvc, + const struct sockaddr_atmsvc *svc) { - sigd_enq2(vcc,type,listen_vcc,pvc,svc,vcc ? &vcc->qos : NULL,0); + sigd_enq2(vcc, type, listen_vcc, pvc, svc, vcc ? &vcc->qos : NULL, 0); /* other ISP applications may use "reply" */ } - static void purge_vcc(struct atm_vcc *vcc) { if (sk_atm(vcc)->sk_family == PF_ATMSVC && @@ -211,7 +214,6 @@ static void purge_vcc(struct atm_vcc *vcc) } } - static void sigd_close(struct atm_vcc *vcc) { struct hlist_node *node; @@ -225,7 +227,7 @@ static void sigd_close(struct atm_vcc *vcc) skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); read_lock(&vcc_sklist_lock); - for(i = 0; i < VCC_HTABLE_SIZE; ++i) { + for (i = 0; i < VCC_HTABLE_SIZE; ++i) { struct hlist_head *head = &vcc_hash[i]; sk_for_each(s, node, head) { @@ -237,13 +239,11 @@ static void sigd_close(struct atm_vcc *vcc) read_unlock(&vcc_sklist_lock); } - static struct atmdev_ops sigd_dev_ops = { .close = sigd_close, .send = sigd_send }; - static struct atm_dev sigd_dev = { .ops = &sigd_dev_ops, .type = "sig", @@ -251,16 +251,16 @@ static struct atm_dev sigd_dev = { .lock = __SPIN_LOCK_UNLOCKED(sigd_dev.lock) }; - int sigd_attach(struct atm_vcc *vcc) { - if (sigd) return -EADDRINUSE; + if (sigd) + return -EADDRINUSE; pr_debug("\n"); sigd = vcc; vcc->dev = &sigd_dev; vcc_insert_socket(sk_atm(vcc)); - set_bit(ATM_VF_META,&vcc->flags); - set_bit(ATM_VF_READY,&vcc->flags); + set_bit(ATM_VF_META, &vcc->flags); + set_bit(ATM_VF_READY, &vcc->flags); #ifdef WAIT_FOR_DEMON wake_up(&sigd_sleep); #endif -- cgit v1.2.3 From b7d9371befd6fa3eb0ad9d574860095642bf70ed Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:18 +0000 Subject: net/atm/svc.c: checkpatch cleanups Convert #include Signed-off-by: David S. Miller --- net/atm/svc.c | 249 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 125 insertions(+), 124 deletions(-) diff --git a/net/atm/svc.c b/net/atm/svc.c index 251ddbc42e4b..3ba9a45a51ac 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -19,14 +19,15 @@ #include #include #include /* for sock_no_* */ -#include +#include #include "resources.h" #include "common.h" /* common for PVCs and SVCs */ #include "signaling.h" #include "addr.h" -static int svc_create(struct net *net, struct socket *sock, int protocol, int kern); +static int svc_create(struct net *net, struct socket *sock, int protocol, + int kern); /* * Note: since all this is still nicely synchronized with the signaling demon, @@ -35,25 +36,25 @@ static int svc_create(struct net *net, struct socket *sock, int protocol, int ke */ -static int svc_shutdown(struct socket *sock,int how) +static int svc_shutdown(struct socket *sock, int how) { return 0; } - static void svc_disconnect(struct atm_vcc *vcc) { DEFINE_WAIT(wait); struct sk_buff *skb; struct sock *sk = sk_atm(vcc); - pr_debug("%p\n",vcc); - if (test_bit(ATM_VF_REGIS,&vcc->flags)) { + pr_debug("%p\n", vcc); + if (test_bit(ATM_VF_REGIS, &vcc->flags)) { prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); - sigd_enq(vcc,as_close,NULL,NULL,NULL); - while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { + sigd_enq(vcc, as_close, NULL, NULL, NULL); + while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { schedule(); - prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, + TASK_UNINTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); } @@ -62,35 +63,35 @@ static void svc_disconnect(struct atm_vcc *vcc) while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { atm_return(vcc, skb->truesize); pr_debug("LISTEN REL\n"); - sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0); + sigd_enq2(NULL, as_reject, vcc, NULL, NULL, &vcc->qos, 0); dev_kfree_skb(skb); } clear_bit(ATM_VF_REGIS, &vcc->flags); /* ... may retry later */ } - static int svc_release(struct socket *sock) { struct sock *sk = sock->sk; struct atm_vcc *vcc; - if (sk) { + if (sk) { vcc = ATM_SD(sock); pr_debug("%p\n", vcc); clear_bit(ATM_VF_READY, &vcc->flags); - /* VCC pointer is used as a reference, so we must not free it - (thereby subjecting it to re-use) before all pending connections - are closed */ + /* + * VCC pointer is used as a reference, + * so we must not free it (thereby subjecting it to re-use) + * before all pending connections are closed + */ svc_disconnect(vcc); vcc_release(sock); } return 0; } - -static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, - int sockaddr_len) +static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, + int sockaddr_len) { DEFINE_WAIT(wait); struct sock *sk = sock->sk; @@ -115,38 +116,37 @@ static int svc_bind(struct socket *sock,struct sockaddr *sockaddr, error = -EAFNOSUPPORT; goto out; } - clear_bit(ATM_VF_BOUND,&vcc->flags); + clear_bit(ATM_VF_BOUND, &vcc->flags); /* failing rebind will kill old binding */ /* @@@ check memory (de)allocation on rebind */ - if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) { + if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) { error = -EBADFD; goto out; } vcc->local = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); - sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); + sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); - clear_bit(ATM_VF_REGIS,&vcc->flags); /* doesn't count */ + clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ if (!sigd) { error = -EUNATCH; goto out; } if (!sk->sk_err) - set_bit(ATM_VF_BOUND,&vcc->flags); + set_bit(ATM_VF_BOUND, &vcc->flags); error = -sk->sk_err; out: release_sock(sk); return error; } - -static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, - int sockaddr_len,int flags) +static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, + int sockaddr_len, int flags) { DEFINE_WAIT(wait); struct sock *sk = sock->sk; @@ -154,7 +154,7 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, struct atm_vcc *vcc = ATM_SD(sock); int error; - pr_debug("%p\n",vcc); + pr_debug("%p\n", vcc); lock_sock(sk); if (sockaddr_len != sizeof(struct sockaddr_atmsvc)) { error = -EINVAL; @@ -202,7 +202,7 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, vcc->remote = *addr; set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote); + sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); if (flags & O_NONBLOCK) { finish_wait(sk->sk_sleep, &wait); sock->state = SS_CONNECTING; @@ -213,7 +213,8 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); if (!signal_pending(current)) { - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); continue; } pr_debug("*ABORT*\n"); @@ -229,20 +230,22 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, * Kernel <--okay---- Demon * Kernel <--close--- Demon */ - sigd_enq(vcc,as_close,NULL,NULL,NULL); + sigd_enq(vcc, as_close, NULL, NULL, NULL); while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); schedule(); } if (!sk->sk_err) - while (!test_bit(ATM_VF_RELEASED,&vcc->flags) - && sigd) { - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && + sigd) { + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); schedule(); } - clear_bit(ATM_VF_REGIS,&vcc->flags); - clear_bit(ATM_VF_RELEASED,&vcc->flags); - clear_bit(ATM_VF_CLOSE,&vcc->flags); + clear_bit(ATM_VF_REGIS, &vcc->flags); + clear_bit(ATM_VF_RELEASED, &vcc->flags); + clear_bit(ATM_VF_CLOSE, &vcc->flags); /* we're gone now but may connect later */ error = -EINTR; break; @@ -270,17 +273,17 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr, /* * #endif */ - if (!(error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci))) + error = vcc_connect(sock, vcc->itf, vcc->vpi, vcc->vci); + if (!error) sock->state = SS_CONNECTED; else - (void) svc_disconnect(vcc); + (void)svc_disconnect(vcc); out: release_sock(sk); return error; } - -static int svc_listen(struct socket *sock,int backlog) +static int svc_listen(struct socket *sock, int backlog) { DEFINE_WAIT(wait); struct sock *sk = sock->sk; @@ -290,17 +293,17 @@ static int svc_listen(struct socket *sock,int backlog) pr_debug("%p\n", vcc); lock_sock(sk); /* let server handle listen on unbound sockets */ - if (test_bit(ATM_VF_SESSION,&vcc->flags)) { + if (test_bit(ATM_VF_SESSION, &vcc->flags)) { error = -EINVAL; goto out; } if (test_bit(ATM_VF_LISTEN, &vcc->flags)) { error = -EADDRINUSE; goto out; - } + } set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); - sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); + sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { schedule(); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); @@ -310,7 +313,7 @@ static int svc_listen(struct socket *sock,int backlog) error = -EUNATCH; goto out; } - set_bit(ATM_VF_LISTEN,&vcc->flags); + set_bit(ATM_VF_LISTEN, &vcc->flags); vcc_insert_socket(sk); sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; error = -sk->sk_err; @@ -319,8 +322,7 @@ out: return error; } - -static int svc_accept(struct socket *sock,struct socket *newsock,int flags) +static int svc_accept(struct socket *sock, struct socket *newsock, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb; @@ -344,8 +346,9 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); while (!(skb = skb_dequeue(&sk->sk_receive_queue)) && sigd) { - if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break; - if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) { + if (test_bit(ATM_VF_RELEASED, &old_vcc->flags)) + break; + if (test_bit(ATM_VF_CLOSE, &old_vcc->flags)) { error = -sk->sk_err; break; } @@ -360,7 +363,8 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) error = -ERESTARTSYS; break; } - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(sk->sk_sleep, &wait, + TASK_INTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); if (error) @@ -369,31 +373,34 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) error = -EUNATCH; goto out; } - msg = (struct atmsvc_msg *) skb->data; + msg = (struct atmsvc_msg *)skb->data; new_vcc->qos = msg->qos; - set_bit(ATM_VF_HASQOS,&new_vcc->flags); + set_bit(ATM_VF_HASQOS, &new_vcc->flags); new_vcc->remote = msg->svc; new_vcc->local = msg->local; new_vcc->sap = msg->sap; error = vcc_connect(newsock, msg->pvc.sap_addr.itf, - msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci); + msg->pvc.sap_addr.vpi, + msg->pvc.sap_addr.vci); dev_kfree_skb(skb); sk->sk_ack_backlog--; if (error) { - sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL, - &old_vcc->qos,error); + sigd_enq2(NULL, as_reject, old_vcc, NULL, NULL, + &old_vcc->qos, error); error = error == -EAGAIN ? -EBUSY : error; goto out; } /* wait should be short, so we ignore the non-blocking flag */ set_bit(ATM_VF_WAITING, &new_vcc->flags); - prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); - sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); + prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, + TASK_UNINTERRUPTIBLE); + sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { release_sock(sk); schedule(); lock_sock(sk); - prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); + prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, + TASK_UNINTERRUPTIBLE); } finish_wait(sk_atm(new_vcc)->sk_sleep, &wait); if (!sigd) { @@ -413,39 +420,37 @@ out: return error; } - -static int svc_getname(struct socket *sock,struct sockaddr *sockaddr, - int *sockaddr_len,int peer) +static int svc_getname(struct socket *sock, struct sockaddr *sockaddr, + int *sockaddr_len, int peer) { struct sockaddr_atmsvc *addr; *sockaddr_len = sizeof(struct sockaddr_atmsvc); addr = (struct sockaddr_atmsvc *) sockaddr; - memcpy(addr,peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, - sizeof(struct sockaddr_atmsvc)); + memcpy(addr, peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, + sizeof(struct sockaddr_atmsvc)); return 0; } - -int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos) +int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) { struct sock *sk = sk_atm(vcc); DEFINE_WAIT(wait); set_bit(ATM_VF_WAITING, &vcc->flags); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); - sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); + sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); while (test_bit(ATM_VF_WAITING, &vcc->flags) && !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { schedule(); prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); - if (!sigd) return -EUNATCH; + if (!sigd) + return -EUNATCH; return -sk->sk_err; } - static int svc_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { @@ -455,37 +460,35 @@ static int svc_setsockopt(struct socket *sock, int level, int optname, lock_sock(sk); switch (optname) { - case SO_ATMSAP: - if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) { - error = -EINVAL; - goto out; - } - if (copy_from_user(&vcc->sap, optval, optlen)) { - error = -EFAULT; - goto out; - } - set_bit(ATM_VF_HASSAP, &vcc->flags); - break; - case SO_MULTIPOINT: - if (level != SOL_ATM || optlen != sizeof(int)) { - error = -EINVAL; - goto out; - } - if (get_user(value, (int __user *) optval)) { - error = -EFAULT; - goto out; - } - if (value == 1) { - set_bit(ATM_VF_SESSION, &vcc->flags); - } else if (value == 0) { - clear_bit(ATM_VF_SESSION, &vcc->flags); - } else { - error = -EINVAL; - } - break; - default: - error = vcc_setsockopt(sock, level, optname, - optval, optlen); + case SO_ATMSAP: + if (level != SOL_ATM || optlen != sizeof(struct atm_sap)) { + error = -EINVAL; + goto out; + } + if (copy_from_user(&vcc->sap, optval, optlen)) { + error = -EFAULT; + goto out; + } + set_bit(ATM_VF_HASSAP, &vcc->flags); + break; + case SO_MULTIPOINT: + if (level != SOL_ATM || optlen != sizeof(int)) { + error = -EINVAL; + goto out; + } + if (get_user(value, (int __user *)optval)) { + error = -EFAULT; + goto out; + } + if (value == 1) + set_bit(ATM_VF_SESSION, &vcc->flags); + else if (value == 0) + clear_bit(ATM_VF_SESSION, &vcc->flags); + else + error = -EINVAL; + break; + default: + error = vcc_setsockopt(sock, level, optname, optval, optlen); } out: @@ -493,9 +496,8 @@ out: return error; } - -static int svc_getsockopt(struct socket *sock,int level,int optname, - char __user *optval,int __user *optlen) +static int svc_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) { struct sock *sk = sock->sk; int error = 0, len; @@ -522,7 +524,6 @@ out: return error; } - static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, int sockaddr_len, int flags) { @@ -553,7 +554,6 @@ out: return error; } - static int svc_dropparty(struct socket *sock, int ep_ref) { DEFINE_WAIT(wait); @@ -580,7 +580,6 @@ out: return error; } - static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { int error, ep_ref; @@ -588,29 +587,31 @@ static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) struct atm_vcc *vcc = ATM_SD(sock); switch (cmd) { - case ATM_ADDPARTY: - if (!test_bit(ATM_VF_SESSION, &vcc->flags)) - return -EINVAL; - if (copy_from_user(&sa, (void __user *) arg, sizeof(sa))) - return -EFAULT; - error = svc_addparty(sock, (struct sockaddr *) &sa, sizeof(sa), 0); - break; - case ATM_DROPPARTY: - if (!test_bit(ATM_VF_SESSION, &vcc->flags)) - return -EINVAL; - if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int))) - return -EFAULT; - error = svc_dropparty(sock, ep_ref); - break; - default: - error = vcc_ioctl(sock, cmd, arg); + case ATM_ADDPARTY: + if (!test_bit(ATM_VF_SESSION, &vcc->flags)) + return -EINVAL; + if (copy_from_user(&sa, (void __user *) arg, sizeof(sa))) + return -EFAULT; + error = svc_addparty(sock, (struct sockaddr *)&sa, sizeof(sa), + 0); + break; + case ATM_DROPPARTY: + if (!test_bit(ATM_VF_SESSION, &vcc->flags)) + return -EINVAL; + if (copy_from_user(&ep_ref, (void __user *) arg, sizeof(int))) + return -EFAULT; + error = svc_dropparty(sock, ep_ref); + break; + default: + error = vcc_ioctl(sock, cmd, arg); } return error; } #ifdef CONFIG_COMPAT -static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +static int svc_compat_ioctl(struct socket *sock, unsigned int cmd, + unsigned long arg) { /* The definition of ATM_ADDPARTY uses the size of struct atm_iobuf. But actually it takes a struct sockaddr_atmsvc, which doesn't need @@ -661,13 +662,13 @@ static int svc_create(struct net *net, struct socket *sock, int protocol, sock->ops = &svc_proto_ops; error = vcc_create(net, sock, protocol, AF_ATMSVC); - if (error) return error; + if (error) + return error; ATM_SD(sock)->local.sas_family = AF_ATMSVC; ATM_SD(sock)->remote.sas_family = AF_ATMSVC; return 0; } - static const struct net_proto_family svc_family_ops = { .family = PF_ATMSVC, .create = svc_create, -- cgit v1.2.3 From b4c84ec0fd9ec2297b796443051554d062007ba3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:19 +0000 Subject: net/atm/lec.c: Add __lec_arp_check_expire and other cleanups Reduce indentation in lec_arp_check_expire Indent a case label Remove != NULL logical tests from while ((skb = foo())) assign and tests Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/lec.c | 153 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 80 insertions(+), 73 deletions(-) diff --git a/net/atm/lec.c b/net/atm/lec.c index aefd278d6af6..5da5753157f9 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -285,7 +285,6 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, /* Make sure we have room for lec_id */ if (skb_headroom(skb) < 2) { - pr_debug("reallocating skb\n"); skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); kfree_skb(skb); @@ -508,34 +507,31 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) break; case l_should_bridge: #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - { - pr_debug("%s: bridge zeppelin asks about %pM\n", - dev->name, mesg->content.proxy.mac_addr); + { + pr_debug("%s: bridge zeppelin asks about %pM\n", + dev->name, mesg->content.proxy.mac_addr); - if (br_fdb_test_addr_hook == NULL) - break; + if (br_fdb_test_addr_hook == NULL) + break; - if (br_fdb_test_addr_hook(dev, - mesg->content.proxy.mac_addr)) { - /* hit from bridge table, send LE_ARP_RESPONSE */ - struct sk_buff *skb2; - struct sock *sk; - - pr_debug("%s: entry found, responding to zeppelin\n", - dev->name); - skb2 = alloc_skb(sizeof(struct atmlec_msg), - GFP_ATOMIC); - if (skb2 == NULL) - break; - skb2->len = sizeof(struct atmlec_msg); - skb_copy_to_linear_data(skb2, mesg, - sizeof(*mesg)); - atm_force_charge(priv->lecd, skb2->truesize); - sk = sk_atm(priv->lecd); - skb_queue_tail(&sk->sk_receive_queue, skb2); - sk->sk_data_ready(sk, skb2->len); - } + if (br_fdb_test_addr_hook(dev, mesg->content.proxy.mac_addr)) { + /* hit from bridge table, send LE_ARP_RESPONSE */ + struct sk_buff *skb2; + struct sock *sk; + + pr_debug("%s: entry found, responding to zeppelin\n", + dev->name); + skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); + if (skb2 == NULL) + break; + skb2->len = sizeof(struct atmlec_msg); + skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); + atm_force_charge(priv->lecd, skb2->truesize); + sk = sk_atm(priv->lecd); + skb_queue_tail(&sk->sk_receive_queue, skb2); + sk->sk_data_ready(sk, skb2->len); } + } #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ break; default: @@ -561,7 +557,7 @@ static void lec_atm_close(struct atm_vcc *vcc) if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) pr_info("%s closing with messages pending\n", dev->name); - while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) { + while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) { atm_return(vcc, skb->truesize); dev_kfree_skb(skb); } @@ -1748,6 +1744,50 @@ static void lec_arp_expire_vcc(unsigned long data) lec_arp_put(to_remove); } +static bool __lec_arp_check_expire(struct lec_arp_table *entry, + unsigned long now, + struct lec_priv *priv) +{ + unsigned long time_to_check; + + if ((entry->flags) & LEC_REMOTE_FLAG && priv->topology_change) + time_to_check = priv->forward_delay_time; + else + time_to_check = priv->aging_time; + + pr_debug("About to expire: %lx - %lx > %lx\n", + now, entry->last_used, time_to_check); + if (time_after(now, entry->last_used + time_to_check) && + !(entry->flags & LEC_PERMANENT_FLAG) && + !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ + /* Remove entry */ + pr_debug("Entry timed out\n"); + lec_arp_remove(priv, entry); + lec_arp_put(entry); + } else { + /* Something else */ + if ((entry->status == ESI_VC_PENDING || + entry->status == ESI_ARP_PENDING) && + time_after_eq(now, entry->timestamp + + priv->max_unknown_frame_time)) { + entry->timestamp = jiffies; + entry->packets_flooded = 0; + if (entry->status == ESI_VC_PENDING) + send_to_lecd(priv, l_svc_setup, + entry->mac_addr, + entry->atm_addr, + NULL); + } + if (entry->status == ESI_FLUSH_PENDING && + time_after_eq(now, entry->timestamp + + priv->path_switching_delay)) { + lec_arp_hold(entry); + return true; + } + } + + return false; +} /* * Expire entries. * 1. Re-set timer @@ -1772,7 +1812,6 @@ static void lec_arp_check_expire(struct work_struct *work) struct hlist_node *node, *next; struct lec_arp_table *entry; unsigned long now; - unsigned long time_to_check; int i; pr_debug("%p\n", priv); @@ -1782,51 +1821,19 @@ restart: for (i = 0; i < LEC_ARP_TABLE_SIZE; i++) { hlist_for_each_entry_safe(entry, node, next, &priv->lec_arp_tables[i], next) { - if ((entry->flags) & LEC_REMOTE_FLAG && - priv->topology_change) - time_to_check = priv->forward_delay_time; - else - time_to_check = priv->aging_time; - - pr_debug("About to expire: %lx - %lx > %lx\n", - now, entry->last_used, time_to_check); - if (time_after(now, entry->last_used + time_to_check) && - !(entry->flags & LEC_PERMANENT_FLAG) && - !(entry->mac_addr[0] & 0x01)) { /* LANE2: 7.1.20 */ - /* Remove entry */ - pr_debug("Entry timed out\n"); - lec_arp_remove(priv, entry); + if (__lec_arp_check_expire(entry, now, priv)) { + struct sk_buff *skb; + struct atm_vcc *vcc = entry->vcc; + + spin_unlock_irqrestore(&priv->lec_arp_lock, + flags); + while ((skb = skb_dequeue(&entry->tx_wait))) + lec_send(vcc, skb); + entry->last_used = jiffies; + entry->status = ESI_FORWARD_DIRECT; lec_arp_put(entry); - } else { - /* Something else */ - if ((entry->status == ESI_VC_PENDING || - entry->status == ESI_ARP_PENDING) && - time_after_eq(now, - entry->timestamp + - priv->max_unknown_frame_time)) { - entry->timestamp = jiffies; - entry->packets_flooded = 0; - if (entry->status == ESI_VC_PENDING) - send_to_lecd(priv, l_svc_setup, - entry->mac_addr, - entry->atm_addr, - NULL); - } - if (entry->status == ESI_FLUSH_PENDING && - time_after_eq(now, entry->timestamp + - priv->path_switching_delay)) { - struct sk_buff *skb; - struct atm_vcc *vcc = entry->vcc; - - lec_arp_hold(entry); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) - lec_send(vcc, skb); - entry->last_used = jiffies; - entry->status = ESI_FORWARD_DIRECT; - lec_arp_put(entry); - goto restart; - } + + goto restart; } } } @@ -2237,7 +2244,7 @@ restart: lec_arp_hold(entry); spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - while ((skb = skb_dequeue(&entry->tx_wait)) != NULL) + while ((skb = skb_dequeue(&entry->tx_wait))) lec_send(vcc, skb); entry->last_used = jiffies; entry->status = ESI_FORWARD_DIRECT; -- cgit v1.2.3 From b50c2ea72a8ed6bc2a954019b6feb6ca41fce07e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 26 Jan 2010 11:40:20 +0000 Subject: net/atm: Cleanup dprint/ddprintk #defines and uses Move "mpoa:%s: ", __func__/__FILE__ to #defines Remove mpoa __func__/__FILE__ from dprintk uses Add and use #define dprint_cont where appropriate Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- net/atm/mpc.c | 153 +++++++++++++++++++++++++------------------------- net/atm/mpoa_caches.c | 50 +++++++++-------- net/atm/mpoa_proc.c | 28 ++++++--- 3 files changed, 124 insertions(+), 107 deletions(-) diff --git a/net/atm/mpc.c b/net/atm/mpc.c index 55dba22e44b3..a6521c8aa88b 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -38,21 +38,31 @@ */ #if 0 -#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ +#define dprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args) +#define dprintk_cont(format, args...) printk(KERN_CONT format, ##args) #else -#define dprintk(format, args...) \ - do { if (0) printk(KERN_DEBUG format, ##args); } while (0) +#define dprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\ + } while (0) +#define dprintk_cont(format, args...) \ + do { if (0) printk(KERN_CONT format, ##args); } while (0) #endif #if 0 -#define ddprintk printk(KERN_DEBUG format, ##args) /* more debug */ +#define ddprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args) +#define ddprintk_cont(format, args...) printk(KERN_CONT format, ##args) #else -#define ddprintk(format, args...) \ - do { if (0) printk(KERN_DEBUG format, ##args); } while (0) +#define ddprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __func__, ##args);\ + } while (0) +#define ddprintk_cont(format, args...) \ + do { if (0) printk(KERN_CONT format, ##args); } while (0) #endif - - #define MPOA_TAG_LEN 4 /* mpc_daemon -> kernel */ @@ -302,7 +312,7 @@ static struct mpoa_client *alloc_mpc(void) static void start_mpc(struct mpoa_client *mpc, struct net_device *dev) { - dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); + dprintk("(%s)\n", mpc->dev->name); if (!dev->netdev_ops) pr_info("(%s) not starting\n", dev->name); else { @@ -316,14 +326,14 @@ static void start_mpc(struct mpoa_client *mpc, struct net_device *dev) static void stop_mpc(struct mpoa_client *mpc) { struct net_device *dev = mpc->dev; - dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); + dprintk("(%s)", mpc->dev->name); /* Lets not nullify lec device's dev->hard_start_xmit */ if (dev->netdev_ops != &mpc->new_ops) { - dprintk(" mpc already stopped, not fatal\n"); + dprintk_cont(" mpc already stopped, not fatal\n"); return; } - dprintk("\n"); + dprintk_cont("\n"); dev->netdev_ops = mpc->old_ops; mpc->old_ops = NULL; @@ -371,7 +381,7 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, struct mpoa_client *mpc; mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */ - dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name); + dprintk("(%s) received TLV(s), ", dev->name); dprintk("total length of all TLVs %d\n", sizeoftlvs); mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */ if (mpc == NULL) { @@ -402,7 +412,7 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, } mpoa_device_type = *tlvs++; number_of_mps_macs = *tlvs++; - dprintk("mpoa: (%s) MPOA device type '%s', ", + dprintk("(%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type)); if (mpoa_device_type == MPS_AND_MPC && length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */ @@ -417,7 +427,7 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, } if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) { - dprintk("ignoring non-MPS device\n"); + dprintk("ignoring non-MPS device "); if (mpoa_device_type == MPC) tlvs += 20; continue; /* we are only interested in MPSs */ @@ -427,7 +437,8 @@ static void lane2_assoc_ind(struct net_device *dev, const u8 *mac_addr, pr_info("(%s) MPS_AND_MPC has zero MACs\n", dev->name); continue; /* someone should read the spec */ } - dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs); + dprintk_cont("this MPS has %d MAC addresses\n", + number_of_mps_macs); /* * ok, now we can go and tell our daemon @@ -498,7 +509,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) iph = (struct iphdr *)buff; ipaddr = iph->daddr; - ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", + ddprintk("(%s) ipaddr 0x%x\n", mpc->dev->name, ipaddr); entry = mpc->in_ops->get(ipaddr, mpc); @@ -510,17 +521,17 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) } /* threshold not exceeded or VCC not ready */ if (mpc->in_ops->cache_hit(entry, mpc) != OPEN) { - ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", + ddprintk("(%s) cache_hit: returns != OPEN\n", mpc->dev->name); mpc->in_ops->put(entry); return 1; } - ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", + ddprintk("(%s) using shortcut\n", mpc->dev->name); /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */ if (iph->ttl <= 1) { - ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", + ddprintk("(%s) IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl); mpc->in_ops->put(entry); return 1; @@ -530,7 +541,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); if (entry->ctrl_info.tag != 0) { - ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", + ddprintk("(%s) adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag); tagged_llc_snap_hdr.tag = entry->ctrl_info.tag; skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ @@ -655,25 +666,23 @@ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev) return; } - dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name); + dprintk("(%s)\n", dev->name); in_entry = mpc->in_ops->get_by_vcc(vcc, mpc); if (in_entry) { - dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %pI4\n", + dprintk("(%s) ingress SVC closed ip = %pI4\n", mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); in_entry->shortcut = NULL; mpc->in_ops->put(in_entry); } eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc); if (eg_entry) { - dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", - mpc->dev->name); + dprintk("(%s) egress SVC closed\n", mpc->dev->name); eg_entry->shortcut = NULL; mpc->eg_ops->put(eg_entry); } if (in_entry == NULL && eg_entry == NULL) - dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", - dev->name); + dprintk("(%s) unused vcc closed\n", dev->name); return; } @@ -687,10 +696,9 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) __be32 tag; char *tmp; - ddprintk("mpoa: (%s) mpc_push:\n", dev->name); + ddprintk("(%s)\n", dev->name); if (skb == NULL) { - dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", - dev->name); + dprintk("(%s) null skb, closing VCC\n", dev->name); mpc_vcc_close(vcc, dev); return; } @@ -700,8 +708,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) sizeof(struct llc_snap_hdr)) == 0) { struct sock *sk = sk_atm(vcc); - dprintk("mpoa: (%s) mpc_push: control packet arrived\n", - dev->name); + dprintk("(%s) control packet arrived\n", dev->name); /* Pass control packets to daemon */ skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); @@ -719,8 +726,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */ - ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", - dev->name); + ddprintk("(%s) tagged data packet arrived\n", dev->name); } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */ @@ -813,8 +819,7 @@ static int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg) mpc = find_mpc_by_itfnum(arg); if (mpc == NULL) { - dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", - arg); + dprintk("allocating new mpc for itf %d\n", arg); mpc = alloc_mpc(); if (mpc == NULL) return -ENOMEM; @@ -923,55 +928,54 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb) pr_info("no mpc found\n"); return 0; } - dprintk("mpoa: (%s) msg_from_mpoad:", - (mpc->dev) ? mpc->dev->name : ""); + dprintk("(%s)", mpc->dev ? mpc->dev->name : ""); switch (mesg->type) { case MPOA_RES_REPLY_RCVD: - dprintk(" mpoa_res_reply_rcvd\n"); + dprintk_cont("mpoa_res_reply_rcvd\n"); MPOA_res_reply_rcvd(mesg, mpc); break; case MPOA_TRIGGER_RCVD: - dprintk(" mpoa_trigger_rcvd\n"); + dprintk_cont("mpoa_trigger_rcvd\n"); MPOA_trigger_rcvd(mesg, mpc); break; case INGRESS_PURGE_RCVD: - dprintk(" nhrp_purge_rcvd\n"); + dprintk_cont("nhrp_purge_rcvd\n"); ingress_purge_rcvd(mesg, mpc); break; case EGRESS_PURGE_RCVD: - dprintk(" egress_purge_reply_rcvd\n"); + dprintk_cont("egress_purge_reply_rcvd\n"); egress_purge_rcvd(mesg, mpc); break; case MPS_DEATH: - dprintk(" mps_death\n"); + dprintk_cont("mps_death\n"); mps_death(mesg, mpc); break; case CACHE_IMPOS_RCVD: - dprintk(" cache_impos_rcvd\n"); + dprintk_cont("cache_impos_rcvd\n"); MPOA_cache_impos_rcvd(mesg, mpc); break; case SET_MPC_CTRL_ADDR: - dprintk(" set_mpc_ctrl_addr\n"); + dprintk_cont("set_mpc_ctrl_addr\n"); set_mpc_ctrl_addr_rcvd(mesg, mpc); break; case SET_MPS_MAC_ADDR: - dprintk(" set_mps_mac_addr\n"); + dprintk_cont("set_mps_mac_addr\n"); set_mps_mac_addr_rcvd(mesg, mpc); break; case CLEAN_UP_AND_EXIT: - dprintk(" clean_up_and_exit\n"); + dprintk_cont("clean_up_and_exit\n"); clean_up(mesg, mpc, DIE); break; case RELOAD: - dprintk(" reload\n"); + dprintk_cont("reload\n"); clean_up(mesg, mpc, RELOAD); break; case SET_MPC_PARAMS: - dprintk(" set_mpc_params\n"); + dprintk_cont("set_mpc_params\n"); mpc->parameters = mesg->content.params; break; default: - dprintk(" unknown message %d\n", mesg->type); + dprintk_cont("unknown message %d\n", mesg->type); break; } kfree_skb(skb); @@ -1027,8 +1031,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, priv->lane2_ops->associate_indicator = lane2_assoc_ind; mpc = find_mpc_by_itfnum(priv->itfnum); if (mpc == NULL) { - dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n", - dev->name); + dprintk("allocating new mpc for %s\n", dev->name); mpc = alloc_mpc(); if (mpc == NULL) { pr_info("no new mpc"); @@ -1038,14 +1041,14 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, mpc->dev_num = priv->itfnum; mpc->dev = dev; dev_hold(dev); - dprintk("mpoa: (%s) was initialized\n", dev->name); + dprintk("(%s) was initialized\n", dev->name); break; case NETDEV_UNREGISTER: /* the lec device was deallocated */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; - dprintk("mpoa: device (%s) was deallocated\n", dev->name); + dprintk("device (%s) was deallocated\n", dev->name); stop_mpc(mpc); dev_put(mpc->dev); mpc->dev = NULL; @@ -1143,7 +1146,7 @@ static void check_qos_and_open_shortcut(struct k_message *msg, entry->shortcut = eg_entry->shortcut; } if (entry->shortcut) { - dprintk("mpoa: (%s) using egress SVC to reach %pI4\n", + dprintk("(%s) using egress SVC to reach %pI4\n", client->dev->name, &dst_ip); client->eg_ops->put(eg_entry); return; @@ -1170,16 +1173,16 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) __be32 dst_ip = msg->content.in_info.in_dst_ip; in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc); - dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %pI4\n", + dprintk("(%s) ip %pI4\n", mpc->dev->name, &dst_ip); - ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", + ddprintk("(%s) entry = %p", mpc->dev->name, entry); if (entry == NULL) { pr_info("(%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name); return; } - ddprintk(" entry_state = %d ", entry->entry_state); + ddprintk_cont(" entry_state = %d ", entry->entry_state); if (entry->entry_state == INGRESS_RESOLVED) { pr_info("(%s) RESOLVED entry!\n", mpc->dev->name); @@ -1191,7 +1194,7 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) do_gettimeofday(&(entry->tv)); do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */ entry->refresh_time = 0; - ddprintk("entry->shortcut = %p\n", entry->shortcut); + ddprintk_cont("entry->shortcut = %p\n", entry->shortcut); if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) { @@ -1228,7 +1231,7 @@ static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) } do { - dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %pI4\n", + dprintk("(%s) removing an ingress entry, ip = %pI4\n", mpc->dev->name, &dst_ip); write_lock_bh(&mpc->ingress_lock); mpc->in_ops->remove_entry(entry, mpc); @@ -1246,7 +1249,7 @@ static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc); if (entry == NULL) { - dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", + dprintk("(%s) purge for a non-existing entry\n", mpc->dev->name); return; } @@ -1266,7 +1269,7 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) struct k_message *purge_msg; struct sk_buff *skb; - dprintk("mpoa: purge_egress_shortcut: entering\n"); + dprintk("entering\n"); if (vcc == NULL) { pr_info("vcc == NULL\n"); return; @@ -1290,7 +1293,7 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) sk = sk_atm(vcc); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); - dprintk("mpoa: purge_egress_shortcut: exiting:\n"); + dprintk("exiting\n"); return; } @@ -1303,7 +1306,7 @@ static void mps_death(struct k_message *msg, struct mpoa_client *mpc) { eg_cache_entry *entry; - dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name); + dprintk("(%s)\n", mpc->dev->name); if (memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)) { pr_info("(%s) wrong MPS\n", mpc->dev->name); @@ -1332,7 +1335,7 @@ static void MPOA_cache_impos_rcvd(struct k_message *msg, eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc); holding_time = msg->content.eg_info.holding_time; - dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n", + dprintk("(%s) entry = %p, holding_time = %u\n", mpc->dev->name, entry, holding_time); if (entry == NULL && holding_time) { entry = mpc->eg_ops->add_entry(msg, mpc); @@ -1369,11 +1372,11 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */ memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN); - dprintk("mpoa: (%s) setting MPC ctrl ATM address to ", - (mpc->dev) ? mpc->dev->name : ""); + dprintk("(%s) setting MPC ctrl ATM address to", + mpc->dev ? mpc->dev->name : ""); for (i = 7; i < sizeof(tlv); i++) - dprintk("%02x ", tlv[i]); - dprintk("\n"); + dprintk_cont(" %02x", tlv[i]); + dprintk_cont("\n"); if (mpc->dev) { priv = netdev_priv(mpc->dev); @@ -1424,7 +1427,7 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action) entry = mpc->eg_cache; while (entry != NULL) { msg->content.eg_info = entry->ctrl_info; - dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id); + dprintk("cache_id %u\n", entry->ctrl_info.cache_id); msg_to_mpoad(msg, mpc); entry = entry->next; } @@ -1537,15 +1540,15 @@ static void __exit atm_mpoa_cleanup(void) if (priv->lane2_ops != NULL) priv->lane2_ops->associate_indicator = NULL; } - ddprintk("mpoa: cleanup_module: about to clear caches\n"); + ddprintk("about to clear caches\n"); mpc->in_ops->destroy_cache(mpc); mpc->eg_ops->destroy_cache(mpc); - ddprintk("mpoa: cleanup_module: caches cleared\n"); + ddprintk("caches cleared\n"); kfree(mpc->mps_macs); memset(mpc, 0, sizeof(struct mpoa_client)); - ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc); + ddprintk("about to kfree %p\n", mpc); kfree(mpc); - ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp); + ddprintk("next mpc is at %p\n", tmp); mpc = tmp; } @@ -1553,7 +1556,7 @@ static void __exit atm_mpoa_cleanup(void) qos_head = NULL; while (qos != NULL) { nextqos = qos->next; - dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos); + dprintk("freeing qos entry %p\n", qos); kfree(qos); qos = nextqos; } diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index de21cc66feb4..4c141810eb6d 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -11,17 +11,23 @@ */ #if 0 -#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ +#define dprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */ #else -#define dprintk(format, args...) \ - do { if (0) printk(KERN_DEBUG format, ##args); } while (0) +#define dprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\ + } while (0) #endif #if 0 -#define ddprintk printk(KERN_DEBUG format, ##args) /* more debug */ +#define ddprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */ #else -#define ddprintk(format, args...) \ - do { if (0) printk(KERN_DEBUG format, ##args); } while (0) +#define ddprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\ + } while (0) #endif static in_cache_entry *in_cache_get(__be32 dst_ip, @@ -96,11 +102,10 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip, return NULL; } - dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %pI4\n", - &dst_ip); + dprintk("adding an ingress entry, ip = %pI4\n", &dst_ip); atomic_set(&entry->use, 1); - dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n"); + dprintk("new_in_cache_entry: about to lock\n"); write_lock_bh(&client->ingress_lock); entry->next = client->in_cache; entry->prev = NULL; @@ -118,7 +123,7 @@ static in_cache_entry *in_cache_add_entry(__be32 dst_ip, atomic_inc(&entry->use); write_unlock_bh(&client->ingress_lock); - dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n"); + dprintk("new_in_cache_entry: unlocked\n"); return entry; } @@ -154,7 +159,7 @@ static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc) if (entry->count > mpc->parameters.mpc_p1 && entry->entry_state == INGRESS_INVALID) { - dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %pI4, sending MPOA res req\n", + dprintk("(%s) threshold exceeded for ip %pI4, sending MPOA res req\n", mpc->dev->name, &entry->ctrl_info.in_dst_ip); entry->entry_state = INGRESS_RESOLVING; msg.type = SND_MPOA_RES_RQST; @@ -190,7 +195,7 @@ static void in_cache_remove_entry(in_cache_entry *entry, struct k_message msg; vcc = entry->shortcut; - dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %pI4\n", + dprintk("removing an ingress entry, ip = %pI4\n", &entry->ctrl_info.in_dst_ip); if (entry->prev != NULL) @@ -235,7 +240,7 @@ static void clear_count_and_expired(struct mpoa_client *client) next_entry = entry->next; if ((now.tv_sec - entry->tv.tv_sec) > entry->ctrl_info.holding_time) { - dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %pI4\n", + dprintk("holding time expired, ip = %pI4\n", &entry->ctrl_info.in_dst_ip); client->in_ops->remove_entry(entry, client); } @@ -302,7 +307,7 @@ static void refresh_entries(struct mpoa_client *client) struct timeval now; struct in_cache_entry *entry = client->in_cache; - ddprintk("mpoa: mpoa_caches.c: refresh_entries\n"); + ddprintk("refresh_entries\n"); do_gettimeofday(&now); read_lock_bh(&client->ingress_lock); @@ -312,7 +317,7 @@ static void refresh_entries(struct mpoa_client *client) entry->refresh_time = (2 * (entry->ctrl_info.holding_time))/3; if ((now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time) { - dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n"); + dprintk("refreshing an entry.\n"); entry->entry_state = INGRESS_REFRESHING; } @@ -435,7 +440,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry, struct k_message msg; vcc = entry->shortcut; - dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n"); + dprintk("removing an egress entry.\n"); if (entry->prev != NULL) entry->prev->next = entry->next; else @@ -471,11 +476,11 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, return NULL; } - dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %pI4, this should be our IP\n", + dprintk("adding an egress entry, ip = %pI4, this should be our IP\n", &msg->content.eg_info.eg_dst_ip); atomic_set(&entry->use, 1); - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n"); + dprintk("new_eg_cache_entry: about to lock\n"); write_lock_irq(&client->egress_lock); entry->next = client->eg_cache; entry->prev = NULL; @@ -487,14 +492,13 @@ static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, entry->ctrl_info = msg->content.eg_info; do_gettimeofday(&(entry->tv)); entry->entry_state = EGRESS_RESOLVED; - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %u\n", + dprintk("new_eg_cache_entry cache_id %u\n", ntohl(entry->ctrl_info.cache_id)); - dprintk("mpoa: mpoa_caches.c: mps_ip = %pI4\n", - &entry->ctrl_info.mps_ip); + dprintk("mps_ip = %pI4\n", &entry->ctrl_info.mps_ip); atomic_inc(&entry->use); write_unlock_irq(&client->egress_lock); - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n"); + dprintk("new_eg_cache_entry: unlocked\n"); return entry; } @@ -524,7 +528,7 @@ static void clear_expired(struct mpoa_client *client) > entry->ctrl_info.holding_time) { msg.type = SND_EGRESS_PURGE; msg.content.eg_info = entry->ctrl_info; - dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %u.\n", + dprintk("egress_cache: holding time expired, cache_id = %u.\n", ntohl(entry->ctrl_info.cache_id)); msg_to_mpoad(&msg, client); client->eg_ops->remove_entry(entry, client); diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index aae4a87c22ac..b9bdb98427e4 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -21,10 +21,23 @@ */ #if 1 -#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) /* debug */ +#define dprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */ #else -#define dprintk(format, args...) \ - do { if (0) printk(KERN_DEBUG format, ##args); } while (0) +#define dprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\ + } while (0) +#endif + +#if 0 +#define ddprintk(format, args...) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args) /* debug */ +#else +#define ddprintk(format, args...) \ + do { if (0) \ + printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\ + } while (0) #endif #define STAT_FILE_NAME "mpc" /* Our statistic file's name */ @@ -258,12 +271,9 @@ static int parse_qos(const char *buff) qos.rxtp.max_pcr = rx_pcr; qos.rxtp.max_sdu = rx_sdu; qos.aal = ATM_AAL5; - dprintk("mpoa: mpoa_proc.c: parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", - qos.txtp.max_pcr, - qos.txtp.max_sdu, - qos.rxtp.max_pcr, - qos.rxtp.max_sdu - ); + dprintk("parse_qos(): setting qos paramameters to tx=%d,%d rx=%d,%d\n", + qos.txtp.max_pcr, qos.txtp.max_sdu, + qos.rxtp.max_pcr, qos.rxtp.max_sdu); atm_mpoa_add_qos(ipaddr, &qos); return 1; -- cgit v1.2.3 From 47db3a677b533489d1a5a027282aa33f46dffa79 Mon Sep 17 00:00:00 2001 From: Luca Verdesca Date: Tue, 22 Dec 2009 18:10:01 +0100 Subject: ath5k: adding LED support for AR5BXB63 cards With following patch, LED should now work with LiteOn AR5BXB63 mini pci-e cards. (Broken patch fixed-up by me...let's hope I did it right! -- JWL) Signed-off-by: Luca Verdesca Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/led.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 60f547503d75..67aa52e9bf94 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -77,6 +77,8 @@ static const struct pci_device_id ath5k_led_devices[] = { { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, /* HP Compaq C700 (nitrousnrg@gmail.com) */ { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, + /* LiteOn AR5BXB63 (magooz@salug.it) */ + { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, /* IBM-specific AR5212 (all others) */ { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, /* Dell Vostro A860 (shahar@shahar-or.co.il) */ -- cgit v1.2.3 From d3d5621abf6d2105700795fcbdf784b9cb46b495 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 27 Jan 2010 14:23:17 -0500 Subject: libertas: add comment re: v10 firmware key handling Comment text suggested by Dan Williams in <1263952092.4481.2.camel@localhost.localdomain>. Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 0979b07799a0..f03d5e4e59c3 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -2062,6 +2062,11 @@ void lbs_association_worker(struct work_struct *work) goto out; } + /* + * v10 FW wants WPA keys to be set/cleared before WEP key operations, + * otherwise it will fail to correctly associate to WEP networks. + * Other firmware versions don't appear to care. + */ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { ret = assoc_helper_wpa_keys(priv, assoc_req); -- cgit v1.2.3 From d2bb8e02810cc5844fe2bd5a81d4058b8afe6de9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 26 Jan 2010 16:22:20 -0500 Subject: rtl8180: implement get_tsf op for mac80211 Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8180_dev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 5a2b7199f5d5..109ab1baf625 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -761,6 +761,14 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); } +static u64 rtl8180_get_tsf(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + static const struct ieee80211_ops rtl8180_ops = { .tx = rtl8180_tx, .start = rtl8180_start, @@ -771,6 +779,7 @@ static const struct ieee80211_ops rtl8180_ops = { .bss_info_changed = rtl8180_bss_info_changed, .prepare_multicast = rtl8180_prepare_multicast, .configure_filter = rtl8180_configure_filter, + .get_tsf = rtl8180_get_tsf, }; static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) -- cgit v1.2.3 From da8604757b1cdf79f24e118b156349543eb1b722 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 26 Jan 2010 16:42:02 -0600 Subject: b43: N PHY: Fix compilation after removal of typdef b43_c32 In the conversion between typedef and struct, two places that needed a "struct" were missed. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index df4bf435e218..8c39fb126d4f 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -822,7 +822,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, { int i; u16 bw, len, rot, angle; - b43_c32 *samples; + struct b43_c32 *samples; bw = (dev->phy.is_40mhz) ? 40 : 20; @@ -840,7 +840,7 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, len = bw << 1; } - samples = kzalloc(len * sizeof(b43_c32), GFP_KERNEL); + samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL); rot = (((freq * 36) / bw) << 16) / 100; angle = 0; -- cgit v1.2.3 From 22e16e55e36ab91148592c9bf0f2444bf766cd3c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 26 Jan 2010 17:45:28 -0600 Subject: rtl8187: Add callback for get_tsf Signed-off-by: Larry Finger Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_dev.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index f336c63053c1..a05382557789 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1265,6 +1265,14 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, return 0; } +static u64 rtl8187_get_tsf(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + static const struct ieee80211_ops rtl8187_ops = { .tx = rtl8187_tx, .start = rtl8187_start, @@ -1276,7 +1284,8 @@ static const struct ieee80211_ops rtl8187_ops = { .prepare_multicast = rtl8187_prepare_multicast, .configure_filter = rtl8187_configure_filter, .conf_tx = rtl8187_conf_tx, - .rfkill_poll = rtl8187_rfkill_poll + .rfkill_poll = rtl8187_rfkill_poll, + .get_tsf = rtl8187_get_tsf, }; static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) -- cgit v1.2.3 From 54233261d5aa2926f080b67ac22f508c9f15e690 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 27 Jan 2010 09:44:48 -0500 Subject: cfg80211: fix wext-compat for setting rate to 'auto' Signed-off-by: John W. Linville --- net/wireless/wext-compat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 966d2f01beac..b17eeae448d5 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1214,7 +1214,7 @@ int cfg80211_wext_siwrate(struct net_device *dev, memset(&mask, 0, sizeof(mask)); fixed = 0; - maxrate = 0; + maxrate = (u32)-1; if (rate->value < 0) { /* nothing */ -- cgit v1.2.3 From 257ddbdad13cd3c4f7d03b85af632c508aa8abc9 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 27 Jan 2010 10:17:41 +0000 Subject: netdev: remove HAVE_ leftovers Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- drivers/net/bnx2x_main.c | 4 ++-- drivers/net/cassini.c | 2 +- drivers/net/ixgbevf/ixgbevf_main.c | 18 ------------------ drivers/net/meth.c | 3 --- drivers/staging/wlags49_h2/wl_netdev.c | 6 ------ 6 files changed, 5 insertions(+), 32 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a7b6b12c1c05..5917b941aca2 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7668,7 +7668,7 @@ bnx2_change_mtu(struct net_device *dev, int new_mtu) return (bnx2_change_ring_size(bp, bp->rx_ring_size, bp->tx_ring_size)); } -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) +#ifdef CONFIG_NET_POLL_CONTROLLER static void poll_bnx2(struct net_device *dev) { @@ -8280,7 +8280,7 @@ static const struct net_device_ops bnx2_netdev_ops = { #ifdef BCM_VLAN .ndo_vlan_rx_register = bnx2_vlan_rx_register, #endif -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) +#ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2, #endif }; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ca4ed634d55e..ffc7381969ae 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11731,7 +11731,7 @@ static void bnx2x_vlan_rx_register(struct net_device *dev, #endif -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) +#ifdef CONFIG_NET_POLL_CONTROLLER static void poll_bnx2x(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); @@ -11755,7 +11755,7 @@ static const struct net_device_ops bnx2x_netdev_ops = { #ifdef BCM_VLAN .ndo_vlan_rx_register = bnx2x_vlan_rx_register, #endif -#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER) +#ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2x, #endif }; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index b3a038c23af1..ad47e5126fde 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -106,7 +106,7 @@ #define cas_page_unmap(x) kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ) #define CAS_NCPUS num_online_cpus() -#if defined(CONFIG_CASSINI_NAPI) && defined(HAVE_NETDEV_POLL) +#ifdef CONFIG_CASSINI_NAPI #define USE_NAPI #define cas_skb_release(x) netif_receive_skb(x) #else diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 7b3af107ca84..b9f10d05049d 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -3262,7 +3262,6 @@ static void ixgbevf_shutdown(struct pci_dev *pdev) pci_disable_device(pdev); } -#ifdef HAVE_NET_DEVICE_OPS static const struct net_device_ops ixgbe_netdev_ops = { .ndo_open = &ixgbevf_open, .ndo_stop = &ixgbevf_close, @@ -3278,29 +3277,12 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid, }; -#endif /* HAVE_NET_DEVICE_OPS */ static void ixgbevf_assign_netdev_ops(struct net_device *dev) { struct ixgbevf_adapter *adapter; adapter = netdev_priv(dev); -#ifdef HAVE_NET_DEVICE_OPS dev->netdev_ops = &ixgbe_netdev_ops; -#else /* HAVE_NET_DEVICE_OPS */ - dev->open = &ixgbevf_open; - dev->stop = &ixgbevf_close; - - dev->hard_start_xmit = &ixgbevf_xmit_frame; - - dev->get_stats = &ixgbevf_get_stats; - dev->set_multicast_list = &ixgbevf_set_rx_mode; - dev->set_mac_address = &ixgbevf_set_mac; - dev->change_mtu = &ixgbevf_change_mtu; - dev->tx_timeout = &ixgbevf_tx_timeout; - dev->vlan_rx_register = &ixgbevf_vlan_rx_register; - dev->vlan_rx_add_vid = &ixgbevf_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = &ixgbevf_vlan_rx_kill_vid; -#endif /* HAVE_NET_DEVICE_OPS */ ixgbevf_set_ethtool_ops(dev); dev->watchdog_timeo = 5 * HZ; } diff --git a/drivers/net/meth.c b/drivers/net/meth.c index 2af81735386b..9f72cb45f4af 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -51,14 +51,11 @@ static const char *meth_str="SGI O2 Fast Ethernet"; -#define HAVE_TX_TIMEOUT /* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */ #define TX_TIMEOUT (400*HZ/1000) -#ifdef HAVE_TX_TIMEOUT static int timeout = TX_TIMEOUT; module_param(timeout, int, 0); -#endif /* * This structure is private to each device. It is used to pass diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c index ac3890247965..0d22e3692fe5 100644 --- a/drivers/staging/wlags49_h2/wl_netdev.c +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -1194,9 +1194,7 @@ static const struct net_device_ops wl_netdev_ops = .ndo_stop = &wl_adapter_close, .ndo_do_ioctl = &wl_ioctl, -#ifdef HAVE_TX_TIMEOUT .ndo_tx_timeout = &wl_tx_timeout, -#endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = wl_poll, @@ -1270,9 +1268,7 @@ struct net_device * wl_device_alloc( void ) dev->stop = &wl_adapter_close; dev->do_ioctl = &wl_ioctl; -#ifdef HAVE_TX_TIMEOUT dev->tx_timeout = &wl_tx_timeout; -#endif #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = wl_poll; @@ -1280,9 +1276,7 @@ struct net_device * wl_device_alloc( void ) #endif // (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) -#ifdef HAVE_TX_TIMEOUT dev->watchdog_timeo = TX_TIMEOUT; -#endif dev->ethtool_ops = &wl_ethtool_ops; -- cgit v1.2.3 From ce96bc86bf2ee12e8a3bf461ca8027557c1ef42f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 28 Jan 2010 06:13:13 -0800 Subject: net: merge fixup for qlge_main Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 4adca94a521f..5be3ae2f5a16 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4499,7 +4499,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, if (qdev->mpi_coredump == NULL) { dev_err(&pdev->dev, "Coredump alloc failed.\n"); err = -ENOMEM; - goto err_out; + goto err_out2; } if (qlge_force_coredump) set_bit(QL_FRC_COREDUMP, &qdev->flags); -- cgit v1.2.3 From e924960dacdf85d118a98c7262edf2f99c3015cf Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:28:21 +0000 Subject: netns xfrm: fixup xfrm6_tunnel error propagation Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/xfrm6_tunnel.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 438831d33593..23fb1002124c 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -353,13 +353,19 @@ static struct xfrm6_tunnel xfrm46_tunnel_handler = { static int __init xfrm6_tunnel_init(void) { - if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) + int rv; + + rv = xfrm_register_type(&xfrm6_tunnel_type, AF_INET6); + if (rv < 0) goto err; - if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) + rv = xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6); + if (rv < 0) goto unreg; - if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) + rv = xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET); + if (rv < 0) goto dereg6; - if (xfrm6_tunnel_spi_init() < 0) + rv = xfrm6_tunnel_spi_init(); + if (rv < 0) goto dereg46; return 0; @@ -370,7 +376,7 @@ dereg6: unreg: xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); err: - return -EAGAIN; + return rv; } static void __exit xfrm6_tunnel_fini(void) -- cgit v1.2.3 From a1664773907a2b69e2a3019598dcbeffa6bc724b Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:37:54 +0000 Subject: netns xfrm: xfrm6_tunnel in netns I'm not sure about rcu stuff near kmem cache destruction: * checks for non-empty hashes look bogus, they're done _before_ rcu_berrier() * unregistering netns ops is done before kmem_cache destoy (as it should), and unregistering involves rcu barriers by itself So it looks nothing should be done. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 6 +-- net/ipv6/ipcomp6.c | 4 +- net/ipv6/xfrm6_tunnel.c | 140 ++++++++++++++++++++++++++++-------------------- 3 files changed, 88 insertions(+), 62 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 60c27706e7b9..fcee547ca7e3 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1408,9 +1408,9 @@ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); -extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); -extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); -extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr); +extern void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr); +extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr); extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_output(struct sk_buff *skb); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 2f2a5ca2c878..1d1faf757c9a 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -81,7 +81,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) goto out; t->id.proto = IPPROTO_IPV6; - t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); + t->id.spi = xfrm6_tunnel_alloc_spi(&init_net, (xfrm_address_t *)&x->props.saddr); if (!t->id.spi) goto error; @@ -112,7 +112,7 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x) struct xfrm_state *t = NULL; __be32 spi; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr); + spi = xfrm6_tunnel_spi_lookup(&init_net, (xfrm_address_t *)&x->props.saddr); if (spi) t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 23fb1002124c..d6f9aeec69f7 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -30,6 +30,25 @@ #include #include #include +#include + +#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 +#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 + +#define XFRM6_TUNNEL_SPI_MIN 1 +#define XFRM6_TUNNEL_SPI_MAX 0xffffffff + +struct xfrm6_tunnel_net { + struct hlist_head spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; + struct hlist_head spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; + u32 spi; +}; + +static int xfrm6_tunnel_net_id __read_mostly; +static inline struct xfrm6_tunnel_net *xfrm6_tunnel_pernet(struct net *net) +{ + return net_generic(net, xfrm6_tunnel_net_id); +} /* * xfrm_tunnel_spi things are for allocating unique id ("spi") @@ -46,19 +65,8 @@ struct xfrm6_tunnel_spi { static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock); -static u32 xfrm6_tunnel_spi; - -#define XFRM6_TUNNEL_SPI_MIN 1 -#define XFRM6_TUNNEL_SPI_MAX 0xffffffff - static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; -#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 -#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 - -static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE]; -static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE]; - static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) { unsigned h; @@ -77,49 +85,30 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) } -static int xfrm6_tunnel_spi_init(void) +static int __init xfrm6_tunnel_spi_init(void) { - int i; - - xfrm6_tunnel_spi = 0; xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", sizeof(struct xfrm6_tunnel_spi), 0, SLAB_HWCACHE_ALIGN, NULL); if (!xfrm6_tunnel_spi_kmem) return -ENOMEM; - - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) - INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]); - for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) - INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byspi[i]); return 0; } static void xfrm6_tunnel_spi_fini(void) { - int i; - - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) { - if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i])) - return; - } - for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) { - if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i])) - return; - } - rcu_barrier(); kmem_cache_destroy(xfrm6_tunnel_spi_kmem); - xfrm6_tunnel_spi_kmem = NULL; } -static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos; hlist_for_each_entry_rcu(x6spi, pos, - &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) return x6spi; @@ -128,13 +117,13 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) return NULL; } -__be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; rcu_read_lock_bh(); - x6spi = __xfrm6_tunnel_spi_lookup(saddr); + x6spi = __xfrm6_tunnel_spi_lookup(net, saddr); spi = x6spi ? x6spi->spi : 0; rcu_read_unlock_bh(); return htonl(spi); @@ -142,14 +131,15 @@ __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); -static int __xfrm6_tunnel_spi_check(u32 spi) +static int __xfrm6_tunnel_spi_check(struct net *net, u32 spi) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; int index = xfrm6_tunnel_spi_hash_byspi(spi); struct hlist_node *pos; hlist_for_each_entry(x6spi, pos, - &xfrm6_tunnel_spi_byspi[index], + &xfrm6_tn->spi_byspi[index], list_byspi) { if (x6spi->spi == spi) return -1; @@ -157,32 +147,33 @@ static int __xfrm6_tunnel_spi_check(u32 spi) return index; } -static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +static u32 __xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); u32 spi; struct xfrm6_tunnel_spi *x6spi; int index; - if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN || - xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX) - xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN; + if (xfrm6_tn->spi < XFRM6_TUNNEL_SPI_MIN || + xfrm6_tn->spi >= XFRM6_TUNNEL_SPI_MAX) + xfrm6_tn->spi = XFRM6_TUNNEL_SPI_MIN; else - xfrm6_tunnel_spi++; + xfrm6_tn->spi++; - for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { - index = __xfrm6_tunnel_spi_check(spi); + for (spi = xfrm6_tn->spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { + index = __xfrm6_tunnel_spi_check(net, spi); if (index >= 0) goto alloc_spi; } - for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { - index = __xfrm6_tunnel_spi_check(spi); + for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tn->spi; spi++) { + index = __xfrm6_tunnel_spi_check(net, spi); if (index >= 0) goto alloc_spi; } spi = 0; goto out; alloc_spi: - xfrm6_tunnel_spi = spi; + xfrm6_tn->spi = spi; x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, GFP_ATOMIC); if (!x6spi) goto out; @@ -192,26 +183,26 @@ alloc_spi: x6spi->spi = spi; atomic_set(&x6spi->refcnt, 1); - hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]); + hlist_add_head_rcu(&x6spi->list_byspi, &xfrm6_tn->spi_byspi[index]); index = xfrm6_tunnel_spi_hash_byaddr(saddr); - hlist_add_head_rcu(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]); + hlist_add_head_rcu(&x6spi->list_byaddr, &xfrm6_tn->spi_byaddr[index]); out: return spi; } -__be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) +__be32 xfrm6_tunnel_alloc_spi(struct net *net, xfrm_address_t *saddr) { struct xfrm6_tunnel_spi *x6spi; u32 spi; spin_lock_bh(&xfrm6_tunnel_spi_lock); - x6spi = __xfrm6_tunnel_spi_lookup(saddr); + x6spi = __xfrm6_tunnel_spi_lookup(net, saddr); if (x6spi) { atomic_inc(&x6spi->refcnt); spi = x6spi->spi; } else - spi = __xfrm6_tunnel_alloc_spi(saddr); + spi = __xfrm6_tunnel_alloc_spi(net, saddr); spin_unlock_bh(&xfrm6_tunnel_spi_lock); return htonl(spi); @@ -225,15 +216,16 @@ static void x6spi_destroy_rcu(struct rcu_head *head) container_of(head, struct xfrm6_tunnel_spi, rcu_head)); } -void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) +void xfrm6_tunnel_free_spi(struct net *net, xfrm_address_t *saddr) { + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); struct xfrm6_tunnel_spi *x6spi; struct hlist_node *pos, *n; spin_lock_bh(&xfrm6_tunnel_spi_lock); hlist_for_each_entry_safe(x6spi, pos, n, - &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + &xfrm6_tn->spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], list_byaddr) { if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { @@ -263,10 +255,11 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) static int xfrm6_tunnel_rcv(struct sk_buff *skb) { + struct net *net = dev_net(skb->dev); struct ipv6hdr *iph = ipv6_hdr(skb); __be32 spi; - spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); + spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&iph->saddr); return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; } @@ -326,7 +319,9 @@ static int xfrm6_tunnel_init_state(struct xfrm_state *x) static void xfrm6_tunnel_destroy(struct xfrm_state *x) { - xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); + struct net *net = xs_net(x); + + xfrm6_tunnel_free_spi(net, (xfrm_address_t *)&x->props.saddr); } static const struct xfrm_type xfrm6_tunnel_type = { @@ -351,6 +346,31 @@ static struct xfrm6_tunnel xfrm46_tunnel_handler = { .priority = 2, }; +static int __net_init xfrm6_tunnel_net_init(struct net *net) +{ + struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); + unsigned int i; + + for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tn->spi_byaddr[i]); + for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) + INIT_HLIST_HEAD(&xfrm6_tn->spi_byspi[i]); + xfrm6_tn->spi = 0; + + return 0; +} + +static void __net_exit xfrm6_tunnel_net_exit(struct net *net) +{ +} + +static struct pernet_operations xfrm6_tunnel_net_ops = { + .init = xfrm6_tunnel_net_init, + .exit = xfrm6_tunnel_net_exit, + .id = &xfrm6_tunnel_net_id, + .size = sizeof(struct xfrm6_tunnel_net), +}; + static int __init xfrm6_tunnel_init(void) { int rv; @@ -367,8 +387,13 @@ static int __init xfrm6_tunnel_init(void) rv = xfrm6_tunnel_spi_init(); if (rv < 0) goto dereg46; + rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); + if (rv < 0) + goto deregspi; return 0; +deregspi: + xfrm6_tunnel_spi_fini(); dereg46: xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); dereg6: @@ -381,6 +406,7 @@ err: static void __exit xfrm6_tunnel_fini(void) { + unregister_pernet_subsys(&xfrm6_tunnel_net_ops); xfrm6_tunnel_spi_fini(); xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); -- cgit v1.2.3 From a92df2545402c1a08e7a158f4477a52dea0eeeed Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:38:34 +0000 Subject: netns xfrm: ipcomp support Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv4/ipcomp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 38fbf04150ae..b55a0c3df82f 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -25,6 +25,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) { + struct net *net = dev_net(skb->dev); __be32 spi; struct iphdr *iph = (struct iphdr *)skb->data; struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); @@ -35,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) return; spi = htonl(ntohs(ipch->cpi)); - x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) return; @@ -47,9 +48,10 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) /* We always hold one tunnel user reference to indicate a tunnel */ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) { + struct net *net = xs_net(x); struct xfrm_state *t; - t = xfrm_state_alloc(&init_net); + t = xfrm_state_alloc(net); if (t == NULL) goto out; @@ -82,10 +84,11 @@ error: */ static int ipcomp_tunnel_attach(struct xfrm_state *x) { + struct net *net = xs_net(x); int err = 0; struct xfrm_state *t; - t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr.a4, + t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr.a4, x->props.saddr.a4, IPPROTO_IPIP, AF_INET); if (!t) { t = ipcomp_tunnel_create(x); -- cgit v1.2.3 From d74340d31bf1dbeb00acadddd8697666528a7846 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 25 Jan 2010 10:39:09 +0000 Subject: netns xfrm: ipcomp6 support Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/ipcomp6.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 1d1faf757c9a..a9fbb151bb79 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -53,6 +53,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { + struct net *net = dev_net(skb->dev); __be32 spi; struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; struct ip_comp_hdr *ipcomph = @@ -63,7 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; spi = htonl(ntohs(ipcomph->cpi)); - x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); + x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -74,14 +75,15 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) { + struct net *net = xs_net(x); struct xfrm_state *t = NULL; - t = xfrm_state_alloc(&init_net); + t = xfrm_state_alloc(net); if (!t) goto out; t->id.proto = IPPROTO_IPV6; - t->id.spi = xfrm6_tunnel_alloc_spi(&init_net, (xfrm_address_t *)&x->props.saddr); + t->id.spi = xfrm6_tunnel_alloc_spi(net, (xfrm_address_t *)&x->props.saddr); if (!t->id.spi) goto error; @@ -108,13 +110,14 @@ error: static int ipcomp6_tunnel_attach(struct xfrm_state *x) { + struct net *net = xs_net(x); int err = 0; struct xfrm_state *t = NULL; __be32 spi; - spi = xfrm6_tunnel_spi_lookup(&init_net, (xfrm_address_t *)&x->props.saddr); + spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr); if (spi) - t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr, + t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); if (!t) { t = ipcomp6_tunnel_create(x); -- cgit v1.2.3 From c1596b75c29eb5b32c65ef1e186c8b08c289bf05 Mon Sep 17 00:00:00 2001 From: Hamish Guthrie Date: Thu, 28 Jan 2010 12:54:09 +0100 Subject: ps3_gelic_wireless: Remove PS3 gelic legacy wpa support The current PS3 gelic wireless driver has support for wireless extensions. The original PS3 gelic wireless driver exposed a dedicated API for a dedicated wpa_supplicant driver. This old API could be enabled with CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE, however, as this is not being used by any distros, and it is being removed from the driver and from wpa_supplicant. Signed-off-by: Hamish Guthrie Acked-by: Geoff Levand Signed-off-by: John W. Linville --- arch/powerpc/configs/ppc64_defconfig | 1 - arch/powerpc/configs/ps3_defconfig | 1 - drivers/net/Kconfig | 14 ---- drivers/net/ps3_gelic_wireless.c | 137 ----------------------------------- 4 files changed, 153 deletions(-) diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 252401824575..070587ae4f74 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -1000,7 +1000,6 @@ CONFIG_TIGON3=y CONFIG_SPIDER_NET=m CONFIG_GELIC_NET=m CONFIG_GELIC_WIRELESS=y -# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 7de127e4ceef..32f7058bb173 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig @@ -593,7 +593,6 @@ CONFIG_MII=m CONFIG_NETDEV_1000=y CONFIG_GELIC_NET=y CONFIG_GELIC_WIRELESS=y -# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set # CONFIG_NETDEV_10000 is not set # diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 18ff622703be..6460505ab24c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2354,20 +2354,6 @@ config GELIC_WIRELESS the driver automatically distinguishes the models, you can safely enable this option even if you have a wireless-less model. -config GELIC_WIRELESS_OLD_PSK_INTERFACE - bool "PS3 Wireless private PSK interface (OBSOLETE)" - depends on GELIC_WIRELESS - select WEXT_PRIV - help - This option retains the obsolete private interface to pass - the PSK from user space programs to the driver. The PSK - stands for 'Pre Shared Key' and is used for WPA[2]-PSK - (WPA-Personal) environment. - If WPA[2]-PSK is used and you need to use old programs that - support only this old interface, say Y. Otherwise N. - - If unsure, say N. - config FSL_PQ_MDIO tristate "Freescale PQ MDIO" depends on FSL_SOC diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 227b141c4fbd..7571dbba6a0a 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -1389,113 +1389,6 @@ static int gelic_wl_get_mode(struct net_device *netdev, return 0; } -#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE -/* SIOCIWFIRSTPRIV */ -static int hex2bin(u8 *str, u8 *bin, unsigned int len) -{ - unsigned int i; - static unsigned char *hex = "0123456789ABCDEF"; - unsigned char *p, *q; - u8 tmp; - - if (len != WPA_PSK_LEN * 2) - return -EINVAL; - - for (i = 0; i < WPA_PSK_LEN * 2; i += 2) { - p = strchr(hex, toupper(str[i])); - q = strchr(hex, toupper(str[i + 1])); - if (!p || !q) { - pr_info("%s: unconvertible PSK digit=%d\n", - __func__, i); - return -EINVAL; - } - tmp = ((p - hex) << 4) + (q - hex); - *bin++ = tmp; - } - return 0; -}; - -static int gelic_wl_priv_set_psk(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); - unsigned int len; - unsigned long irqflag; - int ret = 0; - - pr_debug("%s:<- len=%d\n", __func__, data->data.length); - len = data->data.length - 1; - if (len <= 2) - return -EINVAL; - - spin_lock_irqsave(&wl->lock, irqflag); - if (extra[0] == '"' && extra[len - 1] == '"') { - pr_debug("%s: passphrase mode\n", __func__); - /* pass phrase */ - if (GELIC_WL_EURUS_PSK_MAX_LEN < (len - 2)) { - pr_info("%s: passphrase too long\n", __func__); - ret = -E2BIG; - goto out; - } - memset(wl->psk, 0, sizeof(wl->psk)); - wl->psk_len = len - 2; - memcpy(wl->psk, &(extra[1]), wl->psk_len); - wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE; - } else { - ret = hex2bin(extra, wl->psk, len); - if (ret) - goto out; - wl->psk_len = WPA_PSK_LEN; - wl->psk_type = GELIC_EURUS_WPA_PSK_BIN; - } - set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat); -out: - spin_unlock_irqrestore(&wl->lock, irqflag); - pr_debug("%s:->\n", __func__); - return ret; -} - -static int gelic_wl_priv_get_psk(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, char *extra) -{ - struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); - char *p; - unsigned long irqflag; - unsigned int i; - - pr_debug("%s:<-\n", __func__); - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&wl->lock, irqflag); - p = extra; - if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) { - if (wl->psk_type == GELIC_EURUS_WPA_PSK_BIN) { - for (i = 0; i < wl->psk_len; i++) { - sprintf(p, "%02xu", wl->psk[i]); - p += 2; - } - *p = '\0'; - data->data.length = wl->psk_len * 2; - } else { - *p++ = '"'; - memcpy(p, wl->psk, wl->psk_len); - p += wl->psk_len; - *p++ = '"'; - *p = '\0'; - data->data.length = wl->psk_len + 2; - } - } else - /* no psk set */ - data->data.length = 0; - spin_unlock_irqrestore(&wl->lock, irqflag); - pr_debug("%s:-> %d\n", __func__, data->data.length); - return 0; -} -#endif - /* SIOCGIWNICKN */ static int gelic_wl_get_nick(struct net_device *net_dev, struct iw_request_info *info, @@ -2406,40 +2299,10 @@ static const iw_handler gelic_wl_wext_handler[] = IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick, }; -#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE -static struct iw_priv_args gelic_wl_private_args[] = -{ - { - .cmd = GELIC_WL_PRIV_SET_PSK, - .set_args = IW_PRIV_TYPE_CHAR | - (GELIC_WL_EURUS_PSK_MAX_LEN + 2), - .name = "set_psk" - }, - { - .cmd = GELIC_WL_PRIV_GET_PSK, - .get_args = IW_PRIV_TYPE_CHAR | - (GELIC_WL_EURUS_PSK_MAX_LEN + 2), - .name = "get_psk" - } -}; - -static const iw_handler gelic_wl_private_handler[] = -{ - gelic_wl_priv_set_psk, - gelic_wl_priv_get_psk, -}; -#endif - static const struct iw_handler_def gelic_wl_wext_handler_def = { .num_standard = ARRAY_SIZE(gelic_wl_wext_handler), .standard = gelic_wl_wext_handler, .get_wireless_stats = gelic_wl_get_wireless_stats, -#ifdef CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE - .num_private = ARRAY_SIZE(gelic_wl_private_handler), - .num_private_args = ARRAY_SIZE(gelic_wl_private_args), - .private = gelic_wl_private_handler, - .private_args = gelic_wl_private_args, -#endif }; static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card) -- cgit v1.2.3 From f276586a8af410d2b79733daf52471605b6559e9 Mon Sep 17 00:00:00 2001 From: Hamish Guthrie Date: Thu, 28 Jan 2010 12:54:10 +0100 Subject: ps3_gelic_wireless: fix directed ssid scan If the association worker requests a directed ssid scan and a bss list already exists, the directed scan is not done. This patch corrects this and cleans up a few typos and debug messages. Signed-off-by: Hamish Guthrie Acked-by: Geoff Levand Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 7571dbba6a0a..d520e9e8cdb2 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -1449,7 +1449,8 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, void *buf = NULL; size_t len; - pr_debug("%s: <- always=%d\n", __func__, always_scan); + pr_debug("%s: <- always=%d essid_len=%d\n", __func__, + always_scan, essid_len); if (mutex_lock_interruptible(&wl->scan_lock)) return -ERESTARTSYS; @@ -1464,8 +1465,10 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, init_completion(&wl->scan_done); /* * If we have already a bss list, don't try to get new + * unless we are doing an ESSID scan */ - if (!always_scan && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { + if ((!essid_len && !always_scan) + && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { pr_debug("%s: already has the list\n", __func__); complete(&wl->scan_done); goto out; @@ -1566,7 +1569,7 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) } } - /* put them in the newtork_list */ + /* put them in the network_list */ for (i = 0, scan_info_size = 0, scan_info = buf; scan_info_size < data_len; i++, scan_info_size += be16_to_cpu(scan_info->size), @@ -1902,7 +1905,7 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) /* PSK type */ wpa->psk_type = cpu_to_be16(wl->psk_type); #ifdef DEBUG - pr_debug("%s: sec=%s psktype=%s\nn", __func__, + pr_debug("%s: sec=%s psktype=%s\n", __func__, wpasecstr(wpa->security), (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? "BIN" : "passphrase"); @@ -1912,9 +1915,9 @@ static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) * the debug log because this dumps your precious * passphrase/key. */ - pr_debug("%s: psk=%s\n", + pr_debug("%s: psk=%s\n", __func__, (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? - (char *)"N/A" : (char *)wpa->psk); + "N/A" : wpa->psk); #endif #endif /* issue wpa setup */ -- cgit v1.2.3 From 57dbb2d83d100ea601c54fe129bfde0678db5dee Mon Sep 17 00:00:00 2001 From: Hagen Paul Pfeifer Date: Sun, 24 Jan 2010 12:30:59 +0000 Subject: sched: add head drop fifo queue This adds an additional queuing strategy, called pfifo_head_drop, to remove the oldest skb in the case of an overflow within the queue - the head element - instead of the last skb (tail). To remove the oldest skb in congested situations is useful for sensor network environments where newer packets reflect the superior information. Reviewed-by: Florian Westphal Acked-by: Patrick McHardy Signed-off-by: Hagen Paul Pfeifer Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 1 + include/net/sch_generic.h | 19 +++++++++++++++++++ net/sched/sch_api.c | 1 + net/sched/sch_fifo.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 2d567265363e..b6cdc33b39c1 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -71,6 +71,7 @@ extern void qdisc_watchdog_cancel(struct qdisc_watchdog *wd); extern struct Qdisc_ops pfifo_qdisc_ops; extern struct Qdisc_ops bfifo_qdisc_ops; +extern struct Qdisc_ops pfifo_head_drop_qdisc_ops; extern int fifo_set_limit(struct Qdisc *q, unsigned int limit); extern struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops, diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index dad558bc06fa..67dc08eaaa45 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -427,6 +427,25 @@ static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) return __qdisc_dequeue_head(sch, &sch->q); } +static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch, + struct sk_buff_head *list) +{ + struct sk_buff *skb = __qdisc_dequeue_head(sch, list); + + if (likely(skb != NULL)) { + unsigned int len = qdisc_pkt_len(skb); + kfree_skb(skb); + return len; + } + + return 0; +} + +static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch) +{ + return __qdisc_queue_drop_head(sch, &sch->q); +} + static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch, struct sk_buff_head *list) { diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 75fd1c672c61..6cd491013b50 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1707,6 +1707,7 @@ static int __init pktsched_init(void) { register_qdisc(&pfifo_qdisc_ops); register_qdisc(&bfifo_qdisc_ops); + register_qdisc(&pfifo_head_drop_qdisc_ops); register_qdisc(&mq_qdisc_ops); proc_net_fops_create(&init_net, "psched", 0, &psched_fops); diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 69188e8358b4..4b0a6cc44c77 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -43,6 +43,26 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_reshape_fail(skb, sch); } +static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch) +{ + struct sk_buff *skb_head; + struct fifo_sched_data *q = qdisc_priv(sch); + + if (likely(skb_queue_len(&sch->q) < q->limit)) + return qdisc_enqueue_tail(skb, sch); + + /* queue full, remove one skb to fulfill the limit */ + skb_head = qdisc_dequeue_head(sch); + sch->bstats.bytes -= qdisc_pkt_len(skb_head); + sch->bstats.packets--; + sch->qstats.drops++; + kfree_skb(skb_head); + + qdisc_enqueue_tail(skb, sch); + + return NET_XMIT_CN; +} + static int fifo_init(struct Qdisc *sch, struct nlattr *opt) { struct fifo_sched_data *q = qdisc_priv(sch); @@ -108,6 +128,20 @@ struct Qdisc_ops bfifo_qdisc_ops __read_mostly = { }; EXPORT_SYMBOL(bfifo_qdisc_ops); +struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = { + .id = "pfifo_head_drop", + .priv_size = sizeof(struct fifo_sched_data), + .enqueue = pfifo_tail_enqueue, + .dequeue = qdisc_dequeue_head, + .peek = qdisc_peek_head, + .drop = qdisc_queue_drop_head, + .init = fifo_init, + .reset = qdisc_reset_queue, + .change = fifo_init, + .dump = fifo_dump, + .owner = THIS_MODULE, +}; + /* Pass size change message down to embedded FIFO */ int fifo_set_limit(struct Qdisc *q, unsigned int limit) { -- cgit v1.2.3 From 1dbfd9d46a6df5232ba0b12d2da950da89eff3da Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Fri, 29 Jan 2010 16:56:51 +0530 Subject: ath9k: Handle full sleep in ps_restore. IDLE PS (Full Sleep) doesn't work when ifconfig up is done during Idle unassociated state. Fix this by restoring FULL SLEEP in ps_restore if CONF_IDLE is set. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bdbcc70df075..3f8a7e773d55 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -480,6 +480,7 @@ struct ath_softc { u8 nbcnvifs; u16 nvifs; bool ps_enabled; + bool ps_idle; unsigned long ps_usecount; enum ath9k_int imask; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6f3e71c5071e..e04835cb21b5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -143,8 +143,10 @@ void ath9k_ps_restore(struct ath_softc *sc) if (--sc->ps_usecount != 0) goto unlock; - if (sc->ps_enabled && - !(sc->ps_flags & (PS_WAIT_FOR_BEACON | + if (sc->ps_idle) + ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); + else if (sc->ps_enabled && + !(sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK))) @@ -1528,6 +1530,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) spin_unlock_bh(&sc->wiphy_lock); if (enable_radio) { + sc->ps_idle = false; ath_radio_enable(sc, hw); ath_print(common, ATH_DBG_CONFIG, "not-idle: enabling radio\n"); @@ -1635,6 +1638,7 @@ skip_chan_change: if (disable_radio) { ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); + sc->ps_idle = true; ath_radio_disable(sc, hw); } -- cgit v1.2.3 From 49dcc819b077c2d473062e17d5a1373a8b660e02 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Tue, 19 Jan 2010 10:22:19 -0800 Subject: iwlwifi: optimize power saving In hostap AP mode, every time the client sends the AP a packet the STA_NOTIFY_AWAKE code is sent from mac80211. This results in a command being sent to the uCode even if the client was not asleep. The following simple patch has fixed the issue for me without any degradation that I can find. Signed-off-by: Daniel Halperin Acked-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4a268927377b..380d2087bf3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3007,6 +3007,8 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, break; case STA_NOTIFY_AWAKE: WARN_ON(!sta_priv->client); + if (!sta_priv->asleep) + break; sta_priv->asleep = false; sta_id = iwl_find_station(priv, sta->addr); if (sta_id != IWL_INVALID_STATION) -- cgit v1.2.3 From a7fce6ee8dd693fb2a9d19ddf9ee1fe380893fa1 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 19 Jan 2010 16:51:50 -0800 Subject: iwlwifi: sysassert identifier change Change in uCode to include a unique identifier as part of sysassert, in order to tell the difference, add the "ADVANCED SYSASSERT" description when dump nic error to indicate the difference. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 380d2087bf3a..1c54425afe22 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1757,7 +1757,7 @@ static const char *desc_lookup_text[] = { "DEBUG_1", "DEBUG_2", "DEBUG_3", - "UNKNOWN" + "ADVANCED SYSASSERT" }; static const char *desc_lookup(int i) -- cgit v1.2.3 From 47e28f41dce90ea4317d35cf23f232c1a6b07adf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 20 Jan 2010 11:21:06 -0800 Subject: iwlwifi: fix locking in iwl_mac_add_interface The corresponding iwl_mac_remove_interface only acquires the mutex, leading me to believe that the spinlock is not necessary. However, this doesn't actually acquire the mutex around the vif pointer check and assignment, fix that. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 1cfabd6be0b8..02bf17ecaf54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2631,23 +2631,21 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; - unsigned long flags; + int err = 0; IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); + mutex_lock(&priv->mutex); + if (priv->vif) { IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto out; } - spin_lock_irqsave(&priv->lock, flags); priv->vif = vif; priv->iw_mode = vif->type; - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - if (vif->addr) { IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); memcpy(priv->mac_addr, vif->addr, ETH_ALEN); @@ -2657,10 +2655,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, /* we are not ready, will run again when ready */ set_bit(STATUS_MODE_PENDING, &priv->status); + out: mutex_unlock(&priv->mutex); IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; + return err; } EXPORT_SYMBOL(iwl_mac_add_interface); -- cgit v1.2.3 From 2494f63cc7394fc4424c4833b83d1831f52e54c8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 20 Jan 2010 12:22:52 -0800 Subject: iwlwifi: update sensitivity calibration data for 6x00 series Update sensitivity range values for 6000 & 6x50 series Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 81e03e33ec73..a9f8551e0e40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -108,7 +108,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { .auto_corr_max_ofdm = 145, .auto_corr_max_ofdm_mrc = 232, - .auto_corr_max_ofdm_x1 = 145, + .auto_corr_max_ofdm_x1 = 110, .auto_corr_max_ofdm_mrc_x1 = 232, .auto_corr_min_cck = 125, -- cgit v1.2.3 From 9bead7632adb6341548056a80ec36e7ae098f4f4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 20 Jan 2010 12:22:53 -0800 Subject: iwlwifi: update sensitivity calibration data for 5x00 series Update sensitivity range values for 5x00 series Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6027e2a658d1..6bb433a0e535 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -263,8 +263,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { .auto_corr_max_ofdm = 120, .auto_corr_max_ofdm_mrc = 210, - .auto_corr_max_ofdm_x1 = 155, - .auto_corr_max_ofdm_mrc_x1 = 290, + .auto_corr_max_ofdm_x1 = 120, + .auto_corr_max_ofdm_mrc_x1 = 240, .auto_corr_min_cck = 125, .auto_corr_max_cck = 200, -- cgit v1.2.3 From fac06108701a2a081a47d4dc6f03220aaab54486 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 20 Jan 2010 12:22:54 -0800 Subject: iwlwifi: update sensitivity calibration data for 1000 series Update sensitivity range values for 1000 series Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 72 ++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 4281999cfaaa..9d1820676f30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -89,8 +89,78 @@ static void iwl1000_nic_config(struct iwl_priv *priv) ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); } +static struct iwl_sensitivity_ranges iwl1000_sensitivity = { + .min_nrg_cck = 95, + .max_nrg_cck = 0, /* not used, set to 0 */ + .auto_corr_min_ofdm = 90, + .auto_corr_min_ofdm_mrc = 170, + .auto_corr_min_ofdm_x1 = 120, + .auto_corr_min_ofdm_mrc_x1 = 240, + + .auto_corr_max_ofdm = 120, + .auto_corr_max_ofdm_mrc = 210, + .auto_corr_max_ofdm_x1 = 155, + .auto_corr_max_ofdm_mrc_x1 = 290, + + .auto_corr_min_cck = 125, + .auto_corr_max_cck = 200, + .auto_corr_min_cck_mrc = 170, + .auto_corr_max_cck_mrc = 400, + .nrg_th_cck = 95, + .nrg_th_ofdm = 95, + + .barker_corr_th_min = 190, + .barker_corr_th_min_mrc = 390, + .nrg_th_cca = 62, +}; + +static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) +{ + if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && + priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) + priv->cfg->num_of_queues = + priv->cfg->mod_params->num_of_queues; + + priv->hw_params.max_txq_num = priv->cfg->num_of_queues; + priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; + priv->hw_params.scd_bc_tbls_size = + priv->cfg->num_of_queues * + sizeof(struct iwl5000_scd_bc_tbl); + priv->hw_params.tfd_size = sizeof(struct iwl_tfd); + priv->hw_params.max_stations = IWL5000_STATION_COUNT; + priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; + + priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; + priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; + + priv->hw_params.max_bsm_size = 0; + priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | + BIT(IEEE80211_BAND_5GHZ); + priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + + priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); + priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); + priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; + priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + + if (priv->cfg->ops->lib->temp_ops.set_ct_kill) + priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + + /* Set initial sensitivity parameters */ + /* Set initial calibration set */ + priv->hw_params.sens = &iwl1000_sensitivity; + priv->hw_params.calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_TX_IQ_PERD) | + BIT(IWL_CALIB_BASE_BAND); + + return 0; +} + static struct iwl_lib_ops iwl1000_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, + .set_hw_params = iwl1000_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, .txq_set_sched = iwl5000_txq_set_sched, -- cgit v1.2.3 From 4d6959219bb71aa34383fc1a1a520820aee6292b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 05:24:04 -0800 Subject: iwlwifi: no need to test iw_mode in power saving mac80211 will only enable powersaving for station mode. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-power.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 9e3ca0641451..232dd1879baf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -308,8 +308,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) { int ret = 0; struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && - (priv->hw->conf.flags & IEEE80211_CONF_PS); + bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; bool update_chains; struct iwl_powertable_cmd cmd; int dtimper; -- cgit v1.2.3 From 9f1f3ceacb7e52d9bc0364b4f26ae418de79656f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 05:28:40 -0800 Subject: iwlagn: simplify ucode loading Move the waiting into iwl5000_load_section instead of duplicating it in the caller. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-5000.c | 63 ++++++++++++--------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6bb433a0e535..6d5988901341 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -412,12 +412,14 @@ static void iwl5000_rx_calib_complete(struct iwl_priv *priv, /* * ucode */ -static int iwl5000_load_section(struct iwl_priv *priv, - struct fw_desc *image, - u32 dst_addr) +static int iwl5000_load_section(struct iwl_priv *priv, const char *name, + struct fw_desc *image, u32 dst_addr) { dma_addr_t phy_addr = image->p_addr; u32 byte_cnt = image->len; + int ret; + + priv->ucode_write_complete = 0; iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), @@ -447,57 +449,36 @@ static int iwl5000_load_section(struct iwl_priv *priv, FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - return 0; -} - -static int iwl5000_load_given_ucode(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image) -{ - int ret = 0; - - ret = iwl5000_load_section(priv, inst_image, - IWL50_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - - IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n"); + IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); ret = wait_event_interruptible_timeout(priv->wait_command_queue, priv->ucode_write_complete, 5 * HZ); if (ret == -ERESTARTSYS) { - IWL_ERR(priv, "Could not load the INST uCode section due " - "to interrupt\n"); + IWL_ERR(priv, "Could not load the %s uCode section due " + "to interrupt\n", name); return ret; } if (!ret) { - IWL_ERR(priv, "Could not load the INST uCode section\n"); + IWL_ERR(priv, "Could not load the %s uCode section\n", + name); return -ETIMEDOUT; } - priv->ucode_write_complete = 0; - - ret = iwl5000_load_section( - priv, data_image, IWL50_RTC_DATA_LOWER_BOUND); - if (ret) - return ret; + return 0; +} - IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); +static int iwl5000_load_given_ucode(struct iwl_priv *priv, + struct fw_desc *inst_image, + struct fw_desc *data_image) +{ + int ret = 0; - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - priv->ucode_write_complete, 5 * HZ); - if (ret == -ERESTARTSYS) { - IWL_ERR(priv, "Could not load the INST uCode section due " - "to interrupt\n"); + ret = iwl5000_load_section(priv, "INST", inst_image, + IWL50_RTC_INST_LOWER_BOUND); + if (ret) return ret; - } else if (!ret) { - IWL_ERR(priv, "Could not load the DATA uCode section\n"); - return -ETIMEDOUT; - } else - ret = 0; - - priv->ucode_write_complete = 0; - return ret; + return iwl5000_load_section(priv, "DATA", data_image, + IWL50_RTC_DATA_LOWER_BOUND); } int iwl5000_load_ucode(struct iwl_priv *priv) -- cgit v1.2.3 From 80676518da523e926e70794ac2767829effcf3ba Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 06:07:17 -0800 Subject: iwlwifi: remove bg_up work There's no need to queue a work struct from within a work struct, just move the code to execute directly. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 21 +++++++-------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 21 +++++++-------------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1c54425afe22..b528a20ade4f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2439,18 +2439,6 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) return; } -static void iwl_bg_up(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, up); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - __iwl_up(priv); - mutex_unlock(&priv->mutex); -} - static void iwl_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); @@ -2467,7 +2455,13 @@ static void iwl_bg_restart(struct work_struct *data) ieee80211_restart_hw(priv->hw); } else { iwl_down(priv); - queue_work(priv->workqueue, &priv->up); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + __iwl_up(priv); + mutex_unlock(&priv->mutex); } } @@ -3285,7 +3279,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) init_waitqueue_head(&priv->wait_command_queue); - INIT_WORK(&priv->up, iwl_bg_up); INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9b0a5cbc20f9..1cd565aef62c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1264,7 +1264,6 @@ struct iwl_priv { struct workqueue_struct *workqueue; - struct work_struct up; struct work_struct restart; struct work_struct calibrated_work; struct work_struct scan_completed; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index cd42b5838b38..119da54116de 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3033,18 +3033,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data) mutex_unlock(&priv->mutex); } -static void iwl3945_bg_up(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, up); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - __iwl3945_up(priv); - mutex_unlock(&priv->mutex); -} - static void iwl3945_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); @@ -3061,7 +3049,13 @@ static void iwl3945_bg_restart(struct work_struct *data) ieee80211_restart_hw(priv->hw); } else { iwl3945_down(priv); - queue_work(priv->workqueue, &priv->up); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + mutex_lock(&priv->mutex); + __iwl3945_up(priv); + mutex_unlock(&priv->mutex); } } @@ -3782,7 +3776,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) init_waitqueue_head(&priv->wait_command_queue); - INIT_WORK(&priv->up, iwl3945_bg_up); INIT_WORK(&priv->restart, iwl3945_bg_restart); INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); -- cgit v1.2.3 From 71d75cf9ab858b99d072fece9784ab338af8e388 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 06:08:19 -0800 Subject: iwlwifi: remove unused work structs auth_work, calibrated_work, update_link_led and report_work are never used, so remove them. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 1cd565aef62c..55dc5a866542 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1265,13 +1265,9 @@ struct iwl_priv { struct workqueue_struct *workqueue; struct work_struct restart; - struct work_struct calibrated_work; struct work_struct scan_completed; struct work_struct rx_replenish; struct work_struct abort_scan; - struct work_struct update_link_led; - struct work_struct auth_work; - struct work_struct report_work; struct work_struct request_scan; struct work_struct beacon_update; struct work_struct tt_work; -- cgit v1.2.3 From 7ae810776a51dc4dc6580013b0f6ba0f34d2b165 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 21 Jan 2010 11:47:59 -0800 Subject: iwlwifi: fix typo in IWL_CCK_RATES_MASK Due to a typo, the variable contains OFDM rates as well. The only user doesn't care, so this change doesn't really do anything but fix up my confusion. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 2f0094a43261..e71923961e69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -191,7 +191,7 @@ enum { IWL_RATE_2M_MASK) #define IWL_CCK_RATES_MASK \ - (IWL_BASIC_RATES_MASK | \ + (IWL_CCK_BASIC_RATES_MASK | \ IWL_RATE_5M_MASK | \ IWL_RATE_11M_MASK) -- cgit v1.2.3 From d3a571971e5af241074947fc80f6284677f6e014 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 21 Jan 2010 11:52:28 -0800 Subject: iwlwifi: iwl_power_update_mode always hold mutex iwl_power_update_mode expects to be called with mutex held, for example to protect priv->vif. Only one caller currently does not do this, fix this. Also, add a comment to iwl_power_update_mode to indicate this requirement. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 5c8377b9ad9b..d134301b553c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -815,7 +815,9 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, priv->power_data.debug_sleep_level_override = value; + mutex_lock(&priv->mutex); iwl_power_update_mode(priv, true); + mutex_unlock(&priv->mutex); return count; } diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 232dd1879baf..1a1a9f081cc7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -303,7 +303,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) sizeof(struct iwl_powertable_cmd), cmd); } - +/* priv->mutex must be held */ int iwl_power_update_mode(struct iwl_priv *priv, bool force) { int ret = 0; -- cgit v1.2.3 From d60bec4eb7076acfc940cca3f9f219e7653a1466 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:17 +0000 Subject: tulip_core: Use dev_ and pr_ Convert printks to dev_ where appropriate Convert printks to pr_ Change print formats with %d.dx to %0dx Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/tulip_core.c | 162 +++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index da4fc458f90c..e1a5f03a49c5 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -41,7 +41,6 @@ static char version[] __devinitdata = "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n"; - /* A few user-configurable values. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ @@ -326,7 +325,8 @@ static void tulip_up(struct net_device *dev) udelay(100); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", dev->name, dev->irq); + printk(KERN_DEBUG "%s: tulip_up(), irq==%d\n", + dev->name, dev->irq); iowrite32(tp->rx_ring_dma, ioaddr + CSR3); iowrite32(tp->tx_ring_dma, ioaddr + CSR4); @@ -387,8 +387,9 @@ static void tulip_up(struct net_device *dev) (dev->if_port == 12 ? 0 : dev->if_port); for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == looking_for) { - printk(KERN_INFO "%s: Using user-specified media %s.\n", - dev->name, medianame[dev->if_port]); + dev_info(&dev->dev, + "Using user-specified media %s\n", + medianame[dev->if_port]); goto media_picked; } } @@ -396,8 +397,9 @@ static void tulip_up(struct net_device *dev) int looking_for = tp->mtable->defaultmedia & MEDIA_MASK; for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == looking_for) { - printk(KERN_INFO "%s: Using EEPROM-set media %s.\n", - dev->name, medianame[looking_for]); + dev_info(&dev->dev, + "Using EEPROM-set media %s\n", + medianame[looking_for]); goto media_picked; } } @@ -424,9 +426,10 @@ media_picked: if (tp->mii_cnt) { tulip_select_media(dev, 1); if (tulip_debug > 1) - printk(KERN_INFO "%s: Using MII transceiver %d, status " - "%4.4x.\n", - dev->name, tp->phys[0], tulip_mdio_read(dev, tp->phys[0], 1)); + dev_info(&dev->dev, + "Using MII transceiver %d, status %04x\n", + tp->phys[0], + tulip_mdio_read(dev, tp->phys[0], 1)); iowrite32(csr6_mask_defstate, ioaddr + CSR6); tp->csr6 = csr6_mask_hdcap; dev->if_port = 11; @@ -490,9 +493,10 @@ media_picked: iowrite32(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", - dev->name, ioread32(ioaddr + CSR0), ioread32(ioaddr + CSR5), - ioread32(ioaddr + CSR6)); + printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %08x, CSR5 %08x CSR6 %08x\n", + dev->name, ioread32(ioaddr + CSR0), + ioread32(ioaddr + CSR5), + ioread32(ioaddr + CSR6)); } /* Set the timer to switch to check for link beat and perhaps switch @@ -540,27 +544,30 @@ static void tulip_tx_timeout(struct net_device *dev) if (tulip_media_cap[dev->if_port] & MediaIsMII) { /* Do nothing -- the media monitor should handle this. */ if (tulip_debug > 1) - printk(KERN_WARNING "%s: Transmit timeout using MII device.\n", - dev->name); + dev_warn(&dev->dev, + "Transmit timeout using MII device\n"); } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142 || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881 || tp->chip_id == DM910X) { - printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, " - "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", - dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), - ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); + dev_warn(&dev->dev, + "21140 transmit timed out, status %08x, SIA %08x %08x %08x %08x, resetting...\n", + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12), + ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), + ioread32(ioaddr + CSR15)); tp->timeout_recovery = 1; schedule_work(&tp->media_work); goto out_unlock; } else if (tp->chip_id == PNIC2) { - printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, " - "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n", - dev->name, (int)ioread32(ioaddr + CSR5), (int)ioread32(ioaddr + CSR6), - (int)ioread32(ioaddr + CSR7), (int)ioread32(ioaddr + CSR12)); + dev_warn(&dev->dev, + "PNIC2 transmit timed out, status %08x, CSR6/7 %08x / %08x CSR12 %08x, resetting...\n", + (int)ioread32(ioaddr + CSR5), + (int)ioread32(ioaddr + CSR6), + (int)ioread32(ioaddr + CSR7), + (int)ioread32(ioaddr + CSR12)); } else { - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 " - "%8.8x, resetting...\n", - dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12)); + dev_warn(&dev->dev, + "Transmit timed out, status %08x, CSR12 %08x, resetting...\n", + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12)); dev->if_port = 0; } @@ -570,26 +577,26 @@ static void tulip_tx_timeout(struct net_device *dev) for (i = 0; i < RX_RING_SIZE; i++) { u8 *buf = (u8 *)(tp->rx_ring[i].buffer1); int j; - printk(KERN_DEBUG "%2d: %8.8x %8.8x %8.8x %8.8x " - "%2.2x %2.2x %2.2x.\n", - i, (unsigned int)tp->rx_ring[i].status, - (unsigned int)tp->rx_ring[i].length, - (unsigned int)tp->rx_ring[i].buffer1, - (unsigned int)tp->rx_ring[i].buffer2, - buf[0], buf[1], buf[2]); + printk(KERN_DEBUG + "%2d: %08x %08x %08x %08x %02x %02x %02x\n", + i, + (unsigned int)tp->rx_ring[i].status, + (unsigned int)tp->rx_ring[i].length, + (unsigned int)tp->rx_ring[i].buffer1, + (unsigned int)tp->rx_ring[i].buffer2, + buf[0], buf[1], buf[2]); for (j = 0; buf[j] != 0xee && j < 1600; j++) if (j < 100) - printk(KERN_CONT " %2.2x", buf[j]); - printk(KERN_CONT " j=%d.\n", j); + pr_cont(" %02x", buf[j]); + pr_cont(" j=%d\n", j); } - printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring); + printk(KERN_DEBUG " Rx ring %08x: ", (int)tp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(KERN_CONT " %8.8x", - (unsigned int)tp->rx_ring[i].status); - printk(KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring); + pr_cont(" %08x", (unsigned int)tp->rx_ring[i].status); + printk(KERN_DEBUG " Tx ring %08x: ", (int)tp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status); - printk(KERN_CONT "\n"); + pr_cont(" %08x", (unsigned int)tp->tx_ring[i].status); + pr_cont("\n"); } #endif @@ -832,8 +839,9 @@ static int tulip_close (struct net_device *dev) tulip_down (dev); if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, ioread32 (ioaddr + CSR5)); + dev_printk(KERN_DEBUG, &dev->dev, + "Shutting down ethercard, status was %02x\n", + ioread32 (ioaddr + CSR5)); free_irq (dev->irq, dev); @@ -1073,10 +1081,10 @@ static void set_rx_mode(struct net_device *dev) filterbit &= 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); if (tulip_debug > 2) - printk(KERN_INFO "%s: Added filter for %pM" - " %8.8x bit %d.\n", - dev->name, mclist->dmi_addr, - ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit); + dev_info(&dev->dev, + "Added filter for %pM %08x bit %d\n", + mclist->dmi_addr, + ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit); } if (mc_filter[0] == tp->mc_filter[0] && mc_filter[1] == tp->mc_filter[1]) @@ -1288,9 +1296,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, unsigned int force_csr0 = 0; #ifndef MODULE - static int did_version; /* Already printed version info. */ - if (tulip_debug > 0 && did_version++ == 0) - printk (KERN_INFO "%s", version); + if (tulip_debug > 0) + printk_once(KERN_INFO "%s", version); #endif board_idx++; @@ -1301,7 +1308,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, */ if (pdev->subsystem_vendor == PCI_VENDOR_ID_LMC) { - printk (KERN_ERR PFX "skipping LMC card.\n"); + pr_err(PFX "skipping LMC card\n"); return -ENODEV; } @@ -1317,15 +1324,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (pdev->vendor == 0x1282 && pdev->device == 0x9100 && pdev->revision < 0x30) { - printk(KERN_INFO PFX - "skipping early DM9100 with Crc bug (use dmfe)\n"); + pr_info(PFX "skipping early DM9100 with Crc bug (use dmfe)\n"); return -ENODEV; } dp = pci_device_to_OF_node(pdev); if (!(dp && of_get_property(dp, "local-mac-address", NULL))) { - printk(KERN_INFO PFX - "skipping DM910x expansion card (use dmfe)\n"); + pr_info(PFX "skipping DM910x expansion card (use dmfe)\n"); return -ENODEV; } } @@ -1372,9 +1377,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, i = pci_enable_device(pdev); if (i) { - printk (KERN_ERR PFX - "Cannot enable tulip board #%d, aborting\n", - board_idx); + pr_err(PFX "Cannot enable tulip board #%d, aborting\n", + board_idx); return i; } @@ -1383,22 +1387,22 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, /* alloc_etherdev ensures aligned and zeroed private structures */ dev = alloc_etherdev (sizeof (*tp)); if (!dev) { - printk (KERN_ERR PFX "ether device alloc failed, aborting\n"); + pr_err(PFX "ether device alloc failed, aborting\n"); return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { - printk (KERN_ERR PFX "%s: I/O region (0x%llx@0x%llx) too small, " - "aborting\n", pci_name(pdev), - (unsigned long long)pci_resource_len (pdev, 0), - (unsigned long long)pci_resource_start (pdev, 0)); + pr_err(PFX "%s: I/O region (0x%llx@0x%llx) too small, aborting\n", + pci_name(pdev), + (unsigned long long)pci_resource_len (pdev, 0), + (unsigned long long)pci_resource_start (pdev, 0)); goto err_out_free_netdev; } /* grab all resources from both PIO and MMIO regions, as we * don't want anyone else messing around with our hardware */ - if (pci_request_regions (pdev, "tulip")) + if (pci_request_regions (pdev, DRV_NAME)) goto err_out_free_netdev; ioaddr = pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size); @@ -1611,8 +1615,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (dev->mem_start & MEDIA_MASK) tp->default_port = dev->mem_start & MEDIA_MASK; if (tp->default_port) { - printk(KERN_INFO "tulip%d: Transceiver selection forced to %s.\n", - board_idx, medianame[tp->default_port & MEDIA_MASK]); + pr_info(DRV_NAME "%d: Transceiver selection forced to %s\n", + board_idx, medianame[tp->default_port & MEDIA_MASK]); tp->medialock = 1; if (tulip_media_cap[tp->default_port] & MediaAlwaysFD) tp->full_duplex = 1; @@ -1627,7 +1631,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, } if (tp->flags & HAS_MEDIA_TABLE) { - sprintf(dev->name, "tulip%d", board_idx); /* hack */ + sprintf(dev->name, DRV_NAME "%d", board_idx); /* hack */ tulip_parse_eeprom(dev); strcpy(dev->name, "eth%d"); /* un-hack */ } @@ -1663,20 +1667,18 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, if (register_netdev(dev)) goto err_out_free_ring; - printk(KERN_INFO "%s: %s rev %d at " + pci_set_drvdata(pdev, dev); + + dev_info(&dev->dev, #ifdef CONFIG_TULIP_MMIO - "MMIO" + "%s rev %d at MMIO %#llx,%s %pM, IRQ %d\n", #else - "Port" + "%s rev %d at Port %#llx,%s %pM, IRQ %d\n", #endif - " %#llx,", dev->name, chip_name, pdev->revision, - (unsigned long long) pci_resource_start(pdev, TULIP_BAR)); - pci_set_drvdata(pdev, dev); - - if (eeprom_missing) - printk(" EEPROM not present,"); - printk(" %pM", dev->dev_addr); - printk(", IRQ %d.\n", irq); + chip_name, pdev->revision, + (unsigned long long)pci_resource_start(pdev, TULIP_BAR), + eeprom_missing ? " EEPROM not present," : "", + dev->dev_addr, irq); if (tp->chip_id == PNIC2) tp->link_change = pnic2_lnk_change; @@ -1799,12 +1801,12 @@ static int tulip_resume(struct pci_dev *pdev) return 0; if ((retval = pci_enable_device(pdev))) { - printk (KERN_ERR "tulip: pci_enable_device failed in resume\n"); + pr_err(PFX "pci_enable_device failed in resume\n"); return retval; } if ((retval = request_irq(dev->irq, tulip_interrupt, IRQF_SHARED, dev->name, dev))) { - printk (KERN_ERR "tulip: request_irq failed in resume\n"); + pr_err(PFX "request_irq failed in resume\n"); return retval; } @@ -1874,7 +1876,7 @@ static struct pci_driver tulip_driver = { static int __init tulip_init (void) { #ifdef MODULE - printk (KERN_INFO "%s", version); + pr_info("%s", version); #endif /* copy module parms into globals */ -- cgit v1.2.3 From 985a63ed3faf0faaba840d806f5ca4d360d13ad3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:18 +0000 Subject: tulip/21142.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/21142.c | 76 ++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 9f6742fad6ca..007d8e75666d 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c @@ -43,8 +43,8 @@ void t21142_media_task(struct work_struct *work) if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000) csr12 |= 6; if (tulip_debug > 2) - printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n", - dev->name, csr12, medianame[dev->if_port]); + dev_info(&dev->dev, "21143 negotiation status %08x, %s\n", + csr12, medianame[dev->if_port]); if (tulip_media_cap[dev->if_port] & MediaIsMII) { if (tulip_check_duplex(dev) < 0) { netif_carrier_off(dev); @@ -56,23 +56,26 @@ void t21142_media_task(struct work_struct *work) } else if (tp->nwayset) { /* Don't screw up a negotiated session! */ if (tulip_debug > 1) - printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n", - dev->name, medianame[dev->if_port], csr12); + dev_info(&dev->dev, + "Using NWay-set %s media, csr12 %08x\n", + medianame[dev->if_port], csr12); } else if (tp->medialock) { ; } else if (dev->if_port == 3) { if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ if (tulip_debug > 1) - printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, " - "trying NWay.\n", dev->name, csr12); + dev_info(&dev->dev, + "No 21143 100baseTx link beat, %08x, trying NWay\n", + csr12); t21142_start_nway(dev); next_tick = 3*HZ; } } else if ((csr12 & 0x7000) != 0x5000) { /* Negotiation failed. Search media types. */ if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n", - dev->name, csr12); + dev_info(&dev->dev, + "21143 negotiation failed, status %08x\n", + csr12); if (!(csr12 & 4)) { /* 10mbps link beat good. */ new_csr6 = 0x82420000; dev->if_port = 0; @@ -90,8 +93,8 @@ void t21142_media_task(struct work_struct *work) iowrite32(1, ioaddr + CSR13); } if (tulip_debug > 1) - printk(KERN_INFO"%s: Testing new 21143 media %s.\n", - dev->name, medianame[dev->if_port]); + dev_info(&dev->dev, "Testing new 21143 media %s\n", + medianame[dev->if_port]); if (new_csr6 != (tp->csr6 & ~0x00D5)) { tp->csr6 &= 0x00D5; tp->csr6 |= new_csr6; @@ -119,8 +122,8 @@ void t21142_start_nway(struct net_device *dev) tp->nway = tp->mediasense = 1; tp->nwayset = tp->lpar = 0; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%8.8x.\n", - dev->name, csr14); + printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, csr14=%08x\n", + dev->name, csr14); iowrite32(0x0001, ioaddr + CSR13); udelay(100); iowrite32(csr14, ioaddr + CSR14); @@ -147,8 +150,9 @@ void t21142_lnk_change(struct net_device *dev, int csr5) if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000) csr12 |= 6; if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, " - "%8.8x.\n", dev->name, csr12, csr5, csr14); + dev_info(&dev->dev, + "21143 link status interrupt %08x, CSR5 %x, %08x\n", + csr12, csr5, csr14); /* If NWay finished and we have a negotiated partner capability. */ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { @@ -171,14 +175,15 @@ void t21142_lnk_change(struct net_device *dev, int csr5) if (tulip_debug > 1) { if (tp->nwayset) - printk(KERN_INFO "%s: Switching to %s based on link " - "negotiation %4.4x & %4.4x = %4.4x.\n", - dev->name, medianame[dev->if_port], tp->sym_advertise, - tp->lpar, negotiated); + dev_info(&dev->dev, + "Switching to %s based on link negotiation %04x & %04x = %04x\n", + medianame[dev->if_port], + tp->sym_advertise, tp->lpar, + negotiated); else - printk(KERN_INFO "%s: Autonegotiation failed, using %s," - " link beat status %4.4x.\n", - dev->name, medianame[dev->if_port], csr12); + dev_info(&dev->dev, + "Autonegotiation failed, using %s, link beat status %04x\n", + medianame[dev->if_port], csr12); } if (tp->mtable) { @@ -201,14 +206,14 @@ void t21142_lnk_change(struct net_device *dev, int csr5) #if 0 /* Restart shouldn't be needed. */ iowrite32(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", - dev->name, ioread32(ioaddr + CSR5)); + printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %08x\n", + dev->name, ioread32(ioaddr + CSR5)); #endif tulip_start_rxtx(tp); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n", - dev->name, tp->csr6, ioread32(ioaddr + CSR6), - ioread32(ioaddr + CSR12)); + printk(KERN_DEBUG "%s: Setting CSR6 %08x/%x CSR12 %08x\n", + dev->name, tp->csr6, ioread32(ioaddr + CSR6), + ioread32(ioaddr + CSR12)); } else if ((tp->nwayset && (csr5 & 0x08000000) && (dev->if_port == 3 || dev->if_port == 5) && (csr12 & 2) == 2) || @@ -220,9 +225,9 @@ void t21142_lnk_change(struct net_device *dev, int csr5) add_timer(&tp->timer); } else if (dev->if_port == 3 || dev->if_port == 5) { if (tulip_debug > 1) - printk(KERN_INFO"%s: 21143 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 2) ? "failed" : "good"); + dev_info(&dev->dev, "21143 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 2) ? "failed" : "good"); if ((csr12 & 2) && ! tp->medialock) { del_timer_sync(&tp->timer); t21142_start_nway(dev); @@ -232,21 +237,18 @@ void t21142_lnk_change(struct net_device *dev, int csr5) iowrite32(csr14 & ~0x080, ioaddr + CSR14); } else if (dev->if_port == 0 || dev->if_port == 4) { if ((csr12 & 4) == 0) - printk(KERN_INFO"%s: 21143 10baseT link beat good.\n", - dev->name); + dev_info(&dev->dev, "21143 10baseT link beat good\n"); } else if (!(csr12 & 4)) { /* 10mbps link beat good. */ if (tulip_debug) - printk(KERN_INFO"%s: 21143 10mbps sensed media.\n", - dev->name); + dev_info(&dev->dev, "21143 10mbps sensed media\n"); dev->if_port = 0; } else if (tp->nwayset) { if (tulip_debug) - printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n", - dev->name, medianame[dev->if_port], tp->csr6); + dev_info(&dev->dev, "21143 using NWay-set %s, csr6 %08x\n", + medianame[dev->if_port], tp->csr6); } else { /* 100mbps link beat good. */ if (tulip_debug) - printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n", - dev->name); + dev_info(&dev->dev, "21143 100baseTx sensed media\n"); dev->if_port = 3; tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff); iowrite32(0x0003FF7F, ioaddr + CSR14); -- cgit v1.2.3 From f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:19 +0000 Subject: tulip/de2104x.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 138 ++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 87ea39e2037d..29330209ad8b 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -382,9 +382,9 @@ static void de_rx_err_acct (struct de_private *de, unsigned rx_tail, /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (netif_msg_rx_err(de)) - printk(KERN_WARNING "%s: Oversized Ethernet frame " - "spanned multiple buffers, status %8.8x!\n", - de->dev->name, status); + dev_warn(&de->dev->dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); de->net_stats.rx_length_errors++; } } else if (status & RxError) { @@ -487,7 +487,7 @@ rx_next: } if (!rx_work) - printk(KERN_WARNING "%s: rx work limit reached\n", de->dev->name); + dev_warn(&de->dev->dev, "rx work limit reached\n"); de->rx_tail = rx_tail; } @@ -504,7 +504,8 @@ static irqreturn_t de_interrupt (int irq, void *dev_instance) if (netif_msg_intr(de)) printk(KERN_DEBUG "%s: intr, status %08x mode %08x desc %u/%u/%u\n", - dev->name, status, dr32(MacMode), de->rx_tail, de->tx_head, de->tx_tail); + dev->name, status, dr32(MacMode), + de->rx_tail, de->tx_head, de->tx_tail); dw32(MacStatus, status); @@ -529,8 +530,9 @@ static irqreturn_t de_interrupt (int irq, void *dev_instance) pci_read_config_word(de->pdev, PCI_STATUS, &pci_status); pci_write_config_word(de->pdev, PCI_STATUS, pci_status); - printk(KERN_ERR "%s: PCI bus error, status=%08x, PCI status=%04x\n", - dev->name, status, pci_status); + dev_err(&de->dev->dev, + "PCI bus error, status=%08x, PCI status=%04x\n", + status, pci_status); } return IRQ_HANDLED; @@ -582,7 +584,8 @@ static void de_tx (struct de_private *de) de->net_stats.tx_packets++; de->net_stats.tx_bytes += skb->len; if (netif_msg_tx_done(de)) - printk(KERN_DEBUG "%s: tx done, slot %d\n", de->dev->name, tx_tail); + printk(KERN_DEBUG "%s: tx done, slot %d\n", + de->dev->name, tx_tail); } dev_kfree_skb_irq(skb); } @@ -870,7 +873,7 @@ static void de_stop_rxtx (struct de_private *de) udelay(100); } - printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name); + dev_warn(&de->dev->dev, "timeout expired stopping DMA\n"); } static inline void de_start_rxtx (struct de_private *de) @@ -905,8 +908,8 @@ static void de_link_up(struct de_private *de) if (!netif_carrier_ok(de->dev)) { netif_carrier_on(de->dev); if (netif_msg_link(de)) - printk(KERN_INFO "%s: link up, media %s\n", - de->dev->name, media_name[de->media_type]); + dev_info(&de->dev->dev, "link up, media %s\n", + media_name[de->media_type]); } } @@ -915,7 +918,7 @@ static void de_link_down(struct de_private *de) if (netif_carrier_ok(de->dev)) { netif_carrier_off(de->dev); if (netif_msg_link(de)) - printk(KERN_INFO "%s: link down\n", de->dev->name); + dev_info(&de->dev->dev, "link down\n"); } } @@ -925,7 +928,8 @@ static void de_set_media (struct de_private *de) u32 macmode = dr32(MacMode); if (de_is_running(de)) - printk(KERN_WARNING "%s: chip is running while changing media!\n", de->dev->name); + dev_warn(&de->dev->dev, + "chip is running while changing media!\n"); if (de->de21040) dw32(CSR11, FULL_DUPLEX_MAGIC); @@ -945,15 +949,15 @@ static void de_set_media (struct de_private *de) macmode &= ~FullDuplex; if (netif_msg_link(de)) { - printk(KERN_INFO - "%s: set link %s\n" - "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n" - "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", - de->dev->name, media_name[media], - de->dev->name, dr32(MacMode), dr32(SIAStatus), - dr32(CSR13), dr32(CSR14), dr32(CSR15), - de->dev->name, macmode, de->media[media].csr13, - de->media[media].csr14, de->media[media].csr15); + dev_info(&de->dev->dev, "set link %s\n", media_name[media]); + dev_info(&de->dev->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n", + dr32(MacMode), dr32(SIAStatus), + dr32(CSR13), dr32(CSR14), dr32(CSR15)); + + dev_info(&de->dev->dev, + "set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", + macmode, de->media[media].csr13, + de->media[media].csr14, de->media[media].csr15); } if (macmode != dr32(MacMode)) dw32(MacMode, macmode); @@ -992,9 +996,8 @@ static void de21040_media_timer (unsigned long data) de_link_up(de); else if (netif_msg_timer(de)) - printk(KERN_INFO "%s: %s link ok, status %x\n", - dev->name, media_name[de->media_type], - status); + dev_info(&dev->dev, "%s link ok, status %x\n", + media_name[de->media_type], status); return; } @@ -1022,8 +1025,8 @@ no_link_yet: add_timer(&de->media_timer); if (netif_msg_timer(de)) - printk(KERN_INFO "%s: no link, trying media %s, status %x\n", - dev->name, media_name[de->media_type], status); + dev_info(&dev->dev, "no link, trying media %s, status %x\n", + media_name[de->media_type], status); } static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media) @@ -1079,9 +1082,10 @@ static void de21041_media_timer (unsigned long data) de_link_up(de); else if (netif_msg_timer(de)) - printk(KERN_INFO "%s: %s link ok, mode %x status %x\n", - dev->name, media_name[de->media_type], - dr32(MacMode), status); + dev_info(&dev->dev, + "%s link ok, mode %x status %x\n", + media_name[de->media_type], + dr32(MacMode), status); return; } @@ -1150,8 +1154,8 @@ no_link_yet: add_timer(&de->media_timer); if (netif_msg_timer(de)) - printk(KERN_INFO "%s: no link, trying media %s, status %x\n", - dev->name, media_name[de->media_type], status); + dev_info(&dev->dev, "no link, trying media %s, status %x\n", + media_name[de->media_type], status); } static void de_media_interrupt (struct de_private *de, u32 status) @@ -1378,8 +1382,7 @@ static int de_open (struct net_device *dev) rc = de_alloc_rings(de); if (rc) { - printk(KERN_ERR "%s: ring allocation failure, err=%d\n", - dev->name, rc); + dev_err(&dev->dev, "ring allocation failure, err=%d\n", rc); return rc; } @@ -1387,15 +1390,14 @@ static int de_open (struct net_device *dev) rc = request_irq(dev->irq, de_interrupt, IRQF_SHARED, dev->name, dev); if (rc) { - printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n", - dev->name, dev->irq, rc); + dev_err(&dev->dev, "IRQ %d request failure, err=%d\n", + dev->irq, rc); goto err_out_free; } rc = de_init_hw(de); if (rc) { - printk(KERN_ERR "%s: h/w init failure, err=%d\n", - dev->name, rc); + dev_err(&dev->dev, "h/w init failure, err=%d\n", rc); goto err_out_free_irq; } @@ -1666,8 +1668,8 @@ static int de_nway_reset(struct net_device *dev) status = dr32(SIAStatus); dw32(SIAStatus, (status & ~NWayState) | NWayRestart); if (netif_msg_link(de)) - printk(KERN_INFO "%s: link nway restart, status %x,%x\n", - de->dev->name, status, dr32(SIAStatus)); + dev_info(&de->dev->dev, "link nway restart, status %x,%x\n", + status, dr32(SIAStatus)); return 0; } @@ -1711,7 +1713,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de) de->dev->dev_addr[i] = value; udelay(1); if (boguscnt <= 0) - printk(KERN_WARNING PFX "timeout reading 21040 MAC address byte %u\n", i); + pr_warning(PFX "timeout reading 21040 MAC address byte %u\n", i); } } @@ -1830,9 +1832,8 @@ static void __devinit de21041_get_srom_info (struct de_private *de) } if (netif_msg_probe(de)) - printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n", - de->board_idx, ofs, - media_name[de->media_type]); + pr_info("de%d: SROM leaf offset %u, default media %s\n", + de->board_idx, ofs, media_name[de->media_type]); /* init SIA register values to defaults */ for (i = 0; i < DE_MAX_MEDIA; i++) { @@ -1879,9 +1880,9 @@ static void __devinit de21041_get_srom_info (struct de_private *de) de->media[idx].type = idx; if (netif_msg_probe(de)) - printk(KERN_INFO "de%d: media block #%u: %s", - de->board_idx, i, - media_name[de->media[idx].type]); + pr_info("de%d: media block #%u: %s", + de->board_idx, i, + media_name[de->media[idx].type]); bufp += sizeof (ib->opts); @@ -1893,13 +1894,13 @@ static void __devinit de21041_get_srom_info (struct de_private *de) sizeof(ib->csr15); if (netif_msg_probe(de)) - printk(" (%x,%x,%x)\n", - de->media[idx].csr13, - de->media[idx].csr14, - de->media[idx].csr15); + pr_cont(" (%x,%x,%x)\n", + de->media[idx].csr13, + de->media[idx].csr14, + de->media[idx].csr15); } else if (netif_msg_probe(de)) - printk("\n"); + pr_cont("\n"); if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3])) break; @@ -2005,7 +2006,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, /* check for invalid IRQ value */ if (pdev->irq < 2) { rc = -EIO; - printk(KERN_ERR PFX "invalid irq (%d) for pci dev %s\n", + pr_err(PFX "invalid irq (%d) for pci dev %s\n", pdev->irq, pci_name(pdev)); goto err_out_res; } @@ -2016,14 +2017,14 @@ static int __devinit de_init_one (struct pci_dev *pdev, pciaddr = pci_resource_start(pdev, 1); if (!pciaddr) { rc = -EIO; - printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n", - pci_name(pdev)); + pr_err(PFX "no MMIO resource for pci dev %s\n", pci_name(pdev)); goto err_out_res; } if (pci_resource_len(pdev, 1) < DE_REGS_SIZE) { rc = -EIO; - printk(KERN_ERR PFX "MMIO resource (%llx) too small on pci dev %s\n", - (unsigned long long)pci_resource_len(pdev, 1), pci_name(pdev)); + pr_err(PFX "MMIO resource (%llx) too small on pci dev %s\n", + (unsigned long long)pci_resource_len(pdev, 1), + pci_name(pdev)); goto err_out_res; } @@ -2031,9 +2032,9 @@ static int __devinit de_init_one (struct pci_dev *pdev, regs = ioremap_nocache(pciaddr, DE_REGS_SIZE); if (!regs) { rc = -EIO; - printk(KERN_ERR PFX "Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", - (unsigned long long)pci_resource_len(pdev, 1), - pciaddr, pci_name(pdev)); + pr_err(PFX "Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", + (unsigned long long)pci_resource_len(pdev, 1), + pciaddr, pci_name(pdev)); goto err_out_res; } dev->base_addr = (unsigned long) regs; @@ -2044,8 +2045,7 @@ static int __devinit de_init_one (struct pci_dev *pdev, /* make sure hardware is not running */ rc = de_reset_mac(de); if (rc) { - printk(KERN_ERR PFX "Cannot reset MAC, pci dev %s\n", - pci_name(pdev)); + pr_err(PFX "Cannot reset MAC, pci dev %s\n", pci_name(pdev)); goto err_out_iomap; } @@ -2065,12 +2065,11 @@ static int __devinit de_init_one (struct pci_dev *pdev, goto err_out_iomap; /* print info about board and interface just registered */ - printk (KERN_INFO "%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - de->de21040 ? "21040" : "21041", - dev->base_addr, - dev->dev_addr, - dev->irq); + dev_info(&dev->dev, "%s at 0x%lx, %pM, IRQ %d\n", + de->de21040 ? "21040" : "21041", + dev->base_addr, + dev->dev_addr, + dev->irq); pci_set_drvdata(pdev, dev); @@ -2158,8 +2157,7 @@ static int de_resume (struct pci_dev *pdev) if (!netif_running(dev)) goto out_attach; if ((retval = pci_enable_device(pdev))) { - printk (KERN_ERR "%s: pci_enable_device failed in resume\n", - dev->name); + dev_err(&dev->dev, "pci_enable_device failed in resume\n"); goto out; } de_init_hw(de); -- cgit v1.2.3 From dde7c8ef167996689bc464eb65d2b09ef05263c2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:20 +0000 Subject: tulip/dmfe.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove 'DRV_NAME ": ' from logging messages Convert commented out printks to pr_debug Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/dmfe.c | 67 ++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 2d9f09c6189e..5fc61c1012e5 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -61,6 +61,8 @@ Test and make sure PCI latency is now correct for all cases. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "dmfe" #define DRV_VERSION "1.36.4" #define DRV_RELDATE "2002-01-17" @@ -149,16 +151,17 @@ #define DMFE_TX_TIMEOUT ((3*HZ)/2) /* tx packet time-out time 1.5 s" */ #define DMFE_TX_KICK (HZ/2) /* tx packet Kick-out time 0.5 s" */ -#define DMFE_DBUG(dbug_now, msg, value) \ - do { \ - if (dmfe_debug || (dbug_now)) \ - printk(KERN_ERR DRV_NAME ": %s %lx\n",\ - (msg), (long) (value)); \ +#define DMFE_DBUG(dbug_now, msg, value) \ + do { \ + if (dmfe_debug || (dbug_now)) \ + pr_err("%s %lx\n", \ + (msg), (long) (value)); \ } while (0) -#define SHOW_MEDIA_TYPE(mode) \ - printk (KERN_INFO DRV_NAME ": Change Speed to %sMhz %s duplex\n" , \ - (mode & 1) ? "100":"10", (mode & 4) ? "full":"half"); +#define SHOW_MEDIA_TYPE(mode) \ + pr_info("Change Speed to %sMhz %s duplex\n" , \ + (mode & 1) ? "100":"10", \ + (mode & 4) ? "full":"half"); /* CR9 definition: SROM/MII */ @@ -391,8 +394,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, struct device_node *dp = pci_device_to_OF_node(pdev); if (dp && of_get_property(dp, "local-mac-address", NULL)) { - printk(KERN_INFO DRV_NAME - ": skipping on-board DM910x (use tulip)\n"); + pr_info("skipping on-board DM910x (use tulip)\n"); return -ENODEV; } } @@ -405,8 +407,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_WARNING DRV_NAME - ": 32-bit PCI DMA not available.\n"); + pr_warning("32-bit PCI DMA not available\n"); err = -ENODEV; goto err_out_free; } @@ -417,13 +418,13 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, goto err_out_free; if (!pci_resource_start(pdev, 0)) { - printk(KERN_ERR DRV_NAME ": I/O base is zero\n"); + pr_err("I/O base is zero\n"); err = -ENODEV; goto err_out_disable; } if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) { - printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n"); + pr_err("Allocated I/O size too small\n"); err = -ENODEV; goto err_out_disable; } @@ -438,7 +439,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, #endif if (pci_request_regions(pdev, DRV_NAME)) { - printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n"); + pr_err("Failed to request PCI regions\n"); err = -ENODEV; goto err_out_disable; } @@ -497,12 +498,9 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, if (err) goto err_out_free_buf; - printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, %pM, irq %d.\n", - dev->name, - ent->driver_data >> 16, - pci_name(pdev), - dev->dev_addr, - dev->irq); + dev_info(&dev->dev, "Davicom DM%04lx at pci%s, %pM, irq %d\n", + ent->driver_data >> 16, + pci_name(pdev), dev->dev_addr, dev->irq); pci_set_master(pdev); @@ -696,7 +694,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb, /* Too large packet check */ if (skb->len > MAX_PACKET_SIZE) { - printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len); + pr_err("big packet = %d\n", (u16)skb->len); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -706,8 +704,7 @@ static netdev_tx_t dmfe_start_xmit(struct sk_buff *skb, /* No Tx resource check, it never happen nromally */ if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); - printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", - db->tx_queue_cnt); + pr_err("No Tx resource %ld\n", db->tx_queue_cnt); return NETDEV_TX_BUSY; } @@ -779,12 +776,11 @@ static int dmfe_stop(struct DEVICE *dev) #if 0 /* show statistic counter */ - printk(DRV_NAME ": FU:%lx EC:%lx LC:%lx NC:%lx" - " LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n", - db->tx_fifo_underrun, db->tx_excessive_collision, - db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier, - db->tx_jabber_timeout, db->reset_count, db->reset_cr8, - db->reset_fatal, db->reset_TXtimeout); + printk("FU:%lx EC:%lx LC:%lx NC:%lx LOC:%lx TXJT:%lx RESET:%lx RCR8:%lx FAL:%lx TT:%lx\n", + db->tx_fifo_underrun, db->tx_excessive_collision, + db->tx_late_collision, db->tx_no_carrier, db->tx_loss_carrier, + db->tx_jabber_timeout, db->reset_count, db->reset_cr8, + db->reset_fatal, db->reset_TXtimeout); #endif return 0; @@ -885,7 +881,7 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db) txptr = db->tx_remove_ptr; while(db->tx_packet_cnt) { tdes0 = le32_to_cpu(txptr->tdes0); - /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */ + pr_debug("tdes0=%x\n", tdes0); if (tdes0 & 0x80000000) break; @@ -895,7 +891,7 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db) /* Transmit statistic counter */ if ( tdes0 != 0x7fffffff ) { - /* printk(DRV_NAME ": tdes0=%x\n", tdes0); */ + pr_debug("tdes0=%x\n", tdes0); dev->stats.collisions += (tdes0 >> 3) & 0xf; dev->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff; if (tdes0 & TDES0_ERR_MASK) { @@ -992,7 +988,7 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db) /* error summary bit check */ if (rdes0 & 0x8000) { /* This is a error packet */ - //printk(DRV_NAME ": rdes0: %lx\n", rdes0); + pr_debug("rdes0: %x\n", rdes0); dev->stats.rx_errors++; if (rdes0 & 1) dev->stats.rx_fifo_errors++; @@ -1191,8 +1187,7 @@ static void dmfe_timer(unsigned long data) if ( time_after(jiffies, dev->trans_start + DMFE_TX_TIMEOUT) ) { db->reset_TXtimeout++; db->wait_reset = 1; - printk(KERN_WARNING "%s: Tx timeout - resetting\n", - dev->name); + dev_warn(&dev->dev, "Tx timeout - resetting\n"); } } @@ -1646,7 +1641,7 @@ static u8 dmfe_sense_speed(struct dmfe_board_info * db) else /* DM9102/DM9102A */ phy_mode = phy_read(db->ioaddr, db->phy_addr, 17, db->chip_id) & 0xf000; - /* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */ + pr_debug("Phy_mode %x\n", phy_mode); switch (phy_mode) { case 0x1000: db->op_mode = DMFE_10MHF; break; case 0x2000: db->op_mode = DMFE_10MFD; break; -- cgit v1.2.3 From e9cd1cbcda5e21706b03b543b1b73600b07f323f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:21 +0000 Subject: tulip/eeprom.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/eeprom.c | 47 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 889f57aae89b..93f4e8309f81 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -161,15 +161,15 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) if (ee_data[0] == 0xff) { if (last_mediatable) { controller_index++; - printk(KERN_INFO "%s: Controller %d of multiport board.\n", - dev->name, controller_index); + dev_info(&dev->dev, + "Controller %d of multiport board\n", + controller_index); tp->mtable = last_mediatable; ee_data = last_ee_data; goto subsequent_board; } else - printk(KERN_INFO "%s: Missing EEPROM, this interface may " - "not work correctly!\n", - dev->name); + dev_info(&dev->dev, + "Missing EEPROM, this interface may not work correctly!\n"); return; } /* Do a fix-up based on the vendor half of the station address prefix. */ @@ -181,16 +181,15 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) i++; /* An Accton EN1207, not an outlaw Maxtech. */ memcpy(ee_data + 26, eeprom_fixups[i].newtable, sizeof(eeprom_fixups[i].newtable)); - printk(KERN_INFO "%s: Old format EEPROM on '%s' board. Using" - " substitute media control info.\n", - dev->name, eeprom_fixups[i].name); + dev_info(&dev->dev, + "Old format EEPROM on '%s' board. Using substitute media control info\n", + eeprom_fixups[i].name); break; } } if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ - printk(KERN_INFO "%s: Old style EEPROM with no media selection " - "information.\n", - dev->name); + dev_info(&dev->dev, + "Old style EEPROM with no media selection information\n"); return; } } @@ -218,7 +217,8 @@ subsequent_board: /* there is no phy information, don't even try to build mtable */ if (count == 0) { if (tulip_debug > 0) - printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name); + dev_warn(&dev->dev, + "no phy info, aborting mtable build\n"); return; } @@ -234,8 +234,8 @@ subsequent_board: mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; mtable->csr15dir = mtable->csr15val = 0; - printk(KERN_INFO "%s: EEPROM default media type %s.\n", dev->name, - media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); + dev_info(&dev->dev, "EEPROM default media type %s\n", + media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); for (i = 0; i < count; i++) { struct medialeaf *leaf = &mtable->mleaf[i]; @@ -298,16 +298,17 @@ subsequent_board: } if (tulip_debug > 1 && leaf->media == 11) { unsigned char *bp = leaf->leafdata; - printk(KERN_INFO "%s: MII interface PHY %d, setup/reset " - "sequences %d/%d long, capabilities %2.2x %2.2x.\n", - dev->name, bp[0], bp[1], bp[2 + bp[1]*2], - bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]); + dev_info(&dev->dev, + "MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", + bp[0], bp[1], bp[2 + bp[1]*2], + bp[5 + bp[2 + bp[1]*2]*2], + bp[4 + bp[2 + bp[1]*2]*2]); } - printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described " - "by a %s (%d) block.\n", - dev->name, i, medianame[leaf->media & 15], leaf->media, - leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "", - leaf->type); + dev_info(&dev->dev, + "Index #%d - Media %s (#%d) described by a %s (%d) block\n", + i, medianame[leaf->media & 15], leaf->media, + leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "", + leaf->type); } if (new_advertise) tp->sym_advertise = new_advertise; -- cgit v1.2.3 From abe02af8263ae17e201994a1be7fc5eac6642acf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:22 +0000 Subject: tulip/interrupt.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/interrupt.c | 100 ++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c index 2e8e8ee893c7..1faf7a4d7202 100644 --- a/drivers/net/tulip/interrupt.c +++ b/drivers/net/tulip/interrupt.c @@ -125,12 +125,12 @@ int tulip_poll(struct napi_struct *napi, int budget) #endif if (tulip_debug > 4) - printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, - tp->rx_ring[entry].status); + printk(KERN_DEBUG " In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); do { if (ioread32(tp->base_addr + CSR5) == 0xffffffff) { - printk(KERN_DEBUG " In tulip_poll(), hardware disappeared.\n"); + printk(KERN_DEBUG " In tulip_poll(), hardware disappeared\n"); break; } /* Acknowledge current RX interrupt sources. */ @@ -146,7 +146,7 @@ int tulip_poll(struct napi_struct *napi, int budget) break; if (tulip_debug > 5) - printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", + printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %08x\n", dev->name, entry, status); if (++work_done >= budget) @@ -177,15 +177,15 @@ int tulip_poll(struct napi_struct *napi, int budget) /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) - printk(KERN_WARNING "%s: Oversized Ethernet frame " - "spanned multiple buffers, status %8.8x!\n", - dev->name, status); + dev_warn(&dev->dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); tp->stats.rx_length_errors++; } } else { /* There was a fatal error. */ if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", + printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", dev->name, status); tp->stats.rx_errors++; /* end of a packet.*/ if (pkt_len > 1518 || @@ -226,12 +226,11 @@ int tulip_poll(struct napi_struct *napi, int budget) #ifndef final_version if (tp->rx_buffers[entry].mapping != le32_to_cpu(tp->rx_ring[entry].buffer1)) { - printk(KERN_ERR "%s: Internal fault: The skbuff addresses " - "do not match in tulip_rx: %08x vs. %08llx %p / %p.\n", - dev->name, - le32_to_cpu(tp->rx_ring[entry].buffer1), - (unsigned long long)tp->rx_buffers[entry].mapping, - skb->head, temp); + dev_err(&dev->dev, + "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %08llx %p / %p\n", + le32_to_cpu(tp->rx_ring[entry].buffer1), + (unsigned long long)tp->rx_buffers[entry].mapping, + skb->head, temp); } #endif @@ -365,16 +364,16 @@ static int tulip_rx(struct net_device *dev) int received = 0; if (tulip_debug > 4) - printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, - tp->rx_ring[entry].status); + printk(KERN_DEBUG " In tulip_rx(), entry %d %08x\n", + entry, tp->rx_ring[entry].status); /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); short pkt_len; if (tulip_debug > 5) - printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", - dev->name, entry, status); + printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %08x\n", + dev->name, entry, status); if (--rx_work_limit < 0) break; @@ -402,16 +401,16 @@ static int tulip_rx(struct net_device *dev) /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) - printk(KERN_WARNING "%s: Oversized Ethernet frame " - "spanned multiple buffers, status %8.8x!\n", - dev->name, status); + dev_warn(&dev->dev, + "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", + status); tp->stats.rx_length_errors++; } } else { /* There was a fatal error. */ if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", - dev->name, status); + printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", + dev->name, status); tp->stats.rx_errors++; /* end of a packet.*/ if (pkt_len > 1518 || (status & RxDescRunt)) @@ -450,12 +449,11 @@ static int tulip_rx(struct net_device *dev) #ifndef final_version if (tp->rx_buffers[entry].mapping != le32_to_cpu(tp->rx_ring[entry].buffer1)) { - printk(KERN_ERR "%s: Internal fault: The skbuff addresses " - "do not match in tulip_rx: %08x vs. %Lx %p / %p.\n", - dev->name, - le32_to_cpu(tp->rx_ring[entry].buffer1), - (long long)tp->rx_buffers[entry].mapping, - skb->head, temp); + dev_err(&dev->dev, + "Internal fault: The skbuff addresses do not match in tulip_rx: %08x vs. %Lx %p / %p\n", + le32_to_cpu(tp->rx_ring[entry].buffer1), + (long long)tp->rx_buffers[entry].mapping, + skb->head, temp); } #endif @@ -569,7 +567,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) #endif /* CONFIG_TULIP_NAPI */ if (tulip_debug > 4) - printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", + printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x\n", dev->name, csr5, ioread32(ioaddr + CSR5)); @@ -601,8 +599,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) /* There was an major error, log it. */ #ifndef final_version if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, status); + printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n", + dev->name, status); #endif tp->stats.tx_errors++; if (status & 0x4104) tp->stats.tx_aborted_errors++; @@ -631,8 +629,9 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) #ifndef final_version if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", - dev->name, dirty_tx, tp->cur_tx); + dev_err(&dev->dev, + "Out-of-sync dirty pointer, %d vs. %d\n", + dirty_tx, tp->cur_tx); dirty_tx += TX_RING_SIZE; } #endif @@ -643,9 +642,10 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { if (tulip_debug > 2) - printk(KERN_WARNING "%s: The transmitter stopped." - " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", - dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6); + dev_warn(&dev->dev, + "The transmitter stopped. CSR5 is %x, CSR6 %x, new CSR6 %x\n", + csr5, ioread32(ioaddr + CSR6), + tp->csr6); tulip_restart_rxtx(tp); } spin_unlock(&tp->lock); @@ -696,8 +696,9 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) * to the 21142/3 docs that is). * -- rmk */ - printk(KERN_ERR "%s: (%lu) System Error occurred (%d)\n", - dev->name, tp->nir, error); + dev_err(&dev->dev, + "(%lu) System Error occurred (%d)\n", + tp->nir, error); } /* Clear all error sources, included undocumented ones! */ iowrite32(0x0800f7ba, ioaddr + CSR5); @@ -706,16 +707,17 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) if (csr5 & TimerInt) { if (tulip_debug > 2) - printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n", - dev->name, csr5); + dev_err(&dev->dev, + "Re-enabling interrupts, %08x\n", + csr5); iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); tp->ttimer = 0; oi++; } if (tx > maxtx || rx > maxrx || oi > maxoi) { if (tulip_debug > 1) - printk(KERN_WARNING "%s: Too much work during an interrupt, " - "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi); + dev_warn(&dev->dev, "Too much work during an interrupt, csr5=0x%08x. (%lu) (%d,%d,%d)\n", + csr5, tp->nir, tx, rx, oi); /* Acknowledge all interrupt sources. */ iowrite32(0x8001ffff, ioaddr + CSR5); @@ -764,14 +766,18 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) entry = tp->dirty_rx % RX_RING_SIZE; if (tp->rx_buffers[entry].skb == NULL) { if (tulip_debug > 1) - printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx); + dev_warn(&dev->dev, + "in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", + tp->nir, tp->cur_rx, tp->ttimer, rx); if (tp->chip_id == LC82C168) { iowrite32(0x00, ioaddr + CSR7); mod_timer(&tp->timer, RUN_AT(HZ/50)); } else { if (tp->ttimer == 0 || (ioread32(ioaddr + CSR11) & 0xffff) == 0) { if (tulip_debug > 1) - printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir); + dev_warn(&dev->dev, + "in rx suspend mode: (%lu) set timer\n", + tp->nir); iowrite32(tulip_tbl[tp->chip_id].valid_intrs | TimerInt, ioaddr + CSR7); iowrite32(TimerInt, ioaddr + CSR5); @@ -787,8 +793,8 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance) } if (tulip_debug > 4) - printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n", - dev->name, ioread32(ioaddr + CSR5)); + printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#04x\n", + dev->name, ioread32(ioaddr + CSR5)); return IRQ_HANDLED; } -- cgit v1.2.3 From fa0b9a4c41490d550ebd3bd418f4551c989fec5d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:23 +0000 Subject: tulip/media.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/media.c | 74 +++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c index d8fda83705bf..68b170ae4d15 100644 --- a/drivers/net/tulip/media.c +++ b/drivers/net/tulip/media.c @@ -182,9 +182,8 @@ void tulip_select_media(struct net_device *dev, int startup) switch (mleaf->type) { case 0: /* 21140 non-MII xcvr. */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver" - " with control setting %2.2x.\n", - dev->name, p[1]); + printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver with control setting %02x\n", + dev->name, p[1]); dev->if_port = p[0]; if (startup) iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12); @@ -205,15 +204,15 @@ void tulip_select_media(struct net_device *dev, int startup) struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; unsigned char *rst = rleaf->leafdata; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver.\n", - dev->name); + printk(KERN_DEBUG "%s: Resetting the transceiver\n", + dev->name); for (i = 0; i < rst[0]; i++) iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control " - "%4.4x/%4.4x.\n", - dev->name, medianame[dev->if_port], setup[0], setup[1]); + printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control %04x/%04x\n", + dev->name, medianame[dev->if_port], + setup[0], setup[1]); if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */ csr13val = setup[0]; csr14val = setup[1]; @@ -240,8 +239,8 @@ void tulip_select_media(struct net_device *dev, int startup) if (startup) iowrite32(csr13val, ioaddr + CSR13); } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Setting CSR15 to %8.8x/%8.8x.\n", - dev->name, csr15dir, csr15val); + printk(KERN_DEBUG "%s: Setting CSR15 to %08x/%08x\n", + dev->name, csr15dir, csr15val); if (mleaf->type == 4) new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18); else @@ -317,8 +316,9 @@ void tulip_select_media(struct net_device *dev, int startup) if (tp->mii_advertise == 0) tp->mii_advertise = tp->advertising[phy_num]; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Advertising %4.4x on MII %d.\n", - dev->name, tp->mii_advertise, tp->phys[phy_num]); + printk(KERN_DEBUG "%s: Advertising %04x on MII %d\n", + dev->name, tp->mii_advertise, + tp->phys[phy_num]); tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise); } break; @@ -335,8 +335,8 @@ void tulip_select_media(struct net_device *dev, int startup) struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset]; unsigned char *rst = rleaf->leafdata; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Resetting the transceiver.\n", - dev->name); + printk(KERN_DEBUG "%s: Resetting the transceiver\n", + dev->name); for (i = 0; i < rst[0]; i++) iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15); } @@ -344,20 +344,20 @@ void tulip_select_media(struct net_device *dev, int startup) break; } default: - printk(KERN_DEBUG "%s: Invalid media table selection %d.\n", - dev->name, mleaf->type); + printk(KERN_DEBUG "%s: Invalid media table selection %d\n", + dev->name, mleaf->type); new_csr6 = 0x020E0000; } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n", - dev->name, medianame[dev->if_port], + printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %02x\n", + dev->name, medianame[dev->if_port], ioread32(ioaddr + CSR12) & 0xff); } else if (tp->chip_id == LC82C168) { if (startup && ! tp->medialock) dev->if_port = tp->mii_cnt ? 11 : 0; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s.\n", - dev->name, ioread32(ioaddr + 0xB8), medianame[dev->if_port]); + printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, media %s\n", + dev->name, ioread32(ioaddr + 0xB8), medianame[dev->if_port]); if (tp->mii_cnt) { new_csr6 = 0x810C0000; iowrite32(0x0001, ioaddr + CSR15); @@ -388,10 +388,9 @@ void tulip_select_media(struct net_device *dev, int startup) } else new_csr6 = 0x03860000; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No media description table, assuming " - "%s transceiver, CSR12 %2.2x.\n", - dev->name, medianame[dev->if_port], - ioread32(ioaddr + CSR12)); + printk(KERN_DEBUG "%s: No media description table, assuming %s transceiver, CSR12 %02x\n", + dev->name, medianame[dev->if_port], + ioread32(ioaddr + CSR12)); } tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0); @@ -415,16 +414,17 @@ int tulip_check_duplex(struct net_device *dev) bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA); if (tulip_debug > 1) - printk(KERN_INFO "%s: MII status %4.4x, Link partner report " - "%4.4x.\n", dev->name, bmsr, lpa); + dev_info(&dev->dev, "MII status %04x, Link partner report %04x\n", + bmsr, lpa); if (bmsr == 0xffff) return -2; if ((bmsr & BMSR_LSTATUS) == 0) { int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); if ((new_bmsr & BMSR_LSTATUS) == 0) { if (tulip_debug > 1) - printk(KERN_INFO "%s: No link beat on the MII interface," - " status %4.4x.\n", dev->name, new_bmsr); + dev_info(&dev->dev, + "No link beat on the MII interface, status %04x\n", + new_bmsr); return -1; } } @@ -443,10 +443,10 @@ int tulip_check_duplex(struct net_device *dev) tulip_restart_rxtx(tp); if (tulip_debug > 0) - printk(KERN_INFO "%s: Setting %s-duplex based on MII" - "#%d link partner capability of %4.4x.\n", - dev->name, tp->full_duplex ? "full" : "half", - tp->phys[0], lpa); + dev_info(&dev->dev, + "Setting %s-duplex based on MII#%d link partner capability of %04x\n", + tp->full_duplex ? "full" : "half", + tp->phys[0], lpa); return 1; } @@ -501,15 +501,13 @@ void __devinit tulip_find_mii (struct net_device *dev, int board_idx) tp->phys[phy_idx++] = phy; - printk (KERN_INFO "tulip%d: MII transceiver #%d " - "config %4.4x status %4.4x advertising %4.4x.\n", + pr_info("tulip%d: MII transceiver #%d config %04x status %04x advertising %04x\n", board_idx, phy, mii_reg0, mii_status, mii_advert); /* Fixup for DLink with miswired PHY. */ if (mii_advert != to_advert) { - printk (KERN_DEBUG "tulip%d: Advertising %4.4x on PHY %d," - " previously advertising %4.4x.\n", - board_idx, to_advert, phy, mii_advert); + printk(KERN_DEBUG "tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n", + board_idx, to_advert, phy, mii_advert); tulip_mdio_write (dev, phy, 4, to_advert); } @@ -554,7 +552,7 @@ void __devinit tulip_find_mii (struct net_device *dev, int board_idx) } tp->mii_cnt = phy_idx; if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) { - printk (KERN_INFO "tulip%d: ***WARNING***: No MII transceiver found!\n", + pr_info("tulip%d: ***WARNING***: No MII transceiver found!\n", board_idx); tp->phys[0] = 1; } -- cgit v1.2.3 From 1df8bbd1420705277cd382b1386cda724d61a678 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:24 +0000 Subject: tulip/pnic.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/pnic.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index d3253ed09dfc..966efa1a27d7 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c @@ -40,8 +40,8 @@ void pnic_do_nway(struct net_device *dev) new_csr6 |= 0x00000200; } if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC autonegotiated status %8.8x, %s.\n", - dev->name, phy_reg, medianame[dev->if_port]); + printk(KERN_DEBUG "%s: PNIC autonegotiated status %08x, %s\n", + dev->name, phy_reg, medianame[dev->if_port]); if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; /* Restart Tx */ @@ -58,8 +58,8 @@ void pnic_lnk_change(struct net_device *dev, int csr5) int phy_reg = ioread32(ioaddr + 0xB8); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n", - dev->name, phy_reg, csr5); + printk(KERN_DEBUG "%s: PNIC link changed state %08x, CSR5 %08x\n", + dev->name, phy_reg, csr5); if (ioread32(ioaddr + CSR5) & TPLnkFail) { iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); /* If we use an external MII, then we mustn't use the @@ -114,9 +114,8 @@ void pnic_timer(unsigned long data) int csr5 = ioread32(ioaddr + CSR5); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s " - "CSR5 %8.8x.\n", - dev->name, phy_reg, medianame[dev->if_port], csr5); + printk(KERN_DEBUG "%s: PNIC timer PHY status %08x, %s CSR5 %08x\n", + dev->name, phy_reg, medianame[dev->if_port], csr5); if (phy_reg & 0x04000000) { /* Remote link fault */ iowrite32(0x0201F078, ioaddr + 0xB8); next_tick = 1*HZ; @@ -126,10 +125,11 @@ void pnic_timer(unsigned long data) next_tick = 60*HZ; } else if (csr5 & TPLnkFail) { /* 100baseTx link beat */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " - "CSR5 %8.8x, PHY %3.3x.\n", - dev->name, medianame[dev->if_port], csr12, - ioread32(ioaddr + CSR5), ioread32(ioaddr + 0xB8)); + printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n", + dev->name, medianame[dev->if_port], + csr12, + ioread32(ioaddr + CSR5), + ioread32(ioaddr + 0xB8)); next_tick = 3*HZ; if (tp->medialock) { } else if (tp->nwayset && (dev->if_port & 1)) { @@ -151,10 +151,11 @@ void pnic_timer(unsigned long data) tulip_restart_rxtx(tp); dev->trans_start = jiffies; if (tulip_debug > 1) - printk(KERN_INFO "%s: Changing PNIC configuration to %s " - "%s-duplex, CSR6 %8.8x.\n", - dev->name, medianame[dev->if_port], - tp->full_duplex ? "full" : "half", new_csr6); + dev_info(&dev->dev, + "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n", + medianame[dev->if_port], + tp->full_duplex ? "full" : "half", + new_csr6); } } } @@ -162,7 +163,7 @@ too_good_connection: mod_timer(&tp->timer, RUN_AT(next_tick)); if(!ioread32(ioaddr + CSR7)) { if (tulip_debug > 1) - printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name); + dev_info(&dev->dev, "sw timer wakeup\n"); disable_irq(dev->irq); tulip_refill_rx(dev); enable_irq(dev->irq); -- cgit v1.2.3 From 22086a1172b69b9f6200e169dc99a252a204affb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:25 +0000 Subject: tulip/pnic2.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/pnic2.c | 59 ++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index d8418694bf46..b8197666021e 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c @@ -87,8 +87,8 @@ void pnic2_timer(unsigned long data) int next_tick = 60*HZ; if (tulip_debug > 3) - printk(KERN_INFO"%s: PNIC2 negotiation status %8.8x.\n", - dev->name,ioread32(ioaddr + CSR12)); + dev_info(&dev->dev, "PNIC2 negotiation status %08x\n", + ioread32(ioaddr + CSR12)); if (next_tick) { mod_timer(&tp->timer, RUN_AT(next_tick)); @@ -125,8 +125,8 @@ void pnic2_start_nway(struct net_device *dev) csr14 |= 0x00001184; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Restarting PNIC2 autonegotiation, " - "csr14=%8.8x.\n", dev->name, csr14); + printk(KERN_DEBUG "%s: Restarting PNIC2 autonegotiation, csr14=%08x\n", + dev->name, csr14); /* tell pnic2_lnk_change we are doing an nway negotiation */ dev->if_port = 0; @@ -137,8 +137,8 @@ void pnic2_start_nway(struct net_device *dev) tp->csr6 = ioread32(ioaddr + CSR6); if (tulip_debug > 1) - printk(KERN_DEBUG "%s: On Entry to Nway, " - "csr6=%8.8x.\n", dev->name, tp->csr6); + printk(KERN_DEBUG "%s: On Entry to Nway, csr6=%08x\n", + dev->name, tp->csr6); /* mask off any bits not to touch * comment at top of file explains mask value @@ -181,9 +181,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) int csr12 = ioread32(ioaddr + CSR12); if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 link status interrupt %8.8x, " - " CSR5 %x, %8.8x.\n", dev->name, csr12, - csr5, ioread32(ioaddr + CSR14)); + dev_info(&dev->dev, + "PNIC2 link status interrupt %08x, CSR5 %x, %08x\n", + csr12, csr5, ioread32(ioaddr + CSR14)); /* If NWay finished and we have a negotiated partner capability. * check bits 14:12 for bit pattern 101 - all is good @@ -215,9 +215,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) else if (negotiated & 0x0020) dev->if_port = 0; else { if (tulip_debug > 1) - printk(KERN_INFO "%s: funny autonegotiate result " - "csr12 %8.8x advertising %4.4x\n", - dev->name, csr12, tp->sym_advertise); + dev_info(&dev->dev, + "funny autonegotiate result csr12 %08x advertising %04x\n", + csr12, tp->sym_advertise); tp->nwayset = 0; /* so check if 100baseTx link state is okay */ if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) @@ -231,10 +231,11 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) if (tulip_debug > 1) { if (tp->nwayset) - printk(KERN_INFO "%s: Switching to %s based on link " - "negotiation %4.4x & %4.4x = %4.4x.\n", - dev->name, medianame[dev->if_port], - tp->sym_advertise, tp->lpar, negotiated); + dev_info(&dev->dev, + "Switching to %s based on link negotiation %04x & %04x = %04x\n", + medianame[dev->if_port], + tp->sym_advertise, tp->lpar, + negotiated); } /* remember to turn off bit 7 - autonegotiate @@ -270,9 +271,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) iowrite32(1, ioaddr + CSR13); if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 " - "%8.8x.\n", dev->name, tp->csr6, - ioread32(ioaddr + CSR6), ioread32(ioaddr + CSR12)); + printk(KERN_DEBUG "%s: Setting CSR6 %08x/%x CSR12 %08x\n", + dev->name, tp->csr6, + ioread32(ioaddr + CSR6), ioread32(ioaddr + CSR12)); /* now the following actually writes out the * new csr6 values @@ -282,9 +283,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) return; } else { - printk(KERN_INFO "%s: Autonegotiation failed, " - "using %s, link beat status %4.4x.\n", - dev->name, medianame[dev->if_port], csr12); + dev_info(&dev->dev, + "Autonegotiation failed, using %s, link beat status %04x\n", + medianame[dev->if_port], csr12); /* remember to turn off bit 7 - autonegotiate * enable so we don't forget @@ -339,9 +340,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* we are at 100mb and a potential link change occurred */ if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 2) ? "failed" : "good"); + dev_info(&dev->dev, "PNIC2 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 2) ? "failed" : "good"); /* check 100 link beat */ @@ -364,9 +365,9 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) /* we are at 10mb and a potential link change occurred */ if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 %s link beat %s.\n", - dev->name, medianame[dev->if_port], - (csr12 & 4) ? "failed" : "good"); + dev_info(&dev->dev, "PNIC2 %s link beat %s\n", + medianame[dev->if_port], + (csr12 & 4) ? "failed" : "good"); tp->nway = 0; @@ -385,7 +386,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) if (tulip_debug > 1) - printk(KERN_INFO"%s: PNIC2 Link Change Default?\n",dev->name); + dev_info(&dev->dev, "PNIC2 Link Change Default?\n"); /* if all else fails default to trying 10baseT-HD */ dev->if_port = 0; -- cgit v1.2.3 From 27146c43c4dbb727c4a211541af46577de2984af Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:26 +0000 Subject: tulip/timer.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/timer.c | 52 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index a0e084223082..36c2725ec886 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c @@ -28,11 +28,11 @@ void tulip_media_task(struct work_struct *work) unsigned long flags; if (tulip_debug > 2) { - printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode" - " %8.8x SIA %8.8x %8.8x %8.8x %8.8x.\n", - dev->name, medianame[dev->if_port], ioread32(ioaddr + CSR5), - ioread32(ioaddr + CSR6), csr12, ioread32(ioaddr + CSR13), - ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); + printk(KERN_DEBUG "%s: Media selection tick, %s, status %08x mode %08x SIA %08x %08x %08x %08x\n", + dev->name, medianame[dev->if_port], + ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR6), + csr12, ioread32(ioaddr + CSR13), + ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15)); } switch (tp->chip_id) { case DC21140: @@ -48,9 +48,9 @@ void tulip_media_task(struct work_struct *work) Assume this a generic MII or SYM transceiver. */ next_tick = 60*HZ; if (tulip_debug > 2) - printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x " - "CSR12 0x%2.2x.\n", - dev->name, ioread32(ioaddr + CSR6), csr12 & 0xff); + printk(KERN_DEBUG "%s: network media monitor CSR6 %08x CSR12 0x%02x\n", + dev->name, + ioread32(ioaddr + CSR6), csr12 & 0xff); break; } mleaf = &tp->mtable->mleaf[tp->cur_index]; @@ -62,9 +62,8 @@ void tulip_media_task(struct work_struct *work) s8 bitnum = p[offset]; if (p[offset+1] & 0x80) { if (tulip_debug > 1) - printk(KERN_DEBUG"%s: Transceiver monitor tick " - "CSR12=%#2.2x, no media sense.\n", - dev->name, csr12); + printk(KERN_DEBUG "%s: Transceiver monitor tick CSR12=%#02x, no media sense\n", + dev->name, csr12); if (mleaf->type == 4) { if (mleaf->media == 3 && (csr12 & 0x02)) goto select_next_media; @@ -72,16 +71,16 @@ void tulip_media_task(struct work_struct *work) break; } if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x" - " bit %d is %d, expecting %d.\n", - dev->name, csr12, (bitnum >> 1) & 7, - (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, - (bitnum >= 0)); + printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#02x bit %d is %d, expecting %d\n", + dev->name, csr12, (bitnum >> 1) & 7, + (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, + (bitnum >= 0)); /* Check that the specified bit has the proper value. */ if ((bitnum < 0) != ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { if (tulip_debug > 2) - printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name, + printk(KERN_DEBUG "%s: Link beat detected for %s\n", + dev->name, medianame[mleaf->media & MEDIA_MASK]); if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ goto actually_mii; @@ -100,9 +99,9 @@ void tulip_media_task(struct work_struct *work) if (tulip_media_cap[dev->if_port] & MediaIsFD) goto select_next_media; /* Skip FD entries. */ if (tulip_debug > 1) - printk(KERN_DEBUG "%s: No link beat on media %s," - " trying transceiver type %s.\n", - dev->name, medianame[mleaf->media & MEDIA_MASK], + printk(KERN_DEBUG "%s: No link beat on media %s, trying transceiver type %s\n", + dev->name, + medianame[mleaf->media & MEDIA_MASK], medianame[tp->mtable->mleaf[tp->cur_index].media]); tulip_select_media(dev, 0); /* Restart the transmit process. */ @@ -151,8 +150,8 @@ void mxic_timer(unsigned long data) int next_tick = 60*HZ; if (tulip_debug > 3) { - printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, - ioread32(ioaddr + CSR12)); + dev_info(&dev->dev, "MXIC negotiation status %08x\n", + ioread32(ioaddr + CSR12)); } if (next_tick) { mod_timer(&tp->timer, RUN_AT(next_tick)); @@ -167,11 +166,10 @@ void comet_timer(unsigned long data) int next_tick = 60*HZ; if (tulip_debug > 1) - printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability " - "%4.4x.\n", - dev->name, - tulip_mdio_read(dev, tp->phys[0], 1), - tulip_mdio_read(dev, tp->phys[0], 5)); + printk(KERN_DEBUG "%s: Comet link status %04x partner capability %04x\n", + dev->name, + tulip_mdio_read(dev, tp->phys[0], 1), + tulip_mdio_read(dev, tp->phys[0], 5)); /* mod_timer synchronizes us with potential add_timer calls * from interrupts. */ -- cgit v1.2.3 From e02fb7aa0714ca9357571bb15ef0fe278a150cc7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:27 +0000 Subject: tulip/uli526x.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove DRV_NAME from logging messages Add do {} while(0) to ULI526X_DBUG macro Make SHOW_MEDIA_TYPE macro more readable Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/uli526x.c | 46 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index d549042a01df..dc3335d906f6 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -12,6 +12,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "uli526x" #define DRV_VERSION "0.9.3" #define DRV_RELDATE "2005-7-29" @@ -82,9 +84,16 @@ #define ULI526X_TX_TIMEOUT ((16*HZ)/2) /* tx packet time-out time 8 s" */ #define ULI526X_TX_KICK (4*HZ/2) /* tx packet Kick-out time 2 s" */ -#define ULI526X_DBUG(dbug_now, msg, value) if (uli526x_debug || (dbug_now)) printk(KERN_ERR DRV_NAME ": %s %lx\n", (msg), (long) (value)) +#define ULI526X_DBUG(dbug_now, msg, value) \ +do { \ + if (uli526x_debug || (dbug_now)) \ + pr_err("%s %lx\n", (msg), (long) (value)); \ +} while (0) -#define SHOW_MEDIA_TYPE(mode) printk(KERN_ERR DRV_NAME ": Change Speed to %sMhz %s duplex\n",mode & 1 ?"100":"10", mode & 4 ? "full":"half"); +#define SHOW_MEDIA_TYPE(mode) \ + pr_err("Change Speed to %sMhz %s duplex\n", \ + mode & 1 ? "100" : "10", \ + mode & 4 ? "full" : "half"); /* CR9 definition: SROM/MII */ @@ -284,7 +293,7 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n"); + pr_warning("32-bit PCI DMA not available\n"); err = -ENODEV; goto err_out_free; } @@ -295,19 +304,19 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, goto err_out_free; if (!pci_resource_start(pdev, 0)) { - printk(KERN_ERR DRV_NAME ": I/O base is zero\n"); + pr_err("I/O base is zero\n"); err = -ENODEV; goto err_out_disable; } if (pci_resource_len(pdev, 0) < (ULI526X_IO_SIZE) ) { - printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n"); + pr_err("Allocated I/O size too small\n"); err = -ENODEV; goto err_out_disable; } if (pci_request_regions(pdev, DRV_NAME)) { - printk(KERN_ERR DRV_NAME ": Failed to request PCI regions\n"); + pr_err("Failed to request PCI regions\n"); err = -ENODEV; goto err_out_disable; } @@ -382,9 +391,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, if (err) goto err_out_res; - printk(KERN_INFO "%s: ULi M%04lx at pci%s, %pM, irq %d.\n", - dev->name,ent->driver_data >> 16,pci_name(pdev), - dev->dev_addr, dev->irq); + dev_info(&dev->dev, "ULi M%04lx at pci%s, %pM, irq %d\n", + ent->driver_data >> 16, pci_name(pdev), + dev->dev_addr, dev->irq); pci_set_master(pdev); @@ -516,7 +525,7 @@ static void uli526x_init(struct net_device *dev) } } if(phy_tmp == 32) - printk(KERN_WARNING "Can not find the phy address!!!"); + pr_warning("Can not find the phy address!!!"); /* Parser SROM and media mode */ db->media_mode = uli526x_media_mode; @@ -582,7 +591,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb, /* Too large packet check */ if (skb->len > MAX_PACKET_SIZE) { - printk(KERN_ERR DRV_NAME ": big packet = %d\n", (u16)skb->len); + pr_err("big packet = %d\n", (u16)skb->len); dev_kfree_skb(skb); return NETDEV_TX_OK; } @@ -592,7 +601,7 @@ static netdev_tx_t uli526x_start_xmit(struct sk_buff *skb, /* No Tx resource check, it never happen nromally */ if (db->tx_packet_cnt >= TX_FREE_DESC_CNT) { spin_unlock_irqrestore(&db->lock, flags); - printk(KERN_ERR DRV_NAME ": No Tx resource %ld\n", db->tx_packet_cnt); + pr_err("No Tx resource %ld\n", db->tx_packet_cnt); return NETDEV_TX_BUSY; } @@ -1058,7 +1067,7 @@ static void uli526x_timer(unsigned long data) /* Link Failed */ ULI526X_DBUG(0, "Link Failed", tmp_cr12); netif_carrier_off(dev); - printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name); + pr_info("%s NIC Link is Down\n",dev->name); db->link_failed = 1; /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */ @@ -1090,11 +1099,11 @@ static void uli526x_timer(unsigned long data) } if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD) { - printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed); + pr_info("%s NIC Link is Up %d Mbps Full duplex\n",dev->name,TmpSpeed); } else { - printk(KERN_INFO "uli526x: %s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed); + pr_info("%s NIC Link is Up %d Mbps Half duplex\n",dev->name,TmpSpeed); } netif_carrier_on(dev); } @@ -1104,7 +1113,7 @@ static void uli526x_timer(unsigned long data) { if(db->init==1) { - printk(KERN_INFO "uli526x: %s NIC Link is Down\n",dev->name); + pr_info("%s NIC Link is Down\n",dev->name); netif_carrier_off(dev); } } @@ -1230,8 +1239,7 @@ static int uli526x_resume(struct pci_dev *pdev) err = pci_set_power_state(pdev, PCI_D0); if (err) { - printk(KERN_WARNING "%s: Could not put device into D0\n", - dev->name); + dev_warn(&dev->dev, "Could not put device into D0\n"); return err; } @@ -1432,7 +1440,7 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt) update_cr6(db->cr6_data, dev->base_addr); dev->trans_start = jiffies; } else - printk(KERN_ERR DRV_NAME ": No Tx resource - Send_filter_frame!\n"); + pr_err("No Tx resource - Send_filter_frame!\n"); } -- cgit v1.2.3 From a1e37bc5e2d0ff8d025221e27c2bfff762072311 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:28 +0000 Subject: tulip/winbond-840.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Convert %d.%d.%d.%d to %pI4 Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/winbond-840.c | 177 ++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 23395e1ff238..9fb89afccf7c 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -376,8 +376,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, irq = pdev->irq; if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_WARNING "Winbond-840: Device %s disabled due to DMA limitations.\n", - pci_name(pdev)); + pr_warning("Winbond-840: Device %s disabled due to DMA limitations\n", + pci_name(pdev)); return -EIO; } dev = alloc_etherdev(sizeof(*np)); @@ -422,8 +422,9 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, if (option & 0x200) np->mii_if.full_duplex = 1; if (option & 15) - printk(KERN_INFO "%s: ignoring user supplied media type %d", - dev->name, option & 15); + dev_info(&dev->dev, + "ignoring user supplied media type %d", + option & 15); } if (find_cnt < MAX_UNITS && full_duplex[find_cnt] > 0) np->mii_if.full_duplex = 1; @@ -440,9 +441,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, if (i) goto err_out_cleardev; - printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n", - dev->name, pci_id_tbl[chip_idx].name, ioaddr, - dev->dev_addr, irq); + dev_info(&dev->dev, "%s at %p, %pM, IRQ %d\n", + pci_id_tbl[chip_idx].name, ioaddr, dev->dev_addr, irq); if (np->drv_flags & CanHaveMII) { int phy, phy_idx = 0; @@ -453,16 +453,17 @@ static int __devinit w840_probe1 (struct pci_dev *pdev, np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE); np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+ mdio_read(dev, phy, MII_PHYSID2); - printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status " - "0x%4.4x advertising %4.4x.\n", - dev->name, np->mii, phy, mii_status, np->mii_if.advertising); + dev_info(&dev->dev, + "MII PHY %08xh found at address %d, status 0x%04x advertising %04x\n", + np->mii, phy, mii_status, + np->mii_if.advertising); } } np->mii_cnt = phy_idx; np->mii_if.phy_id = np->phys[0]; if (phy_idx == 0) { - printk(KERN_WARNING "%s: MII PHY not found -- this device may " - "not operate correctly.\n", dev->name); + dev_warn(&dev->dev, + "MII PHY not found -- this device may not operate correctly\n"); } } @@ -644,8 +645,8 @@ static int netdev_open(struct net_device *dev) goto out_err; if (debug > 1) - printk(KERN_DEBUG "%s: w89c840_open() irq %d.\n", - dev->name, dev->irq); + printk(KERN_DEBUG "%s: w89c840_open() irq %d\n", + dev->name, dev->irq); if((i=alloc_ringdesc(dev))) goto out_err; @@ -657,7 +658,7 @@ static int netdev_open(struct net_device *dev) netif_start_queue(dev); if (debug > 2) - printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name); + printk(KERN_DEBUG "%s: Done netdev_open()\n", dev->name); /* Set the timer to check for link beat. */ init_timer(&np->timer); @@ -688,16 +689,18 @@ static int update_link(struct net_device *dev) if (!(mii_reg & 0x4)) { if (netif_carrier_ok(dev)) { if (debug) - printk(KERN_INFO "%s: MII #%d reports no link. Disabling watchdog.\n", - dev->name, np->phys[0]); + dev_info(&dev->dev, + "MII #%d reports no link. Disabling watchdog\n", + np->phys[0]); netif_carrier_off(dev); } return np->csr6; } if (!netif_carrier_ok(dev)) { if (debug) - printk(KERN_INFO "%s: MII #%d link is back. Enabling watchdog.\n", - dev->name, np->phys[0]); + dev_info(&dev->dev, + "MII #%d link is back. Enabling watchdog\n", + np->phys[0]); netif_carrier_on(dev); } @@ -729,9 +732,10 @@ static int update_link(struct net_device *dev) if (fasteth) result |= 0x20000000; if (result != np->csr6 && debug) - printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n", - dev->name, fasteth ? 100 : 10, - duplex ? "full" : "half", np->phys[0]); + dev_info(&dev->dev, + "Setting %dMBit-%s-duplex based on MII#%d\n", + fasteth ? 100 : 10, duplex ? "full" : "half", + np->phys[0]); return result; } @@ -763,8 +767,8 @@ static inline void update_csr6(struct net_device *dev, int new) limit--; if(!limit) { - printk(KERN_INFO "%s: couldn't stop rxtx, IntrStatus %xh.\n", - dev->name, csr5); + dev_info(&dev->dev, + "couldn't stop rxtx, IntrStatus %xh\n", csr5); break; } udelay(1); @@ -783,10 +787,9 @@ static void netdev_timer(unsigned long data) void __iomem *ioaddr = np->base_addr; if (debug > 2) - printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x " - "config %8.8x.\n", - dev->name, ioread32(ioaddr + IntrStatus), - ioread32(ioaddr + NetworkConfig)); + printk(KERN_DEBUG "%s: Media selection timer tick, status %08x config %08x\n", + dev->name, ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); spin_lock_irq(&np->lock); update_csr6(dev, update_link(dev)); spin_unlock_irq(&np->lock); @@ -899,8 +902,8 @@ static void init_registers(struct net_device *dev) /* When not a module we can work around broken '486 PCI boards. */ if (boot_cpu_data.x86 <= 4) { i |= 0x4800; - printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache " - "alignment to 8 longwords.\n", dev->name); + dev_info(&dev->dev, + "This is a 386/486 PCI system, setting cache alignment to 8 longwords\n"); } else { i |= 0xE000; } @@ -931,22 +934,23 @@ static void tx_timeout(struct net_device *dev) struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->base_addr; - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," - " resetting...\n", dev->name, ioread32(ioaddr + IntrStatus)); + dev_warn(&dev->dev, "Transmit timed out, status %08x, resetting...\n", + ioread32(ioaddr + IntrStatus)); { int i; printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(" %8.8x", (unsigned int)np->rx_ring[i].status); - printk(KERN_DEBUG" Tx ring %p: ", np->tx_ring); + printk(KERN_CONT " %08x", (unsigned int)np->rx_ring[i].status); + printk(KERN_CONT "\n"); + printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(" %8.8x", np->tx_ring[i].status); - printk("\n"); + printk(KERN_CONT " %08x", np->tx_ring[i].status); + printk(KERN_CONT "\n"); } - printk(KERN_DEBUG "Tx cur %d Tx dirty %d Tx Full %d, q bytes %d.\n", - np->cur_tx, np->dirty_tx, np->tx_full, np->tx_q_bytes); - printk(KERN_DEBUG "Tx Descriptor addr %xh.\n",ioread32(ioaddr+0x4C)); + printk(KERN_DEBUG "Tx cur %d Tx dirty %d Tx Full %d, q bytes %d\n", + np->cur_tx, np->dirty_tx, np->tx_full, np->tx_q_bytes); + printk(KERN_DEBUG "Tx Descriptor addr %xh\n", ioread32(ioaddr+0x4C)); disable_irq(dev->irq); spin_lock_irq(&np->lock); @@ -1055,8 +1059,8 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (debug > 4) { - printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n", - dev->name, np->cur_tx, entry); + printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d\n", + dev->name, np->cur_tx, entry); } return NETDEV_TX_OK; } @@ -1073,8 +1077,8 @@ static void netdev_tx_done(struct net_device *dev) if (tx_status & 0x8000) { /* There was an error, log it. */ #ifndef final_version if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, tx_status); + printk(KERN_DEBUG "%s: Transmit error, Tx status %08x\n", + dev->name, tx_status); #endif np->stats.tx_errors++; if (tx_status & 0x0104) np->stats.tx_aborted_errors++; @@ -1086,8 +1090,8 @@ static void netdev_tx_done(struct net_device *dev) } else { #ifndef final_version if (debug > 3) - printk(KERN_DEBUG "%s: Transmit slot %d ok, Tx status %8.8x.\n", - dev->name, entry, tx_status); + printk(KERN_DEBUG "%s: Transmit slot %d ok, Tx status %08x\n", + dev->name, entry, tx_status); #endif np->stats.tx_bytes += np->tx_skbuff[entry]->len; np->stats.collisions += (tx_status >> 3) & 15; @@ -1130,8 +1134,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) iowrite32(intr_status & 0x001ffff, ioaddr + IntrStatus); if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", - dev->name, intr_status); + printk(KERN_DEBUG "%s: Interrupt, status %04x\n", + dev->name, intr_status); if ((intr_status & (NormalIntr|AbnormalIntr)) == 0) break; @@ -1156,8 +1160,9 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) netdev_error(dev, intr_status); if (--work_limit < 0) { - printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=0x%4.4x.\n", dev->name, intr_status); + dev_warn(&dev->dev, + "Too much work at interrupt, status=0x%04x\n", + intr_status); /* Set the timer to re-enable the other interrupts after 10*82usec ticks. */ spin_lock(&np->lock); @@ -1171,8 +1176,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) } while (1); if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, ioread32(ioaddr + IntrStatus)); + printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x\n", + dev->name, ioread32(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } @@ -1185,8 +1190,8 @@ static int netdev_rx(struct net_device *dev) int work_limit = np->dirty_rx + RX_RING_SIZE - np->cur_rx; if (debug > 4) { - printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n", - entry, np->rx_ring[entry].status); + printk(KERN_DEBUG " In netdev_rx(), entry %d status %04x\n", + entry, np->rx_ring[entry].status); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ @@ -1195,24 +1200,24 @@ static int netdev_rx(struct net_device *dev) s32 status = desc->status; if (debug > 4) - printk(KERN_DEBUG " netdev_rx() status was %8.8x.\n", - status); + printk(KERN_DEBUG " netdev_rx() status was %08x\n", + status); if (status < 0) break; if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { - printk(KERN_WARNING "%s: Oversized Ethernet frame spanned " - "multiple buffers, entry %#x status %4.4x!\n", - dev->name, np->cur_rx, status); + dev_warn(&dev->dev, + "Oversized Ethernet frame spanned multiple buffers, entry %#x status %04x!\n", + np->cur_rx, status); np->stats.rx_length_errors++; } } else if (status & 0x8000) { /* There was a fatal error. */ if (debug > 2) - printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", - dev->name, status); + printk(KERN_DEBUG "%s: Receive error, Rx status %08x\n", + dev->name, status); np->stats.rx_errors++; /* end of a packet.*/ if (status & 0x0890) np->stats.rx_length_errors++; if (status & 0x004C) np->stats.rx_frame_errors++; @@ -1225,8 +1230,8 @@ static int netdev_rx(struct net_device *dev) #ifndef final_version if (debug > 4) - printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d" - " status %x.\n", pkt_len, status); + printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d status %x\n", + pkt_len, status); #endif /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ @@ -1251,11 +1256,10 @@ static int netdev_rx(struct net_device *dev) #ifndef final_version /* Remove after testing. */ /* You will want this info for the initial debug. */ if (debug > 5) - printk(KERN_DEBUG " Rx data %pM %pM" - " %2.2x%2.2x %d.%d.%d.%d.\n", + printk(KERN_DEBUG " Rx data %pM %pM %02x%02x %pI4\n", &skb->data[0], &skb->data[6], skb->data[12], skb->data[13], - skb->data[14], skb->data[15], skb->data[16], skb->data[17]); + &skb->data[14]); #endif skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); @@ -1293,8 +1297,8 @@ static void netdev_error(struct net_device *dev, int intr_status) void __iomem *ioaddr = np->base_addr; if (debug > 2) - printk(KERN_DEBUG "%s: Abnormal event, %8.8x.\n", - dev->name, intr_status); + printk(KERN_DEBUG "%s: Abnormal event, %08x\n", + dev->name, intr_status); if (intr_status == 0xffffffff) return; spin_lock(&np->lock); @@ -1314,8 +1318,8 @@ static void netdev_error(struct net_device *dev, int intr_status) new = 127; /* load full packet before starting */ new = (np->csr6 & ~(0x7F << 14)) | (new<<14); #endif - printk(KERN_DEBUG "%s: Tx underflow, new csr6 %8.8x.\n", - dev->name, new); + printk(KERN_DEBUG "%s: Tx underflow, new csr6 %08x\n", + dev->name, new); update_csr6(dev, new); } if (intr_status & RxDied) { /* Missed a Rx frame. */ @@ -1487,11 +1491,13 @@ static int netdev_close(struct net_device *dev) netif_stop_queue(dev); if (debug > 1) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was %8.8x " - "Config %8.8x.\n", dev->name, ioread32(ioaddr + IntrStatus), - ioread32(ioaddr + NetworkConfig)); - printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", - dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); + printk(KERN_DEBUG "%s: Shutting down ethercard, status was %08x Config %08x\n", + dev->name, ioread32(ioaddr + IntrStatus), + ioread32(ioaddr + NetworkConfig)); + printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d\n", + dev->name, + np->cur_tx, np->dirty_tx, + np->cur_rx, np->dirty_rx); } /* Stop the chip's Tx and Rx processes. */ @@ -1512,18 +1518,16 @@ static int netdev_close(struct net_device *dev) if (debug > 2) { int i; - printk(KERN_DEBUG" Tx ring at %8.8x:\n", - (int)np->tx_ring); + printk(KERN_DEBUG" Tx ring at %08x:\n", (int)np->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n", - i, np->tx_ring[i].length, - np->tx_ring[i].status, np->tx_ring[i].buffer1); - printk(KERN_DEBUG " Rx ring %8.8x:\n", - (int)np->rx_ring); + printk(KERN_DEBUG " #%d desc. %04x %04x %08x\n", + i, np->tx_ring[i].length, + np->tx_ring[i].status, np->tx_ring[i].buffer1); + printk(KERN_DEBUG " Rx ring %08x:\n", (int)np->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) { - printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n", - i, np->rx_ring[i].length, - np->rx_ring[i].status, np->rx_ring[i].buffer1); + printk(KERN_DEBUG " #%d desc. %04x %04x %08x\n", + i, np->rx_ring[i].length, + np->rx_ring[i].status, np->rx_ring[i].buffer1); } } #endif /* __i386__ debugging only */ @@ -1622,9 +1626,8 @@ static int w840_resume (struct pci_dev *pdev) goto out; /* device not suspended */ if (netif_running(dev)) { if ((retval = pci_enable_device(pdev))) { - printk (KERN_ERR - "%s: pci_enable_device failed in resume\n", - dev->name); + dev_err(&dev->dev, + "pci_enable_device failed in resume\n"); goto out; } spin_lock_irq(&np->lock); -- cgit v1.2.3 From 44298ec0f20c45b9be96e181976aef1152d373b2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 28 Jan 2010 20:59:29 +0000 Subject: tulip/xircom_cb.c: Use dev_ and pr_ Convert printks to dev_ where a dev is available Convert printks to pr_ where not Coalesce format strings Change print formats with %d.dx to %0dx Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove DRV_NAME and xircom_cb from pr_ Convert embedded function names in logging messages to %s, __func__ Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tulip/xircom_cb.c | 44 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index c84123fd635c..acfeeb980562 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c @@ -14,6 +14,8 @@ * $Id: xircom_cb.c,v 1.33 2001/03/19 14:02:07 arjanv Exp $ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -234,7 +236,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ pci_write_config_word (pdev, PCI_STATUS,tmp16); if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) { - printk(KERN_ERR "xircom_probe: failed to allocate io-region\n"); + pr_err("%s: failed to allocate io-region\n", __func__); return -ENODEV; } @@ -245,7 +247,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ */ dev = alloc_etherdev(sizeof(struct xircom_private)); if (!dev) { - printk(KERN_ERR "xircom_probe: failed to allocate etherdev\n"); + pr_err("%s: failed to allocate etherdev\n", __func__); goto device_fail; } private = netdev_priv(dev); @@ -253,12 +255,12 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ /* Allocate the send/receive buffers */ private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle); if (private->rx_buffer == NULL) { - printk(KERN_ERR "xircom_probe: no memory for rx buffer \n"); + pr_err("%s: no memory for rx buffer\n", __func__); goto rx_buf_fail; } private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle); if (private->tx_buffer == NULL) { - printk(KERN_ERR "xircom_probe: no memory for tx buffer \n"); + pr_err("%s: no memory for tx buffer\n", __func__); goto tx_buf_fail; } @@ -281,11 +283,12 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_ pci_set_drvdata(pdev, dev); if (register_netdev(dev)) { - printk(KERN_ERR "xircom_probe: netdevice registration failed.\n"); + pr_err("%s: netdevice registration failed\n", __func__); goto reg_fail; } - printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq); + dev_info(&dev->dev, "Xircom cardbus revision %i at irq %i\n", + pdev->revision, pdev->irq); /* start the transmitter to get a heartbeat */ /* TODO: send 2 dummy packets here */ transceiver_voodoo(private); @@ -347,8 +350,10 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) #ifdef DEBUG print_binary(status); - printk("tx status 0x%08x 0x%08x \n",card->tx_buffer[0],card->tx_buffer[4]); - printk("rx status 0x%08x 0x%08x \n",card->rx_buffer[0],card->rx_buffer[4]); + printk("tx status 0x%08x 0x%08x \n", + card->tx_buffer[0], card->tx_buffer[4]); + printk("rx status 0x%08x 0x%08x \n", + card->rx_buffer[0], card->rx_buffer[4]); #endif /* Handle shared irq and hotplug */ if (status == 0 || status == 0xffffffff) { @@ -358,9 +363,9 @@ static irqreturn_t xircom_interrupt(int irq, void *dev_instance) if (link_status_changed(card)) { int newlink; - printk(KERN_DEBUG "xircom_cb: Link status has changed \n"); + printk(KERN_DEBUG "xircom_cb: Link status has changed\n"); newlink = link_status(card); - printk(KERN_INFO "xircom_cb: Link is %i mbit \n",newlink); + dev_info(&dev->dev, "Link is %i mbit\n", newlink); if (newlink) netif_carrier_on(dev); else @@ -457,7 +462,8 @@ static int xircom_open(struct net_device *dev) struct xircom_private *xp = netdev_priv(dev); int retval; enter("xircom_open"); - printk(KERN_INFO "xircom cardbus adaptor found, registering as %s, using irq %i \n",dev->name,dev->irq); + pr_info("xircom cardbus adaptor found, registering as %s, using irq %i \n", + dev->name, dev->irq); retval = request_irq(dev->irq, xircom_interrupt, IRQF_SHARED, dev->name, dev); if (retval) { leave("xircom_open - No IRQ"); @@ -770,7 +776,7 @@ static void activate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Receiver failed to deactivate\n"); + pr_err("Receiver failed to deactivate\n"); } /* enable the receiver */ @@ -787,7 +793,7 @@ static void activate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Receiver failed to re-activate\n"); + pr_err("Receiver failed to re-activate\n"); } leave("activate_receiver"); @@ -818,7 +824,7 @@ static void deactivate_receiver(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Receiver failed to deactivate\n"); + pr_err("Receiver failed to deactivate\n"); } @@ -861,7 +867,7 @@ static void activate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); + pr_err("Transmitter failed to deactivate\n"); } /* enable the transmitter */ @@ -878,7 +884,7 @@ static void activate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Transmitter failed to re-activate\n"); + pr_err("Transmitter failed to re-activate\n"); } leave("activate_transmitter"); @@ -909,7 +915,7 @@ static void deactivate_transmitter(struct xircom_private *card) udelay(50); counter--; if (counter <= 0) - printk(KERN_ERR "xircom_cb: Transmitter failed to deactivate\n"); + pr_err("Transmitter failed to deactivate\n"); } @@ -1184,7 +1190,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri struct sk_buff *skb; if (pkt_len > 1518) { - printk(KERN_ERR "xircom_cb: Packet length %i is bogus \n",pkt_len); + pr_err("Packet length %i is bogus\n", pkt_len); pkt_len = 1518; } @@ -1222,7 +1228,7 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p status = le32_to_cpu(card->tx_buffer[4*descnr]); #if 0 if (status & 0x8000) { /* Major error */ - printk(KERN_ERR "Major transmit error status %x \n", status); + pr_err("Major transmit error status %x\n", status); card->tx_buffer[4*descnr] = 0; netif_wake_queue (dev); } -- cgit v1.2.3 From c6c97bdaa3307d0811f14c99c38c63a8dae36e1f Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 1 Feb 2010 09:55:56 -0500 Subject: ps3_gelic_wireless: fix format warning Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index d520e9e8cdb2..448c5b6789d3 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -1449,7 +1449,7 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, void *buf = NULL; size_t len; - pr_debug("%s: <- always=%d essid_len=%d\n", __func__, + pr_debug("%s: <- always=%d essid_len=%z\n", __func__, always_scan, essid_len); if (mutex_lock_interruptible(&wl->scan_lock)) return -ERESTARTSYS; -- cgit v1.2.3 From f643e51d717b52ac28830e8bb98559b006a73bf4 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 29 Jan 2010 17:22:12 -0500 Subject: ath: make gcc check format arguments of ath_print(), fix all misuses Numeric channel is hard to get, so it won't be printed. Replace Mhz with MHz on the affected lines and add commas as needed. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 6 +++--- drivers/net/wireless/ath/ath9k/recv.c | 2 +- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- drivers/net/wireless/ath/debug.h | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e04835cb21b5..12069aac1d6c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -206,7 +206,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, r = ath9k_hw_reset(ah, hchan, fastcc); if (r) { ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " + "Unable to reset channel (%u MHz), " "reset status %d\n", channel->center_freq, r); spin_unlock_bh(&sc->sc_resetlock); @@ -869,7 +869,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) r = ath9k_hw_reset(ah, ah->curchan, false); if (r) { ath_print(common, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) ", + "Unable to reset channel (%u MHz), " "reset status %d\n", channel->center_freq, r); } @@ -924,7 +924,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) r = ath9k_hw_reset(ah, ah->curchan, false); if (r) { ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " + "Unable to reset channel (%u MHz), " "reset status %d\n", channel->center_freq, r); } diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 40b5d05edcce..1ca42e5148c8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -429,7 +429,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; ath_print(common, ATH_DBG_PS, "Going back to sleep after having received " - "PS-Poll data (0x%x)\n", + "PS-Poll data (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a6893cf0c43b..3c790a4f38f7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1857,7 +1857,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; ath_print(common, ATH_DBG_PS, "Going back to sleep after having " - "received TX status (0x%x)\n", + "received TX status (0x%lx)\n", sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA | diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index d6b685a06c5e..8263633c003c 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -65,11 +65,11 @@ enum ATH_DEBUG { #define ATH_DBG_DEFAULT (ATH_DBG_FATAL) #ifdef CONFIG_ATH_DEBUG -void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...); +void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); #else -static inline void ath_print(struct ath_common *common, - int dbg_mask, - const char *fmt, ...) +static inline void __attribute__ ((format (printf, 3, 4))) +ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) { } #endif /* CONFIG_ATH_DEBUG */ -- cgit v1.2.3 From 991a0987d9e821df1790bbbc368cf36db0c678d3 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Fri, 29 Jan 2010 17:22:26 -0500 Subject: ath9k: allocate string buffer in read_file_dma() by kmalloc() Using stack for that causes warnings with CONFIG_FRAME_WARN=1024 Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 43 ++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9489b6b25b5f..42d2a506845a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -75,17 +75,24 @@ static const struct file_operations fops_debug = { #endif +#define DMA_BUF_LEN 1024 + static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; struct ath_hw *ah = sc->sc_ah; - char buf[1024]; + char *buf; + int retval; unsigned int len = 0; u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; int i, qcuOffset = 0, dcuOffset = 0; u32 *qcuBase = &val[0], *dcuBase = &val[4]; + buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL); + if (!buf) + return 0; + ath9k_ps_wakeup(sc); REG_WRITE_D(ah, AR_MACMISC, @@ -93,20 +100,20 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S))); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "Raw DMA Debug values:\n"); for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { if (i % 4 == 0) - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); - len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", + len += snprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ", i, val[i]); } - len += snprintf(buf + len, sizeof(buf) - len, "\n\n"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "\n\n"); + len += snprintf(buf + len, DMA_BUF_LEN - len, "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { @@ -120,7 +127,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, dcuBase++; } - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "%2d %2x %1x %2x %2x\n", i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), @@ -128,35 +135,37 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); } - len += snprintf(buf + len, sizeof(buf) - len, "\n"); + len += snprintf(buf + len, DMA_BUF_LEN - len, "\n"); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "qcu_stitch state: %2x qcu_fetch state: %2x\n", (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "qcu_complete state: %2x dcu_complete state: %2x\n", (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "dcu_arb state: %2x dcu_fp state: %2x\n", (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); - len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", + len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n", REG_READ_D(ah, AR_OBS_BUS_1)); - len += snprintf(buf + len, sizeof(buf) - len, + len += snprintf(buf + len, DMA_BUF_LEN - len, "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); ath9k_ps_restore(sc); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return retval; } static const struct file_operations fops_dma = { -- cgit v1.2.3 From 28fd7daabfb35b7a0df2f7eaf460221e16dd2608 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 00:12:19 +0100 Subject: b43: N-PHY: update general workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 215 ++++++++++++++++++++------------------- drivers/net/wireless/b43/phy_n.h | 4 + 2 files changed, 115 insertions(+), 104 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8c39fb126d4f..60e730a6f1dd 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -246,110 +246,6 @@ static void b43_nphy_tables_init(struct b43_wldev *dev) b43_nphy_rev3plus_tables_init(dev); } -static void b43_nphy_workarounds(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - unsigned int i; - - b43_phy_set(dev, B43_NPHY_IQFLIP, - B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); - if (1 /* FIXME band is 2.4GHz */) { - b43_phy_set(dev, B43_NPHY_CLASSCTL, - B43_NPHY_CLASSCTL_CCKEN); - } else { - b43_phy_mask(dev, B43_NPHY_CLASSCTL, - ~B43_NPHY_CLASSCTL_CCKEN); - } - b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); - b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); - - /* Fixup some tables */ - b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); - b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); - b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); - b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); - b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); - b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); - - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); - - //TODO set RF sequence - - /* Set narrowband clip threshold */ - b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); - b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); - - /* Set wideband clip 2 threshold */ - b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, - ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, - 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, - ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, - 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); - - /* Set Clip 2 detect */ - b43_phy_set(dev, B43_NPHY_C1_CGAINI, - B43_NPHY_C1_CGAINI_CL2DETECT); - b43_phy_set(dev, B43_NPHY_C2_CGAINI, - B43_NPHY_C2_CGAINI_CL2DETECT); - - if (0 /*FIXME*/) { - /* Set dwell lengths */ - b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); - b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); - b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); - b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); - - /* Set gain backoff */ - b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, - ~B43_NPHY_C1_CGAINI_GAINBKOFF, - 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, - ~B43_NPHY_C2_CGAINI_GAINBKOFF, - 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); - - /* Set HPVGA2 index */ - b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, - ~B43_NPHY_C1_INITGAIN_HPVGA2, - 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, - ~B43_NPHY_C2_INITGAIN_HPVGA2, - 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); - - //FIXME verify that the specs really mean to use autoinc here. - for (i = 0; i < 3; i++) - b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); - } - - /* Set minimum gain value */ - b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, - ~B43_NPHY_C1_MINGAIN, - 23 << B43_NPHY_C1_MINGAIN_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, - ~B43_NPHY_C2_MINGAIN, - 23 << B43_NPHY_C2_MINGAIN_SHIFT); - - if (phy->rev < 2) { - b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, - ~B43_NPHY_SCRAM_SIGCTL_SCM); - } - - /* Set phase track alpha and beta */ - b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); - b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); - b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); - b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); - b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); - b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) { @@ -816,6 +712,117 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ +static void b43_nphy_workarounds(struct b43_wldev *dev) +{ + struct ssb_bus *bus = dev->dev->bus; + struct b43_phy *phy = &dev->phy; + struct b43_phy_n *nphy = phy->n; + + u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; + u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; + + u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; + u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_nphy_classifier(dev, 1, 0); + else + b43_nphy_classifier(dev, 1, 1); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + b43_phy_set(dev, B43_NPHY_IQFLIP, + B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); + + if (dev->phy.rev >= 3) { + /* TODO */ + } else { + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && + nphy->band5g_pwrgain) { + b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); + b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); + } else { + b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); + b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); + } + + /* TODO: convert to b43_ntab_write? */ + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); + + if (dev->phy.rev < 2) { + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); + } + + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); + b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); + + if (bus->sprom.boardflags2_lo & 0x100 && + bus->boardinfo.type == 0x8B) { + delays1[0] = 0x1; + delays1[5] = 0x14; + } + /*TODO:b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);*/ + /*TODO:b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);*/ + + /*TODO:b43_nphy_gain_crtl_workarounds(dev);*/ + + if (dev->phy.rev < 2) { + if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) + ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/ + } else if (dev->phy.rev == 2) { + b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); + b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); + } + + if (dev->phy.rev < 2) + b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, + ~B43_NPHY_SCRAM_SIGCTL_SCM); + + /* Set phase track alpha and beta */ + b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); + b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); + b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); + b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); + b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); + b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); + + b43_phy_mask(dev, B43_NPHY_PIL_DW1, + (u16)~B43_NPHY_PIL_DW_64QAM); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); + b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); + + if (dev->phy.rev == 2) + b43_phy_set(dev, B43_NPHY_FINERX2_CGC, + B43_NPHY_FINERX2_CGC_DECGC); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, bool test) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index f5a27661f659..ae82f0fc2096 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -976,6 +976,10 @@ struct b43_phy_n { s32 preamble_override; u32 bb_mult_save; + bool gain_boost; + bool elna_gain_config; + bool band5g_pwrgain; + u8 mphase_cal_phase_id; u16 mphase_txcal_cmdidx; u16 mphase_txcal_numcmds; -- cgit v1.2.3 From ef5127a4d256b9c0f47caae6cdc8ccfceedb09f9 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 00:12:20 +0100 Subject: b43: N-PHY: add workarounds for gain control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 130 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 60e730a6f1dd..d738d769b025 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -712,6 +712,134 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ +static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u8 i, j; + u8 code; + + /* TODO: for PHY >= 3 + s8 *lna1_gain, *lna2_gain; + u8 *gain_db, *gain_bits; + u16 *rfseq_init; + u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; + u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; + */ + + u8 rfseq_events[3] = { 6, 8, 7 }; + u8 rfseq_delays[3] = { 10, 30, 1 }; + + if (dev->phy.rev >= 3) { + /* TODO */ + } else { + /* Set Clip 2 detect */ + b43_phy_set(dev, B43_NPHY_C1_CGAINI, + B43_NPHY_C1_CGAINI_CL2DETECT); + b43_phy_set(dev, B43_NPHY_C2_CGAINI, + B43_NPHY_C2_CGAINI_CL2DETECT); + + /* Set narrowband clip threshold */ + b43_phy_set(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); + b43_phy_set(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); + + if (!dev->phy.is_40mhz) { + /* Set dwell lengths */ + b43_phy_set(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); + b43_phy_set(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); + b43_phy_set(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); + b43_phy_set(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); + } + + /* Set wideband clip 2 threshold */ + b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, + ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, + 21); + b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, + ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, + 21); + + if (!dev->phy.is_40mhz) { + b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, + ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1); + b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, + ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1); + b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI, + ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); + b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI, + ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); + } + + b43_phy_set(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); + + if (nphy->gain_boost) { + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && + dev->phy.is_40mhz) + code = 4; + else + code = 5; + } else { + code = dev->phy.is_40mhz ? 6 : 7; + } + + /* Set HPVGA2 index */ + b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, + ~B43_NPHY_C1_INITGAIN_HPVGA2, + code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); + b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, + ~B43_NPHY_C2_INITGAIN_HPVGA2, + code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x7C)); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x7C)); + + /* TODO: b43_nphy_adjust_lna_gain_table(dev); */ + + if (nphy->elna_gain_config) { + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); + + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x74)); + b43_phy_write(dev, B43_NPHY_TABLE_DATALO, + (code << 8 | 0x74)); + } + + if (dev->phy.rev == 2) { + for (i = 0; i < 4; i++) { + b43_phy_write(dev, B43_NPHY_TABLE_ADDR, + (0x0400 * i) + 0x0020); + for (j = 0; j < 21; j++) + b43_phy_write(dev, + B43_NPHY_TABLE_DATALO, 3 * j); + } + + /* TODO: b43_nphy_set_rf_sequence(dev, 5, + rfseq_events, rfseq_delays, 3);*/ + b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, + (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV, + 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_phy_maskset(dev, B43_PHY_N(0xC5D), + 0xFF80, 4); + } + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ static void b43_nphy_workarounds(struct b43_wldev *dev) { @@ -786,7 +914,7 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) /*TODO:b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);*/ /*TODO:b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);*/ - /*TODO:b43_nphy_gain_crtl_workarounds(dev);*/ + b43_nphy_gain_crtl_workarounds(dev); if (dev->phy.rev < 2) { if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) -- cgit v1.2.3 From a2bff2694b02448e1d5873ac010582bc9898021c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 29 Jan 2010 19:58:56 -0500 Subject: cfg80211: avoid flushing the global workqueue for core reg hints When cfg80211 starts it will send a core regulatory hint. This is sent to the global workqueue but we force processing of it by flushing the global workqueue. The flushing was done since cfg80211 needs last_request to always be populated. Avoid flushing the global workqueue by processing the work required immediately instead of putting it into a linked list and processing it after the flush. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/wireless/reg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5f8071de7950..5dcda28b6f04 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1920,14 +1920,12 @@ static int regulatory_hint_core(const char *alpha2) request->alpha2[1] = alpha2[1]; request->initiator = NL80211_REGDOM_SET_BY_CORE; - queue_regulatory_request(request); - /* * This ensures last_request is populated once modules * come swinging in and calling regulatory hints and * wiphy_apply_custom_regulatory(). */ - flush_scheduled_work(); + reg_process_hint(request); return 0; } -- cgit v1.2.3 From 09d989d179d0c679043556dda77c51b41a2dae7e Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Fri, 29 Jan 2010 19:58:57 -0500 Subject: cfg80211: add regulatory hint disconnect support This adds a new regulatory hint to be used when we know all devices have been disconnected and idle. This can happen when we suspend, for instance. When we disconnect we can no longer assume the same regulatory rules learned from a country IE or beacon hints are applicable so restore regulatory settings to an initial state. Since driver hints are cached on the wiphy that called the hint, those hints are not reproduced onto cfg80211 as the wiphy will respect its own wiphy->regd regardless. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- include/net/regulatory.h | 1 + net/wireless/reg.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++- net/wireless/reg.h | 18 ++++++ net/wireless/sme.c | 40 ++++++++++++ 4 files changed, 213 insertions(+), 3 deletions(-) diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 47995b81c5d7..f873ee37f7e4 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -39,6 +39,7 @@ enum environment_cap { * 00 - World regulatory domain * 99 - built by driver but a specific alpha2 cannot be determined * 98 - result of an intersection between two regulatory domains + * 97 - regulatory domain has not yet been configured * @intersect: indicates whether the wireless core should intersect * the requested regulatory domain with the presently set regulatory * domain. diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5dcda28b6f04..ed89c59bb431 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -134,6 +134,7 @@ static const struct ieee80211_regdomain *cfg80211_world_regdom = &world_regdom; static char *ieee80211_regdom = "00"; +static char user_alpha2[2]; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); @@ -252,6 +253,27 @@ static bool regdom_changes(const char *alpha2) return true; } +/* + * The NL80211_REGDOM_SET_BY_USER regdom alpha2 is cached, this lets + * you know if a valid regulatory hint with NL80211_REGDOM_SET_BY_USER + * has ever been issued. + */ +static bool is_user_regdom_saved(void) +{ + if (user_alpha2[0] == '9' && user_alpha2[1] == '7') + return false; + + /* This would indicate a mistake on the design */ + if (WARN((!is_world_regdom(user_alpha2) && + !is_an_alpha2(user_alpha2)), + "Unexpected user alpha2: %c%c\n", + user_alpha2[0], + user_alpha2[1])) + return false; + + return true; +} + /** * country_ie_integrity_changes - tells us if the country IE has changed * @checksum: checksum of country IE of fields we are interested in @@ -1646,7 +1668,7 @@ static int ignore_request(struct wiphy *wiphy, switch (pending_request->initiator) { case NL80211_REGDOM_SET_BY_CORE: - return -EINVAL; + return 0; case NL80211_REGDOM_SET_BY_COUNTRY_IE: last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); @@ -1785,6 +1807,11 @@ new_request: pending_request = NULL; + if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) { + user_alpha2[0] = last_request->alpha2[0]; + user_alpha2[1] = last_request->alpha2[1]; + } + /* When r == REG_INTERSECT we do need to call CRDA */ if (r < 0) { /* @@ -1904,12 +1931,16 @@ static void queue_regulatory_request(struct regulatory_request *request) schedule_work(®_work); } -/* Core regulatory hint -- happens once during cfg80211_init() */ +/* + * Core regulatory hint -- happens during cfg80211_init() + * and when we restore regulatory settings. + */ static int regulatory_hint_core(const char *alpha2) { struct regulatory_request *request; - BUG_ON(last_request); + kfree(last_request); + last_request = NULL; request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); @@ -2107,6 +2138,123 @@ out: mutex_unlock(®_mutex); } +static void restore_alpha2(char *alpha2, bool reset_user) +{ + /* indicates there is no alpha2 to consider for restoration */ + alpha2[0] = '9'; + alpha2[1] = '7'; + + /* The user setting has precedence over the module parameter */ + if (is_user_regdom_saved()) { + /* Unless we're asked to ignore it and reset it */ + if (reset_user) { + REG_DBG_PRINT("cfg80211: Restoring regulatory settings " + "including user preference\n"); + user_alpha2[0] = '9'; + user_alpha2[1] = '7'; + + /* + * If we're ignoring user settings, we still need to + * check the module parameter to ensure we put things + * back as they were for a full restore. + */ + if (!is_world_regdom(ieee80211_regdom)) { + REG_DBG_PRINT("cfg80211: Keeping preference on " + "module parameter ieee80211_regdom: %c%c\n", + ieee80211_regdom[0], + ieee80211_regdom[1]); + alpha2[0] = ieee80211_regdom[0]; + alpha2[1] = ieee80211_regdom[1]; + } + } else { + REG_DBG_PRINT("cfg80211: Restoring regulatory settings " + "while preserving user preference for: %c%c\n", + user_alpha2[0], + user_alpha2[1]); + alpha2[0] = user_alpha2[0]; + alpha2[1] = user_alpha2[1]; + } + } else if (!is_world_regdom(ieee80211_regdom)) { + REG_DBG_PRINT("cfg80211: Keeping preference on " + "module parameter ieee80211_regdom: %c%c\n", + ieee80211_regdom[0], + ieee80211_regdom[1]); + alpha2[0] = ieee80211_regdom[0]; + alpha2[1] = ieee80211_regdom[1]; + } else + REG_DBG_PRINT("cfg80211: Restoring regulatory settings\n"); +} + +/* + * Restoring regulatory settings involves ingoring any + * possibly stale country IE information and user regulatory + * settings if so desired, this includes any beacon hints + * learned as we could have traveled outside to another country + * after disconnection. To restore regulatory settings we do + * exactly what we did at bootup: + * + * - send a core regulatory hint + * - send a user regulatory hint if applicable + * + * Device drivers that send a regulatory hint for a specific country + * keep their own regulatory domain on wiphy->regd so that does does + * not need to be remembered. + */ +static void restore_regulatory_settings(bool reset_user) +{ + char alpha2[2]; + struct reg_beacon *reg_beacon, *btmp; + + mutex_lock(&cfg80211_mutex); + mutex_lock(®_mutex); + + reset_regdomains(); + restore_alpha2(alpha2, reset_user); + + /* Clear beacon hints */ + spin_lock_bh(®_pending_beacons_lock); + if (!list_empty(®_pending_beacons)) { + list_for_each_entry_safe(reg_beacon, btmp, + ®_pending_beacons, list) { + list_del(®_beacon->list); + kfree(reg_beacon); + } + } + spin_unlock_bh(®_pending_beacons_lock); + + if (!list_empty(®_beacon_list)) { + list_for_each_entry_safe(reg_beacon, btmp, + ®_beacon_list, list) { + list_del(®_beacon->list); + kfree(reg_beacon); + } + } + + /* First restore to the basic regulatory settings */ + cfg80211_regdomain = cfg80211_world_regdom; + + mutex_unlock(®_mutex); + mutex_unlock(&cfg80211_mutex); + + regulatory_hint_core(cfg80211_regdomain->alpha2); + + /* + * This restores the ieee80211_regdom module parameter + * preference or the last user requested regulatory + * settings, user regulatory settings takes precedence. + */ + if (is_an_alpha2(alpha2)) + regulatory_hint_user(user_alpha2); +} + + +void regulatory_hint_disconnect(void) +{ + REG_DBG_PRINT("cfg80211: All devices are disconnected, going to " + "restore regulatory settings\n"); + restore_regulatory_settings(false); +} + static bool freq_is_chan_12_13_14(u16 freq) { if (freq == ieee80211_channel_to_frequency(12) || @@ -2496,6 +2644,9 @@ int regulatory_init(void) cfg80211_regdomain = cfg80211_world_regdom; + user_alpha2[0] = '9'; + user_alpha2[1] = '7'; + /* We always try to get an update for the static regdomain */ err = regulatory_hint_core(cfg80211_regdomain->alpha2); if (err) { diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 3018508226ab..b26224a9f3bc 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h @@ -63,4 +63,22 @@ void regulatory_hint_11d(struct wiphy *wiphy, u8 *country_ie, u8 country_ie_len); +/** + * regulatory_hint_disconnect - informs all devices have been disconneted + * + * Regulotory rules can be enhanced further upon scanning and upon + * connection to an AP. These rules become stale if we disconnect + * and go to another country, whether or not we suspend and resume. + * If we suspend, go to another country and resume we'll automatically + * get disconnected shortly after resuming and things will be reset as well. + * This routine is a helper to restore regulatory settings to how they were + * prior to our first connect attempt. This includes ignoring country IE and + * beacon regulatory hints. The ieee80211_regdom module parameter will always + * be respected but if a user had set the regulatory domain that will take + * precedence. + * + * Must be called from process context. + */ +void regulatory_hint_disconnect(void); + #endif /* __NET_WIRELESS_REG_H */ diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 745c37e7992e..17fde0da1b08 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -34,6 +34,44 @@ struct cfg80211_conn { bool auto_auth, prev_bssid_valid; }; +bool cfg80211_is_all_idle(void) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + bool is_all_idle = true; + + mutex_lock(&cfg80211_mutex); + + /* + * All devices must be idle as otherwise if you are actively + * scanning some new beacon hints could be learned and would + * count as new regulatory hints. + */ + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + cfg80211_lock_rdev(rdev); + list_for_each_entry(wdev, &rdev->netdev_list, list) { + wdev_lock(wdev); + if (wdev->sme_state != CFG80211_SME_IDLE) + is_all_idle = false; + wdev_unlock(wdev); + } + cfg80211_unlock_rdev(rdev); + } + + mutex_unlock(&cfg80211_mutex); + + return is_all_idle; +} + +static void disconnect_work(struct work_struct *work) +{ + if (!cfg80211_is_all_idle()) + return; + + regulatory_hint_disconnect(); +} + +static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); static int cfg80211_conn_scan(struct wireless_dev *wdev) { @@ -658,6 +696,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); wdev->wext.connect.ssid_len = 0; #endif + + schedule_work(&cfg80211_disconnect_work); } void cfg80211_disconnected(struct net_device *dev, u16 reason, -- cgit v1.2.3 From 99b82c419bc685c5ca3d8d815564bac41e2716e2 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 20:18:03 +0100 Subject: b43: N-PHY: split RSSI selection into two per-PHY-revision functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 101 ++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index d738d769b025..558d3c052d95 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1316,66 +1316,69 @@ static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ -static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) +static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) { u16 val; - if (dev->phy.rev >= 3) { - /* TODO */ - } else { - if (type < 3) - val = 0; - else if (type == 6) - val = 1; - else if (type == 3) - val = 2; - else - val = 3; + if (type < 3) + val = 0; + else if (type == 6) + val = 1; + else if (type == 3) + val = 2; + else + val = 3; - val = (val << 12) | (val << 14); - b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); - b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); + val = (val << 12) | (val << 14); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); + b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); + if (type < 3) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, + (type + 1) << 4); + b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, + (type + 1) << 4); + } + + /* TODO use some definitions */ + if (code == 0) { + b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); if (type < 3) { - b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, - (type + 1) << 4); - b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, - (type + 1) << 4); + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFEC7, 0); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xEFDC, 0); + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0); + udelay(20); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); } - - /* TODO use some definitions */ - if (code == 0) { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); - if (type < 3) { - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFEC7, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xEFDC, 0); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFFFE, 0); - udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xFFFE, 0); - } - } else { - b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, - 0x3000); - if (type < 3) { - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFEC7, 0x0180); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xEFDC, (code << 1 | 0x1021)); - b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, - 0xFFFE, 0x0001); - udelay(20); - b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, - 0xFFFE, 0); - } + } else { + b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, + 0x3000); + if (type < 3) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, + 0xFEC7, 0x0180); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xEFDC, (code << 1 | 0x1021)); + b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 0xFFFE, 0x1); + udelay(20); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 0xFFFE, 0); } } } +static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) +{ + /* TODO */ +} + +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ +static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) +{ + if (dev->phy.rev >= 3) + b43_nphy_rev3_rssi_select(dev, code, type); + else + b43_nphy_rev2_rssi_select(dev, code, type); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) { -- cgit v1.2.3 From 6e3b15a9e7c3e4f22e9ade658b9e185311078648 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 20:18:04 +0100 Subject: b43: N-PHY: add RSSI selection for newer PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 84 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 558d3c052d95..0e04a2668ea3 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1367,7 +1367,89 @@ static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) { - /* TODO */ + struct b43_phy_n *nphy = dev->phy.n; + u8 i; + u16 reg, val; + + if (code == 0) { + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF); + b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF); + b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF); + b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF); + b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF); + b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF); + b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); + b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); + } else { + for (i = 0; i < 2; i++) { + if ((code == 1 && i == 1) || (code == 2 && !i)) + continue; + + reg = (i == 0) ? + B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER; + b43_phy_maskset(dev, reg, 0xFDFF, 0x0200); + + if (type < 3) { + reg = (i == 0) ? + B43_NPHY_AFECTL_C1 : + B43_NPHY_AFECTL_C2; + b43_phy_maskset(dev, reg, 0xFCFF, 0); + + reg = (i == 0) ? + B43_NPHY_RFCTL_LUT_TRSW_UP1 : + B43_NPHY_RFCTL_LUT_TRSW_UP2; + b43_phy_maskset(dev, reg, 0xFFC3, 0); + + if (type == 0) + val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8; + else if (type == 1) + val = 16; + else + val = 32; + b43_phy_set(dev, reg, val); + + reg = (i == 0) ? + B43_NPHY_TXF_40CO_B1S0 : + B43_NPHY_TXF_40CO_B32S1; + b43_phy_set(dev, reg, 0x0020); + } else { + if (type == 6) + val = 0x0100; + else if (type == 3) + val = 0x0200; + else + val = 0x0300; + + reg = (i == 0) ? + B43_NPHY_AFECTL_C1 : + B43_NPHY_AFECTL_C2; + + b43_phy_maskset(dev, reg, 0xFCFF, val); + b43_phy_maskset(dev, reg, 0xF3FF, val << 2); + + if (type != 3 && type != 6) { + enum ieee80211_band band = + b43_current_band(dev->wl); + + if ((nphy->ipa2g_on && + band == IEEE80211_BAND_2GHZ) || + (nphy->ipa5g_on && + band == IEEE80211_BAND_5GHZ)) + val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; + else + val = 0x11; + reg = (i == 0) ? 0x2000 : 0x3000; + reg |= B2055_PADDRV; + b43_radio_write16(dev, reg, val); + + reg = (i == 0) ? + B43_NPHY_AFECTL_OVER1 : + B43_NPHY_AFECTL_OVER; + b43_phy_set(dev, reg, 0x0200); + } + } + } + } } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ -- cgit v1.2.3 From 38bb902921dc31c15a707b74ebc6896438bb357e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 20:18:05 +0100 Subject: b43: N-PHY: fix Cal TX IQ LO for newer PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 0e04a2668ea3..1dace55d243a 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2229,7 +2229,17 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, (dev->phy.rev == 5 && nphy->ipa2g_on && b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); if (phy6or5x) { - /* TODO */ + if (dev->phy.is_40mhz) { + b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, + tbl_tx_iqlo_cal_loft_ladder_40); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, + tbl_tx_iqlo_cal_iqimb_ladder_40); + } else { + b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, + tbl_tx_iqlo_cal_loft_ladder_20); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, + tbl_tx_iqlo_cal_iqimb_ladder_20); + } } b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); -- cgit v1.2.3 From 52cb5e978f505ba6436dfe1867da0d2818fdb9b7 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 20:18:06 +0100 Subject: b43: N-PHY: add TX radio setup for newer PHYs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 53 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1dace55d243a..78e0cf6c78ca 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1803,9 +1803,60 @@ static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; u16 *save = nphy->tx_rx_cal_radio_saveregs; + u16 tmp; + u8 offset, i; if (dev->phy.rev >= 3) { - /* TODO */ + for (i = 0; i < 2; i++) { + tmp = (i == 0) ? 0x2000 : 0x3000; + offset = i * 11; + + save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL); + save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL); + save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS); + save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS); + save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS); + save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV); + save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1); + save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2); + save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL); + save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC); + save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A); + b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); + b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); + b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); + b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); + if (nphy->ipa5g_on) { + b43_radio_write16(dev, tmp | B2055_PADDRV, 4); + b43_radio_write16(dev, tmp | B2055_XOCTL1, 1); + } else { + b43_radio_write16(dev, tmp | B2055_PADDRV, 0); + b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F); + } + b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); + } else { + b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06); + b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); + b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); + b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); + b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); + b43_radio_write16(dev, tmp | B2055_XOCTL1, 0); + if (nphy->ipa2g_on) { + b43_radio_write16(dev, tmp | B2055_PADDRV, 6); + b43_radio_write16(dev, tmp | B2055_XOCTL2, + (dev->phy.rev < 5) ? 0x11 : 0x01); + } else { + b43_radio_write16(dev, tmp | B2055_PADDRV, 0); + b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); + } + } + b43_radio_write16(dev, tmp | B2055_XOREGUL, 0); + b43_radio_write16(dev, tmp | B2055_XOMISC, 0); + b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0); + } } else { save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); -- cgit v1.2.3 From 9501fefec6aa9a3319bb61edb99851ba30653f30 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 30 Jan 2010 20:18:07 +0100 Subject: b43: N-PHY: implement setting RF sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 78e0cf6c78ca..6392da25efed 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -64,6 +64,8 @@ enum b43_nphy_rf_sequence { B43_RFSEQ_UPDATE_GAINU, }; +static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, + u8 *events, u8 *delays, u8 length); static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, enum b43_nphy_rf_sequence seq); @@ -827,8 +829,8 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) B43_NPHY_TABLE_DATALO, 3 * j); } - /* TODO: b43_nphy_set_rf_sequence(dev, 5, - rfseq_events, rfseq_delays, 3);*/ + b43_nphy_set_rf_sequence(dev, 5, + rfseq_events, rfseq_delays, 3); b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, (u16)~B43_NPHY_OVER_DGAIN_CCKDGECV, 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); @@ -911,8 +913,8 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) delays1[0] = 0x1; delays1[5] = 0x14; } - /*TODO:b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);*/ - /*TODO:b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);*/ + b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); + b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); b43_nphy_gain_crtl_workarounds(dev); @@ -1131,6 +1133,31 @@ static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, false); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ +static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, + u8 *events, u8 *delays, u8 length) +{ + struct b43_phy_n *nphy = dev->phy.n; + u8 i; + u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F; + u16 offset1 = cmd << 4; + u16 offset2 = offset1 + 0x80; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, true); + + b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events); + b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays); + + for (i = length; i < 16; i++) { + b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end); + b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1); + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, false); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, enum b43_nphy_rf_sequence seq) -- cgit v1.2.3 From 4c82bf8e5689b1dddd9bcec70efc3b70edef1670 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sat, 30 Jan 2010 19:55:09 -0500 Subject: mac80211: reduce stack usage in sta_ht_capa_read() The maximal size of the "ht_capa" file is 430 bytes. In most cases, it's much shorter. Use a 512 byte long buffer. 1024 bytes is too much and causes a warning with CONFIG_FRAME_WARN=1024. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 0d4a759ba72c..84865e7ef13b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -165,7 +165,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, if (_cond) \ p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \ } while (0) - char buf[1024], *p = buf; + char buf[512], *p = buf; int i; struct sta_info *sta = file->private_data; struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; -- cgit v1.2.3 From e0b20f1c67fc4379fce430ff720969f35e123eed Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sat, 30 Jan 2010 19:55:27 -0500 Subject: mac80211: reduce stack usage in sta_agg_status_read() Use a more compact and readable format for "agg_status" to reduce the stack frame to less than 1024 bytes. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/debugfs_sta.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 84865e7ef13b..d92800bb2d2f 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -120,36 +120,38 @@ STA_OPS(last_seq_ctrl); static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { - char buf[30 + STA_TID_NUM * 70], *p = buf; + char buf[64 + STA_TID_NUM * 40], *p = buf; int i; struct sta_info *sta = file->private_data; spin_lock_bh(&sta->lock); - p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n", + p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", sta->ampdu_mlme.dialog_token_allocator + 1); + p += scnprintf(p, sizeof(buf) + buf - p, + "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); for (i = 0; i < STA_TID_NUM; i++) { - p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i); - p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x", + p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); + p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", sta->ampdu_mlme.tid_state_rx[i]); - p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", + p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", sta->ampdu_mlme.tid_state_rx[i] ? sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); - p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", + p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", sta->ampdu_mlme.tid_state_rx[i] ? sta->ampdu_mlme.tid_rx[i]->ssn : 0); - p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x", + p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", sta->ampdu_mlme.tid_state_tx[i]); - p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x", + p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", sta->ampdu_mlme.tid_state_tx[i] ? sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); - p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x", + p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", sta->ampdu_mlme.tid_state_tx[i] ? sta->ampdu_mlme.tid_tx[i]->ssn : 0); - p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d", + p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", sta->ampdu_mlme.tid_state_tx[i] ? skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); - p += scnprintf(p, sizeof(buf)+buf-p, "\n"); + p += scnprintf(p, sizeof(buf) + buf - p, "\n"); } spin_unlock_bh(&sta->lock); -- cgit v1.2.3 From 4754ffd68bc14de8db01451c49bb07adebe1e422 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 31 Jan 2010 21:50:12 +0100 Subject: mac80211: fix sta lookup for received action frames on an AP VLAN When looking for a matching interface, __ieee80211_rx_handle_packet loops over all active interfaces, looking for matching stations. Because AP VLAN interfaces are not processed as part of this loop, it needs to use sta_info_get_bss instead of sta_info_get in order to find a STA that has been moved to a VLAN. This fixes issues with aggregation setup/teardown. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7e0b3e340389..5709307fcb9b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2359,7 +2359,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } - rx.sta = sta_info_get(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.flags |= IEEE80211_RX_RA_MATCH; prepares = prepare_for_handlers(prev, &rx, hdr); @@ -2395,7 +2395,7 @@ next: } if (prev) { - rx.sta = sta_info_get(prev, hdr->addr2); + rx.sta = sta_info_get_bss(prev, hdr->addr2); rx.flags |= IEEE80211_RX_RA_MATCH; prepares = prepare_for_handlers(prev, &rx, hdr); -- cgit v1.2.3 From 17ad353b8d9843731258b5d23556667b764939e9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 31 Jan 2010 21:56:25 +0100 Subject: mac80211: fix monitor mode tx radiotap header handling When an injected frame gets buffered for a powersave STA or filtered and retransmitted, mac80211 attempts to parse the radiotap header again, which doesn't work because it's gone at that point. This patch adds a new flag for checking the availability of a radiotap header, so that it only attempts to parse it once, reusing the tx info on the next call to ieee80211_tx(). This fixes severe issues with rekeying in AP mode. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- include/net/mac80211.h | 3 +++ net/mac80211/tx.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1e9c93024cf2..74ccf30fdf8e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -275,6 +275,8 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted * after TX status because the destination was asleep, it must not * be modified again (no seqno assignment, crypto, etc.) + * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still + * has a radiotap header at skb->data. */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -296,6 +298,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17), IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), + IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), }; /** diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 14c70452c245..e7b1cdc7651b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1108,7 +1108,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->flags |= IEEE80211_TX_FRAGMENTED; /* process and remove the injection radiotap header */ - if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { + if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) { if (!__ieee80211_parse_tx_radiotap(tx, skb)) return TX_DROP; @@ -1117,6 +1117,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, * the radiotap header that was present and pre-filled * 'tx' with tx control information. */ + info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP; } /* @@ -1499,7 +1500,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, int hdrlen; u16 len_rthdr; - info->flags |= IEEE80211_TX_CTL_INJECTED; + info->flags |= IEEE80211_TX_CTL_INJECTED | + IEEE80211_TX_INTFL_HAS_RADIOTAP; len_rthdr = ieee80211_get_radiotap_len(skb->data); hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); -- cgit v1.2.3 From b4d57adb727ec7c34020390eeb0eeb9e0a2959bc Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 31 Jan 2010 23:25:24 +0100 Subject: mac80211: fix sta lookup with AP VLAN interfaces and injected frames When injecting frames, mac80211 currently looks for the first AP interface that matches the source address of the injected frame. This breaks when such a frame is directed at a STA that has been moved to a VLAN. This patch fixes it by using sta_info_get_bss instead of sta_info_get, which also finds stations belonging to a VLAN interface of the same BSS as the AP interface. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/tx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e7b1cdc7651b..85e382aa894e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1133,6 +1133,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, tx->sta = rcu_dereference(sdata->u.vlan.sta); if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) return TX_DROP; + } else if (info->flags & IEEE80211_TX_CTL_INJECTED) { + tx->sta = sta_info_get_bss(sdata, hdr->addr1); } if (!tx->sta) tx->sta = sta_info_get(sdata, hdr->addr1); -- cgit v1.2.3 From 3c384053ce4cb1949f5575c28e30e6ceea8cb39b Mon Sep 17 00:00:00 2001 From: Vasanthakumar Date: Mon, 1 Feb 2010 18:49:07 +0530 Subject: mac80211: Don't call rate control when HW handles it Rate control should not be called to update the tx status when HW does the RC. Signed-off-by: Vasanthakumar Signed-off-by: John W. Linville --- net/mac80211/rate.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 669dddd40521..998cf7a935b6 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -44,6 +44,10 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, struct rate_control_ref *ref = local->rate_ctrl; struct ieee80211_sta *ista = &sta->sta; void *priv_sta = sta->rate_ctrl_priv; + + if (!ref) + return; + ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); } -- cgit v1.2.3 From e389900ed31975f3ce091764bf394b045058dad1 Mon Sep 17 00:00:00 2001 From: Hamish Guthrie Date: Mon, 1 Feb 2010 17:42:38 +0100 Subject: ps3_gelic_wireless: Remove superfluous debug info Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 448c5b6789d3..2663b2fdc0bb 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -1449,8 +1449,7 @@ static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan, void *buf = NULL; size_t len; - pr_debug("%s: <- always=%d essid_len=%z\n", __func__, - always_scan, essid_len); + pr_debug("%s: <- always=%d\n", __func__, always_scan); if (mutex_lock_interruptible(&wl->scan_lock)) return -ERESTARTSYS; -- cgit v1.2.3 From ab5132a26236e308c6d3d832a3e04fca351656d8 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sat, 30 Jan 2010 21:37:24 -0500 Subject: ath9k: fix access to freed data on unload Calling ath_bus_cleanup() after ieee80211_free_hw() resulted in access to common->bus_ops, which is already freed as part of the device data. Remove the cleanup field in struct ath_bus_ops, as it was never used properly. Remove ath_bus_cleanup(). Merge cleanup functions in place of the ath_bus_cleanup() calls. Take care not to use any device data after ieee80211_free_hw(). Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 1 - drivers/net/wireless/ath/ath9k/ahb.c | 12 ++---------- drivers/net/wireless/ath/ath9k/ath9k.h | 5 ----- drivers/net/wireless/ath/ath9k/pci.c | 18 +++++------------- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 9e05648356fe..71fc960814f0 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -74,7 +74,6 @@ struct ath_common; struct ath_bus_ops { void (*read_cachesize)(struct ath_common *common, int *csz); - void (*cleanup)(struct ath_common *common); bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); void (*bt_coex_prep)(struct ath_common *common); }; diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9e62a569e816..ca4994f13151 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -27,12 +27,6 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) *csz = L1_CACHE_BYTES >> 2; } -static void ath_ahb_cleanup(struct ath_common *common) -{ - struct ath_softc *sc = (struct ath_softc *)common->priv; - iounmap(sc->mem); -} - static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) { struct ath_softc *sc = (struct ath_softc *)common->priv; @@ -54,8 +48,6 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) static struct ath_bus_ops ath_ahb_bus_ops = { .read_cachesize = ath_ahb_read_cachesize, - .cleanup = ath_ahb_cleanup, - .eeprom_read = ath_ahb_eeprom_read, }; @@ -164,12 +156,12 @@ static int ath_ahb_remove(struct platform_device *pdev) if (hw) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + void __iomem *mem = sc->mem; ath9k_deinit_device(sc); free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); - ath_bus_cleanup(common); + iounmap(mem); platform_set_drvdata(pdev, NULL); } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3f8a7e773d55..0ea340fd071c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -538,11 +538,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) common->bus_ops->read_cachesize(common, csz); } -static inline void ath_bus_cleanup(struct ath_common *common) -{ - common->bus_ops->cleanup(common); -} - extern struct ieee80211_ops ath9k_ops; extern int modparam_nohwcrypt; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 4ae7b5f12029..f2afcbefc076 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -49,16 +49,6 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ } -static void ath_pci_cleanup(struct ath_common *common) -{ - struct ath_softc *sc = (struct ath_softc *) common->priv; - struct pci_dev *pdev = to_pci_dev(sc->dev); - - pci_iounmap(pdev, sc->mem); - pci_disable_device(pdev); - pci_release_region(pdev, 0); -} - static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) { struct ath_hw *ah = (struct ath_hw *) common->ah; @@ -98,7 +88,6 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) static const struct ath_bus_ops ath_pci_bus_ops = { .read_cachesize = ath_pci_read_cachesize, - .cleanup = ath_pci_cleanup, .eeprom_read = ath_pci_eeprom_read, .bt_coex_prep = ath_pci_bt_coex_prep, }; @@ -245,12 +234,15 @@ static void ath_pci_remove(struct pci_dev *pdev) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + void __iomem *mem = sc->mem; ath9k_deinit_device(sc); free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); - ath_bus_cleanup(common); + + pci_iounmap(pdev, mem); + pci_disable_device(pdev); + pci_release_region(pdev, 0); } #ifdef CONFIG_PM -- cgit v1.2.3 From c30f540b63047437ffa894b5353216410c480d1a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 2 Feb 2010 15:03:24 +0100 Subject: netfilter: xtables: CONFIG_COMPAT redux Ifdef out struct nf_sockopt_ops::compat_set struct nf_sockopt_ops::compat_get struct xt_match::compat_from_user struct xt_match::compat_to_user struct xt_match::compatsize to make structures smaller on COMPAT=n kernels. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter.h | 9 ++++++--- include/linux/netfilter/x_tables.h | 12 ++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 48c54960773c..78f33d223680 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -114,15 +114,17 @@ struct nf_sockopt_ops { int set_optmin; int set_optmax; int (*set)(struct sock *sk, int optval, void __user *user, unsigned int len); +#ifdef CONFIG_COMPAT int (*compat_set)(struct sock *sk, int optval, void __user *user, unsigned int len); - +#endif int get_optmin; int get_optmax; int (*get)(struct sock *sk, int optval, void __user *user, int *len); +#ifdef CONFIG_COMPAT int (*compat_get)(struct sock *sk, int optval, void __user *user, int *len); - +#endif /* Use the module struct to lock set/get code in place */ struct module *owner; }; @@ -222,11 +224,12 @@ int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, unsigned int len); int nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, int *len); - +#ifdef CONFIG_COMPAT int compat_nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, unsigned int len); int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, int *len); +#endif /* Call this before modifying an existing packet: ensures it is modifiable and linear to the point you care about (writable_len). diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 3caf5e151102..026eb78ee83c 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -283,11 +283,11 @@ struct xt_match { /* Called when entry of this type deleted. */ void (*destroy)(const struct xt_mtdtor_param *); - +#ifdef CONFIG_COMPAT /* Called when userspace align differs from kernel space one */ void (*compat_from_user)(void *dst, void *src); int (*compat_to_user)(void __user *dst, void *src); - +#endif /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -296,7 +296,9 @@ struct xt_match { const char *table; unsigned int matchsize; +#ifdef CONFIG_COMPAT unsigned int compatsize; +#endif unsigned int hooks; unsigned short proto; @@ -323,17 +325,19 @@ struct xt_target { /* Called when entry of this type deleted. */ void (*destroy)(const struct xt_tgdtor_param *); - +#ifdef CONFIG_COMPAT /* Called when userspace align differs from kernel space one */ void (*compat_from_user)(void *dst, void *src); int (*compat_to_user)(void __user *dst, void *src); - +#endif /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; const char *table; unsigned int targetsize; +#ifdef CONFIG_COMPAT unsigned int compatsize; +#endif unsigned int hooks; unsigned short proto; -- cgit v1.2.3 From 10a199394b8f9b4c4e0be6e14a61109a7d891b1b Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Tue, 2 Feb 2010 15:33:38 +0100 Subject: netfilter: xt_TCPMSS: SYN packets are allowed to contain data The TCPMSS target is dropping SYN packets where: 1) There is data, or 2) The data offset makes the TCP header larger than the packet. Both of these result in an error level printk. This printk has been removed. This change avoids dropping SYN packets containing data. If there is also no MSS option (as well as data), one will not be added because of possible complications due to the increased packet size. Signed-off-by: Simon Arlott Signed-off-by: Patrick McHardy --- net/netfilter/xt_TCPMSS.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index eda64c1cb1e5..6f21b4377dbb 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -60,17 +60,9 @@ tcpmss_mangle_packet(struct sk_buff *skb, tcplen = skb->len - tcphoff; tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - /* Since it passed flags test in tcp match, we know it is is - not a fragment, and has data >= tcp header length. SYN - packets should not contain data: if they did, then we risk - running over MTU, sending Frag Needed and breaking things - badly. --RR */ - if (tcplen != tcph->doff*4) { - if (net_ratelimit()) - printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n", - skb->len); + /* Header cannot be larger than the packet */ + if (tcplen < tcph->doff*4) return -1; - } if (info->mss == XT_TCPMSS_CLAMP_PMTU) { if (dst_mtu(skb_dst(skb)) <= minlen) { @@ -115,6 +107,12 @@ tcpmss_mangle_packet(struct sk_buff *skb, } } + /* There is data after the header so the option can't be added + without moving it, and doing so may make the SYN packet + itself too large. Accept the packet unmodified instead. */ + if (tcplen > tcph->doff*4) + return 0; + /* * MSS Option not found ?! add it.. */ -- cgit v1.2.3 From 8b64056dacf6ec81986d63dff96fca039fe95f6e Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 2 Feb 2010 07:21:34 -0800 Subject: can: deny filterlist access on non-CAN interfaces In commit 20dd3850bcf860561496827b711fa10fecf6e787 "can: Speed up CAN frame receiption by using ml_priv" the formerly used hlist of receiver lists for each CAN netdevice has been replaced. The hlist content ensured only CAN netdevices to be accessed by the can_rx_(un)register() functions which accidently dropped away together with the hlist receiver implementation. This patch re-introduces the check for CAN netdevices in can_rx_(un)register(). Signed-off-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/af_can.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/can/af_can.c b/net/can/af_can.c index bc18b084ffdb..702be5a2c956 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -415,6 +415,9 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, /* insert new receiver (dev,canid,mask) -> (func,data) */ + if (dev && dev->type != ARPHRD_CAN) + return -ENODEV; + r = kmem_cache_alloc(rcv_cache, GFP_KERNEL); if (!r) return -ENOMEM; @@ -478,6 +481,9 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, struct hlist_node *next; struct dev_rcv_lists *d; + if (dev && dev->type != ARPHRD_CAN) + return; + spin_lock(&can_rcvlists_lock); d = find_dev_rcv_lists(dev); -- cgit v1.2.3 From c85bb41e93184bf5494dde6d8fe5a81b564c84c8 Mon Sep 17 00:00:00 2001 From: Flavio Leitner Date: Tue, 2 Feb 2010 07:32:29 -0800 Subject: igmp: fix ip_mc_sf_allow race [v5] Almost all igmp functions accessing inet->mc_list are protected by rtnl_lock(), but there is one exception which is ip_mc_sf_allow(), so there is a chance of either ip_mc_drop_socket or ip_mc_leave_group remove an entry while ip_mc_sf_allow is running causing a crash. Signed-off-by: Flavio Leitner Signed-off-by: David S. Miller --- include/linux/igmp.h | 2 ++ net/ipv4/igmp.c | 83 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 724c27e5d173..93fc2449af10 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -153,6 +153,7 @@ extern int sysctl_igmp_max_msf; struct ip_sf_socklist { unsigned int sl_max; unsigned int sl_count; + struct rcu_head rcu; __be32 sl_addr[0]; }; @@ -170,6 +171,7 @@ struct ip_mc_socklist { struct ip_mreqn multi; unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */ struct ip_sf_socklist *sflist; + struct rcu_head rcu; }; struct ip_sf_list { diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 8f5468393f01..d28363998743 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1799,7 +1799,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr) iml->next = inet->mc_list; iml->sflist = NULL; iml->sfmode = MCAST_EXCLUDE; - inet->mc_list = iml; + rcu_assign_pointer(inet->mc_list, iml); ip_mc_inc_group(in_dev, addr); err = 0; done: @@ -1807,24 +1807,46 @@ done: return err; } +static void ip_sf_socklist_reclaim(struct rcu_head *rp) +{ + struct ip_sf_socklist *psf; + + psf = container_of(rp, struct ip_sf_socklist, rcu); + /* sk_omem_alloc should have been decreased by the caller*/ + kfree(psf); +} + static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml, struct in_device *in_dev) { + struct ip_sf_socklist *psf = iml->sflist; int err; - if (iml->sflist == NULL) { + if (psf == NULL) { /* any-source empty exclude case */ return ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, iml->sfmode, 0, NULL, 0); } err = ip_mc_del_src(in_dev, &iml->multi.imr_multiaddr.s_addr, - iml->sfmode, iml->sflist->sl_count, - iml->sflist->sl_addr, 0); - sock_kfree_s(sk, iml->sflist, IP_SFLSIZE(iml->sflist->sl_max)); - iml->sflist = NULL; + iml->sfmode, psf->sl_count, psf->sl_addr, 0); + rcu_assign_pointer(iml->sflist, NULL); + /* decrease mem now to avoid the memleak warning */ + atomic_sub(IP_SFLSIZE(psf->sl_max), &sk->sk_omem_alloc); + call_rcu(&psf->rcu, ip_sf_socklist_reclaim); return err; } + +static void ip_mc_socklist_reclaim(struct rcu_head *rp) +{ + struct ip_mc_socklist *iml; + + iml = container_of(rp, struct ip_mc_socklist, rcu); + /* sk_omem_alloc should have been decreased by the caller*/ + kfree(iml); +} + + /* * Ask a socket to leave a group. */ @@ -1854,12 +1876,14 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) (void) ip_mc_leave_src(sk, iml, in_dev); - *imlp = iml->next; + rcu_assign_pointer(*imlp, iml->next); if (in_dev) ip_mc_dec_group(in_dev, group); rtnl_unlock(); - sock_kfree_s(sk, iml, sizeof(*iml)); + /* decrease mem now to avoid the memleak warning */ + atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); + call_rcu(&iml->rcu, ip_mc_socklist_reclaim); return 0; } if (!in_dev) @@ -1974,9 +1998,12 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct if (psl) { for (i=0; isl_count; i++) newpsl->sl_addr[i] = psl->sl_addr[i]; - sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max)); + /* decrease mem now to avoid the memleak warning */ + atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); + call_rcu(&psl->rcu, ip_sf_socklist_reclaim); } - pmc->sflist = psl = newpsl; + rcu_assign_pointer(pmc->sflist, newpsl); + psl = newpsl; } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i=0; isl_count; i++) { @@ -2072,11 +2099,13 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) if (psl) { (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, psl->sl_count, psl->sl_addr, 0); - sock_kfree_s(sk, psl, IP_SFLSIZE(psl->sl_max)); + /* decrease mem now to avoid the memleak warning */ + atomic_sub(IP_SFLSIZE(psl->sl_max), &sk->sk_omem_alloc); + call_rcu(&psl->rcu, ip_sf_socklist_reclaim); } else (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, 0, NULL, 0); - pmc->sflist = newpsl; + rcu_assign_pointer(pmc->sflist, newpsl); pmc->sfmode = msf->imsf_fmode; err = 0; done: @@ -2209,30 +2238,40 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif) struct ip_mc_socklist *pmc; struct ip_sf_socklist *psl; int i; + int ret; + ret = 1; if (!ipv4_is_multicast(loc_addr)) - return 1; + goto out; - for (pmc=inet->mc_list; pmc; pmc=pmc->next) { + rcu_read_lock(); + for (pmc=rcu_dereference(inet->mc_list); pmc; pmc=rcu_dereference(pmc->next)) { if (pmc->multi.imr_multiaddr.s_addr == loc_addr && pmc->multi.imr_ifindex == dif) break; } + ret = inet->mc_all; if (!pmc) - return inet->mc_all; + goto unlock; psl = pmc->sflist; + ret = (pmc->sfmode == MCAST_EXCLUDE); if (!psl) - return pmc->sfmode == MCAST_EXCLUDE; + goto unlock; for (i=0; isl_count; i++) { if (psl->sl_addr[i] == rmt_addr) break; } + ret = 0; if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) - return 0; + goto unlock; if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) - return 0; - return 1; + goto unlock; + ret = 1; +unlock: + rcu_read_unlock(); +out: + return ret; } /* @@ -2251,7 +2290,7 @@ void ip_mc_drop_socket(struct sock *sk) rtnl_lock(); while ((iml = inet->mc_list) != NULL) { struct in_device *in_dev; - inet->mc_list = iml->next; + rcu_assign_pointer(inet->mc_list, iml->next); in_dev = inetdev_by_index(net, iml->multi.imr_ifindex); (void) ip_mc_leave_src(sk, iml, in_dev); @@ -2259,7 +2298,9 @@ void ip_mc_drop_socket(struct sock *sk) ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); in_dev_put(in_dev); } - sock_kfree_s(sk, iml, sizeof(*iml)); + /* decrease mem now to avoid the memleak warning */ + atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); + call_rcu(&iml->rcu, ip_mc_socklist_reclaim); } rtnl_unlock(); } -- cgit v1.2.3 From 2a6ace1b3d4dc65401e71fc01af100692b9f27f8 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Feb 2010 07:47:56 -0800 Subject: net/irda: sh_sir: Add SuperH IrDA driver This is very simple IrDA SIR driver for SuperH. This driver was tested by irdaping/ircp on SH7724 EcoVec24 board Signed-off-by: Kuninori Morimoto Signed-off-by: David S. Miller --- drivers/net/irda/Kconfig | 10 + drivers/net/irda/Makefile | 1 + drivers/net/irda/sh_sir.c | 823 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 834 insertions(+) create mode 100644 drivers/net/irda/sh_sir.c diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index f76384221422..af10e97345ce 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -64,6 +64,16 @@ endchoice comment "Dongle support" +config SH_SIR + tristate "SuperH SIR on UART" + depends on IRDA && SUPERH && \ + (CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7723 || \ + CPU_SUBTYPE_SH7724) + default n + help + Say Y here if your want to enable SIR function on SuperH UART + devices. + config DONGLE bool "Serial dongle support" depends on IRTTY_SIR diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index d82e1e3bd8c8..e030d47e2793 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_AU1000_FIR) += au1k_ir.o # SIR drivers obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o obj-$(CONFIG_BFIN_SIR) += bfin_sir.o +obj-$(CONFIG_SH_SIR) += sh_sir.o # dongle drivers for SIR drivers obj-$(CONFIG_ESI_DONGLE) += esi-sir.o obj-$(CONFIG_TEKRAM_DONGLE) += tekram-sir.o diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c new file mode 100644 index 000000000000..d7c983dc91ad --- /dev/null +++ b/drivers/net/irda/sh_sir.c @@ -0,0 +1,823 @@ +/* + * SuperH IrDA Driver + * + * Copyright (C) 2009 Renesas Solutions Corp. + * Kuninori Morimoto + * + * Based on bfin_sir.c + * Copyright 2006-2009 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define DRIVER_NAME "sh_sir" + +#define RX_PHASE (1 << 0) +#define TX_PHASE (1 << 1) +#define TX_COMP_PHASE (1 << 2) /* tx complete */ +#define NONE_PHASE (1 << 31) + +#define IRIF_RINTCLR 0x0016 /* DMA rx interrupt source clear */ +#define IRIF_TINTCLR 0x0018 /* DMA tx interrupt source clear */ +#define IRIF_SIR0 0x0020 /* IrDA-SIR10 control */ +#define IRIF_SIR1 0x0022 /* IrDA-SIR10 baudrate error correction */ +#define IRIF_SIR2 0x0024 /* IrDA-SIR10 baudrate count */ +#define IRIF_SIR3 0x0026 /* IrDA-SIR10 status */ +#define IRIF_SIR_FRM 0x0028 /* Hardware frame processing set */ +#define IRIF_SIR_EOF 0x002A /* EOF value */ +#define IRIF_SIR_FLG 0x002C /* Flag clear */ +#define IRIF_UART_STS2 0x002E /* UART status 2 */ +#define IRIF_UART0 0x0030 /* UART control */ +#define IRIF_UART1 0x0032 /* UART status */ +#define IRIF_UART2 0x0034 /* UART mode */ +#define IRIF_UART3 0x0036 /* UART transmit data */ +#define IRIF_UART4 0x0038 /* UART receive data */ +#define IRIF_UART5 0x003A /* UART interrupt mask */ +#define IRIF_UART6 0x003C /* UART baud rate error correction */ +#define IRIF_UART7 0x003E /* UART baud rate count set */ +#define IRIF_CRC0 0x0040 /* CRC engine control */ +#define IRIF_CRC1 0x0042 /* CRC engine input data */ +#define IRIF_CRC2 0x0044 /* CRC engine calculation */ +#define IRIF_CRC3 0x0046 /* CRC engine output data 1 */ +#define IRIF_CRC4 0x0048 /* CRC engine output data 2 */ + +/* IRIF_SIR0 */ +#define IRTPW (1 << 1) /* transmit pulse width select */ +#define IRERRC (1 << 0) /* Clear receive pulse width error */ + +/* IRIF_SIR3 */ +#define IRERR (1 << 0) /* received pulse width Error */ + +/* IRIF_SIR_FRM */ +#define EOFD (1 << 9) /* EOF detection flag */ +#define FRER (1 << 8) /* Frame Error bit */ +#define FRP (1 << 0) /* Frame processing set */ + +/* IRIF_UART_STS2 */ +#define IRSME (1 << 6) /* Receive Sum Error flag */ +#define IROVE (1 << 5) /* Receive Overrun Error flag */ +#define IRFRE (1 << 4) /* Receive Framing Error flag */ +#define IRPRE (1 << 3) /* Receive Parity Error flag */ + +/* IRIF_UART0_*/ +#define TBEC (1 << 2) /* Transmit Data Clear */ +#define RIE (1 << 1) /* Receive Enable */ +#define TIE (1 << 0) /* Transmit Enable */ + +/* IRIF_UART1 */ +#define URSME (1 << 6) /* Receive Sum Error Flag */ +#define UROVE (1 << 5) /* Receive Overrun Error Flag */ +#define URFRE (1 << 4) /* Receive Framing Error Flag */ +#define URPRE (1 << 3) /* Receive Parity Error Flag */ +#define RBF (1 << 2) /* Receive Buffer Full Flag */ +#define TSBE (1 << 1) /* Transmit Shift Buffer Empty Flag */ +#define TBE (1 << 0) /* Transmit Buffer Empty flag */ +#define TBCOMP (TSBE | TBE) + +/* IRIF_UART5 */ +#define RSEIM (1 << 6) /* Receive Sum Error Flag IRQ Mask */ +#define RBFIM (1 << 2) /* Receive Buffer Full Flag IRQ Mask */ +#define TSBEIM (1 << 1) /* Transmit Shift Buffer Empty Flag IRQ Mask */ +#define TBEIM (1 << 0) /* Transmit Buffer Empty Flag IRQ Mask */ +#define RX_MASK (RSEIM | RBFIM) + +/* IRIF_CRC0 */ +#define CRC_RST (1 << 15) /* CRC Engine Reset */ +#define CRC_CT_MASK 0x0FFF + +/************************************************************************ + + + structure + + +************************************************************************/ +struct sh_sir_self { + void __iomem *membase; + unsigned int irq; + struct clk *clk; + + struct net_device *ndev; + + struct irlap_cb *irlap; + struct qos_info qos; + + iobuff_t tx_buff; + iobuff_t rx_buff; +}; + +/************************************************************************ + + + common function + + +************************************************************************/ +static void sh_sir_write(struct sh_sir_self *self, u32 offset, u16 data) +{ + iowrite16(data, self->membase + offset); +} + +static u16 sh_sir_read(struct sh_sir_self *self, u32 offset) +{ + return ioread16(self->membase + offset); +} + +static void sh_sir_update_bits(struct sh_sir_self *self, u32 offset, + u16 mask, u16 data) +{ + u16 old, new; + + old = sh_sir_read(self, offset); + new = (old & ~mask) | data; + if (old != new) + sh_sir_write(self, offset, new); +} + +/************************************************************************ + + + CRC function + + +************************************************************************/ +static void sh_sir_crc_reset(struct sh_sir_self *self) +{ + sh_sir_write(self, IRIF_CRC0, CRC_RST); +} + +static void sh_sir_crc_add(struct sh_sir_self *self, u8 data) +{ + sh_sir_write(self, IRIF_CRC1, (u16)data); +} + +static u16 sh_sir_crc_cnt(struct sh_sir_self *self) +{ + return CRC_CT_MASK & sh_sir_read(self, IRIF_CRC0); +} + +static u16 sh_sir_crc_out(struct sh_sir_self *self) +{ + return sh_sir_read(self, IRIF_CRC4); +} + +static int sh_sir_crc_init(struct sh_sir_self *self) +{ + struct device *dev = &self->ndev->dev; + int ret = -EIO; + u16 val; + + sh_sir_crc_reset(self); + + sh_sir_crc_add(self, 0xCC); + sh_sir_crc_add(self, 0xF5); + sh_sir_crc_add(self, 0xF1); + sh_sir_crc_add(self, 0xA7); + + val = sh_sir_crc_cnt(self); + if (4 != val) { + dev_err(dev, "CRC count error %x\n", val); + goto crc_init_out; + } + + val = sh_sir_crc_out(self); + if (0x51DF != val) { + dev_err(dev, "CRC result error%x\n", val); + goto crc_init_out; + } + + ret = 0; + +crc_init_out: + + sh_sir_crc_reset(self); + return ret; +} + +/************************************************************************ + + + baud rate functions + + +************************************************************************/ +#define SCLK_BASE 1843200 /* 1.8432MHz */ + +static u32 sh_sir_find_sclk(struct clk *irda_clk) +{ + struct cpufreq_frequency_table *freq_table = irda_clk->freq_table; + struct clk *pclk = clk_get(NULL, "peripheral_clk"); + u32 limit, min = 0xffffffff, tmp; + int i, index = 0; + + limit = clk_get_rate(pclk); + clk_put(pclk); + + /* IrDA can not set over peripheral_clk */ + for (i = 0; + freq_table[i].frequency != CPUFREQ_TABLE_END; + i++) { + u32 freq = freq_table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + + /* IrDA should not over peripheral_clk */ + if (freq > limit) + continue; + + tmp = freq % SCLK_BASE; + if (tmp < min) { + min = tmp; + index = i; + } + } + + return freq_table[index].frequency; +} + +#define ERR_ROUNDING(a) ((a + 5000) / 10000) +static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate) +{ + struct clk *clk; + struct device *dev = &self->ndev->dev; + u32 rate; + u16 uabca, uabc; + u16 irbca, irbc; + u32 min, rerr, tmp; + int i; + + /* Baud Rate Error Correction x 10000 */ + u32 rate_err_array[] = { + 0000, 0625, 1250, 1875, + 2500, 3125, 3750, 4375, + 5000, 5625, 6250, 6875, + 7500, 8125, 8750, 9375, + }; + + /* + * FIXME + * + * it support 9600 only now + */ + switch (baudrate) { + case 9600: + break; + default: + dev_err(dev, "un-supported baudrate %d\n", baudrate); + return -EIO; + } + + clk = clk_get(NULL, "irda_clk"); + if (!clk) { + dev_err(dev, "can not get irda_clk\n"); + return -EIO; + } + + clk_set_rate(clk, sh_sir_find_sclk(clk)); + rate = clk_get_rate(clk); + clk_put(clk); + + dev_dbg(dev, "selected sclk = %d\n", rate); + + /* + * CALCULATION + * + * 1843200 = system rate / (irbca + (irbc + 1)) + */ + + irbc = rate / SCLK_BASE; + + tmp = rate - (SCLK_BASE * irbc); + tmp *= 10000; + + rerr = tmp / SCLK_BASE; + + min = 0xffffffff; + irbca = 0; + for (i = 0; i < ARRAY_SIZE(rate_err_array); i++) { + tmp = abs(rate_err_array[i] - rerr); + if (min > tmp) { + min = tmp; + irbca = i; + } + } + + tmp = rate / (irbc + ERR_ROUNDING(rate_err_array[irbca])); + if ((SCLK_BASE / 100) < abs(tmp - SCLK_BASE)) + dev_warn(dev, "IrDA freq error margin over %d\n", tmp); + + dev_dbg(dev, "target = %d, result = %d, infrared = %d.%d\n", + SCLK_BASE, tmp, irbc, rate_err_array[irbca]); + + irbca = (irbca & 0xF) << 4; + irbc = (irbc - 1) & 0xF; + + if (!irbc) { + dev_err(dev, "sh_sir can not set 0 in IRIF_SIR2\n"); + return -EIO; + } + + sh_sir_write(self, IRIF_SIR0, IRTPW | IRERRC); + sh_sir_write(self, IRIF_SIR1, irbca); + sh_sir_write(self, IRIF_SIR2, irbc); + + /* + * CALCULATION + * + * BaudRate[bps] = system rate / (uabca + (uabc + 1) x 16) + */ + + uabc = rate / baudrate; + uabc = (uabc / 16) - 1; + uabc = (uabc + 1) * 16; + + tmp = rate - (uabc * baudrate); + tmp *= 10000; + + rerr = tmp / baudrate; + + min = 0xffffffff; + uabca = 0; + for (i = 0; i < ARRAY_SIZE(rate_err_array); i++) { + tmp = abs(rate_err_array[i] - rerr); + if (min > tmp) { + min = tmp; + uabca = i; + } + } + + tmp = rate / (uabc + ERR_ROUNDING(rate_err_array[uabca])); + if ((baudrate / 100) < abs(tmp - baudrate)) + dev_warn(dev, "UART freq error margin over %d\n", tmp); + + dev_dbg(dev, "target = %d, result = %d, uart = %d.%d\n", + baudrate, tmp, + uabc, rate_err_array[uabca]); + + uabca = (uabca & 0xF) << 4; + uabc = (uabc / 16) - 1; + + sh_sir_write(self, IRIF_UART6, uabca); + sh_sir_write(self, IRIF_UART7, uabc); + + return 0; +} + +/************************************************************************ + + + iobuf function + + +************************************************************************/ +static int __sh_sir_init_iobuf(iobuff_t *io, int size) +{ + io->head = kmalloc(size, GFP_KERNEL); + if (!io->head) + return -ENOMEM; + + io->truesize = size; + io->in_frame = FALSE; + io->state = OUTSIDE_FRAME; + io->data = io->head; + + return 0; +} + +static void sh_sir_remove_iobuf(struct sh_sir_self *self) +{ + kfree(self->rx_buff.head); + kfree(self->tx_buff.head); + + self->rx_buff.head = NULL; + self->tx_buff.head = NULL; +} + +static int sh_sir_init_iobuf(struct sh_sir_self *self, int rxsize, int txsize) +{ + int err = -ENOMEM; + + if (self->rx_buff.head || + self->tx_buff.head) { + dev_err(&self->ndev->dev, "iobuff has already existed."); + return err; + } + + err = __sh_sir_init_iobuf(&self->rx_buff, rxsize); + if (err) + goto iobuf_err; + + err = __sh_sir_init_iobuf(&self->tx_buff, txsize); + +iobuf_err: + if (err) + sh_sir_remove_iobuf(self); + + return err; +} + +/************************************************************************ + + + status function + + +************************************************************************/ +static void sh_sir_clear_all_err(struct sh_sir_self *self) +{ + /* Clear error flag for receive pulse width */ + sh_sir_update_bits(self, IRIF_SIR0, IRERRC, IRERRC); + + /* Clear frame / EOF error flag */ + sh_sir_write(self, IRIF_SIR_FLG, 0xffff); + + /* Clear all status error */ + sh_sir_write(self, IRIF_UART_STS2, 0); +} + +static void sh_sir_set_phase(struct sh_sir_self *self, int phase) +{ + u16 uart5 = 0; + u16 uart0 = 0; + + switch (phase) { + case TX_PHASE: + uart5 = TBEIM; + uart0 = TBEC | TIE; + break; + case TX_COMP_PHASE: + uart5 = TSBEIM; + uart0 = TIE; + break; + case RX_PHASE: + uart5 = RX_MASK; + uart0 = RIE; + break; + default: + break; + } + + sh_sir_write(self, IRIF_UART5, uart5); + sh_sir_write(self, IRIF_UART0, uart0); +} + +static int sh_sir_is_which_phase(struct sh_sir_self *self) +{ + u16 val = sh_sir_read(self, IRIF_UART5); + + if (val & TBEIM) + return TX_PHASE; + + if (val & TSBEIM) + return TX_COMP_PHASE; + + if (val & RX_MASK) + return RX_PHASE; + + return NONE_PHASE; +} + +static void sh_sir_tx(struct sh_sir_self *self, int phase) +{ + switch (phase) { + case TX_PHASE: + if (0 >= self->tx_buff.len) { + sh_sir_set_phase(self, TX_COMP_PHASE); + } else { + sh_sir_write(self, IRIF_UART3, self->tx_buff.data[0]); + self->tx_buff.len--; + self->tx_buff.data++; + } + break; + case TX_COMP_PHASE: + sh_sir_set_phase(self, RX_PHASE); + netif_wake_queue(self->ndev); + break; + default: + dev_err(&self->ndev->dev, "should not happen\n"); + break; + } +} + +static int sh_sir_read_data(struct sh_sir_self *self) +{ + u16 val; + int timeout = 1024; + + while (timeout--) { + val = sh_sir_read(self, IRIF_UART1); + + /* data get */ + if (val & RBF) { + if (val & (URSME | UROVE | URFRE | URPRE)) + break; + + return (int)sh_sir_read(self, IRIF_UART4); + } + + udelay(1); + } + + dev_err(&self->ndev->dev, "UART1 %04x : STATUS %04x\n", + val, sh_sir_read(self, IRIF_UART_STS2)); + + /* read data register for clear error */ + sh_sir_read(self, IRIF_UART4); + + return -1; +} + +static void sh_sir_rx(struct sh_sir_self *self) +{ + int timeout = 1024; + int data; + + while (timeout--) { + data = sh_sir_read_data(self); + if (data < 0) + break; + + async_unwrap_char(self->ndev, &self->ndev->stats, + &self->rx_buff, (u8)data); + self->ndev->last_rx = jiffies; + + if (EOFD & sh_sir_read(self, IRIF_SIR_FRM)) + continue; + + break; + } +} + +static irqreturn_t sh_sir_irq(int irq, void *dev_id) +{ + struct sh_sir_self *self = dev_id; + struct device *dev = &self->ndev->dev; + int phase = sh_sir_is_which_phase(self); + + switch (phase) { + case TX_COMP_PHASE: + case TX_PHASE: + sh_sir_tx(self, phase); + break; + case RX_PHASE: + if (sh_sir_read(self, IRIF_SIR3)) + dev_err(dev, "rcv pulse width error occurred\n"); + + sh_sir_rx(self); + sh_sir_clear_all_err(self); + break; + default: + dev_err(dev, "unknown interrupt\n"); + } + + return IRQ_HANDLED; +} + +/************************************************************************ + + + net_device_ops function + + +************************************************************************/ +static int sh_sir_hard_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct sh_sir_self *self = netdev_priv(ndev); + int speed = irda_get_next_speed(skb); + + if ((0 < speed) && + (9600 != speed)) { + dev_err(&ndev->dev, "support 9600 only (%d)\n", speed); + return -EIO; + } + + netif_stop_queue(ndev); + + self->tx_buff.data = self->tx_buff.head; + self->tx_buff.len = 0; + if (skb->len) + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, + self->tx_buff.truesize); + + sh_sir_set_phase(self, TX_PHASE); + dev_kfree_skb(skb); + + return 0; +} + +static int sh_sir_ioctl(struct net_device *ndev, struct ifreq *ifreq, int cmd) +{ + /* + * FIXME + * + * This function is needed for irda framework. + * But nothing to do now + */ + return 0; +} + +static struct net_device_stats *sh_sir_stats(struct net_device *ndev) +{ + struct sh_sir_self *self = netdev_priv(ndev); + + return &self->ndev->stats; +} + +static int sh_sir_open(struct net_device *ndev) +{ + struct sh_sir_self *self = netdev_priv(ndev); + int err; + + clk_enable(self->clk); + err = sh_sir_crc_init(self); + if (err) + goto open_err; + + sh_sir_set_baudrate(self, 9600); + + self->irlap = irlap_open(ndev, &self->qos, DRIVER_NAME); + if (!self->irlap) + goto open_err; + + /* + * Now enable the interrupt then start the queue + */ + sh_sir_update_bits(self, IRIF_SIR_FRM, FRP, FRP); + sh_sir_read(self, IRIF_UART1); /* flag clear */ + sh_sir_read(self, IRIF_UART4); /* flag clear */ + sh_sir_set_phase(self, RX_PHASE); + + netif_start_queue(ndev); + + dev_info(&self->ndev->dev, "opened\n"); + + return 0; + +open_err: + clk_disable(self->clk); + + return err; +} + +static int sh_sir_stop(struct net_device *ndev) +{ + struct sh_sir_self *self = netdev_priv(ndev); + + /* Stop IrLAP */ + if (self->irlap) { + irlap_close(self->irlap); + self->irlap = NULL; + } + + netif_stop_queue(ndev); + + dev_info(&ndev->dev, "stoped\n"); + + return 0; +} + +static const struct net_device_ops sh_sir_ndo = { + .ndo_open = sh_sir_open, + .ndo_stop = sh_sir_stop, + .ndo_start_xmit = sh_sir_hard_xmit, + .ndo_do_ioctl = sh_sir_ioctl, + .ndo_get_stats = sh_sir_stats, +}; + +/************************************************************************ + + + platform_driver function + + +************************************************************************/ +static int __devinit sh_sir_probe(struct platform_device *pdev) +{ + struct net_device *ndev; + struct sh_sir_self *self; + struct resource *res; + char clk_name[8]; + void __iomem *base; + unsigned int irq; + int err = -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (!res || irq < 0) { + dev_err(&pdev->dev, "Not enough platform resources.\n"); + goto exit; + } + + ndev = alloc_irdadev(sizeof(*self)); + if (!ndev) + goto exit; + + base = ioremap_nocache(res->start, resource_size(res)); + if (!base) { + err = -ENXIO; + dev_err(&pdev->dev, "Unable to ioremap.\n"); + goto err_mem_1; + } + + self = netdev_priv(ndev); + err = sh_sir_init_iobuf(self, IRDA_SKB_MAX_MTU, IRDA_SIR_MAX_FRAME); + if (err) + goto err_mem_2; + + snprintf(clk_name, sizeof(clk_name), "irda%d", pdev->id); + self->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(self->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + goto err_mem_3; + } + + irda_init_max_qos_capabilies(&self->qos); + + ndev->netdev_ops = &sh_sir_ndo; + ndev->irq = irq; + + self->membase = base; + self->ndev = ndev; + self->qos.baud_rate.bits &= IR_9600; /* FIXME */ + self->qos.min_turn_time.bits = 1; /* 10 ms or more */ + + irda_qos_bits_to_value(&self->qos); + + err = register_netdev(ndev); + if (err) + goto err_mem_4; + + platform_set_drvdata(pdev, ndev); + + if (request_irq(irq, sh_sir_irq, IRQF_DISABLED, "sh_sir", self)) { + dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n"); + goto err_mem_4; + } + + dev_info(&pdev->dev, "SuperH IrDA probed\n"); + + goto exit; + +err_mem_4: + clk_put(self->clk); +err_mem_3: + sh_sir_remove_iobuf(self); +err_mem_2: + iounmap(self->membase); +err_mem_1: + free_netdev(ndev); +exit: + return err; +} + +static int __devexit sh_sir_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct sh_sir_self *self = netdev_priv(ndev); + + if (!self) + return 0; + + unregister_netdev(ndev); + clk_put(self->clk); + sh_sir_remove_iobuf(self); + iounmap(self->membase); + free_netdev(ndev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver sh_sir_driver = { + .probe = sh_sir_probe, + .remove = __devexit_p(sh_sir_remove), + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init sh_sir_init(void) +{ + return platform_driver_register(&sh_sir_driver); +} + +static void __exit sh_sir_exit(void) +{ + platform_driver_unregister(&sh_sir_driver); +} + +module_init(sh_sir_init); +module_exit(sh_sir_exit); + +MODULE_AUTHOR("Kuninori Morimoto "); +MODULE_DESCRIPTION("SuperH IrDA driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d1c9ae6d1e7b95cedc8e39e8949e795379a0669e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 2 Feb 2010 11:46:50 -0800 Subject: ipv4: ip_fragment: fix unbalanced rcu_read_unlock() Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/ip_fragment.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 9f41bd311754..b59430bc041c 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -234,10 +234,9 @@ static void ip_expire(unsigned long arg) /* Send an ICMP "Fragment Reassembly Timeout" message. */ icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); - } - out_rcu_unlock: - rcu_read_unlock(); + rcu_read_unlock(); + } out: spin_unlock(&qp->q.lock); ipq_put(qp); -- cgit v1.2.3 From d0833a6a2dbc169aba3abcc0904e5aea348bb4d3 Mon Sep 17 00:00:00 2001 From: Andriy Tkachuk Date: Tue, 2 Feb 2010 15:58:53 +0200 Subject: lib80211: Cosmetics - make room for MIC/CRC near the actual calculation Signed-off-by: Andriy V. Tkachuk Signed-off-by: John W. Linville --- net/wireless/lib80211_crypt_ccmp.c | 2 +- net/wireless/lib80211_crypt_tkip.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/net/wireless/lib80211_crypt_ccmp.c b/net/wireless/lib80211_crypt_ccmp.c index 2301dc1edc4c..b7fa31d5fd13 100644 --- a/net/wireless/lib80211_crypt_ccmp.c +++ b/net/wireless/lib80211_crypt_ccmp.c @@ -237,7 +237,6 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) return -1; pos = skb->data + hdr_len + CCMP_HDR_LEN; - mic = skb_put(skb, CCMP_MIC_LEN); hdr = (struct ieee80211_hdr *)skb->data; ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); @@ -257,6 +256,7 @@ static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += len; } + mic = skb_put(skb, CCMP_MIC_LEN); for (i = 0; i < CCMP_MIC_LEN; i++) mic[i] = b[i] ^ s0[i]; diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index c36287399d7e..c6a3cae1f85e 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c @@ -384,9 +384,8 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) if ((lib80211_tkip_hdr(skb, hdr_len, rc4key, 16, priv)) < 0) return -1; - icv = skb_put(skb, 4); - crc = ~crc32_le(~0, pos, len); + icv = skb_put(skb, 4); icv[0] = crc; icv[1] = crc >> 8; icv[2] = crc >> 16; -- cgit v1.2.3 From 299af9d3db0fd3a4994e5e66717ecd276bdd60da Mon Sep 17 00:00:00 2001 From: Andriy Tkachuk Date: Tue, 2 Feb 2010 16:33:53 +0200 Subject: lib80211: Introduce TKIP_HDR_LEN define for code clarity Introduce TKIP_HDR_LEN define for code clarity (in the same way as CCMP_HDR_LEN). Also odd len variable (not used) dropped from lib80211_tkip_hdr(). Signed-off-by: Andriy V. Tkachuk Signed-off-by: John W. Linville --- net/wireless/lib80211_crypt_tkip.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index c6a3cae1f85e..8cbdb32ff316 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c @@ -36,6 +36,8 @@ MODULE_AUTHOR("Jouni Malinen"); MODULE_DESCRIPTION("lib80211 crypt: TKIP"); MODULE_LICENSE("GPL"); +#define TKIP_HDR_LEN 8 + struct lib80211_tkip_data { #define TKIP_KEY_LEN 32 u8 key[TKIP_KEY_LEN]; @@ -314,13 +316,12 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, u8 * rc4key, int keylen, void *priv) { struct lib80211_tkip_data *tkey = priv; - int len; u8 *pos; struct ieee80211_hdr *hdr; hdr = (struct ieee80211_hdr *)skb->data; - if (skb_headroom(skb) < 8 || skb->len < hdr_len) + if (skb_headroom(skb) < TKIP_HDR_LEN || skb->len < hdr_len) return -1; if (rc4key == NULL || keylen < 16) @@ -333,9 +334,8 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, } tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); - len = skb->len - hdr_len; - pos = skb_push(skb, 8); - memmove(pos, pos + 8, hdr_len); + pos = skb_push(skb, TKIP_HDR_LEN); + memmove(pos, pos + TKIP_HDR_LEN, hdr_len); pos += hdr_len; *pos++ = *rc4key; @@ -353,7 +353,7 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, tkey->tx_iv32++; } - return 8; + return TKIP_HDR_LEN; } static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) @@ -433,7 +433,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return -1; } - if (skb->len < hdr_len + 8 + 4) + if (skb->len < hdr_len + TKIP_HDR_LEN + 4) return -1; pos = skb->data + hdr_len; @@ -461,7 +461,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) } iv16 = (pos[0] << 8) | pos[2]; iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); - pos += 8; + pos += TKIP_HDR_LEN; if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) { #ifdef CONFIG_LIB80211_DEBUG @@ -522,8 +522,8 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) tkey->rx_iv16_new = iv16; /* Remove IV and ICV */ - memmove(skb->data + 8, skb->data, hdr_len); - skb_pull(skb, 8); + memmove(skb->data + TKIP_HDR_LEN, skb->data, hdr_len); + skb_pull(skb, TKIP_HDR_LEN); skb_trim(skb, skb->len - 4); return keyidx; -- cgit v1.2.3 From f09c256375c7cf1e112b8ef6306cdd313490d7c0 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 2 Feb 2010 15:34:50 +0100 Subject: airo: fix setting zero length WEP key Patch prevents call set_wep_key() with zero key length. That fix long standing regression since commit c0380693520b1a1e4f756799a0edc379378b462a "airo: clean up WEP key operations". Additionally print call trace when someone will try to use improper parameters, and remove key.len = 0 assignment, because it is in not possible code path. Reported-by: Chris Siebenmann Bisected-by: Chris Siebenmann Tested-by: Chris Siebenmann Cc: Dan Williams Cc: Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4331d675fcc6..2a9f029a3c74 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5254,11 +5254,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, WepKeyRid wkr; int rc; - if (keylen == 0) { - airo_print_err(ai->dev->name, "%s: key length to set was zero", - __func__); - return -1; - } + WARN_ON(keylen == 0); memset(&wkr, 0, sizeof(wkr)); wkr.len = cpu_to_le16(sizeof(wkr)); @@ -6405,11 +6401,7 @@ static int airo_set_encode(struct net_device *dev, if (dwrq->length > MIN_KEY_SIZE) key.len = MAX_KEY_SIZE; else - if (dwrq->length > 0) - key.len = MIN_KEY_SIZE; - else - /* Disable the key */ - key.len = 0; + key.len = MIN_KEY_SIZE; /* Check if the key is not marked as invalid */ if(!(dwrq->flags & IW_ENCODE_NOKEY)) { /* Cleanup */ @@ -6590,12 +6582,22 @@ static int airo_set_encodeext(struct net_device *dev, default: return -EINVAL; } - /* Send the key to the card */ - rc = set_wep_key(local, idx, key.key, key.len, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, "failed to set WEP key" - " at index %d: %d.", idx, rc); - return rc; + if (key.len == 0) { + rc = set_wep_tx_idx(local, idx, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, + "failed to set WEP transmit index to %d: %d.", + idx, rc); + return rc; + } + } else { + rc = set_wep_key(local, idx, key.key, key.len, perm, 1); + if (rc < 0) { + airo_print_err(local->dev->name, + "failed to set WEP key at index %d: %d.", + idx, rc); + return rc; + } } } -- cgit v1.2.3 From 5ffaf8a361b4c9025963959a744f21d8173c7669 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 2 Feb 2010 11:58:33 -0500 Subject: ath9k: add support for 802.11n bonded out AR2427 Some single chip family devices are sold in the market with 802.11n bonded out, these have no hardware capability for 802.11n but ath9k can still support them. These are called AR2427. Cc: stable@kernel.org Reported-by: Rolf Leggewie Tested-by: Bernhard Reiter Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 7 ++++++- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 4 +++- drivers/net/wireless/ath/ath9k/pci.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0b1dd10f1d84..0b1b88ffa497 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -334,7 +334,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.pcie_clock_req = 0; ah->config.pcie_waen = 0; ah->config.analog_shiftreg = 1; - ah->config.ht_enable = 1; ah->config.ofdm_trig_low = 200; ah->config.ofdm_trig_high = 500; ah->config.cck_trig_high = 200; @@ -346,6 +345,11 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.spurchans[i][1] = AR_NO_SPUR; } + if (ah->hw_version.devid != AR2427_DEVID_PCIE) + ah->config.ht_enable = 1; + else + ah->config.ht_enable = 0; + ah->config.rx_intr_mitigation = true; /* @@ -542,6 +546,7 @@ static bool ath9k_hw_devid_supported(u16 devid) case AR5416_DEVID_AR9287_PCI: case AR5416_DEVID_AR9287_PCIE: case AR9271_USB: + case AR2427_DEVID_PCIE: return true; default: break; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ab1f1981d857..dbbf7ca5f97d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -40,6 +40,7 @@ #define AR9280_DEVID_PCI 0x0029 #define AR9280_DEVID_PCIE 0x002a #define AR9285_DEVID_PCIE 0x002b +#define AR2427_DEVID_PCIE 0x002c #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index c3066b553546..4b5e54848683 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -620,11 +620,13 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_SPECTRUM_MGMT; + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) + hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; + if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) hw->flags |= IEEE80211_HW_MFP_CAPABLE; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index f2afcbefc076..f318b3b1abe9 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -25,6 +25,7 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ + { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ { 0 } -- cgit v1.2.3 From 28aecb9d7728dc26bf03ce7925fe622023a83a2a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 29 Jan 2010 04:05:52 +0000 Subject: xfrm: avoid spinlock in get_acqseq() Use atomic_inc_return() in get_acqseq() to avoid taking a spinlock Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/key/af_key.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 4744b1f6372f..e2aacf0ba013 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3019,12 +3019,11 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e static u32 get_acqseq(void) { u32 res; - static u32 acqseq; - static DEFINE_SPINLOCK(acqseq_lock); + static atomic_t acqseq; - spin_lock_bh(&acqseq_lock); - res = (++acqseq ? : ++acqseq); - spin_unlock_bh(&acqseq_lock); + do { + res = atomic_inc_return(&acqseq); + } while (!res); return res; } -- cgit v1.2.3 From f9bfbebf34eab707b065116cdc9699d25ba4252a Mon Sep 17 00:00:00 2001 From: Shirley Ma Date: Fri, 29 Jan 2010 03:19:05 +0000 Subject: virtio: Add ability to detach unused buffers from vrings There's currently no way for a virtio driver to ask for unused buffers, so it has to keep a list itself to reclaim them at shutdown. This is redundant, since virtio_ring stores that information. So add a new hook to do this. Signed-off-by: Shirley Ma Signed-off-by: Amit Shah Signed-off-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/virtio/virtio_ring.c | 25 +++++++++++++++++++++++++ include/linux/virtio.h | 4 ++++ 2 files changed, 29 insertions(+) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index fbd2ecde93e4..71929ee00d69 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -334,6 +334,30 @@ static bool vring_enable_cb(struct virtqueue *_vq) return true; } +static void *vring_detach_unused_buf(struct virtqueue *_vq) +{ + struct vring_virtqueue *vq = to_vvq(_vq); + unsigned int i; + void *buf; + + START_USE(vq); + + for (i = 0; i < vq->vring.num; i++) { + if (!vq->data[i]) + continue; + /* detach_buf clears data, so grab it now. */ + buf = vq->data[i]; + detach_buf(vq, i); + END_USE(vq); + return buf; + } + /* That should have freed everything. */ + BUG_ON(vq->num_free != vq->vring.num); + + END_USE(vq); + return NULL; +} + irqreturn_t vring_interrupt(int irq, void *_vq) { struct vring_virtqueue *vq = to_vvq(_vq); @@ -360,6 +384,7 @@ static struct virtqueue_ops vring_vq_ops = { .kick = vring_kick, .disable_cb = vring_disable_cb, .enable_cb = vring_enable_cb, + .detach_unused_buf = vring_detach_unused_buf, }; struct virtqueue *vring_new_virtqueue(unsigned int num, diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 057a2e010758..f508c651e53d 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -51,6 +51,9 @@ struct virtqueue { * This re-enables callbacks; it returns "false" if there are pending * buffers in the queue, to detect a possible race between the driver * checking for more work, and enabling callbacks. + * @detach_unused_buf: detach first unused buffer + * vq: the struct virtqueue we're talking about. + * Returns NULL or the "data" token handed to add_buf * * Locking rules are straightforward: the driver is responsible for * locking. No two operations may be invoked simultaneously, with the exception @@ -71,6 +74,7 @@ struct virtqueue_ops { void (*disable_cb)(struct virtqueue *vq); bool (*enable_cb)(struct virtqueue *vq); + void *(*detach_unused_buf)(struct virtqueue *vq); }; /** -- cgit v1.2.3 From 9ab86bbcf8be755256f0a5e994e0b38af6b4d399 Mon Sep 17 00:00:00 2001 From: Shirley Ma Date: Fri, 29 Jan 2010 03:20:04 +0000 Subject: virtio_net: Defer skb allocation in receive path Date: Wed, 13 Jan 2010 12:53:38 -0800 virtio_net receives packets from its pre-allocated vring buffers, then it delivers these packets to upper layer protocols as skb buffs. So it's not necessary to pre-allocate skb for each mergable buffer, then frees extra skbs when buffers are merged into a large packet. This patch has deferred skb allocation in receiving packets for both big packets and mergeable buffers to reduce skb pre-allocations and skb frees. It frees unused buffers by calling detach_unused_buf in vring, so recv skb queue is not needed. Signed-off-by: Shirley Ma Signed-off-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 427 +++++++++++++++++++++++++++-------------------- 1 file changed, 248 insertions(+), 179 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 6b92e383c653..9d8984a3741c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -56,8 +56,7 @@ struct virtnet_info /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; - /* Receive & send queues. */ - struct sk_buff_head recv; + /* Send queue. */ struct sk_buff_head send; /* Work struct for refilling if we run low on memory. */ @@ -75,34 +74,44 @@ struct skb_vnet_hdr { unsigned int num_sg; }; +struct padded_vnet_hdr { + struct virtio_net_hdr hdr; + /* + * virtio_net_hdr should be in a separated sg buffer because of a + * QEMU bug, and data sg buffer shares same page with this header sg. + * This padding makes next sg 16 byte aligned after virtio_net_hdr. + */ + char padding[6]; +}; + static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb) { return (struct skb_vnet_hdr *)skb->cb; } -static void give_a_page(struct virtnet_info *vi, struct page *page) -{ - page->private = (unsigned long)vi->pages; - vi->pages = page; -} - -static void trim_pages(struct virtnet_info *vi, struct sk_buff *skb) +/* + * private is used to chain pages for big packets, put the whole + * most recent used list in the beginning for reuse + */ +static void give_pages(struct virtnet_info *vi, struct page *page) { - unsigned int i; + struct page *end; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - give_a_page(vi, skb_shinfo(skb)->frags[i].page); - skb_shinfo(skb)->nr_frags = 0; - skb->data_len = 0; + /* Find end of list, sew whole thing into vi->pages. */ + for (end = page; end->private; end = (struct page *)end->private); + end->private = (unsigned long)vi->pages; + vi->pages = page; } static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask) { struct page *p = vi->pages; - if (p) + if (p) { vi->pages = (struct page *)p->private; - else + /* clear private here, it is used to chain pages */ + p->private = 0; + } else p = alloc_page(gfp_mask); return p; } @@ -118,99 +127,142 @@ static void skb_xmit_done(struct virtqueue *svq) netif_wake_queue(vi->dev); } -static void receive_skb(struct net_device *dev, struct sk_buff *skb, - unsigned len) +static void set_skb_frag(struct sk_buff *skb, struct page *page, + unsigned int offset, unsigned int *len) { - struct virtnet_info *vi = netdev_priv(dev); - struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); - int err; - int i; - - if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { - pr_debug("%s: short packet %i\n", dev->name, len); - dev->stats.rx_length_errors++; - goto drop; - } + int i = skb_shinfo(skb)->nr_frags; + skb_frag_t *f; + + f = &skb_shinfo(skb)->frags[i]; + f->size = min((unsigned)PAGE_SIZE - offset, *len); + f->page_offset = offset; + f->page = page; + + skb->data_len += f->size; + skb->len += f->size; + skb_shinfo(skb)->nr_frags++; + *len -= f->size; +} - if (vi->mergeable_rx_bufs) { - unsigned int copy; - char *p = page_address(skb_shinfo(skb)->frags[0].page); +static struct sk_buff *page_to_skb(struct virtnet_info *vi, + struct page *page, unsigned int len) +{ + struct sk_buff *skb; + struct skb_vnet_hdr *hdr; + unsigned int copy, hdr_len, offset; + char *p; - if (len > PAGE_SIZE) - len = PAGE_SIZE; - len -= sizeof(struct virtio_net_hdr_mrg_rxbuf); + p = page_address(page); - memcpy(&hdr->mhdr, p, sizeof(hdr->mhdr)); - p += sizeof(hdr->mhdr); + /* copy small packet so we can reuse these pages for small data */ + skb = netdev_alloc_skb_ip_align(vi->dev, GOOD_COPY_LEN); + if (unlikely(!skb)) + return NULL; - copy = len; - if (copy > skb_tailroom(skb)) - copy = skb_tailroom(skb); + hdr = skb_vnet_hdr(skb); - memcpy(skb_put(skb, copy), p, copy); + if (vi->mergeable_rx_bufs) { + hdr_len = sizeof hdr->mhdr; + offset = hdr_len; + } else { + hdr_len = sizeof hdr->hdr; + offset = sizeof(struct padded_vnet_hdr); + } - len -= copy; + memcpy(hdr, p, hdr_len); - if (!len) { - give_a_page(vi, skb_shinfo(skb)->frags[0].page); - skb_shinfo(skb)->nr_frags--; - } else { - skb_shinfo(skb)->frags[0].page_offset += - sizeof(hdr->mhdr) + copy; - skb_shinfo(skb)->frags[0].size = len; - skb->data_len += len; - skb->len += len; - } + len -= hdr_len; + p += offset; - while (--hdr->mhdr.num_buffers) { - struct sk_buff *nskb; + copy = len; + if (copy > skb_tailroom(skb)) + copy = skb_tailroom(skb); + memcpy(skb_put(skb, copy), p, copy); - i = skb_shinfo(skb)->nr_frags; - if (i >= MAX_SKB_FRAGS) { - pr_debug("%s: packet too long %d\n", dev->name, - len); - dev->stats.rx_length_errors++; - goto drop; - } + len -= copy; + offset += copy; - nskb = vi->rvq->vq_ops->get_buf(vi->rvq, &len); - if (!nskb) { - pr_debug("%s: rx error: %d buffers missing\n", - dev->name, hdr->mhdr.num_buffers); - dev->stats.rx_length_errors++; - goto drop; - } + while (len) { + set_skb_frag(skb, page, offset, &len); + page = (struct page *)page->private; + offset = 0; + } - __skb_unlink(nskb, &vi->recv); - vi->num--; + if (page) + give_pages(vi, page); - skb_shinfo(skb)->frags[i] = skb_shinfo(nskb)->frags[0]; - skb_shinfo(nskb)->nr_frags = 0; - kfree_skb(nskb); + return skb; +} - if (len > PAGE_SIZE) - len = PAGE_SIZE; +static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb) +{ + struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); + struct page *page; + int num_buf, i, len; + + num_buf = hdr->mhdr.num_buffers; + while (--num_buf) { + i = skb_shinfo(skb)->nr_frags; + if (i >= MAX_SKB_FRAGS) { + pr_debug("%s: packet too long\n", skb->dev->name); + skb->dev->stats.rx_length_errors++; + return -EINVAL; + } - skb_shinfo(skb)->frags[i].size = len; - skb_shinfo(skb)->nr_frags++; - skb->data_len += len; - skb->len += len; + page = vi->rvq->vq_ops->get_buf(vi->rvq, &len); + if (!page) { + pr_debug("%s: rx error: %d buffers missing\n", + skb->dev->name, hdr->mhdr.num_buffers); + skb->dev->stats.rx_length_errors++; + return -EINVAL; } - } else { - len -= sizeof(hdr->hdr); + if (len > PAGE_SIZE) + len = PAGE_SIZE; + + set_skb_frag(skb, page, 0, &len); + + --vi->num; + } + return 0; +} + +static void receive_buf(struct net_device *dev, void *buf, unsigned int len) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct sk_buff *skb; + struct page *page; + struct skb_vnet_hdr *hdr; - if (len <= MAX_PACKET_LEN) - trim_pages(vi, skb); + if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { + pr_debug("%s: short packet %i\n", dev->name, len); + dev->stats.rx_length_errors++; + if (vi->mergeable_rx_bufs || vi->big_packets) + give_pages(vi, buf); + else + dev_kfree_skb(buf); + return; + } - err = pskb_trim(skb, len); - if (err) { - pr_debug("%s: pskb_trim failed %i %d\n", dev->name, - len, err); + if (!vi->mergeable_rx_bufs && !vi->big_packets) { + skb = buf; + len -= sizeof(struct virtio_net_hdr); + skb_trim(skb, len); + } else { + page = buf; + skb = page_to_skb(vi, page, len); + if (unlikely(!skb)) { dev->stats.rx_dropped++; - goto drop; + give_pages(vi, page); + return; } + if (vi->mergeable_rx_bufs) + if (receive_mergeable(vi, skb)) { + dev_kfree_skb(skb); + return; + } } + hdr = skb_vnet_hdr(skb); skb->truesize += skb->data_len; dev->stats.rx_bytes += skb->len; dev->stats.rx_packets++; @@ -267,110 +319,119 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, frame_err: dev->stats.rx_frame_errors++; -drop: dev_kfree_skb(skb); } -static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp) +static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp) { struct sk_buff *skb; - struct scatterlist sg[2+MAX_SKB_FRAGS]; - int num, err, i; - bool oom = false; - - sg_init_table(sg, 2+MAX_SKB_FRAGS); - do { - struct skb_vnet_hdr *hdr; + struct skb_vnet_hdr *hdr; + struct scatterlist sg[2]; + int err; - skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); - if (unlikely(!skb)) { - oom = true; - break; - } + skb = netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN); + if (unlikely(!skb)) + return -ENOMEM; - skb_put(skb, MAX_PACKET_LEN); + skb_put(skb, MAX_PACKET_LEN); - hdr = skb_vnet_hdr(skb); - sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr)); + hdr = skb_vnet_hdr(skb); + sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); - if (vi->big_packets) { - for (i = 0; i < MAX_SKB_FRAGS; i++) { - skb_frag_t *f = &skb_shinfo(skb)->frags[i]; - f->page = get_a_page(vi, gfp); - if (!f->page) - break; + skb_to_sgvec(skb, sg + 1, 0, skb->len); - f->page_offset = 0; - f->size = PAGE_SIZE; + err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 2, skb); + if (err < 0) + dev_kfree_skb(skb); - skb->data_len += PAGE_SIZE; - skb->len += PAGE_SIZE; + return err; +} - skb_shinfo(skb)->nr_frags++; - } +static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp) +{ + struct scatterlist sg[MAX_SKB_FRAGS + 2]; + struct page *first, *list = NULL; + char *p; + int i, err, offset; + + /* page in sg[MAX_SKB_FRAGS + 1] is list tail */ + for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { + first = get_a_page(vi, gfp); + if (!first) { + if (list) + give_pages(vi, list); + return -ENOMEM; } + sg_set_buf(&sg[i], page_address(first), PAGE_SIZE); - num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; - skb_queue_head(&vi->recv, skb); + /* chain new page in list head to match sg */ + first->private = (unsigned long)list; + list = first; + } - err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb); - if (err < 0) { - skb_unlink(skb, &vi->recv); - trim_pages(vi, skb); - kfree_skb(skb); - break; - } - vi->num++; - } while (err >= num); - if (unlikely(vi->num > vi->max)) - vi->max = vi->num; - vi->rvq->vq_ops->kick(vi->rvq); - return !oom; + first = get_a_page(vi, gfp); + if (!first) { + give_pages(vi, list); + return -ENOMEM; + } + p = page_address(first); + + /* sg[0], sg[1] share the same page */ + /* a separated sg[0] for virtio_net_hdr only during to QEMU bug*/ + sg_set_buf(&sg[0], p, sizeof(struct virtio_net_hdr)); + + /* sg[1] for data packet, from offset */ + offset = sizeof(struct padded_vnet_hdr); + sg_set_buf(&sg[1], p + offset, PAGE_SIZE - offset); + + /* chain first in list head */ + first->private = (unsigned long)list; + err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, MAX_SKB_FRAGS + 2, + first); + if (err < 0) + give_pages(vi, first); + + return err; } -/* Returns false if we couldn't fill entirely (OOM). */ -static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) +static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp) { - struct sk_buff *skb; - struct scatterlist sg[1]; + struct page *page; + struct scatterlist sg; int err; - bool oom = false; - - if (!vi->mergeable_rx_bufs) - return try_fill_recv_maxbufs(vi, gfp); - do { - skb_frag_t *f; + page = get_a_page(vi, gfp); + if (!page) + return -ENOMEM; - skb = netdev_alloc_skb_ip_align(vi->dev, GOOD_COPY_LEN); - if (unlikely(!skb)) { - oom = true; - break; - } + sg_init_one(&sg, page_address(page), PAGE_SIZE); - f = &skb_shinfo(skb)->frags[0]; - f->page = get_a_page(vi, gfp); - if (!f->page) { - oom = true; - kfree_skb(skb); - break; - } + err = vi->rvq->vq_ops->add_buf(vi->rvq, &sg, 0, 1, page); + if (err < 0) + give_pages(vi, page); - f->page_offset = 0; - f->size = PAGE_SIZE; + return err; +} - skb_shinfo(skb)->nr_frags++; +/* Returns false if we couldn't fill entirely (OOM). */ +static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) +{ + int err; + bool oom = false; - sg_init_one(sg, page_address(f->page), PAGE_SIZE); - skb_queue_head(&vi->recv, skb); + do { + if (vi->mergeable_rx_bufs) + err = add_recvbuf_mergeable(vi, gfp); + else if (vi->big_packets) + err = add_recvbuf_big(vi, gfp); + else + err = add_recvbuf_small(vi, gfp); - err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb); if (err < 0) { - skb_unlink(skb, &vi->recv); - kfree_skb(skb); + oom = true; break; } - vi->num++; + ++vi->num; } while (err > 0); if (unlikely(vi->num > vi->max)) vi->max = vi->num; @@ -407,15 +468,14 @@ static void refill_work(struct work_struct *work) static int virtnet_poll(struct napi_struct *napi, int budget) { struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi); - struct sk_buff *skb = NULL; + void *buf; unsigned int len, received = 0; again: while (received < budget && - (skb = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) { - __skb_unlink(skb, &vi->recv); - receive_skb(vi->dev, skb, len); - vi->num--; + (buf = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) { + receive_buf(vi->dev, buf, len); + --vi->num; received++; } @@ -495,9 +555,9 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) /* Encode metadata header at front. */ if (vi->mergeable_rx_bufs) - sg_set_buf(sg, &hdr->mhdr, sizeof(hdr->mhdr)); + sg_set_buf(sg, &hdr->mhdr, sizeof hdr->mhdr); else - sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr)); + sg_set_buf(sg, &hdr->hdr, sizeof hdr->hdr); hdr->num_sg = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; return vi->svq->vq_ops->add_buf(vi->svq, sg, hdr->num_sg, 0, skb); @@ -917,8 +977,7 @@ static int virtnet_probe(struct virtio_device *vdev) dev->features |= NETIF_F_HW_VLAN_FILTER; } - /* Initialize our empty receive and send queues. */ - skb_queue_head_init(&vi->recv); + /* Initialize our empty send queue. */ skb_queue_head_init(&vi->send); err = register_netdev(dev); @@ -953,25 +1012,35 @@ free: return err; } +static void free_unused_bufs(struct virtnet_info *vi) +{ + void *buf; + while (1) { + buf = vi->rvq->vq_ops->detach_unused_buf(vi->rvq); + if (!buf) + break; + if (vi->mergeable_rx_bufs || vi->big_packets) + give_pages(vi, buf); + else + dev_kfree_skb(buf); + --vi->num; + } + BUG_ON(vi->num != 0); +} + static void __devexit virtnet_remove(struct virtio_device *vdev) { struct virtnet_info *vi = vdev->priv; - struct sk_buff *skb; /* Stop all the virtqueues. */ vdev->config->reset(vdev); - /* Free our skbs in send and recv queues, if any. */ - while ((skb = __skb_dequeue(&vi->recv)) != NULL) { - kfree_skb(skb); - vi->num--; - } + /* Free our skbs in send queue, if any. */ __skb_queue_purge(&vi->send); - BUG_ON(vi->num != 0); - unregister_netdev(vi->dev); cancel_delayed_work_sync(&vi->refill); + free_unused_bufs(vi); vdev->config->del_vqs(vi->vdev); -- cgit v1.2.3 From 0c2dc318e88100e1abdff07e8a7d60460984a2d2 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 1 Feb 2010 00:19:07 +0000 Subject: sky2: Fix TX_MAP_PAGE misspelling Btw of the dma-debug problem reported by Michael Breuer I spotted a tiny misspelling in TX_MAP_PAGE definition introduced by commit 6b84dacadbdc3. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- drivers/net/sky2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 365d79c7d834..54cb303443e0 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -2156,7 +2156,7 @@ struct tx_ring_info { struct sk_buff *skb; unsigned long flags; #define TX_MAP_SINGLE 0x0001 -#define TX_MAP_PAGE 000002 +#define TX_MAP_PAGE 0x0002 DECLARE_PCI_UNMAP_ADDR(mapaddr); DECLARE_PCI_UNMAP_LEN(maplen); }; -- cgit v1.2.3 From 6a902881cc6993f136906559ca04b6a4c9e260fc Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:24:54 +0000 Subject: qlcnic: use DEFINE_PCI_DEVICE_TABLE Use DEFINE_PCI_DEVICE_TABLE() so we get place PCI ids table into correct section in every case. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 1698b6a68ed1..05275f2153be 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -102,7 +102,7 @@ static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long); #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 -static const struct pci_device_id qlcnic_pci_tbl[] __devinitdata = { +static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), {0,} }; -- cgit v1.2.3 From 02420be6fc5fc63526aca43b5bfc571547a1c926 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:24:55 +0000 Subject: qlcnic: add ethernet identifier in board info Added missing identifier that distinguishes between FCOE/ISCSI/ETHERNET functions. Signed-off-by: Rajesh K Borundia Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index abec46846539..9662a37bfc57 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -1068,7 +1068,7 @@ int qlcnic_reset_context(struct qlcnic_adapter *); * QLOGIC Board information */ -#define QLCNIC_MAX_BOARD_NAME_LEN 64 +#define QLCNIC_MAX_BOARD_NAME_LEN 100 struct qlcnic_brdinfo { unsigned short vendor; unsigned short device; @@ -1078,8 +1078,12 @@ struct qlcnic_brdinfo { }; static const struct qlcnic_brdinfo qlcnic_boards[] = { - {0x1077, 0x8020, 0x1077, 0x203, "8200 Series Single Port 10GbE CNA"}, - {0x1077, 0x8020, 0x1077, 0x207, "8200 Series Dual Port 10GbE CNA"}, + {0x1077, 0x8020, 0x1077, 0x203, + "8200 Series Single Port 10GbE Converged Network Adapter \ + (TCP/IP Networking)"}, + {0x1077, 0x8020, 0x1077, 0x207, + "8200 Series Dual Port 10GbE Converged Network Adapter \ + (TCP/IP Networking)"}, {0x1077, 0x8020, 0x1077, 0x20b, "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, {0x1077, 0x8020, 0x1077, 0x20c, -- cgit v1.2.3 From 1b95a839587f40abab2f9cb3e5254dc821b9829b Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:24:56 +0000 Subject: qlcnic: clear device reset state after fw recovery o After firmware recovery, clear device reset state transition register. Otherwise firmware reload can occur unnecessary. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_main.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 05275f2153be..9a98285ee791 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1866,6 +1866,23 @@ qlcnic_set_drv_state(struct qlcnic_adapter *adapter, int state) qlcnic_api_unlock(adapter); } +static int +qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) +{ + u32 val; + + if (qlcnic_api_lock(adapter)) + return -EBUSY; + + val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); + val &= ~((u32)0x3 << (adapter->portnum * 4)); + QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); + + qlcnic_api_unlock(adapter); + + return 0; +} + static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter) { @@ -2119,7 +2136,10 @@ qlcnic_attach_work(struct work_struct *work) done: adapter->fw_fail_cnt = 0; clear_bit(__QLCNIC_RESETTING, &adapter->state); - qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY); + + if (!qlcnic_clr_drv_state(adapter)) + qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, + FW_POLL_DELAY); } static int -- cgit v1.2.3 From ce6684433fb277406dd861fd8a17133253e7c367 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:24:57 +0000 Subject: qlcnic: protect resoruce cleanup by rtnl lock o context resources can be in used, while resoruce cleanup is in progress, during fw recover. o Null pointer execption can occur in send_cmd_desc, if fw recovery module frees tx ring without rtnl lock. o Same applies to ethtool register dump and FW health registers should be dump in any case. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic_ethtool.c | 6 +++--- drivers/net/qlcnic/qlcnic_main.c | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 65e9620e28f1..37df5f6cea08 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -326,12 +326,12 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | (adapter->pdev)->device; - if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) - return; - for (i = 0; diag_registers[i] != -1; i++) regs_buff[i] = QLCRD32(adapter, diag_registers[i]); + if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) + return; + regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/ regs_buff[i++] = 1; /* No. of tx ring */ diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 9a98285ee791..7259adc32631 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2051,7 +2051,9 @@ qlcnic_detach_work(struct work_struct *work) qlcnic_down(adapter, netdev); + rtnl_lock(); qlcnic_detach(adapter); + rtnl_unlock(); status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); -- cgit v1.2.3 From 897d3596e0dfc4c25963cff00f1159c79eaf38d3 Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Mon, 1 Feb 2010 05:24:58 +0000 Subject: qlcnic: support LED blink for device identification Added support of device identification by blinking LED for specified time. Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 1 + drivers/net/qlcnic/qlcnic_ethtool.c | 26 ++++++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_hw.c | 22 ++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 9662a37bfc57..514e805f3ab3 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -1015,6 +1015,7 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); int qlcnic_get_board_info(struct qlcnic_adapter *adapter); int qlcnic_wol_supported(struct qlcnic_adapter *adapter); +int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); /* Functions from qlcnic_init.c */ int qlcnic_phantom_init(struct qlcnic_adapter *adapter); diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 37df5f6cea08..7212319760ba 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -618,6 +618,7 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, u64 *data) { memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN); + data[0] = qlcnic_reg_test(dev); if (data[0]) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -693,6 +694,30 @@ static int qlcnic_set_tso(struct net_device *dev, u32 data) return 0; } +static int qlcnic_blink_led(struct net_device *dev, u32 val) +{ + struct qlcnic_adapter *adapter = netdev_priv(dev); + int ret; + + ret = qlcnic_config_led(adapter, 1, 0xf); + if (ret) { + dev_err(&adapter->pdev->dev, + "Failed to set LED blink state.\n"); + return ret; + } + + msleep_interruptible(val * 1000); + + ret = qlcnic_config_led(adapter, 0, 0xf); + if (ret) { + dev_err(&adapter->pdev->dev, + "Failed to reset LED blink state.\n"); + return ret; + } + + return 0; +} + static void qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { @@ -867,4 +892,5 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_coalesce = qlcnic_set_intr_coalesce, .get_flags = ethtool_op_get_flags, .set_flags = qlcnic_set_flags, + .phys_id = qlcnic_blink_led, }; diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 91234e7b39e4..8724e561ed72 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1199,3 +1199,25 @@ qlcnic_wol_supported(struct qlcnic_adapter *adapter) return 0; } + +int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) +{ + struct qlcnic_nic_req req; + int rv; + u64 word; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64((u64)rate << 32); + req.words[1] = cpu_to_le64(state); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv) + dev_err(&adapter->pdev->dev, "LED configuration failed.\n"); + + return rv; +} -- cgit v1.2.3 From 7eb9855d68faabe0004ed18c2af1f0974d3c2c63 Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:24:59 +0000 Subject: qlcnic: add interrupt diagnostic test Interrupt test (offline) added in ethtool self test. Register a temporary interrupt handler and then send command to fw to raise an interrupt. Signed-off-by: Sucheta Chakraborty Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 13 ++++- drivers/net/qlcnic/qlcnic_ctx.c | 4 +- drivers/net/qlcnic/qlcnic_ethtool.c | 41 ++++++++++++- drivers/net/qlcnic/qlcnic_main.c | 112 ++++++++++++++++++++++++++++++++---- 4 files changed, 154 insertions(+), 16 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index 514e805f3ab3..a5a67e9b5e10 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -560,6 +560,8 @@ struct qlcnic_recv_context { /* * Context state */ +#define QLCHAL_VERSION 1 + #define QLCNIC_HOST_CTX_STATE_ACTIVE 2 /* @@ -894,6 +896,8 @@ struct qlcnic_mac_req { #define __QLCNIC_RESETTING 2 #define __QLCNIC_START_FW 4 +#define QLCNIC_INTERRUPT_TEST 1 + struct qlcnic_adapter { struct qlcnic_hardware_context ahw; @@ -946,9 +950,10 @@ struct qlcnic_adapter { u32 heartbit; u8 dev_state; + u8 diag_test; + u8 diag_cnt; u8 rsrd1; - u32 rsrd2; - + u16 rsrd2; u8 mac_addr[ETH_ALEN]; @@ -1064,6 +1069,10 @@ int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac); /* Functions from qlcnic_main.c */ int qlcnic_reset_context(struct qlcnic_adapter *); +u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter, + u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd); +void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); +int qlcnic_diag_alloc_res(struct net_device *netdev, int test); /* * QLOGIC Board information diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index 71c16a183458..0a6a39914aec 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c @@ -24,8 +24,6 @@ #include "qlcnic.h" -#define QLCHAL_VERSION 1 - static u32 qlcnic_poll_rsp(struct qlcnic_adapter *adapter) { @@ -45,7 +43,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter) return rsp; } -static u32 +u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter, u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd) { diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 7212319760ba..58c50ed791de 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -65,7 +65,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { "Register_Test_on_offline", - "Link_Test_on_offline" + "Link_Test_on_offline", + "Interrupt_Test_offline" }; #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) @@ -613,12 +614,50 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset) } } +static int qlcnic_irq_test(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int max_sds_rings = adapter->max_sds_rings; + int ret; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EIO; + + ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); + if (ret) + goto clear_it; + + adapter->diag_cnt = 0; + ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func, + QLCHAL_VERSION, adapter->portnum, 0, 0, 0x00000011); + if (ret) + goto done; + + msleep(10); + + ret = !adapter->diag_cnt; + +done: + qlcnic_diag_free_res(netdev, max_sds_rings); + +clear_it: + adapter->max_sds_rings = max_sds_rings; + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return ret; +} + static void qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, u64 *data) { memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN); + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + data[2] = qlcnic_irq_test(dev); + if (data[2]) + eth_test->flags |= ETH_TEST_FL_FAILED; + } + data[0] = qlcnic_reg_test(dev); if (data[0]) eth_test->flags |= ETH_TEST_FL_FAILED; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 7259adc32631..a8b07120d362 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -88,6 +88,7 @@ static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter); static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter); +static irqreturn_t qlcnic_tmp_intr(int irq, void *data); static irqreturn_t qlcnic_intr(int irq, void *data); static irqreturn_t qlcnic_msi_intr(int irq, void *data); static irqreturn_t qlcnic_msix_intr(int irq, void *data); @@ -720,13 +721,20 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) struct net_device *netdev = adapter->netdev; struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; - if (adapter->flags & QLCNIC_MSIX_ENABLED) - handler = qlcnic_msix_intr; - else if (adapter->flags & QLCNIC_MSI_ENABLED) - handler = qlcnic_msi_intr; - else { - flags |= IRQF_SHARED; - handler = qlcnic_intr; + if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + handler = qlcnic_tmp_intr; + if (!QLCNIC_IS_MSI_FAMILY(adapter)) + flags |= IRQF_SHARED; + + } else { + if (adapter->flags & QLCNIC_MSIX_ENABLED) + handler = qlcnic_msix_intr; + else if (adapter->flags & QLCNIC_MSI_ENABLED) + handler = qlcnic_msi_intr; + else { + flags |= IRQF_SHARED; + handler = qlcnic_intr; + } } adapter->irq = netdev->irq; @@ -923,6 +931,60 @@ qlcnic_detach(struct qlcnic_adapter *adapter) adapter->is_up = 0; } +void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_host_sds_ring *sds_ring; + int ring; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &adapter->recv_ctx.sds_rings[ring]; + qlcnic_disable_int(sds_ring); + } + + qlcnic_detach(adapter); + + adapter->diag_test = 0; + adapter->max_sds_rings = max_sds_rings; + + if (qlcnic_attach(adapter)) + return; + + if (netif_running(netdev)) + __qlcnic_up(adapter, netdev); + + netif_device_attach(netdev); +} + +int qlcnic_diag_alloc_res(struct net_device *netdev, int test) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_host_sds_ring *sds_ring; + int ring; + int ret; + + netif_device_detach(netdev); + + if (netif_running(netdev)) + __qlcnic_down(adapter, netdev); + + qlcnic_detach(adapter); + + adapter->max_sds_rings = 1; + adapter->diag_test = test; + + ret = qlcnic_attach(adapter); + if (ret) + return ret; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &adapter->recv_ctx.sds_rings[ring]; + qlcnic_enable_int(sds_ring); + } + + return 0; +} + int qlcnic_reset_context(struct qlcnic_adapter *adapter) { @@ -1689,10 +1751,8 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) return stats; } -static irqreturn_t qlcnic_intr(int irq, void *data) +static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter) { - struct qlcnic_host_sds_ring *sds_ring = data; - struct qlcnic_adapter *adapter = sds_ring->adapter; u32 status; status = readl(adapter->isr_int_vec); @@ -1710,6 +1770,38 @@ static irqreturn_t qlcnic_intr(int irq, void *data) readl(adapter->isr_int_vec); readl(adapter->isr_int_vec); + return IRQ_HANDLED; +} + +static irqreturn_t qlcnic_tmp_intr(int irq, void *data) +{ + struct qlcnic_host_sds_ring *sds_ring = data; + struct qlcnic_adapter *adapter = sds_ring->adapter; + + if (adapter->flags & QLCNIC_MSIX_ENABLED) + goto done; + else if (adapter->flags & QLCNIC_MSI_ENABLED) { + writel(0xffffffff, adapter->tgt_status_reg); + goto done; + } + + if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE) + return IRQ_NONE; + +done: + adapter->diag_cnt++; + qlcnic_enable_int(sds_ring); + return IRQ_HANDLED; +} + +static irqreturn_t qlcnic_intr(int irq, void *data) +{ + struct qlcnic_host_sds_ring *sds_ring = data; + struct qlcnic_adapter *adapter = sds_ring->adapter; + + if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE) + return IRQ_NONE; + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; -- cgit v1.2.3 From cdaff1854f32ac9ddb4733530f617d32188665ed Mon Sep 17 00:00:00 2001 From: Amit Kumar Salecha Date: Mon, 1 Feb 2010 05:25:00 +0000 Subject: qlcnic: add loopback diagnostic test Loopback test (offline) added in ethtool self test. o Set device in loopback mode o Send packets o Process receive packets in qlcnic_process_rcv_ring_diag() o Compare packets o Reset device in normal mode. Signed-off-by: Amit Kumar Salecha Signed-off-by: David S. Miller --- drivers/net/qlcnic/qlcnic.h | 6 +++ drivers/net/qlcnic/qlcnic_ethtool.c | 82 ++++++++++++++++++++++++++++++++++++- drivers/net/qlcnic/qlcnic_hw.c | 52 +++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_init.c | 75 +++++++++++++++++++++++++++++++++ drivers/net/qlcnic/qlcnic_main.c | 20 +++++---- 5 files changed, 225 insertions(+), 10 deletions(-) diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index a5a67e9b5e10..b40a851ec7d1 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -897,6 +897,7 @@ struct qlcnic_mac_req { #define __QLCNIC_START_FW 4 #define QLCNIC_INTERRUPT_TEST 1 +#define QLCNIC_LOOPBACK_TEST 2 struct qlcnic_adapter { struct qlcnic_hardware_context ahw; @@ -1066,6 +1067,8 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, struct qlcnic_host_tx_ring *tx_ring); int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u64 *mac); +void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter); +int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter); /* Functions from qlcnic_main.c */ int qlcnic_reset_context(struct qlcnic_adapter *); @@ -1073,6 +1076,9 @@ u32 qlcnic_issue_cmd(struct qlcnic_adapter *adapter, u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd); void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); int qlcnic_diag_alloc_res(struct net_device *netdev, int test); +int qlcnic_check_loopback_buff(unsigned char *data); +netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); +void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); /* * QLOGIC Board information diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 58c50ed791de..8da6ec8c13b9 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -66,7 +66,8 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { "Register_Test_on_offline", "Link_Test_on_offline", - "Interrupt_Test_offline" + "Interrupt_Test_offline", + "Loopback_Test_offline" }; #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) @@ -614,6 +615,80 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset) } } +#define QLC_ILB_PKT_SIZE 64 + +static void qlcnic_create_loopback_buff(unsigned char *data) +{ + unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00}; + memset(data, 0x4e, QLC_ILB_PKT_SIZE); + memset(data, 0xff, 12); + memcpy(data + 12, random_data, sizeof(random_data)); +} + +int qlcnic_check_loopback_buff(unsigned char *data) +{ + unsigned char buff[QLC_ILB_PKT_SIZE]; + qlcnic_create_loopback_buff(buff); + return memcmp(data, buff, QLC_ILB_PKT_SIZE); +} + +static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter) +{ + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; + struct sk_buff *skb; + int i; + + for (i = 0; i < 16; i++) { + skb = dev_alloc_skb(QLC_ILB_PKT_SIZE); + qlcnic_create_loopback_buff(skb->data); + skb_put(skb, QLC_ILB_PKT_SIZE); + + adapter->diag_cnt = 0; + + qlcnic_xmit_frame(skb, adapter->netdev); + + msleep(5); + + qlcnic_process_rcv_ring_diag(sds_ring); + + dev_kfree_skb_any(skb); + if (!adapter->diag_cnt) + return -1; + } + return 0; +} + +static int qlcnic_loopback_test(struct net_device *netdev) +{ + struct qlcnic_adapter *adapter = netdev_priv(netdev); + int max_sds_rings = adapter->max_sds_rings; + int ret; + + if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) + return -EIO; + + ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST); + if (ret) + goto clear_it; + + ret = qlcnic_set_ilb_mode(adapter); + if (ret) + goto done; + + ret = qlcnic_do_ilb_test(adapter); + + qlcnic_clear_ilb_mode(adapter); + +done: + qlcnic_diag_free_res(netdev, max_sds_rings); + +clear_it: + adapter->max_sds_rings = max_sds_rings; + clear_bit(__QLCNIC_RESETTING, &adapter->state); + return ret; +} + static int qlcnic_irq_test(struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); @@ -656,6 +731,11 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, data[2] = qlcnic_irq_test(dev); if (data[2]) eth_test->flags |= ETH_TEST_FL_FAILED; + + data[3] = qlcnic_loopback_test(dev); + if (data[3]) + eth_test->flags |= ETH_TEST_FL_FAILED; + } data[0] = qlcnic_reg_test(dev); diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 8724e561ed72..dc6cd69d6d93 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -1221,3 +1221,55 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) return rv; } + +static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u32 flag) +{ + struct qlcnic_nic_req req; + int rv; + u64 word; + + memset(&req, 0, sizeof(struct qlcnic_nic_req)); + req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); + + word = QLCNIC_H2C_OPCODE_CONFIG_LOOPBACK | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(flag); + + rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv) + dev_err(&adapter->pdev->dev, + "%sting loopback mode failed.\n", + flag ? "Set" : "Reset"); + return rv; +} + +int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter) +{ + if (qlcnic_set_fw_loopback(adapter, 1)) + return -EIO; + + if (qlcnic_nic_set_promisc(adapter, + VPORT_MISS_MODE_ACCEPT_ALL)) { + qlcnic_set_fw_loopback(adapter, 0); + return -EIO; + } + + msleep(1000); + return 0; +} + +void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter) +{ + int mode = VPORT_MISS_MODE_DROP; + struct net_device *netdev = adapter->netdev; + + qlcnic_set_fw_loopback(adapter, 0); + + if (netdev->flags & IFF_PROMISC) + mode = VPORT_MISS_MODE_ACCEPT_ALL; + else if (netdev->flags & IFF_ALLMULTI) + mode = VPORT_MISS_MODE_ACCEPT_MULTI; + + qlcnic_nic_set_promisc(adapter, mode); +} diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 7ae8bcc1e439..ea00ab4d4feb 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1464,3 +1464,78 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, spin_unlock(&rds_ring->lock); } +static struct qlcnic_rx_buffer * +qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, + struct qlcnic_host_sds_ring *sds_ring, + int ring, u64 sts_data0) +{ + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + struct qlcnic_rx_buffer *buffer; + struct sk_buff *skb; + struct qlcnic_host_rds_ring *rds_ring; + int index, length, cksum, pkt_offset; + + if (unlikely(ring >= adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = qlcnic_get_sts_refhandle(sts_data0); + if (unlikely(index >= rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + + length = qlcnic_get_sts_totallength(sts_data0); + cksum = qlcnic_get_sts_status(sts_data0); + pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0); + + skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); + if (!skb) + return buffer; + + skb_put(skb, rds_ring->skb_size); + + if (pkt_offset) + skb_pull(skb, pkt_offset); + + skb->truesize = skb->len + sizeof(struct sk_buff); + + if (!qlcnic_check_loopback_buff(skb->data)) + adapter->diag_cnt++; + + dev_kfree_skb_any(skb); + + return buffer; +} + +void +qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) +{ + struct qlcnic_adapter *adapter = sds_ring->adapter; + struct status_desc *desc; + struct qlcnic_rx_buffer *rxbuf; + u64 sts_data0; + + int opcode, ring, desc_cnt; + u32 consumer = sds_ring->consumer; + + desc = &sds_ring->desc_head[consumer]; + sts_data0 = le64_to_cpu(desc->status_desc_data[0]); + + if (!(sts_data0 & STATUS_OWNER_HOST)) + return; + + desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); + opcode = qlcnic_get_sts_opcode(sts_data0); + + ring = qlcnic_get_sts_type(sts_data0); + rxbuf = qlcnic_process_rcv_diag(adapter, sds_ring, + ring, sts_data0); + + desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); + consumer = get_next_index(consumer, sds_ring->num_desc); + + sds_ring->consumer = consumer; + writel(consumer, sds_ring->crb_sts_consumer); +} diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index a8b07120d362..665e8e56b6a8 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -65,8 +65,6 @@ static int __devinit qlcnic_probe(struct pci_dev *pdev, static void __devexit qlcnic_remove(struct pci_dev *pdev); static int qlcnic_open(struct net_device *netdev); static int qlcnic_close(struct net_device *netdev); -static netdev_tx_t qlcnic_xmit_frame(struct sk_buff *, - struct net_device *); static void qlcnic_tx_timeout(struct net_device *netdev); static void qlcnic_tx_timeout_task(struct work_struct *work); static void qlcnic_attach_work(struct work_struct *work); @@ -937,9 +935,11 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) struct qlcnic_host_sds_ring *sds_ring; int ring; - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &adapter->recv_ctx.sds_rings[ring]; - qlcnic_disable_int(sds_ring); + if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &adapter->recv_ctx.sds_rings[ring]; + qlcnic_disable_int(sds_ring); + } } qlcnic_detach(adapter); @@ -977,9 +977,11 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) if (ret) return ret; - for (ring = 0; ring < adapter->max_sds_rings; ring++) { - sds_ring = &adapter->recv_ctx.sds_rings[ring]; - qlcnic_enable_int(sds_ring); + if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &adapter->recv_ctx.sds_rings[ring]; + qlcnic_enable_int(sds_ring); + } } return 0; @@ -1549,7 +1551,7 @@ qlcnic_clear_cmddesc(u64 *desc) desc[2] = 0ULL; } -static netdev_tx_t +netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct qlcnic_adapter *adapter = netdev_priv(netdev); -- cgit v1.2.3 From 2eff25c18c3d332d3c4dd98f2ac9b7114e9771b0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 13:24:54 +0100 Subject: netfilter: xt_hashlimit: fix race condition and simplify locking As noticed by Shin Hong , there is a race between htable_find_get() and htable_put(): htable_put(): htable_find_get(): spin_lock_bh(&hashlimit_lock); atomic_dec_and_test(&hinfo->use) atomic_inc(&hinfo->use) spin_unlock_bh(&hashlimit_lock) return hinfo; spin_lock_bh(&hashlimit_lock); hlist_del(&hinfo->node); spin_unlock_bh(&hashlimit_lock); htable_destroy(hinfo); The entire locking concept is overly complicated, tables are only created/referenced and released in process context, so a single mutex works just fine. Remove the hashinfo_spinlock and atomic reference count and use the mutex to protect table lookups/creation and reference count changes. Signed-off-by: Patrick McHardy --- net/netfilter/xt_hashlimit.c | 52 +++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index fb7fcb773a3f..017c95966aa8 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -90,7 +90,7 @@ struct dsthash_ent { struct xt_hashlimit_htable { struct hlist_node node; /* global list of all htables */ - atomic_t use; + int use; u_int8_t family; bool rnd_initialized; @@ -109,8 +109,7 @@ struct xt_hashlimit_htable { struct hlist_head hash[0]; /* hashtable itself */ }; -static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ -static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */ +static DEFINE_MUTEX(hashlimit_mutex); /* protects htables list */ static struct kmem_cache *hashlimit_cachep __read_mostly; static inline bool dst_cmp(const struct dsthash_ent *ent, @@ -244,7 +243,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_ for (i = 0; i < hinfo->cfg.size; i++) INIT_HLIST_HEAD(&hinfo->hash[i]); - atomic_set(&hinfo->use, 1); + hinfo->use = 1; hinfo->count = 0; hinfo->family = family; hinfo->rnd_initialized = false; @@ -263,9 +262,9 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_ hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); - spin_lock_bh(&hashlimit_lock); + mutex_lock(&hashlimit_mutex); hlist_add_head(&hinfo->node, &hashlimit_net->htables); - spin_unlock_bh(&hashlimit_lock); + mutex_unlock(&hashlimit_mutex); return 0; } @@ -308,7 +307,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, for (i = 0; i < hinfo->cfg.size; i++) INIT_HLIST_HEAD(&hinfo->hash[i]); - atomic_set(&hinfo->use, 1); + hinfo->use = 1; hinfo->count = 0; hinfo->family = family; hinfo->rnd_initialized = false; @@ -328,9 +327,9 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); - spin_lock_bh(&hashlimit_lock); + mutex_lock(&hashlimit_mutex); hlist_add_head(&hinfo->node, &hashlimit_net->htables); - spin_unlock_bh(&hashlimit_lock); + mutex_unlock(&hashlimit_mutex); return 0; } @@ -402,27 +401,24 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net, struct xt_hashlimit_htable *hinfo; struct hlist_node *pos; - spin_lock_bh(&hashlimit_lock); hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node) { if (!strcmp(name, hinfo->pde->name) && hinfo->family == family) { - atomic_inc(&hinfo->use); - spin_unlock_bh(&hashlimit_lock); + hinfo->use++; return hinfo; } } - spin_unlock_bh(&hashlimit_lock); return NULL; } static void htable_put(struct xt_hashlimit_htable *hinfo) { - if (atomic_dec_and_test(&hinfo->use)) { - spin_lock_bh(&hashlimit_lock); + mutex_lock(&hashlimit_mutex); + if (--hinfo->use == 0) { hlist_del(&hinfo->node); - spin_unlock_bh(&hashlimit_lock); htable_destroy(hinfo); } + mutex_unlock(&hashlimit_mutex); } /* The algorithm used is the Simple Token Bucket Filter (TBF) @@ -710,19 +706,13 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) if (r->name[sizeof(r->name) - 1] != '\0') return false; - /* This is the best we've got: We cannot release and re-grab lock, - * since checkentry() is called before x_tables.c grabs xt_mutex. - * We also cannot grab the hashtable spinlock, since htable_create will - * call vmalloc, and that can sleep. And we cannot just re-search - * the list of htable's in htable_create(), since then we would - * create duplicate proc files. -HW */ - mutex_lock(&hlimit_mutex); + mutex_lock(&hashlimit_mutex); r->hinfo = htable_find_get(net, r->name, par->match->family); if (!r->hinfo && htable_create_v0(net, r, par->match->family) != 0) { - mutex_unlock(&hlimit_mutex); + mutex_unlock(&hashlimit_mutex); return false; } - mutex_unlock(&hlimit_mutex); + mutex_unlock(&hashlimit_mutex); return true; } @@ -752,19 +742,13 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par) return false; } - /* This is the best we've got: We cannot release and re-grab lock, - * since checkentry() is called before x_tables.c grabs xt_mutex. - * We also cannot grab the hashtable spinlock, since htable_create will - * call vmalloc, and that can sleep. And we cannot just re-search - * the list of htable's in htable_create(), since then we would - * create duplicate proc files. -HW */ - mutex_lock(&hlimit_mutex); + mutex_lock(&hashlimit_mutex); info->hinfo = htable_find_get(net, info->name, par->match->family); if (!info->hinfo && htable_create(net, info, par->match->family) != 0) { - mutex_unlock(&hlimit_mutex); + mutex_unlock(&hashlimit_mutex); return false; } - mutex_unlock(&hlimit_mutex); + mutex_unlock(&hashlimit_mutex); return true; } -- cgit v1.2.3 From 794e68716bab578ae8f8912dc934496d7c7abc90 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 13:41:29 +0100 Subject: netfilter: ctnetlink: only assign helpers for matching protocols Make sure not to assign a helper for a different network or transport layer protocol to a connection. Additionally change expectation deletion by helper to compare the name directly - there might be multiple helper registrations using the same name, currently one of them is chosen in an unpredictable manner and only those expectations are removed. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_helper.h | 2 +- net/netfilter/nf_conntrack_helper.c | 8 +++++--- net/netfilter/nf_conntrack_netlink.c | 23 +++++++++++------------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index d015de92e03f..86be7c4816d6 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -40,7 +40,7 @@ struct nf_conntrack_helper { }; extern struct nf_conntrack_helper * -__nf_conntrack_helper_find_byname(const char *name); +__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 65c2a7bc3afc..c0e461f466ae 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -65,7 +65,7 @@ __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) } struct nf_conntrack_helper * -__nf_conntrack_helper_find_byname(const char *name) +__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum) { struct nf_conntrack_helper *h; struct hlist_node *n; @@ -73,13 +73,15 @@ __nf_conntrack_helper_find_byname(const char *name) for (i = 0; i < nf_ct_helper_hsize; i++) { hlist_for_each_entry_rcu(h, n, &nf_ct_helper_hash[i], hnode) { - if (!strcmp(h->name, name)) + if (!strcmp(h->name, name) && + h->tuple.src.l3num == l3num && + h->tuple.dst.protonum == protonum) return h; } } return NULL; } -EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); +EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find); struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) { diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 79478dfba27e..16f86d61e5d1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1001,7 +1001,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) return 0; } - helper = __nf_conntrack_helper_find_byname(helpname); + helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), + nf_ct_protonum(ct)); if (helper == NULL) { #ifdef CONFIG_MODULES spin_unlock_bh(&nf_conntrack_lock); @@ -1012,7 +1013,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) } spin_lock_bh(&nf_conntrack_lock); - helper = __nf_conntrack_helper_find_byname(helpname); + helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), + nf_ct_protonum(ct)); if (helper) return -EAGAIN; #endif @@ -1211,7 +1213,8 @@ ctnetlink_create_conntrack(struct net *net, if (err < 0) goto err2; - helper = __nf_conntrack_helper_find_byname(helpname); + helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), + nf_ct_protonum(ct)); if (helper == NULL) { rcu_read_unlock(); #ifdef CONFIG_MODULES @@ -1221,7 +1224,9 @@ ctnetlink_create_conntrack(struct net *net, } rcu_read_lock(); - helper = __nf_conntrack_helper_find_byname(helpname); + helper = __nf_conntrack_helper_find(helpname, + nf_ct_l3num(ct), + nf_ct_protonum(ct)); if (helper) { err = -EAGAIN; goto err2; @@ -1714,7 +1719,6 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, struct net *net = sock_net(ctnl); struct nf_conntrack_expect *exp; struct nf_conntrack_tuple tuple; - struct nf_conntrack_helper *h; struct nfgenmsg *nfmsg = nlmsg_data(nlh); struct hlist_node *n, *next; u_int8_t u3 = nfmsg->nfgen_family; @@ -1751,18 +1755,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, /* delete all expectations for this helper */ spin_lock_bh(&nf_conntrack_lock); - h = __nf_conntrack_helper_find_byname(name); - if (!h) { - spin_unlock_bh(&nf_conntrack_lock); - return -EOPNOTSUPP; - } for (i = 0; i < nf_ct_expect_hsize; i++) { hlist_for_each_entry_safe(exp, n, next, &net->ct.expect_hash[i], hnode) { m_help = nfct_help(exp->master); - if (m_help->helper == h - && del_timer(&exp->timeout)) { + if (!strcmp(m_help->helper->name, name) && + del_timer(&exp->timeout)) { nf_ct_unlink_expect(exp); nf_ct_expect_put(exp); } -- cgit v1.2.3 From add67461240c1dadc7c8d97e66f8f92b556ca523 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 13:45:12 +0100 Subject: netfilter: add struct net * to target parameters Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 2 ++ net/bridge/netfilter/ebtables.c | 10 ++++++---- net/ipv4/netfilter/ip_tables.c | 8 +++++--- net/ipv6/netfilter/ip6_tables.c | 8 +++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 026eb78ee83c..365fabe1b16e 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -249,6 +249,7 @@ struct xt_target_param { * Other fields see above. */ struct xt_tgchk_param { + struct net *net; const char *table; const void *entryinfo; const struct xt_target *target; @@ -259,6 +260,7 @@ struct xt_tgchk_param { /* Target destructor parameters */ struct xt_tgdtor_param { + struct net *net; const struct xt_target *target; void *targinfo; u_int8_t family; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 1aa0e4c1f52d..12beb580aa21 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -579,13 +579,14 @@ ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i) } static inline int -ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) +ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i) { struct xt_tgdtor_param par; if (i && (*i)-- == 0) return 1; + par.net = net; par.target = w->u.watcher; par.targinfo = w->data; par.family = NFPROTO_BRIDGE; @@ -606,10 +607,11 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt) /* we're done */ if (cnt && (*cnt)-- == 0) return 1; - EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL); + EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL); EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL); t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); + par.net = net; par.target = t->u.target; par.targinfo = t->data; par.family = NFPROTO_BRIDGE; @@ -674,7 +676,7 @@ ebt_check_entry(struct ebt_entry *e, } i = 0; - mtpar.net = net; + mtpar.net = tgpar.net = net; mtpar.table = tgpar.table = name; mtpar.entryinfo = tgpar.entryinfo = e; mtpar.hook_mask = tgpar.hook_mask = hookmask; @@ -730,7 +732,7 @@ ebt_check_entry(struct ebt_entry *e, (*cnt)++; return 0; cleanup_watchers: - EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j); + EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j); cleanup_matches: EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i); return ret; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cfaba0e2e6fc..7fde8f6950d8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -638,10 +638,11 @@ err: return ret; } -static int check_target(struct ipt_entry *e, const char *name) +static int check_target(struct ipt_entry *e, struct net *net, const char *name) { struct ipt_entry_target *t = ipt_get_target(e); struct xt_tgchk_param par = { + .net = net, .table = name, .entryinfo = e, .target = t->u.kernel.target, @@ -697,7 +698,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, } t->u.kernel.target = target; - ret = check_target(e, name); + ret = check_target(e, net, name); if (ret) goto err; @@ -788,6 +789,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i) IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ipt_get_target(e); + par.net = net; par.target = t->u.kernel.target; par.targinfo = t->data; par.family = NFPROTO_IPV4; @@ -1675,7 +1677,7 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, if (ret) goto cleanup_matches; - ret = check_target(e, name); + ret = check_target(e, net, name); if (ret) goto cleanup_matches; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9f1d45f2ba8f..0376ed6d5594 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -669,10 +669,11 @@ err: return ret; } -static int check_target(struct ip6t_entry *e, const char *name) +static int check_target(struct ip6t_entry *e, struct net *net, const char *name) { struct ip6t_entry_target *t = ip6t_get_target(e); struct xt_tgchk_param par = { + .net = net, .table = name, .entryinfo = e, .target = t->u.kernel.target, @@ -729,7 +730,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, } t->u.kernel.target = target; - ret = check_target(e, name); + ret = check_target(e, net, name); if (ret) goto err; @@ -820,6 +821,7 @@ cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ip6t_get_target(e); + par.net = net; par.target = t->u.kernel.target; par.targinfo = t->data; par.family = NFPROTO_IPV6; @@ -1710,7 +1712,7 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, if (ret) goto cleanup_matches; - ret = check_target(e, name); + ret = check_target(e, net, name); if (ret) goto cleanup_matches; -- cgit v1.2.3 From 858b31330054a9ad259feceea0ad1ce5385c47f0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 13:48:53 +0100 Subject: netfilter: nf_conntrack: split up IPCT_STATUS event Split up the IPCT_STATUS event into an IPCT_REPLY event, which is generated when the IPS_SEEN_REPLY bit is set, and an IPCT_ASSURED event, which is generated when the IPS_ASSURED bit is set. In combination with a following patch to support selective event delivery, this can be used for "sparse" conntrack replication: start replicating the conntrack entry after it reached the ASSURED state and that way it's SYN-flood resistant. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_ecache.h | 21 +++++++++++---------- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 6 ++++-- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 2 +- net/netfilter/nf_conntrack_proto_udplite.c | 2 +- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 475facc3051a..5e05fb883ab1 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -14,19 +14,20 @@ /* Connection tracking event types */ enum ip_conntrack_events { - IPCT_NEW = 0, /* new conntrack */ - IPCT_RELATED = 1, /* related conntrack */ - IPCT_DESTROY = 2, /* destroyed conntrack */ - IPCT_STATUS = 3, /* status has changed */ - IPCT_PROTOINFO = 4, /* protocol information has changed */ - IPCT_HELPER = 5, /* new helper has been set */ - IPCT_MARK = 6, /* new mark has been set */ - IPCT_NATSEQADJ = 7, /* NAT is doing sequence adjustment */ - IPCT_SECMARK = 8, /* new security mark has been set */ + IPCT_NEW, /* new conntrack */ + IPCT_RELATED, /* related conntrack */ + IPCT_DESTROY, /* destroyed conntrack */ + IPCT_REPLY, /* connection has seen two-way traffic */ + IPCT_ASSURED, /* connection status has changed to assured */ + IPCT_PROTOINFO, /* protocol information has changed */ + IPCT_HELPER, /* new helper has been set */ + IPCT_MARK, /* new mark has been set */ + IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ + IPCT_SECMARK, /* new security mark has been set */ }; enum ip_conntrack_expect_events { - IPEXP_NEW = 0, /* new expectation */ + IPEXP_NEW, /* new expectation */ }; struct nf_conntrack_ecache { diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0e98c3282d42..091ff770eb7b 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -825,7 +825,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, } if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_REPLY, ct); return ret; } diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 16f86d61e5d1..ff594eb138c1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1371,7 +1371,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, else events = IPCT_NEW; - nf_conntrack_eventmask_report((1 << IPCT_STATUS) | + nf_conntrack_eventmask_report((1 << IPCT_REPLY) | + (1 << IPCT_ASSURED) | (1 << IPCT_HELPER) | (1 << IPCT_PROTOINFO) | (1 << IPCT_NATSEQADJ) | @@ -1396,7 +1397,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err == 0) { nf_conntrack_get(&ct->ct_general); spin_unlock_bh(&nf_conntrack_lock); - nf_conntrack_eventmask_report((1 << IPCT_STATUS) | + nf_conntrack_eventmask_report((1 << IPCT_REPLY) | + (1 << IPCT_ASSURED) | (1 << IPCT_HELPER) | (1 << IPCT_PROTOINFO) | (1 << IPCT_NATSEQADJ) | diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index c99cfba64ddc..d899b1a69940 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -241,7 +241,7 @@ static int gre_packet(struct nf_conn *ct, ct->proto.gre.stream_timeout); /* Also, more likely to be important, and not a probe. */ set_bit(IPS_ASSURED_BIT, &ct->status); - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_ASSURED, ct); } else nf_ct_refresh_acct(ct, ctinfo, skb, ct->proto.gre.timeout); diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index f9d930f80276..b68ff15ed979 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -377,7 +377,7 @@ static int sctp_packet(struct nf_conn *ct, new_state == SCTP_CONNTRACK_ESTABLISHED) { pr_debug("Setting assured bit\n"); set_bit(IPS_ASSURED_BIT, &ct->status); - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_ASSURED, ct); } return NF_ACCEPT; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 3c96437b45ad..ad118053971a 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1045,7 +1045,7 @@ static int tcp_packet(struct nf_conn *ct, after SYN_RECV or a valid answer for a picked up connection. */ set_bit(IPS_ASSURED_BIT, &ct->status); - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_ASSURED, ct); } nf_ct_refresh_acct(ct, ctinfo, skb, timeout); diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 5c5518bedb4b..8d38f9a4bed8 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -77,7 +77,7 @@ static int udp_packet(struct nf_conn *ct, nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream); /* Also, more likely to be important, and not a probe */ if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_ASSURED, ct); } else nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout); diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 458655bb2106..0b1bc9ba6678 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -75,7 +75,7 @@ static int udplite_packet(struct nf_conn *ct, nf_ct_udplite_timeout_stream); /* Also, more likely to be important, and not a probe */ if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_STATUS, ct); + nf_conntrack_event_cache(IPCT_ASSURED, ct); } else nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout); -- cgit v1.2.3 From 0cebe4b4163b6373c9d24c1a192939777bc27e55 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 13:51:51 +0100 Subject: netfilter: ctnetlink: support selective event delivery Add two masks for conntrack end expectation events to struct nf_conntrack_ecache and use them to filter events. Their default value is "all events" when the event sysctl is on and "no events" when it is off. A following patch will add specific initializations. Expectation events depend on the ecache struct of their master conntrack. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_common.h | 18 ++++++++ include/net/netfilter/nf_conntrack_ecache.h | 59 +++++++++++++-------------- net/netfilter/nf_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_netlink.c | 2 +- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index a374787ed9b0..ebfed90733f7 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -74,6 +74,24 @@ enum ip_conntrack_status { IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), }; +/* Connection tracking event types */ +enum ip_conntrack_events { + IPCT_NEW, /* new conntrack */ + IPCT_RELATED, /* related conntrack */ + IPCT_DESTROY, /* destroyed conntrack */ + IPCT_REPLY, /* connection has seen two-way traffic */ + IPCT_ASSURED, /* connection status has changed to assured */ + IPCT_PROTOINFO, /* protocol information has changed */ + IPCT_HELPER, /* new helper has been set */ + IPCT_MARK, /* new mark has been set */ + IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ + IPCT_SECMARK, /* new security mark has been set */ +}; + +enum ip_conntrack_expect_events { + IPEXP_NEW, /* new expectation */ +}; + #ifdef __KERNEL__ struct ip_conntrack_stat { unsigned int searched; diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index 5e05fb883ab1..96ba5f7dcab6 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -12,28 +12,12 @@ #include #include -/* Connection tracking event types */ -enum ip_conntrack_events { - IPCT_NEW, /* new conntrack */ - IPCT_RELATED, /* related conntrack */ - IPCT_DESTROY, /* destroyed conntrack */ - IPCT_REPLY, /* connection has seen two-way traffic */ - IPCT_ASSURED, /* connection status has changed to assured */ - IPCT_PROTOINFO, /* protocol information has changed */ - IPCT_HELPER, /* new helper has been set */ - IPCT_MARK, /* new mark has been set */ - IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ - IPCT_SECMARK, /* new security mark has been set */ -}; - -enum ip_conntrack_expect_events { - IPEXP_NEW, /* new expectation */ -}; - struct nf_conntrack_ecache { - unsigned long cache; /* bitops want long */ - unsigned long missed; /* missed events */ - u32 pid; /* netlink pid of destroyer */ + unsigned long cache; /* bitops want long */ + unsigned long missed; /* missed events */ + u16 ctmask; /* bitmask of ct events to be delivered */ + u16 expmask; /* bitmask of expect events to be delivered */ + u32 pid; /* netlink pid of destroyer */ }; static inline struct nf_conntrack_ecache * @@ -43,14 +27,24 @@ nf_ct_ecache_find(const struct nf_conn *ct) } static inline struct nf_conntrack_ecache * -nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) +nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp) { struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *e; - if (!net->ct.sysctl_events) + if (!ctmask && !expmask && net->ct.sysctl_events) { + ctmask = ~0; + expmask = ~0; + } + if (!ctmask && !expmask) return NULL; - return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); + e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); + if (e) { + e->ctmask = ctmask; + e->expmask = expmask; + } + return e; }; #ifdef CONFIG_NF_CONNTRACK_EVENTS @@ -83,6 +77,9 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) if (e == NULL) return; + if (!(e->ctmask & (1 << event))) + return; + set_bit(event, &e->cache); } @@ -93,7 +90,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask, int report) { int ret = 0; - struct net *net = nf_ct_net(ct); struct nf_ct_event_notifier *notify; struct nf_conntrack_ecache *e; @@ -102,9 +98,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask, if (notify == NULL) goto out_unlock; - if (!net->ct.sysctl_events) - goto out_unlock; - e = nf_ct_ecache_find(ct); if (e == NULL) goto out_unlock; @@ -118,6 +111,9 @@ nf_conntrack_eventmask_report(unsigned int eventmask, /* This is a resent of a destroy event? If so, skip missed */ unsigned long missed = e->pid ? 0 : e->missed; + if (!((eventmask | missed) & e->ctmask)) + goto out_unlock; + ret = notify->fcn(eventmask | missed, &item); if (unlikely(ret < 0 || missed)) { spin_lock_bh(&ct->lock); @@ -173,18 +169,19 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event, u32 pid, int report) { - struct net *net = nf_ct_exp_net(exp); struct nf_exp_event_notifier *notify; + struct nf_conntrack_ecache *e; rcu_read_lock(); notify = rcu_dereference(nf_expect_event_cb); if (notify == NULL) goto out_unlock; - if (!net->ct.sysctl_events) + e = nf_ct_ecache_find(exp->master); + if (e == NULL) goto out_unlock; - { + if (e->expmask & (1 << event)) { struct nf_exp_event item = { .exp = exp, .pid = pid, diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 091ff770eb7b..53b8da6ad6b7 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -648,7 +648,7 @@ init_conntrack(struct net *net, } nf_ct_acct_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); spin_lock_bh(&nf_conntrack_lock); exp = nf_ct_find_expectation(net, tuple); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ff594eb138c1..f5c0b09e12f1 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1281,7 +1281,7 @@ ctnetlink_create_conntrack(struct net *net, } nf_ct_acct_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK]) -- cgit v1.2.3 From b2a15a604d379af323645e330638e2cfcc696aff Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 14:13:03 +0100 Subject: netfilter: nf_conntrack: support conntrack templates Support initializing selected parameters of new conntrack entries from a "conntrack template", which is a specially marked conntrack entry attached to the skb. Currently the helper and the event delivery masks can be initialized this way. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_common.h | 4 +++ include/net/netfilter/nf_conntrack.h | 5 +++ include/net/netfilter/nf_conntrack_helper.h | 3 +- net/ipv4/netfilter/nf_defrag_ipv4.c | 2 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- net/netfilter/nf_conntrack_core.c | 50 +++++++++++++++++--------- net/netfilter/nf_conntrack_helper.c | 17 ++++++--- net/netfilter/nf_conntrack_netlink.c | 2 +- 8 files changed, 61 insertions(+), 24 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index ebfed90733f7..c608677dda60 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h @@ -72,6 +72,10 @@ enum ip_conntrack_status { /* Connection has fixed timeout. */ IPS_FIXED_TIMEOUT_BIT = 10, IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), + + /* Conntrack is a template */ + IPS_TEMPLATE_BIT = 11, + IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), }; /* Connection tracking event types */ diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index a0904adfb8f7..5043d61c99a7 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -272,6 +272,11 @@ nf_conntrack_alloc(struct net *net, const struct nf_conntrack_tuple *repl, gfp_t gfp); +static inline int nf_ct_is_template(const struct nf_conn *ct) +{ + return test_bit(IPS_TEMPLATE_BIT, &ct->status); +} + /* It's confirmed if it is, or has been in the hash table. */ static inline int nf_ct_is_confirmed(struct nf_conn *ct) { diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 86be7c4816d6..e17aaa3e19fd 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -47,7 +47,8 @@ extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); -extern int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags); +extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, + gfp_t flags); extern void nf_ct_helper_destroy(struct nf_conn *ct); diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 331ead3ebd1b..77627fa80561 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -59,7 +59,7 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, #if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE) /* Previously seen (loopback)? Ignore. Do this before fragment check. */ - if (skb->nfct) + if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) return NF_ACCEPT; #endif #endif diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 0956ebabbff2..55ce22e5de49 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -212,7 +212,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, struct sk_buff *reasm; /* Previously seen (loopback)? */ - if (skb->nfct) + if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) return NF_ACCEPT; reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 53b8da6ad6b7..471e2a79d26f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -618,7 +618,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free); /* Allocate a new conntrack: we return -ENOMEM if classification failed due to stress. Otherwise it really is unclassifiable. */ static struct nf_conntrack_tuple_hash * -init_conntrack(struct net *net, +init_conntrack(struct net *net, struct nf_conn *tmpl, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_l3proto *l3proto, struct nf_conntrack_l4proto *l4proto, @@ -628,6 +628,7 @@ init_conntrack(struct net *net, struct nf_conn *ct; struct nf_conn_help *help; struct nf_conntrack_tuple repl_tuple; + struct nf_conntrack_ecache *ecache; struct nf_conntrack_expect *exp; if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { @@ -648,7 +649,11 @@ init_conntrack(struct net *net, } nf_ct_acct_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); + + ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL; + nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0, + ecache ? ecache->expmask : 0, + GFP_ATOMIC); spin_lock_bh(&nf_conntrack_lock); exp = nf_ct_find_expectation(net, tuple); @@ -673,7 +678,7 @@ init_conntrack(struct net *net, nf_conntrack_get(&ct->master->ct_general); NF_CT_STAT_INC(net, expect_new); } else { - __nf_ct_try_assign_helper(ct, GFP_ATOMIC); + __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC); NF_CT_STAT_INC(net, new); } @@ -694,7 +699,7 @@ init_conntrack(struct net *net, /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */ static inline struct nf_conn * -resolve_normal_ct(struct net *net, +resolve_normal_ct(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, unsigned int dataoff, u_int16_t l3num, @@ -718,7 +723,8 @@ resolve_normal_ct(struct net *net, /* look for tuple match */ h = nf_conntrack_find_get(net, &tuple); if (!h) { - h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff); + h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, + skb, dataoff); if (!h) return NULL; if (IS_ERR(h)) @@ -755,7 +761,7 @@ unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, struct sk_buff *skb) { - struct nf_conn *ct; + struct nf_conn *ct, *tmpl = NULL; enum ip_conntrack_info ctinfo; struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l4proto *l4proto; @@ -764,10 +770,14 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, int set_reply = 0; int ret; - /* Previously seen (loopback or untracked)? Ignore. */ if (skb->nfct) { - NF_CT_STAT_INC_ATOMIC(net, ignore); - return NF_ACCEPT; + /* Previously seen (loopback or untracked)? Ignore. */ + tmpl = (struct nf_conn *)skb->nfct; + if (!nf_ct_is_template(tmpl)) { + NF_CT_STAT_INC_ATOMIC(net, ignore); + return NF_ACCEPT; + } + skb->nfct = NULL; } /* rcu_read_lock()ed by nf_hook_slow */ @@ -778,7 +788,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, pr_debug("not prepared to track yet or error occured\n"); NF_CT_STAT_INC_ATOMIC(net, error); NF_CT_STAT_INC_ATOMIC(net, invalid); - return -ret; + ret = -ret; + goto out; } l4proto = __nf_ct_l4proto_find(pf, protonum); @@ -791,22 +802,25 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, if (ret <= 0) { NF_CT_STAT_INC_ATOMIC(net, error); NF_CT_STAT_INC_ATOMIC(net, invalid); - return -ret; + ret = -ret; + goto out; } } - ct = resolve_normal_ct(net, skb, dataoff, pf, protonum, + ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, l3proto, l4proto, &set_reply, &ctinfo); if (!ct) { /* Not valid part of a connection */ NF_CT_STAT_INC_ATOMIC(net, invalid); - return NF_ACCEPT; + ret = NF_ACCEPT; + goto out; } if (IS_ERR(ct)) { /* Too stressed to deal. */ NF_CT_STAT_INC_ATOMIC(net, drop); - return NF_DROP; + ret = NF_DROP; + goto out; } NF_CT_ASSERT(skb->nfct); @@ -821,11 +835,15 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, NF_CT_STAT_INC_ATOMIC(net, invalid); if (ret == -NF_DROP) NF_CT_STAT_INC_ATOMIC(net, drop); - return -ret; + ret = -ret; + goto out; } if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) nf_conntrack_event_cache(IPCT_REPLY, ct); +out: + if (tmpl) + nf_ct_put(tmpl); return ret; } @@ -864,7 +882,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct, return; rcu_read_lock(); - __nf_ct_try_assign_helper(ct, GFP_ATOMIC); + __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC); rcu_read_unlock(); } EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index c0e461f466ae..8144b0da5515 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -96,13 +96,22 @@ struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) } EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); -int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags) +int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, + gfp_t flags) { + struct nf_conntrack_helper *helper = NULL; + struct nf_conn_help *help; int ret = 0; - struct nf_conntrack_helper *helper; - struct nf_conn_help *help = nfct_help(ct); - helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + if (tmpl != NULL) { + help = nfct_help(tmpl); + if (help != NULL) + helper = help->helper; + } + + help = nfct_help(ct); + if (helper == NULL) + helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); if (helper == NULL) { if (help) rcu_assign_pointer(help->helper, NULL); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index f5c0b09e12f1..09044f9f4b2e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1249,7 +1249,7 @@ ctnetlink_create_conntrack(struct net *net, } } else { /* try an implicit helper assignation */ - err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC); + err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC); if (err < 0) goto err2; } -- cgit v1.2.3 From 84f3bb9ae9db90f7fb15d98b55279a58ab1b2363 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 3 Feb 2010 17:17:06 +0100 Subject: netfilter: xtables: add CT target Add a new target for the raw table, which can be used to specify conntrack parameters for specific connections, f.i. the conntrack helper. The target attaches a "template" connection tracking entry to the skb, which is used by the conntrack core when initializing a new conntrack. Signed-off-by: Patrick McHardy --- include/linux/netfilter/Kbuild | 1 + include/linux/netfilter/xt_CT.h | 17 +++ include/net/netfilter/nf_conntrack_helper.h | 3 + net/netfilter/Kconfig | 12 +++ net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_helper.c | 19 ++++ net/netfilter/xt_CT.c | 158 ++++++++++++++++++++++++++++ 7 files changed, 211 insertions(+) create mode 100644 include/linux/netfilter/xt_CT.h create mode 100644 net/netfilter/xt_CT.c diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index 2aea50399c0b..a5a63e41b8af 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild @@ -6,6 +6,7 @@ header-y += nfnetlink_queue.h header-y += xt_CLASSIFY.h header-y += xt_CONNMARK.h header-y += xt_CONNSECMARK.h +header-y += xt_CT.h header-y += xt_DSCP.h header-y += xt_LED.h header-y += xt_MARK.h diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h new file mode 100644 index 000000000000..7fd0effe1316 --- /dev/null +++ b/include/linux/netfilter/xt_CT.h @@ -0,0 +1,17 @@ +#ifndef _XT_CT_H +#define _XT_CT_H + +#define XT_CT_NOTRACK 0x1 + +struct xt_ct_target_info { + u_int16_t flags; + u_int16_t __unused; + u_int32_t ct_events; + u_int32_t exp_events; + char helper[16]; + + /* Used internally by the kernel */ + struct nf_conn *ct __attribute__((aligned(8))); +}; + +#endif /* _XT_CT_H */ diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index e17aaa3e19fd..32c305dbdab6 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -42,6 +42,9 @@ struct nf_conntrack_helper { extern struct nf_conntrack_helper * __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum); +extern struct nf_conntrack_helper * +nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum); + extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 634d14affc8d..4469d45261f4 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -341,6 +341,18 @@ config NETFILTER_XT_TARGET_CONNSECMARK To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_TARGET_CT + tristate '"CT" target support' + depends on NF_CONNTRACK + depends on IP_NF_RAW || IP6_NF_RAW + depends on NETFILTER_ADVANCED + help + This options adds a `CT' target, which allows to specify initial + connection tracking parameters like events to be delivered and + the helper to be used. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_TARGET_DSCP tristate '"DSCP" and "TOS" target support' depends on IP_NF_MANGLE || IP6_NF_MANGLE diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 49f62ee4e9ff..f873644f02f6 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 8144b0da5515..a74a5769877b 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -83,6 +83,25 @@ __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum) } EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find); +struct nf_conntrack_helper * +nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum) +{ + struct nf_conntrack_helper *h; + + h = __nf_conntrack_helper_find(name, l3num, protonum); +#ifdef CONFIG_MODULES + if (h == NULL) { + if (request_module("nfct-helper-%s", name) == 0) + h = __nf_conntrack_helper_find(name, l3num, protonum); + } +#endif + if (h != NULL && !try_module_get(h->me)) + h = NULL; + + return h; +} +EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); + struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) { struct nf_conn_help *help; diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c new file mode 100644 index 000000000000..8183a054256f --- /dev/null +++ b/net/netfilter/xt_CT.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2010 Patrick McHardy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int xt_ct_target(struct sk_buff *skb, + const struct xt_target_param *par) +{ + const struct xt_ct_target_info *info = par->targinfo; + struct nf_conn *ct = info->ct; + + /* Previously seen (loopback)? Ignore. */ + if (skb->nfct != NULL) + return XT_CONTINUE; + + atomic_inc(&ct->ct_general.use); + skb->nfct = &ct->ct_general; + skb->nfctinfo = IP_CT_NEW; + + return XT_CONTINUE; +} + +static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) +{ + if (par->family == AF_INET) { + const struct ipt_entry *e = par->entryinfo; + + if (e->ip.invflags & IPT_INV_PROTO) + return 0; + return e->ip.proto; + } else if (par->family == AF_INET6) { + const struct ip6t_entry *e = par->entryinfo; + + if (e->ipv6.invflags & IP6T_INV_PROTO) + return 0; + return e->ipv6.proto; + } else + return 0; +} + +static bool xt_ct_tg_check(const struct xt_tgchk_param *par) +{ + struct xt_ct_target_info *info = par->targinfo; + struct nf_conntrack_tuple t; + struct nf_conn_help *help; + struct nf_conn *ct; + u8 proto; + + if (info->flags & ~XT_CT_NOTRACK) + return false; + + if (info->flags & XT_CT_NOTRACK) { + ct = &nf_conntrack_untracked; + atomic_inc(&ct->ct_general.use); + goto out; + } + + if (nf_ct_l3proto_try_module_get(par->family) < 0) + goto err1; + + memset(&t, 0, sizeof(t)); + ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL); + if (IS_ERR(ct)) + goto err2; + + if ((info->ct_events || info->exp_events) && + !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, + GFP_KERNEL)) + goto err3; + + if (info->helper[0]) { + proto = xt_ct_find_proto(par); + if (!proto) + goto err3; + + help = nf_ct_helper_ext_add(ct, GFP_KERNEL); + if (help == NULL) + goto err3; + + help->helper = nf_conntrack_helper_try_module_get(info->helper, + par->family, + proto); + if (help->helper == NULL) + goto err3; + } + + __set_bit(IPS_TEMPLATE_BIT, &ct->status); + __set_bit(IPS_CONFIRMED_BIT, &ct->status); +out: + info->ct = ct; + return true; + +err3: + nf_conntrack_free(ct); +err2: + nf_ct_l3proto_module_put(par->family); +err1: + return false; +} + +static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par) +{ + struct xt_ct_target_info *info = par->targinfo; + struct nf_conn *ct = info->ct; + struct nf_conn_help *help; + + if (ct != &nf_conntrack_untracked) { + help = nfct_help(ct); + if (help) + module_put(help->helper->me); + + nf_ct_l3proto_module_put(par->family); + } + nf_ct_put(info->ct); +} + +static struct xt_target xt_ct_tg __read_mostly = { + .name = "CT", + .family = NFPROTO_UNSPEC, + .targetsize = XT_ALIGN(sizeof(struct xt_ct_target_info)), + .checkentry = xt_ct_tg_check, + .destroy = xt_ct_tg_destroy, + .target = xt_ct_target, + .table = "raw", + .me = THIS_MODULE, +}; + +static int __init xt_ct_tg_init(void) +{ + return xt_register_target(&xt_ct_tg); +} + +static void __exit xt_ct_tg_exit(void) +{ + xt_unregister_target(&xt_ct_tg); +} + +module_init(xt_ct_tg_init); +module_exit(xt_ct_tg_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Xtables: connection tracking target"); +MODULE_ALIAS("ipt_CT"); +MODULE_ALIAS("ip6t_CT"); -- cgit v1.2.3 From 76802851b6e1b78b614ba611d6b5d27a83f60ded Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Sun, 31 Jan 2010 02:58:19 +0000 Subject: MCS7830 USB-Ether: add Rx error support ChangeLog: - evaluate Rx error statistics from trailing Rx status byte - add driver TODO list - add myself to authors Quilt series run-tested, based on 2.6.33-rc4 (net-2.6.git mcs7830 has idle history, should be good to go). Signed-off-by: Andreas Mohr Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 87374317f480..22cccda33366 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -3,11 +3,27 @@ * * based on usbnet.c, asix.c and the vendor provided mcs7830 driver * + * Copyright (C) 2010 Andreas Mohr * Copyright (C) 2006 Arnd Bergmann * Copyright (C) 2003-2005 David Hollis * Copyright (C) 2005 Phil Chang * Copyright (c) 2002-2003 TiVo Inc. * + * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!). + * + * TODO: + * - add .reset_resume support (iface is _gone_ after resume w/ power loss) + * - verify that mcs7830_get_regs() does have same output pre-/post-suspend + * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?) + * - implement ethtool_ops get_pauseparam/set_pauseparam + * via HIF_REG_PAUSE_THRESHOLD (>= revision C only!) + * - implement get_eeprom/[set_eeprom] + * - switch PHY on/off on ifup/ifdown (perhaps in usbnet.c, via MII) + * - mcs7830_get_regs() handling is weird: for rev 2 we return 32 regs, + * can access only ~ 24, remaining user buffer is uninitialized garbage + * - anything else? + * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -83,6 +99,17 @@ enum { HIF_REG_PAUSE_THRESHOLD_DEFAULT = 0, }; +/* Trailing status byte in Ethernet Rx frame */ +enum { + MCS7830_RX_SHORT_FRAME = 0x01, /* < 64 bytes */ + MCS7830_RX_LENGTH_ERROR = 0x02, /* framelen != Ethernet length field */ + MCS7830_RX_ALIGNMENT_ERROR = 0x04, /* non-even number of nibbles */ + MCS7830_RX_CRC_ERROR = 0x08, + MCS7830_RX_LARGE_FRAME = 0x10, /* > 1518 bytes */ + MCS7830_RX_FRAME_CORRECT = 0x20, /* frame is correct */ + /* [7:6] reserved */ +}; + struct mcs7830_data { u8 multi_filter[8]; u8 config; @@ -539,9 +566,23 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_trim(skb, skb->len - 1); status = skb->data[skb->len]; - if (status != 0x20) + if (status != MCS7830_RX_FRAME_CORRECT) { dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status); + /* hmm, perhaps usbnet.c already sees a globally visible + frame error and increments rx_errors on its own already? */ + dev->net->stats.rx_errors++; + + if (status & (MCS7830_RX_SHORT_FRAME + |MCS7830_RX_LENGTH_ERROR + |MCS7830_RX_LARGE_FRAME)) + dev->net->stats.rx_length_errors++; + if (status & MCS7830_RX_ALIGNMENT_ERROR) + dev->net->stats.rx_frame_errors++; + if (status & MCS7830_RX_CRC_ERROR) + dev->net->stats.rx_crc_errors++; + } + return skb->len > 0; } -- cgit v1.2.3 From 00e499131e250324a89c93d5dd88c8f2b4bf6dbb Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Sun, 31 Jan 2010 02:58:26 +0000 Subject: MCS7830 USB-Ether: Spelling corrections ChangeLog: - spelling corrections / whitespace Signed-off-by: Andreas Mohr Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 22cccda33366..cb164d6c9b51 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -1,5 +1,5 @@ /* - * MosChips MCS7830 based USB 2.0 Ethernet Devices + * MOSCHIP MCS7830 based USB 2.0 Ethernet Devices * * based on usbnet.c, asix.c and the vendor provided mcs7830 driver * @@ -71,7 +71,7 @@ ADVERTISE_100HALF | ADVERTISE_10FULL | \ ADVERTISE_10HALF | ADVERTISE_CSMA) -/* HIF_REG_XX coressponding index value */ +/* HIF_REG_XX corresponding index value */ enum { HIF_REG_MULTICAST_HASH = 0x00, HIF_REG_PACKET_GAP1 = 0x08, @@ -92,7 +92,7 @@ enum { HIF_REG_CONFIG_TXENABLE = 0x08, HIF_REG_CONFIG_SLEEPMODE = 0x04, HIF_REG_CONFIG_ALLMULTICAST = 0x02, - HIF_REG_CONFIG_PROMISCIOUS = 0x01, + HIF_REG_CONFIG_PROMISCUOUS = 0x01, HIF_REG_ETHERNET_ADDR = 0x0f, HIF_REG_22 = 0x15, HIF_REG_PAUSE_THRESHOLD = 0x16, @@ -417,7 +417,7 @@ static void mcs7830_set_multicast(struct net_device *net) data->config |= HIF_REG_CONFIG_ALLMULTICAST; if (net->flags & IFF_PROMISC) { - data->config |= HIF_REG_CONFIG_PROMISCIOUS; + data->config |= HIF_REG_CONFIG_PROMISCUOUS; } else if (net->flags & IFF_ALLMULTI || net->mc_count > MCS7830_MAX_MCAST) { data->config |= HIF_REG_CONFIG_ALLMULTICAST; @@ -522,7 +522,7 @@ static const struct net_device_ops mcs7830_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = mcs7830_ioctl, .ndo_set_multicast_list = mcs7830_set_multicast, - .ndo_set_mac_address = mcs7830_set_mac_address, + .ndo_set_mac_address = mcs7830_set_mac_address, }; static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) @@ -553,7 +553,7 @@ out: return ret; } -/* The chip always appends a status bytes that we need to strip */ +/* The chip always appends a status byte that we need to strip */ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { u8 status; -- cgit v1.2.3 From c774651a5ffc0250f82d72730753f196c86884c5 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Sun, 31 Jan 2010 02:58:33 +0000 Subject: MCS7830 USB-Ether: change register define ChangeLog: - rename register, add comment Signed-off-by: Andreas Mohr Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index cb164d6c9b51..36a029218e3d 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -85,6 +85,7 @@ enum { HIF_REG_PHY_CMD2_PEND_FLAG_BIT = 0x80, HIF_REG_PHY_CMD2_READY_FLAG_BIT = 0x40, HIF_REG_CONFIG = 0x0e, + /* hmm, spec sez: "R/W", "Except bit 3" (likely TXENABLE). */ HIF_REG_CONFIG_CFG = 0x80, HIF_REG_CONFIG_SPEED100 = 0x40, HIF_REG_CONFIG_FULLDUPLEX_ENABLE = 0x20, @@ -94,7 +95,7 @@ enum { HIF_REG_CONFIG_ALLMULTICAST = 0x02, HIF_REG_CONFIG_PROMISCUOUS = 0x01, HIF_REG_ETHERNET_ADDR = 0x0f, - HIF_REG_22 = 0x15, + HIF_REG_FRAME_DROP_COUNTER = 0x15, /* 0..ff; reset: 0 */ HIF_REG_PAUSE_THRESHOLD = 0x16, HIF_REG_PAUSE_THRESHOLD_DEFAULT = 0, }; @@ -334,7 +335,7 @@ static int mcs7830_get_rev(struct usbnet *dev) { u8 dummy[2]; int ret; - ret = mcs7830_get_reg(dev, HIF_REG_22, 2, dummy); + ret = mcs7830_get_reg(dev, HIF_REG_FRAME_DROP_COUNTER, 2, dummy); if (ret > 0) return 2; /* Rev C or later */ return 1; /* earlier revision */ -- cgit v1.2.3 From ace2a4d0fbf868c00625a8fd91c44ad9fabe7012 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Sun, 31 Jan 2010 02:58:42 +0000 Subject: MCS7830 USB-Ether: resume _with_ working link, via .reset_resume support ChangeLog: Implement .reset_resume support to retain a live network connection during suspend despite USB power loss. - rework operation to reference cached data in mcs7830_data and netdev->dev_addr - update netdev->dev_addr only in case new MAC was set successfully . Tests done: . ethtool -d pre-/post-suspend: register values match . running ssh session suspend, resume: works . ifdown device, suspend, resume: works . ifup, suspend, unplug, resume: WORKS (eth1 is removed, re-ifup of eth1 after card replug works) . verified identical MAC in ifconfig post-resume (ok, should be verified on network side to be fully certain...) Keywords: suspend resume network connection dead interface down Signed-off-by: Andreas Mohr Signed-off-by: David S. Miller --- drivers/net/usb/mcs7830.c | 190 ++++++++++++++++++++++++++++++---------------- 1 file changed, 123 insertions(+), 67 deletions(-) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 36a029218e3d..6fc098fe9ff7 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -12,8 +12,6 @@ * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!). * * TODO: - * - add .reset_resume support (iface is _gone_ after resume w/ power loss) - * - verify that mcs7830_get_regs() does have same output pre-/post-suspend * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?) * - implement ethtool_ops get_pauseparam/set_pauseparam * via HIF_REG_PAUSE_THRESHOLD (>= revision C only!) @@ -137,7 +135,7 @@ static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) return ret; } -static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data) +static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data) { struct usb_device *xdev = dev->udev; int ret; @@ -211,13 +209,43 @@ out: usb_free_urb(urb); } -static int mcs7830_get_address(struct usbnet *dev) +static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr) +{ + int ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr); + if (ret < 0) + return ret; + return 0; +} + +static int mcs7830_hif_set_mac_address(struct usbnet *dev, unsigned char *addr) +{ + int ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, addr); + + if (ret < 0) + return ret; + return 0; +} + +static int mcs7830_set_mac_address(struct net_device *netdev, void *p) { int ret; - ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, - dev->net->dev_addr); + struct usbnet *dev = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (netif_running(netdev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + ret = mcs7830_hif_set_mac_address(dev, addr->sa_data); + if (ret < 0) return ret; + + /* it worked --> adopt it on netdev side */ + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + return 0; } @@ -359,33 +387,6 @@ static void mcs7830_rev_C_fixup(struct usbnet *dev) } } -static int mcs7830_init_dev(struct usbnet *dev) -{ - int ret; - int retry; - - /* Read MAC address from EEPROM */ - ret = -EINVAL; - for (retry = 0; retry < 5 && ret; retry++) - ret = mcs7830_get_address(dev); - if (ret) { - dev_warn(&dev->udev->dev, "Cannot read MAC address\n"); - goto out; - } - - /* Set up PHY */ - ret = mcs7830_set_autoneg(dev, 0); - if (ret) { - dev_info(&dev->udev->dev, "Cannot set autoneg\n"); - goto out; - } - - mcs7830_rev_C_fixup(dev); - ret = 0; -out: - return ret; -} - static int mcs7830_mdio_read(struct net_device *netdev, int phy_id, int location) { @@ -406,11 +407,33 @@ static int mcs7830_ioctl(struct net_device *net, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } -/* credits go to asix_set_multicast */ -static void mcs7830_set_multicast(struct net_device *net) +static inline struct mcs7830_data *mcs7830_get_data(struct usbnet *dev) +{ + return (struct mcs7830_data *)&dev->data; +} + +static void mcs7830_hif_update_multicast_hash(struct usbnet *dev) +{ + struct mcs7830_data *data = mcs7830_get_data(dev); + mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH, + sizeof data->multi_filter, + data->multi_filter); +} + +static void mcs7830_hif_update_config(struct usbnet *dev) +{ + /* implementation specific to data->config + (argument needs to be heap-based anyway - USB DMA!) */ + struct mcs7830_data *data = mcs7830_get_data(dev); + mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config); +} + +static void mcs7830_data_set_multicast(struct net_device *net) { struct usbnet *dev = netdev_priv(net); - struct mcs7830_data *data = (struct mcs7830_data *)&dev->data; + struct mcs7830_data *data = mcs7830_get_data(dev); + + memset(data->multi_filter, 0, sizeof data->multi_filter); data->config = HIF_REG_CONFIG_TXENABLE; @@ -433,21 +456,51 @@ static void mcs7830_set_multicast(struct net_device *net) u32 crc_bits; int i; - memset(data->multi_filter, 0, sizeof data->multi_filter); - /* Build the multicast hash filter. */ for (i = 0; i < net->mc_count; i++) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); mc_list = mc_list->next; } + } +} - mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH, - sizeof data->multi_filter, - data->multi_filter); +static int mcs7830_apply_base_config(struct usbnet *dev) +{ + int ret; + + /* re-configure known MAC (suspend case etc.) */ + ret = mcs7830_hif_set_mac_address(dev, dev->net->dev_addr); + if (ret) { + dev_info(&dev->udev->dev, "Cannot set MAC address\n"); + goto out; } - mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config); + /* Set up PHY */ + ret = mcs7830_set_autoneg(dev, 0); + if (ret) { + dev_info(&dev->udev->dev, "Cannot set autoneg\n"); + goto out; + } + + mcs7830_hif_update_multicast_hash(dev); + mcs7830_hif_update_config(dev); + + mcs7830_rev_C_fixup(dev); + ret = 0; +out: + return ret; +} + +/* credits go to asix_set_multicast */ +static void mcs7830_set_multicast(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + + mcs7830_data_set_multicast(net); + + mcs7830_hif_update_multicast_hash(dev); + mcs7830_hif_update_config(dev); } static int mcs7830_get_regs_len(struct net_device *net) @@ -491,29 +544,6 @@ static const struct ethtool_ops mcs7830_ethtool_ops = { .nway_reset = usbnet_nway_reset, }; -static int mcs7830_set_mac_address(struct net_device *netdev, void *p) -{ - int ret; - struct usbnet *dev = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (netif_running(netdev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - - ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, - netdev->dev_addr); - - if (ret < 0) - return ret; - - return 0; -} - static const struct net_device_ops mcs7830_netdev_ops = { .ndo_open = usbnet_open, .ndo_stop = usbnet_stop, @@ -530,14 +560,25 @@ static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) { struct net_device *net = dev->net; int ret; + int retry; - ret = mcs7830_init_dev(dev); + /* Initial startup: Gather MAC address setting from EEPROM */ + ret = -EINVAL; + for (retry = 0; retry < 5 && ret; retry++) + ret = mcs7830_hif_get_mac_address(dev, net->dev_addr); + if (ret) { + dev_warn(&dev->udev->dev, "Cannot read MAC address\n"); + goto out; + } + + mcs7830_data_set_multicast(net); + + ret = mcs7830_apply_base_config(dev); if (ret) goto out; net->ethtool_ops = &mcs7830_ethtool_ops; net->netdev_ops = &mcs7830_netdev_ops; - mcs7830_set_multicast(net); /* reserve space for the status byte on rx */ dev->rx_urb_size = ETH_FRAME_LEN + 1; @@ -622,6 +663,20 @@ static const struct usb_device_id products[] = { }; MODULE_DEVICE_TABLE(usb, products); +static int mcs7830_reset_resume (struct usb_interface *intf) +{ + /* YES, this function is successful enough that ethtool -d + does show same output pre-/post-suspend */ + + struct usbnet *dev = usb_get_intfdata(intf); + + mcs7830_apply_base_config(dev); + + usbnet_resume(intf); + + return 0; +} + static struct usb_driver mcs7830_driver = { .name = driver_name, .id_table = products, @@ -629,6 +684,7 @@ static struct usb_driver mcs7830_driver = { .disconnect = usbnet_disconnect, .suspend = usbnet_suspend, .resume = usbnet_resume, + .reset_resume = mcs7830_reset_resume, }; static int __init mcs7830_init(void) -- cgit v1.2.3 From 2e02644abc4b3574533b027782820b5a6dfe1920 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Mon, 1 Feb 2010 10:29:29 +0000 Subject: cxgb3: add memory barriers Add memory barriers to fix crashes observed on newest PowerPC platforms. The HW and driver state of the receive rings were getting out of sync. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/sge.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index bdbd14727e4b..4cf9b7962afa 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -480,6 +480,7 @@ static inline void ring_fl_db(struct adapter *adap, struct sge_fl *q) { if (q->pend_cred >= q->credits / 4) { q->pend_cred = 0; + wmb(); t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); } } @@ -2282,11 +2283,14 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, while (likely(budget_left && is_new_response(r, q))) { int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; struct sk_buff *skb = NULL; - u32 len, flags = ntohl(r->flags); - __be32 rss_hi = *(const __be32 *)r, - rss_lo = r->rss_hdr.rss_hash_val; + u32 len, flags; + __be32 rss_hi, rss_lo; + rmb(); eth = r->rss_hdr.opcode == CPL_RX_PKT; + rss_hi = *(const __be32 *)r; + rss_lo = r->rss_hdr.rss_hash_val; + flags = ntohl(r->flags); if (unlikely(flags & F_RSPD_ASYNC_NOTIF)) { skb = alloc_skb(AN_PKT_SIZE, GFP_ATOMIC); @@ -2497,7 +2501,10 @@ static int process_pure_responses(struct adapter *adap, struct sge_qset *qs, refill_rspq(adap, q, q->credits); q->credits = 0; } - } while (is_new_response(r, q) && is_pure_response(r)); + if (!is_new_response(r, q)) + break; + rmb(); + } while (is_pure_response(r)); if (sleeping) check_ring_db(adap, qs, sleeping); @@ -2531,6 +2538,7 @@ static inline int handle_responses(struct adapter *adap, struct sge_rspq *q) if (!is_new_response(r, q)) return -1; + rmb(); if (is_pure_response(r) && process_pure_responses(adap, qs, r) == 0) { t3_write_reg(adap, A_SG_GTS, V_RSPQ(q->cntxt_id) | V_NEWTIMER(q->holdoff_tmr) | V_NEWINDEX(q->cidx)); -- cgit v1.2.3 From 24c4a3b29255f9f8bc48d93597a58256b5a1f83f Mon Sep 17 00:00:00 2001 From: Pavel Cheblakov Date: Mon, 1 Feb 2010 09:42:44 +0000 Subject: can: add support for CAN interface cards based on the PLX90xx PCI bridge This driver is for CAN interface cards based on the PLX90xx PCI bridge. Driver supports now: - Adlink PCI-7841/cPCI-7841 card (http://www.adlinktech.com/) - Adlink PCI-7841/cPCI-7841 SE card - Marathon CAN-bus-PCI card (http://www.marathon.ru/) - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/) Changes since v1: - Added some defines for static inline int plx_pci_check_sja1000(...) - static struct pci_device_id plx_pci_tbl[] replaced by static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) - Typo fixed Signed-off-by: Pavel Cheblakov Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/sja1000/Kconfig | 12 + drivers/net/can/sja1000/Makefile | 1 + drivers/net/can/sja1000/plx_pci.c | 472 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 485 insertions(+) create mode 100644 drivers/net/can/sja1000/plx_pci.c diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 4c674927f247..9e277d64a318 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -44,4 +44,16 @@ config CAN_KVASER_PCI This driver is for the the PCIcanx and PCIcan cards (1, 2 or 4 channel) from Kvaser (http://www.kvaser.com). +config CAN_PLX_PCI + tristate "PLX90xx PCI-bridge based Cards" + depends on PCI + ---help--- + This driver is for CAN interface cards based on + the PLX90xx PCI bridge. + Driver supports now: + - Adlink PCI-7841/cPCI-7841 card (http://www.adlinktech.com/) + - Adlink PCI-7841/cPCI-7841 SE card + - Marathon CAN-bus-PCI card (http://www.marathon.ru/) + - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/) + endif diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 9d245ac03965..ce924553995d 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o +obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c new file mode 100644 index 000000000000..6b46a6395f80 --- /dev/null +++ b/drivers/net/can/sja1000/plx_pci.c @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2008-2010 Pavel Cheblakov + * + * Derived from the ems_pci.c driver: + * Copyright (C) 2007 Wolfgang Grandegger + * Copyright (C) 2008 Markus Plessing + * Copyright (C) 2008 Sebastian Haas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +#define DRV_NAME "sja1000_plx_pci" + +MODULE_AUTHOR("Pavel Cheblakov "); +MODULE_DESCRIPTION("Socket-CAN driver for PLX90xx PCI-bridge cards with " + "the SJA1000 chips"); +MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " + "Adlink PCI-7841/cPCI-7841 SE, " + "Marathon CAN-bus-PCI, " + "TEWS TECHNOLOGIES TPMC810"); +MODULE_LICENSE("GPL v2"); + +#define PLX_PCI_MAX_CHAN 2 + +struct plx_pci_card { + int channels; /* detected channels count */ + struct net_device *net_dev[PLX_PCI_MAX_CHAN]; + void __iomem *conf_addr; +}; + +#define PLX_PCI_CAN_CLOCK (16000000 / 2) + +/* PLX90xx registers */ +#define PLX_INTCSR 0x4c /* Interrupt Control/Status */ +#define PLX_CNTRL 0x50 /* User I/O, Direct Slave Response, + * Serial EEPROM, and Initialization + * Control register + */ + +#define PLX_LINT1_EN 0x1 /* Local interrupt 1 enable */ +#define PLX_LINT2_EN (1 << 3) /* Local interrupt 2 enable */ +#define PLX_PCI_INT_EN (1 << 6) /* PCI Interrupt Enable */ +#define PLX_PCI_RESET (1 << 30) /* PCI Adapter Software Reset */ + +/* + * The board configuration is probably following: + * RX1 is connected to ground. + * TX1 is not connected. + * CLKO is not connected. + * Setting the OCR register to 0xDA is a good idea. + * This means normal output mode, push-pull and the correct polarity. + */ +#define PLX_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) + +/* + * In the CDR register, you should set CBP to 1. + * You will probably also want to set the clock divider value to 7 + * (meaning direct oscillator output) because the second SJA1000 chip + * is driven by the first one CLKOUT output. + */ +#define PLX_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) + +/* SJA1000 Control Register in the BasicCAN Mode */ +#define REG_CR 0x00 + +/* States of some SJA1000 registers after hardware reset in the BasicCAN mode*/ +#define REG_CR_BASICCAN_INITIAL 0x21 +#define REG_CR_BASICCAN_INITIAL_MASK 0xa1 +#define REG_SR_BASICCAN_INITIAL 0x0c +#define REG_IR_BASICCAN_INITIAL 0xe0 + +/* States of some SJA1000 registers after hardware reset in the PeliCAN mode*/ +#define REG_MOD_PELICAN_INITIAL 0x01 +#define REG_SR_PELICAN_INITIAL 0x3c +#define REG_IR_PELICAN_INITIAL 0x00 + +#define ADLINK_PCI_VENDOR_ID 0x144A +#define ADLINK_PCI_DEVICE_ID 0x7841 + +#define MARATHON_PCI_DEVICE_ID 0x2715 + +#define TEWS_PCI_VENDOR_ID 0x1498 +#define TEWS_PCI_DEVICE_ID_TMPC810 0x032A + +static void plx_pci_reset_common(struct pci_dev *pdev); +static void plx_pci_reset_marathon(struct pci_dev *pdev); + +struct plx_pci_channel_map { + u32 bar; + u32 offset; + u32 size; /* 0x00 - auto, e.g. length of entire bar */ +}; + +struct plx_pci_card_info { + const char *name; + int channel_count; + u32 can_clock; + u8 ocr; /* output control register */ + u8 cdr; /* clock divider register */ + + /* Parameters for mapping local configuration space */ + struct plx_pci_channel_map conf_map; + + /* Parameters for mapping the SJA1000 chips */ + struct plx_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CHAN]; + + /* Pointer to device-dependent reset function */ + void (*reset_func)(struct pci_dev *pdev); +}; + +static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = { + "Adlink PCI-7841/cPCI-7841", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {1, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} }, + &plx_pci_reset_common + /* based on PLX9052 */ +}; + +static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = { + "Adlink PCI-7841/cPCI-7841 SE", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} }, + &plx_pci_reset_common + /* based on PLX9052 */ +}; + +static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = { + "Marathon CAN-bus-PCI", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} }, + &plx_pci_reset_marathon + /* based on PLX9052 */ +}; + +static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = { + "TEWS TECHNOLOGIES TPMC810", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} }, + &plx_pci_reset_common + /* based on PLX9030 */ +}; + +static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = { + { + /* Adlink PCI-7841/cPCI-7841 */ + ADLINK_PCI_VENDOR_ID, ADLINK_PCI_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_NETWORK_OTHER << 8, ~0, + (kernel_ulong_t)&plx_pci_card_info_adlink + }, + { + /* Adlink PCI-7841/cPCI-7841 SE */ + ADLINK_PCI_VENDOR_ID, ADLINK_PCI_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_OTHER << 8, ~0, + (kernel_ulong_t)&plx_pci_card_info_adlink_se + }, + { + /* Marathon CAN-bus-PCI card */ + PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + (kernel_ulong_t)&plx_pci_card_info_marathon + }, + { + /* TEWS TECHNOLOGIES TPMC810 card */ + TEWS_PCI_VENDOR_ID, TEWS_PCI_DEVICE_ID_TMPC810, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + (kernel_ulong_t)&plx_pci_card_info_tews + }, + { 0,} +}; +MODULE_DEVICE_TABLE(pci, plx_pci_tbl); + +static u8 plx_pci_read_reg(const struct sja1000_priv *priv, int port) +{ + return ioread8(priv->reg_base + port); +} + +static void plx_pci_write_reg(const struct sja1000_priv *priv, int port, u8 val) +{ + iowrite8(val, priv->reg_base + port); +} + +/* + * Check if a CAN controller is present at the specified location + * by trying to switch 'em from the Basic mode into the PeliCAN mode. + * Also check states of some registers in reset mode. + */ +static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv) +{ + int flag = 0; + + /* + * Check registers after hardware reset (the Basic mode) + * See states on p. 10 of the Datasheet. + */ + if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) == + REG_CR_BASICCAN_INITIAL && + (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) && + (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL)) + flag = 1; + + /* Bring the SJA1000 into the PeliCAN mode*/ + priv->write_reg(priv, REG_CDR, CDR_PELICAN); + + /* + * Check registers after reset in the PeliCAN mode. + * See states on p. 23 of the Datasheet. + */ + if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL && + priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL && + priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL) + return flag; + + return 0; +} + +/* + * PLX90xx software reset + * Also LRESET# asserts and brings to reset device on the Local Bus (if wired). + * For most cards it's enough for reset the SJA1000 chips. + */ +static void plx_pci_reset_common(struct pci_dev *pdev) +{ + struct plx_pci_card *card = pci_get_drvdata(pdev); + u32 cntrl; + + cntrl = ioread32(card->conf_addr + PLX_CNTRL); + cntrl |= PLX_PCI_RESET; + iowrite32(cntrl, card->conf_addr + PLX_CNTRL); + udelay(100); + cntrl ^= PLX_PCI_RESET; + iowrite32(cntrl, card->conf_addr + PLX_CNTRL); +}; + +/* Special reset function for Marathon card */ +static void plx_pci_reset_marathon(struct pci_dev *pdev) +{ + void __iomem *reset_addr; + int i; + int reset_bar[2] = {3, 5}; + + plx_pci_reset_common(pdev); + + for (i = 0; i < 2; i++) { + reset_addr = pci_iomap(pdev, reset_bar[i], 0); + if (!reset_addr) { + dev_err(&pdev->dev, "Failed to remap reset " + "space %d (BAR%d)\n", i, reset_bar[i]); + } else { + /* reset the SJA1000 chip */ + iowrite8(0x1, reset_addr); + udelay(100); + pci_iounmap(pdev, reset_addr); + } + } +} + +static void plx_pci_del_card(struct pci_dev *pdev) +{ + struct plx_pci_card *card = pci_get_drvdata(pdev); + struct net_device *dev; + struct sja1000_priv *priv; + int i = 0; + + for (i = 0; i < card->channels; i++) { + dev = card->net_dev[i]; + if (!dev) + continue; + + dev_info(&pdev->dev, "Removing %s\n", dev->name); + unregister_sja1000dev(dev); + priv = netdev_priv(dev); + if (priv->reg_base) + pci_iounmap(pdev, priv->reg_base); + free_sja1000dev(dev); + } + + plx_pci_reset_common(pdev); + + /* + * Disable interrupts from PCI-card (PLX90xx) and disable Local_1, + * Local_2 interrupts + */ + iowrite32(0x0, card->conf_addr + PLX_INTCSR); + + if (card->conf_addr) + pci_iounmap(pdev, card->conf_addr); + + kfree(card); + + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); +} + +/* + * Probe PLX90xx based device for the SJA1000 chips and register each + * available CAN channel to SJA1000 Socket-CAN subsystem. + */ +static int __devinit plx_pci_add_card(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct sja1000_priv *priv; + struct net_device *dev; + struct plx_pci_card *card; + struct plx_pci_card_info *ci; + int err, i; + u32 val; + void __iomem *addr; + + ci = (struct plx_pci_card_info *)ent->driver_data; + + if (pci_enable_device(pdev) < 0) { + dev_err(&pdev->dev, "Failed to enable PCI device\n"); + return -ENODEV; + } + + dev_info(&pdev->dev, "Detected \"%s\" card at slot #%i\n", + ci->name, PCI_SLOT(pdev->devfn)); + + /* Allocate card structures to hold addresses, ... */ + card = kzalloc(sizeof(*card), GFP_KERNEL); + if (!card) { + dev_err(&pdev->dev, "Unable to allocate memory\n"); + pci_disable_device(pdev); + return -ENOMEM; + } + + pci_set_drvdata(pdev, card); + + card->channels = 0; + + /* Remap PLX90xx configuration space */ + addr = pci_iomap(pdev, ci->conf_map.bar, ci->conf_map.size); + if (!addr) { + err = -ENOMEM; + dev_err(&pdev->dev, "Failed to remap configuration space " + "(BAR%d)\n", ci->conf_map.bar); + goto failure_cleanup; + } + card->conf_addr = addr + ci->conf_map.offset; + + ci->reset_func(pdev); + + /* Detect available channels */ + for (i = 0; i < ci->channel_count; i++) { + struct plx_pci_channel_map *cm = &ci->chan_map_tbl[i]; + + dev = alloc_sja1000dev(0); + if (!dev) { + err = -ENOMEM; + goto failure_cleanup; + } + + card->net_dev[i] = dev; + priv = netdev_priv(dev); + priv->priv = card; + priv->irq_flags = IRQF_SHARED; + + dev->irq = pdev->irq; + + /* + * Remap IO space of the SJA1000 chips + * This is device-dependent mapping + */ + addr = pci_iomap(pdev, cm->bar, cm->size); + if (!addr) { + err = -ENOMEM; + dev_err(&pdev->dev, "Failed to remap BAR%d\n", cm->bar); + goto failure_cleanup; + } + + priv->reg_base = addr + cm->offset; + priv->read_reg = plx_pci_read_reg; + priv->write_reg = plx_pci_write_reg; + + /* Check if channel is present */ + if (plx_pci_check_sja1000(priv)) { + priv->can.clock.freq = ci->can_clock; + priv->ocr = ci->ocr; + priv->cdr = ci->cdr; + + SET_NETDEV_DEV(dev, &pdev->dev); + + /* Register SJA1000 device */ + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, "Registering device failed " + "(err=%d)\n", err); + free_sja1000dev(dev); + goto failure_cleanup; + } + + card->channels++; + + dev_info(&pdev->dev, "Channel #%d at 0x%p, irq %d " + "registered as %s\n", i + 1, priv->reg_base, + dev->irq, dev->name); + } else { + dev_err(&pdev->dev, "Channel #%d not detected\n", + i + 1); + free_sja1000dev(dev); + } + } + + if (!card->channels) { + err = -ENODEV; + goto failure_cleanup; + } + + /* + * Enable interrupts from PCI-card (PLX90xx) and enable Local_1, + * Local_2 interrupts from the SJA1000 chips + */ + val = ioread32(card->conf_addr + PLX_INTCSR); + val |= PLX_LINT1_EN | PLX_LINT2_EN | PLX_PCI_INT_EN; + iowrite32(val, card->conf_addr + PLX_INTCSR); + + return 0; + +failure_cleanup: + dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err); + + plx_pci_del_card(pdev); + + return err; +} + +static struct pci_driver plx_pci_driver = { + .name = DRV_NAME, + .id_table = plx_pci_tbl, + .probe = plx_pci_add_card, + .remove = plx_pci_del_card, +}; + +static int __init plx_pci_init(void) +{ + return pci_register_driver(&plx_pci_driver); +} + +static void __exit plx_pci_exit(void) +{ + pci_unregister_driver(&plx_pci_driver); +} + +module_init(plx_pci_init); +module_exit(plx_pci_exit); -- cgit v1.2.3 From 91e83432f8abc1fc93499a2323f6c4bd6026029e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 31 Jan 2010 10:02:09 +0000 Subject: drivers/net/amd8111e.c: Fix continuation line formats String constants that are continued on subsequent lines with \ are not good. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/amd8111e.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index 545c791f477e..bb27b27d9672 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1176,8 +1176,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id) /* Schedule a polling routine */ __napi_schedule(&lp->napi); } else if (intren0 & RINTEN0) { - printk("************Driver bug! \ - interrupt while in poll\n"); + printk("************Driver bug! interrupt while in poll\n"); /* Fix by disable receive interrupts */ writel(RINTEN0, mmio + INTEN0); } -- cgit v1.2.3 From 5297a98d5dd6de86fe1e2ffc9ea60cdf59b71443 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:28:14 +0000 Subject: sfc: Update MCDI protocol definitions Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi_pcol.h | 202 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 179 insertions(+), 23 deletions(-) diff --git a/drivers/net/sfc/mcdi_pcol.h b/drivers/net/sfc/mcdi_pcol.h index 73e71f420624..bd59302695b3 100644 --- a/drivers/net/sfc/mcdi_pcol.h +++ b/drivers/net/sfc/mcdi_pcol.h @@ -786,16 +786,18 @@ #define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0 #define MC_CMD_GET_PHY_CFG_PRESENT_LBN 0 #define MC_CMD_GET_PHY_CFG_PRESENT_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_SHORTBIST_LBN 1 -#define MC_CMD_GET_PHY_CFG_SHORTBIST_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_LONGBIST_LBN 2 -#define MC_CMD_GET_PHY_CFG_LONGBIST_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN 1 +#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN 2 +#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_WIDTH 1 #define MC_CMD_GET_PHY_CFG_LOWPOWER_LBN 3 #define MC_CMD_GET_PHY_CFG_LOWPOWER_WIDTH 1 #define MC_CMD_GET_PHY_CFG_POWEROFF_LBN 4 #define MC_CMD_GET_PHY_CFG_POWEROFF_WIDTH 1 #define MC_CMD_GET_PHY_CFG_TXDIS_LBN 5 #define MC_CMD_GET_PHY_CFG_TXDIS_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_BIST_LBN 6 +#define MC_CMD_GET_PHY_CFG_BIST_WIDTH 1 #define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4 /* Bitmask of supported capabilities */ #define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8 @@ -832,7 +834,7 @@ #define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52 #define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20 -/* MC_CMD_START_PHY_BIST: +/* MC_CMD_START_BIST: * Start a BIST test on the PHY. * * Locks required: PHY_LOCK if doing a PHY BIST @@ -840,34 +842,71 @@ */ #define MC_CMD_START_BIST 0x25 #define MC_CMD_START_BIST_IN_LEN 4 -#define MC_CMD_START_BIST_TYPE_OFST 0 +#define MC_CMD_START_BIST_IN_TYPE_OFST 0 +#define MC_CMD_START_BIST_OUT_LEN 0 -/* Run the PHY's short BIST */ -#define MC_CMD_PHY_BIST_SHORT 1 -/* Run the PHY's long BIST */ -#define MC_CMD_PHY_BIST_LONG 2 +/* Run the PHY's short cable BIST */ +#define MC_CMD_PHY_BIST_CABLE_SHORT 1 +/* Run the PHY's long cable BIST */ +#define MC_CMD_PHY_BIST_CABLE_LONG 2 /* Run BIST on the currently selected BPX Serdes (XAUI or XFI) */ #define MC_CMD_BPX_SERDES_BIST 3 +/* Run the MC loopback tests */ +#define MC_CMD_MC_LOOPBACK_BIST 4 +/* Run the PHY's standard BIST */ +#define MC_CMD_PHY_BIST 5 /* MC_CMD_POLL_PHY_BIST: (variadic output) * Poll for BIST completion * - * Returns a single status code, and a binary blob of phy-specific - * bist output. If the driver can't succesfully parse the BIST output, - * it should still respect the Pass/Fail in OUT.RESULT. + * Returns a single status code, and optionally some PHY specific + * bist output. The driver should only consume the BIST output + * after validating OUTLEN and PHY_CFG.PHY_TYPE. * - * Locks required: PHY_LOCK if doing a PHY BIST + * If a driver can't succesfully parse the BIST output, it should + * still respect the pass/Fail in OUT.RESULT + * + * Locks required: PHY_LOCK if doing a PHY BIST * Return code: 0, EACCES (if PHY_LOCK is not held) */ #define MC_CMD_POLL_BIST 0x26 #define MC_CMD_POLL_BIST_IN_LEN 0 #define MC_CMD_POLL_BIST_OUT_LEN UNKNOWN +#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 40 +#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8 #define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 #define MC_CMD_POLL_BIST_RUNNING 1 #define MC_CMD_POLL_BIST_PASSED 2 #define MC_CMD_POLL_BIST_FAILED 3 #define MC_CMD_POLL_BIST_TIMEOUT 4 +/* Generic: */ #define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4 +/* SFT9001-specific: */ +/* (offset 4 unused?) */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 8 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 12 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 16 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 20 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 24 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 28 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 32 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 36 +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 1 +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 2 +#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 3 +#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 4 +#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 9 +/* mrsfp "PHY" driver: */ +#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4 +#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0 +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 1 +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 2 +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 3 +#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 4 +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 5 +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 6 +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 7 +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 8 /* MC_CMD_PHY_SPI: (variadic in, variadic out) * Read/Write/Erase the PHY SPI device @@ -1206,6 +1245,13 @@ #define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST \ (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 178) +#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST \ + MC_CMD_WOL_FILTER_SET_IN_DATA_OFST +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1 + #define MC_CMD_WOL_FILTER_SET_OUT_LEN 4 #define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0 @@ -1216,7 +1262,8 @@ #define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 #define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 #define MC_CMD_WOL_TYPE_BITMAP 0x5 -#define MC_CMD_WOL_TYPE_MAX 0x6 +#define MC_CMD_WOL_TYPE_LINK 0x6 +#define MC_CMD_WOL_TYPE_MAX 0x7 #define MC_CMD_FILTER_MODE_SIMPLE 0x0 #define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff @@ -1357,14 +1404,24 @@ * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) */ #define MC_CMD_NVRAM_UPDATE_FINISH 0x3c -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 4 +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8 #define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0 +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4 #define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0 /* MC_CMD_REBOOT: - * Reboot the MC. The AFTER_ASSERTION flag is intended to be used - * when the driver notices an assertion failure, to allow two ports to - * both recover (semi-)gracefully. + * Reboot the MC. + * + * The AFTER_ASSERTION flag is intended to be used when the driver notices + * an assertion failure (at which point it is expected to perform a complete + * tear down and reinitialise), to allow both ports to reset the MC once + * in an atomic fashion. + * + * Production mc firmwares are generally compiled with REBOOT_ON_ASSERT=1, + * which means that they will automatically reboot out of the assertion + * handler, so this is in practise an optional operation. It is still + * recommended that drivers execute this to support custom firmwares + * with REBOOT_ON_ASSERT=0. * * Locks required: NONE * Returns: Nothing. You get back a response with ERR=1, DATALEN=0 @@ -1469,11 +1526,10 @@ ((_ofst) + 6) /* MC_CMD_READ_SENSORS - * Returns the current (value, state) for each sensor + * Returns the current reading from each sensor * - * Returns the current (value, state) [each 16bit] of each sensor supported by - * this board, by DMA'ing a sparse array (indexed by the sensor type) into host - * memory. + * Returns a sparse array of sensor readings (indexed by the sensor + * type) into host memory. Each array element is a dword. * * The MC will send a SENSOREVT event every time any sensor changes state. The * driver is responsible for ensuring that it doesn't miss any events. The board @@ -1486,6 +1542,12 @@ #define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4 #define MC_CMD_READ_SENSORS_OUT_LEN 0 +/* Sensor reading fields */ +#define MC_CMD_READ_SENSOR_VALUE_LBN 0 +#define MC_CMD_READ_SENSOR_VALUE_WIDTH 16 +#define MC_CMD_READ_SENSOR_STATE_LBN 16 +#define MC_CMD_READ_SENSOR_STATE_WIDTH 8 + /* MC_CMD_GET_PHY_STATE: * Report current state of PHY. A "zombie" PHY is a PHY that has failed to @@ -1577,4 +1639,98 @@ #define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0 #define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0 + +/* MC_CMD_TEST_ASSERT: + * Deliberately trigger an assert-detonation in the firmware for testing + * purposes (i.e. to allow tests that the driver copes gracefully). + * + * Locks required: None + * Returns: 0 + */ + +#define MC_CMD_TESTASSERT 0x49 +#define MC_CMD_TESTASSERT_IN_LEN 0 +#define MC_CMD_TESTASSERT_OUT_LEN 0 + +/* MC_CMD_WORKAROUND 0x4a + * + * Enable/Disable a given workaround. The mcfw will return EINVAL if it + * doesn't understand the given workaround number - which should not + * be treated as a hard error by client code. + * + * This op does not imply any semantics about each workaround, that's between + * the driver and the mcfw on a per-workaround basis. + * + * Locks required: None + * Returns: 0, EINVAL + */ +#define MC_CMD_WORKAROUND 0x4a +#define MC_CMD_WORKAROUND_IN_LEN 8 +#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0 +#define MC_CMD_WORKAROUND_BUG17230 1 +#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4 +#define MC_CMD_WORKAROUND_OUT_LEN 0 + +/* MC_CMD_GET_PHY_MEDIA_INFO: + * Read media-specific data from PHY (e.g. SFP/SFP+ module ID information for + * SFP+ PHYs). + * + * The "media type" can be found via GET_PHY_CFG (GET_PHY_CFG_OUT_MEDIA_TYPE); + * the valid "page number" input values, and the output data, are interpreted + * on a per-type basis. + * + * For SFP+: PAGE=0 or 1 returns a 128-byte block read from module I2C address + * 0xA0 offset 0 or 0x80. + * Anything else: currently undefined. + * + * Locks required: None + * Return code: 0 + */ +#define MC_CMD_GET_PHY_MEDIA_INFO 0x4b +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4 +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(_num_bytes) (4 + (_num_bytes)) +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 + +/* MC_CMD_NVRAM_TEST: + * Test a particular NVRAM partition for valid contents (where "valid" + * depends on the type of partition). + * + * Locks required: None + * Return code: 0 + */ +#define MC_CMD_NVRAM_TEST 0x4c +#define MC_CMD_NVRAM_TEST_IN_LEN 4 +#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0 +#define MC_CMD_NVRAM_TEST_OUT_LEN 4 +#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0 +#define MC_CMD_NVRAM_TEST_PASS 0 +#define MC_CMD_NVRAM_TEST_FAIL 1 +#define MC_CMD_NVRAM_TEST_NOTSUPP 2 + +/* MC_CMD_MRSFP_TWEAK: (debug) + * Read status and/or set parameters for the "mrsfp" driver in mr_rusty builds. + * I2C I/O expander bits are always read; if equaliser parameters are supplied, + * they are configured first. + * + * Locks required: None + * Return code: 0, EINVAL + */ +#define MC_CMD_MRSFP_TWEAK 0x4d +#define MC_CMD_MRSFP_TWEAK_IN_LEN_READ_ONLY 0 +#define MC_CMD_MRSFP_TWEAK_IN_LEN_EQ_CONFIG 16 +#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_LEVEL_OFST 0 /* 0-6 low->high de-emph. */ +#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_DT_CFG_OFST 4 /* 0-8 low->high ref.V */ +#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_BOOST_OFST 8 /* 0-8 low->high boost */ +#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_DT_CFG_OFST 12 /* 0-8 low->high ref.V */ +#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 /* input bits */ +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 /* output bits */ +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 /* dirs: 0=out, 1=in */ + +/* Do NOT add new commands beyond 0x4f as part of 3.0 : 0x50 - 0x7f will be + * used for post-3.0 extensions. If you run out of space, look for gaps or + * commands that are unused in the existing range. */ + #endif /* MCDI_PCOL_H */ -- cgit v1.2.3 From 8b2103add08b79abd3ac7015b4bac744c0af534e Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 3 Feb 2010 09:30:17 +0000 Subject: sfc: Handle firmware assertion failure while resetting This allows the driver to recover if the MC firmware has crashed due to an assertion failure. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 63 +++++++++++++++++++++++++++++-------------------- drivers/net/sfc/siena.c | 6 +++++ 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 9f035b9f0350..e9f0e5ee4519 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -896,29 +896,27 @@ fail: return rc; } -int efx_mcdi_handle_assertion(struct efx_nic *efx) +static int efx_mcdi_read_assertion(struct efx_nic *efx) { - union { - u8 asserts[MC_CMD_GET_ASSERTS_IN_LEN]; - u8 reboot[MC_CMD_REBOOT_IN_LEN]; - } inbuf; - u8 assertion[MC_CMD_GET_ASSERTS_OUT_LEN]; + u8 inbuf[MC_CMD_GET_ASSERTS_IN_LEN]; + u8 outbuf[MC_CMD_GET_ASSERTS_OUT_LEN]; unsigned int flags, index, ofst; const char *reason; size_t outlen; int retry; int rc; - /* Check if the MC is in the assertion handler, retrying twice. Once + /* Attempt to read any stored assertion state before we reboot + * the mcfw out of the assertion handler. Retry twice, once * because a boot-time assertion might cause this command to fail * with EINTR. And once again because GET_ASSERTS can race with * MC_CMD_REBOOT running on the other port. */ retry = 2; do { - MCDI_SET_DWORD(inbuf.asserts, GET_ASSERTS_IN_CLEAR, 0); + MCDI_SET_DWORD(inbuf, GET_ASSERTS_IN_CLEAR, 1); rc = efx_mcdi_rpc(efx, MC_CMD_GET_ASSERTS, - inbuf.asserts, MC_CMD_GET_ASSERTS_IN_LEN, - assertion, sizeof(assertion), &outlen); + inbuf, MC_CMD_GET_ASSERTS_IN_LEN, + outbuf, sizeof(outbuf), &outlen); } while ((rc == -EINTR || rc == -EIO) && retry-- > 0); if (rc) @@ -926,21 +924,11 @@ int efx_mcdi_handle_assertion(struct efx_nic *efx) if (outlen < MC_CMD_GET_ASSERTS_OUT_LEN) return -EINVAL; - flags = MCDI_DWORD(assertion, GET_ASSERTS_OUT_GLOBAL_FLAGS); + /* Print out any recorded assertion state */ + flags = MCDI_DWORD(outbuf, GET_ASSERTS_OUT_GLOBAL_FLAGS); if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS) return 0; - /* Reset the hardware atomically such that only one port with succeed. - * This command will succeed if a reboot is no longer required (because - * the other port did it first), but fail with EIO if it succeeds. - */ - BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0); - MCDI_SET_DWORD(inbuf.reboot, REBOOT_IN_FLAGS, - MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); - efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf.reboot, MC_CMD_REBOOT_IN_LEN, - NULL, 0, NULL); - - /* Print out the assertion */ reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL) ? "system-level assertion" : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL) @@ -949,20 +937,45 @@ int efx_mcdi_handle_assertion(struct efx_nic *efx) ? "watchdog reset" : "unknown assertion"; EFX_ERR(efx, "MCPU %s at PC = 0x%.8x in thread 0x%.8x\n", reason, - MCDI_DWORD(assertion, GET_ASSERTS_OUT_SAVED_PC_OFFS), - MCDI_DWORD(assertion, GET_ASSERTS_OUT_THREAD_OFFS)); + MCDI_DWORD(outbuf, GET_ASSERTS_OUT_SAVED_PC_OFFS), + MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS)); /* Print out the registers */ ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST; for (index = 1; index < 32; index++) { EFX_ERR(efx, "R%.2d (?): 0x%.8x\n", index, - MCDI_DWORD2(assertion, ofst)); + MCDI_DWORD2(outbuf, ofst)); ofst += sizeof(efx_dword_t); } return 0; } +static void efx_mcdi_exit_assertion(struct efx_nic *efx) +{ + u8 inbuf[MC_CMD_REBOOT_IN_LEN]; + + /* Atomically reboot the mcfw out of the assertion handler */ + BUILD_BUG_ON(MC_CMD_REBOOT_OUT_LEN != 0); + MCDI_SET_DWORD(inbuf, REBOOT_IN_FLAGS, + MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION); + efx_mcdi_rpc(efx, MC_CMD_REBOOT, inbuf, MC_CMD_REBOOT_IN_LEN, + NULL, 0, NULL); +} + +int efx_mcdi_handle_assertion(struct efx_nic *efx) +{ + int rc; + + rc = efx_mcdi_read_assertion(efx); + if (rc) + return rc; + + efx_mcdi_exit_assertion(efx); + + return 0; +} + void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) { u8 inbuf[MC_CMD_SET_ID_LED_IN_LEN]; diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index f8c6771e66d8..0e4c13abf087 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -181,6 +181,12 @@ static int siena_test_registers(struct efx_nic *efx) static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) { + int rc; + + /* Recover from a failed assertion pre-reset */ + rc = efx_mcdi_handle_assertion(efx); + if (rc) + return rc; if (method == RESET_TYPE_WORLD) return efx_mcdi_reset_mc(efx); -- cgit v1.2.3 From 7a6b8f6f7f74085a1330b0f9765d81bcea8c58b7 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 3 Feb 2010 09:30:38 +0000 Subject: sfc: Enable autonegotiated flow-control by default if supported Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 2 ++ drivers/net/sfc/mcdi_phy.c | 14 +++++++++++++- drivers/net/sfc/siena.c | 7 +------ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 9d009c46e962..1e7858511e35 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -909,6 +909,8 @@ static int falcon_probe_port(struct efx_nic *efx) efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; else efx->wanted_fc = EFX_FC_RX; + if (efx->mdio.mmds & MDIO_DEVS_AN) + efx->wanted_fc |= EFX_FC_AUTO; /* Allocate buffer for stats */ rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer, diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index eb694af7a473..d87e74d3994e 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -381,6 +381,18 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx) * but by convention we don't */ efx->loopback_modes &= ~(1 << LOOPBACK_NONE); + /* Set the initial link mode */ + efx_mcdi_phy_decode_link( + efx, &efx->link_state, + MCDI_DWORD(outbuf, GET_LINK_OUT_LINK_SPEED), + MCDI_DWORD(outbuf, GET_LINK_OUT_FLAGS), + MCDI_DWORD(outbuf, GET_LINK_OUT_FCNTL)); + + /* Default to Autonegotiated flow control if the PHY supports it */ + efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; + if (phy_data->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) + efx->wanted_fc |= EFX_FC_AUTO; + return 0; fail: @@ -436,7 +448,7 @@ void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa) /* The link partner capabilities are only relevent if the * link supports flow control autonegotiation */ - if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN)) + if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) return; /* If flow control autoneg is supported and enabled, then fine */ diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 0e4c13abf087..f6a53895ff27 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -106,16 +106,11 @@ static int siena_probe_port(struct efx_nic *efx) efx->mdio.mdio_read = siena_mdio_read; efx->mdio.mdio_write = siena_mdio_write; - /* Fill out MDIO structure and loopback modes */ + /* Fill out MDIO structure, loopback modes, and initial link state */ rc = efx->phy_op->probe(efx); if (rc != 0) return rc; - /* Initial assumption */ - efx->link_state.speed = 10000; - efx->link_state.fd = true; - efx->wanted_fc = EFX_FC_RX | EFX_FC_TX; - /* Allocate buffer for stats */ rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer, MC_CMD_MAC_NSTATS * sizeof(u64)); -- cgit v1.2.3 From 4f16c0739145476ba37a7fa9eea0c33850efc2ce Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:30:50 +0000 Subject: sfc: Replace PHY MDIO test with an 'alive' test SFC9000-family boards do not all use MDIO PHYs, so we need a different test for PHY aliveness. Introduce a PHY operation test_alive(). For PHYs attached to Falcon, use a common implementation based on the existing PHY MDIO test. For PHYs managed through MCDI, use the appropriate MCDI request. Change test name in ethtool from 'core mdio' to 'phy alive'. Rename test_results::mdio to phy_alive and test_results::phy to phy_ext. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/ethtool.c | 6 +++--- drivers/net/sfc/mcdi_phy.c | 22 ++++++++++++++++++++++ drivers/net/sfc/mdio_10g.c | 24 ++++++++++++++++++++++++ drivers/net/sfc/mdio_10g.h | 3 +++ drivers/net/sfc/net_driver.h | 4 +++- drivers/net/sfc/qt202x_phy.c | 1 + drivers/net/sfc/selftest.c | 40 ++++++---------------------------------- drivers/net/sfc/selftest.h | 4 ++-- drivers/net/sfc/tenxpress.c | 2 ++ 9 files changed, 66 insertions(+), 40 deletions(-) diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 6c0bbed8c477..635c4205b4fb 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -342,8 +342,8 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, unsigned int n = 0, i; enum efx_loopback_mode mode; - efx_fill_test(n++, strings, data, &tests->mdio, - "core", 0, "mdio", NULL); + efx_fill_test(n++, strings, data, &tests->phy_alive, + "phy", 0, "alive", NULL); efx_fill_test(n++, strings, data, &tests->nvram, "core", 0, "nvram", NULL); efx_fill_test(n++, strings, data, &tests->interrupt, @@ -379,7 +379,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx, if (name == NULL) break; - efx_fill_test(n++, strings, data, &tests->phy[i], + efx_fill_test(n++, strings, data, &tests->phy_ext[i], "phy", 0, name, NULL); } } diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index d87e74d3994e..34c22fa986e2 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c @@ -572,6 +572,27 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec return 0; } +static int efx_mcdi_phy_test_alive(struct efx_nic *efx) +{ + u8 outbuf[MC_CMD_GET_PHY_STATE_OUT_LEN]; + size_t outlen; + int rc; + + BUILD_BUG_ON(MC_CMD_GET_PHY_STATE_IN_LEN != 0); + + rc = efx_mcdi_rpc(efx, MC_CMD_GET_PHY_STATE, NULL, 0, + outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + + if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN) + return -EMSGSIZE; + if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK) + return -EINVAL; + + return 0; +} + struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, .init = efx_port_dummy_op_int, @@ -581,6 +602,7 @@ struct efx_phy_operations efx_mcdi_phy_ops = { .remove = efx_mcdi_phy_remove, .get_settings = efx_mcdi_phy_get_settings, .set_settings = efx_mcdi_phy_set_settings, + .test_alive = efx_mcdi_phy_test_alive, .run_tests = NULL, .test_name = NULL, }; diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index 1574e52f0594..0548fcbbdcd0 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -335,3 +335,27 @@ enum efx_fc_type efx_mdio_get_pause(struct efx_nic *efx) mii_advertise_flowctrl(efx->wanted_fc), efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_LPA)); } + +int efx_mdio_test_alive(struct efx_nic *efx) +{ + int rc; + int devad = __ffs(efx->mdio.mmds); + u16 physid1, physid2; + + mutex_lock(&efx->mac_lock); + + physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); + physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); + + if ((physid1 == 0x0000) || (physid1 == 0xffff) || + (physid2 == 0x0000) || (physid2 == 0xffff)) { + EFX_ERR(efx, "no MDIO PHY present with ID %d\n", + efx->mdio.prtad); + rc = -EINVAL; + } else { + rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0); + } + + mutex_unlock(&efx->mac_lock); + return rc; +} diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index f6ac9503339d..f89e71929603 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -106,4 +106,7 @@ efx_mdio_set_flag(struct efx_nic *efx, int devad, int addr, mdio_set_flag(&efx->mdio, efx->mdio.prtad, devad, addr, mask, state); } +/* Liveness self-test for MDIO PHYs */ +extern int efx_mdio_test_alive(struct efx_nic *efx); + #endif /* EFX_MDIO_10G_H */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index d5aab5b3fa06..8f951e4f15be 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -516,8 +516,9 @@ struct efx_mac_operations { * @set_settings: Set ethtool settings. Serialised by the mac_lock. * @set_npage_adv: Set abilities advertised in (Extended) Next Page * (only needed where AN bit is set in mmds) + * @test_alive: Test that PHY is 'alive' (online) * @test_name: Get the name of a PHY-specific test/result - * @run_tests: Run tests and record results as appropriate. + * @run_tests: Run tests and record results as appropriate (offline). * Flags are the ethtool tests flags. */ struct efx_phy_operations { @@ -532,6 +533,7 @@ struct efx_phy_operations { int (*set_settings) (struct efx_nic *efx, struct ethtool_cmd *ecmd); void (*set_npage_adv) (struct efx_nic *efx, u32); + int (*test_alive) (struct efx_nic *efx); const char *(*test_name) (struct efx_nic *efx, unsigned int index); int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags); }; diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index e0d13a451019..14793d8bd661 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -445,4 +445,5 @@ struct efx_phy_operations falcon_qt202x_phy_ops = { .remove = qt202x_phy_remove, .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, + .test_alive = efx_mdio_test_alive, }; diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 250c8827b842..8a5a7b6d042d 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -26,7 +26,6 @@ #include "workarounds.h" #include "spi.h" #include "io.h" -#include "mdio_10g.h" /* * Loopback test packet structure @@ -76,42 +75,15 @@ struct efx_loopback_state { * **************************************************************************/ -static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) +static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; - int devad; - u16 physid1, physid2; - - if (efx->mdio.mode_support & MDIO_SUPPORTS_C45) - devad = __ffs(efx->mdio.mmds); - else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22) - devad = MDIO_DEVAD_NONE; - else - return 0; - - mutex_lock(&efx->mac_lock); - tests->mdio = -1; - - physid1 = efx_mdio_read(efx, devad, MDIO_DEVID1); - physid2 = efx_mdio_read(efx, devad, MDIO_DEVID2); - if ((physid1 == 0x0000) || (physid1 == 0xffff) || - (physid2 == 0x0000) || (physid2 == 0xffff)) { - EFX_ERR(efx, "no MDIO PHY present with ID %d\n", - efx->mdio.prtad); - rc = -EINVAL; - goto out; + if (efx->phy_op->test_alive) { + rc = efx->phy_op->test_alive(efx); + tests->phy_alive = rc ? -1 : 1; } - if (EFX_IS10G(efx)) { - rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0); - if (rc) - goto out; - } - -out: - mutex_unlock(&efx->mac_lock); - tests->mdio = rc ? -1 : 1; return rc; } @@ -258,7 +230,7 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests, return 0; mutex_lock(&efx->mac_lock); - rc = efx->phy_op->run_tests(efx, tests->phy, flags); + rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags); mutex_unlock(&efx->mac_lock); return rc; } @@ -684,7 +656,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Online (i.e. non-disruptive) testing * This checks interrupt generation, event delivery and PHY presence. */ - rc = efx_test_mdio(efx, tests); + rc = efx_test_phy_alive(efx, tests); if (rc && !rc_test) rc_test = rc; diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h index f6feee04c96b..643bef72b99d 100644 --- a/drivers/net/sfc/selftest.h +++ b/drivers/net/sfc/selftest.h @@ -32,7 +32,7 @@ struct efx_loopback_self_tests { */ struct efx_self_tests { /* online tests */ - int mdio; + int phy_alive; int nvram; int interrupt; int eventq_dma[EFX_MAX_CHANNELS]; @@ -40,7 +40,7 @@ struct efx_self_tests { int eventq_poll[EFX_MAX_CHANNELS]; /* offline tests */ int registers; - int phy[EFX_MAX_PHY_TESTS]; + int phy_ext[EFX_MAX_PHY_TESTS]; struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1]; }; diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 3009c297c135..10db071bd837 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -842,6 +842,7 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { .get_settings = tenxpress_get_settings, .set_settings = tenxpress_set_settings, .set_npage_adv = sfx7101_set_npage_adv, + .test_alive = efx_mdio_test_alive, .test_name = sfx7101_test_name, .run_tests = sfx7101_run_tests, }; @@ -856,6 +857,7 @@ struct efx_phy_operations falcon_sft9001_phy_ops = { .get_settings = tenxpress_get_settings, .set_settings = tenxpress_set_settings, .set_npage_adv = sft9001_set_npage_adv, + .test_alive = efx_mdio_test_alive, .test_name = sft9001_test_name, .run_tests = sft9001_run_tests, }; -- cgit v1.2.3 From 2e803407400efe592e5294993a5b1e8251f6dd49 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:31:01 +0000 Subject: sfc: Implement NVRAM selftest for SFC9000 family Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/sfc/mcdi.h | 1 + drivers/net/sfc/siena.c | 1 + 3 files changed, 48 insertions(+) diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index e9f0e5ee4519..86610db2cff5 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -896,6 +896,52 @@ fail: return rc; } +static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type) +{ + u8 inbuf[MC_CMD_NVRAM_TEST_IN_LEN]; + u8 outbuf[MC_CMD_NVRAM_TEST_OUT_LEN]; + int rc; + + MCDI_SET_DWORD(inbuf, NVRAM_TEST_IN_TYPE, type); + + rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_TEST, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), NULL); + if (rc) + return rc; + + switch (MCDI_DWORD(outbuf, NVRAM_TEST_OUT_RESULT)) { + case MC_CMD_NVRAM_TEST_PASS: + case MC_CMD_NVRAM_TEST_NOTSUPP: + return 0; + default: + return -EIO; + } +} + +int efx_mcdi_nvram_test_all(struct efx_nic *efx) +{ + u32 nvram_types; + unsigned int type; + int rc; + + rc = efx_mcdi_nvram_types(efx, &nvram_types); + if (rc) + return rc; + + type = 0; + while (nvram_types != 0) { + if (nvram_types & 1) { + rc = efx_mcdi_nvram_test(efx, type); + if (rc) + return rc; + } + type++; + nvram_types >>= 1; + } + + return 0; +} + static int efx_mcdi_read_assertion(struct efx_nic *efx) { u8 inbuf[MC_CMD_GET_ASSERTS_IN_LEN]; diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h index 10ce98f4c0fb..f1f89ad4075a 100644 --- a/drivers/net/sfc/mcdi.h +++ b/drivers/net/sfc/mcdi.h @@ -116,6 +116,7 @@ extern int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type, loff_t offset, size_t length); extern int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type); +extern int efx_mcdi_nvram_test_all(struct efx_nic *efx); extern int efx_mcdi_handle_assertion(struct efx_nic *efx); extern void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); extern int efx_mcdi_reset_port(struct efx_nic *efx); diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index f6a53895ff27..8e1311284718 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -583,6 +583,7 @@ struct efx_nic_type siena_a0_nic_type = { .set_wol = siena_set_wol, .resume_wol = siena_init_wol, .test_registers = siena_test_registers, + .test_nvram = efx_mcdi_nvram_test_all, .default_mac_ops = &efx_mcdi_mac_operations, .revision = EFX_REV_SIENA_A0, -- cgit v1.2.3 From c91f48d61c5b6fb36a6fc50de923db4db009b0dc Mon Sep 17 00:00:00 2001 From: Guido Barzini Date: Wed, 3 Feb 2010 09:31:24 +0000 Subject: sfc: Survive ISR0=0 bug in the shared IRQ case Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/nic.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index db44224ed2ca..8d9696a38edf 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -1384,6 +1384,15 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx->last_irq_cpu = raw_smp_processor_id(); EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); + } else if (EFX_WORKAROUND_15783(efx)) { + /* We can't return IRQ_HANDLED more than once on seeing ISR0=0 + * because this might be a shared interrupt, but we do need to + * check the channel every time and preemptively rearm it if + * it's idle. */ + efx_for_each_channel(channel, efx) { + if (!channel->work_pending) + efx_nic_eventq_read_ack(channel); + } } return result; -- cgit v1.2.3 From 4cddca5484e047fa77ce090bec96fbfb92a6eb19 Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 3 Feb 2010 09:31:40 +0000 Subject: sfc: Add some missing bits to register self-test masks Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 2 +- drivers/net/sfc/siena.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 1e7858511e35..f63a32cc9d24 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1008,7 +1008,7 @@ static int falcon_test_nvram(struct efx_nic *efx) static const struct efx_nic_register_test falcon_b0_register_tests[] = { { FR_AZ_ADR_REGION, - EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) }, + EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) }, { FR_AZ_RX_CFG, EFX_OWORD32(0xFFFFFFFE, 0x00017FFF, 0x00000000, 0x00000000) }, { FR_AZ_TX_CFG, diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 8e1311284718..1619fb5a64f5 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -134,7 +134,7 @@ void siena_remove_port(struct efx_nic *efx) static const struct efx_nic_register_test siena_register_tests[] = { { FR_AZ_ADR_REGION, - EFX_OWORD32(0x0001FFFF, 0x0001FFFF, 0x0001FFFF, 0x0001FFFF) }, + EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) }, { FR_CZ_USR_EV_CFG, EFX_OWORD32(0x000103FF, 0x00000000, 0x00000000, 0x00000000) }, { FR_AZ_RX_CFG, -- cgit v1.2.3 From 2291b20f4bee6a28087cf4f4b2b382a92063c8b5 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:31:46 +0000 Subject: sfc: Remove declarations of nonexistent functions Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index a615ac051530..7eff0a615cb3 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -79,8 +79,6 @@ extern int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok); /* Global */ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); -extern void efx_suspend(struct efx_nic *efx); -extern void efx_resume(struct efx_nic *efx); extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, bool rx_adaptive); extern int efx_request_power(struct efx_nic *efx, int mw, const char *name); -- cgit v1.2.3 From 754c653a4e62bfa19b4e015c45198863c4211947 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:31:57 +0000 Subject: sfc: Fix some incorrect or redundant comments In particular, the comment about EVQ_RPTR_REG is based on inconsistent preliminary hardware documentation, though the following code was fixed long before release. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/ethtool.c | 4 ++-- drivers/net/sfc/falcon.c | 2 +- drivers/net/sfc/net_driver.h | 12 ++++-------- drivers/net/sfc/nic.c | 4 ---- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 635c4205b4fb..d9f9c02a928e 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -196,7 +196,7 @@ int efx_ethtool_get_settings(struct net_device *net_dev, efx->phy_op->get_settings(efx, ecmd); mutex_unlock(&efx->mac_lock); - /* Falcon GMAC does not support 1000Mbps HD */ + /* GMAC does not support 1000Mbps HD */ ecmd->supported &= ~SUPPORTED_1000baseT_Half; /* Both MACs support pause frames (bidirectional and respond-only) */ ecmd->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; @@ -216,7 +216,7 @@ int efx_ethtool_set_settings(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); int rc; - /* Falcon GMAC does not support 1000Mbps HD */ + /* GMAC does not support 1000Mbps HD */ if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) { EFX_LOG(efx, "rejecting unsupported 1000Mbps HD" " setting\n"); diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index f63a32cc9d24..1b8d83657aaa 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1730,7 +1730,7 @@ static int falcon_set_wol(struct efx_nic *efx, u32 type) /************************************************************************** * - * Revision-dependent attributes used by efx.c + * Revision-dependent attributes used by efx.c and nic.c * ************************************************************************** */ diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 8f951e4f15be..ac77a252c7e2 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -101,9 +101,6 @@ do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0) * Special buffers are used for the event queues and the TX and RX * descriptor queues for each channel. They are *not* used for the * actual transmit and receive buffers. - * - * Note that for Falcon, TX and RX descriptor queues live in host memory. - * Allocation and freeing procedures must take this into account. */ struct efx_special_buffer { void *addr; @@ -300,7 +297,7 @@ struct efx_rx_queue { * @dma_addr: DMA base address of the buffer * @len: Buffer length, in bytes * - * Falcon uses these buffers for its interrupt status registers and + * The NIC uses these buffers for its interrupt status registers and * MAC stats dumps. */ struct efx_buffer { @@ -674,7 +671,7 @@ union efx_multicast_hash { * @irq_status: Interrupt status buffer * @last_irq_cpu: Last CPU to handle interrupt. * This register is written with the SMP processor ID whenever an - * interrupt is handled. It is used by falcon_test_interrupt() + * interrupt is handled. It is used by efx_nic_test_interrupt() * to verify that an interrupt has occurred. * @spi_flash: SPI flash device * This field will be %NULL if no flash device is present (or for Siena). @@ -723,8 +720,7 @@ union efx_multicast_hash { * @loopback_modes: Supported loopback mode bitmask * @loopback_selftest: Offline self-test private state * - * The @priv field of the corresponding &struct net_device points to - * this. + * This is stored in the private area of the &struct net_device. */ struct efx_nic { char name[IFNAMSIZ]; @@ -997,7 +993,7 @@ static inline void clear_bit_le(unsigned nr, unsigned char *addr) * that the net driver will program into the MAC as the maximum frame * length. * - * The 10G MAC used in Falcon requires 8-byte alignment on the frame + * The 10G MAC requires 8-byte alignment on the frame * length, so we round up to the nearest 8. * * Re-clocking by the XGXS on RX can reduce an IPG to 32 bits (half an diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index 8d9696a38edf..b06f8e348307 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c @@ -623,10 +623,6 @@ void efx_nic_remove_rx(struct efx_rx_queue *rx_queue) * * This writes the EVQ_RPTR_REG register for the specified channel's * event queue. - * - * Note that EVQ_RPTR_REG contains the index of the "last read" event, - * whereas channel->eventq_read_ptr contains the index of the "next to - * read" event. */ void efx_nic_eventq_read_ack(struct efx_channel *channel) { -- cgit v1.2.3 From a4b97f2054af2e411c414ed4cb5e1d0dbfd24a47 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 3 Feb 2010 09:32:06 +0000 Subject: sfc: Do not include unneeded headers Earlier refactoring has made these inclusions unnecessary. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/net_driver.h | 1 - drivers/net/sfc/selftest.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index ac77a252c7e2..cb018e272097 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 8a5a7b6d042d..cf0139a7d9a4 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -24,8 +24,6 @@ #include "nic.h" #include "selftest.h" #include "workarounds.h" -#include "spi.h" -#include "io.h" /* * Loopback test packet structure -- cgit v1.2.3 From 10eec95569513206877769ad9336591c08015cfe Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Wed, 3 Feb 2010 14:23:32 +0000 Subject: ixgbe: only process one ixgbe_watchdog_task at a time. Processing multiple ixgbe_watchdog_task calls may cause the link_up variable and IXGBE_FLAG_NEED_LINK_UPDATE flag to be set incorrectly. In the worse case this is causing the netif_carrier_off to be called inappropriately which results in an interface that can't be brought up. Although schedule_work() will only schedule the task if it is not already on the work queue the WORK_STRUCT_PENDING bits are cleared just before calling the work function. This allows WORK_STRUCT_PENDING to be cleared, the work function to start and meanwhile schedule another task. This patch adds a mutex to the watchdog task. This bug is actualized by changing DCB settings or doing extended cable pull or reset tests. Signed-off-by: John Fastabend Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 17 ++++++++--------- drivers/net/ixgbe/ixgbe_main.c | 13 +++++++++---- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index e576fb4740bc..55a319e3a57a 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -341,15 +341,14 @@ struct ixgbe_adapter { #define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19) #define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20) #define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22) -#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23) -#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 24) -#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 25) -#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 26) -#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 27) -#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 28) -#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 29) -#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 30) -#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 31) +#define IXGBE_FLAG_IN_SFP_LINK_TASK (u32)(1 << 23) +#define IXGBE_FLAG_IN_SFP_MOD_TASK (u32)(1 << 24) +#define IXGBE_FLAG_FDIR_HASH_CAPABLE (u32)(1 << 25) +#define IXGBE_FLAG_FDIR_PERFECT_CAPABLE (u32)(1 << 26) +#define IXGBE_FLAG_FCOE_CAPABLE (u32)(1 << 27) +#define IXGBE_FLAG_FCOE_ENABLED (u32)(1 << 28) +#define IXGBE_FLAG_SRIOV_CAPABLE (u32)(1 << 29) +#define IXGBE_FLAG_SRIOV_ENABLED (u32)(1 << 30) u32 flags2; #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f098816d4199..1ec3cbdf8729 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -4996,6 +4996,8 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work) netif_tx_start_all_queues(adapter->netdev); } +static DEFINE_MUTEX(ixgbe_watchdog_lock); + /** * ixgbe_watchdog_task - worker thread to bring link up * @work: pointer to work_struct containing our data @@ -5007,13 +5009,16 @@ static void ixgbe_watchdog_task(struct work_struct *work) watchdog_task); struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; - u32 link_speed = adapter->link_speed; - bool link_up = adapter->link_up; + u32 link_speed; + bool link_up; int i; struct ixgbe_ring *tx_ring; int some_tx_pending = 0; - adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; + mutex_lock(&ixgbe_watchdog_lock); + + link_up = adapter->link_up; + link_speed = adapter->link_speed; if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE) { hw->mac.ops.check_link(hw, &link_speed, &link_up, false); @@ -5102,7 +5107,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) } ixgbe_update_stats(adapter); - adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK; + mutex_unlock(&ixgbe_watchdog_lock); } static int ixgbe_tso(struct ixgbe_adapter *adapter, -- cgit v1.2.3 From b548192acaebcb05d6a87d1e94f19835b1a18a8b Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 3 Feb 2010 14:49:28 +0000 Subject: e1000: Report link status in ethtool when interface is down With this change ethtool will correctly report link status when the interface is down. Currently ethtool reports the link as not detected when the interface is down. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000.h | 1 + drivers/net/e1000/e1000_ethtool.c | 19 ++++++++++++++++++- drivers/net/e1000/e1000_main.c | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index e8932db7ee77..9902b33b7160 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -349,6 +349,7 @@ extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter); extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter); extern void e1000_update_stats(struct e1000_adapter *adapter); +extern bool e1000_has_link(struct e1000_adapter *adapter); extern void e1000_power_up_phy(struct e1000_adapter *); extern void e1000_set_ethtool_ops(struct net_device *netdev); extern void e1000_check_options(struct e1000_adapter *adapter); diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 13e9ece16889..c67e93117271 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -215,6 +215,23 @@ static int e1000_set_settings(struct net_device *netdev, return 0; } +static u32 e1000_get_link(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + /* + * If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly + * stale link state from the driver. + */ + if (!netif_carrier_ok(netdev)) + adapter->hw.get_link_status = 1; + + return e1000_has_link(adapter); +} + static void e1000_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { @@ -1892,7 +1909,7 @@ static const struct ethtool_ops e1000_ethtool_ops = { .get_msglevel = e1000_get_msglevel, .set_msglevel = e1000_set_msglevel, .nway_reset = e1000_nway_reset, - .get_link = ethtool_op_get_link, + .get_link = e1000_get_link, .get_eeprom_len = e1000_get_eeprom_len, .get_eeprom = e1000_get_eeprom, .set_eeprom = e1000_set_eeprom, diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b608528f26fc..4ff50d6fe5e4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2246,7 +2246,7 @@ static void e1000_82547_tx_fifo_stall(unsigned long data) } } -static bool e1000_has_link(struct e1000_adapter *adapter) +bool e1000_has_link(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; bool link_active = false; -- cgit v1.2.3 From dbb5aaebc44ce7f64b12904c58fbc1dd487982a7 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 3 Feb 2010 14:49:48 +0000 Subject: e1000: call pci_save_state after pci_restore_state This patch adds a call to pci_save_state() immediately after the call to pci_restore_state(). Due to a change in the behavior of pci_restore_state() it is necessary to call pci_save_state() to keep the state_saved flag. This patch is based on a similar patch for ixgbe. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4ff50d6fe5e4..3b14dd718ab4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -847,6 +847,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev, goto err_pci_reg; pci_set_master(pdev); + err = pci_save_state(pdev); + if (err) + goto err_alloc_etherdev; err = -ENOMEM; netdev = alloc_etherdev(sizeof(struct e1000_adapter)); @@ -4596,6 +4599,7 @@ static int e1000_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + pci_save_state(pdev); if (adapter->need_ioport) err = pci_enable_device(pdev); -- cgit v1.2.3 From 1a6c14a2c7c313c584f26730e67f062f474bb744 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 3 Feb 2010 14:18:50 +0000 Subject: ixgbe: Allocate driver resources per NUMA node The default policy for the current driver is to do all its memory allocation on whatever processor is running insmod/modprobe. This is less than optimal. This driver's default mode of operation will be to use each node for each subsequent transmit/receive queue. The most efficient allocation will be to then have the interrupts bound in such a way as to match up the interrupt of the queue to the cpu where its memory was allocated. Signed-off-by: Jesse Brandeburg Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 2 ++ drivers/net/ixgbe/ixgbe_main.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 55a319e3a57a..33b79e812b4d 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -399,6 +399,8 @@ struct ixgbe_adapter { u32 wol; u16 eeprom_version; + int node; + /* SR-IOV */ DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); unsigned int num_vfs; diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 1ec3cbdf8729..87e1aa5ba788 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3946,7 +3946,11 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) } for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { - q_vector = kzalloc(sizeof(struct ixgbe_q_vector), GFP_KERNEL); + q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector), + GFP_KERNEL, adapter->node); + if (!q_vector) + q_vector = kzalloc(sizeof(struct ixgbe_q_vector), + GFP_KERNEL); if (!q_vector) goto err_out; q_vector->adapter = adapter; @@ -4246,6 +4250,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) /* enable rx csum by default */ adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; + /* get assigned NUMA node */ + adapter->node = dev_to_node(&pdev->dev); + set_bit(__IXGBE_DOWN, &adapter->state); return 0; @@ -4265,7 +4272,9 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, int size; size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; - tx_ring->tx_buffer_info = vmalloc(size); + tx_ring->tx_buffer_info = vmalloc_node(size, adapter->node); + if (!tx_ring->tx_buffer_info) + tx_ring->tx_buffer_info = vmalloc(size); if (!tx_ring->tx_buffer_info) goto err; memset(tx_ring->tx_buffer_info, 0, size); @@ -4305,8 +4314,15 @@ err: static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; + int orig_node = adapter->node; for (i = 0; i < adapter->num_tx_queues; i++) { + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); if (!err) continue; @@ -4314,6 +4330,9 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) break; } + /* reset the node back to its starting value */ + adapter->node = orig_node; + return err; } @@ -4331,7 +4350,9 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, int size; size = sizeof(struct ixgbe_rx_buffer) * rx_ring->count; - rx_ring->rx_buffer_info = vmalloc(size); + rx_ring->rx_buffer_info = vmalloc_node(size, adapter->node); + if (!rx_ring->rx_buffer_info) + rx_ring->rx_buffer_info = vmalloc(size); if (!rx_ring->rx_buffer_info) { DPRINTK(PROBE, ERR, "vmalloc allocation failed for the rx desc ring\n"); @@ -4375,8 +4396,15 @@ alloc_failed: static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; + int orig_node = adapter->node; for (i = 0; i < adapter->num_rx_queues; i++) { + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); if (!err) continue; @@ -4384,6 +4412,9 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) break; } + /* reset the node back to its starting value */ + adapter->node = orig_node; + return err; } -- cgit v1.2.3 From 4a0b9ca015bae64df7d97c9e0a1d33159b36e69f Mon Sep 17 00:00:00 2001 From: PJ Waskiewicz Date: Wed, 3 Feb 2010 14:19:12 +0000 Subject: ixgbe: Make descriptor ring allocations NUMA-aware This patch allocates the ring structures themselves on each NUMA node along with the buffer_info structures. This way we don't allocate the entire ring memory on a single node in one big block, thus reducing NUMA node memory crosstalk. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 5 +- drivers/net/ixgbe/ixgbe_ethtool.c | 71 +++++----- drivers/net/ixgbe/ixgbe_fcoe.c | 4 +- drivers/net/ixgbe/ixgbe_main.c | 276 ++++++++++++++++++++------------------ 4 files changed, 189 insertions(+), 167 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 33b79e812b4d..bffbe0d52d33 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -175,6 +175,7 @@ struct ixgbe_ring { struct ixgbe_queue_stats stats; unsigned long reinit_state; + int numa_node; u64 rsc_count; /* stat for coalesced packets */ u64 rsc_flush; /* stats for flushed packets */ u32 restart_queue; /* track tx queue restarts */ @@ -293,7 +294,7 @@ struct ixgbe_adapter { u16 eitr_high; /* TX */ - struct ixgbe_ring *tx_ring ____cacheline_aligned_in_smp; /* One per active queue */ + struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; int num_tx_queues; u32 tx_timeout_count; bool detect_tx_hung; @@ -302,7 +303,7 @@ struct ixgbe_adapter { u64 lsc_int; /* RX */ - struct ixgbe_ring *rx_ring ____cacheline_aligned_in_smp; /* One per active queue */ + struct ixgbe_ring *rx_ring[MAX_RX_QUEUES] ____cacheline_aligned_in_smp; int num_rx_queues; int num_rx_pools; /* == num_rx_queues in 82598 */ int num_rx_queues_per_pool; /* 1 if 82598, can be many if 82599 */ diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 1525c86cbccf..07a9410c08d4 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -834,8 +834,8 @@ static void ixgbe_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct ixgbe_adapter *adapter = netdev_priv(netdev); - struct ixgbe_ring *tx_ring = adapter->tx_ring; - struct ixgbe_ring *rx_ring = adapter->rx_ring; + struct ixgbe_ring *tx_ring = adapter->tx_ring[0]; + struct ixgbe_ring *rx_ring = adapter->rx_ring[0]; ring->rx_max_pending = IXGBE_MAX_RXD; ring->tx_max_pending = IXGBE_MAX_TXD; @@ -867,8 +867,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, new_tx_count = min(new_tx_count, (u32)IXGBE_MAX_TXD); new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); - if ((new_tx_count == adapter->tx_ring->count) && - (new_rx_count == adapter->rx_ring->count)) { + if ((new_tx_count == adapter->tx_ring[0]->count) && + (new_rx_count == adapter->rx_ring[0]->count)) { /* nothing to do */ return 0; } @@ -878,25 +878,24 @@ static int ixgbe_set_ringparam(struct net_device *netdev, if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].count = new_tx_count; + adapter->tx_ring[i]->count = new_tx_count; for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].count = new_rx_count; + adapter->rx_ring[i]->count = new_rx_count; adapter->tx_ring_count = new_tx_count; adapter->rx_ring_count = new_rx_count; - goto err_setup; + goto clear_reset; } - temp_tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); + temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring)); if (!temp_tx_ring) { err = -ENOMEM; - goto err_setup; + goto clear_reset; } if (new_tx_count != adapter->tx_ring_count) { - memcpy(temp_tx_ring, adapter->tx_ring, - adapter->num_tx_queues * sizeof(struct ixgbe_ring)); for (i = 0; i < adapter->num_tx_queues; i++) { + memcpy(&temp_tx_ring[i], adapter->tx_ring[i], + sizeof(struct ixgbe_ring)); temp_tx_ring[i].count = new_tx_count; err = ixgbe_setup_tx_resources(adapter, &temp_tx_ring[i]); @@ -904,28 +903,24 @@ static int ixgbe_set_ringparam(struct net_device *netdev, while (i) { i--; ixgbe_free_tx_resources(adapter, - &temp_tx_ring[i]); + &temp_tx_ring[i]); } - goto err_setup; + goto clear_reset; } } need_update = true; } - temp_rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); - if ((!temp_rx_ring) && (need_update)) { - for (i = 0; i < adapter->num_tx_queues; i++) - ixgbe_free_tx_resources(adapter, &temp_tx_ring[i]); - kfree(temp_tx_ring); + temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring)); + if (!temp_rx_ring) { err = -ENOMEM; goto err_setup; } if (new_rx_count != adapter->rx_ring_count) { - memcpy(temp_rx_ring, adapter->rx_ring, - adapter->num_rx_queues * sizeof(struct ixgbe_ring)); for (i = 0; i < adapter->num_rx_queues; i++) { + memcpy(&temp_rx_ring[i], adapter->rx_ring[i], + sizeof(struct ixgbe_ring)); temp_rx_ring[i].count = new_rx_count; err = ixgbe_setup_rx_resources(adapter, &temp_rx_ring[i]); @@ -947,22 +942,32 @@ static int ixgbe_set_ringparam(struct net_device *netdev, /* tx */ if (new_tx_count != adapter->tx_ring_count) { - kfree(adapter->tx_ring); - adapter->tx_ring = temp_tx_ring; - temp_tx_ring = NULL; + for (i = 0; i < adapter->num_tx_queues; i++) { + ixgbe_free_tx_resources(adapter, + adapter->tx_ring[i]); + memcpy(adapter->tx_ring[i], &temp_tx_ring[i], + sizeof(struct ixgbe_ring)); + } adapter->tx_ring_count = new_tx_count; } /* rx */ if (new_rx_count != adapter->rx_ring_count) { - kfree(adapter->rx_ring); - adapter->rx_ring = temp_rx_ring; - temp_rx_ring = NULL; + for (i = 0; i < adapter->num_rx_queues; i++) { + ixgbe_free_rx_resources(adapter, + adapter->rx_ring[i]); + memcpy(adapter->rx_ring[i], &temp_rx_ring[i], + sizeof(struct ixgbe_ring)); + } adapter->rx_ring_count = new_rx_count; } ixgbe_up(adapter); } + + vfree(temp_rx_ring); err_setup: + vfree(temp_tx_ring); +clear_reset: clear_bit(__IXGBE_RESETTING, &adapter->state); return err; } @@ -1007,13 +1012,13 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { - queue_stat = (u64 *)&adapter->tx_ring[j].stats; + queue_stat = (u64 *)&adapter->tx_ring[j]->stats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; i += k; } for (j = 0; j < adapter->num_rx_queues; j++) { - queue_stat = (u64 *)&adapter->rx_ring[j].stats; + queue_stat = (u64 *)&adapter->rx_ring[j]->stats; for (k = 0; k < stat_count; k++) data[i + k] = queue_stat[k]; i += k; @@ -1627,7 +1632,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter) reg_data |= IXGBE_RXDCTL_ENABLE; IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(0), reg_data); if (adapter->hw.mac.type == ixgbe_mac_82599EB) { - int j = adapter->rx_ring[0].reg_idx; + int j = adapter->rx_ring[0]->reg_idx; u32 k; for (k = 0; k < 10; k++) { if (IXGBE_READ_REG(&adapter->hw, @@ -2011,7 +2016,7 @@ static int ixgbe_get_coalesce(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); - ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0].work_limit; + ec->tx_max_coalesced_frames_irq = adapter->tx_ring[0]->work_limit; /* only valid if in constant ITR mode */ switch (adapter->rx_itr_setting) { @@ -2064,7 +2069,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, return -EINVAL; if (ec->tx_max_coalesced_frames_irq) - adapter->tx_ring[0].work_limit = ec->tx_max_coalesced_frames_irq; + adapter->tx_ring[0]->work_limit = ec->tx_max_coalesced_frames_irq; if (ec->rx_coalesce_usecs > 1) { /* check the limits */ diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index e9a20c88c155..4123dec0dfb7 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -525,7 +525,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) for (i = 0; i < IXGBE_FCRETA_SIZE; i++) { fcoe_i = f->mask + i % f->indices; fcoe_i &= IXGBE_FCRETA_ENTRY_MASK; - fcoe_q = adapter->rx_ring[fcoe_i].reg_idx; + fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_FCRETA(i), fcoe_q); } IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, IXGBE_FCRECTL_ENA); @@ -533,7 +533,7 @@ void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter) } else { /* Use single rx queue for FCoE */ fcoe_i = f->mask; - fcoe_q = adapter->rx_ring[fcoe_i].reg_idx; + fcoe_q = adapter->rx_ring[fcoe_i]->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_FCRECTL, 0); IXGBE_WRITE_REG(hw, IXGBE_ETQS(IXGBE_ETQF_FILTER_FCOE), IXGBE_ETQS_QUEUE_EN | diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 87e1aa5ba788..2a3c8315e357 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -494,7 +494,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, { u32 rxctrl; int cpu = get_cpu(); - int q = rx_ring - adapter->rx_ring; + int q = rx_ring->reg_idx; if (rx_ring->cpu != cpu) { rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q)); @@ -522,7 +522,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, { u32 txctrl; int cpu = get_cpu(); - int q = tx_ring - adapter->tx_ring; + int q = tx_ring->reg_idx; struct ixgbe_hw *hw = &adapter->hw; if (tx_ring->cpu != cpu) { @@ -556,12 +556,12 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); for (i = 0; i < adapter->num_tx_queues; i++) { - adapter->tx_ring[i].cpu = -1; - ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]); + adapter->tx_ring[i]->cpu = -1; + ixgbe_update_tx_dca(adapter, adapter->tx_ring[i]); } for (i = 0; i < adapter->num_rx_queues; i++) { - adapter->rx_ring[i].cpu = -1; - ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]); + adapter->rx_ring[i]->cpu = -1; + ixgbe_update_rx_dca(adapter, adapter->rx_ring[i]); } } @@ -1032,7 +1032,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - j = adapter->rx_ring[r_idx].reg_idx; + j = adapter->rx_ring[r_idx]->reg_idx; ixgbe_set_ivar(adapter, 0, j, v_idx); r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, @@ -1042,7 +1042,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - j = adapter->tx_ring[r_idx].reg_idx; + j = adapter->tx_ring[r_idx]->reg_idx; ixgbe_set_ivar(adapter, 1, j, v_idx); r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, @@ -1182,7 +1182,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - tx_ring = &(adapter->tx_ring[r_idx]); + tx_ring = adapter->tx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, q_vector->tx_itr, tx_ring->total_packets, @@ -1197,7 +1197,7 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring = adapter->rx_ring[r_idx]; ret_itr = ixgbe_update_itr(adapter, q_vector->eitr, q_vector->rx_itr, rx_ring->total_packets, @@ -1319,7 +1319,7 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) netif_tx_stop_all_queues(netdev); for (i = 0; i < adapter->num_tx_queues; i++) { struct ixgbe_ring *tx_ring = - &adapter->tx_ring[i]; + adapter->tx_ring[i]; if (test_and_clear_bit(__IXGBE_FDIR_INIT_DONE, &tx_ring->reinit_state)) schedule_work(&adapter->fdir_reinit_task); @@ -1378,7 +1378,7 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - tx_ring = &(adapter->tx_ring[r_idx]); + tx_ring = adapter->tx_ring[r_idx]; tx_ring->total_bytes = 0; tx_ring->total_packets = 0; r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, @@ -1406,7 +1406,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring = adapter->rx_ring[r_idx]; rx_ring->total_bytes = 0; rx_ring->total_packets = 0; r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, @@ -1436,7 +1436,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - ring = &(adapter->tx_ring[r_idx]); + ring = adapter->tx_ring[r_idx]; ring->total_bytes = 0; ring->total_packets = 0; r_idx = find_next_bit(q_vector->txr_idx, adapter->num_tx_queues, @@ -1445,7 +1445,7 @@ static irqreturn_t ixgbe_msix_clean_many(int irq, void *data) r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - ring = &(adapter->rx_ring[r_idx]); + ring = adapter->rx_ring[r_idx]; ring->total_bytes = 0; ring->total_packets = 0; r_idx = find_next_bit(q_vector->rxr_idx, adapter->num_rx_queues, @@ -1476,7 +1476,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) long r_idx; r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - rx_ring = &(adapter->rx_ring[r_idx]); + rx_ring = adapter->rx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_rx_dca(adapter, rx_ring); @@ -1517,7 +1517,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); for (i = 0; i < q_vector->txr_count; i++) { - ring = &(adapter->tx_ring[r_idx]); + ring = adapter->tx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_tx_dca(adapter, ring); @@ -1533,7 +1533,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) budget = max(budget, 1); r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); for (i = 0; i < q_vector->rxr_count; i++) { - ring = &(adapter->rx_ring[r_idx]); + ring = adapter->rx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_rx_dca(adapter, ring); @@ -1544,7 +1544,7 @@ static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget) } r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues); - ring = &(adapter->rx_ring[r_idx]); + ring = adapter->rx_ring[r_idx]; /* If all Rx work done, exit the polling mode */ if (work_done < budget) { napi_complete(napi); @@ -1577,7 +1577,7 @@ static int ixgbe_clean_txonly(struct napi_struct *napi, int budget) long r_idx; r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues); - tx_ring = &(adapter->tx_ring[r_idx]); + tx_ring = adapter->tx_ring[r_idx]; #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) ixgbe_update_tx_dca(adapter, tx_ring); @@ -1762,8 +1762,8 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) struct ixgbe_q_vector *q_vector = adapter->q_vector[0]; u8 current_itr; u32 new_itr = q_vector->eitr; - struct ixgbe_ring *rx_ring = &adapter->rx_ring[0]; - struct ixgbe_ring *tx_ring = &adapter->tx_ring[0]; + struct ixgbe_ring *rx_ring = adapter->rx_ring[0]; + struct ixgbe_ring *tx_ring = adapter->tx_ring[0]; q_vector->tx_itr = ixgbe_update_itr(adapter, new_itr, q_vector->tx_itr, @@ -1875,10 +1875,10 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); if (napi_schedule_prep(&(q_vector->napi))) { - adapter->tx_ring[0].total_packets = 0; - adapter->tx_ring[0].total_bytes = 0; - adapter->rx_ring[0].total_packets = 0; - adapter->rx_ring[0].total_bytes = 0; + adapter->tx_ring[0]->total_packets = 0; + adapter->tx_ring[0]->total_bytes = 0; + adapter->rx_ring[0]->total_packets = 0; + adapter->rx_ring[0]->total_bytes = 0; /* would disable interrupts here but EIAM disabled it */ __napi_schedule(&(q_vector->napi)); } @@ -2010,7 +2010,7 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) /* Setup the HW Tx Head and Tail descriptor pointers */ for (i = 0; i < adapter->num_tx_queues; i++) { - struct ixgbe_ring *ring = &adapter->tx_ring[i]; + struct ixgbe_ring *ring = adapter->tx_ring[i]; j = ring->reg_idx; tdba = ring->dma; tdlen = ring->count * sizeof(union ixgbe_adv_tx_desc); @@ -2020,8 +2020,8 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_TDLEN(j), tdlen); IXGBE_WRITE_REG(hw, IXGBE_TDH(j), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(j), 0); - adapter->tx_ring[i].head = IXGBE_TDH(j); - adapter->tx_ring[i].tail = IXGBE_TDT(j); + adapter->tx_ring[i]->head = IXGBE_TDH(j); + adapter->tx_ring[i]->tail = IXGBE_TDT(j); /* * Disable Tx Head Writeback RO bit, since this hoses * bookkeeping if things aren't delivered in order. @@ -2168,7 +2168,7 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter, int index) u32 rscctrl; int rx_buf_len; - rx_ring = &adapter->rx_ring[index]; + rx_ring = adapter->rx_ring[index]; j = rx_ring->reg_idx; rx_buf_len = rx_ring->rx_buf_len; rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j)); @@ -2266,7 +2266,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) #endif IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); - rdlen = adapter->rx_ring[0].count * sizeof(union ixgbe_adv_rx_desc); + rdlen = adapter->rx_ring[0]->count * sizeof(union ixgbe_adv_rx_desc); /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN); @@ -2276,7 +2276,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) { - rx_ring = &adapter->rx_ring[i]; + rx_ring = adapter->rx_ring[i]; rdba = rx_ring->dma; j = rx_ring->reg_idx; IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32))); @@ -2483,7 +2483,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { for (i = 0; i < adapter->num_rx_queues; i++) { u32 ctrl; - j = adapter->rx_ring[i].reg_idx; + j = adapter->rx_ring[i]->reg_idx; ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(j)); ctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(j), ctrl); @@ -2646,7 +2646,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg); for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); /* PThresh workaround for Tx hang with DFP enabled. */ txdctl |= 32; @@ -2663,7 +2663,7 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter) vlnctrl &= ~IXGBE_VLNCTRL_CFIEN; IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); for (i = 0; i < adapter->num_rx_queues; i++) { - j = adapter->rx_ring[i].reg_idx; + j = adapter->rx_ring[i]->reg_idx; vlnctrl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); vlnctrl |= IXGBE_RXDCTL_VME; IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(j), vlnctrl); @@ -2703,7 +2703,7 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) #endif /* IXGBE_FCOE */ if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) { for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].atr_sample_rate = + adapter->tx_ring[i]->atr_sample_rate = adapter->atr_sample_rate; ixgbe_init_fdir_signature_82599(hw, adapter->fdir_pballoc); } else if (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) { @@ -2713,8 +2713,8 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) ixgbe_configure_tx(adapter); ixgbe_configure_rx(adapter); for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_alloc_rx_buffers(adapter, &adapter->rx_ring[i], - (adapter->rx_ring[i].count - 1)); + ixgbe_alloc_rx_buffers(adapter, adapter->rx_ring[i], + (adapter->rx_ring[i]->count - 1)); } static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw) @@ -2797,7 +2797,7 @@ link_cfg_out: static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, int rxr) { - int j = adapter->rx_ring[rxr].reg_idx; + int j = adapter->rx_ring[rxr]->reg_idx; int k; for (k = 0; k < IXGBE_MAX_RX_DESC_POLL; k++) { @@ -2811,8 +2811,8 @@ static inline void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter, DPRINTK(DRV, ERR, "RXDCTL.ENABLE on Rx queue %d " "not set within the polling period\n", rxr); } - ixgbe_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr], - (adapter->rx_ring[rxr].count - 1)); + ixgbe_release_rx_desc(&adapter->hw, adapter->rx_ring[rxr], + (adapter->rx_ring[rxr]->count - 1)); } static int ixgbe_up_complete(struct ixgbe_adapter *adapter) @@ -2899,7 +2899,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) } for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); /* enable WTHRESH=8 descriptors, to encourage burst writeback */ txdctl |= (8 << 16); @@ -2913,7 +2913,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl); } for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); txdctl |= IXGBE_TXDCTL_ENABLE; IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl); @@ -2932,7 +2932,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) } for (i = 0; i < num_rx_rings; i++) { - j = adapter->rx_ring[i].reg_idx; + j = adapter->rx_ring[i]->reg_idx; rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(j)); /* enable PTHRESH=32 descriptors (half the internal cache) * and HTHRESH=0 descriptors (to minimize latency on fetch), @@ -3006,7 +3006,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) for (i = 0; i < adapter->num_tx_queues; i++) set_bit(__IXGBE_FDIR_INIT_DONE, - &(adapter->tx_ring[i].reinit_state)); + &(adapter->tx_ring[i]->reinit_state)); /* enable transmits */ netif_tx_start_all_queues(netdev); @@ -3177,7 +3177,7 @@ static void ixgbe_clean_all_rx_rings(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - ixgbe_clean_rx_ring(adapter, &adapter->rx_ring[i]); + ixgbe_clean_rx_ring(adapter, adapter->rx_ring[i]); } /** @@ -3189,7 +3189,7 @@ static void ixgbe_clean_all_tx_rings(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - ixgbe_clean_tx_ring(adapter, &adapter->tx_ring[i]); + ixgbe_clean_tx_ring(adapter, adapter->tx_ring[i]); } void ixgbe_down(struct ixgbe_adapter *adapter) @@ -3240,7 +3240,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* disable transmits in the hardware now that interrupts are off */ for (i = 0; i < adapter->num_tx_queues; i++) { - j = adapter->tx_ring[i].reg_idx; + j = adapter->tx_ring[i]->reg_idx; txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j)); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), (txdctl & ~IXGBE_TXDCTL_ENABLE)); @@ -3280,13 +3280,13 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { - ixgbe_update_tx_dca(adapter, adapter->tx_ring); - ixgbe_update_rx_dca(adapter, adapter->rx_ring); + ixgbe_update_tx_dca(adapter, adapter->tx_ring[0]); + ixgbe_update_rx_dca(adapter, adapter->rx_ring[0]); } #endif - tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring); - ixgbe_clean_rx_irq(q_vector, adapter->rx_ring, &work_done, budget); + tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]); + ixgbe_clean_rx_irq(q_vector, adapter->rx_ring[0], &work_done, budget); if (!tx_clean_complete) work_done = budget; @@ -3574,9 +3574,9 @@ static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) { for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].reg_idx = i; + adapter->rx_ring[i]->reg_idx = i; for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].reg_idx = i; + adapter->tx_ring[i]->reg_idx = i; ret = true; } else { ret = false; @@ -3603,8 +3603,8 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) if (adapter->hw.mac.type == ixgbe_mac_82598EB) { /* the number of queues is assumed to be symmetric */ for (i = 0; i < dcb_i; i++) { - adapter->rx_ring[i].reg_idx = i << 3; - adapter->tx_ring[i].reg_idx = i << 2; + adapter->rx_ring[i]->reg_idx = i << 3; + adapter->tx_ring[i]->reg_idx = i << 2; } ret = true; } else if (adapter->hw.mac.type == ixgbe_mac_82599EB) { @@ -3622,18 +3622,18 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) * Rx TC0-TC7 are offset by 16 queues each */ for (i = 0; i < 3; i++) { - adapter->tx_ring[i].reg_idx = i << 5; - adapter->rx_ring[i].reg_idx = i << 4; + adapter->tx_ring[i]->reg_idx = i << 5; + adapter->rx_ring[i]->reg_idx = i << 4; } for ( ; i < 5; i++) { - adapter->tx_ring[i].reg_idx = + adapter->tx_ring[i]->reg_idx = ((i + 2) << 4); - adapter->rx_ring[i].reg_idx = i << 4; + adapter->rx_ring[i]->reg_idx = i << 4; } for ( ; i < dcb_i; i++) { - adapter->tx_ring[i].reg_idx = + adapter->tx_ring[i]->reg_idx = ((i + 8) << 3); - adapter->rx_ring[i].reg_idx = i << 4; + adapter->rx_ring[i]->reg_idx = i << 4; } ret = true; @@ -3646,12 +3646,12 @@ static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter) * * Rx TC0-TC3 are offset by 32 queues each */ - adapter->tx_ring[0].reg_idx = 0; - adapter->tx_ring[1].reg_idx = 64; - adapter->tx_ring[2].reg_idx = 96; - adapter->tx_ring[3].reg_idx = 112; + adapter->tx_ring[0]->reg_idx = 0; + adapter->tx_ring[1]->reg_idx = 64; + adapter->tx_ring[2]->reg_idx = 96; + adapter->tx_ring[3]->reg_idx = 112; for (i = 0 ; i < dcb_i; i++) - adapter->rx_ring[i].reg_idx = i << 5; + adapter->rx_ring[i]->reg_idx = i << 5; ret = true; } else { @@ -3684,9 +3684,9 @@ static bool inline ixgbe_cache_ring_fdir(struct ixgbe_adapter *adapter) ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) || (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))) { for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].reg_idx = i; + adapter->rx_ring[i]->reg_idx = i; for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].reg_idx = i; + adapter->tx_ring[i]->reg_idx = i; ret = true; } @@ -3714,8 +3714,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) ixgbe_cache_ring_dcb(adapter); /* find out queues in TC for FCoE */ - fcoe_rx_i = adapter->rx_ring[fcoe->tc].reg_idx + 1; - fcoe_tx_i = adapter->tx_ring[fcoe->tc].reg_idx + 1; + fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1; + fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1; /* * In 82599, the number of Tx queues for each traffic * class for both 8-TC and 4-TC modes are: @@ -3746,8 +3746,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) fcoe_tx_i = f->mask; } for (i = 0; i < f->indices; i++, fcoe_rx_i++, fcoe_tx_i++) { - adapter->rx_ring[f->mask + i].reg_idx = fcoe_rx_i; - adapter->tx_ring[f->mask + i].reg_idx = fcoe_tx_i; + adapter->rx_ring[f->mask + i]->reg_idx = fcoe_rx_i; + adapter->tx_ring[f->mask + i]->reg_idx = fcoe_tx_i; } ret = true; } @@ -3765,8 +3765,8 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter) */ static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) { - adapter->rx_ring[0].reg_idx = adapter->num_vfs * 2; - adapter->tx_ring[0].reg_idx = adapter->num_vfs * 2; + adapter->rx_ring[0]->reg_idx = adapter->num_vfs * 2; + adapter->tx_ring[0]->reg_idx = adapter->num_vfs * 2; if (adapter->num_vfs) return true; else @@ -3787,8 +3787,8 @@ static inline bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter) static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) { /* start with default case */ - adapter->rx_ring[0].reg_idx = 0; - adapter->tx_ring[0].reg_idx = 0; + adapter->rx_ring[0]->reg_idx = 0; + adapter->tx_ring[0]->reg_idx = 0; if (ixgbe_cache_ring_sriov(adapter)) return; @@ -3821,33 +3821,63 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter) { int i; - - adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); - if (!adapter->tx_ring) - goto err_tx_ring_allocation; - - adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct ixgbe_ring), GFP_KERNEL); - if (!adapter->rx_ring) - goto err_rx_ring_allocation; + int orig_node = adapter->node; for (i = 0; i < adapter->num_tx_queues; i++) { - adapter->tx_ring[i].count = adapter->tx_ring_count; - adapter->tx_ring[i].queue_index = i; + struct ixgbe_ring *ring = adapter->tx_ring[i]; + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } + ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL, + adapter->node); + if (!ring) + ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL); + if (!ring) + goto err_tx_ring_allocation; + ring->count = adapter->tx_ring_count; + ring->queue_index = i; + ring->numa_node = adapter->node; + + adapter->tx_ring[i] = ring; } + /* Restore the adapter's original node */ + adapter->node = orig_node; + for (i = 0; i < adapter->num_rx_queues; i++) { - adapter->rx_ring[i].count = adapter->rx_ring_count; - adapter->rx_ring[i].queue_index = i; + struct ixgbe_ring *ring = adapter->rx_ring[i]; + if (orig_node == -1) { + int cur_node = next_online_node(adapter->node); + if (cur_node == MAX_NUMNODES) + cur_node = first_online_node; + adapter->node = cur_node; + } + ring = kzalloc_node(sizeof(struct ixgbe_ring), GFP_KERNEL, + adapter->node); + if (!ring) + ring = kzalloc(sizeof(struct ixgbe_ring), GFP_KERNEL); + if (!ring) + goto err_rx_ring_allocation; + ring->count = adapter->rx_ring_count; + ring->queue_index = i; + ring->numa_node = adapter->node; + + adapter->rx_ring[i] = ring; } + /* Restore the adapter's original node */ + adapter->node = orig_node; + ixgbe_cache_ring_register(adapter); return 0; err_rx_ring_allocation: - kfree(adapter->tx_ring); + for (i = 0; i < adapter->num_tx_queues; i++) + kfree(adapter->tx_ring[i]); err_tx_ring_allocation: return -ENOMEM; } @@ -4077,10 +4107,16 @@ err_set_interrupt: **/ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) { - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + int i; + + for (i = 0; i < adapter->num_tx_queues; i++) { + kfree(adapter->tx_ring[i]); + adapter->tx_ring[i] = NULL; + } + for (i = 0; i < adapter->num_rx_queues; i++) { + kfree(adapter->rx_ring[i]); + adapter->rx_ring[i] = NULL; + } ixgbe_free_q_vectors(adapter); ixgbe_reset_interrupt_capability(adapter); @@ -4272,7 +4308,7 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, int size; size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; - tx_ring->tx_buffer_info = vmalloc_node(size, adapter->node); + tx_ring->tx_buffer_info = vmalloc_node(size, tx_ring->numa_node); if (!tx_ring->tx_buffer_info) tx_ring->tx_buffer_info = vmalloc(size); if (!tx_ring->tx_buffer_info) @@ -4314,25 +4350,15 @@ err: static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; - int orig_node = adapter->node; for (i = 0; i < adapter->num_tx_queues; i++) { - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } - err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); + err = ixgbe_setup_tx_resources(adapter, adapter->tx_ring[i]); if (!err) continue; DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); break; } - /* reset the node back to its starting value */ - adapter->node = orig_node; - return err; } @@ -4396,25 +4422,15 @@ alloc_failed: static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter) { int i, err = 0; - int orig_node = adapter->node; for (i = 0; i < adapter->num_rx_queues; i++) { - if (orig_node == -1) { - int cur_node = next_online_node(adapter->node); - if (cur_node == MAX_NUMNODES) - cur_node = first_online_node; - adapter->node = cur_node; - } - err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); + err = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]); if (!err) continue; DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); break; } - /* reset the node back to its starting value */ - adapter->node = orig_node; - return err; } @@ -4451,8 +4467,8 @@ static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - if (adapter->tx_ring[i].desc) - ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]); + if (adapter->tx_ring[i]->desc) + ixgbe_free_tx_resources(adapter, adapter->tx_ring[i]); } /** @@ -4488,8 +4504,8 @@ static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - if (adapter->rx_ring[i].desc) - ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]); + if (adapter->rx_ring[i]->desc) + ixgbe_free_rx_resources(adapter, adapter->rx_ring[i]); } /** @@ -4766,8 +4782,8 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) adapter->hw_rx_no_dma_resources += IXGBE_READ_REG(hw, IXGBE_QPRDC(i)); for (i = 0; i < adapter->num_rx_queues; i++) { - rsc_count += adapter->rx_ring[i].rsc_count; - rsc_flush += adapter->rx_ring[i].rsc_flush; + rsc_count += adapter->rx_ring[i]->rsc_count; + rsc_flush += adapter->rx_ring[i]->rsc_flush; } adapter->rsc_total_count = rsc_count; adapter->rsc_total_flush = rsc_flush; @@ -4775,11 +4791,11 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) /* gather some stats to the adapter struct that are per queue */ for (i = 0; i < adapter->num_tx_queues; i++) - restart_queue += adapter->tx_ring[i].restart_queue; + restart_queue += adapter->tx_ring[i]->restart_queue; adapter->restart_queue = restart_queue; for (i = 0; i < adapter->num_rx_queues; i++) - non_eop_descs += adapter->rx_ring[i].non_eop_descs; + non_eop_descs += adapter->rx_ring[i]->non_eop_descs; adapter->non_eop_descs = non_eop_descs; adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); @@ -5018,7 +5034,7 @@ static void ixgbe_fdir_reinit_task(struct work_struct *work) if (ixgbe_reinit_fdir_tables_82599(hw) == 0) { for (i = 0; i < adapter->num_tx_queues; i++) set_bit(__IXGBE_FDIR_INIT_DONE, - &(adapter->tx_ring[i].reinit_state)); + &(adapter->tx_ring[i]->reinit_state)); } else { DPRINTK(PROBE, ERR, "failed to finish FDIR re-initialization, " "ignored adding FDIR ATR filters \n"); @@ -5120,7 +5136,7 @@ static void ixgbe_watchdog_task(struct work_struct *work) if (!netif_carrier_ok(netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) { - tx_ring = &adapter->tx_ring[i]; + tx_ring = adapter->tx_ring[i]; if (tx_ring->next_to_use != tx_ring->next_to_clean) { some_tx_pending = 1; break; @@ -5622,7 +5638,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, } } - tx_ring = &adapter->tx_ring[skb->queue_mapping]; + tx_ring = adapter->tx_ring[skb->queue_mapping]; if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && (skb->protocol == htons(ETH_P_FCOE))) { -- cgit v1.2.3 From a112fd4ce3ed965dfb8dc6791622cb4f25ba3619 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 3 Feb 2010 07:24:11 +0000 Subject: qlge: Move reset from eeh io_resume to slot_reset. Issue asic reset and verify functionality before continuing to the resume call. This allows proper error code to be returned in the case the asic does not recover. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 5be3ae2f5a16..87ec72064158 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4717,6 +4717,12 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; } pci_set_master(pdev); + + if (ql_adapter_reset(qdev)) { + QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + return PCI_ERS_RESULT_RECOVERED; } @@ -4726,8 +4732,6 @@ static void qlge_io_resume(struct pci_dev *pdev) struct ql_adapter *qdev = netdev_priv(ndev); int err = 0; - if (ql_adapter_reset(qdev)) - QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); if (netif_running(ndev)) { err = qlge_open(ndev); if (err) { -- cgit v1.2.3 From 4bbd1a1903639f826215d76af74f4901efc34daa Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 3 Feb 2010 07:24:12 +0000 Subject: qlge: Add check for eeh failure when closing device. Fix crash where resources are freed twice on an eeh recovery failure. If eeh recovery fails we set a flag to indicate to close() that resources have been freed. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 9169c4cf413a..780a38731bcc 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2005,6 +2005,7 @@ enum { QL_SELFTEST = 9, QL_LB_LINK_UP = 10, QL_FRC_COREDUMP = 11, + QL_EEH_FATAL = 12, }; /* link_status bit definitions */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 87ec72064158..7e000295f359 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3929,6 +3929,16 @@ static int qlge_close(struct net_device *ndev) { struct ql_adapter *qdev = netdev_priv(ndev); + /* If we hit pci_channel_io_perm_failure + * failure condition, then we already + * brought the adapter down. + */ + if (test_bit(QL_EEH_FATAL, &qdev->flags)) { + QPRINTK(qdev, DRV, ERR, "EEH fatal did unload.\n"); + clear_bit(QL_EEH_FATAL, &qdev->flags); + return 0; + } + /* * Wait for device to recover from a reset. * (Rarely happens, but possible.) @@ -4677,6 +4687,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, enum pci_channel_state state) { struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); switch (state) { case pci_channel_io_normal: @@ -4690,6 +4701,8 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: dev_err(&pdev->dev, "%s: pci_channel_io_perm_failure.\n", __func__); + ql_eeh_close(ndev); + set_bit(QL_EEH_FATAL, &qdev->flags); return PCI_ERS_RESULT_DISCONNECT; } @@ -4720,6 +4733,7 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) if (ql_adapter_reset(qdev)) { QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); + set_bit(QL_EEH_FATAL, &qdev->flags); return PCI_ERS_RESULT_DISCONNECT; } -- cgit v1.2.3 From e23e11792a77c7d54f363841cd5e33074fb0c8c9 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 12:43:44 +0000 Subject: hisax: timeout off by one in waitrecmsg() With `while (timeout++ < maxdelay)' timeout reaches maxdelay + 1 after the loop This is probably unlikely a problem in practice. Signed-off-by: Roel Kluin Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hisax/isar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index bfeb9b6aa043..6bde16c00fb5 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -138,7 +138,7 @@ waitrecmsg(struct IsdnCardState *cs, u_char *len, while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && (timeout++ < maxdelay)) udelay(1); - if (timeout >= maxdelay) { + if (timeout > maxdelay) { printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); return(0); } -- cgit v1.2.3 From f0f4d641d4ebfeb4194e9c26dfa6286802e2e8d1 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Tue, 2 Feb 2010 12:43:45 +0000 Subject: hardware/mISDN/mISDNinfineon.c: bail out of loop on error If setup_instance() fails we kfree() the card, and then use it in the next loop iteration. So lets bail out of the loop instead. Coverity CID: 13357 Signed-off-by: Darren Jenkins Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/mISDNinfineon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index 62441ba53b95..36c6c616a655 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -1133,6 +1133,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) { kfree(sc); release_card(card); + break; } else card->sc[i - 1] = sc; } -- cgit v1.2.3 From 3e5981774755f2f967cd1d3f3898576cff20e565 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 2 Feb 2010 12:43:46 +0000 Subject: isdn: mISDN, don't compile unused stuff Remove these compiler warnings: drivers/isdn/hardware/mISDN/w6692.c:534: warning: `setvolume' defined but not used drivers/isdn/hardware/mISDN/w6692.c:561: warning: `enable_pots' defined but not used by moving the functions inside #if 0 ... #endif. And an alternative is to remove them completely if nobody has plans to use them. Signed-off-by: Jiri Slaby Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/w6692.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index d3f1077b709b..2952a58c7a61 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -529,6 +529,7 @@ W6692_fill_Bfifo(struct w6692_ch *wch) } } +#if 0 static int setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb) { @@ -571,6 +572,7 @@ enable_pots(struct w6692_ch *wch) WriteW6692(card, W_PCTL, card->pctl); return 0; } +#endif static int disable_pots(struct w6692_ch *wch) -- cgit v1.2.3 From 650b2ef5d7f1378f65e6a313909d783e4b6477ed Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 2 Feb 2010 12:43:47 +0000 Subject: mISDN: positive error return should be negative in mode_hfcmulti() The error return should be negative. Its only caller that acts upon its return, handle_bmsg(), transmits the positive error but can also return negative errors. Signed-off-by: Roel Kluin Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hardware/mISDN/hfcmulti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 1a1420d7a828..ad36df9b759c 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -2846,7 +2846,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, int conf; if (ch < 0 || ch > 31) - return EINVAL; + return -EINVAL; oslot_tx = hc->chan[ch].slot_tx; oslot_rx = hc->chan[ch].slot_rx; conf = hc->chan[ch].conf; -- cgit v1.2.3 From 6884b348ed759184032306c9435a727741a72298 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 2 Feb 2010 12:43:59 +0000 Subject: net/rds: remove uses of NIPQUAD, use %pI4 Signed-off-by: Joe Perches Cc: Andy Grover Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/rds/tcp_connect.c | 7 +++---- net/rds/tcp_listen.c | 6 +++--- net/rds/tcp_send.c | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index 211522f9a9a2..056256285987 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c @@ -90,8 +90,8 @@ int rds_tcp_conn_connect(struct rds_connection *conn) ret = sock->ops->bind(sock, (struct sockaddr *)&src, sizeof(src)); if (ret) { - rdsdebug("bind failed with %d at address %u.%u.%u.%u\n", - ret, NIPQUAD(conn->c_laddr)); + rdsdebug("bind failed with %d at address %pI4\n", + ret, &conn->c_laddr); goto out; } @@ -108,8 +108,7 @@ int rds_tcp_conn_connect(struct rds_connection *conn) O_NONBLOCK); sock = NULL; - rdsdebug("connect to address %u.%u.%u.%u returned %d\n", - NIPQUAD(conn->c_faddr), ret); + rdsdebug("connect to address %pI4 returned %d\n", &conn->c_faddr, ret); if (ret == -EINPROGRESS) ret = 0; diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 45474a436862..53cb1b54165d 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c @@ -66,9 +66,9 @@ static int rds_tcp_accept_one(struct socket *sock) inet = inet_sk(new_sock->sk); - rdsdebug("accepted tcp %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", - NIPQUAD(inet->inet_saddr), ntohs(inet->inet_sport), - NIPQUAD(inet->inet_daddr), ntohs(inet->inet_dport)); + rdsdebug("accepted tcp %pI4:%u -> %pI4:%u\n", + &inet->inet_saddr, ntohs(inet->inet_sport), + &inet->inet_daddr, ntohs(inet->inet_dport)); conn = rds_conn_create(inet->inet_saddr, inet->inet_daddr, &rds_tcp_transport, GFP_KERNEL); diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index ab545e0cd5d6..34fdcc059e54 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c @@ -193,9 +193,9 @@ out: rds_tcp_stats_inc(s_tcp_sndbuf_full); ret = 0; } else { - printk(KERN_WARNING "RDS/tcp: send to %u.%u.%u.%u " + printk(KERN_WARNING "RDS/tcp: send to %pI4 " "returned %d, disconnecting and reconnecting\n", - NIPQUAD(conn->c_faddr), ret); + &conn->c_faddr, ret); rds_conn_drop(conn); } } -- cgit v1.2.3 From 8a83a00b0735190384a348156837918271034144 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 30 Jan 2010 12:23:03 +0000 Subject: net: maintain namespace isolation between vlan and real device In the vlan and macvlan drivers, the start_xmit function forwards data to the dev_queue_xmit function for another device, which may potentially belong to a different namespace. To make sure that classification stays within a single namespace, this resets the potentially critical fields. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 +- include/linux/netdevice.h | 9 +++++++++ net/8021q/vlan_dev.c | 2 +- net/core/dev.c | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index fa0dc514dbaf..d32e0bdfc5e9 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -269,7 +269,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) } xmit_world: - skb->dev = vlan->lowerdev; + skb_set_dev(skb, vlan->lowerdev); return dev_queue_xmit(skb); } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 93a32a5ca74f..622ba5aa93c4 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1004,6 +1004,15 @@ static inline bool netdev_uses_dsa_tags(struct net_device *dev) return 0; } +#ifndef CONFIG_NET_NS +static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev) +{ + skb->dev = dev; +} +#else /* CONFIG_NET_NS */ +void skb_set_dev(struct sk_buff *skb, struct net_device *dev); +#endif + static inline bool netdev_uses_trailer_tags(struct net_device *dev) { #ifdef CONFIG_NET_DSA_TAG_TRAILER diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index a9e1f1785614..9e83272fc5b0 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -322,7 +322,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, } - skb->dev = vlan_dev_info(dev)->real_dev; + skb_set_dev(skb, vlan_dev_info(dev)->real_dev); len = skb->len; ret = dev_queue_xmit(skb); diff --git a/net/core/dev.c b/net/core/dev.c index 2cba5c521e56..94c1eeed25e5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1448,13 +1448,10 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) if (skb->len > (dev->mtu + dev->hard_header_len)) return NET_RX_DROP; - skb_dst_drop(skb); + skb_set_dev(skb, dev); skb->tstamp.tv64 = 0; skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, dev); - skb->mark = 0; - secpath_reset(skb); - nf_reset(skb); return netif_rx(skb); } EXPORT_SYMBOL_GPL(dev_forward_skb); @@ -1614,6 +1611,36 @@ static bool dev_can_checksum(struct net_device *dev, struct sk_buff *skb) return false; } +/** + * skb_dev_set -- assign a new device to a buffer + * @skb: buffer for the new device + * @dev: network device + * + * If an skb is owned by a device already, we have to reset + * all data private to the namespace a device belongs to + * before assigning it a new device. + */ +#ifdef CONFIG_NET_NS +void skb_set_dev(struct sk_buff *skb, struct net_device *dev) +{ + skb_dst_drop(skb); + if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) { + secpath_reset(skb); + nf_reset(skb); + skb_init_secmark(skb); + skb->mark = 0; + skb->priority = 0; + skb->nf_trace = 0; + skb->ipvs_property = 0; +#ifdef CONFIG_NET_SCHED + skb->tc_index = 0; +#endif + } + skb->dev = dev; +} +EXPORT_SYMBOL(skb_set_dev); +#endif /* CONFIG_NET_NS */ + /* * Invalidate hardware checksum when packet is to be mangled, and * complete checksum manually on outgoing path. -- cgit v1.2.3 From fc0663d6b5e6d8e9b57f872a644c0aafd82361b7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 30 Jan 2010 12:23:40 +0000 Subject: macvlan: allow multiple driver backends This makes it possible to hook into the macvlan driver from another kernel module. In particular, the goal is to extend it with the macvtap backend that provides a tun/tap compatible interface directly on the macvlan device. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 113 ++++++++++++++++++++------------------------- include/linux/if_macvlan.h | 70 ++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 64 deletions(-) diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d32e0bdfc5e9..40faa368b07a 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -39,31 +39,6 @@ struct macvlan_port { struct list_head vlans; }; -/** - * struct macvlan_rx_stats - MACVLAN percpu rx stats - * @rx_packets: number of received packets - * @rx_bytes: number of received bytes - * @multicast: number of received multicast packets - * @rx_errors: number of errors - */ -struct macvlan_rx_stats { - unsigned long rx_packets; - unsigned long rx_bytes; - unsigned long multicast; - unsigned long rx_errors; -}; - -struct macvlan_dev { - struct net_device *dev; - struct list_head list; - struct hlist_node hlist; - struct macvlan_port *port; - struct net_device *lowerdev; - struct macvlan_rx_stats *rx_stats; - enum macvlan_mode mode; -}; - - static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port, const unsigned char *addr) { @@ -118,31 +93,17 @@ static int macvlan_addr_busy(const struct macvlan_port *port, return 0; } -static inline void macvlan_count_rx(const struct macvlan_dev *vlan, - unsigned int len, bool success, - bool multicast) -{ - struct macvlan_rx_stats *rx_stats; - - rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); - if (likely(success)) { - rx_stats->rx_packets++;; - rx_stats->rx_bytes += len; - if (multicast) - rx_stats->multicast++; - } else { - rx_stats->rx_errors++; - } -} -static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev, +static int macvlan_broadcast_one(struct sk_buff *skb, + const struct macvlan_dev *vlan, const struct ethhdr *eth, bool local) { + struct net_device *dev = vlan->dev; if (!skb) return NET_RX_DROP; if (local) - return dev_forward_skb(dev, skb); + return vlan->forward(dev, skb); skb->dev = dev; if (!compare_ether_addr_64bits(eth->h_dest, @@ -151,7 +112,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb, struct net_device *dev, else skb->pkt_type = PACKET_MULTICAST; - return netif_rx(skb); + return vlan->receive(skb); } static void macvlan_broadcast(struct sk_buff *skb, @@ -175,7 +136,7 @@ static void macvlan_broadcast(struct sk_buff *skb, continue; nskb = skb_clone(skb, GFP_ATOMIC); - err = macvlan_broadcast_one(nskb, vlan->dev, eth, + err = macvlan_broadcast_one(nskb, vlan, eth, mode == MACVLAN_MODE_BRIDGE); macvlan_count_rx(vlan, skb->len + ETH_HLEN, err == NET_RX_SUCCESS, 1); @@ -238,7 +199,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb) skb->dev = dev; skb->pkt_type = PACKET_HOST; - netif_rx(skb); + vlan->receive(skb); return NULL; } @@ -260,7 +221,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev) dest = macvlan_hash_lookup(port, eth->h_dest); if (dest && dest->mode == MACVLAN_MODE_BRIDGE) { unsigned int length = skb->len + ETH_HLEN; - int ret = dev_forward_skb(dest->dev, skb); + int ret = dest->forward(dest->dev, skb); macvlan_count_rx(dest, length, ret == NET_RX_SUCCESS, 0); @@ -273,8 +234,8 @@ xmit_world: return dev_queue_xmit(skb); } -static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, - struct net_device *dev) +netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, + struct net_device *dev) { int i = skb_get_queue_mapping(skb); struct netdev_queue *txq = netdev_get_tx_queue(dev, i); @@ -290,6 +251,7 @@ static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, return ret; } +EXPORT_SYMBOL_GPL(macvlan_start_xmit); static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, @@ -623,8 +585,11 @@ static int macvlan_get_tx_queues(struct net *net, return 0; } -static int macvlan_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) +int macvlan_common_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + int (*receive)(struct sk_buff *skb), + int (*forward)(struct net_device *dev, + struct sk_buff *skb)) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_port *port; @@ -664,6 +629,8 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev, vlan->lowerdev = lowerdev; vlan->dev = dev; vlan->port = port; + vlan->receive = receive; + vlan->forward = forward; vlan->mode = MACVLAN_MODE_VEPA; if (data && data[IFLA_MACVLAN_MODE]) @@ -677,8 +644,17 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev, netif_stacked_transfer_operstate(lowerdev, dev); return 0; } +EXPORT_SYMBOL_GPL(macvlan_common_newlink); -static void macvlan_dellink(struct net_device *dev, struct list_head *head) +static int macvlan_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + return macvlan_common_newlink(src_net, dev, tb, data, + netif_rx, + dev_forward_skb); +} + +void macvlan_dellink(struct net_device *dev, struct list_head *head) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvlan_port *port = vlan->port; @@ -689,6 +665,7 @@ static void macvlan_dellink(struct net_device *dev, struct list_head *head) if (list_empty(&port->vlans)) macvlan_port_destroy(port->dev); } +EXPORT_SYMBOL_GPL(macvlan_dellink); static int macvlan_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) @@ -720,19 +697,27 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, }; -static struct rtnl_link_ops macvlan_link_ops __read_mostly = { +int macvlan_link_register(struct rtnl_link_ops *ops) +{ + /* common fields */ + ops->priv_size = sizeof(struct macvlan_dev); + ops->get_tx_queues = macvlan_get_tx_queues; + ops->setup = macvlan_setup; + ops->validate = macvlan_validate; + ops->maxtype = IFLA_MACVLAN_MAX; + ops->policy = macvlan_policy; + ops->changelink = macvlan_changelink; + ops->get_size = macvlan_get_size; + ops->fill_info = macvlan_fill_info; + + return rtnl_link_register(ops); +}; +EXPORT_SYMBOL_GPL(macvlan_link_register); + +static struct rtnl_link_ops macvlan_link_ops = { .kind = "macvlan", - .priv_size = sizeof(struct macvlan_dev), - .get_tx_queues = macvlan_get_tx_queues, - .setup = macvlan_setup, - .validate = macvlan_validate, .newlink = macvlan_newlink, .dellink = macvlan_dellink, - .maxtype = IFLA_MACVLAN_MAX, - .policy = macvlan_policy, - .changelink = macvlan_changelink, - .get_size = macvlan_get_size, - .fill_info = macvlan_fill_info, }; static int macvlan_device_event(struct notifier_block *unused, @@ -761,7 +746,7 @@ static int macvlan_device_event(struct notifier_block *unused, break; case NETDEV_UNREGISTER: list_for_each_entry_safe(vlan, next, &port->vlans, list) - macvlan_dellink(vlan->dev, NULL); + vlan->dev->rtnl_link_ops->dellink(vlan->dev, NULL); break; } return NOTIFY_DONE; @@ -778,7 +763,7 @@ static int __init macvlan_init_module(void) register_netdevice_notifier(&macvlan_notifier_block); macvlan_handle_frame_hook = macvlan_handle_frame; - err = rtnl_link_register(&macvlan_link_ops); + err = macvlan_link_register(&macvlan_link_ops); if (err < 0) goto err1; return 0; diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 5f200bac3749..9a11544bb0b1 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -1,6 +1,76 @@ #ifndef _LINUX_IF_MACVLAN_H #define _LINUX_IF_MACVLAN_H +#include +#include +#include +#include +#include + +struct macvlan_port; +struct macvtap_queue; + +/** + * struct macvlan_rx_stats - MACVLAN percpu rx stats + * @rx_packets: number of received packets + * @rx_bytes: number of received bytes + * @multicast: number of received multicast packets + * @rx_errors: number of errors + */ +struct macvlan_rx_stats { + unsigned long rx_packets; + unsigned long rx_bytes; + unsigned long multicast; + unsigned long rx_errors; +}; + +struct macvlan_dev { + struct net_device *dev; + struct list_head list; + struct hlist_node hlist; + struct macvlan_port *port; + struct net_device *lowerdev; + struct macvlan_rx_stats *rx_stats; + enum macvlan_mode mode; + int (*receive)(struct sk_buff *skb); + int (*forward)(struct net_device *dev, struct sk_buff *skb); +}; + +static inline void macvlan_count_rx(const struct macvlan_dev *vlan, + unsigned int len, bool success, + bool multicast) +{ + struct macvlan_rx_stats *rx_stats; + + rx_stats = per_cpu_ptr(vlan->rx_stats, smp_processor_id()); + if (likely(success)) { + rx_stats->rx_packets++;; + rx_stats->rx_bytes += len; + if (multicast) + rx_stats->multicast++; + } else { + rx_stats->rx_errors++; + } +} + +extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + int (*receive)(struct sk_buff *skb), + int (*forward)(struct net_device *dev, + struct sk_buff *skb)); + +extern void macvlan_count_rx(const struct macvlan_dev *vlan, + unsigned int len, bool success, + bool multicast); + +extern void macvlan_dellink(struct net_device *dev, struct list_head *head); + +extern int macvlan_link_register(struct rtnl_link_ops *ops); + +extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, + struct net_device *dev); + + extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *); #endif /* _LINUX_IF_MACVLAN_H */ -- cgit v1.2.3 From 20d29d7a916a47bf533b5709437fe735b6b5b79e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 30 Jan 2010 12:24:26 +0000 Subject: net: macvtap driver In order to use macvlan with qemu and other tools that require a tap file descriptor, the macvtap driver adds a small backend with a character device with the same interface as the tun driver, with a minimum set of features. Macvtap interfaces are created in the same way as macvlan interfaces using ip link, but the netif is just used as a handle for configuration and accounting, while the data goes through the chardev. Each macvtap interface has its own character device, simplifying permission management significantly over the generic tun/tap driver. Cc: Patrick McHardy Cc: Stephen Hemminger Cc: David S. Miller" Cc: "Michael S. Tsirkin" Cc: Herbert Xu Cc: Or Gerlitz Cc: netdev@vger.kernel.org Cc: bridge@lists.linux-foundation.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/Kconfig | 12 + drivers/net/Makefile | 1 + drivers/net/macvtap.c | 581 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/if_macvlan.h | 1 + 4 files changed, 595 insertions(+) create mode 100644 drivers/net/macvtap.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index cb0e534418e3..411e20703110 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -90,6 +90,18 @@ config MACVLAN To compile this driver as a module, choose M here: the module will be called macvlan. +config MACVTAP + tristate "MAC-VLAN based tap driver (EXPERIMENTAL)" + depends on MACVLAN + help + This adds a specialized tap character device driver that is based + on the MAC-VLAN network interface, called macvtap. A macvtap device + can be added in the same way as a macvlan device, using 'type + macvlan', and then be accessed through the tap user space interface. + + To compile this driver as a module, choose M here: the module + will be called macvtap. + config EQUALIZER tristate "EQL (serial line load balancing) support" ---help--- diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0b763cbe9b1f..95958032cd31 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -169,6 +169,7 @@ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_IFB) += ifb.o obj-$(CONFIG_MACVLAN) += macvlan.o +obj-$(CONFIG_MACVTAP) += macvtap.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c new file mode 100644 index 000000000000..ad1f6ef89308 --- /dev/null +++ b/drivers/net/macvtap.c @@ -0,0 +1,581 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * A macvtap queue is the central object of this driver, it connects + * an open character device to a macvlan interface. There can be + * multiple queues on one interface, which map back to queues + * implemented in hardware on the underlying device. + * + * macvtap_proto is used to allocate queues through the sock allocation + * mechanism. + * + * TODO: multiqueue support is currently not implemented, even though + * macvtap is basically prepared for that. We will need to add this + * here as well as in virtio-net and qemu to get line rate on 10gbit + * adapters from a guest. + */ +struct macvtap_queue { + struct sock sk; + struct socket sock; + struct macvlan_dev *vlan; + struct file *file; +}; + +static struct proto macvtap_proto = { + .name = "macvtap", + .owner = THIS_MODULE, + .obj_size = sizeof (struct macvtap_queue), +}; + +/* + * Minor number matches netdev->ifindex, so need a potentially + * large value. This also makes it possible to split the + * tap functionality out again in the future by offering it + * from other drivers besides macvtap. As long as every device + * only has one tap, the interface numbers assure that the + * device nodes are unique. + */ +static unsigned int macvtap_major; +#define MACVTAP_NUM_DEVS 65536 +static struct class *macvtap_class; +static struct cdev macvtap_cdev; + +/* + * RCU usage: + * The macvtap_queue is referenced both from the chardev struct file + * and from the struct macvlan_dev using rcu_read_lock. + * + * We never actually update the contents of a macvtap_queue atomically + * with RCU but it is used for race-free destruction of a queue when + * either the file or the macvlan_dev goes away. Pointers back to + * the dev and the file are implicitly valid as long as the queue + * exists. + * + * The callbacks from macvlan are always done with rcu_read_lock held + * already, while in the file_operations, we get it ourselves. + * + * When destroying a queue, we remove the pointers from the file and + * from the dev and then synchronize_rcu to make sure no thread is + * still using the queue. There may still be references to the struct + * sock inside of the queue from outbound SKBs, but these never + * reference back to the file or the dev. The data structure is freed + * through __sk_free when both our references and any pending SKBs + * are gone. + * + * macvtap_lock is only used to prevent multiple concurrent open() + * calls to assign a new vlan->tap pointer. It could be moved into + * the macvlan_dev itself but is extremely rarely used. + */ +static DEFINE_SPINLOCK(macvtap_lock); + +/* + * Choose the next free queue, for now there is only one + */ +static int macvtap_set_queue(struct net_device *dev, struct file *file, + struct macvtap_queue *q) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + int err = -EBUSY; + + spin_lock(&macvtap_lock); + if (rcu_dereference(vlan->tap)) + goto out; + + err = 0; + q->vlan = vlan; + rcu_assign_pointer(vlan->tap, q); + + q->file = file; + rcu_assign_pointer(file->private_data, q); + +out: + spin_unlock(&macvtap_lock); + return err; +} + +/* + * We must destroy each queue exactly once, when either + * the netdev or the file go away. + * + * Using the spinlock makes sure that we don't get + * to the queue again after destroying it. + * + * synchronize_rcu serializes with the packet flow + * that uses rcu_read_lock. + */ +static void macvtap_del_queue(struct macvtap_queue **qp) +{ + struct macvtap_queue *q; + + spin_lock(&macvtap_lock); + q = rcu_dereference(*qp); + if (!q) { + spin_unlock(&macvtap_lock); + return; + } + + rcu_assign_pointer(q->vlan->tap, NULL); + rcu_assign_pointer(q->file->private_data, NULL); + spin_unlock(&macvtap_lock); + + synchronize_rcu(); + sock_put(&q->sk); +} + +/* + * Since we only support one queue, just dereference the pointer. + */ +static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, + struct sk_buff *skb) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + + return rcu_dereference(vlan->tap); +} + +static void macvtap_del_queues(struct net_device *dev) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + macvtap_del_queue(&vlan->tap); +} + +static inline struct macvtap_queue *macvtap_file_get_queue(struct file *file) +{ + rcu_read_lock_bh(); + return rcu_dereference(file->private_data); +} + +static inline void macvtap_file_put_queue(void) +{ + rcu_read_unlock_bh(); +} + +/* + * Forward happens for data that gets sent from one macvlan + * endpoint to another one in bridge mode. We just take + * the skb and put it into the receive queue. + */ +static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) +{ + struct macvtap_queue *q = macvtap_get_queue(dev, skb); + if (!q) + return -ENOLINK; + + skb_queue_tail(&q->sk.sk_receive_queue, skb); + wake_up(q->sk.sk_sleep); + return 0; +} + +/* + * Receive is for data from the external interface (lowerdev), + * in case of macvtap, we can treat that the same way as + * forward, which macvlan cannot. + */ +static int macvtap_receive(struct sk_buff *skb) +{ + skb_push(skb, ETH_HLEN); + return macvtap_forward(skb->dev, skb); +} + +static int macvtap_newlink(struct net *src_net, + struct net_device *dev, + struct nlattr *tb[], + struct nlattr *data[]) +{ + struct device *classdev; + dev_t devt; + int err; + + err = macvlan_common_newlink(src_net, dev, tb, data, + macvtap_receive, macvtap_forward); + if (err) + goto out; + + devt = MKDEV(MAJOR(macvtap_major), dev->ifindex); + + classdev = device_create(macvtap_class, &dev->dev, devt, + dev, "tap%d", dev->ifindex); + if (IS_ERR(classdev)) { + err = PTR_ERR(classdev); + macvtap_del_queues(dev); + } + +out: + return err; +} + +static void macvtap_dellink(struct net_device *dev, + struct list_head *head) +{ + device_destroy(macvtap_class, + MKDEV(MAJOR(macvtap_major), dev->ifindex)); + + macvtap_del_queues(dev); + macvlan_dellink(dev, head); +} + +static struct rtnl_link_ops macvtap_link_ops __read_mostly = { + .kind = "macvtap", + .newlink = macvtap_newlink, + .dellink = macvtap_dellink, +}; + + +static void macvtap_sock_write_space(struct sock *sk) +{ + if (!sock_writeable(sk) || + !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) + return; + + if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) + wake_up_interruptible_sync(sk->sk_sleep); +} + +static int macvtap_open(struct inode *inode, struct file *file) +{ + struct net *net = current->nsproxy->net_ns; + struct net_device *dev = dev_get_by_index(net, iminor(inode)); + struct macvtap_queue *q; + int err; + + err = -ENODEV; + if (!dev) + goto out; + + /* check if this is a macvtap device */ + err = -EINVAL; + if (dev->rtnl_link_ops != &macvtap_link_ops) + goto out; + + err = -ENOMEM; + q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL, + &macvtap_proto); + if (!q) + goto out; + + init_waitqueue_head(&q->sock.wait); + q->sock.type = SOCK_RAW; + q->sock.state = SS_CONNECTED; + sock_init_data(&q->sock, &q->sk); + q->sk.sk_allocation = GFP_ATOMIC; /* for now */ + q->sk.sk_write_space = macvtap_sock_write_space; + + err = macvtap_set_queue(dev, file, q); + if (err) + sock_put(&q->sk); + +out: + if (dev) + dev_put(dev); + + return err; +} + +static int macvtap_release(struct inode *inode, struct file *file) +{ + macvtap_del_queue((struct macvtap_queue **)&file->private_data); + return 0; +} + +static unsigned int macvtap_poll(struct file *file, poll_table * wait) +{ + struct macvtap_queue *q = macvtap_file_get_queue(file); + unsigned int mask = POLLERR; + + if (!q) + goto out; + + mask = 0; + poll_wait(file, &q->sock.wait, wait); + + if (!skb_queue_empty(&q->sk.sk_receive_queue)) + mask |= POLLIN | POLLRDNORM; + + if (sock_writeable(&q->sk) || + (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &q->sock.flags) && + sock_writeable(&q->sk))) + mask |= POLLOUT | POLLWRNORM; + +out: + macvtap_file_put_queue(); + return mask; +} + +/* Get packet from user space buffer */ +static ssize_t macvtap_get_user(struct macvtap_queue *q, + const struct iovec *iv, size_t count, + int noblock) +{ + struct sk_buff *skb; + size_t len = count; + int err; + + if (unlikely(len < ETH_HLEN)) + return -EINVAL; + + skb = sock_alloc_send_skb(&q->sk, NET_IP_ALIGN + len, noblock, &err); + + if (!skb) { + macvlan_count_rx(q->vlan, 0, false, false); + return err; + } + + skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, count); + + if (skb_copy_datagram_from_iovec(skb, 0, iv, 0, len)) { + macvlan_count_rx(q->vlan, 0, false, false); + kfree_skb(skb); + return -EFAULT; + } + + skb_set_network_header(skb, ETH_HLEN); + + macvlan_start_xmit(skb, q->vlan->dev); + + return count; +} + +static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + ssize_t result = -ENOLINK; + struct macvtap_queue *q = macvtap_file_get_queue(file); + + if (!q) + goto out; + + result = macvtap_get_user(q, iv, iov_length(iv, count), + file->f_flags & O_NONBLOCK); +out: + macvtap_file_put_queue(); + return result; +} + +/* Put packet to the user space buffer */ +static ssize_t macvtap_put_user(struct macvtap_queue *q, + const struct sk_buff *skb, + const struct iovec *iv, int len) +{ + struct macvlan_dev *vlan = q->vlan; + int ret; + + len = min_t(int, skb->len, len); + + ret = skb_copy_datagram_const_iovec(skb, 0, iv, 0, len); + + macvlan_count_rx(vlan, len, ret == 0, 0); + + return ret ? ret : len; +} + +static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct macvtap_queue *q = macvtap_file_get_queue(file); + + DECLARE_WAITQUEUE(wait, current); + struct sk_buff *skb; + ssize_t len, ret = 0; + + if (!q) { + ret = -ENOLINK; + goto out; + } + + len = iov_length(iv, count); + if (len < 0) { + ret = -EINVAL; + goto out; + } + + add_wait_queue(q->sk.sk_sleep, &wait); + while (len) { + current->state = TASK_INTERRUPTIBLE; + + /* Read frames from the queue */ + skb = skb_dequeue(&q->sk.sk_receive_queue); + if (!skb) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + /* Nothing to read, let's sleep */ + schedule(); + continue; + } + ret = macvtap_put_user(q, skb, iv, len); + kfree_skb(skb); + break; + } + + current->state = TASK_RUNNING; + remove_wait_queue(q->sk.sk_sleep, &wait); + +out: + macvtap_file_put_queue(); + return ret; +} + +/* + * provide compatibility with generic tun/tap interface + */ +static long macvtap_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct macvtap_queue *q; + void __user *argp = (void __user *)arg; + struct ifreq __user *ifr = argp; + unsigned int __user *up = argp; + unsigned int u; + char devname[IFNAMSIZ]; + + switch (cmd) { + case TUNSETIFF: + /* ignore the name, just look at flags */ + if (get_user(u, &ifr->ifr_flags)) + return -EFAULT; + if (u != (IFF_TAP | IFF_NO_PI)) + return -EINVAL; + return 0; + + case TUNGETIFF: + q = macvtap_file_get_queue(file); + if (!q) + return -ENOLINK; + memcpy(devname, q->vlan->dev->name, sizeof(devname)); + macvtap_file_put_queue(); + + if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) || + put_user((TUN_TAP_DEV | TUN_NO_PI), &ifr->ifr_flags)) + return -EFAULT; + return 0; + + case TUNGETFEATURES: + if (put_user((IFF_TAP | IFF_NO_PI), up)) + return -EFAULT; + return 0; + + case TUNSETSNDBUF: + if (get_user(u, up)) + return -EFAULT; + + q = macvtap_file_get_queue(file); + q->sk.sk_sndbuf = u; + macvtap_file_put_queue(); + return 0; + + case TUNSETOFFLOAD: + /* let the user check for future flags */ + if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | + TUN_F_TSO_ECN | TUN_F_UFO)) + return -EINVAL; + + /* TODO: add support for these, so far we don't + support any offload */ + if (arg & (TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | + TUN_F_TSO_ECN | TUN_F_UFO)) + return -EINVAL; + + return 0; + + default: + return -EINVAL; + } +} + +#ifdef CONFIG_COMPAT +static long macvtap_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return macvtap_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static const struct file_operations macvtap_fops = { + .owner = THIS_MODULE, + .open = macvtap_open, + .release = macvtap_release, + .aio_read = macvtap_aio_read, + .aio_write = macvtap_aio_write, + .poll = macvtap_poll, + .llseek = no_llseek, + .unlocked_ioctl = macvtap_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = macvtap_compat_ioctl, +#endif +}; + +static int macvtap_init(void) +{ + int err; + + err = alloc_chrdev_region(&macvtap_major, 0, + MACVTAP_NUM_DEVS, "macvtap"); + if (err) + goto out1; + + cdev_init(&macvtap_cdev, &macvtap_fops); + err = cdev_add(&macvtap_cdev, macvtap_major, MACVTAP_NUM_DEVS); + if (err) + goto out2; + + macvtap_class = class_create(THIS_MODULE, "macvtap"); + if (IS_ERR(macvtap_class)) { + err = PTR_ERR(macvtap_class); + goto out3; + } + + err = macvlan_link_register(&macvtap_link_ops); + if (err) + goto out4; + + return 0; + +out4: + class_unregister(macvtap_class); +out3: + cdev_del(&macvtap_cdev); +out2: + unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS); +out1: + return err; +} +module_init(macvtap_init); + +static void macvtap_exit(void) +{ + rtnl_link_unregister(&macvtap_link_ops); + class_unregister(macvtap_class); + cdev_del(&macvtap_cdev); + unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS); +} +module_exit(macvtap_exit); + +MODULE_ALIAS_RTNL_LINK("macvtap"); +MODULE_AUTHOR("Arnd Bergmann "); +MODULE_LICENSE("GPL"); diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 9a11544bb0b1..51f1512045e9 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -34,6 +34,7 @@ struct macvlan_dev { enum macvlan_mode mode; int (*receive)(struct sk_buff *skb); int (*forward)(struct net_device *dev, struct sk_buff *skb); + struct macvtap_queue *tap; }; static inline void macvlan_count_rx(const struct macvlan_dev *vlan, -- cgit v1.2.3 From 59b26c72914920fd12695033c5a099fb0bfae935 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 1 Feb 2010 07:58:59 +0000 Subject: trivial: remove duplicated "from" in CAN USB EMS Kconfig help Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: David S. Miller --- drivers/net/can/usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index bbc78e0b8a15..97ff6febad63 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -5,6 +5,6 @@ config CAN_EMS_USB tristate "EMS CPC-USB/ARM7 CAN/USB interface" ---help--- This driver is for the one channel CPC-USB/ARM7 CAN/USB interface - from from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). + from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). endmenu -- cgit v1.2.3 From 235ecb1db09f481840569fd85eda62e70d03580c Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 1 Feb 2010 21:22:11 +0000 Subject: drivers/net/davinci_emac.c: Fix continuation line formats String constants that are continued on subsequent lines with \ are not good. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/davinci_emac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 33c4fe26178c..faffad409985 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2672,8 +2672,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev) priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; size = res->end - res->start + 1; if (!request_mem_region(res->start, size, ndev->name)) { - dev_err(emac_dev, "DaVinci EMAC: failed request_mem_region() \ - for regs\n"); + dev_err(emac_dev, "DaVinci EMAC: failed request_mem_region() for regs\n"); rc = -ENXIO; goto probe_quit; } -- cgit v1.2.3 From 35cfabdc5e9b99e732899db8f36c63a215e105bc Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Mon, 1 Feb 2010 14:06:52 +0000 Subject: bonding: Remove net_device_stats from bonding struct There is no need to maintain stats in the bonding structure. Use the instance of net_device_stats in netdevice. Signed-off-by: Ajit Khaparde Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- drivers/net/bonding/bonding.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6221936e957a..1787e3c86573 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3742,7 +3742,7 @@ static int bond_close(struct net_device *bond_dev) static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct net_device_stats *stats = &bond->stats; + struct net_device_stats *stats = &bond_dev->stats; struct net_device_stats local_stats; struct slave *slave; int i; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 558ec1352527..257a7a4dfce9 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -197,7 +197,6 @@ struct bonding { s8 send_grat_arp; s8 send_unsol_na; s8 setup_by_slave; - struct net_device_stats stats; #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry; char proc_file_name[IFNAMSIZ]; -- cgit v1.2.3 From bf66f3736a945dd4e92d86427276c6eeab0a6c1d Mon Sep 17 00:00:00 2001 From: Christian Pellegrin Date: Wed, 3 Feb 2010 07:39:54 +0000 Subject: can: mcp251x: Move to threaded interrupts instead of workqueues. This patch addresses concerns about efficiency of handling incoming packets. Handling of interrupts is done in a threaded interrupt handler which has a smaller latency than workqueues. This change needed a rework of the locking scheme that was much simplified. Some other (more or less longstanding) bugs are fixed: utilization of just half of the RX buffers, useless wait for interrupt on open, more reliable reset sequence. The MERR interrupt is not used anymore: it overloads the CPU in error-passive state without any additional information. One shot mode is disabled because it's not clear if it can be handled efficiently on this CAN controller. Signed-off-by: Christian Pellegrin Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/mcp251x.c | 421 ++++++++++++++++++++++------------------------ 1 file changed, 203 insertions(+), 218 deletions(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index bbe186b5a0ed..f8cc168ec76c 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -180,6 +180,14 @@ #define RXBEID0_OFF 4 #define RXBDLC_OFF 5 #define RXBDAT_OFF 6 +#define RXFSIDH(n) ((n) * 4) +#define RXFSIDL(n) ((n) * 4 + 1) +#define RXFEID8(n) ((n) * 4 + 2) +#define RXFEID0(n) ((n) * 4 + 3) +#define RXMSIDH(n) ((n) * 4 + 0x20) +#define RXMSIDL(n) ((n) * 4 + 0x21) +#define RXMEID8(n) ((n) * 4 + 0x22) +#define RXMEID0(n) ((n) * 4 + 0x23) #define GET_BYTE(val, byte) \ (((val) >> ((byte) * 8)) & 0xff) @@ -219,7 +227,8 @@ struct mcp251x_priv { struct net_device *net; struct spi_device *spi; - struct mutex spi_lock; /* SPI buffer lock */ + struct mutex mcp_lock; /* SPI device lock */ + u8 *spi_tx_buf; u8 *spi_rx_buf; dma_addr_t spi_tx_dma; @@ -227,11 +236,11 @@ struct mcp251x_priv { struct sk_buff *tx_skb; int tx_len; + struct workqueue_struct *wq; struct work_struct tx_work; - struct work_struct irq_work; - struct completion awake; - int wake; + struct work_struct restart_work; + int force_quit; int after_suspend; #define AFTER_SUSPEND_UP 1 @@ -245,7 +254,8 @@ static void mcp251x_clean(struct net_device *net) { struct mcp251x_priv *priv = netdev_priv(net); - net->stats.tx_errors++; + if (priv->tx_skb || priv->tx_len) + net->stats.tx_errors++; if (priv->tx_skb) dev_kfree_skb(priv->tx_skb); if (priv->tx_len) @@ -300,16 +310,12 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u8 val = 0; - mutex_lock(&priv->spi_lock); - priv->spi_tx_buf[0] = INSTRUCTION_READ; priv->spi_tx_buf[1] = reg; mcp251x_spi_trans(spi, 3); val = priv->spi_rx_buf[2]; - mutex_unlock(&priv->spi_lock); - return val; } @@ -317,15 +323,11 @@ static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - mutex_lock(&priv->spi_lock); - priv->spi_tx_buf[0] = INSTRUCTION_WRITE; priv->spi_tx_buf[1] = reg; priv->spi_tx_buf[2] = val; mcp251x_spi_trans(spi, 3); - - mutex_unlock(&priv->spi_lock); } static void mcp251x_write_bits(struct spi_device *spi, u8 reg, @@ -333,16 +335,12 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg, { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - mutex_lock(&priv->spi_lock); - priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; priv->spi_tx_buf[1] = reg; priv->spi_tx_buf[2] = mask; priv->spi_tx_buf[3] = val; mcp251x_spi_trans(spi, 4); - - mutex_unlock(&priv->spi_lock); } static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, @@ -358,10 +356,8 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, buf[i]); } else { - mutex_lock(&priv->spi_lock); memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); mcp251x_spi_trans(spi, TXBDAT_OFF + len); - mutex_unlock(&priv->spi_lock); } } @@ -408,13 +404,9 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, for (; i < (RXBDAT_OFF + len); i++) buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); } else { - mutex_lock(&priv->spi_lock); - priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx); mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN); memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN); - - mutex_unlock(&priv->spi_lock); } } @@ -467,21 +459,6 @@ static void mcp251x_hw_sleep(struct spi_device *spi) mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP); } -static void mcp251x_hw_wakeup(struct spi_device *spi) -{ - struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); - - priv->wake = 1; - - /* Can only wake up by generating a wake-up interrupt. */ - mcp251x_write_bits(spi, CANINTE, CANINTE_WAKIE, CANINTE_WAKIE); - mcp251x_write_bits(spi, CANINTF, CANINTF_WAKIF, CANINTF_WAKIF); - - /* Wait until the device is awake */ - if (!wait_for_completion_timeout(&priv->awake, HZ)) - dev_err(&spi->dev, "MCP251x didn't wake-up\n"); -} - static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, struct net_device *net) { @@ -490,7 +467,6 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, if (priv->tx_skb || priv->tx_len) { dev_warn(&spi->dev, "hard_xmit called while tx busy\n"); - netif_stop_queue(net); return NETDEV_TX_BUSY; } @@ -511,12 +487,13 @@ static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) switch (mode) { case CAN_MODE_START: + mcp251x_clean(net); /* We have to delay work since SPI I/O may sleep */ priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->restart_tx = 1; if (priv->can.restart_ms == 0) priv->after_suspend = AFTER_SUSPEND_RESTART; - queue_work(priv->wq, &priv->irq_work); + queue_work(priv->wq, &priv->restart_work); break; default: return -EOPNOTSUPP; @@ -525,7 +502,7 @@ static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) return 0; } -static void mcp251x_set_normal_mode(struct spi_device *spi) +static int mcp251x_set_normal_mode(struct spi_device *spi) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); unsigned long timeout; @@ -533,8 +510,7 @@ static void mcp251x_set_normal_mode(struct spi_device *spi) /* Enable interrupts */ mcp251x_write_reg(spi, CANINTE, CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE | - CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE | - CANINTF_MERRF); + CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE); if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { /* Put device into loopback mode */ @@ -544,9 +520,7 @@ static void mcp251x_set_normal_mode(struct spi_device *spi) mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY); } else { /* Put device into normal mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | - (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT ? - CANCTRL_OSM : 0)); + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); /* Wait for the device to enter normal mode */ timeout = jiffies + HZ; @@ -555,11 +529,12 @@ static void mcp251x_set_normal_mode(struct spi_device *spi) if (time_after(jiffies, timeout)) { dev_err(&spi->dev, "MCP251x didn't" " enter in normal mode\n"); - return; + return -EBUSY; } } } priv->can.state = CAN_STATE_ERROR_ACTIVE; + return 0; } static int mcp251x_do_set_bittiming(struct net_device *net) @@ -590,33 +565,39 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, { mcp251x_do_set_bittiming(net); - /* Enable RX0->RX1 buffer roll over and disable filters */ - mcp251x_write_bits(spi, RXBCTRL(0), - RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1, - RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); - mcp251x_write_bits(spi, RXBCTRL(1), - RXBCTRL_RXM0 | RXBCTRL_RXM1, - RXBCTRL_RXM0 | RXBCTRL_RXM1); + mcp251x_write_reg(spi, RXBCTRL(0), + RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); + mcp251x_write_reg(spi, RXBCTRL(1), + RXBCTRL_RXM0 | RXBCTRL_RXM1); return 0; } -static void mcp251x_hw_reset(struct spi_device *spi) +static int mcp251x_hw_reset(struct spi_device *spi) { struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); int ret; - - mutex_lock(&priv->spi_lock); + unsigned long timeout; priv->spi_tx_buf[0] = INSTRUCTION_RESET; - ret = spi_write(spi, priv->spi_tx_buf, 1); - - mutex_unlock(&priv->spi_lock); - - if (ret) + if (ret) { dev_err(&spi->dev, "reset failed: ret = %d\n", ret); + return -EIO; + } + /* Wait for reset to finish */ + timeout = jiffies + HZ; mdelay(10); + while ((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) + != CANCTRL_REQOP_CONF) { + schedule(); + if (time_after(jiffies, timeout)) { + dev_err(&spi->dev, "MCP251x didn't" + " enter in conf mode after reset\n"); + return -EBUSY; + } + } + return 0; } static int mcp251x_hw_probe(struct spi_device *spi) @@ -640,63 +621,17 @@ static int mcp251x_hw_probe(struct spi_device *spi) return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; } -static irqreturn_t mcp251x_can_isr(int irq, void *dev_id) -{ - struct net_device *net = (struct net_device *)dev_id; - struct mcp251x_priv *priv = netdev_priv(net); - - /* Schedule bottom half */ - if (!work_pending(&priv->irq_work)) - queue_work(priv->wq, &priv->irq_work); - - return IRQ_HANDLED; -} - -static int mcp251x_open(struct net_device *net) +static void mcp251x_open_clean(struct net_device *net) { struct mcp251x_priv *priv = netdev_priv(net); struct spi_device *spi = priv->spi; struct mcp251x_platform_data *pdata = spi->dev.platform_data; - int ret; - - ret = open_candev(net); - if (ret) { - dev_err(&spi->dev, "unable to set initial baudrate!\n"); - return ret; - } + free_irq(spi->irq, priv); + mcp251x_hw_sleep(spi); if (pdata->transceiver_enable) - pdata->transceiver_enable(1); - - priv->force_quit = 0; - priv->tx_skb = NULL; - priv->tx_len = 0; - - ret = request_irq(spi->irq, mcp251x_can_isr, - IRQF_TRIGGER_FALLING, DEVICE_NAME, net); - if (ret) { - dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - close_candev(net); - return ret; - } - - mcp251x_hw_wakeup(spi); - mcp251x_hw_reset(spi); - ret = mcp251x_setup(net, priv, spi); - if (ret) { - free_irq(spi->irq, net); - mcp251x_hw_sleep(spi); - if (pdata->transceiver_enable) - pdata->transceiver_enable(0); - close_candev(net); - return ret; - } - mcp251x_set_normal_mode(spi); - netif_wake_queue(net); - - return 0; + pdata->transceiver_enable(0); + close_candev(net); } static int mcp251x_stop(struct net_device *net) @@ -707,17 +642,19 @@ static int mcp251x_stop(struct net_device *net) close_candev(net); + priv->force_quit = 1; + free_irq(spi->irq, priv); + destroy_workqueue(priv->wq); + priv->wq = NULL; + + mutex_lock(&priv->mcp_lock); + /* Disable and clear pending interrupts */ mcp251x_write_reg(spi, CANINTE, 0x00); mcp251x_write_reg(spi, CANINTF, 0x00); - priv->force_quit = 1; - free_irq(spi->irq, net); - flush_workqueue(priv->wq); - mcp251x_write_reg(spi, TXBCTRL(0), 0); - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); + mcp251x_clean(net); mcp251x_hw_sleep(spi); @@ -726,9 +663,27 @@ static int mcp251x_stop(struct net_device *net) priv->can.state = CAN_STATE_STOPPED; + mutex_unlock(&priv->mcp_lock); + return 0; } +static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) +{ + struct sk_buff *skb; + struct can_frame *frame; + + skb = alloc_can_err_skb(net, &frame); + if (skb) { + frame->can_id = can_id; + frame->data[1] = data1; + netif_rx(skb); + } else { + dev_err(&net->dev, + "cannot allocate error skb\n"); + } +} + static void mcp251x_tx_work_handler(struct work_struct *ws) { struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, @@ -737,33 +692,32 @@ static void mcp251x_tx_work_handler(struct work_struct *ws) struct net_device *net = priv->net; struct can_frame *frame; + mutex_lock(&priv->mcp_lock); if (priv->tx_skb) { - frame = (struct can_frame *)priv->tx_skb->data; - if (priv->can.state == CAN_STATE_BUS_OFF) { mcp251x_clean(net); - netif_wake_queue(net); - return; + } else { + frame = (struct can_frame *)priv->tx_skb->data; + + if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) + frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; + mcp251x_hw_tx(spi, frame, 0); + priv->tx_len = 1 + frame->can_dlc; + can_put_echo_skb(priv->tx_skb, net, 0); + priv->tx_skb = NULL; } - if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) - frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; - mcp251x_hw_tx(spi, frame, 0); - priv->tx_len = 1 + frame->can_dlc; - can_put_echo_skb(priv->tx_skb, net, 0); - priv->tx_skb = NULL; } + mutex_unlock(&priv->mcp_lock); } -static void mcp251x_irq_work_handler(struct work_struct *ws) +static void mcp251x_restart_work_handler(struct work_struct *ws) { struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, - irq_work); + restart_work); struct spi_device *spi = priv->spi; struct net_device *net = priv->net; - u8 txbnctrl; - u8 intf; - enum can_state new_state; + mutex_lock(&priv->mcp_lock); if (priv->after_suspend) { mdelay(10); mcp251x_hw_reset(spi); @@ -772,45 +726,54 @@ static void mcp251x_irq_work_handler(struct work_struct *ws) mcp251x_set_normal_mode(spi); } else if (priv->after_suspend & AFTER_SUSPEND_UP) { netif_device_attach(net); - /* Clean since we lost tx buffer */ - if (priv->tx_skb || priv->tx_len) { - mcp251x_clean(net); - netif_wake_queue(net); - } + mcp251x_clean(net); mcp251x_set_normal_mode(spi); + netif_wake_queue(net); } else { mcp251x_hw_sleep(spi); } priv->after_suspend = 0; + priv->force_quit = 0; } - if (priv->can.restart_ms == 0 && priv->can.state == CAN_STATE_BUS_OFF) - return; + if (priv->restart_tx) { + priv->restart_tx = 0; + mcp251x_write_reg(spi, TXBCTRL(0), 0); + mcp251x_clean(net); + netif_wake_queue(net); + mcp251x_error_skb(net, CAN_ERR_RESTARTED, 0); + } + mutex_unlock(&priv->mcp_lock); +} - while (!priv->force_quit && !freezing(current)) { - u8 eflag = mcp251x_read_reg(spi, EFLG); - int can_id = 0, data1 = 0; +static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) +{ + struct mcp251x_priv *priv = dev_id; + struct spi_device *spi = priv->spi; + struct net_device *net = priv->net; - mcp251x_write_reg(spi, EFLG, 0x00); + mutex_lock(&priv->mcp_lock); + while (!priv->force_quit) { + enum can_state new_state; + u8 intf = mcp251x_read_reg(spi, CANINTF); + u8 eflag; + int can_id = 0, data1 = 0; - if (priv->restart_tx) { - priv->restart_tx = 0; - mcp251x_write_reg(spi, TXBCTRL(0), 0); - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); - netif_wake_queue(net); - can_id |= CAN_ERR_RESTARTED; + if (intf & CANINTF_RX0IF) { + mcp251x_hw_rx(spi, 0); + /* Free one buffer ASAP */ + mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF, + 0x00); } - if (priv->wake) { - /* Wait whilst the device wakes up */ - mdelay(10); - priv->wake = 0; - } + if (intf & CANINTF_RX1IF) + mcp251x_hw_rx(spi, 1); - intf = mcp251x_read_reg(spi, CANINTF); mcp251x_write_bits(spi, CANINTF, intf, 0x00); + eflag = mcp251x_read_reg(spi, EFLG); + mcp251x_write_reg(spi, EFLG, 0x00); + /* Update can state */ if (eflag & EFLG_TXBO) { new_state = CAN_STATE_BUS_OFF; @@ -851,59 +814,31 @@ static void mcp251x_irq_work_handler(struct work_struct *ws) } priv->can.state = new_state; - if ((intf & CANINTF_ERRIF) || (can_id & CAN_ERR_RESTARTED)) { - struct sk_buff *skb; - struct can_frame *frame; - - /* Create error frame */ - skb = alloc_can_err_skb(net, &frame); - if (skb) { - /* Set error frame flags based on bus state */ - frame->can_id = can_id; - frame->data[1] = data1; - - /* Update net stats for overflows */ - if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { - if (eflag & EFLG_RX0OVR) - net->stats.rx_over_errors++; - if (eflag & EFLG_RX1OVR) - net->stats.rx_over_errors++; - frame->can_id |= CAN_ERR_CRTL; - frame->data[1] |= - CAN_ERR_CRTL_RX_OVERFLOW; - } - - netif_rx(skb); - } else { - dev_info(&spi->dev, - "cannot allocate error skb\n"); + if (intf & CANINTF_ERRIF) { + /* Handle overflow counters */ + if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { + if (eflag & EFLG_RX0OVR) + net->stats.rx_over_errors++; + if (eflag & EFLG_RX1OVR) + net->stats.rx_over_errors++; + can_id |= CAN_ERR_CRTL; + data1 |= CAN_ERR_CRTL_RX_OVERFLOW; } + mcp251x_error_skb(net, can_id, data1); } if (priv->can.state == CAN_STATE_BUS_OFF) { if (priv->can.restart_ms == 0) { + priv->force_quit = 1; can_bus_off(net); mcp251x_hw_sleep(spi); - return; + break; } } if (intf == 0) break; - if (intf & CANINTF_WAKIF) - complete(&priv->awake); - - if (intf & CANINTF_MERRF) { - /* If there are pending Tx buffers, restart queue */ - txbnctrl = mcp251x_read_reg(spi, TXBCTRL(0)); - if (!(txbnctrl & TXBCTRL_TXREQ)) { - if (priv->tx_skb || priv->tx_len) - mcp251x_clean(net); - netif_wake_queue(net); - } - } - if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) { net->stats.tx_packets++; net->stats.tx_bytes += priv->tx_len - 1; @@ -914,12 +849,66 @@ static void mcp251x_irq_work_handler(struct work_struct *ws) netif_wake_queue(net); } - if (intf & CANINTF_RX0IF) - mcp251x_hw_rx(spi, 0); + } + mutex_unlock(&priv->mcp_lock); + return IRQ_HANDLED; +} - if (intf & CANINTF_RX1IF) - mcp251x_hw_rx(spi, 1); +static int mcp251x_open(struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct spi_device *spi = priv->spi; + struct mcp251x_platform_data *pdata = spi->dev.platform_data; + int ret; + + ret = open_candev(net); + if (ret) { + dev_err(&spi->dev, "unable to set initial baudrate!\n"); + return ret; + } + + mutex_lock(&priv->mcp_lock); + if (pdata->transceiver_enable) + pdata->transceiver_enable(1); + + priv->force_quit = 0; + priv->tx_skb = NULL; + priv->tx_len = 0; + + ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, + IRQF_TRIGGER_FALLING, DEVICE_NAME, priv); + if (ret) { + dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); + if (pdata->transceiver_enable) + pdata->transceiver_enable(0); + close_candev(net); + goto open_unlock; + } + + priv->wq = create_freezeable_workqueue("mcp251x_wq"); + INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); + INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); + + ret = mcp251x_hw_reset(spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; + } + ret = mcp251x_setup(net, priv, spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; } + ret = mcp251x_set_normal_mode(spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; + } + netif_wake_queue(net); + +open_unlock: + mutex_unlock(&priv->mcp_lock); + return ret; } static const struct net_device_ops mcp251x_netdev_ops = { @@ -955,13 +944,11 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) priv->can.clock.freq = pdata->oscillator_frequency / 2; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; - if (pdata->model == CAN_MCP251X_MCP2515) - priv->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; priv->net = net; dev_set_drvdata(&spi->dev, priv); priv->spi = spi; - mutex_init(&priv->spi_lock); + mutex_init(&priv->mcp_lock); /* If requested, allocate DMA buffers */ if (mcp251x_enable_dma) { @@ -1010,18 +997,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) SET_NETDEV_DEV(net, &spi->dev); - priv->wq = create_freezeable_workqueue("mcp251x_wq"); - - INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); - INIT_WORK(&priv->irq_work, mcp251x_irq_work_handler); - - init_completion(&priv->awake); - /* Configure the SPI bus */ spi->mode = SPI_MODE_0; spi->bits_per_word = 8; spi_setup(spi); + /* Here is OK to not lock the MCP, no one knows about it yet */ if (!mcp251x_hw_probe(spi)) { dev_info(&spi->dev, "Probe failed\n"); goto error_probe; @@ -1064,10 +1045,6 @@ static int __devexit mcp251x_can_remove(struct spi_device *spi) unregister_candev(net); free_candev(net); - priv->force_quit = 1; - flush_workqueue(priv->wq); - destroy_workqueue(priv->wq); - if (mcp251x_enable_dma) { dma_free_coherent(&spi->dev, PAGE_SIZE, priv->spi_tx_buf, priv->spi_tx_dma); @@ -1089,6 +1066,12 @@ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state) struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); struct net_device *net = priv->net; + priv->force_quit = 1; + disable_irq(spi->irq); + /* + * Note: at this point neither IST nor workqueues are running. + * open/stop cannot be called anyway so locking is not needed + */ if (netif_running(net)) { netif_device_detach(net); @@ -1115,16 +1098,18 @@ static int mcp251x_can_resume(struct spi_device *spi) if (priv->after_suspend & AFTER_SUSPEND_POWER) { pdata->power_enable(1); - queue_work(priv->wq, &priv->irq_work); + queue_work(priv->wq, &priv->restart_work); } else { if (priv->after_suspend & AFTER_SUSPEND_UP) { if (pdata->transceiver_enable) pdata->transceiver_enable(1); - queue_work(priv->wq, &priv->irq_work); + queue_work(priv->wq, &priv->restart_work); } else { priv->after_suspend = 0; } } + priv->force_quit = 0; + enable_irq(spi->irq); return 0; } #else -- cgit v1.2.3 From 1621e0940294c20e302faf401f41204de7252e22 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 1 Feb 2010 09:44:19 +0000 Subject: net: CONFIG_COMPAT redux Ifdef out struct proto_ops::compat_ioctl struct proto_ops::compat_setsockopt struct proto_ops::compat_getsockopt to make structures smaller on COMPAT=n kernels. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/net.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/net.h b/include/linux/net.h index 5e8083cacc8b..4157b5d42bd6 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -174,18 +174,22 @@ struct proto_ops { struct poll_table_struct *wait); int (*ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT int (*compat_ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); +#endif int (*listen) (struct socket *sock, int len); int (*shutdown) (struct socket *sock, int flags); int (*setsockopt)(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen); int (*getsockopt)(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); +#ifdef CONFIG_COMPAT int (*compat_setsockopt)(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen); int (*compat_getsockopt)(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen); +#endif int (*sendmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len); int (*recvmsg) (struct kiocb *iocb, struct socket *sock, -- cgit v1.2.3 From 3fbd9187d004149fb8a98c9cb51ef9f4a4f66aca Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 1 Feb 2010 13:45:41 +0000 Subject: sky2: hand receive DMA mapping failures If receive buffer mapping failed, then it was possible to get stuck with unmapped receive buffer in DMA ring. This would be an extremely rare condition because the driver had just released the map for the last receive so it should be able to get another map again (in soft-irq). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 61 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a6ddfc1a9cb2..72c92495a9b3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1103,18 +1103,39 @@ static int sky2_rx_map_skb(struct pci_dev *pdev, struct rx_ring_info *re, int i; re->data_addr = pci_map_single(pdev, skb->data, size, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(pdev, re->data_addr))) - return -EIO; + if (pci_dma_mapping_error(pdev, re->data_addr)) + goto mapping_error; pci_unmap_len_set(re, data_size, size); - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) - re->frag_addr[i] = pci_map_page(pdev, - skb_shinfo(skb)->frags[i].page, - skb_shinfo(skb)->frags[i].page_offset, - skb_shinfo(skb)->frags[i].size, + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + re->frag_addr[i] = pci_map_page(pdev, frag->page, + frag->page_offset, + frag->size, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(pdev, re->frag_addr[i])) + goto map_page_error; + } return 0; + +map_page_error: + while (--i >= 0) { + pci_unmap_page(pdev, re->frag_addr[i], + skb_shinfo(skb)->frags[i].size, + PCI_DMA_FROMDEVICE); + } + + pci_unmap_single(pdev, re->data_addr, pci_unmap_len(re, data_size), + PCI_DMA_FROMDEVICE); + +mapping_error: + if (net_ratelimit()) + dev_warn(&pdev->dev, "%s: rx mapping error\n", + skb->dev->name); + return -EIO; } static void sky2_rx_unmap_skb(struct pci_dev *pdev, struct rx_ring_info *re) @@ -2306,30 +2327,32 @@ static struct sk_buff *receive_new(struct sky2_port *sky2, struct rx_ring_info *re, unsigned int length) { - struct sk_buff *skb, *nskb; + struct sk_buff *skb; + struct rx_ring_info nre; unsigned hdr_space = sky2->rx_data_size; - /* Don't be tricky about reusing pages (yet) */ - nskb = sky2_rx_alloc(sky2); - if (unlikely(!nskb)) - return NULL; + nre.skb = sky2_rx_alloc(sky2); + if (unlikely(!nre.skb)) + goto nobuf; + + if (sky2_rx_map_skb(sky2->hw->pdev, &nre, hdr_space)) + goto nomap; skb = re->skb; sky2_rx_unmap_skb(sky2->hw->pdev, re); - prefetch(skb->data); - re->skb = nskb; - if (sky2_rx_map_skb(sky2->hw->pdev, re, hdr_space)) { - dev_kfree_skb(nskb); - re->skb = skb; - return NULL; - } + *re = nre; if (skb_shinfo(skb)->nr_frags) skb_put_frags(skb, hdr_space, length); else skb_put(skb, length); return skb; + +nomap: + dev_kfree_skb(nre.skb); +nobuf: + return NULL; } /* -- cgit v1.2.3 From 90c30335a70e96b8b8493b7deb15e6b30e6d9fce Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 3 Feb 2010 08:31:12 +0000 Subject: sky2: Flow control frames recorded as dropped packets Thanks for your patch. A more general solution would be to move the rx_dropped up into sky2_receive. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 72c92495a9b3..744362272e2d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2404,6 +2404,9 @@ okay: skb = receive_copy(sky2, re, length); else skb = receive_new(sky2, re, length); + + dev->stats.rx_dropped += (skb == NULL); + resubmit: sky2_rx_submit(sky2, re); @@ -2515,11 +2518,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) case OP_RXSTAT: total_packets[port]++; total_bytes[port] += length; + skb = sky2_receive(dev, length, status); - if (unlikely(!skb)) { - dev->stats.rx_dropped++; + if (!skb) break; - } /* This chip reports checksum status differently */ if (hw->flags & SKY2_HW_NEW_LE) { -- cgit v1.2.3 From ae06b8330aefb0338017c427d5694fc8ea9144c8 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Thu, 4 Feb 2010 09:21:28 -0800 Subject: can: ems_usb: removed duplicated code setting local echo support Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: David S. Miller --- drivers/net/can/usb/ems_usb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index bfab283ba9b1..11c87840cc00 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -1024,8 +1024,6 @@ static int ems_usb_probe(struct usb_interface *intf, dev->can.do_set_mode = ems_usb_set_mode; dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; - netdev->flags |= IFF_ECHO; /* we support local echo */ - netdev->netdev_ops = &ems_usb_netdev_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ -- cgit v1.2.3 From 1b924032533033a4dae1a239981677bdae21949b Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Thu, 4 Feb 2010 09:33:21 -0800 Subject: stmmac: fix 'lenght' typo in comments and code Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/stmmac/common.h | 2 +- drivers/net/stmmac/dwmac100.c | 2 +- drivers/net/stmmac/dwmac1000_dma.c | 4 ++-- drivers/net/stmmac/stmmac_ethtool.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/stmmac/common.h b/drivers/net/stmmac/common.h index 7267bcd43d06..2a58172e986a 100644 --- a/drivers/net/stmmac/common.h +++ b/drivers/net/stmmac/common.h @@ -44,7 +44,7 @@ struct stmmac_extra_stats { unsigned long rx_toolong; unsigned long rx_collision; unsigned long rx_crc; - unsigned long rx_lenght; + unsigned long rx_length; unsigned long rx_mii; unsigned long rx_multicast; unsigned long rx_gmac_overflow; diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c index 82dde774d4c5..ac48ed787040 100644 --- a/drivers/net/stmmac/dwmac100.c +++ b/drivers/net/stmmac/dwmac100.c @@ -265,7 +265,7 @@ static int dwmac100_get_rx_frame_status(void *data, ret = discard_frame; if (unlikely(p->des01.rx.length_error)) { - x->rx_lenght++; + x->rx_length++; ret = discard_frame; } if (unlikely(p->des01.rx.mii_error)) { diff --git a/drivers/net/stmmac/dwmac1000_dma.c b/drivers/net/stmmac/dwmac1000_dma.c index 68245508e2de..39d436a2da68 100644 --- a/drivers/net/stmmac/dwmac1000_dma.c +++ b/drivers/net/stmmac/dwmac1000_dma.c @@ -230,7 +230,7 @@ static int dwmac1000_coe_rdes0(int ipc_err, int type, int payload_err) /* bits 5 7 0 | Frame status * ---------------------------------------------------------- - * 0 0 0 | IEEE 802.3 Type frame (lenght < 1536 octects) + * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects) * 1 0 0 | IPv4/6 No CSUM errorS. * 1 0 1 | IPv4/6 CSUM PAYLOAD error * 1 1 0 | IPv4/6 CSUM IP HR error @@ -331,7 +331,7 @@ static int dwmac1000_get_rx_frame_status(void *data, } if (unlikely(p->des01.erx.length_error)) { DBG(KERN_ERR "GMAC RX: length_error error\n"); - x->rx_lenght++; + x->rx_length++; ret = discard_frame; } #ifdef STMMAC_VLAN_TAG_USED diff --git a/drivers/net/stmmac/stmmac_ethtool.c b/drivers/net/stmmac/stmmac_ethtool.c index 0abeff6193a1..c021eaa3ca69 100644 --- a/drivers/net/stmmac/stmmac_ethtool.c +++ b/drivers/net/stmmac/stmmac_ethtool.c @@ -62,7 +62,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = { STMMAC_STAT(rx_toolong), STMMAC_STAT(rx_collision), STMMAC_STAT(rx_crc), - STMMAC_STAT(rx_lenght), + STMMAC_STAT(rx_length), STMMAC_STAT(rx_mii), STMMAC_STAT(rx_multicast), STMMAC_STAT(rx_gmac_overflow), -- cgit v1.2.3 From 6683ece36e3531fc8c75f69e7165c5f20930be88 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 4 Feb 2010 10:22:25 -0800 Subject: net: use helpers to access mc list V2 This patch introduces the similar helpers as those already done for uc list. However multicast lists are no list_head lists but "mademanually". The three macros added by this patch will make the transition of mc_list to list_head smooth in two steps: 1) convert all drivers to use these macros (with the original iterator of type "struct dev_mc_list") 2) once all drivers are converted, convert list type and iterators to "struct netdev_hw_addr" in one patch. >From now on, drivers can (and should) use "netdev_for_each_mc_addr" to iterate over the addresses with iterator of type "struct netdev_hw_addr". Also macros "netdev_mc_count" and "netdev_mc_empty" to read list's length. This is the state which should be reached in all drivers. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 622ba5aa93c4..e535700a3b72 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -268,6 +268,12 @@ struct netdev_hw_addr_list { #define netdev_for_each_uc_addr(ha, dev) \ list_for_each_entry(ha, &dev->uc.list, list) +#define netdev_mc_count(dev) ((dev)->mc_count) +#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) + +#define netdev_for_each_mc_addr(mclist, dev) \ + for (mclist = dev->mc_list; mclist; mclist = mclist->next) + struct hh_cache { struct hh_cache *hh_next; /* Next entry */ atomic_t hh_refcnt; /* number of users */ -- cgit v1.2.3 From f8f76db1db369f3a130ac3fd33e2eee5f1610d9c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 4 Feb 2010 10:23:02 -0800 Subject: libphy: add phy_find_first function Many drivers do this in them manually. Now they can use this function. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 16 ++++++++++++++++ include/linux/phy.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index adbc0fded130..db1794546c56 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -276,6 +276,22 @@ int phy_device_register(struct phy_device *phydev) } EXPORT_SYMBOL(phy_device_register); +/** + * phy_find_first - finds the first PHY device on the bus + * @bus: the target MII bus + */ +struct phy_device *phy_find_first(struct mii_bus *bus) +{ + int addr; + + for (addr = 0; addr < PHY_MAX_ADDR; addr++) { + if (bus->phy_map[addr]) + return bus->phy_map[addr]; + } + return NULL; +} +EXPORT_SYMBOL(phy_find_first); + /** * phy_prepare_link - prepares the PHY layer to monitor link status * @phydev: target phy_device struct diff --git a/include/linux/phy.h b/include/linux/phy.h index 6a7eb402165d..14d7fdf6a90a 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -452,6 +452,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, u32 flags, phy_interface_t interface); struct phy_device * phy_attach(struct net_device *dev, const char *bus_id, u32 flags, phy_interface_t interface); +struct phy_device *phy_find_first(struct mii_bus *bus); int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, void (*handler)(struct net_device *), u32 flags, phy_interface_t interface); -- cgit v1.2.3 From 15c052fc7f4a1b3544602be8af77e31bba9261bf Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Thu, 4 Feb 2010 13:32:46 -0800 Subject: qlge: Add watchdog timer. Add periodic heartbeat register read to trigger the eeh recovery process. We see cases where an eeh error was injected and the slot was suspended. An asic access attempt is required to flush the recovery process, but without interrupts the process can stall. Adding this periodic register read causes the recovery process to begin. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 780a38731bcc..ebfd17776b53 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2145,6 +2145,7 @@ struct ql_adapter { struct completion ide_completion; struct nic_operations *nic_ops; u16 device_id; + struct timer_list timer; atomic_t lb_count; }; diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 7e000295f359..87a40d168b36 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4574,6 +4574,21 @@ static const struct net_device_ops qlge_netdev_ops = { .ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid, }; +static void ql_timer(unsigned long data) +{ + struct ql_adapter *qdev = (struct ql_adapter *)data; + u32 var = 0; + + var = ql_read32(qdev, STS); + if (pci_channel_offline(qdev->pdev)) { + QPRINTK(qdev, IFUP, ERR, "EEH STS = 0x%.08x.\n", var); + return; + } + + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); +} + static int __devinit qlge_probe(struct pci_dev *pdev, const struct pci_device_id *pci_entry) { @@ -4625,6 +4640,14 @@ static int __devinit qlge_probe(struct pci_dev *pdev, pci_disable_device(pdev); return err; } + /* Start up the timer to trigger EEH if + * the bus goes dead + */ + init_timer_deferrable(&qdev->timer); + qdev->timer.data = (unsigned long)qdev; + qdev->timer.function = ql_timer; + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); ql_link_off(qdev); ql_display_dev_info(ndev); atomic_set(&qdev->lb_count, 0); @@ -4645,6 +4668,8 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget) static void __devexit qlge_remove(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); + struct ql_adapter *qdev = netdev_priv(ndev); + del_timer_sync(&qdev->timer); unregister_netdev(ndev); ql_release_all(pdev); pci_disable_device(pdev); @@ -4757,6 +4782,8 @@ static void qlge_io_resume(struct pci_dev *pdev) QPRINTK(qdev, IFUP, ERR, "Device was not running prior to EEH.\n"); } + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); netif_device_attach(ndev); } @@ -4773,6 +4800,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) int err; netif_device_detach(ndev); + del_timer_sync(&qdev->timer); if (netif_running(ndev)) { err = ql_adapter_down(qdev); @@ -4817,6 +4845,8 @@ static int qlge_resume(struct pci_dev *pdev) return err; } + qdev->timer.expires = jiffies + (5*HZ); + add_timer(&qdev->timer); netif_device_attach(ndev); return 0; -- cgit v1.2.3 From b0f83b280fcfa9cdd66b748f0c12fb26ce69e391 Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Thu, 4 Feb 2010 13:36:50 -0800 Subject: doc: document IPv6 parameters Update documentation to describe IPv6 parameters. Reported by . Signed-off-by: Brian Haley Signed-off-by: David S. Miller --- Documentation/kernel-parameters.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 736d45602886..3ca7f8f56525 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -54,6 +54,7 @@ parameter is applicable: IMA Integrity measurement architecture is enabled. IOSCHED More than one I/O scheduler is enabled. IP_PNP IP DHCP, BOOTP, or RARP is enabled. + IPV6 IPv6 support is enabled. ISAPNP ISA PnP code is enabled. ISDN Appropriate ISDN support is enabled. JOY Appropriate joystick support is enabled. @@ -347,6 +348,9 @@ and is between 256 and 4096 characters. It is defined in the file Change the amount of debugging information output when initialising the APIC and IO-APIC components. + autoconf= [IPV6] + See Documentation/networking/ipv6.txt. + show_lapic= [APIC,X86] Advanced Programmable Interrupt Controller Limit apic dumping. The parameter defines the maximal number of local apics being dumped. Also it is possible @@ -629,6 +633,12 @@ and is between 256 and 4096 characters. It is defined in the file See drivers/char/README.epca and Documentation/serial/digiepca.txt. + disable= [IPV6] + See Documentation/networking/ipv6.txt. + + disable_ipv6= [IPV6] + See Documentation/networking/ipv6.txt. + disable_mtrr_cleanup [X86] The kernel tries to adjust MTRR layout from continuous to discrete, to make X server driver able to add WB -- cgit v1.2.3 From d088dde7b19628f386c486f16cd471f5b5682ca8 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Wed, 3 Feb 2010 06:05:54 +0000 Subject: ipv4: obsolete config in kernel source (IP_ROUTE_PERVASIVE) CONFIG_IP_ROUTE_PERVASIVE is missing a corresponding config IP_ROUTE_PERVASIVE somewhere in KConfig (and missing it for ages already) so it looks like some aging artefact no longer needed. Therefor this patch kills of the only remaining reference to that config Item removing the already unrechable code snipet. Signed-off-by: Christoph Egger Signed-off-by: David S. Miller --- net/ipv4/fib_semantics.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 96b21011a3e4..1af0ea0fb6a2 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -528,10 +528,6 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, if (nh->nh_gw) { struct fib_result res; -#ifdef CONFIG_IP_ROUTE_PERVASIVE - if (nh->nh_flags&RTNH_F_PERVASIVE) - return 0; -#endif if (nh->nh_flags&RTNH_F_ONLINK) { struct net_device *dev; -- cgit v1.2.3 From e0fee99fce97af37b1db6ed8dd6951fb9a8d7201 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 4 Feb 2010 10:11:18 +0000 Subject: qlge: removing unreachable block of code Currently the qlge_change_mtu() is never called if the new_mtu is equal current MTU, due this condition on dev_set_mtu(): if (new_mtu == dev->mtu) return 0; So, this block of code is never reached and is being removed. Signed-off-by: Breno Leitao Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 87a40d168b36..0c9e00f36cd9 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4123,9 +4123,6 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n"); } else if (ndev->mtu == 9000 && new_mtu == 1500) { QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n"); - } else if ((ndev->mtu == 1500 && new_mtu == 1500) || - (ndev->mtu == 9000 && new_mtu == 9000)) { - return 0; } else return -EINVAL; -- cgit v1.2.3 From 746079dabcf74be2a16dc983ac597156e3d2e051 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Thu, 4 Feb 2010 10:11:19 +0000 Subject: qlge: Code clean up Just reordering this assignment that doesn't depend on any condition. Signed-off-by: Breno Leitao Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 0c9e00f36cd9..3cb60e10d456 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4129,12 +4129,12 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) queue_delayed_work(qdev->workqueue, &qdev->mpi_port_cfg_work, 3*HZ); + ndev->mtu = new_mtu; + if (!netif_running(qdev->ndev)) { - ndev->mtu = new_mtu; return 0; } - ndev->mtu = new_mtu; status = ql_change_rx_buffers(qdev); if (status) { QPRINTK(qdev, IFUP, ERR, -- cgit v1.2.3 From bfd5f4a3d605e0f6054df0b59fe0907ff7e696d3 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Thu, 4 Feb 2010 20:24:10 -0800 Subject: packet: Add GSO/csum offload support. This patch adds GSO/checksum offload to af_packet sockets using virtio_net_hdr. Based on Rusty's patch to add this support to tun. It allows GSO/checksum offload to be enabled when using raw socket backend with virtio_net. Adds PACKET_VNET_HDR socket option to prepend virtio_net_hdr in the receive path and process/skip virtio_net_hdr in the send path. This option is only allowed with SOCK_RAW sockets attached to ethernet type devices. v2 updates ---------- Michael's Comments - Perform length check in packet_snd() when GSO is off even when vnet_hdr is present. - Check for SKB_GSO_FCOE type and return -EINVAL - don't allow tx/rx ring when vnet_hdr is enabled. Herbert's Comments - Removed ethernet specific code. - protocol value is assumed to be passed in by the caller. Signed-off-by: Sridhar Samudrala Signed-off-by: David S. Miller --- include/linux/if_packet.h | 1 + net/packet/af_packet.c | 187 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 177 insertions(+), 11 deletions(-) diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h index 4021d47cc437..aa57a5f993fc 100644 --- a/include/linux/if_packet.h +++ b/include/linux/if_packet.h @@ -46,6 +46,7 @@ struct sockaddr_ll { #define PACKET_RESERVE 12 #define PACKET_TX_RING 13 #define PACKET_LOSS 14 +#define PACKET_VNET_HDR 15 struct tpacket_stats { unsigned int tp_packets; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 53633c5fdb1d..178e2937bbaa 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -80,6 +80,7 @@ #include #include #include +#include #ifdef CONFIG_INET #include @@ -193,7 +194,8 @@ struct packet_sock { struct mutex pg_vec_lock; unsigned int running:1, /* prot_hook is attached*/ auxdata:1, - origdev:1; + origdev:1, + has_vnet_hdr:1; int ifindex; /* bound device */ __be16 num; struct packet_mclist *mclist; @@ -1056,6 +1058,30 @@ out: } #endif +static inline struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad, + size_t reserve, size_t len, + size_t linear, int noblock, + int *err) +{ + struct sk_buff *skb; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + err); + if (!skb) + return NULL; + + skb_reserve(skb, reserve); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) { @@ -1066,14 +1092,17 @@ static int packet_snd(struct socket *sock, __be16 proto; unsigned char *addr; int ifindex, err, reserve = 0; + struct virtio_net_hdr vnet_hdr = { 0 }; + int offset = 0; + int vnet_hdr_len; + struct packet_sock *po = pkt_sk(sk); + unsigned short gso_type = 0; /* * Get and verify the address. */ if (saddr == NULL) { - struct packet_sock *po = pkt_sk(sk); - ifindex = po->ifindex; proto = po->num; addr = NULL; @@ -1100,25 +1129,74 @@ static int packet_snd(struct socket *sock, if (!(dev->flags & IFF_UP)) goto out_unlock; + if (po->has_vnet_hdr) { + vnet_hdr_len = sizeof(vnet_hdr); + + err = -EINVAL; + if (len < vnet_hdr_len) + goto out_unlock; + + len -= vnet_hdr_len; + + err = memcpy_fromiovec((void *)&vnet_hdr, msg->msg_iov, + vnet_hdr_len); + if (err < 0) + goto out_unlock; + + if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + (vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > + vnet_hdr.hdr_len)) + vnet_hdr.hdr_len = vnet_hdr.csum_start + + vnet_hdr.csum_offset + 2; + + err = -EINVAL; + if (vnet_hdr.hdr_len > len) + goto out_unlock; + + if (vnet_hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { + switch (vnet_hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_TCPV6: + gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: + gso_type = SKB_GSO_UDP; + break; + default: + goto out_unlock; + } + + if (vnet_hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) + gso_type |= SKB_GSO_TCP_ECN; + + if (vnet_hdr.gso_size == 0) + goto out_unlock; + + } + } + err = -EMSGSIZE; - if (len > dev->mtu+reserve) + if (!gso_type && (len > dev->mtu+reserve)) goto out_unlock; - skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev), - msg->msg_flags & MSG_DONTWAIT, &err); + err = -ENOBUFS; + skb = packet_alloc_skb(sk, LL_ALLOCATED_SPACE(dev), + LL_RESERVED_SPACE(dev), len, vnet_hdr.hdr_len, + msg->msg_flags & MSG_DONTWAIT, &err); if (skb == NULL) goto out_unlock; - skb_reserve(skb, LL_RESERVED_SPACE(dev)); - skb_reset_network_header(skb); + skb_set_network_header(skb, reserve); err = -EINVAL; if (sock->type == SOCK_DGRAM && - dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len) < 0) + (offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len)) < 0) goto out_free; /* Returns -EFAULT on error */ - err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); + err = skb_copy_datagram_from_iovec(skb, offset, msg->msg_iov, 0, len); if (err) goto out_free; @@ -1127,6 +1205,25 @@ static int packet_snd(struct socket *sock, skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; + if (po->has_vnet_hdr) { + if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + if (!skb_partial_csum_set(skb, vnet_hdr.csum_start, + vnet_hdr.csum_offset)) { + err = -EINVAL; + goto out_free; + } + } + + skb_shinfo(skb)->gso_size = vnet_hdr.gso_size; + skb_shinfo(skb)->gso_type = gso_type; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + + len += vnet_hdr_len; + } + /* * Now send it */ @@ -1420,6 +1517,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int copied, err; struct sockaddr_ll *sll; + int vnet_hdr_len = 0; err = -EINVAL; if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) @@ -1451,6 +1549,48 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, if (skb == NULL) goto out; + if (pkt_sk(sk)->has_vnet_hdr) { + struct virtio_net_hdr vnet_hdr = { 0 }; + + err = -EINVAL; + vnet_hdr_len = sizeof(vnet_hdr); + if ((len -= vnet_hdr_len) < 0) + goto out_free; + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + vnet_hdr.hdr_len = skb_headlen(skb); + vnet_hdr.gso_size = sinfo->gso_size; + if (sinfo->gso_type & SKB_GSO_TCPV4) + vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else if (sinfo->gso_type & SKB_GSO_UDP) + vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; + else if (sinfo->gso_type & SKB_GSO_FCOE) + goto out_free; + else + BUG(); + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + vnet_hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + vnet_hdr.csum_start = skb->csum_start - + skb_headroom(skb); + vnet_hdr.csum_offset = skb->csum_offset; + } /* else everything is zero */ + + err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr, + vnet_hdr_len); + if (err < 0) + goto out_free; + } + /* * If the address length field is there to be filled in, we fill * it in now. @@ -1502,7 +1642,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, * Free or return the buffer as appropriate. Again this * hides all the races and re-entrancy issues from us. */ - err = (flags&MSG_TRUNC) ? skb->len : copied; + err = vnet_hdr_len + ((flags&MSG_TRUNC) ? skb->len : copied); out_free: skb_free_datagram(sk, skb); @@ -1740,6 +1880,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv if (optlen < sizeof(req)) return -EINVAL; + if (pkt_sk(sk)->has_vnet_hdr) + return -EINVAL; if (copy_from_user(&req, optval, sizeof(req))) return -EFAULT; return packet_set_ring(sk, &req, 0, optname == PACKET_TX_RING); @@ -1826,6 +1968,22 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv po->origdev = !!val; return 0; } + case PACKET_VNET_HDR: + { + int val; + + if (sock->type != SOCK_RAW) + return -EINVAL; + if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) + return -EBUSY; + if (optlen < sizeof(val)) + return -EINVAL; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + + po->has_vnet_hdr = !!val; + return 0; + } default: return -ENOPROTOOPT; } @@ -1874,6 +2032,13 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, len = sizeof(int); val = po->origdev; + data = &val; + break; + case PACKET_VNET_HDR: + if (len > sizeof(int)) + len = sizeof(int); + val = po->has_vnet_hdr; + data = &val; break; #ifdef CONFIG_PACKET_MMAP -- cgit v1.2.3 From 570930fe1ee497de6aafd895dbe80116cb10525f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 4 Feb 2010 20:28:48 -0800 Subject: bridge: Remove unused age_list This patch removes the unused age_list member from the net_bridge structure. Signed-off-by: Herbert Xu Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 2 -- net/bridge/br_private.h | 1 - 2 files changed, 3 deletions(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 7bc0604069c7..bc2b1badab88 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -206,8 +206,6 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name) br_netfilter_rtable_init(br); - INIT_LIST_HEAD(&br->age_list); - br_stp_timer_init(br); return dev; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 2114e45682ea..1f0c4f44b765 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -93,7 +93,6 @@ struct net_bridge struct net_device *dev; spinlock_t hash_lock; struct hlist_head hash[BR_HASH_SIZE]; - struct list_head age_list; unsigned long feature_mask; #ifdef CONFIG_BRIDGE_NETFILTER struct rtable fake_rtable; -- cgit v1.2.3 From b405e8df26dfe4c56ab3f88f5cc1dfab0d220289 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 4 Feb 2010 22:31:41 -0800 Subject: e1000e: Fix namespace conflicts wrt. e1000_has_link Reported by Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 2 +- drivers/net/e1000e/ethtool.c | 2 +- drivers/net/e1000e/netdev.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 318bdb28a7cd..c2ec095d2163 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -459,7 +459,7 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); extern void e1000e_update_stats(struct e1000_adapter *adapter); -extern bool e1000_has_link(struct e1000_adapter *adapter); +extern bool e1000e_has_link(struct e1000_adapter *adapter); extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 0aa50c229c79..b33e3cbe9ab0 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -202,7 +202,7 @@ static u32 e1000_get_link(struct net_device *netdev) if (!netif_carrier_ok(netdev)) mac->get_link_status = 1; - return e1000_has_link(adapter); + return e1000e_has_link(adapter); } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 14a80f8f6118..ffa37c682a00 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3472,7 +3472,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter) ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" ))); } -bool e1000_has_link(struct e1000_adapter *adapter) +bool e1000e_has_link(struct e1000_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; bool link_active = 0; @@ -3553,7 +3553,7 @@ static void e1000_watchdog_task(struct work_struct *work) u32 link, tctl; int tx_pending = 0; - link = e1000_has_link(adapter); + link = e1000e_has_link(adapter); if ((netif_carrier_ok(netdev)) && link) { e1000e_enable_receives(adapter); goto link_up; -- cgit v1.2.3 From a56ed41d94f80e4342116318754878a045835f40 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 5 Feb 2010 02:47:28 +0000 Subject: net: 8139cp: convert to use mc helpers Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/8139cp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 9d59654748b1..60bc0b0ad4f3 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -899,7 +899,7 @@ static void __cp_set_rx_mode (struct net_device *dev) { struct cp_private *cp = netdev_priv(dev); u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; + int rx_mode; u32 tmp; /* Note: do not reorder, GCC is clever about common statements. */ @@ -909,7 +909,7 @@ static void __cp_set_rx_mode (struct net_device *dev) AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; @@ -918,8 +918,7 @@ static void __cp_set_rx_mode (struct net_device *dev) struct dev_mc_list *mclist; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); -- cgit v1.2.3 From 6d55ad4a534e7de3417819c6e894ff1c0a38f626 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 5 Feb 2010 02:48:11 +0000 Subject: net: 8139too: convert to use mc helpers Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/8139too.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index 321e73aabb2b..c7d6f094cc7a 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -2509,7 +2509,7 @@ static void __set_rx_mode (struct net_device *dev) struct rtl8139_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; + int rx_mode; u32 tmp; pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", @@ -2521,7 +2521,7 @@ static void __set_rx_mode (struct net_device *dev) AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; @@ -2530,8 +2530,7 @@ static void __set_rx_mode (struct net_device *dev) struct dev_mc_list *mclist; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); -- cgit v1.2.3 From 2cc04d27c497af9e8d11181fa8ddef9c99592c78 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 5 Feb 2010 02:51:24 +0000 Subject: net: dm9601: convert to use mc helpers Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/usb/dm9601.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 3d406f9b2f29..c820fec62041 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -381,13 +381,13 @@ static void dm9601_set_multicast(struct net_device *net) if (net->flags & IFF_PROMISC) { rx_ctl |= 0x02; - } else if (net->flags & IFF_ALLMULTI || net->mc_count > DM_MAX_MCAST) { + } else if (net->flags & IFF_ALLMULTI || + netdev_mc_count(net) > DM_MAX_MCAST) { rx_ctl |= 0x04; - } else if (net->mc_count) { - struct dev_mc_list *mc_list = net->mc_list; - int i; + } else if (!netdev_mc_empty(net)) { + struct dev_mc_list *mc_list; - for (i = 0; i < net->mc_count; i++, mc_list = mc_list->next) { + netdev_for_each_mc_addr(mc_list, net) { u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; hashes[crc >> 3] |= 1 << (crc & 0x7); } -- cgit v1.2.3 From 7aeef972cce30b0ab04047e07918b04d867e7a29 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 5 Feb 2010 02:52:39 +0000 Subject: net: e1000e: convert to use mc helpers Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index ffa37c682a00..88d54d3efcef 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2589,21 +2589,16 @@ static void e1000_set_multi(struct net_device *netdev) ew32(RCTL, rctl); - if (netdev->mc_count) { - mta_list = kmalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!netdev_mc_empty(netdev)) { + mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC); if (!mta_list) return; /* prepare a packed array of only addresses. */ - mc_ptr = netdev->mc_list; - - for (i = 0; i < netdev->mc_count; i++) { - if (!mc_ptr) - break; - memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, - ETH_ALEN); - mc_ptr = mc_ptr->next; - } + i = 0; + netdev_for_each_mc_addr(mc_ptr, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), + mc_ptr->dmi_addr, ETH_ALEN); e1000_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); -- cgit v1.2.3 From 889b8f964f2f226b7cd5a0a515109e3d8d9d1613 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 5 Feb 2010 16:29:48 -0800 Subject: packet: Kill CONFIG_PACKET_MMAP. Early on this was an experimental facility that few people other than Alexey Kuznetsov played with. Now it's a pretty fundamental thing and as people add more features to AF_PACKET sockets this config options creates ifdef spaghetti. So kill it off. Signed-off-by: David S. Miller --- Documentation/networking/packet_mmap.txt | 8 ++++---- net/packet/Kconfig | 10 ---------- net/packet/af_packet.c | 29 ----------------------------- 3 files changed, 4 insertions(+), 43 deletions(-) diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index a22fd85e3796..09ab0d290326 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt @@ -2,7 +2,7 @@ + ABSTRACT -------------------------------------------------------------------------------- -This file documents the CONFIG_PACKET_MMAP option available with the PACKET +This file documents the mmap() facility available with the PACKET socket interface on 2.4 and 2.6 kernels. This type of sockets is used for capture network traffic with utilities like tcpdump or any other that needs raw access to network interface. @@ -44,7 +44,7 @@ enabled. For transmission, check the MTU (Maximum Transmission Unit) used and supported by devices of your network. -------------------------------------------------------------------------------- -+ How to use CONFIG_PACKET_MMAP to improve capture process ++ How to use mmap() to improve capture process -------------------------------------------------------------------------------- From the user standpoint, you should use the higher level libpcap library, which @@ -64,7 +64,7 @@ the low level details or want to improve libpcap by including PACKET_MMAP support. -------------------------------------------------------------------------------- -+ How to use CONFIG_PACKET_MMAP directly to improve capture process ++ How to use mmap() directly to improve capture process -------------------------------------------------------------------------------- From the system calls stand point, the use of PACKET_MMAP involves @@ -105,7 +105,7 @@ also the mapping of the circular buffer in the user process and the use of this buffer. -------------------------------------------------------------------------------- -+ How to use CONFIG_PACKET_MMAP directly to improve transmission process ++ How to use mmap() directly to improve transmission process -------------------------------------------------------------------------------- Transmission process is similar to capture as shown below. diff --git a/net/packet/Kconfig b/net/packet/Kconfig index 34ff93ff894d..0060e3b396b7 100644 --- a/net/packet/Kconfig +++ b/net/packet/Kconfig @@ -14,13 +14,3 @@ config PACKET be called af_packet. If unsure, say Y. - -config PACKET_MMAP - bool "Packet socket: mmapped IO" - depends on PACKET - help - If you say Y here, the Packet protocol driver will use an IO - mechanism that results in faster communication. - - If unsure, say N. - diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 178e2937bbaa..6ecb426bc0cf 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -157,7 +157,6 @@ struct packet_mreq_max { unsigned char mr_address[MAX_ADDR_LEN]; }; -#ifdef CONFIG_PACKET_MMAP static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing, int tx_ring); @@ -177,7 +176,6 @@ struct packet_ring_buffer { struct packet_sock; static int tpacket_snd(struct packet_sock *po, struct msghdr *msg); -#endif static void packet_flush_mclist(struct sock *sk); @@ -185,11 +183,9 @@ struct packet_sock { /* struct sock has to be the first member of packet_sock */ struct sock sk; struct tpacket_stats stats; -#ifdef CONFIG_PACKET_MMAP struct packet_ring_buffer rx_ring; struct packet_ring_buffer tx_ring; int copy_thresh; -#endif spinlock_t bind_lock; struct mutex pg_vec_lock; unsigned int running:1, /* prot_hook is attached*/ @@ -199,13 +195,11 @@ struct packet_sock { int ifindex; /* bound device */ __be16 num; struct packet_mclist *mclist; -#ifdef CONFIG_PACKET_MMAP atomic_t mapped; enum tpacket_versions tp_version; unsigned int tp_hdrlen; unsigned int tp_reserve; unsigned int tp_loss:1; -#endif struct packet_type prot_hook ____cacheline_aligned_in_smp; }; @@ -219,8 +213,6 @@ struct packet_skb_cb { #define PACKET_SKB_CB(__skb) ((struct packet_skb_cb *)((__skb)->cb)) -#ifdef CONFIG_PACKET_MMAP - static void __packet_set_status(struct packet_sock *po, void *frame, int status) { union { @@ -315,8 +307,6 @@ static inline void packet_increment_head(struct packet_ring_buffer *buff) buff->head = buff->head != buff->frame_max ? buff->head+1 : 0; } -#endif - static inline struct packet_sock *pkt_sk(struct sock *sk) { return (struct packet_sock *)sk; @@ -640,7 +630,6 @@ drop: return 0; } -#ifdef CONFIG_PACKET_MMAP static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { @@ -1056,7 +1045,6 @@ out: mutex_unlock(&po->pg_vec_lock); return err; } -#endif static inline struct sk_buff *packet_alloc_skb(struct sock *sk, size_t prepad, size_t reserve, size_t len, @@ -1248,13 +1236,11 @@ out: static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { -#ifdef CONFIG_PACKET_MMAP struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); if (po->tx_ring.pg_vec) return tpacket_snd(po, msg); else -#endif return packet_snd(sock, msg, len); } @@ -1268,9 +1254,7 @@ static int packet_release(struct socket *sock) struct sock *sk = sock->sk; struct packet_sock *po; struct net *net; -#ifdef CONFIG_PACKET_MMAP struct tpacket_req req; -#endif if (!sk) return 0; @@ -1299,7 +1283,6 @@ static int packet_release(struct socket *sock) packet_flush_mclist(sk); -#ifdef CONFIG_PACKET_MMAP memset(&req, 0, sizeof(req)); if (po->rx_ring.pg_vec) @@ -1307,7 +1290,6 @@ static int packet_release(struct socket *sock) if (po->tx_ring.pg_vec) packet_set_ring(sk, &req, 1, 1); -#endif /* * Now the socket is dead. No more input will appear. @@ -1872,7 +1854,6 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv return ret; } -#ifdef CONFIG_PACKET_MMAP case PACKET_RX_RING: case PACKET_TX_RING: { @@ -1943,7 +1924,6 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv po->tp_loss = !!val; return 0; } -#endif case PACKET_AUXDATA: { int val; @@ -2041,7 +2021,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, data = &val; break; -#ifdef CONFIG_PACKET_MMAP case PACKET_VERSION: if (len > sizeof(int)) len = sizeof(int); @@ -2077,7 +2056,6 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, val = po->tp_loss; data = &val; break; -#endif default: return -ENOPROTOOPT; } @@ -2197,11 +2175,6 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, return 0; } -#ifndef CONFIG_PACKET_MMAP -#define packet_mmap sock_no_mmap -#define packet_poll datagram_poll -#else - static unsigned int packet_poll(struct file *file, struct socket *sock, poll_table *wait) { @@ -2483,8 +2456,6 @@ out: mutex_unlock(&po->pg_vec_lock); return err; } -#endif - static const struct proto_ops packet_ops_spkt = { .family = PF_PACKET, -- cgit v1.2.3 From 76780373190d7e8ddfb6fed06aef068e2445c743 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 8 Feb 2010 15:39:16 +0100 Subject: netfilter: fix build failure with CONNTRACK=y NAT=n net/ipv4/netfilter/nf_defrag_ipv4.c: In function 'ipv4_conntrack_defrag': net/ipv4/netfilter/nf_defrag_ipv4.c:62: error: implicit declaration of function 'nf_ct_is_template' Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/nf_defrag_ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 77627fa80561..f6f46686cbc0 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -17,6 +17,7 @@ #include #include #include +#include /* Returns new sk_buff, or NULL */ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) -- cgit v1.2.3 From 690680360cd22b55235481ca3421a3450a96138a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Feb 2010 10:47:55 +0100 Subject: mac80211_hwsim: add fake hw scan handler For debugging hardware scan trigger/complete functionality, it was useful to have code in hwsim that pretends to do a hardware scan. This code could be extended to actually do the scan, but for now it was sufficient for me to only pretend. Since hwsim was written to ease debugging, it only makes sense to add it to it permanently. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 44 ++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 0dbda8dfbd99..00ffe6dd435e 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -32,6 +32,10 @@ static int radios = 2; module_param(radios, int, 0444); MODULE_PARM_DESC(radios, "Number of simulated radios"); +static bool fake_hw_scan; +module_param(fake_hw_scan, bool, 0444); +MODULE_PARM_DESC(fake_hw_scan, "Install fake (no-op) hw-scan handler"); + /** * enum hwsim_regtest - the type of regulatory tests we offer * @@ -908,8 +912,43 @@ static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) */ } +struct hw_scan_done { + struct delayed_work w; + struct ieee80211_hw *hw; +}; -static const struct ieee80211_ops mac80211_hwsim_ops = +static void hw_scan_done(struct work_struct *work) +{ + struct hw_scan_done *hsd = + container_of(work, struct hw_scan_done, w.work); + + ieee80211_scan_completed(hsd->hw, false); + kfree(hsd); +} + +static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, + struct cfg80211_scan_request *req) +{ + struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); + int i; + + if (!hsd) + return -ENOMEM; + + hsd->hw = hw; + INIT_DELAYED_WORK(&hsd->w, hw_scan_done); + + printk(KERN_DEBUG "hwsim scan request\n"); + for (i = 0; i < req->n_channels; i++) + printk(KERN_DEBUG "hwsim scan freq %d\n", + req->channels[i]->center_freq); + + ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); + + return 0; +} + +static struct ieee80211_ops mac80211_hwsim_ops = { .tx = mac80211_hwsim_tx, .start = mac80211_hwsim_start, @@ -1119,6 +1158,9 @@ static int __init init_mac80211_hwsim(void) if (radios < 1 || radios > 100) return -EINVAL; + if (fake_hw_scan) + mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; + spin_lock_init(&hwsim_radio_lock); INIT_LIST_HEAD(&hwsim_radios); -- cgit v1.2.3 From 33e5a2f776e331dc8a4379b6efb660d38f182d96 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Feb 2010 10:24:30 +0100 Subject: wireless: update radiotap parser Upstream radiotap has adopted the namespace proposal David Young made and I then took care of, for which I had adapted the radiotap parser as a library outside the kernel. This brings the in-kernel parser up to speed. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 83 ++++++++--- include/net/ieee80211_radiotap.h | 4 + net/mac80211/tx.c | 9 +- net/wireless/radiotap.c | 305 +++++++++++++++++++++++++-------------- 4 files changed, 271 insertions(+), 130 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a3f0a7ed31ac..5b3569b2a74c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1561,37 +1561,82 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, * Documentation in Documentation/networking/radiotap-headers.txt */ +struct radiotap_align_size { + uint8_t align:4, size:4; +}; + +struct ieee80211_radiotap_namespace { + const struct radiotap_align_size *align_size; + int n_bits; + uint32_t oui; + uint8_t subns; +}; + +struct ieee80211_radiotap_vendor_namespaces { + const struct ieee80211_radiotap_namespace *ns; + int n_ns; +}; + /** * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args - * @rtheader: pointer to the radiotap header we are walking through - * @max_length: length of radiotap header in cpu byte ordering - * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg - * @this_arg: pointer to current radiotap arg - * @arg_index: internal next argument index - * @arg: internal next argument pointer - * @next_bitmap: internal pointer to next present u32 - * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + * @this_arg_index: index of current arg, valid after each successful call + * to ieee80211_radiotap_iterator_next() + * @this_arg: pointer to current radiotap arg; it is valid after each + * call to ieee80211_radiotap_iterator_next() but also after + * ieee80211_radiotap_iterator_init() where it will point to + * the beginning of the actual data portion + * @this_arg_size: length of the current arg, for convenience + * @current_namespace: pointer to the current namespace definition + * (or internally %NULL if the current namespace is unknown) + * @is_radiotap_ns: indicates whether the current namespace is the default + * radiotap namespace or not + * + * @overrides: override standard radiotap fields + * @n_overrides: number of overrides + * + * @_rtheader: pointer to the radiotap header we are walking through + * @_max_length: length of radiotap header in cpu byte ordering + * @_arg_index: next argument index + * @_arg: next argument pointer + * @_next_bitmap: internal pointer to next present u32 + * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + * @_vns: vendor namespace definitions + * @_next_ns_data: beginning of the next namespace's data + * @_reset_on_ext: internal; reset the arg index to 0 when going to the + * next bitmap word + * + * Describes the radiotap parser state. Fields prefixed with an underscore + * must not be used by users of the parser, only by the parser internally. */ struct ieee80211_radiotap_iterator { - struct ieee80211_radiotap_header *rtheader; - int max_length; + struct ieee80211_radiotap_header *_rtheader; + const struct ieee80211_radiotap_vendor_namespaces *_vns; + const struct ieee80211_radiotap_namespace *current_namespace; + + unsigned char *_arg, *_next_ns_data; + uint32_t *_next_bitmap; + + unsigned char *this_arg; int this_arg_index; - u8 *this_arg; + int this_arg_size; - int arg_index; - u8 *arg; - __le32 *next_bitmap; - u32 bitmap_shifter; + int is_radiotap_ns; + + int _max_length; + int _arg_index; + uint32_t _bitmap_shifter; + int _reset_on_ext; }; extern int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length); + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns); extern int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator); + struct ieee80211_radiotap_iterator *iterator); + extern const unsigned char rfc1042_header[6]; extern const unsigned char bridge_tunnel_header[6]; diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 9d3d86aaccbb..af49f8ab7f81 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -198,6 +198,10 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, + + /* valid in every it_present bitmap, even vendor namespaces */ + IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, + IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 85e382aa894e..e392820a4c33 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1010,7 +1010,8 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, (struct ieee80211_radiotap_header *) skb->data; struct ieee80211_supported_band *sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); + int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len, + NULL); sband = tx->local->hw.wiphy->bands[tx->channel->band]; @@ -1046,7 +1047,7 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, * because it will be recomputed and added * on transmission */ - if (skb->len < (iterator.max_length + FCS_LEN)) + if (skb->len < (iterator._max_length + FCS_LEN)) return false; skb_trim(skb, skb->len - FCS_LEN); @@ -1073,10 +1074,10 @@ static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, /* * remove the radiotap header - * iterator->max_length was sanity-checked against + * iterator->_max_length was sanity-checked against * skb->len by iterator init */ - skb_pull(skb, iterator.max_length); + skb_pull(skb, iterator._max_length); return true; } diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index f591871a7b4f..1332c445d1c7 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -2,6 +2,16 @@ * Radiotap parser * * Copyright 2007 Andy Green + * Copyright 2009 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See COPYING for more details. */ #include @@ -10,6 +20,35 @@ /* function prototypes and related defs are in include/net/cfg80211.h */ +static const struct radiotap_align_size rtap_namespace_sizes[] = { + [IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, }, + [IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, }, + [IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, + [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, + /* + * add more here as they are defined in radiotap.h + */ +}; + +static const struct ieee80211_radiotap_namespace radiotap_ns = { + .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]), + .align_size = rtap_namespace_sizes, +}; + /** * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization * @iterator: radiotap_iterator to initialize @@ -50,9 +89,9 @@ */ int ieee80211_radiotap_iterator_init( - struct ieee80211_radiotap_iterator *iterator, - struct ieee80211_radiotap_header *radiotap_header, - int max_length) + struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, + int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) { /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) @@ -62,19 +101,24 @@ int ieee80211_radiotap_iterator_init( if (max_length < get_unaligned_le16(&radiotap_header->it_len)) return -EINVAL; - iterator->rtheader = radiotap_header; - iterator->max_length = get_unaligned_le16(&radiotap_header->it_len); - iterator->arg_index = 0; - iterator->bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); - iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); - iterator->this_arg = NULL; + iterator->_rtheader = radiotap_header; + iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len); + iterator->_arg_index = 0; + iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); + iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header); + iterator->_reset_on_ext = 0; + iterator->_next_bitmap = &radiotap_header->it_present; + iterator->_next_bitmap++; + iterator->_vns = vns; + iterator->current_namespace = &radiotap_ns; + iterator->is_radiotap_ns = 1; /* find payload start allowing for extended bitmap(s) */ - if (unlikely(iterator->bitmap_shifter & (1<arg) & - (1 << IEEE80211_RADIOTAP_EXT)) { - iterator->arg += sizeof(u32); + if (iterator->_bitmap_shifter & (1<_arg) & + (1 << IEEE80211_RADIOTAP_EXT)) { + iterator->_arg += sizeof(uint32_t); /* * check for insanity where the present bitmaps @@ -82,12 +126,13 @@ int ieee80211_radiotap_iterator_init( * stated radiotap header length */ - if (((ulong)iterator->arg - - (ulong)iterator->rtheader) > iterator->max_length) + if ((unsigned long)iterator->_arg - + (unsigned long)iterator->_rtheader > + (unsigned long)iterator->_max_length) return -EINVAL; } - iterator->arg += sizeof(u32); + iterator->_arg += sizeof(uint32_t); /* * no need to check again for blowing past stated radiotap @@ -96,12 +141,36 @@ int ieee80211_radiotap_iterator_init( */ } + iterator->this_arg = iterator->_arg; + /* we are all initialized happily */ return 0; } EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); +static void find_ns(struct ieee80211_radiotap_iterator *iterator, + uint32_t oui, uint8_t subns) +{ + int i; + + iterator->current_namespace = NULL; + + if (!iterator->_vns) + return; + + for (i = 0; i < iterator->_vns->n_ns; i++) { + if (iterator->_vns->ns[i].oui != oui) + continue; + if (iterator->_vns->ns[i].subns != subns) + continue; + + iterator->current_namespace = &iterator->_vns->ns[i]; + break; + } +} + + /** * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg @@ -127,99 +196,80 @@ EXPORT_SYMBOL(ieee80211_radiotap_iterator_init); */ int ieee80211_radiotap_iterator_next( - struct ieee80211_radiotap_iterator *iterator) + struct ieee80211_radiotap_iterator *iterator) { - - /* - * small length lookup table for all radiotap types we heard of - * starting from b0 in the bitmap, so we can walk the payload - * area of the radiotap header - * - * There is a requirement to pad args, so that args - * of a given length must begin at a boundary of that length - * -- but note that compound args are allowed (eg, 2 x u16 - * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not - * a reliable indicator of alignment requirement. - * - * upper nybble: content alignment for arg - * lower nybble: content length for arg - */ - - static const u8 rt_sizes[] = { - [IEEE80211_RADIOTAP_TSFT] = 0x88, - [IEEE80211_RADIOTAP_FLAGS] = 0x11, - [IEEE80211_RADIOTAP_RATE] = 0x11, - [IEEE80211_RADIOTAP_CHANNEL] = 0x24, - [IEEE80211_RADIOTAP_FHSS] = 0x22, - [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, - [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, - [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, - [IEEE80211_RADIOTAP_ANTENNA] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, - [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, - [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, - [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, - [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, - /* - * add more here as they are defined in - * include/net/ieee80211_radiotap.h - */ - }; - - /* - * for every radiotap entry we can at - * least skip (by knowing the length)... - */ - - while (iterator->arg_index < sizeof(rt_sizes)) { + while (1) { int hit = 0; - int pad; + int pad, align, size, subns, vnslen; + uint32_t oui; - if (!(iterator->bitmap_shifter & 1)) + /* if no more EXT bits, that's it */ + if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT && + !(iterator->_bitmap_shifter & 1)) + return -ENOENT; + + if (!(iterator->_bitmap_shifter & 1)) goto next_entry; /* arg not present */ + /* get alignment/size of data */ + switch (iterator->_arg_index % 32) { + case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: + case IEEE80211_RADIOTAP_EXT: + align = 1; + size = 0; + break; + case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: + align = 2; + size = 6; + break; + default: + if (!iterator->current_namespace || + iterator->_arg_index >= iterator->current_namespace->n_bits) { + if (iterator->current_namespace == &radiotap_ns) + return -ENOENT; + align = 0; + } else { + align = iterator->current_namespace->align_size[iterator->_arg_index].align; + size = iterator->current_namespace->align_size[iterator->_arg_index].size; + } + if (!align) { + /* skip all subsequent data */ + iterator->_arg = iterator->_next_ns_data; + /* give up on this namespace */ + iterator->current_namespace = NULL; + goto next_entry; + } + break; + } + /* * arg is present, account for alignment padding - * 8-bit args can be at any alignment - * 16-bit args must start on 16-bit boundary - * 32-bit args must start on 32-bit boundary - * 64-bit args must start on 64-bit boundary * - * note that total arg size can differ from alignment of - * elements inside arg, so we use upper nybble of length - * table to base alignment on - * - * also note: these alignments are ** relative to the - * start of the radiotap header **. There is no guarantee + * Note that these alignments are relative to the start + * of the radiotap header. There is no guarantee * that the radiotap header itself is aligned on any * kind of boundary. * - * the above is why get_unaligned() is used to dereference - * multibyte elements from the radiotap area + * The above is why get_unaligned() is used to dereference + * multibyte elements from the radiotap area. */ - pad = (((ulong)iterator->arg) - - ((ulong)iterator->rtheader)) & - ((rt_sizes[iterator->arg_index] >> 4) - 1); + pad = ((unsigned long)iterator->_arg - + (unsigned long)iterator->_rtheader) & (align - 1); if (pad) - iterator->arg += - (rt_sizes[iterator->arg_index] >> 4) - pad; + iterator->_arg += align - pad; /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test */ - iterator->this_arg_index = iterator->arg_index; - iterator->this_arg = iterator->arg; - hit = 1; + iterator->this_arg_index = iterator->_arg_index; + iterator->this_arg = iterator->_arg; + iterator->this_arg_size = size; /* internally move on the size of this arg */ - iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; + iterator->_arg += size; /* * check for insanity where we are given a bitmap that @@ -228,32 +278,73 @@ int ieee80211_radiotap_iterator_next( * max_length on the last arg, never exceeding it. */ - if (((ulong)iterator->arg - (ulong)iterator->rtheader) > - iterator->max_length) + if ((unsigned long)iterator->_arg - + (unsigned long)iterator->_rtheader > + (unsigned long)iterator->_max_length) return -EINVAL; - next_entry: - iterator->arg_index++; - if (unlikely((iterator->arg_index & 31) == 0)) { - /* completed current u32 bitmap */ - if (iterator->bitmap_shifter & 1) { - /* b31 was set, there is more */ - /* move to next u32 bitmap */ - iterator->bitmap_shifter = - get_unaligned_le32(iterator->next_bitmap); - iterator->next_bitmap++; - } else - /* no more bitmaps: end */ - iterator->arg_index = sizeof(rt_sizes); - } else /* just try the next bit */ - iterator->bitmap_shifter >>= 1; + /* these special ones are valid in each bitmap word */ + switch (iterator->_arg_index % 32) { + case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: + iterator->_bitmap_shifter >>= 1; + iterator->_arg_index++; + + iterator->_reset_on_ext = 1; + + vnslen = get_unaligned_le16(iterator->this_arg + 4); + iterator->_next_ns_data = iterator->_arg + vnslen; + oui = (*iterator->this_arg << 16) | + (*(iterator->this_arg + 1) << 8) | + *(iterator->this_arg + 2); + subns = *(iterator->this_arg + 3); + + find_ns(iterator, oui, subns); + + iterator->is_radiotap_ns = 0; + /* allow parsers to show this information */ + iterator->this_arg_index = + IEEE80211_RADIOTAP_VENDOR_NAMESPACE; + iterator->this_arg_size += vnslen; + if ((unsigned long)iterator->this_arg + + iterator->this_arg_size - + (unsigned long)iterator->_rtheader > + (unsigned long)(unsigned long)iterator->_max_length) + return -EINVAL; + hit = 1; + break; + case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: + iterator->_bitmap_shifter >>= 1; + iterator->_arg_index++; + + iterator->_reset_on_ext = 1; + iterator->current_namespace = &radiotap_ns; + iterator->is_radiotap_ns = 1; + break; + case IEEE80211_RADIOTAP_EXT: + /* + * bit 31 was set, there is more + * -- move to next u32 bitmap + */ + iterator->_bitmap_shifter = + get_unaligned_le32(iterator->_next_bitmap); + iterator->_next_bitmap++; + if (iterator->_reset_on_ext) + iterator->_arg_index = 0; + else + iterator->_arg_index++; + iterator->_reset_on_ext = 0; + break; + default: + /* we've got a hit! */ + hit = 1; + next_entry: + iterator->_bitmap_shifter >>= 1; + iterator->_arg_index++; + } /* if we found a valid arg earlier, return it now */ if (hit) return 0; } - - /* we don't know how to handle any more args, we're done */ - return -ENOENT; } EXPORT_SYMBOL(ieee80211_radiotap_iterator_next); -- cgit v1.2.3 From 070bb5477fb4029131aad4941d7aaf0093db0c38 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Feb 2010 13:57:46 +0100 Subject: mac80211: don't probe if we have probe response We can now easily determine whether we already have probe response information for the BSS we are asked to connect to, in which case there's little point in probing the BSS again. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86c6ad1b058d..f437284830ef 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -27,10 +27,6 @@ #include "rate.h" #include "led.h" -#define IEEE80211_AUTH_TIMEOUT (HZ / 5) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) -#define IEEE80211_ASSOC_MAX_TRIES 3 #define IEEE80211_MAX_PROBE_TRIES 5 /* @@ -1844,7 +1840,11 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, wk->probe_auth.algorithm = auth_alg; wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; - wk->type = IEEE80211_WORK_DIRECT_PROBE; + /* if we already have a probe, don't probe again */ + if (req->bss->proberesp_ies) + wk->type = IEEE80211_WORK_AUTH; + else + wk->type = IEEE80211_WORK_DIRECT_PROBE; wk->chan = req->bss->channel; wk->sdata = sdata; wk->done = ieee80211_probe_auth_done; -- cgit v1.2.3 From 34e895075e21be3e21e71d6317440d1ee7969ad0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 3 Feb 2010 13:59:58 +0100 Subject: mac80211: allow station add/remove to sleep Many drivers would like to sleep during station addition and removal, and currently have a high complexity there from not being able to. This introduces two new callbacks sta_add() and sta_remove() that drivers can implement instead of using sta_notify() and that can sleep, and the new sta_add() callback is also allowed to fail. The reason we didn't do this previously is that the IBSS code wants to insert stations from the RX path, which is a tasklet, so cannot sleep. This patch will keep the station allocation in that path, but moves adding the station to the driver out of line. Since the addition can now fail, we can have IBSS peer structs the driver rejected -- in that case we still talk to the station but never tell the driver about it in the control.sta pointer. If there will ever be a driver that has a low limit on the number of stations and that cannot talk to any stations that are not known to it, we need to do come up with a new strategy of handling larger IBSSs, maybe quicker expiry or rejecting peers. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 21 +- net/mac80211/cfg.c | 23 +- net/mac80211/driver-ops.h | 34 +++ net/mac80211/driver-trace.h | 52 ++++ net/mac80211/ibss.c | 22 +- net/mac80211/ieee80211_i.h | 18 +- net/mac80211/mesh_plink.c | 17 +- net/mac80211/mlme.c | 14 +- net/mac80211/pm.c | 10 +- net/mac80211/rx.c | 4 +- net/mac80211/sta_info.c | 731 ++++++++++++++++++++++---------------------- net/mac80211/sta_info.h | 32 +- net/mac80211/tx.c | 2 +- net/mac80211/util.c | 16 +- 14 files changed, 526 insertions(+), 470 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 74ccf30fdf8e..a19fac35259a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -814,7 +814,7 @@ enum set_key_cmd { * mac80211, any ieee80211_sta pointer you get access to must * either be protected by rcu_read_lock() explicitly or implicitly, * or you must take good care to not use such a pointer after a - * call to your sta_notify callback that removed it. + * call to your sta_remove callback that removed it. * * @addr: MAC address * @aid: AID we assigned to the station if we're an AP @@ -840,8 +840,8 @@ struct ieee80211_sta { * indicates addition and removal of a station to station table, * or if a associated station made a power state transition. * - * @STA_NOTIFY_ADD: a station was added to the station table - * @STA_NOTIFY_REMOVE: a station being removed from the station table + * @STA_NOTIFY_ADD: (DEPRECATED) a station was added to the station table + * @STA_NOTIFY_REMOVE: (DEPRECATED) a station being removed from the station table * @STA_NOTIFY_SLEEP: a station is now sleeping * @STA_NOTIFY_AWAKE: a sleeping station woke up */ @@ -1534,9 +1534,14 @@ enum ieee80211_ampdu_mlme_action { * @set_rts_threshold: Configuration of RTS threshold (if device needs it) * The callback can sleep. * - * @sta_notify: Notifies low level driver about addition, removal or power - * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. - * Must be atomic. + * @sta_add: Notifies low level driver about addition of an associated station, + * AP, IBSS/WDS/mesh peer etc. This callback can sleep. + * + * @sta_remove: Notifies low level driver about removal of an associated + * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. + * + * @sta_notify: Notifies low level driver about power state transition of an + * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic. * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. @@ -1635,6 +1640,10 @@ struct ieee80211_ops { void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, u16 *iv16); int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); + int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); + int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index facf233843e0..a362523d8eb7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -747,9 +747,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || sdata->vif.type == NL80211_IFTYPE_AP; - rcu_read_lock(); - - err = sta_info_insert(sta); + err = sta_info_insert_rcu(sta); if (err) { rcu_read_unlock(); return err; @@ -768,26 +766,13 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, { struct ieee80211_local *local = wiphy_priv(wiphy); struct ieee80211_sub_if_data *sdata; - struct sta_info *sta; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (mac) { - rcu_read_lock(); - - sta = sta_info_get_bss(sdata, mac); - if (!sta) { - rcu_read_unlock(); - return -ENOENT; - } - - sta_info_unlink(&sta); - rcu_read_unlock(); - - sta_info_destroy(sta); - } else - sta_info_flush(local, sdata); + if (mac) + return sta_info_destroy_addr_bss(sdata, mac); + sta_info_flush(local, sdata); return 0; } diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 6c31f38ac7f5..855e85b55061 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -243,6 +243,40 @@ static inline void drv_sta_notify(struct ieee80211_local *local, trace_drv_sta_notify(local, sdata, cmd, sta); } +static inline int drv_sta_add(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta) +{ + int ret = 0; + + might_sleep(); + + if (local->ops->sta_add) + ret = local->ops->sta_add(&local->hw, &sdata->vif, sta); + else if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, &sdata->vif, + STA_NOTIFY_ADD, sta); + + trace_drv_sta_add(local, sdata, sta, ret); + + return ret; +} + +static inline void drv_sta_remove(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta) +{ + might_sleep(); + + if (local->ops->sta_remove) + local->ops->sta_remove(&local->hw, &sdata->vif, sta); + else if (local->ops->sta_notify) + local->ops->sta_notify(&local->hw, &sdata->vif, + STA_NOTIFY_REMOVE, sta); + + trace_drv_sta_remove(local, sdata, sta); +} + static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params) { diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 502424b2538a..c984910bf275 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -545,6 +545,58 @@ TRACE_EVENT(drv_sta_notify, ) ); +TRACE_EVENT(drv_sta_add, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta, int ret), + + TP_ARGS(local, sdata, sta, ret), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + __field(int, ret) + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + __entry->ret = ret; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ret:%d", + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ret + ) +); + +TRACE_EVENT(drv_sta_remove, + TP_PROTO(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta *sta), + + TP_ARGS(local, sdata, sta), + + TP_STRUCT__entry( + LOCAL_ENTRY + VIF_ENTRY + STA_ENTRY + ), + + TP_fast_assign( + LOCAL_ASSIGN; + VIF_ASSIGN; + STA_ASSIGN; + ), + + TP_printk( + LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG + ) +); + TRACE_EVENT(drv_conf_tx, TP_PROTO(struct ieee80211_local *local, u16 queue, const struct ieee80211_tx_queue_params *params, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 85c4ba14c77d..f3e942486749 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -275,10 +275,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, (unsigned long long) supp_rates, (unsigned long long) sta->sta.supp_rates[band]); #endif - } else - ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); - - rcu_read_unlock(); + rcu_read_unlock(); + } else { + rcu_read_unlock(); + ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, + supp_rates, GFP_KERNEL); + } } bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, @@ -368,7 +370,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->bssid); #endif ieee80211_sta_join_ibss(sdata, bss); - ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); + ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, + supp_rates, GFP_KERNEL); } put_bss: @@ -381,7 +384,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * must be callable in atomic context. */ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid,u8 *addr, u32 supp_rates) + u8 *bssid,u8 *addr, u32 supp_rates, + gfp_t gfp) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_local *local = sdata->local; @@ -410,7 +414,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, wiphy_name(local->hw.wiphy), addr, sdata->name); #endif - sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); + sta = sta_info_alloc(sdata, addr, gfp); if (!sta) return NULL; @@ -422,9 +426,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, rate_control_rate_init(sta); + /* If it fails, maybe we raced another insertion? */ if (sta_info_insert(sta)) - return NULL; - + return sta_info_get(sdata, addr); return sta; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3067fbd69d63..a5911191f224 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -688,15 +688,18 @@ struct ieee80211_local { /* Station data */ /* - * The lock only protects the list, hash, timer and counter - * against manipulation, reads are done in RCU. Additionally, - * the lock protects each BSS's TIM bitmap. + * The mutex only protects the list and counter, + * reads are done in RCU. + * Additionally, the lock protects the hash table, + * the pending list and each BSS's TIM bitmap. */ + struct mutex sta_mtx; spinlock_t sta_lock; unsigned long num_sta; - struct list_head sta_list; + struct list_head sta_list, sta_pending_list; struct sta_info *sta_hash[STA_HASH_SIZE]; struct timer_list sta_cleanup; + struct work_struct sta_finish_work; int sta_generation; struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; @@ -770,10 +773,6 @@ struct ieee80211_local { assoc_led_name[32], radio_led_name[32]; #endif -#ifdef CONFIG_MAC80211_DEBUGFS - struct work_struct sta_debugfs_add; -#endif - #ifdef CONFIG_MAC80211_DEBUG_COUNTERS /* TX/RX handler statistics */ unsigned int tx_handlers_drop; @@ -985,7 +984,8 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); ieee80211_rx_result ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 *addr, u32 supp_rates); + u8 *bssid, u8 *addr, u32 supp_rates, + gfp_t gfp); int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, struct cfg80211_ibss_params *params); int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7985e5150898..bc4e20e57ff5 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -102,7 +102,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, if (local->num_sta >= MESH_MAX_PLINKS) return NULL; - sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC); + sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); if (!sta) return NULL; @@ -236,12 +236,12 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data sta = sta_info_get(sdata, hw_addr); if (!sta) { + rcu_read_unlock(); + sta = mesh_plink_alloc(sdata, hw_addr, rates); - if (!sta) { - rcu_read_unlock(); + if (!sta) return; - } - if (sta_info_insert(sta)) { + if (sta_info_insert_rcu(sta)) { rcu_read_unlock(); return; } @@ -485,9 +485,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } else if (!sta) { /* ftype == PLINK_OPEN */ u32 rates; + + rcu_read_unlock(); + if (!mesh_plink_free_count(sdata)) { mpl_dbg("Mesh plink error: no more free plinks\n"); - rcu_read_unlock(); return; } @@ -495,10 +497,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta = mesh_plink_alloc(sdata, mgmt->sa, rates); if (!sta) { mpl_dbg("Mesh plink error: plink table full\n"); - rcu_read_unlock(); return; } - if (sta_info_insert(sta)) { + if (sta_info_insert_rcu(sta)) { rcu_read_unlock(); return; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f437284830ef..ac9429e8d72b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -822,19 +822,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) changed |= BSS_CHANGED_BSSID; ieee80211_bss_info_change_notify(sdata, changed); - rcu_read_lock(); - - sta = sta_info_get(sdata, bssid); - if (!sta) { - rcu_read_unlock(); - return; - } - - sta_info_unlink(&sta); - - rcu_read_unlock(); - - sta_info_destroy(sta); + sta_info_destroy_addr(sdata, bssid); } void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 47f818959ad7..0e64484e861c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -11,7 +11,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - unsigned long flags; ieee80211_scan_cancel(local); @@ -55,22 +54,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) rcu_read_unlock(); /* remove STAs */ - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - if (local->ops->sta_notify) { + if (sta->uploaded) { sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, - &sta->sta); + drv_sta_remove(local, sdata, &sta->sta); } mesh_plink_quiesce(sta); } - spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); /* remove all interfaces */ list_for_each_entry(sdata, &local->interfaces, list) { diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5709307fcb9b..01dba7618397 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2244,8 +2244,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, rate_idx = 0; /* TODO: HT rates */ else rate_idx = status->rate_idx; - rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, - BIT(rate_idx)); + rx->sta = ieee80211_ibss_add_sta(sdata, bssid, + hdr->addr2, BIT(rate_idx), GFP_ATOMIC); } break; case NL80211_IFTYPE_MESH_POINT: diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f735826f055c..211c475f73c6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -32,49 +32,33 @@ * for faster lookup and a list for iteration. They are managed using * RCU, i.e. access to the list and hash table is protected by RCU. * - * Upon allocating a STA info structure with sta_info_alloc(), the caller owns - * that structure. It must then either destroy it using sta_info_destroy() - * (which is pretty useless) or insert it into the hash table using - * sta_info_insert() which demotes the reference from ownership to a regular - * RCU-protected reference; if the function is called without protection by an - * RCU critical section the reference is instantly invalidated. Note that the - * caller may not do much with the STA info before inserting it, in particular, - * it may not start any mesh peer link management or add encryption keys. + * Upon allocating a STA info structure with sta_info_alloc(), the caller + * owns that structure. It must then insert it into the hash table using + * either sta_info_insert() or sta_info_insert_rcu(); only in the latter + * case (which acquires an rcu read section but must not be called from + * within one) will the pointer still be valid after the call. Note that + * the caller may not do much with the STA info before inserting it, in + * particular, it may not start any mesh peer link management or add + * encryption keys. * * When the insertion fails (sta_info_insert()) returns non-zero), the * structure will have been freed by sta_info_insert()! * - * sta entries are added by mac80211 when you establish a link with a + * Station entries are added by mac80211 when you establish a link with a * peer. This means different things for the different type of interfaces * we support. For a regular station this mean we add the AP sta when we * receive an assocation response from the AP. For IBSS this occurs when - * we receive a probe response or a beacon from target IBSS network. For - * WDS we add the sta for the peer imediately upon device open. When using - * AP mode we add stations for each respective station upon request from - * userspace through nl80211. + * get to know about a peer on the same IBSS. For WDS we add the sta for + * the peer imediately upon device open. When using AP mode we add stations + * for each respective station upon request from userspace through nl80211. * - * Because there are debugfs entries for each station, and adding those - * must be able to sleep, it is also possible to "pin" a station entry, - * that means it can be removed from the hash table but not be freed. - * See the comment in __sta_info_unlink() for more information, this is - * an internal capability only. + * In order to remove a STA info structure, various sta_info_destroy_*() + * calls are available. * - * In order to remove a STA info structure, the caller needs to first - * unlink it (sta_info_unlink()) from the list and hash tables and - * then destroy it; sta_info_destroy() will wait for an RCU grace period - * to elapse before actually freeing it. Due to the pinning and the - * possibility of multiple callers trying to remove the same STA info at - * the same time, sta_info_unlink() can clear the STA info pointer it is - * passed to indicate that the STA info is owned by somebody else now. - * - * If sta_info_unlink() did not clear the pointer then the caller owns - * the STA info structure now and is responsible of destroying it with - * a call to sta_info_destroy(). - * - * In all other cases, there is no concept of ownership on a STA entry, - * each structure is owned by the global hash table/list until it is - * removed. All users of the structure need to be RCU protected so that - * the structure won't be freed before they are done using it. + * There is no concept of ownership on a STA entry, each structure is + * owned by the global hash table/list until it is removed. All users of + * the structure need to be RCU protected so that the structure won't be + * freed before they are done using it. */ /* Caller must hold local->sta_lock */ @@ -185,101 +169,6 @@ static void __sta_info_free(struct ieee80211_local *local, kfree(sta); } -void sta_info_destroy(struct sta_info *sta) -{ - struct ieee80211_local *local; - struct sk_buff *skb; - int i; - - might_sleep(); - - if (!sta) - return; - - local = sta->local; - - cancel_work_sync(&sta->drv_unblock_wk); - - rate_control_remove_sta_debugfs(sta); - ieee80211_sta_debugfs_remove(sta); - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sta->sdata->vif)) - mesh_plink_deactivate(sta); -#endif - - /* - * We have only unlinked the key, and actually destroying it - * may mean it is removed from hardware which requires that - * the key->sta pointer is still valid, so flush the key todo - * list here. - * - * ieee80211_key_todo() will synchronize_rcu() so after this - * nothing can reference this sta struct any more. - */ - ieee80211_key_todo(); - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_vif_is_mesh(&sta->sdata->vif)) - del_timer_sync(&sta->plink_timer); -#endif - - while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - local->total_ps_buffered--; - dev_kfree_skb_any(skb); - } - - while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) - dev_kfree_skb_any(skb); - - for (i = 0; i < STA_TID_NUM; i++) { - struct tid_ampdu_rx *tid_rx; - struct tid_ampdu_tx *tid_tx; - - spin_lock_bh(&sta->lock); - tid_rx = sta->ampdu_mlme.tid_rx[i]; - /* Make sure timer won't free the tid_rx struct, see below */ - if (tid_rx) - tid_rx->shutdown = true; - - spin_unlock_bh(&sta->lock); - - /* - * Outside spinlock - shutdown is true now so that the timer - * won't free tid_rx, we have to do that now. Can't let the - * timer do it because we have to sync the timer outside the - * lock that it takes itself. - */ - if (tid_rx) { - del_timer_sync(&tid_rx->session_timer); - kfree(tid_rx); - } - - /* - * No need to do such complications for TX agg sessions, the - * path leading to freeing the tid_tx struct goes via a call - * from the driver, and thus needs to look up the sta struct - * again, which cannot be found when we get here. Hence, we - * just need to delete the timer and free the aggregation - * info; we won't be telling the peer about it then but that - * doesn't matter if we're not talking to it again anyway. - */ - tid_tx = sta->ampdu_mlme.tid_tx[i]; - if (tid_tx) { - del_timer_sync(&tid_tx->addba_resp_timer); - /* - * STA removed while aggregation session being - * started? Bit odd, but purge frames anyway. - */ - skb_queue_purge(&tid_tx->pending); - kfree(tid_tx); - } - } - - __sta_info_free(local, sta); -} - - /* Caller must hold local->sta_lock */ static void sta_info_hash_add(struct ieee80211_local *local, struct sta_info *sta) @@ -376,7 +265,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return sta; } -int sta_info_insert(struct sta_info *sta) +static int sta_info_finish_insert(struct sta_info *sta, bool async) { struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -384,6 +273,91 @@ int sta_info_insert(struct sta_info *sta) unsigned long flags; int err = 0; + WARN_ON(!mutex_is_locked(&local->sta_mtx)); + + /* notify driver */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + err = drv_sta_add(local, sdata, &sta->sta); + if (err) { + if (!async) + return err; + printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" + " - keeping it anyway.\n", + sdata->name, sta->sta.addr, err); + } else { + sta->uploaded = true; +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + if (async) + printk(KERN_DEBUG "%s: Finished adding IBSS STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif + } + + sdata = sta->sdata; + + if (!async) { + local->num_sta++; + local->sta_generation++; + smp_mb(); + + /* make the station visible */ + spin_lock_irqsave(&local->sta_lock, flags); + sta_info_hash_add(local, sta); + spin_unlock_irqrestore(&local->sta_lock, flags); + } + + list_add(&sta->list, &local->sta_list); + + ieee80211_sta_debugfs_add(sta); + rate_control_add_sta_debugfs(sta); + + sinfo.filled = 0; + sinfo.generation = local->sta_generation; + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); + + + return 0; +} + +static void sta_info_finish_pending(struct ieee80211_local *local) +{ + struct sta_info *sta; + unsigned long flags; + + spin_lock_irqsave(&local->sta_lock, flags); + while (!list_empty(&local->sta_pending_list)) { + sta = list_first_entry(&local->sta_pending_list, + struct sta_info, list); + list_del(&sta->list); + spin_unlock_irqrestore(&local->sta_lock, flags); + + sta_info_finish_insert(sta, true); + + spin_lock_irqsave(&local->sta_lock, flags); + } + spin_unlock_irqrestore(&local->sta_lock, flags); +} + +static void sta_info_finish_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, sta_finish_work); + + mutex_lock(&local->sta_mtx); + sta_info_finish_pending(local); + mutex_unlock(&local->sta_mtx); +} + +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +{ + struct ieee80211_local *local = sta->local; + struct ieee80211_sub_if_data *sdata = sta->sdata; + unsigned long flags; + int err = 0; + /* * Can't be a WARN_ON because it can be triggered through a race: * something inserts a STA (on one CPU) without holding the RTNL @@ -391,36 +365,87 @@ int sta_info_insert(struct sta_info *sta) */ if (unlikely(!ieee80211_sdata_running(sdata))) { err = -ENETDOWN; + rcu_read_lock(); goto out_free; } if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || is_multicast_ether_addr(sta->sta.addr))) { err = -EINVAL; + rcu_read_lock(); goto out_free; } + /* + * In ad-hoc mode, we sometimes need to insert stations + * from tasklet context from the RX path. To avoid races, + * always do so in that case -- see the comment below. + */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + spin_lock_irqsave(&local->sta_lock, flags); + /* check if STA exists already */ + if (sta_info_get_bss(sdata, sta->sta.addr)) { + spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); + err = -EEXIST; + goto out_free; + } + + local->num_sta++; + local->sta_generation++; + smp_mb(); + sta_info_hash_add(local, sta); + + list_add_tail(&sta->list, &local->sta_pending_list); + + rcu_read_lock(); + spin_unlock_irqrestore(&local->sta_lock, flags); + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: Added IBSS STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + + ieee80211_queue_work(&local->hw, &local->sta_finish_work); + + return 0; + } + + /* + * On first glance, this will look racy, because the code + * below this point, which inserts a station with sleeping, + * unlocks the sta_lock between checking existence in the + * hash table and inserting into it. + * + * However, it is not racy against itself because it keeps + * the mutex locked. It still seems to race against the + * above code that atomically inserts the station... That, + * however, is not true because the above code can only + * be invoked for IBSS interfaces, and the below code will + * not be -- and the two do not race against each other as + * the hash table also keys off the interface. + */ + + might_sleep(); + + mutex_lock(&local->sta_mtx); + spin_lock_irqsave(&local->sta_lock, flags); /* check if STA exists already */ - if (sta_info_get(sdata, sta->sta.addr)) { + if (sta_info_get_bss(sdata, sta->sta.addr)) { spin_unlock_irqrestore(&local->sta_lock, flags); + rcu_read_lock(); err = -EEXIST; goto out_free; } - list_add(&sta->list, &local->sta_list); - local->sta_generation++; - local->num_sta++; - sta_info_hash_add(local, sta); - /* notify driver */ - if (local->ops->sta_notify) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); + spin_unlock_irqrestore(&local->sta_lock, flags); - drv_sta_notify(local, sdata, STA_NOTIFY_ADD, &sta->sta); - sdata = sta->sdata; + err = sta_info_finish_insert(sta, false); + if (err) { + mutex_unlock(&local->sta_mtx); + rcu_read_lock(); + goto out_free; } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -428,22 +453,9 @@ int sta_info_insert(struct sta_info *sta) wiphy_name(local->hw.wiphy), sta->sta.addr); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - spin_unlock_irqrestore(&local->sta_lock, flags); - - sinfo.filled = 0; - sinfo.generation = local->sta_generation; - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); - -#ifdef CONFIG_MAC80211_DEBUGFS - /* - * Debugfs entry adding might sleep, so schedule process - * context task for adding entry for STAs that do not yet - * have one. - * NOTE: due to auto-freeing semantics this may only be done - * if the insertion is successful! - */ - schedule_work(&local->sta_debugfs_add); -#endif + /* move reference to rcu-protected */ + rcu_read_lock(); + mutex_unlock(&local->sta_mtx); if (ieee80211_vif_is_mesh(&sdata->vif)) mesh_accept_plinks_update(sdata); @@ -455,6 +467,15 @@ int sta_info_insert(struct sta_info *sta) return err; } +int sta_info_insert(struct sta_info *sta) +{ + int err = sta_info_insert_rcu(sta); + + rcu_read_unlock(); + + return err; +} + static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) { /* @@ -523,108 +544,6 @@ void sta_info_clear_tim_bit(struct sta_info *sta) spin_unlock_irqrestore(&sta->local->sta_lock, flags); } -static void __sta_info_unlink(struct sta_info **sta) -{ - struct ieee80211_local *local = (*sta)->local; - struct ieee80211_sub_if_data *sdata = (*sta)->sdata; - /* - * pull caller's reference if we're already gone. - */ - if (sta_info_hash_del(local, *sta)) { - *sta = NULL; - return; - } - - if ((*sta)->key) { - ieee80211_key_free((*sta)->key); - WARN_ON((*sta)->key); - } - - list_del(&(*sta)->list); - (*sta)->dead = true; - - if (test_and_clear_sta_flags(*sta, - WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { - BUG_ON(!sdata->bss); - - atomic_dec(&sdata->bss->num_sta_ps); - __sta_info_clear_tim_bit(sdata->bss, *sta); - } - - local->num_sta--; - local->sta_generation++; - - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - rcu_assign_pointer(sdata->u.vlan.sta, NULL); - - if (local->ops->sta_notify) { - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, - struct ieee80211_sub_if_data, - u.ap); - - drv_sta_notify(local, sdata, STA_NOTIFY_REMOVE, - &(*sta)->sta); - sdata = (*sta)->sdata; - } - - if (ieee80211_vif_is_mesh(&sdata->vif)) { - mesh_accept_plinks_update(sdata); -#ifdef CONFIG_MAC80211_MESH - del_timer(&(*sta)->plink_timer); -#endif - } - -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: Removed STA %pM\n", - wiphy_name(local->hw.wiphy), (*sta)->sta.addr); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - - /* - * Finally, pull caller's reference if the STA is pinned by the - * task that is adding the debugfs entries. In that case, we - * leave the STA "to be freed". - * - * The rules are not trivial, but not too complex either: - * (1) pin_status is only modified under the sta_lock - * (2) STAs may only be pinned under the RTNL so that - * sta_info_flush() is guaranteed to actually destroy - * all STAs that are active for a given interface, this - * is required for correctness because otherwise we - * could notify a driver that an interface is going - * away and only after that (!) notify it about a STA - * on that interface going away. - * (3) sta_info_debugfs_add_work() will set the status - * to PINNED when it found an item that needs a new - * debugfs directory created. In that case, that item - * must not be freed although all *RCU* users are done - * with it. Hence, we tell the caller of _unlink() - * that the item is already gone (as can happen when - * two tasks try to unlink/destroy at the same time) - * (4) We set the pin_status to DESTROY here when we - * find such an item. - * (5) sta_info_debugfs_add_work() will reset the pin_status - * from PINNED to NORMAL when it is done with the item, - * but will check for DESTROY before resetting it in - * which case it will free the item. - */ - if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) { - (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY; - *sta = NULL; - return; - } -} - -void sta_info_unlink(struct sta_info **sta) -{ - struct ieee80211_local *local = (*sta)->local; - unsigned long flags; - - spin_lock_irqsave(&local->sta_lock, flags); - __sta_info_unlink(sta); - spin_unlock_irqrestore(&local->sta_lock, flags); -} - static int sta_info_buffer_expired(struct sta_info *sta, struct sk_buff *skb) { @@ -681,109 +600,209 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, } } - -static void sta_info_cleanup(unsigned long data) +static int __must_check __sta_info_destroy(struct sta_info *sta) { - struct ieee80211_local *local = (struct ieee80211_local *) data; - struct sta_info *sta; + struct ieee80211_local *local; + struct ieee80211_sub_if_data *sdata; + struct sk_buff *skb; + unsigned long flags; + int ret, i; - rcu_read_lock(); - list_for_each_entry_rcu(sta, &local->sta_list, list) - sta_info_cleanup_expire_buffered(local, sta); - rcu_read_unlock(); + might_sleep(); - if (local->quiescing) - return; + if (!sta) + return -ENOENT; - local->sta_cleanup.expires = - round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); - add_timer(&local->sta_cleanup); -} + local = sta->local; + sdata = sta->sdata; -#ifdef CONFIG_MAC80211_DEBUGFS -/* - * See comment in __sta_info_unlink, - * caller must hold local->sta_lock. - */ -static void __sta_info_pin(struct sta_info *sta) -{ - WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL); - sta->pin_status = STA_INFO_PIN_STAT_PINNED; + spin_lock_irqsave(&local->sta_lock, flags); + ret = sta_info_hash_del(local, sta); + /* this might still be the pending list ... which is fine */ + if (!ret) + list_del(&sta->list); + spin_unlock_irqrestore(&local->sta_lock, flags); + if (ret) + return ret; + + if (sta->key) { + ieee80211_key_free(sta->key); + /* + * We have only unlinked the key, and actually destroying it + * may mean it is removed from hardware which requires that + * the key->sta pointer is still valid, so flush the key todo + * list here. + * + * ieee80211_key_todo() will synchronize_rcu() so after this + * nothing can reference this sta struct any more. + */ + ieee80211_key_todo(); + + WARN_ON(sta->key); + } + + sta->dead = true; + + if (test_and_clear_sta_flags(sta, + WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) { + BUG_ON(!sdata->bss); + + atomic_dec(&sdata->bss->num_sta_ps); + __sta_info_clear_tim_bit(sdata->bss, sta); + } + + local->num_sta--; + local->sta_generation++; + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + rcu_assign_pointer(sdata->u.vlan.sta, NULL); + + if (sta->uploaded) { + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); + drv_sta_remove(local, sdata, &sta->sta); + sdata = sta->sdata; + } + +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) { + mesh_accept_plinks_update(sdata); + del_timer(&sta->plink_timer); + } +#endif + +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG + printk(KERN_DEBUG "%s: Removed STA %pM\n", + wiphy_name(local->hw.wiphy), sta->sta.addr); +#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ + cancel_work_sync(&sta->drv_unblock_wk); + + rate_control_remove_sta_debugfs(sta); + ieee80211_sta_debugfs_remove(sta); + +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { + mesh_plink_deactivate(sta); + del_timer_sync(&sta->plink_timer); + } +#endif + + while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { + local->total_ps_buffered--; + dev_kfree_skb_any(skb); + } + + while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) + dev_kfree_skb_any(skb); + + for (i = 0; i < STA_TID_NUM; i++) { + struct tid_ampdu_rx *tid_rx; + struct tid_ampdu_tx *tid_tx; + + spin_lock_bh(&sta->lock); + tid_rx = sta->ampdu_mlme.tid_rx[i]; + /* Make sure timer won't free the tid_rx struct, see below */ + if (tid_rx) + tid_rx->shutdown = true; + + spin_unlock_bh(&sta->lock); + + /* + * Outside spinlock - shutdown is true now so that the timer + * won't free tid_rx, we have to do that now. Can't let the + * timer do it because we have to sync the timer outside the + * lock that it takes itself. + */ + if (tid_rx) { + del_timer_sync(&tid_rx->session_timer); + kfree(tid_rx); + } + + /* + * No need to do such complications for TX agg sessions, the + * path leading to freeing the tid_tx struct goes via a call + * from the driver, and thus needs to look up the sta struct + * again, which cannot be found when we get here. Hence, we + * just need to delete the timer and free the aggregation + * info; we won't be telling the peer about it then but that + * doesn't matter if we're not talking to it again anyway. + */ + tid_tx = sta->ampdu_mlme.tid_tx[i]; + if (tid_tx) { + del_timer_sync(&tid_tx->addba_resp_timer); + /* + * STA removed while aggregation session being + * started? Bit odd, but purge frames anyway. + */ + skb_queue_purge(&tid_tx->pending); + kfree(tid_tx); + } + } + + __sta_info_free(local, sta); + + return 0; } -/* - * See comment in __sta_info_unlink, returns sta if it - * needs to be destroyed. - */ -static struct sta_info *__sta_info_unpin(struct sta_info *sta) +int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) { - struct sta_info *ret = NULL; - unsigned long flags; + struct sta_info *sta; + int ret; - spin_lock_irqsave(&sta->local->sta_lock, flags); - WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY && - sta->pin_status != STA_INFO_PIN_STAT_PINNED); - if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY) - ret = sta; - sta->pin_status = STA_INFO_PIN_STAT_NORMAL; - spin_unlock_irqrestore(&sta->local->sta_lock, flags); + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get(sdata, addr); + ret = __sta_info_destroy(sta); + mutex_unlock(&sdata->local->sta_mtx); return ret; } -static void sta_info_debugfs_add_work(struct work_struct *work) +int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr) { - struct ieee80211_local *local = - container_of(work, struct ieee80211_local, sta_debugfs_add); - struct sta_info *sta, *tmp; - unsigned long flags; + struct sta_info *sta; + int ret; - /* We need to keep the RTNL across the whole pinned status. */ - rtnl_lock(); - while (1) { - sta = NULL; + mutex_lock(&sdata->local->sta_mtx); + sta = sta_info_get_bss(sdata, addr); + ret = __sta_info_destroy(sta); + mutex_unlock(&sdata->local->sta_mtx); - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(tmp, &local->sta_list, list) { - /* - * debugfs.add_has_run will be set by - * ieee80211_sta_debugfs_add regardless - * of what else it does. - */ - if (!tmp->debugfs.add_has_run) { - sta = tmp; - __sta_info_pin(sta); - break; - } - } - spin_unlock_irqrestore(&local->sta_lock, flags); + return ret; +} - if (!sta) - break; +static void sta_info_cleanup(unsigned long data) +{ + struct ieee80211_local *local = (struct ieee80211_local *) data; + struct sta_info *sta; + + rcu_read_lock(); + list_for_each_entry_rcu(sta, &local->sta_list, list) + sta_info_cleanup_expire_buffered(local, sta); + rcu_read_unlock(); - ieee80211_sta_debugfs_add(sta); - rate_control_add_sta_debugfs(sta); + if (local->quiescing) + return; - sta = __sta_info_unpin(sta); - sta_info_destroy(sta); - } - rtnl_unlock(); + local->sta_cleanup.expires = + round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); + add_timer(&local->sta_cleanup); } -#endif void sta_info_init(struct ieee80211_local *local) { spin_lock_init(&local->sta_lock); + mutex_init(&local->sta_mtx); INIT_LIST_HEAD(&local->sta_list); + INIT_LIST_HEAD(&local->sta_pending_list); + INIT_WORK(&local->sta_finish_work, sta_info_finish_work); setup_timer(&local->sta_cleanup, sta_info_cleanup, (unsigned long)local); local->sta_cleanup.expires = round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); - -#ifdef CONFIG_MAC80211_DEBUGFS - INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work); -#endif } int sta_info_start(struct ieee80211_local *local) @@ -795,16 +814,6 @@ int sta_info_start(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { del_timer(&local->sta_cleanup); -#ifdef CONFIG_MAC80211_DEBUGFS - /* - * Make sure the debugfs adding work isn't pending after this - * because we're about to be destroyed. It doesn't matter - * whether it ran or not since we're going to flush all STAs - * anyway. - */ - cancel_work_sync(&local->sta_debugfs_add); -#endif - sta_info_flush(local, NULL); } @@ -820,26 +829,19 @@ int sta_info_flush(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { struct sta_info *sta, *tmp; - LIST_HEAD(tmp_list); int ret = 0; - unsigned long flags; might_sleep(); - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); + + sta_info_finish_pending(local); + list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { - if (!sdata || sdata == sta->sdata) { - __sta_info_unlink(&sta); - if (sta) { - list_add_tail(&sta->list, &tmp_list); - ret++; - } - } + if (!sdata || sdata == sta->sdata) + WARN_ON(__sta_info_destroy(sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); - - list_for_each_entry_safe(sta, tmp, &tmp_list, list) - sta_info_destroy(sta); + mutex_unlock(&local->sta_mtx); return ret; } @@ -849,24 +851,17 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct sta_info *sta, *tmp; - LIST_HEAD(tmp_list); - unsigned long flags; - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry_safe(sta, tmp, &local->sta_list, list) if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %pM\n", sdata->name, sta->sta.addr); #endif - __sta_info_unlink(&sta); - if (sta) - list_add(&sta->list, &tmp_list); + WARN_ON(__sta_info_destroy(sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); - - list_for_each_entry_safe(sta, tmp, &tmp_list, list) - sta_info_destroy(sta); + mutex_unlock(&local->sta_mtx); } struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw, diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 6f79bba5706e..5ff611a35979 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -162,11 +162,6 @@ struct sta_ampdu_mlme { }; -/* see __sta_info_unlink */ -#define STA_INFO_PIN_STAT_NORMAL 0 -#define STA_INFO_PIN_STAT_PINNED 1 -#define STA_INFO_PIN_STAT_DESTROY 2 - /** * struct sta_info - STA information * @@ -187,7 +182,6 @@ struct sta_ampdu_mlme { * @flaglock: spinlock for flags accesses * @drv_unblock_wk: used for driver PS unblocking * @listen_interval: listen interval of this station, when we're acting as AP - * @pin_status: used internally for pinning a STA struct into memory * @flags: STA flags, see &enum ieee80211_sta_info_flags * @ps_tx_buf: buffer of frames to transmit to this station * when it leaves power saving state @@ -226,6 +220,7 @@ struct sta_ampdu_mlme { * @debugfs: debug filesystem info * @sta: station information we share with the driver * @dead: set to true when sta is unlinked + * @uploaded: set to true when sta is uploaded to the driver */ struct sta_info { /* General information, mostly static */ @@ -245,11 +240,7 @@ struct sta_info { bool dead; - /* - * for use by the internal lifetime management, - * see __sta_info_unlink - */ - u8 pin_status; + bool uploaded; /* * frequently updated, locked with own spinlock (flaglock), @@ -449,18 +440,19 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, * Insert STA info into hash table/list, returns zero or a * -EEXIST if (if the same MAC address is already present). * - * Calling this without RCU protection makes the caller - * relinquish its reference to @sta. + * Calling the non-rcu version makes the caller relinquish, + * the _rcu version calls read_lock_rcu() and must be called + * without it held. */ int sta_info_insert(struct sta_info *sta); -/* - * Unlink a STA info from the hash table/list. - * This can NULL the STA pointer if somebody else - * has already unlinked it. - */ -void sta_info_unlink(struct sta_info **sta); +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); +int sta_info_insert_atomic(struct sta_info *sta); + +int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, + const u8 *addr); +int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata, + const u8 *addr); -void sta_info_destroy(struct sta_info *sta); void sta_info_set_tim_bit(struct sta_info *sta); void sta_info_clear_tim_bit(struct sta_info *sta); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e392820a4c33..cbe53ed4fb0b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -571,7 +571,7 @@ ieee80211_tx_h_sta(struct ieee80211_tx_data *tx) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - if (tx->sta) + if (tx->sta && tx->sta->uploaded) info->control.sta = &tx->sta->sta; return TX_CONTINUE; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ca170b417da6..3af439a85b33 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1082,7 +1082,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_hw *hw = &local->hw; struct ieee80211_sub_if_data *sdata; struct sta_info *sta; - unsigned long flags; int res; if (local->suspended) @@ -1116,20 +1115,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) } /* add STAs back */ - if (local->ops->sta_notify) { - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(sta, &local->sta_list, list) { + mutex_lock(&local->sta_mtx); + list_for_each_entry(sta, &local->sta_list, list) { + if (sta->uploaded) { sdata = sta->sdata; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - drv_sta_notify(local, sdata, STA_NOTIFY_ADD, - &sta->sta); + WARN_ON(drv_sta_add(local, sdata, &sta->sta)); } - spin_unlock_irqrestore(&local->sta_lock, flags); } + mutex_unlock(&local->sta_mtx); /* Clear Suspend state so that ADDBA requests can be processed */ @@ -1219,10 +1217,10 @@ int ieee80211_reconfig(struct ieee80211_local *local) add_timer(&local->sta_cleanup); - spin_lock_irqsave(&local->sta_lock, flags); + mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) mesh_plink_restart(sta); - spin_unlock_irqrestore(&local->sta_lock, flags); + mutex_unlock(&local->sta_mtx); #else WARN_ON(1); #endif -- cgit v1.2.3 From 1a20034a73a40b8056731f9db0c535cec2961eb7 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 3 Feb 2010 22:50:18 +0530 Subject: ath9k: configure the beacon only if the STA is associated beacons configuration SHOULD be done only if the STA is associated. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 422454fe4ff0..d088ebfe63a6 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -577,6 +577,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, u64 tsf; int num_beacons, offset, dtim_dec_count, cfp_dec_count; + /* No need to configure beacon if we are not associated */ + if (!common->curaid) { + ath_print(common, ATH_DBG_BEACON, + "STA is not yet associated..skipping beacon config\n"); + return; + } + memset(&bs, 0, sizeof(bs)); intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; @@ -739,7 +746,6 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) enum nl80211_iftype iftype; /* Setup the beacon configuration parameters */ - if (vif) { struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -- cgit v1.2.3 From 3f7c5c10e9dc6bf90179eb9f7c06151d508fb324 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Wed, 3 Feb 2010 22:51:13 +0530 Subject: ath9k: Enable TIM timer interrupt only when needed. The TIM timer interrupt is enabled even before the ACK of nullqos is received which is unnecessary. Also clean up the CONF_PS part of config callback properly for better readability. Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 24 ++++++++++++++---------- drivers/net/wireless/ath/ath9k/xmit.c | 7 +++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0ea340fd071c..83c7ea4c007f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -267,6 +267,7 @@ void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid, u16 *ssn); void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); +void ath9k_enable_ps(struct ath_softc *sc); /********/ /* VIFs */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6796d5cdc293..40da7a6e4b6b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1492,6 +1492,19 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, mutex_unlock(&sc->mutex); } +void ath9k_enable_ps(struct ath_softc *sc) +{ + sc->ps_enabled = true; + if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { + sc->imask |= ATH9K_INT_TIM_TIMER; + ath9k_hw_set_interrupts(sc->sc_ah, + sc->imask); + } + } + ath9k_hw_setrxabort(sc->sc_ah, 1); +} + static int ath9k_config(struct ieee80211_hw *hw, u32 changed) { struct ath_wiphy *aphy = hw->priv; @@ -1546,22 +1559,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_PS) { if (conf->flags & IEEE80211_CONF_PS) { sc->ps_flags |= PS_ENABLED; - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); - } - } /* * At this point we know hardware has received an ACK * of a previously sent null data frame. */ if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) { sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; - sc->ps_enabled = true; - ath9k_hw_setrxabort(sc->sc_ah, 1); + ath9k_enable_ps(sc); } } else { sc->ps_enabled = false; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3c790a4f38f7..f5cbbcb9a4aa 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2048,10 +2048,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ if (bf->bf_isnullfunc && (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { - if ((sc->ps_flags & PS_ENABLED)) { - sc->ps_enabled = true; - ath9k_hw_setrxabort(sc->sc_ah, 1); - } else + if ((sc->ps_flags & PS_ENABLED)) + ath9k_enable_ps(sc); + else sc->ps_flags |= PS_NULLFUNC_COMPLETED; } -- cgit v1.2.3 From 74e2bd1fa3ae9695af566ad5a7a288898787b909 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 3 Feb 2010 09:28:55 -0800 Subject: mac80211: tear down all agg queues when restart/reconfig hw When there is a need to restart/reconfig hw, tear down all the aggregation queues and let the mac80211 and driver get in-sync to have the opportunity to re-establish the aggregation queues again. Need to wait until driver re-establish all the station information before tear down the aggregation queues, driver(at least iwlwifi driver) will reject the stop aggregation queue request if station is not ready. But also need to make sure the aggregation queues are tear down before waking up the queues, so mac80211 will not sending frames with aggregation bit set. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- net/mac80211/util.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3af439a85b33..c453226f06b2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1178,6 +1178,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } + rcu_read_lock(); + if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { + list_for_each_entry_rcu(sta, &local->sta_list, list) { + ieee80211_sta_tear_down_BA_sessions(sta); + } + } + rcu_read_unlock(); + /* add back keys */ list_for_each_entry(sdata, &local->interfaces, list) if (ieee80211_sdata_running(sdata)) -- cgit v1.2.3 From 0866b03c7d7dee8a34ffa527ecda426c0f405518 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 3 Feb 2010 13:33:44 -0600 Subject: b43/b43legacy: Wake queues in wireless_core_start If b43 or b43legacy are deauthenticated or disconnected, there is a possibility that a reconnection is tried with the queues stopped in mac80211. To prevent this, start the queues before setting STAT_INITIALIZED. In b43, a similar change has been in place (twice) in the wireless_core_init() routine. Remove the duplicate and add similar code to b43legacy. Signed-off-by: Larry Finger Cc: Stable [2.6.32] Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 3 +-- drivers/net/wireless/b43legacy/main.c | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ddd15c52b346..3c5143b935f2 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3987,6 +3987,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev) } /* We are ready to run. */ + ieee80211_wake_queues(dev->wl->hw); b43_set_status(dev, B43_STAT_STARTED); /* Start data flow (TX/RX). */ @@ -4396,8 +4397,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev) ieee80211_wake_queues(dev->wl->hw); - ieee80211_wake_queues(dev->wl->hw); - b43_set_status(dev, B43_STAT_INITIALIZED); out: diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 174ac6bde2b1..b4e89a35e3fb 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2923,6 +2923,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev) goto out; } /* We are ready to run. */ + ieee80211_wake_queues(dev->wl->hw); b43legacy_set_status(dev, B43legacy_STAT_STARTED); /* Start data flow (TX/RX) */ @@ -3343,6 +3344,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) b43legacy_security_init(dev); b43legacy_rng_init(wl); + ieee80211_wake_queues(dev->wl->hw); b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); b43legacy_leds_init(dev); -- cgit v1.2.3 From 83e34f03ee9b86b49bde4707a1fe03a1837e29be Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Wed, 3 Feb 2010 21:28:11 +0100 Subject: ssb: fix interrupt assignment Explicitely enable shared interrupt 2 for any core that didn't get a dedicated IRQ anymore (fallthrough case) and for EXTIF cores to make gpio interrupts work. Also remove a bogus comment. Signed-off-by: Jochen Friedrich Signed-off-by: John W. Linville --- drivers/ssb/driver_mipscore.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3c6feed46f6e..97efce184a8f 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -270,7 +270,6 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) set_irq(dev, irq++); } break; - /* fallthrough */ case SSB_DEV_PCI: case SSB_DEV_ETHERNET: case SSB_DEV_ETHERNET_GBIT: @@ -281,6 +280,10 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) set_irq(dev, irq++); break; } + /* fallthrough */ + case SSB_DEV_EXTIF: + set_irq(dev, 0); + break; } } ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); -- cgit v1.2.3 From 371ba88322ea5750ad411fdef7674dcee50f7235 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 3 Feb 2010 15:31:07 -0800 Subject: libertas/if_spi: needs linux/semaphore.h libertas/if_spi.c needs to #include linux/semaphore.h to fix build errors: drivers/net/wireless/libertas/if_spi.c:59: error: field 'spi_ready' has incomplete type drivers/net/wireless/libertas/if_spi.c:60: error: field 'spi_thread_terminated' has incomplete type drivers/net/wireless/libertas/if_spi.c:785: error: implicit declaration of function 'down_interruptible' drivers/net/wireless/libertas/if_spi.c:787: error: implicit declaration of function 'up' drivers/net/wireless/libertas/if_spi.c:834: error: implicit declaration of function 'down' drivers/net/wireless/libertas/if_spi.c:943: error: implicit declaration of function 'sema_init' Signed-off-by: Randy Dunlap Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_spi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index bf4bfbae6227..3ea03f259ee7 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 67cbc3ed5b96a5acfddae142fa0e2adb1b6270d5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 12:23:08 +0100 Subject: b43: N-PHY: implement overriding RF control intc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 117 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6392da25efed..8992457b0c0b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -68,6 +68,10 @@ static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, u8 *events, u8 *delays, u8 length); static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, enum b43_nphy_rf_sequence seq); +static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, + u16 value, u8 core, bool off); +static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, + u16 value, u8 core); void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO @@ -498,8 +502,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007); } - /* TODO: Call N PHY RF Ctrl Intc Override with 2, 0, 3 as arguments */ - /* TODO: Call N PHY RF Intc Override with 8, 0, 3, 0 as arguments */ + b43_nphy_rf_control_intc_override(dev, 2, 0, 3); + b43_nphy_rf_control_override(dev, 8, 0, 3, false); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); if (core == 0) { @@ -509,9 +513,8 @@ static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) rxval = 4; txval = 2; } - - /* TODO: Call N PHY RF Ctrl Intc Override with 1, rxval, (core + 1) */ - /* TODO: Call N PHY RF Ctrl Intc Override with 1, txval, (2 - core) */ + b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1)); + b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core)); } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ @@ -1264,6 +1267,104 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ +static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, + u16 value, u8 core) +{ + u8 i, j; + u16 reg, tmp, val; + + B43_WARN_ON(dev->phy.rev < 3); + B43_WARN_ON(field > 4); + + for (i = 0; i < 2; i++) { + if ((core == 1 && i == 1) || (core == 2 && !i)) + continue; + + reg = (i == 0) ? + B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; + b43_phy_mask(dev, reg, 0xFBFF); + + switch (field) { + case 0: + b43_phy_write(dev, reg, 0); + b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); + break; + case 1: + if (!i) { + b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1, + 0xFC3F, (value << 6)); + b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1, + 0xFFFE, 1); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_START); + for (j = 0; j < 100; j++) { + if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) { + j = 0; + break; + } + udelay(10); + } + if (j) + b43err(dev->wl, + "intc override timeout\n"); + b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, + 0xFFFE); + } else { + b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2, + 0xFC3F, (value << 6)); + b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, + 0xFFFE, 1); + b43_phy_set(dev, B43_NPHY_RFCTL_CMD, + B43_NPHY_RFCTL_CMD_RXTX); + for (j = 0; j < 100; j++) { + if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) { + j = 0; + break; + } + udelay(10); + } + if (j) + b43err(dev->wl, + "intc override timeout\n"); + b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, + 0xFFFE); + } + break; + case 2: + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + tmp = 0x0020; + val = value << 5; + } else { + tmp = 0x0010; + val = value << 4; + } + b43_phy_maskset(dev, reg, ~tmp, val); + break; + case 3: + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + tmp = 0x0001; + val = value; + } else { + tmp = 0x0004; + val = value << 2; + } + b43_phy_maskset(dev, reg, ~tmp, val); + break; + case 4: + if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { + tmp = 0x0002; + val = value << 1; + } else { + tmp = 0x0008; + val = value << 3; + } + b43_phy_maskset(dev, reg, ~tmp, val); + break; + } + } +} + static void b43_nphy_bphy_init(struct b43_wldev *dev) { unsigned int i; @@ -2161,9 +2262,9 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); - /* TODO: Call N PHY RF Ctrl Intc Override with 2, 1, 3 */ - /* TODO: Call N PHY RF Ctrl Intc Override with 1, 2, 1 */ - /* TODO: Call N PHY RF Ctrl Intc Override with 1, 8, 2 */ + b43_nphy_rf_control_intc_override(dev, 2, 1, 3); + b43_nphy_rf_control_intc_override(dev, 1, 2, 1); + b43_nphy_rf_control_intc_override(dev, 1, 8, 2); regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); -- cgit v1.2.3 From 984ff4ffb7fa36b9ac440a3802fd19658eccc84e Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 12:23:10 +0100 Subject: b43: N-PHY: prepare code for reapplying TX cal coeffs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 8992457b0c0b..3dd22bc527d0 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2587,6 +2587,39 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, return error; } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ +static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + u8 i; + u16 buffer[7]; + bool equal = true; + + if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */) + return; + + b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); + for (i = 0; i < 4; i++) { + if (buffer[i] != nphy->txiqlocal_bestc[i]) { + equal = false; + break; + } + } + + if (!equal) { + b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, + nphy->txiqlocal_bestc); + for (i = 0; i < 4; i++) + buffer[i] = 0; + b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, + buffer); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, + &nphy->txiqlocal_bestc[5]); + b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, + &nphy->txiqlocal_bestc[5]); + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, struct nphy_txgains target, u8 type, bool debug) @@ -2617,7 +2650,7 @@ static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, b43_nphy_stay_in_carrier_search(dev, 1); if (dev->phy.rev < 2) - ;/* TODO: Call N PHY Reapply TX Cal Coeffs */ + b43_nphy_reapply_tx_cal_coeffs(dev); b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); for (i = 0; i < 2; i++) { b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); -- cgit v1.2.3 From bbc6dc121de92dee506e359eeb9b1d3973d0740a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 12:23:11 +0100 Subject: b43: N-PHY: save calibration for further restore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 51 +++++++++++++++++++++++++++++++++++++++- drivers/net/wireless/b43/phy_n.h | 1 + 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3dd22bc527d0..b332ffbe59d8 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2295,6 +2295,55 @@ static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) } } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ +static void b43_nphy_save_cal(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; + u16 *txcal_radio_regs = NULL; + u8 *iqcal_chanspec; + u16 *table = NULL; + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; + txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; + iqcal_chanspec = &nphy->iqcal_chanspec_2G; + table = nphy->cal_cache.txcal_coeffs_2G; + } else { + rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; + txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; + iqcal_chanspec = &nphy->iqcal_chanspec_5G; + table = nphy->cal_cache.txcal_coeffs_5G; + } + + b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); + /* TODO use some definitions */ + if (dev->phy.rev >= 3) { + txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); + txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); + txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); + txcal_radio_regs[3] = b43_radio_read(dev, 0x3022); + txcal_radio_regs[4] = b43_radio_read(dev, 0x2023); + txcal_radio_regs[5] = b43_radio_read(dev, 0x2024); + txcal_radio_regs[6] = b43_radio_read(dev, 0x3023); + txcal_radio_regs[7] = b43_radio_read(dev, 0x3024); + } else { + txcal_radio_regs[0] = b43_radio_read(dev, 0x8B); + txcal_radio_regs[1] = b43_radio_read(dev, 0xBA); + txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); + txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); + } + *iqcal_chanspec = nphy->radio_chanspec; + b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ static void b43_nphy_restore_cal(struct b43_wldev *dev) { @@ -2992,7 +3041,7 @@ int b43_phy_initn(struct b43_wldev *dev) if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) - ;/* Call N PHY Save Cal */ + b43_nphy_save_cal(dev); else if (nphy->mphase_cal_phase_id == 0) ;/* N PHY Periodic Calibration with argument 3 */ } else { diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index ae82f0fc2096..0400a2cb76a9 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -975,6 +975,7 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; + u16 radio_chanspec; bool gain_boost; bool elna_gain_config; -- cgit v1.2.3 From 9442e5b58edb4a108ec5aae420a6fff3a63acab0 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 12:23:12 +0100 Subject: b43: N-PHY: partly implement SPUR workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 64 +++++++++++++++++++++++++++++++++++++++- drivers/net/wireless/b43/phy_n.h | 3 ++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index b332ffbe59d8..74642d43e1ff 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -717,6 +717,67 @@ static void b43_nphy_stop_playback(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ +static void b43_nphy_spur_workaround(struct b43_wldev *dev) +{ + struct b43_phy_n *nphy = dev->phy.n; + + unsigned int channel; + int tone[2] = { 57, 58 }; + u32 noise[2] = { 0x3FF, 0x3FF }; + + B43_WARN_ON(dev->phy.rev < 3); + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + /* FIXME: channel = radio_chanspec */ + + if (nphy->gband_spurwar_en) { + /* TODO: N PHY Adjust Analog Pfbw (7) */ + if (channel == 11 && dev->phy.is_40mhz) + ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ + else + ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ + /* TODO: N PHY Adjust CRS Min Power (0x1E) */ + } + + if (nphy->aband_spurwar_en) { + if (channel == 54) { + tone[0] = 0x20; + noise[0] = 0x25F; + } else if (channel == 38 || channel == 102 || channel == 118) { + if (0 /* FIXME */) { + tone[0] = 0x20; + noise[0] = 0x21F; + } else { + tone[0] = 0; + noise[0] = 0; + } + } else if (channel == 134) { + tone[0] = 0x20; + noise[0] = 0x21F; + } else if (channel == 151) { + tone[0] = 0x10; + noise[0] = 0x23F; + } else if (channel == 153 || channel == 161) { + tone[0] = 0x30; + noise[0] = 0x23F; + } else { + tone[0] = 0; + noise[0] = 0; + } + + if (!tone[0] && !noise[0]) + ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ + else + ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ + } + + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) { @@ -3055,7 +3116,8 @@ int b43_phy_initn(struct b43_wldev *dev) if (phy->rev >= 3 && phy->rev <= 6) b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); b43_nphy_tx_lp_fbw(dev); - /* TODO N PHY Spur Workaround */ + if (phy->rev >= 3) + b43_nphy_spur_workaround(dev); b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); return 0; diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 0400a2cb76a9..403aad3f894f 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -1002,6 +1002,9 @@ struct b43_phy_n { u16 classifier_state; u16 clip_state[2]; + bool aband_spurwar_en; + bool gband_spurwar_en; + bool ipa2g_on; u8 iqcal_chanspec_2G; u8 rssical_chanspec_2G; -- cgit v1.2.3 From 5f6393ecf5cc7d064ba9172e0a2e1c64bcaaaf2f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 13:08:08 +0100 Subject: b43: N-PHY: load generated samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 74642d43e1ff..074b34c3b383 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1017,6 +1017,33 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_nphy_stay_in_carrier_search(dev, 0); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ +static int b43_nphy_load_samples(struct b43_wldev *dev, + struct b43_c32 *samples, u16 len) { + struct b43_phy_n *nphy = dev->phy.n; + u16 i; + u32 *data; + + data = kzalloc(len * sizeof(u32), GFP_KERNEL); + if (!data) { + b43err(dev->wl, "allocation for samples loading failed\n"); + return -ENOMEM; + } + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 1); + + for (i = 0; i < len; i++) { + data[i] = (samples[i].i & 0x3FF << 10); + data[i] |= samples[i].q & 0x3FF; + } + b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data); + + kfree(data); + if (nphy->hang_avoid) + b43_nphy_stay_in_carrier_search(dev, 0); + return 0; +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, bool test) @@ -1052,9 +1079,9 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, samples[i].i = CORDIC_CONVERT(samples[i].i * max); } - /* TODO: Call N PHY Load Sample Table with buffer, len as arguments */ + i = b43_nphy_load_samples(dev, samples, len); kfree(samples); - return len; + return (i < 0) ? 0 : len; } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ -- cgit v1.2.3 From 40bd5203ddb6b946b55c35d1c26dfe9ec1b232f5 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 4 Feb 2010 13:11:54 +0100 Subject: b43: N-PHY: handle allocation fail in samples generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 074b34c3b383..795bb1e3345d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1069,6 +1069,10 @@ static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, } samples = kzalloc(len * sizeof(struct b43_c32), GFP_KERNEL); + if (!samples) { + b43err(dev->wl, "allocation for samples generation failed\n"); + return 0; + } rot = (((freq * 36) / bw) << 16) / 100; angle = 0; -- cgit v1.2.3 From 85359499eec796e784e2f1e3d7bbb31d84dd4c2b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 4 Feb 2010 15:33:25 +0200 Subject: wl1251: fix txop unit mac80211 uses unit units of 32 usec with txop but wl1251_acx_ac_cfg() expects it to be usecs. This fortunately didn't cause any severe problems, only that firmware was using incorrect WMM settings. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1251_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index a717dde4822e..24ae6a360ac8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1144,9 +1144,10 @@ static int wl1251_op_conf_tx(struct ieee80211_hw *hw, u16 queue, if (ret < 0) goto out; + /* mac80211 uses units of 32 usec */ ret = wl1251_acx_ac_cfg(wl, wl1251_tx_get_queue(queue), params->cw_min, params->cw_max, - params->aifs, params->txop); + params->aifs, params->txop * 32); if (ret < 0) goto out_sleep; -- cgit v1.2.3 From 40e6fa829a2544c9f8fd5a94844fe502334d6afc Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Thu, 4 Feb 2010 14:37:45 +0100 Subject: libertas: don't retry commands Retrying commands seldomly works, most often the firmware is in a weird state anyway and needs the device to reset. So it's better to report the broken state back to user-space. Also rename command_timer_fn() into lbs_cmd_timeout_handler(), which better reflect it's usage. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmdresp.c | 5 ----- drivers/net/wireless/libertas/dev.h | 1 - drivers/net/wireless/libertas/main.c | 31 +++++++------------------------ 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 0334a58820ee..e7470442f76b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -240,11 +240,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) /* Now we got response from FW, cancel the command timer */ del_timer(&priv->command_timer); priv->cmd_timed_out = 0; - if (priv->nr_retries) { - lbs_pr_info("Received result %x to command %x after %d retries\n", - result, curcmd, priv->nr_retries); - priv->nr_retries = 0; - } /* Store the response code to cur_cmd_retcode. */ priv->cur_cmd_retcode = result; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index d5a9dcae4059..efb2519d9d74 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -109,7 +109,6 @@ struct lbs_private { struct list_head cmdpendingq; /* pending command buffers */ wait_queue_head_t cmd_pending; struct timer_list command_timer; - int nr_retries; int cmd_timed_out; /* Command responses sent from the hardware to the driver */ diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index f9f195f7b17c..f5d641efd50a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -533,31 +533,14 @@ static int lbs_thread(void *data) if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; - if (++priv->nr_retries > 3) { - lbs_pr_info("Excessive timeouts submitting " - "command 0x%04x\n", - le16_to_cpu(cmdnode->cmdbuf->command)); - lbs_complete_command(priv, cmdnode, -ETIMEDOUT); - priv->nr_retries = 0; - if (priv->reset_card) - priv->reset_card(priv); - } else { - priv->cur_cmd = NULL; - priv->dnld_sent = DNLD_RES_RECEIVED; - lbs_pr_info("requeueing command 0x%04x due " - "to timeout (#%d)\n", - le16_to_cpu(cmdnode->cmdbuf->command), - priv->nr_retries); - - /* Stick it back at the _top_ of the pending queue - for immediate resubmission */ - list_add(&cmdnode->list, &priv->cmdpendingq); - } + lbs_pr_info("Timeout submitting command 0x%04x\n", + le16_to_cpu(cmdnode->cmdbuf->command)); + lbs_complete_command(priv, cmdnode, -ETIMEDOUT); + if (priv->reset_card) + priv->reset_card(priv); } priv->cmd_timed_out = 0; - - if (!priv->fw_ready) continue; @@ -729,7 +712,7 @@ done: * This function handles the timeout of command sending. * It will re-send the same command again. */ -static void command_timer_fn(unsigned long data) +static void lbs_cmd_timeout_handler(unsigned long data) { struct lbs_private *priv = (struct lbs_private *)data; unsigned long flags; @@ -848,7 +831,7 @@ static int lbs_init_adapter(struct lbs_private *priv) mutex_init(&priv->lock); - setup_timer(&priv->command_timer, command_timer_fn, + setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, (unsigned long)priv); setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, (unsigned long)priv); -- cgit v1.2.3 From 199d69f27326858b16449eb1cc1623299db64415 Mon Sep 17 00:00:00 2001 From: Benoit Papillault Date: Thu, 4 Feb 2010 22:00:20 +0100 Subject: mac80211: Added a new debugfs file for reading channel_type This file helps debugging HT channels since it displays if we are on ht20 or ht40+/ht40- Signed-off-by: Benoit Papillault Signed-off-by: John W. Linville --- net/mac80211/debugfs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index b3bc32b62a5a..637929b65ccc 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -250,6 +250,38 @@ static const struct file_operations uapsd_max_sp_len_ops = { .open = mac80211_open_file_generic }; +static ssize_t channel_type_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + const char *buf; + + switch (local->hw.conf.channel_type) { + case NL80211_CHAN_NO_HT: + buf = "no ht\n"; + break; + case NL80211_CHAN_HT20: + buf = "ht20\n"; + break; + case NL80211_CHAN_HT40MINUS: + buf = "ht40-\n"; + break; + case NL80211_CHAN_HT40PLUS: + buf = "ht40+\n"; + break; + default: + buf = "???"; + break; + } + + return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); +} + +static const struct file_operations channel_type_ops = { + .read = channel_type_read, + .open = mac80211_open_file_generic +}; + static ssize_t queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -408,6 +440,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(noack); DEBUGFS_ADD(uapsd_queues); DEBUGFS_ADD(uapsd_max_sp_len); + DEBUGFS_ADD(channel_type); statsd = debugfs_create_dir("statistics", phyd); -- cgit v1.2.3 From 19885c4fbd79439efd6b3798bfb73f2f30e27104 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 5 Feb 2010 11:45:06 +0100 Subject: mac80211: fix bss_conf.dtim_period In AP mode, the only mode where the parameter is supposed to be valid, we never assign it! Fix that to allow drivers to avoid parsing the TIM IE for the value. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/cfg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a362523d8eb7..e1731b7c2523 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -515,6 +515,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, if (old) memcpy(new->tail, old->tail, new_tail_len); + sdata->vif.bss_conf.dtim_period = new->dtim_period; + rcu_assign_pointer(sdata->u.ap.beacon, new); synchronize_rcu(); -- cgit v1.2.3 From d4fe5ac9e04e6e175a7bd7e29844b351533be591 Mon Sep 17 00:00:00 2001 From: Ben Cahill Date: Fri, 5 Feb 2010 11:33:46 -0800 Subject: iwlwifi: Add chain noise scaling factor 6x50 device requires a different scaling factor for Rx gain values sent to device via PHY_CALIBRATION_CMD (CHAIN_NOISE_GAIN_CMD). Rather than create a new iwlXXXX_gain_computation() function, add new chain_noise_scale member to struct iwl_cfg, and keep using iwl5000_gain_computation(). Signed-off-by: Ben Cahill Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-5000.c | 21 +++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 + 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9d1820676f30..694ceef88590 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -247,6 +247,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -274,6 +275,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 6d5988901341..f3d662c8cbcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -179,14 +179,24 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, data->delta_gain_code[i] = 0; continue; } - delta_g = (1000 * ((s32)average_noise[default_chain] - + + delta_g = (priv->cfg->chain_noise_scale * + ((s32)average_noise[default_chain] - (s32)average_noise[i])) / 1500; + /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) - /* set negative sign */ + /* + * set negative sign ... + * note to Intel developers: This is uCode API format, + * not the format of any internal device registers. + * Do not change this format for e.g. 6050 or similar + * devices. Change format only if more resolution + * (i.e. more than 2 bits magnitude) is needed. + */ data->delta_gain_code[i] |= (1 << 2); } @@ -1587,6 +1597,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -1612,6 +1623,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -1635,6 +1647,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -1660,6 +1673,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -1685,6 +1699,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -1710,6 +1725,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -1733,6 +1749,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a9f8551e0e40..17198253b0bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -324,6 +324,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -354,6 +355,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -384,6 +386,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -415,6 +418,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1500, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -445,6 +449,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1500, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -476,6 +481,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ec1fe1d7cc9a..49795b90246d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -293,6 +293,7 @@ struct iwl_cfg { bool support_ct_kill_exit; const bool support_wimax_coexist; u8 plcp_delta_threshold; + s32 chain_noise_scale; }; /*************************** -- cgit v1.2.3 From ed56a3f15a0561e900957ecca0dee42b9b453a9e Mon Sep 17 00:00:00 2001 From: Ben Cahill Date: Fri, 5 Feb 2010 11:33:47 -0800 Subject: iwlwifi: Add chain_noise support for 6050 Existing iwl6050_ops->iwl6050_hcmd_utils structure had no pointers to chain noise functions (gain_computation and chain_noise_reset). As it turns out, by adding chain_noise_scale (see related patch), there is no need for separate chain noise function, so simply use iwl6000_ops->iwl5000_hcmd_utils, and remove those for 6050. Signed-off-by: Ben Cahill Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 17198253b0bc..782e23a26984 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -277,21 +277,6 @@ static const struct iwl_ops iwl6000_ops = { .led = &iwlagn_led_ops, }; -static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = { - .get_hcmd_size = iwl5000_get_hcmd_size, - .build_addsta_hcmd = iwl5000_build_addsta_hcmd, - .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, - .calc_rssi = iwl5000_calc_rssi, -}; - -static const struct iwl_ops iwl6050_ops = { - .ucode = &iwl5000_ucode, - .lib = &iwl6000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl6050_hcmd_utils, - .led = &iwlagn_led_ops, -}; - /* * "i": Internal configuration, use internal Power Amplifier */ @@ -395,7 +380,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6050_ops, + .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -427,7 +412,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, - .ops = &iwl6050_ops, + .ops = &iwl6000_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, -- cgit v1.2.3 From 21b2d8bd2f0d4e0f21ade147fd193c8b9c1fd2b9 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Fri, 5 Feb 2010 11:33:48 -0800 Subject: iwlwifi: Send broadcast probe request only when asked to When running directed active scans we currently end up sending both the SSID probe requests and an additional broadcast one. This is due to the fact that we always leave the probe request template SSID IE length to 0. Instead we should set it to the first SSID to scan, and fill the direct_scan array with the remaining SSIDs to scan for. This way we only send what we've been asked to: a broadcast probe request when no directed scan is requested, and directed probe requests otherwise. Signed-off-by: Samuel Ortiz Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 49 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b528a20ade4f..f51b8cd80de5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2631,7 +2631,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) */ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX + 1; /* we create the 802.11 header and a zero-length SSID element */ hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 08faafae8497..f786a407638f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -651,9 +651,20 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, if (left < 0) return 0; *pos++ = WLAN_EID_SSID; - *pos++ = 0; - - len += 2; + if (!priv->is_internal_short_scan && + priv->scan_request->n_ssids) { + struct cfg80211_ssid *ssid = + priv->scan_request->ssids; + + /* Broadcast if ssid_len is 0 */ + *pos++ = ssid->ssid_len; + memcpy(pos, ssid->ssid, ssid->ssid_len); + pos += ssid->ssid_len; + len += 2 + ssid->ssid_len; + } else { + *pos++ = 0; + len += 2; + } if (WARN_ON(left < ie_len)) return len; @@ -782,20 +793,26 @@ static void iwl_bg_request_scan(struct work_struct *data) if (priv->is_internal_short_scan) { IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); } else if (priv->scan_request->n_ssids) { - int i, p = 0; IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - for (i = 0; i < priv->scan_request->n_ssids; i++) { - /* always does wildcard anyway */ - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; + /* + * The first SSID to scan is stuffed into the probe request + * template and the remaining ones are handled through the + * direct_scan array. + */ + if (priv->scan_request->n_ssids > 1) { + int i, p = 0; + for (i = 1; i < priv->scan_request->n_ssids; i++) { + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; + } } is_active = true; } else -- cgit v1.2.3 From 29165e4c8b265a415f1fd1dca947b5d4c72abc47 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 6 Feb 2010 15:20:13 +0100 Subject: mac80211: fix deauth race When userspace requests a deauth while the authentication work is pending in the auth (not probe) state, we do not properly abort the work and then things get confused. Fix that and also improve the checks here to include the correct virtual interface, just in case two virtual interfaces would ever try to connect to the same BSS. Also fix a bug -- need to use list_del_rcu instead of just list_del to free a work item. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ac9429e8d72b..7a7921476582 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1995,12 +1995,18 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_lock(&local->work_mtx); list_for_each_entry(wk, &local->work_list, list) { - if (wk->type != IEEE80211_WORK_DIRECT_PROBE) + if (wk->sdata != sdata) continue; + + if (wk->type != IEEE80211_WORK_DIRECT_PROBE && + wk->type != IEEE80211_WORK_AUTH) + continue; + if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) continue; - not_auth_yet = true; - list_del(&wk->list); + + not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE; + list_del_rcu(&wk->list); free_work(wk); break; } -- cgit v1.2.3 From 733da37dab72de6b3f8b0c56b5cdea322f18a684 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 6 Feb 2010 22:38:23 +0800 Subject: ath9k: fix keycache leak in split tkip case If split tkip key is used, ath_delete_key should delete rx key and rx mic key. This patch fixes the leak of hw keycache in the case. Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 40da7a6e4b6b..9c8f925c2093 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -809,6 +809,7 @@ static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf clear_bit(key->hw_key_idx + 64, common->keymap); if (common->splitmic) { + ath9k_hw_keyreset(ah, key->hw_key_idx + 32); clear_bit(key->hw_key_idx + 32, common->keymap); clear_bit(key->hw_key_idx + 64 + 32, common->keymap); } -- cgit v1.2.3 From 4046fe66ce74b66b553035c57c892f4715e074db Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:20:44 +0200 Subject: adm821: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Cc: Michael Wu Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index e1f04bb437e3..6508515feed3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -302,18 +302,6 @@ static int adm8211_get_stats(struct ieee80211_hw *dev, return 0; } -static int adm8211_get_tx_stats(struct ieee80211_hw *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct adm8211_priv *priv = dev->priv; - - stats[0].len = priv->cur_tx - priv->dirty_tx; - stats[0].limit = priv->tx_ring_size - 2; - stats[0].count = priv->dirty_tx; - - return 0; -} - static void adm8211_interrupt_tci(struct ieee80211_hw *dev) { struct adm8211_priv *priv = dev->priv; @@ -1773,7 +1761,6 @@ static const struct ieee80211_ops adm8211_ops = { .prepare_multicast = adm8211_prepare_multicast, .configure_filter = adm8211_configure_filter, .get_stats = adm8211_get_stats, - .get_tx_stats = adm8211_get_tx_stats, .get_tsf = adm8211_get_tsft }; -- cgit v1.2.3 From 8ccbc3b8b0c919e8609560ca56cd777ece8d2c41 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:20:52 +0200 Subject: mwl8k: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. mwl8k used struct ieee80211_tx_queue_stats internally to track the queue lenght. Replace struct ieee80211_tx_queue_stats with a simple len field in struct mwl8k_tx_queue. Limit and count fields seemed to be unused. Compile-tested only. Cc: Lennert Buytenhek Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f0f08f3919cc..0cfdb9db66f7 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -119,7 +119,7 @@ struct mwl8k_tx_queue { /* sw appends here */ int tail; - struct ieee80211_tx_queue_stats stats; + unsigned int len; struct mwl8k_tx_desc *txd; dma_addr_t txd_dma; struct sk_buff **skb; @@ -1136,8 +1136,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) int size; int i; - memset(&txq->stats, 0, sizeof(struct ieee80211_tx_queue_stats)); - txq->stats.limit = MWL8K_TX_DESCS; + txq->len = 0; txq->head = 0; txq->tail = 0; @@ -1213,7 +1212,7 @@ static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw) printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d " "fw_owned=%d drv_owned=%d unused=%d\n", wiphy_name(hw->wiphy), i, - txq->stats.len, txq->head, txq->tail, + txq->len, txq->head, txq->tail, fw_owned, drv_owned, unused); } } @@ -1299,7 +1298,7 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) int processed; processed = 0; - while (txq->stats.len > 0 && limit--) { + while (txq->len > 0 && limit--) { int tx; struct mwl8k_tx_desc *tx_desc; unsigned long addr; @@ -1321,8 +1320,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force) } txq->head = (tx + 1) % MWL8K_TX_DESCS; - BUG_ON(txq->stats.len == 0); - txq->stats.len--; + BUG_ON(txq->len == 0); + txq->len--; priv->pending_tx_pkts--; addr = le32_to_cpu(tx_desc->pkt_phys_addr); @@ -1454,8 +1453,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) wmb(); tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); - txq->stats.count++; - txq->stats.len++; + txq->len++; priv->pending_tx_pkts++; txq->tail++; @@ -3818,24 +3816,6 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, return rc; } -static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq; - int index; - - spin_lock_bh(&priv->tx_lock); - for (index = 0; index < MWL8K_TX_QUEUES; index++) { - txq = priv->txq + index; - memcpy(&stats[index], &txq->stats, - sizeof(struct ieee80211_tx_queue_stats)); - } - spin_unlock_bh(&priv->tx_lock); - - return 0; -} - static int mwl8k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -3871,7 +3851,6 @@ static const struct ieee80211_ops mwl8k_ops = { .set_rts_threshold = mwl8k_set_rts_threshold, .sta_notify = mwl8k_sta_notify, .conf_tx = mwl8k_conf_tx, - .get_tx_stats = mwl8k_get_tx_stats, .get_stats = mwl8k_get_stats, .ampdu_action = mwl8k_ampdu_action, }; -- cgit v1.2.3 From d1ace8e57a4e3af78767684c6f6b5f8b88417abb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:21:00 +0200 Subject: ar9170: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Because ar9170 uses ieee80211_tx_queue_stats internally, create a new identical struct ar9170_tx_queue_stats which the driver can use. Compile-tested only. Signed-off-by: Kalle Valo Tested-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/ar9170.h | 8 +++++++- drivers/net/wireless/ath/ar9170/main.c | 13 ------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index b99a8c2053d8..8c8ce67971e9 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -144,6 +144,12 @@ struct ar9170_sta_tid { bool active; }; +struct ar9170_tx_queue_stats { + unsigned int len; + unsigned int limit; + unsigned int count; +}; + #define AR9170_QUEUE_TIMEOUT 64 #define AR9170_TX_TIMEOUT 8 #define AR9170_BA_TIMEOUT 4 @@ -211,7 +217,7 @@ struct ar9170 { /* qos queue settings */ spinlock_t tx_stats_lock; - struct ieee80211_tx_queue_stats tx_stats[5]; + struct ar9170_tx_queue_stats tx_stats[5]; struct ieee80211_tx_queue_params edcf[5]; spinlock_t cmdlock; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 4d27f7f67c76..91797cb6e0e8 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2396,18 +2396,6 @@ static int ar9170_get_stats(struct ieee80211_hw *hw, return 0; } -static int ar9170_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *tx_stats) -{ - struct ar9170 *ar = hw->priv; - - spin_lock_bh(&ar->tx_stats_lock); - memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); - spin_unlock_bh(&ar->tx_stats_lock); - - return 0; -} - static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *param) { @@ -2509,7 +2497,6 @@ static const struct ieee80211_ops ar9170_ops = { .set_key = ar9170_set_key, .sta_notify = ar9170_sta_notify, .get_stats = ar9170_get_stats, - .get_tx_stats = ar9170_get_tx_stats, .ampdu_action = ar9170_ampdu_action, }; -- cgit v1.2.3 From 3b2119096d7ec4ef50427e07b562897f2c139c11 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:21:07 +0200 Subject: ath5k: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Cc: Jiri Slaby Cc: Nick Kossifidis Cc: Luis R. Rodriguez Signed-off-by: Kalle Valo Acked-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 18 ------------------ drivers/net/wireless/ath/ath5k/base.h | 1 - 2 files changed, 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 535a6afb94e3..97d642575550 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -241,8 +241,6 @@ static int ath5k_set_key(struct ieee80211_hw *hw, struct ieee80211_key_conf *key); static int ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); -static int ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); static u64 ath5k_get_tsf(struct ieee80211_hw *hw); static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); static void ath5k_reset_tsf(struct ieee80211_hw *hw); @@ -269,7 +267,6 @@ static const struct ieee80211_ops ath5k_hw_ops = { .set_key = ath5k_set_key, .get_stats = ath5k_get_stats, .conf_tx = NULL, - .get_tx_stats = ath5k_get_tx_stats, .get_tsf = ath5k_get_tsf, .set_tsf = ath5k_set_tsf, .reset_tsf = ath5k_reset_tsf, @@ -1332,7 +1329,6 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, spin_lock_bh(&txq->lock); list_add_tail(&bf->list, &txq->q); - sc->tx_stats[txq->qnum].len++; if (txq->link == NULL) /* is this first packet? */ ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); else /* no, so only link it */ @@ -1581,7 +1577,6 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) ath5k_txbuf_free(sc, bf); spin_lock_bh(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; list_move_tail(&bf->list, &sc->txbuf); sc->txbuf_len++; spin_unlock_bh(&sc->txbuflock); @@ -2011,10 +2006,8 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) } ieee80211_tx_status(sc->hw, skb); - sc->tx_stats[txq->qnum].count++; spin_lock(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; list_move_tail(&bf->list, &sc->txbuf); sc->txbuf_len++; spin_unlock(&sc->txbuflock); @@ -3116,17 +3109,6 @@ ath5k_get_stats(struct ieee80211_hw *hw, return 0; } -static int -ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - - memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); - - return 0; -} - static u64 ath5k_get_tsf(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index b72338c9bde7..9c2fbf230ce7 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -117,7 +117,6 @@ struct ath5k_softc { struct pci_dev *pdev; /* for dma mapping */ void __iomem *iobase; /* address of the device */ struct mutex lock; /* dev-level lock */ - struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; struct ieee80211_low_level_stats ll_stats; struct ieee80211_hw *hw; /* IEEE 802.11 common */ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; -- cgit v1.2.3 From 3b27521a5be8b700451d54d4fa670f754e7f9720 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 19:50:50 +0200 Subject: b43: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Cc: Stefano Brivio Cc: Michael Buesch Cc: Larry Finger Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 17 ----------------- drivers/net/wireless/b43/dma.h | 5 ----- drivers/net/wireless/b43/main.c | 22 ---------------------- drivers/net/wireless/b43/pio.c | 17 ----------------- drivers/net/wireless/b43/pio.h | 5 ----- 5 files changed, 66 deletions(-) diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 615af22c49fd..be7abf8916ad 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1369,7 +1369,6 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) b43err(dev->wl, "DMA tx mapping failure\n"); goto out; } - ring->nr_tx_packets++; if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || should_inject_overflow(ring)) { /* This TX ring is full. */ @@ -1500,22 +1499,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, } } -void b43_dma_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43_dmaring *ring; - int i; - - for (i = 0; i < nr_queues; i++) { - ring = select_ring_by_priority(dev, i); - - stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME; - stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME; - stats[i].count = ring->nr_tx_packets; - } -} - static void dma_rx(struct b43_dmaring *ring, int *slot) { const struct b43_dma_ops *ops = ring->ops; diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index f7ab37c4cdbc..dc91944d6022 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -228,8 +228,6 @@ struct b43_dmaring { int used_slots; /* Currently used slot in the ring. */ int current_slot; - /* Total number of packets sent. Statistics only. */ - unsigned int nr_tx_packets; /* Frameoffset in octets. */ u32 frameoffset; /* Descriptor buffer size. */ @@ -278,9 +276,6 @@ void b43_dma_free(struct b43_wldev *dev); void b43_dma_tx_suspend(struct b43_wldev *dev); void b43_dma_tx_resume(struct b43_wldev *dev); -void b43_dma_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats); - int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb); void b43_dma_handle_txstatus(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3c5143b935f2..8f7a8c0ec27d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3356,27 +3356,6 @@ out_unlock: return err; } -static int b43_op_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int err = -ENODEV; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (dev && b43_status(dev) >= B43_STAT_STARTED) { - if (b43_using_pio_transfers(dev)) - b43_pio_get_tx_stats(dev, stats); - else - b43_dma_get_tx_stats(dev, stats); - err = 0; - } - mutex_unlock(&wl->mutex); - - return err; -} - static int b43_op_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -4602,7 +4581,6 @@ static const struct ieee80211_ops b43_hw_ops = { .set_key = b43_op_set_key, .update_tkip_key = b43_op_update_tkip_key, .get_stats = b43_op_get_stats, - .get_tx_stats = b43_op_get_tx_stats, .get_tsf = b43_op_get_tsf, .set_tsf = b43_op_set_tsf, .start = b43_op_start, diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index c01b8e02412f..a6062c3e89a5 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -559,7 +559,6 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) b43err(dev->wl, "PIO transmission failure\n"); goto out; } - q->nr_tx_packets++; B43_WARN_ON(q->buffer_used > q->buffer_size); if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || @@ -605,22 +604,6 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, } } -void b43_pio_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43_pio_txqueue *q; - int i; - - for (i = 0; i < nr_queues; i++) { - q = select_queue_by_priority(dev, i); - - stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; - stats[i].limit = B43_PIO_MAX_NR_TXPACKETS; - stats[i].count = q->nr_tx_packets; - } -} - /* Returns whether we should fetch another frame. */ static bool pio_rx_frame(struct b43_pio_rxqueue *q) { diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index 7b3c42f93a16..1e516147424f 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h @@ -90,9 +90,6 @@ struct b43_pio_txqueue { struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS]; struct list_head packets_list; - /* Total number of transmitted packets. */ - unsigned int nr_tx_packets; - /* Shortcut to the 802.11 core revision. This is to * avoid horrible pointer dereferencing in the fastpaths. */ u8 rev; @@ -160,8 +157,6 @@ void b43_pio_free(struct b43_wldev *dev); int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); void b43_pio_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); -void b43_pio_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats); void b43_pio_rx(struct b43_pio_rxqueue *q); void b43_pio_tx_suspend(struct b43_wldev *dev); -- cgit v1.2.3 From 8b2bbe66abfdc60f73b094a56ab29bfbf939201c Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 19:51:00 +0200 Subject: b43legacy: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Cc: Larry Finger Cc: Stefano Brivio Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/dma.c | 20 -------------------- drivers/net/wireless/b43legacy/dma.h | 10 ---------- drivers/net/wireless/b43legacy/main.c | 24 ------------------------ drivers/net/wireless/b43legacy/pio.c | 13 ------------- drivers/net/wireless/b43legacy/pio.h | 11 ----------- 5 files changed, 78 deletions(-) diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 0a86bdf53154..8b9387c6ff36 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -1411,7 +1411,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, b43legacyerr(dev->wl, "DMA tx mapping failure\n"); goto out_unlock; } - ring->nr_tx_packets++; if ((free_slots(ring) < SLOTS_PER_PACKET) || should_inject_overflow(ring)) { /* This TX ring is full. */ @@ -1527,25 +1526,6 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, spin_unlock(&ring->lock); } -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43legacy_dmaring *ring; - unsigned long flags; - int i; - - for (i = 0; i < nr_queues; i++) { - ring = priority_to_txring(dev, i); - - spin_lock_irqsave(&ring->lock, flags); - stats[i].len = ring->used_slots / SLOTS_PER_PACKET; - stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET; - stats[i].count = ring->nr_tx_packets; - spin_unlock_irqrestore(&ring->lock, flags); - } -} - static void dma_rx(struct b43legacy_dmaring *ring, int *slot) { diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index 2f186003c31e..f9681041c2d8 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h @@ -243,8 +243,6 @@ struct b43legacy_dmaring { int used_slots; /* Currently used slot in the ring. */ int current_slot; - /* Total number of packets sent. Statistics only. */ - unsigned int nr_tx_packets; /* Frameoffset in octets. */ u32 frameoffset; /* Descriptor buffer size. */ @@ -292,9 +290,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev); void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats); - int b43legacy_dma_tx(struct b43legacy_wldev *dev, struct sk_buff *skb); void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, @@ -315,11 +310,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) { } static inline -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline int b43legacy_dma_tx(struct b43legacy_wldev *dev, struct sk_buff *skb) { diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index b4e89a35e3fb..08523a45e23b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2446,29 +2446,6 @@ static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; } -static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - int err = -ENODEV; - - if (!dev) - goto out; - spin_lock_irqsave(&wl->irq_lock, flags); - if (likely(b43legacy_status(dev) >= B43legacy_STAT_STARTED)) { - if (b43legacy_using_pio(dev)) - b43legacy_pio_get_tx_stats(dev, stats); - else - b43legacy_dma_get_tx_stats(dev, stats); - err = 0; - } - spin_unlock_irqrestore(&wl->irq_lock, flags); -out: - return err; -} - static int b43legacy_op_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -3513,7 +3490,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .bss_info_changed = b43legacy_op_bss_info_changed, .configure_filter = b43legacy_op_configure_filter, .get_stats = b43legacy_op_get_stats, - .get_tx_stats = b43legacy_op_get_tx_stats, .start = b43legacy_op_start, .stop = b43legacy_op_stop, .set_tim = b43legacy_op_beacon_set_tim, diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 51866c9a2769..017c0e9c37ef 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -477,7 +477,6 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev, list_move_tail(&packet->list, &queue->txqueue); queue->nr_txfree--; - queue->nr_tx_packets++; B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS); tasklet_schedule(&queue->txtask); @@ -546,18 +545,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, tasklet_schedule(&queue->txtask); } -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43legacy_pio *pio = &dev->pio; - struct b43legacy_pioqueue *queue; - - queue = pio->queue1; - stats[0].len = B43legacy_PIO_MAXTXPACKETS - queue->nr_txfree; - stats[0].limit = B43legacy_PIO_MAXTXPACKETS; - stats[0].count = queue->nr_tx_packets; -} - static void pio_rx_error(struct b43legacy_pioqueue *queue, int clear_buffers, const char *error) diff --git a/drivers/net/wireless/b43legacy/pio.h b/drivers/net/wireless/b43legacy/pio.h index 464fec05a06d..8e6773ea6e75 100644 --- a/drivers/net/wireless/b43legacy/pio.h +++ b/drivers/net/wireless/b43legacy/pio.h @@ -74,10 +74,6 @@ struct b43legacy_pioqueue { * posted to the device. We are waiting for the txstatus. */ struct list_head txrunning; - /* Total number or packets sent. - * (This counter can obviously wrap). - */ - unsigned int nr_tx_packets; struct tasklet_struct txtask; struct b43legacy_pio_txpacket tx_packets_cache[B43legacy_PIO_MAXTXPACKETS]; @@ -106,8 +102,6 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev, struct sk_buff *skb); void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, const struct b43legacy_txstatus *status); -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats); void b43legacy_pio_rx(struct b43legacy_pioqueue *queue); /* Suspend TX queue in hardware. */ @@ -140,11 +134,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, { } static inline -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline void b43legacy_pio_rx(struct b43legacy_pioqueue *queue) { } -- cgit v1.2.3 From 1296d4744516aeae8809e2f47ceecd88df4b037f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:21:37 +0200 Subject: iwlwifi: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Cc: Zhu Yi Signed-off-by: Kalle Valo Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 36 ----------------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - 4 files changed, 40 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f51b8cd80de5..c1eff4c5b448 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3440,7 +3440,6 @@ static struct ieee80211_ops iwl_hw_ops = { .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, .get_stats = iwl_mac_get_stats, - .get_tx_stats = iwl_mac_get_tx_stats, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b248fba4875e..d390eef2efe5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2851,42 +2851,6 @@ out: } EXPORT_SYMBOL(iwl_mac_config); -int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} -EXPORT_SYMBOL(iwl_mac_get_tx_stats); - void iwl_mac_reset_tsf(struct ieee80211_hw *hw) { struct iwl_priv *priv = hw->priv; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 49795b90246d..8f0c564e68b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -342,8 +342,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); void iwl_config_ap(struct iwl_priv *priv); -int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); void iwl_mac_reset_tsf(struct ieee80211_hw *hw); int iwl_alloc_txq_mem(struct iwl_priv *priv); void iwl_free_txq_mem(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 119da54116de..eac2b9a95711 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3835,7 +3835,6 @@ static struct ieee80211_ops iwl3945_hw_ops = { .config = iwl_mac_config, .configure_filter = iwl_configure_filter, .set_key = iwl3945_mac_set_key, - .get_tx_stats = iwl_mac_get_tx_stats, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, .bss_info_changed = iwl_bss_info_changed, -- cgit v1.2.3 From 97e93fcd866ee7cc02082fc62509378f50547936 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:21:46 +0200 Subject: p54: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. p54 uses struct ieee80211_tx_queue_stats also internally, so create a new identical struct p54_tx_queue_stats which the driver can use. Compile-tested only. Signed-off-by: Kalle Valo Tested-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/main.c | 11 ----------- drivers/net/wireless/p54/p54.h | 8 +++++++- drivers/net/wireless/p54/txrx.c | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 26428e4c9c60..3fe6366e567c 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -358,16 +358,6 @@ static int p54_get_stats(struct ieee80211_hw *dev, return 0; } -static int p54_get_tx_stats(struct ieee80211_hw *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct p54_common *priv = dev->priv; - - memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA], - sizeof(stats[0]) * dev->queues); - return 0; -} - static void p54_bss_info_changed(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, @@ -522,7 +512,6 @@ static const struct ieee80211_ops p54_ops = { .configure_filter = p54_configure_filter, .conf_tx = p54_conf_tx, .get_stats = p54_get_stats, - .get_tx_stats = p54_get_tx_stats }; struct ieee80211_hw *p54_init_common(size_t priv_data_len) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 1afc39410e85..43a3b2ead81a 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -157,6 +157,12 @@ struct p54_led_dev { #endif /* CONFIG_P54_LEDS */ +struct p54_tx_queue_stats { + unsigned int len; + unsigned int limit; + unsigned int count; +}; + struct p54_common { struct ieee80211_hw *hw; struct ieee80211_vif *vif; @@ -183,7 +189,7 @@ struct p54_common { /* (e)DCF / QOS state */ bool use_short_slot; spinlock_t tx_stats_lock; - struct ieee80211_tx_queue_stats tx_stats[8]; + struct p54_tx_queue_stats tx_stats[8]; struct p54_edcf_queue_param qos_params[8]; /* Radio data */ diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index b6dda2b27fb5..0e8f69461ffe 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -183,7 +183,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, struct sk_buff *skb, const u16 p54_queue) { - struct ieee80211_tx_queue_stats *queue; + struct p54_tx_queue_stats *queue; unsigned long flags; if (WARN_ON(p54_queue > P54_QUEUE_NUM)) -- cgit v1.2.3 From 00a08eb62f790383bcc8ea309d4afb9ef346ef0b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:21:53 +0200 Subject: rt2x00: remove get_tx_stats() mac80211 op get_tx_stats() will be removed from mac80211. Compile-tested only. Signed-off-by: Kalle Valo Acked-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 - drivers/net/wireless/rt2x00/rt2500pci.c | 1 - drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2800lib.c | 1 - drivers/net/wireless/rt2x00/rt2x00.h | 2 -- drivers/net/wireless/rt2x00/rt2x00mac.c | 16 ---------------- drivers/net/wireless/rt2x00/rt61pci.c | 1 - drivers/net/wireless/rt2x00/rt73usb.c | 1 - 8 files changed, 24 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index d86d233c6810..184335950825 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1561,7 +1561,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2400pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, .tx_last_beacon = rt2400pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 46cbc6ef66ab..7dfcffadda2a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1859,7 +1859,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, .tx_last_beacon = rt2500pci_tx_last_beacon, .rfkill_poll = rt2x00mac_rfkill_poll, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9e6f865c57f2..81ca4ec068db 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1761,7 +1761,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .rfkill_poll = rt2x00mac_rfkill_poll, }; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 529a37364eb0..a45e027f2d1f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2297,7 +2297,6 @@ const struct ieee80211_ops rt2800_mac80211_ops = { .set_rts_threshold = rt2800_set_rts_threshold, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2800_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 096da85a66fa..43b70c6e4e9c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1044,8 +1044,6 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, #endif /* CONFIG_RT2X00_LIB_CRYPTO */ int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); -int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 00f1f939f1bb..abbd857ec759 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -555,22 +555,6 @@ int rt2x00mac_get_stats(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_get_stats); -int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - unsigned int i; - - for (i = 0; i < rt2x00dev->ops->tx_queues; i++) { - stats[i].len = rt2x00dev->tx[i].length; - stats[i].limit = rt2x00dev->tx[i].limit; - stats[i].count = rt2x00dev->tx[i].count; - } - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats); - void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c353b497a65d..881340026c2a 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2730,7 +2730,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt61pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index a02691294395..3781eb7b4aa0 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2245,7 +2245,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt73usb_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, }; -- cgit v1.2.3 From 349e6b7289f8a3d3d5d3b859e00b41f27d1211df Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 7 Feb 2010 10:22:01 +0200 Subject: mac80211: remove get_tx_stats() driver op get_tx_stats() driver operation is not currently used anywhere in mac80211 and there are no plans to use it in the not-so-near future. So it can go without anyone missing it. Signed-off-by: Kalle Valo Acked-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/mac80211.tmpl | 1 - include/net/mac80211.h | 22 ---------------------- net/mac80211/driver-ops.h | 8 -------- net/mac80211/driver-trace.h | 23 ----------------------- 4 files changed, 54 deletions(-) diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl index 971d1c0c83e5..affb15a344a1 100644 --- a/Documentation/DocBook/mac80211.tmpl +++ b/Documentation/DocBook/mac80211.tmpl @@ -234,7 +234,6 @@ usage should require reading the full document. Multiple queues and QoS support TBD !Finclude/net/mac80211.h ieee80211_tx_queue_params -!Finclude/net/mac80211.h ieee80211_tx_queue_stats diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a19fac35259a..414d774028ba 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -117,19 +117,6 @@ struct ieee80211_tx_queue_params { bool uapsd; }; -/** - * struct ieee80211_tx_queue_stats - transmit queue statistics - * - * @len: number of packets in queue - * @limit: queue length limit - * @count: number of frames sent - */ -struct ieee80211_tx_queue_stats { - unsigned int len; - unsigned int limit; - unsigned int count; -}; - struct ieee80211_low_level_stats { unsigned int dot11ACKFailureCount; unsigned int dot11RTSFailureCount; @@ -1548,13 +1535,6 @@ enum ieee80211_ampdu_mlme_action { * Returns a negative error code on failure. * The callback can sleep. * - * @get_tx_stats: Get statistics of the current TX queue status. This is used - * to get number of currently queued packets (queue length), maximum queue - * size (limit), and total number of packets sent using each TX queue - * (count). The 'stats' pointer points to an array that has hw->queues - * items. - * The callback must be atomic. - * * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, * this is only used for IBSS mode BSSID merging and debugging. Is not a * required function. @@ -1648,8 +1628,6 @@ struct ieee80211_ops { enum sta_notify_cmd, struct ieee80211_sta *sta); int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); - int (*get_tx_stats)(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); u64 (*get_tsf)(struct ieee80211_hw *hw); void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf); void (*reset_tsf)(struct ieee80211_hw *hw); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 855e85b55061..c3d844093a2f 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -290,14 +290,6 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, return ret; } -static inline int drv_get_tx_stats(struct ieee80211_local *local, - struct ieee80211_tx_queue_stats *stats) -{ - int ret = local->ops->get_tx_stats(&local->hw, stats); - trace_drv_get_tx_stats(local, stats, ret); - return ret; -} - static inline u64 drv_get_tsf(struct ieee80211_local *local) { u64 ret = -1ULL; diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index c984910bf275..41baf730a5c7 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h @@ -630,29 +630,6 @@ TRACE_EVENT(drv_conf_tx, ) ); -TRACE_EVENT(drv_get_tx_stats, - TP_PROTO(struct ieee80211_local *local, - struct ieee80211_tx_queue_stats *stats, - int ret), - - TP_ARGS(local, stats, ret), - - TP_STRUCT__entry( - LOCAL_ENTRY - __field(int, ret) - ), - - TP_fast_assign( - LOCAL_ASSIGN; - __entry->ret = ret; - ), - - TP_printk( - LOCAL_PR_FMT " ret:%d", - LOCAL_PR_ARG, __entry->ret - ) -); - TRACE_EVENT(drv_get_tsf, TP_PROTO(struct ieee80211_local *local, u64 ret), -- cgit v1.2.3 From 641eabb0a3717020d1a93d3f91493ab0d826c910 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 7 Feb 2010 16:01:55 +0100 Subject: ath: fix WARN_ON with Polish (Poland) Contry code This patch fixes a WARN_ON which is triggered by Poland's country code. ath: EEPROM regdomain: 0x8268 ath: EEPROM indicates we should expect a country code ath: doing EEPROM country->regdmn map search ath: country maps to regdmn code: 0x37 ath: Country alpha2 being used: PL ath: Regpair used: 0x37 -----------[ cut here ]------------ WARNING: at drivers/net/wireless/ath/regd.c:155 ath_regd_init+0x30b Pid: 12661, comm: firmware/carl91 2.6.33-rc5-wl #18 Call Trace: [<>] ? warn_slowpath_common+0x76/0x8c [<>] ? ar9170_reg_notifier+0x0/0x2d [carl9170usb] [<>] ? ath_regd_init+0x30b/0x377 [ath] [<>] ? ar9170_register+0x3b3/0x3ca [carl9170usb] [...] ---[ end trace ]--- Note: Poland is just an example. But it is very likely that more country codes are affected. Cc: Luis R. Rodriguez Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/regd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 039ac490465c..04abd1f556b7 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -110,8 +110,9 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { static inline bool is_wwr_sku(u16 regd) { - return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || - (regd == WORLD); + return ((regd & COUNTRY_ERD_FLAG) != COUNTRY_ERD_FLAG) && + (((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || + (regd == WORLD)); } static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) -- cgit v1.2.3 From 209c671db7a917740ab9873d442b10ae7e369937 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Sun, 7 Feb 2010 21:47:50 -0500 Subject: mac80211: make rate_control_alloc static rate_control_alloc is not used by anything outside of ieee80211_init_rate_ctrl_alg. Both are in rate.c; there's no reason to make rate_control_alloc visible outside of it. Signed-off-by: Andres Salomon Signed-off-by: John W. Linville --- net/mac80211/rate.c | 2 +- net/mac80211/rate.h | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index c74b7c85403c..99ab24cc9783 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -145,7 +145,7 @@ static const struct file_operations rcname_ops = { }; #endif -struct rate_control_ref *rate_control_alloc(const char *name, +static struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local) { struct dentry *debugfsdir = NULL; diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 998cf7a935b6..b6108bca96d4 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -26,10 +26,6 @@ struct rate_control_ref { struct kref kref; }; -/* Get a reference to the rate control algorithm. If `name' is NULL, get the - * first available algorithm. */ -struct rate_control_ref *rate_control_alloc(const char *name, - struct ieee80211_local *local); void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, struct ieee80211_tx_rate_control *txrc); @@ -116,7 +112,8 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) #endif } -/* functions for rate control related to a device */ +/* Get a reference to the rate control algorithm. If `name' is NULL, get the + * first available algorithm. */ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, const char *name); void rate_control_deinitialize(struct ieee80211_local *local); -- cgit v1.2.3 From e15276a4b220c54db665cf46a92bd9ceb9aeb052 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 8 Feb 2010 17:47:01 +0530 Subject: mac80211: Reset dynamic ps timer in Rx path. The current mac80211 implementation enables power save if there is no Tx traffic for a specific timeout. Hence, PS is triggered even if there is a continuous Rx only traffic(like UDP) going on. This makes the drivers to wait on the tim bit in the next beacon to awake which leads to redundant sleep-wake cycles. Fix this by restarting the dynamic ps timer on receiving every data packet. Signed-off-by: Vivek Natarajan CC: stable@kernel.org Signed-off-by: John W. Linville --- net/mac80211/rx.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 01dba7618397..c9755f3d986c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1719,6 +1719,7 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_data(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; + struct ieee80211_local *local = rx->local; struct net_device *dev = sdata->dev; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; __le16 fc = hdr->frame_control; @@ -1750,6 +1751,13 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) dev->stats.rx_packets++; dev->stats.rx_bytes += rx->skb->len; + if (ieee80211_is_data(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1) && + local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) { + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); + } + ieee80211_deliver_skb(rx); return RX_QUEUED; -- cgit v1.2.3 From 375177bf35efc08e1bd37bbda4cc0c8cc4db8500 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 9 Feb 2010 14:50:28 +0530 Subject: mac80211: Retry null data frame for power save. Even if the null data frame is not acked by the AP, mac80211 goes into power save. This might lead to loss of frames from the AP. Prevent this by restarting dynamic_ps_timer when ack is not received for null data frames. Cc: Johannes Berg Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 20 +++++++++++++++----- net/mac80211/status.c | 17 +++++++++++++++-- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 414d774028ba..314e98173166 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -945,6 +945,11 @@ enum ieee80211_tkip_key_type { * Hardware supports Unscheduled Automatic Power Save Delivery * (U-APSD) in managed mode. The mode is configured with * conf_tx() operation. + * + * @IEEE80211_HW_REPORTS_TX_ACK_STATUS: + * Hardware can provide ack status reports of Tx frames to + * the stack. + * */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -965,6 +970,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, + IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, }; /** diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a5911191f224..9dd98b674cbc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -316,6 +316,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_CSA_RECEIVED = BIT(5), IEEE80211_STA_MFP_ENABLED = BIT(6), IEEE80211_STA_UAPSD_ENABLED = BIT(7), + IEEE80211_STA_NULLFUNC_ACKED = BIT(8), }; struct ieee80211_if_managed { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7a7921476582..ee9443dc20ff 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -434,8 +434,11 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, } else { if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) ieee80211_send_nullfunc(local, sdata, 1); - conf->flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + + if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { + conf->flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } } } @@ -541,6 +544,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) container_of(work, struct ieee80211_local, dynamic_ps_enable_work); struct ieee80211_sub_if_data *sdata = local->ps_sdata; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; /* can only happen when PS was just disabled anyway */ if (!sdata) @@ -549,11 +553,16 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if (local->hw.conf.flags & IEEE80211_CONF_PS) return; - if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) + if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && + (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) ieee80211_send_nullfunc(local, sdata, 1); - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || + (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { + ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; + local->hw.conf.flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } } void ieee80211_dynamic_ps_timer(unsigned long data) @@ -1892,6 +1901,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, return -ENOMEM; ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; + ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || diff --git a/net/mac80211/status.c b/net/mac80211/status.c index e57ad6b1d7ea..ded98730c111 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -188,6 +188,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_lock(); sband = local->hw.wiphy->bands[info->band]; + fc = hdr->frame_control; for_each_sta_info(local, hdr->addr1, sta, tmp) { /* skip wrong virtual interface */ @@ -205,8 +206,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) return; } - fc = hdr->frame_control; - if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && (ieee80211_is_data_qos(fc))) { u16 tid, ssn; @@ -275,6 +274,20 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) local->dot11FailedCount++; } + if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) && + (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && + !(info->flags & IEEE80211_TX_CTL_INJECTED) && + local->ps_sdata && !(local->scanning)) { + if (info->flags & IEEE80211_TX_STAT_ACK) { + local->ps_sdata->u.mgd.flags |= + IEEE80211_STA_NULLFUNC_ACKED; + ieee80211_queue_work(&local->hw, + &local->dynamic_ps_enable_work); + } else + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(10)); + } + /* this was a transmitted frame, but now we want to reuse it */ skb_orphan(skb); -- cgit v1.2.3 From 05df49865be08b30e7ba91b9d3d94d7d52dd3033 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 9 Feb 2010 11:34:50 +0530 Subject: ath9k: Enable IEEE80211_HW_REPORTS_TX_ACK_STATUS flag for ath9k. Signed-off-by: Vivek Natarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 4b5e54848683..623c2f884987 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -622,7 +622,8 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_SPECTRUM_MGMT; + IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_REPORTS_TX_ACK_STATUS; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; -- cgit v1.2.3 From 0a02604628c49037e1de2091d75462fd856b26ed Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 10 Feb 2010 15:00:32 +0100 Subject: netfilter: xtables: consistent struct compat_xt_counters definition There is compat_u64 type which deals with different u64 type alignment on different compat-capable platforms, so use it and removed some hardcoded assumptions. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 365fabe1b16e..8b6c0e7d2657 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -562,11 +562,7 @@ struct compat_xt_entry_target { * current task alignment */ struct compat_xt_counters { -#if defined(CONFIG_X86_64) || defined(CONFIG_IA64) - u_int32_t cnt[4]; -#else - u_int64_t cnt[2]; -#endif + compat_u64 pcnt, bcnt; /* Packet and byte counters */ }; struct compat_xt_counters_info { -- cgit v1.2.3 From 42107f5009da223daa800d6da6904d77297ae829 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 10 Feb 2010 15:03:27 +0100 Subject: netfilter: xtables: symmetric COMPAT_XT_ALIGN definition Rewrite COMPAT_XT_ALIGN in terms of dummy structure hack. Compat counters logically have nothing to do with it. Use ALIGN() macro while I'm at it for same types. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 13 +++++++++---- net/netfilter/x_tables.c | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 8b6c0e7d2657..9d671ebf0605 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -93,8 +93,7 @@ struct _xt_align { __u64 u64; }; -#define XT_ALIGN(s) (((s) + (__alignof__(struct _xt_align)-1)) \ - & ~(__alignof__(struct _xt_align)-1)) +#define XT_ALIGN(s) ALIGN((s), __alignof__(struct _xt_align)) /* Standard return verdict, or do jump. */ #define XT_STANDARD_TARGET "" @@ -571,8 +570,14 @@ struct compat_xt_counters_info { struct compat_xt_counters counters[0]; }; -#define COMPAT_XT_ALIGN(s) (((s) + (__alignof__(struct compat_xt_counters)-1)) \ - & ~(__alignof__(struct compat_xt_counters)-1)) +struct _compat_xt_align { + __u8 u8; + __u16 u16; + __u32 u32; + compat_u64 u64; +}; + +#define COMPAT_XT_ALIGN(s) ALIGN((s), __alignof__(struct _compat_xt_align)) extern void xt_compat_lock(u_int8_t af); extern void xt_compat_unlock(u_int8_t af); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index f01955cce314..5c564ff10a3b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -364,7 +364,7 @@ int xt_check_match(struct xt_mtchk_param *par, * ebt_among is exempt from centralized matchsize checking * because it uses a dynamic-size data set. */ - pr_err("%s_tables: %s match: invalid size %Zu != %u\n", + pr_err("%s_tables: %s match: invalid size %u != %u\n", xt_prefix[par->family], par->match->name, XT_ALIGN(par->match->matchsize), size); return -EINVAL; @@ -514,7 +514,7 @@ int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { if (XT_ALIGN(par->target->targetsize) != size) { - pr_err("%s_tables: %s target: invalid size %Zu != %u\n", + pr_err("%s_tables: %s target: invalid size %u != %u\n", xt_prefix[par->family], par->target->name, XT_ALIGN(par->target->targetsize), size); return -EINVAL; -- cgit v1.2.3 From d0b0268fddea3235a8df35e52167c3b206bf2f5a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 10 Feb 2010 15:38:33 +0100 Subject: netfilter: ctnetlink: add missing netlink attribute policies Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 41 +++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 327c5174440c..5c103b8c7df0 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -708,6 +708,11 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr, return ret; } +static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = { + [CTA_TUPLE_IP] = { .type = NLA_NESTED }, + [CTA_TUPLE_PROTO] = { .type = NLA_NESTED }, +}; + static int ctnetlink_parse_tuple(const struct nlattr * const cda[], struct nf_conntrack_tuple *tuple, @@ -718,7 +723,7 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[], memset(tuple, 0, sizeof(*tuple)); - nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], NULL); + nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy); if (!tb[CTA_TUPLE_IP]) return -EINVAL; @@ -745,12 +750,16 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[], return 0; } +static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = { + [CTA_HELP_NAME] = { .type = NLA_NUL_STRING }, +}; + static inline int ctnetlink_parse_help(const struct nlattr *attr, char **helper_name) { struct nlattr *tb[CTA_HELP_MAX+1]; - nla_parse_nested(tb, CTA_HELP_MAX, attr, NULL); + nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy); if (!tb[CTA_HELP_NAME]) return -EINVAL; @@ -761,11 +770,17 @@ ctnetlink_parse_help(const struct nlattr *attr, char **helper_name) } static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { + [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, + [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, [CTA_STATUS] = { .type = NLA_U32 }, + [CTA_PROTOINFO] = { .type = NLA_NESTED }, + [CTA_HELP] = { .type = NLA_NESTED }, + [CTA_NAT_SRC] = { .type = NLA_NESTED }, [CTA_TIMEOUT] = { .type = NLA_U32 }, [CTA_MARK] = { .type = NLA_U32 }, - [CTA_USE] = { .type = NLA_U32 }, [CTA_ID] = { .type = NLA_U32 }, + [CTA_NAT_DST] = { .type = NLA_NESTED }, + [CTA_TUPLE_MASTER] = { .type = NLA_NESTED }, }; static int @@ -1053,6 +1068,12 @@ ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) return 0; } +static const struct nla_policy protoinfo_policy[CTA_PROTOINFO_MAX+1] = { + [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED }, + [CTA_PROTOINFO_DCCP] = { .type = NLA_NESTED }, + [CTA_PROTOINFO_SCTP] = { .type = NLA_NESTED }, +}; + static inline int ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]) { @@ -1061,7 +1082,7 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[] struct nf_conntrack_l4proto *l4proto; int err = 0; - nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL); + nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy); rcu_read_lock(); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); @@ -1073,12 +1094,18 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[] } #ifdef CONFIG_NF_NAT_NEEDED +static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = { + [CTA_NAT_SEQ_CORRECTION_POS] = { .type = NLA_U32 }, + [CTA_NAT_SEQ_OFFSET_BEFORE] = { .type = NLA_U32 }, + [CTA_NAT_SEQ_OFFSET_AFTER] = { .type = NLA_U32 }, +}; + static inline int change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) { struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; - nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, NULL); + nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) return -EINVAL; @@ -1648,8 +1675,12 @@ out: } static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { + [CTA_EXPECT_MASTER] = { .type = NLA_NESTED }, + [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED }, + [CTA_EXPECT_MASK] = { .type = NLA_NESTED }, [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, [CTA_EXPECT_ID] = { .type = NLA_U32 }, + [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING }, }; static int -- cgit v1.2.3 From 737535c5cf3524e4bfaa91e22edefd52eccabbce Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 13 Jun 2009 06:46:36 +0200 Subject: netfilter: xtables: compact table hook functions (1/2) This patch combines all the per-hook functions in a given table into a single function. Together with the 2nd patch, further simplifications are possible up to the point of output code reduction. Signed-off-by: Jan Engelhardt --- net/ipv4/netfilter/arptable_filter.c | 30 ++++++-------- net/ipv4/netfilter/iptable_filter.c | 50 ++++++++---------------- net/ipv4/netfilter/iptable_mangle.c | 71 ++++++++++------------------------ net/ipv4/netfilter/iptable_raw.c | 26 +++++-------- net/ipv4/netfilter/iptable_security.c | 50 ++++++++---------------- net/ipv6/netfilter/ip6table_filter.c | 40 ++++++------------- net/ipv6/netfilter/ip6table_mangle.c | 50 ++++++++++-------------- net/ipv6/netfilter/ip6table_raw.c | 26 +++++-------- net/ipv6/netfilter/ip6table_security.c | 41 ++++++-------------- 9 files changed, 126 insertions(+), 258 deletions(-) diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 97337601827a..e9d823b149cd 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -53,43 +53,37 @@ static const struct xt_table packet_filter = { }; /* The work comes in here from netfilter.c */ -static unsigned int arpt_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +static unsigned int +arptable_filter_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return arpt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.arptable_filter); -} + if (hook == NF_ARP_OUT) + return arpt_do_table(skb, hook, in, out, + dev_net(out)->ipv4.arptable_filter); -static unsigned int arpt_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ + /* INPUT/FORWARD: */ return arpt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.arptable_filter); + dev_net(in)->ipv4.arptable_filter); } static struct nf_hook_ops arpt_ops[] __read_mostly = { { - .hook = arpt_in_hook, + .hook = arptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_ARP, .hooknum = NF_ARP_IN, .priority = NF_IP_PRI_FILTER, }, { - .hook = arpt_out_hook, + .hook = arptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_ARP, .hooknum = NF_ARP_OUT, .priority = NF_IP_PRI_FILTER, }, { - .hook = arpt_in_hook, + .hook = arptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_ARP, .hooknum = NF_ARP_FORWARD, diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index dee90eb8aa47..5369833ad56a 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -60,61 +60,43 @@ static const struct xt_table packet_filter = { .af = NFPROTO_IPV4, }; -/* The work comes in here from netfilter.c. */ static unsigned int -ipt_local_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +iptable_filter_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_filter); -} + if (hook == NF_INET_LOCAL_OUT) { + if (skb->len < sizeof(struct iphdr) || + ip_hdrlen(skb) < sizeof(struct iphdr)) + /* root is playing with raw sockets. */ + return NF_ACCEPT; + + return ipt_do_table(skb, hook, in, out, + dev_net(out)->ipv4.iptable_filter); + } -static unsigned int -ipt_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ + /* LOCAL_IN/FORWARD: */ return ipt_do_table(skb, hook, in, out, dev_net(in)->ipv4.iptable_filter); } -static unsigned int -ipt_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - /* root is playing with raw sockets. */ - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) - return NF_ACCEPT; - return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_filter); -} - static struct nf_hook_ops ipt_ops[] __read_mostly = { { - .hook = ipt_local_in_hook, + .hook = iptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FILTER, }, { - .hook = ipt_hook, + .hook = iptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_FILTER, }, { - .hook = ipt_local_out_hook, + .hook = iptable_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index e07bf242343a..4e699cd275c6 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -71,51 +71,6 @@ static const struct xt_table packet_mangler = { .af = NFPROTO_IPV4, }; -/* The work comes in here from netfilter.c. */ -static unsigned int -ipt_pre_routing_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_mangle); -} - -static unsigned int -ipt_post_routing_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_mangle); -} - -static unsigned int -ipt_local_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_mangle); -} - -static unsigned int -ipt_forward_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_mangle); -} - static unsigned int ipt_local_hook(unsigned int hook, struct sk_buff *skb, @@ -158,37 +113,53 @@ ipt_local_hook(unsigned int hook, return ret; } +/* The work comes in here from netfilter.c. */ +static unsigned int +iptable_mangle_hook(unsigned int hook, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + if (hook == NF_INET_LOCAL_OUT) + return ipt_local_hook(hook, skb, in, out, okfn); + + /* PREROUTING/INPUT/FORWARD: */ + return ipt_do_table(skb, hook, in, out, + dev_net(in)->ipv4.iptable_mangle); +} + static struct nf_hook_ops ipt_ops[] __read_mostly = { { - .hook = ipt_pre_routing_hook, + .hook = iptable_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_MANGLE, }, { - .hook = ipt_local_in_hook, + .hook = iptable_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_MANGLE, }, { - .hook = ipt_forward_hook, + .hook = iptable_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_MANGLE, }, { - .hook = ipt_local_hook, + .hook = iptable_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_MANGLE, }, { - .hook = ipt_post_routing_hook, + .hook = iptable_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_POST_ROUTING, diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 40f2b9f611a2..2c55575e89f5 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -45,23 +45,15 @@ static const struct xt_table packet_raw = { /* The work comes in here from netfilter.c. */ static unsigned int -ipt_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +iptable_raw_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_raw); -} + if (hook == NF_INET_PRE_ROUTING) + return ipt_do_table(skb, hook, in, out, + dev_net(in)->ipv4.iptable_raw); -static unsigned int -ipt_local_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ + /* OUTPUT: */ /* root is playing with raw sockets. */ if (skb->len < sizeof(struct iphdr) || ip_hdrlen(skb) < sizeof(struct iphdr)) @@ -73,14 +65,14 @@ ipt_local_hook(unsigned int hook, /* 'raw' is the very first table. */ static struct nf_hook_ops ipt_ops[] __read_mostly = { { - .hook = ipt_hook, + .hook = iptable_raw_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP_PRI_RAW, .owner = THIS_MODULE, }, { - .hook = ipt_local_hook, + .hook = iptable_raw_hook, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_RAW, diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 7ce2366e4305..1c666bab3269 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -65,59 +65,43 @@ static const struct xt_table security_table = { }; static unsigned int -ipt_local_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +iptable_security_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_security); -} + if (hook == NF_INET_LOCAL_OUT) { + if (skb->len < sizeof(struct iphdr) || + ip_hdrlen(skb) < sizeof(struct iphdr)) + /* Somebody is playing with raw sockets. */ + return NF_ACCEPT; -static unsigned int -ipt_forward_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_security); -} + return ipt_do_table(skb, hook, in, out, + dev_net(out)->ipv4.iptable_security); + } -static unsigned int -ipt_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - /* Somebody is playing with raw sockets. */ - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) - return NF_ACCEPT; + /* INPUT/FORWARD: */ return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_security); + dev_net(in)->ipv4.iptable_security); } static struct nf_hook_ops ipt_ops[] __read_mostly = { { - .hook = ipt_local_in_hook, + .hook = iptable_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_SECURITY, }, { - .hook = ipt_forward_hook, + .hook = iptable_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = NF_IP_PRI_SECURITY, }, { - .hook = ipt_local_out_hook, + .hook = iptable_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 33ddfe53e18d..38074e933f67 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -60,54 +60,36 @@ static const struct xt_table packet_filter = { /* The work comes in here from netfilter.c. */ static unsigned int -ip6t_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_filter); -} - -static unsigned int -ip6t_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ -#if 0 - /* root is playing with raw sockets. */ - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) { - if (net_ratelimit()) - printk("ip6t_hook: happy cracking.\n"); - return NF_ACCEPT; - } -#endif + if (hook == NF_INET_LOCAL_OUT) + return ip6t_do_table(skb, hook, in, out, + dev_net(out)->ipv6.ip6table_filter); + /* INPUT/FORWARD: */ return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_filter); + dev_net(in)->ipv6.ip6table_filter); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { { - .hook = ip6t_in_hook, + .hook = ip6table_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_FILTER, }, { - .hook = ip6t_in_hook, + .hook = ip6table_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_FORWARD, .priority = NF_IP6_PRI_FILTER, }, { - .hook = ip6t_local_out_hook, + .hook = ip6table_filter_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 9bc483f000e5..405ac1f76390 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -64,33 +64,9 @@ static const struct xt_table packet_mangler = { .af = NFPROTO_IPV6, }; -/* The work comes in here from netfilter.c. */ -static unsigned int -ip6t_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_mangle); -} - -static unsigned int -ip6t_post_routing_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_mangle); -} - static unsigned int ip6t_local_out_hook(unsigned int hook, struct sk_buff *skb, - const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { @@ -119,7 +95,7 @@ ip6t_local_out_hook(unsigned int hook, /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(skb)); - ret = ip6t_do_table(skb, hook, in, out, + ret = ip6t_do_table(skb, hook, NULL, out, dev_net(out)->ipv6.ip6table_mangle); if (ret != NF_DROP && ret != NF_STOLEN && @@ -132,37 +108,51 @@ ip6t_local_out_hook(unsigned int hook, return ret; } +/* The work comes in here from netfilter.c. */ +static unsigned int +ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + if (hook == NF_INET_LOCAL_OUT) + return ip6t_local_out_hook(hook, skb, out, okfn); + + /* INPUT/FORWARD */ + return ip6t_do_table(skb, hook, in, out, + dev_net(in)->ipv6.ip6table_mangle); +} + static struct nf_hook_ops ip6t_ops[] __read_mostly = { { - .hook = ip6t_in_hook, + .hook = ip6table_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_in_hook, + .hook = ip6table_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_in_hook, + .hook = ip6table_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_FORWARD, .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_local_out_hook, + .hook = ip6table_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_post_routing_hook, + .hook = ip6table_mangle_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_POST_ROUTING, diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 4c90b552e433..985e27cf1e0c 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -44,37 +44,29 @@ static const struct xt_table packet_raw = { /* The work comes in here from netfilter.c. */ static unsigned int -ip6t_pre_routing_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_raw); -} + if (hook == NF_INET_PRE_ROUTING) + return ip6t_do_table(skb, hook, in, out, + dev_net(in)->ipv6.ip6table_raw); -static unsigned int -ip6t_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ + /* OUTPUT: */ return ip6t_do_table(skb, hook, in, out, dev_net(out)->ipv6.ip6table_raw); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { { - .hook = ip6t_pre_routing_hook, + .hook = ip6table_raw_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_PRE_ROUTING, .priority = NF_IP6_PRI_FIRST, .owner = THIS_MODULE, }, { - .hook = ip6t_local_out_hook, + .hook = ip6table_raw_hook, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_FIRST, diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index baa8d4ef3b0a..835858929358 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -64,56 +64,37 @@ static const struct xt_table security_table = { }; static unsigned int -ip6t_local_in_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +ip6table_security_hook(unsigned int hook, struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_security); -} + if (hook == NF_INET_LOCAL_OUT) + return ip6t_do_table(skb, hook, in, out, + dev_net(out)->ipv6.ip6table_security); -static unsigned int -ip6t_forward_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ + /* INPUT/FORWARD: */ return ip6t_do_table(skb, hook, in, out, dev_net(in)->ipv6.ip6table_security); } -static unsigned int -ip6t_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ - /* TBD: handle short packets via raw socket */ - return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_security); -} - static struct nf_hook_ops ip6t_ops[] __read_mostly = { { - .hook = ip6t_local_in_hook, + .hook = ip6table_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_SECURITY, }, { - .hook = ip6t_forward_hook, + .hook = ip6table_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_FORWARD, .priority = NF_IP6_PRI_SECURITY, }, { - .hook = ip6t_local_out_hook, + .hook = ip6table_security_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, -- cgit v1.2.3 From 2b21e051472fdb4680076278b2ccf63ebc1cc3bc Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 13 Jun 2009 06:57:10 +0200 Subject: netfilter: xtables: compact table hook functions (2/2) The calls to ip6t_do_table only show minimal differences, so it seems like a good cleanup to merge them to a single one too. Space saving obtained by both patches: 6807725->6807373 ("Total" column from `size -A`.) Signed-off-by: Jan Engelhardt --- net/ipv4/netfilter/arptable_filter.c | 8 ++------ net/ipv4/netfilter/iptable_filter.c | 21 +++++++++------------ net/ipv4/netfilter/iptable_raw.c | 19 +++++++++---------- net/ipv4/netfilter/iptable_security.c | 23 ++++++++++------------- net/ipv6/netfilter/ip6table_filter.c | 8 ++------ net/ipv6/netfilter/ip6table_raw.c | 8 ++------ net/ipv6/netfilter/ip6table_security.c | 8 ++------ 7 files changed, 36 insertions(+), 59 deletions(-) diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index e9d823b149cd..deeda9b2cf05 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -58,13 +58,9 @@ arptable_filter_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_ARP_OUT) - return arpt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.arptable_filter); + const struct net *net = dev_net((in != NULL) ? in : out); - /* INPUT/FORWARD: */ - return arpt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.arptable_filter); + return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); } static struct nf_hook_ops arpt_ops[] __read_mostly = { diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 5369833ad56a..1bfeaae6f624 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -65,19 +65,16 @@ iptable_filter_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_LOCAL_OUT) { - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) - /* root is playing with raw sockets. */ - return NF_ACCEPT; - - return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_filter); - } + const struct net *net; + + if (hook == NF_INET_LOCAL_OUT && + (skb->len < sizeof(struct iphdr) || + ip_hdrlen(skb) < sizeof(struct iphdr))) + /* root is playing with raw sockets. */ + return NF_ACCEPT; - /* LOCAL_IN/FORWARD: */ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_filter); + net = dev_net((in != NULL) ? in : out); + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); } static struct nf_hook_ops ipt_ops[] __read_mostly = { diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 2c55575e89f5..d16e43777c31 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -49,17 +49,16 @@ iptable_raw_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_PRE_ROUTING) - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_raw); - - /* OUTPUT: */ - /* root is playing with raw sockets. */ - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) + const struct net *net; + + if (hook == NF_INET_LOCAL_OUT && + (skb->len < sizeof(struct iphdr) || + ip_hdrlen(skb) < sizeof(struct iphdr))) + /* root is playing with raw sockets. */ return NF_ACCEPT; - return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_raw); + + net = dev_net((in != NULL) ? in : out); + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); } /* 'raw' is the very first table. */ diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 1c666bab3269..324505aaaa73 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -70,19 +70,16 @@ iptable_security_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_LOCAL_OUT) { - if (skb->len < sizeof(struct iphdr) || - ip_hdrlen(skb) < sizeof(struct iphdr)) - /* Somebody is playing with raw sockets. */ - return NF_ACCEPT; - - return ipt_do_table(skb, hook, in, out, - dev_net(out)->ipv4.iptable_security); - } - - /* INPUT/FORWARD: */ - return ipt_do_table(skb, hook, in, out, - dev_net(in)->ipv4.iptable_security); + const struct net *net; + + if (hook == NF_INET_LOCAL_OUT && + (skb->len < sizeof(struct iphdr) || + ip_hdrlen(skb) < sizeof(struct iphdr))) + /* Somebody is playing with raw sockets. */ + return NF_ACCEPT; + + net = dev_net((in != NULL) ? in : out); + return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); } static struct nf_hook_ops ipt_ops[] __read_mostly = { diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 38074e933f67..866f34ae236b 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -64,13 +64,9 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_LOCAL_OUT) - return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_filter); + const struct net *net = dev_net((in != NULL) ? in : out); - /* INPUT/FORWARD: */ - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_filter); + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 985e27cf1e0c..5451a36fbc21 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -48,13 +48,9 @@ ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_PRE_ROUTING) - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_raw); + const struct net *net = dev_net((in != NULL) ? in : out); - /* OUTPUT: */ - return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_raw); + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 835858929358..841ea77f5218 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -69,13 +69,9 @@ ip6table_security_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - if (hook == NF_INET_LOCAL_OUT) - return ip6t_do_table(skb, hook, in, out, - dev_net(out)->ipv6.ip6table_security); + const struct net *net = dev_net((in != NULL) ? in : out); - /* INPUT/FORWARD: */ - return ip6t_do_table(skb, hook, in, out, - dev_net(in)->ipv6.ip6table_security); + return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); } static struct nf_hook_ops ip6t_ops[] __read_mostly = { -- cgit v1.2.3 From 2b95efe7f6bb750256a702cc32d33b0cb2cd8223 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 17 Jun 2009 13:57:48 +0200 Subject: netfilter: xtables: use xt_table for hook instantiation The respective xt_table structures already have most of the metadata needed for hook setup. Add a 'priority' field to struct xt_table so that xt_hook_link() can be called with a reduced number of arguments. So should we be having more tables in the future, it comes at no static cost (only runtime, as before) - space saved: 6807373->6806555. Signed-off-by: Jan Engelhardt --- include/linux/netfilter/x_tables.h | 4 +++ net/ipv4/netfilter/arptable_filter.c | 33 +++++---------------- net/ipv4/netfilter/iptable_filter.c | 33 +++++---------------- net/ipv4/netfilter/iptable_mangle.c | 47 +++++------------------------ net/ipv4/netfilter/iptable_raw.c | 27 +++++------------ net/ipv4/netfilter/iptable_security.c | 33 +++++---------------- net/ipv6/netfilter/ip6table_filter.c | 33 +++++---------------- net/ipv6/netfilter/ip6table_mangle.c | 48 +++++------------------------- net/ipv6/netfilter/ip6table_raw.c | 26 +++++----------- net/ipv6/netfilter/ip6table_security.c | 33 +++++---------------- net/netfilter/x_tables.c | 54 ++++++++++++++++++++++++++++++++++ 11 files changed, 121 insertions(+), 250 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 365fabe1b16e..fdd3342c1235 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -361,6 +361,7 @@ struct xt_table { struct module *me; u_int8_t af; /* address/protocol family */ + int priority; /* hook order */ /* A unique name... */ const char name[XT_TABLE_MAXNAMELEN]; @@ -522,6 +523,9 @@ static inline unsigned long ifname_compare_aligned(const char *_a, return ret; } +extern struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *); +extern void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *); + #ifdef CONFIG_COMPAT #include diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index deeda9b2cf05..b361de0dac4c 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -50,6 +50,7 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_ARP, + .priority = NF_IP_PRI_FILTER, }; /* The work comes in here from netfilter.c */ @@ -63,29 +64,7 @@ arptable_filter_hook(unsigned int hook, struct sk_buff *skb, return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter); } -static struct nf_hook_ops arpt_ops[] __read_mostly = { - { - .hook = arptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_ARP, - .hooknum = NF_ARP_IN, - .priority = NF_IP_PRI_FILTER, - }, - { - .hook = arptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_ARP, - .hooknum = NF_ARP_OUT, - .priority = NF_IP_PRI_FILTER, - }, - { - .hook = arptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_ARP, - .hooknum = NF_ARP_FORWARD, - .priority = NF_IP_PRI_FILTER, - }, -}; +static struct nf_hook_ops *arpfilter_ops __read_mostly; static int __net_init arptable_filter_net_init(struct net *net) { @@ -115,9 +94,11 @@ static int __init arptable_filter_init(void) if (ret < 0) return ret; - ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); - if (ret < 0) + arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook); + if (IS_ERR(arpfilter_ops)) { + ret = PTR_ERR(arpfilter_ops); goto cleanup_table; + } return ret; cleanup_table: @@ -127,7 +108,7 @@ cleanup_table: static void __exit arptable_filter_fini(void) { - nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); + xt_hook_unlink(&packet_filter, arpfilter_ops); unregister_pernet_subsys(&arptable_filter_net_ops); } diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 1bfeaae6f624..c14bb85db1d9 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -58,6 +58,7 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, + .priority = NF_IP_PRI_FILTER, }; static unsigned int @@ -77,29 +78,7 @@ iptable_filter_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter); } -static struct nf_hook_ops ipt_ops[] __read_mostly = { - { - .hook = iptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP_PRI_FILTER, - }, - { - .hook = iptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_FILTER, - }, - { - .hook = iptable_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP_PRI_FILTER, - }, -}; +static struct nf_hook_ops *filter_ops __read_mostly; /* Default to forward because I got too much mail already. */ static int forward = NF_ACCEPT; @@ -142,9 +121,11 @@ static int __init iptable_filter_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - if (ret < 0) + filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); + if (IS_ERR(filter_ops)) { + ret = PTR_ERR(filter_ops); goto cleanup_table; + } return ret; @@ -155,7 +136,7 @@ static int __init iptable_filter_init(void) static void __exit iptable_filter_fini(void) { - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + xt_hook_unlink(&packet_filter, filter_ops); unregister_pernet_subsys(&iptable_filter_net_ops); } diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 4e699cd275c6..2355a229f8ee 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -69,6 +69,7 @@ static const struct xt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, + .priority = NF_IP_PRI_MANGLE, }; static unsigned int @@ -129,43 +130,7 @@ iptable_mangle_hook(unsigned int hook, dev_net(in)->ipv4.iptable_mangle); } -static struct nf_hook_ops ipt_ops[] __read_mostly = { - { - .hook = iptable_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP_PRI_MANGLE, - }, - { - .hook = iptable_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP_PRI_MANGLE, - }, - { - .hook = iptable_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_MANGLE, - }, - { - .hook = iptable_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP_PRI_MANGLE, - }, - { - .hook = iptable_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_POST_ROUTING, - .priority = NF_IP_PRI_MANGLE, - }, -}; +static struct nf_hook_ops *mangle_ops __read_mostly; static int __net_init iptable_mangle_net_init(struct net *net) { @@ -196,9 +161,11 @@ static int __init iptable_mangle_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - if (ret < 0) + mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); + if (IS_ERR(mangle_ops)) { + ret = PTR_ERR(mangle_ops); goto cleanup_table; + } return ret; @@ -209,7 +176,7 @@ static int __init iptable_mangle_init(void) static void __exit iptable_mangle_fini(void) { - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + xt_hook_unlink(&packet_mangler, mangle_ops); unregister_pernet_subsys(&iptable_mangle_net_ops); } diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index d16e43777c31..62a99154f14c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -41,6 +41,7 @@ static const struct xt_table packet_raw = { .valid_hooks = RAW_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, + .priority = NF_IP_PRI_RAW, }; /* The work comes in here from netfilter.c. */ @@ -61,23 +62,7 @@ iptable_raw_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw); } -/* 'raw' is the very first table. */ -static struct nf_hook_ops ipt_ops[] __read_mostly = { - { - .hook = iptable_raw_hook, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP_PRI_RAW, - .owner = THIS_MODULE, - }, - { - .hook = iptable_raw_hook, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP_PRI_RAW, - .owner = THIS_MODULE, - }, -}; +static struct nf_hook_ops *rawtable_ops __read_mostly; static int __net_init iptable_raw_net_init(struct net *net) { @@ -108,9 +93,11 @@ static int __init iptable_raw_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - if (ret < 0) + rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); + if (IS_ERR(rawtable_ops)) { + ret = PTR_ERR(rawtable_ops); goto cleanup_table; + } return ret; @@ -121,7 +108,7 @@ static int __init iptable_raw_init(void) static void __exit iptable_raw_fini(void) { - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + xt_hook_unlink(&packet_raw, rawtable_ops); unregister_pernet_subsys(&iptable_raw_net_ops); } diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 324505aaaa73..b1bf3ca2c6c7 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -62,6 +62,7 @@ static const struct xt_table security_table = { .valid_hooks = SECURITY_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV4, + .priority = NF_IP_PRI_SECURITY, }; static unsigned int @@ -82,29 +83,7 @@ iptable_security_hook(unsigned int hook, struct sk_buff *skb, return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security); } -static struct nf_hook_ops ipt_ops[] __read_mostly = { - { - .hook = iptable_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP_PRI_SECURITY, - }, - { - .hook = iptable_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_SECURITY, - }, - { - .hook = iptable_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV4, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP_PRI_SECURITY, - }, -}; +static struct nf_hook_ops *sectbl_ops __read_mostly; static int __net_init iptable_security_net_init(struct net *net) { @@ -135,9 +114,11 @@ static int __init iptable_security_init(void) if (ret < 0) return ret; - ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); - if (ret < 0) + sectbl_ops = xt_hook_link(&security_table, iptable_security_hook); + if (IS_ERR(sectbl_ops)) { + ret = PTR_ERR(sectbl_ops); goto cleanup_table; + } return ret; @@ -148,7 +129,7 @@ cleanup_table: static void __exit iptable_security_fini(void) { - nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); + xt_hook_unlink(&security_table, sectbl_ops); unregister_pernet_subsys(&iptable_security_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 866f34ae236b..6e95d0614ca9 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -56,6 +56,7 @@ static const struct xt_table packet_filter = { .valid_hooks = FILTER_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, + .priority = NF_IP6_PRI_FILTER, }; /* The work comes in here from netfilter.c. */ @@ -69,29 +70,7 @@ ip6table_filter_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter); } -static struct nf_hook_ops ip6t_ops[] __read_mostly = { - { - .hook = ip6table_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP6_PRI_FILTER, - }, - { - .hook = ip6table_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP6_PRI_FILTER, - }, - { - .hook = ip6table_filter_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP6_PRI_FILTER, - }, -}; +static struct nf_hook_ops *filter_ops __read_mostly; /* Default to forward because I got too much mail already. */ static int forward = NF_ACCEPT; @@ -134,9 +113,11 @@ static int __init ip6table_filter_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - if (ret < 0) + filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook); + if (IS_ERR(filter_ops)) { + ret = PTR_ERR(filter_ops); goto cleanup_table; + } return ret; @@ -147,7 +128,7 @@ static int __init ip6table_filter_init(void) static void __exit ip6table_filter_fini(void) { - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + xt_hook_unlink(&packet_filter, filter_ops); unregister_pernet_subsys(&ip6table_filter_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 405ac1f76390..5023ac52ffec 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -62,6 +62,7 @@ static const struct xt_table packet_mangler = { .valid_hooks = MANGLE_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, + .priority = NF_IP6_PRI_MANGLE, }; static unsigned int @@ -122,44 +123,7 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, dev_net(in)->ipv6.ip6table_mangle); } -static struct nf_hook_ops ip6t_ops[] __read_mostly = { - { - .hook = ip6table_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP6_PRI_MANGLE, - }, - { - .hook = ip6table_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP6_PRI_MANGLE, - }, - { - .hook = ip6table_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP6_PRI_MANGLE, - }, - { - .hook = ip6table_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP6_PRI_MANGLE, - }, - { - .hook = ip6table_mangle_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_POST_ROUTING, - .priority = NF_IP6_PRI_MANGLE, - }, -}; - +static struct nf_hook_ops *mangle_ops __read_mostly; static int __net_init ip6table_mangle_net_init(struct net *net) { /* Register table */ @@ -189,9 +153,11 @@ static int __init ip6table_mangle_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - if (ret < 0) + mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook); + if (IS_ERR(mangle_ops)) { + ret = PTR_ERR(mangle_ops); goto cleanup_table; + } return ret; @@ -202,7 +168,7 @@ static int __init ip6table_mangle_init(void) static void __exit ip6table_mangle_fini(void) { - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + xt_hook_unlink(&packet_mangler, mangle_ops); unregister_pernet_subsys(&ip6table_mangle_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 5451a36fbc21..3bfa69511641 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -40,6 +40,7 @@ static const struct xt_table packet_raw = { .valid_hooks = RAW_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, + .priority = NF_IP6_PRI_FIRST, }; /* The work comes in here from netfilter.c. */ @@ -53,22 +54,7 @@ ip6table_raw_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw); } -static struct nf_hook_ops ip6t_ops[] __read_mostly = { - { - .hook = ip6table_raw_hook, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP6_PRI_FIRST, - .owner = THIS_MODULE, - }, - { - .hook = ip6table_raw_hook, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP6_PRI_FIRST, - .owner = THIS_MODULE, - }, -}; +static struct nf_hook_ops *rawtable_ops __read_mostly; static int __net_init ip6table_raw_net_init(struct net *net) { @@ -99,9 +85,11 @@ static int __init ip6table_raw_init(void) return ret; /* Register hooks */ - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - if (ret < 0) + rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook); + if (IS_ERR(rawtable_ops)) { + ret = PTR_ERR(rawtable_ops); goto cleanup_table; + } return ret; @@ -112,7 +100,7 @@ static int __init ip6table_raw_init(void) static void __exit ip6table_raw_fini(void) { - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + xt_hook_unlink(&packet_raw, rawtable_ops); unregister_pernet_subsys(&ip6table_raw_net_ops); } diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 841ea77f5218..dd2200f17a6c 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -61,6 +61,7 @@ static const struct xt_table security_table = { .valid_hooks = SECURITY_VALID_HOOKS, .me = THIS_MODULE, .af = NFPROTO_IPV6, + .priority = NF_IP6_PRI_SECURITY, }; static unsigned int @@ -74,29 +75,7 @@ ip6table_security_hook(unsigned int hook, struct sk_buff *skb, return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security); } -static struct nf_hook_ops ip6t_ops[] __read_mostly = { - { - .hook = ip6table_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_IN, - .priority = NF_IP6_PRI_SECURITY, - }, - { - .hook = ip6table_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP6_PRI_SECURITY, - }, - { - .hook = ip6table_security_hook, - .owner = THIS_MODULE, - .pf = NFPROTO_IPV6, - .hooknum = NF_INET_LOCAL_OUT, - .priority = NF_IP6_PRI_SECURITY, - }, -}; +static struct nf_hook_ops *sectbl_ops __read_mostly; static int __net_init ip6table_security_net_init(struct net *net) { @@ -127,9 +106,11 @@ static int __init ip6table_security_init(void) if (ret < 0) return ret; - ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); - if (ret < 0) + sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook); + if (IS_ERR(sectbl_ops)) { + ret = PTR_ERR(sectbl_ops); goto cleanup_table; + } return ret; @@ -140,7 +121,7 @@ cleanup_table: static void __exit ip6table_security_fini(void) { - nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); + xt_hook_unlink(&security_table, sectbl_ops); unregister_pernet_subsys(&ip6table_security_net_ops); } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index f01955cce314..b51cb0d7234a 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -1091,6 +1091,60 @@ static const struct file_operations xt_target_ops = { #endif /* CONFIG_PROC_FS */ +/** + * xt_hook_link - set up hooks for a new table + * @table: table with metadata needed to set up hooks + * @fn: Hook function + * + * This function will take care of creating and registering the necessary + * Netfilter hooks for XT tables. + */ +struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn) +{ + unsigned int hook_mask = table->valid_hooks; + uint8_t i, num_hooks = hweight32(hook_mask); + uint8_t hooknum; + struct nf_hook_ops *ops; + int ret; + + ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL); + if (ops == NULL) + return ERR_PTR(-ENOMEM); + + for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0; + hook_mask >>= 1, ++hooknum) { + if (!(hook_mask & 1)) + continue; + ops[i].hook = fn; + ops[i].owner = table->me; + ops[i].pf = table->af; + ops[i].hooknum = hooknum; + ops[i].priority = table->priority; + ++i; + } + + ret = nf_register_hooks(ops, num_hooks); + if (ret < 0) { + kfree(ops); + return ERR_PTR(ret); + } + + return ops; +} +EXPORT_SYMBOL_GPL(xt_hook_link); + +/** + * xt_hook_unlink - remove hooks for a table + * @ops: nf_hook_ops array as returned by nf_hook_link + * @hook_mask: the very same mask that was passed to nf_hook_link + */ +void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops) +{ + nf_unregister_hooks(ops, hweight32(table->valid_hooks)); + kfree(ops); +} +EXPORT_SYMBOL_GPL(xt_hook_unlink); + int xt_proto_init(struct net *net, u_int8_t af) { #ifdef CONFIG_PROC_FS -- cgit v1.2.3 From e3eaa9910b380530cfd2c0670fcd3f627674da8a Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 17 Jun 2009 22:14:54 +0200 Subject: netfilter: xtables: generate initial table on-demand The static initial tables are pretty large, and after the net namespace has been instantiated, they just hang around for nothing. This commit removes them and creates tables on-demand at runtime when needed. Size shrinks by 7735 bytes (x86_64). Signed-off-by: Jan Engelhardt --- include/linux/netfilter_arp/arp_tables.h | 1 + include/linux/netfilter_ipv4/ip_tables.h | 1 + include/linux/netfilter_ipv6/ip6_tables.h | 1 + net/ipv4/netfilter/arp_tables.c | 7 +++++ net/ipv4/netfilter/arptable_filter.c | 40 ++++++--------------------- net/ipv4/netfilter/ip_tables.c | 7 +++++ net/ipv4/netfilter/iptable_filter.c | 46 ++++++++----------------------- net/ipv4/netfilter/iptable_mangle.c | 46 +++++-------------------------- net/ipv4/netfilter/iptable_raw.c | 36 +++++------------------- net/ipv4/netfilter/iptable_security.c | 39 +++++--------------------- net/ipv4/netfilter/nf_nat_rule.c | 39 +++++--------------------- net/ipv6/netfilter/ip6_tables.c | 7 +++++ net/ipv6/netfilter/ip6table_filter.c | 46 ++++++++----------------------- net/ipv6/netfilter/ip6table_mangle.c | 45 +++++------------------------- net/ipv6/netfilter/ip6table_raw.c | 36 +++++------------------- net/ipv6/netfilter/ip6table_security.c | 39 +++++--------------------- net/netfilter/x_tables.c | 4 ++- net/netfilter/xt_repldata.h | 35 +++++++++++++++++++++++ 18 files changed, 141 insertions(+), 334 deletions(-) create mode 100644 net/netfilter/xt_repldata.h diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index f2336523a9df..0b33980611b2 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -258,6 +258,7 @@ struct arpt_error { .target.errorname = "ERROR", \ } +extern void *arpt_alloc_initial_table(const struct xt_table *); extern struct xt_table *arpt_register_table(struct net *net, const struct xt_table *table, const struct arpt_replace *repl); diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 8d1f273d350b..364973b42133 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -282,6 +282,7 @@ struct ipt_error { .target.errorname = "ERROR", \ } +extern void *ipt_alloc_initial_table(const struct xt_table *); extern unsigned int ipt_do_table(struct sk_buff *skb, unsigned int hook, const struct net_device *in, diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index d2952d2fa658..8031eb486a10 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -297,6 +297,7 @@ ip6t_get_target(struct ip6t_entry *e) #include extern void ip6t_init(void) __init; +extern void *ip6t_alloc_initial_table(const struct xt_table *); extern struct xt_table *ip6t_register_table(struct net *net, const struct xt_table *table, const struct ip6t_replace *repl); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 90203e1b9187..72723ea1054b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -27,6 +27,7 @@ #include #include +#include "../../netfilter/xt_repldata.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("David S. Miller "); @@ -58,6 +59,12 @@ do { \ #define ARP_NF_ASSERT(x) #endif +void *arpt_alloc_initial_table(const struct xt_table *info) +{ + return xt_alloc_initial_table(arpt, ARPT); +} +EXPORT_SYMBOL_GPL(arpt_alloc_initial_table); + static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, const char *hdr_addr, int len) { diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index b361de0dac4c..bfe26f32b930 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -6,6 +6,7 @@ */ #include +#include #include MODULE_LICENSE("GPL"); @@ -15,36 +16,6 @@ MODULE_DESCRIPTION("arptables filter table"); #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ (1 << NF_ARP_FORWARD)) -static const struct -{ - struct arpt_replace repl; - struct arpt_standard entries[3]; - struct arpt_error term; -} initial_table __net_initdata = { - .repl = { - .name = "filter", - .valid_hooks = FILTER_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error), - .hook_entry = { - [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard), - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), - }, - .underflow = { - [NF_ARP_IN] = 0, - [NF_ARP_OUT] = sizeof(struct arpt_standard), - [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), - }, - }, - .entries = { - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */ - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */ - ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */ - }, - .term = ARPT_ERROR_INIT, -}; - static const struct xt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -68,9 +39,14 @@ static struct nf_hook_ops *arpfilter_ops __read_mostly; static int __net_init arptable_filter_net_init(struct net *net) { - /* Register table */ + struct arpt_replace *repl; + + repl = arpt_alloc_initial_table(&packet_filter); + if (repl == NULL) + return -ENOMEM; net->ipv4.arptable_filter = - arpt_register_table(net, &packet_filter, &initial_table.repl); + arpt_register_table(net, &packet_filter, repl); + kfree(repl); if (IS_ERR(net->ipv4.arptable_filter)) return PTR_ERR(net->ipv4.arptable_filter); return 0; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 5bf7de1527a5..2057b1bb6178 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -28,6 +28,7 @@ #include #include #include +#include "../../netfilter/xt_repldata.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); @@ -66,6 +67,12 @@ do { \ #define inline #endif +void *ipt_alloc_initial_table(const struct xt_table *info) +{ + return xt_alloc_initial_table(ipt, IPT); +} +EXPORT_SYMBOL_GPL(ipt_alloc_initial_table); + /* We keep a set of rules for each CPU, so we can avoid write-locking them in the softirq when updating the counters and therefore diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index c14bb85db1d9..c8dc9800d620 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c @@ -23,36 +23,6 @@ MODULE_DESCRIPTION("iptables filter table"); (1 << NF_INET_FORWARD) | \ (1 << NF_INET_LOCAL_OUT)) -static struct -{ - struct ipt_replace repl; - struct ipt_standard entries[3]; - struct ipt_error term; -} initial_table __net_initdata = { - .repl = { - .name = "filter", - .valid_hooks = FILTER_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), - .hook_entry = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, - }, - .underflow = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, - }, - }, - .entries = { - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IPT_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -86,9 +56,18 @@ module_param(forward, bool, 0000); static int __net_init iptable_filter_net_init(struct net *net) { - /* Register table */ + struct ipt_replace *repl; + + repl = ipt_alloc_initial_table(&packet_filter); + if (repl == NULL) + return -ENOMEM; + /* Entry 1 is the FORWARD hook */ + ((struct ipt_standard *)repl->entries)[1].target.verdict = + -forward - 1; + net->ipv4.iptable_filter = - ipt_register_table(net, &packet_filter, &initial_table.repl); + ipt_register_table(net, &packet_filter, repl); + kfree(repl); if (IS_ERR(net->ipv4.iptable_filter)) return PTR_ERR(net->ipv4.iptable_filter); return 0; @@ -113,9 +92,6 @@ static int __init iptable_filter_init(void) return -EINVAL; } - /* Entry 1 is the FORWARD hook */ - initial_table.entries[1].target.verdict = -forward - 1; - ret = register_pernet_subsys(&iptable_filter_net_ops); if (ret < 0) return ret; diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 2355a229f8ee..58d7097baa3d 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -27,43 +27,6 @@ MODULE_DESCRIPTION("iptables mangle table"); (1 << NF_INET_LOCAL_OUT) | \ (1 << NF_INET_POST_ROUTING)) -/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */ -static const struct -{ - struct ipt_replace repl; - struct ipt_standard entries[5]; - struct ipt_error term; -} initial_table __net_initdata = { - .repl = { - .name = "mangle", - .valid_hooks = MANGLE_VALID_HOOKS, - .num_entries = 6, - .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error), - .hook_entry = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, - }, - .underflow = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard), - [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2, - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3, - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4, - }, - }, - .entries = { - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ - }, - .term = IPT_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_mangler = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, @@ -134,9 +97,14 @@ static struct nf_hook_ops *mangle_ops __read_mostly; static int __net_init iptable_mangle_net_init(struct net *net) { - /* Register table */ + struct ipt_replace *repl; + + repl = ipt_alloc_initial_table(&packet_mangler); + if (repl == NULL) + return -ENOMEM; net->ipv4.iptable_mangle = - ipt_register_table(net, &packet_mangler, &initial_table.repl); + ipt_register_table(net, &packet_mangler, repl); + kfree(repl); if (IS_ERR(net->ipv4.iptable_mangle)) return PTR_ERR(net->ipv4.iptable_mangle); return 0; diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 62a99154f14c..06fb9d11953c 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c @@ -9,33 +9,6 @@ #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) -static const struct -{ - struct ipt_replace repl; - struct ipt_standard entries[2]; - struct ipt_error term; -} initial_table __net_initdata = { - .repl = { - .name = "raw", - .valid_hooks = RAW_VALID_HOOKS, - .num_entries = 3, - .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error), - .hook_entry = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) - }, - .underflow = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) - }, - }, - .entries = { - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IPT_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, @@ -66,9 +39,14 @@ static struct nf_hook_ops *rawtable_ops __read_mostly; static int __net_init iptable_raw_net_init(struct net *net) { - /* Register table */ + struct ipt_replace *repl; + + repl = ipt_alloc_initial_table(&packet_raw); + if (repl == NULL) + return -ENOMEM; net->ipv4.iptable_raw = - ipt_register_table(net, &packet_raw, &initial_table.repl); + ipt_register_table(net, &packet_raw, repl); + kfree(repl); if (IS_ERR(net->ipv4.iptable_raw)) return PTR_ERR(net->ipv4.iptable_raw); return 0; diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index b1bf3ca2c6c7..cce2f64e6f21 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c @@ -27,36 +27,6 @@ MODULE_DESCRIPTION("iptables security table, for MAC rules"); (1 << NF_INET_FORWARD) | \ (1 << NF_INET_LOCAL_OUT) -static const struct -{ - struct ipt_replace repl; - struct ipt_standard entries[3]; - struct ipt_error term; -} initial_table __net_initdata = { - .repl = { - .name = "security", - .valid_hooks = SECURITY_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), - .hook_entry = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, - }, - .underflow = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2, - }, - }, - .entries = { - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IPT_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table security_table = { .name = "security", .valid_hooks = SECURITY_VALID_HOOKS, @@ -87,9 +57,14 @@ static struct nf_hook_ops *sectbl_ops __read_mostly; static int __net_init iptable_security_net_init(struct net *net) { - net->ipv4.iptable_security = - ipt_register_table(net, &security_table, &initial_table.repl); + struct ipt_replace *repl; + repl = ipt_alloc_initial_table(&security_table); + if (repl == NULL) + return -ENOMEM; + net->ipv4.iptable_security = + ipt_register_table(net, &security_table, repl); + kfree(repl); if (IS_ERR(net->ipv4.iptable_security)) return PTR_ERR(net->ipv4.iptable_security); diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 85da34fdc755..ab74cc0535e2 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c @@ -28,36 +28,6 @@ (1 << NF_INET_POST_ROUTING) | \ (1 << NF_INET_LOCAL_OUT)) -static const struct -{ - struct ipt_replace repl; - struct ipt_standard entries[3]; - struct ipt_error term; -} nat_initial_table __net_initdata = { - .repl = { - .name = "nat", - .valid_hooks = NAT_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error), - .hook_entry = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 - }, - .underflow = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 - }, - }, - .entries = { - IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ - IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ - IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IPT_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table nat_table = { .name = "nat", .valid_hooks = NAT_VALID_HOOKS, @@ -186,8 +156,13 @@ static struct xt_target ipt_dnat_reg __read_mostly = { static int __net_init nf_nat_rule_net_init(struct net *net) { - net->ipv4.nat_table = ipt_register_table(net, &nat_table, - &nat_initial_table.repl); + struct ipt_replace *repl; + + repl = ipt_alloc_initial_table(&nat_table); + if (repl == NULL) + return -ENOMEM; + net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl); + kfree(repl); if (IS_ERR(net->ipv4.nat_table)) return PTR_ERR(net->ipv4.nat_table); return 0; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 4332f4591482..dcd7825fe7b6 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -29,6 +29,7 @@ #include #include #include +#include "../../netfilter/xt_repldata.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Netfilter Core Team "); @@ -67,6 +68,12 @@ do { \ #define inline #endif +void *ip6t_alloc_initial_table(const struct xt_table *info) +{ + return xt_alloc_initial_table(ip6t, IP6T); +} +EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table); + /* We keep a set of rules for each CPU, so we can avoid write-locking them in the softirq when updating the counters and therefore diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 6e95d0614ca9..36b72cafc227 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c @@ -21,36 +21,6 @@ MODULE_DESCRIPTION("ip6tables filter table"); (1 << NF_INET_FORWARD) | \ (1 << NF_INET_LOCAL_OUT)) -static struct -{ - struct ip6t_replace repl; - struct ip6t_standard entries[3]; - struct ip6t_error term; -} initial_table __net_initdata = { - .repl = { - .name = "filter", - .valid_hooks = FILTER_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), - .hook_entry = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ip6t_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 - }, - .underflow = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ip6t_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 - }, - }, - .entries = { - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IP6T_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_filter = { .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, @@ -78,9 +48,18 @@ module_param(forward, bool, 0000); static int __net_init ip6table_filter_net_init(struct net *net) { - /* Register table */ + struct ip6t_replace *repl; + + repl = ip6t_alloc_initial_table(&packet_filter); + if (repl == NULL) + return -ENOMEM; + /* Entry 1 is the FORWARD hook */ + ((struct ip6t_standard *)repl->entries)[1].target.verdict = + -forward - 1; + net->ipv6.ip6table_filter = - ip6t_register_table(net, &packet_filter, &initial_table.repl); + ip6t_register_table(net, &packet_filter, repl); + kfree(repl); if (IS_ERR(net->ipv6.ip6table_filter)) return PTR_ERR(net->ipv6.ip6table_filter); return 0; @@ -105,9 +84,6 @@ static int __init ip6table_filter_init(void) return -EINVAL; } - /* Entry 1 is the FORWARD hook */ - initial_table.entries[1].target.verdict = -forward - 1; - ret = register_pernet_subsys(&ip6table_filter_net_ops); if (ret < 0) return ret; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 5023ac52ffec..dc803b7e8e54 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -21,42 +21,6 @@ MODULE_DESCRIPTION("ip6tables mangle table"); (1 << NF_INET_LOCAL_OUT) | \ (1 << NF_INET_POST_ROUTING)) -static const struct -{ - struct ip6t_replace repl; - struct ip6t_standard entries[5]; - struct ip6t_error term; -} initial_table __net_initdata = { - .repl = { - .name = "mangle", - .valid_hooks = MANGLE_VALID_HOOKS, - .num_entries = 6, - .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error), - .hook_entry = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, - }, - .underflow = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard), - [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2, - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3, - [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4, - }, - }, - .entries = { - IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */ - }, - .term = IP6T_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_mangler = { .name = "mangle", .valid_hooks = MANGLE_VALID_HOOKS, @@ -126,9 +90,14 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, static struct nf_hook_ops *mangle_ops __read_mostly; static int __net_init ip6table_mangle_net_init(struct net *net) { - /* Register table */ + struct ip6t_replace *repl; + + repl = ip6t_alloc_initial_table(&packet_mangler); + if (repl == NULL) + return -ENOMEM; net->ipv6.ip6table_mangle = - ip6t_register_table(net, &packet_mangler, &initial_table.repl); + ip6t_register_table(net, &packet_mangler, repl); + kfree(repl); if (IS_ERR(net->ipv6.ip6table_mangle)) return PTR_ERR(net->ipv6.ip6table_mangle); return 0; diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 3bfa69511641..aef31a29de9e 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c @@ -8,33 +8,6 @@ #define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) -static const struct -{ - struct ip6t_replace repl; - struct ip6t_standard entries[2]; - struct ip6t_error term; -} initial_table __net_initdata = { - .repl = { - .name = "raw", - .valid_hooks = RAW_VALID_HOOKS, - .num_entries = 3, - .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error), - .hook_entry = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) - }, - .underflow = { - [NF_INET_PRE_ROUTING] = 0, - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) - }, - }, - .entries = { - IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IP6T_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table packet_raw = { .name = "raw", .valid_hooks = RAW_VALID_HOOKS, @@ -58,9 +31,14 @@ static struct nf_hook_ops *rawtable_ops __read_mostly; static int __net_init ip6table_raw_net_init(struct net *net) { - /* Register table */ + struct ip6t_replace *repl; + + repl = ip6t_alloc_initial_table(&packet_raw); + if (repl == NULL) + return -ENOMEM; net->ipv6.ip6table_raw = - ip6t_register_table(net, &packet_raw, &initial_table.repl); + ip6t_register_table(net, &packet_raw, repl); + kfree(repl); if (IS_ERR(net->ipv6.ip6table_raw)) return PTR_ERR(net->ipv6.ip6table_raw); return 0; diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index dd2200f17a6c..0824d865aa9b 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c @@ -26,36 +26,6 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules"); (1 << NF_INET_FORWARD) | \ (1 << NF_INET_LOCAL_OUT) -static const struct -{ - struct ip6t_replace repl; - struct ip6t_standard entries[3]; - struct ip6t_error term; -} initial_table __net_initdata = { - .repl = { - .name = "security", - .valid_hooks = SECURITY_VALID_HOOKS, - .num_entries = 4, - .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error), - .hook_entry = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ip6t_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, - }, - .underflow = { - [NF_INET_LOCAL_IN] = 0, - [NF_INET_FORWARD] = sizeof(struct ip6t_standard), - [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2, - }, - }, - .entries = { - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */ - IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */ - }, - .term = IP6T_ERROR_INIT, /* ERROR */ -}; - static const struct xt_table security_table = { .name = "security", .valid_hooks = SECURITY_VALID_HOOKS, @@ -79,9 +49,14 @@ static struct nf_hook_ops *sectbl_ops __read_mostly; static int __net_init ip6table_security_net_init(struct net *net) { - net->ipv6.ip6table_security = - ip6t_register_table(net, &security_table, &initial_table.repl); + struct ip6t_replace *repl; + repl = ip6t_alloc_initial_table(&security_table); + if (repl == NULL) + return -ENOMEM; + net->ipv6.ip6table_security = + ip6t_register_table(net, &security_table, repl); + kfree(repl); if (IS_ERR(net->ipv6.ip6table_security)) return PTR_ERR(net->ipv6.ip6table_security); diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index b51cb0d7234a..dc2e05cb54c0 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -26,7 +26,9 @@ #include #include - +#include +#include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); diff --git a/net/netfilter/xt_repldata.h b/net/netfilter/xt_repldata.h new file mode 100644 index 000000000000..6efe4e5a81c6 --- /dev/null +++ b/net/netfilter/xt_repldata.h @@ -0,0 +1,35 @@ +/* + * Today's hack: quantum tunneling in structs + * + * 'entries' and 'term' are never anywhere referenced by word in code. In fact, + * they serve as the hanging-off data accessed through repl.data[]. + */ + +#define xt_alloc_initial_table(type, typ2) ({ \ + unsigned int hook_mask = info->valid_hooks; \ + unsigned int nhooks = hweight32(hook_mask); \ + unsigned int bytes = 0, hooknum = 0, i = 0; \ + struct { \ + struct type##_replace repl; \ + struct type##_standard entries[nhooks]; \ + struct type##_error term; \ + } *tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); \ + if (tbl == NULL) \ + return NULL; \ + strncpy(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \ + tbl->term = (struct type##_error)typ2##_ERROR_INIT; \ + tbl->repl.valid_hooks = hook_mask; \ + tbl->repl.num_entries = nhooks + 1; \ + tbl->repl.size = nhooks * sizeof(struct type##_standard) + \ + sizeof(struct type##_error); \ + for (; hook_mask != 0; hook_mask >>= 1, ++hooknum) { \ + if (!(hook_mask & 1)) \ + continue; \ + tbl->repl.hook_entry[hooknum] = bytes; \ + tbl->repl.underflow[hooknum] = bytes; \ + tbl->entries[i++] = (struct type##_standard) \ + typ2##_STANDARD_INIT(NF_ACCEPT); \ + bytes += sizeof(struct type##_standard); \ + } \ + tbl; \ +}) -- cgit v1.2.3 From 66655de6d132b726be64c324bc3f9ea366d20697 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:18:22 +0000 Subject: seq_file: Add helpers for iteration over a hlist Some places in kernel need to iterate over a hlist in seq_file, so provide some common helpers. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- fs/seq_file.c | 59 +++++++++++++++++++++++++++++++++++++++++++++--- include/linux/seq_file.h | 11 +++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/fs/seq_file.c b/fs/seq_file.c index eae7d9dbf3ff..f65b16f02da3 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -674,7 +674,6 @@ struct list_head *seq_list_start(struct list_head *head, loff_t pos) return NULL; } - EXPORT_SYMBOL(seq_list_start); struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) @@ -684,7 +683,6 @@ struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) return seq_list_start(head, pos - 1); } - EXPORT_SYMBOL(seq_list_start_head); struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) @@ -695,5 +693,60 @@ struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) ++*ppos; return lh == head ? NULL : lh; } - EXPORT_SYMBOL(seq_list_next); + +/** + * seq_hlist_start - start an iteration of a hlist + * @head: the head of the hlist + * @pos: the start position of the sequence + * + * Called at seq_file->op->start(). + */ +struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos) +{ + struct hlist_node *node; + + hlist_for_each(node, head) + if (pos-- == 0) + return node; + return NULL; +} +EXPORT_SYMBOL(seq_hlist_start); + +/** + * seq_hlist_start_head - start an iteration of a hlist + * @head: the head of the hlist + * @pos: the start position of the sequence + * + * Called at seq_file->op->start(). Call this function if you want to + * print a header at the top of the output. + */ +struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos) +{ + if (!pos) + return SEQ_START_TOKEN; + + return seq_hlist_start(head, pos - 1); +} +EXPORT_SYMBOL(seq_hlist_start_head); + +/** + * seq_hlist_next - move to the next position of the hlist + * @v: the current iterator + * @head: the head of the hlist + * @pos: the current posision + * + * Called at seq_file->op->next(). + */ +struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, + loff_t *ppos) +{ + struct hlist_node *node = v; + + ++*ppos; + if (v == SEQ_START_TOKEN) + return head->first; + else + return node->next; +} +EXPORT_SYMBOL(seq_hlist_next); diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 8366d8f12e53..c95bcdc18f4c 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -135,4 +135,15 @@ extern struct list_head *seq_list_start_head(struct list_head *head, extern struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos); +/* + * Helpers for iteration over hlist_head-s in seq_files + */ + +extern struct hlist_node *seq_hlist_start(struct hlist_head *head, + loff_t pos); +extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head, + loff_t pos); +extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, + loff_t *ppos); + #endif -- cgit v1.2.3 From c4146644a56b1f213c4c5567c75771883bec33c7 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:18:45 +0000 Subject: net: add a wrapper sk_entry() Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- include/net/sock.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index 3f1a4804bb3f..c8d400063c16 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -317,6 +317,11 @@ struct sock { /* * Hashed lists helper routines */ +static inline struct sock *sk_entry(const struct hlist_node *node) +{ + return hlist_entry(node, struct sock, sk_node); +} + static inline struct sock *__sk_head(const struct hlist_head *head) { return hlist_entry(head->first, struct sock, sk_node); -- cgit v1.2.3 From 32d2e3a149772441a6a146ad96cbae319e27742a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:19:04 +0000 Subject: net: x25: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/x25/x25_proc.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index 0a04e62e0e18..c4cd3226a053 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c @@ -93,40 +93,16 @@ out: return 0; } -static __inline__ struct sock *x25_get_socket_idx(loff_t pos) -{ - struct sock *s; - struct hlist_node *node; - - sk_for_each(s, node, &x25_list) - if (!pos--) - goto found; - s = NULL; -found: - return s; -} - static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) __acquires(x25_list_lock) { - loff_t l = *pos; - read_lock_bh(&x25_list_lock); - return l ? x25_get_socket_idx(--l) : SEQ_START_TOKEN; + return seq_hlist_start_head(&x25_list, *pos); } static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) { - struct sock *s; - - ++*pos; - if (v == SEQ_START_TOKEN) { - s = sk_head(&x25_list); - goto out; - } - s = sk_next(v); -out: - return s; + return seq_hlist_next(v, &x25_list, pos); } static void x25_seq_socket_stop(struct seq_file *seq, void *v) @@ -148,7 +124,7 @@ static int x25_seq_socket_show(struct seq_file *seq, void *v) goto out; } - s = v; + s = sk_entry(v); x25 = x25_sk(s); if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) -- cgit v1.2.3 From b999748acce739675a5e9420f21e54b8cbad9d81 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:19:17 +0000 Subject: net: rose: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/rose/af_rose.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8feb9e5d6623..e90b9b6c16ae 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1404,29 +1404,13 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static void *rose_info_start(struct seq_file *seq, loff_t *pos) __acquires(rose_list_lock) { - int i; - struct sock *s; - struct hlist_node *node; - spin_lock_bh(&rose_list_lock); - if (*pos == 0) - return SEQ_START_TOKEN; - - i = 1; - sk_for_each(s, node, &rose_list) { - if (i == *pos) - return s; - ++i; - } - return NULL; + return seq_hlist_start_head(&rose_list, *pos); } static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - - return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) - : sk_next((struct sock *)v); + return seq_hlist_next(v, &rose_list, pos); } static void rose_info_stop(struct seq_file *seq, void *v) @@ -1444,7 +1428,7 @@ static int rose_info_show(struct seq_file *seq, void *v) "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); else { - struct sock *s = v; + struct sock *s = sk_entry(v); struct rose_sock *rose = rose_sk(s); const char *devname, *callsign; const struct net_device *dev = rose->device; -- cgit v1.2.3 From b7ceabd9b528417973619c5b655bc5b21857ac36 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:19:29 +0000 Subject: net: packet: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/packet/af_packet.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6ecb426bc0cf..10f7295bcefb 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2510,33 +2510,19 @@ static struct notifier_block packet_netdev_notifier = { }; #ifdef CONFIG_PROC_FS -static inline struct sock *packet_seq_idx(struct net *net, loff_t off) -{ - struct sock *s; - struct hlist_node *node; - - sk_for_each(s, node, &net->packet.sklist) { - if (!off--) - return s; - } - return NULL; -} static void *packet_seq_start(struct seq_file *seq, loff_t *pos) __acquires(seq_file_net(seq)->packet.sklist_lock) { struct net *net = seq_file_net(seq); read_lock(&net->packet.sklist_lock); - return *pos ? packet_seq_idx(net, *pos - 1) : SEQ_START_TOKEN; + return seq_hlist_start_head(&net->packet.sklist, *pos); } static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct net *net = seq_file_net(seq); - ++*pos; - return (v == SEQ_START_TOKEN) - ? sk_head(&net->packet.sklist) - : sk_next((struct sock *)v) ; + return seq_hlist_next(v, &net->packet.sklist, pos); } static void packet_seq_stop(struct seq_file *seq, void *v) @@ -2551,7 +2537,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_puts(seq, "sk RefCnt Type Proto Iface R Rmem User Inode\n"); else { - struct sock *s = v; + struct sock *s = sk_entry(v); const struct packet_sock *po = pkt_sk(s); seq_printf(seq, -- cgit v1.2.3 From 90dd7f5ace558314fa431ae0f59388ed3e5c7695 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:19:42 +0000 Subject: net: netrom: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 21 +++----------------- net/netrom/nr_route.c | 53 +++++++++----------------------------------------- 2 files changed, 12 insertions(+), 62 deletions(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 71604c6613b5..a249127020a5 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1267,28 +1267,13 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static void *nr_info_start(struct seq_file *seq, loff_t *pos) { - struct sock *s; - struct hlist_node *node; - int i = 1; - spin_lock_bh(&nr_list_lock); - if (*pos == 0) - return SEQ_START_TOKEN; - - sk_for_each(s, node, &nr_list) { - if (i == *pos) - return s; - ++i; - } - return NULL; + return seq_hlist_start_head(&nr_list, *pos); } static void *nr_info_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - - return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) - : sk_next((struct sock *)v); + return seq_hlist_next(v, &nr_list, pos); } static void nr_info_stop(struct seq_file *seq, void *v) @@ -1298,7 +1283,7 @@ static void nr_info_stop(struct seq_file *seq, void *v) static int nr_info_show(struct seq_file *seq, void *v) { - struct sock *s = v; + struct sock *s = sk_entry(v); struct net_device *dev; struct nr_sock *nr; const char *devname; diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index e2e2d33cafdf..5cc648012f50 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -863,33 +863,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) static void *nr_node_start(struct seq_file *seq, loff_t *pos) { - struct nr_node *nr_node; - struct hlist_node *node; - int i = 1; - spin_lock_bh(&nr_node_list_lock); - if (*pos == 0) - return SEQ_START_TOKEN; - - nr_node_for_each(nr_node, node, &nr_node_list) { - if (i == *pos) - return nr_node; - ++i; - } - - return NULL; + return seq_hlist_start_head(&nr_node_list, *pos); } static void *nr_node_next(struct seq_file *seq, void *v, loff_t *pos) { - struct hlist_node *node; - ++*pos; - - node = (v == SEQ_START_TOKEN) - ? nr_node_list.first - : ((struct nr_node *)v)->node_node.next; - - return hlist_entry(node, struct nr_node, node_node); + return seq_hlist_next(v, &nr_node_list, pos); } static void nr_node_stop(struct seq_file *seq, void *v) @@ -906,7 +886,9 @@ static int nr_node_show(struct seq_file *seq, void *v) seq_puts(seq, "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); else { - struct nr_node *nr_node = v; + struct nr_node *nr_node = hlist_entry(v, struct nr_node, + node_node); + nr_node_lock(nr_node); seq_printf(seq, "%-9s %-7s %d %d", ax2asc(buf, &nr_node->callsign), @@ -949,31 +931,13 @@ const struct file_operations nr_nodes_fops = { static void *nr_neigh_start(struct seq_file *seq, loff_t *pos) { - struct nr_neigh *nr_neigh; - struct hlist_node *node; - int i = 1; - spin_lock_bh(&nr_neigh_list_lock); - if (*pos == 0) - return SEQ_START_TOKEN; - - nr_neigh_for_each(nr_neigh, node, &nr_neigh_list) { - if (i == *pos) - return nr_neigh; - } - return NULL; + return seq_hlist_start_head(&nr_neigh_list, *pos); } static void *nr_neigh_next(struct seq_file *seq, void *v, loff_t *pos) { - struct hlist_node *node; - ++*pos; - - node = (v == SEQ_START_TOKEN) - ? nr_neigh_list.first - : ((struct nr_neigh *)v)->neigh_node.next; - - return hlist_entry(node, struct nr_neigh, neigh_node); + return seq_hlist_next(v, &nr_neigh_list, pos); } static void nr_neigh_stop(struct seq_file *seq, void *v) @@ -989,8 +953,9 @@ static int nr_neigh_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n"); else { - struct nr_neigh *nr_neigh = v; + struct nr_neigh *nr_neigh; + nr_neigh = hlist_entry(v, struct nr_neigh, neigh_node); seq_printf(seq, "%05d %-9s %-4s %3d %d %3d %3d", nr_neigh->number, ax2asc(buf, &nr_neigh->callsign), -- cgit v1.2.3 From b512f3d841370aedee9a2c24a14a0ab5fc0a02b2 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:19:59 +0000 Subject: net: ax25: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 18 +++--------------- net/ax25/ax25_uid.c | 25 ++++--------------------- 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 5588ba69c468..a5beedf43e2d 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1863,25 +1863,13 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static void *ax25_info_start(struct seq_file *seq, loff_t *pos) __acquires(ax25_list_lock) { - struct ax25_cb *ax25; - struct hlist_node *node; - int i = 0; - spin_lock_bh(&ax25_list_lock); - ax25_for_each(ax25, node, &ax25_list) { - if (i == *pos) - return ax25; - ++i; - } - return NULL; + return seq_hlist_start(&ax25_list, *pos); } static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - - return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next, - struct ax25_cb, ax25_node); + return seq_hlist_next(v, &ax25_list, pos); } static void ax25_info_stop(struct seq_file *seq, void *v) @@ -1892,7 +1880,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v) static int ax25_info_show(struct seq_file *seq, void *v) { - ax25_cb *ax25 = v; + ax25_cb *ax25 = hlist_entry(v, struct ax25_cb, ax25_node); char buf[11]; int k; diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 832bcf092a01..9f13f6eefcba 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -146,31 +146,13 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) __acquires(ax25_uid_lock) { - struct ax25_uid_assoc *pt; - struct hlist_node *node; - int i = 1; - read_lock(&ax25_uid_lock); - - if (*pos == 0) - return SEQ_START_TOKEN; - - ax25_uid_for_each(pt, node, &ax25_uid_list) { - if (i == *pos) - return pt; - ++i; - } - return NULL; + return seq_hlist_start_head(&ax25_uid_list, *pos); } static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - if (v == SEQ_START_TOKEN) - return ax25_uid_list.first; - else - return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next, - ax25_uid_assoc, uid_node); + return seq_hlist_next(v, &ax25_uid_list, pos); } static void ax25_uid_seq_stop(struct seq_file *seq, void *v) @@ -186,8 +168,9 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_printf(seq, "Policy: %d\n", ax25_uid_policy); else { - struct ax25_uid_assoc *pt = v; + struct ax25_uid_assoc *pt; + pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call)); } return 0; -- cgit v1.2.3 From efaffb78d875a155b9f327532c2ddccf28c592b4 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:20:15 +0000 Subject: net: appletalk: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/appletalk/atalk_proc.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index 80caad1a31a5..6ef0e761e5de 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c @@ -144,40 +144,16 @@ out: return 0; } -static __inline__ struct sock *atalk_get_socket_idx(loff_t pos) -{ - struct sock *s; - struct hlist_node *node; - - sk_for_each(s, node, &atalk_sockets) - if (!pos--) - goto found; - s = NULL; -found: - return s; -} - static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos) __acquires(atalk_sockets_lock) { - loff_t l = *pos; - read_lock_bh(&atalk_sockets_lock); - return l ? atalk_get_socket_idx(--l) : SEQ_START_TOKEN; + return seq_hlist_start_head(&atalk_sockets, *pos); } static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) { - struct sock *i; - - ++*pos; - if (v == SEQ_START_TOKEN) { - i = sk_head(&atalk_sockets); - goto out; - } - i = sk_next(v); -out: - return i; + return seq_hlist_next(v, &atalk_sockets, pos); } static void atalk_seq_socket_stop(struct seq_file *seq, void *v) @@ -197,7 +173,7 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v) goto out; } - s = v; + s = sk_entry(v); at = at_sk(s); seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " -- cgit v1.2.3 From 27b5b8657a2aa761f76e45fa60c20b7bafc249dc Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:20:29 +0000 Subject: net: af_key: use seq_hlist_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/key/af_key.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 41dd2cb07ef3..79d2c0f3c334 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3654,9 +3654,8 @@ static const struct net_proto_family pfkey_family_ops = { #ifdef CONFIG_PROC_FS static int pfkey_seq_show(struct seq_file *f, void *v) { - struct sock *s; + struct sock *s = sk_entry(v); - s = (struct sock *)v; if (v == SEQ_START_TOKEN) seq_printf(f ,"sk RefCnt Rmem Wmem User Inode\n"); else @@ -3675,19 +3674,9 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos) { struct net *net = seq_file_net(f); struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - struct sock *s; - struct hlist_node *node; - loff_t pos = *ppos; read_lock(&pfkey_table_lock); - if (pos == 0) - return SEQ_START_TOKEN; - - sk_for_each(s, node, &net_pfkey->table) - if (pos-- == 1) - return s; - - return NULL; + return seq_hlist_start_head(&net_pfkey->table, *ppos); } static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) @@ -3695,10 +3684,7 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) struct net *net = seq_file_net(f); struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - ++*ppos; - return (v == SEQ_START_TOKEN) ? - sk_head(&net_pfkey->table) : - sk_next((struct sock *)v); + return seq_hlist_next(v, &net_pfkey->table, ppos); } static void pfkey_seq_stop(struct seq_file *f, void *v) -- cgit v1.2.3 From 4f134204f740d9fbf992843a6615175f5105f49e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:20:42 +0000 Subject: net: x25: use seq_list_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/x25/x25_proc.c | 84 ++++++------------------------------------------------ 1 file changed, 8 insertions(+), 76 deletions(-) diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index c4cd3226a053..7ff373792324 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c @@ -25,49 +25,17 @@ #include #ifdef CONFIG_PROC_FS -static __inline__ struct x25_route *x25_get_route_idx(loff_t pos) -{ - struct list_head *route_entry; - struct x25_route *rt = NULL; - - list_for_each(route_entry, &x25_route_list) { - rt = list_entry(route_entry, struct x25_route, node); - if (!pos--) - goto found; - } - rt = NULL; -found: - return rt; -} static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) __acquires(x25_route_list_lock) { - loff_t l = *pos; - read_lock_bh(&x25_route_list_lock); - return l ? x25_get_route_idx(--l) : SEQ_START_TOKEN; + return seq_list_start_head(&x25_route_list, *pos); } static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) { - struct x25_route *rt; - - ++*pos; - if (v == SEQ_START_TOKEN) { - rt = NULL; - if (!list_empty(&x25_route_list)) - rt = list_entry(x25_route_list.next, - struct x25_route, node); - goto out; - } - rt = v; - if (rt->node.next != &x25_route_list) - rt = list_entry(rt->node.next, struct x25_route, node); - else - rt = NULL; -out: - return rt; + return seq_list_next(v, &x25_route_list, pos); } static void x25_seq_route_stop(struct seq_file *seq, void *v) @@ -78,9 +46,9 @@ static void x25_seq_route_stop(struct seq_file *seq, void *v) static int x25_seq_route_show(struct seq_file *seq, void *v) { - struct x25_route *rt; + struct x25_route *rt = list_entry(v, struct x25_route, node); - if (v == SEQ_START_TOKEN) { + if (v == &x25_route_list) { seq_puts(seq, "Address Digits Device\n"); goto out; } @@ -146,51 +114,16 @@ out: return 0; } -static __inline__ struct x25_forward *x25_get_forward_idx(loff_t pos) -{ - struct x25_forward *f; - struct list_head *entry; - - list_for_each(entry, &x25_forward_list) { - f = list_entry(entry, struct x25_forward, node); - if (!pos--) - goto found; - } - - f = NULL; -found: - return f; -} - static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) __acquires(x25_forward_list_lock) { - loff_t l = *pos; - read_lock_bh(&x25_forward_list_lock); - return l ? x25_get_forward_idx(--l) : SEQ_START_TOKEN; + return seq_list_start_head(&x25_forward_list, *pos); } static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) { - struct x25_forward *f; - - ++*pos; - if (v == SEQ_START_TOKEN) { - f = NULL; - if (!list_empty(&x25_forward_list)) - f = list_entry(x25_forward_list.next, - struct x25_forward, node); - goto out; - } - f = v; - if (f->node.next != &x25_forward_list) - f = list_entry(f->node.next, struct x25_forward, node); - else - f = NULL; -out: - return f; - + return seq_list_next(v, &x25_forward_list, pos); } static void x25_seq_forward_stop(struct seq_file *seq, void *v) @@ -201,9 +134,9 @@ static void x25_seq_forward_stop(struct seq_file *seq, void *v) static int x25_seq_forward_show(struct seq_file *seq, void *v) { - struct x25_forward *f; + struct x25_forward *f = list_entry(v, struct x25_forward, node); - if (v == SEQ_START_TOKEN) { + if (v == &x25_forward_list) { seq_printf(seq, "lci dev1 dev2\n"); goto out; } @@ -212,7 +145,6 @@ static int x25_seq_forward_show(struct seq_file *seq, void *v) seq_printf(seq, "%d %-10s %-10s\n", f->lci, f->dev1->name, f->dev2->name); - out: return 0; } -- cgit v1.2.3 From 216437eb8b5adf12ab91e1f0c046ffba22c63431 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:21:05 +0000 Subject: net: irda: use seq_list_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/irda/irlan/irlan_common.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 315ead3cb926..e486dc89ea59 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -1128,34 +1128,14 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) */ static void *irlan_seq_start(struct seq_file *seq, loff_t *pos) { - int i = 1; - struct irlan_cb *self; - rcu_read_lock(); - if (*pos == 0) - return SEQ_START_TOKEN; - - list_for_each_entry(self, &irlans, dev_list) { - if (*pos == i) - return self; - ++i; - } - return NULL; + return seq_list_start_head(&irlans, *pos); } /* Return entry after v, and increment pos */ static void *irlan_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct list_head *nxt; - - ++*pos; - if (v == SEQ_START_TOKEN) - nxt = irlans.next; - else - nxt = ((struct irlan_cb *)v)->dev_list.next; - - return (nxt == &irlans) ? NULL - : list_entry(nxt, struct irlan_cb, dev_list); + return seq_list_next(v, &irlans, pos); } /* End of reading /proc file */ @@ -1170,10 +1150,10 @@ static void irlan_seq_stop(struct seq_file *seq, void *v) */ static int irlan_seq_show(struct seq_file *seq, void *v) { - if (v == SEQ_START_TOKEN) + if (v == &irlans) seq_puts(seq, "IrLAN instances:\n"); else { - struct irlan_cb *self = v; + struct irlan_cb *self = list_entry(v, struct irlan_cb, dev_list); IRDA_ASSERT(self != NULL, return -1;); IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;); -- cgit v1.2.3 From a2b79b414df97a70c33f874b631e06830431d233 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:21:22 +0000 Subject: net: ipx: use seq_list_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/ipx/ipx_proc.c | 90 ++++++++---------------------------------------------- 1 file changed, 12 insertions(+), 78 deletions(-) diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index 576178482f89..26b5bfcf1d03 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c @@ -13,45 +13,15 @@ #include #include -static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos) -{ - struct ipx_interface *i; - - list_for_each_entry(i, &ipx_interfaces, node) - if (!pos--) - goto out; - i = NULL; -out: - return i; -} - -static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i) -{ - struct ipx_interface *rc = NULL; - - if (i->node.next != &ipx_interfaces) - rc = list_entry(i->node.next, struct ipx_interface, node); - return rc; -} - static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) { - loff_t l = *pos; - spin_lock_bh(&ipx_interfaces_lock); - return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN; + return seq_list_start_head(&ipx_interfaces, *pos); } static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) { - struct ipx_interface *i; - - ++*pos; - if (v == SEQ_START_TOKEN) - i = ipx_interfaces_head(); - else - i = ipx_interfaces_next(v); - return i; + return seq_list_next(v, &ipx_interfaces, pos); } static void ipx_seq_interface_stop(struct seq_file *seq, void *v) @@ -63,7 +33,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v) { struct ipx_interface *i; - if (v == SEQ_START_TOKEN) { + if (v == &ipx_interfaces) { seq_puts(seq, "Network Node_Address Primary Device " "Frame_Type"); #ifdef IPX_REFCNT_DEBUG @@ -73,7 +43,7 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v) goto out; } - i = v; + i = list_entry(v, struct ipx_interface, node); seq_printf(seq, "%08lX ", (unsigned long int)ntohl(i->if_netnum)); seq_printf(seq, "%02X%02X%02X%02X%02X%02X ", i->if_node[0], i->if_node[1], i->if_node[2], @@ -89,53 +59,15 @@ out: return 0; } -static struct ipx_route *ipx_routes_head(void) -{ - struct ipx_route *rc = NULL; - - if (!list_empty(&ipx_routes)) - rc = list_entry(ipx_routes.next, struct ipx_route, node); - return rc; -} - -static struct ipx_route *ipx_routes_next(struct ipx_route *r) -{ - struct ipx_route *rc = NULL; - - if (r->node.next != &ipx_routes) - rc = list_entry(r->node.next, struct ipx_route, node); - return rc; -} - -static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos) -{ - struct ipx_route *r; - - list_for_each_entry(r, &ipx_routes, node) - if (!pos--) - goto out; - r = NULL; -out: - return r; -} - static void *ipx_seq_route_start(struct seq_file *seq, loff_t *pos) { - loff_t l = *pos; read_lock_bh(&ipx_routes_lock); - return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN; + return seq_list_start_head(&ipx_routes, *pos); } static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) { - struct ipx_route *r; - - ++*pos; - if (v == SEQ_START_TOKEN) - r = ipx_routes_head(); - else - r = ipx_routes_next(v); - return r; + return seq_list_next(v, &ipx_routes, pos); } static void ipx_seq_route_stop(struct seq_file *seq, void *v) @@ -147,11 +79,13 @@ static int ipx_seq_route_show(struct seq_file *seq, void *v) { struct ipx_route *rt; - if (v == SEQ_START_TOKEN) { + if (v == &ipx_routes) { seq_puts(seq, "Network Router_Net Router_Node\n"); goto out; } - rt = v; + + rt = list_entry(v, struct ipx_route, node); + seq_printf(seq, "%08lX ", (unsigned long int)ntohl(rt->ir_net)); if (rt->ir_routed) seq_printf(seq, "%08lX %02X%02X%02X%02X%02X%02X\n", @@ -226,9 +160,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) spin_unlock_bh(&i->if_sklist_lock); sk = NULL; for (;;) { - i = ipx_interfaces_next(i); - if (!i) + if (i->node.next == &ipx_interfaces) break; + i = list_entry(i->node.next, struct ipx_interface, node); spin_lock_bh(&i->if_sklist_lock); if (!hlist_empty(&i->if_sklist)) { sk = sk_head(&i->if_sklist); -- cgit v1.2.3 From 67de792420be2daa1c6fec07ec8552af9ea0bde3 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 8 Feb 2010 23:21:51 +0000 Subject: net: atm: use seq_list_foo() helpers Simplify seq_file code. Signed-off-by: Li Zefan Signed-off-by: David S. Miller --- net/atm/proc.c | 2 +- net/atm/resources.c | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/net/atm/proc.c b/net/atm/proc.c index 476779d845eb..7a96b2376bd7 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -238,7 +238,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v) "Itf Type ESI/\"MAC\"addr " "AAL(TX,err,RX,err,drop) ... [refcnt]\n"; - if (v == SEQ_START_TOKEN) + if (v == &atm_devs) seq_puts(seq, atm_dev_banner); else { struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list); diff --git a/net/atm/resources.c b/net/atm/resources.c index 447ed89205d8..90082904f20d 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -444,21 +444,10 @@ done: return error; } -static inline void *dev_get_idx(loff_t left) -{ - struct list_head *p; - - list_for_each(p, &atm_devs) { - if (!--left) - break; - } - return (p != &atm_devs) ? p : NULL; -} - void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) { mutex_lock(&atm_dev_mutex); - return *pos ? dev_get_idx(*pos) : SEQ_START_TOKEN; + return seq_list_start_head(&atm_devs, *pos); } void atm_dev_seq_stop(struct seq_file *seq, void *v) @@ -468,8 +457,5 @@ void atm_dev_seq_stop(struct seq_file *seq, void *v) void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - v = (v == SEQ_START_TOKEN) - ? atm_devs.next : ((struct list_head *)v)->next; - return (v == &atm_devs) ? NULL : v; + return seq_list_next(v, &atm_devs, pos); } -- cgit v1.2.3 From 633e7533cec78b99d806248e832fc83e689d2453 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 5 Feb 2010 08:56:20 +0000 Subject: fec: fix uninitialized rx buffer usage The fec driver was enabling receive buffer descriptor without allocating the buffers. Make sure the buffer descriptors are initialized to not start receiving packets. Open also calls fec_restart after the rx buffers are allocated. With the code in fec_restart, it zeroes out the buffer descriptors that have just been setup. Signed-off-by: Rob Herring Signed-off-by: Amit Kucheria Acked-by: Grant Likely Acked-by: Greg Ungerer Signed-off-by: David S. Miller --- drivers/net/fec.c | 57 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 16a1d58419d9..9a8743daa3e5 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1658,6 +1658,7 @@ static int fec_enet_init(struct net_device *dev, int index) { struct fec_enet_private *fep = netdev_priv(dev); struct bufdesc *cbd_base; + struct bufdesc *bdp; int i; /* Allocate memory for buffer descriptors. */ @@ -1710,6 +1711,34 @@ static int fec_enet_init(struct net_device *dev, int index) /* Set MII speed to 2.5 MHz */ fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999) / 2500000) / 2) & 0x3F) << 1; + + /* Initialize the receive buffer descriptors. */ + bdp = fep->rx_bd_base; + for (i = 0; i < RX_RING_SIZE; i++) { + + /* Initialize the BD for every fragment in the page. */ + bdp->cbd_sc = 0; + bdp++; + } + + /* Set the last buffer to wrap */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* ...and the same for transmit */ + bdp = fep->tx_bd_base; + for (i = 0; i < TX_RING_SIZE; i++) { + + /* Initialize the BD for every fragment in the page. */ + bdp->cbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + fec_restart(dev, 0); /* Queue up command to detect the PHY and initialize the @@ -1730,7 +1759,6 @@ static void fec_restart(struct net_device *dev, int duplex) { struct fec_enet_private *fep = netdev_priv(dev); - struct bufdesc *bdp; int i; /* Whack a reset. We should wait for this. */ @@ -1768,33 +1796,6 @@ fec_restart(struct net_device *dev, int duplex) } } - /* Initialize the receive buffer descriptors. */ - bdp = fep->rx_bd_base; - for (i = 0; i < RX_RING_SIZE; i++) { - - /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = BD_ENET_RX_EMPTY; - bdp++; - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - - /* ...and the same for transmit */ - bdp = fep->tx_bd_base; - for (i = 0; i < TX_RING_SIZE; i++) { - - /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; - bdp++; - } - - /* Set the last buffer to wrap */ - bdp--; - bdp->cbd_sc |= BD_SC_WRAP; - /* Enable MII mode */ if (duplex) { /* MII enable / FD enable */ -- cgit v1.2.3 From fceb2919192d7a667be81c17c0bfa227fd7fa992 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 5 Feb 2010 08:56:21 +0000 Subject: fec: Add LAN8700 phy support The i.MX51 babbage board has a FEC ethernet controller with this phy. In the long term we should resurrect the phylib patches for fec. Signed-off-by: Amit Kucheria Acked-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/fec.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9a8743daa3e5..5d0d33268155 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1128,6 +1128,26 @@ static phy_info_t phy_info_dp83848= { }, }; +static phy_info_t phy_info_lan8700 = { + 0x0007C0C, + "LAN8700", + (const phy_cmd_t []) { /* config */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup */ + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* act_int */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown */ + { mk_mii_end, } + }, +}; /* ------------------------------------------------------------------------- */ static phy_info_t const * const phy_info[] = { @@ -1137,6 +1157,7 @@ static phy_info_t const * const phy_info[] = { &phy_info_am79c874, &phy_info_ks8721bl, &phy_info_dp83848, + &phy_info_lan8700, NULL }; -- cgit v1.2.3 From bd011e8826978b0f6cd0f929edec353fd755f49b Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 5 Feb 2010 08:56:22 +0000 Subject: fec: Add ARCH_MX5 as a dependency i.MX51 babbage board has a FEC ethernet controller Signed-off-by: Amit Kucheria Signed-off-by: David S. Miller --- drivers/net/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ef662e15c3d3..1bf1987571ff 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1895,7 +1895,8 @@ config 68360_ENET config FEC bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" - depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || ARCH_MX35 || ARCH_MX25 + depends on M523x || M527x || M5272 || M528x || M520x || M532x || \ + MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 help Say Y here if you want to use the built-in 10/100 Fast ethernet controller on some Motorola ColdFire and Freescale i.MX processors. -- cgit v1.2.3 From 2ac2927a953a01c83df255118922cce1523d1a18 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Tue, 9 Feb 2010 13:06:54 -0500 Subject: ath5k: use correct packet type when transmitting The hardware needs to know what type of frames are being sent in order to fill in various fields, for example the timestamp in probe responses (before this patch, it was always 0). Set it correctly when initializing the TX descriptor. Signed-off-by: Bob Copeland Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 1 - drivers/net/wireless/ath/ath5k/base.c | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ad4d446f0264..ac67f02e26d8 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -541,7 +541,6 @@ struct ath5k_txq_info { /* * Transmit packet types. * used on tx control descriptor - * TODO: Use them inside base.c corectly */ enum ath5k_pkt_type { AR5K_PKT_TYPE_NORMAL = 0, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 97d642575550..2468c64d6c12 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1246,6 +1246,29 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) return 0; } +static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + enum ath5k_pkt_type htype; + __le16 fc; + + hdr = (struct ieee80211_hdr *)skb->data; + fc = hdr->frame_control; + + if (ieee80211_is_beacon(fc)) + htype = AR5K_PKT_TYPE_BEACON; + else if (ieee80211_is_probe_resp(fc)) + htype = AR5K_PKT_TYPE_PROBE_RESP; + else if (ieee80211_is_atim(fc)) + htype = AR5K_PKT_TYPE_ATIM; + else if (ieee80211_is_pspoll(fc)) + htype = AR5K_PKT_TYPE_PSPOLL; + else + htype = AR5K_PKT_TYPE_NORMAL; + + return htype; +} + static int ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, struct ath5k_txq *txq) @@ -1300,7 +1323,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, sc->vif, pktlen, info)); } ret = ah->ah_setup_tx_desc(ah, ds, pktlen, - ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, + ieee80211_get_hdrlen_from_skb(skb), + get_hw_packet_type(skb), (sc->power_level * 2), hw_rate, info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, -- cgit v1.2.3 From f32338319f10c4ca5499c19edc5b3618896920ba Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Tue, 9 Feb 2010 13:35:43 -0800 Subject: Add Station and AdHoc mode support to libertas_tf Add support for using the libertas_tf driver on a managed or ad-hoc network. Signed-off-by: Deepak Saxena Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index ba3eb0101d55..6ab30033c26c 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -555,6 +555,9 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) priv->band.n_channels = ARRAY_SIZE(lbtf_channels); priv->band.channels = priv->channels; hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); skb_queue_head_init(&priv->bc_ps_buf); SET_IEEE80211_DEV(hw, dmdev); -- cgit v1.2.3 From 4cad6c7c38930618d77e65af82c1403d63879eee Mon Sep 17 00:00:00 2001 From: Sujith Date: Wed, 10 Feb 2010 14:52:21 +0530 Subject: mac80211: Deny TX BA session requests during disassociation In associated state, when bringing an interface down, existing BA sessions are torn down. When this is in progress, nothing prevents mac80211 from accepting another BA session start request. Use a new station flag to fix this. Signed-off-by: Sujith Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 8 ++++++++ net/mac80211/mlme.c | 4 +++- net/mac80211/sta_info.h | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 718fbcff84d2..5538e1b4a697 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -237,6 +237,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; + if (test_sta_flags(sta, WLAN_STA_DISASSOC)) { +#ifdef CONFIG_MAC80211_HT_DEBUG + printk(KERN_DEBUG "Disassociation is in progress. " + "Denying BA session request\n"); +#endif + return -EINVAL; + } + if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Suspend in progress. " diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ee9443dc20ff..bfc4a5070013 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -797,8 +797,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); sta = sta_info_get(sdata, bssid); - if (sta) + if (sta) { + set_sta_flags(sta, WLAN_STA_DISASSOC); ieee80211_sta_tear_down_BA_sessions(sta); + } rcu_read_unlock(); changed |= ieee80211_reset_erp_info(sdata); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5ff611a35979..822d84522937 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -42,6 +42,9 @@ * be in the queues * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping * station in power-save mode, reply when the driver unblocks. + * @WLAN_STA_DISASSOC: Disassociation in progress. + * This is used to reject TX BA session requests when disassociation + * is in progress. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH = 1<<0, @@ -57,6 +60,7 @@ enum ieee80211_sta_info_flags { WLAN_STA_SUSPEND = 1<<11, WLAN_STA_PS_DRIVER = 1<<12, WLAN_STA_PSPOLL = 1<<13, + WLAN_STA_DISASSOC = 1<<14, }; #define STA_TID_NUM 16 -- cgit v1.2.3 From a0db28b898266265c1cc2ff84f041a561a265504 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sun, 7 Feb 2010 06:23:53 +0000 Subject: sky2: resume clocks Change the resume path to use pci write config for a couple of reasons: 1. pci_write_config_dword() allows for more error checking of PCI health after resume. 2. better to toggle this register on all chip types, since that is what vendor driver does. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 744362272e2d..1593ed49e8fe 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4859,10 +4859,11 @@ static int sky2_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D0, 0); /* Re-enable all clocks */ - if (hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_FE_P) - sky2_pci_write32(hw, PCI_DEV_REG3, 0); + err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0); + if (err) { + dev_err(&pdev->dev, "PCI write config failed\n"); + goto out; + } sky2_reset(hw); sky2_write32(hw, B0_IMSK, Y2_IS_BASE); -- cgit v1.2.3 From acd12dde26eef5186a9d2ead9399d136932d2398 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sun, 7 Feb 2010 06:24:50 +0000 Subject: sky2: disable ASF on Yukon Supreme Clone of vendor code to disable ASF on Extreme and Supreme chips. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1593ed49e8fe..1aa1f3316702 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3035,11 +3035,20 @@ static void sky2_reset(struct sky2_hw *hw) u32 hwe_mask = Y2_HWE_ALL_MASK; /* disable ASF */ - if (hw->chip_id == CHIP_ID_YUKON_EX) { + if (hw->chip_id == CHIP_ID_YUKON_EX + || hw->chip_id == CHIP_ID_YUKON_SUPR) { + sky2_write32(hw, CPU_WDOG, 0); status = sky2_read16(hw, HCU_CCSR); status &= ~(HCU_CCSR_AHB_RST | HCU_CCSR_CPU_RST_MODE | HCU_CCSR_UC_STATE_MSK); + /* + * CPU clock divider shouldn't be used because + * - ASF firmware may malfunction + * - Yukon-Supreme: Parallel FLASH doesn't support divided clocks + */ + status &= ~HCU_CCSR_CPU_CLK_DIVIDE_MSK; sky2_write16(hw, HCU_CCSR, status); + sky2_write32(hw, CPU_WDOG, 0); } else sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE); -- cgit v1.2.3 From 375c568844e49d292885c7485d4a255f71680e56 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Sun, 7 Feb 2010 06:28:36 +0000 Subject: sky2: receive checksum refactoring Break the largish case for handling receive checksum into a separate function, and if there is a problem use dev_XXX routines to show which hardware is the problem. Turn one corner case into a BUG(). This only happens if the driver is expecting one behavior but the chip does the old behavior; only ever saw this when bringing up a new chip type and driver was buggy. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 59 ++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1aa1f3316702..478288b8bc21 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2484,6 +2484,32 @@ static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, } } +static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) +{ + /* If this happens then driver assuming wrong format for chip type */ + BUG_ON(sky2->hw->flags & SKY2_HW_NEW_LE); + + /* Both checksum counters are programmed to start at + * the same offset, so unless there is a problem they + * should match. This failure is an early indication that + * hardware receive checksumming won't work. + */ + if (likely((u16)(status >> 16) == (u16)status)) { + struct sk_buff *skb = sky2->rx_ring[sky2->rx_next].skb; + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = le16_to_cpu(status); + } else { + dev_notice(&sky2->hw->pdev->dev, + "%s: receive checksum problem (status = %#x)\n", + sky2->netdev->name, status); + + /* Disable checksum offload */ + sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + BMU_DIS_RX_CHKSUM); + } +} + /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) { @@ -2552,37 +2578,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) /* fall through */ #endif case OP_RXCHKS: - if (!(sky2->flags & SKY2_FLAG_RX_CHECKSUM)) - break; - - /* If this happens then driver assuming wrong format */ - if (unlikely(hw->flags & SKY2_HW_NEW_LE)) { - if (net_ratelimit()) - printk(KERN_NOTICE "%s: unexpected" - " checksum status\n", - dev->name); - break; - } - - /* Both checksum counters are programmed to start at - * the same offset, so unless there is a problem they - * should match. This failure is an early indication that - * hardware receive checksumming won't work. - */ - if (likely(status >> 16 == (status & 0xffff))) { - skb = sky2->rx_ring[sky2->rx_next].skb; - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = le16_to_cpu(status); - } else { - printk(KERN_NOTICE PFX "%s: hardware receive " - "checksum problem (status = %#x)\n", - dev->name, status); - sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM; - - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[port], Q_CSR), - BMU_DIS_RX_CHKSUM); - } + if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM)) + sky2_rx_checksum(sky2, status); break; case OP_TXINDEXLE: -- cgit v1.2.3 From 15682bc488d4af8c9bb998844a94281025e0a333 Mon Sep 17 00:00:00 2001 From: Peter P Waskiewicz Jr Date: Wed, 10 Feb 2010 20:03:05 -0800 Subject: ethtool: Introduce n-tuple filter programming support This patchset enables the ethtool layer to program n-tuple filters to an underlying device. The idea is to allow capable hardware to have static rules applied that can assist steering flows into appropriate queues. Hardware that is known to support these types of filters today are ixgbe and niu. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- include/linux/ethtool.h | 50 +++++++ include/linux/netdevice.h | 3 + net/core/dev.c | 5 + net/core/ethtool.c | 329 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 386 insertions(+), 1 deletion(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ef4a2d84d922..a3cac53a0766 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -14,6 +14,7 @@ #define _LINUX_ETHTOOL_H #include +#include /* This should work for both 32 and 64 bit userland. */ struct ethtool_cmd { @@ -242,6 +243,7 @@ enum ethtool_stringset { ETH_SS_TEST = 0, ETH_SS_STATS, ETH_SS_PRIV_FLAGS, + ETH_SS_NTUPLE_FILTERS, }; /* for passing string sets for data tagging */ @@ -290,6 +292,7 @@ struct ethtool_perm_addr { */ enum ethtool_flags { ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ + ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ }; /* The following structures are for supporting RX network flow @@ -363,6 +366,35 @@ struct ethtool_rxnfc { __u32 rule_locs[0]; }; +struct ethtool_rx_ntuple_flow_spec { + __u32 flow_type; + union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_rawip4_spec raw_ip4_spec; + struct ethtool_ether_spec ether_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + __u8 hdata[64]; + } h_u, m_u; /* entry, mask */ + + __u16 vlan_tag; + __u16 vlan_tag_mask; + __u64 data; /* user-defined flow spec data */ + __u64 data_mask; /* user-defined flow spec mask */ + + /* signed to distinguish between queue and actions (DROP) */ + __s32 action; +#define ETHTOOL_RXNTUPLE_ACTION_DROP -1 +}; + +struct ethtool_rx_ntuple { + __u32 cmd; + struct ethtool_rx_ntuple_flow_spec fs; +}; + #define ETHTOOL_FLASH_MAX_FILENAME 128 enum ethtool_flash_op_type { ETHTOOL_FLASH_ALL_REGIONS = 0, @@ -377,6 +409,18 @@ struct ethtool_flash { #ifdef __KERNEL__ +struct ethtool_rx_ntuple_flow_spec_container { + struct ethtool_rx_ntuple_flow_spec fs; + struct list_head list; +}; + +struct ethtool_rx_ntuple_list { +#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024 +#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14 + struct list_head list; + unsigned int count; +}; + struct net_device; /* Some generic methods drivers may use in their ethtool_ops */ @@ -394,6 +438,7 @@ u32 ethtool_op_get_ufo(struct net_device *dev); int ethtool_op_set_ufo(struct net_device *dev, u32 data); u32 ethtool_op_get_flags(struct net_device *dev); int ethtool_op_set_flags(struct net_device *dev, u32 data); +void ethtool_ntuple_flush(struct net_device *dev); /** * ðtool_ops - Alter and report network device settings @@ -500,6 +545,8 @@ struct ethtool_ops { int (*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *); int (*flash_device)(struct net_device *, struct ethtool_flash *); int (*reset)(struct net_device *, u32 *); + int (*set_rx_ntuple)(struct net_device *, struct ethtool_rx_ntuple *); + int (*get_rx_ntuple)(struct net_device *, u32 stringset, void *); }; #endif /* __KERNEL__ */ @@ -559,6 +606,9 @@ struct ethtool_ops { #define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ #define ETHTOOL_RESET 0x00000034 /* Reset hardware */ +#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ +#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */ + /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET #define SPARC_ETH_SSET ETHTOOL_SSET diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e535700a3b72..cdf53a8d9ff5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -746,6 +746,7 @@ struct net_device { #define NETIF_F_FCOE_CRC (1 << 24) /* FCoE CRC32 */ #define NETIF_F_SCTP_CSUM (1 << 25) /* SCTP checksum offload */ #define NETIF_F_FCOE_MTU (1 << 26) /* Supports max FCoE MTU, 2158 bytes*/ +#define NETIF_F_NTUPLE (1 << 27) /* N-tuple filters supported */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 @@ -954,6 +955,8 @@ struct net_device { /* max exchange id for FCoE LRO by ddp */ unsigned int fcoe_ddp_xid; #endif + /* n-tuple filter list attached to this device */ + struct ethtool_rx_ntuple_list ethtool_ntuple_list; }; #define to_net_dev(d) container_of(d, struct net_device, dev) diff --git a/net/core/dev.c b/net/core/dev.c index 94c1eeed25e5..ae75f25ac0a5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5419,6 +5419,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, netdev_init_queues(dev); + INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list); + dev->ethtool_ntuple_list.count = 0; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); INIT_LIST_HEAD(&dev->link_watch_list); @@ -5455,6 +5457,9 @@ void free_netdev(struct net_device *dev) /* Flush device addresses */ dev_addr_flush(dev); + /* Clear ethtool n-tuple list */ + ethtool_ntuple_flush(dev); + list_for_each_entry_safe(p, n, &dev->napi_list, dev_list) netif_napi_del(p); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d8aee584e8d1..6ec73d3983a3 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -120,7 +120,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data) * NETIF_F_xxx values in include/linux/netdevice.h */ static const u32 flags_dup_features = - ETH_FLAG_LRO; + (ETH_FLAG_LRO | ETH_FLAG_NTUPLE); u32 ethtool_op_get_flags(struct net_device *dev) { @@ -139,9 +139,26 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data) else dev->features &= ~NETIF_F_LRO; + if (data & ETH_FLAG_NTUPLE) + dev->features |= NETIF_F_NTUPLE; + else + dev->features &= ~NETIF_F_NTUPLE; + return 0; } +void ethtool_ntuple_flush(struct net_device *dev) +{ + struct ethtool_rx_ntuple_flow_spec_container *fsc, *f; + + list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) { + list_del(&fsc->list); + kfree(fsc); + } + dev->ethtool_ntuple_list.count = 0; +} +EXPORT_SYMBOL(ethtool_ntuple_flush); + /* Handlers for each ethtool command */ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) @@ -266,6 +283,307 @@ err_out: return ret; } +static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, + struct ethtool_rx_ntuple_flow_spec *spec) +{ + struct ethtool_rx_ntuple_flow_spec_container *fsc; + + /* don't add filters forever */ + if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) + return 0; + + fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); + if (!fsc) + return -ENOMEM; + + /* Copy the whole filter over */ + fsc->fs.flow_type = spec->flow_type; + memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u)); + memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u)); + + fsc->fs.vlan_tag = spec->vlan_tag; + fsc->fs.vlan_tag_mask = spec->vlan_tag_mask; + fsc->fs.data = spec->data; + fsc->fs.data_mask = spec->data_mask; + fsc->fs.action = spec->action; + + /* add to the list */ + list_add_tail_rcu(&fsc->list, &list->list); + list->count++; + + return 0; +} + +static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) +{ + struct ethtool_rx_ntuple cmd; + const struct ethtool_ops *ops = dev->ethtool_ops; + int ret; + + if (!ops->set_rx_ntuple) + return -EOPNOTSUPP; + + if (!(dev->features & NETIF_F_NTUPLE)) + return -EINVAL; + + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) + return -EFAULT; + + ret = ops->set_rx_ntuple(dev, &cmd); + + /* + * Cache filter in dev struct for GET operation only if + * the underlying driver doesn't have its own GET operation, and + * only if the filter was added successfully. + */ + if (!ops->get_rx_ntuple && !ret) + if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs)) + return -ENOMEM; + + return ret; +} + +static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr) +{ + struct ethtool_gstrings gstrings; + const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rx_ntuple_flow_spec_container *fsc; + u8 *data; + char *p; + int ret, i, num_strings = 0; + + if (!ops->get_sset_count) + return -EOPNOTSUPP; + + if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) + return -EFAULT; + + ret = ops->get_sset_count(dev, gstrings.string_set); + if (ret < 0) + return ret; + + gstrings.len = ret; + + data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); + if (!data) + return -ENOMEM; + + if (ops->get_rx_ntuple) { + /* driver-specific filter grab */ + ret = ops->get_rx_ntuple(dev, gstrings.string_set, data); + goto copy; + } + + /* default ethtool filter grab */ + i = 0; + p = (char *)data; + list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) { + sprintf(p, "Filter %d:\n", i); + p += ETH_GSTRING_LEN; + num_strings++; + + switch (fsc->fs.flow_type) { + case TCP_V4_FLOW: + sprintf(p, "\tFlow Type: TCP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case UDP_V4_FLOW: + sprintf(p, "\tFlow Type: UDP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case SCTP_V4_FLOW: + sprintf(p, "\tFlow Type: SCTP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case AH_ESP_V4_FLOW: + sprintf(p, "\tFlow Type: AH ESP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case ESP_V4_FLOW: + sprintf(p, "\tFlow Type: ESP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case IP_USER_FLOW: + sprintf(p, "\tFlow Type: Raw IP\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case IPV4_FLOW: + sprintf(p, "\tFlow Type: IPv4\n"); + p += ETH_GSTRING_LEN; + num_strings++; + break; + default: + sprintf(p, "\tFlow Type: Unknown\n"); + p += ETH_GSTRING_LEN; + num_strings++; + goto unknown_filter; + }; + + /* now the rest of the filters */ + switch (fsc->fs.flow_type) { + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case SCTP_V4_FLOW: + sprintf(p, "\tSrc IP addr: 0x%x\n", + fsc->fs.h_u.tcp_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSrc IP mask: 0x%x\n", + fsc->fs.m_u.tcp_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP addr: 0x%x\n", + fsc->fs.h_u.tcp_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP mask: 0x%x\n", + fsc->fs.m_u.tcp_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSrc Port: %d, mask: 0x%x\n", + fsc->fs.h_u.tcp_ip4_spec.psrc, + fsc->fs.m_u.tcp_ip4_spec.psrc); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest Port: %d, mask: 0x%x\n", + fsc->fs.h_u.tcp_ip4_spec.pdst, + fsc->fs.m_u.tcp_ip4_spec.pdst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tTOS: %d, mask: 0x%x\n", + fsc->fs.h_u.tcp_ip4_spec.tos, + fsc->fs.m_u.tcp_ip4_spec.tos); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case AH_ESP_V4_FLOW: + case ESP_V4_FLOW: + sprintf(p, "\tSrc IP addr: 0x%x\n", + fsc->fs.h_u.ah_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSrc IP mask: 0x%x\n", + fsc->fs.m_u.ah_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP addr: 0x%x\n", + fsc->fs.h_u.ah_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP mask: 0x%x\n", + fsc->fs.m_u.ah_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSPI: %d, mask: 0x%x\n", + fsc->fs.h_u.ah_ip4_spec.spi, + fsc->fs.m_u.ah_ip4_spec.spi); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tTOS: %d, mask: 0x%x\n", + fsc->fs.h_u.ah_ip4_spec.tos, + fsc->fs.m_u.ah_ip4_spec.tos); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case IP_USER_FLOW: + sprintf(p, "\tSrc IP addr: 0x%x\n", + fsc->fs.h_u.raw_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSrc IP mask: 0x%x\n", + fsc->fs.m_u.raw_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP addr: 0x%x\n", + fsc->fs.h_u.raw_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP mask: 0x%x\n", + fsc->fs.m_u.raw_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + break; + case IPV4_FLOW: + sprintf(p, "\tSrc IP addr: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tSrc IP mask: 0x%x\n", + fsc->fs.m_u.usr_ip4_spec.ip4src); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP addr: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tDest IP mask: 0x%x\n", + fsc->fs.m_u.usr_ip4_spec.ip4dst); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.l4_4_bytes, + fsc->fs.m_u.usr_ip4_spec.l4_4_bytes); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tTOS: %d, mask: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.tos, + fsc->fs.m_u.usr_ip4_spec.tos); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tIP Version: %d, mask: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.ip_ver, + fsc->fs.m_u.usr_ip4_spec.ip_ver); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tProtocol: %d, mask: 0x%x\n", + fsc->fs.h_u.usr_ip4_spec.proto, + fsc->fs.m_u.usr_ip4_spec.proto); + p += ETH_GSTRING_LEN; + num_strings++; + break; + }; + sprintf(p, "\tVLAN: %d, mask: 0x%x\n", + fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data); + p += ETH_GSTRING_LEN; + num_strings++; + sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask); + p += ETH_GSTRING_LEN; + num_strings++; + if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) + sprintf(p, "\tAction: Drop\n"); + else + sprintf(p, "\tAction: Direct to queue %d\n", + fsc->fs.action); + p += ETH_GSTRING_LEN; + num_strings++; +unknown_filter: + i++; + } +copy: + /* indicate to userspace how many strings we actually have */ + gstrings.len = num_strings; + ret = -EFAULT; + if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) + goto out; + useraddr += sizeof(gstrings); + if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) + goto out; + ret = 0; + +out: + kfree(data); + return ret; +} + static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) { struct ethtool_regs regs; @@ -313,6 +631,9 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) if (copy_from_user(&reset, useraddr, sizeof(reset))) return -EFAULT; + /* Clear ethtool n-tuple list */ + ethtool_ntuple_flush(dev); + ret = dev->ethtool_ops->reset(dev, &reset.data); if (ret) return ret; @@ -1112,6 +1433,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_RESET: rc = ethtool_reset(dev, useraddr); break; + case ETHTOOL_SRXNTUPLE: + rc = ethtool_set_rx_ntuple(dev, useraddr); + break; + case ETHTOOL_GRXNTUPLE: + rc = ethtool_get_rx_ntuple(dev, useraddr); + break; default: rc = -EOPNOTSUPP; } -- cgit v1.2.3 From 9a713e7c7cca2f31c89367bb7b48310ab8a3e630 Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Wed, 10 Feb 2010 16:07:54 +0000 Subject: ixgbe: Add support for the new ethtool n-tuple programming interface This patch adds n-tuple filter programming to 82599. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe.h | 4 ++ drivers/net/ixgbe/ixgbe_82599.c | 106 +++++++++++++++++++++++++++++++----- drivers/net/ixgbe/ixgbe_ethtool.c | 111 ++++++++++++++++++++++++++++++++++++-- drivers/net/ixgbe/ixgbe_main.c | 16 +++++- drivers/net/ixgbe/ixgbe_type.h | 9 ++++ 5 files changed, 228 insertions(+), 18 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index bffbe0d52d33..19e94ee155a2 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -453,6 +453,10 @@ extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc); extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, struct ixgbe_atr_input *input, u8 queue); +extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, + struct ixgbe_atr_input *input, + struct ixgbe_atr_input_masks *input_masks, + u16 soft_id, u8 queue); extern s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan_id); extern s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index d4ed6adb7975..4fa8633fae3c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1439,6 +1439,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) /* Send interrupt when 64 filters are left */ fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT; + /* Initialize the drop queue to Rx queue 127 */ + fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT); + switch (pballoc) { case IXGBE_FDIR_PBALLOC_64K: /* 2k - 1 perfect filters */ @@ -1628,6 +1631,7 @@ static u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream * @input: input stream to modify * @vlan: the VLAN id to load + * @vlan_mask: bitwise mask for the VLAN **/ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) { @@ -1641,6 +1645,7 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address * @input: input stream to modify * @src_addr: the IP address to load + * @src_addr_mask: bitwise mask for the source IP address **/ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) { @@ -1658,6 +1663,7 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address * @input: input stream to modify * @dst_addr: the IP address to load + * @dst_addr_mask: bitwise mask for the destination IP address **/ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) { @@ -1680,8 +1686,8 @@ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) * @src_addr_4: the fourth 4 bytes of the IP address to load **/ s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, - u32 src_addr_1, u32 src_addr_2, - u32 src_addr_3, u32 src_addr_4) + u32 src_addr_1, u32 src_addr_2, + u32 src_addr_3, u32 src_addr_4) { input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] = @@ -1723,8 +1729,8 @@ s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, * @dst_addr_4: the fourth 4 bytes of the IP address to load **/ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, - u32 dst_addr_1, u32 dst_addr_2, - u32 dst_addr_3, u32 dst_addr_4) + u32 dst_addr_1, u32 dst_addr_2, + u32 dst_addr_3, u32 dst_addr_4) { input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff; input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] = @@ -1761,6 +1767,7 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, * ixgbe_atr_set_src_port_82599 - Sets the source port * @input: input stream to modify * @src_port: the source port to load + * @src_port_mask: bitwise mask for the source port **/ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) { @@ -1774,6 +1781,7 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) * ixgbe_atr_set_dst_port_82599 - Sets the destination port * @input: input stream to modify * @dst_port: the destination port to load + * @dst_port_mask: bitwise mask for the destination port **/ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) { @@ -1802,7 +1810,7 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte) * @vm_pool: the Virtual Machine pool to load **/ s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, - u8 vm_pool) + u8 vm_pool) { input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool; @@ -1826,8 +1834,7 @@ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type) * @input: input stream to search * @vlan: the VLAN id to load **/ -static s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, - u16 *vlan) +static s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan) { *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET]; *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8; @@ -2083,23 +2090,26 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw, * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter * @hw: pointer to hardware structure * @input: input bitstream + * @input_masks: bitwise masks for relevant fields + * @soft_id: software index into the silicon hash tables for filter storage * @queue: queue index to direct traffic to * * Note that the caller to this function must lock before calling, since the * hardware writes must be protected from one another. **/ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, - struct ixgbe_atr_input *input, - u16 soft_id, - u8 queue) + struct ixgbe_atr_input *input, + struct ixgbe_atr_input_masks *input_masks, + u16 soft_id, u8 queue) { u32 fdircmd = 0; u32 fdirhash; - u32 src_ipv4, dst_ipv4; + u32 src_ipv4 = 0, dst_ipv4 = 0; u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4; u16 src_port, dst_port, vlan_id, flex_bytes; u16 bucket_hash; u8 l4type; + u8 fdirm = 0; /* Get our input values */ ixgbe_atr_get_l4type_82599(input, &l4type); @@ -2154,7 +2164,6 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, /* IPv4 */ ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4); IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4); - } ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4); @@ -2163,7 +2172,78 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id | (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT))); IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port | - (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); + (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); + + /* + * Program the relevant mask registers. If src/dst_port or src/dst_addr + * are zero, then assume a full mask for that field. Also assume that + * a VLAN of 0 is unspecified, so mask that out as well. L4type + * cannot be masked out in this implementation. + * + * This also assumes IPv4 only. IPv6 masking isn't supported at this + * point in time. + */ + if (src_ipv4 == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask); + + if (dst_ipv4 == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask); + + switch (l4type & IXGBE_ATR_L4TYPE_MASK) { + case IXGBE_ATR_L4TYPE_TCP: + if (src_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + input_masks->src_port_mask); + + if (dst_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | + (0xffff << 16))); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | + (input_masks->dst_port_mask << 16))); + break; + case IXGBE_ATR_L4TYPE_UDP: + if (src_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + input_masks->src_port_mask); + + if (dst_port == 0) + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | + (0xffff << 16))); + else + IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, + (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | + (input_masks->src_port_mask << 16))); + break; + default: + /* this already would have failed above */ + break; + } + + /* Program the last mask register, FDIRM */ + if (input_masks->vlan_id_mask || !vlan_id) + /* Mask both VLAN and VLANP - bits 0 and 1 */ + fdirm |= 0x3; + + if (input_masks->data_mask || !flex_bytes) + /* Flex bytes need masking, so mask the whole thing - bit 4 */ + fdirm |= 0x10; + + /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ + fdirm |= 0x24; + + IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW; fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE; diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 07a9410c08d4..0d234346a4ea 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -979,6 +979,9 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset) return IXGBE_TEST_LEN; case ETH_SS_STATS: return IXGBE_STATS_LEN; + case ETH_SS_NTUPLE_FILTERS: + return (ETHTOOL_MAX_NTUPLE_LIST_ENTRY * + ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY); default: return -EOPNOTSUPP; } @@ -2150,23 +2153,124 @@ static int ixgbe_set_coalesce(struct net_device *netdev, static int ixgbe_set_flags(struct net_device *netdev, u32 data) { struct ixgbe_adapter *adapter = netdev_priv(netdev); + bool need_reset = false; ethtool_op_set_flags(netdev, data); - if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)) - return 0; - /* if state changes we need to update adapter->flags and reset */ if ((!!(data & ETH_FLAG_LRO)) != (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) { adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED; + need_reset = true; + } + + /* + * Check if Flow Director n-tuple support was enabled or disabled. If + * the state changed, we need to reset. + */ + if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) && + (!(data & ETH_FLAG_NTUPLE))) { + /* turn off Flow Director perfect, set hash and reset */ + adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + need_reset = true; + } else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) && + (data & ETH_FLAG_NTUPLE)) { + /* turn off Flow Director hash, enable perfect and reset */ + adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + need_reset = true; + } else { + /* no state change */ + } + + if (need_reset) { if (netif_running(netdev)) ixgbe_reinit_locked(adapter); else ixgbe_reset(adapter); } + return 0; +} + +static int ixgbe_set_rx_ntuple(struct net_device *dev, + struct ethtool_rx_ntuple *cmd) +{ + struct ixgbe_adapter *adapter = netdev_priv(dev); + struct ethtool_rx_ntuple_flow_spec fs = cmd->fs; + struct ixgbe_atr_input input_struct; + struct ixgbe_atr_input_masks input_masks; + int target_queue; + + if (adapter->hw.mac.type == ixgbe_mac_82598EB) + return -EOPNOTSUPP; + + /* + * Don't allow programming if the action is a queue greater than + * the number of online Tx queues. + */ + if ((fs.action >= adapter->num_tx_queues) || + (fs.action < ETHTOOL_RXNTUPLE_ACTION_DROP)) + return -EINVAL; + + memset(&input_struct, 0, sizeof(struct ixgbe_atr_input)); + memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks)); + + input_masks.src_ip_mask = fs.m_u.tcp_ip4_spec.ip4src; + input_masks.dst_ip_mask = fs.m_u.tcp_ip4_spec.ip4dst; + input_masks.src_port_mask = fs.m_u.tcp_ip4_spec.psrc; + input_masks.dst_port_mask = fs.m_u.tcp_ip4_spec.pdst; + input_masks.vlan_id_mask = fs.vlan_tag_mask; + /* only use the lowest 2 bytes for flex bytes */ + input_masks.data_mask = (fs.data_mask & 0xffff); + + switch (fs.flow_type) { + case TCP_V4_FLOW: + ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_TCP); + break; + case UDP_V4_FLOW: + ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_UDP); + break; + case SCTP_V4_FLOW: + ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_SCTP); + break; + default: + return -1; + } + /* Mask bits from the inputs based on user-supplied mask */ + ixgbe_atr_set_src_ipv4_82599(&input_struct, + (fs.h_u.tcp_ip4_spec.ip4src & ~fs.m_u.tcp_ip4_spec.ip4src)); + ixgbe_atr_set_dst_ipv4_82599(&input_struct, + (fs.h_u.tcp_ip4_spec.ip4dst & ~fs.m_u.tcp_ip4_spec.ip4dst)); + /* 82599 expects these to be byte-swapped for perfect filtering */ + ixgbe_atr_set_src_port_82599(&input_struct, + ((ntohs(fs.h_u.tcp_ip4_spec.psrc)) & ~fs.m_u.tcp_ip4_spec.psrc)); + ixgbe_atr_set_dst_port_82599(&input_struct, + ((ntohs(fs.h_u.tcp_ip4_spec.pdst)) & ~fs.m_u.tcp_ip4_spec.pdst)); + + /* VLAN and Flex bytes are either completely masked or not */ + if (!fs.vlan_tag_mask) + ixgbe_atr_set_vlan_id_82599(&input_struct, fs.vlan_tag); + + if (!input_masks.data_mask) + /* make sure we only use the first 2 bytes of user data */ + ixgbe_atr_set_flex_byte_82599(&input_struct, + (fs.data & 0xffff)); + + /* determine if we need to drop or route the packet */ + if (fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP) + target_queue = MAX_RX_QUEUES - 1; + else + target_queue = fs.action; + + spin_lock(&adapter->fdir_perfect_lock); + ixgbe_fdir_add_perfect_filter_82599(&adapter->hw, &input_struct, + &input_masks, 0, target_queue); + spin_unlock(&adapter->fdir_perfect_lock); + + return 0; } static const struct ethtool_ops ixgbe_ethtool_ops = { @@ -2204,6 +2308,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = { .set_coalesce = ixgbe_set_coalesce, .get_flags = ethtool_op_get_flags, .set_flags = ixgbe_set_flags, + .set_rx_ntuple = ixgbe_set_rx_ntuple, }; void ixgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2a3c8315e357..f04b5396e057 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3253,6 +3253,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); + /* clear n-tuple filters that are cached */ + ethtool_ntuple_flush(netdev); + if (!pci_channel_offline(adapter->pdev)) ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); @@ -4187,6 +4190,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; + struct net_device *dev = adapter->netdev; unsigned int rss; #ifdef CONFIG_IXGBE_DCB int j; @@ -4214,10 +4218,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; - adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + if (dev->features & NETIF_F_NTUPLE) { + /* Flow Director perfect filter enabled */ + adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; + adapter->atr_sample_rate = 0; + spin_lock_init(&adapter->fdir_perfect_lock); + } else { + /* Flow Director hash filters enabled */ + adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE; + adapter->atr_sample_rate = 20; + } adapter->ring_feature[RING_F_FDIR].indices = IXGBE_MAX_FDIR_INDICES; - adapter->atr_sample_rate = 20; adapter->fdir_pballoc = 0; #ifdef IXGBE_FCOE adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE; diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 0db67c19b2c4..2be907466593 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -2129,6 +2129,15 @@ struct ixgbe_atr_input { u8 byte_stream[42]; }; +struct ixgbe_atr_input_masks { + u32 src_ip_mask; + u32 dst_ip_mask; + u16 src_port_mask; + u16 dst_port_mask; + u16 vlan_id_mask; + u16 data_mask; +}; + enum ixgbe_eeprom_type { ixgbe_eeprom_uninitialized = 0, ixgbe_eeprom_spi, -- cgit v1.2.3 From 92eb879ff59c5995bf18f76eb0a00cb7db758e42 Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Wed, 10 Feb 2010 16:08:13 +0000 Subject: ixgbe: Bump driver version up Driver has gone under significant changes, the version should reflect that. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index f04b5396e057..382bf8945d11 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -51,7 +51,7 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "2.0.44-k2" +#define DRV_VERSION "2.0.62-k2" const char ixgbe_driver_version[] = DRV_VERSION; static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation."; -- cgit v1.2.3 From d1e7a03f4fee4059ee3fa7ce0edb7c48c1a75fcf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:22:28 +0100 Subject: netfilter: ctnetlink: dump expectation helper name Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 5c103b8c7df0..db35edac307b 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1512,6 +1512,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, const struct nf_conntrack_expect *exp) { struct nf_conn *master = exp->master; + struct nf_conntrack_helper *helper; long timeout = (exp->timeout.expires - jiffies) / HZ; if (timeout < 0) @@ -1528,6 +1529,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); + helper = rcu_dereference(nfct_help(master)->helper); + if (helper) + NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name); return 0; -- cgit v1.2.3 From b87921bdf25485afd8f5a5f25e86b5acef32a9cf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:22:48 +0100 Subject: netfilter: nf_conntrack: show helper and class in /proc/net/nf_conntrack_expect Make the output a bit more informative by showing the helper an expectation belongs to and the expectation class. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_expect.h | 1 + net/netfilter/nf_conntrack_expect.c | 9 +++++++++ net/netfilter/nf_conntrack_sip.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 9a2b9cb52271..917e170fa752 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -66,6 +66,7 @@ static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp) struct nf_conntrack_expect_policy { unsigned int max_expected; unsigned int timeout; + const char *name; }; #define NF_CT_EXPECT_CLASS_DEFAULT 0 diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 2f25ff610982..33b85f834c06 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -500,6 +500,7 @@ static void exp_seq_stop(struct seq_file *seq, void *v) static int exp_seq_show(struct seq_file *s, void *v) { struct nf_conntrack_expect *expect; + struct nf_conntrack_helper *helper; struct hlist_node *n = v; char *delim = ""; @@ -525,6 +526,14 @@ static int exp_seq_show(struct seq_file *s, void *v) if (expect->flags & NF_CT_EXPECT_INACTIVE) seq_printf(s, "%sINACTIVE", delim); + helper = rcu_dereference(nfct_help(expect->master)->helper); + if (helper) { + seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); + if (helper->expect_policy[expect->class].name) + seq_printf(s, "/%s", + helper->expect_policy[expect->class].name); + } + return seq_putc(s, '\n'); } diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 023966b569bf..419c5cabb332 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1305,14 +1305,17 @@ static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly; static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { [SIP_EXPECT_SIGNALLING] = { + .name = "signalling", .max_expected = 1, .timeout = 3 * 60, }, [SIP_EXPECT_AUDIO] = { + .name = "audio", .max_expected = 2 * IP_CT_DIR_MAX, .timeout = 3 * 60, }, [SIP_EXPECT_VIDEO] = { + .name = "video", .max_expected = 2 * IP_CT_DIR_MAX, .timeout = 3 * 60, }, -- cgit v1.2.3 From 54101f4f3bed87fa968b57f77f8ff3b09fd88bcf Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:23:12 +0100 Subject: netfilter: nf_conntrack_sip: fix ct_sip_parse_request() REGISTER request parsing When requests are parsed, the "sip:" part of the SIP URI should be skipped. Usually this doesn't matter because address parsing skips forward until after the username part, but in case REGISTER requests it doesn't contain a username and the address can not be parsed. Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_sip.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 419c5cabb332..0ca2f2b5c2fa 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -236,12 +236,13 @@ int ct_sip_parse_request(const struct nf_conn *ct, return 0; /* Find SIP URI */ - limit -= strlen("sip:"); - for (; dptr < limit; dptr++) { + for (; dptr < limit - strlen("sip:"); dptr++) { if (*dptr == '\r' || *dptr == '\n') return -1; - if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) + if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) { + dptr += strlen("sip:"); break; + } } if (!skp_epaddr_len(ct, dptr, limit, &shift)) return 0; -- cgit v1.2.3 From 3b6b9fab42fe98358d70735cf98d43fc18dc79c9 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:23:53 +0100 Subject: netfilter: nf_conntrack_sip: pass data offset to NAT functions When using TCP multiple SIP messages might be present in a single packet. A following patch will parse them by setting the dptr to the beginning of each message. The NAT helper needs to reload the dptr value after mangling the packet however, so it needs to know the offset of the message to the beginning of the packet. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_sip.h | 14 ++-- net/ipv4/netfilter/nf_nat_sip.c | 101 +++++++++++++++-------------- net/netfilter/nf_conntrack_sip.c | 82 ++++++++++++----------- 3 files changed, 105 insertions(+), 92 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 23aa2ec6b7b7..2c6950b8bf7e 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -34,10 +34,10 @@ struct sdp_media_type { struct sip_handler { const char *method; unsigned int len; - int (*request)(struct sk_buff *skb, + int (*request)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq); - int (*response)(struct sk_buff *skb, + int (*response)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code); }; @@ -100,33 +100,39 @@ enum sdp_header_types { }; extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, + unsigned int dataoff, const char **dptr, unsigned int *datalen); extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, + unsigned int dataoff, const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *exp, unsigned int matchoff, unsigned int matchlen); extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, - const char **dptr, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, enum sdp_header_types type, enum sdp_header_types term, const union nf_inet_addr *addr); extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, + unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int matchoff, unsigned int matchlen, u_int16_t port); extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, - const char **dptr, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, const union nf_inet_addr *addr); extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, + unsigned int dataoff, const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *rtp_exp, diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 07d61a57613c..2454ea5abb79 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -29,7 +29,7 @@ MODULE_DESCRIPTION("SIP NAT helper"); MODULE_ALIAS("ip_nat_sip"); -static unsigned int mangle_packet(struct sk_buff *skb, +static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int matchoff, unsigned int matchlen, const char *buffer, unsigned int buflen) @@ -42,12 +42,12 @@ static unsigned int mangle_packet(struct sk_buff *skb, return 0; /* Reload data pointer and adjust datalen value */ - *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); + *dptr = skb->data + dataoff; *datalen += buflen - matchlen; return 1; } -static int map_addr(struct sk_buff *skb, +static int map_addr(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int matchoff, unsigned int matchlen, union nf_inet_addr *addr, __be16 port) @@ -76,11 +76,11 @@ static int map_addr(struct sk_buff *skb, buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport)); - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, buffer, buflen); } -static int map_sip_addr(struct sk_buff *skb, +static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, enum sip_header_types type) { @@ -93,16 +93,17 @@ static int map_sip_addr(struct sk_buff *skb, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, &matchoff, &matchlen, &addr, &port) <= 0) return 1; - return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port); + return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, + &addr, port); } -static unsigned int ip_nat_sip(struct sk_buff *skb, +static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - unsigned int dataoff, matchoff, matchlen; + unsigned int coff, matchoff, matchlen; union nf_inet_addr addr; __be16 port; int request, in_header; @@ -112,7 +113,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, if (ct_sip_parse_request(ct, *dptr, *datalen, &matchoff, &matchlen, &addr, &port) > 0 && - !map_addr(skb, dptr, datalen, matchoff, matchlen, + !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; request = 1; @@ -138,7 +139,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, goto next; } - if (!map_addr(skb, dptr, datalen, matchoff, matchlen, + if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; @@ -153,8 +154,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { buflen = sprintf(buffer, "%pI4", &ct->tuplehash[!dir].tuple.dst.u3.ip); - if (!mangle_packet(skb, dptr, datalen, poff, plen, - buffer, buflen)) + if (!mangle_packet(skb, dataoff, dptr, datalen, + poff, plen, buffer, buflen)) return NF_DROP; } @@ -167,8 +168,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { buflen = sprintf(buffer, "%pI4", &ct->tuplehash[!dir].tuple.src.u3.ip); - if (!mangle_packet(skb, dptr, datalen, poff, plen, - buffer, buflen)) + if (!mangle_packet(skb, dataoff, dptr, datalen, + poff, plen, buffer, buflen)) return NF_DROP; } @@ -181,27 +182,27 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; buflen = sprintf(buffer, "%u", ntohs(p)); - if (!mangle_packet(skb, dptr, datalen, poff, plen, - buffer, buflen)) + if (!mangle_packet(skb, dataoff, dptr, datalen, + poff, plen, buffer, buflen)) return NF_DROP; } } next: /* Translate Contact headers */ - dataoff = 0; + coff = 0; in_header = 0; - while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, + while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, SIP_HDR_CONTACT, &in_header, &matchoff, &matchlen, &addr, &port) > 0) { - if (!map_addr(skb, dptr, datalen, matchoff, matchlen, + if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; } - if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || - !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO)) + if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) || + !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO)) return NF_DROP; return NF_ACCEPT; } @@ -232,7 +233,7 @@ static void ip_nat_sip_expected(struct nf_conn *ct, } } -static unsigned int ip_nat_sip_expect(struct sk_buff *skb, +static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *exp, unsigned int matchoff, @@ -279,8 +280,8 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, if (exp->tuple.dst.u3.ip != exp->saved_ip || exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { buflen = sprintf(buffer, "%pI4:%u", &newip, port); - if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, - buffer, buflen)) + if (!mangle_packet(skb, dataoff, dptr, datalen, + matchoff, matchlen, buffer, buflen)) goto err; } return NF_ACCEPT; @@ -290,7 +291,7 @@ err: return NF_DROP; } -static int mangle_content_len(struct sk_buff *skb, +static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; @@ -312,12 +313,13 @@ static int mangle_content_len(struct sk_buff *skb, return 0; buflen = sprintf(buffer, "%u", c_len); - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, buffer, buflen); } -static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, - unsigned int dataoff, unsigned int *datalen, +static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, enum sdp_header_types type, enum sdp_header_types term, char *buffer, int buflen) @@ -326,16 +328,16 @@ static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, struct nf_conn *ct = nf_ct_get(skb, &ctinfo); unsigned int matchlen, matchoff; - if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, + if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term, &matchoff, &matchlen) <= 0) return -ENOENT; - return mangle_packet(skb, dptr, datalen, matchoff, matchlen, + return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL; } -static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, - unsigned int dataoff, - unsigned int *datalen, +static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, enum sdp_header_types type, enum sdp_header_types term, const union nf_inet_addr *addr) @@ -344,16 +346,15 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, unsigned int buflen; buflen = sprintf(buffer, "%pI4", &addr->ip); - if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, + if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term, buffer, buflen)) return 0; - return mangle_content_len(skb, dptr, datalen); + return mangle_content_len(skb, dataoff, dptr, datalen); } -static unsigned int ip_nat_sdp_port(struct sk_buff *skb, - const char **dptr, - unsigned int *datalen, +static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, unsigned int matchoff, unsigned int matchlen, u_int16_t port) @@ -362,16 +363,16 @@ static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int buflen; buflen = sprintf(buffer, "%u", port); - if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, + if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, buffer, buflen)) return 0; - return mangle_content_len(skb, dptr, datalen); + return mangle_content_len(skb, dataoff, dptr, datalen); } -static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, - unsigned int dataoff, - unsigned int *datalen, +static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, const union nf_inet_addr *addr) { char buffer[sizeof("nnn.nnn.nnn.nnn")]; @@ -379,12 +380,12 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, /* Mangle session description owner and contact addresses */ buflen = sprintf(buffer, "%pI4", &addr->ip); - if (mangle_sdp_packet(skb, dptr, dataoff, datalen, + if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, buffer, buflen)) return 0; - switch (mangle_sdp_packet(skb, dptr, dataoff, datalen, + switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, buffer, buflen)) { case 0: @@ -401,14 +402,13 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, return 0; } - return mangle_content_len(skb, dptr, datalen); + return mangle_content_len(skb, dataoff, dptr, datalen); } /* So, this packet has hit the connection tracking matching code. Mangle it, and change the expectation to match the new version. */ -static unsigned int ip_nat_sdp_media(struct sk_buff *skb, - const char **dptr, - unsigned int *datalen, +static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *rtp_exp, struct nf_conntrack_expect *rtcp_exp, unsigned int mediaoff, @@ -456,7 +456,8 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, /* Update media port. */ if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && - !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port)) + !ip_nat_sdp_port(skb, dataoff, dptr, datalen, + mediaoff, medialen, port)) goto err2; return NF_ACCEPT; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 0ca2f2b5c2fa..0ec37d6a2df7 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -50,12 +50,13 @@ module_param(sip_direct_media, int, 0600); MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " "endpoints only (default 1)"); -unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, +unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sip_hook); unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, + unsigned int dataoff, const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *exp, @@ -63,17 +64,17 @@ unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, unsigned int matchlen) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); -unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, +unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, - unsigned int dataoff, unsigned int *datalen, + unsigned int sdpoff, enum sdp_header_types type, enum sdp_header_types term, const union nf_inet_addr *addr) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); -unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, +unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int matchoff, @@ -82,14 +83,15 @@ unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, - const char **dptr, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int sdpoff, const union nf_inet_addr *addr) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); -unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, +unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, struct nf_conntrack_expect *rtp_exp, @@ -729,7 +731,7 @@ static void flush_expectations(struct nf_conn *ct, bool media) spin_unlock_bh(&nf_conntrack_lock); } -static int set_expected_rtp_rtcp(struct sk_buff *skb, +static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, union nf_inet_addr *daddr, __be16 port, enum sip_expectation_classes class, @@ -806,7 +808,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, if (direct_rtp) { nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); if (nf_nat_sdp_port && - !nf_nat_sdp_port(skb, dptr, datalen, + !nf_nat_sdp_port(skb, dataoff, dptr, datalen, mediaoff, medialen, ntohs(rtp_port))) goto err1; } @@ -828,7 +830,8 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) - ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp, + ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen, + rtp_exp, rtcp_exp, mediaoff, medialen, daddr); else { if (nf_ct_expect_related(rtp_exp) == 0) { @@ -867,7 +870,7 @@ static const struct sdp_media_type *sdp_media_type(const char *dptr, return NULL; } -static int process_sdp(struct sk_buff *skb, +static int process_sdp(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq) { @@ -942,7 +945,7 @@ static int process_sdp(struct sk_buff *skb, else return NF_DROP; - ret = set_expected_rtp_rtcp(skb, dptr, datalen, + ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen, &rtp_addr, htons(port), t->class, mediaoff, medialen); if (ret != NF_ACCEPT) @@ -950,8 +953,9 @@ static int process_sdp(struct sk_buff *skb, /* Update media connection address if present */ if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { - ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen, - c_hdr, SDP_HDR_MEDIA, &rtp_addr); + ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen, + mediaoff, c_hdr, SDP_HDR_MEDIA, + &rtp_addr); if (ret != NF_ACCEPT) return ret; } @@ -961,14 +965,15 @@ static int process_sdp(struct sk_buff *skb, /* Update session connection and owner addresses */ nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) - ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr); + ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff, + &rtp_addr); if (ret == NF_ACCEPT && i > 0) help->help.ct_sip_info.invite_cseq = cseq; return ret; } -static int process_invite_response(struct sk_buff *skb, +static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { @@ -978,13 +983,13 @@ static int process_invite_response(struct sk_buff *skb, if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) - return process_sdp(skb, dptr, datalen, cseq); + return process_sdp(skb, dataoff, dptr, datalen, cseq); else if (help->help.ct_sip_info.invite_cseq == cseq) flush_expectations(ct, true); return NF_ACCEPT; } -static int process_update_response(struct sk_buff *skb, +static int process_update_response(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { @@ -994,13 +999,13 @@ static int process_update_response(struct sk_buff *skb, if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) - return process_sdp(skb, dptr, datalen, cseq); + return process_sdp(skb, dataoff, dptr, datalen, cseq); else if (help->help.ct_sip_info.invite_cseq == cseq) flush_expectations(ct, true); return NF_ACCEPT; } -static int process_prack_response(struct sk_buff *skb, +static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { @@ -1010,13 +1015,13 @@ static int process_prack_response(struct sk_buff *skb, if ((code >= 100 && code <= 199) || (code >= 200 && code <= 299)) - return process_sdp(skb, dptr, datalen, cseq); + return process_sdp(skb, dataoff, dptr, datalen, cseq); else if (help->help.ct_sip_info.invite_cseq == cseq) flush_expectations(ct, true); return NF_ACCEPT; } -static int process_bye_request(struct sk_buff *skb, +static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq) { @@ -1031,7 +1036,7 @@ static int process_bye_request(struct sk_buff *skb, * signalling connections. The expectation is marked inactive and is activated * when receiving a response indicating success from the registrar. */ -static int process_register_request(struct sk_buff *skb, +static int process_register_request(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq) { @@ -1101,7 +1106,7 @@ static int process_register_request(struct sk_buff *skb, nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) - ret = nf_nat_sip_expect(skb, dptr, datalen, exp, + ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp, matchoff, matchlen); else { if (nf_ct_expect_related(exp) != 0) @@ -1117,7 +1122,7 @@ store_cseq: return ret; } -static int process_register_response(struct sk_buff *skb, +static int process_register_response(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq, unsigned int code) { @@ -1127,7 +1132,7 @@ static int process_register_response(struct sk_buff *skb, enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); union nf_inet_addr addr; __be16 port; - unsigned int matchoff, matchlen, dataoff = 0; + unsigned int matchoff, matchlen, coff = 0; unsigned int expires = 0; int in_contact = 0, ret; @@ -1154,7 +1159,7 @@ static int process_register_response(struct sk_buff *skb, while (1) { unsigned int c_expires = expires; - ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, + ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, SIP_HDR_CONTACT, &in_contact, &matchoff, &matchlen, &addr, &port); @@ -1193,13 +1198,13 @@ static const struct sip_handler sip_handlers[] = { SIP_HANDLER("REGISTER", process_register_request, process_register_response), }; -static int process_sip_response(struct sk_buff *skb, +static int process_sip_response(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); - unsigned int matchoff, matchlen; - unsigned int code, cseq, dataoff, i; + unsigned int matchoff, matchlen, matchend; + unsigned int code, cseq, i; if (*datalen < strlen("SIP/2.0 200")) return NF_ACCEPT; @@ -1213,7 +1218,7 @@ static int process_sip_response(struct sk_buff *skb, cseq = simple_strtoul(*dptr + matchoff, NULL, 10); if (!cseq) return NF_DROP; - dataoff = matchoff + matchlen + 1; + matchend = matchoff + matchlen + 1; for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { const struct sip_handler *handler; @@ -1221,15 +1226,16 @@ static int process_sip_response(struct sk_buff *skb, handler = &sip_handlers[i]; if (handler->response == NULL) continue; - if (*datalen < dataoff + handler->len || - strnicmp(*dptr + dataoff, handler->method, handler->len)) + if (*datalen < matchend + handler->len || + strnicmp(*dptr + matchend, handler->method, handler->len)) continue; - return handler->response(skb, dptr, datalen, cseq, code); + return handler->response(skb, dataoff, dptr, datalen, + cseq, code); } return NF_ACCEPT; } -static int process_sip_request(struct sk_buff *skb, +static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen) { enum ip_conntrack_info ctinfo; @@ -1254,7 +1260,7 @@ static int process_sip_request(struct sk_buff *skb, if (!cseq) return NF_DROP; - return handler->request(skb, dptr, datalen, cseq); + return handler->request(skb, dataoff, dptr, datalen, cseq); } return NF_ACCEPT; } @@ -1288,13 +1294,13 @@ static int sip_help(struct sk_buff *skb, return NF_ACCEPT; if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) - ret = process_sip_request(skb, &dptr, &datalen); + ret = process_sip_request(skb, dataoff, &dptr, &datalen); else - ret = process_sip_response(skb, &dptr, &datalen); + ret = process_sip_response(skb, dataoff, &dptr, &datalen); if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { nf_nat_sip = rcu_dereference(nf_nat_sip_hook); - if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen)) + if (nf_nat_sip && !nf_nat_sip(skb, dataoff, &dptr, &datalen)) ret = NF_DROP; } -- cgit v1.2.3 From f5b321bd37fbec9188feb1f721ab46a5ac0b35da Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:26:19 +0100 Subject: netfilter: nf_conntrack_sip: add TCP support Add TCP support, which is mandated by RFC3261 for all SIP elements. SIP over TCP is similar to UDP, except that messages are delimited by Content-Length: headers and multiple messages may appear in one packet. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_sip.h | 3 +- net/ipv4/netfilter/nf_nat_sip.c | 2 +- net/netfilter/nf_conntrack_sip.c | 205 +++++++++++++++++++++++++---- 3 files changed, 179 insertions(+), 31 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 2c6950b8bf7e..fa9bb8981450 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -84,7 +84,8 @@ enum sip_header_types { SIP_HDR_FROM, SIP_HDR_TO, SIP_HDR_CONTACT, - SIP_HDR_VIA, + SIP_HDR_VIA_UDP, + SIP_HDR_VIA_TCP, SIP_HDR_EXPIRES, SIP_HDR_CONTENT_LENGTH, }; diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 2454ea5abb79..b232e4040dc6 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -122,7 +122,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, /* Translate topmost Via header and parameters */ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, - SIP_HDR_VIA, NULL, &matchoff, &matchlen, + SIP_HDR_VIA_UDP, NULL, &matchoff, &matchlen, &addr, &port) > 0) { unsigned int matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 0ec37d6a2df7..1cc75c5a822b 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -287,7 +288,8 @@ static const struct sip_header ct_sip_hdrs[] = { [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len), [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len), [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len), - [SIP_HDR_VIA] = SIP_HDR("Via", "v", "UDP ", epaddr_len), + [SIP_HDR_VIA_UDP] = SIP_HDR("Via", "v", "UDP ", epaddr_len), + [SIP_HDR_VIA_TCP] = SIP_HDR("Via", "v", "TCP ", epaddr_len), [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len), [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len), }; @@ -519,6 +521,33 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, } EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri); +static int ct_sip_parse_param(const struct nf_conn *ct, const char *dptr, + unsigned int dataoff, unsigned int datalen, + const char *name, + unsigned int *matchoff, unsigned int *matchlen) +{ + const char *limit = dptr + datalen; + const char *start; + const char *end; + + limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(",")); + if (!limit) + limit = dptr + datalen; + + start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name)); + if (!start) + return 0; + start += strlen(name); + + end = ct_sip_header_search(start, limit, ";", strlen(";")); + if (!end) + end = limit; + + *matchoff = start - dptr; + *matchlen = end - start; + return 1; +} + /* Parse address from header parameter and return address, offset and length */ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, unsigned int dataoff, unsigned int datalen, @@ -577,6 +606,29 @@ int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, } EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param); +static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, + unsigned int dataoff, unsigned int datalen, + u8 *proto) +{ + unsigned int matchoff, matchlen; + + if (ct_sip_parse_param(ct, dptr, dataoff, datalen, "transport=", + &matchoff, &matchlen)) { + if (!strnicmp(dptr + matchoff, "TCP", strlen("TCP"))) + *proto = IPPROTO_TCP; + else if (!strnicmp(dptr + matchoff, "UDP", strlen("UDP"))) + *proto = IPPROTO_UDP; + else + return 0; + + if (*proto != nf_ct_protonum(ct)) + return 0; + } else + *proto = nf_ct_protonum(ct); + + return 1; +} + /* SDP header parsing: a SDP session description contains an ordered set of * headers, starting with a section containing general session parameters, * optionally followed by multiple media descriptions. @@ -685,7 +737,7 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, static int refresh_signalling_expectation(struct nf_conn *ct, union nf_inet_addr *addr, - __be16 port, + u8 proto, __be16 port, unsigned int expires) { struct nf_conn_help *help = nfct_help(ct); @@ -697,6 +749,7 @@ static int refresh_signalling_expectation(struct nf_conn *ct, hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { if (exp->class != SIP_EXPECT_SIGNALLING || !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) || + exp->tuple.dst.protonum != proto || exp->tuple.dst.u.udp.port != port) continue; if (!del_timer(&exp->timeout)) @@ -1048,6 +1101,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, struct nf_conntrack_expect *exp; union nf_inet_addr *saddr, daddr; __be16 port; + u8 proto; unsigned int expires = 0; int ret; typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect; @@ -1080,6 +1134,10 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr)) return NF_ACCEPT; + if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, *datalen, + &proto) == 0) + return NF_ACCEPT; + if (ct_sip_parse_numerical_param(ct, *dptr, matchoff + matchlen, *datalen, "expires=", NULL, NULL, &expires) < 0) @@ -1099,7 +1157,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, saddr = &ct->tuplehash[!dir].tuple.src.u3; nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct), - saddr, &daddr, IPPROTO_UDP, NULL, &port); + saddr, &daddr, proto, NULL, &port); exp->timeout.expires = sip_timeout * HZ; exp->helper = nfct_help(ct)->helper; exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE; @@ -1132,6 +1190,7 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); union nf_inet_addr addr; __be16 port; + u8 proto; unsigned int matchoff, matchlen, coff = 0; unsigned int expires = 0; int in_contact = 0, ret; @@ -1172,6 +1231,10 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff, if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr)) continue; + if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, + *datalen, &proto) == 0) + continue; + ret = ct_sip_parse_numerical_param(ct, *dptr, matchoff + matchlen, *datalen, "expires=", @@ -1180,7 +1243,8 @@ static int process_register_response(struct sk_buff *skb, unsigned int dataoff, return NF_DROP; if (c_expires == 0) break; - if (refresh_signalling_expectation(ct, &addr, port, c_expires)) + if (refresh_signalling_expectation(ct, &addr, proto, port, + c_expires)) return NF_ACCEPT; } @@ -1265,50 +1329,123 @@ static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, return NF_ACCEPT; } -static int sip_help(struct sk_buff *skb, - unsigned int protoff, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo) +static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, + unsigned int dataoff, const char **dptr, + unsigned int *datalen) +{ + typeof(nf_nat_sip_hook) nf_nat_sip; + int ret; + + if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) + ret = process_sip_request(skb, dataoff, dptr, datalen); + else + ret = process_sip_response(skb, dataoff, dptr, datalen); + + if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { + nf_nat_sip = rcu_dereference(nf_nat_sip_hook); + if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen)) + ret = NF_DROP; + } + + return ret; +} + +static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) { + struct tcphdr *th, _tcph; unsigned int dataoff, datalen; - const char *dptr; + unsigned int matchoff, matchlen, clen; + unsigned int msglen, origlen; + const char *dptr, *end; + s16 diff, tdiff = 0; int ret; - typeof(nf_nat_sip_hook) nf_nat_sip; + + if (ctinfo != IP_CT_ESTABLISHED && + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) + return NF_ACCEPT; /* No Data ? */ - dataoff = protoff + sizeof(struct udphdr); + th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); + if (th == NULL) + return NF_ACCEPT; + dataoff = protoff + th->doff * 4; if (dataoff >= skb->len) return NF_ACCEPT; nf_ct_refresh(ct, skb, sip_timeout * HZ); - if (!skb_is_nonlinear(skb)) - dptr = skb->data + dataoff; - else { + if (skb_is_nonlinear(skb)) { pr_debug("Copy of skbuff not supported yet.\n"); return NF_ACCEPT; } + dptr = skb->data + dataoff; datalen = skb->len - dataoff; if (datalen < strlen("SIP/2.0 200")) return NF_ACCEPT; - if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) - ret = process_sip_request(skb, dataoff, &dptr, &datalen); - else - ret = process_sip_response(skb, dataoff, &dptr, &datalen); + while (1) { + if (ct_sip_get_header(ct, dptr, 0, datalen, + SIP_HDR_CONTENT_LENGTH, + &matchoff, &matchlen) <= 0) + break; - if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { - nf_nat_sip = rcu_dereference(nf_nat_sip_hook); - if (nf_nat_sip && !nf_nat_sip(skb, dataoff, &dptr, &datalen)) - ret = NF_DROP; + clen = simple_strtoul(dptr + matchoff, (char **)&end, 10); + if (dptr + matchoff == end) + break; + + if (end + strlen("\r\n\r\n") > dptr + datalen) + break; + if (end[0] != '\r' || end[1] != '\n' || + end[2] != '\r' || end[3] != '\n') + break; + end += strlen("\r\n\r\n") + clen; + + msglen = origlen = end - dptr; + + ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen); + if (ret != NF_ACCEPT) + break; + diff = msglen - origlen; + tdiff += diff; + + dataoff += msglen; + dptr += msglen; + datalen = datalen + diff - msglen; } return ret; } -static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; -static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly; +static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, + struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + unsigned int dataoff, datalen; + const char *dptr; + + /* No Data ? */ + dataoff = protoff + sizeof(struct udphdr); + if (dataoff >= skb->len) + return NF_ACCEPT; + + nf_ct_refresh(ct, skb, sip_timeout * HZ); + + if (skb_is_nonlinear(skb)) { + pr_debug("Copy of skbuff not supported yet.\n"); + return NF_ACCEPT; + } + + dptr = skb->data + dataoff; + datalen = skb->len - dataoff; + if (datalen < strlen("SIP/2.0 200")) + return NF_ACCEPT; + + return process_sip_msg(skb, ct, dataoff, &dptr, &datalen); +} + +static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; +static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { [SIP_EXPECT_SIGNALLING] = { @@ -1333,7 +1470,7 @@ static void nf_conntrack_sip_fini(void) int i, j; for (i = 0; i < ports_c; i++) { - for (j = 0; j < 2; j++) { + for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { if (sip[i][j].me == NULL) continue; nf_conntrack_helper_unregister(&sip[i][j]); @@ -1353,14 +1490,24 @@ static int __init nf_conntrack_sip_init(void) memset(&sip[i], 0, sizeof(sip[i])); sip[i][0].tuple.src.l3num = AF_INET; - sip[i][1].tuple.src.l3num = AF_INET6; - for (j = 0; j < 2; j++) { - sip[i][j].tuple.dst.protonum = IPPROTO_UDP; + sip[i][0].tuple.dst.protonum = IPPROTO_UDP; + sip[i][0].help = sip_help_udp; + sip[i][1].tuple.src.l3num = AF_INET; + sip[i][1].tuple.dst.protonum = IPPROTO_TCP; + sip[i][1].help = sip_help_tcp; + + sip[i][2].tuple.src.l3num = AF_INET6; + sip[i][2].tuple.dst.protonum = IPPROTO_UDP; + sip[i][2].help = sip_help_udp; + sip[i][3].tuple.src.l3num = AF_INET6; + sip[i][3].tuple.dst.protonum = IPPROTO_TCP; + sip[i][3].help = sip_help_tcp; + + for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { sip[i][j].tuple.src.u.udp.port = htons(ports[i]); sip[i][j].expect_policy = sip_exp_policy; sip[i][j].expect_class_max = SIP_EXPECT_MAX; sip[i][j].me = THIS_MODULE; - sip[i][j].help = sip_help; tmpname = &sip_names[i][j][0]; if (ports[i] == SIP_PORT) -- cgit v1.2.3 From 010c0b9f34a4c567b431f8b49a58b7332ed42e47 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:27:09 +0100 Subject: netfilter: nf_nat: support mangling a single TCP packet multiple times nf_nat_mangle_tcp_packet() can currently only handle a single mangling per window because it only maintains two sequence adjustment positions: the one before the last adjustment and the one after. This patch makes sequence number adjustment tracking in nf_nat_mangle_tcp_packet() optional and allows a helper to manually update the offsets after the packet has been fully handled. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_nat_helper.h | 32 +++++++++++++++++++++------- net/ipv4/netfilter/nf_nat_helper.c | 39 +++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index 4222220920a5..02bb6c29dc3d 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h @@ -7,13 +7,27 @@ struct sk_buff; /* These return true or false. */ -extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int match_offset, - unsigned int match_len, - const char *rep_buffer, - unsigned int rep_len); +extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len, bool adjust); + +static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len) +{ + return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, + match_offset, match_len, + rep_buffer, rep_len, true); +} + extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, @@ -21,6 +35,10 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, unsigned int match_len, const char *rep_buffer, unsigned int rep_len); + +extern void nf_nat_set_seq_adjust(struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + __be32 seq, s16 off); extern int nf_nat_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo); diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 7f10a6be0191..4b6af4bb1f50 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c @@ -141,6 +141,17 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra) return 1; } +void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, + __be32 seq, s16 off) +{ + if (!off) + return; + set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); + adjust_tcp_sequence(ntohl(seq), off, ct, ctinfo); + nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); +} +EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); + /* Generic function for mangling variable-length address changes inside * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX * command in FTP). @@ -149,14 +160,13 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra) * skb enlargement, ... * * */ -int -nf_nat_mangle_tcp_packet(struct sk_buff *skb, - struct nf_conn *ct, - enum ip_conntrack_info ctinfo, - unsigned int match_offset, - unsigned int match_len, - const char *rep_buffer, - unsigned int rep_len) +int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, + struct nf_conn *ct, + enum ip_conntrack_info ctinfo, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len, bool adjust) { struct rtable *rt = skb_rtable(skb); struct iphdr *iph; @@ -202,16 +212,13 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, inet_proto_csum_replace2(&tcph->check, skb, htons(oldlen), htons(datalen), 1); - if (rep_len != match_len) { - set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); - adjust_tcp_sequence(ntohl(tcph->seq), - (int)rep_len - (int)match_len, - ct, ctinfo); - nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); - } + if (adjust && rep_len != match_len) + nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, + (int)rep_len - (int)match_len); + return 1; } -EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); +EXPORT_SYMBOL(__nf_nat_mangle_tcp_packet); /* Generic function for mangling variable-length address changes inside * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX -- cgit v1.2.3 From 48f8ac26537c1b7b1a2422f5232f45d06c945348 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:29:38 +0100 Subject: netfilter: nf_nat_sip: add TCP support Add support for mangling TCP SIP packets. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_sip.h | 1 + net/ipv4/netfilter/nf_nat_sip.c | 53 ++++++++++++++++++++++++++---- net/netfilter/nf_conntrack_sip.c | 10 ++++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index fa9bb8981450..cd84d6f44d11 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -104,6 +104,7 @@ extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen); +extern void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off); extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index b232e4040dc6..11b538deaaec 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -1,4 +1,4 @@ -/* SIP extension for UDP NAT alteration. +/* SIP extension for NAT alteration. * * (C) 2005 by Christian Hentschel * based on RR's ip_nat_ftp.c and other modules. @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -36,10 +37,27 @@ static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); - - if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen, - buffer, buflen)) - return 0; + struct tcphdr *th; + unsigned int baseoff; + + if (nf_ct_protonum(ct) == IPPROTO_TCP) { + th = (struct tcphdr *)(skb->data + ip_hdrlen(skb)); + baseoff = ip_hdrlen(skb) + th->doff * 4; + matchoff += dataoff - baseoff; + + if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo, + matchoff, matchlen, + buffer, buflen, false)) + return 0; + } else { + baseoff = ip_hdrlen(skb) + sizeof(struct udphdr); + matchoff += dataoff - baseoff; + + if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, + matchoff, matchlen, + buffer, buflen)) + return 0; + } /* Reload data pointer and adjust datalen value */ *dptr = skb->data + dataoff; @@ -104,6 +122,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, struct nf_conn *ct = nf_ct_get(skb, &ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); unsigned int coff, matchoff, matchlen; + enum sip_header_types hdr; union nf_inet_addr addr; __be16 port; int request, in_header; @@ -120,9 +139,14 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, } else request = 0; + if (nf_ct_protonum(ct) == IPPROTO_TCP) + hdr = SIP_HDR_VIA_TCP; + else + hdr = SIP_HDR_VIA_UDP; + /* Translate topmost Via header and parameters */ if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, - SIP_HDR_VIA_UDP, NULL, &matchoff, &matchlen, + hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { unsigned int matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; @@ -204,9 +228,23 @@ next: if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) || !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO)) return NF_DROP; + return NF_ACCEPT; } +static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off) +{ + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + const struct tcphdr *th; + + if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0) + return; + + th = (struct tcphdr *)(skb->data + ip_hdrlen(skb)); + nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off); +} + /* Handles expected signalling connections and media streams */ static void ip_nat_sip_expected(struct nf_conn *ct, struct nf_conntrack_expect *exp) @@ -472,6 +510,7 @@ err1: static void __exit nf_nat_sip_fini(void) { rcu_assign_pointer(nf_nat_sip_hook, NULL); + rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, NULL); rcu_assign_pointer(nf_nat_sip_expect_hook, NULL); rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL); rcu_assign_pointer(nf_nat_sdp_port_hook, NULL); @@ -483,12 +522,14 @@ static void __exit nf_nat_sip_fini(void) static int __init nf_nat_sip_init(void) { BUG_ON(nf_nat_sip_hook != NULL); + BUG_ON(nf_nat_sip_seq_adjust_hook != NULL); BUG_ON(nf_nat_sip_expect_hook != NULL); BUG_ON(nf_nat_sdp_addr_hook != NULL); BUG_ON(nf_nat_sdp_port_hook != NULL); BUG_ON(nf_nat_sdp_session_hook != NULL); BUG_ON(nf_nat_sdp_media_hook != NULL); rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); + rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust); rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect); rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr); rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port); diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 1cc75c5a822b..3bb3aaff76e9 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -56,6 +56,9 @@ unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, unsigned int *datalen) __read_mostly; EXPORT_SYMBOL_GPL(nf_nat_sip_hook); +void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly; +EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook); + unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, unsigned int dataoff, const char **dptr, @@ -1360,6 +1363,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, const char *dptr, *end; s16 diff, tdiff = 0; int ret; + typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) @@ -1415,6 +1419,12 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, datalen = datalen + diff - msglen; } + if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { + nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook); + if (nf_nat_sip_seq_adjust) + nf_nat_sip_seq_adjust(skb, tdiff); + } + return ret; } -- cgit v1.2.3 From 9d288dffe3a276e1f06ba556845c456d696c5a4f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 11 Feb 2010 12:30:21 +0100 Subject: netfilter: nf_conntrack_sip: add T.38 FAX support Signed-off-by: Patrick McHardy --- include/linux/netfilter/nf_conntrack_sip.h | 1 + include/net/netfilter/nf_conntrack.h | 2 +- net/netfilter/nf_conntrack_sip.c | 28 +++++++++++++++++++++++----- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index cd84d6f44d11..ff8cfbcf3b81 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -14,6 +14,7 @@ enum sip_expectation_classes { SIP_EXPECT_SIGNALLING, SIP_EXPECT_AUDIO, SIP_EXPECT_VIDEO, + SIP_EXPECT_IMAGE, __SIP_EXPECT_MAX }; #define SIP_EXPECT_MAX (__SIP_EXPECT_MAX - 1) diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 5043d61c99a7..5b7d8835523f 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -70,7 +70,7 @@ union nf_conntrack_help { struct nf_conntrack_helper; /* Must be kept in sync with the classes defined by helpers */ -#define NF_CT_MAX_EXPECT_CLASSES 3 +#define NF_CT_MAX_EXPECT_CLASSES 4 /* nf_conn feature for connections that have a helper */ struct nf_conn_help { diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 3bb3aaff76e9..fbe8ff5a420a 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -907,6 +907,7 @@ err1: static const struct sdp_media_type sdp_media_types[] = { SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO), SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO), + SDP_MEDIA_TYPE("image ", SIP_EXPECT_IMAGE), }; static const struct sdp_media_type *sdp_media_type(const char *dptr, @@ -932,7 +933,6 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, { enum ip_conntrack_info ctinfo; struct nf_conn *ct = nf_ct_get(skb, &ctinfo); - struct nf_conn_help *help = nfct_help(ct); unsigned int matchoff, matchlen; unsigned int mediaoff, medialen; unsigned int sdpoff; @@ -1024,9 +1024,6 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff, &rtp_addr); - if (ret == NF_ACCEPT && i > 0) - help->help.ct_sip_info.invite_cseq = cseq; - return ret; } static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, @@ -1077,6 +1074,22 @@ static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, return NF_ACCEPT; } +static int process_invite_request(struct sk_buff *skb, unsigned int dataoff, + const char **dptr, unsigned int *datalen, + unsigned int cseq) +{ + enum ip_conntrack_info ctinfo; + struct nf_conn *ct = nf_ct_get(skb, &ctinfo); + struct nf_conn_help *help = nfct_help(ct); + unsigned int ret; + + flush_expectations(ct, true); + ret = process_sdp(skb, dataoff, dptr, datalen, cseq); + if (ret == NF_ACCEPT) + help->help.ct_sip_info.invite_cseq = cseq; + return ret; +} + static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, const char **dptr, unsigned int *datalen, unsigned int cseq) @@ -1257,7 +1270,7 @@ flush: } static const struct sip_handler sip_handlers[] = { - SIP_HANDLER("INVITE", process_sdp, process_invite_response), + SIP_HANDLER("INVITE", process_invite_request, process_invite_response), SIP_HANDLER("UPDATE", process_sdp, process_update_response), SIP_HANDLER("ACK", process_sdp, NULL), SIP_HANDLER("PRACK", process_sdp, process_prack_response), @@ -1473,6 +1486,11 @@ static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1 .max_expected = 2 * IP_CT_DIR_MAX, .timeout = 3 * 60, }, + [SIP_EXPECT_IMAGE] = { + .name = "image", + .max_expected = IP_CT_DIR_MAX, + .timeout = 3 * 60, + }, }; static void nf_conntrack_sip_fini(void) -- cgit v1.2.3 From b2907e501945d5d13326a6a7441c13e41cd0e799 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 11 Feb 2010 18:41:35 +0100 Subject: netfilter: xtables: fix mangle tables In POST_ROUTING hook, calling dev_net(in) is going to oops. Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/iptable_mangle.c | 4 +++- net/ipv6/netfilter/ip6table_mangle.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 58d7097baa3d..c8333305d631 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -87,7 +87,9 @@ iptable_mangle_hook(unsigned int hook, { if (hook == NF_INET_LOCAL_OUT) return ipt_local_hook(hook, skb, in, out, okfn); - + if (hook == NF_INET_POST_ROUTING) + return ipt_do_table(skb, hook, in, out, + dev_net(out)->ipv4.iptable_mangle); /* PREROUTING/INPUT/FORWARD: */ return ipt_do_table(skb, hook, in, out, dev_net(in)->ipv4.iptable_mangle); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index dc803b7e8e54..b6216dede52c 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -81,7 +81,9 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, { if (hook == NF_INET_LOCAL_OUT) return ip6t_local_out_hook(hook, skb, out, okfn); - + if (hook == NF_INET_POST_ROUTING) + return ip6t_do_table(skb, hook, in, out, + dev_net(out)->ipv6.ip6table_mangle); /* INPUT/FORWARD */ return ip6t_do_table(skb, hook, in, out, dev_net(in)->ipv6.ip6table_mangle); -- cgit v1.2.3 From dff010ac8e57e43669518a14c0e945dfeb80c2a7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 2 Feb 2010 16:58:34 -0800 Subject: iwlwifi: clear all tx queues when firmware ready Reset and clear all the tx queues when finished downloading runtime uCode and ready to go into operation mode. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-5000.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index aebe8c51d3e1..e4794885d079 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -581,6 +581,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + /* reset to 0 to enable all the queue first */ + priv->txq_ctx_active_msk = 0; /* Map each Tx/cmd queue to its corresponding fifo */ for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { int ac = default_queue_to_tx_fifo[i]; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f3d662c8cbcf..a7fa1ad7e6e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -648,6 +648,8 @@ int iwl5000_alive_notify(struct iwl_priv *priv) iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + /* reset to 0 to enable all the queue first */ + priv->txq_ctx_active_msk = 0; /* map qos queues to fifos one-to-one */ for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { int ac = iwl5000_default_queue_to_tx_fifo[i]; -- cgit v1.2.3 From a93e7973d0983d22fcbe5f691244736211639fe7 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 3 Feb 2010 11:47:19 -0800 Subject: iwlwifi: multiple force reset mode Provide the function to perform different type of uCode reset/reload operation. When uCode detect error and can not fix itself, this iwl_force_reset() function allow driver to perform the necessary reset/reload functions and help to bring uCode back to normal operation state. Currently only 2 type of force reset are available: - reset radio - reload firmware Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.c | 44 +++++++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 9 ++++++- drivers/net/wireless/iwlwifi/iwl-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 10 -------- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d390eef2efe5..500ced452098 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) } EXPORT_SYMBOL(iwl_dump_fh); -void iwl_force_rf_reset(struct iwl_priv *priv) +static void iwl_force_rf_reset(struct iwl_priv *priv) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -3356,7 +3356,47 @@ void iwl_force_rf_reset(struct iwl_priv *priv) iwl_internal_short_hw_scan(priv); return; } -EXPORT_SYMBOL(iwl_force_rf_reset); + +#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3) + +int iwl_force_reset(struct iwl_priv *priv, int mode) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return -EINVAL; + + if (priv->last_force_reset_jiffies && + time_after(priv->last_force_reset_jiffies + + IWL_DELAY_NEXT_FORCE_RESET, jiffies)) { + IWL_DEBUG_INFO(priv, "force reset rejected\n"); + return -EAGAIN; + } + + IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); + + switch (mode) { + case IWL_RF_RESET: + iwl_force_rf_reset(priv); + break; + case IWL_FW_RESET: + IWL_ERR(priv, "On demand firmware reload\n"); + /* Set the FW error flag -- cleared on iwl_down */ + set_bit(STATUS_FW_ERROR, &priv->status); + wake_up_interruptible(&priv->wait_command_queue); + /* + * Keep the restart process from trying to send host + * commands by clearing the INIT status bit + */ + clear_bit(STATUS_READY, &priv->status); + queue_work(priv->workqueue, &priv->restart); + break; + default: + IWL_DEBUG_INFO(priv, "invalid reset request.\n"); + return -EINVAL; + } + priv->last_force_reset_jiffies = jiffies; + + return 0; +} #ifdef CONFIG_PM diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 8f0c564e68b0..df558796fbe6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -501,7 +501,7 @@ int iwl_scan_cancel(struct iwl_priv *priv); int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); int iwl_internal_short_hw_scan(struct iwl_priv *priv); -void iwl_force_rf_reset(struct iwl_priv *priv); +int iwl_force_reset(struct iwl_priv *priv, int mode); u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, const u8 *ie, int ie_len, int left); void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 55dc5a866542..9f1d302e3a34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1035,6 +1035,11 @@ struct iwl_event_log { #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) +enum iwl_reset { + IWL_RF_RESET = 0, + IWL_FW_RESET, +}; + struct iwl_priv { /* ieee device used by generic ieee processing code */ @@ -1066,6 +1071,9 @@ struct iwl_priv { /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; + /* force reset */ + unsigned long last_force_reset_jiffies; + /* we allocate array of iwl4965_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ struct iwl_channel_info *channel_info; /* channel info array */ @@ -1087,7 +1095,6 @@ struct iwl_priv { unsigned long scan_start; unsigned long scan_pass_start; unsigned long scan_start_tsf; - unsigned long last_internal_scan_jiffies; void *scan; int scan_bands; struct cfg80211_scan_request *scan_request; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 5df66382d922..909d9c9b9ad8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -689,7 +689,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, * Reset the RF radio due to the high plcp * error rate */ - iwl_force_rf_reset(priv); + iwl_force_reset(priv, IWL_RF_RESET); } } diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index f786a407638f..501477464e07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, if (!priv->is_internal_short_scan) priv->next_scan_jiffies = 0; - else - priv->last_internal_scan_jiffies = jiffies; IWL_DEBUG_INFO(priv, "Setting scan to off\n"); @@ -551,8 +549,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); * internal short scan, this function should only been called while associated. * It will reset and tune the radio to prevent possible RF related problem */ -#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1) - int iwl_internal_short_hw_scan(struct iwl_priv *priv) { int ret = 0; @@ -572,12 +568,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) ret = -EAGAIN; goto out; } - if (priv->last_internal_scan_jiffies && - time_after(priv->last_internal_scan_jiffies + - IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) { - IWL_DEBUG_SCAN(priv, "internal scan rejected\n"); - goto out; - } priv->scan_bands = 0; if (priv->band == IEEE80211_BAND_5GHZ) -- cgit v1.2.3 From 04cafd7fa74d5f70efc93bef36f118177057ff74 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 3 Feb 2010 11:47:20 -0800 Subject: iwlwifi: add debug function to reset/reload radio/firmware Adding function to force reset radio or reload firmware from debugfs. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d134301b553c..78298be0bdb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2223,6 +2223,32 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_force_reset_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + char buf[8]; + int buf_size; + int reset, ret; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &reset) != 1) + return -EINVAL; + switch (reset) { + case IWL_RF_RESET: + case IWL_FW_RESET: + ret = iwl_force_reset(priv, reset); + break; + default: + return -EINVAL; + } + return ret ? ret : count; +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -2243,6 +2269,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_WRITE_FILE_OPS(internal_scan); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); +DEBUGFS_WRITE_FILE_OPS(force_reset); /* * Create the debugfs files and directories @@ -2296,6 +2323,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); -- cgit v1.2.3 From 45d427001b5eec03cecaacddb53c73af46bb263e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 3 Feb 2010 12:24:44 -0800 Subject: iwlwifi: check for aggregation frame and queue Error checking for aggregation frames should go into aggregation queue, if aggregation queue not available, use legacy queue instead. Also make sure the aggregation queue is available to activate, if driver and mac80211 is out-of-sync, try to disable the queue and sync-up with mac80211. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 15 ++++++++++++++- drivers/net/wireless/iwlwifi/iwl-tx.c | 18 ++++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 6aebcedaca8d..8bf7c20b9d39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl_lq_sta *lq_data, u8 tid, struct ieee80211_sta *sta) { + int ret; + if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); - ieee80211_start_tx_ba_session(sta, tid); + ret = ieee80211_start_tx_ba_session(sta, tid); + if (ret == -EAGAIN) { + /* + * driver and mac80211 is out of sync + * this might be cause by reloading firmware + * stop the tx ba session here + */ + IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", + tid); + ret = ieee80211_stop_tx_ba_session(sta, tid, + WLAN_BACK_INITIATOR); + } } } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index d365d13e3291..3788a3d4ddc2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -806,8 +806,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr->seq_ctrl |= cpu_to_le16(seq_number); seq_number += 0x10; /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) + if (info->flags & IEEE80211_TX_CTL_AMPDU && + priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; + } } txq = &priv->txq[txq_id]; @@ -1328,7 +1330,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) { int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl_tid_data *tid_data; - int ret, write_ptr, read_ptr; + int write_ptr, read_ptr; unsigned long flags; if (!ra) { @@ -1380,13 +1382,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; spin_lock_irqsave(&priv->lock, flags); - ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, + /* + * the only reason this call can fail is queue number out of range, + * which can happen if uCode is reloaded and all the station + * information are lost. if it is outside the range, there is no need + * to deactivate the uCode queue, just return "success" to allow + * mac80211 to clean up it own data. + */ + priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); - if (ret) - return ret; - ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); return 0; -- cgit v1.2.3 From a24dd27c47fcb31ba5c906b66e5cbc28bfa3fa5e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 3 Feb 2010 12:51:07 -0800 Subject: iwlwifi: remove unused op-code in PHY Calibration command Number of calibration op-code are not used by driver, remove those from iwl-commands.h Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c2f31eb26bef..ab3c77b92cc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3470,11 +3470,7 @@ enum { IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, IWL_PHY_CALIBRATE_DC_CMD = 8, IWL_PHY_CALIBRATE_LO_CMD = 9, - IWL_PHY_CALIBRATE_RX_BB_CMD = 10, IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, - IWL_PHY_CALIBRATE_RX_IQ_CMD = 12, - IWL_PHY_CALIBRATION_NOISE_CMD = 13, - IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, -- cgit v1.2.3 From 7bfedc59ee350727b115bbc79780c69b114f162d Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Wed, 3 Feb 2010 13:47:56 -0800 Subject: iwlwifi: cleanup return values Cleanup return values and removes unnecessary code. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-rx.c | 11 +++-------- drivers/net/wireless/iwlwifi/iwl-tx.c | 21 +++++++-------------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++------------ 4 files changed, 17 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index df558796fbe6..530fae8cf16d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -414,13 +414,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_cmd_queue_free(struct iwl_priv *priv); int iwl_rx_queue_alloc(struct iwl_priv *priv); void iwl_rx_handle(struct iwl_priv *priv); -int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); void iwl_rx_replenish(struct iwl_priv *priv); void iwl_rx_replenish_now(struct iwl_priv *priv); int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -int iwl_rx_queue_restock(struct iwl_priv *priv); +void iwl_rx_queue_restock(struct iwl_priv *priv); int iwl_rx_queue_space(const struct iwl_rx_queue *q); void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); @@ -450,7 +450,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); void iwl_hw_txq_ctx_free(struct iwl_priv *priv); int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 909d9c9b9ad8..428c9d689d4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); /** * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) +void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) { unsigned long flags; u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; u32 reg; - int ret = 0; spin_lock_irqsave(&q->lock, flags); @@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) exit_unlock: spin_unlock_irqrestore(&q->lock, flags); - return ret; } EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); /** @@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, * also updates the memory address in the firmware to reference the new * target buffer. */ -int iwl_rx_queue_restock(struct iwl_priv *priv) +void iwl_rx_queue_restock(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; int write; - int ret = 0; spin_lock_irqsave(&rxq->lock, flags); write = rxq->write & ~0x7; @@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - ret = iwl_rx_queue_update_write_ptr(priv, rxq); + iwl_rx_queue_update_write_ptr(priv, rxq); } - - return ret; } EXPORT_SYMBOL(iwl_rx_queue_restock); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 3788a3d4ddc2..2199b1bc1c28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -80,14 +80,13 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, /** * iwl_txq_update_write_ptr - Send new write index to hardware */ -int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) +void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) { u32 reg = 0; - int ret = 0; int txq_id = txq->q.id; if (txq->need_update == 0) - return ret; + return; /* if we're trying to save power */ if (test_bit(STATUS_POWER_PMI, &priv->status)) { @@ -101,7 +100,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) txq_id, reg); iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - return ret; + return; } iwl_write_direct32(priv, HBUS_TARG_WRPTR, @@ -114,8 +113,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) txq->q.write_ptr | (txq_id << 8)); txq->need_update = 0; - - return ret; } EXPORT_SYMBOL(iwl_txq_update_write_ptr); @@ -731,7 +728,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 tid = 0; u8 *qc = NULL; unsigned long flags; - int ret; spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { @@ -951,7 +947,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); /* @@ -965,9 +961,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (sta_priv && sta_priv->client) atomic_inc(&sta_priv->pending_frames); - if (ret) - return ret; - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { spin_lock_irqsave(&priv->lock, flags); @@ -1006,7 +999,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) struct iwl_cmd_meta *out_meta; dma_addr_t phys_addr; unsigned long flags; - int len, ret; + int len; u32 idx; u16 fix_size; @@ -1103,10 +1096,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); - return ret ? ret : idx; + return idx; } static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index eac2b9a95711..f6e8f45ff7f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) u8 wait_write_ptr = 0; u8 *qc = NULL; unsigned long flags; - int rc; spin_lock_irqsave(&priv->lock, flags); if (iwl_is_rfkill(priv)) { @@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - rc = iwl_txq_update_write_ptr(priv, txq); + iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); - if (rc) - return rc; - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { @@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, * also updates the memory address in the firmware to reference the new * target buffer. */ -static int iwl3945_rx_queue_restock(struct iwl_priv *priv) +static void iwl3945_rx_queue_restock(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; struct list_head *element; struct iwl_rx_mem_buffer *rxb; unsigned long flags; - int write, rc; + int write; spin_lock_irqsave(&rxq->lock, flags); write = rxq->write & ~0x7; @@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) spin_lock_irqsave(&rxq->lock, flags); rxq->need_update = 1; spin_unlock_irqrestore(&rxq->lock, flags); - rc = iwl_rx_queue_update_write_ptr(priv, rxq); - if (rc) - return rc; + iwl_rx_queue_update_write_ptr(priv, rxq); } - - return 0; } /** -- cgit v1.2.3 From bbcbb9ef9735c67da303d30bd6beb9e699f0f508 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 2 Feb 2010 10:57:12 -0800 Subject: iwlwifi: fix scan race There is a problem if an "internal short scan" is in progress when a mac80211 requested scan arrives. If this new scan request arrives within the "next_scan_jiffies" period then driver will immediately return success and complete the scan. The problem here is that the scan has not been fully initialized at this time (is_internal_short_scan is still set to true because of the currently running scan), which results in the scan completion never to be sent to mac80211. At this time also, evan though the internal short scan is still running the state (is_internal_short_scan) will be set to false, so when the internal scan does complete then mac80211 will receive a scan completion. Fix this by checking right away if a scan is in progress when a scan request arrives from mac80211. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-scan.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 501477464e07..dd9ff2ed645a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -469,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params); static int iwl_scan_initiate(struct iwl_priv *priv) { - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); - return -EIO; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); - return -EAGAIN; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); - return -EAGAIN; - } - IWL_DEBUG_INFO(priv, "Starting scan...\n"); set_bit(STATUS_SCANNING, &priv->status); priv->is_internal_short_scan = false; @@ -515,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, goto out_unlock; } + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); + ret = -EAGAIN; + goto out_unlock; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); + ret = -EAGAIN; + goto out_unlock; + } + /* We don't schedule scan within next_scan_jiffies period. * Avoid scanning during possible EAPOL exchange, return * success immediately. -- cgit v1.2.3 From 4843b5a731b31916d100cfc5ba4d03ae78462ed9 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 3 Feb 2010 09:38:59 -0800 Subject: iwlwifi: reset card during probe To ensure that card is in a sane state during probe we add a reset call. This change was prompted by users of kdump who was not able to bring up the wireless driver in the kdump kernel. The problem here was that the primary kernel, which is not running at the time, left the wireless card up and running. When the kdump kernel starts it is thus possible to immediately receive interrupts from firmware after registering interrupt, but without being ready to deal with interrupts from firmware yet. Reported-by: Stanislaw Gruszka Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 ++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c1eff4c5b448..31b156d58d7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3540,6 +3540,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ spin_lock_init(&priv->reg_lock); spin_lock_init(&priv->lock); + + /* + * stop and reset the on-board processor just in case it is in a + * strange state ... like being left stranded by a primary kernel + * and this is now the kdump kernel trying to start up + */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_hw_detect(priv); IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", priv->cfg->name, priv->hw_rev); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f6e8f45ff7f0..7af8ab80dcf1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4039,6 +4039,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e spin_lock_init(&priv->reg_lock); spin_lock_init(&priv->lock); + /* + * stop and reset the on-board processor just in case it is in a + * strange state ... like being left stranded by a primary kernel + * and this is now the kdump kernel trying to start up + */ + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + /*********************** * 4. Read EEPROM * ********************/ -- cgit v1.2.3 From 6c3872e1d52290dcd506473028867cacc6b7393d Mon Sep 17 00:00:00 2001 From: Trieu 'Andrew' Nguyen Date: Mon, 8 Feb 2010 13:53:05 -0800 Subject: iwlwifi: Adjusting PLCP error threshold for 1000 NIC While testing the station with the NIC 1000 family, it is found that the plcp error can easily exceed 50 value in 100mSecs. This creates unneccessary radio reset/tuning. This patch raises the PLCP error threshold of the NIC 1000 from 50 to 200 error count. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 694ceef88590..3bf2e6e9b2d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, }; @@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .support_ct_kill_exit = true, - .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9f1d302e3a34..71cf1558e640 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1033,6 +1033,7 @@ struct iwl_event_log { #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) +#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200) #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) enum iwl_reset { -- cgit v1.2.3 From f36d04abe684f9e2b07c6ebe9f77ae20eb5c1e84 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 10 Feb 2010 05:07:45 -0800 Subject: iwlwifi: use dma_alloc_coherent Change pci_alloc_consistent() to dma_alloc_coherent() so we can use GFP_KERNEL flag. Signed-off-by: Stanislaw Gruszka Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 8 +++----- drivers/net/wireless/iwlwifi/iwl-core.c | 12 ++++++------ drivers/net/wireless/iwlwifi/iwl-helpers.h | 7 ++++--- drivers/net/wireless/iwlwifi/iwl-rx.c | 21 +++++++++++---------- drivers/net/wireless/iwlwifi/iwl-tx.c | 23 ++++++++++++----------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++++++-------- 6 files changed, 44 insertions(+), 43 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 57194bbd2762..5913418872ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) memset((void *)&priv->hw_params, 0, sizeof(struct iwl_hw_params)); - priv->shared_virt = - pci_alloc_consistent(priv->pci_dev, - sizeof(struct iwl3945_shared), - &priv->shared_phys); - + priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, + sizeof(struct iwl3945_shared), + &priv->shared_phys, GFP_KERNEL); if (!priv->shared_virt) { IWL_ERR(priv, "failed to allocate pci memory\n"); mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 500ced452098..bd56827b8fef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power); void iwl_free_isr_ict(struct iwl_priv *priv) { if (priv->ict_tbl_vir) { - pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + - PAGE_SIZE, priv->ict_tbl_vir, - priv->ict_tbl_dma); + dma_free_coherent(&priv->pci_dev->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + priv->ict_tbl_vir, priv->ict_tbl_dma); priv->ict_tbl_vir = NULL; } } @@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) if (priv->cfg->use_isr_legacy) return 0; /* allocate shrared data table */ - priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * - ICT_COUNT) + PAGE_SIZE, - &priv->ict_tbl_dma); + priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, + (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, + &priv->ict_tbl_dma, GFP_KERNEL); if (!priv->ict_tbl_vir) return -ENOMEM; diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 45af5bbc1c56..51a67fb2e185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) { if (desc->v_addr) - pci_free_consistent(pci_dev, desc->len, - desc->v_addr, desc->p_addr); + dma_free_coherent(&pci_dev->dev, desc->len, + desc->v_addr, desc->p_addr); desc->v_addr = NULL; desc->len = 0; } @@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) { - desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); + desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, + &desc->p_addr, GFP_KERNEL); return (desc->v_addr != NULL) ? 0 : -ENOMEM; } diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 428c9d689d4c..aba8f4c20c1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -345,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) } } - pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); + dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, + rxq->dma_addr); + dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); rxq->bd = NULL; rxq->rb_stts = NULL; } @@ -357,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); int iwl_rx_queue_alloc(struct iwl_priv *priv) { struct iwl_rx_queue *rxq = &priv->rxq; - struct pci_dev *dev = priv->pci_dev; + struct device *dev = &priv->pci_dev->dev; int i; spin_lock_init(&rxq->lock); @@ -365,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) INIT_LIST_HEAD(&rxq->rx_used); /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); + rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, + GFP_KERNEL); if (!rxq->bd) goto err_bd; - rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), - &rxq->rb_stts_dma); + rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), + &rxq->rb_stts_dma, GFP_KERNEL); if (!rxq->rb_stts) goto err_rb; @@ -387,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) return 0; err_rb: - pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); + dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, + rxq->dma_addr); err_bd: return -ENOMEM; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 2199b1bc1c28..d8c11f955e42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = { static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, struct iwl_dma_ptr *ptr, size_t size) { - ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); + ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, + GFP_KERNEL); if (!ptr->addr) return -ENOMEM; ptr->size = size; @@ -73,7 +74,7 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, if (unlikely(!ptr->addr)) return; - pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); + dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); memset(ptr, 0, sizeof(*ptr)); } @@ -129,7 +130,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; - struct pci_dev *dev = priv->pci_dev; + struct device *dev = &priv->pci_dev->dev; int i; if (q->n_bd == 0) @@ -146,8 +147,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) - pci_free_consistent(dev, priv->hw_params.tfd_size * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); + dma_free_coherent(dev, priv->hw_params.tfd_size * + txq->q.n_bd, txq->tfds, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ kfree(txq->txb); @@ -176,7 +177,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) { struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl_queue *q = &txq->q; - struct pci_dev *dev = priv->pci_dev; + struct device *dev = &priv->pci_dev->dev; int i; if (q->n_bd == 0) @@ -188,8 +189,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) - pci_free_consistent(dev, priv->hw_params.tfd_size * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); + dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, + txq->tfds, txq->q.dma_addr); /* deallocate arrays */ kfree(txq->cmd); @@ -280,7 +281,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, static int iwl_tx_queue_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, u32 id) { - struct pci_dev *dev = priv->pci_dev; + struct device *dev = &priv->pci_dev->dev; size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; /* Driver private data, only for Tx (not command) queues, @@ -299,8 +300,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, /* Circular buffer of transmit frame descriptors (TFDs), * shared with device */ - txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); - + txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, + GFP_KERNEL); if (!txq->tfds) { IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); goto error; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7af8ab80dcf1..3df488a8cf75 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) static void iwl3945_unset_hw_params(struct iwl_priv *priv) { if (priv->shared_virt) - pci_free_consistent(priv->pci_dev, - sizeof(struct iwl3945_shared), - priv->shared_virt, - priv->shared_phys); + dma_free_coherent(&priv->pci_dev->dev, + sizeof(struct iwl3945_shared), + priv->shared_virt, + priv->shared_phys); } static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, @@ -1241,10 +1241,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx } } - pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); + dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, + rxq->dma_addr); + dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); rxq->bd = NULL; rxq->rb_stts = NULL; } -- cgit v1.2.3 From a9e10fb9b1c6ad16e73cf2656951fce3a817611e Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 9 Feb 2010 08:14:11 -0800 Subject: iwlwifi: clear all the stop_queue flag after load firmware All the queues are awake and ready to use after loading firmware, for firmware reload case, if any queues was stopped before reload, mac80211 will wake those queues after restart hardware, so make sure all the flag used to keep track of the queue status are reset correctly. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-4965.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e4794885d079..17e91ad3496c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -581,6 +581,11 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + /* make sure all queue are not stopped */ + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + for (i = 0; i < 4; i++) + atomic_set(&priv->queue_stop_count[i], 0); + /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; /* Map each Tx/cmd queue to its corresponding fifo */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a7fa1ad7e6e5..94fc83671f20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -648,6 +648,11 @@ int iwl5000_alive_notify(struct iwl_priv *priv) iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); + /* make sure all queue are not stopped */ + memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); + for (i = 0; i < 4; i++) + atomic_set(&priv->queue_stop_count[i], 0); + /* reset to 0 to enable all the queue first */ priv->txq_ctx_active_msk = 0; /* map qos queues to fifos one-to-one */ -- cgit v1.2.3 From 1db5950f1d0b82e07371b211a48317b8972da063 Mon Sep 17 00:00:00 2001 From: Trieu 'Andrew' Nguyen Date: Wed, 10 Feb 2010 10:27:34 -0800 Subject: iwlwifi: Monitor and recover the aggregation TX flow failure This change monitors the tx statistics to detect the drop in throughput. When the throughput drops, the ratio of the actual_ack_count and the expected_ ack_count also drops. At the same time, the aggregated ba_timeout (the number of ba timeout retries) also rises. If the actual_ack_count/expected_ack_count ratio is 0 and the number of ba timeout retries rises to 16, no tx packets (tcp, udp, or ping - icmp) can be delivered. The driver recovers from this situation by reseting the uCode firmware. If the actual_ack_count/expected_ ack_count ratio drops below 50% (but not 0) and the aggregated ba_timeout retries just exceed 5 (but not 16), then the driver can reset the radio to bring the throughput up. Signed-off-by: Trieu 'Andrew' Nguyen Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 ++++++++++- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-rx.c | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 31b156d58d7f..4157c6c8645f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - return iwl_tx_agg_start(priv, sta->addr, tid, ssn); + ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); + if (ret == 0) { + priv->agg_tids_count++; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); + } + return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwl_tx_agg_stop(priv, sta->addr, tid); + if ((ret == 0) && (priv->agg_tids_count > 0)) { + priv->agg_tids_count--; + IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", + priv->agg_tids_count); + } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else @@ -3364,6 +3375,7 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; + priv->agg_tids_count = 0; /* Choose which receivers/antennas to use */ if (priv->cfg->ops->hcmd->set_rxon_chain) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 71cf1558e640..f81317d478ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1072,6 +1072,9 @@ struct iwl_priv { /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; + /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ + u8 agg_tids_count; + /* force reset */ unsigned long last_force_reset_jiffies; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index aba8f4c20c1b..fed554accedc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) +/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ +#define ACK_CNT_RATIO (50) +#define BA_TIMEOUT_CNT (5) +#define BA_TIMEOUT_MAX (16) + #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -625,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; + int actual_ack_cnt_delta; + int expected_ack_cnt_delta; + int ba_timeout_delta; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), @@ -639,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif + actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - + le32_to_cpu(priv->statistics.tx.actual_ack_cnt); + expected_ack_cnt_delta = le32_to_cpu( + pkt->u.stats.tx.expected_ack_cnt) - + le32_to_cpu(priv->statistics.tx.expected_ack_cnt); + ba_timeout_delta = le32_to_cpu( + pkt->u.stats.tx.agg.ba_timeout) - + le32_to_cpu(priv->statistics.tx.agg.ba_timeout); + if ((priv->agg_tids_count > 0) && + (expected_ack_cnt_delta > 0) && + (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < + ACK_CNT_RATIO) && + (ba_timeout_delta > BA_TIMEOUT_CNT)) { + IWL_DEBUG_RADIO(priv, + "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", + actual_ack_cnt_delta, expected_ack_cnt_delta); + +#ifdef CONFIG_IWLWIFI_DEBUG + IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", + priv->delta_statistics.tx.rx_detected_cnt); + IWL_DEBUG_RADIO(priv, + "ack_or_ba_timeout_collision delta = %d\n", + priv->delta_statistics.tx.ack_or_ba_timeout_collision); +#endif + IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", + ba_timeout_delta); + if ((actual_ack_cnt_delta == 0) && + (ba_timeout_delta >= + BA_TIMEOUT_MAX)) { + IWL_DEBUG_RADIO(priv, + "call iwl_force_reset(IWL_FW_RESET)\n"); + iwl_force_reset(priv, IWL_FW_RESET); + } else { + IWL_DEBUG_RADIO(priv, + "call iwl_force_reset(IWL_RF_RESET)\n"); + iwl_force_reset(priv, IWL_RF_RESET); + } + } /* * check for plcp_err and trigger radio reset if it exceeds * the plcp error threshold plcp_delta. -- cgit v1.2.3 From 8e5574211d96c0552f84c757718475fdb4021be7 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 11 Feb 2010 12:14:23 -0800 Subject: ethtool: Use explicit designated initializers for .cmd Initialize the .cmd member of various ethtool using a designated struct initializer rather. This makes things a teeny bit more robust, although the chance of a struct layout changing is extremely remote, and also makes the code a little easier to read. Signed-off-by: Roland Dreier Signed-off-by: David S. Miller --- net/core/ethtool.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 6ec73d3983a3..a1280f643bf4 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -163,7 +163,7 @@ EXPORT_SYMBOL(ethtool_ntuple_flush); static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) { - struct ethtool_cmd cmd = { ETHTOOL_GSET }; + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; int err; if (!dev->ethtool_ops->get_settings) @@ -645,7 +645,7 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) { - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; if (!dev->ethtool_ops->get_wol) return -EOPNOTSUPP; @@ -779,7 +779,7 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) { - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; + struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; if (!dev->ethtool_ops->get_coalesce) return -EOPNOTSUPP; @@ -806,7 +806,7 @@ static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) static int ethtool_get_ringparam(struct net_device *dev, void __user *useraddr) { - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; + struct ethtool_ringparam ringparam = { .cmd = ETHTOOL_GRINGPARAM }; if (!dev->ethtool_ops->get_ringparam) return -EOPNOTSUPP; @@ -1160,7 +1160,7 @@ static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) static int ethtool_get_value(struct net_device *dev, char __user *useraddr, u32 cmd, u32 (*actor)(struct net_device *)) { - struct ethtool_value edata = { cmd }; + struct ethtool_value edata = { .cmd = cmd }; if (!actor) return -EOPNOTSUPP; -- cgit v1.2.3 From 857b409a48bdc33e824dff2d730e271b964e78bd Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 12 Feb 2010 06:24:46 +0100 Subject: netfilter: nf_conntrack: elegantly simplify nf_ct_exp_net() Remove #ifdef at nf_ct_exp_net() by using nf_ct_net(). Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_expect.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 917e170fa752..4b47ec19ef39 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -56,11 +56,7 @@ struct nf_conntrack_expect { static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp) { -#ifdef CONFIG_NET_NS - return exp->master->ct_net; /* by definition */ -#else - return &init_net; -#endif + return nf_ct_net(exp->master); } struct nf_conntrack_expect_policy { -- cgit v1.2.3 From ca1c2e2da9637c131436bf6d6ae41b58f5353afe Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 12 Feb 2010 06:25:36 +0100 Subject: netfilter: don't use INIT_RCU_HEAD() call_rcu() will unconditionally reinitialize RCU head anyway. Signed-off-by: Alexey Dobriyan Reviewed-by: Paul E. McKenney Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_expect.c | 1 - net/netfilter/nf_conntrack_extend.c | 1 - net/netfilter/nfnetlink_queue.c | 1 - 3 files changed, 3 deletions(-) diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 33b85f834c06..6182fb1b55de 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -232,7 +232,6 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me) new->master = me; atomic_set(&new->use, 1); - INIT_RCU_HEAD(&new->rcu); return new; } EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index fef95be334bd..fdc8fb4ae10f 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -59,7 +59,6 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) if (!*ext) return NULL; - INIT_RCU_HEAD(&(*ext)->rcu); (*ext)->offset[id] = off; (*ext)->len = len; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 90cf36decea3..7ba4abc405c9 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -112,7 +112,6 @@ instance_create(u_int16_t queue_num, int pid) inst->copy_mode = NFQNL_COPY_NONE; spin_lock_init(&inst->lock); INIT_LIST_HEAD(&inst->queue_list); - INIT_RCU_HEAD(&inst->rcu); if (!try_module_get(THIS_MODULE)) { err = -EAGAIN; -- cgit v1.2.3 From 42c4568a4ace0adc27a9d6f02936e2047ba6fc7e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 11 Feb 2010 18:07:19 +0100 Subject: ath9k: add a workaround for ack timeout issues Adding support for setting the coverage class in some cases broke association and data transfer, as it overwrote the initial ACK timeout value from the initvals with a smaller value. I don't know why the new value works in 5 GHz (matches the initval there), but not in 2.4 GHz (initvals use 64us here), so until the problem is fully understood, the value should be increased again. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f15fee76a4e2..f00f5c744f48 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1217,6 +1217,17 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) /* As defined by IEEE 802.11-2007 17.3.8.6 */ slottime = ah->slottime + 3 * ah->coverage_class; acktimeout = slottime + sifstime; + + /* + * Workaround for early ACK timeouts, add an offset to match the + * initval's 64us ack timeout value. + * This was initially only meant to work around an issue with delayed + * BA frames in some implementations, but it has been found to fix ACK + * timeout issues in other cases as well. + */ + if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) + acktimeout += 64 - sifstime - ah->slottime; + ath9k_hw_setslottime(ah, slottime); ath9k_hw_set_ack_timeout(ah, acktimeout); ath9k_hw_set_cts_timeout(ah, acktimeout); -- cgit v1.2.3 From 4cd24eaf0c6ee7f0242e34ee77ec899f255e66b5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 8 Feb 2010 04:30:35 +0000 Subject: net: use netdev_mc_count and netdev_mc_empty when appropriate This patch replaces dev->mc_count in all drivers (hopefully I didn't miss anything). Used spatch and did small tweaks and conding style changes when it was suitable. Jirka Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- arch/xtensa/platforms/iss/network.c | 2 +- drivers/infiniband/hw/nes/nes_nic.c | 2 +- drivers/media/dvb/dvb-core/dvb_net.c | 7 +++---- drivers/net/3c505.c | 6 +++--- drivers/net/3c509.c | 10 ++++++---- drivers/net/3c523.c | 4 ++-- drivers/net/3c527.c | 11 ++++++----- drivers/net/7990.c | 2 +- drivers/net/82596.c | 8 ++++---- drivers/net/a2065.c | 2 +- drivers/net/acenic.c | 2 +- drivers/net/amd8111e.c | 7 ++++--- drivers/net/ariadne.c | 2 +- drivers/net/arm/at91_ether.c | 4 ++-- drivers/net/arm/ether3.c | 2 +- drivers/net/arm/ixp4xx_eth.c | 2 +- drivers/net/arm/ks8695net.c | 4 ++-- drivers/net/at1700.c | 6 +++--- drivers/net/atarilance.c | 2 +- drivers/net/atp.c | 7 ++++--- drivers/net/au1000_eth.c | 4 ++-- drivers/net/b44.c | 4 ++-- drivers/net/bcm63xx_enet.c | 4 ++-- drivers/net/benet/be_main.c | 5 +++-- drivers/net/bfin_mac.c | 4 ++-- drivers/net/bmac.c | 8 ++++---- drivers/net/bnx2.c | 2 +- drivers/net/bnx2x_main.c | 7 ++++--- drivers/net/chelsio/common.h | 4 ++-- drivers/net/cpmac.c | 2 +- drivers/net/cris/eth_v10.c | 2 +- drivers/net/davinci_emac.c | 4 ++-- drivers/net/de620.c | 2 +- drivers/net/declance.c | 2 +- drivers/net/defxx.c | 4 ++-- drivers/net/depca.c | 2 +- drivers/net/dl2k.c | 6 +++--- drivers/net/dm9000.c | 2 +- drivers/net/e100.c | 6 +++--- drivers/net/eepro.c | 15 ++++++++------- drivers/net/eexpress.c | 6 +++--- drivers/net/ehea/ehea_main.c | 6 +++--- drivers/net/enc28j60.c | 2 +- drivers/net/enic/enic_main.c | 4 ++-- drivers/net/epic100.c | 6 +++--- drivers/net/eth16i.c | 2 +- drivers/net/ewrk3.c | 2 +- drivers/net/fealnx.c | 4 ++-- drivers/net/fec.c | 2 +- drivers/net/fec_mpc52xx.c | 2 +- drivers/net/fs_enet/mac-fcc.c | 2 +- drivers/net/fs_enet/mac-fec.c | 2 +- drivers/net/fs_enet/mac-scc.c | 2 +- drivers/net/gianfar.c | 2 +- drivers/net/hamachi.c | 6 +++--- drivers/net/hp100.c | 7 ++++--- drivers/net/ibm_newemac/core.c | 6 +++--- drivers/net/ibmveth.c | 5 +++-- drivers/net/igb/igb_main.c | 8 ++++---- drivers/net/igbvf/netdev.c | 6 +++--- drivers/net/ioc3-eth.c | 5 +++-- drivers/net/ipg.c | 4 ++-- drivers/net/isa-skeleton.c | 5 +++-- drivers/net/iseries_veth.c | 4 ++-- drivers/net/ixgb/ixgb_main.c | 6 +++--- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/jme.c | 2 +- drivers/net/korina.c | 6 +++--- drivers/net/ks8851.c | 4 ++-- drivers/net/ks8851_mll.c | 4 ++-- drivers/net/lance.c | 2 +- drivers/net/lib82596.c | 6 +++--- drivers/net/ll_temac_main.c | 6 +++--- drivers/net/lp486e.c | 12 +++++++----- drivers/net/macb.c | 4 ++-- drivers/net/mace.c | 2 +- drivers/net/macmace.c | 2 +- drivers/net/natsemi.c | 4 ++-- drivers/net/netxen/netxen_nic_hw.c | 10 +++++----- drivers/net/ni52.c | 2 +- drivers/net/ni65.c | 2 +- drivers/net/niu.c | 4 ++-- drivers/net/ns83820.c | 2 +- drivers/net/octeon/octeon_mgmt.c | 6 +++--- drivers/net/pci-skeleton.c | 4 ++-- drivers/net/pcmcia/3c574_cs.c | 2 +- drivers/net/pcmcia/3c589_cs.c | 2 +- drivers/net/pcmcia/fmvj18x_cs.c | 6 +++--- drivers/net/pcmcia/nmclan_cs.c | 14 +++++++------- drivers/net/pcmcia/smc91c92_cs.c | 4 ++-- drivers/net/pcmcia/xirc2ps_cs.c | 8 ++++---- drivers/net/pcnet32.c | 2 +- drivers/net/ps3_gelic_net.c | 2 +- drivers/net/qlcnic/qlcnic_hw.c | 4 ++-- drivers/net/qlge/qlge_main.c | 4 ++-- drivers/net/r6040.c | 11 ++++++----- drivers/net/r8169.c | 4 ++-- drivers/net/s2io.c | 8 ++++---- drivers/net/sc92031.c | 2 +- drivers/net/sfc/efx.c | 2 +- drivers/net/sgiseeq.c | 2 +- drivers/net/sis190.c | 4 ++-- drivers/net/sis900.c | 4 ++-- drivers/net/skfp/skfddi.c | 6 +++--- drivers/net/skge.c | 6 +++--- drivers/net/sky2.c | 4 ++-- drivers/net/smc911x.c | 6 +++--- drivers/net/smc9194.c | 4 ++-- drivers/net/smc91x.c | 6 +++--- drivers/net/smsc911x.c | 4 ++-- drivers/net/smsc9420.c | 2 +- drivers/net/sonic.c | 8 +++++--- drivers/net/starfire.c | 8 ++++---- drivers/net/stmmac/dwmac100.c | 6 +++--- drivers/net/stmmac/dwmac1000_core.c | 8 ++++---- drivers/net/sun3_82586.c | 2 +- drivers/net/sun3lance.c | 2 +- drivers/net/sunbmac.c | 4 ++-- drivers/net/sundance.c | 6 +++--- drivers/net/sungem.c | 4 ++-- drivers/net/sunhme.c | 8 ++++---- drivers/net/sunlance.c | 2 +- drivers/net/sunqe.c | 4 ++-- drivers/net/tc35815.c | 6 +++--- drivers/net/tehuti.c | 4 ++-- drivers/net/tg3.c | 4 ++-- drivers/net/tlan.c | 2 +- drivers/net/tokenring/3c359.c | 2 +- drivers/net/tokenring/ibmtr.c | 2 +- drivers/net/tokenring/lanstreamer.c | 2 +- drivers/net/tokenring/olympic.c | 2 +- drivers/net/tokenring/tms380tr.c | 2 +- drivers/net/tsi108_eth.c | 2 +- drivers/net/tulip/de2104x.c | 8 ++++---- drivers/net/tulip/de4x5.c | 6 +++--- drivers/net/tulip/dmfe.c | 15 ++++++++------- drivers/net/tulip/tulip_core.c | 18 +++++++++++------- drivers/net/tulip/uli526x.c | 12 +++++++----- drivers/net/tulip/winbond-840.c | 7 ++++--- drivers/net/typhoon.c | 9 +++++---- drivers/net/ucc_geth.c | 3 ++- drivers/net/usb/asix.c | 12 ++++++------ drivers/net/usb/catc.c | 4 +++- drivers/net/usb/int51x1.c | 2 +- drivers/net/usb/kaweth.c | 2 +- drivers/net/usb/mcs7830.c | 6 +++--- drivers/net/usb/pegasus.c | 2 +- drivers/net/usb/rtl8150.c | 2 +- drivers/net/usb/smsc95xx.c | 4 ++-- drivers/net/via-rhine.c | 5 +++-- drivers/net/via-velocity.c | 6 ++++-- drivers/net/virtio_net.c | 13 ++++++++----- drivers/net/vmxnet3/vmxnet3_drv.c | 8 ++++---- drivers/net/vxge/vxge-main.c | 6 +++--- drivers/net/wireless/airo.c | 2 +- drivers/net/wireless/orinoco/main.c | 4 ++-- drivers/net/wireless/ray_cs.c | 2 +- drivers/net/wireless/rndis_wlan.c | 6 +++--- drivers/net/wireless/zd1201.c | 7 +++---- drivers/net/yellowfin.c | 7 ++++--- drivers/staging/et131x/et131x_netdev.c | 10 +++++----- drivers/staging/netwave/netwave_cs.c | 8 ++++---- drivers/staging/slicoss/slicoss.c | 2 +- drivers/staging/vt6655/device_main.c | 4 ++-- drivers/staging/vt6656/main_usb.c | 5 +++-- drivers/staging/wavelan/wavelan.c | 8 ++++---- drivers/staging/wavelan/wavelan_cs.c | 11 ++++++----- drivers/staging/wlags49_h2/wl_netdev.c | 12 ++++++------ net/bluetooth/bnep/netdev.c | 6 ++++-- net/core/dev.c | 2 +- net/irda/irlan/irlan_eth.c | 5 +++-- net/mac80211/iface.c | 2 +- 173 files changed, 440 insertions(+), 401 deletions(-) diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 2f0b86b37cf9..87e218f98ef4 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -560,7 +560,7 @@ static void iss_net_set_multicast_list(struct net_device *dev) #if 0 if (dev->flags & IFF_PROMISC) return; - else if (dev->mc_count) + else if (!netdev_mc_empty(dev)) dev->flags |= IFF_ALLMULTI; else dev->flags &= ~IFF_ALLMULTI; diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index ab1102780186..c04f8fc6fc2d 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -862,7 +862,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) } nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", - netdev->mc_count, !!(netdev->flags & IFF_PROMISC), + netdev_mc_count(netdev), !!(netdev->flags & IFF_PROMISC), !!(netdev->flags & IFF_ALLMULTI)); if (!mc_all_on) { multicast_addr = netdev->mc_list; diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c index da6552d32cfe..37d8579fc7a9 100644 --- a/drivers/media/dvb/dvb-core/dvb_net.c +++ b/drivers/media/dvb/dvb-core/dvb_net.c @@ -1138,18 +1138,18 @@ static void wq_set_multicast_list (struct work_struct *work) } else if ((dev->flags & IFF_ALLMULTI)) { dprintk("%s: allmulti mode\n", dev->name); priv->rx_mode = RX_MODE_ALL_MULTI; - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { int mci; struct dev_mc_list *mc; dprintk("%s: set_mc_list, %d entries\n", - dev->name, dev->mc_count); + dev->name, netdev_mc_count(dev)); priv->rx_mode = RX_MODE_MULTI; priv->multi_num = 0; for (mci = 0, mc=dev->mc_list; - mci < dev->mc_count; + mci < netdev_mc_count(dev); mc = mc->next, mci++) { dvb_set_mc_filter(dev, mc); } @@ -1236,7 +1236,6 @@ static void dvb_net_setup(struct net_device *dev) dev->header_ops = &dvb_header_ops; dev->netdev_ops = &dvb_netdev_ops; dev->mtu = 4096; - dev->mc_count = 0; dev->flags |= IFF_NOARP; } diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index 9257d7ce0378..dadb46a8833a 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1229,8 +1229,8 @@ static void elp_set_mc_list(struct net_device *dev) /* send a "load multicast list" command to the board, max 10 addrs/cmd */ /* if num_addrs==0 the list will be cleared */ adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; - adapter->tx_pcb.length = 6 * dev->mc_count; - for (i = 0; i < dev->mc_count; i++) { + adapter->tx_pcb.length = 6 * netdev_mc_count(dev); + for (i = 0; i < netdev_mc_count(dev); i++) { memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr, 6); dmi = dmi->next; } @@ -1244,7 +1244,7 @@ static void elp_set_mc_list(struct net_device *dev) TIMEOUT_MSG(__LINE__); } } - if (dev->mc_count) + if (!netdev_mc_empty(dev)) adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI; else /* num_addrs == 0 */ adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 9d85efce5916..902435a76466 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -1111,12 +1111,14 @@ set_multicast_list(struct net_device *dev) unsigned long flags; struct el3_private *lp = netdev_priv(dev); int ioaddr = dev->base_addr; + int mc_count = netdev_mc_count(dev); if (el3_debug > 1) { static int old; - if (old != dev->mc_count) { - old = dev->mc_count; - pr_debug("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count); + if (old != mc_count) { + old = mc_count; + pr_debug("%s: Setting Rx mode to %d addresses.\n", + dev->name, mc_count); } } spin_lock_irqsave(&lp->lock, flags); @@ -1124,7 +1126,7 @@ set_multicast_list(struct net_device *dev) outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, ioaddr + EL3_CMD); } - else if (dev->mc_count || (dev->flags&IFF_ALLMULTI)) { + else if (mc_count || (dev->flags&IFF_ALLMULTI)) { outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD); } else diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 27d80ca5e4c0..6948d667fc5e 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -626,7 +626,7 @@ static int init586(struct net_device *dev) volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; struct dev_mc_list *dmi = dev->mc_list; - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); @@ -771,7 +771,7 @@ static int init586(struct net_device *dev) * Multicast setup */ - if (dev->mc_count) { + if (num_addrs) { /* I don't understand this: do we really need memory after the init? */ int len = ((char *) p->iscp - (char *) ptr - 8) / 6; if (len <= 0) { diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index 36c4191e7bca..ce9826980517 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1526,10 +1526,10 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) if ((dev->flags&IFF_PROMISC) || (dev->flags&IFF_ALLMULTI) || - dev->mc_count > 10) + netdev_mc_count(dev) > 10) /* Enable promiscuous mode */ filt |= 1; - else if(dev->mc_count) + else if (!netdev_mc_empty(dev)) { unsigned char block[62]; unsigned char *bp; @@ -1542,16 +1542,17 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) if(!lp->mc_list_valid) { block[1]=0; - block[0]=dev->mc_count; + block[0]=netdev_mc_count(dev); bp=block+2; - for(i=0;imc_count;i++) + for(i=0;idmi_addr, 6); bp+=6; dmc=dmc->next; } - if(mc32_command_nowait(dev, 2, block, 2+6*dev->mc_count)==-1) + if(mc32_command_nowait(dev, 2, block, + 2+6*netdev_mc_count(dev))==-1) { lp->mc_reload_wait = 1; return; diff --git a/drivers/net/7990.c b/drivers/net/7990.c index b1e5764628c6..079d0be37821 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -611,7 +611,7 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++){ + for (i = 0; i < netdev_mc_count(dev); i++){ addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 1663bc9e45de..638ce3b29854 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1505,7 +1505,7 @@ static void set_multicast_list(struct net_device *dev) int config = 0, cnt; DEB(DEB_MULTI,printk(KERN_DEBUG "%s: set multicast list, %d entries, promisc %s, allmulti %s\n", - dev->name, dev->mc_count, + dev->name, netdev_mc_count(dev), dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); @@ -1533,7 +1533,7 @@ static void set_multicast_list(struct net_device *dev) i596_add_cmd(dev, &lp->cf_cmd.cmd); } - cnt = dev->mc_count; + cnt = netdev_mc_count(dev); if (cnt > MAX_MC_CNT) { cnt = MAX_MC_CNT; @@ -1541,7 +1541,7 @@ static void set_multicast_list(struct net_device *dev) dev->name, cnt); } - if (dev->mc_count > 0) { + if (!netdev_mc_empty(dev)) { struct dev_mc_list *dmi; unsigned char *cp; struct mc_cmd *cmd; @@ -1550,7 +1550,7 @@ static void set_multicast_list(struct net_device *dev) return; cmd = &lp->mc_cmd; cmd->cmd.command = CmdMulticastList; - cmd->mc_cnt = dev->mc_count * 6; + cmd->mc_cnt = netdev_mc_count(dev) * 6; cp = cmd->mc_addrs; for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { memcpy(cp, dmi->dmi_addr, 6); diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index b7ec0368d7e8..6a65f660c192 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -619,7 +619,7 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++){ + for (i = 0; i < netdev_mc_count(dev); i++){ addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index ec624ab03e88..4ae750ef1e10 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -2845,7 +2845,7 @@ static void ace_set_multicast_list(struct net_device *dev) * set the entire multicast list at a time and keeping track of * it here is going to be messy. */ - if ((dev->mc_count) && !(ap->mcast_all)) { + if (!netdev_mc_empty(dev) && !ap->mcast_all) { cmd.evt = C_SET_MULTICAST_MODE; cmd.code = C_C_MCAST_ENABLE; cmd.idx = 0; diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index bb27b27d9672..bdffdfb4c88b 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1387,7 +1387,8 @@ static void amd8111e_set_multicast_list(struct net_device *dev) } else writel( PROM, lp->mmio + CMD2); - if(dev->flags & IFF_ALLMULTI || dev->mc_count > MAX_FILTER_SIZE){ + if (dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev) > MAX_FILTER_SIZE) { /* get all multicast packet */ mc_filter[1] = mc_filter[0] = 0xffffffff; lp->mc_list = dev->mc_list; @@ -1395,7 +1396,7 @@ static void amd8111e_set_multicast_list(struct net_device *dev) amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF); return; } - if( dev->mc_count == 0 ){ + if (netdev_mc_empty(dev)) { /* get only own packets */ mc_filter[1] = mc_filter[0] = 0; lp->mc_list = NULL; @@ -1409,7 +1410,7 @@ static void amd8111e_set_multicast_list(struct net_device *dev) lp->options |= OPTION_MULTICAST_ENABLE; lp->mc_list = dev->mc_list; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mc_ptr = dev->mc_list; mc_ptr && i < dev->mc_count; + for (i = 0, mc_ptr = dev->mc_list; mc_ptr && i < netdev_mc_count(dev); i++, mc_ptr = mc_ptr->next) { bit_num = (ether_crc_le(ETH_ALEN, mc_ptr->dmi_addr) >> 26) & 0x3f; mc_filter[bit_num >> 5] |= 1 << (bit_num & 31); diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index e2c202493fa7..08d8be47dae0 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -819,7 +819,7 @@ static void set_multicast_list(struct net_device *dev) lance->RDP = PROM; /* Set promiscuous mode */ } else { short multicast_table[4]; - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); int i; /* We don't use the multicast table, but rely on upper-layer filtering. */ memset(multicast_table, (num_addrs == 0) ? 0 : -1, diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index c8bc60a7040c..17d85d98987d 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -563,7 +563,7 @@ static void at91ether_sethashtable(struct net_device *dev) mc_filter[0] = mc_filter[1] = 0; curr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + for (i = 0; i < netdev_mc_count(dev); i++, curr = curr->next) { if (!curr) break; /* unexpected end of list */ bitnr = hash_get_index(curr->dmi_addr); @@ -592,7 +592,7 @@ static void at91ether_set_multicast_list(struct net_device *dev) at91_emac_write(AT91_EMAC_HSH, -1); at91_emac_write(AT91_EMAC_HSL, -1); cfg |= AT91_EMAC_MTI; - } else if (dev->mc_count > 0) { /* Enable specific multicasts */ + } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ at91ether_sethashtable(dev); cfg |= AT91_EMAC_MTI; } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c index 1f7a69c929a6..d9de9bce2395 100644 --- a/drivers/net/arm/ether3.c +++ b/drivers/net/arm/ether3.c @@ -463,7 +463,7 @@ static void ether3_setmulticastlist(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* promiscuous mode */ priv(dev)->regs.config1 |= CFG1_RECVPROMISC; - } else if (dev->flags & IFF_ALLMULTI || dev->mc_count) { + } else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI; } else priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD; diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index c3dfbdd2cdcf..1a5f78b160f9 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -737,7 +737,7 @@ static void eth_set_mcast_list(struct net_device *dev) struct port *port = netdev_priv(dev); struct dev_mc_list *mclist = dev->mc_list; u8 diffs[ETH_ALEN], *addr; - int cnt = dev->mc_count, i; + int cnt = netdev_mc_count(dev), i; if ((dev->flags & IFF_PROMISC) || !mclist || !cnt) { __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN, diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index be256b34cea8..1dc181a9fbc3 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1207,7 +1207,7 @@ ks8695_set_multicast(struct net_device *ndev) if (ndev->flags & IFF_ALLMULTI) { /* enable all multicast mode */ ctrl |= DRXC_RM; - } else if (ndev->mc_count > KS8695_NR_ADDRESSES) { + } else if (netdev_mc_count(ndev) > KS8695_NR_ADDRESSES) { /* more specific multicast addresses than can be * handled in hardware */ @@ -1216,7 +1216,7 @@ ks8695_set_multicast(struct net_device *ndev) /* enable specific multicasts */ ctrl &= ~DRXC_RM; ks8695_init_partial_multicast(ksp, ndev->mc_list, - ndev->mc_count); + netdev_mc_count(ndev)); } ks8695_writereg(ksp, KS8695_DRXC, ctrl); diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index b14f4799d5d1..fe60cd02c86c 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -839,12 +839,12 @@ set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { memset(mc_filter, 0xff, sizeof(mc_filter)); outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ - } else if (dev->mc_count > MC_FILTERBREAK || + } else if (netdev_mc_count(dev) > MC_FILTERBREAK || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); outb(2, ioaddr + RX_MODE); /* Use normal mode. */ - } else if (dev->mc_count == 0) { + } else if (netdev_mc_empty(dev)) { memset(mc_filter, 0x00, sizeof(mc_filter)); outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { @@ -852,7 +852,7 @@ set_rx_mode(struct net_device *dev) int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c index cc9ed8643910..280cfff48b49 100644 --- a/drivers/net/atarilance.c +++ b/drivers/net/atarilance.c @@ -1097,7 +1097,7 @@ static void set_multicast_list( struct net_device *dev ) REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ } else { short multicast_table[4]; - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); int i; /* We don't use the multicast table, but rely on upper-layer * filtering. */ diff --git a/drivers/net/atp.c b/drivers/net/atp.c index 2f8261c9614a..a841feb5df20 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -861,7 +861,7 @@ static void set_rx_mode_8002(struct net_device *dev) struct net_local *lp = netdev_priv(dev); long ioaddr = dev->base_addr; - if (dev->mc_count > 0 || (dev->flags & (IFF_ALLMULTI|IFF_PROMISC))) + if (!netdev_mc_empty(dev) || (dev->flags & (IFF_ALLMULTI|IFF_PROMISC))) lp->addr_mode = CMR2h_PROMISC; else lp->addr_mode = CMR2h_Normal; @@ -877,7 +877,8 @@ static void set_rx_mode_8012(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ new_mode = CMR2h_PROMISC; - } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + } else if ((netdev_mc_count(dev) > 1000) || + (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); new_mode = CMR2h_Normal; @@ -885,7 +886,7 @@ static void set_rx_mode_8012(struct net_device *dev) struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 6bac04603a88..9337d023919c 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -1013,7 +1013,7 @@ static void au1000_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ aup->mac->control |= MAC_PROMISCUOUS; } else if ((dev->flags & IFF_ALLMULTI) || - dev->mc_count > MULTICAST_FILTER_LIMIT) { + netdev_mc_count(dev) > MULTICAST_FILTER_LIMIT) { aup->mac->control |= MAC_PASS_ALL_MULTI; aup->mac->control &= ~MAC_PROMISCUOUS; printk(KERN_INFO "%s: Pass all multicast\n", dev->name); @@ -1023,7 +1023,7 @@ static void au1000_multicast_list(struct net_device *dev) u32 mc_filter[2]; /* Multicast hash filter */ mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, (long *)mc_filter); diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 44b66be38134..9091c6574b1c 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1691,7 +1691,7 @@ static int __b44_load_mcast(struct b44 *bp, struct net_device *dev) struct dev_mc_list *mclist; int i, num_ents; - num_ents = min_t(int, dev->mc_count, B44_MCAST_TABLE_SIZE); + num_ents = min_t(int, netdev_mc_count(dev), B44_MCAST_TABLE_SIZE); mclist = dev->mc_list; for (i = 0; mclist && i < num_ents; i++, mclist = mclist->next) { __b44_cam_write(bp, mclist->dmi_addr, i + 1); @@ -1716,7 +1716,7 @@ static void __b44_set_rx_mode(struct net_device *dev) __b44_set_mac_addr(bp); if ((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > B44_MCAST_TABLE_SIZE)) + (netdev_mc_count(dev) > B44_MCAST_TABLE_SIZE)) val |= RXCONFIG_ALLMULTI; else i = __b44_load_mcast(bp, dev); diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index 0bd47d32ec42..0927ffa0d753 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -619,7 +619,7 @@ static void bcm_enet_set_multicast_list(struct net_device *dev) /* only 3 perfect match registers left, first one is used for * own mac address */ - if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 3) + if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > 3) val |= ENET_RXCFG_ALLMCAST_MASK; else val &= ~ENET_RXCFG_ALLMCAST_MASK; @@ -632,7 +632,7 @@ static void bcm_enet_set_multicast_list(struct net_device *dev) } for (i = 0, mc_list = dev->mc_list; - (mc_list != NULL) && (i < dev->mc_count) && (i < 3); + (mc_list != NULL) && (i < netdev_mc_count(dev)) && (i < 3); i++, mc_list = mc_list->next) { u8 *dmi_addr; u32 tmp; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 626b76c0ebc7..0014a4e86446 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -565,14 +565,15 @@ static void be_set_multicast_list(struct net_device *netdev) } /* Enable multicast promisc if num configured exceeds what we support */ - if (netdev->flags & IFF_ALLMULTI || netdev->mc_count > BE_MAX_MC) { + if (netdev->flags & IFF_ALLMULTI || + netdev_mc_count(netdev) > BE_MAX_MC) { be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0, &adapter->mc_cmd_mem); goto done; } be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, - netdev->mc_count, &adapter->mc_cmd_mem); + netdev_mc_count(netdev), &adapter->mc_cmd_mem); done: return; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 0b23bc4f56c6..ef7f77113e26 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -819,7 +819,7 @@ static void bfin_mac_multicast_hash(struct net_device *dev) emac_hashhi = emac_hashlo = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; @@ -862,7 +862,7 @@ static void bfin_mac_set_multicast_list(struct net_device *dev) sysctl = bfin_read_EMAC_OPMODE(); sysctl |= PAM; bfin_write_EMAC_OPMODE(sysctl); - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { /* set up multicast hash table */ sysctl = bfin_read_EMAC_OPMODE(); sysctl |= HM; diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 9b587c344194..189fa69c2094 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -973,7 +973,7 @@ static void bmac_set_multicast(struct net_device *dev) { struct dev_mc_list *dmi; struct bmac_data *bp = netdev_priv(dev); - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); unsigned short rx_cfg; int i; @@ -982,7 +982,7 @@ static void bmac_set_multicast(struct net_device *dev) XXDEBUG(("bmac: enter bmac_set_multicast, n_addrs=%d\n", num_addrs)); - if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) { for (i=0; i<4; i++) bp->hash_table_mask[i] = 0xffff; bmac_update_hash_table_mask(dev, bp); rx_cfg = bmac_rx_on(dev, 1, 0); @@ -1021,7 +1021,7 @@ static void bmac_set_multicast(struct net_device *dev) unsigned short rx_cfg; u32 crc; - if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) { bmwrite(dev, BHASH0, 0xffff); bmwrite(dev, BHASH1, 0xffff); bmwrite(dev, BHASH2, 0xffff); @@ -1039,7 +1039,7 @@ static void bmac_set_multicast(struct net_device *dev) for(i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < dev->mc_count; i++) { + for(i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5917b941aca2..c7f5515ddaa4 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3560,7 +3560,7 @@ bnx2_set_rx_mode(struct net_device *dev) memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr); diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ffc7381969ae..6d8559052ee6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11471,7 +11471,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev) rx_mode = BNX2X_RX_MODE_PROMISC; else if ((dev->flags & IFF_ALLMULTI) || - ((dev->mc_count > BNX2X_MAX_MULTICAST) && CHIP_IS_E1(bp))) + ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) && + CHIP_IS_E1(bp))) rx_mode = BNX2X_RX_MODE_ALLMULTI; else { /* some multicasts */ @@ -11482,7 +11483,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) bnx2x_sp(bp, mcast_config); for (i = 0, mclist = dev->mc_list; - mclist && (i < dev->mc_count); + mclist && (i < netdev_mc_count(dev)); i++, mclist = mclist->next) { config->config_table[i]. @@ -11554,7 +11555,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) memset(mc_filter, 0, 4 * MC_HASH_SIZE); for (i = 0, mclist = dev->mc_list; - mclist && (i < dev->mc_count); + mclist && (i < netdev_mc_count(dev)); i++, mclist = mclist->next) { DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n", diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index f6462b54f823..bb159d9603bf 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -97,13 +97,13 @@ struct t1_rx_mode { #define t1_rx_mode_promisc(rm) (rm->dev->flags & IFF_PROMISC) #define t1_rx_mode_allmulti(rm) (rm->dev->flags & IFF_ALLMULTI) -#define t1_rx_mode_mc_cnt(rm) (rm->dev->mc_count) +#define t1_rx_mode_mc_cnt(rm) (netdev_mc_count(rm->dev)) static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm) { u8 *addr = NULL; - if (rm->idx++ < rm->dev->mc_count) { + if (rm->idx++ < t1_rx_mode_mc_cnt(rm)) { addr = rm->list->dmi_addr; rm->list = rm->list->next; } diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 8d0be26f94e3..c9c537be4ab9 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -340,7 +340,7 @@ static void cpmac_set_multicast_list(struct net_device *dev) * cpmac uses some strange mac address hashing * (not crc32) */ - for (i = 0, iter = dev->mc_list; i < dev->mc_count; + for (i = 0, iter = dev->mc_list; i < netdev_mc_count(dev); i++, iter = iter->next) { bit = 0; tmp = iter->dmi_addr[0]; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index a24be34a3f7a..c9309eadebc1 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1564,7 +1564,7 @@ static void set_multicast_list(struct net_device *dev) { struct net_local *lp = netdev_priv(dev); - int num_addr = dev->mc_count; + int num_addr = netdev_mc_count(dev); unsigned long int lo_bits; unsigned long int hi_bits; diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index faffad409985..d1e03b5984c0 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -956,11 +956,11 @@ static void emac_dev_mcast_set(struct net_device *ndev) } else { mbp_enable = (mbp_enable & ~EMAC_MBP_RXPROMISC); if ((ndev->flags & IFF_ALLMULTI) || - (ndev->mc_count > EMAC_DEF_MAX_MULTICAST_ADDRESSES)) { + netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); } - if (ndev->mc_count > 0) { + if (!netdev_mc_empty(ndev)) { struct dev_mc_list *mc_ptr; mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); diff --git a/drivers/net/de620.c b/drivers/net/de620.c index 45794f6cb0f6..a0a6830b5e6d 100644 --- a/drivers/net/de620.c +++ b/drivers/net/de620.c @@ -464,7 +464,7 @@ static int de620_close(struct net_device *dev) static void de620_set_multicast_list(struct net_device *dev) { - if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) + if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) { /* Enable promiscuous mode */ de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL); } diff --git a/drivers/net/declance.c b/drivers/net/declance.c index be9590253aa1..76e0de6a4263 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -960,7 +960,7 @@ static void lance_load_multicast(struct net_device *dev) *lib_ptr(ib, filter[3], lp->type) = 0; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 98da085445e6..5adb1e03956d 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -2227,7 +2227,7 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) * perfect filtering will be used. */ - if (dev->mc_count > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count)) + if (netdev_mc_count(dev) > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count)) { bp->group_prom = PI_FSTATE_K_PASS; /* Enable LLC group prom mode */ bp->mc_count = 0; /* Don't add mc addrs to CAM */ @@ -2235,7 +2235,7 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) else { bp->group_prom = PI_FSTATE_K_BLOCK; /* Disable LLC group prom mode */ - bp->mc_count = dev->mc_count; /* Add mc addrs to CAM */ + bp->mc_count = netdev_mc_count(dev); /* Add mc addrs to CAM */ } /* Copy addresses to multicast address table, then update adapter CAM */ diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 0c1f491d20bf..314bc96689f4 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1287,7 +1287,7 @@ static void SetMulticastFilter(struct net_device *dev) lp->init_block.mcast_table[i] = 0; } /* Add multicast addresses */ - for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ + for (i = 0; i < netdev_mc_count(dev); i++) { /* for each address in the list */ addrs = dmi->dmi_addr; dmi = dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index 2a8b6a7c0b87..dea40953ed1b 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1128,17 +1128,17 @@ set_multicast (struct net_device *dev) /* Receive all frames promiscuously. */ rx_mode = ReceiveAllFrames; } else if ((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > multicast_filter_limit)) { + (netdev_mc_count(dev) > multicast_filter_limit)) { /* Receive broadcast and multicast frames */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { int i; struct dev_mc_list *mclist; /* Receive broadcast frames and multicast frames filtering by Hashtable */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; - for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i=0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist=mclist->next) { int bit, index = 0; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index b37730065688..da0985a7a87a 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -725,7 +725,7 @@ dm9000_hash_table(struct net_device *dev) { board_info_t *db = netdev_priv(dev); struct dev_mc_list *mcptr = dev->mc_list; - int mc_cnt = dev->mc_count; + int mc_cnt = netdev_mc_count(dev); int i, oft; u32 hash_val; u16 hash_table[4]; diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 5c7a155e849a..e8c0e823a06f 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1538,7 +1538,7 @@ static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) { struct net_device *netdev = nic->netdev; struct dev_mc_list *list = netdev->mc_list; - u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); + u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); cb->command = cpu_to_le16(cb_multi); cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); @@ -1552,7 +1552,7 @@ static void e100_set_multicast_list(struct net_device *netdev) struct nic *nic = netdev_priv(netdev); DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", - netdev->mc_count, netdev->flags); + netdev_mc_count(netdev), netdev->flags); if (netdev->flags & IFF_PROMISC) nic->flags |= promiscuous; @@ -1560,7 +1560,7 @@ static void e100_set_multicast_list(struct net_device *netdev) nic->flags &= ~promiscuous; if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > E100_MAX_MULTICAST_ADDRS) + netdev_mc_count(netdev) > E100_MAX_MULTICAST_ADDRS) nic->flags |= multicast_all; else nic->flags &= ~multicast_all; diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 94c59498cdb6..488bc13cc7e6 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1288,8 +1288,9 @@ set_multicast_list(struct net_device *dev) short ioaddr = dev->base_addr; unsigned short mode; struct dev_mc_list *dmi=dev->mc_list; + int mc_count = mc_count; - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) + if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) { eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); @@ -1299,7 +1300,7 @@ set_multicast_list(struct net_device *dev) eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ } - else if (dev->mc_count==0 ) + else if (mc_count == 0) { eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ mode = inb(ioaddr + REG2); @@ -1329,9 +1330,9 @@ set_multicast_list(struct net_device *dev) outw(MC_SETUP, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); - outw(6*(dev->mc_count + 1), ioaddr + IO_PORT); + outw(6 * (mc_count + 1), ioaddr + IO_PORT); - for (i = 0; i < dev->mc_count; i++) + for (i = 0; i < mc_count; i++) { eaddrs=(unsigned short *)dmi->dmi_addr; dmi=dmi->next; @@ -1348,7 +1349,7 @@ set_multicast_list(struct net_device *dev) outb(MC_SETUP, ioaddr); /* Update the transmit queue */ - i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1); + i = lp->tx_end + XMT_HEADER + 6 * (mc_count + 1); if (lp->tx_start != lp->tx_end) { @@ -1380,8 +1381,8 @@ set_multicast_list(struct net_device *dev) break; } else if ((i & 0x0f) == 0x03) { /* MC-Done */ printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n", - dev->name, dev->mc_count, - dev->mc_count > 1 ? "es":""); + dev->name, mc_count, + mc_count > 1 ? "es":""); break; } } diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index 6fbfc8eee632..d804ff18eda8 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -1578,7 +1578,7 @@ static void eexp_setup_filter(struct net_device *dev) { struct dev_mc_list *dmi; unsigned short ioaddr = dev->base_addr; - int count = dev->mc_count; + int count = netdev_mc_count(dev); int i; if (count > 8) { printk(KERN_INFO "%s: too many multicast addresses (%d)\n", @@ -1627,9 +1627,9 @@ eexp_set_multicast(struct net_device *dev) } if (!(dev->flags & IFF_PROMISC)) { eexp_setup_filter(dev); - if (lp->old_mc_count != dev->mc_count) { + if (lp->old_mc_count != netdev_mc_count(dev)) { kick = 1; - lp->old_mc_count = dev->mc_count; + lp->old_mc_count = netdev_mc_count(dev); } } if (kick) { diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 7b62336e6736..99e4f8360d2f 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1981,7 +1981,7 @@ static void ehea_set_multicast_list(struct net_device *dev) } ehea_allmulti(dev, 0); - if (dev->mc_count) { + if (!netdev_mc_empty(dev)) { ret = ehea_drop_multicast_list(dev); if (ret) { /* Dropping the current multicast list failed. @@ -1990,14 +1990,14 @@ static void ehea_set_multicast_list(struct net_device *dev) ehea_allmulti(dev, 1); } - if (dev->mc_count > port->adapter->max_mc_mac) { + if (netdev_mc_count(dev) > port->adapter->max_mc_mac) { ehea_info("Mcast registration limit reached (0x%llx). " "Use ALLMULTI!", port->adapter->max_mc_mac); goto out; } - for (i = 0, k_mcl_entry = dev->mc_list; i < dev->mc_count; i++, + for (i = 0, k_mcl_entry = dev->mc_list; i < netdev_mc_count(dev); i++, k_mcl_entry = k_mcl_entry->next) ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr); diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 66813c91a720..3ee32e58c7ec 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -1413,7 +1413,7 @@ static void enc28j60_set_multicast_list(struct net_device *dev) if (netif_msg_link(priv)) dev_info(&dev->dev, "promiscuous mode\n"); priv->rxfilter = RXFILTER_PROMISC; - } else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count) { + } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { if (netif_msg_link(priv)) dev_info(&dev->dev, "%smulticast mode\n", (dev->flags & IFF_ALLMULTI) ? "all-" : ""); diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index c81bc4b1816f..94749ebaaea8 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -827,11 +827,11 @@ static void enic_set_multicast_list(struct net_device *netdev) int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; int promisc = (netdev->flags & IFF_PROMISC) ? 1 : 0; + unsigned int mc_count = netdev_mc_count(netdev); int allmulti = (netdev->flags & IFF_ALLMULTI) || - (netdev->mc_count > ENIC_MULTICAST_PERFECT_FILTERS); + mc_count > ENIC_MULTICAST_PERFECT_FILTERS; unsigned int flags = netdev->flags | (allmulti ? IFF_ALLMULTI : 0); u8 mc_addr[ENIC_MULTICAST_PERFECT_FILTERS][ETH_ALEN]; - unsigned int mc_count = netdev->mc_count; unsigned int i, j; if (mc_count > ENIC_MULTICAST_PERFECT_FILTERS) diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 1f8b11449fad..31a3adb65566 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1390,20 +1390,20 @@ static void set_rx_mode(struct net_device *dev) outl(0x002C, ioaddr + RxCtrl); /* Unconditionally log net taps. */ memset(mc_filter, 0xff, sizeof(mc_filter)); - } else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) { + } else if ((!netdev_mc_empty(dev)) || (dev->flags & IFF_ALLMULTI)) { /* There is apparently a chip bug, so the multicast filter is never enabled. */ /* Too many to filter perfectly -- accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); outl(0x000C, ioaddr + RxCtrl); - } else if (dev->mc_count == 0) { + } else if (netdev_mc_empty(dev)) { outl(0x0004, ioaddr + RxCtrl); return; } else { /* Never executed, for now. */ struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { unsigned int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c index 71bfeec33a0b..d3abeee3f110 100644 --- a/drivers/net/eth16i.c +++ b/drivers/net/eth16i.c @@ -1359,7 +1359,7 @@ static void eth16i_multicast(struct net_device *dev) { int ioaddr = dev->base_addr; - if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) + if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) { outb(3, ioaddr + RECEIVE_MODE_REG); } else { diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index dd4ba01fd92d..96817a872f47 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1213,7 +1213,7 @@ static void SetMulticastFilter(struct net_device *dev) } /* Update table */ - for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */ + for (i = 0; i < netdev_mc_count(dev); i++) { /* for each address in the list */ addrs = dmi->dmi_addr; dmi = dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index e6a98129d787..f95b5ff0587d 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1786,7 +1786,7 @@ static void __set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = CR_W_PROM | CR_W_AB | CR_W_AM; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); @@ -1796,7 +1796,7 @@ static void __set_rx_mode(struct net_device *dev) int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { unsigned int bit; bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 5d0d33268155..d9d14c83f51c 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1606,7 +1606,7 @@ static void set_multicast_list(struct net_device *dev) dmi = dev->mc_list; - for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) { + for (j = 0; j < netdev_mc_count(dev); j++, dmi = dmi->next) { /* Only support group multicast for now */ if (!(dmi->dmi_addr[0] & 1)) continue; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 848e8407ea8f..10903b75802f 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -581,7 +581,7 @@ static void mpc52xx_fec_set_multicast_list(struct net_device *dev) u32 gaddr2 = 0x00000000; dmi = dev->mc_list; - for (i=0; imc_count; i++) { + for (i=0; idmi_addr) >> 26; if (crc >= 32) gaddr1 |= 1 << (crc-32); diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 22e5a847a588..482f27d5f7d4 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -218,7 +218,7 @@ static void set_multicast_finish(struct net_device *dev) /* if all multi or too many multicasts; just enable all */ if ((dev->flags & IFF_ALLMULTI) != 0 || - dev->mc_count > FCC_MAX_MULTICAST_ADDRS) { + netdev_mc_count(dev) > FCC_MAX_MULTICAST_ADDRS) { W32(ep, fen_gaddrh, 0xffffffff); W32(ep, fen_gaddrl, 0xffffffff); diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index ca7bcb8ab3a1..ddf13ef8ac87 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -220,7 +220,7 @@ static void set_multicast_finish(struct net_device *dev) /* if all multi or too many multicasts; just enable all */ if ((dev->flags & IFF_ALLMULTI) != 0 || - dev->mc_count > FEC_MAX_MULTICAST_ADDRS) { + netdev_mc_count(dev) > FEC_MAX_MULTICAST_ADDRS) { fep->fec.hthi = 0xffffffffU; fep->fec.htlo = 0xffffffffU; } diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 008cdd9cc536..141dbc91e5e7 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -213,7 +213,7 @@ static void set_multicast_finish(struct net_device *dev) /* if all multi or too many multicasts; just enable all */ if ((dev->flags & IFF_ALLMULTI) != 0 || - dev->mc_count > SCC_MAX_MULTICAST_ADDRS) { + netdev_mc_count(dev) > SCC_MAX_MULTICAST_ADDRS) { W16(ep, sen_gaddr1, 0xffff); W16(ep, sen_gaddr2, 0xffff); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 8bd3c9f17532..c9be090485dd 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2863,7 +2863,7 @@ static void gfar_set_multi(struct net_device *dev) em_num = 0; } - if (dev->mc_count == 0) + if (netdev_mc_empty(dev)) return; /* Parse the list, and set the appropriate bits */ diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index dd72c5025e6a..c70b147b4feb 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1854,13 +1854,13 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ writew(0x000F, ioaddr + AddrMode); - } else if ((dev->mc_count > 63) || (dev->flags & IFF_ALLMULTI)) { + } else if ((netdev_mc_count(dev) > 63) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ writew(0x000B, ioaddr + AddrMode); - } else if (dev->mc_count > 0) { /* Must use the CAM filter. */ + } else if (!netdev_mc_empty(dev)) { /* Must use the CAM filter. */ struct dev_mc_list *mclist; int i; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { writel(*(u32*)(mclist->dmi_addr), ioaddr + 0x100 + i*8); writel(0x20000 | (*(u16*)&mclist->dmi_addr[4]), diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index 0c2f2e8b1c47..debac1bc6799 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2090,7 +2090,7 @@ static void hp100_set_multicast_list(struct net_device *dev) lp->mac2_mode = HP100_MAC2MODE6; /* promiscuous mode = get all good */ lp->mac1_mode = HP100_MAC1MODE6; /* packets on the net */ memset(&lp->hash_bytes, 0xff, 8); - } else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { + } else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) { lp->mac2_mode = HP100_MAC2MODE5; /* multicast mode = get packets for */ lp->mac1_mode = HP100_MAC1MODE5; /* me, broadcasts and all multicasts */ #ifdef HP100_MULTICAST_FILTER /* doesn't work!!! */ @@ -2104,9 +2104,10 @@ static void hp100_set_multicast_list(struct net_device *dev) memset(&lp->hash_bytes, 0x00, 8); #ifdef HP100_DEBUG - printk("hp100: %s: computing hash filter - mc_count = %i\n", dev->name, dev->mc_count); + printk("hp100: %s: computing hash filter - mc_count = %i\n", + dev->name, netdev_mc_count(dev)); #endif - for (i = 0, dmi = dev->mc_list; i < dev->mc_count; i++, dmi = dmi->next) { + for (i = 0, dmi = dev->mc_list; i < netdev_mc_count(dev); i++, dmi = dmi->next) { addrs = dmi->dmi_addr; if ((*addrs & 0x01) == 0x01) { /* multicast address? */ #ifdef HP100_DEBUG diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index fb5e019169ee..b75d27e82a3d 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -391,7 +391,7 @@ static void emac_hash_mc(struct emac_instance *dev) struct dev_mc_list *dmi; int i; - DBG(dev, "hash_mc %d" NL, dev->ndev->mc_count); + DBG(dev, "hash_mc %d" NL, netdev_mc_count(dev->ndev)); memset(gaht_temp, 0, sizeof (gaht_temp)); @@ -425,9 +425,9 @@ static inline u32 emac_iff2rmr(struct net_device *ndev) if (ndev->flags & IFF_PROMISC) r |= EMAC_RMR_PME; else if (ndev->flags & IFF_ALLMULTI || - (ndev->mc_count > EMAC_XAHT_SLOTS(dev))) + (netdev_mc_count(ndev) > EMAC_XAHT_SLOTS(dev))) r |= EMAC_RMR_PMME; - else if (ndev->mc_count > 0) + else if (!netdev_mc_empty(ndev)) r |= EMAC_RMR_MAE; return r; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index a86693906ac8..41b9c0efcbdd 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1062,7 +1062,8 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) struct ibmveth_adapter *adapter = netdev_priv(netdev); unsigned long lpar_rc; - if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) { + if ((netdev->flags & IFF_PROMISC) || + (netdev_mc_count(netdev) > adapter->mcastFilterSize)) { lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableRecv | IbmVethMcastDisableFiltering, @@ -1083,7 +1084,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); } /* add the addresses to the filter table */ - for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) { + for(i = 0; i < netdev_mc_count(netdev); ++i, mclist = mclist->next) { // add the multicast address to the filter table unsigned long mcast_addr = 0; memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 83cd0d7417d0..28371d648208 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2848,14 +2848,14 @@ static int igb_write_mc_addr_list(struct net_device *netdev) u32 vmolr = 0; int i; - if (!netdev->mc_count) { + if (netdev_mc_empty(netdev)) { /* nothing to program, so clear mc list */ igb_update_mc_addr_list(hw, NULL, 0); igb_restore_vf_multicasts(adapter); return 0; } - mta_list = kzalloc(netdev->mc_count * 6, GFP_ATOMIC); + mta_list = kzalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC); if (!mta_list) return -ENOMEM; @@ -2865,7 +2865,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev) /* The shared function expects a packed array of only addresses. */ mc_ptr = netdev->mc_list; - for (i = 0; i < netdev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(netdev); i++) { if (!mc_ptr) break; memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); @@ -2874,7 +2874,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev) igb_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); - return netdev->mc_count; + return netdev_mc_count(netdev); } /** diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 23ce07d3de08..6029c400f2be 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1403,8 +1403,8 @@ static void igbvf_set_multi(struct net_device *netdev) u8 *mta_list = NULL; int i; - if (netdev->mc_count) { - mta_list = kmalloc(netdev->mc_count * 6, GFP_ATOMIC); + if (!netdev_mc_empty(netdev)) { + mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC); if (!mta_list) { dev_err(&adapter->pdev->dev, "failed to allocate multicast filter list\n"); @@ -1415,7 +1415,7 @@ static void igbvf_set_multi(struct net_device *netdev) /* prepare a packed array of only addresses. */ mc_ptr = netdev->mc_list; - for (i = 0; i < netdev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(netdev); i++) { if (!mc_ptr) break; memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 81a4c5d30733..0bd5fef22d49 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1681,14 +1681,15 @@ static void ioc3_set_multicast_list(struct net_device *dev) ioc3_w_emcr(ip->emcr); /* Clear promiscuous. */ (void) ioc3_r_emcr(); - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if ((dev->flags & IFF_ALLMULTI) || + (netdev_mc_count(dev) > 64)) { /* Too many for hashing to make sense or we want all multicast packets anyway, so skip computing all the hashes and just accept all packets. */ ip->ehar_h = 0xffffffff; ip->ehar_l = 0xffffffff; } else { - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { char *addr = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 49f35e2ed19f..dbdebd5efe86 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -585,11 +585,11 @@ static void ipg_nic_set_multicast_list(struct net_device *dev) receivemode = IPG_RM_RECEIVEALLFRAMES; } else if ((dev->flags & IFF_ALLMULTI) || ((dev->flags & IFF_MULTICAST) && - (dev->mc_count > IPG_MULTICAST_HASHTABLE_SIZE))) { + (netdev_mc_count(dev) > IPG_MULTICAST_HASHTABLE_SIZE))) { /* NIC to be configured to receive all multicast * frames. */ receivemode |= IPG_RM_RECEIVEMULTICAST; - } else if ((dev->flags & IFF_MULTICAST) && (dev->mc_count > 0)) { + } else if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) { /* NIC to be configured to receive selected * multicast addresses. */ receivemode |= IPG_RM_RECEIVEMULTICASTHASH; diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index 04d0502726c0..bb4a3cda6e4b 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -655,14 +655,15 @@ set_multicast_list(struct net_device *dev) /* Enable promiscuous mode */ outw(MULTICAST|PROMISC, ioaddr); } - else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) + else if ((dev->flags&IFF_ALLMULTI) || + netdev_mc_count(dev) > HW_MAX_ADDRS) { /* Disable promiscuous mode, use normal mode. */ hardware_set_filter(NULL); outw(MULTICAST, ioaddr); } - else if(dev->mc_count) + else if (!netdev_mc_empty(dev)) { /* Walk the address list, and load the filter */ hardware_set_filter(dev->mc_list); diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 16c91910d6c1..ff015e15f5d1 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -958,7 +958,7 @@ static void veth_set_multicast_list(struct net_device *dev) write_lock_irqsave(&port->mcast_gate, flags); if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > VETH_MAX_MCAST)) { + (netdev_mc_count(dev) > VETH_MAX_MCAST)) { port->promiscuous = 1; } else { struct dev_mc_list *dmi = dev->mc_list; @@ -969,7 +969,7 @@ static void veth_set_multicast_list(struct net_device *dev) /* Update table */ port->num_mcast = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { u8 *addr = dmi->dmi_addr; u64 xaddr = 0; diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index c56ea69762cd..6a7b2ccef72c 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1077,7 +1077,7 @@ ixgb_set_multi(struct net_device *netdev) rctl |= IXGB_RCTL_VFE; } - if (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES) { + if (netdev_mc_count(netdev) > IXGB_MAX_NUM_MULTICAST_ADDRESSES) { rctl |= IXGB_RCTL_MPE; IXGB_WRITE_REG(hw, RCTL, rctl); } else { @@ -1092,7 +1092,7 @@ ixgb_set_multi(struct net_device *netdev) memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS], mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS); - ixgb_mc_addr_list_update(hw, mta, netdev->mc_count, 0); + ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0); } } @@ -1616,7 +1616,7 @@ ixgb_update_stats(struct ixgb_adapter *adapter) return; if ((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) || - (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) { + (netdev_mc_count(netdev) > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) { u64 multi = IXGB_READ_REG(&adapter->hw, MPRCL); u32 bcast_l = IXGB_READ_REG(&adapter->hw, BPRCL); u32 bcast_h = IXGB_READ_REG(&adapter->hw, BPRCH); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 382bf8945d11..0792f151de99 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2571,7 +2571,7 @@ void ixgbe_set_rx_mode(struct net_device *netdev) hw->mac.ops.update_uc_addr_list(hw, netdev); /* reprogram multicast list */ - addr_count = netdev->mc_count; + addr_count = netdev_mc_count(netdev); if (addr_count) addr_list = netdev->mc_list->dmi_addr; hw->mac.ops.update_mc_addr_list(hw, addr_list, addr_count, diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index b9f10d05049d..235b5fd4b8d4 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1527,7 +1527,7 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev) int addr_count = 0; /* reprogram multicast list */ - addr_count = netdev->mc_count; + addr_count = netdev_mc_count(netdev); if (addr_count) addr_list = netdev->mc_list->dmi_addr; if (hw->mac.ops.update_mc_addr_list) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 26eed49d3208..d44c39dfbef1 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2013,7 +2013,7 @@ jme_set_multi(struct net_device *netdev) jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; for (i = 0, mclist = netdev->mc_list; - mclist && i < netdev->mc_count; + mclist && i < netdev_mc_count(netdev); ++i, mclist = mclist->next) { bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 25e2af6997e4..af0c764130e6 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -490,19 +490,19 @@ static void korina_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) recognise |= ETH_ARC_PRO; - else if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 4)) + else if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 4)) /* All multicast and broadcast */ recognise |= ETH_ARC_AM; /* Build the hash table */ - if (dev->mc_count > 4) { + if (netdev_mc_count(dev) > 4) { u16 hash_table[4]; u32 crc; for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { char *addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 6d3ac65bc35c..9845ab1e5573 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -965,14 +965,14 @@ static void ks8851_set_rx_mode(struct net_device *dev) rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA | RXCR1_RXMAFMA); - } else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) { + } else if (dev->flags & IFF_MULTICAST && !netdev_mc_empty(dev)) { struct dev_mc_list *mcptr = dev->mc_list; u32 crc; int i; /* accept some multicast */ - for (i = dev->mc_count; i > 0; i--) { + for (i = netdev_mc_count(dev); i > 0; i--) { crc = ether_crc(ETH_ALEN, mcptr->dmi_addr); crc >>= (32 - 6); /* get top six bits */ diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index c0ceebccaa49..ffffb3889704 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -1193,8 +1193,8 @@ static void ks_set_rx_mode(struct net_device *netdev) else ks_set_promis(ks, false); - if ((netdev->flags & IFF_MULTICAST) && netdev->mc_count) { - if (netdev->mc_count <= MAX_MCAST_LST) { + if ((netdev->flags & IFF_MULTICAST) && netdev_mc_count(netdev)) { + if (netdev_mc_count(netdev) <= MAX_MCAST_LST) { int i = 0; for (ptr = netdev->mc_list; ptr; ptr = ptr->next) { if (!(*ptr->dmi_addr & 1)) diff --git a/drivers/net/lance.c b/drivers/net/lance.c index 8d7d3d4625f6..7b9447646f8a 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -1288,7 +1288,7 @@ static void set_multicast_list(struct net_device *dev) } else { short multicast_table[4]; int i; - int num_addrs=dev->mc_count; + int num_addrs=netdev_mc_count(dev); if(dev->flags&IFF_ALLMULTI) num_addrs=1; /* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */ diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index b60efd4bd017..371b58b1d151 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1380,21 +1380,21 @@ static void set_multicast_list(struct net_device *dev) } } - cnt = dev->mc_count; + cnt = netdev_mc_count(dev); if (cnt > MAX_MC_CNT) { cnt = MAX_MC_CNT; printk(KERN_NOTICE "%s: Only %d multicast addresses supported", dev->name, cnt); } - if (dev->mc_count > 0) { + if (!netdev_mc_empty(dev)) { struct dev_mc_list *dmi; unsigned char *cp; struct mc_cmd *cmd; cmd = &dma->mc_cmd; cmd->cmd.command = SWAP16(CmdMulticastList); - cmd->mc_cnt = SWAP16(dev->mc_count * 6); + cmd->mc_cnt = SWAP16(netdev_mc_count(dev) * 6); cp = cmd->mc_addrs; for (dmi = dev->mc_list; cnt && dmi != NULL; diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index a8522bd73ae7..8442c47e93e8 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -232,7 +232,7 @@ static void temac_set_multicast_list(struct net_device *ndev) mutex_lock(&lp->indirect_mutex); if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) || - ndev->mc_count > MULTICAST_CAM_TABLE_NUM) { + netdev_mc_count(ndev) > MULTICAST_CAM_TABLE_NUM) { /* * We must make the kernel realise we had to move * into promisc mode or we start all out war on @@ -242,9 +242,9 @@ static void temac_set_multicast_list(struct net_device *ndev) ndev->flags |= IFF_PROMISC; temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); - } else if (ndev->mc_count) { + } else if (!netdev_mc_empty(ndev)) { struct dev_mc_list *mclist = ndev->mc_list; - for (i = 0; mclist && i < ndev->mc_count; i++) { + for (i = 0; mclist && i < netdev_mc_count(ndev); i++) { if (i >= MULTICAST_CAM_TABLE_NUM) break; diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index e20fefc73c8b..b1f5d79af61f 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1253,18 +1253,19 @@ static void set_multicast_list(struct net_device *dev) { if (i596_debug > 1) printk ("%s: set multicast list %d\n", - dev->name, dev->mc_count); + dev->name, netdev_mc_count(dev)); - if (dev->mc_count > 0) { + if (!netdev_mc_empty(dev)) { struct dev_mc_list *dmi; char *cp; - cmd = kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC); + cmd = kmalloc(sizeof(struct i596_cmd) + 2 + + netdev_mc_count(dev) * 6, GFP_ATOMIC); if (cmd == NULL) { printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name); return; } cmd->command = CmdMulticastList; - *((unsigned short *) (cmd + 1)) = dev->mc_count * 6; + *((unsigned short *) (cmd + 1)) = netdev_mc_count(dev) * 6; cp = ((char *)(cmd + 1))+2; for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { memcpy(cp, dmi,6); @@ -1277,7 +1278,8 @@ static void set_multicast_list(struct net_device *dev) { if (lp->set_conf.pa_next != I596_NULL) { return; } - if (dev->mc_count == 0 && !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { + if (netdev_mc_empty(dev) && + !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { lp->i596_config[8] &= ~0x01; } else { lp->i596_config[8] |= 0x01; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 1d0d4d9ab623..fbc371fa19b5 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -901,7 +901,7 @@ static void macb_sethashtable(struct net_device *dev) mc_filter[0] = mc_filter[1] = 0; curr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + for (i = 0; i < netdev_mc_count(dev); i++, curr = curr->next) { if (!curr) break; /* unexpected end of list */ bitnr = hash_get_index(curr->dmi_addr); @@ -934,7 +934,7 @@ static void macb_set_rx_mode(struct net_device *dev) macb_writel(bp, HRB, -1); macb_writel(bp, HRT, -1); cfg |= MACB_BIT(NCFGR_MTI); - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ macb_sethashtable(dev); cfg |= MACB_BIT(NCFGR_MTI); diff --git a/drivers/net/mace.c b/drivers/net/mace.c index d9fbad386389..fdb0bbdd6782 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -606,7 +606,7 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 44f3c2896f20..740accbf0806 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -518,7 +518,7 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { crc = ether_crc_le(6, dmi->dmi_addr); j = crc >> 26; /* bit number in multicast_filter */ multicast_filter[j >> 3] |= 1 << (j & 7); diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 2d7b3bbfed01..c64e5b0d3596 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2488,7 +2488,7 @@ static void __set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ rx_mode = RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptAllPhys | AcceptMyPhys; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { rx_mode = RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys; @@ -2496,7 +2496,7 @@ static void __set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int b = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff; mc_filter[b/8] |= (1 << (b & 0x07)); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index dd45c7a9122e..25f4414cc33e 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -554,7 +554,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) return; } - if (netdev->mc_count == 0) { + if (netdev_mc_empty(netdev)) { adapter->set_promisc(adapter, NETXEN_NIU_NON_PROMISC_MODE); netxen_nic_disable_mcast_filter(adapter); @@ -563,7 +563,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE); if (netdev->flags & IFF_ALLMULTI || - netdev->mc_count > adapter->max_mc_count) { + netdev_mc_count(netdev) > adapter->max_mc_count) { netxen_nic_disable_mcast_filter(adapter); return; } @@ -573,7 +573,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++) netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr); - if (index != netdev->mc_count) + if (index != netdev_mc_count(netdev)) printk(KERN_WARNING "%s: %s multicast address count mismatch\n", netxen_nic_driver_name, netdev->name); @@ -704,12 +704,12 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) } if ((netdev->flags & IFF_ALLMULTI) || - (netdev->mc_count > adapter->max_mc_count)) { + (netdev_mc_count(netdev) > adapter->max_mc_count)) { mode = VPORT_MISS_MODE_ACCEPT_MULTI; goto send_fw_cmd; } - if (netdev->mc_count > 0) { + if (!netdev_mc_empty(netdev)) { for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index b42f5e522f90..497c6d514a68 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -597,7 +597,7 @@ static int init586(struct net_device *dev) struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; struct dev_mc_list *dmi = dev->mc_list; - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); ptr = p->scb + 1; diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c index ae19aafd2c7e..9225c76cac40 100644 --- a/drivers/net/ni65.c +++ b/drivers/net/ni65.c @@ -849,7 +849,7 @@ static int ni65_lance_reinit(struct net_device *dev) if(dev->flags & IFF_PROMISC) ni65_init_lance(p,dev->dev_addr,0x00,M_PROM); - else if(dev->mc_count || dev->flags & IFF_ALLMULTI) + else if (netdev_mc_count(dev) || dev->flags & IFF_ALLMULTI) ni65_init_lance(p,dev->dev_addr,0xff,0x0); else ni65_init_lance(p,dev->dev_addr,0x00,0x00); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index af9a8647c7e8..7b52d9762b00 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6369,7 +6369,7 @@ static void niu_set_rx_mode(struct net_device *dev) np->flags &= ~(NIU_FLAGS_MCAST | NIU_FLAGS_PROMISC); if (dev->flags & IFF_PROMISC) np->flags |= NIU_FLAGS_PROMISC; - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 0)) + if ((dev->flags & IFF_ALLMULTI) || (!netdev_mc_empty(dev))) np->flags |= NIU_FLAGS_MCAST; alt_cnt = netdev_uc_count(dev); @@ -6412,7 +6412,7 @@ static void niu_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 16; i++) hash[i] = 0xffff; - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { for (addr = dev->mc_list; addr; addr = addr->next) { u32 crc = ether_crc_le(ETH_ALEN, addr->da_addr); diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index a3b6aa0f375d..8dd509c09bc8 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -1719,7 +1719,7 @@ static void ns83820_set_multicast(struct net_device *ndev) else and_mask &= ~(RFCR_AAU | RFCR_AAM); - if (ndev->flags & IFF_ALLMULTI || ndev->mc_count) + if (ndev->flags & IFF_ALLMULTI || netdev_mc_count(ndev)) or_mask |= RFCR_AAM; else and_mask &= ~RFCR_AAM; diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index 6fd8789ef487..3a0f910924a5 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -493,8 +493,8 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) } if (netdev->flags & IFF_MULTICAST) { - if (cam_mode == 0 || (netdev->flags & IFF_ALLMULTI) - || netdev->mc_count > available_cam_entries) + if (cam_mode == 0 || (netdev->flags & IFF_ALLMULTI) || + netdev_mc_count(netdev) > available_cam_entries) multicast_mode = 2; /* 1 - Accept all multicast. */ else multicast_mode = 0; /* 0 - Use CAM. */ @@ -511,7 +511,7 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) } } if (multicast_mode == 0) { - i = netdev->mc_count; + i = netdev_mc_count(netdev); list = netdev->mc_list; while (i--) { octeon_mgmt_cam_state_add(&cam_state, list->da_addr); diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 20273832bfce..bbdf0398c93f 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1820,7 +1820,7 @@ static void netdrv_set_rx_mode (struct net_device *dev) AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; @@ -1829,7 +1829,7 @@ static void netdrv_set_rx_mode (struct net_device *dev) struct dev_mc_list *mclist; rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 98938ea9e0bd..3d1d3a7b7ed3 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -1148,7 +1148,7 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, ioaddr + EL3_CMD); - else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) + else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); else outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 322e11df0097..091e0b00043e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -886,7 +886,7 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) opts |= RxMulticast | RxProm; - else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) + else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) opts |= RxMulticast; outw(opts, ioaddr + EL3_CMD); } diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 7b17404d0858..3d573ed5f7c5 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -1187,19 +1187,19 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { memset(mc_filter, 0xff, sizeof(mc_filter)); outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ - } else if (dev->mc_count > MC_FILTERBREAK || + } else if (netdev_mc_count(dev) > MC_FILTERBREAK || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); outb(2, ioaddr + RX_MODE); /* Use normal mode. */ - } else if (dev->mc_count == 0) { + } else if (netdev_mc_empty(dev)) { memset(mc_filter, 0x00, sizeof(mc_filter)); outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 12e3233868e9..c42a31a97fa3 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1481,8 +1481,8 @@ static void set_multicast_list(struct net_device *dev) #ifdef PCMCIA_DEBUG { static int old; - if (dev->mc_count != old) { - old = dev->mc_count; + if (netdev_mc_count(dev) != old) { + old = netdev_mc_count(dev); pr_debug("%s: setting Rx mode to %d addresses.\n", dev->name, old); } @@ -1490,13 +1490,13 @@ static void set_multicast_list(struct net_device *dev) #endif /* Set multicast_num_addrs. */ - lp->multicast_num_addrs = dev->mc_count; + lp->multicast_num_addrs = netdev_mc_count(dev); /* Set multicast_ladrf. */ if (num_addrs > 0) { /* Calculate multicast logical address filter */ memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN); dmi = dmi->next; BuildLAF(lp->multicast_ladrf, adr); @@ -1537,15 +1537,15 @@ static void set_multicast_list(struct net_device *dev) #ifdef PCMCIA_DEBUG { static int old; - if (dev->mc_count != old) { - old = dev->mc_count; + if (netdev_mc_count(dev) != old) { + old = netdev_mc_count(dev); pr_debug("%s: setting Rx mode to %d addresses.\n", dev->name, old); } } #endif - lp->multicast_num_addrs = dev->mc_count; + lp->multicast_num_addrs = netdev_mc_count(dev); restore_multicast_list(dev); } /* set_multicast_list */ diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 6dd486d2977b..d2e86b8887c8 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1638,8 +1638,8 @@ static void set_rx_mode(struct net_device *dev) } else if (dev->flags & IFF_ALLMULTI) rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti; else { - if (dev->mc_count) { - fill_multicast_tbl(dev->mc_count, dev->mc_list, + if (!netdev_mc_empty(dev)) { + fill_multicast_tbl(netdev_mc_count(dev), dev->mc_list, (u_char *)multicast_table); } rx_cfg_setting = RxStripCRC | RxEnable; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 466fc72698c0..4ace18a71152 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1384,7 +1384,7 @@ set_addresses(struct net_device *dev) if (++n > 9) break; i = 0; - if (n > 1 && n <= dev->mc_count && dmi) { + if (n > 1 && n <= netdev_mc_count(dev) && dmi) { dmi = dmi->next; } } @@ -1394,7 +1394,7 @@ set_addresses(struct net_device *dev) SelectPage(k); } - if (n && n <= dev->mc_count && dmi) + if (n && n <= netdev_mc_count(dev) && dmi) addr = dmi->dmi_addr; else addr = dev->dev_addr; @@ -1424,9 +1424,9 @@ set_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* snoop */ PutByte(XIRCREG42_SWC1, value | 0x06); /* set MPE and PME */ - } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) { + } else if (netdev_mc_count(dev) > 9 || (dev->flags & IFF_ALLMULTI)) { PutByte(XIRCREG42_SWC1, value | 0x02); /* set MPE */ - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { /* the chip can filter 9 addresses perfectly */ PutByte(XIRCREG42_SWC1, value | 0x01); SelectPage(0x40); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 0dc7ff896eeb..3522794550dd 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2698,7 +2698,7 @@ static void pcnet32_load_multicast(struct net_device *dev) ib->filter[1] = 0; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 0c768593aad0..c19dd4a6cd76 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -568,7 +568,7 @@ void gelic_net_set_multi(struct net_device *netdev) status); if ((netdev->flags & IFF_ALLMULTI) || - (netdev->mc_count > GELIC_NET_MC_COUNT_MAX)) { + (netdev_mc_count(netdev) > GELIC_NET_MC_COUNT_MAX)) { status = lv1_net_add_multicast_address(bus_id(card), dev_id(card), 0, 1); diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index dc6cd69d6d93..8ea7f869e293 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -447,12 +447,12 @@ void qlcnic_set_multi(struct net_device *netdev) } if ((netdev->flags & IFF_ALLMULTI) || - (netdev->mc_count > adapter->max_mc_count)) { + (netdev_mc_count(netdev) > adapter->max_mc_count)) { mode = VPORT_MISS_MODE_ACCEPT_MULTI; goto send_fw_cmd; } - if (netdev->mc_count > 0) { + if (!netdev_mc_empty(netdev)) { for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr, diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 3cb60e10d456..dd3e0f1b2965 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4221,7 +4221,7 @@ static void qlge_set_multicast_list(struct net_device *ndev) * transition is taking place. */ if ((ndev->flags & IFF_ALLMULTI) || - (ndev->mc_count > MAX_MULTICAST_ENTRIES)) { + (netdev_mc_count(ndev) > MAX_MULTICAST_ENTRIES)) { if (!test_bit(QL_ALLMULTI, &qdev->flags)) { if (ql_set_routing_reg (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 1)) { @@ -4243,7 +4243,7 @@ static void qlge_set_multicast_list(struct net_device *ndev) } } - if (ndev->mc_count) { + if (!netdev_mc_empty(ndev)) { status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) goto exit; diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index d68ba7a58631..b8103425facb 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -958,21 +958,22 @@ static void r6040_multicast_list(struct net_device *dev) } /* Too many multicast addresses * accept all traffic */ - else if ((dev->mc_count > MCAST_MAX) || (dev->flags & IFF_ALLMULTI)) + else if ((netdev_mc_count(dev) > MCAST_MAX) || + (dev->flags & IFF_ALLMULTI)) reg |= 0x0020; iowrite16(reg, ioaddr); spin_unlock_irqrestore(&lp->lock, flags); /* Build the hash table */ - if (dev->mc_count > MCAST_MAX) { + if (netdev_mc_count(dev) > MCAST_MAX) { u16 hash_table[4]; u32 crc; for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { char *addrs = dmi->dmi_addr; dmi = dmi->next; @@ -994,14 +995,14 @@ static void r6040_multicast_list(struct net_device *dev) iowrite16(hash_table[3], ioaddr + MAR3); } /* Multicast Address 1~4 case */ - for (i = 0, dmi; (i < dev->mc_count) && (i < MCAST_MAX); i++) { + for (i = 0, dmi; (i < netdev_mc_count(dev)) && (i < MCAST_MAX); i++) { adrp = (u16 *)dmi->dmi_addr; iowrite16(adrp[0], ioaddr + MID_1L + 8*i); iowrite16(adrp[1], ioaddr + MID_1M + 8*i); iowrite16(adrp[2], ioaddr + MID_1H + 8*i); dmi = dmi->next; } - for (i = dev->mc_count; i < MCAST_MAX; i++) { + for (i = netdev_mc_count(dev); i < MCAST_MAX; i++) { iowrite16(0xffff, ioaddr + MID_0L + 8*i); iowrite16(0xffff, ioaddr + MID_0M + 8*i); iowrite16(0xffff, ioaddr + MID_0H + 8*i); diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c1bb24cf0793..85c635f354b5 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4758,7 +4758,7 @@ static void rtl_set_rx_mode(struct net_device *dev) AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; @@ -4769,7 +4769,7 @@ static void rtl_set_rx_mode(struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index d1664586e8ff..102be16e9b52 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5055,8 +5055,8 @@ static void s2io_set_multicast(struct net_device *dev) } /* Update individual M_CAST address list */ - if ((!sp->m_cast_flg) && dev->mc_count) { - if (dev->mc_count > + if ((!sp->m_cast_flg) && netdev_mc_count(dev)) { + if (netdev_mc_count(dev) > (config->max_mc_addr - config->max_mac_addr)) { DBG_PRINT(ERR_DBG, "%s: No more Rx filters can be added - " @@ -5066,7 +5066,7 @@ static void s2io_set_multicast(struct net_device *dev) } prev_cnt = sp->mc_addr_count; - sp->mc_addr_count = dev->mc_count; + sp->mc_addr_count = netdev_mc_count(dev); /* Clear out the previous list of Mc in the H/W. */ for (i = 0; i < prev_cnt; i++) { @@ -5092,7 +5092,7 @@ static void s2io_set_multicast(struct net_device *dev) } /* Create the new Rx filter list and update the same in H/W. */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); i++, mclist = mclist->next) { memcpy(sp->usr_addrs[i].addr, mclist->dmi_addr, ETH_ALEN); diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index fd8cb506a2bb..00ff8995ad69 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -429,7 +429,7 @@ static void _sc92031_set_mar(struct net_device *dev) u32 mar0 = 0, mar1 = 0; if ((dev->flags & IFF_PROMISC) || - dev->mc_count > multicast_filter_limit || + netdev_mc_count(dev) > multicast_filter_limit || (dev->flags & IFF_ALLMULTI)) mar0 = mar1 = 0xffffffff; else if (dev->flags & IFF_MULTICAST) { diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 62d5cd51a9dd..fafaf30ecd9a 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1615,7 +1615,7 @@ static void efx_set_multicast_list(struct net_device *net_dev) memset(mc_hash, 0xff, sizeof(*mc_hash)); } else { memset(mc_hash, 0x00, sizeof(*mc_hash)); - for (i = 0; i < net_dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(net_dev); i++) { crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr); bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); set_bit_le(bit, mc_hash->byte); diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 6b364a6c6c60..ed999d31f1fa 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -660,7 +660,7 @@ static void sgiseeq_set_multicast(struct net_device *dev) if(dev->flags & IFF_PROMISC) sp->mode = SEEQ_RCMD_RANY; - else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count) + else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) sp->mode = SEEQ_RCMD_RBMCAST; else sp->mode = SEEQ_RCMD_RBCAST; diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 626de766443a..8c4e38f9ebf7 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -841,7 +841,7 @@ static void sis190_set_rx_mode(struct net_device *dev) AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; @@ -852,7 +852,7 @@ static void sis190_set_rx_mode(struct net_device *dev) rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 20c5ce474891..32ae87c09f5e 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -2288,7 +2288,7 @@ static void set_rx_mode(struct net_device *net_dev) rx_mode = RFPromiscuous; for (i = 0; i < table_entries; i++) mc_filter[i] = 0xffff; - } else if ((net_dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(net_dev) > multicast_filter_limit) || (net_dev->flags & IFF_ALLMULTI)) { /* too many multicast addresses or accept all multicast packet */ rx_mode = RFAAB | RFAAM; @@ -2301,7 +2301,7 @@ static void set_rx_mode(struct net_device *net_dev) struct dev_mc_list *mclist; rx_mode = RFAAB; for (i = 0, mclist = net_dev->mc_list; - mclist && i < net_dev->mc_count; + mclist && i < netdev_mc_count(net_dev); i++, mclist = mclist->next) { unsigned int bit_nr = sis900_mcast_bitnr(mclist->dmi_addr, sis_priv->chipset_rev); diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 6b955a4f19b2..346adfae986f 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -872,14 +872,14 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { mac_drv_rx_mode(smc, RX_ENABLE_ALLMULTI); pr_debug(KERN_INFO "ENABLE ALL MC ADDRESSES\n"); - } else if (dev->mc_count > 0) { - if (dev->mc_count <= FPMAX_MULTICAST) { + } else if (!netdev_mc_empty(dev)) { + if (netdev_mc_count(dev) <= FPMAX_MULTICAST) { /* use exact filtering */ // point to first multicast addr dmi = dev->mc_list; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { mac_add_multicast(smc, (struct fddi_addr *)dmi->dmi_addr, 1); diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5ff46eb18d0c..36ead52dea71 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2932,7 +2932,7 @@ static void genesis_set_multicast(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - int i, count = dev->mc_count; + int i, count = netdev_mc_count(dev); struct dev_mc_list *list = dev->mc_list; u32 mode; u8 filter[8]; @@ -2987,7 +2987,7 @@ static void yukon_set_multicast(struct net_device *dev) reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); else if (dev->flags & IFF_ALLMULTI) /* all multicast */ memset(filter, 0xff, sizeof(filter)); - else if (dev->mc_count == 0 && !rx_pause)/* no multicast */ + else if (netdev_mc_empty(dev) && !rx_pause)/* no multicast */ reg &= ~GM_RXCR_MCF_ENA; else { int i; @@ -2996,7 +2996,7 @@ static void yukon_set_multicast(struct net_device *dev) if (rx_pause) yukon_add_filter(filter, pause_mc_addr); - for (i = 0; list && i < dev->mc_count; i++, list = list->next) + for (i = 0; list && i < netdev_mc_count(dev); i++, list = list->next) yukon_add_filter(filter, list->dmi_addr); } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 478288b8bc21..45299d663498 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3626,7 +3626,7 @@ static void sky2_set_multicast(struct net_device *dev) reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); else if (dev->flags & IFF_ALLMULTI) memset(filter, 0xff, sizeof(filter)); - else if (dev->mc_count == 0 && !rx_pause) + else if (netdev_mc_empty(dev) && !rx_pause) reg &= ~GM_RXCR_MCF_ENA; else { int i; @@ -3635,7 +3635,7 @@ static void sky2_set_multicast(struct net_device *dev) if (rx_pause) sky2_add_filter(filter, pause_mc_addr); - for (i = 0; list && i < dev->mc_count; i++, list = list->next) + for (i = 0; list && i < netdev_mc_count(dev); i++, list = list->next) sky2_add_filter(filter, list->dmi_addr); } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 3c5a4f52345c..ef9674c6713f 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1323,7 +1323,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) * I don't need to zero the multicast table, because the flag is * checked before the table is */ - else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + else if (dev->flags & IFF_ALLMULTI || netdev_mc_count(dev) > 16) { DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name); mcr |= MAC_CR_MCPAS_; } @@ -1340,7 +1340,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) * the number of the 32 bit register, while the low 5 bits are the bit * within that register. */ - else if (dev->mc_count) { + else if (!netdev_mc_empty(dev)) { int i; struct dev_mc_list *cur_addr; @@ -1351,7 +1351,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) memset(multicast_table, 0, sizeof(multicast_table)); cur_addr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { u32 position; /* do we have a pointer here? */ diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 8371b82323ac..41c3dddeab50 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -1542,7 +1542,7 @@ static void smc_set_multicast_list(struct net_device *dev) /* We just get all multicast packets even if we only want them . from one source. This will be changed at some future . point. */ - else if (dev->mc_count ) { + else if (!netdev_mc_empty(dev)) { /* support hardware multicasting */ /* be sure I get rid of flags I might have set */ @@ -1550,7 +1550,7 @@ static void smc_set_multicast_list(struct net_device *dev) ioaddr + RCR ); /* NOTE: this has to set the bank, so make sure it is the last thing called. The bank is set to zero at the top */ - smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list ); + smc_setmulticast(ioaddr, netdev_mc_count(dev), dev->mc_list); } else { outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index ea4fae79d6ec..66450127c5a1 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1395,7 +1395,7 @@ static void smc_set_multicast_list(struct net_device *dev) * I don't need to zero the multicast table, because the flag is * checked before the table is */ - else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + else if (dev->flags & IFF_ALLMULTI || netdev_mc_count(dev) > 16) { DBG(2, "%s: RCR_ALMUL\n", dev->name); lp->rcr_cur_mode |= RCR_ALMUL; } @@ -1412,7 +1412,7 @@ static void smc_set_multicast_list(struct net_device *dev) * the number of the 8 bit register, while the low 3 bits are the bit * within that register. */ - else if (dev->mc_count) { + else if (!netdev_mc_empty(dev)) { int i; struct dev_mc_list *cur_addr; @@ -1423,7 +1423,7 @@ static void smc_set_multicast_list(struct net_device *dev) memset(multicast_table, 0, sizeof(multicast_table)); cur_addr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { int position; /* do we have a pointer here? */ diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 494cd91ea39c..3c1f9aa84cf5 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1383,7 +1383,7 @@ static void smsc911x_set_multicast_list(struct net_device *dev) pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_HPFILT_); pdata->hashhi = 0; pdata->hashlo = 0; - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { /* Enabling specific multicast addresses */ unsigned int hash_high = 0; unsigned int hash_low = 0; @@ -1408,7 +1408,7 @@ static void smsc911x_set_multicast_list(struct net_device *dev) } mc_list = mc_list->next; } - if (count != (unsigned int)dev->mc_count) + if (count != (unsigned int)netdev_mc_count(dev)) SMSC_WARNING(DRV, "mc_count != dev->mc_count"); pdata->hashhi = hash_high; diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 1495a5dd4b46..2bd3c986559a 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1062,7 +1062,7 @@ static void smsc9420_set_multicast_list(struct net_device *dev) mac_cr &= (~MAC_CR_PRMS_); mac_cr |= MAC_CR_MCPAS_; mac_cr &= (~MAC_CR_HPFILT_); - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { struct dev_mc_list *mc_list = dev->mc_list; u32 hash_lo = 0, hash_hi = 0; diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index 9599ce77ef85..bd8bc66f2e00 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -541,13 +541,15 @@ static void sonic_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ rcr |= SONIC_RCR_PRO; } else { - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 15)) { + if ((dev->flags & IFF_ALLMULTI) || + (netdev_mc_count(dev) > 15)) { rcr |= SONIC_RCR_AMC; } else { if (sonic_debug > 2) - printk("sonic_multicast_list: mc_count %d\n", dev->mc_count); + printk("sonic_multicast_list: mc_count %d\n", + netdev_mc_count(dev)); sonic_set_cam_enable(dev, 1); /* always enable our own address */ - for (i = 1; i <= dev->mc_count; i++) { + for (i = 1; i <= netdev_mc_count(dev); i++) { addr = dmi->dmi_addr; dmi = dmi->next; sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]); diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index d0556a9b456c..58bc7ac086cf 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1796,15 +1796,15 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ rx_mode |= AcceptAll; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ rx_mode |= AcceptBroadcast|AcceptAllMulticast|PerfectFilter; - } else if (dev->mc_count <= 14) { + } else if (netdev_mc_count(dev) <= 14) { /* Use the 16 element perfect filter, skip first two entries. */ void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16; __be16 *eaddrs; - for (i = 2, mclist = dev->mc_list; mclist && i < dev->mc_count + 2; + for (i = 2, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev) + 2; i++, mclist = mclist->next) { eaddrs = (__be16 *)mclist->dmi_addr; writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4; @@ -1825,7 +1825,7 @@ static void set_rx_mode(struct net_device *dev) __le16 mc_filter[32] __attribute__ ((aligned(sizeof(long)))); /* Multicast hash filter */ memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { /* The chip uses the upper 9 CRC bits as index into the hash table */ diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c index ac48ed787040..576b256ee388 100644 --- a/drivers/net/stmmac/dwmac100.c +++ b/drivers/net/stmmac/dwmac100.c @@ -305,13 +305,13 @@ static void dwmac100_set_filter(struct net_device *dev) value |= MAC_CONTROL_PR; value &= ~(MAC_CONTROL_PM | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); - } else if ((dev->mc_count > HASH_TABLE_SIZE) + } else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) || (dev->flags & IFF_ALLMULTI)) { value |= MAC_CONTROL_PM; value &= ~(MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO); writel(0xffffffff, ioaddr + MAC_HASH_HIGH); writel(0xffffffff, ioaddr + MAC_HASH_LOW); - } else if (dev->mc_count == 0) { /* no multicast */ + } else if (netdev_mc_empty(dev)) { /* no multicast */ value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else { @@ -327,7 +327,7 @@ static void dwmac100_set_filter(struct net_device *dev) memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; - mclist && i < dev->mc_count; i++, mclist = mclist->next) { + mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { /* The upper 6 bits of the calculated CRC are used to * index the contens of the hash table */ int bit_nr = diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index d812e9cdb3db..90dbb4f41ef3 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -83,16 +83,16 @@ static void dwmac1000_set_filter(struct net_device *dev) unsigned int value = 0; DBG(KERN_INFO "%s: # mcasts %d, # unicast %d\n", - __func__, dev->mc_count, netdev_uc_count(dev)); + __func__, netdev_mc_count(dev), netdev_uc_count(dev)); if (dev->flags & IFF_PROMISC) value = GMAC_FRAME_FILTER_PR; - else if ((dev->mc_count > HASH_TABLE_SIZE) + else if ((netdev_mc_count(dev) > HASH_TABLE_SIZE) || (dev->flags & IFF_ALLMULTI)) { value = GMAC_FRAME_FILTER_PM; /* pass all multi */ writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); writel(0xffffffff, ioaddr + GMAC_HASH_LOW); - } else if (dev->mc_count > 0) { + } else if (!netdev_mc_empty(dev)) { int i; u32 mc_filter[2]; struct dev_mc_list *mclist; @@ -102,7 +102,7 @@ static void dwmac1000_set_filter(struct net_device *dev) memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; - mclist && i < dev->mc_count; i++, mclist = mclist->next) { + mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { /* The upper 6 bits of the calculated CRC are used to index the contens of the hash table */ int bit_nr = diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index b447a8719427..efedc252e4be 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -414,7 +414,7 @@ static int init586(struct net_device *dev) volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; struct dev_mc_list *dmi=dev->mc_list; - int num_addrs=dev->mc_count; + int num_addrs=netdev_mc_count(dev); ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 0ca4241b4f63..99998862c22e 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -917,7 +917,7 @@ static void set_multicast_list( struct net_device *dev ) REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ } else { short multicast_table[4]; - int num_addrs = dev->mc_count; + int num_addrs = netdev_mc_count(dev); int i; /* We don't use the multicast table, but rely on upper-layer * filtering. */ diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 25e81ebd9cd8..dfea56fa39e3 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -1013,7 +1013,7 @@ static void bigmac_set_multicast(struct net_device *dev) while ((sbus_readl(bregs + BMAC_RXCFG) & BIGMAC_RXCFG_ENABLE) != 0) udelay(20); - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) { sbus_writel(0xffff, bregs + BMAC_HTABLE0); sbus_writel(0xffff, bregs + BMAC_HTABLE1); sbus_writel(0xffff, bregs + BMAC_HTABLE2); @@ -1028,7 +1028,7 @@ static void bigmac_set_multicast(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 0c972e560cf3..4171259590b2 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1517,18 +1517,18 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = AcceptBroadcast | AcceptMulticast | AcceptAll | AcceptMyPhys; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { struct dev_mc_list *mclist; int bit; int index; int crc; memset (mc_filter, 0, sizeof (mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); for (index=0, bit=0; bit < 6; bit++, crc <<= 1) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index b55ceb88d93f..d497ec053953 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1837,7 +1837,7 @@ static u32 gem_setup_multicast(struct gem *gp) int i; if ((gp->dev->flags & IFF_ALLMULTI) || - (gp->dev->mc_count > 256)) { + (netdev_mc_count(gp->dev) > 256)) { for (i=0; i<16; i++) writel(0xffff, gp->regs + MAC_HASH0 + (i << 2)); rxcfg |= MAC_RXCFG_HFE; @@ -1852,7 +1852,7 @@ static u32 gem_setup_multicast(struct gem *gp) for (i = 0; i < 16; i++) hash_table[i] = 0; - for (i = 0; i < gp->dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(gp->dev); i++) { char *addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 76ccd31cbf50..905df35ff78a 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1516,7 +1516,7 @@ static int happy_meal_init(struct happy_meal *hp) HMD(("htable, ")); if ((hp->dev->flags & IFF_ALLMULTI) || - (hp->dev->mc_count > 64)) { + (netdev_mc_count(hp->dev) > 64)) { hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff); @@ -1531,7 +1531,7 @@ static int happy_meal_init(struct happy_meal *hp) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < hp->dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(hp->dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; @@ -2373,7 +2373,7 @@ static void happy_meal_set_multicast(struct net_device *dev) spin_lock_irq(&hp->happy_lock); - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) { hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff); hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff); @@ -2387,7 +2387,7 @@ static void happy_meal_set_multicast(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 64e7d08c878f..cf9d5bb9e1e9 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1196,7 +1196,7 @@ static void lance_load_multicast(struct net_device *dev) return; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 45c383f285ee..3bc35d86ed66 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -636,7 +636,7 @@ static void qe_set_multicast(struct net_device *dev) /* Lock out others. */ netif_stop_queue(dev); - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) { + if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 64)) { sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET, qep->mregs + MREGS_IACONFIG); while ((sbus_readb(qep->mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0) @@ -653,7 +653,7 @@ static void qe_set_multicast(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { addrs = dmi->dmi_addr; dmi = dmi->next; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 033408f589fb..d838d4015c63 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1941,18 +1941,18 @@ tc35815_set_multicast_list(struct net_device *dev) /* Enable promiscuous mode */ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc | CAM_StationAcc, &tr->CAM_Ctl); } else if ((dev->flags & IFF_ALLMULTI) || - dev->mc_count > CAM_ENTRY_MAX - 3) { + netdev_mc_count(dev) > CAM_ENTRY_MAX - 3) { /* CAM 0, 1, 20 are reserved. */ /* Disable promiscuous mode, use normal mode. */ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl); - } else if (dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { struct dev_mc_list *cur_addr = dev->mc_list; int i; int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE); tc_writel(0, &tr->CAM_Ctl); /* Walk the address list, and load the filter */ - for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { if (!cur_addr) break; /* entry 0,1 is reserved. */ diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index b907bee31fd5..ab9b0280317e 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -808,7 +808,7 @@ static void bdx_setmulti(struct net_device *ndev) /* set IMF to accept all multicast frmaes */ for (i = 0; i < MAC_MCST_HASH_NUM; i++) WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, ~0); - } else if (ndev->mc_count) { + } else if (!netdev_mc_empty(ndev)) { u8 hash; struct dev_mc_list *mclist; u32 reg, val; @@ -840,7 +840,7 @@ static void bdx_setmulti(struct net_device *ndev) } } else { - DBG("only own mac %d\n", ndev->mc_count); + DBG("only own mac %d\n", netdev_mc_count(ndev)); rxf_val |= GMAC_RX_FILTER_AB; } WRITE_REG(priv, regGMAC_RXF_A, rxf_val); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7195bdec17f3..d29282f01c23 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9430,7 +9430,7 @@ static void __tg3_set_rx_mode(struct net_device *dev) } else if (dev->flags & IFF_ALLMULTI) { /* Accept all multicast. */ tg3_set_multi (tp, 1); - } else if (dev->mc_count < 1) { + } else if (netdev_mc_empty(dev)) { /* Reject all multicast. */ tg3_set_multi (tp, 0); } else { @@ -9442,7 +9442,7 @@ static void __tg3_set_rx_mode(struct net_device *dev) u32 bit; u32 crc; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { crc = calc_crc (mclist->dmi_addr, ETH_ALEN); diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 3ec31dce99f9..e44d5a074c69 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1335,7 +1335,7 @@ static void TLan_SetMulticastList( struct net_device *dev ) TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF ); TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF ); } else { - for ( i = 0; i < dev->mc_count; i++ ) { + for ( i = 0; i < netdev_mc_count(dev); i++ ) { if ( i < 3 ) { TLan_SetMac( dev, i + 1, (char *) &dmi->dmi_addr ); diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index b0d7db9d8bb4..eff68e1d107b 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -1408,7 +1408,7 @@ static void xl_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { + for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 66272f2a0758..1ce8f85a89aa 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -996,7 +996,7 @@ static void tok_set_multicast_list(struct net_device *dev) if (/*BMSHELPdev->start == 0 ||*/ ti->open_status != OPEN) return; address[0] = address[1] = address[2] = address[3] = 0; mclist = dev->mc_list; - for (i = 0; i < dev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(dev); i++) { address[0] |= mclist->dmi_addr[2]; address[1] |= mclist->dmi_addr[3]; address[2] |= mclist->dmi_addr[4]; diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 3f9d5a25562e..26d84daf660b 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -1303,7 +1303,7 @@ static void streamer_set_rx_mode(struct net_device *dev) writel(streamer_priv->srb,streamer_mmio+LAPA); dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) + for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index f010a4dc5f19..a242d125b34c 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1178,7 +1178,7 @@ static void olympic_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { + for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index e3c42f5ac4a9..6b8868959b85 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -1214,7 +1214,7 @@ static void tms380tr_set_multicast_list(struct net_device *dev) { int i; struct dev_mc_list *mclist = dev->mc_list; - for (i=0; i< dev->mc_count; i++) + for (i=0; i< netdev_mc_count(dev); i++) { ((char *)(&tp->ocpl.FunctAddr))[0] |= mclist->dmi_addr[2]; diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index a69c4a48bab9..f4b30c4826fb 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1184,7 +1184,7 @@ static void tsi108_set_rx_mode(struct net_device *dev) rxcfg &= ~(TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE); - if (dev->flags & IFF_ALLMULTI || dev->mc_count) { + if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { int i; struct dev_mc_list *mc = dev->mc_list; rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 29330209ad8b..a4cff23dcdf9 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -677,7 +677,7 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; @@ -706,7 +706,7 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); i++, mclist = mclist->next) { eaddrs = (u16 *)mclist->dmi_addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; @@ -741,7 +741,7 @@ static void __de_set_rx_mode (struct net_device *dev) goto out; } - if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + if ((netdev_mc_count(dev) > 1000) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well -- accept all multicasts. */ macmode |= AcceptAllMulticast; goto out; @@ -749,7 +749,7 @@ static void __de_set_rx_mode (struct net_device *dev) /* Note that only the low-address shortword of setup_frame is valid! The values are doubled for big-endian architectures. */ - if (dev->mc_count > 14) /* Must use a multicast hash table. */ + if (netdev_mc_count(dev) > 14) /* Must use a multicast hash table. */ build_setup_frame_hash (de->setup_frame, dev); else build_setup_frame_perfect (de->setup_frame, dev); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index a8349b7200b5..0b6a9731091c 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1963,10 +1963,10 @@ SetMulticastFilter(struct net_device *dev) omr &= ~(OMR_PR | OMR_PM); pa = build_setup_frame(dev, ALL); /* Build the basic frame */ - if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) { + if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 14)) { omr |= OMR_PM; /* Pass all multicasts */ } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */ - for (i=0;imc_count;i++) { /* for each address in the list */ + for (i = 0; i < netdev_mc_count(dev) ;i++) { addrs=dmi->dmi_addr; dmi=dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ @@ -1984,7 +1984,7 @@ SetMulticastFilter(struct net_device *dev) } } } else { /* Perfect filtering */ - for (j=0; jmc_count; j++) { + for (j=0; jdmi_addr; dmi=dmi->next; for (i=0; ichip_id == PCI_DM9132_ID) - dm9132_id_table(dev, dev->mc_count); /* DM9132 */ + dm9132_id_table(dev, netdev_mc_count(dev)); /* DM9132 */ else - send_filter_frame(dev, dev->mc_count); /* DM9102/DM9102A */ + send_filter_frame(dev, netdev_mc_count(dev)); /* DM9102/DM9102A */ /* Init CR7, interrupt active bit */ db->cr7_data = CR7_DEFAULT; @@ -1052,6 +1052,7 @@ static void dmfe_set_filter_mode(struct DEVICE * dev) { struct dmfe_board_info *db = netdev_priv(dev); unsigned long flags; + int mc_count = netdev_mc_count(dev); DMFE_DBUG(0, "dmfe_set_filter_mode()", 0); spin_lock_irqsave(&db->lock, flags); @@ -1064,19 +1065,19 @@ static void dmfe_set_filter_mode(struct DEVICE * dev) return; } - if (dev->flags & IFF_ALLMULTI || dev->mc_count > DMFE_MAX_MULTICAST) { - DMFE_DBUG(0, "Pass all multicast address", dev->mc_count); + if (dev->flags & IFF_ALLMULTI || mc_count > DMFE_MAX_MULTICAST) { + DMFE_DBUG(0, "Pass all multicast address", mc_count); db->cr6_data &= ~(CR6_PM | CR6_PBF); db->cr6_data |= CR6_PAM; spin_unlock_irqrestore(&db->lock, flags); return; } - DMFE_DBUG(0, "Set multicast address", dev->mc_count); + DMFE_DBUG(0, "Set multicast address", mc_count); if (db->chip_id == PCI_DM9132_ID) - dm9132_id_table(dev, dev->mc_count); /* DM9132 */ + dm9132_id_table(dev, mc_count); /* DM9132 */ else - send_filter_frame(dev, dev->mc_count); /* DM9102/DM9102A */ + send_filter_frame(dev, mc_count); /* DM9102/DM9102A */ spin_unlock_irqrestore(&db->lock, flags); } diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index e1a5f03a49c5..cce2ada07950 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -997,7 +997,7 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; @@ -1026,7 +1026,7 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); i++, mclist = mclist->next) { eaddrs = (u16 *)mclist->dmi_addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; @@ -1057,7 +1057,8 @@ static void set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ tp->csr6 |= AcceptAllMulticast | AcceptAllPhys; csr6 |= AcceptAllMulticast | AcceptAllPhys; - } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { + } else if ((netdev_mc_count(dev) > 1000) || + (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well -- accept all multicasts. */ tp->csr6 |= AcceptAllMulticast; csr6 |= AcceptAllMulticast; @@ -1066,14 +1067,16 @@ static void set_rx_mode(struct net_device *dev) /* Should verify correctness on big-endian/__powerpc__ */ struct dev_mc_list *mclist; int i; - if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ + if (netdev_mc_count(dev) > 64) { + /* Arbitrary non-effective limit. */ tp->csr6 |= AcceptAllMulticast; csr6 |= AcceptAllMulticast; } else { u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ int filterbit; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + for (i = 0, mclist = dev->mc_list; + mclist && i < netdev_mc_count(dev); + i++, mclist = mclist->next) { if (tp->flags & COMET_MAC_ADDR) filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr); else @@ -1107,7 +1110,8 @@ static void set_rx_mode(struct net_device *dev) /* Note that only the low-address shortword of setup_frame is valid! The values are doubled for big-endian architectures. */ - if (dev->mc_count > 14) { /* Must use a multicast hash table. */ + if (netdev_mc_count(dev) > 14) { + /* Must use a multicast hash table. */ build_setup_frame_hash(tp->setup_frame, dev); tx_flags = 0x08400000 | 192; } else { diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index dc3335d906f6..216ceb322ed4 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -557,7 +557,7 @@ static void uli526x_init(struct net_device *dev) update_cr6(db->cr6_data, ioaddr); /* Send setup frame */ - send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */ + send_filter_frame(dev, netdev_mc_count(dev)); /* M5261/M5263 */ /* Init CR7, interrupt active bit */ db->cr7_data = CR7_DEFAULT; @@ -906,16 +906,18 @@ static void uli526x_set_filter_mode(struct net_device * dev) return; } - if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) { - ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count); + if (dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev) > ULI5261_MAX_MULTICAST) { + ULI526X_DBUG(0, "Pass all multicast address", + netdev_mc_count(dev)); db->cr6_data &= ~(CR6_PM | CR6_PBF); db->cr6_data |= CR6_PAM; spin_unlock_irqrestore(&db->lock, flags); return; } - ULI526X_DBUG(0, "Set multicast address", dev->mc_count); - send_filter_frame(dev, dev->mc_count); /* M5261/M5263 */ + ULI526X_DBUG(0, "Set multicast address", netdev_mc_count(dev)); + send_filter_frame(dev, netdev_mc_count(dev)); /* M5261/M5263 */ spin_unlock_irqrestore(&db->lock, flags); } diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 9fb89afccf7c..98711a9f35ac 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1361,7 +1361,7 @@ static u32 __set_rx_mode(struct net_device *dev) memset(mc_filter, 0xff, sizeof(mc_filter)); rx_mode = RxAcceptBroadcast | AcceptMulticast | RxAcceptAllPhys | AcceptMyPhys; - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); @@ -1370,8 +1370,9 @@ static u32 __set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + for (i = 0, mclist = dev->mc_list; + mclist && i < netdev_mc_count(dev); + i++, mclist = mclist->next) { int filterbit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; filterbit &= 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 6e4f754c4baf..edabc49a49bc 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -924,17 +924,18 @@ typhoon_set_rx_mode(struct net_device *dev) filter = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST; if(dev->flags & IFF_PROMISC) { filter |= TYPHOON_RX_FILTER_PROMISCOUS; - } else if((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ filter |= TYPHOON_RX_FILTER_ALL_MCAST; - } else if(dev->mc_count) { + } else if (!netdev_mc_empty(dev)) { struct dev_mc_list *mclist; int i; memset(mc_filter, 0, sizeof(mc_filter)); - for(i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { + for (i = 0, mclist = dev->mc_list; + mclist && i < netdev_mc_count(dev); + i++, mclist = mclist->next) { int bit = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; mc_filter[bit >> 5] |= 1 << (bit & 0x1f); } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 225f65812f2e..a05720289c7e 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2031,7 +2031,8 @@ static void ucc_geth_set_multi(struct net_device *dev) dmi = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) { + for (i = 0; i < netdev_mc_count(dev); + i++, dmi = dmi->next) { /* Only support group multicast for now. */ diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index a516185cbc9f..f02551713b13 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -542,9 +542,9 @@ static void asix_set_multicast(struct net_device *net) if (net->flags & IFF_PROMISC) { rx_ctl |= AX_RX_CTL_PRO; } else if (net->flags & IFF_ALLMULTI || - net->mc_count > AX_MAX_MCAST) { + netdev_mc_count(net) > AX_MAX_MCAST) { rx_ctl |= AX_RX_CTL_AMALL; - } else if (net->mc_count == 0) { + } else if (netdev_mc_empty(net)) { /* just broadcast and directed */ } else { /* We use the 20 byte dev->data @@ -558,7 +558,7 @@ static void asix_set_multicast(struct net_device *net) memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - for (i = 0; i < net->mc_count; i++) { + for (i = 0; i < netdev_mc_count(net); i++) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; @@ -754,9 +754,9 @@ static void ax88172_set_multicast(struct net_device *net) if (net->flags & IFF_PROMISC) { rx_ctl |= 0x01; } else if (net->flags & IFF_ALLMULTI || - net->mc_count > AX_MAX_MCAST) { + netdev_mc_count(net) > AX_MAX_MCAST) { rx_ctl |= 0x02; - } else if (net->mc_count == 0) { + } else if (netdev_mc_empty(net)) { /* just broadcast and directed */ } else { /* We use the 20 byte dev->data @@ -770,7 +770,7 @@ static void ax88172_set_multicast(struct net_device *net) memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - for (i = 0; i < net->mc_count; i++) { + for (i = 0; i < netdev_mc_count(net); i++) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 7d3fa06980c1..5a13660ebd17 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -648,7 +648,9 @@ static void catc_set_multicast_list(struct net_device *netdev) if (netdev->flags & IFF_ALLMULTI) { memset(catc->multicast, 0xff, 64); } else { - for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) { + for (i = 0, mc = netdev->mc_list; + mc && i < netdev_mc_count(netdev); + i++, mc = mc->next) { u32 crc = ether_crc_le(6, mc->dmi_addr); if (!catc->is_f5u011) { catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c index 55cf7081de10..9ab5c1983a7d 100644 --- a/drivers/net/usb/int51x1.c +++ b/drivers/net/usb/int51x1.c @@ -139,7 +139,7 @@ static void int51x1_set_multicast(struct net_device *netdev) /* do not expect to see traffic of other PLCs */ filter |= PACKET_TYPE_PROMISCUOUS; devinfo(dev, "promiscuous mode enabled"); - } else if (netdev->mc_count || + } else if (!netdev_mc_empty(netdev) || (netdev->flags & IFF_ALLMULTI)) { filter |= PACKET_TYPE_ALL_MULTICAST; devdbg(dev, "receive all multicast enabled"); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index f1d64ef67efa..52671ea043a7 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -881,7 +881,7 @@ static void kaweth_set_rx_mode(struct net_device *net) if (net->flags & IFF_PROMISC) { packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS; } - else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) { + else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) { packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST; } diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 6fc098fe9ff7..34665137f2c3 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -443,9 +443,9 @@ static void mcs7830_data_set_multicast(struct net_device *net) if (net->flags & IFF_PROMISC) { data->config |= HIF_REG_CONFIG_PROMISCUOUS; } else if (net->flags & IFF_ALLMULTI || - net->mc_count > MCS7830_MAX_MCAST) { + netdev_mc_count(net) > MCS7830_MAX_MCAST) { data->config |= HIF_REG_CONFIG_ALLMULTICAST; - } else if (net->mc_count == 0) { + } else if (netdev_mc_empty(net)) { /* just broadcast and directed */ } else { /* We use the 20 byte dev->data @@ -457,7 +457,7 @@ static void mcs7830_data_set_multicast(struct net_device *net) int i; /* Build the multicast hash filter. */ - for (i = 0; i < net->mc_count; i++) { + for (i = 0; i < netdev_mc_count(net); i++) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); mc_list = mc_list->next; diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index ed4a508ef262..44ae8f6d3135 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -1232,7 +1232,7 @@ static void pegasus_set_multicast(struct net_device *net) pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; if (netif_msg_link(pegasus)) pr_info("%s: Promiscuous mode enabled.\n", net->name); - } else if (net->mc_count || (net->flags & IFF_ALLMULTI)) { + } else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) { pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; if (netif_msg_link(pegasus)) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 21ac103fbb71..e85c89c6706d 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -711,7 +711,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) if (netdev->flags & IFF_PROMISC) { dev->rx_creg |= cpu_to_le16(0x0001); dev_info(&netdev->dev, "%s: promiscuous mode\n", netdev->name); - } else if (netdev->mc_count || + } else if (!netdev_mc_empty(netdev) || (netdev->flags & IFF_ALLMULTI)) { dev->rx_creg &= cpu_to_le16(0xfffe); dev->rx_creg |= cpu_to_le16(0x0002); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 0c3c738d7419..48555d0e374d 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -384,7 +384,7 @@ static void smsc95xx_set_multicast(struct net_device *netdev) devdbg(dev, "receive all multicast enabled"); pdata->mac_cr |= MAC_CR_MCPAS_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); - } else if (dev->net->mc_count > 0) { + } else if (!netdev_mc_empty(dev->net)) { struct dev_mc_list *mc_list = dev->net->mc_list; int count = 0; @@ -406,7 +406,7 @@ static void smsc95xx_set_multicast(struct net_device *netdev) mc_list = mc_list->next; } - if (count != ((u32)dev->net->mc_count)) + if (count != ((u32) netdev_mc_count(dev->net))) devwarn(dev, "mc_count != dev->mc_count"); if (netif_msg_drv(dev)) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index a7e0c84426ea..85df7ac636b5 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1697,7 +1697,7 @@ static void rhine_set_rx_mode(struct net_device *dev) rx_mode = 0x1C; iowrite32(0xffffffff, ioaddr + MulticastFilter0); iowrite32(0xffffffff, ioaddr + MulticastFilter1); - } else if ((dev->mc_count > multicast_filter_limit) || + } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ iowrite32(0xffffffff, ioaddr + MulticastFilter0); @@ -1707,7 +1707,8 @@ static void rhine_set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; + mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index f15485efe40e..bdb19c3d6568 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1132,7 +1132,7 @@ static void velocity_set_multi(struct net_device *dev) writel(0xffffffff, ®s->MARCAM[0]); writel(0xffffffff, ®s->MARCAM[4]); rx_mode = (RCR_AM | RCR_AB | RCR_PROM); - } else if ((dev->mc_count > vptr->multicast_limit) || + } else if ((netdev_mc_count(dev) > vptr->multicast_limit) || (dev->flags & IFF_ALLMULTI)) { writel(0xffffffff, ®s->MARCAM[0]); writel(0xffffffff, ®s->MARCAM[4]); @@ -1141,7 +1141,9 @@ static void velocity_set_multi(struct net_device *dev) int offset = MCAM_SIZE - vptr->multicast_limit; mac_get_cam_mask(regs, vptr->mCAMmask); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { + for (i = 0, mclist = dev->mc_list; + mclist && i < netdev_mc_count(dev); + i++, mclist = mclist->next) { mac_set_cam(regs, i + offset, mclist->dmi_addr); vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7); } diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9d8984a3741c..4c347a3df657 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -735,6 +735,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) struct dev_addr_list *addr; struct netdev_hw_addr *ha; int uc_count; + int mc_count; void *buf; int i; @@ -762,9 +763,11 @@ static void virtnet_set_rx_mode(struct net_device *dev) allmulti ? "en" : "dis"); uc_count = netdev_uc_count(dev); + mc_count = netdev_mc_count(dev); /* MAC filter - use one buffer for both lists */ - mac_data = buf = kzalloc(((uc_count + dev->mc_count) * ETH_ALEN) + - (2 * sizeof(mac_data->entries)), GFP_ATOMIC); + buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) + + (2 * sizeof(mac_data->entries)), GFP_ATOMIC); + mac_data = buf; if (!buf) { dev_warn(&dev->dev, "No memory for MAC address buffer\n"); return; @@ -784,13 +787,13 @@ static void virtnet_set_rx_mode(struct net_device *dev) /* multicast list and count fill the end */ mac_data = (void *)&mac_data->macs[uc_count][0]; - mac_data->entries = dev->mc_count; + mac_data->entries = mc_count; addr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, addr = addr->next) + for (i = 0; i < mc_count; i++, addr = addr->next) memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); sg_set_buf(&sg[1], mac_data, - sizeof(mac_data->entries) + (dev->mc_count * ETH_ALEN)); + sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, VIRTIO_NET_CTRL_MAC_TABLE_SET, diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index b896f9386110..ee1b397417f3 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1668,7 +1668,7 @@ static u8 * vmxnet3_copy_mc(struct net_device *netdev) { u8 *buf = NULL; - u32 sz = netdev->mc_count * ETH_ALEN; + u32 sz = netdev_mc_count(netdev) * ETH_ALEN; /* struct Vmxnet3_RxFilterConf.mfTableLen is u16. */ if (sz <= 0xffff) { @@ -1678,7 +1678,7 @@ vmxnet3_copy_mc(struct net_device *netdev) int i; struct dev_mc_list *mc = netdev->mc_list; - for (i = 0; i < netdev->mc_count; i++) { + for (i = 0; i < netdev_mc_count(netdev); i++) { BUG_ON(!mc); memcpy(buf + i * ETH_ALEN, mc->dmi_addr, ETH_ALEN); @@ -1708,12 +1708,12 @@ vmxnet3_set_mc(struct net_device *netdev) if (netdev->flags & IFF_ALLMULTI) new_mode |= VMXNET3_RXM_ALL_MULTI; else - if (netdev->mc_count > 0) { + if (!netdev_mc_empty(netdev)) { new_table = vmxnet3_copy_mc(netdev); if (new_table) { new_mode |= VMXNET3_RXM_MCAST; rxConf->mfTableLen = cpu_to_le16( - netdev->mc_count * ETH_ALEN); + netdev_mc_count(netdev) * ETH_ALEN); rxConf->mfTablePA = cpu_to_le64(virt_to_phys( new_table)); } else { diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index a6606b8948e9..c248b01218a1 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -1178,11 +1178,11 @@ static void vxge_set_multicast(struct net_device *dev) memset(&mac_info, 0, sizeof(struct macInfo)); /* Update individual M_CAST address list */ - if ((!vdev->all_multi_flg) && dev->mc_count) { + if ((!vdev->all_multi_flg) && netdev_mc_count(dev)) { mcast_cnt = vdev->vpaths[0].mcast_addr_cnt; list_head = &vdev->vpaths[0].mac_addr_list; - if ((dev->mc_count + + if ((netdev_mc_count(dev) + (vdev->vpaths[0].mac_addr_cnt - mcast_cnt)) > vdev->vpaths[0].max_mac_addr_cnt) goto _set_all_mcast; @@ -1217,7 +1217,7 @@ static void vxge_set_multicast(struct net_device *dev) } /* Add new ones */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); i++, mclist = mclist->next) { memcpy(mac_info.macaddr, mclist->dmi_addr, ETH_ALEN); diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index ef6b78da370f..c22a34c7639c 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2310,7 +2310,7 @@ static void airo_set_multicast_list(struct net_device *dev) { airo_set_promisc(ai); } - if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { + if ((dev->flags&IFF_ALLMULTI) || !netdev_mc_empty(dev)) { /* Turn on multicast. (Should be already setup...) */ } } diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 753a1804eee7..a9e9cea2d767 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1668,12 +1668,12 @@ __orinoco_set_multicast_list(struct net_device *dev) /* The Hermes doesn't seem to have an allmulti mode, so we go * into promiscuous mode and let the upper levels deal. */ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > MAX_MULTICAST(priv))) { + (netdev_mc_count(dev) > MAX_MULTICAST(priv))) { promisc = 1; mc_count = 0; } else { promisc = 0; - mc_count = dev->mc_count; + mc_count = netdev_mc_count(dev); } err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count, diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 88e1e4e32b22..85905cab4f16 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1950,7 +1950,7 @@ static void set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) ray_update_multi_list(dev, 1); else { - if (local->num_multi != dev->mc_count) + if (local->num_multi != netdev_mc_count(dev)) ray_update_multi_list(dev, 0); } } /* end set_multicast_list */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 305c106fdc1c..14692bc51b51 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1492,10 +1492,10 @@ static void set_multicast_list(struct usbnet *usbdev) filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | RNDIS_PACKET_TYPE_ALL_LOCAL; } else if (usbdev->net->flags & IFF_ALLMULTI || - usbdev->net->mc_count > priv->multicast_size) { + netdev_mc_count(usbdev->net) > priv->multicast_size) { filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - } else if (usbdev->net->mc_count > 0) { - size = min(priv->multicast_size, usbdev->net->mc_count); + } else if (!netdev_mc_empty(usbdev->net)) { + size = min(priv->multicast_size, netdev_mc_count(usbdev->net)); buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); if (!buf) { devwarn(usbdev, diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 33c8be7ec8e6..5d2b52f4717f 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -879,16 +879,15 @@ static void zd1201_set_multicast(struct net_device *dev) unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; int i; - if (dev->mc_count > ZD1201_MAXMULTI) + if (netdev_mc_count(dev) > ZD1201_MAXMULTI) return; - for (i=0; imc_count; i++) { + for (i=0; idmi_addr, ETH_ALEN); mc = mc->next; } zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, - dev->mc_count*ETH_ALEN, 0); - + netdev_mc_count(dev) * ETH_ALEN, 0); } static int zd1201_config_commit(struct net_device *dev, diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 8b231b30fd12..5c880240a642 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1301,15 +1301,16 @@ static void set_rx_mode(struct net_device *dev) iowrite16(cfg_value & ~0x1000, ioaddr + Cnfg); if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ iowrite16(0x000F, ioaddr + AddrMode); - } else if ((dev->mc_count > 64) || (dev->flags & IFF_ALLMULTI)) { + } else if ((netdev_mc_count(dev) > 64) || + (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well, or accept all multicasts. */ iowrite16(0x000B, ioaddr + AddrMode); - } else if (dev->mc_count > 0) { /* Must use the multicast hash table. */ + } else if (!netdev_mc_empty(dev)) { /* Must use the multicast hash table. */ struct dev_mc_list *mclist; u16 hash_table[4]; int i; memset(hash_table, 0, sizeof(hash_table)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { unsigned int bit; diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index 24d97b4fa6fb..bc1fad248952 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -444,11 +444,11 @@ void et131x_multicast(struct net_device *netdev) adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } - if (netdev->mc_count > NIC_MAX_MCAST_LIST) { + if (netdev_mc_count(netdev) > NIC_MAX_MCAST_LIST) { adapter->PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST; } - if (netdev->mc_count < 1) { + if (netdev_mc_count(netdev) < 1) { adapter->PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST; adapter->PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST; } else { @@ -456,10 +456,10 @@ void et131x_multicast(struct net_device *netdev) } /* Set values in the private adapter struct */ - adapter->MCAddressCount = netdev->mc_count; + adapter->MCAddressCount = netdev_mc_count(netdev); - if (netdev->mc_count) { - count = netdev->mc_count - 1; + if (!netdev_mc_empty(netdev)) { + count = netdev_mc_count(netdev) - 1; memcpy(adapter->MCList[count], mclist->dmi_addr, ETH_ALEN); } diff --git a/drivers/staging/netwave/netwave_cs.c b/drivers/staging/netwave/netwave_cs.c index e61e6b9440ab..e936717d1f4b 100644 --- a/drivers/staging/netwave/netwave_cs.c +++ b/drivers/staging/netwave/netwave_cs.c @@ -1341,15 +1341,15 @@ static void set_multicast_list(struct net_device *dev) #ifdef PCMCIA_DEBUG { xstatic int old; - if (old != dev->mc_count) { - old = dev->mc_count; + if (old != netdev_mc_count(dev)) { + old = netdev_mc_count(dev); pr_debug("%s: setting Rx mode to %d addresses.\n", - dev->name, dev->mc_count); + dev->name, netdev_mc_count(dev)); } } #endif - if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { + if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) { /* Multicast Mode */ rcvMode = rxConfRxEna + rxConfAMP + rxConfBcast; } else if (dev->flags & IFF_PROMISC) { diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 5b191afc1442..8c9d5e5c7702 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1365,7 +1365,7 @@ static void slic_mcast_set_list(struct net_device *dev) int i; char *addresses; struct dev_mc_list *mc_list = dev->mc_list; - int mc_count = dev->mc_count; + int mc_count = netdev_mc_count(dev); ASSERT(adapter); diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 0db8d7b6e79c..82b3a6e0b15a 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -3093,7 +3093,7 @@ static void device_set_multi(struct net_device *dev) { /* Unconditionally log net taps. */ pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST); } - else if ((dev->mc_count > pDevice->multicast_limit) + else if ((netdev_mc_count(dev) > pDevice->multicast_limit) || (dev->flags & IFF_ALLMULTI)) { MACvSelectPage1(pDevice->PortOffset); VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff); @@ -3103,7 +3103,7 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ef17c4958c67..2c6a5350547c 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1619,7 +1619,8 @@ static void device_set_multi(struct net_device *dev) { // Unconditionally log net taps. pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST); } - else if ((dev->mc_count > pDevice->multicast_limit) || (dev->flags & IFF_ALLMULTI)) { + else if ((netdev_mc_count(dev) > pDevice->multicast_limit) || + (dev->flags & IFF_ALLMULTI)) { CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, MAC_REG_MAR0, @@ -1631,7 +1632,7 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - for (ii = 0, mclist = dev->mc_list; mclist && ii < dev->mc_count; + for (ii = 0, mclist = dev->mc_list; mclist && ii < netdev_mc_count(dev); ii++, mclist = mclist->next) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); diff --git a/drivers/staging/wavelan/wavelan.c b/drivers/staging/wavelan/wavelan.c index d634b2da3b84..961f1417fb58 100644 --- a/drivers/staging/wavelan/wavelan.c +++ b/drivers/staging/wavelan/wavelan.c @@ -1367,7 +1367,7 @@ static void wavelan_set_multicast_list(struct net_device * dev) #ifdef DEBUG_IOCTL_INFO printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", - dev->name, dev->flags, dev->mc_count); + dev->name, dev->flags, netdev_mc_count(dev)); #endif /* Are we asking for promiscuous mode, @@ -1375,7 +1375,7 @@ static void wavelan_set_multicast_list(struct net_device * dev) * or too many multicast addresses for the hardware filter? */ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) { + (netdev_mc_count(dev) > I82586_MAX_MULTICAST_ADDRESSES)) { /* * Enable promiscuous mode: receive all packets. */ @@ -1393,11 +1393,11 @@ static void wavelan_set_multicast_list(struct net_device * dev) * in multicast list */ #ifdef MULTICAST_AVOID - if (lp->promiscuous || (dev->mc_count != lp->mc_count)) + if (lp->promiscuous || (netdev_mc_count(dev) != lp->mc_count)) #endif { lp->promiscuous = 0; - lp->mc_count = dev->mc_count; + lp->mc_count = netdev_mc_count(dev); wv_82586_reconfig(dev); } diff --git a/drivers/staging/wavelan/wavelan_cs.c b/drivers/staging/wavelan/wavelan_cs.c index 10c702b5be4a..08fcb226d7d6 100644 --- a/drivers/staging/wavelan/wavelan_cs.c +++ b/drivers/staging/wavelan/wavelan_cs.c @@ -1373,7 +1373,7 @@ wavelan_set_multicast_list(struct net_device * dev) #ifdef DEBUG_IOCTL_INFO printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", - dev->name, dev->flags, dev->mc_count); + dev->name, dev->flags, netdev_mc_count(dev)); #endif if(dev->flags & IFF_PROMISC) @@ -1394,7 +1394,7 @@ wavelan_set_multicast_list(struct net_device * dev) /* If all multicast addresses * or too much multicast addresses for the hardware filter */ if((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > I82593_MAX_MULTICAST_ADDRESSES)) + (netdev_mc_count(dev) > I82593_MAX_MULTICAST_ADDRESSES)) { /* * Disable promiscuous mode, but active the all multicast mode @@ -1418,12 +1418,12 @@ wavelan_set_multicast_list(struct net_device * dev) */ #ifdef MULTICAST_AVOID if(lp->promiscuous || lp->allmulticast || - (dev->mc_count != lp->mc_count)) + (netdev_mc_count(dev) != lp->mc_count)) #endif { lp->promiscuous = 0; lp->allmulticast = 0; - lp->mc_count = dev->mc_count; + lp->mc_count = netdev_mc_count(dev); wv_82593_reconfig(dev); } @@ -3622,7 +3622,8 @@ wv_82593_config(struct net_device * dev) if(!wv_82593_cmd(dev, "wv_82593_config(): mc-setup", OP0_MC_SETUP, SR0_MC_SETUP_DONE)) ret = FALSE; - lp->mc_count = dev->mc_count; /* remember to avoid repeated reset */ + /* remember to avoid repeated reset */ + lp->mc_count = netdev_mc_count(dev); } /* Job done, clear the flag */ diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c index 0d22e3692fe5..a95ebf881fcd 100644 --- a/drivers/staging/wlags49_h2/wl_netdev.c +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -1070,9 +1070,9 @@ void wl_multicast( struct net_device *dev ) ( dev->flags & IFF_MULTICAST ) ? "Multicast " : "", ( dev->flags & IFF_ALLMULTI ) ? "All-Multicast" : "" ); - DBG_PRINT( " mc_count: %d\n", dev->mc_count ); + DBG_PRINT( " mc_count: %d\n", netdev_mc_count(dev)); - for( x = 0, mclist = dev->mc_list; mclist && x < dev->mc_count; + for( x = 0, mclist = dev->mc_list; mclist && x < netdev_mc_count(dev); x++, mclist = mclist->next ) { DBG_PRINT( " %s (%d)\n", DbgHwAddr(mclist->dmi_addr), mclist->dmi_addrlen ); @@ -1103,7 +1103,7 @@ void wl_multicast( struct net_device *dev ) DBG_PRINT( "Enabling Promiscuous mode (IFF_PROMISC)\n" ); hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); } - else if(( dev->mc_count > HCF_MAX_MULTICAST ) || + else if ((netdev_mc_count(dev) > HCF_MAX_MULTICAST) || ( dev->flags & IFF_ALLMULTI )) { /* Shutting off this filter will enable all multicast frames to be sent up from the device; however, this is a static RID, so @@ -1115,13 +1115,13 @@ void wl_multicast( struct net_device *dev ) hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); wl_apply( lp ); } - else if( dev->mc_count != 0 ) { + else if (!netdev_mc_empty(dev)) { /* Set the multicast addresses */ - lp->ltvRecord.len = ( dev->mc_count * 3 ) + 1; + lp->ltvRecord.len = ( netdev_mc_count(dev) * 3 ) + 1; lp->ltvRecord.typ = CFG_GROUP_ADDR; for( x = 0, mclist = dev->mc_list; - ( x < dev->mc_count ) && ( mclist != NULL ); + ( x < netdev_mc_count(dev)) && ( mclist != NULL ); x++, mclist = mclist->next ) { memcpy( &( lp->ltvRecord.u.u8[x * ETH_ALEN] ), mclist->dmi_addr, ETH_ALEN ); diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index 26fb831ef7e0..b6234b73c4cf 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c @@ -64,7 +64,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) struct sk_buff *skb; int size; - BT_DBG("%s mc_count %d", dev->name, dev->mc_count); + BT_DBG("%s mc_count %d", dev->name, netdev_mc_count(dev)); size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2; skb = alloc_skb(size, GFP_ATOMIC); @@ -97,7 +97,9 @@ static void bnep_net_set_mc_list(struct net_device *dev) /* FIXME: We should group addresses here. */ - for (i = 0; i < dev->mc_count && i < BNEP_MAX_MULTICAST_FILTERS; i++) { + for (i = 0; + i < netdev_mc_count(dev) && i < BNEP_MAX_MULTICAST_FILTERS; + i++) { memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); dmi = dmi->next; diff --git a/net/core/dev.c b/net/core/dev.c index ae75f25ac0a5..d1cf53d0d597 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4263,7 +4263,7 @@ static void dev_addr_discard(struct net_device *dev) netif_addr_lock_bh(dev); __dev_addr_discard(&dev->mc_list); - dev->mc_count = 0; + netdev_mc_count(dev) = 0; netif_addr_unlock_bh(dev); } diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index d340110f5c0c..9616c32d1076 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -321,14 +321,15 @@ static void irlan_eth_set_multicast_list(struct net_device *dev) /* Enable promiscuous mode */ IRDA_WARNING("Promiscuous mode not implemented by IrLAN!\n"); } - else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) { + else if ((dev->flags & IFF_ALLMULTI) || + netdev_mc_count(dev) > HW_MAX_ADDRS) { /* Disable promiscuous mode, use normal mode. */ IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); /* hardware_set_filter(NULL); */ irlan_set_multicast_filter(self, TRUE); } - else if (dev->mc_count) { + else if (!netdev_mc_empty(dev)) { IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __func__ ); /* Walk the address list, and load the filter */ /* hardware_set_filter(dev->mc_list); */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09fff4662e80..f943f5fa7286 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -413,7 +413,7 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_lock_bh(dev); spin_lock_bh(&local->filter_lock); __dev_addr_unsync(&local->mc_list, &local->mc_count, - &dev->mc_list, &dev->mc_count); + &dev->mc_list, dev->mc_count); spin_unlock_bh(&local->filter_lock); netif_addr_unlock_bh(dev); -- cgit v1.2.3 From 7455a76f170f794498d26081a5f15b797ef1a2aa Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 8 Feb 2010 05:12:08 +0000 Subject: macb: straighten out macb_mii_probe function Use "phy_find_first" instead of manual lookup. Also use "phy_connect_direct" instead of "phy_connect" since we already have phy_device pointer here. Signed-off-by: Jiri Pirko Acked-by: Haavard Skinnemoen Signed-off-by: David S. Miller --- drivers/net/macb.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index fbc371fa19b5..7a5f89728a81 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -189,18 +189,11 @@ static void macb_handle_link_change(struct net_device *dev) static int macb_mii_probe(struct net_device *dev) { struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = NULL; + struct phy_device *phydev; struct eth_platform_data *pdata; - int phy_addr; - - /* find the first phy */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (bp->mii_bus->phy_map[phy_addr]) { - phydev = bp->mii_bus->phy_map[phy_addr]; - break; - } - } + int ret; + phydev = phy_find_first(bp->mii_bus); if (!phydev) { printk (KERN_ERR "%s: no PHY found\n", dev->name); return -1; @@ -210,17 +203,13 @@ static int macb_mii_probe(struct net_device *dev) /* TODO : add pin_irq */ /* attach the mac to the phy */ - if (pdata && pdata->is_rmii) { - phydev = phy_connect(dev, dev_name(&phydev->dev), - &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); - } else { - phydev = phy_connect(dev, dev_name(&phydev->dev), - &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); - } - - if (IS_ERR(phydev)) { + ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0, + pdata && pdata->is_rmii ? + PHY_INTERFACE_MODE_RMII : + PHY_INTERFACE_MODE_MII); + if (ret) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); + return ret; } /* mask with MAC supported features */ -- cgit v1.2.3 From 69a6a0b38a139ccceef32222108caca8a9b0b795 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 7 Feb 2010 20:20:28 +0000 Subject: dccp: allow probing of CCID-array length This fixes a problem in the DCCP getsockopt() API: currently there is no way for a user to a priori know the number of built-in CCIDs, other than trying DCCP_SOCKOPT_AVAILABLE_CCIDS in a loop, incrementing the option length until EINVAL is no longer returned. This patch truncates the array to the user-provided length. No copy is made when the length is <= 0. Due to the length restriction in do_dccp_getsockopt() to sizeof(int), the minimum array length remains 4, which is a reasonable default (only 3 CCIDs, CCID-2..4, are currently defined). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- Documentation/networking/dccp.txt | 6 ++++-- net/dccp/ccid.c | 9 ++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt index b132e4a3cf0f..a62fdf7a6bff 100644 --- a/Documentation/networking/dccp.txt +++ b/Documentation/networking/dccp.txt @@ -58,8 +58,10 @@ DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet size (application payload size) in bytes, see RFC 4340, section 14. DCCP_SOCKOPT_AVAILABLE_CCIDS is also read-only and returns the list of CCIDs -supported by the endpoint (see include/linux/dccp.h for symbolic constants). -The caller needs to provide a sufficiently large (> 2) array of type uint8_t. +supported by the endpoint. The option value is an array of type uint8_t whose +size is passed as option length. The minimum array size is 4 elements, the +value returned in the optlen argument always reflects the true number of +built-in CCIDs. DCCP_SOCKOPT_CCID is write-only and sets both the TX and RX CCIDs at the same time, combining the operation of the next two socket options. This option is diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index ff16e9df1969..49d27c556bec 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -63,14 +63,13 @@ int ccid_getsockopt_builtin_ccids(struct sock *sk, int len, u8 *ccid_array, array_len; int err = 0; - if (len < ARRAY_SIZE(ccids)) - return -EINVAL; - if (ccid_get_builtin_ccids(&ccid_array, &array_len)) return -ENOBUFS; - if (put_user(array_len, optlen) || - copy_to_user(optval, ccid_array, array_len)) + if (put_user(array_len, optlen)) + err = -EFAULT; + else if (len > 0 && copy_to_user(optval, ccid_array, + len > array_len ? array_len : len)) err = -EFAULT; kfree(ccid_array); -- cgit v1.2.3 From 2bec5a369ee79576a3eea2c23863325089785a2c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 8 Feb 2010 05:19:03 +0000 Subject: ipv6: fib: fix crash when changing large fib while dumping it When the fib size exceeds what can be dumped in a single skb, the dump is suspended and resumed once the last skb has been received by userspace. When the fib is changed while the dump is suspended, the walker might contain stale pointers, causing a crash when the dump is resumed. BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: [] fib6_walk_continue+0xbb/0x124 [ipv6] PGD 5347a067 PUD 65c7067 PMD 0 Oops: 0000 [#1] PREEMPT SMP ... RIP: 0010:[] [] fib6_walk_continue+0xbb/0x124 [ipv6] ... Call Trace: [] ? mutex_spin_on_owner+0x59/0x71 [] inet6_dump_fib+0x11b/0x1b9 [ipv6] [] netlink_dump+0x5b/0x19e [] ? consume_skb+0x28/0x2a [] netlink_recvmsg+0x1ab/0x2c6 [] ? netlink_unicast+0xfa/0x151 [] __sock_recvmsg+0x6d/0x79 [] sock_recvmsg+0xca/0xe3 [] ? autoremove_wake_function+0x0/0x38 [] ? radix_tree_lookup_slot+0xe/0x10 [] ? find_get_page+0x90/0xa5 [] ? filemap_fault+0x201/0x34f [] ? fget_light+0x2f/0xac [] ? verify_iovec+0x4f/0x94 [] sys_recvmsg+0x14d/0x223 Store the serial number when beginning to walk the fib and reload pointers when continuing to walk after a change occured. Similar to other dumping functions, this might cause unrelated entries to be missed when entries are deleted. Tested-by: Ben Greear Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 2 ++ net/ipv6/ip6_fib.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 257808188add..8f279ddb3593 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -129,6 +129,8 @@ struct fib6_walker_t { struct rt6_info *leaf; unsigned char state; unsigned char prune; + unsigned int skip; + unsigned int count; int (*func)(struct fib6_walker_t *); void *args; }; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f626ea2b304f..77e122f53ea6 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -319,12 +319,26 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb, w->root = &table->tb6_root; if (cb->args[4] == 0) { + w->count = 0; + w->skip = 0; + read_lock_bh(&table->tb6_lock); res = fib6_walk(w); read_unlock_bh(&table->tb6_lock); - if (res > 0) + if (res > 0) { cb->args[4] = 1; + cb->args[5] = w->root->fn_sernum; + } } else { + if (cb->args[5] != w->root->fn_sernum) { + /* Begin at the root if the tree changed */ + cb->args[5] = w->root->fn_sernum; + w->state = FWS_INIT; + w->node = w->root; + w->skip = w->count; + } else + w->skip = 0; + read_lock_bh(&table->tb6_lock); res = fib6_walk_continue(w); read_unlock_bh(&table->tb6_lock); @@ -1250,9 +1264,18 @@ static int fib6_walk_continue(struct fib6_walker_t *w) w->leaf = fn->leaf; case FWS_C: if (w->leaf && fn->fn_flags&RTN_RTINFO) { - int err = w->func(w); + int err; + + if (w->count < w->skip) { + w->count++; + continue; + } + + err = w->func(w); if (err) return err; + + w->count++; continue; } w->state = FWS_U; @@ -1346,6 +1369,8 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, c.w.root = root; c.w.func = fib6_clean_node; c.w.prune = prune; + c.w.count = 0; + c.w.skip = 0; c.func = func; c.arg = arg; c.net = net; -- cgit v1.2.3 From 447d8c2603a417cca68240059fbf1babfd27774f Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 12 Feb 2010 12:10:47 -0800 Subject: net: move am79c961's probe function to .devinit.text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pointer to am79c961_probe is passed to the core via platform_driver_register and so the function must not disappear when the .init sections are discarded. Otherwise (if also having HOTPLUG=y) unbinding and binding a device to the driver via sysfs will result in an oops as does a device being registered late. An alternative to this patch is using platform_driver_probe instead of platform_driver_register plus removing the pointer to the probe function from the struct platform_driver. Signed-off-by: Uwe Kleine-König Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 164b37e85eea..1c3c1f94268e 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -680,7 +680,7 @@ static const struct net_device_ops am79c961_netdev_ops = { #endif }; -static int __init am79c961_probe(struct platform_device *pdev) +static int __devinit am79c961_probe(struct platform_device *pdev) { struct resource *res; struct net_device *dev; -- cgit v1.2.3 From 8ca86fd83eae6c73db5f6b23ee3a63b77d52c8ee Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 8 Feb 2010 11:36:53 +0000 Subject: net: Micrel KSZ8841/2 PCI Ethernet driver This is a new network driver for Micrel KSZ8841/KSZ8842 PCI Ethernet chips. The same driver can run both chips at the same time. It supports IPv4 TCP hardware checksumming and so can use scatter/gather transmission. The KSZ8842 switch has 2 ports. Some users like to take direct control of those ports. So KSZ8842 has a multiple devices mode in which the driver creates another network device so that users can specify which port to send packets. This mode is enabled by passing the "multi_dev=1" parameter to the driver during loading. The KSZ884X can receive huge frames with size up to 1916 bytes. To use this feature change the network device MTU from 1500 to 1898. The KSZ884X driver has 3 packet receive processing functions for the normal mode, multiple devices mode, and huge frame mode. Those functions are identical except for more checking for the new features. In normal programming point of view the huge frame version is the one to use because it covers all the cases, but this is done for performance consideration because the target clients for the KSZ884X chips are embedded systems, which unlike desktop PC may not have powerful CPU. Signed-off-by: Tristram Ha Signed-off-by: David S. Miller --- drivers/net/ksz884x.c | 7335 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 7335 insertions(+) create mode 100644 drivers/net/ksz884x.c diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c new file mode 100644 index 000000000000..6f187c7e61fa --- /dev/null +++ b/drivers/net/ksz884x.c @@ -0,0 +1,7335 @@ +/** + * drivers/net/ksx884x.c - Micrel KSZ8841/2 PCI Ethernet driver + * + * Copyright (c) 2009-2010 Micrel, Inc. + * Tristram Ha + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* DMA Registers */ + +#define KS_DMA_TX_CTRL 0x0000 +#define DMA_TX_ENABLE 0x00000001 +#define DMA_TX_CRC_ENABLE 0x00000002 +#define DMA_TX_PAD_ENABLE 0x00000004 +#define DMA_TX_LOOPBACK 0x00000100 +#define DMA_TX_FLOW_ENABLE 0x00000200 +#define DMA_TX_CSUM_IP 0x00010000 +#define DMA_TX_CSUM_TCP 0x00020000 +#define DMA_TX_CSUM_UDP 0x00040000 +#define DMA_TX_BURST_SIZE 0x3F000000 + +#define KS_DMA_RX_CTRL 0x0004 +#define DMA_RX_ENABLE 0x00000001 +#define KS884X_DMA_RX_MULTICAST 0x00000002 +#define DMA_RX_PROMISCUOUS 0x00000004 +#define DMA_RX_ERROR 0x00000008 +#define DMA_RX_UNICAST 0x00000010 +#define DMA_RX_ALL_MULTICAST 0x00000020 +#define DMA_RX_BROADCAST 0x00000040 +#define DMA_RX_FLOW_ENABLE 0x00000200 +#define DMA_RX_CSUM_IP 0x00010000 +#define DMA_RX_CSUM_TCP 0x00020000 +#define DMA_RX_CSUM_UDP 0x00040000 +#define DMA_RX_BURST_SIZE 0x3F000000 + +#define DMA_BURST_SHIFT 24 +#define DMA_BURST_DEFAULT 8 + +#define KS_DMA_TX_START 0x0008 +#define KS_DMA_RX_START 0x000C +#define DMA_START 0x00000001 + +#define KS_DMA_TX_ADDR 0x0010 +#define KS_DMA_RX_ADDR 0x0014 + +#define DMA_ADDR_LIST_MASK 0xFFFFFFFC +#define DMA_ADDR_LIST_SHIFT 2 + +/* MTR0 */ +#define KS884X_MULTICAST_0_OFFSET 0x0020 +#define KS884X_MULTICAST_1_OFFSET 0x0021 +#define KS884X_MULTICAST_2_OFFSET 0x0022 +#define KS884x_MULTICAST_3_OFFSET 0x0023 +/* MTR1 */ +#define KS884X_MULTICAST_4_OFFSET 0x0024 +#define KS884X_MULTICAST_5_OFFSET 0x0025 +#define KS884X_MULTICAST_6_OFFSET 0x0026 +#define KS884X_MULTICAST_7_OFFSET 0x0027 + +/* Interrupt Registers */ + +/* INTEN */ +#define KS884X_INTERRUPTS_ENABLE 0x0028 +/* INTST */ +#define KS884X_INTERRUPTS_STATUS 0x002C + +#define KS884X_INT_RX_STOPPED 0x02000000 +#define KS884X_INT_TX_STOPPED 0x04000000 +#define KS884X_INT_RX_OVERRUN 0x08000000 +#define KS884X_INT_TX_EMPTY 0x10000000 +#define KS884X_INT_RX 0x20000000 +#define KS884X_INT_TX 0x40000000 +#define KS884X_INT_PHY 0x80000000 + +#define KS884X_INT_RX_MASK \ + (KS884X_INT_RX | KS884X_INT_RX_OVERRUN) +#define KS884X_INT_TX_MASK \ + (KS884X_INT_TX | KS884X_INT_TX_EMPTY) +#define KS884X_INT_MASK (KS884X_INT_RX | KS884X_INT_TX | KS884X_INT_PHY) + +/* MAC Additional Station Address */ + +/* MAAL0 */ +#define KS_ADD_ADDR_0_LO 0x0080 +/* MAAH0 */ +#define KS_ADD_ADDR_0_HI 0x0084 +/* MAAL1 */ +#define KS_ADD_ADDR_1_LO 0x0088 +/* MAAH1 */ +#define KS_ADD_ADDR_1_HI 0x008C +/* MAAL2 */ +#define KS_ADD_ADDR_2_LO 0x0090 +/* MAAH2 */ +#define KS_ADD_ADDR_2_HI 0x0094 +/* MAAL3 */ +#define KS_ADD_ADDR_3_LO 0x0098 +/* MAAH3 */ +#define KS_ADD_ADDR_3_HI 0x009C +/* MAAL4 */ +#define KS_ADD_ADDR_4_LO 0x00A0 +/* MAAH4 */ +#define KS_ADD_ADDR_4_HI 0x00A4 +/* MAAL5 */ +#define KS_ADD_ADDR_5_LO 0x00A8 +/* MAAH5 */ +#define KS_ADD_ADDR_5_HI 0x00AC +/* MAAL6 */ +#define KS_ADD_ADDR_6_LO 0x00B0 +/* MAAH6 */ +#define KS_ADD_ADDR_6_HI 0x00B4 +/* MAAL7 */ +#define KS_ADD_ADDR_7_LO 0x00B8 +/* MAAH7 */ +#define KS_ADD_ADDR_7_HI 0x00BC +/* MAAL8 */ +#define KS_ADD_ADDR_8_LO 0x00C0 +/* MAAH8 */ +#define KS_ADD_ADDR_8_HI 0x00C4 +/* MAAL9 */ +#define KS_ADD_ADDR_9_LO 0x00C8 +/* MAAH9 */ +#define KS_ADD_ADDR_9_HI 0x00CC +/* MAAL10 */ +#define KS_ADD_ADDR_A_LO 0x00D0 +/* MAAH10 */ +#define KS_ADD_ADDR_A_HI 0x00D4 +/* MAAL11 */ +#define KS_ADD_ADDR_B_LO 0x00D8 +/* MAAH11 */ +#define KS_ADD_ADDR_B_HI 0x00DC +/* MAAL12 */ +#define KS_ADD_ADDR_C_LO 0x00E0 +/* MAAH12 */ +#define KS_ADD_ADDR_C_HI 0x00E4 +/* MAAL13 */ +#define KS_ADD_ADDR_D_LO 0x00E8 +/* MAAH13 */ +#define KS_ADD_ADDR_D_HI 0x00EC +/* MAAL14 */ +#define KS_ADD_ADDR_E_LO 0x00F0 +/* MAAH14 */ +#define KS_ADD_ADDR_E_HI 0x00F4 +/* MAAL15 */ +#define KS_ADD_ADDR_F_LO 0x00F8 +/* MAAH15 */ +#define KS_ADD_ADDR_F_HI 0x00FC + +#define ADD_ADDR_HI_MASK 0x0000FFFF +#define ADD_ADDR_ENABLE 0x80000000 +#define ADD_ADDR_INCR 8 + +/* Miscellaneous Registers */ + +/* MARL */ +#define KS884X_ADDR_0_OFFSET 0x0200 +#define KS884X_ADDR_1_OFFSET 0x0201 +/* MARM */ +#define KS884X_ADDR_2_OFFSET 0x0202 +#define KS884X_ADDR_3_OFFSET 0x0203 +/* MARH */ +#define KS884X_ADDR_4_OFFSET 0x0204 +#define KS884X_ADDR_5_OFFSET 0x0205 + +/* OBCR */ +#define KS884X_BUS_CTRL_OFFSET 0x0210 + +#define BUS_SPEED_125_MHZ 0x0000 +#define BUS_SPEED_62_5_MHZ 0x0001 +#define BUS_SPEED_41_66_MHZ 0x0002 +#define BUS_SPEED_25_MHZ 0x0003 + +/* EEPCR */ +#define KS884X_EEPROM_CTRL_OFFSET 0x0212 + +#define EEPROM_CHIP_SELECT 0x0001 +#define EEPROM_SERIAL_CLOCK 0x0002 +#define EEPROM_DATA_OUT 0x0004 +#define EEPROM_DATA_IN 0x0008 +#define EEPROM_ACCESS_ENABLE 0x0010 + +/* MBIR */ +#define KS884X_MEM_INFO_OFFSET 0x0214 + +#define RX_MEM_TEST_FAILED 0x0008 +#define RX_MEM_TEST_FINISHED 0x0010 +#define TX_MEM_TEST_FAILED 0x0800 +#define TX_MEM_TEST_FINISHED 0x1000 + +/* GCR */ +#define KS884X_GLOBAL_CTRL_OFFSET 0x0216 +#define GLOBAL_SOFTWARE_RESET 0x0001 + +#define KS8841_POWER_MANAGE_OFFSET 0x0218 + +/* WFCR */ +#define KS8841_WOL_CTRL_OFFSET 0x021A +#define KS8841_WOL_MAGIC_ENABLE 0x0080 +#define KS8841_WOL_FRAME3_ENABLE 0x0008 +#define KS8841_WOL_FRAME2_ENABLE 0x0004 +#define KS8841_WOL_FRAME1_ENABLE 0x0002 +#define KS8841_WOL_FRAME0_ENABLE 0x0001 + +/* WF0 */ +#define KS8841_WOL_FRAME_CRC_OFFSET 0x0220 +#define KS8841_WOL_FRAME_BYTE0_OFFSET 0x0224 +#define KS8841_WOL_FRAME_BYTE2_OFFSET 0x0228 + +/* IACR */ +#define KS884X_IACR_P 0x04A0 +#define KS884X_IACR_OFFSET KS884X_IACR_P + +/* IADR1 */ +#define KS884X_IADR1_P 0x04A2 +#define KS884X_IADR2_P 0x04A4 +#define KS884X_IADR3_P 0x04A6 +#define KS884X_IADR4_P 0x04A8 +#define KS884X_IADR5_P 0x04AA + +#define KS884X_ACC_CTRL_SEL_OFFSET KS884X_IACR_P +#define KS884X_ACC_CTRL_INDEX_OFFSET (KS884X_ACC_CTRL_SEL_OFFSET + 1) + +#define KS884X_ACC_DATA_0_OFFSET KS884X_IADR4_P +#define KS884X_ACC_DATA_1_OFFSET (KS884X_ACC_DATA_0_OFFSET + 1) +#define KS884X_ACC_DATA_2_OFFSET KS884X_IADR5_P +#define KS884X_ACC_DATA_3_OFFSET (KS884X_ACC_DATA_2_OFFSET + 1) +#define KS884X_ACC_DATA_4_OFFSET KS884X_IADR2_P +#define KS884X_ACC_DATA_5_OFFSET (KS884X_ACC_DATA_4_OFFSET + 1) +#define KS884X_ACC_DATA_6_OFFSET KS884X_IADR3_P +#define KS884X_ACC_DATA_7_OFFSET (KS884X_ACC_DATA_6_OFFSET + 1) +#define KS884X_ACC_DATA_8_OFFSET KS884X_IADR1_P + +/* P1MBCR */ +#define KS884X_P1MBCR_P 0x04D0 +#define KS884X_P1MBSR_P 0x04D2 +#define KS884X_PHY1ILR_P 0x04D4 +#define KS884X_PHY1IHR_P 0x04D6 +#define KS884X_P1ANAR_P 0x04D8 +#define KS884X_P1ANLPR_P 0x04DA + +/* P2MBCR */ +#define KS884X_P2MBCR_P 0x04E0 +#define KS884X_P2MBSR_P 0x04E2 +#define KS884X_PHY2ILR_P 0x04E4 +#define KS884X_PHY2IHR_P 0x04E6 +#define KS884X_P2ANAR_P 0x04E8 +#define KS884X_P2ANLPR_P 0x04EA + +#define KS884X_PHY_1_CTRL_OFFSET KS884X_P1MBCR_P +#define PHY_CTRL_INTERVAL (KS884X_P2MBCR_P - KS884X_P1MBCR_P) + +#define KS884X_PHY_CTRL_OFFSET 0x00 + +/* Mode Control Register */ +#define PHY_REG_CTRL 0 + +#define PHY_RESET 0x8000 +#define PHY_LOOPBACK 0x4000 +#define PHY_SPEED_100MBIT 0x2000 +#define PHY_AUTO_NEG_ENABLE 0x1000 +#define PHY_POWER_DOWN 0x0800 +#define PHY_MII_DISABLE 0x0400 +#define PHY_AUTO_NEG_RESTART 0x0200 +#define PHY_FULL_DUPLEX 0x0100 +#define PHY_COLLISION_TEST 0x0080 +#define PHY_HP_MDIX 0x0020 +#define PHY_FORCE_MDIX 0x0010 +#define PHY_AUTO_MDIX_DISABLE 0x0008 +#define PHY_REMOTE_FAULT_DISABLE 0x0004 +#define PHY_TRANSMIT_DISABLE 0x0002 +#define PHY_LED_DISABLE 0x0001 + +#define KS884X_PHY_STATUS_OFFSET 0x02 + +/* Mode Status Register */ +#define PHY_REG_STATUS 1 + +#define PHY_100BT4_CAPABLE 0x8000 +#define PHY_100BTX_FD_CAPABLE 0x4000 +#define PHY_100BTX_CAPABLE 0x2000 +#define PHY_10BT_FD_CAPABLE 0x1000 +#define PHY_10BT_CAPABLE 0x0800 +#define PHY_MII_SUPPRESS_CAPABLE 0x0040 +#define PHY_AUTO_NEG_ACKNOWLEDGE 0x0020 +#define PHY_REMOTE_FAULT 0x0010 +#define PHY_AUTO_NEG_CAPABLE 0x0008 +#define PHY_LINK_STATUS 0x0004 +#define PHY_JABBER_DETECT 0x0002 +#define PHY_EXTENDED_CAPABILITY 0x0001 + +#define KS884X_PHY_ID_1_OFFSET 0x04 +#define KS884X_PHY_ID_2_OFFSET 0x06 + +/* PHY Identifier Registers */ +#define PHY_REG_ID_1 2 +#define PHY_REG_ID_2 3 + +#define KS884X_PHY_AUTO_NEG_OFFSET 0x08 + +/* Auto-Negotiation Advertisement Register */ +#define PHY_REG_AUTO_NEGOTIATION 4 + +#define PHY_AUTO_NEG_NEXT_PAGE 0x8000 +#define PHY_AUTO_NEG_REMOTE_FAULT 0x2000 +/* Not supported. */ +#define PHY_AUTO_NEG_ASYM_PAUSE 0x0800 +#define PHY_AUTO_NEG_SYM_PAUSE 0x0400 +#define PHY_AUTO_NEG_100BT4 0x0200 +#define PHY_AUTO_NEG_100BTX_FD 0x0100 +#define PHY_AUTO_NEG_100BTX 0x0080 +#define PHY_AUTO_NEG_10BT_FD 0x0040 +#define PHY_AUTO_NEG_10BT 0x0020 +#define PHY_AUTO_NEG_SELECTOR 0x001F +#define PHY_AUTO_NEG_802_3 0x0001 + +#define PHY_AUTO_NEG_PAUSE (PHY_AUTO_NEG_SYM_PAUSE | PHY_AUTO_NEG_ASYM_PAUSE) + +#define KS884X_PHY_REMOTE_CAP_OFFSET 0x0A + +/* Auto-Negotiation Link Partner Ability Register */ +#define PHY_REG_REMOTE_CAPABILITY 5 + +#define PHY_REMOTE_NEXT_PAGE 0x8000 +#define PHY_REMOTE_ACKNOWLEDGE 0x4000 +#define PHY_REMOTE_REMOTE_FAULT 0x2000 +#define PHY_REMOTE_SYM_PAUSE 0x0400 +#define PHY_REMOTE_100BTX_FD 0x0100 +#define PHY_REMOTE_100BTX 0x0080 +#define PHY_REMOTE_10BT_FD 0x0040 +#define PHY_REMOTE_10BT 0x0020 + +/* P1VCT */ +#define KS884X_P1VCT_P 0x04F0 +#define KS884X_P1PHYCTRL_P 0x04F2 + +/* P2VCT */ +#define KS884X_P2VCT_P 0x04F4 +#define KS884X_P2PHYCTRL_P 0x04F6 + +#define KS884X_PHY_SPECIAL_OFFSET KS884X_P1VCT_P +#define PHY_SPECIAL_INTERVAL (KS884X_P2VCT_P - KS884X_P1VCT_P) + +#define KS884X_PHY_LINK_MD_OFFSET 0x00 + +#define PHY_START_CABLE_DIAG 0x8000 +#define PHY_CABLE_DIAG_RESULT 0x6000 +#define PHY_CABLE_STAT_NORMAL 0x0000 +#define PHY_CABLE_STAT_OPEN 0x2000 +#define PHY_CABLE_STAT_SHORT 0x4000 +#define PHY_CABLE_STAT_FAILED 0x6000 +#define PHY_CABLE_10M_SHORT 0x1000 +#define PHY_CABLE_FAULT_COUNTER 0x01FF + +#define KS884X_PHY_PHY_CTRL_OFFSET 0x02 + +#define PHY_STAT_REVERSED_POLARITY 0x0020 +#define PHY_STAT_MDIX 0x0010 +#define PHY_FORCE_LINK 0x0008 +#define PHY_POWER_SAVING_DISABLE 0x0004 +#define PHY_REMOTE_LOOPBACK 0x0002 + +/* SIDER */ +#define KS884X_SIDER_P 0x0400 +#define KS884X_CHIP_ID_OFFSET KS884X_SIDER_P +#define KS884X_FAMILY_ID_OFFSET (KS884X_CHIP_ID_OFFSET + 1) + +#define REG_FAMILY_ID 0x88 + +#define REG_CHIP_ID_41 0x8810 +#define REG_CHIP_ID_42 0x8800 + +#define KS884X_CHIP_ID_MASK_41 0xFF10 +#define KS884X_CHIP_ID_MASK 0xFFF0 +#define KS884X_CHIP_ID_SHIFT 4 +#define KS884X_REVISION_MASK 0x000E +#define KS884X_REVISION_SHIFT 1 +#define KS8842_START 0x0001 + +#define CHIP_IP_41_M 0x8810 +#define CHIP_IP_42_M 0x8800 +#define CHIP_IP_61_M 0x8890 +#define CHIP_IP_62_M 0x8880 + +#define CHIP_IP_41_P 0x8850 +#define CHIP_IP_42_P 0x8840 +#define CHIP_IP_61_P 0x88D0 +#define CHIP_IP_62_P 0x88C0 + +/* SGCR1 */ +#define KS8842_SGCR1_P 0x0402 +#define KS8842_SWITCH_CTRL_1_OFFSET KS8842_SGCR1_P + +#define SWITCH_PASS_ALL 0x8000 +#define SWITCH_TX_FLOW_CTRL 0x2000 +#define SWITCH_RX_FLOW_CTRL 0x1000 +#define SWITCH_CHECK_LENGTH 0x0800 +#define SWITCH_AGING_ENABLE 0x0400 +#define SWITCH_FAST_AGING 0x0200 +#define SWITCH_AGGR_BACKOFF 0x0100 +#define SWITCH_PASS_PAUSE 0x0008 +#define SWITCH_LINK_AUTO_AGING 0x0001 + +/* SGCR2 */ +#define KS8842_SGCR2_P 0x0404 +#define KS8842_SWITCH_CTRL_2_OFFSET KS8842_SGCR2_P + +#define SWITCH_VLAN_ENABLE 0x8000 +#define SWITCH_IGMP_SNOOP 0x4000 +#define IPV6_MLD_SNOOP_ENABLE 0x2000 +#define IPV6_MLD_SNOOP_OPTION 0x1000 +#define PRIORITY_SCHEME_SELECT 0x0800 +#define SWITCH_MIRROR_RX_TX 0x0100 +#define UNICAST_VLAN_BOUNDARY 0x0080 +#define MULTICAST_STORM_DISABLE 0x0040 +#define SWITCH_BACK_PRESSURE 0x0020 +#define FAIR_FLOW_CTRL 0x0010 +#define NO_EXC_COLLISION_DROP 0x0008 +#define SWITCH_HUGE_PACKET 0x0004 +#define SWITCH_LEGAL_PACKET 0x0002 +#define SWITCH_BUF_RESERVE 0x0001 + +/* SGCR3 */ +#define KS8842_SGCR3_P 0x0406 +#define KS8842_SWITCH_CTRL_3_OFFSET KS8842_SGCR3_P + +#define BROADCAST_STORM_RATE_LO 0xFF00 +#define SWITCH_REPEATER 0x0080 +#define SWITCH_HALF_DUPLEX 0x0040 +#define SWITCH_FLOW_CTRL 0x0020 +#define SWITCH_10_MBIT 0x0010 +#define SWITCH_REPLACE_NULL_VID 0x0008 +#define BROADCAST_STORM_RATE_HI 0x0007 + +#define BROADCAST_STORM_RATE 0x07FF + +/* SGCR4 */ +#define KS8842_SGCR4_P 0x0408 + +/* SGCR5 */ +#define KS8842_SGCR5_P 0x040A +#define KS8842_SWITCH_CTRL_5_OFFSET KS8842_SGCR5_P + +#define LED_MODE 0x8200 +#define LED_SPEED_DUPLEX_ACT 0x0000 +#define LED_SPEED_DUPLEX_LINK_ACT 0x8000 +#define LED_DUPLEX_10_100 0x0200 + +/* SGCR6 */ +#define KS8842_SGCR6_P 0x0410 +#define KS8842_SWITCH_CTRL_6_OFFSET KS8842_SGCR6_P + +#define KS8842_PRIORITY_MASK 3 +#define KS8842_PRIORITY_SHIFT 2 + +/* SGCR7 */ +#define KS8842_SGCR7_P 0x0412 +#define KS8842_SWITCH_CTRL_7_OFFSET KS8842_SGCR7_P + +#define SWITCH_UNK_DEF_PORT_ENABLE 0x0008 +#define SWITCH_UNK_DEF_PORT_3 0x0004 +#define SWITCH_UNK_DEF_PORT_2 0x0002 +#define SWITCH_UNK_DEF_PORT_1 0x0001 + +/* MACAR1 */ +#define KS8842_MACAR1_P 0x0470 +#define KS8842_MACAR2_P 0x0472 +#define KS8842_MACAR3_P 0x0474 +#define KS8842_MAC_ADDR_1_OFFSET KS8842_MACAR1_P +#define KS8842_MAC_ADDR_0_OFFSET (KS8842_MAC_ADDR_1_OFFSET + 1) +#define KS8842_MAC_ADDR_3_OFFSET KS8842_MACAR2_P +#define KS8842_MAC_ADDR_2_OFFSET (KS8842_MAC_ADDR_3_OFFSET + 1) +#define KS8842_MAC_ADDR_5_OFFSET KS8842_MACAR3_P +#define KS8842_MAC_ADDR_4_OFFSET (KS8842_MAC_ADDR_5_OFFSET + 1) + +/* TOSR1 */ +#define KS8842_TOSR1_P 0x0480 +#define KS8842_TOSR2_P 0x0482 +#define KS8842_TOSR3_P 0x0484 +#define KS8842_TOSR4_P 0x0486 +#define KS8842_TOSR5_P 0x0488 +#define KS8842_TOSR6_P 0x048A +#define KS8842_TOSR7_P 0x0490 +#define KS8842_TOSR8_P 0x0492 +#define KS8842_TOS_1_OFFSET KS8842_TOSR1_P +#define KS8842_TOS_2_OFFSET KS8842_TOSR2_P +#define KS8842_TOS_3_OFFSET KS8842_TOSR3_P +#define KS8842_TOS_4_OFFSET KS8842_TOSR4_P +#define KS8842_TOS_5_OFFSET KS8842_TOSR5_P +#define KS8842_TOS_6_OFFSET KS8842_TOSR6_P + +#define KS8842_TOS_7_OFFSET KS8842_TOSR7_P +#define KS8842_TOS_8_OFFSET KS8842_TOSR8_P + +/* P1CR1 */ +#define KS8842_P1CR1_P 0x0500 +#define KS8842_P1CR2_P 0x0502 +#define KS8842_P1VIDR_P 0x0504 +#define KS8842_P1CR3_P 0x0506 +#define KS8842_P1IRCR_P 0x0508 +#define KS8842_P1ERCR_P 0x050A +#define KS884X_P1SCSLMD_P 0x0510 +#define KS884X_P1CR4_P 0x0512 +#define KS884X_P1SR_P 0x0514 + +/* P2CR1 */ +#define KS8842_P2CR1_P 0x0520 +#define KS8842_P2CR2_P 0x0522 +#define KS8842_P2VIDR_P 0x0524 +#define KS8842_P2CR3_P 0x0526 +#define KS8842_P2IRCR_P 0x0528 +#define KS8842_P2ERCR_P 0x052A +#define KS884X_P2SCSLMD_P 0x0530 +#define KS884X_P2CR4_P 0x0532 +#define KS884X_P2SR_P 0x0534 + +/* P3CR1 */ +#define KS8842_P3CR1_P 0x0540 +#define KS8842_P3CR2_P 0x0542 +#define KS8842_P3VIDR_P 0x0544 +#define KS8842_P3CR3_P 0x0546 +#define KS8842_P3IRCR_P 0x0548 +#define KS8842_P3ERCR_P 0x054A + +#define KS8842_PORT_1_CTRL_1 KS8842_P1CR1_P +#define KS8842_PORT_2_CTRL_1 KS8842_P2CR1_P +#define KS8842_PORT_3_CTRL_1 KS8842_P3CR1_P + +#define PORT_CTRL_ADDR(port, addr) \ + (addr = KS8842_PORT_1_CTRL_1 + (port) * \ + (KS8842_PORT_2_CTRL_1 - KS8842_PORT_1_CTRL_1)) + +#define KS8842_PORT_CTRL_1_OFFSET 0x00 + +#define PORT_BROADCAST_STORM 0x0080 +#define PORT_DIFFSERV_ENABLE 0x0040 +#define PORT_802_1P_ENABLE 0x0020 +#define PORT_BASED_PRIORITY_MASK 0x0018 +#define PORT_BASED_PRIORITY_BASE 0x0003 +#define PORT_BASED_PRIORITY_SHIFT 3 +#define PORT_BASED_PRIORITY_0 0x0000 +#define PORT_BASED_PRIORITY_1 0x0008 +#define PORT_BASED_PRIORITY_2 0x0010 +#define PORT_BASED_PRIORITY_3 0x0018 +#define PORT_INSERT_TAG 0x0004 +#define PORT_REMOVE_TAG 0x0002 +#define PORT_PRIO_QUEUE_ENABLE 0x0001 + +#define KS8842_PORT_CTRL_2_OFFSET 0x02 + +#define PORT_INGRESS_VLAN_FILTER 0x4000 +#define PORT_DISCARD_NON_VID 0x2000 +#define PORT_FORCE_FLOW_CTRL 0x1000 +#define PORT_BACK_PRESSURE 0x0800 +#define PORT_TX_ENABLE 0x0400 +#define PORT_RX_ENABLE 0x0200 +#define PORT_LEARN_DISABLE 0x0100 +#define PORT_MIRROR_SNIFFER 0x0080 +#define PORT_MIRROR_RX 0x0040 +#define PORT_MIRROR_TX 0x0020 +#define PORT_USER_PRIORITY_CEILING 0x0008 +#define PORT_VLAN_MEMBERSHIP 0x0007 + +#define KS8842_PORT_CTRL_VID_OFFSET 0x04 + +#define PORT_DEFAULT_VID 0x0001 + +#define KS8842_PORT_CTRL_3_OFFSET 0x06 + +#define PORT_INGRESS_LIMIT_MODE 0x000C +#define PORT_INGRESS_ALL 0x0000 +#define PORT_INGRESS_UNICAST 0x0004 +#define PORT_INGRESS_MULTICAST 0x0008 +#define PORT_INGRESS_BROADCAST 0x000C +#define PORT_COUNT_IFG 0x0002 +#define PORT_COUNT_PREAMBLE 0x0001 + +#define KS8842_PORT_IN_RATE_OFFSET 0x08 +#define KS8842_PORT_OUT_RATE_OFFSET 0x0A + +#define PORT_PRIORITY_RATE 0x0F +#define PORT_PRIORITY_RATE_SHIFT 4 + +#define KS884X_PORT_LINK_MD 0x10 + +#define PORT_CABLE_10M_SHORT 0x8000 +#define PORT_CABLE_DIAG_RESULT 0x6000 +#define PORT_CABLE_STAT_NORMAL 0x0000 +#define PORT_CABLE_STAT_OPEN 0x2000 +#define PORT_CABLE_STAT_SHORT 0x4000 +#define PORT_CABLE_STAT_FAILED 0x6000 +#define PORT_START_CABLE_DIAG 0x1000 +#define PORT_FORCE_LINK 0x0800 +#define PORT_POWER_SAVING_DISABLE 0x0400 +#define PORT_PHY_REMOTE_LOOPBACK 0x0200 +#define PORT_CABLE_FAULT_COUNTER 0x01FF + +#define KS884X_PORT_CTRL_4_OFFSET 0x12 + +#define PORT_LED_OFF 0x8000 +#define PORT_TX_DISABLE 0x4000 +#define PORT_AUTO_NEG_RESTART 0x2000 +#define PORT_REMOTE_FAULT_DISABLE 0x1000 +#define PORT_POWER_DOWN 0x0800 +#define PORT_AUTO_MDIX_DISABLE 0x0400 +#define PORT_FORCE_MDIX 0x0200 +#define PORT_LOOPBACK 0x0100 +#define PORT_AUTO_NEG_ENABLE 0x0080 +#define PORT_FORCE_100_MBIT 0x0040 +#define PORT_FORCE_FULL_DUPLEX 0x0020 +#define PORT_AUTO_NEG_SYM_PAUSE 0x0010 +#define PORT_AUTO_NEG_100BTX_FD 0x0008 +#define PORT_AUTO_NEG_100BTX 0x0004 +#define PORT_AUTO_NEG_10BT_FD 0x0002 +#define PORT_AUTO_NEG_10BT 0x0001 + +#define KS884X_PORT_STATUS_OFFSET 0x14 + +#define PORT_HP_MDIX 0x8000 +#define PORT_REVERSED_POLARITY 0x2000 +#define PORT_RX_FLOW_CTRL 0x0800 +#define PORT_TX_FLOW_CTRL 0x1000 +#define PORT_STATUS_SPEED_100MBIT 0x0400 +#define PORT_STATUS_FULL_DUPLEX 0x0200 +#define PORT_REMOTE_FAULT 0x0100 +#define PORT_MDIX_STATUS 0x0080 +#define PORT_AUTO_NEG_COMPLETE 0x0040 +#define PORT_STATUS_LINK_GOOD 0x0020 +#define PORT_REMOTE_SYM_PAUSE 0x0010 +#define PORT_REMOTE_100BTX_FD 0x0008 +#define PORT_REMOTE_100BTX 0x0004 +#define PORT_REMOTE_10BT_FD 0x0002 +#define PORT_REMOTE_10BT 0x0001 + +/* +#define STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF +#define STATIC_MAC_TABLE_FWD_PORTS 00-00070000-00000000 +#define STATIC_MAC_TABLE_VALID 00-00080000-00000000 +#define STATIC_MAC_TABLE_OVERRIDE 00-00100000-00000000 +#define STATIC_MAC_TABLE_USE_FID 00-00200000-00000000 +#define STATIC_MAC_TABLE_FID 00-03C00000-00000000 +*/ + +#define STATIC_MAC_TABLE_ADDR 0x0000FFFF +#define STATIC_MAC_TABLE_FWD_PORTS 0x00070000 +#define STATIC_MAC_TABLE_VALID 0x00080000 +#define STATIC_MAC_TABLE_OVERRIDE 0x00100000 +#define STATIC_MAC_TABLE_USE_FID 0x00200000 +#define STATIC_MAC_TABLE_FID 0x03C00000 + +#define STATIC_MAC_FWD_PORTS_SHIFT 16 +#define STATIC_MAC_FID_SHIFT 22 + +/* +#define VLAN_TABLE_VID 00-00000000-00000FFF +#define VLAN_TABLE_FID 00-00000000-0000F000 +#define VLAN_TABLE_MEMBERSHIP 00-00000000-00070000 +#define VLAN_TABLE_VALID 00-00000000-00080000 +*/ + +#define VLAN_TABLE_VID 0x00000FFF +#define VLAN_TABLE_FID 0x0000F000 +#define VLAN_TABLE_MEMBERSHIP 0x00070000 +#define VLAN_TABLE_VALID 0x00080000 + +#define VLAN_TABLE_FID_SHIFT 12 +#define VLAN_TABLE_MEMBERSHIP_SHIFT 16 + +/* +#define DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF +#define DYNAMIC_MAC_TABLE_FID 00-000F0000-00000000 +#define DYNAMIC_MAC_TABLE_SRC_PORT 00-00300000-00000000 +#define DYNAMIC_MAC_TABLE_TIMESTAMP 00-00C00000-00000000 +#define DYNAMIC_MAC_TABLE_ENTRIES 03-FF000000-00000000 +#define DYNAMIC_MAC_TABLE_MAC_EMPTY 04-00000000-00000000 +#define DYNAMIC_MAC_TABLE_RESERVED 78-00000000-00000000 +#define DYNAMIC_MAC_TABLE_NOT_READY 80-00000000-00000000 +*/ + +#define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF +#define DYNAMIC_MAC_TABLE_FID 0x000F0000 +#define DYNAMIC_MAC_TABLE_SRC_PORT 0x00300000 +#define DYNAMIC_MAC_TABLE_TIMESTAMP 0x00C00000 +#define DYNAMIC_MAC_TABLE_ENTRIES 0xFF000000 + +#define DYNAMIC_MAC_TABLE_ENTRIES_H 0x03 +#define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x04 +#define DYNAMIC_MAC_TABLE_RESERVED 0x78 +#define DYNAMIC_MAC_TABLE_NOT_READY 0x80 + +#define DYNAMIC_MAC_FID_SHIFT 16 +#define DYNAMIC_MAC_SRC_PORT_SHIFT 20 +#define DYNAMIC_MAC_TIMESTAMP_SHIFT 22 +#define DYNAMIC_MAC_ENTRIES_SHIFT 24 +#define DYNAMIC_MAC_ENTRIES_H_SHIFT 8 + +/* +#define MIB_COUNTER_VALUE 00-00000000-3FFFFFFF +#define MIB_COUNTER_VALID 00-00000000-40000000 +#define MIB_COUNTER_OVERFLOW 00-00000000-80000000 +*/ + +#define MIB_COUNTER_VALUE 0x3FFFFFFF +#define MIB_COUNTER_VALID 0x40000000 +#define MIB_COUNTER_OVERFLOW 0x80000000 + +#define MIB_PACKET_DROPPED 0x0000FFFF + +#define KS_MIB_PACKET_DROPPED_TX_0 0x100 +#define KS_MIB_PACKET_DROPPED_TX_1 0x101 +#define KS_MIB_PACKET_DROPPED_TX 0x102 +#define KS_MIB_PACKET_DROPPED_RX_0 0x103 +#define KS_MIB_PACKET_DROPPED_RX_1 0x104 +#define KS_MIB_PACKET_DROPPED_RX 0x105 + +/* Change default LED mode. */ +#define SET_DEFAULT_LED LED_SPEED_DUPLEX_ACT + +#define MAC_ADDR_LEN 6 +#define MAC_ADDR_ORDER(i) (MAC_ADDR_LEN - 1 - (i)) + +#define MAX_ETHERNET_BODY_SIZE 1500 +#define ETHERNET_HEADER_SIZE 14 + +#define MAX_ETHERNET_PACKET_SIZE \ + (MAX_ETHERNET_BODY_SIZE + ETHERNET_HEADER_SIZE) + +#define REGULAR_RX_BUF_SIZE (MAX_ETHERNET_PACKET_SIZE + 4) +#define MAX_RX_BUF_SIZE (1912 + 4) + +#define ADDITIONAL_ENTRIES 16 +#define MAX_MULTICAST_LIST 32 + +#define HW_MULTICAST_SIZE 8 + +#define HW_TO_DEV_PORT(port) (port - 1) + +enum { + media_connected, + media_disconnected +}; + +enum { + OID_COUNTER_UNKOWN, + + OID_COUNTER_FIRST, + + /* total transmit errors */ + OID_COUNTER_XMIT_ERROR, + + /* total receive errors */ + OID_COUNTER_RCV_ERROR, + + OID_COUNTER_LAST +}; + +/* + * Hardware descriptor definitions + */ + +#define DESC_ALIGNMENT 16 +#define BUFFER_ALIGNMENT 8 + +#define NUM_OF_RX_DESC 64 +#define NUM_OF_TX_DESC 64 + +#define KS_DESC_RX_FRAME_LEN 0x000007FF +#define KS_DESC_RX_FRAME_TYPE 0x00008000 +#define KS_DESC_RX_ERROR_CRC 0x00010000 +#define KS_DESC_RX_ERROR_RUNT 0x00020000 +#define KS_DESC_RX_ERROR_TOO_LONG 0x00040000 +#define KS_DESC_RX_ERROR_PHY 0x00080000 +#define KS884X_DESC_RX_PORT_MASK 0x00300000 +#define KS_DESC_RX_MULTICAST 0x01000000 +#define KS_DESC_RX_ERROR 0x02000000 +#define KS_DESC_RX_ERROR_CSUM_UDP 0x04000000 +#define KS_DESC_RX_ERROR_CSUM_TCP 0x08000000 +#define KS_DESC_RX_ERROR_CSUM_IP 0x10000000 +#define KS_DESC_RX_LAST 0x20000000 +#define KS_DESC_RX_FIRST 0x40000000 +#define KS_DESC_RX_ERROR_COND \ + (KS_DESC_RX_ERROR_CRC | \ + KS_DESC_RX_ERROR_RUNT | \ + KS_DESC_RX_ERROR_PHY | \ + KS_DESC_RX_ERROR_TOO_LONG) + +#define KS_DESC_HW_OWNED 0x80000000 + +#define KS_DESC_BUF_SIZE 0x000007FF +#define KS884X_DESC_TX_PORT_MASK 0x00300000 +#define KS_DESC_END_OF_RING 0x02000000 +#define KS_DESC_TX_CSUM_GEN_UDP 0x04000000 +#define KS_DESC_TX_CSUM_GEN_TCP 0x08000000 +#define KS_DESC_TX_CSUM_GEN_IP 0x10000000 +#define KS_DESC_TX_LAST 0x20000000 +#define KS_DESC_TX_FIRST 0x40000000 +#define KS_DESC_TX_INTERRUPT 0x80000000 + +#define KS_DESC_PORT_SHIFT 20 + +#define KS_DESC_RX_MASK (KS_DESC_BUF_SIZE) + +#define KS_DESC_TX_MASK \ + (KS_DESC_TX_INTERRUPT | \ + KS_DESC_TX_FIRST | \ + KS_DESC_TX_LAST | \ + KS_DESC_TX_CSUM_GEN_IP | \ + KS_DESC_TX_CSUM_GEN_TCP | \ + KS_DESC_TX_CSUM_GEN_UDP | \ + KS_DESC_BUF_SIZE) + +struct ksz_desc_rx_stat { +#ifdef __BIG_ENDIAN_BITFIELD + u32 hw_owned:1; + u32 first_desc:1; + u32 last_desc:1; + u32 csum_err_ip:1; + u32 csum_err_tcp:1; + u32 csum_err_udp:1; + u32 error:1; + u32 multicast:1; + u32 src_port:4; + u32 err_phy:1; + u32 err_too_long:1; + u32 err_runt:1; + u32 err_crc:1; + u32 frame_type:1; + u32 reserved1:4; + u32 frame_len:11; +#else + u32 frame_len:11; + u32 reserved1:4; + u32 frame_type:1; + u32 err_crc:1; + u32 err_runt:1; + u32 err_too_long:1; + u32 err_phy:1; + u32 src_port:4; + u32 multicast:1; + u32 error:1; + u32 csum_err_udp:1; + u32 csum_err_tcp:1; + u32 csum_err_ip:1; + u32 last_desc:1; + u32 first_desc:1; + u32 hw_owned:1; +#endif +}; + +struct ksz_desc_tx_stat { +#ifdef __BIG_ENDIAN_BITFIELD + u32 hw_owned:1; + u32 reserved1:31; +#else + u32 reserved1:31; + u32 hw_owned:1; +#endif +}; + +struct ksz_desc_rx_buf { +#ifdef __BIG_ENDIAN_BITFIELD + u32 reserved4:6; + u32 end_of_ring:1; + u32 reserved3:14; + u32 buf_size:11; +#else + u32 buf_size:11; + u32 reserved3:14; + u32 end_of_ring:1; + u32 reserved4:6; +#endif +}; + +struct ksz_desc_tx_buf { +#ifdef __BIG_ENDIAN_BITFIELD + u32 intr:1; + u32 first_seg:1; + u32 last_seg:1; + u32 csum_gen_ip:1; + u32 csum_gen_tcp:1; + u32 csum_gen_udp:1; + u32 end_of_ring:1; + u32 reserved4:1; + u32 dest_port:4; + u32 reserved3:9; + u32 buf_size:11; +#else + u32 buf_size:11; + u32 reserved3:9; + u32 dest_port:4; + u32 reserved4:1; + u32 end_of_ring:1; + u32 csum_gen_udp:1; + u32 csum_gen_tcp:1; + u32 csum_gen_ip:1; + u32 last_seg:1; + u32 first_seg:1; + u32 intr:1; +#endif +}; + +union desc_stat { + struct ksz_desc_rx_stat rx; + struct ksz_desc_tx_stat tx; + u32 data; +}; + +union desc_buf { + struct ksz_desc_rx_buf rx; + struct ksz_desc_tx_buf tx; + u32 data; +}; + +/** + * struct ksz_hw_desc - Hardware descriptor data structure + * @ctrl: Descriptor control value. + * @buf: Descriptor buffer value. + * @addr: Physical address of memory buffer. + * @next: Pointer to next hardware descriptor. + */ +struct ksz_hw_desc { + union desc_stat ctrl; + union desc_buf buf; + u32 addr; + u32 next; +}; + +/** + * struct ksz_sw_desc - Software descriptor data structure + * @ctrl: Descriptor control value. + * @buf: Descriptor buffer value. + * @buf_size: Current buffers size value in hardware descriptor. + */ +struct ksz_sw_desc { + union desc_stat ctrl; + union desc_buf buf; + u32 buf_size; +}; + +/** + * struct ksz_dma_buf - OS dependent DMA buffer data structure + * @skb: Associated socket buffer. + * @dma: Associated physical DMA address. + * len: Actual len used. + */ +struct ksz_dma_buf { + struct sk_buff *skb; + dma_addr_t dma; + int len; +}; + +/** + * struct ksz_desc - Descriptor structure + * @phw: Hardware descriptor pointer to uncached physical memory. + * @sw: Cached memory to hold hardware descriptor values for + * manipulation. + * @dma_buf: Operating system dependent data structure to hold physical + * memory buffer allocation information. + */ +struct ksz_desc { + struct ksz_hw_desc *phw; + struct ksz_sw_desc sw; + struct ksz_dma_buf dma_buf; +}; + +#define DMA_BUFFER(desc) ((struct ksz_dma_buf *)(&(desc)->dma_buf)) + +/** + * struct ksz_desc_info - Descriptor information data structure + * @ring: First descriptor in the ring. + * @cur: Current descriptor being manipulated. + * @ring_virt: First hardware descriptor in the ring. + * @ring_phys: The physical address of the first descriptor of the ring. + * @size: Size of hardware descriptor. + * @alloc: Number of descriptors allocated. + * @avail: Number of descriptors available for use. + * @last: Index for last descriptor released to hardware. + * @next: Index for next descriptor available for use. + * @mask: Mask for index wrapping. + */ +struct ksz_desc_info { + struct ksz_desc *ring; + struct ksz_desc *cur; + struct ksz_hw_desc *ring_virt; + u32 ring_phys; + int size; + int alloc; + int avail; + int last; + int next; + int mask; +}; + +/* + * KSZ8842 switch definitions + */ + +enum { + TABLE_STATIC_MAC = 0, + TABLE_VLAN, + TABLE_DYNAMIC_MAC, + TABLE_MIB +}; + +#define LEARNED_MAC_TABLE_ENTRIES 1024 +#define STATIC_MAC_TABLE_ENTRIES 8 + +/** + * struct ksz_mac_table - Static MAC table data structure + * @mac_addr: MAC address to filter. + * @vid: VID value. + * @fid: FID value. + * @ports: Port membership. + * @override: Override setting. + * @use_fid: FID use setting. + * @valid: Valid setting indicating the entry is being used. + */ +struct ksz_mac_table { + u8 mac_addr[MAC_ADDR_LEN]; + u16 vid; + u8 fid; + u8 ports; + u8 override:1; + u8 use_fid:1; + u8 valid:1; +}; + +#define VLAN_TABLE_ENTRIES 16 + +/** + * struct ksz_vlan_table - VLAN table data structure + * @vid: VID value. + * @fid: FID value. + * @member: Port membership. + */ +struct ksz_vlan_table { + u16 vid; + u8 fid; + u8 member; +}; + +#define DIFFSERV_ENTRIES 64 +#define PRIO_802_1P_ENTRIES 8 +#define PRIO_QUEUES 4 + +#define SWITCH_PORT_NUM 2 +#define TOTAL_PORT_NUM (SWITCH_PORT_NUM + 1) +#define HOST_MASK (1 << SWITCH_PORT_NUM) +#define PORT_MASK 7 + +#define MAIN_PORT 0 +#define OTHER_PORT 1 +#define HOST_PORT SWITCH_PORT_NUM + +#define PORT_COUNTER_NUM 0x20 +#define TOTAL_PORT_COUNTER_NUM (PORT_COUNTER_NUM + 2) + +#define MIB_COUNTER_RX_LO_PRIORITY 0x00 +#define MIB_COUNTER_RX_HI_PRIORITY 0x01 +#define MIB_COUNTER_RX_UNDERSIZE 0x02 +#define MIB_COUNTER_RX_FRAGMENT 0x03 +#define MIB_COUNTER_RX_OVERSIZE 0x04 +#define MIB_COUNTER_RX_JABBER 0x05 +#define MIB_COUNTER_RX_SYMBOL_ERR 0x06 +#define MIB_COUNTER_RX_CRC_ERR 0x07 +#define MIB_COUNTER_RX_ALIGNMENT_ERR 0x08 +#define MIB_COUNTER_RX_CTRL_8808 0x09 +#define MIB_COUNTER_RX_PAUSE 0x0A +#define MIB_COUNTER_RX_BROADCAST 0x0B +#define MIB_COUNTER_RX_MULTICAST 0x0C +#define MIB_COUNTER_RX_UNICAST 0x0D +#define MIB_COUNTER_RX_OCTET_64 0x0E +#define MIB_COUNTER_RX_OCTET_65_127 0x0F +#define MIB_COUNTER_RX_OCTET_128_255 0x10 +#define MIB_COUNTER_RX_OCTET_256_511 0x11 +#define MIB_COUNTER_RX_OCTET_512_1023 0x12 +#define MIB_COUNTER_RX_OCTET_1024_1522 0x13 +#define MIB_COUNTER_TX_LO_PRIORITY 0x14 +#define MIB_COUNTER_TX_HI_PRIORITY 0x15 +#define MIB_COUNTER_TX_LATE_COLLISION 0x16 +#define MIB_COUNTER_TX_PAUSE 0x17 +#define MIB_COUNTER_TX_BROADCAST 0x18 +#define MIB_COUNTER_TX_MULTICAST 0x19 +#define MIB_COUNTER_TX_UNICAST 0x1A +#define MIB_COUNTER_TX_DEFERRED 0x1B +#define MIB_COUNTER_TX_TOTAL_COLLISION 0x1C +#define MIB_COUNTER_TX_EXCESS_COLLISION 0x1D +#define MIB_COUNTER_TX_SINGLE_COLLISION 0x1E +#define MIB_COUNTER_TX_MULTI_COLLISION 0x1F + +#define MIB_COUNTER_RX_DROPPED_PACKET 0x20 +#define MIB_COUNTER_TX_DROPPED_PACKET 0x21 + +/** + * struct ksz_port_mib - Port MIB data structure + * @cnt_ptr: Current pointer to MIB counter index. + * @link_down: Indication the link has just gone down. + * @state: Connection status of the port. + * @mib_start: The starting counter index. Some ports do not start at 0. + * @counter: 64-bit MIB counter value. + * @dropped: Temporary buffer to remember last read packet dropped values. + * + * MIB counters needs to be read periodically so that counters do not get + * overflowed and give incorrect values. A right balance is needed to + * satisfy this condition and not waste too much CPU time. + * + * It is pointless to read MIB counters when the port is disconnected. The + * @state provides the connection status so that MIB counters are read only + * when the port is connected. The @link_down indicates the port is just + * disconnected so that all MIB counters are read one last time to update the + * information. + */ +struct ksz_port_mib { + u8 cnt_ptr; + u8 link_down; + u8 state; + u8 mib_start; + + u64 counter[TOTAL_PORT_COUNTER_NUM]; + u32 dropped[2]; +}; + +/** + * struct ksz_port_cfg - Port configuration data structure + * @vid: VID value. + * @member: Port membership. + * @port_prio: Port priority. + * @rx_rate: Receive priority rate. + * @tx_rate: Transmit priority rate. + * @stp_state: Current Spanning Tree Protocol state. + */ +struct ksz_port_cfg { + u16 vid; + u8 member; + u8 port_prio; + u32 rx_rate[PRIO_QUEUES]; + u32 tx_rate[PRIO_QUEUES]; + int stp_state; +}; + +/** + * struct ksz_switch - KSZ8842 switch data structure + * @mac_table: MAC table entries information. + * @vlan_table: VLAN table entries information. + * @port_cfg: Port configuration information. + * @diffserv: DiffServ priority settings. Possible values from 6-bit of ToS + * (bit7 ~ bit2) field. + * @p_802_1p: 802.1P priority settings. Possible values from 3-bit of 802.1p + * Tag priority field. + * @br_addr: Bridge address. Used for STP. + * @other_addr: Other MAC address. Used for multiple network device mode. + * @broad_per: Broadcast storm percentage. + * @member: Current port membership. Used for STP. + */ +struct ksz_switch { + struct ksz_mac_table mac_table[STATIC_MAC_TABLE_ENTRIES]; + struct ksz_vlan_table vlan_table[VLAN_TABLE_ENTRIES]; + struct ksz_port_cfg port_cfg[TOTAL_PORT_NUM]; + + u8 diffserv[DIFFSERV_ENTRIES]; + u8 p_802_1p[PRIO_802_1P_ENTRIES]; + + u8 br_addr[MAC_ADDR_LEN]; + u8 other_addr[MAC_ADDR_LEN]; + + u8 broad_per; + u8 member; +}; + +#define TX_RATE_UNIT 10000 + +/** + * struct ksz_port_info - Port information data structure + * @state: Connection status of the port. + * @tx_rate: Transmit rate divided by 10000 to get Mbit. + * @duplex: Duplex mode. + * @advertised: Advertised auto-negotiation setting. Used to determine link. + * @partner: Auto-negotiation partner setting. Used to determine link. + * @port_id: Port index to access actual hardware register. + * @pdev: Pointer to OS dependent network device. + */ +struct ksz_port_info { + uint state; + uint tx_rate; + u8 duplex; + u8 advertised; + u8 partner; + u8 port_id; + void *pdev; +}; + +#define MAX_TX_HELD_SIZE 52000 + +/* Hardware features and bug fixes. */ +#define LINK_INT_WORKING (1 << 0) +#define SMALL_PACKET_TX_BUG (1 << 1) +#define HALF_DUPLEX_SIGNAL_BUG (1 << 2) +#define IPV6_CSUM_GEN_HACK (1 << 3) +#define RX_HUGE_FRAME (1 << 4) +#define STP_SUPPORT (1 << 8) + +/* Software overrides. */ +#define PAUSE_FLOW_CTRL (1 << 0) +#define FAST_AGING (1 << 1) + +/** + * struct ksz_hw - KSZ884X hardware data structure + * @io: Virtual address assigned. + * @ksz_switch: Pointer to KSZ8842 switch. + * @port_info: Port information. + * @port_mib: Port MIB information. + * @dev_count: Number of network devices this hardware supports. + * @dst_ports: Destination ports in switch for transmission. + * @id: Hardware ID. Used for display only. + * @mib_cnt: Number of MIB counters this hardware has. + * @mib_port_cnt: Number of ports with MIB counters. + * @tx_cfg: Cached transmit control settings. + * @rx_cfg: Cached receive control settings. + * @intr_mask: Current interrupt mask. + * @intr_set: Current interrup set. + * @intr_blocked: Interrupt blocked. + * @rx_desc_info: Receive descriptor information. + * @tx_desc_info: Transmit descriptor information. + * @tx_int_cnt: Transmit interrupt count. Used for TX optimization. + * @tx_int_mask: Transmit interrupt mask. Used for TX optimization. + * @tx_size: Transmit data size. Used for TX optimization. + * The maximum is defined by MAX_TX_HELD_SIZE. + * @perm_addr: Permanent MAC address. + * @override_addr: Overrided MAC address. + * @address: Additional MAC address entries. + * @addr_list_size: Additional MAC address list size. + * @mac_override: Indication of MAC address overrided. + * @promiscuous: Counter to keep track of promiscuous mode set. + * @all_multi: Counter to keep track of all multicast mode set. + * @multi_list: Multicast address entries. + * @multi_bits: Cached multicast hash table settings. + * @multi_list_size: Multicast address list size. + * @enabled: Indication of hardware enabled. + * @rx_stop: Indication of receive process stop. + * @features: Hardware features to enable. + * @overrides: Hardware features to override. + * @parent: Pointer to parent, network device private structure. + */ +struct ksz_hw { + void __iomem *io; + + struct ksz_switch *ksz_switch; + struct ksz_port_info port_info[SWITCH_PORT_NUM]; + struct ksz_port_mib port_mib[TOTAL_PORT_NUM]; + int dev_count; + int dst_ports; + int id; + int mib_cnt; + int mib_port_cnt; + + u32 tx_cfg; + u32 rx_cfg; + u32 intr_mask; + u32 intr_set; + uint intr_blocked; + + struct ksz_desc_info rx_desc_info; + struct ksz_desc_info tx_desc_info; + + int tx_int_cnt; + int tx_int_mask; + int tx_size; + + u8 perm_addr[MAC_ADDR_LEN]; + u8 override_addr[MAC_ADDR_LEN]; + u8 address[ADDITIONAL_ENTRIES][MAC_ADDR_LEN]; + u8 addr_list_size; + u8 mac_override; + u8 promiscuous; + u8 all_multi; + u8 multi_list[MAX_MULTICAST_LIST][MAC_ADDR_LEN]; + u8 multi_bits[HW_MULTICAST_SIZE]; + u8 multi_list_size; + + u8 enabled; + u8 rx_stop; + u8 reserved2[1]; + + uint features; + uint overrides; + + void *parent; +}; + +enum { + PHY_NO_FLOW_CTRL, + PHY_FLOW_CTRL, + PHY_TX_ONLY, + PHY_RX_ONLY +}; + +/** + * struct ksz_port - Virtual port data structure + * @duplex: Duplex mode setting. 1 for half duplex, 2 for full + * duplex, and 0 for auto, which normally results in full + * duplex. + * @speed: Speed setting. 10 for 10 Mbit, 100 for 100 Mbit, and + * 0 for auto, which normally results in 100 Mbit. + * @force_link: Force link setting. 0 for auto-negotiation, and 1 for + * force. + * @flow_ctrl: Flow control setting. PHY_NO_FLOW_CTRL for no flow + * control, and PHY_FLOW_CTRL for flow control. + * PHY_TX_ONLY and PHY_RX_ONLY are not supported for 100 + * Mbit PHY. + * @first_port: Index of first port this port supports. + * @mib_port_cnt: Number of ports with MIB counters. + * @port_cnt: Number of ports this port supports. + * @counter: Port statistics counter. + * @hw: Pointer to hardware structure. + * @linked: Pointer to port information linked to this port. + */ +struct ksz_port { + u8 duplex; + u8 speed; + u8 force_link; + u8 flow_ctrl; + + int first_port; + int mib_port_cnt; + int port_cnt; + u64 counter[OID_COUNTER_LAST]; + + struct ksz_hw *hw; + struct ksz_port_info *linked; +}; + +/** + * struct ksz_timer_info - Timer information data structure + * @timer: Kernel timer. + * @cnt: Running timer counter. + * @max: Number of times to run timer; -1 for infinity. + * @period: Timer period in jiffies. + */ +struct ksz_timer_info { + struct timer_list timer; + int cnt; + int max; + int period; +}; + +/** + * struct ksz_shared_mem - OS dependent shared memory data structure + * @dma_addr: Physical DMA address allocated. + * @alloc_size: Allocation size. + * @phys: Actual physical address used. + * @alloc_virt: Virtual address allocated. + * @virt: Actual virtual address used. + */ +struct ksz_shared_mem { + dma_addr_t dma_addr; + uint alloc_size; + uint phys; + u8 *alloc_virt; + u8 *virt; +}; + +/** + * struct ksz_counter_info - OS dependent counter information data structure + * @counter: Wait queue to wakeup after counters are read. + * @time: Next time in jiffies to read counter. + * @read: Indication of counters read in full or not. + */ +struct ksz_counter_info { + wait_queue_head_t counter; + unsigned long time; + int read; +}; + +/** + * struct dev_info - Network device information data structure + * @dev: Pointer to network device. + * @pdev: Pointer to PCI device. + * @hw: Hardware structure. + * @desc_pool: Physical memory used for descriptor pool. + * @hwlock: Spinlock to prevent hardware from accessing. + * @lock: Mutex lock to prevent device from accessing. + * @dev_rcv: Receive process function used. + * @last_skb: Socket buffer allocated for descriptor rx fragments. + * @skb_index: Buffer index for receiving fragments. + * @skb_len: Buffer length for receiving fragments. + * @mib_read: Workqueue to read MIB counters. + * @mib_timer_info: Timer to read MIB counters. + * @counter: Used for MIB reading. + * @mtu: Current MTU used. The default is REGULAR_RX_BUF_SIZE; + * the maximum is MAX_RX_BUF_SIZE. + * @opened: Counter to keep track of device open. + * @rx_tasklet: Receive processing tasklet. + * @tx_tasklet: Transmit processing tasklet. + * @wol_enable: Wake-on-LAN enable set by ethtool. + * @wol_support: Wake-on-LAN support used by ethtool. + * @pme_wait: Used for KSZ8841 power management. + */ +struct dev_info { + struct net_device *dev; + struct pci_dev *pdev; + + struct ksz_hw hw; + struct ksz_shared_mem desc_pool; + + spinlock_t hwlock; + struct mutex lock; + + int (*dev_rcv)(struct dev_info *); + + struct sk_buff *last_skb; + int skb_index; + int skb_len; + + struct work_struct mib_read; + struct ksz_timer_info mib_timer_info; + struct ksz_counter_info counter[TOTAL_PORT_NUM]; + + int mtu; + int opened; + + struct tasklet_struct rx_tasklet; + struct tasklet_struct tx_tasklet; + + int wol_enable; + int wol_support; + unsigned long pme_wait; +}; + +/** + * struct dev_priv - Network device private data structure + * @adapter: Adapter device information. + * @port: Port information. + * @monitor_time_info: Timer to monitor ports. + * @stats: Network statistics. + * @proc_sem: Semaphore for proc accessing. + * @id: Device ID. + * @mii_if: MII interface information. + * @advertising: Temporary variable to store advertised settings. + * @msg_enable: The message flags controlling driver output. + * @media_state: The connection status of the device. + * @multicast: The all multicast state of the device. + * @promiscuous: The promiscuous state of the device. + */ +struct dev_priv { + struct dev_info *adapter; + struct ksz_port port; + struct ksz_timer_info monitor_timer_info; + struct net_device_stats stats; + + struct semaphore proc_sem; + int id; + + struct mii_if_info mii_if; + u32 advertising; + + u32 msg_enable; + int media_state; + int multicast; + int promiscuous; +}; + +#define ks_info(_ks, _msg...) dev_info(&(_ks)->pdev->dev, _msg) +#define ks_warn(_ks, _msg...) dev_warn(&(_ks)->pdev->dev, _msg) +#define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->pdev->dev, _msg) +#define ks_err(_ks, _msg...) dev_err(&(_ks)->pdev->dev, _msg) + +#define DRV_NAME "KSZ884X PCI" +#define DEVICE_NAME "KSZ884x PCI" +#define DRV_VERSION "1.0.0" +#define DRV_RELDATE "Feb 8, 2010" + +static char version[] __devinitdata = + "Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")"; + +static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 }; + +/* + * Interrupt processing primary routines + */ + +static inline void hw_ack_intr(struct ksz_hw *hw, uint interrupt) +{ + writel(interrupt, hw->io + KS884X_INTERRUPTS_STATUS); +} + +static inline void hw_dis_intr(struct ksz_hw *hw) +{ + hw->intr_blocked = hw->intr_mask; + writel(0, hw->io + KS884X_INTERRUPTS_ENABLE); + hw->intr_set = readl(hw->io + KS884X_INTERRUPTS_ENABLE); +} + +static inline void hw_set_intr(struct ksz_hw *hw, uint interrupt) +{ + hw->intr_set = interrupt; + writel(interrupt, hw->io + KS884X_INTERRUPTS_ENABLE); +} + +static inline void hw_ena_intr(struct ksz_hw *hw) +{ + hw->intr_blocked = 0; + hw_set_intr(hw, hw->intr_mask); +} + +static inline void hw_dis_intr_bit(struct ksz_hw *hw, uint bit) +{ + hw->intr_mask &= ~(bit); +} + +static inline void hw_turn_off_intr(struct ksz_hw *hw, uint interrupt) +{ + u32 read_intr; + + read_intr = readl(hw->io + KS884X_INTERRUPTS_ENABLE); + hw->intr_set = read_intr & ~interrupt; + writel(hw->intr_set, hw->io + KS884X_INTERRUPTS_ENABLE); + hw_dis_intr_bit(hw, interrupt); +} + +/** + * hw_turn_on_intr - turn on specified interrupts + * @hw: The hardware instance. + * @bit: The interrupt bits to be on. + * + * This routine turns on the specified interrupts in the interrupt mask so that + * those interrupts will be enabled. + */ +static void hw_turn_on_intr(struct ksz_hw *hw, u32 bit) +{ + hw->intr_mask |= bit; + + if (!hw->intr_blocked) + hw_set_intr(hw, hw->intr_mask); +} + +static inline void hw_ena_intr_bit(struct ksz_hw *hw, uint interrupt) +{ + u32 read_intr; + + read_intr = readl(hw->io + KS884X_INTERRUPTS_ENABLE); + hw->intr_set = read_intr | interrupt; + writel(hw->intr_set, hw->io + KS884X_INTERRUPTS_ENABLE); +} + +static inline void hw_read_intr(struct ksz_hw *hw, uint *status) +{ + *status = readl(hw->io + KS884X_INTERRUPTS_STATUS); + *status = *status & hw->intr_set; +} + +static inline void hw_restore_intr(struct ksz_hw *hw, uint interrupt) +{ + if (interrupt) + hw_ena_intr(hw); +} + +/** + * hw_block_intr - block hardware interrupts + * + * This function blocks all interrupts of the hardware and returns the current + * interrupt enable mask so that interrupts can be restored later. + * + * Return the current interrupt enable mask. + */ +static uint hw_block_intr(struct ksz_hw *hw) +{ + uint interrupt = 0; + + if (!hw->intr_blocked) { + hw_dis_intr(hw); + interrupt = hw->intr_blocked; + } + return interrupt; +} + +/* + * Hardware descriptor routines + */ + +static inline void reset_desc(struct ksz_desc *desc, union desc_stat status) +{ + status.rx.hw_owned = 0; + desc->phw->ctrl.data = cpu_to_le32(status.data); +} + +static inline void release_desc(struct ksz_desc *desc) +{ + desc->sw.ctrl.tx.hw_owned = 1; + if (desc->sw.buf_size != desc->sw.buf.data) { + desc->sw.buf_size = desc->sw.buf.data; + desc->phw->buf.data = cpu_to_le32(desc->sw.buf.data); + } + desc->phw->ctrl.data = cpu_to_le32(desc->sw.ctrl.data); +} + +static void get_rx_pkt(struct ksz_desc_info *info, struct ksz_desc **desc) +{ + *desc = &info->ring[info->last]; + info->last++; + info->last &= info->mask; + info->avail--; + (*desc)->sw.buf.data &= ~KS_DESC_RX_MASK; +} + +static inline void set_rx_buf(struct ksz_desc *desc, u32 addr) +{ + desc->phw->addr = cpu_to_le32(addr); +} + +static inline void set_rx_len(struct ksz_desc *desc, u32 len) +{ + desc->sw.buf.rx.buf_size = len; +} + +static inline void get_tx_pkt(struct ksz_desc_info *info, + struct ksz_desc **desc) +{ + *desc = &info->ring[info->next]; + info->next++; + info->next &= info->mask; + info->avail--; + (*desc)->sw.buf.data &= ~KS_DESC_TX_MASK; +} + +static inline void set_tx_buf(struct ksz_desc *desc, u32 addr) +{ + desc->phw->addr = cpu_to_le32(addr); +} + +static inline void set_tx_len(struct ksz_desc *desc, u32 len) +{ + desc->sw.buf.tx.buf_size = len; +} + +/* Switch functions */ + +#define TABLE_READ 0x10 +#define TABLE_SEL_SHIFT 2 + +#define HW_DELAY(hw, reg) \ + do { \ + u16 dummy; \ + dummy = readw(hw->io + reg); \ + } while (0) + +/** + * sw_r_table - read 4 bytes of data from switch table + * @hw: The hardware instance. + * @table: The table selector. + * @addr: The address of the table entry. + * @data: Buffer to store the read data. + * + * This routine reads 4 bytes of data from the table of the switch. + * Hardware interrupts are disabled to minimize corruption of read data. + */ +static void sw_r_table(struct ksz_hw *hw, int table, u16 addr, u32 *data) +{ + u16 ctrl_addr; + uint interrupt; + + ctrl_addr = (((table << TABLE_SEL_SHIFT) | TABLE_READ) << 8) | addr; + + interrupt = hw_block_intr(hw); + + writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET); + HW_DELAY(hw, KS884X_IACR_OFFSET); + *data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET); + + hw_restore_intr(hw, interrupt); +} + +/** + * sw_w_table_64 - write 8 bytes of data to the switch table + * @hw: The hardware instance. + * @table: The table selector. + * @addr: The address of the table entry. + * @data_hi: The high part of data to be written (bit63 ~ bit32). + * @data_lo: The low part of data to be written (bit31 ~ bit0). + * + * This routine writes 8 bytes of data to the table of the switch. + * Hardware interrupts are disabled to minimize corruption of written data. + */ +static void sw_w_table_64(struct ksz_hw *hw, int table, u16 addr, u32 data_hi, + u32 data_lo) +{ + u16 ctrl_addr; + uint interrupt; + + ctrl_addr = ((table << TABLE_SEL_SHIFT) << 8) | addr; + + interrupt = hw_block_intr(hw); + + writel(data_hi, hw->io + KS884X_ACC_DATA_4_OFFSET); + writel(data_lo, hw->io + KS884X_ACC_DATA_0_OFFSET); + + writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET); + HW_DELAY(hw, KS884X_IACR_OFFSET); + + hw_restore_intr(hw, interrupt); +} + +/** + * sw_w_sta_mac_table - write to the static MAC table + * @hw: The hardware instance. + * @addr: The address of the table entry. + * @mac_addr: The MAC address. + * @ports: The port members. + * @override: The flag to override the port receive/transmit settings. + * @valid: The flag to indicate entry is valid. + * @use_fid: The flag to indicate the FID is valid. + * @fid: The FID value. + * + * This routine writes an entry of the static MAC table of the switch. It + * calls sw_w_table_64() to write the data. + */ +static void sw_w_sta_mac_table(struct ksz_hw *hw, u16 addr, u8 *mac_addr, + u8 ports, int override, int valid, int use_fid, u8 fid) +{ + u32 data_hi; + u32 data_lo; + + data_lo = ((u32) mac_addr[2] << 24) | + ((u32) mac_addr[3] << 16) | + ((u32) mac_addr[4] << 8) | mac_addr[5]; + data_hi = ((u32) mac_addr[0] << 8) | mac_addr[1]; + data_hi |= (u32) ports << STATIC_MAC_FWD_PORTS_SHIFT; + + if (override) + data_hi |= STATIC_MAC_TABLE_OVERRIDE; + if (use_fid) { + data_hi |= STATIC_MAC_TABLE_USE_FID; + data_hi |= (u32) fid << STATIC_MAC_FID_SHIFT; + } + if (valid) + data_hi |= STATIC_MAC_TABLE_VALID; + + sw_w_table_64(hw, TABLE_STATIC_MAC, addr, data_hi, data_lo); +} + +/** + * sw_r_vlan_table - read from the VLAN table + * @hw: The hardware instance. + * @addr: The address of the table entry. + * @vid: Buffer to store the VID. + * @fid: Buffer to store the VID. + * @member: Buffer to store the port membership. + * + * This function reads an entry of the VLAN table of the switch. It calls + * sw_r_table() to get the data. + * + * Return 0 if the entry is valid; otherwise -1. + */ +static int sw_r_vlan_table(struct ksz_hw *hw, u16 addr, u16 *vid, u8 *fid, + u8 *member) +{ + u32 data; + + sw_r_table(hw, TABLE_VLAN, addr, &data); + if (data & VLAN_TABLE_VALID) { + *vid = (u16)(data & VLAN_TABLE_VID); + *fid = (u8)((data & VLAN_TABLE_FID) >> VLAN_TABLE_FID_SHIFT); + *member = (u8)((data & VLAN_TABLE_MEMBERSHIP) >> + VLAN_TABLE_MEMBERSHIP_SHIFT); + return 0; + } + return -1; +} + +/** + * port_r_mib_cnt - read MIB counter + * @hw: The hardware instance. + * @port: The port index. + * @addr: The address of the counter. + * @cnt: Buffer to store the counter. + * + * This routine reads a MIB counter of the port. + * Hardware interrupts are disabled to minimize corruption of read data. + */ +static void port_r_mib_cnt(struct ksz_hw *hw, int port, u16 addr, u64 *cnt) +{ + u32 data; + u16 ctrl_addr; + uint interrupt; + int timeout; + + ctrl_addr = addr + PORT_COUNTER_NUM * port; + + interrupt = hw_block_intr(hw); + + ctrl_addr |= (((TABLE_MIB << TABLE_SEL_SHIFT) | TABLE_READ) << 8); + writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET); + HW_DELAY(hw, KS884X_IACR_OFFSET); + + for (timeout = 100; timeout > 0; timeout--) { + data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET); + + if (data & MIB_COUNTER_VALID) { + if (data & MIB_COUNTER_OVERFLOW) + *cnt += MIB_COUNTER_VALUE + 1; + *cnt += data & MIB_COUNTER_VALUE; + break; + } + } + + hw_restore_intr(hw, interrupt); +} + +/** + * port_r_mib_pkt - read dropped packet counts + * @hw: The hardware instance. + * @port: The port index. + * @cnt: Buffer to store the receive and transmit dropped packet counts. + * + * This routine reads the dropped packet counts of the port. + * Hardware interrupts are disabled to minimize corruption of read data. + */ +static void port_r_mib_pkt(struct ksz_hw *hw, int port, u32 *last, u64 *cnt) +{ + u32 cur; + u32 data; + u16 ctrl_addr; + uint interrupt; + int index; + + index = KS_MIB_PACKET_DROPPED_RX_0 + port; + do { + interrupt = hw_block_intr(hw); + + ctrl_addr = (u16) index; + ctrl_addr |= (((TABLE_MIB << TABLE_SEL_SHIFT) | TABLE_READ) + << 8); + writew(ctrl_addr, hw->io + KS884X_IACR_OFFSET); + HW_DELAY(hw, KS884X_IACR_OFFSET); + data = readl(hw->io + KS884X_ACC_DATA_0_OFFSET); + + hw_restore_intr(hw, interrupt); + + data &= MIB_PACKET_DROPPED; + cur = *last; + if (data != cur) { + *last = data; + if (data < cur) + data += MIB_PACKET_DROPPED + 1; + data -= cur; + *cnt += data; + } + ++last; + ++cnt; + index -= KS_MIB_PACKET_DROPPED_TX - + KS_MIB_PACKET_DROPPED_TX_0 + 1; + } while (index >= KS_MIB_PACKET_DROPPED_TX_0 + port); +} + +/** + * port_r_cnt - read MIB counters periodically + * @hw: The hardware instance. + * @port: The port index. + * + * This routine is used to read the counters of the port periodically to avoid + * counter overflow. The hardware should be acquired first before calling this + * routine. + * + * Return non-zero when not all counters not read. + */ +static int port_r_cnt(struct ksz_hw *hw, int port) +{ + struct ksz_port_mib *mib = &hw->port_mib[port]; + + if (mib->mib_start < PORT_COUNTER_NUM) + while (mib->cnt_ptr < PORT_COUNTER_NUM) { + port_r_mib_cnt(hw, port, mib->cnt_ptr, + &mib->counter[mib->cnt_ptr]); + ++mib->cnt_ptr; + } + if (hw->mib_cnt > PORT_COUNTER_NUM) + port_r_mib_pkt(hw, port, mib->dropped, + &mib->counter[PORT_COUNTER_NUM]); + mib->cnt_ptr = 0; + return 0; +} + +/** + * port_init_cnt - initialize MIB counter values + * @hw: The hardware instance. + * @port: The port index. + * + * This routine is used to initialize all counters to zero if the hardware + * cannot do it after reset. + */ +static void port_init_cnt(struct ksz_hw *hw, int port) +{ + struct ksz_port_mib *mib = &hw->port_mib[port]; + + mib->cnt_ptr = 0; + if (mib->mib_start < PORT_COUNTER_NUM) + do { + port_r_mib_cnt(hw, port, mib->cnt_ptr, + &mib->counter[mib->cnt_ptr]); + ++mib->cnt_ptr; + } while (mib->cnt_ptr < PORT_COUNTER_NUM); + if (hw->mib_cnt > PORT_COUNTER_NUM) + port_r_mib_pkt(hw, port, mib->dropped, + &mib->counter[PORT_COUNTER_NUM]); + memset((void *) mib->counter, 0, sizeof(u64) * TOTAL_PORT_COUNTER_NUM); + mib->cnt_ptr = 0; +} + +/* + * Port functions + */ + +/** + * port_chk - check port register bits + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the port register. + * @bits: The data bits to check. + * + * This function checks whether the specified bits of the port register are set + * or not. + * + * Return 0 if the bits are not set. + */ +static int port_chk(struct ksz_hw *hw, int port, int offset, u16 bits) +{ + u32 addr; + u16 data; + + PORT_CTRL_ADDR(port, addr); + addr += offset; + data = readw(hw->io + addr); + return (data & bits) == bits; +} + +/** + * port_cfg - set port register bits + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the port register. + * @bits: The data bits to set. + * @set: The flag indicating whether the bits are to be set or not. + * + * This routine sets or resets the specified bits of the port register. + */ +static void port_cfg(struct ksz_hw *hw, int port, int offset, u16 bits, + int set) +{ + u32 addr; + u16 data; + + PORT_CTRL_ADDR(port, addr); + addr += offset; + data = readw(hw->io + addr); + if (set) + data |= bits; + else + data &= ~bits; + writew(data, hw->io + addr); +} + +/** + * port_chk_shift - check port bit + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the register. + * @shift: Number of bits to shift. + * + * This function checks whether the specified port is set in the register or + * not. + * + * Return 0 if the port is not set. + */ +static int port_chk_shift(struct ksz_hw *hw, int port, u32 addr, int shift) +{ + u16 data; + u16 bit = 1 << port; + + data = readw(hw->io + addr); + data >>= shift; + return (data & bit) == bit; +} + +/** + * port_cfg_shift - set port bit + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the register. + * @shift: Number of bits to shift. + * @set: The flag indicating whether the port is to be set or not. + * + * This routine sets or resets the specified port in the register. + */ +static void port_cfg_shift(struct ksz_hw *hw, int port, u32 addr, int shift, + int set) +{ + u16 data; + u16 bits = 1 << port; + + data = readw(hw->io + addr); + bits <<= shift; + if (set) + data |= bits; + else + data &= ~bits; + writew(data, hw->io + addr); +} + +/** + * port_r8 - read byte from port register + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the port register. + * @data: Buffer to store the data. + * + * This routine reads a byte from the port register. + */ +static void port_r8(struct ksz_hw *hw, int port, int offset, u8 *data) +{ + u32 addr; + + PORT_CTRL_ADDR(port, addr); + addr += offset; + *data = readb(hw->io + addr); +} + +/** + * port_r16 - read word from port register. + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the port register. + * @data: Buffer to store the data. + * + * This routine reads a word from the port register. + */ +static void port_r16(struct ksz_hw *hw, int port, int offset, u16 *data) +{ + u32 addr; + + PORT_CTRL_ADDR(port, addr); + addr += offset; + *data = readw(hw->io + addr); +} + +/** + * port_w16 - write word to port register. + * @hw: The hardware instance. + * @port: The port index. + * @offset: The offset of the port register. + * @data: Data to write. + * + * This routine writes a word to the port register. + */ +static void port_w16(struct ksz_hw *hw, int port, int offset, u16 data) +{ + u32 addr; + + PORT_CTRL_ADDR(port, addr); + addr += offset; + writew(data, hw->io + addr); +} + +/** + * sw_chk - check switch register bits + * @hw: The hardware instance. + * @addr: The address of the switch register. + * @bits: The data bits to check. + * + * This function checks whether the specified bits of the switch register are + * set or not. + * + * Return 0 if the bits are not set. + */ +static int sw_chk(struct ksz_hw *hw, u32 addr, u16 bits) +{ + u16 data; + + data = readw(hw->io + addr); + return (data & bits) == bits; +} + +/** + * sw_cfg - set switch register bits + * @hw: The hardware instance. + * @addr: The address of the switch register. + * @bits: The data bits to set. + * @set: The flag indicating whether the bits are to be set or not. + * + * This function sets or resets the specified bits of the switch register. + */ +static void sw_cfg(struct ksz_hw *hw, u32 addr, u16 bits, int set) +{ + u16 data; + + data = readw(hw->io + addr); + if (set) + data |= bits; + else + data &= ~bits; + writew(data, hw->io + addr); +} + +/* Bandwidth */ + +static inline void port_cfg_broad_storm(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_BROADCAST_STORM, set); +} + +static inline int port_chk_broad_storm(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_BROADCAST_STORM); +} + +/* Driver set switch broadcast storm protection at 10% rate. */ +#define BROADCAST_STORM_PROTECTION_RATE 10 + +/* 148,800 frames * 67 ms / 100 */ +#define BROADCAST_STORM_VALUE 9969 + +/** + * sw_cfg_broad_storm - configure broadcast storm threshold + * @hw: The hardware instance. + * @percent: Broadcast storm threshold in percent of transmit rate. + * + * This routine configures the broadcast storm threshold of the switch. + */ +static void sw_cfg_broad_storm(struct ksz_hw *hw, u8 percent) +{ + u16 data; + u32 value = ((u32) BROADCAST_STORM_VALUE * (u32) percent / 100); + + if (value > BROADCAST_STORM_RATE) + value = BROADCAST_STORM_RATE; + + data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET); + data &= ~(BROADCAST_STORM_RATE_LO | BROADCAST_STORM_RATE_HI); + data |= ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8); + writew(data, hw->io + KS8842_SWITCH_CTRL_3_OFFSET); +} + +/** + * sw_get_board_storm - get broadcast storm threshold + * @hw: The hardware instance. + * @percent: Buffer to store the broadcast storm threshold percentage. + * + * This routine retrieves the broadcast storm threshold of the switch. + */ +static void sw_get_broad_storm(struct ksz_hw *hw, u8 *percent) +{ + int num; + u16 data; + + data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET); + num = (data & BROADCAST_STORM_RATE_HI); + num <<= 8; + num |= (data & BROADCAST_STORM_RATE_LO) >> 8; + num = (num * 100 + BROADCAST_STORM_VALUE / 2) / BROADCAST_STORM_VALUE; + *percent = (u8) num; +} + +/** + * sw_dis_broad_storm - disable broadstorm + * @hw: The hardware instance. + * @port: The port index. + * + * This routine disables the broadcast storm limit function of the switch. + */ +static void sw_dis_broad_storm(struct ksz_hw *hw, int port) +{ + port_cfg_broad_storm(hw, port, 0); +} + +/** + * sw_ena_broad_storm - enable broadcast storm + * @hw: The hardware instance. + * @port: The port index. + * + * This routine enables the broadcast storm limit function of the switch. + */ +static void sw_ena_broad_storm(struct ksz_hw *hw, int port) +{ + sw_cfg_broad_storm(hw, hw->ksz_switch->broad_per); + port_cfg_broad_storm(hw, port, 1); +} + +/** + * sw_init_broad_storm - initialize broadcast storm + * @hw: The hardware instance. + * + * This routine initializes the broadcast storm limit function of the switch. + */ +static void sw_init_broad_storm(struct ksz_hw *hw) +{ + int port; + + hw->ksz_switch->broad_per = 1; + sw_cfg_broad_storm(hw, hw->ksz_switch->broad_per); + for (port = 0; port < TOTAL_PORT_NUM; port++) + sw_dis_broad_storm(hw, port); + sw_cfg(hw, KS8842_SWITCH_CTRL_2_OFFSET, MULTICAST_STORM_DISABLE, 1); +} + +/** + * hw_cfg_broad_storm - configure broadcast storm + * @hw: The hardware instance. + * @percent: Broadcast storm threshold in percent of transmit rate. + * + * This routine configures the broadcast storm threshold of the switch. + * It is called by user functions. The hardware should be acquired first. + */ +static void hw_cfg_broad_storm(struct ksz_hw *hw, u8 percent) +{ + if (percent > 100) + percent = 100; + + sw_cfg_broad_storm(hw, percent); + sw_get_broad_storm(hw, &percent); + hw->ksz_switch->broad_per = percent; +} + +/** + * sw_dis_prio_rate - disable switch priority rate + * @hw: The hardware instance. + * @port: The port index. + * + * This routine disables the priority rate function of the switch. + */ +static void sw_dis_prio_rate(struct ksz_hw *hw, int port) +{ + u32 addr; + + PORT_CTRL_ADDR(port, addr); + addr += KS8842_PORT_IN_RATE_OFFSET; + writel(0, hw->io + addr); +} + +/** + * sw_init_prio_rate - initialize switch prioirty rate + * @hw: The hardware instance. + * + * This routine initializes the priority rate function of the switch. + */ +static void sw_init_prio_rate(struct ksz_hw *hw) +{ + int port; + int prio; + struct ksz_switch *sw = hw->ksz_switch; + + for (port = 0; port < TOTAL_PORT_NUM; port++) { + for (prio = 0; prio < PRIO_QUEUES; prio++) { + sw->port_cfg[port].rx_rate[prio] = + sw->port_cfg[port].tx_rate[prio] = 0; + } + sw_dis_prio_rate(hw, port); + } +} + +/* Communication */ + +static inline void port_cfg_back_pressure(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_BACK_PRESSURE, set); +} + +static inline void port_cfg_force_flow_ctrl(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_FORCE_FLOW_CTRL, set); +} + +static inline int port_chk_back_pressure(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_BACK_PRESSURE); +} + +static inline int port_chk_force_flow_ctrl(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_FORCE_FLOW_CTRL); +} + +/* Spanning Tree */ + +static inline void port_cfg_dis_learn(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_LEARN_DISABLE, set); +} + +static inline void port_cfg_rx(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_RX_ENABLE, set); +} + +static inline void port_cfg_tx(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_TX_ENABLE, set); +} + +static inline void sw_cfg_fast_aging(struct ksz_hw *hw, int set) +{ + sw_cfg(hw, KS8842_SWITCH_CTRL_1_OFFSET, SWITCH_FAST_AGING, set); +} + +static inline void sw_flush_dyn_mac_table(struct ksz_hw *hw) +{ + if (!(hw->overrides & FAST_AGING)) { + sw_cfg_fast_aging(hw, 1); + mdelay(1); + sw_cfg_fast_aging(hw, 0); + } +} + +/* VLAN */ + +static inline void port_cfg_ins_tag(struct ksz_hw *hw, int p, int insert) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_INSERT_TAG, insert); +} + +static inline void port_cfg_rmv_tag(struct ksz_hw *hw, int p, int remove) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_REMOVE_TAG, remove); +} + +static inline int port_chk_ins_tag(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_INSERT_TAG); +} + +static inline int port_chk_rmv_tag(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_REMOVE_TAG); +} + +static inline void port_cfg_dis_non_vid(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_DISCARD_NON_VID, set); +} + +static inline void port_cfg_in_filter(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_INGRESS_VLAN_FILTER, set); +} + +static inline int port_chk_dis_non_vid(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_DISCARD_NON_VID); +} + +static inline int port_chk_in_filter(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_INGRESS_VLAN_FILTER); +} + +/* Mirroring */ + +static inline void port_cfg_mirror_sniffer(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_SNIFFER, set); +} + +static inline void port_cfg_mirror_rx(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_RX, set); +} + +static inline void port_cfg_mirror_tx(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_MIRROR_TX, set); +} + +static inline void sw_cfg_mirror_rx_tx(struct ksz_hw *hw, int set) +{ + sw_cfg(hw, KS8842_SWITCH_CTRL_2_OFFSET, SWITCH_MIRROR_RX_TX, set); +} + +static void sw_init_mirror(struct ksz_hw *hw) +{ + int port; + + for (port = 0; port < TOTAL_PORT_NUM; port++) { + port_cfg_mirror_sniffer(hw, port, 0); + port_cfg_mirror_rx(hw, port, 0); + port_cfg_mirror_tx(hw, port, 0); + } + sw_cfg_mirror_rx_tx(hw, 0); +} + +static inline void sw_cfg_unk_def_deliver(struct ksz_hw *hw, int set) +{ + sw_cfg(hw, KS8842_SWITCH_CTRL_7_OFFSET, + SWITCH_UNK_DEF_PORT_ENABLE, set); +} + +static inline int sw_cfg_chk_unk_def_deliver(struct ksz_hw *hw) +{ + return sw_chk(hw, KS8842_SWITCH_CTRL_7_OFFSET, + SWITCH_UNK_DEF_PORT_ENABLE); +} + +static inline void sw_cfg_unk_def_port(struct ksz_hw *hw, int port, int set) +{ + port_cfg_shift(hw, port, KS8842_SWITCH_CTRL_7_OFFSET, 0, set); +} + +static inline int sw_chk_unk_def_port(struct ksz_hw *hw, int port) +{ + return port_chk_shift(hw, port, KS8842_SWITCH_CTRL_7_OFFSET, 0); +} + +/* Priority */ + +static inline void port_cfg_diffserv(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_DIFFSERV_ENABLE, set); +} + +static inline void port_cfg_802_1p(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_802_1P_ENABLE, set); +} + +static inline void port_cfg_replace_vid(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_USER_PRIORITY_CEILING, set); +} + +static inline void port_cfg_prio(struct ksz_hw *hw, int p, int set) +{ + port_cfg(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_PRIO_QUEUE_ENABLE, set); +} + +static inline int port_chk_diffserv(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_DIFFSERV_ENABLE); +} + +static inline int port_chk_802_1p(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_802_1P_ENABLE); +} + +static inline int port_chk_replace_vid(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_2_OFFSET, PORT_USER_PRIORITY_CEILING); +} + +static inline int port_chk_prio(struct ksz_hw *hw, int p) +{ + return port_chk(hw, p, + KS8842_PORT_CTRL_1_OFFSET, PORT_PRIO_QUEUE_ENABLE); +} + +/** + * sw_dis_diffserv - disable switch DiffServ priority + * @hw: The hardware instance. + * @port: The port index. + * + * This routine disables the DiffServ priority function of the switch. + */ +static void sw_dis_diffserv(struct ksz_hw *hw, int port) +{ + port_cfg_diffserv(hw, port, 0); +} + +/** + * sw_dis_802_1p - disable switch 802.1p priority + * @hw: The hardware instance. + * @port: The port index. + * + * This routine disables the 802.1p priority function of the switch. + */ +static void sw_dis_802_1p(struct ksz_hw *hw, int port) +{ + port_cfg_802_1p(hw, port, 0); +} + +/** + * sw_cfg_replace_null_vid - + * @hw: The hardware instance. + * @set: The flag to disable or enable. + * + */ +static void sw_cfg_replace_null_vid(struct ksz_hw *hw, int set) +{ + sw_cfg(hw, KS8842_SWITCH_CTRL_3_OFFSET, SWITCH_REPLACE_NULL_VID, set); +} + +/** + * sw_cfg_replace_vid - enable switch 802.10 priority re-mapping + * @hw: The hardware instance. + * @port: The port index. + * @set: The flag to disable or enable. + * + * This routine enables the 802.1p priority re-mapping function of the switch. + * That allows 802.1p priority field to be replaced with the port's default + * tag's priority value if the ingress packet's 802.1p priority has a higher + * priority than port's default tag's priority. + */ +static void sw_cfg_replace_vid(struct ksz_hw *hw, int port, int set) +{ + port_cfg_replace_vid(hw, port, set); +} + +/** + * sw_cfg_port_based - configure switch port based priority + * @hw: The hardware instance. + * @port: The port index. + * @prio: The priority to set. + * + * This routine configures the port based priority of the switch. + */ +static void sw_cfg_port_based(struct ksz_hw *hw, int port, u8 prio) +{ + u16 data; + + if (prio > PORT_BASED_PRIORITY_BASE) + prio = PORT_BASED_PRIORITY_BASE; + + hw->ksz_switch->port_cfg[port].port_prio = prio; + + port_r16(hw, port, KS8842_PORT_CTRL_1_OFFSET, &data); + data &= ~PORT_BASED_PRIORITY_MASK; + data |= prio << PORT_BASED_PRIORITY_SHIFT; + port_w16(hw, port, KS8842_PORT_CTRL_1_OFFSET, data); +} + +/** + * sw_dis_multi_queue - disable transmit multiple queues + * @hw: The hardware instance. + * @port: The port index. + * + * This routine disables the transmit multiple queues selection of the switch + * port. Only single transmit queue on the port. + */ +static void sw_dis_multi_queue(struct ksz_hw *hw, int port) +{ + port_cfg_prio(hw, port, 0); +} + +/** + * sw_init_prio - initialize switch priority + * @hw: The hardware instance. + * + * This routine initializes the switch QoS priority functions. + */ +static void sw_init_prio(struct ksz_hw *hw) +{ + int port; + int tos; + struct ksz_switch *sw = hw->ksz_switch; + + /* + * Init all the 802.1p tag priority value to be assigned to different + * priority queue. + */ + sw->p_802_1p[0] = 0; + sw->p_802_1p[1] = 0; + sw->p_802_1p[2] = 1; + sw->p_802_1p[3] = 1; + sw->p_802_1p[4] = 2; + sw->p_802_1p[5] = 2; + sw->p_802_1p[6] = 3; + sw->p_802_1p[7] = 3; + + /* + * Init all the DiffServ priority value to be assigned to priority + * queue 0. + */ + for (tos = 0; tos < DIFFSERV_ENTRIES; tos++) + sw->diffserv[tos] = 0; + + /* All QoS functions disabled. */ + for (port = 0; port < TOTAL_PORT_NUM; port++) { + sw_dis_multi_queue(hw, port); + sw_dis_diffserv(hw, port); + sw_dis_802_1p(hw, port); + sw_cfg_replace_vid(hw, port, 0); + + sw->port_cfg[port].port_prio = 0; + sw_cfg_port_based(hw, port, sw->port_cfg[port].port_prio); + } + sw_cfg_replace_null_vid(hw, 0); +} + +/** + * port_get_def_vid - get port default VID. + * @hw: The hardware instance. + * @port: The port index. + * @vid: Buffer to store the VID. + * + * This routine retrieves the default VID of the port. + */ +static void port_get_def_vid(struct ksz_hw *hw, int port, u16 *vid) +{ + u32 addr; + + PORT_CTRL_ADDR(port, addr); + addr += KS8842_PORT_CTRL_VID_OFFSET; + *vid = readw(hw->io + addr); +} + +/** + * sw_init_vlan - initialize switch VLAN + * @hw: The hardware instance. + * + * This routine initializes the VLAN function of the switch. + */ +static void sw_init_vlan(struct ksz_hw *hw) +{ + int port; + int entry; + struct ksz_switch *sw = hw->ksz_switch; + + /* Read 16 VLAN entries from device's VLAN table. */ + for (entry = 0; entry < VLAN_TABLE_ENTRIES; entry++) { + sw_r_vlan_table(hw, entry, + &sw->vlan_table[entry].vid, + &sw->vlan_table[entry].fid, + &sw->vlan_table[entry].member); + } + + for (port = 0; port < TOTAL_PORT_NUM; port++) { + port_get_def_vid(hw, port, &sw->port_cfg[port].vid); + sw->port_cfg[port].member = PORT_MASK; + } +} + +/** + * sw_cfg_port_base_vlan - configure port-based VLAN membership + * @hw: The hardware instance. + * @port: The port index. + * @member: The port-based VLAN membership. + * + * This routine configures the port-based VLAN membership of the port. + */ +static void sw_cfg_port_base_vlan(struct ksz_hw *hw, int port, u8 member) +{ + u32 addr; + u8 data; + + PORT_CTRL_ADDR(port, addr); + addr += KS8842_PORT_CTRL_2_OFFSET; + + data = readb(hw->io + addr); + data &= ~PORT_VLAN_MEMBERSHIP; + data |= (member & PORT_MASK); + writeb(data, hw->io + addr); + + hw->ksz_switch->port_cfg[port].member = member; +} + +/** + * sw_get_addr - get the switch MAC address. + * @hw: The hardware instance. + * @mac_addr: Buffer to store the MAC address. + * + * This function retrieves the MAC address of the switch. + */ +static inline void sw_get_addr(struct ksz_hw *hw, u8 *mac_addr) +{ + int i; + + for (i = 0; i < 6; i += 2) { + mac_addr[i] = readb(hw->io + KS8842_MAC_ADDR_0_OFFSET + i); + mac_addr[1 + i] = readb(hw->io + KS8842_MAC_ADDR_1_OFFSET + i); + } +} + +/** + * sw_set_addr - configure switch MAC address + * @hw: The hardware instance. + * @mac_addr: The MAC address. + * + * This function configures the MAC address of the switch. + */ +static void sw_set_addr(struct ksz_hw *hw, u8 *mac_addr) +{ + int i; + + for (i = 0; i < 6; i += 2) { + writeb(mac_addr[i], hw->io + KS8842_MAC_ADDR_0_OFFSET + i); + writeb(mac_addr[1 + i], hw->io + KS8842_MAC_ADDR_1_OFFSET + i); + } +} + +/** + * sw_set_global_ctrl - set switch global control + * @hw: The hardware instance. + * + * This routine sets the global control of the switch function. + */ +static void sw_set_global_ctrl(struct ksz_hw *hw) +{ + u16 data; + + /* Enable switch MII flow control. */ + data = readw(hw->io + KS8842_SWITCH_CTRL_3_OFFSET); + data |= SWITCH_FLOW_CTRL; + writew(data, hw->io + KS8842_SWITCH_CTRL_3_OFFSET); + + data = readw(hw->io + KS8842_SWITCH_CTRL_1_OFFSET); + + /* Enable aggressive back off algorithm in half duplex mode. */ + data |= SWITCH_AGGR_BACKOFF; + + /* Enable automatic fast aging when link changed detected. */ + data |= SWITCH_AGING_ENABLE; + data |= SWITCH_LINK_AUTO_AGING; + + if (hw->overrides & FAST_AGING) + data |= SWITCH_FAST_AGING; + else + data &= ~SWITCH_FAST_AGING; + writew(data, hw->io + KS8842_SWITCH_CTRL_1_OFFSET); + + data = readw(hw->io + KS8842_SWITCH_CTRL_2_OFFSET); + + /* Enable no excessive collision drop. */ + data |= NO_EXC_COLLISION_DROP; + writew(data, hw->io + KS8842_SWITCH_CTRL_2_OFFSET); +} + +enum { + STP_STATE_DISABLED = 0, + STP_STATE_LISTENING, + STP_STATE_LEARNING, + STP_STATE_FORWARDING, + STP_STATE_BLOCKED, + STP_STATE_SIMPLE +}; + +/** + * port_set_stp_state - configure port spanning tree state + * @hw: The hardware instance. + * @port: The port index. + * @state: The spanning tree state. + * + * This routine configures the spanning tree state of the port. + */ +static void port_set_stp_state(struct ksz_hw *hw, int port, int state) +{ + u16 data; + + port_r16(hw, port, KS8842_PORT_CTRL_2_OFFSET, &data); + switch (state) { + case STP_STATE_DISABLED: + data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE); + data |= PORT_LEARN_DISABLE; + break; + case STP_STATE_LISTENING: +/* + * No need to turn on transmit because of port direct mode. + * Turning on receive is required if static MAC table is not setup. + */ + data &= ~PORT_TX_ENABLE; + data |= PORT_RX_ENABLE; + data |= PORT_LEARN_DISABLE; + break; + case STP_STATE_LEARNING: + data &= ~PORT_TX_ENABLE; + data |= PORT_RX_ENABLE; + data &= ~PORT_LEARN_DISABLE; + break; + case STP_STATE_FORWARDING: + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); + data &= ~PORT_LEARN_DISABLE; + break; + case STP_STATE_BLOCKED: +/* + * Need to setup static MAC table with override to keep receiving BPDU + * messages. See sw_init_stp routine. + */ + data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE); + data |= PORT_LEARN_DISABLE; + break; + case STP_STATE_SIMPLE: + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); + data |= PORT_LEARN_DISABLE; + break; + } + port_w16(hw, port, KS8842_PORT_CTRL_2_OFFSET, data); + hw->ksz_switch->port_cfg[port].stp_state = state; +} + +#define STP_ENTRY 0 +#define BROADCAST_ENTRY 1 +#define BRIDGE_ADDR_ENTRY 2 +#define IPV6_ADDR_ENTRY 3 + +/** + * sw_clr_sta_mac_table - clear static MAC table + * @hw: The hardware instance. + * + * This routine clears the static MAC table. + */ +static void sw_clr_sta_mac_table(struct ksz_hw *hw) +{ + struct ksz_mac_table *entry; + int i; + + for (i = 0; i < STATIC_MAC_TABLE_ENTRIES; i++) { + entry = &hw->ksz_switch->mac_table[i]; + sw_w_sta_mac_table(hw, i, + entry->mac_addr, entry->ports, + entry->override, 0, + entry->use_fid, entry->fid); + } +} + +/** + * sw_init_stp - initialize switch spanning tree support + * @hw: The hardware instance. + * + * This routine initializes the spanning tree support of the switch. + */ +static void sw_init_stp(struct ksz_hw *hw) +{ + struct ksz_mac_table *entry; + + entry = &hw->ksz_switch->mac_table[STP_ENTRY]; + entry->mac_addr[0] = 0x01; + entry->mac_addr[1] = 0x80; + entry->mac_addr[2] = 0xC2; + entry->mac_addr[3] = 0x00; + entry->mac_addr[4] = 0x00; + entry->mac_addr[5] = 0x00; + entry->ports = HOST_MASK; + entry->override = 1; + entry->valid = 1; + sw_w_sta_mac_table(hw, STP_ENTRY, + entry->mac_addr, entry->ports, + entry->override, entry->valid, + entry->use_fid, entry->fid); +} + +/** + * sw_block_addr - block certain packets from the host port + * @hw: The hardware instance. + * + * This routine blocks certain packets from reaching to the host port. + */ +static void sw_block_addr(struct ksz_hw *hw) +{ + struct ksz_mac_table *entry; + int i; + + for (i = BROADCAST_ENTRY; i <= IPV6_ADDR_ENTRY; i++) { + entry = &hw->ksz_switch->mac_table[i]; + entry->valid = 0; + sw_w_sta_mac_table(hw, i, + entry->mac_addr, entry->ports, + entry->override, entry->valid, + entry->use_fid, entry->fid); + } +} + +#define PHY_LINK_SUPPORT \ + (PHY_AUTO_NEG_ASYM_PAUSE | \ + PHY_AUTO_NEG_SYM_PAUSE | \ + PHY_AUTO_NEG_100BT4 | \ + PHY_AUTO_NEG_100BTX_FD | \ + PHY_AUTO_NEG_100BTX | \ + PHY_AUTO_NEG_10BT_FD | \ + PHY_AUTO_NEG_10BT) + +static inline void hw_r_phy_ctrl(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_CTRL_OFFSET); +} + +static inline void hw_w_phy_ctrl(struct ksz_hw *hw, int phy, u16 data) +{ + writew(data, hw->io + phy + KS884X_PHY_CTRL_OFFSET); +} + +static inline void hw_r_phy_link_stat(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_STATUS_OFFSET); +} + +static inline void hw_r_phy_auto_neg(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_AUTO_NEG_OFFSET); +} + +static inline void hw_w_phy_auto_neg(struct ksz_hw *hw, int phy, u16 data) +{ + writew(data, hw->io + phy + KS884X_PHY_AUTO_NEG_OFFSET); +} + +static inline void hw_r_phy_rem_cap(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_REMOTE_CAP_OFFSET); +} + +static inline void hw_r_phy_crossover(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_CTRL_OFFSET); +} + +static inline void hw_w_phy_crossover(struct ksz_hw *hw, int phy, u16 data) +{ + writew(data, hw->io + phy + KS884X_PHY_CTRL_OFFSET); +} + +static inline void hw_r_phy_polarity(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_PHY_CTRL_OFFSET); +} + +static inline void hw_w_phy_polarity(struct ksz_hw *hw, int phy, u16 data) +{ + writew(data, hw->io + phy + KS884X_PHY_PHY_CTRL_OFFSET); +} + +static inline void hw_r_phy_link_md(struct ksz_hw *hw, int phy, u16 *data) +{ + *data = readw(hw->io + phy + KS884X_PHY_LINK_MD_OFFSET); +} + +static inline void hw_w_phy_link_md(struct ksz_hw *hw, int phy, u16 data) +{ + writew(data, hw->io + phy + KS884X_PHY_LINK_MD_OFFSET); +} + +/** + * hw_r_phy - read data from PHY register + * @hw: The hardware instance. + * @port: Port to read. + * @reg: PHY register to read. + * @val: Buffer to store the read data. + * + * This routine reads data from the PHY register. + */ +static void hw_r_phy(struct ksz_hw *hw, int port, u16 reg, u16 *val) +{ + int phy; + + phy = KS884X_PHY_1_CTRL_OFFSET + port * PHY_CTRL_INTERVAL + reg; + *val = readw(hw->io + phy); +} + +/** + * port_w_phy - write data to PHY register + * @hw: The hardware instance. + * @port: Port to write. + * @reg: PHY register to write. + * @val: Word data to write. + * + * This routine writes data to the PHY register. + */ +static void hw_w_phy(struct ksz_hw *hw, int port, u16 reg, u16 val) +{ + int phy; + + phy = KS884X_PHY_1_CTRL_OFFSET + port * PHY_CTRL_INTERVAL + reg; + writew(val, hw->io + phy); +} + +/* + * EEPROM access functions + */ + +#define AT93C_CODE 0 +#define AT93C_WR_OFF 0x00 +#define AT93C_WR_ALL 0x10 +#define AT93C_ER_ALL 0x20 +#define AT93C_WR_ON 0x30 + +#define AT93C_WRITE 1 +#define AT93C_READ 2 +#define AT93C_ERASE 3 + +#define EEPROM_DELAY 4 + +static inline void drop_gpio(struct ksz_hw *hw, u8 gpio) +{ + u16 data; + + data = readw(hw->io + KS884X_EEPROM_CTRL_OFFSET); + data &= ~gpio; + writew(data, hw->io + KS884X_EEPROM_CTRL_OFFSET); +} + +static inline void raise_gpio(struct ksz_hw *hw, u8 gpio) +{ + u16 data; + + data = readw(hw->io + KS884X_EEPROM_CTRL_OFFSET); + data |= gpio; + writew(data, hw->io + KS884X_EEPROM_CTRL_OFFSET); +} + +static inline u8 state_gpio(struct ksz_hw *hw, u8 gpio) +{ + u16 data; + + data = readw(hw->io + KS884X_EEPROM_CTRL_OFFSET); + return (u8)(data & gpio); +} + +static void eeprom_clk(struct ksz_hw *hw) +{ + raise_gpio(hw, EEPROM_SERIAL_CLOCK); + udelay(EEPROM_DELAY); + drop_gpio(hw, EEPROM_SERIAL_CLOCK); + udelay(EEPROM_DELAY); +} + +static u16 spi_r(struct ksz_hw *hw) +{ + int i; + u16 temp = 0; + + for (i = 15; i >= 0; i--) { + raise_gpio(hw, EEPROM_SERIAL_CLOCK); + udelay(EEPROM_DELAY); + + temp |= (state_gpio(hw, EEPROM_DATA_IN)) ? 1 << i : 0; + + drop_gpio(hw, EEPROM_SERIAL_CLOCK); + udelay(EEPROM_DELAY); + } + return temp; +} + +static void spi_w(struct ksz_hw *hw, u16 data) +{ + int i; + + for (i = 15; i >= 0; i--) { + (data & (0x01 << i)) ? raise_gpio(hw, EEPROM_DATA_OUT) : + drop_gpio(hw, EEPROM_DATA_OUT); + eeprom_clk(hw); + } +} + +static void spi_reg(struct ksz_hw *hw, u8 data, u8 reg) +{ + int i; + + /* Initial start bit */ + raise_gpio(hw, EEPROM_DATA_OUT); + eeprom_clk(hw); + + /* AT93C operation */ + for (i = 1; i >= 0; i--) { + (data & (0x01 << i)) ? raise_gpio(hw, EEPROM_DATA_OUT) : + drop_gpio(hw, EEPROM_DATA_OUT); + eeprom_clk(hw); + } + + /* Address location */ + for (i = 5; i >= 0; i--) { + (reg & (0x01 << i)) ? raise_gpio(hw, EEPROM_DATA_OUT) : + drop_gpio(hw, EEPROM_DATA_OUT); + eeprom_clk(hw); + } +} + +#define EEPROM_DATA_RESERVED 0 +#define EEPROM_DATA_MAC_ADDR_0 1 +#define EEPROM_DATA_MAC_ADDR_1 2 +#define EEPROM_DATA_MAC_ADDR_2 3 +#define EEPROM_DATA_SUBSYS_ID 4 +#define EEPROM_DATA_SUBSYS_VEN_ID 5 +#define EEPROM_DATA_PM_CAP 6 + +/* User defined EEPROM data */ +#define EEPROM_DATA_OTHER_MAC_ADDR 9 + +/** + * eeprom_read - read from AT93C46 EEPROM + * @hw: The hardware instance. + * @reg: The register offset. + * + * This function reads a word from the AT93C46 EEPROM. + * + * Return the data value. + */ +static u16 eeprom_read(struct ksz_hw *hw, u8 reg) +{ + u16 data; + + raise_gpio(hw, EEPROM_ACCESS_ENABLE | EEPROM_CHIP_SELECT); + + spi_reg(hw, AT93C_READ, reg); + data = spi_r(hw); + + drop_gpio(hw, EEPROM_ACCESS_ENABLE | EEPROM_CHIP_SELECT); + + return data; +} + +/** + * eeprom_write - write to AT93C46 EEPROM + * @hw: The hardware instance. + * @reg: The register offset. + * @data: The data value. + * + * This procedure writes a word to the AT93C46 EEPROM. + */ +static void eeprom_write(struct ksz_hw *hw, u8 reg, u16 data) +{ + int timeout; + + raise_gpio(hw, EEPROM_ACCESS_ENABLE | EEPROM_CHIP_SELECT); + + /* Enable write. */ + spi_reg(hw, AT93C_CODE, AT93C_WR_ON); + drop_gpio(hw, EEPROM_CHIP_SELECT); + udelay(1); + + /* Erase the register. */ + raise_gpio(hw, EEPROM_CHIP_SELECT); + spi_reg(hw, AT93C_ERASE, reg); + drop_gpio(hw, EEPROM_CHIP_SELECT); + udelay(1); + + /* Check operation complete. */ + raise_gpio(hw, EEPROM_CHIP_SELECT); + timeout = 8; + mdelay(2); + do { + mdelay(1); + } while (!state_gpio(hw, EEPROM_DATA_IN) && --timeout); + drop_gpio(hw, EEPROM_CHIP_SELECT); + udelay(1); + + /* Write the register. */ + raise_gpio(hw, EEPROM_CHIP_SELECT); + spi_reg(hw, AT93C_WRITE, reg); + spi_w(hw, data); + drop_gpio(hw, EEPROM_CHIP_SELECT); + udelay(1); + + /* Check operation complete. */ + raise_gpio(hw, EEPROM_CHIP_SELECT); + timeout = 8; + mdelay(2); + do { + mdelay(1); + } while (!state_gpio(hw, EEPROM_DATA_IN) && --timeout); + drop_gpio(hw, EEPROM_CHIP_SELECT); + udelay(1); + + /* Disable write. */ + raise_gpio(hw, EEPROM_CHIP_SELECT); + spi_reg(hw, AT93C_CODE, AT93C_WR_OFF); + + drop_gpio(hw, EEPROM_ACCESS_ENABLE | EEPROM_CHIP_SELECT); +} + +/* + * Link detection routines + */ + +static u16 advertised_flow_ctrl(struct ksz_port *port, u16 ctrl) +{ + ctrl &= ~PORT_AUTO_NEG_SYM_PAUSE; + switch (port->flow_ctrl) { + case PHY_FLOW_CTRL: + ctrl |= PORT_AUTO_NEG_SYM_PAUSE; + break; + /* Not supported. */ + case PHY_TX_ONLY: + case PHY_RX_ONLY: + default: + break; + } + return ctrl; +} + +static void set_flow_ctrl(struct ksz_hw *hw, int rx, int tx) +{ + u32 rx_cfg; + u32 tx_cfg; + + rx_cfg = hw->rx_cfg; + tx_cfg = hw->tx_cfg; + if (rx) + hw->rx_cfg |= DMA_RX_FLOW_ENABLE; + else + hw->rx_cfg &= ~DMA_RX_FLOW_ENABLE; + if (tx) + hw->tx_cfg |= DMA_TX_FLOW_ENABLE; + else + hw->tx_cfg &= ~DMA_TX_FLOW_ENABLE; + if (hw->enabled) { + if (rx_cfg != hw->rx_cfg) + writel(hw->rx_cfg, hw->io + KS_DMA_RX_CTRL); + if (tx_cfg != hw->tx_cfg) + writel(hw->tx_cfg, hw->io + KS_DMA_TX_CTRL); + } +} + +static void determine_flow_ctrl(struct ksz_hw *hw, struct ksz_port *port, + u16 local, u16 remote) +{ + int rx; + int tx; + + if (hw->overrides & PAUSE_FLOW_CTRL) + return; + + rx = tx = 0; + if (port->force_link) + rx = tx = 1; + if (remote & PHY_AUTO_NEG_SYM_PAUSE) { + if (local & PHY_AUTO_NEG_SYM_PAUSE) { + rx = tx = 1; + } else if ((remote & PHY_AUTO_NEG_ASYM_PAUSE) && + (local & PHY_AUTO_NEG_PAUSE) == + PHY_AUTO_NEG_ASYM_PAUSE) { + tx = 1; + } + } else if (remote & PHY_AUTO_NEG_ASYM_PAUSE) { + if ((local & PHY_AUTO_NEG_PAUSE) == PHY_AUTO_NEG_PAUSE) + rx = 1; + } + if (!hw->ksz_switch) + set_flow_ctrl(hw, rx, tx); +} + +static inline void port_cfg_change(struct ksz_hw *hw, struct ksz_port *port, + struct ksz_port_info *info, u16 link_status) +{ + if ((hw->features & HALF_DUPLEX_SIGNAL_BUG) && + !(hw->overrides & PAUSE_FLOW_CTRL)) { + u32 cfg = hw->tx_cfg; + + /* Disable flow control in the half duplex mode. */ + if (1 == info->duplex) + hw->tx_cfg &= ~DMA_TX_FLOW_ENABLE; + if (hw->enabled && cfg != hw->tx_cfg) + writel(hw->tx_cfg, hw->io + KS_DMA_TX_CTRL); + } +} + +/** + * port_get_link_speed - get current link status + * @port: The port instance. + * + * This routine reads PHY registers to determine the current link status of the + * switch ports. + */ +static void port_get_link_speed(struct ksz_port *port) +{ + uint interrupt; + struct ksz_port_info *info; + struct ksz_port_info *linked = NULL; + struct ksz_hw *hw = port->hw; + u16 data; + u16 status; + u8 local; + u8 remote; + int i; + int p; + int change = 0; + + interrupt = hw_block_intr(hw); + + for (i = 0, p = port->first_port; i < port->port_cnt; i++, p++) { + info = &hw->port_info[p]; + port_r16(hw, p, KS884X_PORT_CTRL_4_OFFSET, &data); + port_r16(hw, p, KS884X_PORT_STATUS_OFFSET, &status); + + /* + * Link status is changing all the time even when there is no + * cable connection! + */ + remote = status & (PORT_AUTO_NEG_COMPLETE | + PORT_STATUS_LINK_GOOD); + local = (u8) data; + + /* No change to status. */ + if (local == info->advertised && remote == info->partner) + continue; + + info->advertised = local; + info->partner = remote; + if (status & PORT_STATUS_LINK_GOOD) { + + /* Remember the first linked port. */ + if (!linked) + linked = info; + + info->tx_rate = 10 * TX_RATE_UNIT; + if (status & PORT_STATUS_SPEED_100MBIT) + info->tx_rate = 100 * TX_RATE_UNIT; + + info->duplex = 1; + if (status & PORT_STATUS_FULL_DUPLEX) + info->duplex = 2; + + if (media_connected != info->state) { + hw_r_phy(hw, p, KS884X_PHY_AUTO_NEG_OFFSET, + &data); + hw_r_phy(hw, p, KS884X_PHY_REMOTE_CAP_OFFSET, + &status); + determine_flow_ctrl(hw, port, data, status); + if (hw->ksz_switch) { + port_cfg_back_pressure(hw, p, + (1 == info->duplex)); + } + change |= 1 << i; + port_cfg_change(hw, port, info, status); + } + info->state = media_connected; + } else { + if (media_disconnected != info->state) { + change |= 1 << i; + + /* Indicate the link just goes down. */ + hw->port_mib[p].link_down = 1; + } + info->state = media_disconnected; + } + hw->port_mib[p].state = (u8) info->state; + } + + if (linked && media_disconnected == port->linked->state) + port->linked = linked; + + hw_restore_intr(hw, interrupt); +} + +#define PHY_RESET_TIMEOUT 10 + +/** + * port_set_link_speed - set port speed + * @port: The port instance. + * + * This routine sets the link speed of the switch ports. + */ +static void port_set_link_speed(struct ksz_port *port) +{ + struct ksz_port_info *info; + struct ksz_hw *hw = port->hw; + u16 data; + u16 cfg; + u8 status; + int i; + int p; + + for (i = 0, p = port->first_port; i < port->port_cnt; i++, p++) { + info = &hw->port_info[p]; + + port_r16(hw, p, KS884X_PORT_CTRL_4_OFFSET, &data); + port_r8(hw, p, KS884X_PORT_STATUS_OFFSET, &status); + + cfg = 0; + if (status & PORT_STATUS_LINK_GOOD) + cfg = data; + + data |= PORT_AUTO_NEG_ENABLE; + data = advertised_flow_ctrl(port, data); + + data |= PORT_AUTO_NEG_100BTX_FD | PORT_AUTO_NEG_100BTX | + PORT_AUTO_NEG_10BT_FD | PORT_AUTO_NEG_10BT; + + /* Check if manual configuration is specified by the user. */ + if (port->speed || port->duplex) { + if (10 == port->speed) + data &= ~(PORT_AUTO_NEG_100BTX_FD | + PORT_AUTO_NEG_100BTX); + else if (100 == port->speed) + data &= ~(PORT_AUTO_NEG_10BT_FD | + PORT_AUTO_NEG_10BT); + if (1 == port->duplex) + data &= ~(PORT_AUTO_NEG_100BTX_FD | + PORT_AUTO_NEG_10BT_FD); + else if (2 == port->duplex) + data &= ~(PORT_AUTO_NEG_100BTX | + PORT_AUTO_NEG_10BT); + } + if (data != cfg) { + data |= PORT_AUTO_NEG_RESTART; + port_w16(hw, p, KS884X_PORT_CTRL_4_OFFSET, data); + } + } +} + +/** + * port_force_link_speed - force port speed + * @port: The port instance. + * + * This routine forces the link speed of the switch ports. + */ +static void port_force_link_speed(struct ksz_port *port) +{ + struct ksz_hw *hw = port->hw; + u16 data; + int i; + int phy; + int p; + + for (i = 0, p = port->first_port; i < port->port_cnt; i++, p++) { + phy = KS884X_PHY_1_CTRL_OFFSET + p * PHY_CTRL_INTERVAL; + hw_r_phy_ctrl(hw, phy, &data); + + data &= ~PHY_AUTO_NEG_ENABLE; + + if (10 == port->speed) + data &= ~PHY_SPEED_100MBIT; + else if (100 == port->speed) + data |= PHY_SPEED_100MBIT; + if (1 == port->duplex) + data &= ~PHY_FULL_DUPLEX; + else if (2 == port->duplex) + data |= PHY_FULL_DUPLEX; + hw_w_phy_ctrl(hw, phy, data); + } +} + +static void port_set_power_saving(struct ksz_port *port, int enable) +{ + struct ksz_hw *hw = port->hw; + int i; + int p; + + for (i = 0, p = port->first_port; i < port->port_cnt; i++, p++) + port_cfg(hw, p, + KS884X_PORT_CTRL_4_OFFSET, PORT_POWER_DOWN, enable); +} + +/* + * KSZ8841 power management functions + */ + +/** + * hw_chk_wol_pme_status - check PMEN pin + * @hw: The hardware instance. + * + * This function is used to check PMEN pin is asserted. + * + * Return 1 if PMEN pin is asserted; otherwise, 0. + */ +static int hw_chk_wol_pme_status(struct ksz_hw *hw) +{ + struct dev_info *hw_priv = container_of(hw, struct dev_info, hw); + struct pci_dev *pdev = hw_priv->pdev; + u16 data; + + if (!pdev->pm_cap) + return 0; + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &data); + return (data & PCI_PM_CTRL_PME_STATUS) == PCI_PM_CTRL_PME_STATUS; +} + +/** + * hw_clr_wol_pme_status - clear PMEN pin + * @hw: The hardware instance. + * + * This routine is used to clear PME_Status to deassert PMEN pin. + */ +static void hw_clr_wol_pme_status(struct ksz_hw *hw) +{ + struct dev_info *hw_priv = container_of(hw, struct dev_info, hw); + struct pci_dev *pdev = hw_priv->pdev; + u16 data; + + if (!pdev->pm_cap) + return; + + /* Clear PME_Status to deassert PMEN pin. */ + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &data); + data |= PCI_PM_CTRL_PME_STATUS; + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, data); +} + +/** + * hw_cfg_wol_pme - enable or disable Wake-on-LAN + * @hw: The hardware instance. + * @set: The flag indicating whether to enable or disable. + * + * This routine is used to enable or disable Wake-on-LAN. + */ +static void hw_cfg_wol_pme(struct ksz_hw *hw, int set) +{ + struct dev_info *hw_priv = container_of(hw, struct dev_info, hw); + struct pci_dev *pdev = hw_priv->pdev; + u16 data; + + if (!pdev->pm_cap) + return; + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &data); + data &= ~PCI_PM_CTRL_STATE_MASK; + if (set) + data |= PCI_PM_CTRL_PME_ENABLE | PCI_D3hot; + else + data &= ~PCI_PM_CTRL_PME_ENABLE; + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, data); +} + +/** + * hw_cfg_wol - configure Wake-on-LAN features + * @hw: The hardware instance. + * @frame: The pattern frame bit. + * @set: The flag indicating whether to enable or disable. + * + * This routine is used to enable or disable certain Wake-on-LAN features. + */ +static void hw_cfg_wol(struct ksz_hw *hw, u16 frame, int set) +{ + u16 data; + + data = readw(hw->io + KS8841_WOL_CTRL_OFFSET); + if (set) + data |= frame; + else + data &= ~frame; + writew(data, hw->io + KS8841_WOL_CTRL_OFFSET); +} + +/** + * hw_set_wol_frame - program Wake-on-LAN pattern + * @hw: The hardware instance. + * @i: The frame index. + * @mask_size: The size of the mask. + * @mask: Mask to ignore certain bytes in the pattern. + * @frame_size: The size of the frame. + * @pattern: The frame data. + * + * This routine is used to program Wake-on-LAN pattern. + */ +static void hw_set_wol_frame(struct ksz_hw *hw, int i, uint mask_size, + u8 *mask, uint frame_size, u8 *pattern) +{ + int bits; + int from; + int len; + int to; + u32 crc; + u8 data[64]; + u8 val = 0; + + if (frame_size > mask_size * 8) + frame_size = mask_size * 8; + if (frame_size > 64) + frame_size = 64; + + i *= 0x10; + writel(0, hw->io + KS8841_WOL_FRAME_BYTE0_OFFSET + i); + writel(0, hw->io + KS8841_WOL_FRAME_BYTE2_OFFSET + i); + + bits = len = from = to = 0; + do { + if (bits) { + if ((val & 1)) + data[to++] = pattern[from]; + val >>= 1; + ++from; + --bits; + } else { + val = mask[len]; + writeb(val, hw->io + KS8841_WOL_FRAME_BYTE0_OFFSET + i + + len); + ++len; + if (val) + bits = 8; + else + from += 8; + } + } while (from < (int) frame_size); + if (val) { + bits = mask[len - 1]; + val <<= (from % 8); + bits &= ~val; + writeb(bits, hw->io + KS8841_WOL_FRAME_BYTE0_OFFSET + i + len - + 1); + } + crc = ether_crc(to, data); + writel(crc, hw->io + KS8841_WOL_FRAME_CRC_OFFSET + i); +} + +/** + * hw_add_wol_arp - add ARP pattern + * @hw: The hardware instance. + * @ip_addr: The IPv4 address assigned to the device. + * + * This routine is used to add ARP pattern for waking up the host. + */ +static void hw_add_wol_arp(struct ksz_hw *hw, u8 *ip_addr) +{ + u8 mask[6] = { 0x3F, 0xF0, 0x3F, 0x00, 0xC0, 0x03 }; + u8 pattern[42] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + memcpy(&pattern[38], ip_addr, 4); + hw_set_wol_frame(hw, 3, 6, mask, 42, pattern); +} + +/** + * hw_add_wol_bcast - add broadcast pattern + * @hw: The hardware instance. + * + * This routine is used to add broadcast pattern for waking up the host. + */ +static void hw_add_wol_bcast(struct ksz_hw *hw) +{ + u8 mask[] = { 0x3F }; + u8 pattern[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + hw_set_wol_frame(hw, 2, 1, mask, MAC_ADDR_LEN, pattern); +} + +/** + * hw_add_wol_mcast - add multicast pattern + * @hw: The hardware instance. + * + * This routine is used to add multicast pattern for waking up the host. + * + * It is assumed the multicast packet is the ICMPv6 neighbor solicitation used + * by IPv6 ping command. Note that multicast packets are filtred through the + * multicast hash table, so not all multicast packets can wake up the host. + */ +static void hw_add_wol_mcast(struct ksz_hw *hw) +{ + u8 mask[] = { 0x3F }; + u8 pattern[] = { 0x33, 0x33, 0xFF, 0x00, 0x00, 0x00 }; + + memcpy(&pattern[3], &hw->override_addr[3], 3); + hw_set_wol_frame(hw, 1, 1, mask, 6, pattern); +} + +/** + * hw_add_wol_ucast - add unicast pattern + * @hw: The hardware instance. + * + * This routine is used to add unicast pattern to wakeup the host. + * + * It is assumed the unicast packet is directed to the device, as the hardware + * can only receive them in normal case. + */ +static void hw_add_wol_ucast(struct ksz_hw *hw) +{ + u8 mask[] = { 0x3F }; + + hw_set_wol_frame(hw, 0, 1, mask, MAC_ADDR_LEN, hw->override_addr); +} + +/** + * hw_enable_wol - enable Wake-on-LAN + * @hw: The hardware instance. + * @wol_enable: The Wake-on-LAN settings. + * @net_addr: The IPv4 address assigned to the device. + * + * This routine is used to enable Wake-on-LAN depending on driver settings. + */ +static void hw_enable_wol(struct ksz_hw *hw, u32 wol_enable, u8 *net_addr) +{ + hw_cfg_wol(hw, KS8841_WOL_MAGIC_ENABLE, (wol_enable & WAKE_MAGIC)); + hw_cfg_wol(hw, KS8841_WOL_FRAME0_ENABLE, (wol_enable & WAKE_UCAST)); + hw_add_wol_ucast(hw); + hw_cfg_wol(hw, KS8841_WOL_FRAME1_ENABLE, (wol_enable & WAKE_MCAST)); + hw_add_wol_mcast(hw); + hw_cfg_wol(hw, KS8841_WOL_FRAME2_ENABLE, (wol_enable & WAKE_BCAST)); + hw_cfg_wol(hw, KS8841_WOL_FRAME3_ENABLE, (wol_enable & WAKE_ARP)); + hw_add_wol_arp(hw, net_addr); +} + +/** + * hw_init - check driver is correct for the hardware + * @hw: The hardware instance. + * + * This function checks the hardware is correct for this driver and sets the + * hardware up for proper initialization. + * + * Return number of ports or 0 if not right. + */ +static int hw_init(struct ksz_hw *hw) +{ + int rc = 0; + u16 data; + u16 revision; + + /* Set bus speed to 125MHz. */ + writew(BUS_SPEED_125_MHZ, hw->io + KS884X_BUS_CTRL_OFFSET); + + /* Check KSZ884x chip ID. */ + data = readw(hw->io + KS884X_CHIP_ID_OFFSET); + + revision = (data & KS884X_REVISION_MASK) >> KS884X_REVISION_SHIFT; + data &= KS884X_CHIP_ID_MASK_41; + if (REG_CHIP_ID_41 == data) + rc = 1; + else if (REG_CHIP_ID_42 == data) + rc = 2; + else + return 0; + + /* Setup hardware features or bug workarounds. */ + if (revision <= 1) { + hw->features |= SMALL_PACKET_TX_BUG; + if (1 == rc) + hw->features |= HALF_DUPLEX_SIGNAL_BUG; + } + hw->features |= IPV6_CSUM_GEN_HACK; + return rc; +} + +/** + * hw_reset - reset the hardware + * @hw: The hardware instance. + * + * This routine resets the hardware. + */ +static void hw_reset(struct ksz_hw *hw) +{ + writew(GLOBAL_SOFTWARE_RESET, hw->io + KS884X_GLOBAL_CTRL_OFFSET); + + /* Wait for device to reset. */ + mdelay(10); + + /* Write 0 to clear device reset. */ + writew(0, hw->io + KS884X_GLOBAL_CTRL_OFFSET); +} + +/** + * hw_setup - setup the hardware + * @hw: The hardware instance. + * + * This routine setup the hardware for proper operation. + */ +static void hw_setup(struct ksz_hw *hw) +{ +#if SET_DEFAULT_LED + u16 data; + + /* Change default LED mode. */ + data = readw(hw->io + KS8842_SWITCH_CTRL_5_OFFSET); + data &= ~LED_MODE; + data |= SET_DEFAULT_LED; + writew(data, hw->io + KS8842_SWITCH_CTRL_5_OFFSET); +#endif + + /* Setup transmit control. */ + hw->tx_cfg = (DMA_TX_PAD_ENABLE | DMA_TX_CRC_ENABLE | + (DMA_BURST_DEFAULT << DMA_BURST_SHIFT) | DMA_TX_ENABLE); + + /* Setup receive control. */ + hw->rx_cfg = (DMA_RX_BROADCAST | DMA_RX_UNICAST | + (DMA_BURST_DEFAULT << DMA_BURST_SHIFT) | DMA_RX_ENABLE); + hw->rx_cfg |= KS884X_DMA_RX_MULTICAST; + + /* Hardware cannot handle UDP packet in IP fragments. */ + hw->rx_cfg |= (DMA_RX_CSUM_TCP | DMA_RX_CSUM_IP); + + if (hw->all_multi) + hw->rx_cfg |= DMA_RX_ALL_MULTICAST; + if (hw->promiscuous) + hw->rx_cfg |= DMA_RX_PROMISCUOUS; +} + +/** + * hw_setup_intr - setup interrupt mask + * @hw: The hardware instance. + * + * This routine setup the interrupt mask for proper operation. + */ +static void hw_setup_intr(struct ksz_hw *hw) +{ + hw->intr_mask = KS884X_INT_MASK | KS884X_INT_RX_OVERRUN; +} + +static void ksz_check_desc_num(struct ksz_desc_info *info) +{ +#define MIN_DESC_SHIFT 2 + + int alloc = info->alloc; + int shift; + + shift = 0; + while (!(alloc & 1)) { + shift++; + alloc >>= 1; + } + if (alloc != 1 || shift < MIN_DESC_SHIFT) { + printk(KERN_ALERT "Hardware descriptor numbers not right!\n"); + while (alloc) { + shift++; + alloc >>= 1; + } + if (shift < MIN_DESC_SHIFT) + shift = MIN_DESC_SHIFT; + alloc = 1 << shift; + info->alloc = alloc; + } + info->mask = info->alloc - 1; +} + +static void hw_init_desc(struct ksz_desc_info *desc_info, int transmit) +{ + int i; + u32 phys = desc_info->ring_phys; + struct ksz_hw_desc *desc = desc_info->ring_virt; + struct ksz_desc *cur = desc_info->ring; + struct ksz_desc *previous = NULL; + + for (i = 0; i < desc_info->alloc; i++) { + cur->phw = desc++; + phys += desc_info->size; + previous = cur++; + previous->phw->next = cpu_to_le32(phys); + } + previous->phw->next = cpu_to_le32(desc_info->ring_phys); + previous->sw.buf.rx.end_of_ring = 1; + previous->phw->buf.data = cpu_to_le32(previous->sw.buf.data); + + desc_info->avail = desc_info->alloc; + desc_info->last = desc_info->next = 0; + + desc_info->cur = desc_info->ring; +} + +/** + * hw_set_desc_base - set descriptor base addresses + * @hw: The hardware instance. + * @tx_addr: The transmit descriptor base. + * @rx_addr: The receive descriptor base. + * + * This routine programs the descriptor base addresses after reset. + */ +static void hw_set_desc_base(struct ksz_hw *hw, u32 tx_addr, u32 rx_addr) +{ + /* Set base address of Tx/Rx descriptors. */ + writel(tx_addr, hw->io + KS_DMA_TX_ADDR); + writel(rx_addr, hw->io + KS_DMA_RX_ADDR); +} + +static void hw_reset_pkts(struct ksz_desc_info *info) +{ + info->cur = info->ring; + info->avail = info->alloc; + info->last = info->next = 0; +} + +static inline void hw_resume_rx(struct ksz_hw *hw) +{ + writel(DMA_START, hw->io + KS_DMA_RX_START); +} + +/** + * hw_start_rx - start receiving + * @hw: The hardware instance. + * + * This routine starts the receive function of the hardware. + */ +static void hw_start_rx(struct ksz_hw *hw) +{ + writel(hw->rx_cfg, hw->io + KS_DMA_RX_CTRL); + + /* Notify when the receive stops. */ + hw->intr_mask |= KS884X_INT_RX_STOPPED; + + writel(DMA_START, hw->io + KS_DMA_RX_START); + hw_ack_intr(hw, KS884X_INT_RX_STOPPED); + hw->rx_stop++; + + /* Variable overflows. */ + if (0 == hw->rx_stop) + hw->rx_stop = 2; +} + +/* + * hw_stop_rx - stop receiving + * @hw: The hardware instance. + * + * This routine stops the receive function of the hardware. + */ +static void hw_stop_rx(struct ksz_hw *hw) +{ + hw->rx_stop = 0; + hw_turn_off_intr(hw, KS884X_INT_RX_STOPPED); + writel((hw->rx_cfg & ~DMA_RX_ENABLE), hw->io + KS_DMA_RX_CTRL); +} + +/** + * hw_start_tx - start transmitting + * @hw: The hardware instance. + * + * This routine starts the transmit function of the hardware. + */ +static void hw_start_tx(struct ksz_hw *hw) +{ + writel(hw->tx_cfg, hw->io + KS_DMA_TX_CTRL); +} + +/** + * hw_stop_tx - stop transmitting + * @hw: The hardware instance. + * + * This routine stops the transmit function of the hardware. + */ +static void hw_stop_tx(struct ksz_hw *hw) +{ + writel((hw->tx_cfg & ~DMA_TX_ENABLE), hw->io + KS_DMA_TX_CTRL); +} + +/** + * hw_disable - disable hardware + * @hw: The hardware instance. + * + * This routine disables the hardware. + */ +static void hw_disable(struct ksz_hw *hw) +{ + hw_stop_rx(hw); + hw_stop_tx(hw); + hw->enabled = 0; +} + +/** + * hw_enable - enable hardware + * @hw: The hardware instance. + * + * This routine enables the hardware. + */ +static void hw_enable(struct ksz_hw *hw) +{ + hw_start_tx(hw); + hw_start_rx(hw); + hw->enabled = 1; +} + +/** + * hw_alloc_pkt - allocate enough descriptors for transmission + * @hw: The hardware instance. + * @length: The length of the packet. + * @physical: Number of descriptors required. + * + * This function allocates descriptors for transmission. + * + * Return 0 if not successful; 1 for buffer copy; or number of descriptors. + */ +static int hw_alloc_pkt(struct ksz_hw *hw, int length, int physical) +{ + /* Always leave one descriptor free. */ + if (hw->tx_desc_info.avail <= 1) + return 0; + + /* Allocate a descriptor for transmission and mark it current. */ + get_tx_pkt(&hw->tx_desc_info, &hw->tx_desc_info.cur); + hw->tx_desc_info.cur->sw.buf.tx.first_seg = 1; + + /* Keep track of number of transmit descriptors used so far. */ + ++hw->tx_int_cnt; + hw->tx_size += length; + + /* Cannot hold on too much data. */ + if (hw->tx_size >= MAX_TX_HELD_SIZE) + hw->tx_int_cnt = hw->tx_int_mask + 1; + + if (physical > hw->tx_desc_info.avail) + return 1; + + return hw->tx_desc_info.avail; +} + +/** + * hw_send_pkt - mark packet for transmission + * @hw: The hardware instance. + * + * This routine marks the packet for transmission in PCI version. + */ +static void hw_send_pkt(struct ksz_hw *hw) +{ + struct ksz_desc *cur = hw->tx_desc_info.cur; + + cur->sw.buf.tx.last_seg = 1; + + /* Interrupt only after specified number of descriptors used. */ + if (hw->tx_int_cnt > hw->tx_int_mask) { + cur->sw.buf.tx.intr = 1; + hw->tx_int_cnt = 0; + hw->tx_size = 0; + } + + /* KSZ8842 supports port directed transmission. */ + cur->sw.buf.tx.dest_port = hw->dst_ports; + + release_desc(cur); + + writel(0, hw->io + KS_DMA_TX_START); +} + +static int empty_addr(u8 *addr) +{ + u32 *addr1 = (u32 *) addr; + u16 *addr2 = (u16 *) &addr[4]; + + return 0 == *addr1 && 0 == *addr2; +} + +/** + * hw_set_addr - set MAC address + * @hw: The hardware instance. + * + * This routine programs the MAC address of the hardware when the address is + * overrided. + */ +static void hw_set_addr(struct ksz_hw *hw) +{ + int i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + writeb(hw->override_addr[MAC_ADDR_ORDER(i)], + hw->io + KS884X_ADDR_0_OFFSET + i); + + sw_set_addr(hw, hw->override_addr); +} + +/** + * hw_read_addr - read MAC address + * @hw: The hardware instance. + * + * This routine retrieves the MAC address of the hardware. + */ +static void hw_read_addr(struct ksz_hw *hw) +{ + int i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + hw->perm_addr[MAC_ADDR_ORDER(i)] = readb(hw->io + + KS884X_ADDR_0_OFFSET + i); + + if (!hw->mac_override) { + memcpy(hw->override_addr, hw->perm_addr, MAC_ADDR_LEN); + if (empty_addr(hw->override_addr)) { + memcpy(hw->perm_addr, DEFAULT_MAC_ADDRESS, + MAC_ADDR_LEN); + memcpy(hw->override_addr, DEFAULT_MAC_ADDRESS, + MAC_ADDR_LEN); + hw->override_addr[5] += hw->id; + hw_set_addr(hw); + } + } +} + +static void hw_ena_add_addr(struct ksz_hw *hw, int index, u8 *mac_addr) +{ + int i; + u32 mac_addr_lo; + u32 mac_addr_hi; + + mac_addr_hi = 0; + for (i = 0; i < 2; i++) { + mac_addr_hi <<= 8; + mac_addr_hi |= mac_addr[i]; + } + mac_addr_hi |= ADD_ADDR_ENABLE; + mac_addr_lo = 0; + for (i = 2; i < 6; i++) { + mac_addr_lo <<= 8; + mac_addr_lo |= mac_addr[i]; + } + index *= ADD_ADDR_INCR; + + writel(mac_addr_lo, hw->io + index + KS_ADD_ADDR_0_LO); + writel(mac_addr_hi, hw->io + index + KS_ADD_ADDR_0_HI); +} + +static void hw_set_add_addr(struct ksz_hw *hw) +{ + int i; + + for (i = 0; i < ADDITIONAL_ENTRIES; i++) { + if (empty_addr(hw->address[i])) + writel(0, hw->io + ADD_ADDR_INCR * i + + KS_ADD_ADDR_0_HI); + else + hw_ena_add_addr(hw, i, hw->address[i]); + } +} + +static int hw_add_addr(struct ksz_hw *hw, u8 *mac_addr) +{ + int i; + int j = ADDITIONAL_ENTRIES; + + if (!memcmp(hw->override_addr, mac_addr, MAC_ADDR_LEN)) + return 0; + for (i = 0; i < hw->addr_list_size; i++) { + if (!memcmp(hw->address[i], mac_addr, MAC_ADDR_LEN)) + return 0; + if (ADDITIONAL_ENTRIES == j && empty_addr(hw->address[i])) + j = i; + } + if (j < ADDITIONAL_ENTRIES) { + memcpy(hw->address[j], mac_addr, MAC_ADDR_LEN); + hw_ena_add_addr(hw, j, hw->address[j]); + return 0; + } + return -1; +} + +static int hw_del_addr(struct ksz_hw *hw, u8 *mac_addr) +{ + int i; + + for (i = 0; i < hw->addr_list_size; i++) { + if (!memcmp(hw->address[i], mac_addr, MAC_ADDR_LEN)) { + memset(hw->address[i], 0, MAC_ADDR_LEN); + writel(0, hw->io + ADD_ADDR_INCR * i + + KS_ADD_ADDR_0_HI); + return 0; + } + } + return -1; +} + +/** + * hw_clr_multicast - clear multicast addresses + * @hw: The hardware instance. + * + * This routine removes all multicast addresses set in the hardware. + */ +static void hw_clr_multicast(struct ksz_hw *hw) +{ + int i; + + for (i = 0; i < HW_MULTICAST_SIZE; i++) { + hw->multi_bits[i] = 0; + + writeb(0, hw->io + KS884X_MULTICAST_0_OFFSET + i); + } +} + +/** + * hw_set_grp_addr - set multicast addresses + * @hw: The hardware instance. + * + * This routine programs multicast addresses for the hardware to accept those + * addresses. + */ +static void hw_set_grp_addr(struct ksz_hw *hw) +{ + int i; + int index; + int position; + int value; + + memset(hw->multi_bits, 0, sizeof(u8) * HW_MULTICAST_SIZE); + + for (i = 0; i < hw->multi_list_size; i++) { + position = (ether_crc(6, hw->multi_list[i]) >> 26) & 0x3f; + index = position >> 3; + value = 1 << (position & 7); + hw->multi_bits[index] |= (u8) value; + } + + for (i = 0; i < HW_MULTICAST_SIZE; i++) + writeb(hw->multi_bits[i], hw->io + KS884X_MULTICAST_0_OFFSET + + i); +} + +/** + * hw_set_multicast - enable or disable all multicast receiving + * @hw: The hardware instance. + * @multicast: To turn on or off the all multicast feature. + * + * This routine enables/disables the hardware to accept all multicast packets. + */ +static void hw_set_multicast(struct ksz_hw *hw, u8 multicast) +{ + /* Stop receiving for reconfiguration. */ + hw_stop_rx(hw); + + if (multicast) + hw->rx_cfg |= DMA_RX_ALL_MULTICAST; + else + hw->rx_cfg &= ~DMA_RX_ALL_MULTICAST; + + if (hw->enabled) + hw_start_rx(hw); +} + +/** + * hw_set_promiscuous - enable or disable promiscuous receiving + * @hw: The hardware instance. + * @prom: To turn on or off the promiscuous feature. + * + * This routine enables/disables the hardware to accept all packets. + */ +static void hw_set_promiscuous(struct ksz_hw *hw, u8 prom) +{ + /* Stop receiving for reconfiguration. */ + hw_stop_rx(hw); + + if (prom) + hw->rx_cfg |= DMA_RX_PROMISCUOUS; + else + hw->rx_cfg &= ~DMA_RX_PROMISCUOUS; + + if (hw->enabled) + hw_start_rx(hw); +} + +/** + * sw_enable - enable the switch + * @hw: The hardware instance. + * @enable: The flag to enable or disable the switch + * + * This routine is used to enable/disable the switch in KSZ8842. + */ +static void sw_enable(struct ksz_hw *hw, int enable) +{ + int port; + + for (port = 0; port < SWITCH_PORT_NUM; port++) { + if (hw->dev_count > 1) { + /* Set port-base vlan membership with host port. */ + sw_cfg_port_base_vlan(hw, port, + HOST_MASK | (1 << port)); + port_set_stp_state(hw, port, STP_STATE_DISABLED); + } else { + sw_cfg_port_base_vlan(hw, port, PORT_MASK); + port_set_stp_state(hw, port, STP_STATE_FORWARDING); + } + } + if (hw->dev_count > 1) + port_set_stp_state(hw, SWITCH_PORT_NUM, STP_STATE_SIMPLE); + else + port_set_stp_state(hw, SWITCH_PORT_NUM, STP_STATE_FORWARDING); + + if (enable) + enable = KS8842_START; + writew(enable, hw->io + KS884X_CHIP_ID_OFFSET); +} + +/** + * sw_setup - setup the switch + * @hw: The hardware instance. + * + * This routine setup the hardware switch engine for default operation. + */ +static void sw_setup(struct ksz_hw *hw) +{ + int port; + + sw_set_global_ctrl(hw); + + /* Enable switch broadcast storm protection at 10% percent rate. */ + sw_init_broad_storm(hw); + hw_cfg_broad_storm(hw, BROADCAST_STORM_PROTECTION_RATE); + for (port = 0; port < SWITCH_PORT_NUM; port++) + sw_ena_broad_storm(hw, port); + + sw_init_prio(hw); + + sw_init_mirror(hw); + + sw_init_prio_rate(hw); + + sw_init_vlan(hw); + + if (hw->features & STP_SUPPORT) + sw_init_stp(hw); + if (!sw_chk(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_TX_FLOW_CTRL | SWITCH_RX_FLOW_CTRL)) + hw->overrides |= PAUSE_FLOW_CTRL; + sw_enable(hw, 1); +} + +/** + * ksz_start_timer - start kernel timer + * @info: Kernel timer information. + * @time: The time tick. + * + * This routine starts the kernel timer after the specified time tick. + */ +static void ksz_start_timer(struct ksz_timer_info *info, int time) +{ + info->cnt = 0; + info->timer.expires = jiffies + time; + add_timer(&info->timer); + + /* infinity */ + info->max = -1; +} + +/** + * ksz_stop_timer - stop kernel timer + * @info: Kernel timer information. + * + * This routine stops the kernel timer. + */ +static void ksz_stop_timer(struct ksz_timer_info *info) +{ + if (info->max) { + info->max = 0; + del_timer_sync(&info->timer); + } +} + +static void ksz_init_timer(struct ksz_timer_info *info, int period, + void (*function)(unsigned long), void *data) +{ + info->max = 0; + info->period = period; + init_timer(&info->timer); + info->timer.function = function; + info->timer.data = (unsigned long) data; +} + +static void ksz_update_timer(struct ksz_timer_info *info) +{ + ++info->cnt; + if (info->max > 0) { + if (info->cnt < info->max) { + info->timer.expires = jiffies + info->period; + add_timer(&info->timer); + } else + info->max = 0; + } else if (info->max < 0) { + info->timer.expires = jiffies + info->period; + add_timer(&info->timer); + } +} + +/** + * ksz_alloc_soft_desc - allocate software descriptors + * @desc_info: Descriptor information structure. + * @transmit: Indication that descriptors are for transmit. + * + * This local function allocates software descriptors for manipulation in + * memory. + * + * Return 0 if successful. + */ +static int ksz_alloc_soft_desc(struct ksz_desc_info *desc_info, int transmit) +{ + desc_info->ring = kmalloc(sizeof(struct ksz_desc) * desc_info->alloc, + GFP_KERNEL); + if (!desc_info->ring) + return 1; + memset((void *) desc_info->ring, 0, + sizeof(struct ksz_desc) * desc_info->alloc); + hw_init_desc(desc_info, transmit); + return 0; +} + +/** + * ksz_alloc_desc - allocate hardware descriptors + * @adapter: Adapter information structure. + * + * This local function allocates hardware descriptors for receiving and + * transmitting. + * + * Return 0 if successful. + */ +static int ksz_alloc_desc(struct dev_info *adapter) +{ + struct ksz_hw *hw = &adapter->hw; + int offset; + + /* Allocate memory for RX & TX descriptors. */ + adapter->desc_pool.alloc_size = + hw->rx_desc_info.size * hw->rx_desc_info.alloc + + hw->tx_desc_info.size * hw->tx_desc_info.alloc + + DESC_ALIGNMENT; + + adapter->desc_pool.alloc_virt = + pci_alloc_consistent( + adapter->pdev, adapter->desc_pool.alloc_size, + &adapter->desc_pool.dma_addr); + if (adapter->desc_pool.alloc_virt == NULL) { + adapter->desc_pool.alloc_size = 0; + return 1; + } + memset(adapter->desc_pool.alloc_virt, 0, adapter->desc_pool.alloc_size); + + /* Align to the next cache line boundary. */ + offset = (((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT) ? + (DESC_ALIGNMENT - + ((ulong) adapter->desc_pool.alloc_virt % DESC_ALIGNMENT)) : 0); + adapter->desc_pool.virt = adapter->desc_pool.alloc_virt + offset; + adapter->desc_pool.phys = adapter->desc_pool.dma_addr + offset; + + /* Allocate receive/transmit descriptors. */ + hw->rx_desc_info.ring_virt = (struct ksz_hw_desc *) + adapter->desc_pool.virt; + hw->rx_desc_info.ring_phys = adapter->desc_pool.phys; + offset = hw->rx_desc_info.alloc * hw->rx_desc_info.size; + hw->tx_desc_info.ring_virt = (struct ksz_hw_desc *) + (adapter->desc_pool.virt + offset); + hw->tx_desc_info.ring_phys = adapter->desc_pool.phys + offset; + + if (ksz_alloc_soft_desc(&hw->rx_desc_info, 0)) + return 1; + if (ksz_alloc_soft_desc(&hw->tx_desc_info, 1)) + return 1; + + return 0; +} + +/** + * free_dma_buf - release DMA buffer resources + * @adapter: Adapter information structure. + * + * This routine is just a helper function to release the DMA buffer resources. + */ +static void free_dma_buf(struct dev_info *adapter, struct ksz_dma_buf *dma_buf, + int direction) +{ + pci_unmap_single(adapter->pdev, dma_buf->dma, dma_buf->len, direction); + dev_kfree_skb(dma_buf->skb); + dma_buf->skb = NULL; + dma_buf->dma = 0; +} + +/** + * ksz_init_rx_buffers - initialize receive descriptors + * @adapter: Adapter information structure. + * + * This routine initializes DMA buffers for receiving. + */ +static void ksz_init_rx_buffers(struct dev_info *adapter) +{ + int i; + struct ksz_desc *desc; + struct ksz_dma_buf *dma_buf; + struct ksz_hw *hw = &adapter->hw; + struct ksz_desc_info *info = &hw->rx_desc_info; + + for (i = 0; i < hw->rx_desc_info.alloc; i++) { + get_rx_pkt(info, &desc); + + dma_buf = DMA_BUFFER(desc); + if (dma_buf->skb && dma_buf->len != adapter->mtu) + free_dma_buf(adapter, dma_buf, PCI_DMA_FROMDEVICE); + dma_buf->len = adapter->mtu; + if (!dma_buf->skb) + dma_buf->skb = alloc_skb(dma_buf->len, GFP_ATOMIC); + if (dma_buf->skb && !dma_buf->dma) { + dma_buf->skb->dev = adapter->dev; + dma_buf->dma = pci_map_single( + adapter->pdev, + skb_tail_pointer(dma_buf->skb), + dma_buf->len, + PCI_DMA_FROMDEVICE); + } + + /* Set descriptor. */ + set_rx_buf(desc, dma_buf->dma); + set_rx_len(desc, dma_buf->len); + release_desc(desc); + } +} + +/** + * ksz_alloc_mem - allocate memory for hardware descriptors + * @adapter: Adapter information structure. + * + * This function allocates memory for use by hardware descriptors for receiving + * and transmitting. + * + * Return 0 if successful. + */ +static int ksz_alloc_mem(struct dev_info *adapter) +{ + struct ksz_hw *hw = &adapter->hw; + + /* Determine the number of receive and transmit descriptors. */ + hw->rx_desc_info.alloc = NUM_OF_RX_DESC; + hw->tx_desc_info.alloc = NUM_OF_TX_DESC; + + /* Determine how many descriptors to skip transmit interrupt. */ + hw->tx_int_cnt = 0; + hw->tx_int_mask = NUM_OF_TX_DESC / 4; + if (hw->tx_int_mask > 8) + hw->tx_int_mask = 8; + while (hw->tx_int_mask) { + hw->tx_int_cnt++; + hw->tx_int_mask >>= 1; + } + if (hw->tx_int_cnt) { + hw->tx_int_mask = (1 << (hw->tx_int_cnt - 1)) - 1; + hw->tx_int_cnt = 0; + } + + /* Determine the descriptor size. */ + hw->rx_desc_info.size = + (((sizeof(struct ksz_hw_desc) + DESC_ALIGNMENT - 1) / + DESC_ALIGNMENT) * DESC_ALIGNMENT); + hw->tx_desc_info.size = + (((sizeof(struct ksz_hw_desc) + DESC_ALIGNMENT - 1) / + DESC_ALIGNMENT) * DESC_ALIGNMENT); + if (hw->rx_desc_info.size != sizeof(struct ksz_hw_desc)) + printk(KERN_ALERT + "Hardware descriptor size not right!\n"); + ksz_check_desc_num(&hw->rx_desc_info); + ksz_check_desc_num(&hw->tx_desc_info); + + /* Allocate descriptors. */ + if (ksz_alloc_desc(adapter)) + return 1; + + return 0; +} + +/** + * ksz_free_desc - free software and hardware descriptors + * @adapter: Adapter information structure. + * + * This local routine frees the software and hardware descriptors allocated by + * ksz_alloc_desc(). + */ +static void ksz_free_desc(struct dev_info *adapter) +{ + struct ksz_hw *hw = &adapter->hw; + + /* Reset descriptor. */ + hw->rx_desc_info.ring_virt = NULL; + hw->tx_desc_info.ring_virt = NULL; + hw->rx_desc_info.ring_phys = 0; + hw->tx_desc_info.ring_phys = 0; + + /* Free memory. */ + if (adapter->desc_pool.alloc_virt) + pci_free_consistent( + adapter->pdev, + adapter->desc_pool.alloc_size, + adapter->desc_pool.alloc_virt, + adapter->desc_pool.dma_addr); + + /* Reset resource pool. */ + adapter->desc_pool.alloc_size = 0; + adapter->desc_pool.alloc_virt = NULL; + + kfree(hw->rx_desc_info.ring); + hw->rx_desc_info.ring = NULL; + kfree(hw->tx_desc_info.ring); + hw->tx_desc_info.ring = NULL; +} + +/** + * ksz_free_buffers - free buffers used in the descriptors + * @adapter: Adapter information structure. + * @desc_info: Descriptor information structure. + * + * This local routine frees buffers used in the DMA buffers. + */ +static void ksz_free_buffers(struct dev_info *adapter, + struct ksz_desc_info *desc_info, int direction) +{ + int i; + struct ksz_dma_buf *dma_buf; + struct ksz_desc *desc = desc_info->ring; + + for (i = 0; i < desc_info->alloc; i++) { + dma_buf = DMA_BUFFER(desc); + if (dma_buf->skb) + free_dma_buf(adapter, dma_buf, direction); + desc++; + } +} + +/** + * ksz_free_mem - free all resources used by descriptors + * @adapter: Adapter information structure. + * + * This local routine frees all the resources allocated by ksz_alloc_mem(). + */ +static void ksz_free_mem(struct dev_info *adapter) +{ + /* Free transmit buffers. */ + ksz_free_buffers(adapter, &adapter->hw.tx_desc_info, + PCI_DMA_TODEVICE); + + /* Free receive buffers. */ + ksz_free_buffers(adapter, &adapter->hw.rx_desc_info, + PCI_DMA_FROMDEVICE); + + /* Free descriptors. */ + ksz_free_desc(adapter); +} + +static void get_mib_counters(struct ksz_hw *hw, int first, int cnt, + u64 *counter) +{ + int i; + int mib; + int port; + struct ksz_port_mib *port_mib; + + memset(counter, 0, sizeof(u64) * TOTAL_PORT_COUNTER_NUM); + for (i = 0, port = first; i < cnt; i++, port++) { + port_mib = &hw->port_mib[port]; + for (mib = port_mib->mib_start; mib < hw->mib_cnt; mib++) + counter[mib] += port_mib->counter[mib]; + } +} + +/** + * send_packet - send packet + * @skb: Socket buffer. + * @dev: Network device. + * + * This routine is used to send a packet out to the network. + */ +static void send_packet(struct sk_buff *skb, struct net_device *dev) +{ + struct ksz_desc *desc; + struct ksz_desc *first; + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_desc_info *info = &hw->tx_desc_info; + struct ksz_dma_buf *dma_buf; + int len; + int last_frag = skb_shinfo(skb)->nr_frags; + + /* + * KSZ8842 with multiple device interfaces needs to be told which port + * to send. + */ + if (hw->dev_count > 1) + hw->dst_ports = 1 << priv->port.first_port; + + /* Hardware will pad the length to 60. */ + len = skb->len; + + /* Remember the very first descriptor. */ + first = info->cur; + desc = first; + + dma_buf = DMA_BUFFER(desc); + if (last_frag) { + int frag; + skb_frag_t *this_frag; + + dma_buf->len = skb->len - skb->data_len; + + dma_buf->dma = pci_map_single( + hw_priv->pdev, skb->data, dma_buf->len, + PCI_DMA_TODEVICE); + set_tx_buf(desc, dma_buf->dma); + set_tx_len(desc, dma_buf->len); + + frag = 0; + do { + this_frag = &skb_shinfo(skb)->frags[frag]; + + /* Get a new descriptor. */ + get_tx_pkt(info, &desc); + + /* Keep track of descriptors used so far. */ + ++hw->tx_int_cnt; + + dma_buf = DMA_BUFFER(desc); + dma_buf->len = this_frag->size; + + dma_buf->dma = pci_map_single( + hw_priv->pdev, + page_address(this_frag->page) + + this_frag->page_offset, + dma_buf->len, + PCI_DMA_TODEVICE); + set_tx_buf(desc, dma_buf->dma); + set_tx_len(desc, dma_buf->len); + + frag++; + if (frag == last_frag) + break; + + /* Do not release the last descriptor here. */ + release_desc(desc); + } while (1); + + /* current points to the last descriptor. */ + info->cur = desc; + + /* Release the first descriptor. */ + release_desc(first); + } else { + dma_buf->len = len; + + dma_buf->dma = pci_map_single( + hw_priv->pdev, skb->data, dma_buf->len, + PCI_DMA_TODEVICE); + set_tx_buf(desc, dma_buf->dma); + set_tx_len(desc, dma_buf->len); + } + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + (desc)->sw.buf.tx.csum_gen_tcp = 1; + (desc)->sw.buf.tx.csum_gen_udp = 1; + } + + /* + * The last descriptor holds the packet so that it can be returned to + * network subsystem after all descriptors are transmitted. + */ + dma_buf->skb = skb; + + hw_send_pkt(hw); + + /* Update transmit statistics. */ + priv->stats.tx_packets++; + priv->stats.tx_bytes += len; +} + +/** + * transmit_cleanup - clean up transmit descriptors + * @dev: Network device. + * + * This routine is called to clean up the transmitted buffers. + */ +static void transmit_cleanup(struct dev_info *hw_priv, int normal) +{ + int last; + union desc_stat status; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_desc_info *info = &hw->tx_desc_info; + struct ksz_desc *desc; + struct ksz_dma_buf *dma_buf; + struct net_device *dev = NULL; + + spin_lock(&hw_priv->hwlock); + last = info->last; + + while (info->avail < info->alloc) { + /* Get next descriptor which is not hardware owned. */ + desc = &info->ring[last]; + status.data = le32_to_cpu(desc->phw->ctrl.data); + if (status.tx.hw_owned) { + if (normal) + break; + else + reset_desc(desc, status); + } + + dma_buf = DMA_BUFFER(desc); + pci_unmap_single( + hw_priv->pdev, dma_buf->dma, dma_buf->len, + PCI_DMA_TODEVICE); + + /* This descriptor contains the last buffer in the packet. */ + if (dma_buf->skb) { + dev = dma_buf->skb->dev; + + /* Release the packet back to network subsystem. */ + dev_kfree_skb_irq(dma_buf->skb); + dma_buf->skb = NULL; + } + + /* Free the transmitted descriptor. */ + last++; + last &= info->mask; + info->avail++; + } + info->last = last; + spin_unlock(&hw_priv->hwlock); + + /* Notify the network subsystem that the packet has been sent. */ + if (dev) + dev->trans_start = jiffies; +} + +/** + * transmit_done - transmit done processing + * @dev: Network device. + * + * This routine is called when the transmit interrupt is triggered, indicating + * either a packet is sent successfully or there are transmit errors. + */ +static void tx_done(struct dev_info *hw_priv) +{ + struct ksz_hw *hw = &hw_priv->hw; + int port; + + transmit_cleanup(hw_priv, 1); + + for (port = 0; port < hw->dev_count; port++) { + struct net_device *dev = hw->port_info[port].pdev; + + if (netif_running(dev) && netif_queue_stopped(dev)) + netif_wake_queue(dev); + } +} + +static inline void copy_old_skb(struct sk_buff *old, struct sk_buff *skb) +{ + skb->dev = old->dev; + skb->protocol = old->protocol; + skb->ip_summed = old->ip_summed; + skb->csum = old->csum; + skb_set_network_header(skb, ETH_HLEN); + + dev_kfree_skb(old); +} + +/** + * netdev_tx - send out packet + * @skb: Socket buffer. + * @dev: Network device. + * + * This function is used by the upper network layer to send out a packet. + * + * Return 0 if successful; otherwise an error code indicating failure. + */ +static int netdev_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + int left; + int num = 1; + int rc = 0; + + if (hw->features & SMALL_PACKET_TX_BUG) { + struct sk_buff *org_skb = skb; + + if (skb->len <= 48) { + if (skb_end_pointer(skb) - skb->data >= 50) { + memset(&skb->data[skb->len], 0, 50 - skb->len); + skb->len = 50; + } else { + skb = dev_alloc_skb(50); + if (!skb) + return NETDEV_TX_BUSY; + memcpy(skb->data, org_skb->data, org_skb->len); + memset(&skb->data[org_skb->len], 0, + 50 - org_skb->len); + skb->len = 50; + copy_old_skb(org_skb, skb); + } + } + } + + spin_lock_irq(&hw_priv->hwlock); + + num = skb_shinfo(skb)->nr_frags + 1; + left = hw_alloc_pkt(hw, skb->len, num); + if (left) { + if (left < num || + ((hw->features & IPV6_CSUM_GEN_HACK) && + (CHECKSUM_PARTIAL == skb->ip_summed) && + (ETH_P_IPV6 == htons(skb->protocol)))) { + struct sk_buff *org_skb = skb; + + skb = dev_alloc_skb(org_skb->len); + if (!skb) + return NETDEV_TX_BUSY; + skb_copy_and_csum_dev(org_skb, skb->data); + org_skb->ip_summed = 0; + skb->len = org_skb->len; + copy_old_skb(org_skb, skb); + } + send_packet(skb, dev); + if (left <= num) + netif_stop_queue(dev); + } else { + /* Stop the transmit queue until packet is allocated. */ + netif_stop_queue(dev); + rc = NETDEV_TX_BUSY; + } + + spin_unlock_irq(&hw_priv->hwlock); + + return rc; +} + +/** + * netdev_tx_timeout - transmit timeout processing + * @dev: Network device. + * + * This routine is called when the transmit timer expires. That indicates the + * hardware is not running correctly because transmit interrupts are not + * triggered to free up resources so that the transmit routine can continue + * sending out packets. The hardware is reset to correct the problem. + */ +static void netdev_tx_timeout(struct net_device *dev) +{ + static unsigned long last_reset; + + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + int port; + + if (hw->dev_count > 1) { + /* + * Only reset the hardware if time between calls is long + * enough. + */ + if (jiffies - last_reset <= dev->watchdog_timeo) + hw_priv = NULL; + } + + last_reset = jiffies; + if (hw_priv) { + hw_dis_intr(hw); + hw_disable(hw); + + transmit_cleanup(hw_priv, 0); + hw_reset_pkts(&hw->rx_desc_info); + hw_reset_pkts(&hw->tx_desc_info); + ksz_init_rx_buffers(hw_priv); + + hw_reset(hw); + + hw_set_desc_base(hw, + hw->tx_desc_info.ring_phys, + hw->rx_desc_info.ring_phys); + hw_set_addr(hw); + if (hw->all_multi) + hw_set_multicast(hw, hw->all_multi); + else if (hw->multi_list_size) + hw_set_grp_addr(hw); + + if (hw->dev_count > 1) { + hw_set_add_addr(hw); + for (port = 0; port < SWITCH_PORT_NUM; port++) { + struct net_device *port_dev; + + port_set_stp_state(hw, port, + STP_STATE_DISABLED); + + port_dev = hw->port_info[port].pdev; + if (netif_running(port_dev)) + port_set_stp_state(hw, port, + STP_STATE_SIMPLE); + } + } + + hw_enable(hw); + hw_ena_intr(hw); + } + + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +static inline void csum_verified(struct sk_buff *skb) +{ + unsigned short protocol; + struct iphdr *iph; + + protocol = skb->protocol; + skb_reset_network_header(skb); + iph = (struct iphdr *) skb_network_header(skb); + if (protocol == htons(ETH_P_8021Q)) { + protocol = iph->tot_len; + skb_set_network_header(skb, VLAN_HLEN); + iph = (struct iphdr *) skb_network_header(skb); + } + if (protocol == htons(ETH_P_IP)) { + if (iph->protocol == IPPROTO_TCP) + skb->ip_summed = CHECKSUM_UNNECESSARY; + } +} + +static inline int rx_proc(struct net_device *dev, struct ksz_hw* hw, + struct ksz_desc *desc, union desc_stat status) +{ + int packet_len; + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_dma_buf *dma_buf; + struct sk_buff *skb; + int rx_status; + + /* Received length includes 4-byte CRC. */ + packet_len = status.rx.frame_len - 4; + + dma_buf = DMA_BUFFER(desc); + pci_dma_sync_single_for_cpu( + hw_priv->pdev, dma_buf->dma, packet_len + 4, + PCI_DMA_FROMDEVICE); + + do { + /* skb->data != skb->head */ + skb = dev_alloc_skb(packet_len + 2); + if (!skb) { + priv->stats.rx_dropped++; + return -ENOMEM; + } + + /* + * Align socket buffer in 4-byte boundary for better + * performance. + */ + skb_reserve(skb, 2); + + memcpy(skb_put(skb, packet_len), + dma_buf->skb->data, packet_len); + } while (0); + + skb->dev = dev; + + skb->protocol = eth_type_trans(skb, dev); + + if (hw->rx_cfg & (DMA_RX_CSUM_UDP | DMA_RX_CSUM_TCP)) + csum_verified(skb); + + /* Update receive statistics. */ + priv->stats.rx_packets++; + priv->stats.rx_bytes += packet_len; + + /* Notify upper layer for received packet. */ + dev->last_rx = jiffies; + + rx_status = netif_rx(skb); + + return 0; +} + +static int dev_rcv_packets(struct dev_info *hw_priv) +{ + int next; + union desc_stat status; + struct ksz_hw *hw = &hw_priv->hw; + struct net_device *dev = hw->port_info[0].pdev; + struct ksz_desc_info *info = &hw->rx_desc_info; + int left = info->alloc; + struct ksz_desc *desc; + int received = 0; + + next = info->next; + while (left--) { + /* Get next descriptor which is not hardware owned. */ + desc = &info->ring[next]; + status.data = le32_to_cpu(desc->phw->ctrl.data); + if (status.rx.hw_owned) + break; + + /* Status valid only when last descriptor bit is set. */ + if (status.rx.last_desc && status.rx.first_desc) { + if (rx_proc(dev, hw, desc, status)) + goto release_packet; + received++; + } + +release_packet: + release_desc(desc); + next++; + next &= info->mask; + } + info->next = next; + + return received; +} + +static int port_rcv_packets(struct dev_info *hw_priv) +{ + int next; + union desc_stat status; + struct ksz_hw *hw = &hw_priv->hw; + struct net_device *dev = hw->port_info[0].pdev; + struct ksz_desc_info *info = &hw->rx_desc_info; + int left = info->alloc; + struct ksz_desc *desc; + int received = 0; + + next = info->next; + while (left--) { + /* Get next descriptor which is not hardware owned. */ + desc = &info->ring[next]; + status.data = le32_to_cpu(desc->phw->ctrl.data); + if (status.rx.hw_owned) + break; + + if (hw->dev_count > 1) { + /* Get received port number. */ + int p = HW_TO_DEV_PORT(status.rx.src_port); + + dev = hw->port_info[p].pdev; + if (!netif_running(dev)) + goto release_packet; + } + + /* Status valid only when last descriptor bit is set. */ + if (status.rx.last_desc && status.rx.first_desc) { + if (rx_proc(dev, hw, desc, status)) + goto release_packet; + received++; + } + +release_packet: + release_desc(desc); + next++; + next &= info->mask; + } + info->next = next; + + return received; +} + +static int dev_rcv_special(struct dev_info *hw_priv) +{ + int next; + union desc_stat status; + struct ksz_hw *hw = &hw_priv->hw; + struct net_device *dev = hw->port_info[0].pdev; + struct ksz_desc_info *info = &hw->rx_desc_info; + int left = info->alloc; + struct ksz_desc *desc; + int received = 0; + + next = info->next; + while (left--) { + /* Get next descriptor which is not hardware owned. */ + desc = &info->ring[next]; + status.data = le32_to_cpu(desc->phw->ctrl.data); + if (status.rx.hw_owned) + break; + + if (hw->dev_count > 1) { + /* Get received port number. */ + int p = HW_TO_DEV_PORT(status.rx.src_port); + + dev = hw->port_info[p].pdev; + if (!netif_running(dev)) + goto release_packet; + } + + /* Status valid only when last descriptor bit is set. */ + if (status.rx.last_desc && status.rx.first_desc) { + /* + * Receive without error. With receive errors + * disabled, packets with receive errors will be + * dropped, so no need to check the error bit. + */ + if (!status.rx.error || (status.data & + KS_DESC_RX_ERROR_COND) == + KS_DESC_RX_ERROR_TOO_LONG) { + if (rx_proc(dev, hw, desc, status)) + goto release_packet; + received++; + } else { + struct dev_priv *priv = netdev_priv(dev); + + /* Update receive error statistics. */ + priv->port.counter[OID_COUNTER_RCV_ERROR]++; + } + } + +release_packet: + release_desc(desc); + next++; + next &= info->mask; + } + info->next = next; + + return received; +} + +static void rx_proc_task(unsigned long data) +{ + struct dev_info *hw_priv = (struct dev_info *) data; + struct ksz_hw *hw = &hw_priv->hw; + + if (!hw->enabled) + return; + if (unlikely(!hw_priv->dev_rcv(hw_priv))) { + + /* In case receive process is suspended because of overrun. */ + hw_resume_rx(hw); + + /* tasklets are interruptible. */ + spin_lock_irq(&hw_priv->hwlock); + hw_turn_on_intr(hw, KS884X_INT_RX_MASK); + spin_unlock_irq(&hw_priv->hwlock); + } else { + hw_ack_intr(hw, KS884X_INT_RX); + tasklet_schedule(&hw_priv->rx_tasklet); + } +} + +static void tx_proc_task(unsigned long data) +{ + struct dev_info *hw_priv = (struct dev_info *) data; + struct ksz_hw *hw = &hw_priv->hw; + + hw_ack_intr(hw, KS884X_INT_TX_MASK); + + tx_done(hw_priv); + + /* tasklets are interruptible. */ + spin_lock_irq(&hw_priv->hwlock); + hw_turn_on_intr(hw, KS884X_INT_TX); + spin_unlock_irq(&hw_priv->hwlock); +} + +static inline void handle_rx_stop(struct ksz_hw *hw) +{ + /* Receive just has been stopped. */ + if (0 == hw->rx_stop) + hw->intr_mask &= ~KS884X_INT_RX_STOPPED; + else if (hw->rx_stop > 1) { + if (hw->enabled && (hw->rx_cfg & DMA_RX_ENABLE)) { + hw_start_rx(hw); + } else { + hw->intr_mask &= ~KS884X_INT_RX_STOPPED; + hw->rx_stop = 0; + } + } else + /* Receive just has been started. */ + hw->rx_stop++; +} + +/** + * netdev_intr - interrupt handling + * @irq: Interrupt number. + * @dev_id: Network device. + * + * This function is called by upper network layer to signal interrupt. + * + * Return IRQ_HANDLED if interrupt is handled. + */ +static irqreturn_t netdev_intr(int irq, void *dev_id) +{ + uint int_enable = 0; + struct net_device *dev = (struct net_device *) dev_id; + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + hw_read_intr(hw, &int_enable); + + /* Not our interrupt! */ + if (!int_enable) + return IRQ_NONE; + + do { + hw_ack_intr(hw, int_enable); + int_enable &= hw->intr_mask; + + if (unlikely(int_enable & KS884X_INT_TX_MASK)) { + hw_dis_intr_bit(hw, KS884X_INT_TX_MASK); + tasklet_schedule(&hw_priv->tx_tasklet); + } + + if (likely(int_enable & KS884X_INT_RX)) { + hw_dis_intr_bit(hw, KS884X_INT_RX); + tasklet_schedule(&hw_priv->rx_tasklet); + } + + if (unlikely(int_enable & KS884X_INT_RX_OVERRUN)) { + priv->stats.rx_fifo_errors++; + hw_resume_rx(hw); + } + + if (unlikely(int_enable & KS884X_INT_PHY)) { + struct ksz_port *port = &priv->port; + + hw->features |= LINK_INT_WORKING; + port_get_link_speed(port); + } + + if (unlikely(int_enable & KS884X_INT_RX_STOPPED)) { + handle_rx_stop(hw); + break; + } + + if (unlikely(int_enable & KS884X_INT_TX_STOPPED)) { + u32 data; + + hw->intr_mask &= ~KS884X_INT_TX_STOPPED; + printk(KERN_INFO "Tx stopped\n"); + data = readl(hw->io + KS_DMA_TX_CTRL); + if (!(data & DMA_TX_ENABLE)) + printk(KERN_INFO "Tx disabled\n"); + break; + } + } while (0); + + hw_ena_intr(hw); + + return IRQ_HANDLED; +} + +/* + * Linux network device functions + */ + +static unsigned long next_jiffies; + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void netdev_netpoll(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + + hw_dis_intr(&hw_priv->hw); + netdev_intr(dev->irq, dev); +} +#endif + +static void bridge_change(struct ksz_hw *hw) +{ + int port; + u8 member; + struct ksz_switch *sw = hw->ksz_switch; + + /* No ports in forwarding state. */ + if (!sw->member) { + port_set_stp_state(hw, SWITCH_PORT_NUM, STP_STATE_SIMPLE); + sw_block_addr(hw); + } + for (port = 0; port < SWITCH_PORT_NUM; port++) { + if (STP_STATE_FORWARDING == sw->port_cfg[port].stp_state) + member = HOST_MASK | sw->member; + else + member = HOST_MASK | (1 << port); + if (member != sw->port_cfg[port].member) + sw_cfg_port_base_vlan(hw, port, member); + } +} + +/** + * netdev_close - close network device + * @dev: Network device. + * + * This function process the close operation of network device. This is caused + * by the user command "ifconfig ethX down." + * + * Return 0 if successful; otherwise an error code indicating failure. + */ +static int netdev_close(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_port *port = &priv->port; + struct ksz_hw *hw = &hw_priv->hw; + int pi; + + netif_stop_queue(dev); + + ksz_stop_timer(&priv->monitor_timer_info); + + /* Need to shut the port manually in multiple device interfaces mode. */ + if (hw->dev_count > 1) { + port_set_stp_state(hw, port->first_port, STP_STATE_DISABLED); + + /* Port is closed. Need to change bridge setting. */ + if (hw->features & STP_SUPPORT) { + pi = 1 << port->first_port; + if (hw->ksz_switch->member & pi) { + hw->ksz_switch->member &= ~pi; + bridge_change(hw); + } + } + } + if (port->first_port > 0) + hw_del_addr(hw, dev->dev_addr); + if (!hw_priv->wol_enable) + port_set_power_saving(port, true); + + if (priv->multicast) + --hw->all_multi; + if (priv->promiscuous) + --hw->promiscuous; + + hw_priv->opened--; + if (!(hw_priv->opened)) { + ksz_stop_timer(&hw_priv->mib_timer_info); + flush_work(&hw_priv->mib_read); + + hw_dis_intr(hw); + hw_disable(hw); + hw_clr_multicast(hw); + + /* Delay for receive task to stop scheduling itself. */ + msleep(2000 / HZ); + + tasklet_disable(&hw_priv->rx_tasklet); + tasklet_disable(&hw_priv->tx_tasklet); + free_irq(dev->irq, hw_priv->dev); + + transmit_cleanup(hw_priv, 0); + hw_reset_pkts(&hw->rx_desc_info); + hw_reset_pkts(&hw->tx_desc_info); + + /* Clean out static MAC table when the switch is shutdown. */ + if (hw->features & STP_SUPPORT) + sw_clr_sta_mac_table(hw); + } + + return 0; +} + +static void hw_cfg_huge_frame(struct dev_info *hw_priv, struct ksz_hw *hw) +{ + if (hw->ksz_switch) { + u32 data; + + data = readw(hw->io + KS8842_SWITCH_CTRL_2_OFFSET); + if (hw->features & RX_HUGE_FRAME) + data |= SWITCH_HUGE_PACKET; + else + data &= ~SWITCH_HUGE_PACKET; + writew(data, hw->io + KS8842_SWITCH_CTRL_2_OFFSET); + } + if (hw->features & RX_HUGE_FRAME) { + hw->rx_cfg |= DMA_RX_ERROR; + hw_priv->dev_rcv = dev_rcv_special; + } else { + hw->rx_cfg &= ~DMA_RX_ERROR; + if (hw->dev_count > 1) + hw_priv->dev_rcv = port_rcv_packets; + else + hw_priv->dev_rcv = dev_rcv_packets; + } +} + +static int prepare_hardware(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + int rc = 0; + + /* Remember the network device that requests interrupts. */ + hw_priv->dev = dev; + rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); + if (rc) + return rc; + tasklet_enable(&hw_priv->rx_tasklet); + tasklet_enable(&hw_priv->tx_tasklet); + + hw->promiscuous = 0; + hw->all_multi = 0; + hw->multi_list_size = 0; + + hw_reset(hw); + + hw_set_desc_base(hw, + hw->tx_desc_info.ring_phys, hw->rx_desc_info.ring_phys); + hw_set_addr(hw); + hw_cfg_huge_frame(hw_priv, hw); + ksz_init_rx_buffers(hw_priv); + return 0; +} + +/** + * netdev_open - open network device + * @dev: Network device. + * + * This function process the open operation of network device. This is caused + * by the user command "ifconfig ethX up." + * + * Return 0 if successful; otherwise an error code indicating failure. + */ +static int netdev_open(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port *port = &priv->port; + int i; + int p; + int rc = 0; + + priv->multicast = 0; + priv->promiscuous = 0; + + /* Reset device statistics. */ + memset(&priv->stats, 0, sizeof(struct net_device_stats)); + memset((void *) port->counter, 0, + (sizeof(u64) * OID_COUNTER_LAST)); + + if (!(hw_priv->opened)) { + rc = prepare_hardware(dev); + if (rc) + return rc; + for (i = 0; i < hw->mib_port_cnt; i++) { + if (next_jiffies < jiffies) + next_jiffies = jiffies + HZ * 2; + else + next_jiffies += HZ * 1; + hw_priv->counter[i].time = next_jiffies; + hw->port_mib[i].state = media_disconnected; + port_init_cnt(hw, i); + } + if (hw->ksz_switch) + hw->port_mib[HOST_PORT].state = media_connected; + else { + hw_add_wol_bcast(hw); + hw_cfg_wol_pme(hw, 0); + hw_clr_wol_pme_status(&hw_priv->hw); + } + } + port_set_power_saving(port, false); + + for (i = 0, p = port->first_port; i < port->port_cnt; i++, p++) { + /* + * Initialize to invalid value so that link detection + * is done. + */ + hw->port_info[p].partner = 0xFF; + hw->port_info[p].state = media_disconnected; + } + + /* Need to open the port in multiple device interfaces mode. */ + if (hw->dev_count > 1) { + port_set_stp_state(hw, port->first_port, STP_STATE_SIMPLE); + if (port->first_port > 0) + hw_add_addr(hw, dev->dev_addr); + } + + port_get_link_speed(port); + if (port->force_link) + port_force_link_speed(port); + else + port_set_link_speed(port); + + if (!(hw_priv->opened)) { + hw_setup_intr(hw); + hw_enable(hw); + hw_ena_intr(hw); + + if (hw->mib_port_cnt) + ksz_start_timer(&hw_priv->mib_timer_info, + hw_priv->mib_timer_info.period); + } + + hw_priv->opened++; + + ksz_start_timer(&priv->monitor_timer_info, + priv->monitor_timer_info.period); + + priv->media_state = port->linked->state; + + if (media_connected == priv->media_state) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s link %s\n", dev->name, + (media_connected == priv->media_state ? + "on" : "off")); + + netif_start_queue(dev); + + return 0; +} + +/* RX errors = rx_errors */ +/* RX dropped = rx_dropped */ +/* RX overruns = rx_fifo_errors */ +/* RX frame = rx_crc_errors + rx_frame_errors + rx_length_errors */ +/* TX errors = tx_errors */ +/* TX dropped = tx_dropped */ +/* TX overruns = tx_fifo_errors */ +/* TX carrier = tx_aborted_errors + tx_carrier_errors + tx_window_errors */ +/* collisions = collisions */ + +/** + * netdev_query_statistics - query network device statistics + * @dev: Network device. + * + * This function returns the statistics of the network device. The device + * needs not be opened. + * + * Return network device statistics. + */ +static struct net_device_stats *netdev_query_statistics(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct ksz_port *port = &priv->port; + struct ksz_hw *hw = &priv->adapter->hw; + struct ksz_port_mib *mib; + int i; + int p; + + priv->stats.rx_errors = port->counter[OID_COUNTER_RCV_ERROR]; + priv->stats.tx_errors = port->counter[OID_COUNTER_XMIT_ERROR]; + + /* Reset to zero to add count later. */ + priv->stats.multicast = 0; + priv->stats.collisions = 0; + priv->stats.rx_length_errors = 0; + priv->stats.rx_crc_errors = 0; + priv->stats.rx_frame_errors = 0; + priv->stats.tx_window_errors = 0; + + for (i = 0, p = port->first_port; i < port->mib_port_cnt; i++, p++) { + mib = &hw->port_mib[p]; + + priv->stats.multicast += (unsigned long) + mib->counter[MIB_COUNTER_RX_MULTICAST]; + + priv->stats.collisions += (unsigned long) + mib->counter[MIB_COUNTER_TX_TOTAL_COLLISION]; + + priv->stats.rx_length_errors += (unsigned long)( + mib->counter[MIB_COUNTER_RX_UNDERSIZE] + + mib->counter[MIB_COUNTER_RX_FRAGMENT] + + mib->counter[MIB_COUNTER_RX_OVERSIZE] + + mib->counter[MIB_COUNTER_RX_JABBER]); + priv->stats.rx_crc_errors += (unsigned long) + mib->counter[MIB_COUNTER_RX_CRC_ERR]; + priv->stats.rx_frame_errors += (unsigned long)( + mib->counter[MIB_COUNTER_RX_ALIGNMENT_ERR] + + mib->counter[MIB_COUNTER_RX_SYMBOL_ERR]); + + priv->stats.tx_window_errors += (unsigned long) + mib->counter[MIB_COUNTER_TX_LATE_COLLISION]; + } + + return &priv->stats; +} + +/** + * netdev_set_mac_address - set network device MAC address + * @dev: Network device. + * @addr: Buffer of MAC address. + * + * This function is used to set the MAC address of the network device. + * + * Return 0 to indicate success. + */ +static int netdev_set_mac_address(struct net_device *dev, void *addr) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct sockaddr *mac = addr; + uint interrupt; + + if (priv->port.first_port > 0) + hw_del_addr(hw, dev->dev_addr); + else { + hw->mac_override = 1; + memcpy(hw->override_addr, mac->sa_data, MAC_ADDR_LEN); + } + + memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN); + + interrupt = hw_block_intr(hw); + + if (priv->port.first_port > 0) + hw_add_addr(hw, dev->dev_addr); + else + hw_set_addr(hw); + hw_restore_intr(hw, interrupt); + + return 0; +} + +static void dev_set_promiscuous(struct net_device *dev, struct dev_priv *priv, + struct ksz_hw *hw, int promiscuous) +{ + if (promiscuous != priv->promiscuous) { + u8 prev_state = hw->promiscuous; + + if (promiscuous) + ++hw->promiscuous; + else + --hw->promiscuous; + priv->promiscuous = promiscuous; + + /* Turn on/off promiscuous mode. */ + if (hw->promiscuous <= 1 && prev_state <= 1) + hw_set_promiscuous(hw, hw->promiscuous); + + /* + * Port is not in promiscuous mode, meaning it is released + * from the bridge. + */ + if ((hw->features & STP_SUPPORT) && !promiscuous && + dev->br_port) { + struct ksz_switch *sw = hw->ksz_switch; + int port = priv->port.first_port; + + port_set_stp_state(hw, port, STP_STATE_DISABLED); + port = 1 << port; + if (sw->member & port) { + sw->member &= ~port; + bridge_change(hw); + } + } + } +} + +static void dev_set_multicast(struct dev_priv *priv, struct ksz_hw *hw, + int multicast) +{ + if (multicast != priv->multicast) { + u8 all_multi = hw->all_multi; + + if (multicast) + ++hw->all_multi; + else + --hw->all_multi; + priv->multicast = multicast; + + /* Turn on/off all multicast mode. */ + if (hw->all_multi <= 1 && all_multi <= 1) + hw_set_multicast(hw, hw->all_multi); + } +} + +/** + * netdev_set_rx_mode + * @dev: Network device. + * + * This routine is used to set multicast addresses or put the network device + * into promiscuous mode. + */ +static void netdev_set_rx_mode(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct dev_mc_list *mc_ptr; + int multicast = (dev->flags & IFF_ALLMULTI); + + dev_set_promiscuous(dev, priv, hw, (dev->flags & IFF_PROMISC)); + + if (hw_priv->hw.dev_count > 1) + multicast |= (dev->flags & IFF_MULTICAST); + dev_set_multicast(priv, hw, multicast); + + /* Cannot use different hashes in multiple device interfaces mode. */ + if (hw_priv->hw.dev_count > 1) + return; + + if ((dev->flags & IFF_MULTICAST) && dev->mc_count) { + int i = 0; + + /* List too big to support so turn on all multicast mode. */ + if (dev->mc_count > MAX_MULTICAST_LIST) { + if (MAX_MULTICAST_LIST != hw->multi_list_size) { + hw->multi_list_size = MAX_MULTICAST_LIST; + ++hw->all_multi; + hw_set_multicast(hw, hw->all_multi); + } + return; + } + + for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + if (!(*mc_ptr->dmi_addr & 1)) + continue; + if (i >= MAX_MULTICAST_LIST) + break; + memcpy(hw->multi_list[i++], mc_ptr->dmi_addr, + MAC_ADDR_LEN); + } + hw->multi_list_size = (u8) i; + hw_set_grp_addr(hw); + } else { + if (MAX_MULTICAST_LIST == hw->multi_list_size) { + --hw->all_multi; + hw_set_multicast(hw, hw->all_multi); + } + hw->multi_list_size = 0; + hw_clr_multicast(hw); + } +} + +static int netdev_change_mtu(struct net_device *dev, int new_mtu) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + int hw_mtu; + + if (netif_running(dev)) + return -EBUSY; + + /* Cannot use different MTU in multiple device interfaces mode. */ + if (hw->dev_count > 1) + if (dev != hw_priv->dev) + return 0; + if (new_mtu < 60) + return -EINVAL; + + if (dev->mtu != new_mtu) { + hw_mtu = new_mtu + ETHERNET_HEADER_SIZE + 4; + if (hw_mtu > MAX_RX_BUF_SIZE) + return -EINVAL; + if (hw_mtu > REGULAR_RX_BUF_SIZE) { + hw->features |= RX_HUGE_FRAME; + hw_mtu = MAX_RX_BUF_SIZE; + } else { + hw->features &= ~RX_HUGE_FRAME; + hw_mtu = REGULAR_RX_BUF_SIZE; + } + hw_mtu = (hw_mtu + 3) & ~3; + hw_priv->mtu = hw_mtu; + dev->mtu = new_mtu; + } + return 0; +} + +/** + * netdev_ioctl - I/O control processing + * @dev: Network device. + * @ifr: Interface request structure. + * @cmd: I/O control code. + * + * This function is used to process I/O control calls. + * + * Return 0 to indicate success. + */ +static int netdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port *port = &priv->port; + int rc; + int result = 0; + struct mii_ioctl_data *data = if_mii(ifr); + + if (down_interruptible(&priv->proc_sem)) + return -ERESTARTSYS; + + /* assume success */ + rc = 0; + switch (cmd) { + /* Get address of MII PHY in use. */ + case SIOCGMIIPHY: + data->phy_id = priv->id; + + /* Fallthrough... */ + + /* Read MII PHY register. */ + case SIOCGMIIREG: + if (data->phy_id != priv->id || data->reg_num >= 6) + result = -EIO; + else + hw_r_phy(hw, port->linked->port_id, data->reg_num, + &data->val_out); + break; + + /* Write MII PHY register. */ + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + result = -EPERM; + else if (data->phy_id != priv->id || data->reg_num >= 6) + result = -EIO; + else + hw_w_phy(hw, port->linked->port_id, data->reg_num, + data->val_in); + break; + + default: + result = -EOPNOTSUPP; + } + + up(&priv->proc_sem); + + return result; +} + +/* + * MII support + */ + +/** + * mdio_read - read PHY register + * @dev: Network device. + * @phy_id: The PHY id. + * @reg_num: The register number. + * + * This function returns the PHY register value. + * + * Return the register value. + */ +static int mdio_read(struct net_device *dev, int phy_id, int reg_num) +{ + struct dev_priv *priv = netdev_priv(dev); + struct ksz_port *port = &priv->port; + struct ksz_hw *hw = port->hw; + u16 val_out; + + hw_r_phy(hw, port->linked->port_id, reg_num << 1, &val_out); + return val_out; +} + +/** + * mdio_write - set PHY register + * @dev: Network device. + * @phy_id: The PHY id. + * @reg_num: The register number. + * @val: The register value. + * + * This procedure sets the PHY register value. + */ +static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) +{ + struct dev_priv *priv = netdev_priv(dev); + struct ksz_port *port = &priv->port; + struct ksz_hw *hw = port->hw; + int i; + int pi; + + for (i = 0, pi = port->first_port; i < port->port_cnt; i++, pi++) + hw_w_phy(hw, pi, reg_num << 1, val); +} + +/* + * ethtool support + */ + +#define EEPROM_SIZE 0x40 + +static u16 eeprom_data[EEPROM_SIZE] = { 0 }; + +#define ADVERTISED_ALL \ + (ADVERTISED_10baseT_Half | \ + ADVERTISED_10baseT_Full | \ + ADVERTISED_100baseT_Half | \ + ADVERTISED_100baseT_Full) + +/* These functions use the MII functions in mii.c. */ + +/** + * netdev_get_settings - get network device settings + * @dev: Network device. + * @cmd: Ethtool command. + * + * This function queries the PHY and returns its state in the ethtool command. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + + mutex_lock(&hw_priv->lock); + mii_ethtool_gset(&priv->mii_if, cmd); + cmd->advertising |= SUPPORTED_TP; + mutex_unlock(&hw_priv->lock); + + /* Save advertised settings for workaround in next function. */ + priv->advertising = cmd->advertising; + return 0; +} + +/** + * netdev_set_settings - set network device settings + * @dev: Network device. + * @cmd: Ethtool command. + * + * This function sets the PHY according to the ethtool command. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_port *port = &priv->port; + int rc; + + /* + * ethtool utility does not change advertised setting if auto + * negotiation is not specified explicitly. + */ + if (cmd->autoneg && priv->advertising == cmd->advertising) { + cmd->advertising |= ADVERTISED_ALL; + if (10 == cmd->speed) + cmd->advertising &= + ~(ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half); + else if (100 == cmd->speed) + cmd->advertising &= + ~(ADVERTISED_10baseT_Full | + ADVERTISED_10baseT_Half); + if (0 == cmd->duplex) + cmd->advertising &= + ~(ADVERTISED_100baseT_Full | + ADVERTISED_10baseT_Full); + else if (1 == cmd->duplex) + cmd->advertising &= + ~(ADVERTISED_100baseT_Half | + ADVERTISED_10baseT_Half); + } + mutex_lock(&hw_priv->lock); + if (cmd->autoneg && + (cmd->advertising & ADVERTISED_ALL) == + ADVERTISED_ALL) { + port->duplex = 0; + port->speed = 0; + port->force_link = 0; + } else { + port->duplex = cmd->duplex + 1; + if (cmd->speed != 1000) + port->speed = cmd->speed; + if (cmd->autoneg) + port->force_link = 0; + else + port->force_link = 1; + } + rc = mii_ethtool_sset(&priv->mii_if, cmd); + mutex_unlock(&hw_priv->lock); + return rc; +} + +/** + * netdev_nway_reset - restart auto-negotiation + * @dev: Network device. + * + * This function restarts the PHY for auto-negotiation. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_nway_reset(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + int rc; + + mutex_lock(&hw_priv->lock); + rc = mii_nway_restart(&priv->mii_if); + mutex_unlock(&hw_priv->lock); + return rc; +} + +/** + * netdev_get_link - get network device link status + * @dev: Network device. + * + * This function gets the link status from the PHY. + * + * Return true if PHY is linked and false otherwise. + */ +static u32 netdev_get_link(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + int rc; + + rc = mii_link_ok(&priv->mii_if); + return rc; +} + +/** + * netdev_get_drvinfo - get network driver information + * @dev: Network device. + * @info: Ethtool driver info data structure. + * + * This procedure returns the driver information. + */ +static void netdev_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(hw_priv->pdev)); +} + +/** + * netdev_get_regs_len - get length of register dump + * @dev: Network device. + * + * This function returns the length of the register dump. + * + * Return length of the register dump. + */ +static struct hw_regs { + int start; + int end; +} hw_regs_range[] = { + { KS_DMA_TX_CTRL, KS884X_INTERRUPTS_STATUS }, + { KS_ADD_ADDR_0_LO, KS_ADD_ADDR_F_HI }, + { KS884X_ADDR_0_OFFSET, KS8841_WOL_FRAME_BYTE2_OFFSET }, + { KS884X_SIDER_P, KS8842_SGCR7_P }, + { KS8842_MACAR1_P, KS8842_TOSR8_P }, + { KS884X_P1MBCR_P, KS8842_P3ERCR_P }, + { 0, 0 } +}; + +static int netdev_get_regs_len(struct net_device *dev) +{ + struct hw_regs *range = hw_regs_range; + int regs_len = 0x10 * sizeof(u32); + + while (range->end > range->start) { + regs_len += (range->end - range->start + 3) / 4 * 4; + range++; + } + return regs_len; +} + +/** + * netdev_get_regs - get register dump + * @dev: Network device. + * @regs: Ethtool registers data structure. + * @ptr: Buffer to store the register values. + * + * This procedure dumps the register values in the provided buffer. + */ +static void netdev_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *ptr) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + int *buf = (int *) ptr; + struct hw_regs *range = hw_regs_range; + int len; + + mutex_lock(&hw_priv->lock); + regs->version = 0; + for (len = 0; len < 0x40; len += 4) { + pci_read_config_dword(hw_priv->pdev, len, buf); + buf++; + } + while (range->end > range->start) { + for (len = range->start; len < range->end; len += 4) { + *buf = readl(hw->io + len); + buf++; + } + range++; + } + mutex_unlock(&hw_priv->lock); +} + +#define WOL_SUPPORT \ + (WAKE_PHY | WAKE_MAGIC | \ + WAKE_UCAST | WAKE_MCAST | \ + WAKE_BCAST | WAKE_ARP) + +/** + * netdev_get_wol - get Wake-on-LAN support + * @dev: Network device. + * @wol: Ethtool Wake-on-LAN data structure. + * + * This procedure returns Wake-on-LAN support. + */ +static void netdev_get_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + + wol->supported = hw_priv->wol_support; + wol->wolopts = hw_priv->wol_enable; + memset(&wol->sopass, 0, sizeof(wol->sopass)); +} + +/** + * netdev_set_wol - set Wake-on-LAN support + * @dev: Network device. + * @wol: Ethtool Wake-on-LAN data structure. + * + * This function sets Wake-on-LAN support. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_set_wol(struct net_device *dev, + struct ethtool_wolinfo *wol) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + + /* Need to find a way to retrieve the device IP address. */ + u8 net_addr[] = { 192, 168, 1, 1 }; + + if (wol->wolopts & ~hw_priv->wol_support) + return -EINVAL; + + hw_priv->wol_enable = wol->wolopts; + + /* Link wakeup cannot really be disabled. */ + if (wol->wolopts) + hw_priv->wol_enable |= WAKE_PHY; + hw_enable_wol(&hw_priv->hw, hw_priv->wol_enable, net_addr); + return 0; +} + +/** + * netdev_get_msglevel - get debug message level + * @dev: Network device. + * + * This function returns current debug message level. + * + * Return current debug message flags. + */ +static u32 netdev_get_msglevel(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + + return priv->msg_enable; +} + +/** + * netdev_set_msglevel - set debug message level + * @dev: Network device. + * @value: Debug message flags. + * + * This procedure sets debug message level. + */ +static void netdev_set_msglevel(struct net_device *dev, u32 value) +{ + struct dev_priv *priv = netdev_priv(dev); + + priv->msg_enable = value; +} + +/** + * netdev_get_eeprom_len - get EEPROM length + * @dev: Network device. + * + * This function returns the length of the EEPROM. + * + * Return length of the EEPROM. + */ +static int netdev_get_eeprom_len(struct net_device *dev) +{ + return EEPROM_SIZE * 2; +} + +/** + * netdev_get_eeprom - get EEPROM data + * @dev: Network device. + * @eeprom: Ethtool EEPROM data structure. + * @data: Buffer to store the EEPROM data. + * + * This function dumps the EEPROM data in the provided buffer. + * + * Return 0 if successful; otherwise an error code. + */ +#define EEPROM_MAGIC 0x10A18842 + +static int netdev_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + u8 *eeprom_byte = (u8 *) eeprom_data; + int i; + int len; + + len = (eeprom->offset + eeprom->len + 1) / 2; + for (i = eeprom->offset / 2; i < len; i++) + eeprom_data[i] = eeprom_read(&hw_priv->hw, i); + eeprom->magic = EEPROM_MAGIC; + memcpy(data, &eeprom_byte[eeprom->offset], eeprom->len); + + return 0; +} + +/** + * netdev_set_eeprom - write EEPROM data + * @dev: Network device. + * @eeprom: Ethtool EEPROM data structure. + * @data: Data buffer. + * + * This function modifies the EEPROM data one byte at a time. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + u16 eeprom_word[EEPROM_SIZE]; + u8 *eeprom_byte = (u8 *) eeprom_word; + int i; + int len; + + if (eeprom->magic != EEPROM_MAGIC) + return 1; + + len = (eeprom->offset + eeprom->len + 1) / 2; + for (i = eeprom->offset / 2; i < len; i++) + eeprom_data[i] = eeprom_read(&hw_priv->hw, i); + memcpy(eeprom_word, eeprom_data, EEPROM_SIZE * 2); + memcpy(&eeprom_byte[eeprom->offset], data, eeprom->len); + for (i = 0; i < EEPROM_SIZE; i++) + if (eeprom_word[i] != eeprom_data[i]) { + eeprom_data[i] = eeprom_word[i]; + eeprom_write(&hw_priv->hw, i, eeprom_data[i]); + } + + return 0; +} + +/** + * netdev_get_pauseparam - get flow control parameters + * @dev: Network device. + * @pause: Ethtool PAUSE settings data structure. + * + * This procedure returns the PAUSE control flow settings. + */ +static void netdev_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + pause->autoneg = (hw->overrides & PAUSE_FLOW_CTRL) ? 0 : 1; + if (!hw->ksz_switch) { + pause->rx_pause = + (hw->rx_cfg & DMA_RX_FLOW_ENABLE) ? 1 : 0; + pause->tx_pause = + (hw->tx_cfg & DMA_TX_FLOW_ENABLE) ? 1 : 0; + } else { + pause->rx_pause = + (sw_chk(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_RX_FLOW_CTRL)) ? 1 : 0; + pause->tx_pause = + (sw_chk(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_TX_FLOW_CTRL)) ? 1 : 0; + } +} + +/** + * netdev_set_pauseparam - set flow control parameters + * @dev: Network device. + * @pause: Ethtool PAUSE settings data structure. + * + * This function sets the PAUSE control flow settings. + * Not implemented yet. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port *port = &priv->port; + + mutex_lock(&hw_priv->lock); + if (pause->autoneg) { + if (!pause->rx_pause && !pause->tx_pause) + port->flow_ctrl = PHY_NO_FLOW_CTRL; + else + port->flow_ctrl = PHY_FLOW_CTRL; + hw->overrides &= ~PAUSE_FLOW_CTRL; + port->force_link = 0; + if (hw->ksz_switch) { + sw_cfg(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_RX_FLOW_CTRL, 1); + sw_cfg(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_TX_FLOW_CTRL, 1); + } + port_set_link_speed(port); + } else { + hw->overrides |= PAUSE_FLOW_CTRL; + if (hw->ksz_switch) { + sw_cfg(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_RX_FLOW_CTRL, pause->rx_pause); + sw_cfg(hw, KS8842_SWITCH_CTRL_1_OFFSET, + SWITCH_TX_FLOW_CTRL, pause->tx_pause); + } else + set_flow_ctrl(hw, pause->rx_pause, pause->tx_pause); + } + mutex_unlock(&hw_priv->lock); + + return 0; +} + +/** + * netdev_get_ringparam - get tx/rx ring parameters + * @dev: Network device. + * @pause: Ethtool RING settings data structure. + * + * This procedure returns the TX/RX ring settings. + */ +static void netdev_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + ring->tx_max_pending = (1 << 9); + ring->tx_pending = hw->tx_desc_info.alloc; + ring->rx_max_pending = (1 << 9); + ring->rx_pending = hw->rx_desc_info.alloc; +} + +#define STATS_LEN (TOTAL_PORT_COUNTER_NUM) + +static struct { + char string[ETH_GSTRING_LEN]; +} ethtool_stats_keys[STATS_LEN] = { + { "rx_lo_priority_octets" }, + { "rx_hi_priority_octets" }, + { "rx_undersize_packets" }, + { "rx_fragments" }, + { "rx_oversize_packets" }, + { "rx_jabbers" }, + { "rx_symbol_errors" }, + { "rx_crc_errors" }, + { "rx_align_errors" }, + { "rx_mac_ctrl_packets" }, + { "rx_pause_packets" }, + { "rx_bcast_packets" }, + { "rx_mcast_packets" }, + { "rx_ucast_packets" }, + { "rx_64_or_less_octet_packets" }, + { "rx_65_to_127_octet_packets" }, + { "rx_128_to_255_octet_packets" }, + { "rx_256_to_511_octet_packets" }, + { "rx_512_to_1023_octet_packets" }, + { "rx_1024_to_1522_octet_packets" }, + + { "tx_lo_priority_octets" }, + { "tx_hi_priority_octets" }, + { "tx_late_collisions" }, + { "tx_pause_packets" }, + { "tx_bcast_packets" }, + { "tx_mcast_packets" }, + { "tx_ucast_packets" }, + { "tx_deferred" }, + { "tx_total_collisions" }, + { "tx_excessive_collisions" }, + { "tx_single_collisions" }, + { "tx_mult_collisions" }, + + { "rx_discards" }, + { "tx_discards" }, +}; + +/** + * netdev_get_strings - get statistics identity strings + * @dev: Network device. + * @stringset: String set identifier. + * @buf: Buffer to store the strings. + * + * This procedure returns the strings used to identify the statistics. + */ +static void netdev_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + if (ETH_SS_STATS == stringset) + memcpy(buf, ðtool_stats_keys, + ETH_GSTRING_LEN * hw->mib_cnt); +} + +/** + * netdev_get_sset_count - get statistics size + * @dev: Network device. + * @sset: The statistics set number. + * + * This function returns the size of the statistics to be reported. + * + * Return size of the statistics to be reported. + */ +static int netdev_get_sset_count(struct net_device *dev, int sset) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + switch (sset) { + case ETH_SS_STATS: + return hw->mib_cnt; + default: + return -EOPNOTSUPP; + } +} + +/** + * netdev_get_ethtool_stats - get network device statistics + * @dev: Network device. + * @stats: Ethtool statistics data structure. + * @data: Buffer to store the statistics. + * + * This procedure returns the statistics. + */ +static void netdev_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port *port = &priv->port; + int n_stats = stats->n_stats; + int i; + int n; + int p; + int rc; + u64 counter[TOTAL_PORT_COUNTER_NUM]; + + mutex_lock(&hw_priv->lock); + n = SWITCH_PORT_NUM; + for (i = 0, p = port->first_port; i < port->mib_port_cnt; i++, p++) { + if (media_connected == hw->port_mib[p].state) { + hw_priv->counter[p].read = 1; + + /* Remember first port that requests read. */ + if (n == SWITCH_PORT_NUM) + n = p; + } + } + mutex_unlock(&hw_priv->lock); + + if (n < SWITCH_PORT_NUM) + schedule_work(&hw_priv->mib_read); + + if (1 == port->mib_port_cnt && n < SWITCH_PORT_NUM) { + p = n; + rc = wait_event_interruptible_timeout( + hw_priv->counter[p].counter, + 2 == hw_priv->counter[p].read, + HZ * 1); + } else + for (i = 0, p = n; i < port->mib_port_cnt - n; i++, p++) { + if (0 == i) { + rc = wait_event_interruptible_timeout( + hw_priv->counter[p].counter, + 2 == hw_priv->counter[p].read, + HZ * 2); + } else if (hw->port_mib[p].cnt_ptr) { + rc = wait_event_interruptible_timeout( + hw_priv->counter[p].counter, + 2 == hw_priv->counter[p].read, + HZ * 1); + } + } + + get_mib_counters(hw, port->first_port, port->mib_port_cnt, counter); + n = hw->mib_cnt; + if (n > n_stats) + n = n_stats; + n_stats -= n; + for (i = 0; i < n; i++) + *data++ = counter[i]; +} + +/** + * netdev_get_rx_csum - get receive checksum support + * @dev: Network device. + * + * This function gets receive checksum support setting. + * + * Return true if receive checksum is enabled; false otherwise. + */ +static u32 netdev_get_rx_csum(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + + return hw->rx_cfg & + (DMA_RX_CSUM_UDP | + DMA_RX_CSUM_TCP | + DMA_RX_CSUM_IP); +} + +/** + * netdev_set_rx_csum - set receive checksum support + * @dev: Network device. + * @data: Zero to disable receive checksum support. + * + * This function sets receive checksum support setting. + * + * Return 0 if successful; otherwise an error code. + */ +static int netdev_set_rx_csum(struct net_device *dev, u32 data) +{ + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + u32 new_setting = hw->rx_cfg; + + if (data) + new_setting |= + (DMA_RX_CSUM_UDP | DMA_RX_CSUM_TCP | + DMA_RX_CSUM_IP); + else + new_setting &= + ~(DMA_RX_CSUM_UDP | DMA_RX_CSUM_TCP | + DMA_RX_CSUM_IP); + new_setting &= ~DMA_RX_CSUM_UDP; + mutex_lock(&hw_priv->lock); + if (new_setting != hw->rx_cfg) { + hw->rx_cfg = new_setting; + if (hw->enabled) + writel(hw->rx_cfg, hw->io + KS_DMA_RX_CTRL); + } + mutex_unlock(&hw_priv->lock); + return 0; +} + +static struct ethtool_ops netdev_ethtool_ops = { + .get_settings = netdev_get_settings, + .set_settings = netdev_set_settings, + .nway_reset = netdev_nway_reset, + .get_link = netdev_get_link, + .get_drvinfo = netdev_get_drvinfo, + .get_regs_len = netdev_get_regs_len, + .get_regs = netdev_get_regs, + .get_wol = netdev_get_wol, + .set_wol = netdev_set_wol, + .get_msglevel = netdev_get_msglevel, + .set_msglevel = netdev_set_msglevel, + .get_eeprom_len = netdev_get_eeprom_len, + .get_eeprom = netdev_get_eeprom, + .set_eeprom = netdev_set_eeprom, + .get_pauseparam = netdev_get_pauseparam, + .set_pauseparam = netdev_set_pauseparam, + .get_ringparam = netdev_get_ringparam, + .get_strings = netdev_get_strings, + .get_sset_count = netdev_get_sset_count, + .get_ethtool_stats = netdev_get_ethtool_stats, + .get_rx_csum = netdev_get_rx_csum, + .set_rx_csum = netdev_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +}; + +/* + * Hardware monitoring + */ + +static void update_link(struct net_device *dev, struct dev_priv *priv, + struct ksz_port *port) +{ + if (priv->media_state != port->linked->state) { + priv->media_state = port->linked->state; + if (netif_running(dev)) { + if (media_connected == priv->media_state) + netif_carrier_on(dev); + else + netif_carrier_off(dev); + if (netif_msg_link(priv)) + printk(KERN_INFO "%s link %s\n", dev->name, + (media_connected == priv->media_state ? + "on" : "off")); + } + } +} + +static void mib_read_work(struct work_struct *work) +{ + struct dev_info *hw_priv = + container_of(work, struct dev_info, mib_read); + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port_mib *mib; + int i; + + next_jiffies = jiffies; + for (i = 0; i < hw->mib_port_cnt; i++) { + mib = &hw->port_mib[i]; + + /* Reading MIB counters or requested to read. */ + if (mib->cnt_ptr || 1 == hw_priv->counter[i].read) { + + /* Need to process receive interrupt. */ + if (port_r_cnt(hw, i)) + break; + hw_priv->counter[i].read = 0; + + /* Finish reading counters. */ + if (0 == mib->cnt_ptr) { + hw_priv->counter[i].read = 2; + wake_up_interruptible( + &hw_priv->counter[i].counter); + } + } else if (jiffies >= hw_priv->counter[i].time) { + /* Only read MIB counters when the port is connected. */ + if (media_connected == mib->state) + hw_priv->counter[i].read = 1; + next_jiffies += HZ * 1 * hw->mib_port_cnt; + hw_priv->counter[i].time = next_jiffies; + + /* Port is just disconnected. */ + } else if (mib->link_down) { + mib->link_down = 0; + + /* Read counters one last time after link is lost. */ + hw_priv->counter[i].read = 1; + } + } +} + +static void mib_monitor(unsigned long ptr) +{ + struct dev_info *hw_priv = (struct dev_info *) ptr; + + mib_read_work(&hw_priv->mib_read); + + /* This is used to verify Wake-on-LAN is working. */ + if (hw_priv->pme_wait) { + if (hw_priv->pme_wait <= jiffies) { + hw_clr_wol_pme_status(&hw_priv->hw); + hw_priv->pme_wait = 0; + } + } else if (hw_chk_wol_pme_status(&hw_priv->hw)) { + + /* PME is asserted. Wait 2 seconds to clear it. */ + hw_priv->pme_wait = jiffies + HZ * 2; + } + + ksz_update_timer(&hw_priv->mib_timer_info); +} + +/** + * dev_monitor - periodic monitoring + * @ptr: Network device pointer. + * + * This routine is run in a kernel timer to monitor the network device. + */ +static void dev_monitor(unsigned long ptr) +{ + struct net_device *dev = (struct net_device *) ptr; + struct dev_priv *priv = netdev_priv(dev); + struct dev_info *hw_priv = priv->adapter; + struct ksz_hw *hw = &hw_priv->hw; + struct ksz_port *port = &priv->port; + + if (!(hw->features & LINK_INT_WORKING)) + port_get_link_speed(port); + update_link(dev, priv, port); + + ksz_update_timer(&priv->monitor_timer_info); +} + +/* + * Linux network device interface functions + */ + +/* Driver exported variables */ + +static int msg_enable; + +static char *macaddr = ":"; +static char *mac1addr = ":"; + +/* + * This enables multiple network device mode for KSZ8842, which contains a + * switch with two physical ports. Some users like to take control of the + * ports for running Spanning Tree Protocol. The driver will create an + * additional eth? device for the other port. + * + * Some limitations are the network devices cannot have different MTU and + * multicast hash tables. + */ +static int multi_dev; + +/* + * As most users select multiple network device mode to use Spanning Tree + * Protocol, this enables a feature in which most unicast and multicast packets + * are forwarded inside the switch and not passed to the host. Only packets + * that need the host's attention are passed to it. This prevents the host + * wasting CPU time to examine each and every incoming packets and do the + * forwarding itself. + * + * As the hack requires the private bridge header, the driver cannot compile + * with just the kernel headers. + * + * Enabling STP support also turns on multiple network device mode. + */ +static int stp; + +/* + * This enables fast aging in the KSZ8842 switch. Not sure what situation + * needs that. However, fast aging is used to flush the dynamic MAC table when + * STP suport is enabled. + */ +static int fast_aging; + +/** + * netdev_init - initalize network device. + * @dev: Network device. + * + * This function initializes the network device. + * + * Return 0 if successful; otherwise an error code indicating failure. + */ +static int __init netdev_init(struct net_device *dev) +{ + struct dev_priv *priv = netdev_priv(dev); + + /* 500 ms timeout */ + ksz_init_timer(&priv->monitor_timer_info, 500 * HZ / 1000, + dev_monitor, dev); + + /* 500 ms timeout */ + dev->watchdog_timeo = HZ / 2; + + dev->features |= NETIF_F_IP_CSUM; + + /* + * Hardware does not really support IPv6 checksum generation, but + * driver actually runs faster with this on. Refer IPV6_CSUM_GEN_HACK. + */ + dev->features |= NETIF_F_IPV6_CSUM; + dev->features |= NETIF_F_SG; + + sema_init(&priv->proc_sem, 1); + + priv->mii_if.phy_id_mask = 0x1; + priv->mii_if.reg_num_mask = 0x7; + priv->mii_if.dev = dev; + priv->mii_if.mdio_read = mdio_read; + priv->mii_if.mdio_write = mdio_write; + priv->mii_if.phy_id = priv->port.first_port + 1; + + priv->msg_enable = netif_msg_init(msg_enable, + (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)); + + return 0; +} + +static const struct net_device_ops netdev_ops = { + .ndo_init = netdev_init, + .ndo_open = netdev_open, + .ndo_stop = netdev_close, + .ndo_get_stats = netdev_query_statistics, + .ndo_start_xmit = netdev_tx, + .ndo_tx_timeout = netdev_tx_timeout, + .ndo_change_mtu = netdev_change_mtu, + .ndo_set_mac_address = netdev_set_mac_address, + .ndo_do_ioctl = netdev_ioctl, + .ndo_set_rx_mode = netdev_set_rx_mode, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = netdev_netpoll, +#endif +}; + +static void netdev_free(struct net_device *dev) +{ + if (dev->watchdog_timeo) + unregister_netdev(dev); + + free_netdev(dev); +} + +struct platform_info { + struct dev_info dev_info; + struct net_device *netdev[SWITCH_PORT_NUM]; +}; + +static int net_device_present; + +static void get_mac_addr(struct dev_info *hw_priv, u8 *macaddr, int port) +{ + int i; + int j; + int got_num; + int num; + + i = j = num = got_num = 0; + while (j < MAC_ADDR_LEN) { + if (macaddr[i]) { + got_num = 1; + if ('0' <= macaddr[i] && macaddr[i] <= '9') + num = num * 16 + macaddr[i] - '0'; + else if ('A' <= macaddr[i] && macaddr[i] <= 'F') + num = num * 16 + 10 + macaddr[i] - 'A'; + else if ('a' <= macaddr[i] && macaddr[i] <= 'f') + num = num * 16 + 10 + macaddr[i] - 'a'; + else if (':' == macaddr[i]) + got_num = 2; + else + break; + } else if (got_num) + got_num = 2; + else + break; + if (2 == got_num) { + if (MAIN_PORT == port) { + hw_priv->hw.override_addr[j++] = (u8) num; + hw_priv->hw.override_addr[5] += + hw_priv->hw.id; + } else { + hw_priv->hw.ksz_switch->other_addr[j++] = + (u8) num; + hw_priv->hw.ksz_switch->other_addr[5] += + hw_priv->hw.id; + } + num = got_num = 0; + } + i++; + } + if (MAC_ADDR_LEN == j) { + if (MAIN_PORT == port) + hw_priv->hw.mac_override = 1; + } +} + +#define KS884X_DMA_MASK (~0x0UL) + +static void read_other_addr(struct ksz_hw *hw) +{ + int i; + u16 data[3]; + struct ksz_switch *sw = hw->ksz_switch; + + for (i = 0; i < 3; i++) + data[i] = eeprom_read(hw, i + EEPROM_DATA_OTHER_MAC_ADDR); + if ((data[0] || data[1] || data[2]) && data[0] != 0xffff) { + sw->other_addr[5] = (u8) data[0]; + sw->other_addr[4] = (u8)(data[0] >> 8); + sw->other_addr[3] = (u8) data[1]; + sw->other_addr[2] = (u8)(data[1] >> 8); + sw->other_addr[1] = (u8) data[2]; + sw->other_addr[0] = (u8)(data[2] >> 8); + } +} + +#ifndef PCI_VENDOR_ID_MICREL_KS +#define PCI_VENDOR_ID_MICREL_KS 0x16c6 +#endif + +static int __init pcidev_init(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct net_device *dev; + struct dev_priv *priv; + struct dev_info *hw_priv; + struct ksz_hw *hw; + struct platform_info *info; + struct ksz_port *port; + unsigned long reg_base; + unsigned long reg_len; + int cnt; + int i; + int mib_port_count; + int pi; + int port_count; + int result; + char banner[80]; + struct ksz_switch *sw = NULL; + + result = pci_enable_device(pdev); + if (result) + return result; + + result = -ENODEV; + + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) + return result; + + reg_base = pci_resource_start(pdev, 0); + reg_len = pci_resource_len(pdev, 0); + if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) + return result; + + if (!request_mem_region(reg_base, reg_len, DRV_NAME)) + return result; + pci_set_master(pdev); + + result = -ENOMEM; + + info = kmalloc(sizeof(struct platform_info), GFP_KERNEL); + if (!info) + goto pcidev_init_dev_err; + memset(info, 0, sizeof(struct platform_info)); + + hw_priv = &info->dev_info; + hw_priv->pdev = pdev; + + hw = &hw_priv->hw; + + hw->io = ioremap(reg_base, reg_len); + if (!hw->io) + goto pcidev_init_io_err; + + cnt = hw_init(hw); + if (!cnt) { + if (msg_enable & NETIF_MSG_PROBE) + printk(KERN_ALERT "chip not detected\n"); + result = -ENODEV; + goto pcidev_init_alloc_err; + } + + sprintf(banner, "%s\n", version); + banner[13] = cnt + '0'; + ks_info(hw_priv, "%s", banner); + ks_dbg(hw_priv, "Mem = %p; IRQ = %d\n", hw->io, pdev->irq); + + /* Assume device is KSZ8841. */ + hw->dev_count = 1; + port_count = 1; + mib_port_count = 1; + hw->addr_list_size = 0; + hw->mib_cnt = PORT_COUNTER_NUM; + hw->mib_port_cnt = 1; + + /* KSZ8842 has a switch with multiple ports. */ + if (2 == cnt) { + if (fast_aging) + hw->overrides |= FAST_AGING; + + hw->mib_cnt = TOTAL_PORT_COUNTER_NUM; + + /* Multiple network device interfaces are required. */ + if (multi_dev) { + hw->dev_count = SWITCH_PORT_NUM; + hw->addr_list_size = SWITCH_PORT_NUM - 1; + } + + /* Single network device has multiple ports. */ + if (1 == hw->dev_count) { + port_count = SWITCH_PORT_NUM; + mib_port_count = SWITCH_PORT_NUM; + } + hw->mib_port_cnt = TOTAL_PORT_NUM; + hw->ksz_switch = kmalloc(sizeof(struct ksz_switch), GFP_KERNEL); + if (!hw->ksz_switch) + goto pcidev_init_alloc_err; + memset(hw->ksz_switch, 0, sizeof(struct ksz_switch)); + + sw = hw->ksz_switch; + } + for (i = 0; i < hw->mib_port_cnt; i++) + hw->port_mib[i].mib_start = 0; + + hw->parent = hw_priv; + + /* Default MTU is 1500. */ + hw_priv->mtu = (REGULAR_RX_BUF_SIZE + 3) & ~3; + + if (ksz_alloc_mem(hw_priv)) + goto pcidev_init_mem_err; + + hw_priv->hw.id = net_device_present; + + spin_lock_init(&hw_priv->hwlock); + mutex_init(&hw_priv->lock); + + /* tasklet is enabled. */ + tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, + (unsigned long) hw_priv); + tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, + (unsigned long) hw_priv); + + /* tasklet_enable will decrement the atomic counter. */ + tasklet_disable(&hw_priv->rx_tasklet); + tasklet_disable(&hw_priv->tx_tasklet); + + for (i = 0; i < TOTAL_PORT_NUM; i++) + init_waitqueue_head(&hw_priv->counter[i].counter); + + if (macaddr[0] != ':') + get_mac_addr(hw_priv, macaddr, MAIN_PORT); + + /* Read MAC address and initialize override address if not overrided. */ + hw_read_addr(hw); + + /* Multiple device interfaces mode requires a second MAC address. */ + if (hw->dev_count > 1) { + memcpy(sw->other_addr, hw->override_addr, MAC_ADDR_LEN); + read_other_addr(hw); + if (mac1addr[0] != ':') + get_mac_addr(hw_priv, mac1addr, OTHER_PORT); + } + + hw_setup(hw); + if (hw->ksz_switch) + sw_setup(hw); + else { + hw_priv->wol_support = WOL_SUPPORT; + hw_priv->wol_enable = 0; + } + + INIT_WORK(&hw_priv->mib_read, mib_read_work); + + /* 500 ms timeout */ + ksz_init_timer(&hw_priv->mib_timer_info, 500 * HZ / 1000, + mib_monitor, hw_priv); + + for (i = 0; i < hw->dev_count; i++) { + dev = alloc_etherdev(sizeof(struct dev_priv)); + if (!dev) + goto pcidev_init_reg_err; + info->netdev[i] = dev; + + priv = netdev_priv(dev); + priv->adapter = hw_priv; + priv->id = net_device_present++; + + port = &priv->port; + port->port_cnt = port_count; + port->mib_port_cnt = mib_port_count; + port->first_port = i; + port->flow_ctrl = PHY_FLOW_CTRL; + + port->hw = hw; + port->linked = &hw->port_info[port->first_port]; + + for (cnt = 0, pi = i; cnt < port_count; cnt++, pi++) { + hw->port_info[pi].port_id = pi; + hw->port_info[pi].pdev = dev; + hw->port_info[pi].state = media_disconnected; + } + + dev->mem_start = (unsigned long) hw->io; + dev->mem_end = dev->mem_start + reg_len - 1; + dev->irq = pdev->irq; + if (MAIN_PORT == i) + memcpy(dev->dev_addr, hw_priv->hw.override_addr, + MAC_ADDR_LEN); + else { + memcpy(dev->dev_addr, sw->other_addr, + MAC_ADDR_LEN); + if (!memcmp(sw->other_addr, hw->override_addr, + MAC_ADDR_LEN)) + dev->dev_addr[5] += port->first_port; + } + + dev->netdev_ops = &netdev_ops; + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); + if (register_netdev(dev)) + goto pcidev_init_reg_err; + port_set_power_saving(port, true); + } + + pci_dev_get(hw_priv->pdev); + pci_set_drvdata(pdev, info); + return 0; + +pcidev_init_reg_err: + for (i = 0; i < hw->dev_count; i++) { + if (info->netdev[i]) { + netdev_free(info->netdev[i]); + info->netdev[i] = NULL; + } + } + +pcidev_init_mem_err: + ksz_free_mem(hw_priv); + kfree(hw->ksz_switch); + +pcidev_init_alloc_err: + iounmap(hw->io); + +pcidev_init_io_err: + kfree(info); + +pcidev_init_dev_err: + release_mem_region(reg_base, reg_len); + + return result; +} + +static void pcidev_exit(struct pci_dev *pdev) +{ + int i; + struct platform_info *info = pci_get_drvdata(pdev); + struct dev_info *hw_priv = &info->dev_info; + + pci_set_drvdata(pdev, NULL); + + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + for (i = 0; i < hw_priv->hw.dev_count; i++) { + if (info->netdev[i]) + netdev_free(info->netdev[i]); + } + if (hw_priv->hw.io) + iounmap(hw_priv->hw.io); + ksz_free_mem(hw_priv); + kfree(hw_priv->hw.ksz_switch); + pci_dev_put(hw_priv->pdev); + kfree(info); +} + +#ifdef CONFIG_PM +static int pcidev_resume(struct pci_dev *pdev) +{ + int i; + struct platform_info *info = pci_get_drvdata(pdev); + struct dev_info *hw_priv = &info->dev_info; + struct ksz_hw *hw = &hw_priv->hw; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + + if (hw_priv->wol_enable) + hw_cfg_wol_pme(hw, 0); + for (i = 0; i < hw->dev_count; i++) { + if (info->netdev[i]) { + struct net_device *dev = info->netdev[i]; + + if (netif_running(dev)) { + netdev_open(dev); + netif_device_attach(dev); + } + } + } + return 0; +} + +static int pcidev_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int i; + struct platform_info *info = pci_get_drvdata(pdev); + struct dev_info *hw_priv = &info->dev_info; + struct ksz_hw *hw = &hw_priv->hw; + + /* Need to find a way to retrieve the device IP address. */ + u8 net_addr[] = { 192, 168, 1, 1 }; + + for (i = 0; i < hw->dev_count; i++) { + if (info->netdev[i]) { + struct net_device *dev = info->netdev[i]; + + if (netif_running(dev)) { + netif_device_detach(dev); + netdev_close(dev); + } + } + } + if (hw_priv->wol_enable) { + hw_enable_wol(hw, hw_priv->wol_enable, net_addr); + hw_cfg_wol_pme(hw, 1); + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} +#endif + +static char pcidev_name[] = "ksz884xp"; + +static struct pci_device_id pcidev_table[] = { + { PCI_VENDOR_ID_MICREL_KS, 0x8841, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_MICREL_KS, 0x8842, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, pcidev_table); + +static struct pci_driver pci_device_driver = { +#ifdef CONFIG_PM + .suspend = pcidev_suspend, + .resume = pcidev_resume, +#endif + .name = pcidev_name, + .id_table = pcidev_table, + .probe = pcidev_init, + .remove = pcidev_exit +}; + +static int __init ksz884x_init_module(void) +{ + return pci_register_driver(&pci_device_driver); +} + +static void __exit ksz884x_cleanup_module(void) +{ + pci_unregister_driver(&pci_device_driver); +} + +module_init(ksz884x_init_module); +module_exit(ksz884x_cleanup_module); + +MODULE_DESCRIPTION("KSZ8841/2 PCI network driver"); +MODULE_AUTHOR("Tristram Ha "); +MODULE_LICENSE("GPL"); + +module_param_named(message, msg_enable, int, 0); +MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)"); + +module_param(macaddr, charp, 0); +module_param(mac1addr, charp, 0); +module_param(fast_aging, int, 0); +module_param(multi_dev, int, 0); +module_param(stp, int, 0); +MODULE_PARM_DESC(macaddr, "MAC address"); +MODULE_PARM_DESC(mac1addr, "Second MAC address"); +MODULE_PARM_DESC(fast_aging, "Fast aging"); +MODULE_PARM_DESC(multi_dev, "Multiple device interfaces"); +MODULE_PARM_DESC(stp, "STP support"); -- cgit v1.2.3 From 1eb1cc7a209f9593312ba014f1b1f02c31eda4fb Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 8 Feb 2010 11:38:28 +0000 Subject: net: Kconfig change for KSZ884X driver Add Micrel KSZ8841/KSZ8842 PCI Ethernet chip support. Signed-off-by: Tristram Ha Signed-off-by: David S. Miller --- drivers/net/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1bf1987571ff..5f646523c5ae 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1380,6 +1380,17 @@ config AC3200 To compile this driver as a module, choose M here. The module will be called ac3200. +config KSZ884X_PCI + tristate "Micrel KSZ8841/2 PCI" + depends on NET_PCI && PCI + select MII + select CRC32 + help + This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip. + + To compile this driver as a module, choose M here. The module + will be called ksz884x. + config APRICOT tristate "Apricot Xen-II on board Ethernet" depends on NET_PCI && ISA -- cgit v1.2.3 From b25822ca5e3d6551b74506e2c69afada7c29c967 Mon Sep 17 00:00:00 2001 From: Tristram Ha Date: Mon, 8 Feb 2010 11:40:04 +0000 Subject: net: Makefile change for KSZ884X driver Add Micrel KSZ884X network driver for KSZ8841/KSZ8842 PCI Ethernet chips. Signed-off-by: Tristram Ha Signed-off-by: David S. Miller --- drivers/net/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 95958032cd31..622cfd450d48 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -96,6 +96,7 @@ obj-$(CONFIG_SKFP) += skfp/ obj-$(CONFIG_KS8842) += ks8842.o obj-$(CONFIG_KS8851) += ks8851.o obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o +obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o -- cgit v1.2.3 From 830a8a976ff2236ebc383e9a06f7872ed9243bfb Mon Sep 17 00:00:00 2001 From: Shirley Ma Date: Mon, 8 Feb 2010 14:14:42 +0000 Subject: virtio_net: remove send queue Now we have a virtio detach API (in commit f9bfbebf34eab707b065116cdc9699d25ba4252a), we don't need to track xmit skbs in the virio_net driver, which improves transmission performance. Signed-off-by: Shirley Ma Acked-by: Rusty Russell Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 4c347a3df657..ce35b42cc2cb 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -56,9 +56,6 @@ struct virtnet_info /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; - /* Send queue. */ - struct sk_buff_head send; - /* Work struct for refilling if we run low on memory. */ struct delayed_work refill; @@ -505,7 +502,6 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) while ((skb = vi->svq->vq_ops->get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); - __skb_unlink(skb, &vi->send); vi->dev->stats.tx_bytes += skb->len; vi->dev->stats.tx_packets++; tot_sgs += skb_vnet_hdr(skb)->num_sg; @@ -588,15 +584,6 @@ again: } vi->svq->vq_ops->kick(vi->svq); - /* - * Put new one in send queue. You'd expect we'd need this before - * xmit_skb calls add_buf(), since the callback can be triggered - * immediately after that. But since the callback just triggers - * another call back here, normal network xmit locking prevents the - * race. - */ - __skb_queue_head(&vi->send, skb); - /* Don't wait up for transmitted skbs to be freed. */ skb_orphan(skb); nf_reset(skb); @@ -980,9 +967,6 @@ static int virtnet_probe(struct virtio_device *vdev) dev->features |= NETIF_F_HW_VLAN_FILTER; } - /* Initialize our empty send queue. */ - skb_queue_head_init(&vi->send); - err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -1018,6 +1002,12 @@ free: static void free_unused_bufs(struct virtnet_info *vi) { void *buf; + while (1) { + buf = vi->svq->vq_ops->detach_unused_buf(vi->svq); + if (!buf) + break; + dev_kfree_skb(buf); + } while (1) { buf = vi->rvq->vq_ops->detach_unused_buf(vi->rvq); if (!buf) @@ -1038,11 +1028,11 @@ static void __devexit virtnet_remove(struct virtio_device *vdev) /* Stop all the virtqueues. */ vdev->config->reset(vdev); - /* Free our skbs in send queue, if any. */ - __skb_queue_purge(&vi->send); unregister_netdev(vi->dev); cancel_delayed_work_sync(&vi->refill); + + /* Free unused buffers in both send and recv, if any. */ free_unused_bufs(vi); vdev->config->del_vqs(vi->vdev); -- cgit v1.2.3 From e254f6ecaeb4e7c0588e739bf4641df0e8c22bba Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:28:35 +0000 Subject: be2net: remove unused pci device id We are not going to use this device id. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 6 ++---- drivers/net/benet/be_main.c | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 5bc74590c73e..242013157f20 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -44,16 +44,14 @@ #define BE_DEVICE_ID1 0x211 #define BE_DEVICE_ID2 0x221 #define OC_DEVICE_ID1 0x700 -#define OC_DEVICE_ID2 0x701 -#define OC_DEVICE_ID3 0x710 +#define OC_DEVICE_ID2 0x710 static inline char *nic_name(struct pci_dev *pdev) { switch (pdev->device) { case OC_DEVICE_ID1: - case OC_DEVICE_ID2: return OC_NAME; - case OC_DEVICE_ID3: + case OC_DEVICE_ID2: return OC_NAME1; case BE_DEVICE_ID2: return BE3_NAME; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 0014a4e86446..0779f6b5e29b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -34,7 +34,6 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, - { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); -- cgit v1.2.3 From 3f0d4560aedaa67546eaeb3dc75fcdf68ec21036 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:30:35 +0000 Subject: be2net: bug fix for flashing the BladeEngine3 ASIC Now flashing both BE2 and BE3 devices is supported. From: Naresh G Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 9 +- drivers/net/benet/be_cmds.h | 3 +- drivers/net/benet/be_hw.h | 119 +++++++++++++++------- drivers/net/benet/be_main.c | 239 +++++++++++++++++++++++--------------------- 4 files changed, 217 insertions(+), 153 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 3227b11131c4..d1a0e5ede4b3 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1374,7 +1374,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_type, u32 flash_opcode, u32 buf_size) { struct be_mcc_wrb *wrb; - struct be_cmd_write_flashrom *req = cmd->va; + struct be_cmd_write_flashrom *req; struct be_sge *sge; int status; @@ -1408,7 +1408,8 @@ err: return status; } -int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc) +int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + int offset) { struct be_mcc_wrb *wrb; struct be_cmd_write_flashrom *req; @@ -1429,9 +1430,9 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc) be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4); - req->params.op_type = cpu_to_le32(FLASHROM_TYPE_REDBOOT); + req->params.op_type = cpu_to_le32(IMG_TYPE_REDBOOT); req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); - req->params.offset = 0x3FFFC; + req->params.offset = offset; req->params.data_buf_size = 0x4; status = be_mcc_notify_wait(adapter); diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index c622a968c379..7297b5a47657 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -931,7 +931,8 @@ extern int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); -extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc); +int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + int offset); extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_dma_mem *nonemb_cmd); extern int be_cmd_fw_init(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index e2b3beffd49d..bb2ae6f924db 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -99,6 +99,63 @@ /* Number of entries posted */ #define DB_MCCQ_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ +/* Flashrom related descriptors */ +#define IMAGE_TYPE_FIRMWARE 160 +#define IMAGE_TYPE_BOOTCODE 224 +#define IMAGE_TYPE_OPTIONROM 32 + +#define NUM_FLASHDIR_ENTRIES 32 + +#define IMG_TYPE_ISCSI_ACTIVE 0 +#define IMG_TYPE_REDBOOT 1 +#define IMG_TYPE_BIOS 2 +#define IMG_TYPE_PXE_BIOS 3 +#define IMG_TYPE_FCOE_BIOS 8 +#define IMG_TYPE_ISCSI_BACKUP 9 +#define IMG_TYPE_FCOE_FW_ACTIVE 10 +#define IMG_TYPE_FCOE_FW_BACKUP 11 +#define IMG_TYPE_NCSI_BITFILE 13 +#define IMG_TYPE_NCSI_8051 14 + +#define FLASHROM_OPER_FLASH 1 +#define FLASHROM_OPER_SAVE 2 +#define FLASHROM_OPER_REPORT 4 + +#define FLASH_IMAGE_MAX_SIZE_g2 (1310720) /* Max firmware image sz */ +#define FLASH_BIOS_IMAGE_MAX_SIZE_g2 (262144) /* Max OPTION ROM img sz */ +#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2 (262144) /* Max Redboot image sz */ +#define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max fw image size */ +#define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM img sz */ +#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */ + +#define FLASH_NCSI_MAGIC (0x16032009) +#define FLASH_NCSI_DISABLED (0) +#define FLASH_NCSI_ENABLED (1) + +#define FLASH_NCSI_BITFILE_HDR_OFFSET (0x600000) + +/* Offsets for components on Flash. */ +#define FLASH_iSCSI_PRIMARY_IMAGE_START_g2 (1048576) +#define FLASH_iSCSI_BACKUP_IMAGE_START_g2 (2359296) +#define FLASH_FCoE_PRIMARY_IMAGE_START_g2 (3670016) +#define FLASH_FCoE_BACKUP_IMAGE_START_g2 (4980736) +#define FLASH_iSCSI_BIOS_START_g2 (7340032) +#define FLASH_PXE_BIOS_START_g2 (7864320) +#define FLASH_FCoE_BIOS_START_g2 (524288) +#define FLASH_REDBOOT_START_g2 (0) + +#define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 (2097152) +#define FLASH_iSCSI_BACKUP_IMAGE_START_g3 (4194304) +#define FLASH_FCoE_PRIMARY_IMAGE_START_g3 (6291456) +#define FLASH_FCoE_BACKUP_IMAGE_START_g3 (8388608) +#define FLASH_iSCSI_BIOS_START_g3 (12582912) +#define FLASH_PXE_BIOS_START_g3 (13107200) +#define FLASH_FCoE_BIOS_START_g3 (13631488) +#define FLASH_REDBOOT_START_g3 (262144) + + + + /* * BE descriptors: host memory data structures whose formats * are hardwired in BE silicon. @@ -107,6 +164,7 @@ #define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ #define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ #define EQ_ENTRY_RES_ID_SHIFT 16 + struct be_eq_entry { u32 evt; }; @@ -221,41 +279,6 @@ struct be_eth_rx_compl { u32 dw[4]; }; -/* Flashrom related descriptors */ -#define IMAGE_TYPE_FIRMWARE 160 -#define IMAGE_TYPE_BOOTCODE 224 -#define IMAGE_TYPE_OPTIONROM 32 - -#define NUM_FLASHDIR_ENTRIES 32 - -#define FLASHROM_TYPE_ISCSI_ACTIVE 0 -#define FLASHROM_TYPE_REDBOOT 1 -#define FLASHROM_TYPE_BIOS 2 -#define FLASHROM_TYPE_PXE_BIOS 3 -#define FLASHROM_TYPE_FCOE_BIOS 8 -#define FLASHROM_TYPE_ISCSI_BACKUP 9 -#define FLASHROM_TYPE_FCOE_FW_ACTIVE 10 -#define FLASHROM_TYPE_FCOE_FW_BACKUP 11 - -#define FLASHROM_OPER_FLASH 1 -#define FLASHROM_OPER_SAVE 2 -#define FLASHROM_OPER_REPORT 4 - -#define FLASH_IMAGE_MAX_SIZE (1310720) /* Max firmware image size */ -#define FLASH_BIOS_IMAGE_MAX_SIZE (262144) /* Max OPTION ROM image sz */ -#define FLASH_REDBOOT_IMAGE_MAX_SIZE (262144) /* Max redboot image sz */ - -/* Offsets for components on Flash. */ -#define FLASH_iSCSI_PRIMARY_IMAGE_START (1048576) -#define FLASH_iSCSI_BACKUP_IMAGE_START (2359296) -#define FLASH_FCoE_PRIMARY_IMAGE_START (3670016) -#define FLASH_FCoE_BACKUP_IMAGE_START (4980736) -#define FLASH_iSCSI_BIOS_START (7340032) -#define FLASH_PXE_BIOS_START (7864320) -#define FLASH_FCoE_BIOS_START (524288) -#define FLASH_REDBOOT_START (32768) -#define FLASH_REDBOOT_ISM_START (0) - struct controller_id { u32 vendor; u32 device; @@ -263,7 +286,20 @@ struct controller_id { u32 subdevice; }; -struct flash_file_hdr { +struct flash_comp { + unsigned long offset; + int optype; + int size; +}; + +struct image_hdr { + u32 imageid; + u32 imageoffset; + u32 imagelength; + u32 image_checksum; + u8 image_version[32]; +}; +struct flash_file_hdr_g2 { u8 sign[32]; u32 cksum; u32 antidote; @@ -275,6 +311,17 @@ struct flash_file_hdr { u8 build[24]; }; +struct flash_file_hdr_g3 { + u8 sign[52]; + u8 ufi_version[4]; + u32 file_len; + u32 cksum; + u32 antidote; + u32 num_imgs; + u8 build[24]; + u8 rsvd[32]; +}; + struct flash_section_hdr { u32 format_rev; u32 cksum; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 0779f6b5e29b..99061488eeb3 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1798,15 +1798,19 @@ char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; static bool be_flash_redboot(struct be_adapter *adapter, - const u8 *p) + const u8 *p, u32 img_start, int image_size, + int hdr_size) { u32 crc_offset; u8 flashed_crc[4]; int status; - crc_offset = FLASH_REDBOOT_START + FLASH_REDBOOT_IMAGE_MAX_SIZE - 4 - + sizeof(struct flash_file_hdr) - 32*1024; + + crc_offset = hdr_size + img_start + image_size - 4; + p += crc_offset; - status = be_cmd_get_flash_crc(adapter, flashed_crc); + + status = be_cmd_get_flash_crc(adapter, flashed_crc, + (img_start + image_size - 4)); if (status) { dev_err(&adapter->pdev->dev, "could not get crc from flash, not flashing redboot\n"); @@ -1818,102 +1822,124 @@ static bool be_flash_redboot(struct be_adapter *adapter, return false; else return true; - } -static int be_flash_image(struct be_adapter *adapter, +static int be_flash_data(struct be_adapter *adapter, const struct firmware *fw, - struct be_dma_mem *flash_cmd, u32 flash_type) + struct be_dma_mem *flash_cmd, int num_of_images) + { - int status; - u32 flash_op, image_offset = 0, total_bytes, image_size = 0; + int status = 0, i, filehdr_size = 0; + u32 total_bytes = 0, flash_op; int num_bytes; const u8 *p = fw->data; struct be_cmd_write_flashrom *req = flash_cmd->va; - - switch (flash_type) { - case FLASHROM_TYPE_ISCSI_ACTIVE: - image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_ISCSI_BACKUP: - image_offset = FLASH_iSCSI_BACKUP_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_FW_ACTIVE: - image_offset = FLASH_FCoE_PRIMARY_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_FW_BACKUP: - image_offset = FLASH_FCoE_BACKUP_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_BIOS: - image_offset = FLASH_iSCSI_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_BIOS: - image_offset = FLASH_FCoE_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_PXE_BIOS: - image_offset = FLASH_PXE_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_REDBOOT: - if (!be_flash_redboot(adapter, fw->data)) - return 0; - image_offset = FLASH_REDBOOT_ISM_START; - image_size = FLASH_REDBOOT_IMAGE_MAX_SIZE; - break; - default: - return 0; + struct flash_comp *pflashcomp; + + struct flash_comp gen3_flash_types[8] = { + { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, + FLASH_REDBOOT_IMAGE_MAX_SIZE_g3}, + { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, + FLASH_IMAGE_MAX_SIZE_g3} + }; + struct flash_comp gen2_flash_types[8] = { + { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT, + FLASH_REDBOOT_IMAGE_MAX_SIZE_g2}, + { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP, + FLASH_IMAGE_MAX_SIZE_g2} + }; + + if (adapter->generation == BE_GEN3) { + pflashcomp = gen3_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g3); + } else { + pflashcomp = gen2_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g2); } - - p += sizeof(struct flash_file_hdr) + image_offset; - if (p + image_size > fw->data + fw->size) + for (i = 0; i < 8; i++) { + if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && + (!be_flash_redboot(adapter, fw->data, + pflashcomp[i].offset, pflashcomp[i].size, + filehdr_size))) + continue; + p = fw->data; + p += filehdr_size + pflashcomp[i].offset + + (num_of_images * sizeof(struct image_hdr)); + if (p + pflashcomp[i].size > fw->data + fw->size) return -1; - - total_bytes = image_size; - - while (total_bytes) { - if (total_bytes > 32*1024) - num_bytes = 32*1024; - else - num_bytes = total_bytes; - total_bytes -= num_bytes; - - if (!total_bytes) - flash_op = FLASHROM_OPER_FLASH; - else - flash_op = FLASHROM_OPER_SAVE; - memcpy(req->params.data_buf, p, num_bytes); - p += num_bytes; - status = be_cmd_write_flashrom(adapter, flash_cmd, - flash_type, flash_op, num_bytes); - if (status) { - dev_err(&adapter->pdev->dev, - "cmd to write to flash rom failed. type/op %d/%d\n", - flash_type, flash_op); - return -1; + total_bytes = pflashcomp[i].size; + while (total_bytes) { + if (total_bytes > 32*1024) + num_bytes = 32*1024; + else + num_bytes = total_bytes; + total_bytes -= num_bytes; + + if (!total_bytes) + flash_op = FLASHROM_OPER_FLASH; + else + flash_op = FLASHROM_OPER_SAVE; + memcpy(req->params.data_buf, p, num_bytes); + p += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, + pflashcomp[i].optype, flash_op, num_bytes); + if (status) { + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); + return -1; + } + yield(); } - yield(); } - return 0; } +static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) +{ + if (fhdr == NULL) + return 0; + if (fhdr->build[0] == '3') + return BE_GEN3; + else if (fhdr->build[0] == '2') + return BE_GEN2; + else + return 0; +} + int be_load_fw(struct be_adapter *adapter, u8 *func) { char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; const struct firmware *fw; - struct flash_file_hdr *fhdr; - struct flash_section_info *fsec = NULL; + struct flash_file_hdr_g2 *fhdr; + struct flash_file_hdr_g3 *fhdr3; + struct image_hdr *img_hdr_ptr = NULL; struct be_dma_mem flash_cmd; - int status; + int status, i = 0; const u8 *p; - bool entry_found = false; - int flash_type; char fw_ver[FW_VER_LEN]; char fw_cfg; @@ -1931,34 +1957,9 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) goto fw_exit; p = fw->data; - fhdr = (struct flash_file_hdr *) p; - if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) { - dev_err(&adapter->pdev->dev, - "Firmware(%s) load error (signature did not match)\n", - fw_file); - status = -1; - goto fw_exit; - } - + fhdr = (struct flash_file_hdr_g2 *) p; dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); - p += sizeof(struct flash_file_hdr); - while (p < (fw->data + fw->size)) { - fsec = (struct flash_section_info *)p; - if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) { - entry_found = true; - break; - } - p += 32; - } - - if (!entry_found) { - status = -1; - dev_err(&adapter->pdev->dev, - "Flash cookie not found in firmware image\n"); - goto fw_exit; - } - flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, &flash_cmd.dma); @@ -1969,12 +1970,26 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) goto fw_exit; } - for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE; - flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) { - status = be_flash_image(adapter, fw, &flash_cmd, - flash_type); - if (status) - break; + if ((adapter->generation == BE_GEN3) && + (get_ufigen_type(fhdr) == BE_GEN3)) { + fhdr3 = (struct flash_file_hdr_g3 *) fw->data; + for (i = 0; i < fhdr3->num_imgs; i++) { + img_hdr_ptr = (struct image_hdr *) (fw->data + + (sizeof(struct flash_file_hdr_g3) + + i * sizeof(struct image_hdr))); + if (img_hdr_ptr->imageid == 1) { + status = be_flash_data(adapter, fw, + &flash_cmd, fhdr3->num_imgs); + } + + } + } else if ((adapter->generation == BE_GEN2) && + (get_ufigen_type(fhdr) == BE_GEN2)) { + status = be_flash_data(adapter, fw, &flash_cmd, 0); + } else { + dev_err(&adapter->pdev->dev, + "UFI and Interface are not compatible for flashing\n"); + status = -1; } pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, -- cgit v1.2.3 From 34a89b8c75abe2873a95524552cc266fdd3b6a85 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:32:43 +0000 Subject: be2net: bug fix in be_change_mtu Current code allows the new mtu to cross the supported value. This patch fixes the boundary checks. From: Suresh R Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 99061488eeb3..c65c63427d41 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -473,10 +473,12 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) { struct be_adapter *adapter = netdev_priv(netdev); if (new_mtu < BE_MIN_MTU || - new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { + new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN))) { dev_info(&adapter->pdev->dev, "MTU must be between %d and %d bytes\n", - BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); + BE_MIN_MTU, + (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); return -EINVAL; } dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", -- cgit v1.2.3 From 205859a2ff922d0587a819b08007398cbd0a6a30 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:34:21 +0000 Subject: be2net: minor code optimizations Couple of code optimizations in the Rx path (to avoid a memset). From: Sathya P Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index c65c63427d41..1951d7620a88 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -636,9 +636,11 @@ get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; BUG_ON(!rx_page_info->page); - if (rx_page_info->last_page_user) + if (rx_page_info->last_page_user) { pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), adapter->big_page_size, PCI_DMA_FROMDEVICE); + rx_page_info->last_page_user = false; + } atomic_dec(&rxq->used); return rx_page_info; @@ -706,7 +708,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, skb->data_len = curr_frag_len - hdr_len; skb->tail += hdr_len; } - memset(page_info, 0, sizeof(*page_info)); + page_info->page = NULL; if (pktsize <= rx_frag_size) { BUG_ON(num_rcvd != 1); @@ -739,7 +741,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, skb->len += curr_frag_len; skb->data_len += curr_frag_len; - memset(page_info, 0, sizeof(*page_info)); + page_info->page = NULL; } BUG_ON(j > MAX_SKB_FRAGS); -- cgit v1.2.3 From 82903e4bfca1578336a91c0c17839b484c12295d Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:34:57 +0000 Subject: be2net: fix to limit max vlans supported in certain skews In certain skews the ASIC can support only 16 vlans per interface. Once the limit is crossed, the ASIC is programmed in vlan promiscuous mode. Switch off the vlan promiscuous mode once the number of vlans falls back to the max vlans supported. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 3 ++- drivers/net/benet/be_main.c | 30 +++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 242013157f20..476a5c455794 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -250,7 +250,8 @@ struct be_adapter { bool rx_post_starved; /* Zero rx frags have been posted to BE */ struct vlan_group *vlan_grp; - u16 num_vlans; + u16 vlans_added; + u16 max_vlans; /* Number of vlans supported */ u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; struct be_dma_mem mc_cmd_mem; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 1951d7620a88..92c55f679466 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -488,17 +488,16 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) } /* - * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, - * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, - * set the BE in promiscuous VLAN mode. + * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE. + * If the user configures more, place BE in vlan promiscuous mode. */ static int be_vid_config(struct be_adapter *adapter) { u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; - int status; + int status = 0; - if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { + if (adapter->vlans_added <= adapter->max_vlans) { /* Construct VLAN Table to give to HW */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { if (adapter->vlan_tag[i]) { @@ -532,21 +531,21 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); - adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - - be_vid_config(adapter); + adapter->vlans_added++; + if (adapter->vlans_added <= (adapter->max_vlans + 1)) + be_vid_config(adapter); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); - adapter->num_vlans--; adapter->vlan_tag[vid] = 0; - vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vid_config(adapter); + adapter->vlans_added--; + if (adapter->vlans_added <= adapter->max_vlans) + be_vid_config(adapter); } static void be_set_multicast_list(struct net_device *netdev) @@ -786,7 +785,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb->dev = adapter->netdev; if (vlanf) { - if (!adapter->vlan_grp || adapter->num_vlans == 0) { + if (!adapter->vlan_grp || adapter->vlans_added == 0) { kfree_skb(skb); return; } @@ -866,7 +865,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); vid = be16_to_cpu(vid); - if (!adapter->vlan_grp || adapter->num_vlans == 0) + if (!adapter->vlan_grp || adapter->vlans_added == 0) return; vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); @@ -2241,6 +2240,11 @@ static int be_get_config(struct be_adapter *adapter) memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); + if (adapter->cap & 0x400) + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + return 0; } -- cgit v1.2.3 From 35ecf03c833d9aae35df9f1d86e6efa86d3d2628 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:38:06 +0000 Subject: be2net: change the driver description Since the driver is supporting multiple generations of the ASIC remove ASIC generation information from the driver description. This information is displayed by modinfo. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 476a5c455794..b39b38542623 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -38,7 +38,7 @@ #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" #define OC_NAME "Emulex OneConnect 10Gbps NIC" #define OC_NAME1 "Emulex OneConnect 10Gbps NIC (be3)" -#define DRV_DESC BE_NAME "Driver" +#define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" #define BE_VENDOR_ID 0x19a2 #define BE_DEVICE_ID1 0x211 -- cgit v1.2.3 From 1a8cdc5d49cdbd79dedce8db3840fca825304d8d Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:39:05 +0000 Subject: be2net: remove ASIC generation number from Kconfig Since the driver is supporting multiple generations of the ASIC don't mention any ASIC generation number. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig index fdb6e81a4374..1a41a49bb619 100644 --- a/drivers/net/benet/Kconfig +++ b/drivers/net/benet/Kconfig @@ -1,6 +1,6 @@ config BE2NET - tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" + tristate "ServerEngines' 10Gbps NIC - BladeEngine" depends on PCI && INET help This driver implements the NIC functionality for ServerEngines' - 10Gbps network adapter - BladeEngine 2. + 10Gbps network adapter - BladeEngine. -- cgit v1.2.3 From c0ad98453f23b98f73a1f1be2a75303a6c0dee4c Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Mon, 8 Feb 2010 17:51:26 +0000 Subject: be2net: bug fix in be_read_eeprom The offset to read the eeprom data was missing and wrong eeprom data was being dumped. This patch fixes this. >From Suresh R Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index 09d8899b2de9..dcc7f37b5428 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -614,7 +614,7 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, if (!status) { resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va; - memcpy(data, resp->seeprom_data, eeprom->len); + memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len); } pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va, eeprom_cmd.dma); -- cgit v1.2.3 From dc2b99f71ef477a31020511876ab4403fb7c4420 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 8 Feb 2010 19:48:05 +0000 Subject: IPv6: keep permanent addresses on admin down Permanent IPV6 addresses should not be removed when the link is set to admin down, only when device is removed. When link is lost permanent addresses should be marked as tentative so that when link comes back they are subject to duplicate address detection (if DAD was enabled for that address). Other routing systems keep manually configured IPv6 addresses when link is set down. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1593289155ff..b0e1430b64f1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2646,7 +2646,8 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_lock_bh(&addrconf_hash_lock); while ((ifa = *bifa) != NULL) { - if (ifa->idev == idev) { + if (ifa->idev == idev && + (how || !(ifa->flags&IFA_F_PERMANENT))) { *bifa = ifa->lst_next; ifa->lst_next = NULL; addrconf_del_timer(ifa); @@ -2686,18 +2687,30 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_lock_bh(&idev->lock); } #endif - while ((ifa = idev->addr_list) != NULL) { - idev->addr_list = ifa->if_next; - ifa->if_next = NULL; - ifa->dead = 1; - addrconf_del_timer(ifa); - write_unlock_bh(&idev->lock); + bifa = &idev->addr_list; + while ((ifa = *bifa) != NULL) { + if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) { + /* Retain permanent address on admin down */ + bifa = &ifa->if_next; + + /* Restart DAD if needed when link comes back up */ + if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || + idev->cnf.accept_dad <= 0 || + (ifa->flags & IFA_F_NODAD))) + ifa->flags |= IFA_F_TENTATIVE; + } else { + *bifa = ifa->if_next; + ifa->if_next = NULL; - __ipv6_ifa_notify(RTM_DELADDR, ifa); - atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); - in6_ifa_put(ifa); + ifa->dead = 1; + write_unlock_bh(&idev->lock); - write_lock_bh(&idev->lock); + __ipv6_ifa_notify(RTM_DELADDR, ifa); + atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); + in6_ifa_put(ifa); + + write_lock_bh(&idev->lock); + } } write_unlock_bh(&idev->lock); -- cgit v1.2.3 From 21809fafa042fcfff3f788419bed99f3c289745c Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 8 Feb 2010 19:48:52 +0000 Subject: IPv6: remove trivial nested _bh suffix Don't need to disable bottom half it is already down in the previous lock. Move some blank lines to group locking in same context. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/ipv6/addrconf.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b0e1430b64f1..764ad37ca070 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2802,14 +2802,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) read_lock_bh(&idev->lock); if (ifp->dead) goto out; - spin_lock_bh(&ifp->lock); + spin_lock(&ifp->lock); if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || idev->cnf.accept_dad < 1 || !(ifp->flags&IFA_F_TENTATIVE) || ifp->flags & IFA_F_NODAD) { ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); read_unlock_bh(&idev->lock); addrconf_dad_completed(ifp); @@ -2817,7 +2817,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) } if (!(idev->if_flags & IF_READY)) { - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); read_unlock_bh(&idev->lock); /* * If the device is not ready: @@ -2837,7 +2837,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) ip6_ins_rt(ifp->rt); addrconf_dad_kick(ifp); - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); out: read_unlock_bh(&idev->lock); } @@ -2853,14 +2853,15 @@ static void addrconf_dad_timer(unsigned long data) read_unlock_bh(&idev->lock); goto out; } - spin_lock_bh(&ifp->lock); + + spin_lock(&ifp->lock); if (ifp->probes == 0) { /* * DAD was successful */ ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); read_unlock_bh(&idev->lock); addrconf_dad_completed(ifp); @@ -2870,7 +2871,7 @@ static void addrconf_dad_timer(unsigned long data) ifp->probes--; addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); read_unlock_bh(&idev->lock); /* send a neighbour solicitation for our addr */ @@ -2918,12 +2919,12 @@ static void addrconf_dad_run(struct inet6_dev *idev) { read_lock_bh(&idev->lock); for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { - spin_lock_bh(&ifp->lock); + spin_lock(&ifp->lock); if (!(ifp->flags & IFA_F_TENTATIVE)) { - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); continue; } - spin_unlock_bh(&ifp->lock); + spin_unlock(&ifp->lock); addrconf_dad_kick(ifp); } read_unlock_bh(&idev->lock); -- cgit v1.2.3 From 571ba42303813106d533bf6bda929d8e289f51bf Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:47 +0000 Subject: netdevice.h: Add netdev_printk helpers like dev_printk These netdev_printk routines take a struct net_device * and emit dev_printk logging messages adding "%s: " ... netdev->dev.parent to the dev_printk format and arguments. This can create some uniformity in the output message log. These helpers should not be used until a successful alloc_netdev. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/linux/netdevice.h | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cdf53a8d9ff5..a51228ac9331 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2095,6 +2095,77 @@ static inline u32 dev_ethtool_get_flags(struct net_device *dev) return 0; return dev->ethtool_ops->get_flags(dev); } + +/* Logging, debugging and troubleshooting/diagnostic helpers. */ + +/* netdev_printk helpers, similar to dev_printk */ + +static inline const char *netdev_name(const struct net_device *dev) +{ + if (dev->reg_state != NETREG_REGISTERED) + return "(unregistered net_device)"; + return dev->name; +} + +#define netdev_printk(level, netdev, format, args...) \ + dev_printk(level, (netdev)->dev.parent, \ + "%s: " format, \ + netdev_name(netdev), ##args) + +#define netdev_emerg(dev, format, args...) \ + netdev_printk(KERN_EMERG, dev, format, ##args) +#define netdev_alert(dev, format, args...) \ + netdev_printk(KERN_ALERT, dev, format, ##args) +#define netdev_crit(dev, format, args...) \ + netdev_printk(KERN_CRIT, dev, format, ##args) +#define netdev_err(dev, format, args...) \ + netdev_printk(KERN_ERR, dev, format, ##args) +#define netdev_warn(dev, format, args...) \ + netdev_printk(KERN_WARNING, dev, format, ##args) +#define netdev_notice(dev, format, args...) \ + netdev_printk(KERN_NOTICE, dev, format, ##args) +#define netdev_info(dev, format, args...) \ + netdev_printk(KERN_INFO, dev, format, ##args) + +#if defined(DEBUG) +#define netdev_dbg(__dev, format, args...) \ + netdev_printk(KERN_DEBUG, __dev, format, ##args) +#elif defined(CONFIG_DYNAMIC_DEBUG) +#define netdev_dbg(__dev, format, args...) \ +do { \ + dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ + netdev_name(__dev), ##args); \ +} while (0) +#else +#define netdev_dbg(__dev, format, args...) \ +({ \ + if (0) \ + netdev_printk(KERN_DEBUG, __dev, format, ##args); \ + 0; \ +}) +#endif + +#if defined(VERBOSE_DEBUG) +#define netdev_vdbg netdev_dbg +#else + +#define netdev_vdbg(dev, format, args...) \ +({ \ + if (0) \ + netdev_printk(KERN_DEBUG, dev, format, ##args); \ + 0; \ +}) +#endif + +/* + * netdev_WARN() acts like dev_printk(), but with the key difference + * of using a WARN/WARN_ON to get the message out, including the + * file/line information and a backtrace. + */ +#define netdev_WARN(dev, format, args...) \ + WARN(1, "netdevice: %s\n" format, netdev_name(dev), ##args); + + #endif /* __KERNEL__ */ #endif /* _LINUX_NETDEVICE_H */ -- cgit v1.2.3 From ba211e3ec35820eced89bfe12e2d94e6352a4c5f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:48 +0000 Subject: drivers/net/atl1e: Use netdev_printk helpers Logging messages sometimes had duplicated "ATL1E" output. For instance: ATL1E 0000:03:00.0: ATL1E: eth0 NIC Link is Up<100 Mbps Full Duplex> is now: ATL1E 0000:03:00.0: eth0: NIC Link is Up <100 Mbps Full Duplex> Add some consistency to logging messages Add some missing \n's to logging messages Miscellaneous typo spelling corrections Change atl1e_validate_option argument from pdev to adapter Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/atl1e/atl1e_hw.c | 23 +++--- drivers/net/atl1e/atl1e_main.c | 153 ++++++++++++++++++---------------------- drivers/net/atl1e/atl1e_param.c | 35 +++++---- 3 files changed, 99 insertions(+), 112 deletions(-) diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c index 4a7700620119..76cc043def8c 100644 --- a/drivers/net/atl1e/atl1e_hw.c +++ b/drivers/net/atl1e/atl1e_hw.c @@ -394,7 +394,6 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw) int atl1e_phy_commit(struct atl1e_hw *hw) { struct atl1e_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; int ret_val; u16 phy_data; @@ -415,12 +414,12 @@ int atl1e_phy_commit(struct atl1e_hw *hw) } if (0 != (val & (MDIO_START | MDIO_BUSY))) { - dev_err(&pdev->dev, - "pcie linkdown at least for 25ms\n"); + netdev_err(adapter->netdev, + "pcie linkdown at least for 25ms\n"); return ret_val; } - dev_err(&pdev->dev, "pcie linkup after %d ms\n", i); + netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i); } return 0; } @@ -428,7 +427,6 @@ int atl1e_phy_commit(struct atl1e_hw *hw) int atl1e_phy_init(struct atl1e_hw *hw) { struct atl1e_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; s32 ret_val; u16 phy_val; @@ -492,20 +490,22 @@ int atl1e_phy_init(struct atl1e_hw *hw) /*Enable PHY LinkChange Interrupt */ ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00); if (ret_val) { - dev_err(&pdev->dev, "Error enable PHY linkChange Interrupt\n"); + netdev_err(adapter->netdev, + "Error enable PHY linkChange Interrupt\n"); return ret_val; } /* setup AutoNeg parameters */ ret_val = atl1e_phy_setup_autoneg_adv(hw); if (ret_val) { - dev_err(&pdev->dev, "Error Setting up Auto-Negotiation\n"); + netdev_err(adapter->netdev, + "Error Setting up Auto-Negotiation\n"); return ret_val; } /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/ - dev_dbg(&pdev->dev, "Restarting Auto-Neg"); + netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n"); ret_val = atl1e_phy_commit(hw); if (ret_val) { - dev_err(&pdev->dev, "Error Resetting the phy"); + netdev_err(adapter->netdev, "Error resetting the phy\n"); return ret_val; } @@ -559,9 +559,8 @@ int atl1e_reset_hw(struct atl1e_hw *hw) } if (timeout >= AT_HW_MAX_IDLE_DELAY) { - dev_err(&pdev->dev, - "MAC state machine cann't be idle since" - " disabled for 10ms second\n"); + netdev_err(adapter->netdev, + "MAC state machine can't be idle since disabled for 10ms second\n"); return AT_ERR_TIMEOUT; } diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index d59f8e89c65d..7d8de10ba628 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -164,11 +164,10 @@ static int atl1e_check_link(struct atl1e_adapter *adapter) { struct atl1e_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; int err = 0; u16 speed, duplex, phy_data; - /* MII_BMSR must read twise */ + /* MII_BMSR must read twice */ atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); if ((phy_data & BMSR_LSTATUS) == 0) { @@ -195,12 +194,11 @@ static int atl1e_check_link(struct atl1e_adapter *adapter) adapter->link_speed = speed; adapter->link_duplex = duplex; atl1e_setup_mac_ctrl(adapter); - dev_info(&pdev->dev, - "%s: %s NIC Link is Up<%d Mbps %s>\n", - atl1e_driver_name, netdev->name, - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex"); + netdev_info(netdev, + "NIC Link is Up <%d Mbps %s Duplex>\n", + adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "Full" : "Half"); } if (!netif_carrier_ok(netdev)) { @@ -230,7 +228,6 @@ static void atl1e_link_chg_task(struct work_struct *work) static void atl1e_link_chg_event(struct atl1e_adapter *adapter) { struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; u16 phy_data = 0; u16 link_up = 0; @@ -243,8 +240,7 @@ static void atl1e_link_chg_event(struct atl1e_adapter *adapter) if (!link_up) { if (netif_carrier_ok(netdev)) { /* old link state: Up */ - dev_info(&pdev->dev, "%s: %s NIC Link is Down\n", - atl1e_driver_name, netdev->name); + netdev_info(netdev, "NIC Link is Down\n"); adapter->link_speed = SPEED_0; netif_stop_queue(netdev); } @@ -321,10 +317,9 @@ static void atl1e_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) { struct atl1e_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; u32 mac_ctrl_data = 0; - dev_dbg(&pdev->dev, "atl1e_vlan_rx_register\n"); + netdev_dbg(adapter->netdev, "%s\n", __func__); atl1e_irq_disable(adapter); @@ -345,9 +340,7 @@ static void atl1e_vlan_rx_register(struct net_device *netdev, static void atl1e_restore_vlan(struct atl1e_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; - - dev_dbg(&pdev->dev, "atl1e_restore_vlan !"); + netdev_dbg(adapter->netdev, "%s\n", __func__); atl1e_vlan_rx_register(adapter->netdev, adapter->vlgrp); } /* @@ -391,7 +384,7 @@ static int atl1e_change_mtu(struct net_device *netdev, int new_mtu) if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + netdev_warn(adapter->netdev, "invalid MTU setting\n"); return -EINVAL; } /* set MTU */ @@ -438,7 +431,6 @@ static int atl1e_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct atl1e_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; struct mii_ioctl_data *data = if_mii(ifr); unsigned long flags; int retval = 0; @@ -466,8 +458,8 @@ static int atl1e_mii_ioctl(struct net_device *netdev, goto out; } - dev_dbg(&pdev->dev, " write %x %x", - data->reg_num, data->val_in); + netdev_dbg(adapter->netdev, " write %x %x\n", + data->reg_num, data->val_in); if (atl1e_write_phy_reg(&adapter->hw, data->reg_num, data->val_in)) { retval = -EIO; @@ -602,7 +594,7 @@ static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter) hw->dmaw_dly_cnt = 4; if (atl1e_alloc_queues(adapter)) { - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + netdev_err(adapter->netdev, "Unable to allocate memory for queues\n"); return -ENOMEM; } @@ -800,8 +792,8 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) adapter->ring_size, &adapter->ring_dma); if (adapter->ring_vir_addr == NULL) { - dev_err(&pdev->dev, "pci_alloc_consistent failed, " - "size = D%d", size); + netdev_err(adapter->netdev, + "pci_alloc_consistent failed, size = D%d\n", size); return -ENOMEM; } @@ -817,7 +809,8 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count); tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL); if (tx_ring->tx_buffer == NULL) { - dev_err(&pdev->dev, "kzalloc failed , size = D%d", size); + netdev_err(adapter->netdev, "kzalloc failed, size = D%d\n", + size); err = -ENOMEM; goto failed; } @@ -852,8 +845,8 @@ static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) } if (unlikely(offset > adapter->ring_size)) { - dev_err(&pdev->dev, "offset(%d) > ring size(%d) !!\n", - offset, adapter->ring_size); + netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n", + offset, adapter->ring_size); err = -1; goto failed; } @@ -1077,7 +1070,6 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) static int atl1e_configure(struct atl1e_adapter *adapter) { struct atl1e_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; u32 intr_status_data = 0; @@ -1130,8 +1122,8 @@ static int atl1e_configure(struct atl1e_adapter *adapter) intr_status_data = AT_READ_REG(hw, REG_ISR); if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) { - dev_err(&pdev->dev, "atl1e_configure failed," - "PCIE phy link down\n"); + netdev_err(adapter->netdev, + "atl1e_configure failed, PCIE phy link down\n"); return -1; } @@ -1262,7 +1254,6 @@ static irqreturn_t atl1e_intr(int irq, void *data) { struct net_device *netdev = data; struct atl1e_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; struct atl1e_hw *hw = &adapter->hw; int max_ints = AT_MAX_INT_WORK; int handled = IRQ_NONE; @@ -1285,8 +1276,8 @@ static irqreturn_t atl1e_intr(int irq, void *data) handled = IRQ_HANDLED; /* check if PCIE PHY Link down */ if (status & ISR_PHY_LINKDOWN) { - dev_err(&pdev->dev, - "pcie phy linkdown %x\n", status); + netdev_err(adapter->netdev, + "pcie phy linkdown %x\n", status); if (netif_running(adapter->netdev)) { /* reset MAC */ atl1e_irq_reset(adapter); @@ -1297,9 +1288,9 @@ static irqreturn_t atl1e_intr(int irq, void *data) /* check if DMA read/write error */ if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { - dev_err(&pdev->dev, - "PCIE DMA RW error (status = 0x%x)\n", - status); + netdev_err(adapter->netdev, + "PCIE DMA RW error (status = 0x%x)\n", + status); atl1e_irq_reset(adapter); schedule_work(&adapter->reset_task); break; @@ -1382,7 +1373,6 @@ static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter, static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, int *work_done, int work_to_do) { - struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; struct atl1e_rx_ring *rx_ring = (struct atl1e_rx_ring *) &adapter->rx_ring; @@ -1404,11 +1394,10 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, rx_page->read_offset); /* check sequence number */ if (prrs->seq_num != rx_page_desc[que].rx_nxseq) { - dev_err(&pdev->dev, - "rx sequence number" - " error (rx=%d) (expect=%d)\n", - prrs->seq_num, - rx_page_desc[que].rx_nxseq); + netdev_err(netdev, + "rx sequence number error (rx=%d) (expect=%d)\n", + prrs->seq_num, + rx_page_desc[que].rx_nxseq); rx_page_desc[que].rx_nxseq++; /* just for debug use */ AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0, @@ -1424,9 +1413,9 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, RRS_ERR_DRIBBLE | RRS_ERR_CODE | RRS_ERR_TRUNC)) { /* hardware error, discard this packet*/ - dev_err(&pdev->dev, - "rx packet desc error %x\n", - *((u32 *)prrs + 1)); + netdev_err(netdev, + "rx packet desc error %x\n", + *((u32 *)prrs + 1)); goto skip_pkt; } } @@ -1435,8 +1424,8 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, RRS_PKT_SIZE_MASK) - 4; /* CRC */ skb = netdev_alloc_skb_ip_align(netdev, packet_size); if (skb == NULL) { - dev_warn(&pdev->dev, "%s: Memory squeeze," - "deferring packet.\n", netdev->name); + netdev_warn(netdev, + "Memory squeeze, deferring packet\n"); goto skip_pkt; } skb->dev = netdev; @@ -1450,9 +1439,9 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, u16 vlan_tag = (prrs->vtag >> 4) | ((prrs->vtag & 7) << 13) | ((prrs->vtag & 8) << 9); - dev_dbg(&pdev->dev, - "RXD VLAN TAG=0x%04x\n", - prrs->vtag); + netdev_dbg(netdev, + "RXD VLAN TAG=0x%04x\n", + prrs->vtag); vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vlan_tag); } else { @@ -1500,7 +1489,6 @@ static int atl1e_clean(struct napi_struct *napi, int budget) { struct atl1e_adapter *adapter = container_of(napi, struct atl1e_adapter, napi); - struct pci_dev *pdev = adapter->pdev; u32 imr_data; int work_done = 0; @@ -1519,8 +1507,8 @@ quit_polling: /* test debug */ if (test_bit(__AT_DOWN, &adapter->flags)) { atomic_dec(&adapter->irq_sem); - dev_err(&pdev->dev, - "atl1e_clean is called when AT_DOWN\n"); + netdev_err(adapter->netdev, + "atl1e_clean is called when AT_DOWN\n"); } /* reenable RX intr */ /*atl1e_irq_enable(adapter); */ @@ -1618,7 +1606,6 @@ static u16 atl1e_cal_tdp_req(const struct sk_buff *skb) static int atl1e_tso_csum(struct atl1e_adapter *adapter, struct sk_buff *skb, struct atl1e_tpd_desc *tpd) { - struct pci_dev *pdev = adapter->pdev; u8 hdr_len; u32 real_len; unsigned short offload_type; @@ -1642,8 +1629,8 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); if (unlikely(skb->len == hdr_len)) { /* only xsum need */ - dev_warn(&pdev->dev, - "IPV4 tso with zero data??\n"); + netdev_warn(adapter->netdev, + "IPV4 tso with zero data??\n"); goto check_sum; } else { ip_hdr(skb)->check = 0; @@ -1672,8 +1659,8 @@ check_sum: cso = skb_transport_offset(skb); if (unlikely(cso & 0x1)) { - dev_err(&adapter->pdev->dev, - "pay load offset should not ant event number\n"); + netdev_err(adapter->netdev, + "payload offset should not ant event number\n"); return -1; } else { css = cso + skb->csum_offset; @@ -1886,8 +1873,8 @@ static int atl1e_request_irq(struct atl1e_adapter *adapter) adapter->have_msi = true; err = pci_enable_msi(adapter->pdev); if (err) { - dev_dbg(&pdev->dev, - "Unable to allocate MSI interrupt Error: %d\n", err); + netdev_dbg(adapter->netdev, + "Unable to allocate MSI interrupt Error: %d\n", err); adapter->have_msi = false; } else netdev->irq = pdev->irq; @@ -1898,13 +1885,13 @@ static int atl1e_request_irq(struct atl1e_adapter *adapter) err = request_irq(adapter->pdev->irq, atl1e_intr, flags, netdev->name, netdev); if (err) { - dev_dbg(&pdev->dev, - "Unable to allocate interrupt Error: %d\n", err); + netdev_dbg(adapter->netdev, + "Unable to allocate interrupt Error: %d\n", err); if (adapter->have_msi) pci_disable_msi(adapter->pdev); return err; } - dev_dbg(&pdev->dev, "atl1e_request_irq OK\n"); + netdev_dbg(adapter->netdev, "atl1e_request_irq OK\n"); return err; } @@ -2078,7 +2065,7 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) (atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_advertise_data) != 0) || (atl1e_phy_commit(hw)) != 0) { - dev_dbg(&pdev->dev, "set phy register failed\n"); + netdev_dbg(adapter->netdev, "set phy register failed\n"); goto wol_dis; } @@ -2100,17 +2087,14 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) } if ((mii_bmsr_data & BMSR_LSTATUS) == 0) - dev_dbg(&pdev->dev, - "%s: Link may change" - "when suspend\n", - atl1e_driver_name); + netdev_dbg(adapter->netdev, + "Link may change when suspend\n"); } wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; /* only link up can wake up */ if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) { - dev_dbg(&pdev->dev, "%s: read write phy " - "register failed.\n", - atl1e_driver_name); + netdev_dbg(adapter->netdev, + "read write phy register failed\n"); goto wol_dis; } } @@ -2131,9 +2115,8 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) if (wufc & AT_WUFC_MAG) mac_ctrl_data |= MAC_CTRL_BC_EN; - dev_dbg(&pdev->dev, - "%s: suspend MAC=0x%x\n", - atl1e_driver_name, mac_ctrl_data); + netdev_dbg(adapter->netdev, "suspend MAC=0x%x\n", + mac_ctrl_data); AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); @@ -2183,8 +2166,8 @@ static int atl1e_resume(struct pci_dev *pdev) err = pci_enable_device(pdev); if (err) { - dev_err(&pdev->dev, "ATL1e: Cannot enable PCI" - " device from suspend\n"); + netdev_err(adapter->netdev, + "Cannot enable PCI device from suspend\n"); return err; } @@ -2315,7 +2298,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, err = atl1e_init_netdev(netdev, pdev); if (err) { - dev_err(&pdev->dev, "init netdevice failed\n"); + netdev_err(netdev, "init netdevice failed\n"); goto err_init_netdev; } adapter = netdev_priv(netdev); @@ -2326,7 +2309,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0); if (!adapter->hw.hw_addr) { err = -EIO; - dev_err(&pdev->dev, "cannot map device registers\n"); + netdev_err(netdev, "cannot map device registers\n"); goto err_ioremap; } netdev->base_addr = (unsigned long)adapter->hw.hw_addr; @@ -2356,7 +2339,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, /* setup the private structure */ err = atl1e_sw_init(adapter); if (err) { - dev_err(&pdev->dev, "net device private data init failed\n"); + netdev_err(netdev, "net device private data init failed\n"); goto err_sw_init; } @@ -2372,19 +2355,19 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, if (atl1e_read_mac_addr(&adapter->hw) != 0) { err = -EIO; - dev_err(&pdev->dev, "get mac address failed\n"); + netdev_err(netdev, "get mac address failed\n"); goto err_eeprom; } memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len); - dev_dbg(&pdev->dev, "mac address : %pM\n", adapter->hw.mac_addr); + netdev_dbg(netdev, "mac address : %pM\n", adapter->hw.mac_addr); INIT_WORK(&adapter->reset_task, atl1e_reset_task); INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task); err = register_netdev(netdev); if (err) { - dev_err(&pdev->dev, "register netdevice failed\n"); + netdev_err(netdev, "register netdevice failed\n"); goto err_register; } @@ -2485,8 +2468,8 @@ static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev) struct atl1e_adapter *adapter = netdev_priv(netdev); if (pci_enable_device(pdev)) { - dev_err(&pdev->dev, - "ATL1e: Cannot re-enable PCI device after reset.\n"); + netdev_err(adapter->netdev, + "Cannot re-enable PCI device after reset\n"); return PCI_ERS_RESULT_DISCONNECT; } pci_set_master(pdev); @@ -2514,8 +2497,8 @@ static void atl1e_io_resume(struct pci_dev *pdev) if (netif_running(netdev)) { if (atl1e_up(adapter)) { - dev_err(&pdev->dev, - "ATL1e: can't bring device back up after reset\n"); + netdev_err(adapter->netdev, + "can't bring device back up after reset\n"); return; } } diff --git a/drivers/net/atl1e/atl1e_param.c b/drivers/net/atl1e/atl1e_param.c index b3be59fd3fb5..0ce60b6e7ef0 100644 --- a/drivers/net/atl1e/atl1e_param.c +++ b/drivers/net/atl1e/atl1e_param.c @@ -116,7 +116,7 @@ struct atl1e_option { } arg; }; -static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct pci_dev *pdev) +static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter) { if (*value == OPTION_UNSET) { *value = opt->def; @@ -127,16 +127,19 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, case enable_option: switch (*value) { case OPTION_ENABLED: - dev_info(&pdev->dev, "%s Enabled\n", opt->name); + netdev_info(adapter->netdev, + "%s Enabled\n", opt->name); return 0; case OPTION_DISABLED: - dev_info(&pdev->dev, "%s Disabled\n", opt->name); + netdev_info(adapter->netdev, + "%s Disabled\n", opt->name); return 0; } break; case range_option: if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - dev_info(&pdev->dev, "%s set to %i\n", opt->name, *value); + netdev_info(adapter->netdev, "%s set to %i\n", + opt->name, *value); return 0; } break; @@ -148,8 +151,8 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, ent = &opt->arg.l.p[i]; if (*value == ent->i) { if (ent->str[0] != '\0') - dev_info(&pdev->dev, "%s\n", - ent->str); + netdev_info(adapter->netdev, + "%s\n", ent->str); return 0; } } @@ -159,8 +162,8 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, BUG(); } - dev_info(&pdev->dev, "Invalid %s specified (%i) %s\n", - opt->name, *value, opt->err); + netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n", + opt->name, *value, opt->err); *value = opt->def; return -1; } @@ -176,11 +179,13 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, */ void __devinit atl1e_check_options(struct atl1e_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; int bd = adapter->bd_number; + if (bd >= ATL1E_MAX_NIC) { - dev_notice(&pdev->dev, "no configuration for board #%i\n", bd); - dev_notice(&pdev->dev, "Using defaults for all values\n"); + netdev_notice(adapter->netdev, + "no configuration for board #%i\n", bd); + netdev_notice(adapter->netdev, + "Using defaults for all values\n"); } { /* Transmit Ring Size */ @@ -196,7 +201,7 @@ void __devinit atl1e_check_options(struct atl1e_adapter *adapter) int val; if (num_tx_desc_cnt > bd) { val = tx_desc_cnt[bd]; - atl1e_validate_option(&val, &opt, pdev); + atl1e_validate_option(&val, &opt, adapter); adapter->tx_ring.count = (u16) val & 0xFFFC; } else adapter->tx_ring.count = (u16)opt.def; @@ -215,7 +220,7 @@ void __devinit atl1e_check_options(struct atl1e_adapter *adapter) int val; if (num_rx_mem_size > bd) { val = rx_mem_size[bd]; - atl1e_validate_option(&val, &opt, pdev); + atl1e_validate_option(&val, &opt, adapter); adapter->rx_ring.page_size = (u32)val * 1024; } else { adapter->rx_ring.page_size = (u32)opt.def * 1024; @@ -235,7 +240,7 @@ void __devinit atl1e_check_options(struct atl1e_adapter *adapter) int val; if (num_int_mod_timer > bd) { val = int_mod_timer[bd]; - atl1e_validate_option(&val, &opt, pdev); + atl1e_validate_option(&val, &opt, adapter); adapter->hw.imt = (u16) val; } else adapter->hw.imt = (u16)(opt.def); @@ -254,7 +259,7 @@ void __devinit atl1e_check_options(struct atl1e_adapter *adapter) int val; if (num_media_type > bd) { val = media_type[bd]; - atl1e_validate_option(&val, &opt, pdev); + atl1e_validate_option(&val, &opt, adapter); adapter->hw.media_type = (u16) val; } else adapter->hw.media_type = (u16)(opt.def); -- cgit v1.2.3 From b3d95c5c93d4b57eaea0ad3f582b08a6b5fb3eb1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:49 +0000 Subject: include/linux/netdevice.h: Add netif_printk helpers Add macros to test a private structure for msg_enable bits and the netif_msg_##bit to test and call netdev_printk if set Simplifies logic in callers and adds message logging consistency Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/linux/netdevice.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a51228ac9331..1412dde16d00 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2165,6 +2165,59 @@ do { \ #define netdev_WARN(dev, format, args...) \ WARN(1, "netdevice: %s\n" format, netdev_name(dev), ##args); +/* netif printk helpers, similar to netdev_printk */ + +#define netif_printk(priv, type, level, dev, fmt, args...) \ +do { \ + if (netif_msg_##type(priv)) \ + netdev_printk(level, (dev), fmt, ##args); \ +} while (0) + +#define netif_emerg(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_EMERG, dev, fmt, ##args) +#define netif_alert(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_ALERT, dev, fmt, ##args) +#define netif_crit(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_CRIT, dev, fmt, ##args) +#define netif_err(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_ERR, dev, fmt, ##args) +#define netif_warn(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_WARNING, dev, fmt, ##args) +#define netif_notice(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_NOTICE, dev, fmt, ##args) +#define netif_info(priv, type, dev, fmt, args...) \ + netif_printk(priv, type, KERN_INFO, (dev), fmt, ##args) + +#if defined(DEBUG) +#define netif_dbg(priv, type, dev, format, args...) \ + netif_printk(priv, type, KERN_DEBUG, dev, format, ##args) +#elif defined(CONFIG_DYNAMIC_DEBUG) +#define netif_dbg(priv, type, netdev, format, args...) \ +do { \ + if (netif_msg_##type(priv)) \ + dynamic_dev_dbg((netdev)->dev.parent, \ + "%s: " format, \ + netdev_name(netdev), ##args); \ +} while (0) +#else +#define netif_dbg(priv, type, dev, format, args...) \ +({ \ + if (0) \ + netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \ + 0; \ +}) +#endif + +#if defined(VERBOSE_DEBUG) +#define netif_vdbg netdev_dbg +#else +#define netif_vdbg(priv, type, dev, format, args...) \ +({ \ + if (0) \ + netif_printk(KERN_DEBUG, dev, format, ##args); \ + 0; \ +}) +#endif #endif /* __KERNEL__ */ -- cgit v1.2.3 From bf82c189a92f06967cf790d3ab0fc9827a9d00ff Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:50 +0000 Subject: drivers/net/r8196.c: Use netif_printk macros Simplify the logic a bit, make the message logs a bit more consistent. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/r8169.c | 136 +++++++++++++++++++--------------------------------- 1 file changed, 48 insertions(+), 88 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 85c635f354b5..616ae5aa66aa 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -744,12 +744,10 @@ static void rtl8169_check_link_status(struct net_device *dev, spin_lock_irqsave(&tp->lock, flags); if (tp->link_ok(ioaddr)) { netif_carrier_on(dev); - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); + netif_info(tp, ifup, dev, "link up\n"); } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); netif_carrier_off(dev); + netif_info(tp, ifdown, dev, "link down\n"); } spin_unlock_irqrestore(&tp->lock, flags); } @@ -862,11 +860,8 @@ static int rtl8169_set_speed_tbi(struct net_device *dev, } else if (autoneg == AUTONEG_ENABLE) RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); else { - if (netif_msg_link(tp)) { - printk(KERN_WARNING "%s: " - "incorrect speed setting refused in TBI mode\n", - dev->name); - } + netif_warn(tp, link, dev, + "incorrect speed setting refused in TBI mode\n"); ret = -EOPNOTSUPP; } @@ -901,9 +896,9 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, (tp->mac_version != RTL_GIGA_MAC_VER_15) && (tp->mac_version != RTL_GIGA_MAC_VER_16)) { giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; - } else if (netif_msg_link(tp)) { - printk(KERN_INFO "%s: PHY does not support 1000Mbps.\n", - dev->name); + } else { + netif_info(tp, link, dev, + "PHY does not support 1000Mbps\n"); } bmcr = BMCR_ANENABLE | BMCR_ANRESTART; @@ -2705,8 +2700,7 @@ static void rtl8169_phy_timer(unsigned long __opaque) if (tp->link_ok(ioaddr)) goto out_unlock; - if (netif_msg_link(tp)) - printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name); + netif_warn(tp, link, dev, "PHY reset until link up\n"); tp->phy_reset_enable(ioaddr); @@ -2776,8 +2770,7 @@ static void rtl8169_phy_reset(struct net_device *dev, return; msleep(1); } - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); + netif_err(tp, link, dev, "PHY reset failed\n"); } static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) @@ -2811,8 +2804,8 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) */ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL); - if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name); + if (RTL_R8(PHYstatus) & TBI_Enable) + netif_info(tp, link, dev, "TBI auto-negotiating\n"); } static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) @@ -3012,8 +3005,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pci_enable_device(pdev); if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); + netif_err(tp, probe, dev, "enable failure\n"); goto err_out_free_dev_1; } @@ -3023,29 +3015,24 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* make sure PCI base addr 1 is MMIO */ if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "region #%d not an MMIO resource, aborting\n", - region); - } + netif_err(tp, probe, dev, + "region #%d not an MMIO resource, aborting\n", + region); rc = -ENODEV; goto err_out_mwi_3; } /* check for weird/broken PCI region reporting */ if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "Invalid PCI region size(s), aborting\n"); - } + netif_err(tp, probe, dev, + "Invalid PCI region size(s), aborting\n"); rc = -ENODEV; goto err_out_mwi_3; } rc = pci_request_regions(pdev, MODULENAME); if (rc < 0) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); + netif_err(tp, probe, dev, "could not request regions\n"); goto err_out_mwi_3; } @@ -3058,10 +3045,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } else { rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc < 0) { - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, - "DMA configuration failed.\n"); - } + netif_err(tp, probe, dev, "DMA configuration failed\n"); goto err_out_free_res_4; } } @@ -3069,15 +3053,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* ioremap MMIO region */ ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); if (!ioaddr) { - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); + netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); rc = -EIO; goto err_out_free_res_4; } tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap && netif_msg_probe(tp)) - dev_info(&pdev->dev, "no PCI Express capability\n"); + if (!tp->pcie_cap) + netif_info(tp, probe, dev, "no PCI Express capability\n"); RTL_W16(IntrMask, 0x0000); @@ -3100,10 +3083,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Use appropriate default if unknown */ if (tp->mac_version == RTL_GIGA_MAC_NONE) { - if (netif_msg_probe(tp)) { - dev_notice(&pdev->dev, - "unknown MAC, using family default\n"); - } + netif_notice(tp, probe, dev, + "unknown MAC, using family default\n"); tp->mac_version = cfg->default_ver; } @@ -3185,14 +3166,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, dev); - if (netif_msg_probe(tp)) { - u32 xid = RTL_R32(TxConfig) & 0x9cf0f8ff; - - printk(KERN_INFO "%s: %s at 0x%lx, %pM, XID %08x IRQ %d\n", - dev->name, - rtl_chip_info[tp->chipset].name, - dev->base_addr, dev->dev_addr, xid, dev->irq); - } + netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", + rtl_chip_info[tp->chipset].name, + dev->base_addr, dev->dev_addr, + (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); rtl8169_init_phy(dev, tp); @@ -4131,10 +4108,10 @@ static void rtl8169_reinit_task(struct work_struct *work) ret = rtl8169_open(dev); if (unlikely(ret < 0)) { - if (net_ratelimit() && netif_msg_drv(tp)) { - printk(KERN_ERR PFX "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } + if (net_ratelimit()) + netif_err(tp, drv, dev, + "reinit failure (status = %d). Rescheduling\n", + ret); rtl8169_schedule_work(dev, rtl8169_reinit_task); } @@ -4164,10 +4141,8 @@ static void rtl8169_reset_task(struct work_struct *work) netif_wake_queue(dev); rtl8169_check_link_status(dev, tp, tp->mmio_addr); } else { - if (net_ratelimit() && netif_msg_intr(tp)) { - printk(KERN_EMERG PFX "%s: Rx buffers shortage\n", - dev->name); - } + if (net_ratelimit()) + netif_emerg(tp, intr, dev, "Rx buffers shortage\n"); rtl8169_schedule_work(dev, rtl8169_reset_task); } @@ -4255,11 +4230,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, u32 opts1; if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } + netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); goto err_stop; } @@ -4321,11 +4292,8 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); pci_read_config_word(pdev, PCI_STATUS, &pci_status); - if (netif_msg_intr(tp)) { - printk(KERN_ERR - "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n", - dev->name, pci_cmd, pci_status); - } + netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", + pci_cmd, pci_status); /* * The recovery sequence below admits a very elaborated explanation: @@ -4349,8 +4317,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) /* The infamous DAC f*ckup only happens at boot time */ if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) { - if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name); + netif_info(tp, intr, dev, "disabling PCI DAC\n"); tp->cp_cmd &= ~PCIDAC; RTL_W16(CPlusCmd, tp->cp_cmd); dev->features &= ~NETIF_F_HIGHDMA; @@ -4477,11 +4444,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev, if (status & DescOwn) break; if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } + netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", + status); dev->stats.rx_errors++; if (status & (RxRWT | RxRUNT)) dev->stats.rx_length_errors++; @@ -4544,8 +4508,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev, tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + if (!delta && count) + netif_info(tp, intr, dev, "no Rx buffer allocated\n"); tp->dirty_rx += delta; /* @@ -4555,8 +4519,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev, * after refill ? * - how do others driver handle this condition (Uh oh...). */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) + netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); return count; } @@ -4611,10 +4575,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) if (likely(napi_schedule_prep(&tp->napi))) __napi_schedule(&tp->napi); - else if (netif_msg_intr(tp)) { - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } + else + netif_info(tp, intr, dev, + "interrupt %04x in poll\n", status); } /* We only get a new MSI interrupt when all active irq @@ -4750,10 +4713,7 @@ static void rtl_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) { - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - } + netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys; -- cgit v1.2.3 From f8502ce4f986a8fd486302980285b5e786b8dabe Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:51 +0000 Subject: drivers/net/jme: Use netif_printk helpers Convert uses of msg_ to netif_( Remove msg_ macros Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/jme.c | 54 +++++++++++++++++++++++++++--------------------------- drivers/net/jme.h | 41 +++++++---------------------------------- 2 files changed, 34 insertions(+), 61 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index d44c39dfbef1..558b6a0b15fc 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -288,7 +288,7 @@ jme_set_rx_pcc(struct jme_adapter *jme, int p) wmb(); if (!(test_bit(JME_FLAG_POLL, &jme->flags))) - msg_rx_status(jme, "Switched to PCC_P%d\n", p); + netif_info(jme, rx_status, jme->dev, "Switched to PCC_P%d\n", p); } static void @@ -483,13 +483,13 @@ jme_check_link(struct net_device *netdev, int testonly) strcat(linkmsg, (phylink & PHY_LINK_MDI_STAT) ? "MDI-X" : "MDI"); - msg_link(jme, "Link is up at %s.\n", linkmsg); + netif_info(jme, link, jme->dev, "Link is up at %s.\n", linkmsg); netif_carrier_on(netdev); } else { if (testonly) goto out; - msg_link(jme, "Link is down.\n"); + netif_info(jme, link, jme->dev, "Link is down.\n"); jme->phylink = 0; netif_carrier_off(netdev); } @@ -883,20 +883,20 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags) if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_TCPON | RXWBFLAG_TCPCS)) == RXWBFLAG_TCPON)) { if (flags & RXWBFLAG_IPV4) - msg_rx_err(jme, "TCP Checksum error\n"); + netif_err(jme, rx_err, jme->dev, "TCP Checksum error\n"); return false; } if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS)) == RXWBFLAG_UDPON)) { if (flags & RXWBFLAG_IPV4) - msg_rx_err(jme, "UDP Checksum error.\n"); + netif_err(jme, rx_err, jme->dev, "UDP Checksum error.\n"); return false; } if (unlikely((flags & (RXWBFLAG_IPV4 | RXWBFLAG_IPCS)) == RXWBFLAG_IPV4)) { - msg_rx_err(jme, "IPv4 Checksum error.\n"); + netif_err(jme, rx_err, jme->dev, "IPv4 Checksum error.\n"); return false; } @@ -1186,9 +1186,9 @@ jme_link_change_tasklet(unsigned long arg) while (!atomic_dec_and_test(&jme->link_changing)) { atomic_inc(&jme->link_changing); - msg_intr(jme, "Get link change lock failed.\n"); + netif_info(jme, intr, jme->dev, "Get link change lock failed.\n"); while (atomic_read(&jme->link_changing) != 1) - msg_intr(jme, "Waiting link change lock.\n"); + netif_info(jme, intr, jme->dev, "Waiting link change lock.\n"); } if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) @@ -1305,7 +1305,7 @@ jme_rx_empty_tasklet(unsigned long arg) if (unlikely(!netif_carrier_ok(jme->dev))) return; - msg_rx_status(jme, "RX Queue Full!\n"); + netif_info(jme, rx_status, jme->dev, "RX Queue Full!\n"); jme_rx_clean_tasklet(arg); @@ -1325,7 +1325,7 @@ jme_wake_queue_if_stopped(struct jme_adapter *jme) smp_wmb(); if (unlikely(netif_queue_stopped(jme->dev) && atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold))) { - msg_tx_done(jme, "TX Queue Waked.\n"); + netif_info(jme, tx_done, jme->dev, "TX Queue Waked.\n"); netif_wake_queue(jme->dev); } @@ -1835,7 +1835,7 @@ jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) *flags |= TXFLAG_UDPCS; break; default: - msg_tx_err(jme, "Error upper layer protocol.\n"); + netif_err(jme, tx_err, jme->dev, "Error upper layer protocol.\n"); break; } } @@ -1910,12 +1910,12 @@ jme_stop_queue_if_full(struct jme_adapter *jme) smp_wmb(); if (unlikely(atomic_read(&txring->nr_free) < (MAX_SKB_FRAGS+2))) { netif_stop_queue(jme->dev); - msg_tx_queued(jme, "TX Queue Paused.\n"); + netif_info(jme, tx_queued, jme->dev, "TX Queue Paused.\n"); smp_wmb(); if (atomic_read(&txring->nr_free) >= (jme->tx_wake_threshold)) { netif_wake_queue(jme->dev); - msg_tx_queued(jme, "TX Queue Fast Waked.\n"); + netif_info(jme, tx_queued, jme->dev, "TX Queue Fast Waked.\n"); } } @@ -1923,7 +1923,7 @@ jme_stop_queue_if_full(struct jme_adapter *jme) (jiffies - txbi->start_xmit) >= TX_TIMEOUT && txbi->skb)) { netif_stop_queue(jme->dev); - msg_tx_queued(jme, "TX Queue Stopped %d@%lu.\n", idx, jiffies); + netif_info(jme, tx_queued, jme->dev, "TX Queue Stopped %d@%lu.\n", idx, jiffies); } } @@ -1946,7 +1946,7 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) if (unlikely(idx < 0)) { netif_stop_queue(netdev); - msg_tx_err(jme, "BUG! Tx ring full when queue awake!\n"); + netif_err(jme, tx_err, jme->dev, "BUG! Tx ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -2473,7 +2473,7 @@ jme_smb_read(struct jme_adapter *jme, unsigned int addr) val = jread32(jme, JME_SMBCSR); } if (!to) { - msg_hw(jme, "SMB Bus Busy.\n"); + netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n"); return 0xFF; } @@ -2489,7 +2489,7 @@ jme_smb_read(struct jme_adapter *jme, unsigned int addr) val = jread32(jme, JME_SMBINTF); } if (!to) { - msg_hw(jme, "SMB Bus Busy.\n"); + netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n"); return 0xFF; } @@ -2509,7 +2509,7 @@ jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data) val = jread32(jme, JME_SMBCSR); } if (!to) { - msg_hw(jme, "SMB Bus Busy.\n"); + netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n"); return; } @@ -2526,7 +2526,7 @@ jme_smb_write(struct jme_adapter *jme, unsigned int addr, u8 data) val = jread32(jme, JME_SMBINTF); } if (!to) { - msg_hw(jme, "SMB Bus Busy.\n"); + netif_err(jme, hw, jme->dev, "SMB Bus Busy.\n"); return; } @@ -2876,14 +2876,14 @@ jme_init_one(struct pci_dev *pdev, goto err_out_unmap; } - msg_probe(jme, "%s%s ver:%x rev:%x macaddr:%pM\n", - (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? - "JMC250 Gigabit Ethernet" : - (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? - "JMC260 Fast Ethernet" : "Unknown", - (jme->fpgaver != 0) ? " (FPGA)" : "", - (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, - jme->rev, netdev->dev_addr); + netif_info(jme, probe, jme->dev, "%s%s ver:%x rev:%x macaddr:%pM\n", + (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? + "JMC250 Gigabit Ethernet" : + (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? + "JMC260 Fast Ethernet" : "Unknown", + (jme->fpgaver != 0) ? " (FPGA)" : "", + (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, + jme->rev, netdev->dev_addr); return 0; diff --git a/drivers/net/jme.h b/drivers/net/jme.h index 251abed3817e..c19db9146a2f 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -45,43 +45,16 @@ printk(KERN_ERR PFX fmt, ## args) #ifdef TX_DEBUG -#define tx_dbg(priv, fmt, args...) \ - printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ## args) +#define tx_dbg(priv, fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args) #else -#define tx_dbg(priv, fmt, args...) +#define tx_dbg(priv, fmt, args...) \ +do { \ + if (0) \ + printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args); \ +} while (0) #endif -#define jme_msg(msglvl, type, priv, fmt, args...) \ - if (netif_msg_##type(priv)) \ - printk(msglvl "%s: " fmt, (priv)->dev->name, ## args) - -#define msg_probe(priv, fmt, args...) \ - jme_msg(KERN_INFO, probe, priv, fmt, ## args) - -#define msg_link(priv, fmt, args...) \ - jme_msg(KERN_INFO, link, priv, fmt, ## args) - -#define msg_intr(priv, fmt, args...) \ - jme_msg(KERN_INFO, intr, priv, fmt, ## args) - -#define msg_rx_err(priv, fmt, args...) \ - jme_msg(KERN_ERR, rx_err, priv, fmt, ## args) - -#define msg_rx_status(priv, fmt, args...) \ - jme_msg(KERN_INFO, rx_status, priv, fmt, ## args) - -#define msg_tx_err(priv, fmt, args...) \ - jme_msg(KERN_ERR, tx_err, priv, fmt, ## args) - -#define msg_tx_done(priv, fmt, args...) \ - jme_msg(KERN_INFO, tx_done, priv, fmt, ## args) - -#define msg_tx_queued(priv, fmt, args...) \ - jme_msg(KERN_INFO, tx_queued, priv, fmt, ## args) - -#define msg_hw(priv, fmt, args...) \ - jme_msg(KERN_ERR, hw, priv, fmt, ## args) - /* * Extra PCI Configuration space interface */ -- cgit v1.2.3 From ae9540f75d5a69e7604cc5391cc0726b3aa82ff6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:52 +0000 Subject: drivers/net/qlge: Use netif_printk helpers Convert QPRINTK macros to netif_ equivalents. Expands and standardizes the logging message output. Removes __func__ from most logging messages. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 8 - drivers/net/qlge/qlge_dbg.c | 58 +-- drivers/net/qlge/qlge_ethtool.c | 49 +-- drivers/net/qlge/qlge_main.c | 841 +++++++++++++++++++++------------------- drivers/net/qlge/qlge_mpi.c | 183 +++++---- 5 files changed, 580 insertions(+), 559 deletions(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index ebfd17776b53..57d135e3bfaf 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -19,14 +19,6 @@ #define DRV_VERSION "v1.00.00.23.00.00-01" #define PFX "qlge: " -#define QPRINTK(qdev, nlevel, klevel, fmt, args...) \ - do { \ - if (!((qdev)->msg_enable & NETIF_MSG_##nlevel)) \ - ; \ - else \ - dev_printk(KERN_##klevel, &((qdev)->pdev->dev), \ - "%s: " fmt, __func__, ##args); \ - } while (0) #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 57df835147eb..ff8550d2ca82 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c @@ -443,8 +443,8 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf) status = ql_get_mac_addr_reg(qdev, MAC_ADDR_TYPE_CAM_MAC, i, value); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed read of mac index register.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed read of mac index register.\n"); goto err; } *buf++ = value[0]; /* lower MAC address */ @@ -455,8 +455,8 @@ static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf) status = ql_get_mac_addr_reg(qdev, MAC_ADDR_TYPE_MULTI_MAC, i, value); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed read of mac index register.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed read of mac index register.\n"); goto err; } *buf++ = value[0]; /* lower Mcast address */ @@ -479,8 +479,8 @@ static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf) for (i = 0; i < 16; i++) { status = ql_get_routing_reg(qdev, i, &value); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed read of routing index register.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed read of routing index register.\n"); goto err; } else { *buf++ = value; @@ -736,8 +736,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) int i; if (!mpi_coredump) { - QPRINTK(qdev, DRV, ERR, - "No memory available.\n"); + netif_err(qdev, drv, qdev->ndev, "No memory available.\n"); return -ENOMEM; } @@ -749,8 +748,8 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) status = ql_pause_mpi_risc(qdev); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed RISC pause. Status = 0x%.08x\n", status); + netif_err(qdev, drv, qdev->ndev, + "Failed RISC pause. Status = 0x%.08x\n", status); goto err; } @@ -911,9 +910,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) status = ql_get_serdes_regs(qdev, mpi_coredump); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed Dump of Serdes Registers. Status = 0x%.08x\n", - status); + netif_err(qdev, drv, qdev->ndev, + "Failed Dump of Serdes Registers. Status = 0x%.08x\n", + status); goto err; } @@ -1177,16 +1176,16 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) /* clear the pause */ status = ql_unpause_mpi_risc(qdev); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed RISC unpause. Status = 0x%.08x\n", status); + netif_err(qdev, drv, qdev->ndev, + "Failed RISC unpause. Status = 0x%.08x\n", status); goto err; } /* Reset the RISC so we can dump RAM */ status = ql_hard_reset_mpi_risc(qdev); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed RISC reset. Status = 0x%.08x\n", status); + netif_err(qdev, drv, qdev->ndev, + "Failed RISC reset. Status = 0x%.08x\n", status); goto err; } @@ -1198,8 +1197,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) status = ql_dump_risc_ram_area(qdev, &mpi_coredump->code_ram[0], CODE_RAM_ADDR, CODE_RAM_CNT); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed Dump of CODE RAM. Status = 0x%.08x\n", status); + netif_err(qdev, drv, qdev->ndev, + "Failed Dump of CODE RAM. Status = 0x%.08x\n", + status); goto err; } @@ -1212,8 +1212,9 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump) status = ql_dump_risc_ram_area(qdev, &mpi_coredump->memc_ram[0], MEMC_RAM_ADDR, MEMC_RAM_CNT); if (status) { - QPRINTK(qdev, DRV, ERR, - "Failed Dump of MEMC RAM. Status = 0x%.08x\n", status); + netif_err(qdev, drv, qdev->ndev, + "Failed Dump of MEMC RAM. Status = 0x%.08x\n", + status); goto err; } err: @@ -1225,21 +1226,19 @@ err: static void ql_get_core_dump(struct ql_adapter *qdev) { if (!ql_own_firmware(qdev)) { - QPRINTK(qdev, DRV, ERR, "%s: Don't own firmware!\n", - qdev->ndev->name); + netif_err(qdev, drv, qdev->ndev, "Don't own firmware!\n"); return; } if (!netif_running(qdev->ndev)) { - QPRINTK(qdev, IFUP, ERR, - "Force Coredump can only be done from interface " - "that is up.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Force Coredump can only be done from interface that is up.\n"); return; } if (ql_mb_sys_err(qdev)) { - QPRINTK(qdev, IFUP, ERR, - "Fail force coredump with ql_mb_sys_err().\n"); + netif_err(qdev, ifup, qdev->ndev, + "Fail force coredump with ql_mb_sys_err().\n"); return; } } @@ -1334,7 +1333,8 @@ void ql_mpi_core_to_log(struct work_struct *work) count = sizeof(struct ql_mpi_coredump) / sizeof(u32); tmp = (u32 *)qdev->mpi_coredump; - QPRINTK(qdev, DRV, DEBUG, "Core is dumping to log file!\n"); + netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, + "Core is dumping to log file!\n"); for (i = 0; i < count; i += 8) { printk(KERN_ERR "%.08x: %.08x %.08x %.08x %.08x %.08x " diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 058fa0a48c6f..4f26afeb0f38 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -67,8 +67,8 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to load CQICB.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to load CQICB.\n"); goto exit; } } @@ -89,8 +89,8 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb), CFG_LCQ, rx_ring->cq_id); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to load CQICB.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to load CQICB.\n"); goto exit; } } @@ -107,8 +107,8 @@ static void ql_update_stats(struct ql_adapter *qdev) spin_lock(&qdev->stats_lock); if (ql_sem_spinlock(qdev, qdev->xg_sem_mask)) { - QPRINTK(qdev, DRV, ERR, - "Couldn't get xgmac sem.\n"); + netif_err(qdev, drv, qdev->ndev, + "Couldn't get xgmac sem.\n"); goto quit; } /* @@ -116,8 +116,9 @@ static void ql_update_stats(struct ql_adapter *qdev) */ for (i = 0x200; i < 0x280; i += 8) { if (ql_read_xgmac_reg64(qdev, i, &data)) { - QPRINTK(qdev, DRV, ERR, - "Error reading status register 0x%.04x.\n", i); + netif_err(qdev, drv, qdev->ndev, + "Error reading status register 0x%.04x.\n", + i); goto end; } else *iter = data; @@ -129,8 +130,9 @@ static void ql_update_stats(struct ql_adapter *qdev) */ for (i = 0x300; i < 0x3d0; i += 8) { if (ql_read_xgmac_reg64(qdev, i, &data)) { - QPRINTK(qdev, DRV, ERR, - "Error reading status register 0x%.04x.\n", i); + netif_err(qdev, drv, qdev->ndev, + "Error reading status register 0x%.04x.\n", + i); goto end; } else *iter = data; @@ -142,8 +144,9 @@ static void ql_update_stats(struct ql_adapter *qdev) */ for (i = 0x500; i < 0x540; i += 8) { if (ql_read_xgmac_reg64(qdev, i, &data)) { - QPRINTK(qdev, DRV, ERR, - "Error reading status register 0x%.04x.\n", i); + netif_err(qdev, drv, qdev->ndev, + "Error reading status register 0x%.04x.\n", + i); goto end; } else *iter = data; @@ -155,8 +158,9 @@ static void ql_update_stats(struct ql_adapter *qdev) */ for (i = 0x568; i < 0x5a8; i += 8) { if (ql_read_xgmac_reg64(qdev, i, &data)) { - QPRINTK(qdev, DRV, ERR, - "Error reading status register 0x%.04x.\n", i); + netif_err(qdev, drv, qdev->ndev, + "Error reading status register 0x%.04x.\n", + i); goto end; } else *iter = data; @@ -167,8 +171,8 @@ static void ql_update_stats(struct ql_adapter *qdev) * Get RX NIC FIFO DROP statistics. */ if (ql_read_xgmac_reg64(qdev, 0x5b8, &data)) { - QPRINTK(qdev, DRV, ERR, - "Error reading status register 0x%.04x.\n", i); + netif_err(qdev, drv, qdev->ndev, + "Error reading status register 0x%.04x.\n", i); goto end; } else *iter = data; @@ -396,14 +400,13 @@ static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) return -EINVAL; qdev->wol = wol->wolopts; - QPRINTK(qdev, DRV, INFO, "Set wol option 0x%x on %s\n", - qdev->wol, ndev->name); + netif_info(qdev, drv, qdev->ndev, "Set wol option 0x%x\n", qdev->wol); if (!qdev->wol) { u32 wol = 0; status = ql_mb_wol_mode(qdev, wol); - QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n", - (status == 0) ? "cleared sucessfully" : "clear failed", - wol, qdev->ndev->name); + netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x)\n", + status == 0 ? "cleared sucessfully" : "clear failed", + wol); } return 0; @@ -534,8 +537,8 @@ static void ql_self_test(struct net_device *ndev, } clear_bit(QL_SELFTEST, &qdev->flags); } else { - QPRINTK(qdev, DRV, ERR, - "%s: is down, Loopback test will fail.\n", ndev->name); + netif_err(qdev, drv, qdev->ndev, + "is down, Loopback test will fail.\n"); eth_test->flags |= ETH_TEST_FL_FAILED; } } diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index dd3e0f1b2965..2c052caee884 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -128,7 +128,7 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask) sem_bits = SEM_SET << SEM_PROC_REG_SHIFT; break; default: - QPRINTK(qdev, PROBE, ALERT, "Bad Semaphore mask!.\n"); + netif_alert(qdev, probe, qdev->ndev, "bad Semaphore mask!.\n"); return -EINVAL; } @@ -168,17 +168,17 @@ int ql_wait_reg_rdy(struct ql_adapter *qdev, u32 reg, u32 bit, u32 err_bit) /* check for errors */ if (temp & err_bit) { - QPRINTK(qdev, PROBE, ALERT, - "register 0x%.08x access error, value = 0x%.08x!.\n", - reg, temp); + netif_alert(qdev, probe, qdev->ndev, + "register 0x%.08x access error, value = 0x%.08x!.\n", + reg, temp); return -EIO; } else if (temp & bit) return 0; udelay(UDELAY_DELAY); count--; } - QPRINTK(qdev, PROBE, ALERT, - "Timed out waiting for reg %x to come ready.\n", reg); + netif_alert(qdev, probe, qdev->ndev, + "Timed out waiting for reg %x to come ready.\n", reg); return -ETIMEDOUT; } @@ -221,7 +221,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, map = pci_map_single(qdev->pdev, ptr, size, direction); if (pci_dma_mapping_error(qdev->pdev, map)) { - QPRINTK(qdev, IFUP, ERR, "Couldn't map DMA area.\n"); + netif_err(qdev, ifup, qdev->ndev, "Couldn't map DMA area.\n"); return -ENOMEM; } @@ -231,8 +231,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit, status = ql_wait_cfg(qdev, bit); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Timed out waiting for CFG to come ready.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Timed out waiting for CFG to come ready.\n"); goto exit; } @@ -313,8 +313,8 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, case MAC_ADDR_TYPE_VLAN: case MAC_ADDR_TYPE_MULTI_FLTR: default: - QPRINTK(qdev, IFUP, CRIT, - "Address type %d not yet supported.\n", type); + netif_crit(qdev, ifup, qdev->ndev, + "Address type %d not yet supported.\n", type); status = -EPERM; } exit: @@ -371,12 +371,11 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | (addr[5]); - QPRINTK(qdev, IFUP, DEBUG, - "Adding %s address %pM" - " at index %d in the CAM.\n", - ((type == - MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" : - "UNICAST"), addr, index); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Adding %s address %pM at index %d in the CAM.\n", + type == MAC_ADDR_TYPE_MULTI_MAC ? + "MULTICAST" : "UNICAST", + addr, index); status = ql_wait_reg_rdy(qdev, @@ -426,9 +425,11 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, * addressing. It's either MAC_ADDR_E on or off. * That's bit-27 we're talking about. */ - QPRINTK(qdev, IFUP, INFO, "%s VLAN ID %d %s the CAM.\n", - (enable_bit ? "Adding" : "Removing"), - index, (enable_bit ? "to" : "from")); + netif_info(qdev, ifup, qdev->ndev, + "%s VLAN ID %d %s the CAM.\n", + enable_bit ? "Adding" : "Removing", + index, + enable_bit ? "to" : "from"); status = ql_wait_reg_rdy(qdev, @@ -443,8 +444,8 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, } case MAC_ADDR_TYPE_MULTI_FLTR: default: - QPRINTK(qdev, IFUP, CRIT, - "Address type %d not yet supported.\n", type); + netif_crit(qdev, ifup, qdev->ndev, + "Address type %d not yet supported.\n", type); status = -EPERM; } exit: @@ -463,14 +464,13 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) if (set) { addr = &qdev->ndev->dev_addr[0]; - QPRINTK(qdev, IFUP, DEBUG, - "Set Mac addr %pM\n", addr); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Set Mac addr %pM\n", addr); } else { memset(zero_mac_addr, 0, ETH_ALEN); addr = &zero_mac_addr[0]; - QPRINTK(qdev, IFUP, DEBUG, - "Clearing MAC address on %s\n", - qdev->ndev->name); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Clearing MAC address\n"); } status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) @@ -479,23 +479,21 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (status) - QPRINTK(qdev, IFUP, ERR, "Failed to init mac " - "address.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init mac address.\n"); return status; } void ql_link_on(struct ql_adapter *qdev) { - QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n", - qdev->ndev->name); + netif_err(qdev, link, qdev->ndev, "Link is up.\n"); netif_carrier_on(qdev->ndev); ql_set_mac_addr(qdev, 1); } void ql_link_off(struct ql_adapter *qdev) { - QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n", - qdev->ndev->name); + netif_err(qdev, link, qdev->ndev, "Link is down.\n"); netif_carrier_off(qdev->ndev); ql_set_mac_addr(qdev, 0); } @@ -532,27 +530,27 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, int status = -EINVAL; /* Return error if no mask match. */ u32 value = 0; - QPRINTK(qdev, IFUP, DEBUG, - "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s mask %s the routing reg.\n", - (enable ? "Adding" : "Removing"), - ((index == RT_IDX_ALL_ERR_SLOT) ? "MAC ERROR/ALL ERROR" : ""), - ((index == RT_IDX_IP_CSUM_ERR_SLOT) ? "IP CSUM ERROR" : ""), - ((index == - RT_IDX_TCP_UDP_CSUM_ERR_SLOT) ? "TCP/UDP CSUM ERROR" : ""), - ((index == RT_IDX_BCAST_SLOT) ? "BROADCAST" : ""), - ((index == RT_IDX_MCAST_MATCH_SLOT) ? "MULTICAST MATCH" : ""), - ((index == RT_IDX_ALLMULTI_SLOT) ? "ALL MULTICAST MATCH" : ""), - ((index == RT_IDX_UNUSED6_SLOT) ? "UNUSED6" : ""), - ((index == RT_IDX_UNUSED7_SLOT) ? "UNUSED7" : ""), - ((index == RT_IDX_RSS_MATCH_SLOT) ? "RSS ALL/IPV4 MATCH" : ""), - ((index == RT_IDX_RSS_IPV6_SLOT) ? "RSS IPV6" : ""), - ((index == RT_IDX_RSS_TCP4_SLOT) ? "RSS TCP4" : ""), - ((index == RT_IDX_RSS_TCP6_SLOT) ? "RSS TCP6" : ""), - ((index == RT_IDX_CAM_HIT_SLOT) ? "CAM HIT" : ""), - ((index == RT_IDX_UNUSED013) ? "UNUSED13" : ""), - ((index == RT_IDX_UNUSED014) ? "UNUSED14" : ""), - ((index == RT_IDX_PROMISCUOUS_SLOT) ? "PROMISCUOUS" : ""), - (enable ? "to" : "from")); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "%s %s mask %s the routing reg.\n", + enable ? "Adding" : "Removing", + index == RT_IDX_ALL_ERR_SLOT ? "MAC ERROR/ALL ERROR" : + index == RT_IDX_IP_CSUM_ERR_SLOT ? "IP CSUM ERROR" : + index == RT_IDX_TCP_UDP_CSUM_ERR_SLOT ? "TCP/UDP CSUM ERROR" : + index == RT_IDX_BCAST_SLOT ? "BROADCAST" : + index == RT_IDX_MCAST_MATCH_SLOT ? "MULTICAST MATCH" : + index == RT_IDX_ALLMULTI_SLOT ? "ALL MULTICAST MATCH" : + index == RT_IDX_UNUSED6_SLOT ? "UNUSED6" : + index == RT_IDX_UNUSED7_SLOT ? "UNUSED7" : + index == RT_IDX_RSS_MATCH_SLOT ? "RSS ALL/IPV4 MATCH" : + index == RT_IDX_RSS_IPV6_SLOT ? "RSS IPV6" : + index == RT_IDX_RSS_TCP4_SLOT ? "RSS TCP4" : + index == RT_IDX_RSS_TCP6_SLOT ? "RSS TCP6" : + index == RT_IDX_CAM_HIT_SLOT ? "CAM HIT" : + index == RT_IDX_UNUSED013 ? "UNUSED13" : + index == RT_IDX_UNUSED014 ? "UNUSED14" : + index == RT_IDX_PROMISCUOUS_SLOT ? "PROMISCUOUS" : + "(Bad index != RT_IDX)", + enable ? "to" : "from"); switch (mask) { case RT_IDX_CAM_HIT: @@ -612,8 +610,8 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, break; } default: - QPRINTK(qdev, IFUP, ERR, "Mask type %d not yet supported.\n", - mask); + netif_err(qdev, ifup, qdev->ndev, + "Mask type %d not yet supported.\n", mask); status = -EPERM; goto exit; } @@ -719,7 +717,7 @@ static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) status = strncmp((char *)&qdev->flash, str, 4); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash signature.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash signature.\n"); return status; } @@ -727,8 +725,8 @@ static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) csum += le16_to_cpu(*flash++); if (csum) - QPRINTK(qdev, IFUP, ERR, - "Invalid flash checksum, csum = 0x%.04x.\n", csum); + netif_err(qdev, ifup, qdev->ndev, + "Invalid flash checksum, csum = 0x%.04x.\n", csum); return csum; } @@ -780,7 +778,8 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) for (i = 0; i < size; i++, p++) { status = ql_read_flash_word(qdev, i+offset, p); if (status) { - QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Error reading flash.\n"); goto exit; } } @@ -789,7 +788,7 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) sizeof(struct flash_params_8000) / sizeof(u16), "8000"); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; goto exit; } @@ -807,7 +806,7 @@ static int ql_get_8000_flash_params(struct ql_adapter *qdev) qdev->ndev->addr_len); if (!is_valid_ether_addr(mac_addr)) { - QPRINTK(qdev, IFUP, ERR, "Invalid MAC address.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid MAC address.\n"); status = -EINVAL; goto exit; } @@ -841,7 +840,8 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) for (i = 0; i < size; i++, p++) { status = ql_read_flash_word(qdev, i+offset, p); if (status) { - QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Error reading flash.\n"); goto exit; } @@ -851,7 +851,7 @@ static int ql_get_8012_flash_params(struct ql_adapter *qdev) sizeof(struct flash_params_8012) / sizeof(u16), "8012"); if (status) { - QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + netif_err(qdev, ifup, qdev->ndev, "Invalid flash.\n"); status = -EINVAL; goto exit; } @@ -969,17 +969,17 @@ static int ql_8012_port_initialize(struct ql_adapter *qdev) /* Another function has the semaphore, so * wait for the port init bit to come ready. */ - QPRINTK(qdev, LINK, INFO, - "Another function has the semaphore, so wait for the port init bit to come ready.\n"); + netif_info(qdev, link, qdev->ndev, + "Another function has the semaphore, so wait for the port init bit to come ready.\n"); status = ql_wait_reg_rdy(qdev, STS, qdev->port_init, 0); if (status) { - QPRINTK(qdev, LINK, CRIT, - "Port initialize timed out.\n"); + netif_crit(qdev, link, qdev->ndev, + "Port initialize timed out.\n"); } return status; } - QPRINTK(qdev, LINK, INFO, "Got xgmac semaphore!.\n"); + netif_info(qdev, link, qdev->ndev, "Got xgmac semaphore!.\n"); /* Set the core reset. */ status = ql_read_xgmac_reg(qdev, GLOBAL_CFG, &data); if (status) @@ -1109,8 +1109,8 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, GFP_ATOMIC, qdev->lbq_buf_order); if (unlikely(!rx_ring->pg_chunk.page)) { - QPRINTK(qdev, DRV, ERR, - "page allocation failed.\n"); + netif_err(qdev, drv, qdev->ndev, + "page allocation failed.\n"); return -ENOMEM; } rx_ring->pg_chunk.offset = 0; @@ -1120,8 +1120,8 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, if (pci_dma_mapping_error(qdev->pdev, map)) { __free_pages(rx_ring->pg_chunk.page, qdev->lbq_buf_order); - QPRINTK(qdev, DRV, ERR, - "PCI mapping failed.\n"); + netif_err(qdev, drv, qdev->ndev, + "PCI mapping failed.\n"); return -ENOMEM; } rx_ring->pg_chunk.map = map; @@ -1158,15 +1158,15 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) while (rx_ring->lbq_free_cnt > 32) { for (i = 0; i < 16; i++) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "lbq: try cleaning clean_idx = %d.\n", - clean_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "lbq: try cleaning clean_idx = %d.\n", + clean_idx); lbq_desc = &rx_ring->lbq[clean_idx]; if (ql_get_next_chunk(qdev, rx_ring, lbq_desc)) { - QPRINTK(qdev, IFUP, ERR, - "Could not get a page chunk.\n"); - return; - } + netif_err(qdev, ifup, qdev->ndev, + "Could not get a page chunk.\n"); + return; + } map = lbq_desc->p.pg_chunk.map + lbq_desc->p.pg_chunk.offset; @@ -1191,9 +1191,9 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (start_idx != clean_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "lbq: updating prod idx = %d.\n", - rx_ring->lbq_prod_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "lbq: updating prod idx = %d.\n", + rx_ring->lbq_prod_idx); ql_write_db_reg(rx_ring->lbq_prod_idx, rx_ring->lbq_prod_idx_db_reg); } @@ -1211,19 +1211,20 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) while (rx_ring->sbq_free_cnt > 16) { for (i = 0; i < 16; i++) { sbq_desc = &rx_ring->sbq[clean_idx]; - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: try cleaning clean_idx = %d.\n", - clean_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "sbq: try cleaning clean_idx = %d.\n", + clean_idx); if (sbq_desc->p.skb == NULL) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: getting new skb for index %d.\n", - sbq_desc->index); + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "sbq: getting new skb for index %d.\n", + sbq_desc->index); sbq_desc->p.skb = netdev_alloc_skb(qdev->ndev, SMALL_BUFFER_SIZE); if (sbq_desc->p.skb == NULL) { - QPRINTK(qdev, PROBE, ERR, - "Couldn't get an skb.\n"); + netif_err(qdev, probe, qdev->ndev, + "Couldn't get an skb.\n"); rx_ring->sbq_clean_idx = clean_idx; return; } @@ -1233,7 +1234,8 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) rx_ring->sbq_buf_size, PCI_DMA_FROMDEVICE); if (pci_dma_mapping_error(qdev->pdev, map)) { - QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "PCI mapping failed.\n"); rx_ring->sbq_clean_idx = clean_idx; dev_kfree_skb_any(sbq_desc->p.skb); sbq_desc->p.skb = NULL; @@ -1257,9 +1259,9 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (start_idx != clean_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "sbq: updating prod idx = %d.\n", - rx_ring->sbq_prod_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "sbq: updating prod idx = %d.\n", + rx_ring->sbq_prod_idx); ql_write_db_reg(rx_ring->sbq_prod_idx, rx_ring->sbq_prod_idx_db_reg); } @@ -1291,8 +1293,9 @@ static void ql_unmap_send(struct ql_adapter *qdev, * then its an OAL. */ if (i == 7) { - QPRINTK(qdev, TX_DONE, DEBUG, - "unmapping OAL area.\n"); + netif_printk(qdev, tx_done, KERN_DEBUG, + qdev->ndev, + "unmapping OAL area.\n"); } pci_unmap_single(qdev->pdev, pci_unmap_addr(&tx_ring_desc->map[i], @@ -1301,8 +1304,8 @@ static void ql_unmap_send(struct ql_adapter *qdev, maplen), PCI_DMA_TODEVICE); } else { - QPRINTK(qdev, TX_DONE, DEBUG, "unmapping frag %d.\n", - i); + netif_printk(qdev, tx_done, KERN_DEBUG, qdev->ndev, + "unmapping frag %d.\n", i); pci_unmap_page(qdev->pdev, pci_unmap_addr(&tx_ring_desc->map[i], mapaddr), @@ -1327,7 +1330,8 @@ static int ql_map_send(struct ql_adapter *qdev, int frag_cnt = skb_shinfo(skb)->nr_frags; if (frag_cnt) { - QPRINTK(qdev, TX_QUEUED, DEBUG, "frag_cnt = %d.\n", frag_cnt); + netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev, + "frag_cnt = %d.\n", frag_cnt); } /* * Map the skb buffer first. @@ -1336,8 +1340,8 @@ static int ql_map_send(struct ql_adapter *qdev, err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping failed with error: %d\n", err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping failed with error: %d\n", err); return NETDEV_TX_BUSY; } @@ -1383,9 +1387,9 @@ static int ql_map_send(struct ql_adapter *qdev, PCI_DMA_TODEVICE); err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping outbound address list with error: %d\n", - err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping outbound address list with error: %d\n", + err); goto map_error; } @@ -1413,9 +1417,9 @@ static int ql_map_send(struct ql_adapter *qdev, err = pci_dma_mapping_error(qdev->pdev, map); if (err) { - QPRINTK(qdev, TX_QUEUED, ERR, - "PCI mapping frags failed with error: %d.\n", - err); + netif_err(qdev, tx_queued, qdev->ndev, + "PCI mapping frags failed with error: %d.\n", + err); goto map_error; } @@ -1460,7 +1464,8 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, skb = napi_get_frags(napi); if (!skb) { - QPRINTK(qdev, DRV, ERR, "Couldn't get an skb, exiting.\n"); + netif_err(qdev, drv, qdev->ndev, + "Couldn't get an skb, exiting.\n"); rx_ring->rx_dropped++; put_page(lbq_desc->p.pg_chunk.page); return; @@ -1503,8 +1508,8 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, skb = netdev_alloc_skb(ndev, length); if (!skb) { - QPRINTK(qdev, DRV, ERR, "Couldn't get an skb, " - "need to unwind!.\n"); + netif_err(qdev, drv, qdev->ndev, + "Couldn't get an skb, need to unwind!.\n"); rx_ring->rx_dropped++; put_page(lbq_desc->p.pg_chunk.page); return; @@ -1516,8 +1521,8 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, /* Frame error, so drop the packet. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", - ib_mac_rsp->flags2); + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); rx_ring->rx_errors++; goto err_out; } @@ -1526,14 +1531,15 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, * MTU since FCoE uses 2k frames. */ if (skb->len > ndev->mtu + ETH_HLEN) { - QPRINTK(qdev, DRV, ERR, "Segment too small, dropping.\n"); + netif_err(qdev, drv, qdev->ndev, + "Segment too small, dropping.\n"); rx_ring->rx_dropped++; goto err_out; } memcpy(skb_put(skb, ETH_HLEN), addr, ETH_HLEN); - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes of headers and data in large. Chain " - "page to new skb and pull tail.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", + length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset+ETH_HLEN, length-ETH_HLEN); @@ -1550,8 +1556,8 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); skb->ip_summed = CHECKSUM_UNNECESSARY; } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { @@ -1560,8 +1566,9 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, if (!(iph->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "TCP checksum done!\n"); } } } @@ -1600,8 +1607,8 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, /* Allocate new_skb and copy */ new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN); if (new_skb == NULL) { - QPRINTK(qdev, PROBE, ERR, - "No skb available, drop the packet.\n"); + netif_err(qdev, probe, qdev->ndev, + "No skb available, drop the packet.\n"); rx_ring->rx_dropped++; return; } @@ -1611,8 +1618,8 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, /* Frame error, so drop the packet. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", - ib_mac_rsp->flags2); + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); dev_kfree_skb_any(skb); rx_ring->rx_errors++; return; @@ -1637,16 +1644,18 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, prefetch(skb->data); skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { - QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); } if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) - QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Promiscuous Packet.\n"); rx_ring->rx_packets++; rx_ring->rx_bytes += skb->len; @@ -1660,8 +1669,8 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); skb->ip_summed = CHECKSUM_UNNECESSARY; } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { @@ -1670,8 +1679,9 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, if (!(iph->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, + qdev->ndev, + "TCP checksum done!\n"); } } } @@ -1725,7 +1735,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, */ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV && ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, "Header of %d bytes in small buffer.\n", hdr_len); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Header of %d bytes in small buffer.\n", hdr_len); /* * Headers fit nicely into a small buffer. */ @@ -1744,15 +1755,16 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, * Handle the data buffer(s). */ if (unlikely(!length)) { /* Is there data too? */ - QPRINTK(qdev, RX_STATUS, DEBUG, - "No Data buffer in this packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "No Data buffer in this packet.\n"); return skb; } if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DS) { if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Headers in small, data of %d bytes in small, combine them.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Headers in small, data of %d bytes in small, combine them.\n", + length); /* * Data is less than small buffer size so it's * stuffed in a small buffer. @@ -1778,8 +1790,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, maplen), PCI_DMA_FROMDEVICE); } else { - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes in a single small buffer.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes in a single small buffer.\n", + length); sbq_desc = ql_get_curr_sbuf(rx_ring); skb = sbq_desc->p.skb; ql_realign_skb(skb, length); @@ -1794,18 +1807,18 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, } } else if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_DL) { if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Header in small, %d bytes in large. Chain large to small!\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Header in small, %d bytes in large. Chain large to small!\n", + length); /* * The data is in a single large buffer. We * chain it to the header buffer's skb and let * it rip. */ lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); - QPRINTK(qdev, RX_STATUS, DEBUG, - "Chaining page at offset = %d," - "for %d bytes to skb.\n", - lbq_desc->p.pg_chunk.offset, length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Chaining page at offset = %d, for %d bytes to skb.\n", + lbq_desc->p.pg_chunk.offset, length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, length); @@ -1821,8 +1834,8 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); skb = netdev_alloc_skb(qdev->ndev, length); if (skb == NULL) { - QPRINTK(qdev, PROBE, DEBUG, - "No skb available, drop the packet.\n"); + netif_printk(qdev, probe, KERN_DEBUG, qdev->ndev, + "No skb available, drop the packet.\n"); return NULL; } pci_unmap_page(qdev->pdev, @@ -1831,8 +1844,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, pci_unmap_len(lbq_desc, maplen), PCI_DMA_FROMDEVICE); skb_reserve(skb, NET_IP_ALIGN); - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", + length); skb_fill_page_desc(skb, 0, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, @@ -1873,8 +1887,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, * a local buffer and use it to find the * pages to chain. */ - QPRINTK(qdev, RX_STATUS, DEBUG, - "%d bytes of headers & data in chain of large.\n", length); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "%d bytes of headers & data in chain of large.\n", + length); skb = sbq_desc->p.skb; sbq_desc->p.skb = NULL; skb_reserve(skb, NET_IP_ALIGN); @@ -1884,9 +1899,9 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, size = (length < rx_ring->lbq_buf_size) ? length : rx_ring->lbq_buf_size; - QPRINTK(qdev, RX_STATUS, DEBUG, - "Adding page %d to skb for %d bytes.\n", - i, size); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Adding page %d to skb for %d bytes.\n", + i, size); skb_fill_page_desc(skb, i, lbq_desc->p.pg_chunk.page, lbq_desc->p.pg_chunk.offset, @@ -1916,16 +1931,16 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, skb = ql_build_rx_skb(qdev, rx_ring, ib_mac_rsp); if (unlikely(!skb)) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "No skb available, drop packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "No skb available, drop packet.\n"); rx_ring->rx_dropped++; return; } /* Frame error, so drop the packet. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - QPRINTK(qdev, DRV, ERR, "Receive error, flags2 = 0x%x\n", - ib_mac_rsp->flags2); + netif_err(qdev, drv, qdev->ndev, + "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); dev_kfree_skb_any(skb); rx_ring->rx_errors++; return; @@ -1950,17 +1965,18 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, prefetch(skb->data); skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { - QPRINTK(qdev, RX_STATUS, DEBUG, "%s%s%s Multicast.\n", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_HASH ? "Hash" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_REG ? "Registered" : "", - (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == - IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_HASH ? "Hash" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_REG ? "Registered" : + (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == + IB_MAC_IOCB_RSP_M_PROM ? "Promiscuous" : ""); rx_ring->rx_multicast++; } if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { - QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Promiscuous Packet.\n"); } skb->protocol = eth_type_trans(skb, ndev); @@ -1973,8 +1989,8 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { /* TCP frame. */ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); skb->ip_summed = CHECKSUM_UNNECESSARY; } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { @@ -1983,8 +1999,8 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, if (!(iph->frag_off & cpu_to_be16(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; - QPRINTK(qdev, RX_STATUS, DEBUG, - "TCP checksum done!\n"); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "TCP checksum done!\n"); } } } @@ -2054,8 +2070,9 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, /* Free small buffer that holds the IAL */ lbq_desc = ql_get_curr_sbuf(rx_ring); - QPRINTK(qdev, RX_ERR, ERR, "Dropping frame, len %d > mtu %d\n", - length, qdev->ndev->mtu); + netif_err(qdev, rx_err, qdev->ndev, + "Dropping frame, len %d > mtu %d\n", + length, qdev->ndev->mtu); /* Unwind the large buffers for this frame. */ while (length > 0) { @@ -2090,20 +2107,20 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, OB_MAC_IOCB_RSP_L | OB_MAC_IOCB_RSP_P | OB_MAC_IOCB_RSP_B))) { if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_E) { - QPRINTK(qdev, TX_DONE, WARNING, - "Total descriptor length did not match transfer length.\n"); + netif_warn(qdev, tx_done, qdev->ndev, + "Total descriptor length did not match transfer length.\n"); } if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_S) { - QPRINTK(qdev, TX_DONE, WARNING, - "Frame too short to be legal, not sent.\n"); + netif_warn(qdev, tx_done, qdev->ndev, + "Frame too short to be valid, not sent.\n"); } if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_L) { - QPRINTK(qdev, TX_DONE, WARNING, - "Frame too long, but sent anyway.\n"); + netif_warn(qdev, tx_done, qdev->ndev, + "Frame too long, but sent anyway.\n"); } if (mac_rsp->flags1 & OB_MAC_IOCB_RSP_B) { - QPRINTK(qdev, TX_DONE, WARNING, - "PCI backplane error. Frame not sent.\n"); + netif_warn(qdev, tx_done, qdev->ndev, + "PCI backplane error. Frame not sent.\n"); } } atomic_inc(&tx_ring->tx_count); @@ -2133,33 +2150,35 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev, { switch (ib_ae_rsp->event) { case MGMT_ERR_EVENT: - QPRINTK(qdev, RX_ERR, ERR, - "Management Processor Fatal Error.\n"); + netif_err(qdev, rx_err, qdev->ndev, + "Management Processor Fatal Error.\n"); ql_queue_fw_error(qdev); return; case CAM_LOOKUP_ERR_EVENT: - QPRINTK(qdev, LINK, ERR, - "Multiple CAM hits lookup occurred.\n"); - QPRINTK(qdev, DRV, ERR, "This event shouldn't occur.\n"); + netif_err(qdev, link, qdev->ndev, + "Multiple CAM hits lookup occurred.\n"); + netif_err(qdev, drv, qdev->ndev, + "This event shouldn't occur.\n"); ql_queue_asic_error(qdev); return; case SOFT_ECC_ERROR_EVENT: - QPRINTK(qdev, RX_ERR, ERR, "Soft ECC error detected.\n"); + netif_err(qdev, rx_err, qdev->ndev, + "Soft ECC error detected.\n"); ql_queue_asic_error(qdev); break; case PCI_ERR_ANON_BUF_RD: - QPRINTK(qdev, RX_ERR, ERR, - "PCI error occurred when reading anonymous buffers from rx_ring %d.\n", - ib_ae_rsp->q_id); + netif_err(qdev, rx_err, qdev->ndev, + "PCI error occurred when reading anonymous buffers from rx_ring %d.\n", + ib_ae_rsp->q_id); ql_queue_asic_error(qdev); break; default: - QPRINTK(qdev, DRV, ERR, "Unexpected event %d.\n", - ib_ae_rsp->event); + netif_err(qdev, drv, qdev->ndev, "Unexpected event %d.\n", + ib_ae_rsp->event); ql_queue_asic_error(qdev); break; } @@ -2176,9 +2195,9 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) /* While there are entries in the completion queue. */ while (prod != rx_ring->cnsmr_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id, - prod, rx_ring->cnsmr_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "cq_id = %d, prod = %d, cnsmr = %d.\n.", + rx_ring->cq_id, prod, rx_ring->cnsmr_idx); net_rsp = (struct ob_mac_iocb_rsp *)rx_ring->curr_entry; rmb(); @@ -2189,9 +2208,9 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ql_process_mac_tx_intr(qdev, net_rsp); break; default: - QPRINTK(qdev, RX_STATUS, DEBUG, - "Hit default case, not handled! dropping the packet, opcode = %x.\n", - net_rsp->opcode); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Hit default case, not handled! dropping the packet, opcode = %x.\n", + net_rsp->opcode); } count++; ql_update_cq(rx_ring); @@ -2223,9 +2242,9 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) /* While there are entries in the completion queue. */ while (prod != rx_ring->cnsmr_idx) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "cq_id = %d, prod = %d, cnsmr = %d.\n.", rx_ring->cq_id, - prod, rx_ring->cnsmr_idx); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "cq_id = %d, prod = %d, cnsmr = %d.\n.", + rx_ring->cq_id, prod, rx_ring->cnsmr_idx); net_rsp = rx_ring->curr_entry; rmb(); @@ -2241,11 +2260,10 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) net_rsp); break; default: - { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Hit default case, not handled! dropping the packet, opcode = %x.\n", - net_rsp->opcode); - } + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Hit default case, not handled! dropping the packet, opcode = %x.\n", + net_rsp->opcode); + break; } count++; ql_update_cq(rx_ring); @@ -2266,8 +2284,8 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) int i, work_done = 0; struct intr_context *ctx = &qdev->intr_context[rx_ring->cq_id]; - QPRINTK(qdev, RX_STATUS, DEBUG, "Enter, NAPI POLL cq_id = %d.\n", - rx_ring->cq_id); + netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, + "Enter, NAPI POLL cq_id = %d.\n", rx_ring->cq_id); /* Service the TX rings first. They start * right after the RSS rings. */ @@ -2279,9 +2297,9 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) if ((ctx->irq_mask & (1 << trx_ring->cq_id)) && (ql_read_sh_reg(trx_ring->prod_idx_sh_reg) != trx_ring->cnsmr_idx)) { - QPRINTK(qdev, INTR, DEBUG, - "%s: Servicing TX completion ring %d.\n", - __func__, trx_ring->cq_id); + netif_printk(qdev, intr, KERN_DEBUG, qdev->ndev, + "%s: Servicing TX completion ring %d.\n", + __func__, trx_ring->cq_id); ql_clean_outbound_rx_ring(trx_ring); } } @@ -2291,9 +2309,9 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) */ if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { - QPRINTK(qdev, INTR, DEBUG, - "%s: Servicing RX completion ring %d.\n", - __func__, rx_ring->cq_id); + netif_printk(qdev, intr, KERN_DEBUG, qdev->ndev, + "%s: Servicing RX completion ring %d.\n", + __func__, rx_ring->cq_id); work_done = ql_clean_inbound_rx_ring(rx_ring, budget); } @@ -2310,12 +2328,13 @@ static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *gr qdev->vlgrp = grp; if (grp) { - QPRINTK(qdev, IFUP, DEBUG, "Turning on VLAN in NIC_RCV_CFG.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Turning on VLAN in NIC_RCV_CFG.\n"); ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK | NIC_RCV_CFG_VLAN_MATCH_AND_NON); } else { - QPRINTK(qdev, IFUP, DEBUG, - "Turning off VLAN in NIC_RCV_CFG.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Turning off VLAN in NIC_RCV_CFG.\n"); ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK); } } @@ -2331,7 +2350,8 @@ static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid) return; if (ql_set_mac_addr_reg (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { - QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init vlan address.\n"); } ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } @@ -2348,7 +2368,8 @@ static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) if (ql_set_mac_addr_reg (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { - QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to clear vlan address.\n"); } ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); @@ -2377,7 +2398,8 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) spin_lock(&qdev->hw_lock); if (atomic_read(&qdev->intr_context[0].irq_cnt)) { - QPRINTK(qdev, INTR, DEBUG, "Shared Interrupt, Not ours!\n"); + netif_printk(qdev, intr, KERN_DEBUG, qdev->ndev, + "Shared Interrupt, Not ours!\n"); spin_unlock(&qdev->hw_lock); return IRQ_NONE; } @@ -2390,10 +2412,11 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) */ if (var & STS_FE) { ql_queue_asic_error(qdev); - QPRINTK(qdev, INTR, ERR, "Got fatal error, STS = %x.\n", var); + netif_err(qdev, intr, qdev->ndev, + "Got fatal error, STS = %x.\n", var); var = ql_read32(qdev, ERR_STS); - QPRINTK(qdev, INTR, ERR, - "Resetting chip. Error Status Register = 0x%x\n", var); + netif_err(qdev, intr, qdev->ndev, + "Resetting chip. Error Status Register = 0x%x\n", var); return IRQ_HANDLED; } @@ -2406,7 +2429,8 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) * We've got an async event or mailbox completion. * Handle it and clear the source of the interrupt. */ - QPRINTK(qdev, INTR, ERR, "Got MPI processor interrupt.\n"); + netif_err(qdev, intr, qdev->ndev, + "Got MPI processor interrupt.\n"); ql_disable_completion_interrupt(qdev, intr_context->intr); ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); queue_delayed_work_on(smp_processor_id(), @@ -2421,8 +2445,8 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) */ var = ql_read32(qdev, ISR1); if (var & intr_context->irq_mask) { - QPRINTK(qdev, INTR, INFO, - "Waking handler for rx_ring[0].\n"); + netif_info(qdev, intr, qdev->ndev, + "Waking handler for rx_ring[0].\n"); ql_disable_completion_interrupt(qdev, intr_context->intr); napi_schedule(&rx_ring->napi); work_done++; @@ -2519,9 +2543,9 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { - QPRINTK(qdev, TX_QUEUED, INFO, - "%s: shutting down tx queue %d du to lack of resources.\n", - __func__, tx_ring_idx); + netif_info(qdev, tx_queued, qdev->ndev, + "%s: shutting down tx queue %d du to lack of resources.\n", + __func__, tx_ring_idx); netif_stop_subqueue(ndev, tx_ring->wq_id); atomic_inc(&tx_ring->queue_stopped); tx_ring->tx_errors++; @@ -2542,8 +2566,8 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) mac_iocb_ptr->frame_len = cpu_to_le16((u16) skb->len); if (qdev->vlgrp && vlan_tx_tag_present(skb)) { - QPRINTK(qdev, TX_QUEUED, DEBUG, "Adding a vlan tag %d.\n", - vlan_tx_tag_get(skb)); + netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev, + "Adding a vlan tag %d.\n", vlan_tx_tag_get(skb)); mac_iocb_ptr->flags3 |= OB_MAC_IOCB_V; mac_iocb_ptr->vlan_tci = cpu_to_le16(vlan_tx_tag_get(skb)); } @@ -2557,8 +2581,8 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) } if (ql_map_send(qdev, mac_iocb_ptr, skb, tx_ring_desc) != NETDEV_TX_OK) { - QPRINTK(qdev, TX_QUEUED, ERR, - "Could not map the segments.\n"); + netif_err(qdev, tx_queued, qdev->ndev, + "Could not map the segments.\n"); tx_ring->tx_errors++; return NETDEV_TX_BUSY; } @@ -2569,8 +2593,9 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) wmb(); ql_write_db_reg(tx_ring->prod_idx, tx_ring->prod_idx_db_reg); - QPRINTK(qdev, TX_QUEUED, DEBUG, "tx queued, slot %d, len %d\n", - tx_ring->prod_idx, skb->len); + netif_printk(qdev, tx_queued, KERN_DEBUG, qdev->ndev, + "tx queued, slot %d, len %d\n", + tx_ring->prod_idx, skb->len); atomic_dec(&tx_ring->tx_count); return NETDEV_TX_OK; @@ -2601,8 +2626,8 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) pci_alloc_consistent(qdev->pdev, PAGE_SIZE, &qdev->rx_ring_shadow_reg_dma); if (qdev->rx_ring_shadow_reg_area == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Allocation of RX shadow space failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Allocation of RX shadow space failed.\n"); return -ENOMEM; } memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE); @@ -2610,8 +2635,8 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) pci_alloc_consistent(qdev->pdev, PAGE_SIZE, &qdev->tx_ring_shadow_reg_dma); if (qdev->tx_ring_shadow_reg_area == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Allocation of TX shadow space failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Allocation of TX shadow space failed.\n"); goto err_wqp_sh_area; } memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE); @@ -2665,7 +2690,7 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, if ((tx_ring->wq_base == NULL) || tx_ring->wq_base_dma & WQ_ADDR_ALIGN) { - QPRINTK(qdev, IFUP, ERR, "tx_ring alloc failed.\n"); + netif_err(qdev, ifup, qdev->ndev, "tx_ring alloc failed.\n"); return -ENOMEM; } tx_ring->q = @@ -2716,7 +2741,8 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring for (i = 0; i < rx_ring->sbq_len; i++) { sbq_desc = &rx_ring->sbq[i]; if (sbq_desc == NULL) { - QPRINTK(qdev, IFUP, ERR, "sbq_desc %d is NULL.\n", i); + netif_err(qdev, ifup, qdev->ndev, + "sbq_desc %d is NULL.\n", i); return; } if (sbq_desc->p.skb) { @@ -2843,7 +2869,7 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, &rx_ring->cq_base_dma); if (rx_ring->cq_base == NULL) { - QPRINTK(qdev, IFUP, ERR, "rx_ring alloc failed.\n"); + netif_err(qdev, ifup, qdev->ndev, "rx_ring alloc failed.\n"); return -ENOMEM; } @@ -2856,8 +2882,8 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, &rx_ring->sbq_base_dma); if (rx_ring->sbq_base == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Small buffer queue allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Small buffer queue allocation failed.\n"); goto err_mem; } @@ -2868,8 +2894,8 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, kmalloc(rx_ring->sbq_len * sizeof(struct bq_desc), GFP_KERNEL); if (rx_ring->sbq == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Small buffer queue control block allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Small buffer queue control block allocation failed.\n"); goto err_mem; } @@ -2885,8 +2911,8 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, &rx_ring->lbq_base_dma); if (rx_ring->lbq_base == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Large buffer queue allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Large buffer queue allocation failed.\n"); goto err_mem; } /* @@ -2896,8 +2922,8 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, kmalloc(rx_ring->lbq_len * sizeof(struct bq_desc), GFP_KERNEL); if (rx_ring->lbq == NULL) { - QPRINTK(qdev, IFUP, ERR, - "Large buffer queue control block allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Large buffer queue control block allocation failed.\n"); goto err_mem; } @@ -2926,10 +2952,10 @@ static void ql_tx_ring_clean(struct ql_adapter *qdev) for (i = 0; i < tx_ring->wq_len; i++) { tx_ring_desc = &tx_ring->q[i]; if (tx_ring_desc && tx_ring_desc->skb) { - QPRINTK(qdev, IFDOWN, ERR, - "Freeing lost SKB %p, from queue %d, index %d.\n", - tx_ring_desc->skb, j, - tx_ring_desc->index); + netif_err(qdev, ifdown, qdev->ndev, + "Freeing lost SKB %p, from queue %d, index %d.\n", + tx_ring_desc->skb, j, + tx_ring_desc->index); ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt); dev_kfree_skb(tx_ring_desc->skb); @@ -2960,16 +2986,16 @@ static int ql_alloc_mem_resources(struct ql_adapter *qdev) for (i = 0; i < qdev->rx_ring_count; i++) { if (ql_alloc_rx_resources(qdev, &qdev->rx_ring[i]) != 0) { - QPRINTK(qdev, IFUP, ERR, - "RX resource allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "RX resource allocation failed.\n"); goto err_mem; } } /* Allocate tx queue resources */ for (i = 0; i < qdev->tx_ring_count; i++) { if (ql_alloc_tx_resources(qdev, &qdev->tx_ring[i]) != 0) { - QPRINTK(qdev, IFUP, ERR, - "TX resource allocation failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "TX resource allocation failed.\n"); goto err_mem; } } @@ -3104,14 +3130,15 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) cqicb->pkt_delay = cpu_to_le16(qdev->rx_max_coalesced_frames); break; default: - QPRINTK(qdev, IFUP, DEBUG, "Invalid rx_ring->type = %d.\n", - rx_ring->type); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Invalid rx_ring->type = %d.\n", rx_ring->type); } - QPRINTK(qdev, IFUP, DEBUG, "Initializing rx work queue.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Initializing rx work queue.\n"); err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb), CFG_LCQ, rx_ring->cq_id); if (err) { - QPRINTK(qdev, IFUP, ERR, "Failed to load CQICB.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to load CQICB.\n"); return err; } return err; @@ -3157,10 +3184,11 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ, (u16) tx_ring->wq_id); if (err) { - QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to load tx_ring.\n"); return err; } - QPRINTK(qdev, IFUP, DEBUG, "Successfully loaded WQICB.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Successfully loaded WQICB.\n"); return err; } @@ -3214,15 +3242,15 @@ static void ql_enable_msix(struct ql_adapter *qdev) if (err < 0) { kfree(qdev->msi_x_entry); qdev->msi_x_entry = NULL; - QPRINTK(qdev, IFUP, WARNING, - "MSI-X Enable failed, trying MSI.\n"); + netif_warn(qdev, ifup, qdev->ndev, + "MSI-X Enable failed, trying MSI.\n"); qdev->intr_count = 1; qlge_irq_type = MSI_IRQ; } else if (err == 0) { set_bit(QL_MSIX_ENABLED, &qdev->flags); - QPRINTK(qdev, IFUP, INFO, - "MSI-X Enabled, got %d vectors.\n", - qdev->intr_count); + netif_info(qdev, ifup, qdev->ndev, + "MSI-X Enabled, got %d vectors.\n", + qdev->intr_count); return; } } @@ -3231,13 +3259,14 @@ msi: if (qlge_irq_type == MSI_IRQ) { if (!pci_enable_msi(qdev->pdev)) { set_bit(QL_MSI_ENABLED, &qdev->flags); - QPRINTK(qdev, IFUP, INFO, - "Running with MSI interrupts.\n"); + netif_info(qdev, ifup, qdev->ndev, + "Running with MSI interrupts.\n"); return; } } qlge_irq_type = LEG_IRQ; - QPRINTK(qdev, IFUP, DEBUG, "Running with legacy interrupts.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Running with legacy interrupts.\n"); } /* Each vector services 1 RSS ring and and 1 or more @@ -3409,12 +3438,12 @@ static void ql_free_irq(struct ql_adapter *qdev) if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { free_irq(qdev->msi_x_entry[i].vector, &qdev->rx_ring[i]); - QPRINTK(qdev, IFDOWN, DEBUG, - "freeing msix interrupt %d.\n", i); + netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev, + "freeing msix interrupt %d.\n", i); } else { free_irq(qdev->pdev->irq, &qdev->rx_ring[0]); - QPRINTK(qdev, IFDOWN, DEBUG, - "freeing msi interrupt %d.\n", i); + netif_printk(qdev, ifdown, KERN_DEBUG, qdev->ndev, + "freeing msi interrupt %d.\n", i); } } } @@ -3439,32 +3468,33 @@ static int ql_request_irq(struct ql_adapter *qdev) intr_context->name, &qdev->rx_ring[i]); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed request for MSIX interrupt %d.\n", - i); + netif_err(qdev, ifup, qdev->ndev, + "Failed request for MSIX interrupt %d.\n", + i); goto err_irq; } else { - QPRINTK(qdev, IFUP, DEBUG, - "Hooked intr %d, queue type %s%s%s, with name %s.\n", - i, - qdev->rx_ring[i].type == - DEFAULT_Q ? "DEFAULT_Q" : "", - qdev->rx_ring[i].type == - TX_Q ? "TX_Q" : "", - qdev->rx_ring[i].type == - RX_Q ? "RX_Q" : "", intr_context->name); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Hooked intr %d, queue type %s, with name %s.\n", + i, + qdev->rx_ring[i].type == DEFAULT_Q ? + "DEFAULT_Q" : + qdev->rx_ring[i].type == TX_Q ? + "TX_Q" : + qdev->rx_ring[i].type == RX_Q ? + "RX_Q" : "", + intr_context->name); } } else { - QPRINTK(qdev, IFUP, DEBUG, - "trying msi or legacy interrupts.\n"); - QPRINTK(qdev, IFUP, DEBUG, - "%s: irq = %d.\n", __func__, pdev->irq); - QPRINTK(qdev, IFUP, DEBUG, - "%s: context->name = %s.\n", __func__, - intr_context->name); - QPRINTK(qdev, IFUP, DEBUG, - "%s: dev_id = 0x%p.\n", __func__, - &qdev->rx_ring[0]); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "trying msi or legacy interrupts.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "%s: irq = %d.\n", __func__, pdev->irq); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "%s: context->name = %s.\n", __func__, + intr_context->name); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "%s: dev_id = 0x%p.\n", __func__, + &qdev->rx_ring[0]); status = request_irq(pdev->irq, qlge_isr, test_bit(QL_MSI_ENABLED, @@ -3474,20 +3504,20 @@ static int ql_request_irq(struct ql_adapter *qdev) if (status) goto err_irq; - QPRINTK(qdev, IFUP, ERR, - "Hooked intr %d, queue type %s%s%s, with name %s.\n", - i, - qdev->rx_ring[0].type == - DEFAULT_Q ? "DEFAULT_Q" : "", - qdev->rx_ring[0].type == TX_Q ? "TX_Q" : "", - qdev->rx_ring[0].type == RX_Q ? "RX_Q" : "", - intr_context->name); + netif_err(qdev, ifup, qdev->ndev, + "Hooked intr %d, queue type %s, with name %s.\n", + i, + qdev->rx_ring[0].type == DEFAULT_Q ? + "DEFAULT_Q" : + qdev->rx_ring[0].type == TX_Q ? "TX_Q" : + qdev->rx_ring[0].type == RX_Q ? "RX_Q" : "", + intr_context->name); } intr_context->hooked = 1; } return status; err_irq: - QPRINTK(qdev, IFUP, ERR, "Failed to get the interrupts!!!/n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to get the interrupts!!!/n"); ql_free_irq(qdev); return status; } @@ -3521,14 +3551,15 @@ static int ql_start_rss(struct ql_adapter *qdev) memcpy((void *)&ricb->ipv6_hash_key[0], init_hash_seed, 40); memcpy((void *)&ricb->ipv4_hash_key[0], init_hash_seed, 16); - QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, "Initializing RSS.\n"); status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0); if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to load RICB.\n"); return status; } - QPRINTK(qdev, IFUP, DEBUG, "Successfully loaded RICB.\n"); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Successfully loaded RICB.\n"); return status; } @@ -3543,9 +3574,8 @@ static int ql_clear_routing_entries(struct ql_adapter *qdev) for (i = 0; i < 16; i++) { status = ql_set_routing_reg(qdev, i, 0, 0); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for CAM " - "packets.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init routing register for CAM packets.\n"); break; } } @@ -3569,14 +3599,14 @@ static int ql_route_initialize(struct ql_adapter *qdev) status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for error packets.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init routing register for error packets.\n"); goto exit; } status = ql_set_routing_reg(qdev, RT_IDX_BCAST_SLOT, RT_IDX_BCAST, 1); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for broadcast packets.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init routing register for broadcast packets.\n"); goto exit; } /* If we have more than one inbound queue, then turn on RSS in the @@ -3586,8 +3616,8 @@ static int ql_route_initialize(struct ql_adapter *qdev) status = ql_set_routing_reg(qdev, RT_IDX_RSS_MATCH_SLOT, RT_IDX_RSS_MATCH, 1); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for MATCH RSS packets.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init routing register for MATCH RSS packets.\n"); goto exit; } } @@ -3595,8 +3625,8 @@ static int ql_route_initialize(struct ql_adapter *qdev) status = ql_set_routing_reg(qdev, RT_IDX_CAM_HIT_SLOT, RT_IDX_CAM_HIT, 1); if (status) - QPRINTK(qdev, IFUP, ERR, - "Failed to init routing register for CAM packets.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init routing register for CAM packets.\n"); exit: ql_sem_unlock(qdev, SEM_RT_IDX_MASK); return status; @@ -3614,13 +3644,13 @@ int ql_cam_route_initialize(struct ql_adapter *qdev) set &= qdev->port_link_up; status = ql_set_mac_addr(qdev, set); if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to init mac address.\n"); return status; } status = ql_route_initialize(qdev); if (status) - QPRINTK(qdev, IFUP, ERR, "Failed to init routing table.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to init routing table.\n"); return status; } @@ -3685,8 +3715,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) for (i = 0; i < qdev->rx_ring_count; i++) { status = ql_start_rx_ring(qdev, &qdev->rx_ring[i]); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to start rx ring[%d].\n", i); + netif_err(qdev, ifup, qdev->ndev, + "Failed to start rx ring[%d].\n", i); return status; } } @@ -3697,7 +3727,7 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) if (qdev->rss_ring_count > 1) { status = ql_start_rss(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to start RSS.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to start RSS.\n"); return status; } } @@ -3706,8 +3736,8 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) for (i = 0; i < qdev->tx_ring_count; i++) { status = ql_start_tx_ring(qdev, &qdev->tx_ring[i]); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to start tx ring[%d].\n", i); + netif_err(qdev, ifup, qdev->ndev, + "Failed to start tx ring[%d].\n", i); return status; } } @@ -3715,20 +3745,20 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Initialize the port and set the max framesize. */ status = qdev->nic_ops->port_initialize(qdev); if (status) - QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to start port.\n"); /* Set up the MAC address and frame routing filter. */ status = ql_cam_route_initialize(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init CAM/Routing tables.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init CAM/Routing tables.\n"); return status; } /* Start NAPI for the RSS queues. */ for (i = 0; i < qdev->rss_ring_count; i++) { - QPRINTK(qdev, IFUP, DEBUG, "Enabling NAPI for rx_ring[%d].\n", - i); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "Enabling NAPI for rx_ring[%d].\n", i); napi_enable(&qdev->rx_ring[i].napi); } @@ -3745,7 +3775,7 @@ static int ql_adapter_reset(struct ql_adapter *qdev) /* Clear all the entries in the routing table. */ status = ql_clear_routing_entries(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n"); + netif_err(qdev, ifup, qdev->ndev, "Failed to clear routing bits.\n"); return status; } @@ -3768,8 +3798,8 @@ static int ql_adapter_reset(struct ql_adapter *qdev) } while (time_before(jiffies, end_jiffies)); if (value & RST_FO_FR) { - QPRINTK(qdev, IFDOWN, ERR, - "ETIMEDOUT!!! errored out of resetting the chip!\n"); + netif_err(qdev, ifdown, qdev->ndev, + "ETIMEDOUT!!! errored out of resetting the chip!\n"); status = -ETIMEDOUT; } @@ -3782,16 +3812,17 @@ static void ql_display_dev_info(struct net_device *ndev) { struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); - QPRINTK(qdev, PROBE, INFO, - "Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, " - "XG Roll = %d, XG Rev = %d.\n", - qdev->func, - qdev->port, - qdev->chip_rev_id & 0x0000000f, - qdev->chip_rev_id >> 4 & 0x0000000f, - qdev->chip_rev_id >> 8 & 0x0000000f, - qdev->chip_rev_id >> 12 & 0x0000000f); - QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr); + netif_info(qdev, probe, qdev->ndev, + "Function #%d, Port %d, NIC Roll %d, NIC Rev = %d, " + "XG Roll = %d, XG Rev = %d.\n", + qdev->func, + qdev->port, + qdev->chip_rev_id & 0x0000000f, + qdev->chip_rev_id >> 4 & 0x0000000f, + qdev->chip_rev_id >> 8 & 0x0000000f, + qdev->chip_rev_id >> 12 & 0x0000000f); + netif_info(qdev, probe, qdev->ndev, + "MAC address %pM\n", ndev->dev_addr); } int ql_wol(struct ql_adapter *qdev) @@ -3808,23 +3839,23 @@ int ql_wol(struct ql_adapter *qdev) if (qdev->wol & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) { - QPRINTK(qdev, IFDOWN, ERR, - "Unsupported WOL paramter. qdev->wol = 0x%x.\n", - qdev->wol); + netif_err(qdev, ifdown, qdev->ndev, + "Unsupported WOL paramter. qdev->wol = 0x%x.\n", + qdev->wol); return -EINVAL; } if (qdev->wol & WAKE_MAGIC) { status = ql_mb_wol_set_magic(qdev, 1); if (status) { - QPRINTK(qdev, IFDOWN, ERR, - "Failed to set magic packet on %s.\n", - qdev->ndev->name); + netif_err(qdev, ifdown, qdev->ndev, + "Failed to set magic packet on %s.\n", + qdev->ndev->name); return status; } else - QPRINTK(qdev, DRV, INFO, - "Enabled magic packet successfully on %s.\n", - qdev->ndev->name); + netif_info(qdev, drv, qdev->ndev, + "Enabled magic packet successfully on %s.\n", + qdev->ndev->name); wol |= MB_WOL_MAGIC_PKT; } @@ -3832,9 +3863,10 @@ int ql_wol(struct ql_adapter *qdev) if (qdev->wol) { wol |= MB_WOL_MODE_ON; status = ql_mb_wol_mode(qdev, wol); - QPRINTK(qdev, DRV, ERR, "WOL %s (wol code 0x%x) on %s\n", - (status == 0) ? "Sucessfully set" : "Failed", wol, - qdev->ndev->name); + netif_err(qdev, drv, qdev->ndev, + "WOL %s (wol code 0x%x) on %s\n", + (status == 0) ? "Sucessfully set" : "Failed", + wol, qdev->ndev->name); } return status; @@ -3875,8 +3907,8 @@ static int ql_adapter_down(struct ql_adapter *qdev) status = ql_adapter_reset(qdev); if (status) - QPRINTK(qdev, IFDOWN, ERR, "reset(func #%d) FAILED!\n", - qdev->func); + netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n", + qdev->func); return status; } @@ -3886,7 +3918,7 @@ static int ql_adapter_up(struct ql_adapter *qdev) err = ql_adapter_initialize(qdev); if (err) { - QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n"); + netif_info(qdev, ifup, qdev->ndev, "Unable to initialize adapter.\n"); goto err_init; } set_bit(QL_ADAPTER_UP, &qdev->flags); @@ -3918,7 +3950,7 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev) int status = 0; if (ql_alloc_mem_resources(qdev)) { - QPRINTK(qdev, IFUP, ERR, "Unable to allocate memory.\n"); + netif_err(qdev, ifup, qdev->ndev, "Unable to allocate memory.\n"); return -ENOMEM; } status = ql_request_irq(qdev); @@ -3934,7 +3966,7 @@ static int qlge_close(struct net_device *ndev) * brought the adapter down. */ if (test_bit(QL_EEH_FATAL, &qdev->flags)) { - QPRINTK(qdev, DRV, ERR, "EEH fatal did unload.\n"); + netif_err(qdev, drv, qdev->ndev, "EEH fatal did unload.\n"); clear_bit(QL_EEH_FATAL, &qdev->flags); return 0; } @@ -4008,9 +4040,10 @@ static int ql_configure_rings(struct ql_adapter *qdev) rx_ring->lbq_size = rx_ring->lbq_len * sizeof(__le64); rx_ring->lbq_buf_size = (u16)lbq_buf_len; - QPRINTK(qdev, IFUP, DEBUG, - "lbq_buf_size %d, order = %d\n", - rx_ring->lbq_buf_size, qdev->lbq_buf_order); + netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, + "lbq_buf_size %d, order = %d\n", + rx_ring->lbq_buf_size, + qdev->lbq_buf_order); rx_ring->sbq_len = NUM_SMALL_BUFFERS; rx_ring->sbq_size = rx_ring->sbq_len * sizeof(__le64); @@ -4074,14 +4107,14 @@ static int ql_change_rx_buffers(struct ql_adapter *qdev) if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) { int i = 3; while (i-- && !test_bit(QL_ADAPTER_UP, &qdev->flags)) { - QPRINTK(qdev, IFUP, ERR, - "Waiting for adapter UP...\n"); + netif_err(qdev, ifup, qdev->ndev, + "Waiting for adapter UP...\n"); ssleep(1); } if (!i) { - QPRINTK(qdev, IFUP, ERR, - "Timed out waiting for adapter UP\n"); + netif_err(qdev, ifup, qdev->ndev, + "Timed out waiting for adapter UP\n"); return -ETIMEDOUT; } } @@ -4107,8 +4140,8 @@ static int ql_change_rx_buffers(struct ql_adapter *qdev) return status; error: - QPRINTK(qdev, IFUP, ALERT, - "Driver up/down cycle failed, closing device.\n"); + netif_alert(qdev, ifup, qdev->ndev, + "Driver up/down cycle failed, closing device.\n"); set_bit(QL_ADAPTER_UP, &qdev->flags); dev_close(qdev->ndev); return status; @@ -4120,9 +4153,9 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) int status; if (ndev->mtu == 1500 && new_mtu == 9000) { - QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n"); + netif_err(qdev, ifup, qdev->ndev, "Changing to jumbo MTU.\n"); } else if (ndev->mtu == 9000 && new_mtu == 1500) { - QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n"); + netif_err(qdev, ifup, qdev->ndev, "Changing to normal MTU.\n"); } else return -EINVAL; @@ -4137,8 +4170,8 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) status = ql_change_rx_buffers(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Changing MTU failed.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Changing MTU failed.\n"); } return status; @@ -4198,8 +4231,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (!test_bit(QL_PROMISCUOUS, &qdev->flags)) { if (ql_set_routing_reg (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 1)) { - QPRINTK(qdev, HW, ERR, - "Failed to set promiscous mode.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to set promiscous mode.\n"); } else { set_bit(QL_PROMISCUOUS, &qdev->flags); } @@ -4208,8 +4241,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (test_bit(QL_PROMISCUOUS, &qdev->flags)) { if (ql_set_routing_reg (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 0)) { - QPRINTK(qdev, HW, ERR, - "Failed to clear promiscous mode.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to clear promiscous mode.\n"); } else { clear_bit(QL_PROMISCUOUS, &qdev->flags); } @@ -4225,8 +4258,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (!test_bit(QL_ALLMULTI, &qdev->flags)) { if (ql_set_routing_reg (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 1)) { - QPRINTK(qdev, HW, ERR, - "Failed to set all-multi mode.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to set all-multi mode.\n"); } else { set_bit(QL_ALLMULTI, &qdev->flags); } @@ -4235,8 +4268,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) if (test_bit(QL_ALLMULTI, &qdev->flags)) { if (ql_set_routing_reg (qdev, RT_IDX_ALLMULTI_SLOT, RT_IDX_MCAST, 0)) { - QPRINTK(qdev, HW, ERR, - "Failed to clear all-multi mode.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to clear all-multi mode.\n"); } else { clear_bit(QL_ALLMULTI, &qdev->flags); } @@ -4251,16 +4284,16 @@ static void qlge_set_multicast_list(struct net_device *ndev) i++, mc_ptr = mc_ptr->next) if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr, MAC_ADDR_TYPE_MULTI_MAC, i)) { - QPRINTK(qdev, HW, ERR, - "Failed to loadmulticast address.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to loadmulticast address.\n"); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); goto exit; } ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (ql_set_routing_reg (qdev, RT_IDX_MCAST_MATCH_SLOT, RT_IDX_MCAST_MATCH, 1)) { - QPRINTK(qdev, HW, ERR, - "Failed to set multicast match mode.\n"); + netif_err(qdev, hw, qdev->ndev, + "Failed to set multicast match mode.\n"); } else { set_bit(QL_ALLMULTI, &qdev->flags); } @@ -4285,7 +4318,7 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) status = ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); if (status) - QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n"); + netif_err(qdev, hw, qdev->ndev, "Failed to load MAC address.\n"); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); return status; } @@ -4318,8 +4351,8 @@ static void ql_asic_reset_work(struct work_struct *work) rtnl_unlock(); return; error: - QPRINTK(qdev, IFUP, ALERT, - "Driver up/down cycle failed, closing device\n"); + netif_alert(qdev, ifup, qdev->ndev, + "Driver up/down cycle failed, closing device\n"); set_bit(QL_ADAPTER_UP, &qdev->flags); dev_close(qdev->ndev); @@ -4578,7 +4611,7 @@ static void ql_timer(unsigned long data) var = ql_read32(qdev, STS); if (pci_channel_offline(qdev->pdev)) { - QPRINTK(qdev, IFUP, ERR, "EEH STS = 0x%.08x.\n", var); + netif_err(qdev, ifup, qdev->ndev, "EEH STS = 0x%.08x.\n", var); return; } @@ -4747,14 +4780,14 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) pci_restore_state(pdev); if (pci_enable_device(pdev)) { - QPRINTK(qdev, IFUP, ERR, - "Cannot re-enable PCI device after reset.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Cannot re-enable PCI device after reset.\n"); return PCI_ERS_RESULT_DISCONNECT; } pci_set_master(pdev); if (ql_adapter_reset(qdev)) { - QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); + netif_err(qdev, drv, qdev->ndev, "reset FAILED!\n"); set_bit(QL_EEH_FATAL, &qdev->flags); return PCI_ERS_RESULT_DISCONNECT; } @@ -4771,13 +4804,13 @@ static void qlge_io_resume(struct pci_dev *pdev) if (netif_running(ndev)) { err = qlge_open(ndev); if (err) { - QPRINTK(qdev, IFUP, ERR, - "Device initialization failed after reset.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Device initialization failed after reset.\n"); return; } } else { - QPRINTK(qdev, IFUP, ERR, - "Device was not running prior to EEH.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Device was not running prior to EEH.\n"); } qdev->timer.expires = jiffies + (5*HZ); add_timer(&qdev->timer); @@ -4828,7 +4861,7 @@ static int qlge_resume(struct pci_dev *pdev) pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) { - QPRINTK(qdev, IFUP, ERR, "Cannot enable PCI device from suspend\n"); + netif_err(qdev, ifup, qdev->ndev, "Cannot enable PCI device from suspend\n"); return err; } pci_set_master(pdev); diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index e2c846f17fc7..3c00462a5d22 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c @@ -135,7 +135,7 @@ static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp) ql_read_mpi_reg(qdev, qdev->mailbox_out + i, &mbcp->mbox_out[i]); if (status) { - QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n"); + netif_err(qdev, drv, qdev->ndev, "Failed mailbox read.\n"); break; } } @@ -208,7 +208,7 @@ static int ql_idc_req_aen(struct ql_adapter *qdev) int status; struct mbox_params *mbcp = &qdev->idc_mbc; - QPRINTK(qdev, DRV, ERR, "Enter!\n"); + netif_err(qdev, drv, qdev->ndev, "Enter!\n"); /* Get the status data and start up a thread to * handle the request. */ @@ -216,8 +216,8 @@ static int ql_idc_req_aen(struct ql_adapter *qdev) mbcp->out_count = 4; status = ql_get_mb_sts(qdev, mbcp); if (status) { - QPRINTK(qdev, DRV, ERR, - "Could not read MPI, resetting ASIC!\n"); + netif_err(qdev, drv, qdev->ndev, + "Could not read MPI, resetting ASIC!\n"); ql_queue_asic_error(qdev); } else { /* Begin polled mode early so @@ -240,8 +240,8 @@ static int ql_idc_cmplt_aen(struct ql_adapter *qdev) mbcp->out_count = 4; status = ql_get_mb_sts(qdev, mbcp); if (status) { - QPRINTK(qdev, DRV, ERR, - "Could not read MPI, resetting RISC!\n"); + netif_err(qdev, drv, qdev->ndev, + "Could not read MPI, resetting RISC!\n"); ql_queue_fw_error(qdev); } else /* Wake up the sleeping mpi_idc_work thread that is @@ -259,13 +259,13 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) { - QPRINTK(qdev, DRV, ERR, - "%s: Could not get mailbox status.\n", __func__); + netif_err(qdev, drv, qdev->ndev, + "%s: Could not get mailbox status.\n", __func__); return; } qdev->link_status = mbcp->mbox_out[1]; - QPRINTK(qdev, DRV, ERR, "Link Up.\n"); + netif_err(qdev, drv, qdev->ndev, "Link Up.\n"); /* If we're coming back from an IDC event * then set up the CAM and frame routing. @@ -273,8 +273,8 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) if (test_bit(QL_CAM_RT_SET, &qdev->flags)) { status = ql_cam_route_initialize(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, - "Failed to init CAM/Routing tables.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init CAM/Routing tables.\n"); return; } else clear_bit(QL_CAM_RT_SET, &qdev->flags); @@ -285,7 +285,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) * to our liking. */ if (!test_bit(QL_PORT_CFG, &qdev->flags)) { - QPRINTK(qdev, DRV, ERR, "Queue Port Config Worker!\n"); + netif_err(qdev, drv, qdev->ndev, "Queue Port Config Worker!\n"); set_bit(QL_PORT_CFG, &qdev->flags); /* Begin polled mode early so * we don't get another interrupt @@ -307,7 +307,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) - QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n"); + netif_err(qdev, drv, qdev->ndev, "Link down AEN broken!\n"); ql_link_off(qdev); } @@ -320,9 +320,9 @@ static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) - QPRINTK(qdev, DRV, ERR, "SFP in AEN broken!\n"); + netif_err(qdev, drv, qdev->ndev, "SFP in AEN broken!\n"); else - QPRINTK(qdev, DRV, ERR, "SFP insertion detected.\n"); + netif_err(qdev, drv, qdev->ndev, "SFP insertion detected.\n"); return status; } @@ -335,9 +335,9 @@ static int ql_sfp_out(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) - QPRINTK(qdev, DRV, ERR, "SFP out AEN broken!\n"); + netif_err(qdev, drv, qdev->ndev, "SFP out AEN broken!\n"); else - QPRINTK(qdev, DRV, ERR, "SFP removal detected.\n"); + netif_err(qdev, drv, qdev->ndev, "SFP removal detected.\n"); return status; } @@ -350,13 +350,13 @@ static int ql_aen_lost(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) - QPRINTK(qdev, DRV, ERR, "Lost AEN broken!\n"); + netif_err(qdev, drv, qdev->ndev, "Lost AEN broken!\n"); else { int i; - QPRINTK(qdev, DRV, ERR, "Lost AEN detected.\n"); + netif_err(qdev, drv, qdev->ndev, "Lost AEN detected.\n"); for (i = 0; i < mbcp->out_count; i++) - QPRINTK(qdev, DRV, ERR, "mbox_out[%d] = 0x%.08x.\n", - i, mbcp->mbox_out[i]); + netif_err(qdev, drv, qdev->ndev, "mbox_out[%d] = 0x%.08x.\n", + i, mbcp->mbox_out[i]); } @@ -371,15 +371,15 @@ static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp) status = ql_get_mb_sts(qdev, mbcp); if (status) { - QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n"); + netif_err(qdev, drv, qdev->ndev, "Firmware did not initialize!\n"); } else { - QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n", - mbcp->mbox_out[1]); + netif_err(qdev, drv, qdev->ndev, "Firmware Revision = 0x%.08x.\n", + mbcp->mbox_out[1]); qdev->fw_rev_id = mbcp->mbox_out[1]; status = ql_cam_route_initialize(qdev); if (status) - QPRINTK(qdev, IFUP, ERR, - "Failed to init CAM/Routing tables.\n"); + netif_err(qdev, ifup, qdev->ndev, + "Failed to init CAM/Routing tables.\n"); } } @@ -398,8 +398,8 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) mbcp->out_count = 1; status = ql_get_mb_sts(qdev, mbcp); if (status) { - QPRINTK(qdev, DRV, ERR, - "Could not read MPI, resetting ASIC!\n"); + netif_err(qdev, drv, qdev->ndev, + "Could not read MPI, resetting ASIC!\n"); ql_queue_asic_error(qdev); goto end; } @@ -488,15 +488,14 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) mbcp->mbox_out[0] = MB_CMD_STS_ERR; return status; } - QPRINTK(qdev, DRV, ERR, - "Firmware initialization failed.\n"); + netif_err(qdev, drv, qdev->ndev, + "Firmware initialization failed.\n"); status = -EIO; ql_queue_fw_error(qdev); break; case AEN_SYS_ERR: - QPRINTK(qdev, DRV, ERR, - "System Error.\n"); + netif_err(qdev, drv, qdev->ndev, "System Error.\n"); ql_queue_fw_error(qdev); status = -EIO; break; @@ -509,8 +508,8 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) /* Need to support AEN 8110 */ break; default: - QPRINTK(qdev, DRV, ERR, - "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); + netif_err(qdev, drv, qdev->ndev, + "Unsupported AE %.08x.\n", mbcp->mbox_out[0]); /* Clear the MPI firmware status. */ } end: @@ -583,8 +582,8 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) goto done; } while (time_before(jiffies, count)); - QPRINTK(qdev, DRV, ERR, - "Timed out waiting for mailbox complete.\n"); + netif_err(qdev, drv, qdev->ndev, + "Timed out waiting for mailbox complete.\n"); status = -ETIMEDOUT; goto end; @@ -646,8 +645,8 @@ int ql_mb_about_fw(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed about firmware command\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed about firmware command\n"); status = -EIO; } @@ -678,8 +677,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed Get Firmware State.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed Get Firmware State.\n"); status = -EIO; } @@ -688,8 +687,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev) * happen. */ if (mbcp->mbox_out[1] & 1) { - QPRINTK(qdev, DRV, ERR, - "Firmware waiting for initialization.\n"); + netif_err(qdev, drv, qdev->ndev, + "Firmware waiting for initialization.\n"); status = -EIO; } @@ -721,8 +720,7 @@ int ql_mb_idc_ack(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed IDC ACK send.\n"); + netif_err(qdev, drv, qdev->ndev, "Failed IDC ACK send.\n"); status = -EIO; } return status; @@ -753,11 +751,11 @@ int ql_mb_set_port_cfg(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] == MB_CMD_STS_INTRMDT) { - QPRINTK(qdev, DRV, ERR, - "Port Config sent, wait for IDC.\n"); + netif_err(qdev, drv, qdev->ndev, + "Port Config sent, wait for IDC.\n"); } else if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed Set Port Configuration.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed Set Port Configuration.\n"); status = -EIO; } return status; @@ -791,8 +789,7 @@ int ql_mb_dump_ram(struct ql_adapter *qdev, u64 req_dma, u32 addr, return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed to dump risc RAM.\n"); + netif_err(qdev, drv, qdev->ndev, "Failed to dump risc RAM.\n"); status = -EIO; } return status; @@ -842,12 +839,12 @@ int ql_mb_get_port_cfg(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed Get Port Configuration.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed Get Port Configuration.\n"); status = -EIO; } else { - QPRINTK(qdev, DRV, DEBUG, - "Passed Get Port Configuration.\n"); + netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, + "Passed Get Port Configuration.\n"); qdev->link_config = mbcp->mbox_out[1]; qdev->max_frame_size = mbcp->mbox_out[2]; } @@ -874,8 +871,7 @@ int ql_mb_wol_mode(struct ql_adapter *qdev, u32 wol) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed to set WOL mode.\n"); + netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); status = -EIO; } return status; @@ -917,8 +913,7 @@ int ql_mb_wol_set_magic(struct ql_adapter *qdev, u32 enable_wol) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed to set WOL mode.\n"); + netif_err(qdev, drv, qdev->ndev, "Failed to set WOL mode.\n"); status = -EIO; } return status; @@ -944,8 +939,7 @@ static int ql_idc_wait(struct ql_adapter *qdev) wait_for_completion_timeout(&qdev->ide_completion, wait_time); if (!wait_time) { - QPRINTK(qdev, DRV, ERR, - "IDC Timeout.\n"); + netif_err(qdev, drv, qdev->ndev, "IDC Timeout.\n"); break; } /* Now examine the response from the IDC process. @@ -953,18 +947,17 @@ static int ql_idc_wait(struct ql_adapter *qdev) * more wait time. */ if (mbcp->mbox_out[0] == AEN_IDC_EXT) { - QPRINTK(qdev, DRV, ERR, - "IDC Time Extension from function.\n"); + netif_err(qdev, drv, qdev->ndev, + "IDC Time Extension from function.\n"); wait_time += (mbcp->mbox_out[1] >> 8) & 0x0000000f; } else if (mbcp->mbox_out[0] == AEN_IDC_CMPLT) { - QPRINTK(qdev, DRV, ERR, - "IDC Success.\n"); + netif_err(qdev, drv, qdev->ndev, "IDC Success.\n"); status = 0; break; } else { - QPRINTK(qdev, DRV, ERR, - "IDC: Invalid State 0x%.04x.\n", - mbcp->mbox_out[0]); + netif_err(qdev, drv, qdev->ndev, + "IDC: Invalid State 0x%.04x.\n", + mbcp->mbox_out[0]); status = -EIO; break; } @@ -993,8 +986,8 @@ int ql_mb_set_led_cfg(struct ql_adapter *qdev, u32 led_config) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed to set LED Configuration.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed to set LED Configuration.\n"); status = -EIO; } @@ -1019,8 +1012,8 @@ int ql_mb_get_led_cfg(struct ql_adapter *qdev) return status; if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { - QPRINTK(qdev, DRV, ERR, - "Failed to get LED Configuration.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed to get LED Configuration.\n"); status = -EIO; } else qdev->led_config = mbcp->mbox_out[1]; @@ -1050,16 +1043,16 @@ int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) return status; if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { - QPRINTK(qdev, DRV, ERR, - "Command not supported by firmware.\n"); + netif_err(qdev, drv, qdev->ndev, + "Command not supported by firmware.\n"); status = -EINVAL; } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { /* This indicates that the firmware is * already in the state we are trying to * change it to. */ - QPRINTK(qdev, DRV, ERR, - "Command parameters make no change.\n"); + netif_err(qdev, drv, qdev->ndev, + "Command parameters make no change.\n"); } return status; } @@ -1089,12 +1082,12 @@ static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) } if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { - QPRINTK(qdev, DRV, ERR, - "Command not supported by firmware.\n"); + netif_err(qdev, drv, qdev->ndev, + "Command not supported by firmware.\n"); status = -EINVAL; } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { - QPRINTK(qdev, DRV, ERR, - "Failed to get MPI traffic control.\n"); + netif_err(qdev, drv, qdev->ndev, + "Failed to get MPI traffic control.\n"); status = -EIO; } return status; @@ -1150,8 +1143,8 @@ void ql_mpi_port_cfg_work(struct work_struct *work) status = ql_mb_get_port_cfg(qdev); rtnl_unlock(); if (status) { - QPRINTK(qdev, DRV, ERR, - "Bug: Failed to get port config data.\n"); + netif_err(qdev, drv, qdev->ndev, + "Bug: Failed to get port config data.\n"); goto err; } @@ -1164,8 +1157,8 @@ void ql_mpi_port_cfg_work(struct work_struct *work) qdev->max_frame_size = CFG_DEFAULT_MAX_FRAME_SIZE; status = ql_set_port_cfg(qdev); if (status) { - QPRINTK(qdev, DRV, ERR, - "Bug: Failed to set port config data.\n"); + netif_err(qdev, drv, qdev->ndev, + "Bug: Failed to set port config data.\n"); goto err; } end: @@ -1197,8 +1190,8 @@ void ql_mpi_idc_work(struct work_struct *work) switch (aen) { default: - QPRINTK(qdev, DRV, ERR, - "Bug: Unhandled IDC action.\n"); + netif_err(qdev, drv, qdev->ndev, + "Bug: Unhandled IDC action.\n"); break; case MB_CMD_PORT_RESET: case MB_CMD_STOP_FW: @@ -1213,11 +1206,11 @@ void ql_mpi_idc_work(struct work_struct *work) if (timeout) { status = ql_mb_idc_ack(qdev); if (status) - QPRINTK(qdev, DRV, ERR, - "Bug: No pending IDC!\n"); + netif_err(qdev, drv, qdev->ndev, + "Bug: No pending IDC!\n"); } else { - QPRINTK(qdev, DRV, DEBUG, - "IDC ACK not required\n"); + netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, + "IDC ACK not required\n"); status = 0; /* success */ } break; @@ -1246,11 +1239,11 @@ void ql_mpi_idc_work(struct work_struct *work) if (timeout) { status = ql_mb_idc_ack(qdev); if (status) - QPRINTK(qdev, DRV, ERR, - "Bug: No pending IDC!\n"); + netif_err(qdev, drv, qdev->ndev, + "Bug: No pending IDC!\n"); } else { - QPRINTK(qdev, DRV, DEBUG, - "IDC ACK not required\n"); + netif_printk(qdev, drv, KERN_DEBUG, qdev->ndev, + "IDC ACK not required\n"); status = 0; /* success */ } break; @@ -1298,12 +1291,12 @@ void ql_mpi_reset_work(struct work_struct *work) * then there is nothing to do. */ if (!ql_own_firmware(qdev)) { - QPRINTK(qdev, DRV, ERR, "Don't own firmware!\n"); + netif_err(qdev, drv, qdev->ndev, "Don't own firmware!\n"); return; } if (!ql_core_dump(qdev, qdev->mpi_coredump)) { - QPRINTK(qdev, DRV, ERR, "Core is dumped!\n"); + netif_err(qdev, drv, qdev->ndev, "Core is dumped!\n"); qdev->core_is_dumped = 1; queue_delayed_work(qdev->workqueue, &qdev->mpi_core_to_log, 5 * HZ); -- cgit v1.2.3 From d707204c1fd21ab49242aad17f92f949538e1507 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 9 Feb 2010 11:49:53 +0000 Subject: drivers/net/skge.c: Use netif_printk macros Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/skge.c | 73 ++++++++++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 36ead52dea71..ffa55df4d607 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -1074,13 +1074,11 @@ static void skge_link_up(struct skge_port *skge) netif_carrier_on(skge->netdev); netif_wake_queue(skge->netdev); - if (netif_msg_link(skge)) { - printk(KERN_INFO PFX - "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", - skge->netdev->name, skge->speed, - skge->duplex == DUPLEX_FULL ? "full" : "half", - skge_pause(skge->flow_status)); - } + netif_info(skge, link, skge->netdev, + "Link is up at %d Mbps, %s duplex, flow control %s\n", + skge->speed, + skge->duplex == DUPLEX_FULL ? "full" : "half", + skge_pause(skge->flow_status)); } static void skge_link_down(struct skge_port *skge) @@ -1089,8 +1087,7 @@ static void skge_link_down(struct skge_port *skge) netif_carrier_off(skge->netdev); netif_stop_queue(skge->netdev); - if (netif_msg_link(skge)) - printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name); + netif_info(skge, link, skge->netdev, "Link is down\n"); } @@ -1792,9 +1789,8 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) struct skge_port *skge = netdev_priv(dev); u16 status = xm_read16(hw, port, XM_ISRC); - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", - dev->name, status); + netif_printk(skge, intr, KERN_DEBUG, skge->netdev, + "mac interrupt status 0x%x\n", status); if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { xm_link_down(hw, port); @@ -1898,9 +1894,8 @@ static inline void bcom_phy_intr(struct skge_port *skge) u16 isrc; isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x\n", - skge->netdev->name, isrc); + netif_printk(skge, intr, KERN_DEBUG, skge->netdev, + "phy interrupt status 0x%x\n", isrc); if (isrc & PHY_B_IS_PSE) printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n", @@ -2298,9 +2293,8 @@ static void yukon_mac_intr(struct skge_hw *hw, int port) struct skge_port *skge = netdev_priv(dev); u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: mac interrupt status 0x%x\n", - dev->name, status); + netif_printk(skge, intr, KERN_DEBUG, skge->netdev, + "mac interrupt status 0x%x\n", status); if (status & GM_IS_RX_FF_OR) { ++dev->stats.rx_fifo_errors; @@ -2379,9 +2373,8 @@ static void yukon_phy_intr(struct skge_port *skge) istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - if (netif_msg_intr(skge)) - printk(KERN_DEBUG PFX "%s: phy interrupt status 0x%x 0x%x\n", - skge->netdev->name, istatus, phystat); + netif_printk(skge, intr, KERN_DEBUG, skge->netdev, + "phy interrupt status 0x%x 0x%x\n", istatus, phystat); if (istatus & PHY_M_IS_AN_COMPL) { if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP) @@ -2571,8 +2564,7 @@ static int skge_up(struct net_device *dev) if (!is_valid_ether_addr(dev->dev_addr)) return -EINVAL; - if (netif_msg_ifup(skge)) - printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + netif_info(skge, ifup, skge->netdev, "enabling interface\n"); if (dev->mtu > RX_BUF_SIZE) skge->rx_buf_size = dev->mtu + ETH_HLEN; @@ -2670,8 +2662,7 @@ static int skge_down(struct net_device *dev) if (skge->mem == NULL) return 0; - if (netif_msg_ifdown(skge)) - printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + netif_info(skge, ifdown, skge->netdev, "disabling interface\n"); netif_tx_disable(dev); @@ -2825,9 +2816,9 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); - if (unlikely(netif_msg_tx_queued(skge))) - printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n", - dev->name, e - skge->tx_ring.start, skb->len); + netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev, + "tx queued, slot %td, len %d\n", + e - skge->tx_ring.start, skb->len); skge->tx_ring.to_use = e->next; smp_wmb(); @@ -2858,9 +2849,8 @@ static void skge_tx_free(struct skge_port *skge, struct skge_element *e, PCI_DMA_TODEVICE); if (control & BMU_EOF) { - if (unlikely(netif_msg_tx_done(skge))) - printk(KERN_DEBUG PFX "%s: tx done slot %td\n", - skge->netdev->name, e - skge->tx_ring.start); + netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, + "tx done slot %td\n", e - skge->tx_ring.start); dev_kfree_skb(e->skb); } @@ -2885,8 +2875,7 @@ static void skge_tx_timeout(struct net_device *dev) { struct skge_port *skge = netdev_priv(dev); - if (netif_msg_timer(skge)) - printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name); + netif_printk(skge, timer, KERN_DEBUG, skge->netdev, "tx timeout\n"); skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP); skge_tx_clean(dev); @@ -3054,10 +3043,9 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, struct sk_buff *skb; u16 len = control & BMU_BBC; - if (unlikely(netif_msg_rx_status(skge))) - printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n", - dev->name, e - skge->rx_ring.start, - status, len); + netif_printk(skge, rx_status, KERN_DEBUG, skge->netdev, + "rx slot %td status 0x%x len %d\n", + e - skge->rx_ring.start, status, len); if (len > skge->rx_buf_size) goto error; @@ -3111,10 +3099,9 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, return skb; error: - if (netif_msg_rx_err(skge)) - printk(KERN_DEBUG PFX "%s: rx err, slot %td control 0x%x status 0x%x\n", - dev->name, e - skge->rx_ring.start, - control, status); + netif_printk(skge, rx_err, KERN_DEBUG, skge->netdev, + "rx err, slot %td control 0x%x status 0x%x\n", + e - skge->rx_ring.start, control, status); if (skge->hw->chip_id == CHIP_ID_GENESIS) { if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) @@ -3885,9 +3872,7 @@ static void __devinit skge_show_addr(struct net_device *dev) { const struct skge_port *skge = netdev_priv(dev); - if (netif_msg_probe(skge)) - printk(KERN_INFO PFX "%s: addr %pM\n", - dev->name, dev->dev_addr); + netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); } static int __devinit skge_probe(struct pci_dev *pdev, -- cgit v1.2.3 From c28e93040b497e895d5c41b54abef3bc8db17fa9 Mon Sep 17 00:00:00 2001 From: jamal Date: Tue, 9 Feb 2010 03:59:38 +0000 Subject: xfrm: validate attributes Some XFRM attributes were not going through basic validation. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d5a712976004..943c8712bd97 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2054,6 +2054,10 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { #undef XMSGSIZE static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { + [XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, + [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, + [XFRMA_LASTUSED] = { .type = NLA_U64}, + [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, -- cgit v1.2.3 From a63374631e7192a64648ecc6672619a7abf9ebcd Mon Sep 17 00:00:00 2001 From: jamal Date: Tue, 9 Feb 2010 13:21:17 +0000 Subject: xfrm: use proper kernel types kernel side should use uxx instead of __uxx types Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index fcee547ca7e3..0beb413c01c4 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -317,8 +317,8 @@ extern void xfrm_state_delete_tunnel(struct xfrm_state *x); struct xfrm_type { char *description; struct module *owner; - __u8 proto; - __u8 flags; + u8 proto; + u8 flags; #define XFRM_TYPE_NON_FRAGMENT 1 #define XFRM_TYPE_REPLAY_PROT 2 #define XFRM_TYPE_LOCAL_COADDR 4 @@ -434,24 +434,24 @@ struct xfrm_tmpl { unsigned short encap_family; - __u32 reqid; + u32 reqid; /* Mode: transport, tunnel etc. */ - __u8 mode; + u8 mode; /* Sharing mode: unique, this session only, this user only etc. */ - __u8 share; + u8 share; /* May skip this transfomration if no SA is found */ - __u8 optional; + u8 optional; /* Skip aalgos/ealgos/calgos checks. */ - __u8 allalgs; + u8 allalgs; /* Bit mask of algos allowed for acquisition */ - __u32 aalgos; - __u32 ealgos; - __u32 calgos; + u32 aalgos; + u32 ealgos; + u32 calgos; }; #define XFRM_MAX_DEPTH 6 @@ -770,7 +770,7 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen) int pdw; int pbi; - pdw = prefixlen >> 5; /* num of whole __u32 in prefix */ + pdw = prefixlen >> 5; /* num of whole u32 in prefix */ pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */ if (pdw) @@ -1259,7 +1259,7 @@ struct xfrm_algo_desc { /* XFRM tunnel handlers. */ struct xfrm_tunnel { int (*handler)(struct sk_buff *skb); - int (*err_handler)(struct sk_buff *skb, __u32 info); + int (*err_handler)(struct sk_buff *skb, u32 info); struct xfrm_tunnel *next; int priority; @@ -1500,7 +1500,7 @@ static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, switch (family) { default: case AF_INET: - return (__force __u32)a->a4 - (__force __u32)b->a4; + return (__force u32)a->a4 - (__force u32)b->a4; case AF_INET6: return ipv6_addr_cmp((struct in6_addr *)a, (struct in6_addr *)b); -- cgit v1.2.3 From 8b05543129a5f216e08625e947a16b844bc4766d Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 12 Feb 2010 06:57:58 +0000 Subject: sky2: fix sparse warning Warning about hidden variable Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 45299d663498..92f7ba0953ee 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3128,7 +3128,7 @@ static void sky2_reset(struct sky2_hw *hw) /* check if PSMv2 was running before */ reg = sky2_pci_read16(hw, PSM_CONFIG_REG3); if (reg & PCI_EXP_LNKCTL_ASPMC) { - int cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); /* restore the PCIe Link Control register */ sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg); } -- cgit v1.2.3 From 5f8ae5c537d937bab9cfeb83a30a9b670c3cfb35 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 12 Feb 2010 06:57:59 +0000 Subject: sky2: WoL changes Change Wake On Lan code to be similar to vendor driver. The definition of Y2_HW_WOL_ON is confusing; what it means is transition to firmware SPI setting when doing power change. Since same code is done for both shutdown and suspend, use common code path. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 65 ++++++++---------------------------------------------- 1 file changed, 9 insertions(+), 56 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 92f7ba0953ee..edf37aaf67f8 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -251,6 +251,8 @@ static void sky2_power_on(struct sky2_hw *hw) sky2_pci_write32(hw, PCI_CFG_REG_1, 0); + sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); + /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */ reg = sky2_read32(hw, B2_GP_IO); reg |= GLB_GPIO_STAT_RACE_DIS; @@ -782,6 +784,9 @@ static void sky2_wol_init(struct sky2_port *sky2) ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; sky2_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); + /* Disable PiG firmware */ + sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF); + /* Turn on legacy PCI-Express PME mode */ reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); reg1 |= PCI_Y2_PME_LEGACY; @@ -789,7 +794,6 @@ static void sky2_wol_init(struct sky2_port *sky2) /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); - } static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) @@ -3272,27 +3276,6 @@ static inline u8 sky2_wol_supported(const struct sky2_hw *hw) return sky2_is_copper(hw) ? (WAKE_PHY | WAKE_MAGIC) : 0; } -static void sky2_hw_set_wol(struct sky2_hw *hw) -{ - int wol = 0; - int i; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct sky2_port *sky2 = netdev_priv(dev); - - if (sky2->wol) - wol = 1; - } - - if (hw->chip_id == CHIP_ID_YUKON_EC_U || - hw->chip_id == CHIP_ID_YUKON_EX || - hw->chip_id == CHIP_ID_YUKON_FE_P) - sky2_write32(hw, B0_CTST, wol ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); - - device_set_wakeup_enable(&hw->pdev->dev, wol); -} - static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { const struct sky2_port *sky2 = netdev_priv(dev); @@ -3311,11 +3294,6 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) return -EOPNOTSUPP; sky2->wol = wol->wolopts; - - sky2_hw_set_wol(hw); - - if (!netif_running(dev)) - sky2_wol_init(sky2); return 0; } @@ -4809,7 +4787,6 @@ static void __devexit sky2_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); } -#ifdef CONFIG_PM static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) { struct sky2_hw *hw = pci_get_drvdata(pdev); @@ -4834,6 +4811,8 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) wol |= sky2->wol; } + device_set_wakeup_enable(&pdev->dev, wol != 0); + sky2_write32(hw, B0_IMSK, 0); napi_disable(&hw->napi); sky2_power_aux(hw); @@ -4846,6 +4825,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } +#ifdef CONFIG_PM static int sky2_resume(struct pci_dev *pdev) { struct sky2_hw *hw = pci_get_drvdata(pdev); @@ -4895,34 +4875,7 @@ out: static void sky2_shutdown(struct pci_dev *pdev) { - struct sky2_hw *hw = pci_get_drvdata(pdev); - int i, wol = 0; - - if (!hw) - return; - - rtnl_lock(); - del_timer_sync(&hw->watchdog_timer); - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct sky2_port *sky2 = netdev_priv(dev); - - if (sky2->wol) { - wol = 1; - sky2_wol_init(sky2); - } - } - - if (wol) - sky2_power_aux(hw); - rtnl_unlock(); - - pci_enable_wake(pdev, PCI_D3hot, wol); - pci_enable_wake(pdev, PCI_D3cold, wol); - - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); + sky2_suspend(pdev, PMSG_SUSPEND); } static struct pci_driver sky2_driver = { -- cgit v1.2.3 From 87b09f1f25cd1e01d7c50bf423c7fe33027d7511 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 12 Feb 2010 06:58:00 +0000 Subject: sky2: dont enable PME legacy mode This bit is not changed by vendor driver, and should be left alone. The documentation implies this a debug bit. 0 = WAKE# only asserted when VMAIN not available 1 = WAKE# is depend on wake events and independent of VMAIN. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index edf37aaf67f8..249484220a5f 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -733,7 +733,6 @@ static void sky2_wol_init(struct sky2_port *sky2) unsigned port = sky2->port; enum flow_control save_mode; u16 ctrl; - u32 reg1; /* Bring hardware out of reset */ sky2_write16(hw, B0_CTST, CS_RST_CLR); @@ -787,11 +786,6 @@ static void sky2_wol_init(struct sky2_port *sky2) /* Disable PiG firmware */ sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF); - /* Turn on legacy PCI-Express PME mode */ - reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); - reg1 |= PCI_Y2_PME_LEGACY; - sky2_pci_write32(hw, PCI_DEV_REG1, reg1); - /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); } -- cgit v1.2.3 From 44dde56d37787cbad2e867a41fe87d6b0aa37fc8 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 12 Feb 2010 06:58:01 +0000 Subject: sky2: jumbo packet changes Change how FIFO is programmed in jumbo mode (to match vendor driver). Mostly cosmetic, the only register change is that the bits 22,23 are not programemd used. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 36 ++++++++++++++---------------------- drivers/net/sky2.h | 8 ++++---- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 249484220a5f..8a87e16e732f 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -798,29 +798,15 @@ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) hw->chip_rev != CHIP_REV_YU_EX_A0) || hw->chip_id >= CHIP_ID_YUKON_FE_P) { /* Yukon-Extreme B0 and further Extreme devices */ - /* enable Store & Forward mode for TX */ + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); + } else if (dev->mtu > ETH_DATA_LEN) { + /* set Tx GMAC FIFO Almost Empty Threshold */ + sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), + (ECU_JUMBO_WM << 16) | ECU_AE_THR); - if (dev->mtu <= ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_DIS | TX_STFW_ENA); - - else - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), - TX_JUMBO_ENA| TX_STFW_ENA); - } else { - if (dev->mtu <= ETH_DATA_LEN) - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); - else { - /* set Tx GMAC FIFO Almost Empty Threshold */ - sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), - (ECU_JUMBO_WM << 16) | ECU_AE_THR); - - sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); - - /* Can't do offload because of lack of store/forward */ - dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM); - } - } + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS); + } else + sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA); } static void sky2_mac_init(struct sky2_hw *hw, unsigned port) @@ -2206,14 +2192,20 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) u16 ctl, mode; u32 imask; + /* MTU size outside the spec */ if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) return -EINVAL; + /* MTU > 1500 on yukon FE and FE+ not allowed */ if (new_mtu > ETH_DATA_LEN && (hw->chip_id == CHIP_ID_YUKON_FE || hw->chip_id == CHIP_ID_YUKON_FE_P)) return -EINVAL; + /* TSO, etc on Yukon Ultra and MTU > 1500 not supported */ + if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U) + dev->features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM); + if (!netif_running(dev)) { dev->mtu = new_mtu; return 0; diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 54cb303443e0..a5e182dd9819 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1895,14 +1895,14 @@ enum { /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ enum { - TX_STFW_DIS = 1<<31,/* Disable Store & Forward (Yukon-EC Ultra) */ - TX_STFW_ENA = 1<<30,/* Enable Store & Forward (Yukon-EC Ultra) */ + TX_STFW_DIS = 1<<31,/* Disable Store & Forward */ + TX_STFW_ENA = 1<<30,/* Enable Store & Forward */ TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */ TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */ - TX_JUMBO_ENA = 1<<23,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */ - TX_JUMBO_DIS = 1<<22,/* PCI Jumbo Mode enable (Yukon-EC Ultra) */ + TX_PCI_JUM_ENA = 1<<23,/* PCI Jumbo Mode enable */ + TX_PCI_JUM_DIS = 1<<22,/* PCI Jumbo Mode enable */ GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ -- cgit v1.2.3 From 39ef110ba859f44efeb9a88d0e85316cd1bbecda Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 12 Feb 2010 06:58:02 +0000 Subject: sky2: Factor out code to calculate packet sizes Move code to calculate receive threshold and packet size out of sky2_rx_start() so that is can be called from elsewhere easily. Signed-off-by: Mike McCormack Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 57 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 8a87e16e732f..c5de65c6f6e1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1049,6 +1049,40 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2) return le; } +static unsigned sky2_get_rx_threshold(struct sky2_port* sky2) +{ + unsigned size; + + /* Space needed for frame data + headers rounded up */ + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); + + /* Stopping point for hardware truncation */ + return (size - 8) / sizeof(u32); +} + +static unsigned sky2_get_rx_data_size(struct sky2_port* sky2) +{ + struct rx_ring_info *re; + unsigned size; + + /* Space needed for frame data + headers rounded up */ + size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); + + sky2->rx_nfrags = size >> PAGE_SHIFT; + BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr)); + + /* Compute residue after pages */ + size -= sky2->rx_nfrags << PAGE_SHIFT; + + /* Optimize to handle small packets and headers */ + if (size < copybreak) + size = copybreak; + if (size < ETH_HLEN) + size = ETH_HLEN; + + return size; +} + /* Build description to hardware for one receive segment */ static void sky2_rx_add(struct sky2_port *sky2, u8 op, dma_addr_t map, unsigned len) @@ -1343,7 +1377,7 @@ static int sky2_rx_start(struct sky2_port *sky2) struct sky2_hw *hw = sky2->hw; struct rx_ring_info *re; unsigned rxq = rxqaddr[sky2->port]; - unsigned i, size, thresh; + unsigned i, thresh; sky2->rx_put = sky2->rx_next = 0; sky2_qset(hw, rxq); @@ -1364,25 +1398,7 @@ static int sky2_rx_start(struct sky2_port *sky2) if (!(hw->flags & SKY2_HW_NEW_LE)) rx_set_checksum(sky2); - /* Space needed for frame data + headers rounded up */ - size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8); - - /* Stopping point for hardware truncation */ - thresh = (size - 8) / sizeof(u32); - - sky2->rx_nfrags = size >> PAGE_SHIFT; - BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr)); - - /* Compute residue after pages */ - size -= sky2->rx_nfrags << PAGE_SHIFT; - - /* Optimize to handle small packets and headers */ - if (size < copybreak) - size = copybreak; - if (size < ETH_HLEN) - size = ETH_HLEN; - - sky2->rx_data_size = size; + sky2->rx_data_size = sky2_get_rx_data_size(sky2); /* Fill Rx ring */ for (i = 0; i < sky2->rx_pending; i++) { @@ -1407,6 +1423,7 @@ static int sky2_rx_start(struct sky2_port *sky2) * the register is limited to 9 bits, so if you do frames > 2052 * you better get the MTU right! */ + thresh = sky2_get_rx_threshold(sky2); if (thresh > 0x1ff) sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); else { -- cgit v1.2.3 From 200ac492b3c366346fcabd11897fadbd1a7a6599 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 12 Feb 2010 06:58:03 +0000 Subject: sky2: Allocate initial skbs in sky2_alloc_buffers Allocate everything in one place so there's a single point of failure in sky2_up, and sky2_rx_start can no longer fail. Don't leave the hardware in a partially initialized state in the case rx ring allocation fails. As with the old code, the rx ring still needs to be fully allocated for sky2_up to succeed. Signed-off-by: Mike McCormack Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 66 +++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c5de65c6f6e1..493a82018cbd 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1363,8 +1363,32 @@ static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) sky2_put_idx(sky2->hw, rxq, sky2->rx_put); } +static int sky2_alloc_rx_skbs(struct sky2_port *sky2) +{ + struct sky2_hw *hw = sky2->hw; + unsigned i; + + sky2->rx_data_size = sky2_get_rx_data_size(sky2); + + /* Fill Rx ring */ + for (i = 0; i < sky2->rx_pending; i++) { + struct rx_ring_info *re = sky2->rx_ring + i; + + re->skb = sky2_rx_alloc(sky2); + if (!re->skb) + return -ENOMEM; + + if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) { + dev_kfree_skb(re->skb); + re->skb = NULL; + return -ENOMEM; + } + } + return 0; +} + /* - * Allocate and setup receiver buffer pool. + * Setup receiver buffer pool. * Normal case this ends up creating one list element for skb * in the receive ring. Worst case if using large MTU and each * allocation falls on a different 64 bit region, that results @@ -1372,7 +1396,7 @@ static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq) * One element is used for checksum enable/disable, and one * extra to avoid wrap. */ -static int sky2_rx_start(struct sky2_port *sky2) +static void sky2_rx_start(struct sky2_port *sky2) { struct sky2_hw *hw = sky2->hw; struct rx_ring_info *re; @@ -1398,22 +1422,9 @@ static int sky2_rx_start(struct sky2_port *sky2) if (!(hw->flags & SKY2_HW_NEW_LE)) rx_set_checksum(sky2); - sky2->rx_data_size = sky2_get_rx_data_size(sky2); - - /* Fill Rx ring */ + /* submit Rx ring */ for (i = 0; i < sky2->rx_pending; i++) { re = sky2->rx_ring + i; - - re->skb = sky2_rx_alloc(sky2); - if (!re->skb) - goto nomem; - - if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) { - dev_kfree_skb(re->skb); - re->skb = NULL; - goto nomem; - } - sky2_rx_submit(sky2, re); } @@ -1455,13 +1466,6 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2_write32(hw, Q_ADDR(txqaddr[sky2->port], Q_TEST), TBMU_TEST_HOME_ADD_FIX_EN | TBMU_TEST_ROUTING_ADD_FIX_EN); } - - - - return 0; -nomem: - sky2_rx_clean(sky2); - return -ENOMEM; } static int sky2_alloc_buffers(struct sky2_port *sky2) @@ -1492,7 +1496,7 @@ static int sky2_alloc_buffers(struct sky2_port *sky2) if (!sky2->rx_ring) goto nomem; - return 0; + return sky2_alloc_rx_skbs(sky2); nomem: return -ENOMEM; } @@ -1501,6 +1505,8 @@ static void sky2_free_buffers(struct sky2_port *sky2) { struct sky2_hw *hw = sky2->hw; + sky2_rx_clean(sky2); + if (sky2->rx_le) { pci_free_consistent(hw->pdev, RX_LE_BYTES, sky2->rx_le, sky2->rx_le_map); @@ -1590,9 +1596,7 @@ static int sky2_up(struct net_device *dev) sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL); #endif - err = sky2_rx_start(sky2); - if (err) - goto err_out; + sky2_rx_start(sky2); /* Enable interrupts from phy/mac for port */ imask = sky2_read32(hw, B0_IMSK); @@ -1960,8 +1964,6 @@ static int sky2_down(struct net_device *dev) /* Free any pending frames stuck in HW queue */ sky2_tx_complete(sky2, sky2->tx_prod); - sky2_rx_clean(sky2); - sky2_free_buffers(sky2); return 0; @@ -2257,7 +2259,11 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD); - err = sky2_rx_start(sky2); + err = sky2_alloc_rx_skbs(sky2); + if (!err) + sky2_rx_start(sky2); + else + sky2_rx_clean(sky2); sky2_write32(hw, B0_IMSK, imask); sky2_read32(hw, B0_Y2_SP_LISR); -- cgit v1.2.3 From ea0f71e59c20ea1e413cacfc971e051b3d6c6f64 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 12 Feb 2010 06:58:04 +0000 Subject: sky2: Refactor sky2_up into two functions Move hardware initialization into sky2_hw_up. Signed-off-by: Mike McCormack Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 493a82018cbd..1f0180f1f0c3 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1525,16 +1525,16 @@ static void sky2_free_buffers(struct sky2_port *sky2) sky2->rx_ring = NULL; } -/* Bring up network interface. */ -static int sky2_up(struct net_device *dev) +static void sky2_hw_up(struct sky2_port *sky2) { - struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 imask, ramsize; - int cap, err; + u32 ramsize; + int cap; struct net_device *otherdev = hw->dev[sky2->port^1]; + tx_init(sky2); + /* * On dual port PCI-X card, there is an problem where status * can be received out of order due to split transactions @@ -1546,16 +1546,7 @@ static int sky2_up(struct net_device *dev) cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); cmd &= ~PCI_X_CMD_MAX_SPLIT; sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); - - } - - netif_carrier_off(dev); - - err = sky2_alloc_buffers(sky2); - if (err) - goto err_out; - - tx_init(sky2); + } sky2_mac_init(hw, port); @@ -1564,7 +1555,7 @@ static int sky2_up(struct net_device *dev) if (ramsize > 0) { u32 rxspace; - pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); + pr_debug(PFX "%s: ram buffer %dK\n", sky2->netdev->name, ramsize); if (ramsize < 16) rxspace = ramsize / 2; else @@ -1597,6 +1588,24 @@ static int sky2_up(struct net_device *dev) #endif sky2_rx_start(sky2); +} + +/* Bring up network interface. */ +static int sky2_up(struct net_device *dev) +{ + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + unsigned port = sky2->port; + u32 imask; + int err; + + netif_carrier_off(dev); + + err = sky2_alloc_buffers(sky2); + if (err) + goto err_out; + + sky2_hw_up(sky2); /* Enable interrupts from phy/mac for port */ imask = sky2_read32(hw, B0_IMSK); -- cgit v1.2.3 From f2b31cb3ae491f9e82443cf25cc5a9ebdbc63619 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 12 Feb 2010 06:58:05 +0000 Subject: sky2: Refactor sky2_down into two functions Create a sky2_hw_down that brings the hardware down. Signed-off-by: Mike McCormack Acked-by: Stephen Hemminber Signed-off-by: David S. Miller --- drivers/net/sky2.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1f0180f1f0c3..61a0451957b0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1908,21 +1908,12 @@ static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); } -/* Network shutdown */ -static int sky2_down(struct net_device *dev) +static void sky2_hw_down(struct sky2_port *sky2) { - struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u16 ctrl; u32 imask; - - /* Never really got started! */ - if (!sky2->tx_le) - return 0; - - if (netif_msg_ifdown(sky2)) - printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + u16 ctrl; /* Force flow control off */ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); @@ -1972,6 +1963,21 @@ static int sky2_down(struct net_device *dev) /* Free any pending frames stuck in HW queue */ sky2_tx_complete(sky2, sky2->tx_prod); +} + +/* Network shutdown */ +static int sky2_down(struct net_device *dev) +{ + struct sky2_port *sky2 = netdev_priv(dev); + + /* Never really got started! */ + if (!sky2->tx_le) + return 0; + + if (netif_msg_ifdown(sky2)) + printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + + sky2_hw_down(sky2); sky2_free_buffers(sky2); -- cgit v1.2.3 From 8a0c9228f110218f443d9ef8f9ab629251959733 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 12 Feb 2010 06:58:06 +0000 Subject: sky2: Avoid down and up during sky2_reset Rewrite sky2_reset to work with interrupts disabled and avoid freeing and reallocing memory. The old code used sky2_down and sky2_up to implement sky2_reset, which meant interrupts could not be disabled, and the transmit and receive ring buffers would be free'd and reallocated. To avoid the interrupt handler waking the transmit queue while we're doing a reset, it's better to have interrupts and NAPI polls disabled. Note: Modified Mike's patch to do IRQ disable in sky2_down before calling sky2_hw_down - Stephen Signed-off-by: Mike McCormack Acked-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 68 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 61a0451957b0..4147530cee02 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1880,10 +1880,6 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) sky2->tx_cons = idx; smp_mb(); - - /* Wake unless it's detached, and called e.g. from sky2_down() */ - if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev)) - netif_wake_queue(dev); } static void sky2_tx_reset(struct sky2_hw *hw, unsigned port) @@ -1912,7 +1908,6 @@ static void sky2_hw_down(struct sky2_port *sky2) { struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 imask; u16 ctrl; /* Force flow control off */ @@ -1946,15 +1941,6 @@ static void sky2_hw_down(struct sky2_port *sky2) sky2_rx_stop(sky2); - /* Disable port IRQ */ - imask = sky2_read32(hw, B0_IMSK); - imask &= ~portirq_msk[port]; - sky2_write32(hw, B0_IMSK, imask); - sky2_read32(hw, B0_IMSK); - - synchronize_irq(hw->pdev->irq); - napi_synchronize(&hw->napi); - spin_lock_bh(&sky2->phy_lock); sky2_phy_power_down(hw, port); spin_unlock_bh(&sky2->phy_lock); @@ -1969,6 +1955,7 @@ static void sky2_hw_down(struct sky2_port *sky2) static int sky2_down(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; /* Never really got started! */ if (!sky2->tx_le) @@ -1977,6 +1964,14 @@ static int sky2_down(struct net_device *dev) if (netif_msg_ifdown(sky2)) printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + /* Disable port IRQ */ + sky2_write32(hw, B0_IMSK, + sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]); + sky2_read32(hw, B0_IMSK); + + synchronize_irq(hw->pdev->irq); + napi_synchronize(&hw->napi); + sky2_hw_down(sky2); sky2_free_buffers(sky2); @@ -2475,8 +2470,13 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) { struct sky2_port *sky2 = netdev_priv(dev); - if (netif_running(dev)) + if (netif_running(dev)) { sky2_tx_complete(sky2, last); + + /* Wake unless it's detached, and called e.g. from sky2_down() */ + if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) + netif_wake_queue(dev); + } } static inline void sky2_skb_rx(const struct sky2_port *sky2, @@ -3277,20 +3277,46 @@ static int sky2_reattach(struct net_device *dev) static void sky2_restart(struct work_struct *work) { struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); + u32 imask; int i; rtnl_lock(); - for (i = 0; i < hw->ports; i++) - sky2_detach(hw->dev[i]); napi_disable(&hw->napi); + synchronize_irq(hw->pdev->irq); + imask = sky2_read32(hw, B0_IMSK); sky2_write32(hw, B0_IMSK, 0); + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (!netif_running(dev)) + continue; + + netif_carrier_off(dev); + netif_tx_disable(dev); + sky2_hw_down(sky2); + } + sky2_reset(hw); - sky2_write32(hw, B0_IMSK, Y2_IS_BASE); - napi_enable(&hw->napi); - for (i = 0; i < hw->ports; i++) - sky2_reattach(hw->dev[i]); + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + + if (!netif_running(dev)) + continue; + + sky2_hw_up(sky2); + netif_wake_queue(dev); + } + + sky2_write32(hw, B0_IMSK, imask); + sky2_read32(hw, B0_IMSK); + + sky2_read32(hw, B0_Y2_SP_LISR); + napi_enable(&hw->napi); rtnl_unlock(); } -- cgit v1.2.3 From cfc0861ba32643c63901832a583054bea0445961 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 12 Feb 2010 06:58:07 +0000 Subject: sky2: version 1.27 Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4147530cee02..dfff8e56a51e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -50,7 +50,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.26" +#define DRV_VERSION "1.27" #define PFX DRV_NAME " " /* -- cgit v1.2.3 From 55d955902a7f78e3e7c9ddbc71a4a050d9d44810 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 10 Feb 2010 20:26:18 +0000 Subject: dccp: support for passing MSG_TRUNC DCCP is datagram-oriented but lacks UDP's support for MSG_TRUNC as defined in recvmsg(2)/recv(2). Hence the following 'Hello world\0' receiver len = recv(fd, buf, 10, MSG_PEEK | MSG_TRUNC); wrongly (always) returns 10, while in UDP it returns 12 as expected. This patch adds the missing MSG_TRUNC support to recvmsg(). Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/dccp/proto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 671cd1413d59..85ec1cb7fd41 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -835,6 +835,8 @@ verify_sock_status: len = -EFAULT; break; } + if (flags & MSG_TRUNC) + len = skb->len; found_fin_ok: if (!(flags & MSG_PEEK)) sk_eat_skb(sk, skb, 0); -- cgit v1.2.3 From 81d54ec8479a2c695760da81f05b5a9fb2dbe40a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Wed, 10 Feb 2010 20:26:19 +0000 Subject: udp: remove redundant variable The variable 'copied' is used in udp_recvmsg() to emphasize that the passed 'len' is adjusted to fit the actual datagram length. But the same can be done by adjusting 'len' directly. This patch thus removes the indirection. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/ipv4/udp.c | 15 +++++++-------- net/ipv6/udp.c | 15 +++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4f7d2122d818..608a5446d05b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1117,7 +1117,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; struct sk_buff *skb; - unsigned int ulen, copied; + unsigned int ulen; int peeked; int err; int is_udplite = IS_UDPLITE(sk); @@ -1138,10 +1138,9 @@ try_again: goto out; ulen = skb->len - sizeof(struct udphdr); - copied = len; - if (copied > ulen) - copied = ulen; - else if (copied < ulen) + if (len > ulen) + len = ulen; + else if (len < ulen) msg->msg_flags |= MSG_TRUNC; /* @@ -1150,14 +1149,14 @@ try_again: * coverage checksum (UDP-Lite), do it before the copy. */ - if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { if (udp_lib_checksum_complete(skb)) goto csum_copy_err; } if (skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), - msg->msg_iov, copied); + msg->msg_iov, len); else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), @@ -1186,7 +1185,7 @@ try_again: if (inet->cmsg_flags) ip_cmsg_recv(msg, skb); - err = copied; + err = len; if (flags & MSG_TRUNC) err = ulen; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 34efb3589ffa..a7af9d68cd6c 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -322,7 +322,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, struct ipv6_pinfo *np = inet6_sk(sk); struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; - unsigned int ulen, copied; + unsigned int ulen; int peeked; int err; int is_udplite = IS_UDPLITE(sk); @@ -341,10 +341,9 @@ try_again: goto out; ulen = skb->len - sizeof(struct udphdr); - copied = len; - if (copied > ulen) - copied = ulen; - else if (copied < ulen) + if (len > ulen) + len = ulen; + else if (len < ulen) msg->msg_flags |= MSG_TRUNC; is_udp4 = (skb->protocol == htons(ETH_P_IP)); @@ -355,14 +354,14 @@ try_again: * coverage checksum (UDP-Lite), do it before the copy. */ - if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { + if (len < ulen || UDP_SKB_CB(skb)->partial_cov) { if (udp_lib_checksum_complete(skb)) goto csum_copy_err; } if (skb_csum_unnecessary(skb)) err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), - msg->msg_iov, copied ); + msg->msg_iov,len); else { err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); if (err == -EINVAL) @@ -411,7 +410,7 @@ try_again: datagram_recv_ctl(sk, msg, skb); } - err = copied; + err = len; if (flags & MSG_TRUNC) err = ulen; -- cgit v1.2.3 From fb8a0d9d1bfd1e4355f307e86a6da7209eefd5f3 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 10 Feb 2010 01:43:04 +0000 Subject: pci: Add SR-IOV convenience functions and macros Add and export pci_num_vf to allow other subsystems to determine how many virtual function devices are associated with an SR-IOV physical function device. Add macros dev_is_pci, dev_is_ps, and dev_num_vf to make it easier for non-PCI specific code to determine SR-IOV capabilities. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/pci/iov.c | 15 +++++++++++++++ include/linux/pci.h | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index b2a448e19fe6..3e5ab2bf6a5c 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -706,6 +706,21 @@ irqreturn_t pci_sriov_migration(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_sriov_migration); +/** + * pci_num_vf - return number of VFs associated with a PF device_release_driver + * @dev: the PCI device + * + * Returns number of VFs, or 0 if SR-IOV is not enabled. + */ +int pci_num_vf(struct pci_dev *dev) +{ + if (!dev || !dev->is_physfn) + return 0; + else + return dev->sriov->nr_virtfn; +} +EXPORT_SYMBOL_GPL(pci_num_vf); + static int ats_alloc_one(struct pci_dev *dev, int ps) { int pos; diff --git a/include/linux/pci.h b/include/linux/pci.h index 174e5392e51e..59a98e2ee2c6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -612,6 +612,9 @@ extern void pci_remove_bus_device(struct pci_dev *dev); extern void pci_stop_bus_device(struct pci_dev *dev); void pci_setup_cardbus(struct pci_bus *bus); extern void pci_sort_breadthfirst(void); +#define dev_is_pci(d) ((d)->bus == &pci_bus_type) +#define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false)) +#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0)) /* Generic PCI functions exported to card drivers */ @@ -1129,6 +1132,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) { return NULL; } +#define dev_is_pci(d) (false) +#define dev_is_pf(d) (false) +#define dev_num_vf(d) (0) #endif /* CONFIG_PCI */ /* Include architecture-dependent settings and functions */ @@ -1286,6 +1292,7 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); extern void pci_disable_sriov(struct pci_dev *dev); extern irqreturn_t pci_sriov_migration(struct pci_dev *dev); +extern int pci_num_vf(struct pci_dev *dev); #else static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { @@ -1298,6 +1305,10 @@ static inline irqreturn_t pci_sriov_migration(struct pci_dev *dev) { return IRQ_NONE; } +static inline int pci_num_vf(struct pci_dev *dev) +{ + return 0; +} #endif #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) -- cgit v1.2.3 From b280da8d54b8d82b52f368a8703b7ada6c1744d5 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 10 Feb 2010 01:43:24 +0000 Subject: if_link: Add SR-IOV configuration methods Add SR-IOV VF management methods to IFLA_LINKINFO. This allows userspace to use rtnetlink to configure VF network devices. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- include/linux/if_link.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 6674791622ca..c9bf92cd7653 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -78,6 +78,11 @@ enum { #define IFLA_LINKINFO IFLA_LINKINFO IFLA_NET_NS_PID, IFLA_IFALIAS, + IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ + IFLA_VF_MAC, /* Hardware queue specific attributes */ + IFLA_VF_VLAN, + IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + IFLA_VFINFO, __IFLA_MAX }; @@ -196,4 +201,29 @@ enum macvlan_mode { MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ }; +/* SR-IOV virtual function managment section */ + +struct ifla_vf_mac { + __u32 vf; + __u8 mac[32]; /* MAX_ADDR_LEN */ +}; + +struct ifla_vf_vlan { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; +}; + +struct ifla_vf_tx_rate { + __u32 vf; + __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ +}; + +struct ifla_vf_info { + __u32 vf; + __u8 mac[32]; + __u32 vlan; + __u32 qos; + __u32 tx_rate; +}; #endif /* _LINUX_IF_LINK_H */ -- cgit v1.2.3 From 95c26df829ba4a25f40595cadb4c9433883cbe28 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 10 Feb 2010 01:43:46 +0000 Subject: net: Add netdev ops for SR-IOV configuration Add netdev ops for configuring SR-IOV VF devices through the PF driver. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- include/linux/netdevice.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1412dde16d00..682d02521bbc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef __KERNEL__ #include @@ -621,6 +622,13 @@ struct netdev_queue { * this function is called when a VLAN id is unregistered. * * void (*ndo_poll_controller)(struct net_device *dev); + * + * SR-IOV management functions. + * int (*ndo_set_vf_mac)(struct net_device *dev, int vf, u8* mac); + * int (*ndo_set_vf_vlan)(struct net_device *dev, int vf, u16 vlan, u8 qos); + * int (*ndo_set_vf_tx_rate)(struct net_device *dev, int vf, int rate); + * int (*ndo_get_vf_config)(struct net_device *dev, + * int vf, struct ifla_vf_info *ivf); */ #define HAVE_NET_DEVICE_OPS struct net_device_ops { @@ -660,6 +668,15 @@ struct net_device_ops { #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); #endif + int (*ndo_set_vf_mac)(struct net_device *dev, + int queue, u8 *mac); + int (*ndo_set_vf_vlan)(struct net_device *dev, + int queue, u16 vlan, u8 qos); + int (*ndo_set_vf_tx_rate)(struct net_device *dev, + int vf, int rate); + int (*ndo_get_vf_config)(struct net_device *dev, + int vf, + struct ifla_vf_info *ivf); #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) int (*ndo_fcoe_enable)(struct net_device *dev); int (*ndo_fcoe_disable)(struct net_device *dev); -- cgit v1.2.3 From ebc08a6f47ee76ecad8e9f26c26e6ec9b46ca659 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 10 Feb 2010 01:44:05 +0000 Subject: rtnetlink: Add VF config code to rtnetlink Add code to allow rtnetlink clients to query and set VF information through the PF driver. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 62f3878a6010..42da96a4eeee 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -580,6 +581,15 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->tx_compressed = b->tx_compressed; }; +static inline int rtnl_vfinfo_size(const struct net_device *dev) +{ + if (dev->dev.parent && dev_is_pci(dev->dev.parent)) + return dev_num_vf(dev->dev.parent) * + sizeof(struct ifla_vf_info); + else + return 0; +} + static inline size_t if_nlmsg_size(const struct net_device *dev) { return NLMSG_ALIGN(sizeof(struct ifinfomsg)) @@ -597,6 +607,8 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) + nla_total_size(4) /* IFLA_MASTER */ + nla_total_size(1) /* IFLA_OPERSTATE */ + nla_total_size(1) /* IFLA_LINKMODE */ + + nla_total_size(4) /* IFLA_NUM_VF */ + + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ } @@ -665,6 +677,17 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, stats = dev_get_stats(dev); copy_rtnl_link_stats(nla_data(attr), stats); + if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { + int i; + struct ifla_vf_info ivi; + + NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); + for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { + if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) + break; + NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); + } + } if (dev->rtnl_link_ops) { if (rtnl_link_fill(skb, dev) < 0) goto nla_put_failure; @@ -725,6 +748,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_NET_NS_PID] = { .type = NLA_U32 }, [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, + [IFLA_VF_MAC] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_mac) }, + [IFLA_VF_VLAN] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_vlan) }, + [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_tx_rate) }, }; EXPORT_SYMBOL(ifla_policy); @@ -898,6 +927,44 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, write_unlock_bh(&dev_base_lock); } + if (tb[IFLA_VF_MAC]) { + struct ifla_vf_mac *ivm; + ivm = nla_data(tb[IFLA_VF_MAC]); + write_lock_bh(&dev_base_lock); + if (ops->ndo_set_vf_mac) + err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); + write_unlock_bh(&dev_base_lock); + if (err < 0) + goto errout; + modified = 1; + } + + if (tb[IFLA_VF_VLAN]) { + struct ifla_vf_vlan *ivv; + ivv = nla_data(tb[IFLA_VF_VLAN]); + write_lock_bh(&dev_base_lock); + if (ops->ndo_set_vf_vlan) + err = ops->ndo_set_vf_vlan(dev, ivv->vf, + (u16)ivv->vlan, + (u8)ivv->qos); + write_unlock_bh(&dev_base_lock); + if (err < 0) + goto errout; + modified = 1; + } + err = 0; + + if (tb[IFLA_VF_TX_RATE]) { + struct ifla_vf_tx_rate *ivt; + ivt = nla_data(tb[IFLA_VF_TX_RATE]); + write_lock_bh(&dev_base_lock); + if (ops->ndo_set_vf_tx_rate) + err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); + write_unlock_bh(&dev_base_lock); + if (err < 0) + goto errout; + modified = 1; + } err = 0; errout: -- cgit v1.2.3 From 8151d2948e088c20b7d29c793cf1fd744b6a2699 Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 10 Feb 2010 01:44:24 +0000 Subject: igb: support for VF configuration tools Add support to the igb driver for VF configuration mechanisms through the PF interface. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.h | 3 + drivers/net/igb/e1000_regs.h | 1 + drivers/net/igb/igb.h | 3 + drivers/net/igb/igb_main.c | 130 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 126 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index d51c9927c819..bb53083ec61f 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -219,6 +219,9 @@ struct e1000_adv_tx_context_desc { #define E1000_VLVF_LVLAN 0x00100000 #define E1000_VLVF_VLANID_ENABLE 0x80000000 +#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */ +#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */ + #define E1000_IOVCTL 0x05BBC #define E1000_IOVCTL_REUSE_VFQ 0x00000001 diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h index dd4e6ffd29f5..abb7333a1fbf 100644 --- a/drivers/net/igb/e1000_regs.h +++ b/drivers/net/igb/e1000_regs.h @@ -310,6 +310,7 @@ #define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n))) #define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine * Filter - RW */ +#define E1000_VMVIR(_n) (0x03700 + (4 * (_n))) #define wr32(reg, value) (writel(value, hw->hw_addr + reg)) #define rd32(reg) (readl(hw->hw_addr + reg)) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index b1c1eb88893f..83ea11701f45 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -75,11 +75,14 @@ struct vf_data_storage { u16 vlans_enabled; u32 flags; unsigned long last_nack; + u16 pf_vlan; /* When set, guest VLAN config not allowed. */ + u16 pf_qos; }; #define IGB_VF_FLAG_CTS 0x00000001 /* VF is clear to send data */ #define IGB_VF_FLAG_UNI_PROMISC 0x00000002 /* VF has unicast promisc */ #define IGB_VF_FLAG_MULTI_PROMISC 0x00000004 /* VF has multicast promisc */ +#define IGB_VF_FLAG_PF_SET_MAC 0x00000008 /* PF has set MAC address */ /* RX descriptor control thresholds. * PTHRESH - MAC will consider prefetch if it has fewer than this number of diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 28371d648208..4fe7b0ba6310 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -133,6 +133,12 @@ static void igb_msg_task(struct igb_adapter *); static void igb_vmm_control(struct igb_adapter *); static int igb_set_vf_mac(struct igb_adapter *, int, unsigned char *); static void igb_restore_vf_multicasts(struct igb_adapter *adapter); +static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac); +static int igb_ndo_set_vf_vlan(struct net_device *netdev, + int vf, u16 vlan, u8 qos); +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); +static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, + struct ifla_vf_info *ivi); #ifdef CONFIG_PM static int igb_suspend(struct pci_dev *, pm_message_t); @@ -1352,6 +1358,10 @@ static const struct net_device_ops igb_netdev_ops = { .ndo_vlan_rx_register = igb_vlan_rx_register, .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid, + .ndo_set_vf_mac = igb_ndo_set_vf_mac, + .ndo_set_vf_vlan = igb_ndo_set_vf_vlan, + .ndo_set_vf_tx_rate = igb_ndo_set_vf_bw, + .ndo_get_vf_config = igb_ndo_get_vf_config, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = igb_netpoll, #endif @@ -2479,7 +2489,8 @@ static void igb_rlpml_set(struct igb_adapter *adapter) wr32(E1000_RLPML, max_frame_size); } -static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn) +static inline void igb_set_vmolr(struct igb_adapter *adapter, + int vfn, bool aupe) { struct e1000_hw *hw = &adapter->hw; u32 vmolr; @@ -2492,8 +2503,11 @@ static inline void igb_set_vmolr(struct igb_adapter *adapter, int vfn) return; vmolr = rd32(E1000_VMOLR(vfn)); - vmolr |= E1000_VMOLR_AUPE | /* Accept untagged packets */ - E1000_VMOLR_STRVLAN; /* Strip vlan tags */ + vmolr |= E1000_VMOLR_STRVLAN; /* Strip vlan tags */ + if (aupe) + vmolr |= E1000_VMOLR_AUPE; /* Accept untagged packets */ + else + vmolr &= ~(E1000_VMOLR_AUPE); /* Tagged packets ONLY */ /* clear all bits that might not be set */ vmolr &= ~(E1000_VMOLR_BAM | E1000_VMOLR_RSSE); @@ -2564,7 +2578,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, wr32(E1000_SRRCTL(reg_idx), srrctl); /* set filtering for VMDQ pools */ - igb_set_vmolr(adapter, reg_idx & 0x7); + igb_set_vmolr(adapter, reg_idx & 0x7, true); /* enable receive descriptor fetching */ rxdctl = rd32(E1000_RXDCTL(reg_idx)); @@ -4490,10 +4504,57 @@ static s32 igb_vlvf_set(struct igb_adapter *adapter, u32 vid, bool add, u32 vf) reg |= size; wr32(E1000_VMOLR(vf), reg); } - return 0; } } - return -1; + return 0; +} + +static void igb_set_vmvir(struct igb_adapter *adapter, u32 vid, u32 vf) +{ + struct e1000_hw *hw = &adapter->hw; + + if (vid) + wr32(E1000_VMVIR(vf), (vid | E1000_VMVIR_VLANA_DEFAULT)); + else + wr32(E1000_VMVIR(vf), 0); +} + +static int igb_ndo_set_vf_vlan(struct net_device *netdev, + int vf, u16 vlan, u8 qos) +{ + int err = 0; + struct igb_adapter *adapter = netdev_priv(netdev); + + if ((vf >= adapter->vfs_allocated_count) || (vlan > 4095) || (qos > 7)) + return -EINVAL; + if (vlan || qos) { + err = igb_vlvf_set(adapter, vlan, !!vlan, vf); + if (err) + goto out; + igb_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); + igb_set_vmolr(adapter, vf, !vlan); + adapter->vf_data[vf].pf_vlan = vlan; + adapter->vf_data[vf].pf_qos = qos; + dev_info(&adapter->pdev->dev, + "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); + if (test_bit(__IGB_DOWN, &adapter->state)) { + dev_warn(&adapter->pdev->dev, + "The VF VLAN has been set," + " but the PF device is not up.\n"); + dev_warn(&adapter->pdev->dev, + "Bring the PF device up before" + " attempting to use the VF device.\n"); + } + } else { + igb_vlvf_set(adapter, adapter->vf_data[vf].pf_vlan, + false, vf); + igb_set_vmvir(adapter, vlan, vf); + igb_set_vmolr(adapter, vf, true); + adapter->vf_data[vf].pf_vlan = 0; + adapter->vf_data[vf].pf_qos = 0; + } +out: + return err; } static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) @@ -4506,15 +4567,21 @@ static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) static inline void igb_vf_reset(struct igb_adapter *adapter, u32 vf) { - /* clear all flags */ - adapter->vf_data[vf].flags = 0; + /* clear flags */ + adapter->vf_data[vf].flags &= ~(IGB_VF_FLAG_PF_SET_MAC); adapter->vf_data[vf].last_nack = jiffies; /* reset offloads to defaults */ - igb_set_vmolr(adapter, vf); + igb_set_vmolr(adapter, vf, true); /* reset vlans for device */ igb_clear_vf_vfta(adapter, vf); + if (adapter->vf_data[vf].pf_vlan) + igb_ndo_set_vf_vlan(adapter->netdev, vf, + adapter->vf_data[vf].pf_vlan, + adapter->vf_data[vf].pf_qos); + else + igb_clear_vf_vfta(adapter, vf); /* reset multicast table array for vf */ adapter->vf_data[vf].num_vf_mc_hashes = 0; @@ -4528,7 +4595,8 @@ static void igb_vf_reset_event(struct igb_adapter *adapter, u32 vf) unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses; /* generate a new mac address as we were hotplug removed/added */ - random_ether_addr(vf_mac); + if (!(adapter->vf_data[vf].flags & IGB_VF_FLAG_PF_SET_MAC)) + random_ether_addr(vf_mac); /* process remaining reset events */ igb_vf_reset(adapter, vf); @@ -4641,7 +4709,10 @@ static void igb_rcv_msg_from_vf(struct igb_adapter *adapter, u32 vf) retval = igb_set_vf_rlpml(adapter, msgbuf[1], vf); break; case E1000_VF_SET_VLAN: - retval = igb_set_vf_vlan(adapter, msgbuf, vf); + if (adapter->vf_data[vf].pf_vlan) + retval = -1; + else + retval = igb_set_vf_vlan(adapter, msgbuf, vf); break; default: dev_err(&pdev->dev, "Unhandled Msg %08x\n", msgbuf[0]); @@ -6003,6 +6074,43 @@ static int igb_set_vf_mac(struct igb_adapter *adapter, return 0; } +static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + if (!is_valid_ether_addr(mac) || (vf >= adapter->vfs_allocated_count)) + return -EINVAL; + adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; + dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf); + dev_info(&adapter->pdev->dev, "Reload the VF driver to make this" + " change effective."); + if (test_bit(__IGB_DOWN, &adapter->state)) { + dev_warn(&adapter->pdev->dev, "The VF MAC address has been set," + " but the PF device is not up.\n"); + dev_warn(&adapter->pdev->dev, "Bring the PF device up before" + " attempting to use the VF device.\n"); + } + return igb_set_vf_mac(adapter, vf, mac); +} + +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) +{ + return -EOPNOTSUPP; +} + +static int igb_ndo_get_vf_config(struct net_device *netdev, + int vf, struct ifla_vf_info *ivi) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + if (vf >= adapter->vfs_allocated_count) + return -EINVAL; + ivi->vf = vf; + memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN); + ivi->tx_rate = 0; + ivi->vlan = adapter->vf_data[vf].pf_vlan; + ivi->qos = adapter->vf_data[vf].pf_qos; + return 0; +} + static void igb_vmm_control(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; -- cgit v1.2.3 From e4af1af900328e4aa71cd5df75bb22669ab11522 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:05 +0000 Subject: tg3: Give MSI-X vec 1 rx backlog space RSS ring 1 is responsible for submitting new rx buffers to the hardware on behalf of all the other RSS rx return rings. Up until now this ring submitted its new rx buffers to the producer ring directly. The following patch will require that this ring have a place to put backlogged rx packets. As a consequence, it can no longer submit new buffers to the producer ring. This patch adds code to allocate an extra shadow producer ring for this RSS ring and adds RSS ring 1 to the list of rings needing buffer transfers. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 46 +++++++++++++++++++++------------------------- drivers/net/tg3.h | 2 +- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d29282f01c23..661e9ddd1401 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4733,7 +4733,7 @@ next_pkt_nopost: tw32_rx_mbox(tnapi->consmbox, sw_idx); /* Refill RX ring(s). */ - if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) || tnapi == &tp->napi[1]) { + if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) { if (work_mask & RXD_OPAQUE_RING_STD) { tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, @@ -4755,7 +4755,8 @@ next_pkt_nopost: tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE; - napi_schedule(&tp->napi[1].napi); + if (tnapi != &tp->napi[1]) + napi_schedule(&tp->napi[1].napi); } return received; @@ -4893,25 +4894,23 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) work_done += tg3_rx(tnapi, budget - work_done); if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) { + struct tg3_rx_prodring_set *dpr = &tp->prodring[0]; int i; - u32 std_prod_idx = tp->prodring[0].rx_std_prod_idx; - u32 jmb_prod_idx = tp->prodring[0].rx_jmb_prod_idx; + u32 std_prod_idx = dpr->rx_std_prod_idx; + u32 jmb_prod_idx = dpr->rx_jmb_prod_idx; - for (i = 2; i < tp->irq_cnt; i++) - tg3_rx_prodring_xfer(tp, tnapi->prodring, - tp->napi[i].prodring); + for (i = 1; i < tp->irq_cnt; i++) + tg3_rx_prodring_xfer(tp, dpr, tp->napi[i].prodring); wmb(); - if (std_prod_idx != tp->prodring[0].rx_std_prod_idx) { - u32 mbox = TG3_RX_STD_PROD_IDX_REG; - tw32_rx_mbox(mbox, tp->prodring[0].rx_std_prod_idx); - } + if (std_prod_idx != dpr->rx_std_prod_idx) + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, + dpr->rx_std_prod_idx); - if (jmb_prod_idx != tp->prodring[0].rx_jmb_prod_idx) { - u32 mbox = TG3_RX_JMB_PROD_IDX_REG; - tw32_rx_mbox(mbox, tp->prodring[0].rx_jmb_prod_idx); - } + if (jmb_prod_idx != dpr->rx_jmb_prod_idx) + tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, + dpr->rx_jmb_prod_idx); mmiowb(); } @@ -6173,8 +6172,7 @@ static void tg3_free_rings(struct tg3 *tp) dev_kfree_skb_any(skb); } - if (tp->irq_cnt == 1 || j != tp->irq_cnt - 1) - tg3_rx_prodring_free(tp, &tp->prodring[j]); + tg3_rx_prodring_free(tp, &tp->prodring[j]); } } @@ -6210,9 +6208,10 @@ static int tg3_init_rings(struct tg3 *tp) if (tnapi->rx_rcb) memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp)); - if ((tp->irq_cnt == 1 || i != tp->irq_cnt - 1) && - tg3_rx_prodring_alloc(tp, &tp->prodring[i])) + if (tg3_rx_prodring_alloc(tp, &tp->prodring[i])) { + tg3_free_rings(tp); return -ENOMEM; + } } return 0; @@ -6259,7 +6258,7 @@ static void tg3_free_consistent(struct tg3 *tp) tp->hw_stats = NULL; } - for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++) + for (i = 0; i < tp->irq_cnt; i++) tg3_rx_prodring_fini(tp, &tp->prodring[i]); } @@ -6271,7 +6270,7 @@ static int tg3_alloc_consistent(struct tg3 *tp) { int i; - for (i = 0; i < (tp->irq_cnt == 1 ? 1 : tp->irq_cnt - 1); i++) { + for (i = 0; i < tp->irq_cnt; i++) { if (tg3_rx_prodring_init(tp, &tp->prodring[i])) goto err_out; } @@ -6336,10 +6335,7 @@ static int tg3_alloc_consistent(struct tg3 *tp) break; } - if (tp->irq_cnt == 1) - tnapi->prodring = &tp->prodring[0]; - else if (i) - tnapi->prodring = &tp->prodring[i - 1]; + tnapi->prodring = &tp->prodring[i]; /* * If multivector RSS is enabled, vector 0 does not handle diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index e7f6214a1680..88a87bb618c0 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2717,7 +2717,7 @@ struct tg3 { struct vlan_group *vlgrp; #endif - struct tg3_rx_prodring_set prodring[TG3_IRQ_MAX_VECS - 1]; + struct tg3_rx_prodring_set prodring[TG3_IRQ_MAX_VECS]; /* begin "everything else" cacheline(s) section */ -- cgit v1.2.3 From e92967bfb1f4fa7da7c425df9239c4bb615dec30 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:06 +0000 Subject: tg3: Prevent rx producer ring overruns When operating in RSS mode, it is possible for one rx return ring to submit enough rx buffers back to the hardware such that it inadvertently overwrites data needed by another rx return ring. This patch addresses the problem by looking for non-NULL skb pointers in the rx_[std|jmb]_buffers rings that parallel the rx producer rings. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 661e9ddd1401..a46c26764ba7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4552,6 +4552,12 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi, pci_unmap_addr(src_map, mapping)); dest_desc->addr_hi = src_desc->addr_hi; dest_desc->addr_lo = src_desc->addr_lo; + + /* Ensure that the update to the skb happens after the physical + * addresses have been transferred to the new BD location. + */ + smp_wmb(); + src_map->skb = NULL; } @@ -4816,6 +4822,22 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp, si = spr->rx_std_cons_idx; di = dpr->rx_std_prod_idx; + for (i = di; i < di + cpycnt; i++) { + if (dpr->rx_std_buffers[i].skb) { + cpycnt = i - di; + break; + } + } + + if (!cpycnt) + break; + + /* Ensure that updates to the rx_std_buffers ring and the + * shadowed hardware producer ring from tg3_recycle_skb() are + * ordered correctly WRT the skb check above. + */ + smp_rmb(); + memcpy(&dpr->rx_std_buffers[di], &spr->rx_std_buffers[si], cpycnt * sizeof(struct ring_info)); @@ -4856,6 +4878,22 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp, si = spr->rx_jmb_cons_idx; di = dpr->rx_jmb_prod_idx; + for (i = di; i < di + cpycnt; i++) { + if (dpr->rx_jmb_buffers[i].skb) { + cpycnt = i - di; + break; + } + } + + if (!cpycnt) + break; + + /* Ensure that updates to the rx_jmb_buffers ring and the + * shadowed hardware producer ring from tg3_recycle_skb() are + * ordered correctly WRT the skb check above. + */ + smp_rmb(); + memcpy(&dpr->rx_jmb_buffers[di], &spr->rx_jmb_buffers[si], cpycnt * sizeof(struct ring_info)); -- cgit v1.2.3 From f89f38b8ec3171664314669a1396ab70b43e8961 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:07 +0000 Subject: tg3: Unwedge stuck MSI-X vectors The previous patch changed the code so that new rx buffer submissions to the hardware stall if a new submission would overwrite data needed by an unserviced rx packet. On very busy 5717 and 57765 asic rev devices, there is a corner case where the hardware will fail to assert an MSI-X interrupt for rx traffic. If that vector's interrupt never has another reason to assert, any rx buffers held will never be serviced. If the buffers are never serviced and the hardware consumes all the available rx packets for other rx rings, deadlock will result. The most reliable and least intrusive way to work around the problem is to detect the case where new submissions would overwrite existing data and force all rx interrupt vectors to fire. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 29 +++++++++++++++++++---------- drivers/net/tg3.h | 1 + 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index a46c26764ba7..c140e1bf6e02 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -642,7 +642,6 @@ static void tg3_disable_ints(struct tg3 *tp) static void tg3_enable_ints(struct tg3 *tp) { int i; - u32 coal_now = 0; tp->irq_sync = 0; wmb(); @@ -650,13 +649,14 @@ static void tg3_enable_ints(struct tg3 *tp) tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); + tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE; for (i = 0; i < tp->irq_cnt; i++) { struct tg3_napi *tnapi = &tp->napi[i]; tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24); - coal_now |= tnapi->coal_now; + tp->coal_now |= tnapi->coal_now; } /* Force an initial interrupt */ @@ -664,8 +664,9 @@ static void tg3_enable_ints(struct tg3 *tp) (tp->napi[0].hw_status->status & SD_STATUS_UPDATED)) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT); else - tw32(HOSTCC_MODE, tp->coalesce_mode | - HOSTCC_MODE_ENABLE | coal_now); + tw32(HOSTCC_MODE, tp->coal_now); + + tp->coal_now &= ~(tp->napi[0].coal_now | tp->napi[1].coal_now); } static inline unsigned int tg3_has_work(struct tg3_napi *tnapi) @@ -4794,12 +4795,12 @@ static void tg3_poll_link(struct tg3 *tp) } } -static void tg3_rx_prodring_xfer(struct tg3 *tp, - struct tg3_rx_prodring_set *dpr, - struct tg3_rx_prodring_set *spr) +static int tg3_rx_prodring_xfer(struct tg3 *tp, + struct tg3_rx_prodring_set *dpr, + struct tg3_rx_prodring_set *spr) { u32 si, di, cpycnt, src_prod_idx; - int i; + int i, err = 0; while (1) { src_prod_idx = spr->rx_std_prod_idx; @@ -4825,6 +4826,7 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp, for (i = di; i < di + cpycnt; i++) { if (dpr->rx_std_buffers[i].skb) { cpycnt = i - di; + err = -ENOSPC; break; } } @@ -4881,6 +4883,7 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp, for (i = di; i < di + cpycnt; i++) { if (dpr->rx_jmb_buffers[i].skb) { cpycnt = i - di; + err = -ENOSPC; break; } } @@ -4911,6 +4914,8 @@ static void tg3_rx_prodring_xfer(struct tg3 *tp, dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) % TG3_RX_JUMBO_RING_SIZE; } + + return err; } static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) @@ -4933,12 +4938,13 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) if ((tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) && tnapi == &tp->napi[1]) { struct tg3_rx_prodring_set *dpr = &tp->prodring[0]; - int i; + int i, err = 0; u32 std_prod_idx = dpr->rx_std_prod_idx; u32 jmb_prod_idx = dpr->rx_jmb_prod_idx; for (i = 1; i < tp->irq_cnt; i++) - tg3_rx_prodring_xfer(tp, dpr, tp->napi[i].prodring); + err |= tg3_rx_prodring_xfer(tp, dpr, + tp->napi[i].prodring); wmb(); @@ -4951,6 +4957,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) dpr->rx_jmb_prod_idx); mmiowb(); + + if (err) + tw32_f(HOSTCC_MODE, tp->coal_now); } return work_done; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 88a87bb618c0..cc8bf7d6823a 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2699,6 +2699,7 @@ struct tg3 { struct net_device *dev; struct pci_dev *pdev; + u32 coal_now; u32 msg_enable; /* begin "tx thread" cacheline section */ -- cgit v1.2.3 From 6b10c1653e425e30cff7f41d0e6f9743bfa9810f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:08 +0000 Subject: tg3: Fix 57765 A0 bootcode race condition On A0 revision of 57765 asic rev devices, the bootcode will perform some hardware operations, after the magic signature is presented, that will collide with setup operations performed by the driver. The best way to avoid the contention is to have the driver delay an additional 10 milliseconds. B0 revisions of the chip will make this workaround unnecessary. Signed-off-by: Matt Carlson Signed-off-by: Benjamin Li Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 +++++++ drivers/net/tg3.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c140e1bf6e02..2c5e1b7e1088 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6721,6 +6721,13 @@ static int tg3_poll_fw(struct tg3 *tp) tp->dev->name); } + if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { + /* The 57765 A0 needs a little more + * time to do some important work. + */ + mdelay(10); + } + return 0; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cc8bf7d6823a..46db4ad46bbc 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -110,6 +110,7 @@ #define CHIPREV_ID_57780_A0 0x57780000 #define CHIPREV_ID_57780_A1 0x57780001 #define CHIPREV_ID_5717_A0 0x05717000 +#define CHIPREV_ID_57765_A0 0x57785000 #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define ASIC_REV_5700 0x07 #define ASIC_REV_5701 0x00 -- cgit v1.2.3 From 0339e4e3effeae71e2b19c6340ef9672fb7a2cb3 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:09 +0000 Subject: tg3: Turn off multiple DMA reads for 5717 The 5717's DMA read engine has a bug when initiating multiple DMA reads across the PCIe bus. This patch disables the feature. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 +++ drivers/net/tg3.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2c5e1b7e1088..673ea314aa18 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7915,6 +7915,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB | RDMAC_MODE_LNGREAD_ENAB); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) + rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 46db4ad46bbc..a8fb53aaf742 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1258,6 +1258,7 @@ #define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000 #define RDMAC_MODE_FIFO_SIZE_128 0x00020000 #define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 +#define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000 #define RDMAC_MODE_IPV4_LSO_EN 0x08000000 #define RDMAC_MODE_IPV6_LSO_EN 0x10000000 #define RDMAC_STATUS 0x00004804 -- cgit v1.2.3 From 603f11738cee4d46a2a1d394ae80d718f8d37cba Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:10 +0000 Subject: tg3: Reset phy during bringup when using phylib The driver puts the phy into low-power mode when it releases the device. If the device were to be reacquired, the phy needs a reset to bring it back to full powered operation. This patch allows phylib-enabled devices to reset the phy. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 673ea314aa18..33dfb7fda8cc 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7595,8 +7595,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_abort_hw(tp, 1); } - if (reset_phy && - !(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) + if (reset_phy) tg3_phy_reset(tp); err = tg3_chip_reset(tp); -- cgit v1.2.3 From c88734054e787542ea093b02120e324e92cad882 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:11 +0000 Subject: tg3: Fix napi assignments in loopback test The 57765 lacks TSS support. This renders the napi assignments incorrect in the loopback test function. This patch fixes the problem. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 33dfb7fda8cc..cb6967947c30 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10780,12 +10780,12 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) struct tg3_napi *tnapi, *rnapi; struct tg3_rx_prodring_set *tpr = &tp->prodring[0]; + tnapi = &tp->napi[0]; + rnapi = &tp->napi[0]; if (tp->irq_cnt > 1) { - tnapi = &tp->napi[1]; rnapi = &tp->napi[1]; - } else { - tnapi = &tp->napi[0]; - rnapi = &tp->napi[0]; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS) + tnapi = &tp->napi[1]; } coal_now = tnapi->coal_now | rnapi->coal_now; -- cgit v1.2.3 From 1061b7c56482310bbb8197045d51e2986afabfce Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:12 +0000 Subject: tg3: Fix AC131 loopback test errors for 5785 The AC131 does not enable the forced transmit clock settings immediately. The workaround is to read the register again to get the setting to take effect. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reviewed-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 ++++++-- drivers/net/tg3.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index cb6967947c30..128126a87c34 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10822,8 +10822,12 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; if (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) { - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) - tg3_writephy(tp, MII_TG3_FET_PTEST, 0x1800); + tg3_writephy(tp, MII_TG3_FET_PTEST, + MII_TG3_FET_PTEST_FRC_TX_LINK | + MII_TG3_FET_PTEST_FRC_TX_LOCK); + /* The write needs to be flushed for the AC131 */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + tg3_readphy(tp, MII_TG3_FET_PTEST, &val); mac_mode |= MAC_MODE_PORT_MODE_MII; } else mac_mode |= MAC_MODE_PORT_MODE_GMII; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index a8fb53aaf742..b4fd59623cfb 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2112,6 +2112,9 @@ /* Fast Ethernet Tranceiver definitions */ #define MII_TG3_FET_PTEST 0x17 +#define MII_TG3_FET_PTEST_FRC_TX_LINK 0x1000 +#define MII_TG3_FET_PTEST_FRC_TX_LOCK 0x0800 + #define MII_TG3_FET_TEST 0x1f #define MII_TG3_FET_SHADOW_EN 0x0080 -- cgit v1.2.3 From b3b3f04fb587ecb61b5baa6c1c5f0e666fd12d73 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 12 Feb 2010 14:47:13 +0000 Subject: tg3: Update driver version to 3.107 This patch updates the tg3 version to 3.107. Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 128126a87c34..385434ff3960 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.106" -#define DRV_MODULE_RELDATE "January 12, 2010" +#define DRV_MODULE_VERSION "3.107" +#define DRV_MODULE_RELDATE "February 12, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From 1a5778aa000ebfec7f07eed0ffa2852ffb5d16bb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 14 Feb 2010 22:35:47 -0800 Subject: net: Fix first line of kernel-doc for a few functions The function name must be followed by a space, hypen, space, and a short description. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- include/linux/skbuff.h | 4 ++-- include/net/sock.h | 2 +- net/sunrpc/rpc_pipe.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ae836fded530..ba0f8e3a9cda 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -738,7 +738,7 @@ static inline struct sk_buff *skb_unshare(struct sk_buff *skb, } /** - * skb_peek + * skb_peek - peek at the head of an &sk_buff_head * @list_: list to peek at * * Peek an &sk_buff. Unlike most other operations you _MUST_ @@ -759,7 +759,7 @@ static inline struct sk_buff *skb_peek(struct sk_buff_head *list_) } /** - * skb_peek_tail + * skb_peek_tail - peek at the tail of an &sk_buff_head * @list_: list to peek at * * Peek an &sk_buff. Unlike most other operations you _MUST_ diff --git a/include/net/sock.h b/include/net/sock.h index c8d400063c16..580d51fa28e9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1049,7 +1049,7 @@ extern void sk_common_release(struct sock *sk); extern void sock_init_data(struct socket *sock, struct sock *sk); /** - * sk_filter_release: Release a socket filter + * sk_filter_release - release a socket filter * @fp: filter to remove * * Remove a filter from a socket and release its resources. diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 49278f830367..9ea45383480e 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -78,7 +78,7 @@ rpc_timeout_upcall_queue(struct work_struct *work) } /** - * rpc_queue_upcall + * rpc_queue_upcall - queue an upcall message to userspace * @inode: inode of upcall pipe on which to queue given message * @msg: message to queue * -- cgit v1.2.3 From a1467085dcad8214bbb1d7edafbaa295cbd8c0e7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 14 Feb 2010 22:38:54 -0800 Subject: ethtool: Fix includes build break Based upon a patch by Oliver Hartkopp . Signed-off-by: David S. Miller --- include/linux/ethtool.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index a3cac53a0766..cca1c3de140d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -14,7 +14,6 @@ #define _LINUX_ETHTOOL_H #include -#include /* This should work for both 32 and 64 bit userland. */ struct ethtool_cmd { @@ -409,6 +408,8 @@ struct ethtool_flash { #ifdef __KERNEL__ +#include + struct ethtool_rx_ntuple_flow_spec_container { struct ethtool_rx_ntuple_flow_spec fs; struct list_head list; -- cgit v1.2.3 From f10a1f2e7e93a35cb603b63090ff0e70a576a641 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 14 Feb 2010 22:40:39 -0800 Subject: niu: Use pr_, netdev_ and netif_ macros Remove #define PFX Add pr_fmt(fmt) KBUILD_MODNAME ": " fmt Convert printks to pr_ Convert printks without levels to pr_cont Convert pr_ with np->dev to netdev_ Convert dev_ to netdev_ Convert niudbg to netif_printk Convert niuinfo, niuwarn macros to netif_(priv, type, dev... Coalesce long formats Convert embedded function names to "%s", __func__ Always use "%s()..." when __func__ is printed Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/niu.c | 703 ++++++++++++++++++++++++------------------------------ 1 file changed, 311 insertions(+), 392 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 7b52d9762b00..347788f11c74 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3,6 +3,8 @@ * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net) */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -33,7 +35,6 @@ #include "niu.h" #define DRV_MODULE_NAME "niu" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "1.0" #define DRV_MODULE_RELDATE "Nov 14, 2008" @@ -89,21 +90,6 @@ static int debug = -1; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "NIU debug level"); -#define niudbg(TYPE, f, a...) \ -do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \ - printk(KERN_DEBUG PFX f, ## a); \ -} while (0) - -#define niuinfo(TYPE, f, a...) \ -do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \ - printk(KERN_INFO PFX f, ## a); \ -} while (0) - -#define niuwarn(TYPE, f, a...) \ -do { if ((np)->msg_enable & NETIF_MSG_##TYPE) \ - printk(KERN_WARNING PFX f, ## a); \ -} while (0) - #define niu_lock_parent(np, flags) \ spin_lock_irqsave(&np->parent->lock, flags) #define niu_unlock_parent(np, flags) \ @@ -135,10 +121,9 @@ static int __niu_set_and_wait_clear_mac(struct niu *np, unsigned long reg, nw64_mac(reg, bits); err = __niu_wait_bits_clear_mac(np, reg, bits, limit, delay); if (err) - dev_err(np->device, PFX "%s: bits (%llx) of register %s " - "would not clear, val[%llx]\n", - np->dev->name, (unsigned long long) bits, reg_name, - (unsigned long long) nr64_mac(reg)); + netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", + (unsigned long long)bits, reg_name, + (unsigned long long)nr64_mac(reg)); return err; } @@ -175,10 +160,9 @@ static int __niu_set_and_wait_clear_ipp(struct niu *np, unsigned long reg, err = __niu_wait_bits_clear_ipp(np, reg, bits, limit, delay); if (err) - dev_err(np->device, PFX "%s: bits (%llx) of register %s " - "would not clear, val[%llx]\n", - np->dev->name, (unsigned long long) bits, reg_name, - (unsigned long long) nr64_ipp(reg)); + netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", + (unsigned long long)bits, reg_name, + (unsigned long long)nr64_ipp(reg)); return err; } @@ -216,10 +200,9 @@ static int __niu_set_and_wait_clear(struct niu *np, unsigned long reg, nw64(reg, bits); err = __niu_wait_bits_clear(np, reg, bits, limit, delay); if (err) - dev_err(np->device, PFX "%s: bits (%llx) of register %s " - "would not clear, val[%llx]\n", - np->dev->name, (unsigned long long) bits, reg_name, - (unsigned long long) nr64(reg)); + netdev_err(np->dev, "bits (%llx) of register %s would not clear, val[%llx]\n", + (unsigned long long)bits, reg_name, + (unsigned long long)nr64(reg)); return err; } @@ -475,9 +458,8 @@ static int serdes_init_niu_1g_serdes(struct niu *np) err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, ESR2_TI_PLL_CFG_L, pll_cfg); if (err) { - dev_err(np->device, PFX "NIU Port %d " - "serdes_init_niu_1g_serdes: " - "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); + netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n", + np->port, __func__); return err; } @@ -486,9 +468,8 @@ static int serdes_init_niu_1g_serdes(struct niu *np) err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, ESR2_TI_PLL_STS_L, pll_sts); if (err) { - dev_err(np->device, PFX "NIU Port %d " - "serdes_init_niu_1g_serdes: " - "mdio write to ESR2_TI_PLL_STS_L failed", np->port); + netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n", + np->port, __func__); return err; } @@ -531,8 +512,8 @@ static int serdes_init_niu_1g_serdes(struct niu *np) } if ((sig & mask) != val) { - dev_err(np->device, PFX "Port %u signal bits [%08x] are not " - "[%08x]\n", np->port, (int) (sig & mask), (int) val); + netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", + np->port, (int)(sig & mask), (int)val); return -ENODEV; } @@ -569,9 +550,8 @@ static int serdes_init_niu_10g_serdes(struct niu *np) err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff); if (err) { - dev_err(np->device, PFX "NIU Port %d " - "serdes_init_niu_10g_serdes: " - "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); + netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_CFG_L failed\n", + np->port, __func__); return err; } @@ -580,9 +560,8 @@ static int serdes_init_niu_10g_serdes(struct niu *np) err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, ESR2_TI_PLL_STS_L, pll_sts & 0xffff); if (err) { - dev_err(np->device, PFX "NIU Port %d " - "serdes_init_niu_10g_serdes: " - "mdio write to ESR2_TI_PLL_STS_L failed", np->port); + netdev_err(np->dev, "NIU Port %d %s() mdio write to ESR2_TI_PLL_STS_L failed\n", + np->port, __func__); return err; } @@ -639,9 +618,8 @@ static int serdes_init_niu_10g_serdes(struct niu *np) } if ((sig & mask) != val) { - pr_info(PFX "NIU Port %u signal bits [%08x] are not " - "[%08x] for 10G...trying 1G\n", - np->port, (int) (sig & mask), (int) val); + pr_info("NIU Port %u signal bits [%08x] are not [%08x] for 10G...trying 1G\n", + np->port, (int)(sig & mask), (int)val); /* 10G failed, try initializing at 1G */ err = serdes_init_niu_1g_serdes(np); @@ -649,8 +627,8 @@ static int serdes_init_niu_10g_serdes(struct niu *np) np->flags &= ~NIU_FLAGS_10G; np->mac_xcvr = MAC_XCVR_PCS; } else { - dev_err(np->device, PFX "Port %u 10G/1G SERDES " - "Link Failed \n", np->port); + netdev_err(np->dev, "Port %u 10G/1G SERDES Link Failed\n", + np->port); return -ENODEV; } } @@ -764,9 +742,8 @@ static int esr_reset(struct niu *np) if (err) return err; if (reset != 0) { - dev_err(np->device, PFX "Port %u ESR_RESET " - "did not clear [%08x]\n", - np->port, reset); + netdev_err(np->dev, "Port %u ESR_RESET did not clear [%08x]\n", + np->port, reset); return -ENODEV; } @@ -890,8 +867,8 @@ static int serdes_init_10g(struct niu *np) np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; return 0; } - dev_err(np->device, PFX "Port %u signal bits [%08x] are not " - "[%08x]\n", np->port, (int) (sig & mask), (int) val); + netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", + np->port, (int)(sig & mask), (int)val); return -ENODEV; } if (np->flags & NIU_FLAGS_HOTPLUG_PHY) @@ -1039,8 +1016,8 @@ static int serdes_init_1g_serdes(struct niu *np) } if ((sig & mask) != val) { - dev_err(np->device, PFX "Port %u signal bits [%08x] are not " - "[%08x]\n", np->port, (int) (sig & mask), (int) val); + netdev_err(np->dev, "Port %u signal bits [%08x] are not [%08x]\n", + np->port, (int)(sig & mask), (int)val); return -ENODEV; } @@ -1332,8 +1309,8 @@ static int bcm8704_reset(struct niu *np) break; } if (limit < 0) { - dev_err(np->device, PFX "Port %u PHY will not reset " - "(bmcr=%04x)\n", np->port, (err & 0xffff)); + netdev_err(np->dev, "Port %u PHY will not reset (bmcr=%04x)\n", + np->port, (err & 0xffff)); return -ENODEV; } return 0; @@ -1515,21 +1492,18 @@ static int xcvr_diag_bcm870x(struct niu *np) MII_STAT1000); if (err < 0) return err; - pr_info(PFX "Port %u PMA_PMD(MII_STAT1000) [%04x]\n", - np->port, err); + pr_info("Port %u PMA_PMD(MII_STAT1000) [%04x]\n", np->port, err); err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR, 0x20); if (err < 0) return err; - pr_info(PFX "Port %u USER_DEV3(0x20) [%04x]\n", - np->port, err); + pr_info("Port %u USER_DEV3(0x20) [%04x]\n", np->port, err); err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, MII_NWAYTEST); if (err < 0) return err; - pr_info(PFX "Port %u PHYXS(MII_NWAYTEST) [%04x]\n", - np->port, err); + pr_info("Port %u PHYXS(MII_NWAYTEST) [%04x]\n", np->port, err); #endif /* XXX dig this out it might not be so useful XXX */ @@ -1555,11 +1529,11 @@ static int xcvr_diag_bcm870x(struct niu *np) if (analog_stat0 != 0x03fc) { if ((analog_stat0 == 0x43bc) && (tx_alarm_status != 0)) { - pr_info(PFX "Port %u cable not connected " - "or bad cable.\n", np->port); + pr_info("Port %u cable not connected or bad cable\n", + np->port); } else if (analog_stat0 == 0x639c) { - pr_info(PFX "Port %u optical module is bad " - "or missing.\n", np->port); + pr_info("Port %u optical module is bad or missing\n", + np->port); } } @@ -1699,8 +1673,8 @@ static int mii_reset(struct niu *np) break; } if (limit < 0) { - dev_err(np->device, PFX "Port %u MII would not reset, " - "bmcr[%04x]\n", np->port, err); + netdev_err(np->dev, "Port %u MII would not reset, bmcr[%04x]\n", + np->port, err); return -ENODEV; } @@ -1895,7 +1869,7 @@ static int mii_init_common(struct niu *np) return err; bmsr = err; - pr_info(PFX "Port %u after MII init bmcr[%04x] bmsr[%04x]\n", + pr_info("Port %u after MII init bmcr[%04x] bmsr[%04x]\n", np->port, bmcr, bmsr); #endif @@ -1948,16 +1922,12 @@ static int niu_link_status_common(struct niu *np, int link_up) unsigned long flags; if (!netif_carrier_ok(dev) && link_up) { - niuinfo(LINK, "%s: Link is up at %s, %s duplex\n", - dev->name, - (lp->active_speed == SPEED_10000 ? - "10Gb/sec" : - (lp->active_speed == SPEED_1000 ? - "1Gb/sec" : - (lp->active_speed == SPEED_100 ? - "100Mbit/sec" : "10Mbit/sec"))), - (lp->active_duplex == DUPLEX_FULL ? - "full" : "half")); + netif_info(np, link, dev, "Link is up at %s, %s duplex\n", + lp->active_speed == SPEED_10000 ? "10Gb/sec" : + lp->active_speed == SPEED_1000 ? "1Gb/sec" : + lp->active_speed == SPEED_100 ? "100Mbit/sec" : + "10Mbit/sec", + lp->active_duplex == DUPLEX_FULL ? "full" : "half"); spin_lock_irqsave(&np->lock, flags); niu_init_xif(np); @@ -1966,7 +1936,7 @@ static int niu_link_status_common(struct niu *np, int link_up) netif_carrier_on(dev); } else if (netif_carrier_ok(dev) && !link_up) { - niuwarn(LINK, "%s: Link is down\n", dev->name); + netif_warn(np, link, dev, "Link is down\n"); spin_lock_irqsave(&np->lock, flags); niu_handle_led(np, 0); spin_unlock_irqrestore(&np->lock, flags); @@ -2232,8 +2202,8 @@ static int link_status_10g_hotplug(struct niu *np, int *link_up_p) } else { np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; *link_up_p = 0; - niuwarn(LINK, "%s: Hotplug PHY Removed\n", - np->dev->name); + netif_warn(np, link, np->dev, + "Hotplug PHY Removed\n"); } } out: @@ -2531,8 +2501,8 @@ static int serdes_init_10g_serdes(struct niu *np) np->flags &= ~NIU_FLAGS_10G; np->mac_xcvr = MAC_XCVR_PCS; } else { - dev_err(np->device, PFX "Port %u 10G/1G SERDES Link Failed \n", - np->port); + netdev_err(np->dev, "Port %u 10G/1G SERDES Link Failed\n", + np->port); return -ENODEV; } } @@ -3234,23 +3204,25 @@ static int fflp_early_init(struct niu *np) parent = np->parent; err = 0; if (!(parent->flags & PARENT_FLGS_CLS_HWINIT)) { - niudbg(PROBE, "fflp_early_init: Initting hw on port %u\n", - np->port); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() Initting hw on port %u\n", + __func__, np->port); if (np->parent->plat_type != PLAT_TYPE_NIU) { fflp_reset(np); fflp_set_timings(np); err = fflp_disable_all_partitions(np); if (err) { - niudbg(PROBE, "fflp_disable_all_partitions " - "failed, err=%d\n", err); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "fflp_disable_all_partitions failed, err=%d\n", + err); goto out; } } err = tcam_early_init(np); if (err) { - niudbg(PROBE, "tcam_early_init failed, err=%d\n", - err); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "tcam_early_init failed, err=%d\n", err); goto out; } fflp_llcsnap_enable(np, 1); @@ -3260,22 +3232,24 @@ static int fflp_early_init(struct niu *np) err = tcam_flush_all(np); if (err) { - niudbg(PROBE, "tcam_flush_all failed, err=%d\n", - err); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "tcam_flush_all failed, err=%d\n", err); goto out; } if (np->parent->plat_type != PLAT_TYPE_NIU) { err = fflp_hash_clear(np); if (err) { - niudbg(PROBE, "fflp_hash_clear failed, " - "err=%d\n", err); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "fflp_hash_clear failed, err=%d\n", + err); goto out; } } vlan_tbl_clear(np); - niudbg(PROBE, "fflp_early_init: Success\n"); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() Success\n", __func__); parent->flags |= PARENT_FLGS_CLS_HWINIT; } out: @@ -3665,8 +3639,8 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) cons = rp->cons; - niudbg(TX_DONE, "%s: niu_tx_work() pkt_cnt[%u] cons[%d]\n", - np->dev->name, pkt_cnt, cons); + netif_printk(np, tx_done, KERN_DEBUG, np->dev, + "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons); while (pkt_cnt--) cons = release_tx_packet(np, rp, cons); @@ -3714,11 +3688,12 @@ static inline void niu_sync_rx_discard_stats(struct niu *np, rp->rx_errors += misc & RXMISC_COUNT; if (unlikely(misc & RXMISC_OFLOW)) - dev_err(np->device, "rx-%d: Counter overflow " - "RXMISC discard\n", rx_channel); + dev_err(np->device, "rx-%d: Counter overflow RXMISC discard\n", + rx_channel); - niudbg(RX_ERR, "%s-rx-%d: MISC drop=%u over=%u\n", - np->dev->name, rx_channel, misc, misc-limit); + netif_printk(np, rx_err, KERN_DEBUG, np->dev, + "rx-%d: MISC drop=%u over=%u\n", + rx_channel, misc, misc-limit); } /* WRED (Weighted Random Early Discard) by hardware */ @@ -3728,11 +3703,11 @@ static inline void niu_sync_rx_discard_stats(struct niu *np, rp->rx_dropped += wred & RED_DIS_CNT_COUNT; if (unlikely(wred & RED_DIS_CNT_OFLOW)) - dev_err(np->device, "rx-%d: Counter overflow " - "WRED discard\n", rx_channel); + dev_err(np->device, "rx-%d: Counter overflow WRED discard\n", rx_channel); - niudbg(RX_ERR, "%s-rx-%d: WRED drop=%u over=%u\n", - np->dev->name, rx_channel, wred, wred-limit); + netif_printk(np, rx_err, KERN_DEBUG, np->dev, + "rx-%d: WRED drop=%u over=%u\n", + rx_channel, wred, wred-limit); } } @@ -3753,8 +3728,9 @@ static int niu_rx_work(struct napi_struct *napi, struct niu *np, mbox->rx_dma_ctl_stat = 0; mbox->rcrstat_a = 0; - niudbg(RX_STATUS, "%s: niu_rx_work(chan[%d]), stat[%llx] qlen=%d\n", - np->dev->name, rp->rx_channel, (unsigned long long) stat, qlen); + netif_printk(np, rx_status, KERN_DEBUG, np->dev, + "%s(chan[%d]), stat[%llx] qlen=%d\n", + __func__, rp->rx_channel, (unsigned long long)stat, qlen); rcr_done = work_done = 0; qlen = min(qlen, budget); @@ -3791,8 +3767,8 @@ static int niu_poll_core(struct niu *np, struct niu_ldg *lp, int budget) u32 rx_vec = (v0 & 0xffffffff); int i, work_done = 0; - niudbg(INTR, "%s: niu_poll_core() v0[%016llx]\n", - np->dev->name, (unsigned long long) v0); + netif_printk(np, intr, KERN_DEBUG, np->dev, + "%s() v0[%016llx]\n", __func__, (unsigned long long)v0); for (i = 0; i < np->num_tx_rings; i++) { struct tx_ring_info *rp = &np->tx_rings[i]; @@ -3837,39 +3813,38 @@ static int niu_poll(struct napi_struct *napi, int budget) static void niu_log_rxchan_errors(struct niu *np, struct rx_ring_info *rp, u64 stat) { - dev_err(np->device, PFX "%s: RX channel %u errors ( ", - np->dev->name, rp->rx_channel); + netdev_err(np->dev, "RX channel %u errors ( ", rp->rx_channel); if (stat & RX_DMA_CTL_STAT_RBR_TMOUT) - printk("RBR_TMOUT "); + pr_cont("RBR_TMOUT "); if (stat & RX_DMA_CTL_STAT_RSP_CNT_ERR) - printk("RSP_CNT "); + pr_cont("RSP_CNT "); if (stat & RX_DMA_CTL_STAT_BYTE_EN_BUS) - printk("BYTE_EN_BUS "); + pr_cont("BYTE_EN_BUS "); if (stat & RX_DMA_CTL_STAT_RSP_DAT_ERR) - printk("RSP_DAT "); + pr_cont("RSP_DAT "); if (stat & RX_DMA_CTL_STAT_RCR_ACK_ERR) - printk("RCR_ACK "); + pr_cont("RCR_ACK "); if (stat & RX_DMA_CTL_STAT_RCR_SHA_PAR) - printk("RCR_SHA_PAR "); + pr_cont("RCR_SHA_PAR "); if (stat & RX_DMA_CTL_STAT_RBR_PRE_PAR) - printk("RBR_PRE_PAR "); + pr_cont("RBR_PRE_PAR "); if (stat & RX_DMA_CTL_STAT_CONFIG_ERR) - printk("CONFIG "); + pr_cont("CONFIG "); if (stat & RX_DMA_CTL_STAT_RCRINCON) - printk("RCRINCON "); + pr_cont("RCRINCON "); if (stat & RX_DMA_CTL_STAT_RCRFULL) - printk("RCRFULL "); + pr_cont("RCRFULL "); if (stat & RX_DMA_CTL_STAT_RBRFULL) - printk("RBRFULL "); + pr_cont("RBRFULL "); if (stat & RX_DMA_CTL_STAT_RBRLOGPAGE) - printk("RBRLOGPAGE "); + pr_cont("RBRLOGPAGE "); if (stat & RX_DMA_CTL_STAT_CFIGLOGPAGE) - printk("CFIGLOGPAGE "); + pr_cont("CFIGLOGPAGE "); if (stat & RX_DMA_CTL_STAT_DC_FIFO_ERR) - printk("DC_FIDO "); + pr_cont("DC_FIDO "); - printk(")\n"); + pr_cont(")\n"); } static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) @@ -3883,9 +3858,9 @@ static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) err = -EINVAL; if (err) { - dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n", - np->dev->name, rp->rx_channel, - (unsigned long long) stat); + netdev_err(np->dev, "RX channel %u error, stat[%llx]\n", + rp->rx_channel, + (unsigned long long) stat); niu_log_rxchan_errors(np, rp, stat); } @@ -3899,27 +3874,26 @@ static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) static void niu_log_txchan_errors(struct niu *np, struct tx_ring_info *rp, u64 cs) { - dev_err(np->device, PFX "%s: TX channel %u errors ( ", - np->dev->name, rp->tx_channel); + netdev_err(np->dev, "TX channel %u errors ( ", rp->tx_channel); if (cs & TX_CS_MBOX_ERR) - printk("MBOX "); + pr_cont("MBOX "); if (cs & TX_CS_PKT_SIZE_ERR) - printk("PKT_SIZE "); + pr_cont("PKT_SIZE "); if (cs & TX_CS_TX_RING_OFLOW) - printk("TX_RING_OFLOW "); + pr_cont("TX_RING_OFLOW "); if (cs & TX_CS_PREF_BUF_PAR_ERR) - printk("PREF_BUF_PAR "); + pr_cont("PREF_BUF_PAR "); if (cs & TX_CS_NACK_PREF) - printk("NACK_PREF "); + pr_cont("NACK_PREF "); if (cs & TX_CS_NACK_PKT_RD) - printk("NACK_PKT_RD "); + pr_cont("NACK_PKT_RD "); if (cs & TX_CS_CONF_PART_ERR) - printk("CONF_PART "); + pr_cont("CONF_PART "); if (cs & TX_CS_PKT_PRT_ERR) - printk("PKT_PTR "); + pr_cont("PKT_PTR "); - printk(")\n"); + pr_cont(")\n"); } static int niu_tx_error(struct niu *np, struct tx_ring_info *rp) @@ -3930,12 +3904,11 @@ static int niu_tx_error(struct niu *np, struct tx_ring_info *rp) logh = nr64(TX_RNG_ERR_LOGH(rp->tx_channel)); logl = nr64(TX_RNG_ERR_LOGL(rp->tx_channel)); - dev_err(np->device, PFX "%s: TX channel %u error, " - "cs[%llx] logh[%llx] logl[%llx]\n", - np->dev->name, rp->tx_channel, - (unsigned long long) cs, - (unsigned long long) logh, - (unsigned long long) logl); + netdev_err(np->dev, "TX channel %u error, cs[%llx] logh[%llx] logl[%llx]\n", + rp->tx_channel, + (unsigned long long)cs, + (unsigned long long)logh, + (unsigned long long)logl); niu_log_txchan_errors(np, rp, cs); @@ -3954,9 +3927,8 @@ static int niu_mif_interrupt(struct niu *np) phy_mdint = 1; } - dev_err(np->device, PFX "%s: MIF interrupt, " - "stat[%llx] phy_mdint(%d)\n", - np->dev->name, (unsigned long long) mif_status, phy_mdint); + netdev_err(np->dev, "MIF interrupt, stat[%llx] phy_mdint(%d)\n", + (unsigned long long)mif_status, phy_mdint); return -ENODEV; } @@ -4081,41 +4053,40 @@ static int niu_mac_interrupt(struct niu *np) static void niu_log_device_error(struct niu *np, u64 stat) { - dev_err(np->device, PFX "%s: Core device errors ( ", - np->dev->name); + netdev_err(np->dev, "Core device errors ( "); if (stat & SYS_ERR_MASK_META2) - printk("META2 "); + pr_cont("META2 "); if (stat & SYS_ERR_MASK_META1) - printk("META1 "); + pr_cont("META1 "); if (stat & SYS_ERR_MASK_PEU) - printk("PEU "); + pr_cont("PEU "); if (stat & SYS_ERR_MASK_TXC) - printk("TXC "); + pr_cont("TXC "); if (stat & SYS_ERR_MASK_RDMC) - printk("RDMC "); + pr_cont("RDMC "); if (stat & SYS_ERR_MASK_TDMC) - printk("TDMC "); + pr_cont("TDMC "); if (stat & SYS_ERR_MASK_ZCP) - printk("ZCP "); + pr_cont("ZCP "); if (stat & SYS_ERR_MASK_FFLP) - printk("FFLP "); + pr_cont("FFLP "); if (stat & SYS_ERR_MASK_IPP) - printk("IPP "); + pr_cont("IPP "); if (stat & SYS_ERR_MASK_MAC) - printk("MAC "); + pr_cont("MAC "); if (stat & SYS_ERR_MASK_SMX) - printk("SMX "); + pr_cont("SMX "); - printk(")\n"); + pr_cont(")\n"); } static int niu_device_error(struct niu *np) { u64 stat = nr64(SYS_ERR_STAT); - dev_err(np->device, PFX "%s: Core device error, stat[%llx]\n", - np->dev->name, (unsigned long long) stat); + netdev_err(np->dev, "Core device error, stat[%llx]\n", + (unsigned long long)stat); niu_log_device_error(np, stat); @@ -4197,8 +4168,8 @@ static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp, RX_DMA_CTL_STAT_RCRTO); nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat_write); - niudbg(INTR, "%s: rxchan_intr stat[%llx]\n", - np->dev->name, (unsigned long long) stat); + netif_printk(np, intr, KERN_DEBUG, np->dev, + "%s() stat[%llx]\n", __func__, (unsigned long long)stat); } static void niu_txchan_intr(struct niu *np, struct tx_ring_info *rp, @@ -4206,8 +4177,8 @@ static void niu_txchan_intr(struct niu *np, struct tx_ring_info *rp, { rp->tx_cs = nr64(TX_CS(rp->tx_channel)); - niudbg(INTR, "%s: txchan_intr cs[%llx]\n", - np->dev->name, (unsigned long long) rp->tx_cs); + netif_printk(np, intr, KERN_DEBUG, np->dev, + "%s() cs[%llx]\n", __func__, (unsigned long long)rp->tx_cs); } static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0) @@ -4265,8 +4236,8 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) u64 v0, v1, v2; if (netif_msg_intr(np)) - printk(KERN_DEBUG PFX "niu_interrupt() ldg[%p](%d) ", - lp, ldg); + printk(KERN_DEBUG KBUILD_MODNAME ": " "%s() ldg[%p](%d)", + __func__, lp, ldg); spin_lock_irqsave(&np->lock, flags); @@ -4275,11 +4246,13 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) v2 = nr64(LDSV2(ldg)); if (netif_msg_intr(np)) - printk("v0[%llx] v1[%llx] v2[%llx]\n", + pr_cont(" v0[%llx] v1[%llx] v2[%llx]", (unsigned long long) v0, (unsigned long long) v1, (unsigned long long) v2); + pr_cont("\n"); + if (unlikely(!v0 && !v1 && !v2)) { spin_unlock_irqrestore(&np->lock, flags); return IRQ_NONE; @@ -4400,8 +4373,8 @@ static int niu_alloc_rx_ring_info(struct niu *np, if (!rp->mbox) return -ENOMEM; if ((unsigned long)rp->mbox & (64UL - 1)) { - dev_err(np->device, PFX "%s: Coherent alloc gives misaligned " - "RXDMA mailbox %p\n", np->dev->name, rp->mbox); + netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA mailbox %p\n", + rp->mbox); return -EINVAL; } @@ -4411,8 +4384,8 @@ static int niu_alloc_rx_ring_info(struct niu *np, if (!rp->rcr) return -ENOMEM; if ((unsigned long)rp->rcr & (64UL - 1)) { - dev_err(np->device, PFX "%s: Coherent alloc gives misaligned " - "RXDMA RCR table %p\n", np->dev->name, rp->rcr); + netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA RCR table %p\n", + rp->rcr); return -EINVAL; } rp->rcr_table_size = MAX_RCR_RING_SIZE; @@ -4424,8 +4397,8 @@ static int niu_alloc_rx_ring_info(struct niu *np, if (!rp->rbr) return -ENOMEM; if ((unsigned long)rp->rbr & (64UL - 1)) { - dev_err(np->device, PFX "%s: Coherent alloc gives misaligned " - "RXDMA RBR table %p\n", np->dev->name, rp->rbr); + netdev_err(np->dev, "Coherent alloc gives misaligned RXDMA RBR table %p\n", + rp->rbr); return -EINVAL; } rp->rbr_table_size = MAX_RBR_RING_SIZE; @@ -4458,8 +4431,8 @@ static int niu_alloc_tx_ring_info(struct niu *np, if (!rp->mbox) return -ENOMEM; if ((unsigned long)rp->mbox & (64UL - 1)) { - dev_err(np->device, PFX "%s: Coherent alloc gives misaligned " - "TXDMA mailbox %p\n", np->dev->name, rp->mbox); + netdev_err(np->dev, "Coherent alloc gives misaligned TXDMA mailbox %p\n", + rp->mbox); return -EINVAL; } @@ -4469,8 +4442,8 @@ static int niu_alloc_tx_ring_info(struct niu *np, if (!rp->descr) return -ENOMEM; if ((unsigned long)rp->descr & (64UL - 1)) { - dev_err(np->device, PFX "%s: Coherent alloc gives misaligned " - "TXDMA descr table %p\n", np->dev->name, rp->descr); + netdev_err(np->dev, "Coherent alloc gives misaligned TXDMA descr table %p\n", + rp->descr); return -EINVAL; } @@ -4726,10 +4699,8 @@ static int niu_init_one_tx_channel(struct niu *np, struct tx_ring_info *rp) if (rp->descr_dma & ~(TX_RNG_CFIG_STADDR_BASE | TX_RNG_CFIG_STADDR)) { - dev_err(np->device, PFX "%s: TX ring channel %d " - "DMA addr (%llx) is not aligned.\n", - np->dev->name, channel, - (unsigned long long) rp->descr_dma); + netdev_err(np->dev, "TX ring channel %d DMA addr (%llx) is not aligned\n", + channel, (unsigned long long)rp->descr_dma); return -EINVAL; } @@ -4746,10 +4717,8 @@ static int niu_init_one_tx_channel(struct niu *np, struct tx_ring_info *rp) if (((rp->mbox_dma >> 32) & ~TXDMA_MBH_MBADDR) || ((u32)rp->mbox_dma & ~TXDMA_MBL_MBADDR)) { - dev_err(np->device, PFX "%s: TX ring channel %d " - "MBOX addr (%llx) is has illegal bits.\n", - np->dev->name, channel, - (unsigned long long) rp->mbox_dma); + netdev_err(np->dev, "TX ring channel %d MBOX addr (%llx) has invalid bits\n", + channel, (unsigned long long)rp->mbox_dma); return -EINVAL; } nw64(TXDMA_MBH(channel), rp->mbox_dma >> 32); @@ -5146,9 +5115,8 @@ static int niu_zcp_read(struct niu *np, int index, u64 *data) err = niu_wait_bits_clear(np, ZCP_RAM_ACC, ZCP_RAM_ACC_BUSY, 1000, 100); if (err) { - dev_err(np->device, PFX "%s: ZCP read busy won't clear, " - "ZCP_RAM_ACC[%llx]\n", np->dev->name, - (unsigned long long) nr64(ZCP_RAM_ACC)); + netdev_err(np->dev, "ZCP read busy won't clear, ZCP_RAM_ACC[%llx]\n", + (unsigned long long)nr64(ZCP_RAM_ACC)); return err; } @@ -5160,9 +5128,8 @@ static int niu_zcp_read(struct niu *np, int index, u64 *data) err = niu_wait_bits_clear(np, ZCP_RAM_ACC, ZCP_RAM_ACC_BUSY, 1000, 100); if (err) { - dev_err(np->device, PFX "%s: ZCP read busy2 won't clear, " - "ZCP_RAM_ACC[%llx]\n", np->dev->name, - (unsigned long long) nr64(ZCP_RAM_ACC)); + netdev_err(np->dev, "ZCP read busy2 won't clear, ZCP_RAM_ACC[%llx]\n", + (unsigned long long)nr64(ZCP_RAM_ACC)); return err; } @@ -5527,8 +5494,7 @@ static int niu_reset_tx_bmac(struct niu *np) udelay(100); } if (limit < 0) { - dev_err(np->device, PFX "Port %u TX BMAC would not reset, " - "BTXMAC_SW_RST[%llx]\n", + dev_err(np->device, "Port %u TX BMAC would not reset, BTXMAC_SW_RST[%llx]\n", np->port, (unsigned long long) nr64_mac(BTXMAC_SW_RST)); return -ENODEV; @@ -5629,12 +5595,11 @@ static int niu_reset_rx_xmac(struct niu *np) while (--limit >= 0) { if (!(nr64_mac(XRXMAC_SW_RST) & (XRXMAC_SW_RST_REG_RS | XRXMAC_SW_RST_SOFT_RST))) - break; + break; udelay(100); } if (limit < 0) { - dev_err(np->device, PFX "Port %u RX XMAC would not reset, " - "XRXMAC_SW_RST[%llx]\n", + dev_err(np->device, "Port %u RX XMAC would not reset, XRXMAC_SW_RST[%llx]\n", np->port, (unsigned long long) nr64_mac(XRXMAC_SW_RST)); return -ENODEV; @@ -5655,8 +5620,7 @@ static int niu_reset_rx_bmac(struct niu *np) udelay(100); } if (limit < 0) { - dev_err(np->device, PFX "Port %u RX BMAC would not reset, " - "BRXMAC_SW_RST[%llx]\n", + dev_err(np->device, "Port %u RX BMAC would not reset, BRXMAC_SW_RST[%llx]\n", np->port, (unsigned long long) nr64_mac(BRXMAC_SW_RST)); return -ENODEV; @@ -5960,11 +5924,9 @@ static void niu_disable_ipp(struct niu *np) } if (limit < 0 && (rd != 0 && wr != 1)) { - dev_err(np->device, PFX "%s: IPP would not quiesce, " - "rd_ptr[%llx] wr_ptr[%llx]\n", - np->dev->name, - (unsigned long long) nr64_ipp(IPP_DFIFO_RD_PTR), - (unsigned long long) nr64_ipp(IPP_DFIFO_WR_PTR)); + netdev_err(np->dev, "IPP would not quiesce, rd_ptr[%llx] wr_ptr[%llx]\n", + (unsigned long long)nr64_ipp(IPP_DFIFO_RD_PTR), + (unsigned long long)nr64_ipp(IPP_DFIFO_WR_PTR)); } val = nr64_ipp(IPP_CFIG); @@ -5981,12 +5943,12 @@ static int niu_init_hw(struct niu *np) { int i, err; - niudbg(IFUP, "%s: Initialize TXC\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize TXC\n"); niu_txc_enable_port(np, 1); niu_txc_port_dma_enable(np, 1); niu_txc_set_imask(np, 0); - niudbg(IFUP, "%s: Initialize TX channels\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize TX channels\n"); for (i = 0; i < np->num_tx_rings; i++) { struct tx_ring_info *rp = &np->tx_rings[i]; @@ -5995,27 +5957,27 @@ static int niu_init_hw(struct niu *np) return err; } - niudbg(IFUP, "%s: Initialize RX channels\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize RX channels\n"); err = niu_init_rx_channels(np); if (err) goto out_uninit_tx_channels; - niudbg(IFUP, "%s: Initialize classifier\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize classifier\n"); err = niu_init_classifier_hw(np); if (err) goto out_uninit_rx_channels; - niudbg(IFUP, "%s: Initialize ZCP\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize ZCP\n"); err = niu_init_zcp(np); if (err) goto out_uninit_rx_channels; - niudbg(IFUP, "%s: Initialize IPP\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize IPP\n"); err = niu_init_ipp(np); if (err) goto out_uninit_rx_channels; - niudbg(IFUP, "%s: Initialize MAC\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Initialize MAC\n"); err = niu_init_mac(np); if (err) goto out_uninit_ipp; @@ -6023,16 +5985,16 @@ static int niu_init_hw(struct niu *np) return 0; out_uninit_ipp: - niudbg(IFUP, "%s: Uninit IPP\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit IPP\n"); niu_disable_ipp(np); out_uninit_rx_channels: - niudbg(IFUP, "%s: Uninit RX channels\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit RX channels\n"); niu_stop_rx_channels(np); niu_reset_rx_channels(np); out_uninit_tx_channels: - niudbg(IFUP, "%s: Uninit TX channels\n", np->dev->name); + netif_printk(np, ifup, KERN_DEBUG, np->dev, "Uninit TX channels\n"); niu_stop_tx_channels(np); niu_reset_tx_channels(np); @@ -6041,25 +6003,25 @@ out_uninit_tx_channels: static void niu_stop_hw(struct niu *np) { - niudbg(IFDOWN, "%s: Disable interrupts\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable interrupts\n"); niu_enable_interrupts(np, 0); - niudbg(IFDOWN, "%s: Disable RX MAC\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable RX MAC\n"); niu_enable_rx_mac(np, 0); - niudbg(IFDOWN, "%s: Disable IPP\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Disable IPP\n"); niu_disable_ipp(np); - niudbg(IFDOWN, "%s: Stop TX channels\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Stop TX channels\n"); niu_stop_tx_channels(np); - niudbg(IFDOWN, "%s: Stop RX channels\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Stop RX channels\n"); niu_stop_rx_channels(np); - niudbg(IFDOWN, "%s: Reset TX channels\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Reset TX channels\n"); niu_reset_tx_channels(np); - niudbg(IFDOWN, "%s: Reset RX channels\n", np->dev->name); + netif_printk(np, ifdown, KERN_DEBUG, np->dev, "Reset RX channels\n"); niu_reset_rx_channels(np); } @@ -6384,14 +6346,12 @@ static void niu_set_rx_mode(struct net_device *dev) netdev_for_each_uc_addr(ha, dev) { err = niu_set_alt_mac(np, index, ha->addr); if (err) - printk(KERN_WARNING PFX "%s: Error %d " - "adding alt mac %d\n", - dev->name, err, index); + netdev_warn(dev, "Error %d adding alt mac %d\n", + err, index); err = niu_enable_alt_mac(np, index, 1); if (err) - printk(KERN_WARNING PFX "%s: Error %d " - "enabling alt mac %d\n", - dev->name, err, index); + netdev_warn(dev, "Error %d enabling alt mac %d\n", + err, index); index++; } @@ -6404,9 +6364,8 @@ static void niu_set_rx_mode(struct net_device *dev) for (i = alt_start; i < niu_num_alt_addr(np); i++) { err = niu_enable_alt_mac(np, i, 0); if (err) - printk(KERN_WARNING PFX "%s: Error %d " - "disabling alt mac %d\n", - dev->name, err, i); + netdev_warn(dev, "Error %d disabling alt mac %d\n", + err, i); } } if (dev->flags & IFF_ALLMULTI) { @@ -6570,7 +6529,7 @@ static void niu_tx_timeout(struct net_device *dev) { struct niu *np = netdev_priv(dev); - dev_err(np->device, PFX "%s: Transmit timed out, resetting\n", + dev_err(np->device, "%s: Transmit timed out, resetting\n", dev->name); schedule_work(&np->reset_task); @@ -6672,8 +6631,7 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, if (niu_tx_avail(rp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_tx_stop_queue(txq); - dev_err(np->device, PFX "%s: BUG! Tx ring full when " - "queue awake!\n", dev->name); + dev_err(np->device, "%s: BUG! Tx ring full when queue awake!\n", dev->name); rp->tx_errors++; return NETDEV_TX_BUSY; } @@ -7237,8 +7195,8 @@ static int niu_get_ethtool_tcam_entry(struct niu *np, tp = &parent->tcam[idx]; if (!tp->valid) { - pr_info(PFX "niu%d: %s entry [%d] invalid for idx[%d]\n", - parent->index, np->dev->name, (u16)nfc->fs.location, idx); + netdev_info(np->dev, "niu%d: entry [%d] invalid for idx[%d]\n", + parent->index, (u16)nfc->fs.location, idx); return -EINVAL; } @@ -7248,8 +7206,8 @@ static int niu_get_ethtool_tcam_entry(struct niu *np, ret = niu_class_to_ethflow(class, &fsp->flow_type); if (ret < 0) { - pr_info(PFX "niu%d: %s niu_class_to_ethflow failed\n", - parent->index, np->dev->name); + netdev_info(np->dev, "niu%d: niu_class_to_ethflow failed\n", + parent->index); ret = -EINVAL; goto out; } @@ -7332,9 +7290,8 @@ static int niu_get_ethtool_tcam_all(struct niu *np, if (n_entries != cnt) { /* print warning, this should not happen */ - pr_info(PFX "niu%d: %s In niu_get_ethtool_tcam_all, " - "n_entries[%d] != cnt[%d]!!!\n\n", - np->parent->index, np->dev->name, n_entries, cnt); + netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n", + np->parent->index, __func__, n_entries, cnt); } return 0; @@ -7561,9 +7518,8 @@ static int niu_add_ethtool_tcam_entry(struct niu *np, } } if (!add_usr_cls) { - pr_info(PFX "niu%d: %s niu_add_ethtool_tcam_entry: " - "Could not find/insert class for pid %d\n", - parent->index, np->dev->name, uspec->proto); + netdev_info(np->dev, "niu%d: %s(): Could not find/insert class for pid %d\n", + parent->index, __func__, uspec->proto); ret = -EINVAL; goto out; } @@ -7596,9 +7552,8 @@ static int niu_add_ethtool_tcam_entry(struct niu *np, case AH_V6_FLOW: case ESP_V6_FLOW: /* Not yet implemented */ - pr_info(PFX "niu%d: %s In niu_add_ethtool_tcam_entry: " - "flow %d for IPv6 not implemented\n\n", - parent->index, np->dev->name, fsp->flow_type); + netdev_info(np->dev, "niu%d: In %s(): flow %d for IPv6 not implemented\n", + parent->index, __func__, fsp->flow_type); ret = -EINVAL; goto out; case IP_USER_FLOW: @@ -7607,17 +7562,15 @@ static int niu_add_ethtool_tcam_entry(struct niu *np, class); } else { /* Not yet implemented */ - pr_info(PFX "niu%d: %s In niu_add_ethtool_tcam_entry: " - "usr flow for IPv6 not implemented\n\n", - parent->index, np->dev->name); + netdev_info(np->dev, "niu%d: In %s(): usr flow for IPv6 not implemented\n", + parent->index, __func__); ret = -EINVAL; goto out; } break; default: - pr_info(PFX "niu%d: %s In niu_add_ethtool_tcam_entry: " - "Unknown flow type %d\n\n", - parent->index, np->dev->name, fsp->flow_type); + netdev_info(np->dev, "niu%d: In %s(): Unknown flow type %d\n", + parent->index, __func__, fsp->flow_type); ret = -EINVAL; goto out; } @@ -7627,10 +7580,9 @@ static int niu_add_ethtool_tcam_entry(struct niu *np, tp->assoc_data = TCAM_ASSOCDATA_DISC; } else { if (fsp->ring_cookie >= np->num_rx_rings) { - pr_info(PFX "niu%d: %s In niu_add_ethtool_tcam_entry: " - "Invalid RX ring %lld\n\n", - parent->index, np->dev->name, - (long long) fsp->ring_cookie); + netdev_info(np->dev, "niu%d: In %s(): Invalid RX ring %lld\n", + parent->index, __func__, + (long long)fsp->ring_cookie); ret = -EINVAL; goto out; } @@ -7699,10 +7651,9 @@ static int niu_del_ethtool_tcam_entry(struct niu *np, u32 loc) } } if (i == NIU_L3_PROG_CLS) { - pr_info(PFX "niu%d: %s In niu_del_ethtool_tcam_entry," - "Usr class 0x%llx not found \n", - parent->index, np->dev->name, - (unsigned long long) class); + netdev_info(np->dev, "niu%d: In %s(): Usr class 0x%llx not found\n", + parent->index, __func__, + (unsigned long long)class); ret = -EINVAL; goto out; } @@ -8001,9 +7952,7 @@ static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent, * won't get any interrupts and that's painful to debug. */ if (nr64(LDG_NUM(ldn)) != ldg) { - dev_err(np->device, PFX "Port %u, mis-matched " - "LDG assignment " - "for ldn %d, should be %d is %llu\n", + dev_err(np->device, "Port %u, mis-matched LDG assignment for ldn %d, should be %d is %llu\n", np->port, ldn, ldg, (unsigned long long) nr64(LDG_NUM(ldn))); return -EINVAL; @@ -8056,7 +8005,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr) break; } while (limit--); if (!(frame & ESPC_PIO_STAT_READ_END)) { - dev_err(np->device, PFX "EEPROM read timeout frame[%llx]\n", + dev_err(np->device, "EEPROM read timeout frame[%llx]\n", (unsigned long long) frame); return -ENODEV; } @@ -8071,7 +8020,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr) break; } while (limit--); if (!(frame & ESPC_PIO_STAT_READ_END)) { - dev_err(np->device, PFX "EEPROM read timeout frame[%llx]\n", + dev_err(np->device, "EEPROM read timeout frame[%llx]\n", (unsigned long long) frame); return -ENODEV; } @@ -8152,8 +8101,9 @@ static void __devinit niu_vpd_parse_version(struct niu *np) s += i + 5; sscanf(s, "%d.%d", &vpd->fcode_major, &vpd->fcode_minor); - niudbg(PROBE, "VPD_SCAN: FCODE major(%d) minor(%d)\n", - vpd->fcode_major, vpd->fcode_minor); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "VPD_SCAN: FCODE major(%d) minor(%d)\n", + vpd->fcode_major, vpd->fcode_minor); if (vpd->fcode_major > NIU_VPD_MIN_MAJOR || (vpd->fcode_major == NIU_VPD_MIN_MAJOR && vpd->fcode_minor >= NIU_VPD_MIN_MINOR)) @@ -8173,8 +8123,8 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, #define FOUND_MASK_PHY 0x00000020 #define FOUND_MASK_ALL 0x0000003f - niudbg(PROBE, "VPD_SCAN: start[%x] end[%x]\n", - start, end); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "VPD_SCAN: start[%x] end[%x]\n", start, end); while (start < end) { int len, err, instance, type, prop_len; char namebuf[64]; @@ -8228,8 +8178,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, } if (max_len && prop_len > max_len) { - dev_err(np->device, PFX "Property '%s' length (%d) is " - "too long.\n", namebuf, prop_len); + dev_err(np->device, "Property '%s' length (%d) is too long\n", namebuf, prop_len); return -EINVAL; } @@ -8237,8 +8186,9 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np, u32 off = start + 5 + err; int i; - niudbg(PROBE, "VPD_SCAN: Reading in property [%s] " - "len[%d]\n", namebuf, prop_len); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "VPD_SCAN: Reading in property [%s] len[%d]\n", + namebuf, prop_len); for (i = 0; i < prop_len; i++) *prop_buf++ = niu_pci_eeprom_read(np, off + i); } @@ -8402,8 +8352,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) u8 val8; if (!is_valid_ether_addr(&vpd->local_mac[0])) { - dev_err(np->device, PFX "VPD MAC invalid, " - "falling back to SPROM.\n"); + dev_err(np->device, "VPD MAC invalid, falling back to SPROM\n"); np->flags &= ~NIU_FLAGS_VPD_VALID; return; @@ -8420,14 +8369,14 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) np->flags &= ~NIU_FLAGS_10G; } if (np->flags & NIU_FLAGS_10G) - np->mac_xcvr = MAC_XCVR_XPCS; + np->mac_xcvr = MAC_XCVR_XPCS; } else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) { np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER | NIU_FLAGS_HOTPLUG_PHY); } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) { - dev_err(np->device, PFX "Illegal phy string [%s].\n", + dev_err(np->device, "Illegal phy string [%s]\n", np->vpd.phy_type); - dev_err(np->device, PFX "Falling back to SPROM.\n"); + dev_err(np->device, "Falling back to SPROM\n"); np->flags &= ~NIU_FLAGS_VPD_VALID; return; } @@ -8455,7 +8404,8 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) np->eeprom_len = len; - niudbg(PROBE, "SPROM: Image size %llu\n", (unsigned long long) val); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: Image size %llu\n", (unsigned long long)val); sum = 0; for (i = 0; i < len; i++) { @@ -8465,10 +8415,10 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) sum += (val >> 16) & 0xff; sum += (val >> 24) & 0xff; } - niudbg(PROBE, "SPROM: Checksum %x\n", (int)(sum & 0xff)); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: Checksum %x\n", (int)(sum & 0xff)); if ((sum & 0xff) != 0xab) { - dev_err(np->device, PFX "Bad SPROM checksum " - "(%x, should be 0xab)\n", (int) (sum & 0xff)); + dev_err(np->device, "Bad SPROM checksum (%x, should be 0xab)\n", (int)(sum & 0xff)); return -EINVAL; } @@ -8491,11 +8441,12 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) ESPC_PHY_TYPE_PORT3_SHIFT; break; default: - dev_err(np->device, PFX "Bogus port number %u\n", + dev_err(np->device, "Bogus port number %u\n", np->port); return -EINVAL; } - niudbg(PROBE, "SPROM: PHY type %x\n", val8); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: PHY type %x\n", val8); switch (val8) { case ESPC_PHY_TYPE_1G_COPPER: @@ -8527,30 +8478,27 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) break; default: - dev_err(np->device, PFX "Bogus SPROM phy type %u\n", val8); + dev_err(np->device, "Bogus SPROM phy type %u\n", val8); return -EINVAL; } val = nr64(ESPC_MAC_ADDR0); - niudbg(PROBE, "SPROM: MAC_ADDR0[%08llx]\n", - (unsigned long long) val); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: MAC_ADDR0[%08llx]\n", (unsigned long long)val); dev->perm_addr[0] = (val >> 0) & 0xff; dev->perm_addr[1] = (val >> 8) & 0xff; dev->perm_addr[2] = (val >> 16) & 0xff; dev->perm_addr[3] = (val >> 24) & 0xff; val = nr64(ESPC_MAC_ADDR1); - niudbg(PROBE, "SPROM: MAC_ADDR1[%08llx]\n", - (unsigned long long) val); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: MAC_ADDR1[%08llx]\n", (unsigned long long)val); dev->perm_addr[4] = (val >> 0) & 0xff; dev->perm_addr[5] = (val >> 8) & 0xff; if (!is_valid_ether_addr(&dev->perm_addr[0])) { - dev_err(np->device, PFX "SPROM MAC address invalid\n"); - dev_err(np->device, PFX "[ \n"); - for (i = 0; i < 6; i++) - printk("%02x ", dev->perm_addr[i]); - printk("]\n"); + dev_err(np->device, "SPROM MAC address invalid [ %pM ]\n", + dev->perm_addr); return -EINVAL; } @@ -8562,8 +8510,8 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len); val = nr64(ESPC_MOD_STR_LEN); - niudbg(PROBE, "SPROM: MOD_STR_LEN[%llu]\n", - (unsigned long long) val); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: MOD_STR_LEN[%llu]\n", (unsigned long long)val); if (val >= 8 * 4) return -EINVAL; @@ -8578,8 +8526,8 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) np->vpd.model[val] = '\0'; val = nr64(ESPC_BD_MOD_STR_LEN); - niudbg(PROBE, "SPROM: BD_MOD_STR_LEN[%llu]\n", - (unsigned long long) val); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: BD_MOD_STR_LEN[%llu]\n", (unsigned long long)val); if (val >= 4 * 4) return -EINVAL; @@ -8595,8 +8543,8 @@ static int __devinit niu_pci_probe_sprom(struct niu *np) np->vpd.mac_num = nr64(ESPC_NUM_PORTS_MACS) & ESPC_NUM_PORTS_MACS_VAL; - niudbg(PROBE, "SPROM: NUM_PORTS_MACS[%d]\n", - np->vpd.mac_num); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "SPROM: NUM_PORTS_MACS[%d]\n", np->vpd.mac_num); return 0; } @@ -8629,8 +8577,9 @@ static int __devinit niu_get_and_validate_port(struct niu *np) } } - niudbg(PROBE, "niu_get_and_validate_port: port[%d] num_ports[%d]\n", - np->port, parent->num_ports); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() port[%d] num_ports[%d]\n", + __func__, np->port, parent->num_ports); if (np->port >= parent->num_ports) return -ENODEV; @@ -8659,14 +8608,12 @@ static int __devinit phy_record(struct niu_parent *parent, pr_info("niu%d: Found PHY %08x type %s at phy_port %u\n", parent->index, id, - (type == PHY_TYPE_PMA_PMD ? - "PMA/PMD" : - (type == PHY_TYPE_PCS ? - "PCS" : "MII")), + type == PHY_TYPE_PMA_PMD ? "PMA/PMD" : + type == PHY_TYPE_PCS ? "PCS" : "MII", phy_port); if (p->cur[type] >= NIU_MAX_PORTS) { - printk(KERN_ERR PFX "Too many PHY ports.\n"); + pr_err("Too many PHY ports\n"); return -EINVAL; } idx = p->cur[type]; @@ -8727,8 +8674,7 @@ static void __devinit niu_n2_divide_channels(struct niu_parent *parent) parent->rxchan_per_port[i] = (16 / num_ports); parent->txchan_per_port[i] = (16 / num_ports); - pr_info(PFX "niu%d: Port %u [%u RX chans] " - "[%u TX chans]\n", + pr_info("niu%d: Port %u [%u RX chans] [%u TX chans]\n", parent->index, i, parent->rxchan_per_port[i], parent->txchan_per_port[i]); @@ -8771,8 +8717,7 @@ static void __devinit niu_divide_channels(struct niu_parent *parent, parent->rxchan_per_port[i] = rx_chans_per_1g; parent->txchan_per_port[i] = tx_chans_per_1g; } - pr_info(PFX "niu%d: Port %u [%u RX chans] " - "[%u TX chans]\n", + pr_info("niu%d: Port %u [%u RX chans] [%u TX chans]\n", parent->index, i, parent->rxchan_per_port[i], parent->txchan_per_port[i]); @@ -8781,23 +8726,20 @@ static void __devinit niu_divide_channels(struct niu_parent *parent, } if (tot_rx > NIU_NUM_RXCHAN) { - printk(KERN_ERR PFX "niu%d: Too many RX channels (%d), " - "resetting to one per port.\n", + pr_err("niu%d: Too many RX channels (%d), resetting to one per port\n", parent->index, tot_rx); for (i = 0; i < num_ports; i++) parent->rxchan_per_port[i] = 1; } if (tot_tx > NIU_NUM_TXCHAN) { - printk(KERN_ERR PFX "niu%d: Too many TX channels (%d), " - "resetting to one per port.\n", + pr_err("niu%d: Too many TX channels (%d), resetting to one per port\n", parent->index, tot_tx); for (i = 0; i < num_ports; i++) parent->txchan_per_port[i] = 1; } if (tot_rx < NIU_NUM_RXCHAN || tot_tx < NIU_NUM_TXCHAN) { - printk(KERN_WARNING PFX "niu%d: Driver bug, wasted channels, " - "RX[%d] TX[%d]\n", - parent->index, tot_rx, tot_tx); + pr_warning("niu%d: Driver bug, wasted channels, RX[%d] TX[%d]\n", + parent->index, tot_rx, tot_tx); } } @@ -8825,18 +8767,18 @@ static void __devinit niu_divide_rdc_groups(struct niu_parent *parent, struct rdc_table *rt = &tp->tables[grp]; int slot; - pr_info(PFX "niu%d: Port %d RDC tbl(%d) [ ", + pr_info("niu%d: Port %d RDC tbl(%d) [ ", parent->index, i, tp->first_table_num + grp); for (slot = 0; slot < NIU_RDC_TABLE_SLOTS; slot++) { rt->rxdma_channel[slot] = rdc_channel_base + this_channel_offset; - printk("%d ", rt->rxdma_channel[slot]); + pr_cont("%d ", rt->rxdma_channel[slot]); if (++this_channel_offset == num_channels) this_channel_offset = 0; } - printk("]\n"); + pr_cont("]\n"); } parent->rdc_default[i] = rdc_channel_base; @@ -8996,8 +8938,7 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) break; default: - printk(KERN_ERR PFX "Unsupported port config " - "10G[%d] 1G[%d]\n", + pr_err("Unsupported port config 10G[%d] 1G[%d]\n", num_10g, num_1g); return -EINVAL; } @@ -9015,8 +8956,7 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) return 0; unknown_vg_1g_port: - printk(KERN_ERR PFX "Cannot identify platform type, 1gport=%d\n", - lowest_1g); + pr_err("Cannot identify platform type, 1gport=%d\n", lowest_1g); return -EINVAL; } @@ -9025,8 +8965,8 @@ static int __devinit niu_probe_ports(struct niu *np) struct niu_parent *parent = np->parent; int err, i; - niudbg(PROBE, "niu_probe_ports(): port_phy[%08x]\n", - parent->port_phy); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() port_phy[%08x]\n", __func__, parent->port_phy); if (parent->port_phy == PORT_PHY_UNKNOWN) { err = walk_phys(np, parent); @@ -9048,8 +8988,9 @@ static int __devinit niu_classifier_swstate_init(struct niu *np) { struct niu_classifier *cp = &np->clas; - niudbg(PROBE, "niu_classifier_swstate_init: num_tcam(%d)\n", - np->parent->tcam_num_entries); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() num_tcam(%d)\n", + __func__, np->parent->tcam_num_entries); cp->tcam_top = (u16) np->port; cp->tcam_sz = np->parent->tcam_num_entries / np->parent->num_ports; @@ -9116,8 +9057,7 @@ static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np) break; default: - dev_err(np->device, PFX "Port %u is invalid, cannot " - "compute MAC block offset.\n", np->port); + dev_err(np->device, "Port %u is invalid, cannot compute MAC block offset\n", np->port); return -EINVAL; } @@ -9327,9 +9267,8 @@ static int __devinit niu_get_of_props(struct niu *np) phy_type = of_get_property(dp, "phy-type", &prop_len); if (!phy_type) { - dev_err(np->device, PFX "%s: OF node lacks " - "phy-type property\n", - dp->full_name); + netdev_err(dev, "%s: OF node lacks phy-type property\n", + dp->full_name); return -EINVAL; } @@ -9339,34 +9278,26 @@ static int __devinit niu_get_of_props(struct niu *np) strcpy(np->vpd.phy_type, phy_type); if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) { - dev_err(np->device, PFX "%s: Illegal phy string [%s].\n", - dp->full_name, np->vpd.phy_type); + netdev_err(dev, "%s: Illegal phy string [%s]\n", + dp->full_name, np->vpd.phy_type); return -EINVAL; } mac_addr = of_get_property(dp, "local-mac-address", &prop_len); if (!mac_addr) { - dev_err(np->device, PFX "%s: OF node lacks " - "local-mac-address property\n", - dp->full_name); + netdev_err(dev, "%s: OF node lacks local-mac-address property\n", + dp->full_name); return -EINVAL; } if (prop_len != dev->addr_len) { - dev_err(np->device, PFX "%s: OF MAC address prop len (%d) " - "is wrong.\n", - dp->full_name, prop_len); + netdev_err(dev, "%s: OF MAC address prop len (%d) is wrong\n", + dp->full_name, prop_len); } memcpy(dev->perm_addr, mac_addr, dev->addr_len); if (!is_valid_ether_addr(&dev->perm_addr[0])) { - int i; - - dev_err(np->device, PFX "%s: OF MAC address is invalid\n", - dp->full_name); - dev_err(np->device, PFX "%s: [ \n", - dp->full_name); - for (i = 0; i < 6; i++) - printk("%02x ", dev->perm_addr[i]); - printk("]\n"); + netdev_err(dev, "%s: OF MAC address is invalid\n", + dp->full_name); + netdev_err(dev, "%s: [ %pM ]\n", dp->full_name, dev->perm_addr); return -EINVAL; } @@ -9414,8 +9345,8 @@ static int __devinit niu_get_invariants(struct niu *np) nw64(ESPC_PIO_EN, ESPC_PIO_EN_ENABLE); offset = niu_pci_vpd_offset(np); - niudbg(PROBE, "niu_get_invariants: VPD offset [%08x]\n", - offset); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() VPD offset [%08x]\n", __func__, offset); if (offset) niu_pci_vpd_fetch(np, offset); nw64(ESPC_PIO_EN, 0); @@ -9575,7 +9506,8 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np, struct niu_parent *p; int i; - niudbg(PROBE, "niu_new_parent: Creating new parent.\n"); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() Creating new parent\n", __func__); plat_dev = platform_device_register_simple("niu", niu_parent_index, NULL, 0); @@ -9641,8 +9573,9 @@ static struct niu_parent * __devinit niu_get_parent(struct niu *np, struct niu_parent *p, *tmp; int port = np->port; - niudbg(PROBE, "niu_get_parent: platform_type[%u] port[%u]\n", - ptype, port); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() platform_type[%u] port[%u]\n", + __func__, ptype, port); mutex_lock(&niu_parent_lock); p = NULL; @@ -9681,7 +9614,8 @@ static void niu_put_parent(struct niu *np) BUG_ON(!p || p->ports[port] != np); - niudbg(PROBE, "niu_put_parent: port[%u]\n", port); + netif_printk(np, probe, KERN_DEBUG, np->dev, + "%s() port[%u]\n", __func__, port); sprintf(port_name, "port%d", port); @@ -9772,7 +9706,7 @@ static struct net_device * __devinit niu_alloc_and_init( dev = alloc_etherdev_mq(sizeof(struct niu), NIU_NUM_TXCHAN); if (!dev) { - dev_err(gen_dev, PFX "Etherdev alloc failed, aborting.\n"); + dev_err(gen_dev, "Etherdev alloc failed, aborting\n"); return NULL; } @@ -9858,30 +9792,26 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) { - dev_err(&pdev->dev, PFX "Cannot enable PCI device, " - "aborting.\n"); + dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); return err; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || !(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - dev_err(&pdev->dev, PFX "Cannot find proper PCI device " - "base addresses, aborting.\n"); + dev_err(&pdev->dev, "Cannot find proper PCI device base addresses, aborting\n"); err = -ENODEV; goto err_out_disable_pdev; } err = pci_request_regions(pdev, DRV_MODULE_NAME); if (err) { - dev_err(&pdev->dev, PFX "Cannot obtain PCI resources, " - "aborting.\n"); + dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); goto err_out_disable_pdev; } pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (pos <= 0) { - dev_err(&pdev->dev, PFX "Cannot find PCI Express capability, " - "aborting.\n"); + dev_err(&pdev->dev, "Cannot find PCI Express capability, aborting\n"); goto err_out_free_res; } @@ -9920,17 +9850,14 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, dev->features |= NETIF_F_HIGHDMA; err = pci_set_consistent_dma_mask(pdev, dma_mask); if (err) { - dev_err(&pdev->dev, PFX "Unable to obtain 44 bit " - "DMA for consistent allocations, " - "aborting.\n"); + dev_err(&pdev->dev, "Unable to obtain 44 bit DMA for consistent allocations, aborting\n"); goto err_out_release_parent; } } if (err || dma_mask == DMA_BIT_MASK(32)) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { - dev_err(&pdev->dev, PFX "No usable DMA configuration, " - "aborting.\n"); + dev_err(&pdev->dev, "No usable DMA configuration, aborting\n"); goto err_out_release_parent; } } @@ -9939,8 +9866,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, np->regs = pci_ioremap_bar(pdev, 0); if (!np->regs) { - dev_err(&pdev->dev, PFX "Cannot map device registers, " - "aborting.\n"); + dev_err(&pdev->dev, "Cannot map device registers, aborting\n"); err = -ENOMEM; goto err_out_release_parent; } @@ -9955,15 +9881,13 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, err = niu_get_invariants(np); if (err) { if (err != -ENODEV) - dev_err(&pdev->dev, PFX "Problem fetching invariants " - "of chip, aborting.\n"); + dev_err(&pdev->dev, "Problem fetching invariants of chip, aborting\n"); goto err_out_iounmap; } err = register_netdev(dev); if (err) { - dev_err(&pdev->dev, PFX "Cannot register net device, " - "aborting.\n"); + dev_err(&pdev->dev, "Cannot register net device, aborting\n"); goto err_out_iounmap; } @@ -10157,7 +10081,7 @@ static int __devinit niu_of_probe(struct of_device *op, reg = of_get_property(op->node, "reg", NULL); if (!reg) { - dev_err(&op->dev, PFX "%s: No 'reg' property, aborting.\n", + dev_err(&op->dev, "%s: No 'reg' property, aborting\n", op->node->full_name); return -ENODEV; } @@ -10186,8 +10110,7 @@ static int __devinit niu_of_probe(struct of_device *op, resource_size(&op->resource[1]), "niu regs"); if (!np->regs) { - dev_err(&op->dev, PFX "Cannot map device registers, " - "aborting.\n"); + dev_err(&op->dev, "Cannot map device registers, aborting\n"); err = -ENOMEM; goto err_out_release_parent; } @@ -10196,8 +10119,7 @@ static int __devinit niu_of_probe(struct of_device *op, resource_size(&op->resource[2]), "niu vregs-1"); if (!np->vir_regs_1) { - dev_err(&op->dev, PFX "Cannot map device vir registers 1, " - "aborting.\n"); + dev_err(&op->dev, "Cannot map device vir registers 1, aborting\n"); err = -ENOMEM; goto err_out_iounmap; } @@ -10206,8 +10128,7 @@ static int __devinit niu_of_probe(struct of_device *op, resource_size(&op->resource[3]), "niu vregs-2"); if (!np->vir_regs_2) { - dev_err(&op->dev, PFX "Cannot map device vir registers 2, " - "aborting.\n"); + dev_err(&op->dev, "Cannot map device vir registers 2, aborting\n"); err = -ENOMEM; goto err_out_iounmap; } @@ -10217,15 +10138,13 @@ static int __devinit niu_of_probe(struct of_device *op, err = niu_get_invariants(np); if (err) { if (err != -ENODEV) - dev_err(&op->dev, PFX "Problem fetching invariants " - "of chip, aborting.\n"); + dev_err(&op->dev, "Problem fetching invariants of chip, aborting\n"); goto err_out_iounmap; } err = register_netdev(dev); if (err) { - dev_err(&op->dev, PFX "Cannot register net device, " - "aborting.\n"); + dev_err(&op->dev, "Cannot register net device, aborting\n"); goto err_out_iounmap; } -- cgit v1.2.3 From 5659338c88963ea791118e5e11e314b24f90c3eb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 1 Feb 2010 07:21:02 +0000 Subject: vhost-net: switch to smp barriers vhost-net only uses memory barriers to control SMP effects (communication with userspace potentially running on a different CPU), so it should use SMP barriers and not mandatory barriers for memory access ordering, as suggested by Documentation/memory-barriers.txt Signed-off-by: Michael S. Tsirkin Acked-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/vhost/vhost.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c8c25dbc5857..6eb15259f5ae 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -685,7 +685,7 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, int i, r; /* Make sure data written is seen before log. */ - wmb(); + smp_wmb(); for (i = 0; i < log_num; ++i) { u64 l = min(log[i].len, len); r = log_write(vq->log_base, log[i].addr, l); @@ -884,7 +884,7 @@ unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, return vq->num; /* Only get avail ring entries after they have been exposed by guest. */ - rmb(); + smp_rmb(); /* Grab the next descriptor number they're advertising, and increment * the index we've seen. */ @@ -996,14 +996,14 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) return -EFAULT; } /* Make sure buffer is written before we update index. */ - wmb(); + smp_wmb(); if (put_user(vq->last_used_idx + 1, &vq->used->idx)) { vq_err(vq, "Failed to increment used idx"); return -EFAULT; } if (unlikely(vq->log_used)) { /* Make sure data is seen before log. */ - wmb(); + smp_wmb(); log_write(vq->log_base, vq->log_addr + sizeof *vq->used->ring * (vq->last_used_idx % vq->num), sizeof *vq->used->ring); @@ -1060,7 +1060,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq) } /* They could have slipped one in as we were doing that: make * sure it's written, then check again. */ - mb(); + smp_mb(); r = get_user(avail_idx, &vq->avail->idx); if (r) { vq_err(vq, "Failed to check avail idx at %p: %d\n", -- cgit v1.2.3 From 228da6c2e63b3b2064492b24ef83c07bcc48abbd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 14 Feb 2010 22:49:52 -0800 Subject: mac80211: Fix error introduced in netdev_mc_count() changes. Commit 4cd24eaf0c6ee7f0242e34ee77ec899f255e66b5 ("net: use netdev_mc_count and netdev_mc_empty when appropriate") added this hunk to net/mac80211/iface.c: __dev_addr_unsync(&local->mc_list, &local->mc_count, - &dev->mc_list, &dev->mc_count); + &dev->mc_list, dev->mc_count); which is definitely not correct, introduced a warning (reported by Stephen Rothwell): net/mac80211/iface.c: In function 'ieee80211_stop': net/mac80211/iface.c:416: warning: passing argument 4 of '__dev_addr_unsync' makes pointer from integer without a cast include/linux/netdevice.h:1967: note: expected 'int *' but argument is of type 'int' and is thus reverted here. Signed-off-by: David S. Miller --- net/mac80211/iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f943f5fa7286..09fff4662e80 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -413,7 +413,7 @@ static int ieee80211_stop(struct net_device *dev) netif_addr_lock_bh(dev); spin_lock_bh(&local->filter_lock); __dev_addr_unsync(&local->mc_list, &local->mc_count, - &dev->mc_list, dev->mc_count); + &dev->mc_list, &dev->mc_count); spin_unlock_bh(&local->filter_lock); netif_addr_unlock_bh(dev); -- cgit v1.2.3 From 02b1bae5e1c0f810168037be0134685085e95e88 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 15 Feb 2010 00:07:00 -0800 Subject: niu: Refinements to kernel logging. Fix unconditional empty kerne log message every interrupt. Kill some informational log messages that are superfluous and anyways occur before the netdev is registered. Signed-off-by: David S. Miller --- drivers/net/niu.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 347788f11c74..5e604e305d95 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3204,9 +3204,6 @@ static int fflp_early_init(struct niu *np) parent = np->parent; err = 0; if (!(parent->flags & PARENT_FLGS_CLS_HWINIT)) { - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() Initting hw on port %u\n", - __func__, np->port); if (np->parent->plat_type != PLAT_TYPE_NIU) { fflp_reset(np); fflp_set_timings(np); @@ -3248,8 +3245,6 @@ static int fflp_early_init(struct niu *np) vlan_tbl_clear(np); - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() Success\n", __func__); parent->flags |= PARENT_FLGS_CLS_HWINIT; } out: @@ -4246,13 +4241,11 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) v2 = nr64(LDSV2(ldg)); if (netif_msg_intr(np)) - pr_cont(" v0[%llx] v1[%llx] v2[%llx]", + pr_cont(" v0[%llx] v1[%llx] v2[%llx]\n", (unsigned long long) v0, (unsigned long long) v1, (unsigned long long) v2); - pr_cont("\n"); - if (unlikely(!v0 && !v1 && !v2)) { spin_unlock_irqrestore(&np->lock, flags); return IRQ_NONE; @@ -8577,9 +8570,6 @@ static int __devinit niu_get_and_validate_port(struct niu *np) } } - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() port[%d] num_ports[%d]\n", - __func__, np->port, parent->num_ports); if (np->port >= parent->num_ports) return -ENODEV; @@ -8965,9 +8955,6 @@ static int __devinit niu_probe_ports(struct niu *np) struct niu_parent *parent = np->parent; int err, i; - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() port_phy[%08x]\n", __func__, parent->port_phy); - if (parent->port_phy == PORT_PHY_UNKNOWN) { err = walk_phys(np, parent); if (err) @@ -8988,10 +8975,6 @@ static int __devinit niu_classifier_swstate_init(struct niu *np) { struct niu_classifier *cp = &np->clas; - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() num_tcam(%d)\n", - __func__, np->parent->tcam_num_entries); - cp->tcam_top = (u16) np->port; cp->tcam_sz = np->parent->tcam_num_entries / np->parent->num_ports; cp->h1_init = 0xffffffff; @@ -9506,9 +9489,6 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np, struct niu_parent *p; int i; - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() Creating new parent\n", __func__); - plat_dev = platform_device_register_simple("niu", niu_parent_index, NULL, 0); if (IS_ERR(plat_dev)) @@ -9573,10 +9553,6 @@ static struct niu_parent * __devinit niu_get_parent(struct niu *np, struct niu_parent *p, *tmp; int port = np->port; - netif_printk(np, probe, KERN_DEBUG, np->dev, - "%s() platform_type[%u] port[%u]\n", - __func__, ptype, port); - mutex_lock(&niu_parent_lock); p = NULL; list_for_each_entry(tmp, &niu_parent_list, list) { -- cgit v1.2.3 From 98e6d2d5ee26bf56850a10eb64139c68fb09ba19 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 15 Feb 2010 16:31:35 +0100 Subject: netfilter: xt_recent: inform user when hitcount is too large It is one of these things that iptables cannot catch and which can cause "Invalid argument" to be printed. Without a hint in dmesg, it is not going to be helpful. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/netfilter/xt_recent.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 203333107367..132cfaa84cdc 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -53,7 +53,7 @@ module_param(ip_list_perms, uint, 0400); module_param(ip_list_uid, uint, 0400); module_param(ip_list_gid, uint, 0400); MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); -MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)"); +MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)"); MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files"); @@ -306,8 +306,12 @@ static bool recent_mt_check(const struct xt_mtchk_param *par) if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) && (info->seconds || info->hit_count)) return false; - if (info->hit_count > ip_pkt_list_tot) + if (info->hit_count > ip_pkt_list_tot) { + pr_info(KBUILD_MODNAME ": hitcount (%u) is larger than " + "packets to be remembered (%u)\n", + info->hit_count, ip_pkt_list_tot); return false; + } if (info->name[0] == '\0' || strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) return false; -- cgit v1.2.3 From fa96a0e2e67fe34a3d994e3f354a5c229dd14286 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 1 Nov 2009 00:36:40 +0100 Subject: netfilter: iptables: remove unused function arguments Signed-off-by: Jan Engelhardt --- net/ipv4/netfilter/iptable_mangle.c | 10 +++------- net/ipv6/netfilter/ip6table_mangle.c | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index c8333305d631..b9b83464cbf4 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -36,11 +36,7 @@ static const struct xt_table packet_mangler = { }; static unsigned int -ipt_local_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +ipt_mangle_out(struct sk_buff *skb, const struct net_device *out) { unsigned int ret; const struct iphdr *iph; @@ -60,7 +56,7 @@ ipt_local_hook(unsigned int hook, daddr = iph->daddr; tos = iph->tos; - ret = ipt_do_table(skb, hook, in, out, + ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, dev_net(out)->ipv4.iptable_mangle); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { @@ -86,7 +82,7 @@ iptable_mangle_hook(unsigned int hook, int (*okfn)(struct sk_buff *)) { if (hook == NF_INET_LOCAL_OUT) - return ipt_local_hook(hook, skb, in, out, okfn); + return ipt_mangle_out(skb, out); if (hook == NF_INET_POST_ROUTING) return ipt_do_table(skb, hook, in, out, dev_net(out)->ipv4.iptable_mangle); diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index b6216dede52c..7844e557c0ec 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -30,12 +30,8 @@ static const struct xt_table packet_mangler = { }; static unsigned int -ip6t_local_out_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) +ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) { - unsigned int ret; struct in6_addr saddr, daddr; u_int8_t hop_limit; @@ -60,7 +56,7 @@ ip6t_local_out_hook(unsigned int hook, /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *)ipv6_hdr(skb)); - ret = ip6t_do_table(skb, hook, NULL, out, + ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, NULL, out, dev_net(out)->ipv6.ip6table_mangle); if (ret != NF_DROP && ret != NF_STOLEN && @@ -80,7 +76,7 @@ ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb, int (*okfn)(struct sk_buff *)) { if (hook == NF_INET_LOCAL_OUT) - return ip6t_local_out_hook(hook, skb, out, okfn); + return ip6t_mangle_out(skb, out); if (hook == NF_INET_POST_ROUTING) return ip6t_do_table(skb, hook, in, out, dev_net(out)->ipv6.ip6table_mangle); -- cgit v1.2.3 From 23f3733d440b918ccb7746718f77256334cf6176 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 5 Jun 2009 17:31:46 +0200 Subject: netfilter: reduce NF_HOOK by one argument No changes in vmlinux filesize. Signed-off-by: Jan Engelhardt --- include/linux/netfilter.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 78f33d223680..2f22816a5514 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -163,11 +163,8 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sk_buff *), int thresh, - int cond) + int (*okfn)(struct sk_buff *), int thresh) { - if (!cond) - return 1; #ifndef CONFIG_NETFILTER_DEBUG if (list_empty(&nf_hooks[pf][hook])) return 1; @@ -179,7 +176,7 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, int (*okfn)(struct sk_buff *)) { - return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN, 1); + return nf_hook_thresh(pf, hook, skb, indev, outdev, okfn, INT_MIN); } /* Activate hook; either okfn or kfree_skb called, unless a hook @@ -206,13 +203,13 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ ({int __ret; \ -if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh, 1)) == 1)\ +if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh)) == 1)\ __ret = (okfn)(skb); \ __ret;}) #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \ ({int __ret; \ -if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN, cond)) == 1)\ +if ((cond) || (__ret = nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN)) == 1)\ __ret = (okfn)(skb); \ __ret;}) @@ -328,8 +325,7 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *indev, struct net_device *outdev, - int (*okfn)(struct sk_buff *), int thresh, - int cond) + int (*okfn)(struct sk_buff *), int thresh) { return okfn(skb); } -- cgit v1.2.3 From 2249065f4b22b493bae2caf549b86f175f33188e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 13 Jun 2009 04:13:26 +0200 Subject: netfilter: get rid of the grossness in netfilter.h GCC is now smart enough to follow the inline trail correctly. vmlinux size remain the same. Signed-off-by: Jan Engelhardt --- include/linux/netfilter.h | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 2f22816a5514..70079454ffd0 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -196,25 +196,36 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb, coders :) */ -/* This is gross, but inline doesn't cut it for avoiding the function - call in fast path: gcc doesn't inline (needs value tracking?). --RR */ - -/* HX: It's slightly less gross now. */ - -#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \ -({int __ret; \ -if ((__ret=nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, thresh)) == 1)\ - __ret = (okfn)(skb); \ -__ret;}) +static inline int +NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb, + struct net_device *in, struct net_device *out, + int (*okfn)(struct sk_buff *), int thresh) +{ + int ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, thresh); + if (ret == 1) + ret = okfn(skb); + return ret; +} -#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \ -({int __ret; \ -if ((cond) || (__ret = nf_hook_thresh(pf, hook, (skb), indev, outdev, okfn, INT_MIN)) == 1)\ - __ret = (okfn)(skb); \ -__ret;}) +static inline int +NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb, + struct net_device *in, struct net_device *out, + int (*okfn)(struct sk_buff *), bool cond) +{ + int ret = 1; + if (cond || + (ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN) == 1)) + ret = okfn(skb); + return ret; +} -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \ - NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN) +static inline int +NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb, + struct net_device *in, struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN); +} /* Call setsockopt() */ int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt, -- cgit v1.2.3 From b402405d71beed8e4df354844353f66b4e18269f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 25 Jun 2009 18:32:12 +0200 Subject: netfilter: xtables: print details on size mismatch Print which revision has been used and which size are which (kernel/user) for easier debugging. Signed-off-by: Jan Engelhardt --- net/netfilter/x_tables.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 255ab0657ce8..12503199826f 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -366,8 +366,10 @@ int xt_check_match(struct xt_mtchk_param *par, * ebt_among is exempt from centralized matchsize checking * because it uses a dynamic-size data set. */ - pr_err("%s_tables: %s match: invalid size %u != %u\n", + pr_err("%s_tables: %s.%u match: invalid size " + "%u (kernel) != (user) %u\n", xt_prefix[par->family], par->match->name, + par->match->revision, XT_ALIGN(par->match->matchsize), size); return -EINVAL; } @@ -516,8 +518,10 @@ int xt_check_target(struct xt_tgchk_param *par, unsigned int size, u_int8_t proto, bool inv_proto) { if (XT_ALIGN(par->target->targetsize) != size) { - pr_err("%s_tables: %s target: invalid size %u != %u\n", + pr_err("%s_tables: %s.%u target: invalid size " + "%u (kernel) != (user) %u\n", xt_prefix[par->family], par->target->name, + par->target->revision, XT_ALIGN(par->target->targetsize), size); return -EINVAL; } -- cgit v1.2.3 From 739674fb7febf116e7d647031fab16989a08a965 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 26 Jun 2009 08:23:19 +0200 Subject: netfilter: xtables: constify args in compat copying functions Signed-off-by: Jan Engelhardt --- include/linux/netfilter/x_tables.h | 12 ++++++------ net/ipv4/netfilter/arp_tables.c | 4 ++-- net/ipv4/netfilter/ip_tables.c | 4 ++-- net/ipv4/netfilter/ipt_ULOG.c | 4 ++-- net/ipv6/netfilter/ip6_tables.c | 4 ++-- net/netfilter/x_tables.c | 8 ++++---- net/netfilter/xt_hashlimit.c | 4 ++-- net/netfilter/xt_limit.c | 4 ++-- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index a0a144a6c6d9..c61758f4be31 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -286,8 +286,8 @@ struct xt_match { void (*destroy)(const struct xt_mtdtor_param *); #ifdef CONFIG_COMPAT /* Called when userspace align differs from kernel space one */ - void (*compat_from_user)(void *dst, void *src); - int (*compat_to_user)(void __user *dst, void *src); + void (*compat_from_user)(void *dst, const void *src); + int (*compat_to_user)(void __user *dst, const void *src); #endif /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -328,8 +328,8 @@ struct xt_target { void (*destroy)(const struct xt_tgdtor_param *); #ifdef CONFIG_COMPAT /* Called when userspace align differs from kernel space one */ - void (*compat_from_user)(void *dst, void *src); - int (*compat_to_user)(void __user *dst, void *src); + void (*compat_from_user)(void *dst, const void *src); + int (*compat_to_user)(void __user *dst, const void *src); #endif /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -593,13 +593,13 @@ extern short xt_compat_calc_jump(u_int8_t af, unsigned int offset); extern int xt_compat_match_offset(const struct xt_match *match); extern int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, unsigned int *size); -extern int xt_compat_match_to_user(struct xt_entry_match *m, +extern int xt_compat_match_to_user(const struct xt_entry_match *m, void __user **dstptr, unsigned int *size); extern int xt_compat_target_offset(const struct xt_target *target); extern void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, unsigned int *size); -extern int xt_compat_target_to_user(struct xt_entry_target *t, +extern int xt_compat_target_to_user(const struct xt_entry_target *t, void __user **dstptr, unsigned int *size); #endif /* CONFIG_COMPAT */ diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 72723ea1054b..2303dc92a277 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -842,7 +842,7 @@ static int copy_entries_to_user(unsigned int total_size, } #ifdef CONFIG_COMPAT -static void compat_standard_from_user(void *dst, void *src) +static void compat_standard_from_user(void *dst, const void *src) { int v = *(compat_int_t *)src; @@ -851,7 +851,7 @@ static void compat_standard_from_user(void *dst, void *src) memcpy(dst, &v, sizeof(v)); } -static int compat_standard_to_user(void __user *dst, void *src) +static int compat_standard_to_user(void __user *dst, const void *src) { compat_int_t cv = *(int *)src; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2057b1bb6178..2a4f745ce36e 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1047,7 +1047,7 @@ copy_entries_to_user(unsigned int total_size, } #ifdef CONFIG_COMPAT -static void compat_standard_from_user(void *dst, void *src) +static void compat_standard_from_user(void *dst, const void *src) { int v = *(compat_int_t *)src; @@ -1056,7 +1056,7 @@ static void compat_standard_from_user(void *dst, void *src) memcpy(dst, &v, sizeof(v)); } -static int compat_standard_to_user(void __user *dst, void *src) +static int compat_standard_to_user(void __user *dst, const void *src) { compat_int_t cv = *(int *)src; diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 399061c3fd7d..09a5d3f7cc41 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -338,7 +338,7 @@ struct compat_ipt_ulog_info { char prefix[ULOG_PREFIX_LEN]; }; -static void ulog_tg_compat_from_user(void *dst, void *src) +static void ulog_tg_compat_from_user(void *dst, const void *src) { const struct compat_ipt_ulog_info *cl = src; struct ipt_ulog_info l = { @@ -351,7 +351,7 @@ static void ulog_tg_compat_from_user(void *dst, void *src) memcpy(dst, &l, sizeof(l)); } -static int ulog_tg_compat_to_user(void __user *dst, void *src) +static int ulog_tg_compat_to_user(void __user *dst, const void *src) { const struct ipt_ulog_info *l = src; struct compat_ipt_ulog_info cl = { diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index dcd7825fe7b6..3ff4fd50e96e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1079,7 +1079,7 @@ copy_entries_to_user(unsigned int total_size, } #ifdef CONFIG_COMPAT -static void compat_standard_from_user(void *dst, void *src) +static void compat_standard_from_user(void *dst, const void *src) { int v = *(compat_int_t *)src; @@ -1088,7 +1088,7 @@ static void compat_standard_from_user(void *dst, void *src) memcpy(dst, &v, sizeof(v)); } -static int compat_standard_to_user(void __user *dst, void *src) +static int compat_standard_to_user(void __user *dst, const void *src) { compat_int_t cv = *(int *)src; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 12503199826f..69c56287d518 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -485,8 +485,8 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, } EXPORT_SYMBOL_GPL(xt_compat_match_from_user); -int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, - unsigned int *size) +int xt_compat_match_to_user(const struct xt_entry_match *m, + void __user **dstptr, unsigned int *size) { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match __user *cm = *dstptr; @@ -588,8 +588,8 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, } EXPORT_SYMBOL_GPL(xt_compat_target_from_user); -int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr, - unsigned int *size) +int xt_compat_target_to_user(const struct xt_entry_target *t, + void __user **dstptr, unsigned int *size) { const struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target __user *ct = *dstptr; diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 017c95966aa8..e47fb805ffb4 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -775,7 +775,7 @@ struct compat_xt_hashlimit_info { compat_uptr_t master; }; -static void hashlimit_mt_compat_from_user(void *dst, void *src) +static void hashlimit_mt_compat_from_user(void *dst, const void *src) { int off = offsetof(struct compat_xt_hashlimit_info, hinfo); @@ -783,7 +783,7 @@ static void hashlimit_mt_compat_from_user(void *dst, void *src) memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off); } -static int hashlimit_mt_compat_to_user(void __user *dst, void *src) +static int hashlimit_mt_compat_to_user(void __user *dst, const void *src) { int off = offsetof(struct compat_xt_hashlimit_info, hinfo); diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 2773be6a71dd..a0ca5339af41 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -148,7 +148,7 @@ struct compat_xt_rateinfo { /* To keep the full "prev" timestamp, the upper 32 bits are stored in the * master pointer, which does not need to be preserved. */ -static void limit_mt_compat_from_user(void *dst, void *src) +static void limit_mt_compat_from_user(void *dst, const void *src) { const struct compat_xt_rateinfo *cm = src; struct xt_rateinfo m = { @@ -162,7 +162,7 @@ static void limit_mt_compat_from_user(void *dst, void *src) memcpy(dst, &m, sizeof(m)); } -static int limit_mt_compat_to_user(void __user *dst, void *src) +static int limit_mt_compat_to_user(void __user *dst, const void *src) { const struct xt_rateinfo *m = src; struct compat_xt_rateinfo cm = { -- cgit v1.2.3 From d5d1baa15f5b05e9110403724d5dc72d6d541e04 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 26 Jun 2009 07:51:59 +0200 Subject: netfilter: xtables: add const qualifiers This should make it easier to remove redundant arguments later. Signed-off-by: Jan Engelhardt --- net/bridge/netfilter/ebtables.c | 59 ++++++++++++++------------- net/ipv4/netfilter/arp_tables.c | 69 ++++++++++++++++++-------------- net/ipv4/netfilter/ip_tables.c | 88 +++++++++++++++++++++++------------------ net/ipv6/netfilter/ip6_tables.c | 88 ++++++++++++++++++++++------------------- 4 files changed, 168 insertions(+), 136 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 208f4e32e732..bcdf02d866b8 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -82,7 +82,8 @@ static inline int ebt_do_match (struct ebt_entry_match *m, return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH; } -static inline int ebt_dev_check(char *entry, const struct net_device *device) +static inline int +ebt_dev_check(const char *entry, const struct net_device *device) { int i = 0; const char *devname; @@ -100,8 +101,9 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device) #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) /* process standard matches */ -static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, - const struct net_device *in, const struct net_device *out) +static inline int +ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h, + const struct net_device *in, const struct net_device *out) { int verdict, i; @@ -156,12 +158,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, int i, nentries; struct ebt_entry *point; struct ebt_counter *counter_base, *cb_base; - struct ebt_entry_target *t; + const struct ebt_entry_target *t; int verdict, sp = 0; struct ebt_chainstack *cs; struct ebt_entries *chaininfo; - char *base; - struct ebt_table_info *private; + const char *base; + const struct ebt_table_info *private; bool hotdrop = false; struct xt_match_param mtpar; struct xt_target_param tgpar; @@ -395,7 +397,7 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par, return 0; } -static int ebt_verify_pointers(struct ebt_replace *repl, +static int ebt_verify_pointers(const struct ebt_replace *repl, struct ebt_table_info *newinfo) { unsigned int limit = repl->entries_size; @@ -466,8 +468,8 @@ static int ebt_verify_pointers(struct ebt_replace *repl, * to parse the userspace data */ static inline int -ebt_check_entry_size_and_hooks(struct ebt_entry *e, - struct ebt_table_info *newinfo, +ebt_check_entry_size_and_hooks(const struct ebt_entry *e, + const struct ebt_table_info *newinfo, unsigned int *n, unsigned int *cnt, unsigned int *totalcnt, unsigned int *udc_cnt) { @@ -622,9 +624,8 @@ ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt) } static inline int -ebt_check_entry(struct ebt_entry *e, - struct net *net, - struct ebt_table_info *newinfo, +ebt_check_entry(struct ebt_entry *e, struct net *net, + const struct ebt_table_info *newinfo, const char *name, unsigned int *cnt, struct ebt_cl_stack *cl_s, unsigned int udc_cnt) { @@ -743,12 +744,12 @@ cleanup_matches: * the hook mask for udc tells us from which base chains the udc can be * accessed. This mask is a parameter to the check() functions of the extensions */ -static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, +static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s, unsigned int udc_cnt, unsigned int hooknr, char *base) { int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; - struct ebt_entry *e = (struct ebt_entry *)chain->data; - struct ebt_entry_target *t; + const struct ebt_entry *e = (struct ebt_entry *)chain->data; + const struct ebt_entry_target *t; while (pos < nentries || chain_nr != -1) { /* end of udc, go back one 'recursion' step */ @@ -814,7 +815,7 @@ letscontinue: } /* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ -static int translate_table(struct net *net, char *name, +static int translate_table(struct net *net, const char *name, struct ebt_table_info *newinfo) { unsigned int i, j, k, udc_cnt; @@ -934,7 +935,7 @@ static int translate_table(struct net *net, char *name, } /* called under write_lock */ -static void get_counters(struct ebt_counter *oldcounters, +static void get_counters(const struct ebt_counter *oldcounters, struct ebt_counter *counters, unsigned int nentries) { int i, cpu; @@ -957,7 +958,8 @@ static void get_counters(struct ebt_counter *oldcounters, } /* replace the table */ -static int do_replace(struct net *net, void __user *user, unsigned int len) +static int do_replace(struct net *net, const void __user *user, + unsigned int len) { int ret, i, countersize; struct ebt_table_info *newinfo; @@ -1237,7 +1239,8 @@ void ebt_unregister_table(struct net *net, struct ebt_table *table) } /* userspace just supplied us with counters */ -static int update_counters(struct net *net, void __user *user, unsigned int len) +static int update_counters(struct net *net, const void __user *user, + unsigned int len) { int i, ret; struct ebt_counter *tmp; @@ -1292,8 +1295,8 @@ free_tmp: return ret; } -static inline int ebt_make_matchname(struct ebt_entry_match *m, - char *base, char __user *ubase) +static inline int ebt_make_matchname(const struct ebt_entry_match *m, + const char *base, char __user *ubase) { char __user *hlp = ubase + ((char *)m - base); if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) @@ -1301,8 +1304,8 @@ static inline int ebt_make_matchname(struct ebt_entry_match *m, return 0; } -static inline int ebt_make_watchername(struct ebt_entry_watcher *w, - char *base, char __user *ubase) +static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, + const char *base, char __user *ubase) { char __user *hlp = ubase + ((char *)w - base); if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) @@ -1310,11 +1313,12 @@ static inline int ebt_make_watchername(struct ebt_entry_watcher *w, return 0; } -static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase) +static inline int +ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) { int ret; char __user *hlp; - struct ebt_entry_target *t; + const struct ebt_entry_target *t; if (e->bitmask == 0) return 0; @@ -1335,10 +1339,11 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *u /* called with ebt_mutex locked */ static int copy_everything_to_user(struct ebt_table *t, void __user *user, - int *len, int cmd) + const int *len, int cmd) { struct ebt_replace tmp; - struct ebt_counter *counterstmp, *oldcounters; + struct ebt_counter *counterstmp; + const struct ebt_counter *oldcounters; unsigned int entries_size, nentries; char *entries; diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 2303dc92a277..4db5c1ece0f9 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -233,7 +233,14 @@ arpt_error(struct sk_buff *skb, const struct xt_target_param *par) return NF_DROP; } -static inline struct arpt_entry *get_entry(void *base, unsigned int offset) +static inline const struct arpt_entry_target * +arpt_get_target_c(const struct arpt_entry *e) +{ + return arpt_get_target((struct arpt_entry *)e); +} + +static inline struct arpt_entry * +get_entry(const void *base, unsigned int offset) { return (struct arpt_entry *)(base + offset); } @@ -280,7 +287,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, arp = arp_hdr(skb); do { - struct arpt_entry_target *t; + const struct arpt_entry_target *t; int hdr_len; if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { @@ -292,7 +299,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, (2 * skb->dev->addr_len); ADD_COUNTER(e->counters, hdr_len, 1); - t = arpt_get_target(e); + t = arpt_get_target_c(e); /* Standard target? */ if (!t->u.kernel.target->target) { @@ -358,7 +365,7 @@ static inline bool unconditional(const struct arpt_arp *arp) /* Figures out from what hook each rule can be called: returns 0 if * there are loops. Puts hook bitmask in comefrom. */ -static int mark_source_chains(struct xt_table_info *newinfo, +static int mark_source_chains(const struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -379,7 +386,7 @@ static int mark_source_chains(struct xt_table_info *newinfo, for (;;) { const struct arpt_standard_target *t - = (void *)arpt_get_target(e); + = (void *)arpt_get_target_c(e); int visited = e->comefrom & (1 << hook); if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { @@ -463,7 +470,7 @@ static int mark_source_chains(struct xt_table_info *newinfo, return 1; } -static inline int check_entry(struct arpt_entry *e, const char *name) +static inline int check_entry(const struct arpt_entry *e, const char *name) { const struct arpt_entry_target *t; @@ -475,7 +482,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name) if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset) return -EINVAL; - t = arpt_get_target(e); + t = arpt_get_target_c(e); if (e->target_offset + t->u.target_size > e->next_offset) return -EINVAL; @@ -540,14 +547,14 @@ out: return ret; } -static bool check_underflow(struct arpt_entry *e) +static bool check_underflow(const struct arpt_entry *e) { const struct arpt_entry_target *t; unsigned int verdict; if (!unconditional(&e->arp)) return false; - t = arpt_get_target(e); + t = arpt_get_target_c(e); if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) return false; verdict = ((struct arpt_standard_target *)t)->verdict; @@ -557,8 +564,8 @@ static bool check_underflow(struct arpt_entry *e) static inline int check_entry_size_and_hooks(struct arpt_entry *e, struct xt_table_info *newinfo, - unsigned char *base, - unsigned char *limit, + const unsigned char *base, + const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, unsigned int valid_hooks, @@ -768,11 +775,11 @@ static void get_counters(const struct xt_table_info *t, local_bh_enable(); } -static struct xt_counters *alloc_counters(struct xt_table *table) +static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - struct xt_table_info *private = table->private; + const struct xt_table_info *private = table->private; /* We need atomic snapshot of counters: rest doesn't change * (other than comefrom, which userspace doesn't care @@ -790,11 +797,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) } static int copy_entries_to_user(unsigned int total_size, - struct xt_table *table, + const struct xt_table *table, void __user *userptr) { unsigned int off, num; - struct arpt_entry *e; + const struct arpt_entry *e; struct xt_counters *counters; struct xt_table_info *private = table->private; int ret = 0; @@ -814,7 +821,7 @@ static int copy_entries_to_user(unsigned int total_size, /* FIXME: use iterator macros --RR */ /* ... then go back and fix counters and names */ for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ - struct arpt_entry_target *t; + const struct arpt_entry_target *t; e = (struct arpt_entry *)(loc_cpu_entry + off); if (copy_to_user(userptr + off @@ -825,7 +832,7 @@ static int copy_entries_to_user(unsigned int total_size, goto free_counters; } - t = arpt_get_target(e); + t = arpt_get_target_c(e); if (copy_to_user(userptr + off + e->target_offset + offsetof(struct arpt_entry_target, u.user.name), @@ -860,18 +867,18 @@ static int compat_standard_to_user(void __user *dst, const void *src) return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; } -static int compat_calc_entry(struct arpt_entry *e, +static int compat_calc_entry(const struct arpt_entry *e, const struct xt_table_info *info, - void *base, struct xt_table_info *newinfo) + const void *base, struct xt_table_info *newinfo) { - struct arpt_entry_target *t; + const struct arpt_entry_target *t; unsigned int entry_offset; int off, i, ret; off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); entry_offset = (void *)e - base; - t = arpt_get_target(e); + t = arpt_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off); @@ -907,7 +914,8 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(struct net *net, void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, + const int *len, int compat) { char name[ARPT_TABLE_MAXNAMELEN]; struct xt_table *t; @@ -966,7 +974,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) } static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, - int *len) + const int *len) { int ret; struct arpt_get_entries get; @@ -1080,7 +1088,8 @@ static int __do_replace(struct net *net, const char *name, return ret; } -static int do_replace(struct net *net, void __user *user, unsigned int len) +static int do_replace(struct net *net, const void __user *user, + unsigned int len) { int ret; struct arpt_replace tmp; @@ -1140,8 +1149,8 @@ add_counter_to_entry(struct arpt_entry *e, return 0; } -static int do_add_counters(struct net *net, void __user *user, unsigned int len, - int compat) +static int do_add_counters(struct net *net, const void __user *user, + unsigned int len, int compat) { unsigned int i, curcpu; struct xt_counters_info tmp; @@ -1245,10 +1254,10 @@ static inline int check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, struct xt_table_info *newinfo, unsigned int *size, - unsigned char *base, - unsigned char *limit, - unsigned int *hook_entries, - unsigned int *underflows, + const unsigned char *base, + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, unsigned int *i, const char *name) { diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 2a4f745ce36e..e94c18bdfc68 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -176,7 +176,7 @@ ipt_error(struct sk_buff *skb, const struct xt_target_param *par) /* Performance critical - called for every packet */ static inline bool -do_match(struct ipt_entry_match *m, const struct sk_buff *skb, +do_match(const struct ipt_entry_match *m, const struct sk_buff *skb, struct xt_match_param *par) { par->match = m->u.kernel.match; @@ -191,7 +191,7 @@ do_match(struct ipt_entry_match *m, const struct sk_buff *skb, /* Performance critical */ static inline struct ipt_entry * -get_entry(void *base, unsigned int offset) +get_entry(const void *base, unsigned int offset) { return (struct ipt_entry *)(base + offset); } @@ -206,6 +206,13 @@ static inline bool unconditional(const struct ipt_ip *ip) #undef FWINV } +/* for const-correctness */ +static inline const struct ipt_entry_target * +ipt_get_target_c(const struct ipt_entry *e) +{ + return ipt_get_target((struct ipt_entry *)e); +} + #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) static const char *const hooknames[] = { @@ -240,11 +247,11 @@ static struct nf_loginfo trace_loginfo = { /* Mildly perf critical (only if packet tracing is on) */ static inline int -get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, +get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e, const char *hookname, const char **chainname, const char **comment, unsigned int *rulenum) { - struct ipt_standard_target *t = (void *)ipt_get_target(s); + const struct ipt_standard_target *t = (void *)ipt_get_target_c(s); if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) { /* Head of user chain: ERROR target with chainname */ @@ -270,15 +277,15 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, return 0; } -static void trace_packet(struct sk_buff *skb, +static void trace_packet(const struct sk_buff *skb, unsigned int hook, const struct net_device *in, const struct net_device *out, const char *tablename, - struct xt_table_info *private, - struct ipt_entry *e) + const struct xt_table_info *private, + const struct ipt_entry *e) { - void *table_base; + const void *table_base; const struct ipt_entry *root; const char *hookname, *chainname, *comment; unsigned int rulenum = 0; @@ -322,9 +329,9 @@ ipt_do_table(struct sk_buff *skb, /* Initializing verdict to NF_DROP keeps gcc happy. */ unsigned int verdict = NF_DROP; const char *indev, *outdev; - void *table_base; + const void *table_base; struct ipt_entry *e, *back; - struct xt_table_info *private; + const struct xt_table_info *private; struct xt_match_param mtpar; struct xt_target_param tgpar; @@ -357,7 +364,7 @@ ipt_do_table(struct sk_buff *skb, back = get_entry(table_base, private->underflow[hook]); do { - struct ipt_entry_target *t; + const struct ipt_entry_target *t; IP_NF_ASSERT(e); IP_NF_ASSERT(back); @@ -450,7 +457,7 @@ ipt_do_table(struct sk_buff *skb, /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct xt_table_info *newinfo, +mark_source_chains(const struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -468,8 +475,8 @@ mark_source_chains(struct xt_table_info *newinfo, e->counters.pcnt = pos; for (;;) { - struct ipt_standard_target *t - = (void *)ipt_get_target(e); + const struct ipt_standard_target *t + = (void *)ipt_get_target_c(e); int visited = e->comefrom & (1 << hook); if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { @@ -578,9 +585,9 @@ cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) } static int -check_entry(struct ipt_entry *e, const char *name) +check_entry(const struct ipt_entry *e, const char *name) { - struct ipt_entry_target *t; + const struct ipt_entry_target *t; if (!ip_checkentry(&e->ip)) { duprintf("ip_tables: ip check failed %p %s.\n", e, name); @@ -591,7 +598,7 @@ check_entry(struct ipt_entry *e, const char *name) e->next_offset) return -EINVAL; - t = ipt_get_target(e); + t = ipt_get_target_c(e); if (e->target_offset + t->u.target_size > e->next_offset) return -EINVAL; @@ -718,14 +725,14 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, return ret; } -static bool check_underflow(struct ipt_entry *e) +static bool check_underflow(const struct ipt_entry *e) { const struct ipt_entry_target *t; unsigned int verdict; if (!unconditional(&e->ip)) return false; - t = ipt_get_target(e); + t = ipt_get_target_c(e); if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) return false; verdict = ((struct ipt_standard_target *)t)->verdict; @@ -736,8 +743,8 @@ static bool check_underflow(struct ipt_entry *e) static int check_entry_size_and_hooks(struct ipt_entry *e, struct xt_table_info *newinfo, - unsigned char *base, - unsigned char *limit, + const unsigned char *base, + const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, unsigned int valid_hooks, @@ -952,11 +959,11 @@ get_counters(const struct xt_table_info *t, local_bh_enable(); } -static struct xt_counters * alloc_counters(struct xt_table *table) +static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - struct xt_table_info *private = table->private; + const struct xt_table_info *private = table->private; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -974,11 +981,11 @@ static struct xt_counters * alloc_counters(struct xt_table *table) static int copy_entries_to_user(unsigned int total_size, - struct xt_table *table, + const struct xt_table *table, void __user *userptr) { unsigned int off, num; - struct ipt_entry *e; + const struct ipt_entry *e; struct xt_counters *counters; const struct xt_table_info *private = table->private; int ret = 0; @@ -1030,7 +1037,7 @@ copy_entries_to_user(unsigned int total_size, } } - t = ipt_get_target(e); + t = ipt_get_target_c(e); if (copy_to_user(userptr + off + e->target_offset + offsetof(struct ipt_entry_target, u.user.name), @@ -1066,24 +1073,24 @@ static int compat_standard_to_user(void __user *dst, const void *src) } static inline int -compat_calc_match(struct ipt_entry_match *m, int *size) +compat_calc_match(const struct ipt_entry_match *m, int *size) { *size += xt_compat_match_offset(m->u.kernel.match); return 0; } -static int compat_calc_entry(struct ipt_entry *e, +static int compat_calc_entry(const struct ipt_entry *e, const struct xt_table_info *info, - void *base, struct xt_table_info *newinfo) + const void *base, struct xt_table_info *newinfo) { - struct ipt_entry_target *t; + const struct ipt_entry_target *t; unsigned int entry_offset; int off, i, ret; off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); entry_offset = (void *)e - base; IPT_MATCH_ITERATE(e, compat_calc_match, &off); - t = ipt_get_target(e); + t = ipt_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; ret = xt_compat_add_offset(AF_INET, entry_offset, off); @@ -1119,7 +1126,8 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(struct net *net, void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, + const int *len, int compat) { char name[IPT_TABLE_MAXNAMELEN]; struct xt_table *t; @@ -1179,7 +1187,8 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) } static int -get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len) +get_entries(struct net *net, struct ipt_get_entries __user *uptr, + const int *len) { int ret; struct ipt_get_entries get; @@ -1289,7 +1298,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, } static int -do_replace(struct net *net, void __user *user, unsigned int len) +do_replace(struct net *net, const void __user *user, unsigned int len) { int ret; struct ipt_replace tmp; @@ -1350,7 +1359,8 @@ add_counter_to_entry(struct ipt_entry *e, } static int -do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) +do_add_counters(struct net *net, const void __user *user, + unsigned int len, int compat) { unsigned int i, curcpu; struct xt_counters_info tmp; @@ -1546,10 +1556,10 @@ static int check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, struct xt_table_info *newinfo, unsigned int *size, - unsigned char *base, - unsigned char *limit, - unsigned int *hook_entries, - unsigned int *underflows, + const unsigned char *base, + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, unsigned int *i, const char *name) { diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 3ff4fd50e96e..4185099c2943 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -208,7 +208,7 @@ ip6t_error(struct sk_buff *skb, const struct xt_target_param *par) /* Performance critical - called for every packet */ static inline bool -do_match(struct ip6t_entry_match *m, const struct sk_buff *skb, +do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb, struct xt_match_param *par) { par->match = m->u.kernel.match; @@ -222,7 +222,7 @@ do_match(struct ip6t_entry_match *m, const struct sk_buff *skb, } static inline struct ip6t_entry * -get_entry(void *base, unsigned int offset) +get_entry(const void *base, unsigned int offset) { return (struct ip6t_entry *)(base + offset); } @@ -236,6 +236,12 @@ static inline bool unconditional(const struct ip6t_ip6 *ipv6) return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; } +static inline const struct ip6t_entry_target * +ip6t_get_target_c(const struct ip6t_entry *e) +{ + return ip6t_get_target((struct ip6t_entry *)e); +} + #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) /* This cries for unification! */ @@ -271,11 +277,11 @@ static struct nf_loginfo trace_loginfo = { /* Mildly perf critical (only if packet tracing is on) */ static inline int -get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, +get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e, const char *hookname, const char **chainname, const char **comment, unsigned int *rulenum) { - struct ip6t_standard_target *t = (void *)ip6t_get_target(s); + const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s); if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { /* Head of user chain: ERROR target with chainname */ @@ -301,15 +307,15 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, return 0; } -static void trace_packet(struct sk_buff *skb, +static void trace_packet(const struct sk_buff *skb, unsigned int hook, const struct net_device *in, const struct net_device *out, const char *tablename, - struct xt_table_info *private, - struct ip6t_entry *e) + const struct xt_table_info *private, + const struct ip6t_entry *e) { - void *table_base; + const void *table_base; const struct ip6t_entry *root; const char *hookname, *chainname, *comment; unsigned int rulenum = 0; @@ -352,9 +358,9 @@ ip6t_do_table(struct sk_buff *skb, /* Initializing verdict to NF_DROP keeps gcc happy. */ unsigned int verdict = NF_DROP; const char *indev, *outdev; - void *table_base; + const void *table_base; struct ip6t_entry *e, *back; - struct xt_table_info *private; + const struct xt_table_info *private; struct xt_match_param mtpar; struct xt_target_param tgpar; @@ -385,7 +391,7 @@ ip6t_do_table(struct sk_buff *skb, back = get_entry(table_base, private->underflow[hook]); do { - struct ip6t_entry_target *t; + const struct ip6t_entry_target *t; IP_NF_ASSERT(e); IP_NF_ASSERT(back); @@ -400,7 +406,7 @@ ip6t_do_table(struct sk_buff *skb, ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr), 1); - t = ip6t_get_target(e); + t = ip6t_get_target_c(e); IP_NF_ASSERT(t->u.kernel.target); #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ @@ -482,7 +488,7 @@ ip6t_do_table(struct sk_buff *skb, /* Figures out from what hook each rule can be called: returns 0 if there are loops. Puts hook bitmask in comefrom. */ static int -mark_source_chains(struct xt_table_info *newinfo, +mark_source_chains(const struct xt_table_info *newinfo, unsigned int valid_hooks, void *entry0) { unsigned int hook; @@ -500,8 +506,8 @@ mark_source_chains(struct xt_table_info *newinfo, e->counters.pcnt = pos; for (;;) { - struct ip6t_standard_target *t - = (void *)ip6t_get_target(e); + const struct ip6t_standard_target *t + = (void *)ip6t_get_target_c(e); int visited = e->comefrom & (1 << hook); if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { @@ -610,9 +616,9 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) } static int -check_entry(struct ip6t_entry *e, const char *name) +check_entry(const struct ip6t_entry *e, const char *name) { - struct ip6t_entry_target *t; + const struct ip6t_entry_target *t; if (!ip6_checkentry(&e->ipv6)) { duprintf("ip_tables: ip check failed %p %s.\n", e, name); @@ -623,7 +629,7 @@ check_entry(struct ip6t_entry *e, const char *name) e->next_offset) return -EINVAL; - t = ip6t_get_target(e); + t = ip6t_get_target_c(e); if (e->target_offset + t->u.target_size > e->next_offset) return -EINVAL; @@ -750,14 +756,14 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, return ret; } -static bool check_underflow(struct ip6t_entry *e) +static bool check_underflow(const struct ip6t_entry *e) { const struct ip6t_entry_target *t; unsigned int verdict; if (!unconditional(&e->ipv6)) return false; - t = ip6t_get_target(e); + t = ip6t_get_target_c(e); if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) return false; verdict = ((struct ip6t_standard_target *)t)->verdict; @@ -768,8 +774,8 @@ static bool check_underflow(struct ip6t_entry *e) static int check_entry_size_and_hooks(struct ip6t_entry *e, struct xt_table_info *newinfo, - unsigned char *base, - unsigned char *limit, + const unsigned char *base, + const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, unsigned int valid_hooks, @@ -984,11 +990,11 @@ get_counters(const struct xt_table_info *t, local_bh_enable(); } -static struct xt_counters *alloc_counters(struct xt_table *table) +static struct xt_counters *alloc_counters(const struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; - struct xt_table_info *private = table->private; + const struct xt_table_info *private = table->private; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -1006,11 +1012,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) static int copy_entries_to_user(unsigned int total_size, - struct xt_table *table, + const struct xt_table *table, void __user *userptr) { unsigned int off, num; - struct ip6t_entry *e; + const struct ip6t_entry *e; struct xt_counters *counters; const struct xt_table_info *private = table->private; int ret = 0; @@ -1062,7 +1068,7 @@ copy_entries_to_user(unsigned int total_size, } } - t = ip6t_get_target(e); + t = ip6t_get_target_c(e); if (copy_to_user(userptr + off + e->target_offset + offsetof(struct ip6t_entry_target, u.user.name), @@ -1098,24 +1104,24 @@ static int compat_standard_to_user(void __user *dst, const void *src) } static inline int -compat_calc_match(struct ip6t_entry_match *m, int *size) +compat_calc_match(const struct ip6t_entry_match *m, int *size) { *size += xt_compat_match_offset(m->u.kernel.match); return 0; } -static int compat_calc_entry(struct ip6t_entry *e, +static int compat_calc_entry(const struct ip6t_entry *e, const struct xt_table_info *info, - void *base, struct xt_table_info *newinfo) + const void *base, struct xt_table_info *newinfo) { - struct ip6t_entry_target *t; + const struct ip6t_entry_target *t; unsigned int entry_offset; int off, i, ret; off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); entry_offset = (void *)e - base; IP6T_MATCH_ITERATE(e, compat_calc_match, &off); - t = ip6t_get_target(e); + t = ip6t_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; ret = xt_compat_add_offset(AF_INET6, entry_offset, off); @@ -1151,7 +1157,8 @@ static int compat_table_info(const struct xt_table_info *info, } #endif -static int get_info(struct net *net, void __user *user, int *len, int compat) +static int get_info(struct net *net, void __user *user, + const int *len, int compat) { char name[IP6T_TABLE_MAXNAMELEN]; struct xt_table *t; @@ -1211,7 +1218,8 @@ static int get_info(struct net *net, void __user *user, int *len, int compat) } static int -get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len) +get_entries(struct net *net, struct ip6t_get_entries __user *uptr, + const int *len) { int ret; struct ip6t_get_entries get; @@ -1322,7 +1330,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, } static int -do_replace(struct net *net, void __user *user, unsigned int len) +do_replace(struct net *net, const void __user *user, unsigned int len) { int ret; struct ip6t_replace tmp; @@ -1383,7 +1391,7 @@ add_counter_to_entry(struct ip6t_entry *e, } static int -do_add_counters(struct net *net, void __user *user, unsigned int len, +do_add_counters(struct net *net, const void __user *user, unsigned int len, int compat) { unsigned int i, curcpu; @@ -1582,10 +1590,10 @@ static int check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, struct xt_table_info *newinfo, unsigned int *size, - unsigned char *base, - unsigned char *limit, - unsigned int *hook_entries, - unsigned int *underflows, + const unsigned char *base, + const unsigned char *limit, + const unsigned int *hook_entries, + const unsigned int *underflows, unsigned int *i, const char *name) { -- cgit v1.2.3 From 8fea97ec1772bbf553d89187340ef624d548e115 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 15 Feb 2010 17:45:08 +0100 Subject: netfilter: nf_conntrack: pass template to l4proto ->error() handler The error handlers might need the template to get the conntrack zone introduced in the next patches to perform a conntrack lookup. Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_l4proto.h | 4 ++-- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 3 ++- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 3 ++- net/netfilter/nf_conntrack_core.c | 3 ++- net/netfilter/nf_conntrack_proto_dccp.c | 5 +++-- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 4 ++-- net/netfilter/nf_conntrack_proto_udplite.c | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index ca6dcf3445ab..e3d3ee3c06a2 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -49,8 +49,8 @@ struct nf_conntrack_l4proto { /* Called when a conntrack entry is destroyed */ void (*destroy)(struct nf_conn *ct); - int (*error)(struct net *net, struct sk_buff *skb, unsigned int dataoff, - enum ip_conntrack_info *ctinfo, + int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, + unsigned int dataoff, enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum); /* Print out the per-protocol part of the tuple. Return like seq_* */ diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7afd39b5b781..327826a968a8 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -163,7 +163,8 @@ icmp_error_message(struct net *net, struct sk_buff *skb, /* Small and modified version of icmp_rcv */ static int -icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, +icmp_error(struct net *net, struct nf_conn *tmpl, + struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) { const struct icmphdr *icmph; diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c7b8bd1d7984..d772dc21857f 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -179,7 +179,8 @@ icmpv6_error_message(struct net *net, } static int -icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, +icmpv6_error(struct net *net, struct nf_conn *tmpl, + struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) { const struct icmp6hdr *icmp6h; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index bd831410a396..65351ed5d815 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -799,7 +799,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, * inverse of the return code tells to the netfilter * core what to do with the packet. */ if (l4proto->error != NULL) { - ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum); + ret = l4proto->error(net, tmpl, skb, dataoff, &ctinfo, + pf, hooknum); if (ret <= 0) { NF_CT_STAT_INC_ATOMIC(net, error); NF_CT_STAT_INC_ATOMIC(net, invalid); diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index dd375500dccc..9a2815549375 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -561,8 +561,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, return NF_ACCEPT; } -static int dccp_error(struct net *net, struct sk_buff *skb, - unsigned int dataoff, enum ip_conntrack_info *ctinfo, +static int dccp_error(struct net *net, struct nf_conn *tmpl, + struct sk_buff *skb, unsigned int dataoff, + enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) { struct dccp_hdr _dh, *dh; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index ad118053971a..9dd8cd4fb6e6 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -760,7 +760,7 @@ static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] = }; /* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */ -static int tcp_error(struct net *net, +static int tcp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 8d38f9a4bed8..8289088b8218 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -91,8 +91,8 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb, return true; } -static int udp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, - enum ip_conntrack_info *ctinfo, +static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, + unsigned int dataoff, enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) { diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 0b1bc9ba6678..263b5a72588d 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -89,7 +89,7 @@ static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb, return true; } -static int udplite_error(struct net *net, +static int udplite_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, unsigned int dataoff, enum ip_conntrack_info *ctinfo, -- cgit v1.2.3 From 5d0aa2ccd4699a01cfdf14886191c249d7b45a01 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 15 Feb 2010 18:13:33 +0100 Subject: netfilter: nf_conntrack: add support for "conntrack zones" Normally, each connection needs a unique identity. Conntrack zones allow to specify a numerical zone using the CT target, connections in different zones can use the same identity. Example: iptables -t raw -A PREROUTING -i veth0 -j CT --zone 1 iptables -t raw -A OUTPUT -o veth1 -j CT --zone 1 Signed-off-by: Patrick McHardy --- include/linux/netfilter/xt_CT.h | 2 +- include/net/ip.h | 3 + include/net/ipv6.h | 3 + include/net/netfilter/nf_conntrack.h | 5 +- include/net/netfilter/nf_conntrack_core.h | 3 +- include/net/netfilter/nf_conntrack_expect.h | 9 +- include/net/netfilter/nf_conntrack_extend.h | 2 + include/net/netfilter/nf_conntrack_zones.h | 23 ++++++ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 3 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 8 +- net/ipv4/netfilter/nf_defrag_ipv4.c | 12 ++- net/ipv4/netfilter/nf_nat_core.c | 24 +++--- net/ipv4/netfilter/nf_nat_pptp.c | 3 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 12 ++- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 8 +- net/netfilter/Kconfig | 13 +++ net/netfilter/nf_conntrack_core.c | 109 +++++++++++++++++++------ net/netfilter/nf_conntrack_expect.c | 21 +++-- net/netfilter/nf_conntrack_h323_main.c | 3 +- net/netfilter/nf_conntrack_netlink.c | 20 ++--- net/netfilter/nf_conntrack_pptp.c | 14 ++-- net/netfilter/nf_conntrack_sip.c | 3 +- net/netfilter/nf_conntrack_standalone.c | 6 ++ net/netfilter/xt_CT.c | 8 +- net/netfilter/xt_connlimit.c | 4 +- 25 files changed, 236 insertions(+), 85 deletions(-) create mode 100644 include/net/netfilter/nf_conntrack_zones.h diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index 7fd0effe1316..1b564106891d 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h @@ -5,7 +5,7 @@ struct xt_ct_target_info { u_int16_t flags; - u_int16_t __unused; + u_int16_t zone; u_int32_t ct_events; u_int32_t exp_events; char helper[16]; diff --git a/include/net/ip.h b/include/net/ip.h index fb63371c07a8..7bc47873e3fc 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -352,8 +352,11 @@ enum ip_defrag_users { IP_DEFRAG_LOCAL_DELIVER, IP_DEFRAG_CALL_RA_CHAIN, IP_DEFRAG_CONNTRACK_IN, + __IP_DEFRAG_CONNTRACK_IN_END = IP_DEFRAG_CONNTRACK_IN + USHORT_MAX, IP_DEFRAG_CONNTRACK_OUT, + __IP_DEFRAG_CONNTRACK_OUT_END = IP_DEFRAG_CONNTRACK_OUT + USHORT_MAX, IP_DEFRAG_CONNTRACK_BRIDGE_IN, + __IP_DEFRAG_CONNTRACK_BRIDGE_IN = IP_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX, IP_DEFRAG_VS_IN, IP_DEFRAG_VS_OUT, IP_DEFRAG_VS_FWD diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 299bbf5adfb6..639ec53ea081 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -355,8 +355,11 @@ struct inet_frag_queue; enum ip6_defrag_users { IP6_DEFRAG_LOCAL_DELIVER, IP6_DEFRAG_CONNTRACK_IN, + __IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHORT_MAX, IP6_DEFRAG_CONNTRACK_OUT, + __IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHORT_MAX, IP6_DEFRAG_CONNTRACK_BRIDGE_IN, + __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHORT_MAX, }; struct ip6_create_arg { diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 5b7d8835523f..bde095f7e845 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -198,7 +198,8 @@ extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int null extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size); extern struct nf_conntrack_tuple_hash * -__nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple); +__nf_conntrack_find(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple); extern void nf_conntrack_hash_insert(struct nf_conn *ct); extern void nf_ct_delete_from_lists(struct nf_conn *ct); @@ -267,7 +268,7 @@ extern void nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data); extern void nf_conntrack_free(struct nf_conn *ct); extern struct nf_conn * -nf_conntrack_alloc(struct net *net, +nf_conntrack_alloc(struct net *net, u16 zone, const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *repl, gfp_t gfp); diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 5a449b44ba33..dffde8e6920e 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -49,7 +49,8 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, /* Find a connection corresponding to a tuple. */ extern struct nf_conntrack_tuple_hash * -nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); +nf_conntrack_find_get(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple); extern int __nf_conntrack_confirm(struct sk_buff *skb); diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 4b47ec19ef39..11e815084fcf 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -74,13 +74,16 @@ int nf_conntrack_expect_init(struct net *net); void nf_conntrack_expect_fini(struct net *net); struct nf_conntrack_expect * -__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple); +__nf_ct_expect_find(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * -nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple); +nf_ct_expect_find_get(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple); struct nf_conntrack_expect * -nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple); +nf_ct_find_expectation(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple); void nf_ct_unlink_expect(struct nf_conntrack_expect *exp); void nf_ct_remove_expectations(struct nf_conn *ct); diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index e192dc17c583..2d2a1f9a61d8 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -8,6 +8,7 @@ enum nf_ct_ext_id { NF_CT_EXT_NAT, NF_CT_EXT_ACCT, NF_CT_EXT_ECACHE, + NF_CT_EXT_ZONE, NF_CT_EXT_NUM, }; @@ -15,6 +16,7 @@ enum nf_ct_ext_id { #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache +#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone /* Extensions: optional stuff which isn't permanently in struct. */ struct nf_ct_ext { diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h new file mode 100644 index 000000000000..0bbb2bd51e89 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_zones.h @@ -0,0 +1,23 @@ +#ifndef _NF_CONNTRACK_ZONES_H +#define _NF_CONNTRACK_ZONES_H + +#include + +#define NF_CT_DEFAULT_ZONE 0 + +struct nf_conntrack_zone { + u16 id; +}; + +static inline u16 nf_ct_zone(const struct nf_conn *ct) +{ +#ifdef CONFIG_NF_CONNTRACK_ZONES + struct nf_conntrack_zone *nf_ct_zone; + nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE); + if (nf_ct_zone) + return nf_ct_zone->id; +#endif + return NF_CT_DEFAULT_ZONE; +} + +#endif /* _NF_CONNTRACK_ZONES_H */ diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index d1ea38a7c490..2bb1f87051c4 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -266,7 +267,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) return -EINVAL; } - h = nf_conntrack_find_get(sock_net(sk), &tuple); + h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple); if (h) { struct sockaddr_in sin; struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 327826a968a8..7404bde95994 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; @@ -114,13 +115,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ static int -icmp_error_message(struct net *net, struct sk_buff *skb, +icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, enum ip_conntrack_info *ctinfo, unsigned int hooknum) { struct nf_conntrack_tuple innertuple, origtuple; const struct nf_conntrack_l4proto *innerproto; const struct nf_conntrack_tuple_hash *h; + u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; NF_CT_ASSERT(skb->nfct == NULL); @@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb, *ctinfo = IP_CT_RELATED; - h = nf_conntrack_find_get(net, &innertuple); + h = nf_conntrack_find_get(net, zone, &innertuple); if (!h) { pr_debug("icmp_error_message: no match\n"); return -NF_ACCEPT; @@ -209,7 +211,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, icmph->type != ICMP_REDIRECT) return NF_ACCEPT; - return icmp_error_message(net, skb, ctinfo, hooknum); + return icmp_error_message(net, tmpl, skb, ctinfo, hooknum); } #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index f6f46686cbc0..d498a704d456 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -39,15 +40,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, struct sk_buff *skb) { + u16 zone = NF_CT_DEFAULT_ZONE; + + if (skb->nfct) + zone = nf_ct_zone((struct nf_conn *)skb->nfct); + #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) - return IP_DEFRAG_CONNTRACK_BRIDGE_IN; + return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; #endif if (hooknum == NF_INET_PRE_ROUTING) - return IP_DEFRAG_CONNTRACK_IN; + return IP_DEFRAG_CONNTRACK_IN + zone; else - return IP_DEFRAG_CONNTRACK_OUT; + return IP_DEFRAG_CONNTRACK_OUT + zone; } static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 26066a2327ad..4595281c2863 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -30,6 +30,7 @@ #include #include #include +#include static DEFINE_SPINLOCK(nf_nat_lock); @@ -69,13 +70,14 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put); /* We keep an extra hash for each conntrack, for fast searching. */ static inline unsigned int -hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) +hash_by_src(const struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { unsigned int hash; /* Original src, to ensure we map it consistently if poss. */ hash = jhash_3words((__force u32)tuple->src.u3.ip, - (__force u32)tuple->src.u.all, + (__force u32)tuple->src.u.all ^ zone, tuple->dst.protonum, 0); return ((u64)hash * net->ipv4.nat_htable_size) >> 32; } @@ -139,12 +141,12 @@ same_src(const struct nf_conn *ct, /* Only called for SRC manip */ static int -find_appropriate_src(struct net *net, +find_appropriate_src(struct net *net, u16 zone, const struct nf_conntrack_tuple *tuple, struct nf_conntrack_tuple *result, const struct nf_nat_range *range) { - unsigned int h = hash_by_src(net, tuple); + unsigned int h = hash_by_src(net, zone, tuple); const struct nf_conn_nat *nat; const struct nf_conn *ct; const struct hlist_node *n; @@ -152,7 +154,7 @@ find_appropriate_src(struct net *net, rcu_read_lock(); hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { ct = nat->ct; - if (same_src(ct, tuple)) { + if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) { /* Copy source part from reply tuple. */ nf_ct_invert_tuplepr(result, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); @@ -175,7 +177,7 @@ find_appropriate_src(struct net *net, the ip with the lowest src-ip/dst-ip/proto usage. */ static void -find_best_ips_proto(struct nf_conntrack_tuple *tuple, +find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, const struct nf_nat_range *range, const struct nf_conn *ct, enum nf_nat_manip_type maniptype) @@ -209,7 +211,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, maxip = ntohl(range->max_ip); j = jhash_2words((__force u32)tuple->src.u3.ip, range->flags & IP_NAT_RANGE_PERSISTENT ? - 0 : (__force u32)tuple->dst.u3.ip, 0); + 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); j = ((u64)j * (maxip - minip + 1)) >> 32; *var_ipp = htonl(minip + j); } @@ -229,6 +231,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, { struct net *net = nf_ct_net(ct); const struct nf_nat_protocol *proto; + u16 zone = nf_ct_zone(ct); /* 1) If this srcip/proto/src-proto-part is currently mapped, and that same mapping gives a unique tuple within the given @@ -239,7 +242,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, manips not an issue. */ if (maniptype == IP_NAT_MANIP_SRC && !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { - if (find_appropriate_src(net, orig_tuple, tuple, range)) { + if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) { pr_debug("get_unique_tuple: Found current src map\n"); if (!nf_nat_used_tuple(tuple, ct)) return; @@ -249,7 +252,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, /* 2) Select the least-used IP/proto combination in the given range. */ *tuple = *orig_tuple; - find_best_ips_proto(tuple, range, ct, maniptype); + find_best_ips_proto(zone, tuple, range, ct, maniptype); /* 3) The per-protocol part of the manip is made to map into the range to make a unique tuple. */ @@ -327,7 +330,8 @@ nf_nat_setup_info(struct nf_conn *ct, if (have_to_hash) { unsigned int srchash; - srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + srchash = hash_by_src(net, nf_ct_zone(ct), + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); spin_lock_bh(&nf_nat_lock); /* nf_conntrack_alter_reply might re-allocate exntension aera */ nat = nfct_nat(ct); diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 9eb171056c63..4c060038d29f 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct, pr_debug("trying to unexpect other dir: "); nf_ct_dump_tuple_ip(&t); - other_exp = nf_ct_expect_find_get(net, &t); + other_exp = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); if (other_exp) { nf_ct_unexpect_related(other_exp); nf_ct_expect_put(other_exp); diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 55ce22e5de49..996c3f41fecd 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -191,15 +192,20 @@ out: static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, struct sk_buff *skb) { + u16 zone = NF_CT_DEFAULT_ZONE; + + if (skb->nfct) + zone = nf_ct_zone((struct nf_conn *)skb->nfct); + #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) - return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; + return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; #endif if (hooknum == NF_INET_PRE_ROUTING) - return IP6_DEFRAG_CONNTRACK_IN; + return IP6_DEFRAG_CONNTRACK_IN + zone; else - return IP6_DEFRAG_CONNTRACK_OUT; + return IP6_DEFRAG_CONNTRACK_OUT + zone; } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index d772dc21857f..9be81776415e 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, } static int -icmpv6_error_message(struct net *net, +icmpv6_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, unsigned int icmp6off, enum ip_conntrack_info *ctinfo, @@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net, struct nf_conntrack_tuple intuple, origtuple; const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_l4proto *inproto; + u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; NF_CT_ASSERT(skb->nfct == NULL); @@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net, *ctinfo = IP_CT_RELATED; - h = nf_conntrack_find_get(net, &intuple); + h = nf_conntrack_find_get(net, zone, &intuple); if (!h) { pr_debug("icmpv6_error: no match\n"); return -NF_ACCEPT; @@ -216,7 +218,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, if (icmp6h->icmp6_type >= 128) return NF_ACCEPT; - return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum); + return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum); } #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 4469d45261f4..18d77b5c351a 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -83,6 +83,19 @@ config NF_CONNTRACK_SECMARK If unsure, say 'N'. +config NF_CONNTRACK_ZONES + bool 'Connection tracking zones' + depends on NETFILTER_ADVANCED + depends on NETFILTER_XT_TARGET_CT + help + This option enables support for connection tracking zones. + Normally, each connection needs to have a unique system wide + identity. Connection tracking zones allow to have multiple + connections using the same identity, as long as they are + contained in different zones. + + If unsure, say `N'. + config NF_CONNTRACK_EVENTS bool "Connection tracking events" depends on NETFILTER_ADVANCED diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 65351ed5d815..0c9bbe93cc16 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ static int nf_conntrack_hash_rnd_initted; static unsigned int nf_conntrack_hash_rnd; static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, - unsigned int size, unsigned int rnd) + u16 zone, unsigned int size, unsigned int rnd) { unsigned int n; u_int32_t h; @@ -79,16 +80,16 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, */ n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); h = jhash2((u32 *)tuple, n, - rnd ^ (((__force __u16)tuple->dst.u.all << 16) | - tuple->dst.protonum)); + zone ^ rnd ^ (((__force __u16)tuple->dst.u.all << 16) | + tuple->dst.protonum)); return ((u64)h * size) >> 32; } -static inline u_int32_t hash_conntrack(const struct net *net, +static inline u_int32_t hash_conntrack(const struct net *net, u16 zone, const struct nf_conntrack_tuple *tuple) { - return __hash_conntrack(tuple, net->ct.htable_size, + return __hash_conntrack(tuple, zone, net->ct.htable_size, nf_conntrack_hash_rnd); } @@ -292,11 +293,12 @@ static void death_by_timeout(unsigned long ul_conntrack) * - Caller must lock nf_conntrack_lock before calling this function */ struct nf_conntrack_tuple_hash * -__nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) +__nf_conntrack_find(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; - unsigned int hash = hash_conntrack(net, tuple); + unsigned int hash = hash_conntrack(net, zone, tuple); /* Disable BHs the entire time since we normally need to disable them * at least once for the stats anyway. @@ -304,7 +306,8 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) local_bh_disable(); begin: hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { - if (nf_ct_tuple_equal(tuple, &h->tuple)) { + if (nf_ct_tuple_equal(tuple, &h->tuple) && + nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) { NF_CT_STAT_INC(net, found); local_bh_enable(); return h; @@ -326,21 +329,23 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find); /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * -nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) +nf_conntrack_find_get(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; rcu_read_lock(); begin: - h = __nf_conntrack_find(net, tuple); + h = __nf_conntrack_find(net, zone, tuple); if (h) { ct = nf_ct_tuplehash_to_ctrack(h); if (unlikely(nf_ct_is_dying(ct) || !atomic_inc_not_zero(&ct->ct_general.use))) h = NULL; else { - if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { + if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) || + nf_ct_zone(ct) != zone)) { nf_ct_put(ct); goto begin; } @@ -368,9 +373,11 @@ void nf_conntrack_hash_insert(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); unsigned int hash, repl_hash; + u16 zone; - hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); + zone = nf_ct_zone(ct); + hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); __nf_conntrack_hash_insert(ct, hash, repl_hash); } @@ -387,6 +394,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) struct hlist_nulls_node *n; enum ip_conntrack_info ctinfo; struct net *net; + u16 zone; ct = nf_ct_get(skb, &ctinfo); net = nf_ct_net(ct); @@ -398,8 +406,9 @@ __nf_conntrack_confirm(struct sk_buff *skb) if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) return NF_ACCEPT; - hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); + zone = nf_ct_zone(ct); + hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); /* We're not in hash table, and we refuse to set up related connections for unconfirmed conns. But packet copies and @@ -418,11 +427,13 @@ __nf_conntrack_confirm(struct sk_buff *skb) not in the hash. If there is, we lost race. */ hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - &h->tuple)) + &h->tuple) && + zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) goto out; hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, - &h->tuple)) + &h->tuple) && + zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) goto out; /* Remove from unconfirmed list */ @@ -469,15 +480,19 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, struct net *net = nf_ct_net(ignored_conntrack); struct nf_conntrack_tuple_hash *h; struct hlist_nulls_node *n; - unsigned int hash = hash_conntrack(net, tuple); + struct nf_conn *ct; + u16 zone = nf_ct_zone(ignored_conntrack); + unsigned int hash = hash_conntrack(net, zone, tuple); /* Disable BHs the entire time since we need to disable them at * least once for the stats anyway. */ rcu_read_lock_bh(); hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { - if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && - nf_ct_tuple_equal(tuple, &h->tuple)) { + ct = nf_ct_tuplehash_to_ctrack(h); + if (ct != ignored_conntrack && + nf_ct_tuple_equal(tuple, &h->tuple) && + nf_ct_zone(ct) == zone) { NF_CT_STAT_INC(net, found); rcu_read_unlock_bh(); return 1; @@ -540,7 +555,7 @@ static noinline int early_drop(struct net *net, unsigned int hash) return dropped; } -struct nf_conn *nf_conntrack_alloc(struct net *net, +struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone, const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *repl, gfp_t gfp) @@ -558,7 +573,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, if (nf_conntrack_max && unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { - unsigned int hash = hash_conntrack(net, orig); + unsigned int hash = hash_conntrack(net, zone, orig); if (!early_drop(net, hash)) { atomic_dec(&net->ct.count); if (net_ratelimit()) @@ -595,13 +610,28 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, #ifdef CONFIG_NET_NS ct->ct_net = net; #endif - +#ifdef CONFIG_NF_CONNTRACK_ZONES + if (zone) { + struct nf_conntrack_zone *nf_ct_zone; + + nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, GFP_ATOMIC); + if (!nf_ct_zone) + goto out_free; + nf_ct_zone->id = zone; + } +#endif /* * changes to lookup keys must be done before setting refcnt to 1 */ smp_wmb(); atomic_set(&ct->ct_general.use, 1); return ct; + +#ifdef CONFIG_NF_CONNTRACK_ZONES +out_free: + kmem_cache_free(net->ct.nf_conntrack_cachep, ct); + return ERR_PTR(-ENOMEM); +#endif } EXPORT_SYMBOL_GPL(nf_conntrack_alloc); @@ -631,13 +661,14 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, struct nf_conntrack_tuple repl_tuple; struct nf_conntrack_ecache *ecache; struct nf_conntrack_expect *exp; + u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { pr_debug("Can't invert tuple.\n"); return NULL; } - ct = nf_conntrack_alloc(net, tuple, &repl_tuple, GFP_ATOMIC); + ct = nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC); if (IS_ERR(ct)) { pr_debug("Can't allocate conntrack.\n"); return (struct nf_conntrack_tuple_hash *)ct; @@ -657,7 +688,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, GFP_ATOMIC); spin_lock_bh(&nf_conntrack_lock); - exp = nf_ct_find_expectation(net, tuple); + exp = nf_ct_find_expectation(net, zone, tuple); if (exp) { pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", ct, exp); @@ -713,6 +744,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; + u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num, protonum, &tuple, l3proto, @@ -722,7 +754,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, } /* look for tuple match */ - h = nf_conntrack_find_get(net, &tuple); + h = nf_conntrack_find_get(net, zone, &tuple); if (!h) { h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, skb, dataoff); @@ -958,6 +990,14 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, } EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); +#ifdef CONFIG_NF_CONNTRACK_ZONES +static struct nf_ct_ext_type nf_ct_zone_extend __read_mostly = { + .len = sizeof(struct nf_conntrack_zone), + .align = __alignof__(struct nf_conntrack_zone), + .id = NF_CT_EXT_ZONE, +}; +#endif + #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include @@ -1139,6 +1179,9 @@ static void nf_conntrack_cleanup_init_net(void) nf_conntrack_helper_fini(); nf_conntrack_proto_fini(); +#ifdef CONFIG_NF_CONNTRACK_ZONES + nf_ct_extend_unregister(&nf_ct_zone_extend); +#endif } static void nf_conntrack_cleanup_net(struct net *net) @@ -1214,6 +1257,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) unsigned int hashsize, old_size; struct hlist_nulls_head *hash, *old_hash; struct nf_conntrack_tuple_hash *h; + struct nf_conn *ct; if (current->nsproxy->net_ns != &init_net) return -EOPNOTSUPP; @@ -1240,8 +1284,10 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) while (!hlist_nulls_empty(&init_net.ct.hash[i])) { h = hlist_nulls_entry(init_net.ct.hash[i].first, struct nf_conntrack_tuple_hash, hnnode); + ct = nf_ct_tuplehash_to_ctrack(h); hlist_nulls_del_rcu(&h->hnnode); - bucket = __hash_conntrack(&h->tuple, hashsize, + bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct), + hashsize, nf_conntrack_hash_rnd); hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); } @@ -1299,6 +1345,11 @@ static int nf_conntrack_init_init_net(void) if (ret < 0) goto err_helper; +#ifdef CONFIG_NF_CONNTRACK_ZONES + ret = nf_ct_extend_register(&nf_ct_zone_extend); + if (ret < 0) + goto err_extend; +#endif /* Set up fake conntrack: to never be deleted, not in any hashes */ #ifdef CONFIG_NET_NS nf_conntrack_untracked.ct_net = &init_net; @@ -1309,6 +1360,10 @@ static int nf_conntrack_init_init_net(void) return 0; +#ifdef CONFIG_NF_CONNTRACK_ZONES +err_extend: + nf_conntrack_helper_fini(); +#endif err_helper: nf_conntrack_proto_fini(); err_proto: diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 6182fb1b55de..acb29ccaa41f 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -27,6 +27,7 @@ #include #include #include +#include unsigned int nf_ct_expect_hsize __read_mostly; EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); @@ -84,7 +85,8 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple } struct nf_conntrack_expect * -__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) +__nf_ct_expect_find(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; struct hlist_node *n; @@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) h = nf_ct_expect_dst_hash(tuple); hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) { - if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) + if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && + nf_ct_zone(i->master) == zone) return i; } return NULL; @@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find); /* Just find a expectation corresponding to a tuple. */ struct nf_conntrack_expect * -nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) +nf_ct_expect_find_get(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i; rcu_read_lock(); - i = __nf_ct_expect_find(net, tuple); + i = __nf_ct_expect_find(net, zone, tuple); if (i && !atomic_inc_not_zero(&i->use)) i = NULL; rcu_read_unlock(); @@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); /* If an expectation for this connection is found, it gets delete from * global list then returned. */ struct nf_conntrack_expect * -nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) +nf_ct_find_expectation(struct net *net, u16 zone, + const struct nf_conntrack_tuple *tuple) { struct nf_conntrack_expect *i, *exp = NULL; struct hlist_node *n; @@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) h = nf_ct_expect_dst_hash(tuple); hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { if (!(i->flags & NF_CT_EXPECT_INACTIVE) && - nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { + nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) && + nf_ct_zone(i->master) == zone) { exp = i; break; } @@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, { return a->master == b->master && a->class == b->class && nf_ct_tuple_equal(&a->tuple, &b->tuple) && - nf_ct_tuple_mask_equal(&a->mask, &b->mask); + nf_ct_tuple_mask_equal(&a->mask, &b->mask) && + nf_ct_zone(a->master) == nf_ct_zone(b->master); } /* Generally a bad idea to call this: could have matched already. */ diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 66369490230e..a1c8dd917e12 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -29,6 +29,7 @@ #include #include #include +#include #include /* Parameters */ @@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, tuple.dst.u.tcp.port = port; tuple.dst.protonum = IPPROTO_TCP; - exp = __nf_ct_expect_find(net, &tuple); + exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); if (exp && exp->master == ct) return exp; return NULL; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index db35edac307b..51089cfe1167 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -811,7 +811,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(net, &tuple); + h = nf_conntrack_find_get(net, 0, &tuple); if (!h) return -ENOENT; @@ -872,7 +872,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(net, &tuple); + h = nf_conntrack_find_get(net, 0, &tuple); if (!h) return -ENOENT; @@ -1221,7 +1221,7 @@ ctnetlink_create_conntrack(struct net *net, int err = -EINVAL; struct nf_conntrack_helper *helper; - ct = nf_conntrack_alloc(net, otuple, rtuple, GFP_ATOMIC); + ct = nf_conntrack_alloc(net, 0, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) return ERR_PTR(-ENOMEM); @@ -1325,7 +1325,7 @@ ctnetlink_create_conntrack(struct net *net, if (err < 0) goto err2; - master_h = nf_conntrack_find_get(net, &master); + master_h = nf_conntrack_find_get(net, 0, &master); if (master_h == NULL) { err = -ENOENT; goto err2; @@ -1374,9 +1374,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, spin_lock_bh(&nf_conntrack_lock); if (cda[CTA_TUPLE_ORIG]) - h = __nf_conntrack_find(net, &otuple); + h = __nf_conntrack_find(net, 0, &otuple); else if (cda[CTA_TUPLE_REPLY]) - h = __nf_conntrack_find(net, &rtuple); + h = __nf_conntrack_find(net, 0, &rtuple); if (h == NULL) { err = -ENOENT; @@ -1714,7 +1714,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = nf_ct_expect_find_get(net, &tuple); + exp = nf_ct_expect_find_get(net, 0, &tuple); if (!exp) return -ENOENT; @@ -1770,7 +1770,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, return err; /* bump usage count to 2 */ - exp = nf_ct_expect_find_get(net, &tuple); + exp = nf_ct_expect_find_get(net, 0, &tuple); if (!exp) return -ENOENT; @@ -1855,7 +1855,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], return err; /* Look for master conntrack of this expectation */ - h = nf_conntrack_find_get(net, &master_tuple); + h = nf_conntrack_find_get(net, 0, &master_tuple); if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); @@ -1912,7 +1912,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, return err; spin_lock_bh(&nf_conntrack_lock); - exp = __nf_ct_expect_find(net, &tuple); + exp = __nf_ct_expect_find(net, 0, &tuple); if (!exp) { spin_unlock_bh(&nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 3807ac7faf4c..088944824e13 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct, pr_debug("trying to unexpect other dir: "); nf_ct_dump_tuple(&inv_t); - exp_other = nf_ct_expect_find_get(net, &inv_t); + exp_other = nf_ct_expect_find_get(net, nf_ct_zone(ct), &inv_t); if (exp_other) { /* delete other expectation. */ pr_debug("found\n"); @@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct, rcu_read_unlock(); } -static int destroy_sibling_or_exp(struct net *net, +static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct, const struct nf_conntrack_tuple *t) { const struct nf_conntrack_tuple_hash *h; struct nf_conntrack_expect *exp; struct nf_conn *sibling; + u16 zone = nf_ct_zone(ct); pr_debug("trying to timeout ct or exp for tuple "); nf_ct_dump_tuple(t); - h = nf_conntrack_find_get(net, t); + h = nf_conntrack_find_get(net, zone, t); if (h) { sibling = nf_ct_tuplehash_to_ctrack(h); pr_debug("setting timeout of conntrack %p to 0\n", sibling); @@ -157,7 +159,7 @@ static int destroy_sibling_or_exp(struct net *net, nf_ct_put(sibling); return 1; } else { - exp = nf_ct_expect_find_get(net, t); + exp = nf_ct_expect_find_get(net, zone, t); if (exp) { pr_debug("unexpect_related of expect %p\n", exp); nf_ct_unexpect_related(exp); @@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) t.dst.protonum = IPPROTO_GRE; t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; - if (!destroy_sibling_or_exp(net, &t)) + if (!destroy_sibling_or_exp(net, ct, &t)) pr_debug("failed to timeout original pns->pac ct/exp\n"); /* try reply (pac->pns) tuple */ @@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct) t.dst.protonum = IPPROTO_GRE; t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; - if (!destroy_sibling_or_exp(net, &t)) + if (!destroy_sibling_or_exp(net, ct, &t)) pr_debug("failed to timeout reply pac->pns ct/exp\n"); } diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index fbe8ff5a420a..8dd75d90efc0 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -23,6 +23,7 @@ #include #include #include +#include #include MODULE_LICENSE("GPL"); @@ -836,7 +837,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, rcu_read_lock(); do { - exp = __nf_ct_expect_find(net, &tuple); + exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); if (!exp || exp->master == ct || nfct_help(exp->master)->helper != nfct_help(ct)->helper || diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index e310f1561bb2..24a42efe62ef 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -26,6 +26,7 @@ #include #include #include +#include MODULE_LICENSE("GPL"); @@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v) goto release; #endif +#ifdef CONFIG_NF_CONNTRACK_ZONES + if (seq_printf(s, "zone=%u ", nf_ct_zone(ct))) + goto release; +#endif + if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) goto release; diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 8183a054256f..61c50fa84703 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -16,6 +16,7 @@ #include #include #include +#include static unsigned int xt_ct_target(struct sk_buff *skb, const struct xt_target_param *par) @@ -69,11 +70,16 @@ static bool xt_ct_tg_check(const struct xt_tgchk_param *par) goto out; } +#ifndef CONFIG_NF_CONNTRACK_ZONES + if (info->zone) + goto err1; +#endif + if (nf_ct_l3proto_try_module_get(par->family) < 0) goto err1; memset(&t, 0, sizeof(t)); - ct = nf_conntrack_alloc(par->net, &t, &t, GFP_KERNEL); + ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); if (IS_ERR(ct)) goto err2; diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 0d9d18ea2b09..26997ce90e48 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c @@ -28,6 +28,7 @@ #include #include #include +#include /* we will save the tuples of all connections we care about */ struct xt_connlimit_conn { @@ -114,7 +115,8 @@ static int count_them(struct net *net, /* check the saved connections */ list_for_each_entry_safe(conn, tmp, hash, list) { - found = nf_conntrack_find_get(net, &conn->tuple); + found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, + &conn->tuple); found_ct = NULL; if (found != NULL) -- cgit v1.2.3 From ef00f89f1eb7e056aab9dfe068521e6f2320c94a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 15 Feb 2010 18:14:57 +0100 Subject: netfilter: ctnetlink: add zone support Parse and dump the conntrack zone in ctnetlink. Signed-off-by: Patrick McHardy --- include/linux/netfilter/nfnetlink_conntrack.h | 2 + net/netfilter/nf_conntrack_netlink.c | 92 +++++++++++++++++++++------ 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index ed4ef8d0b11b..9ed534c991b9 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -40,6 +40,7 @@ enum ctattr_type { CTA_NAT_SEQ_ADJ_ORIG, CTA_NAT_SEQ_ADJ_REPLY, CTA_SECMARK, + CTA_ZONE, __CTA_MAX }; #define CTA_MAX (__CTA_MAX - 1) @@ -159,6 +160,7 @@ enum ctattr_expect { CTA_EXPECT_TIMEOUT, CTA_EXPECT_ID, CTA_EXPECT_HELP_NAME, + CTA_EXPECT_ZONE, __CTA_EXPECT_MAX }; #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 51089cfe1167..8b05f364b2f2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_NF_NAT_NEEDED #include #include @@ -379,6 +380,9 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, goto nla_put_failure; nla_nest_end(skb, nest_parms); + if (nf_ct_zone(ct)) + NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct))); + if (ctnetlink_dump_status(skb, ct) < 0 || ctnetlink_dump_timeout(skb, ct) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || @@ -517,6 +521,9 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) goto nla_put_failure; nla_nest_end(skb, nest_parms); + if (nf_ct_zone(ct)) + NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct))); + if (ctnetlink_dump_id(skb, ct) < 0) goto nla_put_failure; @@ -750,6 +757,21 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[], return 0; } +static int +ctnetlink_parse_zone(const struct nlattr *attr, u16 *zone) +{ + if (attr) +#ifdef CONFIG_NF_CONNTRACK_ZONES + *zone = ntohs(nla_get_be16(attr)); +#else + return -EOPNOTSUPP; +#endif + else + *zone = 0; + + return 0; +} + static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = { [CTA_HELP_NAME] = { .type = NLA_NUL_STRING }, }; @@ -781,6 +803,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { [CTA_ID] = { .type = NLA_U32 }, [CTA_NAT_DST] = { .type = NLA_NESTED }, [CTA_TUPLE_MASTER] = { .type = NLA_NESTED }, + [CTA_ZONE] = { .type = NLA_U16 }, }; static int @@ -794,7 +817,12 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conn *ct; struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; - int err = 0; + u16 zone; + int err; + + err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); + if (err < 0) + return err; if (cda[CTA_TUPLE_ORIG]) err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); @@ -811,7 +839,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(net, 0, &tuple); + h = nf_conntrack_find_get(net, zone, &tuple); if (!h) return -ENOENT; @@ -856,12 +884,17 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, struct sk_buff *skb2 = NULL; struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; - int err = 0; + u16 zone; + int err; if (nlh->nlmsg_flags & NLM_F_DUMP) return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, ctnetlink_done); + err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); + if (err < 0) + return err; + if (cda[CTA_TUPLE_ORIG]) err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); else if (cda[CTA_TUPLE_REPLY]) @@ -872,7 +905,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - h = nf_conntrack_find_get(net, 0, &tuple); + h = nf_conntrack_find_get(net, zone, &tuple); if (!h) return -ENOENT; @@ -1211,7 +1244,7 @@ ctnetlink_change_conntrack(struct nf_conn *ct, } static struct nf_conn * -ctnetlink_create_conntrack(struct net *net, +ctnetlink_create_conntrack(struct net *net, u16 zone, const struct nlattr * const cda[], struct nf_conntrack_tuple *otuple, struct nf_conntrack_tuple *rtuple, @@ -1221,7 +1254,7 @@ ctnetlink_create_conntrack(struct net *net, int err = -EINVAL; struct nf_conntrack_helper *helper; - ct = nf_conntrack_alloc(net, 0, otuple, rtuple, GFP_ATOMIC); + ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); if (IS_ERR(ct)) return ERR_PTR(-ENOMEM); @@ -1325,7 +1358,7 @@ ctnetlink_create_conntrack(struct net *net, if (err < 0) goto err2; - master_h = nf_conntrack_find_get(net, 0, &master); + master_h = nf_conntrack_find_get(net, zone, &master); if (master_h == NULL) { err = -ENOENT; goto err2; @@ -1358,7 +1391,12 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_tuple_hash *h = NULL; struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; - int err = 0; + u16 zone; + int err; + + err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone); + if (err < 0) + return err; if (cda[CTA_TUPLE_ORIG]) { err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3); @@ -1374,9 +1412,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, spin_lock_bh(&nf_conntrack_lock); if (cda[CTA_TUPLE_ORIG]) - h = __nf_conntrack_find(net, 0, &otuple); + h = __nf_conntrack_find(net, zone, &otuple); else if (cda[CTA_TUPLE_REPLY]) - h = __nf_conntrack_find(net, 0, &rtuple); + h = __nf_conntrack_find(net, zone, &rtuple); if (h == NULL) { err = -ENOENT; @@ -1384,7 +1422,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, struct nf_conn *ct; enum ip_conntrack_events events; - ct = ctnetlink_create_conntrack(net, cda, &otuple, + ct = ctnetlink_create_conntrack(net, zone, cda, &otuple, &rtuple, u3); if (IS_ERR(ct)) { err = PTR_ERR(ct); @@ -1698,7 +1736,8 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, struct sk_buff *skb2; struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; - int err = 0; + u16 zone; + int err; if (nlh->nlmsg_flags & NLM_F_DUMP) { return netlink_dump_start(ctnl, skb, nlh, @@ -1706,6 +1745,10 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, ctnetlink_exp_done); } + err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); + if (err < 0) + return err; + if (cda[CTA_EXPECT_MASTER]) err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3); else @@ -1714,7 +1757,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (err < 0) return err; - exp = nf_ct_expect_find_get(net, 0, &tuple); + exp = nf_ct_expect_find_get(net, zone, &tuple); if (!exp) return -ENOENT; @@ -1761,16 +1804,21 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, struct hlist_node *n, *next; u_int8_t u3 = nfmsg->nfgen_family; unsigned int i; + u16 zone; int err; if (cda[CTA_EXPECT_TUPLE]) { /* delete a single expect by tuple */ + err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); + if (err < 0) + return err; + err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); if (err < 0) return err; /* bump usage count to 2 */ - exp = nf_ct_expect_find_get(net, 0, &tuple); + exp = nf_ct_expect_find_get(net, zone, &tuple); if (!exp) return -ENOENT; @@ -1832,7 +1880,8 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, } static int -ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], +ctnetlink_create_expect(struct net *net, u16 zone, + const struct nlattr * const cda[], u_int8_t u3, u32 pid, int report) { @@ -1855,7 +1904,7 @@ ctnetlink_create_expect(struct net *net, const struct nlattr * const cda[], return err; /* Look for master conntrack of this expectation */ - h = nf_conntrack_find_get(net, 0, &master_tuple); + h = nf_conntrack_find_get(net, zone, &master_tuple); if (!h) return -ENOENT; ct = nf_ct_tuplehash_to_ctrack(h); @@ -1900,25 +1949,30 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, struct nf_conntrack_expect *exp; struct nfgenmsg *nfmsg = nlmsg_data(nlh); u_int8_t u3 = nfmsg->nfgen_family; - int err = 0; + u16 zone; + int err; if (!cda[CTA_EXPECT_TUPLE] || !cda[CTA_EXPECT_MASK] || !cda[CTA_EXPECT_MASTER]) return -EINVAL; + err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone); + if (err < 0) + return err; + err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); if (err < 0) return err; spin_lock_bh(&nf_conntrack_lock); - exp = __nf_ct_expect_find(net, 0, &tuple); + exp = __nf_ct_expect_find(net, zone, &tuple); if (!exp) { spin_unlock_bh(&nf_conntrack_lock); err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) { - err = ctnetlink_create_expect(net, cda, + err = ctnetlink_create_expect(net, zone, cda, u3, NETLINK_CB(skb).pid, nlmsg_report(nlh)); -- cgit v1.2.3 From 1756de262e41112a8a8927808eb2f03d21fd4786 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 15 Feb 2010 18:15:55 +0100 Subject: netfilter: ebtables: abort if next_offset is too small next_offset must be > 0, otherwise this loops forever. The offset also contains the size of the ebt_entry structure itself, so anything smaller is invalid. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- net/bridge/netfilter/ebtables.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index bcdf02d866b8..4370e9680487 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -444,6 +444,8 @@ static int ebt_verify_pointers(const struct ebt_replace *repl, break; if (left < e->next_offset) break; + if (e->next_offset < sizeof(struct ebt_entry)) + return -EINVAL; offset += e->next_offset; } } -- cgit v1.2.3 From fc0e3df4f00a5f62c2f2fce84bf496136b58c474 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 15 Feb 2010 18:16:26 +0100 Subject: netfilter: ebtables: avoid explicit XT_ALIGN() in match/targets This will cause trouble once CONFIG_COMPAT support is added to ebtables. xt_compat_*_offset() calculate the kernel/userland structure size delta using: XT_ALIGN(size) - COMPAT_XT_ALIGN(size) If the match/target sizes are aligned at registration time, delta is always zero. Should have zero effect for existing systems: xtables uses XT_ALIGN() whenever it deals with match/target sizes. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- net/bridge/netfilter/ebt_802_3.c | 2 +- net/bridge/netfilter/ebt_arp.c | 2 +- net/bridge/netfilter/ebt_arpreply.c | 2 +- net/bridge/netfilter/ebt_dnat.c | 2 +- net/bridge/netfilter/ebt_ip.c | 2 +- net/bridge/netfilter/ebt_ip6.c | 2 +- net/bridge/netfilter/ebt_limit.c | 2 +- net/bridge/netfilter/ebt_log.c | 2 +- net/bridge/netfilter/ebt_mark.c | 2 +- net/bridge/netfilter/ebt_mark_m.c | 2 +- net/bridge/netfilter/ebt_nflog.c | 2 +- net/bridge/netfilter/ebt_pkttype.c | 2 +- net/bridge/netfilter/ebt_redirect.c | 2 +- net/bridge/netfilter/ebt_snat.c | 2 +- net/bridge/netfilter/ebt_stp.c | 2 +- net/bridge/netfilter/ebt_ulog.c | 2 +- net/bridge/netfilter/ebt_vlan.c | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c index bd91dc58d49b..5d1176758ca5 100644 --- a/net/bridge/netfilter/ebt_802_3.c +++ b/net/bridge/netfilter/ebt_802_3.c @@ -52,7 +52,7 @@ static struct xt_match ebt_802_3_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_802_3_mt, .checkentry = ebt_802_3_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_802_3_info)), + .matchsize = sizeof(struct ebt_802_3_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c index b7ad60419f9a..e727697c5847 100644 --- a/net/bridge/netfilter/ebt_arp.c +++ b/net/bridge/netfilter/ebt_arp.c @@ -120,7 +120,7 @@ static struct xt_match ebt_arp_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_arp_mt, .checkentry = ebt_arp_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_arp_info)), + .matchsize = sizeof(struct ebt_arp_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c index 76584cd72e57..f392e9d93f53 100644 --- a/net/bridge/netfilter/ebt_arpreply.c +++ b/net/bridge/netfilter/ebt_arpreply.c @@ -78,7 +78,7 @@ static struct xt_target ebt_arpreply_tg_reg __read_mostly = { .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING), .target = ebt_arpreply_tg, .checkentry = ebt_arpreply_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_arpreply_info)), + .targetsize = sizeof(struct ebt_arpreply_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index 6b49ea9e31fb..2bb40d728a35 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c @@ -54,7 +54,7 @@ static struct xt_target ebt_dnat_tg_reg __read_mostly = { (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING), .target = ebt_dnat_tg, .checkentry = ebt_dnat_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), + .targetsize = sizeof(struct ebt_nat_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index d771bbfbcbe6..5de6df6f86b8 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -110,7 +110,7 @@ static struct xt_match ebt_ip_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_ip_mt, .checkentry = ebt_ip_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_ip_info)), + .matchsize = sizeof(struct ebt_ip_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index 784a6573876c..bbf2534ef026 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c @@ -122,7 +122,7 @@ static struct xt_match ebt_ip6_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_ip6_mt, .checkentry = ebt_ip6_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_ip6_info)), + .matchsize = sizeof(struct ebt_ip6_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c index f7bd9192ff0c..9dd16e6b10e7 100644 --- a/net/bridge/netfilter/ebt_limit.c +++ b/net/bridge/netfilter/ebt_limit.c @@ -90,7 +90,7 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_limit_mt, .checkentry = ebt_limit_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_limit_info)), + .matchsize = sizeof(struct ebt_limit_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index e4ea3fdd1d41..e873924ddb5d 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -195,7 +195,7 @@ static struct xt_target ebt_log_tg_reg __read_mostly = { .family = NFPROTO_BRIDGE, .target = ebt_log_tg, .checkentry = ebt_log_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_log_info)), + .targetsize = sizeof(struct ebt_log_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 2fee7e8e2e93..153e167374a2 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -59,7 +59,7 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = { .family = NFPROTO_BRIDGE, .target = ebt_mark_tg, .checkentry = ebt_mark_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_mark_t_info)), + .targetsize = sizeof(struct ebt_mark_t_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index ea570f214b1d..89abf4030399 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c @@ -41,7 +41,7 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_mark_mt, .checkentry = ebt_mark_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_mark_m_info)), + .matchsize = sizeof(struct ebt_mark_m_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c index 2a63d996dd4e..40dbd248b9ae 100644 --- a/net/bridge/netfilter/ebt_nflog.c +++ b/net/bridge/netfilter/ebt_nflog.c @@ -51,7 +51,7 @@ static struct xt_target ebt_nflog_tg_reg __read_mostly = { .family = NFPROTO_BRIDGE, .target = ebt_nflog_tg, .checkentry = ebt_nflog_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_nflog_info)), + .targetsize = sizeof(struct ebt_nflog_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c index 883e96e2a542..e2a07e6cbef3 100644 --- a/net/bridge/netfilter/ebt_pkttype.c +++ b/net/bridge/netfilter/ebt_pkttype.c @@ -36,7 +36,7 @@ static struct xt_match ebt_pkttype_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_pkttype_mt, .checkentry = ebt_pkttype_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_pkttype_info)), + .matchsize = sizeof(struct ebt_pkttype_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index c8a49f7a57ba..9be8fbcd370b 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c @@ -59,7 +59,7 @@ static struct xt_target ebt_redirect_tg_reg __read_mostly = { (1 << NF_BR_BROUTING), .target = ebt_redirect_tg, .checkentry = ebt_redirect_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_redirect_info)), + .targetsize = sizeof(struct ebt_redirect_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index 8d04d4c302bd..9c7b520765a2 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c @@ -67,7 +67,7 @@ static struct xt_target ebt_snat_tg_reg __read_mostly = { .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING), .target = ebt_snat_tg, .checkentry = ebt_snat_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), + .targetsize = sizeof(struct ebt_nat_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 75e29a9cebda..92a93d363765 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c @@ -177,7 +177,7 @@ static struct xt_match ebt_stp_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_stp_mt, .checkentry = ebt_stp_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_stp_info)), + .matchsize = sizeof(struct ebt_stp_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index ce50688a6431..c6ac657074a6 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -275,7 +275,7 @@ static struct xt_target ebt_ulog_tg_reg __read_mostly = { .family = NFPROTO_BRIDGE, .target = ebt_ulog_tg, .checkentry = ebt_ulog_tg_check, - .targetsize = XT_ALIGN(sizeof(struct ebt_ulog_info)), + .targetsize = sizeof(struct ebt_ulog_info), .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index 3dddd489328e..be1dd2e1f615 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c @@ -163,7 +163,7 @@ static struct xt_match ebt_vlan_mt_reg __read_mostly = { .family = NFPROTO_BRIDGE, .match = ebt_vlan_mt, .checkentry = ebt_vlan_mt_check, - .matchsize = XT_ALIGN(sizeof(struct ebt_vlan_info)), + .matchsize = sizeof(struct ebt_vlan_info), .me = THIS_MODULE, }; -- cgit v1.2.3 From 3e5e524ffb5fcf2447eb5dd9f8e54ad22dd9baa7 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Mon, 15 Feb 2010 18:17:10 +0100 Subject: netfilter: CONFIG_COMPAT: allow delta to exceed 32767 with 32 bit userland and 64 bit kernels, it is unlikely but possible that insertion of new rules fails even tough there are only about 2000 iptables rules. This happens because the compat delta is using a short int. Easily reproducible via "iptables -m limit" ; after about 2050 rules inserting new ones fails with -ELOOP. Note that compat_delta included 2 bytes of padding on x86_64, so structure size remains the same. Signed-off-by: Florian Westphal Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 2 +- net/netfilter/x_tables.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index c61758f4be31..a18119fb88f0 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -588,7 +588,7 @@ extern void xt_compat_unlock(u_int8_t af); extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta); extern void xt_compat_flush_offsets(u_int8_t af); -extern short xt_compat_calc_jump(u_int8_t af, unsigned int offset); +extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset); extern int xt_compat_match_offset(const struct xt_match *match); extern int xt_compat_match_from_user(struct xt_entry_match *m, diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 69c56287d518..0a12cedfe9e3 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -39,7 +39,7 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module"); struct compat_delta { struct compat_delta *next; unsigned int offset; - short delta; + int delta; }; struct xt_af { @@ -439,10 +439,10 @@ void xt_compat_flush_offsets(u_int8_t af) } EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); -short xt_compat_calc_jump(u_int8_t af, unsigned int offset) +int xt_compat_calc_jump(u_int8_t af, unsigned int offset) { struct compat_delta *tmp; - short delta; + int delta; for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next) if (tmp->offset < offset) -- cgit v1.2.3 From 2f5265e6e785b2a666dd985ea157bc8c260be8fa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Feb 2010 10:45:05 +0100 Subject: mac80211: fix netdev rename Fix a copy bug introduced by commit 47846c9b0c10808d9337d2e7d09361f3e0a0a71a Author: Johannes Berg Date: Wed Nov 25 17:46:19 2009 +0100 mac80211: reduce reliance on netdev This manifested itself only in debug messages and in the debugfs rename failure that would always happen due to trying to rename the dir over itself. Signed-off-by: Johannes Berg Tested-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09fff4662e80..0793d7a8d743 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1031,7 +1031,7 @@ static int netdev_notify(struct notifier_block *nb, sdata = IEEE80211_DEV_TO_SUB_IF(dev); - memcpy(sdata->name, sdata->name, IFNAMSIZ); + memcpy(sdata->name, dev->name, IFNAMSIZ); ieee80211_debugfs_rename_netdev(sdata); return 0; -- cgit v1.2.3 From 0e956c132f822d414a4ce84726ac1d1294364581 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 12 Feb 2010 12:34:50 -0200 Subject: nl80211: does not allow NEW_STATION and DEL_STATION for mesh As discussed in linux-wireless mailing list, adding and removing stations for mesh topologies is not necessary. Since doing it triggers bugs, the sugestion was to simply disable it. Tested using a custom iw command "station new". Works only after using hostapd. "station del" command also works. Signed-off-by: Thadeu Lima de Souza Cascardo Cc: Johannes Berg Cc: Simon Raffeiner Cc: Andrey Yurovsky Cc: Javier Cardona Signed-off-by: John W. Linville --- net/wireless/nl80211.c | 49 +++++++++++++------------------------------------ 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5b79ecf17bea..a95ab9e4c19e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2010,6 +2010,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) return -EINVAL; + if (!info->attrs[NL80211_ATTR_STA_AID]) + return -EINVAL; + mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); params.supported_rates = nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); @@ -2018,11 +2021,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - if (info->attrs[NL80211_ATTR_STA_AID]) { - params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); - if (!params.aid || params.aid > IEEE80211_MAX_AID) - return -EINVAL; - } + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (!params.aid || params.aid > IEEE80211_MAX_AID) + return -EINVAL; if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) params.ht_capa = @@ -2037,6 +2038,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (err) goto out_rtnl; + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { + err = -EINVAL; + goto out; + } + err = get_vlan(info, rdev, ¶ms.vlan); if (err) goto out; @@ -2044,35 +2051,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) /* validate settings */ err = 0; - switch (dev->ieee80211_ptr->iftype) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - /* all ok but must have AID */ - if (!params.aid) - err = -EINVAL; - break; - case NL80211_IFTYPE_MESH_POINT: - /* disallow things mesh doesn't support */ - if (params.vlan) - err = -EINVAL; - if (params.aid) - err = -EINVAL; - if (params.ht_capa) - err = -EINVAL; - if (params.listen_interval >= 0) - err = -EINVAL; - if (params.supported_rates) - err = -EINVAL; - if (params.sta_flags_mask) - err = -EINVAL; - break; - default: - err = -EINVAL; - } - - if (err) - goto out; - if (!rdev->ops->add_station) { err = -EOPNOTSUPP; goto out; @@ -2113,8 +2091,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) goto out_rtnl; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { err = -EINVAL; goto out; } -- cgit v1.2.3 From 2bf9fa6980a5ca12333634e48c8dd69024b88eba Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 12 Feb 2010 13:02:23 -0800 Subject: wireless: airo_cs build fixes When WEXT_PRIV is not enabled, airo_cs has build errors. It needs to include net/iw_handler.h and it should select WEXT_PRIV, like the airo driver does. drivers/net/wireless/airo.c:7655: error: unknown field 'num_private' specified in initializer drivers/net/wireless/airo.c:7655: warning: initialization makes pointer from integer without a cast drivers/net/wireless/airo.c:7656: error: unknown field 'num_private_args' specified in initializer drivers/net/wireless/airo.c:7656: warning: excess elements in struct initializer drivers/net/wireless/airo.c:7656: warning: (near initialization for 'airo_handler_def') drivers/net/wireless/airo.c:7658: error: unknown field 'private' specified in initializer drivers/net/wireless/airo.c:7658: warning: initialization makes integer from pointer without a cast drivers/net/wireless/airo.c:7658: error: initializer element is not computable at load time drivers/net/wireless/airo.c:7658: error: (near initialization for 'airo_handler_def.num_standard') drivers/net/wireless/airo.c:7659: error: unknown field 'private_args' specified in initializer drivers/net/wireless/airo.c:7659: warning: initialization from incompatible pointer type Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/airo.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 56dd6650c97a..588943660755 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -112,6 +112,7 @@ config AIRO_CS depends on PCMCIA && (BROKEN || !M32R) select WIRELESS_EXT select WEXT_SPY + select WEXT_PRIV select CRYPTO select CRYPTO_AES ---help--- diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2a9f029a3c74..260fb9905e97 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -51,6 +51,7 @@ #include #include +#include #include "airo.h" -- cgit v1.2.3 From 063b2dfffc896fc5ac6943248c940619b94f09c2 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Feb 2010 18:10:52 +0100 Subject: b43legacy: fix typo in ifdef comment Cc: Larry Finger Cc: Stefano Brivio Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/leds.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h index 82167a90088f..9ff6750dc57f 100644 --- a/drivers/net/wireless/b43legacy/leds.h +++ b/drivers/net/wireless/b43legacy/leds.h @@ -45,7 +45,7 @@ enum b43legacy_led_behaviour { void b43legacy_leds_init(struct b43legacy_wldev *dev); void b43legacy_leds_exit(struct b43legacy_wldev *dev); -#else /* CONFIG_B43EGACY_LEDS */ +#else /* CONFIG_B43LEGACY_LEDS */ /* LED support disabled */ struct b43legacy_led { -- cgit v1.2.3 From 634c8d2587abbd680603e016ae1060129abdf46f Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Feb 2010 18:10:53 +0100 Subject: rtl8187: fix typo in ifdef comment Cc: Herton Ronaldo Krzesinski Cc: Larry Finger Signed-off-by: Hauke Mehrtens Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/rtl818x/rtl8187_leds.c | 2 +- drivers/net/wireless/rtl818x/rtl8187_leds.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index f82aa8b4bdde..4637337d5ce6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c @@ -241,5 +241,5 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) cancel_delayed_work_sync(&priv->led_off); cancel_delayed_work_sync(&priv->led_on); } -#endif /* def CONFIG_RTL8187_LED */ +#endif /* def CONFIG_RTL8187_LEDS */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h index efe8041bdda4..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h @@ -54,6 +54,6 @@ struct rtl8187_led { void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); void rtl8187_leds_exit(struct ieee80211_hw *dev); -#endif /* def CONFIG_RTL8187_LED */ +#endif /* def CONFIG_RTL8187_LEDS */ #endif /* RTL8187_LED_H */ -- cgit v1.2.3 From 0052b8bb5ad24ff2c5b065adc7ed44dc8390bd4b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 13 Feb 2010 18:10:54 +0100 Subject: ssb: fix typo in ifdef comment Cc: Michael Buesch Signed-off-by: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/ssb/ssb_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 56054be4d113..0331139a726f 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h @@ -196,7 +196,7 @@ extern int ssb_devices_thaw(struct ssb_freeze_context *ctx); #ifdef CONFIG_SSB_B43_PCI_BRIDGE extern int __init b43_pci_ssb_bridge_init(void); extern void __exit b43_pci_ssb_bridge_exit(void); -#else /* CONFIG_SSB_B43_PCI_BRIDGR */ +#else /* CONFIG_SSB_B43_PCI_BRIDGE */ static inline int b43_pci_ssb_bridge_init(void) { return 0; @@ -204,6 +204,6 @@ static inline int b43_pci_ssb_bridge_init(void) static inline void b43_pci_ssb_bridge_exit(void) { } -#endif /* CONFIG_SSB_PCIHOST */ +#endif /* CONFIG_SSB_B43_PCI_BRIDGE */ #endif /* LINUX_SSB_PRIVATE_H_ */ -- cgit v1.2.3 From 15a69a81731d337a3d9db51692ff8704c1114f43 Mon Sep 17 00:00:00 2001 From: Shimada Hirofumi Date: Sun, 14 Feb 2010 04:16:16 +0900 Subject: p54usb: Add usbid for Corega CG-WLUSB2GT. Signed-off-by: Shimada Hirofumi Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 92af9b96bb7a..dcb484bd5984 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -36,6 +36,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ + {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ -- cgit v1.2.3 From cea90e55969ff70b970d64d564076a5469331527 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 13 Feb 2010 20:55:47 +0100 Subject: rt2x00: Introduce SoC interface type. Introduce the SoC interface type to detect SoC devices, instead of having them mimic being PCI devices. This allows for easier detection of SoC devices. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 38 ++++++++++++++++----------------- drivers/net/wireless/rt2x00/rt2800pci.c | 18 ++++++---------- drivers/net/wireless/rt2x00/rt2x00.h | 10 +++++++-- drivers/net/wireless/rt2x00/rt2x00soc.c | 6 +----- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a45e027f2d1f..e78df53b9515 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -89,7 +89,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); - if (rt2x00_intf_is_pci(rt2x00dev)) + if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); @@ -118,7 +118,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); - if (rt2x00_intf_is_pci(rt2x00dev)) + if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); @@ -218,9 +218,9 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, u32 reg; /* - * RT2880 and RT3052 don't support MCU requests. + * SOC devices don't support MCU requests. */ - if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052)) + if (rt2x00_is_soc(rt2x00dev)) return; mutex_lock(&rt2x00dev->csr_mutex); @@ -660,7 +660,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) switch ((int)ant->tx) { case 1: rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); - if (rt2x00_intf_is_pci(rt2x00dev)) + if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); break; case 2: @@ -1057,7 +1057,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - if (rt2x00_intf_is_usb(rt2x00dev) && + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rev(rt2x00dev) == RT3070_VERSION) return 0x1c + (2 * rt2x00dev->lna_gain); else @@ -1109,7 +1109,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) u32 reg; unsigned int i; - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { /* * Wait until BBP and RF are ready. */ @@ -1128,7 +1128,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - } else if (rt2x00_intf_is_pci(rt2x00dev)) + } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); @@ -1136,7 +1136,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, @@ -1174,7 +1174,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); - if (rt2x00_intf_is_usb(rt2x00dev) && + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rev(rt2x00dev) == RT3070_VERSION) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); @@ -1293,7 +1293,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); @@ -1353,7 +1353,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); @@ -1490,7 +1490,7 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) rt2800_bbp_write(rt2x00dev, 84, 0x19); - if (rt2x00_intf_is_usb(rt2x00dev) && + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rev(rt2x00dev) == RT3070_VERSION) { rt2800_bbp_write(rt2x00dev, 70, 0x0a); rt2800_bbp_write(rt2x00dev, 84, 0x99); @@ -1582,11 +1582,11 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u8 rfcsr; u8 bbp; - if (rt2x00_intf_is_usb(rt2x00dev) && + if (rt2x00_is_usb(rt2x00dev) && rt2x00_rev(rt2x00dev) != RT3070_VERSION) return 0; - if (rt2x00_intf_is_pci(rt2x00dev)) { + if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { if (!rt2x00_rf(rt2x00dev, RF3020) && !rt2x00_rf(rt2x00dev, RF3021) && !rt2x00_rf(rt2x00dev, RF3022)) @@ -1603,7 +1603,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { rt2800_rfcsr_write(rt2x00dev, 4, 0x40); rt2800_rfcsr_write(rt2x00dev, 5, 0x03); rt2800_rfcsr_write(rt2x00dev, 6, 0x02); @@ -1624,7 +1624,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 25, 0x01); rt2800_rfcsr_write(rt2x00dev, 27, 0x03); rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); - } else if (rt2x00_intf_is_pci(rt2x00dev)) { + } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { rt2800_rfcsr_write(rt2x00dev, 0, 0x50); rt2800_rfcsr_write(rt2x00dev, 1, 0x01); rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); @@ -1855,7 +1855,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_chip_rf(rt2x00dev, value, reg); - if (rt2x00_intf_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) { /* * The check for rt2860 is not a typo, some rt2870 hardware * identifies itself as rt2860 in the CSR register. @@ -2039,7 +2039,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Disable powersaving as default on PCI devices. */ - if (rt2x00_intf_is_pci(rt2x00dev)) + if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; /* diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index daea0b7c416e..d57531ce1f82 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1041,18 +1041,12 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read EEPROM into buffer */ - switch (rt2x00dev->chip.rt) { - case RT2880: - case RT3052: + if (rt2x00_is_soc(rt2x00dev)) rt2800pci_read_eeprom_soc(rt2x00dev); - break; - default: - if (rt2800pci_efuse_detect(rt2x00dev)) - rt2800pci_read_eeprom_efuse(rt2x00dev); - else - rt2800pci_read_eeprom_pci(rt2x00dev); - break; - } + else if (rt2800pci_efuse_detect(rt2x00dev)) + rt2800pci_read_eeprom_efuse(rt2x00dev); + else + rt2800pci_read_eeprom_pci(rt2x00dev); return rt2800_validate_eeprom(rt2x00dev); } @@ -1103,7 +1097,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * This device requires firmware. */ - if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052)) + if (!rt2x00_is_soc(rt2x00dev)) __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 43b70c6e4e9c..d741367304bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -160,6 +160,7 @@ struct avg_val { enum rt2x00_chip_intf { RT2X00_CHIP_INTF_PCI, RT2X00_CHIP_INTF_USB, + RT2X00_CHIP_INTF_SOC, }; /* @@ -976,16 +977,21 @@ static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, return (rt2x00dev->chip.intf == intf); } -static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) +static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) { return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); } -static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) +static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) { return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); } +static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) +{ + return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); +} + /** * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. * @rt2x00dev: Pointer to &struct rt2x00_dev. diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 19e684f8ffa1..0d6b43afc4e8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -94,11 +94,7 @@ int rt2x00soc_probe(struct platform_device *pdev, rt2x00dev->irq = platform_get_irq(pdev, 0); rt2x00dev->name = pdev->dev.driver->name; - /* - * SoC devices mimic PCI behavior. - */ - rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); - + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); rt2x00_set_chip_rt(rt2x00dev, chipset); retval = rt2x00soc_alloc_reg(rt2x00dev); -- cgit v1.2.3 From 714fa6636331d33c6045efe394f36c964a6c14ee Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 13 Feb 2010 20:55:48 +0100 Subject: rt2x00: Reorganize RT chipset setting for PCI/SOC devices. Don't set the RT chipset for a device from within the generic PCI/SOC code, but rather from the individual drivers, so that individual drivers have more control over what RT chipset is set. Preparation for chip handling updates for rt2800 devices. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 ++++++-- drivers/net/wireless/rt2x00/rt2500pci.c | 9 ++++++-- drivers/net/wireless/rt2x00/rt2500usb.c | 1 - drivers/net/wireless/rt2x00/rt2800lib.c | 39 ++++++++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2800pci.c | 11 +++++----- drivers/net/wireless/rt2x00/rt2x00.h | 15 ------------- drivers/net/wireless/rt2x00/rt2x00pci.c | 7 ------ drivers/net/wireless/rt2x00/rt2x00pci.h | 1 + drivers/net/wireless/rt2x00/rt2x00soc.c | 5 +---- drivers/net/wireless/rt2x00/rt2x00soc.h | 10 +-------- drivers/net/wireless/rt2x00/rt61pci.c | 9 ++++++-- drivers/net/wireless/rt2x00/rt73usb.c | 1 - 12 files changed, 58 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 184335950825..9207b9b100b0 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1327,6 +1327,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; + u16 chip; u16 value; u16 eeprom; @@ -1335,13 +1336,17 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + /* + * Identify RT chipset. + */ + pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); + /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - rt2x00_print_chip(rt2x00dev); + rt2x00_set_chip(rt2x00dev, chip, value, reg); if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 7dfcffadda2a..0f6d001267ac 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1490,6 +1490,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; + u16 chip; u16 value; u16 eeprom; @@ -1498,13 +1499,17 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + /* + * Identify RT chipset. + */ + pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); + /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - rt2x00_print_chip(rt2x00dev); + rt2x00_set_chip(rt2x00dev, chip, value, reg); if (!rt2x00_rf(rt2x00dev, RF2522) && !rt2x00_rf(rt2x00dev, RF2523) && diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 81ca4ec068db..99b7cb88a648 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1408,7 +1408,6 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - rt2x00_print_chip(rt2x00dev); if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e78df53b9515..7340e487df6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -40,6 +40,9 @@ #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) #include "rt2x00usb.h" #endif +#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) +#include "rt2x00pci.h" +#endif #include "rt2800lib.h" #include "rt2800.h" #include "rt2800usb.h" @@ -1839,6 +1842,7 @@ EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; + u16 chip; u16 value; u16 eeprom; @@ -1853,25 +1857,40 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - - if (rt2x00_is_usb(rt2x00dev)) { + if (rt2x00_is_pci(rt2x00dev)) { +#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) + pci_read_config_word(to_pci_dev(rt2x00dev->dev), + PCI_DEVICE_ID, + &chip); +#else + BUG(); +#endif + } else if (rt2x00_is_usb(rt2x00dev)) { /* * The check for rt2860 is not a typo, some rt2870 hardware * identifies itself as rt2860 in the CSR register. */ - if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) || - rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) || - rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) { - rt2x00_set_chip_rt(rt2x00dev, RT2870); - } else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) { - rt2x00_set_chip_rt(rt2x00dev, RT3070); + if (((reg & 0xfff00000) == 0x28600000) || + ((reg & 0xfff00000) == 0x28700000) || + ((reg & 0xfff00000) == 0x28800000)) { + chip = RT2870; + } else if ((reg & 0xffff0000) == 0x30700000) { + chip = RT3070; } else { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } + } else if (rt2x00_is_soc(rt2x00dev)) { +#if defined(CONFIG_RALINK_RT288X) + chip = RT2880; +#elif defined(CONFIG_RALINK_RT305X) + chip = RT3052; +#else + BUG(); +#endif } - rt2x00_print_chip(rt2x00dev); + + rt2x00_set_chip(rt2x00dev, chip, value, reg); if (!rt2x00_rf(rt2x00dev, RF2820) && !rt2x00_rf(rt2x00dev, RF2850) && diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index d57531ce1f82..fc351052229b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1219,11 +1219,10 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); MODULE_LICENSE("GPL"); #ifdef CONFIG_RT2800PCI_SOC -#if defined(CONFIG_RALINK_RT288X) -__rt2x00soc_probe(RT2880, &rt2800pci_ops); -#elif defined(CONFIG_RALINK_RT305X) -__rt2x00soc_probe(RT3052, &rt2800pci_ops); -#endif +static int rt2800soc_probe(struct platform_device *pdev) +{ + return rt2x00soc_probe(pdev, rt2800pci_ops); +} static struct platform_driver rt2800soc_driver = { .driver = { @@ -1231,7 +1230,7 @@ static struct platform_driver rt2800soc_driver = { .owner = THIS_MODULE, .mod_name = KBUILD_MODNAME, }, - .probe = __rt2x00soc_probe, + .probe = rt2800soc_probe, .remove = __devexit_p(rt2x00soc_remove), .suspend = rt2x00soc_suspend, .resume = rt2x00soc_resume, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d741367304bb..1fed90acd198 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -923,22 +923,7 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, rt2x00dev->chip.rt = rt; rt2x00dev->chip.rf = rf; rt2x00dev->chip.rev = rev; -} - -static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, - const u16 rt) -{ - rt2x00dev->chip.rt = rt; -} -static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, - const u16 rf, const u32 rev) -{ - rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); -} - -static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) -{ INFO(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 801be436cf1d..047123b766fc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -272,7 +272,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; int retval; - u16 chip; retval = pci_request_regions(pci_dev, pci_name(pci_dev)); if (retval) { @@ -315,12 +314,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); - /* - * Determine RT chipset by reading PCI header. - */ - pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); - rt2x00_set_chip_rt(rt2x00dev, chip); - retval = rt2x00pci_alloc_reg(rt2x00dev); if (retval) goto exit_free_device; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index d4f9449ab0a4..8149ff68410a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -27,6 +27,7 @@ #define RT2X00PCI_H #include +#include /* * This variable should be used with the diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 0d6b43afc4e8..4efdc96010f6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -71,9 +71,7 @@ exit: return -ENOMEM; } -int rt2x00soc_probe(struct platform_device *pdev, - const unsigned short chipset, - const struct rt2x00_ops *ops) +int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops) { struct ieee80211_hw *hw; struct rt2x00_dev *rt2x00dev; @@ -95,7 +93,6 @@ int rt2x00soc_probe(struct platform_device *pdev, rt2x00dev->name = pdev->dev.driver->name; rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); - rt2x00_set_chip_rt(rt2x00dev, chipset); retval = rt2x00soc_alloc_reg(rt2x00dev); if (retval) diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 8a3416624af5..4739edfe2f00 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h @@ -28,18 +28,10 @@ #define KSEG1ADDR(__ptr) __ptr -#define __rt2x00soc_probe(__chipset, __ops) \ -static int __rt2x00soc_probe(struct platform_device *pdev) \ -{ \ - return rt2x00soc_probe(pdev, (__chipset), (__ops)); \ -} - /* * SoC driver handlers. */ -int rt2x00soc_probe(struct platform_device *pdev, - const unsigned short chipset, - const struct rt2x00_ops *ops); +int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops); int rt2x00soc_remove(struct platform_device *pdev); #ifdef CONFIG_PM int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 881340026c2a..4ca1d48fb737 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2282,6 +2282,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; + u16 chip; u16 value; u16 eeprom; @@ -2290,13 +2291,17 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); + /* + * Identify RT chipset. + */ + pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); + /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - rt2x00_print_chip(rt2x00dev); + rt2x00_set_chip(rt2x00dev, chip, value, reg); if (!rt2x00_rf(rt2x00dev, RF5225) && !rt2x00_rf(rt2x00dev, RF5325) && diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 3781eb7b4aa0..2950ac754921 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1821,7 +1821,6 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - rt2x00_print_chip(rt2x00dev); if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { -- cgit v1.2.3 From 49e721ec6ca74f90ee99089ad2de1c338a95c6d5 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sat, 13 Feb 2010 20:55:49 +0100 Subject: rt2x00: rework RT chipset and revision determination for PCI an SOC devices. The recent rt2800 devices are no longer really identified by their PCI ID's, but rather by the contents of their CSR0 register. Also for the other chipsets is the contents of this CSR0 register important. Change the chipset determination logic to be more aligned with the rt2800 model. Preparation for the support of rt3070 / rt3090 based devices. Signed-off-by: Gertjan van Wingerde Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 +-- drivers/net/wireless/rt2x00/rt2400pci.h | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 9 +-- drivers/net/wireless/rt2x00/rt2500pci.h | 1 + drivers/net/wireless/rt2x00/rt2500usb.c | 3 +- drivers/net/wireless/rt2x00/rt2800.h | 14 ++--- drivers/net/wireless/rt2x00/rt2800lib.c | 92 ++++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2800usb.c | 20 +++---- drivers/net/wireless/rt2x00/rt2x00.h | 41 ++++++-------- drivers/net/wireless/rt2x00/rt2x00debug.c | 4 +- drivers/net/wireless/rt2x00/rt61pci.c | 19 +++---- drivers/net/wireless/rt2x00/rt61pci.h | 9 +++ drivers/net/wireless/rt2x00/rt73usb.c | 6 +- drivers/net/wireless/rt2x00/rt73usb.h | 2 + 14 files changed, 112 insertions(+), 118 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 9207b9b100b0..676814d3a81b 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1327,7 +1327,6 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 chip; u16 value; u16 eeprom; @@ -1336,17 +1335,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - /* - * Identify RT chipset. - */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); - /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, chip, value, reg); + rt2x00_set_chip(rt2x00dev, RT2460, value, + rt2x00_get_field32(reg, CSR0_REVISION)); if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 6c21ef66dfe0..606137738848 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -65,6 +65,7 @@ * CSR0: ASIC revision number. */ #define CSR0 0x0000 +#define CSR0_REVISION FIELD32(0x0000ffff) /* * CSR1: System control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0f6d001267ac..c71266142ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1490,7 +1490,6 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 chip; u16 value; u16 eeprom; @@ -1499,17 +1498,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - /* - * Identify RT chipset. - */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); - /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip(rt2x00dev, chip, value, reg); + rt2x00_set_chip(rt2x00dev, RT2560, value, + rt2x00_get_field32(reg, CSR0_REVISION)); if (!rt2x00_rf(rt2x00dev, RF2522) && !rt2x00_rf(rt2x00dev, RF2523) && diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index b0075674c09b..6471f8e74b35 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -76,6 +76,7 @@ * CSR0: ASIC revision number. */ #define CSR0 0x0000 +#define CSR0_REVISION FIELD32(0x0000ffff) /* * CSR1: System control register. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 99b7cb88a648..ee34c137e7cd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1409,8 +1409,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || - rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { + if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 1a7eae357fef..74c0433dba37 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -60,11 +60,11 @@ /* * Chipset version. */ -#define RT2860C_VERSION 0x28600100 -#define RT2860D_VERSION 0x28600101 -#define RT2880E_VERSION 0x28720200 -#define RT2883_VERSION 0x28830300 -#define RT3070_VERSION 0x30700200 +#define RT2860C_VERSION 0x0100 +#define RT2860D_VERSION 0x0101 +#define RT2880E_VERSION 0x0200 +#define RT2883_VERSION 0x0300 +#define RT3070_VERSION 0x0200 /* * Signal information. @@ -408,8 +408,8 @@ * ASIC_VER: 2860 or 2870 */ #define MAC_CSR0 0x1000 -#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) -#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) +#define MAC_CSR0_REVISION FIELD32(0x0000ffff) +#define MAC_CSR0_CHIPSET FIELD32(0xffff0000) /* * MAC_SYS_CTRL: diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7340e487df6b..18d4d8e4ae6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -898,7 +898,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); rt2800_bbp_write(rt2x00dev, 3, bbp); - if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { + if (rt2x00_rt(rt2x00dev, RT2860) && + (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { if (conf_is_ht40(conf)) { rt2800_bbp_write(rt2x00dev, 69, 0x1a); rt2800_bbp_write(rt2x00dev, 70, 0x0a); @@ -1061,7 +1062,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) { if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rev(rt2x00dev) == RT3070_VERSION) + rt2x00_rt(rt2x00dev, RT3070) && + (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) return 0x1c + (2 * rt2x00dev->lna_gain); else return 0x2e + rt2x00dev->lna_gain; @@ -1092,7 +1094,8 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, const u32 count) { - if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) + if (rt2x00_rt(rt2x00dev, RT2860) && + (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) return; /* @@ -1178,7 +1181,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rev(rt2x00dev) == RT3070_VERSION) { + rt2x00_rt(rt2x00dev, RT3070) && + (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); @@ -1205,8 +1209,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION && - rt2x00_rev(rt2x00dev) < RT3070_VERSION) + if ((rt2x00_rt(rt2x00dev, RT2872) && + (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || + rt2x00_rt(rt2x00dev, RT2880) || + rt2x00_rt(rt2x00dev, RT2883) || + rt2x00_rt(rt2x00dev, RT2890) || + rt2x00_rt(rt2x00dev, RT3052) || + (rt2x00_rt(rt2x00dev, RT3070) && + (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); else rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); @@ -1485,16 +1495,19 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) rt2800_bbp_write(rt2x00dev, 103, 0x00); rt2800_bbp_write(rt2x00dev, 105, 0x05); - if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { + if (rt2x00_rt(rt2x00dev, RT2860) && + (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { rt2800_bbp_write(rt2x00dev, 69, 0x16); rt2800_bbp_write(rt2x00dev, 73, 0x12); } - if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) + if (rt2x00_rt(rt2x00dev, RT2860) && + (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) rt2800_bbp_write(rt2x00dev, 84, 0x19); if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rev(rt2x00dev) == RT3070_VERSION) { + rt2x00_rt(rt2x00dev, RT3070) && + (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { rt2800_bbp_write(rt2x00dev, 70, 0x0a); rt2800_bbp_write(rt2x00dev, 84, 0x99); rt2800_bbp_write(rt2x00dev, 105, 0x05); @@ -1586,7 +1599,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) u8 bbp; if (rt2x00_is_usb(rt2x00dev) && - rt2x00_rev(rt2x00dev) != RT3070_VERSION) + rt2x00_rt(rt2x00dev, RT3070) && + (rt2x00_rev(rt2x00dev) != RT3070_VERSION)) return 0; if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { @@ -1757,7 +1771,12 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) { + } else if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2870) || + rt2x00_rt(rt2x00dev, RT2872) || + rt2x00_rt(rt2x00dev, RT2880) || + (rt2x00_rt(rt2x00dev, RT2883) && + (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) { /* * There is a max of 2 RX streams for RT28x0 series */ @@ -1842,7 +1861,6 @@ EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 chip; u16 value; u16 eeprom; @@ -1857,41 +1875,25 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - if (rt2x00_is_pci(rt2x00dev)) { -#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) - pci_read_config_word(to_pci_dev(rt2x00dev->dev), - PCI_DEVICE_ID, - &chip); -#else - BUG(); -#endif - } else if (rt2x00_is_usb(rt2x00dev)) { - /* - * The check for rt2860 is not a typo, some rt2870 hardware - * identifies itself as rt2860 in the CSR register. - */ - if (((reg & 0xfff00000) == 0x28600000) || - ((reg & 0xfff00000) == 0x28700000) || - ((reg & 0xfff00000) == 0x28800000)) { - chip = RT2870; - } else if ((reg & 0xffff0000) == 0x30700000) { - chip = RT3070; - } else { - ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); - return -ENODEV; - } - } else if (rt2x00_is_soc(rt2x00dev)) { -#if defined(CONFIG_RALINK_RT288X) - chip = RT2880; -#elif defined(CONFIG_RALINK_RT305X) - chip = RT3052; -#else - BUG(); -#endif + rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), + value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); + + if (!rt2x00_rt(rt2x00dev, RT2860) && + !rt2x00_rt(rt2x00dev, RT2870) && + !rt2x00_rt(rt2x00dev, RT2872) && + !rt2x00_rt(rt2x00dev, RT2880) && + !rt2x00_rt(rt2x00dev, RT2883) && + !rt2x00_rt(rt2x00dev, RT2890) && + !rt2x00_rt(rt2x00dev, RT3052) && + !rt2x00_rt(rt2x00dev, RT3070) && + !rt2x00_rt(rt2x00dev, RT3071) && + !rt2x00_rt(rt2x00dev, RT3090) && + !rt2x00_rt(rt2x00dev, RT3390) && + !rt2x00_rt(rt2x00dev, RT3572)) { + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); + return -ENODEV; } - rt2x00_set_chip(rt2x00dev, chip, value, reg); - if (!rt2x00_rf(rt2x00dev, RF2820) && !rt2x00_rf(rt2x00dev, RF2850) && !rt2x00_rf(rt2x00dev, RF2720) && diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 82755cf8b73e..79ea3798d597 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -92,7 +92,6 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, const u8 *data, const size_t len) { - u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; size_t offset = 0; /* @@ -111,9 +110,9 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, * Check if we need the upper 4kb firmware data or not. */ if ((len == 4096) && - (chipset != 0x2860) && - (chipset != 0x2872) && - (chipset != 0x3070)) + !rt2x00_rt(rt2x00dev, RT2860) && + !rt2x00_rt(rt2x00dev, RT2872) && + !rt2x00_rt(rt2x00dev, RT3070)) return FW_BAD_VERSION; /* @@ -138,14 +137,13 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, u32 reg; u32 offset; u32 length; - u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; /* * Check which section of the firmware we need. */ - if ((chipset == 0x2860) || - (chipset == 0x2872) || - (chipset == 0x3070)) { + if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2872) || + rt2x00_rt(rt2x00dev, RT3070)) { offset = 0; length = 4096; } else { @@ -200,9 +198,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, */ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); - if ((chipset == 0x3070) || - (chipset == 0x3071) || - (chipset == 0x3572)) { + if (rt2x00_rt(rt2x00dev, RT3070) || + rt2x00_rt(rt2x00dev, RT3071) || + rt2x00_rt(rt2x00dev, RT3572)) { udelay(200); rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); udelay(10); diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1fed90acd198..d9daa9c406fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -170,25 +170,26 @@ enum rt2x00_chip_intf { */ struct rt2x00_chip { u16 rt; -#define RT2460 0x0101 -#define RT2560 0x0201 -#define RT2570 0x1201 -#define RT2561s 0x0301 /* Turbo */ -#define RT2561 0x0302 -#define RT2661 0x0401 -#define RT2571 0x1300 -#define RT2860 0x0601 /* 2.4GHz PCI/CB */ -#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ -#define RT2890 0x0701 /* 2.4GHz PCIe */ -#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ +#define RT2460 0x2460 +#define RT2560 0x2560 +#define RT2570 0x2570 +#define RT2661 0x2661 +#define RT2573 0x2573 +#define RT2860 0x2860 /* 2.4GHz PCI/CB */ +#define RT2870 0x2870 +#define RT2872 0x2872 #define RT2880 0x2880 /* WSOC */ +#define RT2883 0x2883 /* WSOC */ +#define RT2890 0x2890 /* 2.4GHz PCIe */ #define RT3052 0x3052 /* WSOC */ +#define RT3070 0x3070 +#define RT3071 0x3071 #define RT3090 0x3090 /* 2.4GHz PCIe */ -#define RT2870 0x1600 -#define RT3070 0x1800 +#define RT3390 0x3390 +#define RT3572 0x3572 u16 rf; - u32 rev; + u16 rev; enum rt2x00_chip_intf intf; }; @@ -918,14 +919,14 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, * Chipset handlers */ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, - const u16 rt, const u16 rf, const u32 rev) + const u16 rt, const u16 rf, const u16 rev) { rt2x00dev->chip.rt = rt; rt2x00dev->chip.rf = rf; rt2x00dev->chip.rev = rev; INFO(rt2x00dev, - "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", + "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n", rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); } @@ -939,17 +940,11 @@ static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) return (rt2x00dev->chip.rf == rf); } -static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev) +static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) { return rt2x00dev->chip.rev; } -static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev, - const u32 mask, const u32 rev) -{ - return ((rt2x00dev->chip.rev & mask) == rev); -} - static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, enum rt2x00_chip_intf intf) { diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 7d323a763b54..70c04c282efc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -184,7 +184,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->data_length = cpu_to_le32(skb->len); dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); - dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); + dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev); dump_hdr->type = cpu_to_le16(type); dump_hdr->queue_index = desc->entry->queue->qid; dump_hdr->entry_index = desc->entry->entry_idx; @@ -573,7 +573,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, blob->data = data; data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); - data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev); + data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev); data += sprintf(data, "\n"); data += sprintf(data, "register\tbase\twords\twordsize\n"); data += sprintf(data, "csr\t%d\t%d\t%d\n", diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 4ca1d48fb737..ee9c696fe1d4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1131,16 +1131,18 @@ dynamic_cca_tune: */ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) { + u16 chip; char *fw_name; - switch (rt2x00dev->chip.rt) { - case RT2561: + pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); + switch (chip) { + case RT2561_PCI_ID: fw_name = FIRMWARE_RT2561; break; - case RT2561s: + case RT2561s_PCI_ID: fw_name = FIRMWARE_RT2561s; break; - case RT2661: + case RT2661_PCI_ID: fw_name = FIRMWARE_RT2661; break; default: @@ -2282,7 +2284,6 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) { u32 reg; - u16 chip; u16 value; u16 eeprom; @@ -2291,17 +2292,13 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - /* - * Identify RT chipset. - */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); - /* * Identify RF chipset. */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, chip, value, reg); + rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), + value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); if (!rt2x00_rf(rt2x00dev, RF5225) && !rt2x00_rf(rt2x00dev, RF5325) && diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 6f33f7f5668c..ab20c7758824 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -27,6 +27,13 @@ #ifndef RT61PCI_H #define RT61PCI_H +/* + * RT chip PCI IDs. + */ +#define RT2561s_PCI_ID 0x0301 +#define RT2561_PCI_ID 0x0302 +#define RT2661_PCI_ID 0x0401 + /* * RF chip defines. */ @@ -225,6 +232,8 @@ struct hw_pairwise_ta_entry { * MAC_CSR0: ASIC revision number. */ #define MAC_CSR0 0x3000 +#define MAC_CSR0_REVISION FIELD32(0x0000000f) +#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) /* * MAC_CSR1: System control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 2950ac754921..f39a8ed17841 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1820,10 +1820,10 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) */ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2571, value, reg); + rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), + value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); - if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || - rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { + if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index e783a099a8f1..b4e3ddda06cf 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -142,6 +142,8 @@ struct hw_pairwise_ta_entry { * MAC_CSR0: ASIC revision number. */ #define MAC_CSR0 0x3000 +#define MAC_CSR0_REVISION FIELD32(0x0000000f) +#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) /* * MAC_CSR1: System control register. -- cgit v1.2.3 From de1ebdceb6a4fe1b7073b81d273285b7c8bed312 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 14 Feb 2010 12:52:05 +0100 Subject: rt2x00: rt2800 - Make rt30xx and rt35xx chipsets configurable. Support for rt30xx- and rt35xx-based devices is currently not functional in rt2800pci and rt2800usb. In order to not confuse users we shouldn't claim the PCI and USB device ID's for these devices. However, to allow for testing it is good to still have them available, although disabled by default. Make support for these device configuration options that default to off. For rt2800usb a 3rd class of devices is added, which are the unknown devices. For these devices it is known that they are either based on rt28xx, rt30xx or rt35xx, but it is not known on what chipset exactly. These devices are disabled by default as well, until it can be established on what chipset exactly they are based. Signed-off-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 67 +++++++- drivers/net/wireless/rt2x00/rt2800pci.c | 20 ++- drivers/net/wireless/rt2x00/rt2800usb.c | 286 ++++++++++++++++++++------------ 3 files changed, 258 insertions(+), 115 deletions(-) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 3ca824a91ad9..5239e082cd0f 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -64,7 +64,7 @@ config RT2800PCI_SOC default y config RT2800PCI - tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)" + tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL select RT2800_LIB select RT2X00_LIB_PCI if RT2800PCI_PCI @@ -75,7 +75,7 @@ config RT2800PCI select CRC_CCITT select EEPROM_93CX6 ---help--- - This adds support for rt2800 wireless chipset family. + This adds support for rt2800/rt3000/rt3500 wireless chipset family. Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 This driver is non-functional at the moment and is intended for @@ -83,6 +83,32 @@ config RT2800PCI When compiled as a module, this driver will be called "rt2800pci.ko". +if RT2800PCI + +config RT2800PCI_RT30XX + bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" + default n + ---help--- + This adds support for rt30xx wireless chipset family to the + rt2800pci driver. + Supported chips: RT3090, RT3091 & RT3092 + + Support for these devices is non-functional at the moment and is + intended for testers and developers. + +config RT2800PCI_RT35XX + bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices" + default n + ---help--- + This adds support for rt35xx wireless chipset family to the + rt2800pci driver. + Supported chips: RT3060, RT3062, RT3562, RT3592 + + Support for these devices is non-functional at the moment and is + intended for testers and developers. + +endif + config RT2500USB tristate "Ralink rt2500 (USB) support" depends on USB @@ -126,6 +152,43 @@ config RT2800USB When compiled as a module, this driver will be called "rt2800usb.ko". +if RT2800USB + +config RT2800USB_RT30XX + bool "rt2800usb - Include support for rt30xx (USB) devices" + default n + ---help--- + This adds support for rt30xx wireless chipset family to the + rt2800usb driver. + Supported chips: RT3070, RT3071 & RT3072 + + Support for these devices is non-functional at the moment and is + intended for testers and developers. + +config RT2800USB_RT35XX + bool "rt2800usb - Include support for rt35xx (USB) devices" + default n + ---help--- + This adds support for rt35xx wireless chipset family to the + rt2800usb driver. + Supported chips: RT3572 + + Support for these devices is non-functional at the moment and is + intended for testers and developers. + +config RT2800USB_UNKNOWN + bool "rt2800usb - Include support for unknown (USB) devices" + default n + ---help--- + This adds support for rt2800 family devices that are known to + have a rt2800 family chipset, but for which the exact chipset + is unknown. + + Support status for these devices is unknown, and enabling these + devices may or may not work. + +endif + config RT2800_LIB tristate diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index fc351052229b..0e4c41766edc 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1185,7 +1185,10 @@ static const struct rt2x00_ops rt2800pci_ops = { * RT2800pci module information. */ static struct pci_device_id rt2800pci_device_table[] = { - { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, @@ -1193,18 +1196,19 @@ static struct pci_device_id rt2800pci_device_table[] = { { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#ifdef CONFIG_RT2800PCI_RT30XX { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#endif +#ifdef CONFIG_RT2800PCI_RT35XX + { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, - { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +#endif { 0, } }; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 79ea3798d597..5e4ee2023fcf 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -805,51 +805,27 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Abocom */ { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Amigo */ - { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Amit */ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Askey */ { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, /* ASUS */ { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Belkin */ { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Cisco */ - { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -858,157 +834,257 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, /* D-Link */ { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Edimax */ + { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* EnGenius */ + { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gigabyte */ + { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Hawking */ + { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Linksys */ + { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Logitec */ + { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Motorola */ + { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* MSI */ + { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Philips */ + { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Planex */ + { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Samsung */ + { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Siemens */ + { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* SMC */ + { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sparklan */ + { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sweex */ + { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* U-Media*/ + { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ZCOM */ + { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zyxel */ + { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, +#ifdef CONFIG_RT2800USB_RT30XX + /* Abocom */ + { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AirTies */ + { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AzureWave */ + { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Corega */ + { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* D-Link */ { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Edimax */ { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Encore */ { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, /* EnGenius */ - { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Gigabyte */ + { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* MSI */ + { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Pegatron */ + { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Planex */ + { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Quanta */ + { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* SMC */ + { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, +#endif +#ifdef CONFIG_RT2800USB_RT35XX + /* Askey */ + { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Cisco */ + { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* EnGenius */ + { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* I-O DATA */ + { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Sitecom */ + { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Zinwell */ + { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, +#endif +#ifdef CONFIG_RT2800USB_UNKNOWN + /* + * Unclear what kind of devices these are (they aren't supported by the + * vendor driver). + */ + /* Allwin */ + { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Amigo */ + { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Askey */ + { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* AzureWave */ + { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Belkin */ + { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Conceptronic */ + { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Corega */ + { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* D-Link */ + { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Encore */ + { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* EnGenius */ { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Hawking */ - { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, /* LevelOne */ { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Linksys */ - { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Motorola */ - { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, /* MSI */ - { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Ovislink */ { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Para */ { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Pegatron */ + { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Philips */ - { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ - { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Ralink */ - { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Samsung */ - { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Siemens */ - { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, /* SMC */ - { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Sparklan */ - { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sweex */ { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* U-Media*/ - { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* ZCOM */ - { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ - { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, +#endif { 0, } }; -- cgit v1.2.3 From 8404080568613d93ad7cf0a16dfb68459b42a264 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 15 Feb 2010 12:46:39 +0200 Subject: mac80211: reject unhandled action frames 802.11-2007 7.3.1.11 mandates that we need to reject action frames we don't handle by setting the 0x80 bit in the category and returning them to the sender, so do that. In AP mode, hostapd is responsible for this. Additionally, drop completely malformed action frames or ones that should've been encrypted as unusable, userspace shouldn't see those. Signed-off-by: Johannes Berg Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- net/mac80211/rx.c | 90 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c9755f3d986c..a177472adc13 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc - * Copyright 2007 Johannes Berg + * Copyright 2007-2010 Johannes Berg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1855,23 +1855,28 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) struct ieee80211_local *local = rx->local; struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; + struct sk_buff *nskb; int len = rx->skb->len; if (!ieee80211_is_action(mgmt->frame_control)) return RX_CONTINUE; if (!rx->sta) - return RX_DROP_MONITOR; + return RX_DROP_UNUSABLE; if (!(rx->flags & IEEE80211_RX_RA_MATCH)) - return RX_DROP_MONITOR; + return RX_DROP_UNUSABLE; if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) - return RX_DROP_MONITOR; + return RX_DROP_UNUSABLE; - /* all categories we currently handle have action_code */ + /* drop too small frames */ + if (len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_UNUSABLE; + + /* return action frames that have *only* category */ if (len < IEEE80211_MIN_ACTION_SIZE + 1) - return RX_DROP_MONITOR; + goto return_frame; switch (mgmt->u.action.category) { case WLAN_CATEGORY_BACK: @@ -1884,7 +1889,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_AP) - return RX_DROP_MONITOR; + break; switch (mgmt->u.action.u.addba_req.action_code) { case WLAN_ACTION_ADDBA_REQ: @@ -1892,45 +1897,45 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sizeof(mgmt->u.action.u.addba_req))) return RX_DROP_MONITOR; ieee80211_process_addba_request(local, rx->sta, mgmt, len); - break; + goto handled; case WLAN_ACTION_ADDBA_RESP: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_resp))) - return RX_DROP_MONITOR; + break; ieee80211_process_addba_resp(local, rx->sta, mgmt, len); - break; + goto handled; case WLAN_ACTION_DELBA: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.delba))) - return RX_DROP_MONITOR; + break; ieee80211_process_delba(sdata, rx->sta, mgmt, len); - break; + goto handled; } break; case WLAN_CATEGORY_SPECTRUM_MGMT: if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) - return RX_DROP_MONITOR; + break; if (sdata->vif.type != NL80211_IFTYPE_STATION) - return RX_DROP_MONITOR; + break; switch (mgmt->u.action.u.measurement.action_code) { case WLAN_ACTION_SPCT_MSR_REQ: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) - return RX_DROP_MONITOR; + break; ieee80211_process_measurement_req(sdata, mgmt, len); - break; + goto handled; case WLAN_ACTION_SPCT_CHL_SWITCH: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.chan_switch))) - return RX_DROP_MONITOR; + break; if (sdata->vif.type != NL80211_IFTYPE_STATION) - return RX_DROP_MONITOR; + break; if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) - return RX_DROP_MONITOR; + break; return ieee80211_sta_rx_mgmt(sdata, rx->skb); } @@ -1938,29 +1943,48 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) case WLAN_CATEGORY_SA_QUERY: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.sa_query))) - return RX_DROP_MONITOR; + break; + switch (mgmt->u.action.u.sa_query.action) { case WLAN_ACTION_SA_QUERY_REQUEST: if (sdata->vif.type != NL80211_IFTYPE_STATION) - return RX_DROP_MONITOR; + break; ieee80211_process_sa_query_req(sdata, mgmt, len); - break; - case WLAN_ACTION_SA_QUERY_RESPONSE: - /* - * SA Query response is currently only used in AP mode - * and it is processed in user space. - */ - return RX_CONTINUE; + goto handled; } break; - default: - /* do not process rejected action frames */ - if (mgmt->u.action.category & 0x80) - return RX_DROP_MONITOR; + } + return_frame: + /* + * For AP mode, hostapd is responsible for handling any action + * frames that we didn't handle, including returning unknown + * ones. For all other modes we will return them to the sender, + * setting the 0x80 bit in the action category, as required by + * 802.11-2007 7.3.1.11. + */ + if (sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + return RX_DROP_MONITOR; - return RX_CONTINUE; + /* do not return rejected action frames */ + if (mgmt->u.action.category & 0x80) + return RX_DROP_UNUSABLE; + + nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, + GFP_ATOMIC); + if (nskb) { + struct ieee80211_mgmt *mgmt = (void *)nskb->data; + + mgmt->u.action.category |= 0x80; + memcpy(mgmt->da, mgmt->sa, ETH_ALEN); + memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN); + + memset(nskb->cb, 0, sizeof(nskb->cb)); + + ieee80211_tx_skb(rx->sdata, nskb); } + handled: rx->sta->rx_packets++; dev_kfree_skb(rx->skb); return RX_QUEUED; -- cgit v1.2.3 From 026331c4d9b526561ea96f95fac4bfc52b69e316 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Feb 2010 12:53:10 +0200 Subject: cfg80211/mac80211: allow registering for and sending action frames This implements a new command to register for action frames that userspace wants to handle instead of the in-kernel rejection. It is then responsible for rejecting ones that it decided not to handle. There is no unregistration, but the socket can be closed for that. Frames that are not registered for will not be forwarded to userspace and will be rejected by the kernel, the cfg80211 API helps implementing that. Additionally, this patch adds a new command that allows doing action frame transmission from userspace. It can be used either to exchange action frames on the current operational channel (e.g., with the AP with which we are currently associated) or to exchange off-channel Public Action frames with the remain-on-channel command. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/nl80211.h | 41 ++++++- include/net/cfg80211.h | 47 +++++++- include/net/mac80211.h | 6 +- net/mac80211/cfg.c | 12 ++- net/mac80211/ieee80211_i.h | 6 +- net/mac80211/mlme.c | 35 ++++++ net/mac80211/rx.c | 42 ++++++-- net/mac80211/status.c | 7 +- net/wireless/core.c | 4 + net/wireless/core.h | 9 ++ net/wireless/mlme.c | 166 +++++++++++++++++++++++++++++ net/wireless/nl80211.c | 260 ++++++++++++++++++++++++++++++++++++++++++++- net/wireless/nl80211.h | 8 ++ 13 files changed, 625 insertions(+), 18 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 127a73015760..8e6384f8fda6 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -3,7 +3,7 @@ /* * 802.11 netlink interface public header * - * Copyright 2006, 2007, 2008 Johannes Berg + * Copyright 2006-2010 Johannes Berg * Copyright 2008 Michael Wu * Copyright 2008 Luis Carlos Cobo * Copyright 2008 Michael Buesch @@ -299,6 +299,31 @@ * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface * and @NL80211_ATTR_TX_RATES the set of allowed rates. * + * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames + * (via @NL80211_CMD_ACTION) for processing in userspace. This command + * requires an interface index and a match attribute containing the first + * few bytes of the frame that should match, e.g. a single byte for only + * a category match or four bytes for vendor frames including the OUI. + * The registration cannot be dropped, but is removed automatically + * when the netlink socket is closed. Multiple registrations can be made. + * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This + * command is used both as a request to transmit an Action frame and as an + * event indicating reception of an Action frame that was not processed in + * kernel code, but is for us (i.e., which may need to be processed in a + * user space application). %NL80211_ATTR_FRAME is used to specify the + * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and + * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on + * which channel the frame is to be transmitted or was received. This + * channel has to be the current channel (remain-on-channel or the + * operational channel). When called, this operation returns a cookie + * (%NL80211_ATTR_COOKIE) that will be included with the TX status event + * pertaining to the TX request. + * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame + * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies + * the TX command and %NL80211_ATTR_FRAME includes the contents of the + * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged + * the frame. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -387,6 +412,10 @@ enum nl80211_commands { NL80211_CMD_SET_TX_BITRATE_MASK, + NL80211_CMD_REGISTER_ACTION, + NL80211_CMD_ACTION, + NL80211_CMD_ACTION_TX_STATUS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -653,6 +682,12 @@ enum nl80211_commands { * rates based on negotiated supported rates information. This attribute * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. * + * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain + * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION. + * + * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was + * acknowledged by the recipient. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -798,6 +833,10 @@ enum nl80211_attrs { NL80211_ATTR_TX_RATES, + NL80211_ATTR_FRAME_MATCH, + + NL80211_ATTR_ACK, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5b3569b2a74c..7188934b64d3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3,7 +3,7 @@ /* * 802.11 device and configuration interface * - * Copyright 2006-2009 Johannes Berg + * Copyright 2006-2010 Johannes Berg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -998,6 +998,7 @@ struct cfg80211_pmksa { * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. * This allows the operation to be terminated prior to timeout based on * the duration value. + * @action: Transmit an action frame * * @testmode_cmd: run a test mode command * @@ -1144,6 +1145,11 @@ struct cfg80211_ops { struct net_device *dev, u64 cookie); + int (*action)(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie); + /* some temporary stuff to finish wext */ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); @@ -1445,6 +1451,8 @@ struct cfg80211_cached_keys; * set by driver (if supported) on add_interface BEFORE registering the * netdev and may otherwise be used by driver read-only, will be update * by cfg80211 on change_interface + * @action_registrations: list of registrations for action frames + * @action_registrations_lock: lock for the list */ struct wireless_dev { struct wiphy *wiphy; @@ -1454,6 +1462,9 @@ struct wireless_dev { struct list_head list; struct net_device *netdev; + struct list_head action_registrations; + spinlock_t action_registrations_lock; + struct mutex mtx; struct work_struct cleanup_work; @@ -2291,4 +2302,38 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); +/** + * cfg80211_rx_action - notification of received, unprocessed Action frame + * @dev: network device + * @freq: Frequency on which the frame was received in MHz + * @buf: Action frame (header + body) + * @len: length of the frame data + * @gfp: context flags + * Returns %true if a user space application is responsible for rejecting the + * unrecognized Action frame; %false if no such application is registered + * (i.e., the driver is responsible for rejecting the unrecognized Action + * frame) + * + * This function is called whenever an Action frame is received for a station + * mode interface, but is not processed in kernel. + */ +bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, + size_t len, gfp_t gfp); + +/** + * cfg80211_action_tx_status - notification of TX status for Action frame + * @dev: network device + * @cookie: Cookie returned by cfg80211_ops::action() + * @buf: Action frame (header + body) + * @len: length of the frame data + * @ack: Whether frame was acknowledged + * @gfp: context flags + * + * This function is called whenever an Action frame was requested to be + * transmitted with cfg80211_ops::action() to report the TX status of the + * transmission attempt. + */ +void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, + const u8 *buf, size_t len, bool ack, gfp_t gfp); + #endif /* __NET_CFG80211_H */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 314e98173166..80eb7cc42ce9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3,7 +3,7 @@ * * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc - * Copyright 2007-2008 Johannes Berg + * Copyright 2007-2010 Johannes Berg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -264,6 +264,9 @@ struct ieee80211_bss_conf { * be modified again (no seqno assignment, crypto, etc.) * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still * has a radiotap header at skb->data. + * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 + * MLME command (internal to mac80211 to figure out whether to send TX + * status to user space) */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -286,6 +289,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), + IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e1731b7c2523..b7116ef84a3b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1,7 +1,7 @@ /* * mac80211 configuration hooks for cfg80211 * - * Copyright 2006, 2007 Johannes Berg + * Copyright 2006-2010 Johannes Berg * * This file is GPLv2 as found in COPYING. */ @@ -1448,6 +1448,15 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); } +static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie) +{ + return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan, + channel_type, buf, len, cookie); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1496,4 +1505,5 @@ struct cfg80211_ops mac80211_config_ops = { .set_bitrate_mask = ieee80211_set_bitrate_mask, .remain_on_channel = ieee80211_remain_on_channel, .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, + .action = ieee80211_action, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9dd98b674cbc..241533e1bc03 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc - * Copyright 2007-2008 Johannes Berg + * Copyright 2007-2010 Johannes Berg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -966,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, struct cfg80211_disassoc_request *req, void *cookie); +int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie); ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); void ieee80211_send_pspoll(struct ieee80211_local *local, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bfc4a5070013..41812a15eea0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2084,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, return 0; } + +int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct sk_buff *skb; + + /* Check that we are on the requested channel for transmission */ + if ((chan != local->tmp_channel || + channel_type != local->tmp_channel_type) && + (chan != local->oper_channel || + channel_type != local->oper_channel_type)) + return -EBUSY; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); + if (!skb) + return -ENOMEM; + skb_reserve(skb, local->hw.extra_tx_headroom); + + memcpy(skb_put(skb, len), buf, len); + + if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) + IEEE80211_SKB_CB(skb)->flags |= + IEEE80211_TX_INTFL_DONT_ENCRYPT; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | + IEEE80211_TX_CTL_REQ_TX_STATUS; + skb->dev = sdata->dev; + ieee80211_tx_skb(sdata, skb); + + *cookie = (unsigned long) skb; + return 0; +} diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a177472adc13..a6080d8d72bb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1856,28 +1856,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; struct sk_buff *nskb; + struct ieee80211_rx_status *status; int len = rx->skb->len; if (!ieee80211_is_action(mgmt->frame_control)) return RX_CONTINUE; - if (!rx->sta) + /* drop too small frames */ + if (len < IEEE80211_MIN_ACTION_SIZE) return RX_DROP_UNUSABLE; - if (!(rx->flags & IEEE80211_RX_RA_MATCH)) + if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) return RX_DROP_UNUSABLE; - if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) + if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; - /* drop too small frames */ - if (len < IEEE80211_MIN_ACTION_SIZE) + if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) return RX_DROP_UNUSABLE; - /* return action frames that have *only* category */ - if (len < IEEE80211_MIN_ACTION_SIZE + 1) - goto return_frame; - switch (mgmt->u.action.category) { case WLAN_CATEGORY_BACK: /* @@ -1891,6 +1888,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sdata->vif.type != NL80211_IFTYPE_AP) break; + /* verify action_code is present */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) + break; + switch (mgmt->u.action.u.addba_req.action_code) { case WLAN_ACTION_ADDBA_REQ: if (len < (IEEE80211_MIN_ACTION_SIZE + @@ -1919,6 +1920,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (sdata->vif.type != NL80211_IFTYPE_STATION) break; + /* verify action_code is present */ + if (len < IEEE80211_MIN_ACTION_SIZE + 1) + break; + switch (mgmt->u.action.u.measurement.action_code) { case WLAN_ACTION_SPCT_MSR_REQ: if (len < (IEEE80211_MIN_ACTION_SIZE + @@ -1954,7 +1959,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; } - return_frame: + /* * For AP mode, hostapd is responsible for handling any action * frames that we didn't handle, including returning unknown @@ -1966,6 +1971,20 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) sdata->vif.type == NL80211_IFTYPE_AP_VLAN) return RX_DROP_MONITOR; + /* + * Getting here means the kernel doesn't know how to handle + * it, but maybe userspace does ... include returned frames + * so userspace can register for those to know whether ones + * it transmitted were processed or returned. + */ + status = IEEE80211_SKB_RXCB(rx->skb); + + if (sdata->vif.type == NL80211_IFTYPE_STATION && + cfg80211_rx_action(rx->sdata->dev, status->freq, + rx->skb->data, rx->skb->len, + GFP_ATOMIC)) + goto handled; + /* do not return rejected action frames */ if (mgmt->u.action.category & 0x80) return RX_DROP_UNUSABLE; @@ -1985,7 +2004,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } handled: - rx->sta->rx_packets++; + if (rx->sta) + rx->sta->rx_packets++; dev_kfree_skb(rx->skb); return RX_QUEUED; } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ded98730c111..56d5b9a6ec5b 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc - * Copyright 2008-2009 Johannes Berg + * Copyright 2008-2010 Johannes Berg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -288,6 +288,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) msecs_to_jiffies(10)); } + if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) + cfg80211_action_tx_status( + skb->dev, (unsigned long) skb, skb->data, skb->len, + !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); + /* this was a transmitted frame, but now we want to reuse it */ skb_orphan(skb); diff --git a/net/wireless/core.c b/net/wireless/core.c index 71b6b3a9cf1f..51908dc2ea00 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -677,6 +677,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); INIT_LIST_HEAD(&wdev->event_list); spin_lock_init(&wdev->event_lock); + INIT_LIST_HEAD(&wdev->action_registrations); + spin_lock_init(&wdev->action_registrations_lock); + mutex_lock(&rdev->devlist_mtx); list_add_rcu(&wdev->list, &rdev->netdev_list); rdev->devlist_generation++; @@ -792,6 +795,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, sysfs_remove_link(&dev->dev.kobj, "phy80211"); list_del_rcu(&wdev->list); rdev->devlist_generation++; + cfg80211_mlme_purge_actions(wdev); #ifdef CONFIG_CFG80211_WEXT kfree(wdev->wext.keys); #endif diff --git a/net/wireless/core.h b/net/wireless/core.h index c326a667022a..d52da913145a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -329,6 +329,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *resp_ie, size_t resp_ie_len, u16 status, bool wextev, struct cfg80211_bss *bss); +int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, + const u8 *match_data, int match_len); +void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); +void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); +int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie); /* SME */ int __cfg80211_connect(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 94d151f6f73e..62bc8855e123 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -728,3 +728,169 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); } EXPORT_SYMBOL(cfg80211_new_sta); + +struct cfg80211_action_registration { + struct list_head list; + + u32 nlpid; + + int match_len; + + u8 match[]; +}; + +int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, + const u8 *match_data, int match_len) +{ + struct cfg80211_action_registration *reg, *nreg; + int err = 0; + + nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); + if (!nreg) + return -ENOMEM; + + spin_lock_bh(&wdev->action_registrations_lock); + + list_for_each_entry(reg, &wdev->action_registrations, list) { + int mlen = min(match_len, reg->match_len); + + if (memcmp(reg->match, match_data, mlen) == 0) { + err = -EALREADY; + break; + } + } + + if (err) { + kfree(nreg); + goto out; + } + + memcpy(nreg->match, match_data, match_len); + nreg->match_len = match_len; + nreg->nlpid = snd_pid; + list_add(&nreg->list, &wdev->action_registrations); + + out: + spin_unlock_bh(&wdev->action_registrations_lock); + return err; +} + +void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) +{ + struct cfg80211_action_registration *reg, *tmp; + + spin_lock_bh(&wdev->action_registrations_lock); + + list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { + if (reg->nlpid == nlpid) { + list_del(®->list); + kfree(reg); + } + } + + spin_unlock_bh(&wdev->action_registrations_lock); +} + +void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) +{ + struct cfg80211_action_registration *reg, *tmp; + + spin_lock_bh(&wdev->action_registrations_lock); + + list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { + list_del(®->list); + kfree(reg); + } + + spin_unlock_bh(&wdev->action_registrations_lock); +} + +int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + const u8 *buf, size_t len, u64 *cookie) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + const struct ieee80211_mgmt *mgmt; + + if (rdev->ops->action == NULL) + return -EOPNOTSUPP; + if (len < 24 + 1) + return -EINVAL; + + mgmt = (const struct ieee80211_mgmt *) buf; + if (!ieee80211_is_action(mgmt->frame_control)) + return -EINVAL; + if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { + /* Verify that we are associated with the destination AP */ + if (!wdev->current_bss || + memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, + ETH_ALEN) != 0 || + memcmp(wdev->current_bss->pub.bssid, mgmt->da, + ETH_ALEN) != 0) + return -ENOTCONN; + } + + if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) + return -EINVAL; + + /* Transmit the Action frame as requested by user space */ + return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, + buf, len, cookie); +} + +bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, + size_t len, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct cfg80211_action_registration *reg; + const u8 *action_data; + int action_data_len; + bool result = false; + + /* frame length - min size excluding category */ + action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); + + /* action data starts with category */ + action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; + + spin_lock_bh(&wdev->action_registrations_lock); + + list_for_each_entry(reg, &wdev->action_registrations, list) { + if (reg->match_len > action_data_len) + continue; + + if (memcmp(reg->match, action_data, reg->match_len)) + continue; + + /* found match! */ + + /* Indicate the received Action frame to user space */ + if (nl80211_send_action(rdev, dev, reg->nlpid, freq, + buf, len, gfp)) + continue; + + result = true; + break; + } + + spin_unlock_bh(&wdev->action_registrations_lock); + + return result; +} +EXPORT_SYMBOL(cfg80211_rx_action); + +void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, + const u8 *buf, size_t len, bool ack, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + + /* Indicate TX status of the Action frame to user space */ + nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); +} +EXPORT_SYMBOL(cfg80211_action_tx_status); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a95ab9e4c19e..328112081358 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1,7 +1,7 @@ /* * This is the new netlink-based wireless configuration interface. * - * Copyright 2006-2009 Johannes Berg + * Copyright 2006-2010 Johannes Berg */ #include @@ -145,6 +145,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, + [NL80211_ATTR_FRAME] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, }; /* policy for the attributes */ @@ -577,6 +580,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(flush_pmksa, FLUSH_PMKSA); CMD(remain_on_channel, REMAIN_ON_CHANNEL); CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); + CMD(action, ACTION); if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); @@ -4526,6 +4530,139 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, return err; } +static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct net_device *dev; + int err; + + if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) + return -EINVAL; + + if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + + /* not much point in registering if we can't reply */ + if (!rdev->ops->action) { + err = -EOPNOTSUPP; + goto out; + } + + err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, + nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), + nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + unlock_rtnl: + rtnl_unlock(); + return err; +} + +static int nl80211_action(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct net_device *dev; + struct ieee80211_channel *chan; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u32 freq; + int err; + void *hdr; + u64 cookie; + struct sk_buff *msg; + + if (!info->attrs[NL80211_ATTR_FRAME] || + !info->attrs[NL80211_ATTR_WIPHY_FREQ]) + return -EINVAL; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + if (!rdev->ops->action) { + err = -EOPNOTSUPP; + goto out; + } + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_running(dev)) { + err = -ENETDOWN; + goto out; + } + + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { + channel_type = nla_get_u32( + info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); + if (channel_type != NL80211_CHAN_NO_HT && + channel_type != NL80211_CHAN_HT20 && + channel_type != NL80211_CHAN_HT40PLUS && + channel_type != NL80211_CHAN_HT40MINUS) + err = -EINVAL; + goto out; + } + + freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); + chan = rdev_freq_to_chan(rdev, freq, channel_type); + if (chan == NULL) { + err = -EINVAL; + goto out; + } + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) { + err = -ENOMEM; + goto out; + } + + hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, + NL80211_CMD_ACTION); + + if (IS_ERR(hdr)) { + err = PTR_ERR(hdr); + goto free_msg; + } + err = cfg80211_mlme_action(rdev, dev, chan, channel_type, + nla_data(info->attrs[NL80211_ATTR_FRAME]), + nla_len(info->attrs[NL80211_ATTR_FRAME]), + &cookie); + if (err) + goto free_msg; + + NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + + genlmsg_end(msg, hdr); + err = genlmsg_reply(msg, info); + goto out; + + nla_put_failure: + err = -ENOBUFS; + free_msg: + nlmsg_free(msg); + out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); +unlock_rtnl: + rtnl_unlock(); + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -4806,6 +4943,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_REGISTER_ACTION, + .doit = nl80211_register_action, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_ACTION, + .doit = nl80211_action, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { @@ -5478,6 +5627,110 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, nl80211_mlme_mcgrp.id, gfp); } +int nl80211_send_action(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 nlpid, + int freq, const u8 *buf, size_t len, gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + int err; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return -ENOMEM; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); + if (!hdr) { + nlmsg_free(msg); + return -ENOMEM; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); + + err = genlmsg_end(msg, hdr); + if (err < 0) { + nlmsg_free(msg); + return err; + } + + err = genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid); + if (err < 0) + return err; + return 0; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); + return -ENOBUFS; +} + +void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); + if (!hdr) { + nlmsg_free(msg); + return; + } + + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); + NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); + if (ack) + NLA_PUT_FLAG(msg, NL80211_ATTR_ACK); + + if (genlmsg_end(msg, hdr) < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); + return; + + nla_put_failure: + genlmsg_cancel(msg, hdr); + nlmsg_free(msg); +} + +static int nl80211_netlink_notify(struct notifier_block * nb, + unsigned long state, + void *_notify) +{ + struct netlink_notify *notify = _notify; + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + + if (state != NETLINK_URELEASE) + return NOTIFY_DONE; + + rcu_read_lock(); + + list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) + list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) + cfg80211_mlme_unregister_actions(wdev, notify->pid); + + rcu_read_unlock(); + + return NOTIFY_DONE; +} + +static struct notifier_block nl80211_netlink_notifier = { + .notifier_call = nl80211_netlink_notify, +}; + /* initialisation/exit functions */ int nl80211_init(void) @@ -5511,6 +5764,10 @@ int nl80211_init(void) goto err_out; #endif + err = netlink_register_notifier(&nl80211_netlink_notifier); + if (err) + goto err_out; + return 0; err_out: genl_unregister_family(&nl80211_fam); @@ -5519,5 +5776,6 @@ int nl80211_init(void) void nl80211_exit(void) { + netlink_unregister_notifier(&nl80211_netlink_notifier); genl_unregister_family(&nl80211_fam); } diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 14855b8fb430..4ca511102c6c 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -74,4 +74,12 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, struct net_device *dev, const u8 *mac_addr, struct station_info *sinfo, gfp_t gfp); +int nl80211_send_action(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u32 nlpid, int freq, + const u8 *buf, size_t len, gfp_t gfp); +void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, + struct net_device *netdev, u64 cookie, + const u8 *buf, size_t len, bool ack, + gfp_t gfp); + #endif /* __NET_WIRELESS_NL80211_H */ -- cgit v1.2.3 From e858911804f5ecadb41afd61582a11f68d416328 Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Fri, 12 Feb 2010 13:48:05 +0000 Subject: ethtool: Fix filter addition when caching n-tuple filters We can allow a filter to be added successfully to the underlying hardware, but still return an error if the cached list memory allocation fails. This patch fixes that condition. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- net/core/ethtool.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index a1280f643bf4..fbbe4b49116b 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -283,18 +283,17 @@ err_out: return ret; } -static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, - struct ethtool_rx_ntuple_flow_spec *spec) +static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, + struct ethtool_rx_ntuple_flow_spec *spec, + struct ethtool_rx_ntuple_flow_spec_container *fsc) { - struct ethtool_rx_ntuple_flow_spec_container *fsc; /* don't add filters forever */ - if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) - return 0; - - fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); - if (!fsc) - return -ENOMEM; + if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY) { + /* free the container */ + kfree(fsc); + return; + } /* Copy the whole filter over */ fsc->fs.flow_type = spec->flow_type; @@ -310,14 +309,13 @@ static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, /* add to the list */ list_add_tail_rcu(&fsc->list, &list->list); list->count++; - - return 0; } static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) { struct ethtool_rx_ntuple cmd; const struct ethtool_ops *ops = dev->ethtool_ops; + struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; int ret; if (!ops->set_rx_ntuple) @@ -329,16 +327,26 @@ static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) if (copy_from_user(&cmd, useraddr, sizeof(cmd))) return -EFAULT; - ret = ops->set_rx_ntuple(dev, &cmd); - /* * Cache filter in dev struct for GET operation only if * the underlying driver doesn't have its own GET operation, and - * only if the filter was added successfully. + * only if the filter was added successfully. First make sure we + * can allocate the filter, then continue if successful. */ - if (!ops->get_rx_ntuple && !ret) - if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs)) + if (!ops->get_rx_ntuple) { + fsc = kmalloc(sizeof(*fsc), GFP_ATOMIC); + if (!fsc) return -ENOMEM; + } + + ret = ops->set_rx_ntuple(dev, &cmd); + if (ret) { + kfree(fsc); + return ret; + } + + if (!ops->get_rx_ntuple) + __rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs, fsc); return ret; } -- cgit v1.2.3 From 0d643e1fb4207711d9c148b5c6a2820550a4a154 Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Fri, 12 Feb 2010 13:48:25 +0000 Subject: ethtool: Move n-tuple capability check into set_flags set_flags should check if the underlying device supports n-tuple filter programming before setting the device flags on the netdevice. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- net/core/ethtool.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index fbbe4b49116b..794cf57078cd 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -134,15 +134,21 @@ u32 ethtool_op_get_flags(struct net_device *dev) int ethtool_op_set_flags(struct net_device *dev, u32 data) { + const struct ethtool_ops *ops = dev->ethtool_ops; + if (data & ETH_FLAG_LRO) dev->features |= NETIF_F_LRO; else dev->features &= ~NETIF_F_LRO; - if (data & ETH_FLAG_NTUPLE) + if (data & ETH_FLAG_NTUPLE) { + if (!ops->set_rx_ntuple) + return -EOPNOTSUPP; dev->features |= NETIF_F_NTUPLE; - else + } else { + /* safe to clear regardless */ dev->features &= ~NETIF_F_NTUPLE; + } return 0; } @@ -318,9 +324,6 @@ static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; int ret; - if (!ops->set_rx_ntuple) - return -EOPNOTSUPP; - if (!(dev->features & NETIF_F_NTUPLE)) return -EINVAL; -- cgit v1.2.3 From d41a5b7da223f7a80844fb3e948e8d5e6181f214 Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Fri, 12 Feb 2010 13:48:44 +0000 Subject: ixgbe: Cleanup incorrect header comments The recent n-tuple patches added some comments to the headers of the Flow Director functions that aren't accurate. This cleans them up, and is a purely cosmetic patch. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_82599.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 4fa8633fae3c..1f30e163bd9c 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1631,7 +1631,6 @@ static u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream * @input: input stream to modify * @vlan: the VLAN id to load - * @vlan_mask: bitwise mask for the VLAN **/ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) { @@ -1645,7 +1644,6 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan) * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address * @input: input stream to modify * @src_addr: the IP address to load - * @src_addr_mask: bitwise mask for the source IP address **/ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) { @@ -1663,7 +1661,6 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr) * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address * @input: input stream to modify * @dst_addr: the IP address to load - * @dst_addr_mask: bitwise mask for the destination IP address **/ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr) { @@ -1767,7 +1764,6 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, * ixgbe_atr_set_src_port_82599 - Sets the source port * @input: input stream to modify * @src_port: the source port to load - * @src_port_mask: bitwise mask for the source port **/ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) { @@ -1781,7 +1777,6 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port) * ixgbe_atr_set_dst_port_82599 - Sets the destination port * @input: input stream to modify * @dst_port: the destination port to load - * @dst_port_mask: bitwise mask for the destination port **/ s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port) { -- cgit v1.2.3 From 38a8fc0fcf86f131f8bddf3787f9dfa7325bd981 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 13 Feb 2010 09:44:30 +0000 Subject: cxgb3: FIx VLAN over Jumbo frames The mac is expected to auto-inflate the Maximum Frame size for VLAN tagged frames. It however does not work with jumbo frames. Work around the bug adding 4 to the Maximum Frame for MTUs greater than 1536. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/xgmac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 0109ee4f2f91..0c08de5d09fd 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -353,6 +353,9 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu) * packet size register includes header, but not FCS. */ mtu += 14; + if (mtu > 1536) + mtu += 4; + if (mtu > MAX_FRAME_SIZE - 4) return -EINVAL; t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); -- cgit v1.2.3 From e9449d85c67127d6f9d01aad8963d567ab02cb96 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sat, 13 Feb 2010 09:44:35 +0000 Subject: cxgb3: fix link flap The driver is expected to report that the link is up when the phy Rx signal is established and the mac has not detected a link fault. The code is however broken, the driver does not check the link fault status when the phy link status changes. The link fault status being checked within a short period of time, it leads to link up/link down events. Signed-off-by: Divy Le Ray Signed-off-by: David S. Miller --- drivers/net/cxgb3/t3_hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 032cfe065570..3ab9f51918aa 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -1262,7 +1262,8 @@ void t3_link_changed(struct adapter *adapter, int port_id) lc->fc = fc; } - t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc); + t3_os_link_changed(adapter, port_id, link_ok && !pi->link_fault, + speed, duplex, fc); } void t3_link_fault(struct adapter *adapter, int port_id) -- cgit v1.2.3 From 564517e804c9c6d4e29c270bfc1517404d27107b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 Feb 2010 05:55:39 +0000 Subject: net/macvtap: fix reference counting The RCU usage in the original code was broken because there are cases where we possibly sleep with rcu_read_lock held. As a fix, change the macvtap_file_get_queue to get a reference on the socket and the netdev instead of taking the full rcu_read_lock. Also, change macvtap_file_get_queue failure case to not require a subsequent macvtap_file_put_queue, as pointed out by Ed Swierk. Signed-off-by: Arnd Bergmann Cc: Ed Swierk Cc: Sridhar Samudrala Acked-by: Sridhar Samudrala Acked-by: Ed Swierk Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index ad1f6ef89308..fe7656bf68c6 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -70,7 +70,8 @@ static struct cdev macvtap_cdev; * exists. * * The callbacks from macvlan are always done with rcu_read_lock held - * already, while in the file_operations, we get it ourselves. + * already. For calls from file_operations, we use the rcu_read_lock_bh + * to get a reference count on the socket and the device. * * When destroying a queue, we remove the pointers from the file and * from the dev and then synchronize_rcu to make sure no thread is @@ -159,13 +160,21 @@ static void macvtap_del_queues(struct net_device *dev) static inline struct macvtap_queue *macvtap_file_get_queue(struct file *file) { + struct macvtap_queue *q; rcu_read_lock_bh(); - return rcu_dereference(file->private_data); + q = rcu_dereference(file->private_data); + if (q) { + sock_hold(&q->sk); + dev_hold(q->vlan->dev); + } + rcu_read_unlock_bh(); + return q; } -static inline void macvtap_file_put_queue(void) +static inline void macvtap_file_put_queue(struct macvtap_queue *q) { - rcu_read_unlock_bh(); + sock_put(&q->sk); + dev_put(q->vlan->dev); } /* @@ -314,8 +323,8 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait) sock_writeable(&q->sk))) mask |= POLLOUT | POLLWRNORM; + macvtap_file_put_queue(q); out: - macvtap_file_put_queue(); return mask; } @@ -366,8 +375,8 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, result = macvtap_get_user(q, iv, iov_length(iv, count), file->f_flags & O_NONBLOCK); + macvtap_file_put_queue(q); out: - macvtap_file_put_queue(); return result; } @@ -398,10 +407,8 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, struct sk_buff *skb; ssize_t len, ret = 0; - if (!q) { - ret = -ENOLINK; - goto out; - } + if (!q) + return -ENOLINK; len = iov_length(iv, count); if (len < 0) { @@ -437,7 +444,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, remove_wait_queue(q->sk.sk_sleep, &wait); out: - macvtap_file_put_queue(); + macvtap_file_put_queue(q); return ret; } @@ -468,7 +475,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, if (!q) return -ENOLINK; memcpy(devname, q->vlan->dev->name, sizeof(devname)); - macvtap_file_put_queue(); + macvtap_file_put_queue(q); if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) || put_user((TUN_TAP_DEV | TUN_NO_PI), &ifr->ifr_flags)) @@ -485,8 +492,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return -EFAULT; q = macvtap_file_get_queue(file); + if (!q) + return -ENOLINK; q->sk.sk_sndbuf = u; - macvtap_file_put_queue(); + macvtap_file_put_queue(q); return 0; case TUNSETOFFLOAD: -- cgit v1.2.3 From 9546377c42e12513b33925ab829d893dcf521c5f Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Thu, 11 Feb 2010 00:12:45 +0000 Subject: IPv6: Delete redundant counter of IPSTATS_MIB_REASMFAILS When no more memory can be allocated, fq_find() will return NULL and increase the value of IPSTATS_MIB_REASMFAILS. In this case, ipv6_frag_rcv() also increase the value of IPSTATS_MIB_REASMFAILS. So, the patch deletes redundant counter of IPSTATS_MIB_REASMFAILS in fq_find(). and deletes the unused parameter of idev. Signed-off-by: Shan Wei Signed-off-by: David S. Miller --- net/ipv6/reassembly.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index fa38fc7cc6e9..fe27eb4264d6 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -237,8 +237,7 @@ out: } static __inline__ struct frag_queue * -fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, - struct inet6_dev *idev) +fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst) { struct inet_frag_queue *q; struct ip6_create_arg arg; @@ -254,13 +253,9 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); if (q == NULL) - goto oom; + return NULL; return container_of(q, struct frag_queue, q); - -oom: - IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS); - return NULL; } static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, @@ -606,8 +601,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); - if ((fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, - ip6_dst_idev(skb_dst(skb)))) != NULL) { + fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr); + if (fq != NULL) { int ret; spin_lock(&fq->q.lock); -- cgit v1.2.3 From 19f4c7133fc1b94001b997c4843d0a9192ee63e5 Mon Sep 17 00:00:00 2001 From: jamal Date: Wed, 10 Feb 2010 23:51:27 +0000 Subject: xfrm: Flushing empty SAD generates false events To see the effect make sure you have an empty SAD. -On window1 "ip xfrm mon" -on window2 issue "ip xfrm state flush" You get prompt back in window1 and you see the flush event on window2. With this fix, you still get prompt on window1 but no event on window2. I was tempted to return -ESRCH on window1 (which would show "RTNETLINK answers: No such process") but didnt want to change current behavior. cheers, jamal commit 5f3dd4a772326166e1bcf54acc2391df00dc7ab5 Author: Jamal Hadi Salim Date: Thu Feb 11 04:41:36 2010 -0500 xfrm: Flushing empty SAD generates false events To see the effect make sure you have an empty SAD. On window1 "ip xfrm mon" and on window2 issue "ip xfrm state flush" You get prompt back in window1 and you see the flush event on window2. With this fix, you still get prompt on window1 but no event on window2. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 2 +- net/xfrm/xfrm_state.c | 8 ++++++-- net/xfrm/xfrm_user.c | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 79d2c0f3c334..9d47a6aa53dc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1751,7 +1751,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); if (err) - return err; + return 0; c.data.proto = proto; c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index b36cc344474b..f50ee9badf47 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -603,13 +603,14 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) { - int i, err = 0; + int i, err = 0, cnt = 0; spin_lock_bh(&xfrm_state_lock); err = xfrm_state_flush_secctx_check(net, proto, audit_info); if (err) goto out; + err = -ESRCH; for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; @@ -626,13 +627,16 @@ restart: audit_info->sessionid, audit_info->secid); xfrm_state_put(x); + if (!err) + cnt++; spin_lock_bh(&xfrm_state_lock); goto restart; } } } - err = 0; + if (cnt) + err = 0; out: spin_unlock_bh(&xfrm_state_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 943c8712bd97..7c8700447040 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1525,7 +1525,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_state_flush(net, p->proto, &audit_info); if (err) - return err; + return 0; c.data.proto = p->proto; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- cgit v1.2.3 From 0dca3a843632c2fbb6e358734fb08fc23e800f50 Mon Sep 17 00:00:00 2001 From: jamal Date: Thu, 11 Feb 2010 00:53:13 +0000 Subject: xfrm: Flushing empty SPD generates false events Observed similar behavior on SPD as previouly seen on SAD flushing.. This fixes it. cheers, jamal commit 428b20432dc31bc2e01a94cd451cf5a2c00d2bf4 Author: Jamal Hadi Salim Date: Thu Feb 11 05:49:38 2010 -0500 xfrm: Flushing empty SPD generates false events To see the effect make sure you have an empty SPD. On window1 "ip xfrm mon" and on window2 issue "ip xfrm policy flush" You get prompt back in window1 and you see the flush event on window2. With this fix, you still get prompt on window1 but no event on window2. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 2 +- net/xfrm/xfrm_policy.c | 13 ++++++++++--- net/xfrm/xfrm_user.c | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 9d47a6aa53dc..8b8e26a9e401 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2713,7 +2713,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); if (err) - return err; + return 0; c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0ecb16a9a883..eb870fcc29cc 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -771,7 +771,8 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) { - int dir, err = 0; + int dir, err = 0, cnt = 0; + struct xfrm_policy *dp; write_lock_bh(&xfrm_policy_lock); @@ -789,8 +790,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, audit_info->sessionid, @@ -809,8 +812,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, @@ -824,6 +829,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) } } + if (!cnt) + err = -ESRCH; atomic_inc(&flow_cache_genid); out: write_unlock_bh(&xfrm_policy_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7c8700447040..b0fb7d3bc15e 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1677,7 +1677,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_policy_flush(net, type, &audit_info); if (err) - return err; + return 0; c.data.type = type; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- cgit v1.2.3 From cf588477a3fbf085426e5c0b6205984ebb7e2187 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Sun, 14 Feb 2010 21:22:01 +0000 Subject: be2net: implement EEH pci error recovery handlers The code has been tested on IBM pSeries server. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_cmds.c | 23 +++++++++- drivers/net/benet/be_main.c | 103 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index b39b38542623..5038c16bfe9b 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -265,6 +265,7 @@ struct be_adapter { u32 if_handle; /* Used to configure filtering */ u32 pmac_id; /* MAC addr handle used by BE card */ + bool eeh_err; bool link_up; u32 port_num; bool promiscuous; diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index d1a0e5ede4b3..3397ee327e1f 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -167,7 +167,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) u32 ready; do { - ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; + ready = ioread32(db); + if (ready == 0xffffffff) { + dev_err(&adapter->pdev->dev, + "pci slot disconnected\n"); + return -1; + } + + ready &= MPU_MAILBOX_DB_RDY_MASK; if (ready) break; @@ -198,6 +205,11 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) struct be_mcc_mailbox *mbox = mbox_mem->va; struct be_mcc_compl *compl = &mbox->compl; + /* wait for ready to be set */ + status = be_mbox_db_ready_wait(adapter, db); + if (status != 0) + return status; + val |= MPU_MAILBOX_DB_HI_MASK; /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; @@ -396,6 +408,9 @@ int be_cmd_fw_clean(struct be_adapter *adapter) u8 *wrb; int status; + if (adapter->eeh_err) + return -EIO; + spin_lock(&adapter->mbox_lock); wrb = (u8 *)wrb_from_mbox(adapter); @@ -768,6 +783,9 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, u8 subsys = 0, opcode = 0; int status; + if (adapter->eeh_err) + return -EIO; + spin_lock(&adapter->mbox_lock); wrb = wrb_from_mbox(adapter); @@ -856,6 +874,9 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id) struct be_cmd_req_if_destroy *req; int status; + if (adapter->eeh_err) + return -EIO; + spin_lock(&adapter->mbox_lock); wrb = wrb_from_mbox(adapter); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 92c55f679466..cbfaa3feb7c4 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -68,6 +68,9 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) u32 reg = ioread32(addr); u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + if (adapter->eeh_err) + return; + if (!enabled && enable) reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; else if (enabled && !enable) @@ -99,6 +102,10 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, { u32 val = 0; val |= qid & DB_EQ_RING_ID_MASK; + + if (adapter->eeh_err) + return; + if (arm) val |= 1 << DB_EQ_REARM_SHIFT; if (clear_int) @@ -112,6 +119,10 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) { u32 val = 0; val |= qid & DB_CQ_RING_ID_MASK; + + if (adapter->eeh_err) + return; + if (arm) val |= 1 << DB_CQ_REARM_SHIFT; val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; @@ -2154,6 +2165,7 @@ static int be_ctrl_init(struct be_adapter *adapter) spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); + pci_save_state(adapter->pdev); return 0; free_mbox: @@ -2417,13 +2429,102 @@ static int be_resume(struct pci_dev *pdev) return 0; } +static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + dev_err(&adapter->pdev->dev, "EEH error detected\n"); + + adapter->eeh_err = true; + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + rtnl_lock(); + be_close(netdev); + rtnl_unlock(); + } + be_clear(adapter); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + int status; + + dev_info(&adapter->pdev->dev, "EEH reset\n"); + adapter->eeh_err = false; + + status = pci_enable_device(pdev); + if (status) + return PCI_ERS_RESULT_DISCONNECT; + + pci_set_master(pdev); + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + /* Check if card is ok and fw is ready */ + status = be_cmd_POST(adapter); + if (status) + return PCI_ERS_RESULT_DISCONNECT; + + return PCI_ERS_RESULT_RECOVERED; +} + +static void be_eeh_resume(struct pci_dev *pdev) +{ + int status = 0; + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + dev_info(&adapter->pdev->dev, "EEH resume\n"); + + pci_save_state(pdev); + + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); + if (status) + goto err; + + status = be_setup(adapter); + if (status) + goto err; + + if (netif_running(netdev)) { + status = be_open(netdev); + if (status) + goto err; + } + netif_device_attach(netdev); + return; +err: + dev_err(&adapter->pdev->dev, "EEH resume failed\n"); + return; +} + +static struct pci_error_handlers be_eeh_handlers = { + .error_detected = be_eeh_err_detected, + .slot_reset = be_eeh_reset, + .resume = be_eeh_resume, +}; + static struct pci_driver be_driver = { .name = DRV_NAME, .id_table = be_dev_ids, .probe = be_probe, .remove = be_remove, .suspend = be_suspend, - .resume = be_resume + .resume = be_resume, + .err_handler = &be_eeh_handlers }; static int __init be_init_module(void) -- cgit v1.2.3 From b18e7a06857833d2c7c8c8457e5a3a7c3327f643 Mon Sep 17 00:00:00 2001 From: andrew hendry Date: Sun, 14 Feb 2010 02:00:11 +0000 Subject: X25: Fix x25_create errors for bad protocol and ENOBUFS alloc_socket failures should return -ENOBUFS a bad protocol should return -EINVAL Signed-off-by: Andrew Hendry Signed-off-by: David S. Miller --- net/x25/af_x25.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e3219e4cd044..6c7104edec60 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -512,15 +512,20 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; struct x25_sock *x25; - int rc = -ESOCKTNOSUPPORT; + int rc = -EAFNOSUPPORT; if (!net_eq(net, &init_net)) - return -EAFNOSUPPORT; + goto out; + + rc = -ESOCKTNOSUPPORT; + if (sock->type != SOCK_SEQPACKET) + goto out; - if (sock->type != SOCK_SEQPACKET || protocol) + rc = -EINVAL; + if (protocol) goto out; - rc = -ENOMEM; + rc = -ENOBUFS; if ((sk = x25_alloc_socket(net)) == NULL) goto out; -- cgit v1.2.3 From a9288525d2aed806c1b8a785c226d4a9e6371650 Mon Sep 17 00:00:00 2001 From: andrew hendry Date: Sun, 14 Feb 2010 02:00:45 +0000 Subject: X25: Dont let x25_bind use addresses containing characters Addresses should be all digits. Stops x25_bind using addresses containing characters. Signed-off-by: Andrew Hendry Signed-off-by: David S. Miller --- net/x25/af_x25.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 6c7104edec60..9796f3ed1edb 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -648,7 +649,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; - int rc = 0; + int len, i, rc = 0; lock_kernel(); if (!sock_flag(sk, SOCK_ZAPPED) || @@ -658,6 +659,14 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; } + len = strlen(addr->sx25_addr.x25_addr); + for (i = 0; i < len; i++) { + if (!isdigit(addr->sx25_addr.x25_addr[i])) { + rc = -EINVAL; + goto out; + } + } + x25_sk(sk)->source_addr = addr->sx25_addr; x25_insert_socket(sk); sock_reset_flag(sk, SOCK_ZAPPED); -- cgit v1.2.3 From 5cdaaa12866e916d0ada8b56c5f0e543cfc7fe3d Mon Sep 17 00:00:00 2001 From: John Linn Date: Mon, 15 Feb 2010 21:51:00 -0800 Subject: net: emaclite: adding MDIO and phy lib support These changes add MDIO and phy lib support to the driver as the IP core now supports the MDIO bus. The MDIO bus and phy are added as a child to the emaclite in the device tree as illustrated below. mdio { #address-cells = <1>; #size-cells = <0>; phy0: phy@7 { compatible = "marvell,88e1111"; reg = <7>; } ; } Signed-off-by: Sadanand Mutyala Signed-off-by: John Linn Acked-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/xilinx_emaclite.c | 378 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 336 insertions(+), 43 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5f646523c5ae..b711d5416100 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1963,6 +1963,7 @@ config ATL2 config XILINX_EMACLITE tristate "Xilinx 10/100 Ethernet Lite support" depends on PPC32 || MICROBLAZE + select PHYLIB help This driver supports the 10/100 Ethernet Lite from Xilinx. diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c index f7fe1aa03b42..1a74594224b1 100644 --- a/drivers/net/xilinx_emaclite.c +++ b/drivers/net/xilinx_emaclite.c @@ -22,11 +22,17 @@ #include #include +#include +#include #define DRIVER_NAME "xilinx_emaclite" /* Register offsets for the EmacLite Core */ #define XEL_TXBUFF_OFFSET 0x0 /* Transmit Buffer */ +#define XEL_MDIOADDR_OFFSET 0x07E4 /* MDIO Address Register */ +#define XEL_MDIOWR_OFFSET 0x07E8 /* MDIO Write Data Register */ +#define XEL_MDIORD_OFFSET 0x07EC /* MDIO Read Data Register */ +#define XEL_MDIOCTRL_OFFSET 0x07F0 /* MDIO Control Register */ #define XEL_GIER_OFFSET 0x07F8 /* GIE Register */ #define XEL_TSR_OFFSET 0x07FC /* Tx status */ #define XEL_TPLR_OFFSET 0x07F4 /* Tx packet length */ @@ -37,6 +43,22 @@ #define XEL_BUFFER_OFFSET 0x0800 /* Next Tx/Rx buffer's offset */ +/* MDIO Address Register Bit Masks */ +#define XEL_MDIOADDR_REGADR_MASK 0x0000001F /* Register Address */ +#define XEL_MDIOADDR_PHYADR_MASK 0x000003E0 /* PHY Address */ +#define XEL_MDIOADDR_PHYADR_SHIFT 5 +#define XEL_MDIOADDR_OP_MASK 0x00000400 /* RD/WR Operation */ + +/* MDIO Write Data Register Bit Masks */ +#define XEL_MDIOWR_WRDATA_MASK 0x0000FFFF /* Data to be Written */ + +/* MDIO Read Data Register Bit Masks */ +#define XEL_MDIORD_RDDATA_MASK 0x0000FFFF /* Data to be Read */ + +/* MDIO Control Register Bit Masks */ +#define XEL_MDIOCTRL_MDIOSTS_MASK 0x00000001 /* MDIO Status Mask */ +#define XEL_MDIOCTRL_MDIOEN_MASK 0x00000008 /* MDIO Enable */ + /* Global Interrupt Enable Register (GIER) Bit Masks */ #define XEL_GIER_GIE_MASK 0x80000000 /* Global Enable */ @@ -87,6 +109,12 @@ * @reset_lock: lock used for synchronization * @deferred_skb: holds an skb (for transmission at a later time) when the * Tx buffer is not free + * @phy_dev: pointer to the PHY device + * @phy_node: pointer to the PHY device node + * @mii_bus: pointer to the MII bus + * @mdio_irqs: IRQs table for MDIO bus + * @last_link: last link status + * @has_mdio: indicates whether MDIO is included in the HW */ struct net_local { @@ -100,6 +128,15 @@ struct net_local { spinlock_t reset_lock; struct sk_buff *deferred_skb; + + struct phy_device *phy_dev; + struct device_node *phy_node; + + struct mii_bus *mii_bus; + int mdio_irqs[PHY_MAX_ADDR]; + + int last_link; + bool has_mdio; }; @@ -431,7 +468,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) } /** - * xemaclite_set_mac_address - Set the MAC address for this device + * xemaclite_update_address - Update the MAC address in the device * @drvdata: Pointer to the Emaclite device private data * @address_ptr:Pointer to the MAC address (MAC address is a 48-bit value) * @@ -441,8 +478,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data) * The MAC address can be programmed using any of the two transmit * buffers (if configured). */ -static void xemaclite_set_mac_address(struct net_local *drvdata, - u8 *address_ptr) +static void xemaclite_update_address(struct net_local *drvdata, + u8 *address_ptr) { void __iomem *addr; u32 reg_data; @@ -464,6 +501,30 @@ static void xemaclite_set_mac_address(struct net_local *drvdata, ; } +/** + * xemaclite_set_mac_address - Set the MAC address for this device + * @dev: Pointer to the network device instance + * @addr: Void pointer to the sockaddr structure + * + * This function copies the HW address from the sockaddr strucutre to the + * net_device structure and updates the address in HW. + * + * Return: Error if the net device is busy or 0 if the addr is set + * successfully + */ +static int xemaclite_set_mac_address(struct net_device *dev, void *address) +{ + struct net_local *lp = (struct net_local *) netdev_priv(dev); + struct sockaddr *addr = address; + + if (netif_running(dev)) + return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + xemaclite_update_address(lp, dev->dev_addr); + return 0; +} + /** * xemaclite_tx_timeout - Callback for Tx Timeout * @dev: Pointer to the network device @@ -641,12 +702,219 @@ static irqreturn_t xemaclite_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +/**********************/ +/* MDIO Bus functions */ +/**********************/ + +/** + * xemaclite_mdio_wait - Wait for the MDIO to be ready to use + * @lp: Pointer to the Emaclite device private data + * + * This function waits till the device is ready to accept a new MDIO + * request. + * + * Return: 0 for success or ETIMEDOUT for a timeout + */ + +static int xemaclite_mdio_wait(struct net_local *lp) +{ + long end = jiffies + 2; + + /* wait for the MDIO interface to not be busy or timeout + after some time. + */ + while (in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET) & + XEL_MDIOCTRL_MDIOSTS_MASK) { + if (end - jiffies <= 0) { + WARN_ON(1); + return -ETIMEDOUT; + } + msleep(1); + } + return 0; +} + +/** + * xemaclite_mdio_read - Read from a given MII management register + * @bus: the mii_bus struct + * @phy_id: the phy address + * @reg: register number to read from + * + * This function waits till the device is ready to accept a new MDIO + * request and then writes the phy address to the MDIO Address register + * and reads data from MDIO Read Data register, when its available. + * + * Return: Value read from the MII management register + */ +static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct net_local *lp = bus->priv; + u32 ctrl_reg; + u32 rc; + + if (xemaclite_mdio_wait(lp)) + return -ETIMEDOUT; + + /* Write the PHY address, register number and set the OP bit in the + * MDIO Address register. Set the Status bit in the MDIO Control + * register to start a MDIO read transaction. + */ + ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET); + out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET, + XEL_MDIOADDR_OP_MASK | + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg)); + out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, + ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK); + + if (xemaclite_mdio_wait(lp)) + return -ETIMEDOUT; + + rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET); + + dev_dbg(&lp->ndev->dev, + "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n", + phy_id, reg, rc); + + return rc; +} + +/** + * xemaclite_mdio_write - Write to a given MII management register + * @bus: the mii_bus struct + * @phy_id: the phy address + * @reg: register number to write to + * @val: value to write to the register number specified by reg + * + * This fucntion waits till the device is ready to accept a new MDIO + * request and then writes the val to the MDIO Write Data register. + */ +static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg, + u16 val) +{ + struct net_local *lp = bus->priv; + u32 ctrl_reg; + + dev_dbg(&lp->ndev->dev, + "xemaclite_mdio_write(phy_id=%i, reg=%x, val=%x)\n", + phy_id, reg, val); + + if (xemaclite_mdio_wait(lp)) + return -ETIMEDOUT; + + /* Write the PHY address, register number and clear the OP bit in the + * MDIO Address register and then write the value into the MDIO Write + * Data register. Finally, set the Status bit in the MDIO Control + * register to start a MDIO write transaction. + */ + ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET); + out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET, + ~XEL_MDIOADDR_OP_MASK & + ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg)); + out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val); + out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, + ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK); + + return 0; +} + +/** + * xemaclite_mdio_reset - Reset the mdio bus. + * @bus: Pointer to the MII bus + * + * This function is required(?) as per Documentation/networking/phy.txt. + * There is no reset in this device; this function always returns 0. + */ +static int xemaclite_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +/** + * xemaclite_mdio_setup - Register mii_bus for the Emaclite device + * @lp: Pointer to the Emaclite device private data + * @ofdev: Pointer to OF device structure + * + * This function enables MDIO bus in the Emaclite device and registers a + * mii_bus. + * + * Return: 0 upon success or a negative error upon failure + */ +static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev) +{ + struct mii_bus *bus; + int rc; + struct resource res; + struct device_node *np = of_get_parent(lp->phy_node); + + /* Don't register the MDIO bus if the phy_node or its parent node + * can't be found. + */ + if (!np) + return -ENODEV; + + /* Enable the MDIO bus by asserting the enable bit in MDIO Control + * register. + */ + out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET, + XEL_MDIOCTRL_MDIOEN_MASK); + + bus = mdiobus_alloc(); + if (!bus) + return -ENOMEM; + + of_address_to_resource(np, 0, &res); + snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", + (unsigned long long)res.start); + bus->priv = lp; + bus->name = "Xilinx Emaclite MDIO"; + bus->read = xemaclite_mdio_read; + bus->write = xemaclite_mdio_write; + bus->reset = xemaclite_mdio_reset; + bus->parent = dev; + bus->irq = lp->mdio_irqs; /* preallocated IRQ table */ + + lp->mii_bus = bus; + + rc = of_mdiobus_register(bus, np); + if (rc) + goto err_register; + + return 0; + +err_register: + mdiobus_free(bus); + return rc; +} + +/** + * xemaclite_adjust_link - Link state callback for the Emaclite device + * @ndev: pointer to net_device struct + * + * There's nothing in the Emaclite device to be configured when the link + * state changes. We just print the status. + */ +void xemaclite_adjust_link(struct net_device *ndev) +{ + struct net_local *lp = netdev_priv(ndev); + struct phy_device *phy = lp->phy_dev; + int link_state; + + /* hash together the state values to decide if something has changed */ + link_state = phy->speed | (phy->duplex << 1) | phy->link; + + if (lp->last_link != link_state) { + lp->last_link = link_state; + phy_print_status(phy); + } +} + /** * xemaclite_open - Open the network device * @dev: Pointer to the network device * * This function sets the MAC address, requests an IRQ and enables interrupts * for the Emaclite device and starts the Tx queue. + * It also connects to the phy device, if MDIO is included in Emaclite device. */ static int xemaclite_open(struct net_device *dev) { @@ -656,14 +924,47 @@ static int xemaclite_open(struct net_device *dev) /* Just to be safe, stop the device first */ xemaclite_disable_interrupts(lp); + if (lp->phy_node) { + u32 bmcr; + + lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node, + xemaclite_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (!lp->phy_dev) { + dev_err(&lp->ndev->dev, "of_phy_connect() failed\n"); + return -ENODEV; + } + + /* EmacLite doesn't support giga-bit speeds */ + lp->phy_dev->supported &= (PHY_BASIC_FEATURES); + lp->phy_dev->advertising = lp->phy_dev->supported; + + /* Don't advertise 1000BASE-T Full/Half duplex speeds */ + phy_write(lp->phy_dev, MII_CTRL1000, 0); + + /* Advertise only 10 and 100mbps full/half duplex speeds */ + phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL); + + /* Restart auto negotiation */ + bmcr = phy_read(lp->phy_dev, MII_BMCR); + bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(lp->phy_dev, MII_BMCR, bmcr); + + phy_start(lp->phy_dev); + } + /* Set the MAC address each time opened */ - xemaclite_set_mac_address(lp, dev->dev_addr); + xemaclite_update_address(lp, dev->dev_addr); /* Grab the IRQ */ retval = request_irq(dev->irq, xemaclite_interrupt, 0, dev->name, dev); if (retval) { dev_err(&lp->ndev->dev, "Could not allocate interrupt %d\n", dev->irq); + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + return retval; } @@ -682,6 +983,7 @@ static int xemaclite_open(struct net_device *dev) * * This function stops the Tx queue, disables interrupts and frees the IRQ for * the Emaclite device. + * It also disconnects the phy device associated with the Emaclite device. */ static int xemaclite_close(struct net_device *dev) { @@ -691,6 +993,10 @@ static int xemaclite_close(struct net_device *dev) xemaclite_disable_interrupts(lp); free_irq(dev->irq, dev); + if (lp->phy_dev) + phy_disconnect(lp->phy_dev); + lp->phy_dev = NULL; + return 0; } @@ -753,42 +1059,6 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev) return 0; } -/** - * xemaclite_ioctl - Perform IO Control operations on the network device - * @dev: Pointer to the network device - * @rq: Pointer to the interface request structure - * @cmd: IOCTL command - * - * The only IOCTL operation supported by this function is setting the MAC - * address. An error is reported if any other operations are requested. - * - * Return: 0 to indicate success, or a negative error for failure. - */ -static int xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct net_local *lp = (struct net_local *) netdev_priv(dev); - struct hw_addr_data *hw_addr = (struct hw_addr_data *) &rq->ifr_hwaddr; - - switch (cmd) { - case SIOCETHTOOL: - return -EIO; - - case SIOCSIFHWADDR: - dev_err(&lp->ndev->dev, "SIOCSIFHWADDR\n"); - - /* Copy MAC address in from user space */ - copy_from_user((void __force *) dev->dev_addr, - (void __user __force *) hw_addr, - IFHWADDRLEN); - xemaclite_set_mac_address(lp, dev->dev_addr); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - /** * xemaclite_remove_ndev - Free the network device * @ndev: Pointer to the network device to be freed @@ -840,6 +1110,8 @@ static struct net_device_ops xemaclite_netdev_ops; * This function probes for the Emaclite device in the device tree. * It initializes the driver data structure and the hardware, sets the MAC * address and registers the network device. + * It also registers a mii_bus for the Emaclite device, if MDIO is included + * in the device. * * Return: 0, if the driver is bound to the Emaclite device, or * a negative error if there is failure. @@ -880,6 +1152,7 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev, } dev_set_drvdata(dev, ndev); + SET_NETDEV_DEV(ndev, &ofdev->dev); ndev->irq = r_irq.start; ndev->mem_start = r_mem.start; @@ -923,7 +1196,12 @@ static int __devinit xemaclite_of_probe(struct of_device *ofdev, out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0); /* Set the MAC address in the EmacLite device */ - xemaclite_set_mac_address(lp, ndev->dev_addr); + xemaclite_update_address(lp, ndev->dev_addr); + + lp->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0); + rc = xemaclite_mdio_setup(lp, &ofdev->dev); + if (rc) + dev_warn(&ofdev->dev, "error registering MDIO bus\n"); dev_info(dev, "MAC address is now %pM\n", ndev->dev_addr); @@ -968,12 +1246,25 @@ static int __devexit xemaclite_of_remove(struct of_device *of_dev) struct device *dev = &of_dev->dev; struct net_device *ndev = dev_get_drvdata(dev); + struct net_local *lp = (struct net_local *) netdev_priv(ndev); + + /* Un-register the mii_bus, if configured */ + if (lp->has_mdio) { + mdiobus_unregister(lp->mii_bus); + kfree(lp->mii_bus->irq); + mdiobus_free(lp->mii_bus); + lp->mii_bus = NULL; + } + unregister_netdev(ndev); + if (lp->phy_node) + of_node_put(lp->phy_node); + lp->phy_node = NULL; + release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1); xemaclite_remove_ndev(ndev); - dev_set_drvdata(dev, NULL); return 0; @@ -983,7 +1274,7 @@ static struct net_device_ops xemaclite_netdev_ops = { .ndo_open = xemaclite_open, .ndo_stop = xemaclite_close, .ndo_start_xmit = xemaclite_send, - .ndo_do_ioctl = xemaclite_ioctl, + .ndo_set_mac_address = xemaclite_set_mac_address, .ndo_tx_timeout = xemaclite_tx_timeout, .ndo_get_stats = xemaclite_get_stats, }; @@ -995,6 +1286,7 @@ static struct of_device_id xemaclite_of_match[] __devinitdata = { { .compatible = "xlnx,xps-ethernetlite-1.00.a", }, { .compatible = "xlnx,xps-ethernetlite-2.00.a", }, { .compatible = "xlnx,xps-ethernetlite-2.01.a", }, + { .compatible = "xlnx,xps-ethernetlite-3.00.a", }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, xemaclite_of_match); -- cgit v1.2.3 From 339c6e99853d2ef1f02ad8a313e079050a300427 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 15 Feb 2010 21:51:33 -0800 Subject: ethtool: reduce stack usage dev_ethtool() is currently using 604 bytes of stack, even with gcc-4.4.2 objdump -d vmlinux | scripts/checkstack.pl ... 0xc04bbc33 dev_ethtool [vmlinux]: 604 ... Adding noinline attributes to selected functions can reduce stack usage. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/ethtool.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 794cf57078cd..82cae3bca78d 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -197,7 +197,10 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->set_settings(dev, &cmd); } -static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) { struct ethtool_drvinfo info; const struct ethtool_ops *ops = dev->ethtool_ops; @@ -232,7 +235,10 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) return 0; } -static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) { struct ethtool_rxnfc cmd; @@ -245,7 +251,10 @@ static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) return dev->ethtool_ops->set_rxnfc(dev, &cmd); } -static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) { struct ethtool_rxnfc info; const struct ethtool_ops *ops = dev->ethtool_ops; @@ -317,7 +326,10 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, list->count++; } -static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) { struct ethtool_rx_ntuple cmd; const struct ethtool_ops *ops = dev->ethtool_ops; @@ -788,7 +800,10 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) return ret; } -static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) { struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; @@ -802,7 +817,10 @@ static int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) return 0; } -static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) { struct ethtool_coalesce coalesce; @@ -1212,7 +1230,10 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr, return actor(dev, edata.data); } -static int ethtool_flash_device(struct net_device *dev, char __user *useraddr) +/* + * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() + */ +static noinline int ethtool_flash_device(struct net_device *dev, char __user *useraddr) { struct ethtool_flash efl; -- cgit v1.2.3 From e788759f44b29e5b1bc27a265dece7dcfa4234af Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 4 Feb 2010 18:38:53 +0100 Subject: netfilter: ebtables: split do_replace into two functions once CONFIG_COMPAT support is merged this allows to call do_replace_finish() after doing the CONFIG_COMPAT conversion instead of copy & pasting this. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebtables.c | 136 +++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 65 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 4370e9680487..a707dbdc0327 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -959,91 +959,45 @@ static void get_counters(const struct ebt_counter *oldcounters, } } -/* replace the table */ -static int do_replace(struct net *net, const void __user *user, - unsigned int len) +static int do_replace_finish(struct net *net, struct ebt_replace *repl, + struct ebt_table_info *newinfo) { - int ret, i, countersize; - struct ebt_table_info *newinfo; - struct ebt_replace tmp; - struct ebt_table *t; + int ret, i; struct ebt_counter *counterstmp = NULL; /* used to be able to unlock earlier */ struct ebt_table_info *table; - - if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) - return -EFAULT; - - if (len != sizeof(tmp) + tmp.entries_size) { - BUGPRINT("Wrong len argument\n"); - return -EINVAL; - } - - if (tmp.entries_size == 0) { - BUGPRINT("Entries_size never zero\n"); - return -EINVAL; - } - /* overflow check */ - if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS - - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) - return -ENOMEM; - if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) - return -ENOMEM; - - countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; - newinfo = vmalloc(sizeof(*newinfo) + countersize); - if (!newinfo) - return -ENOMEM; - - if (countersize) - memset(newinfo->counters, 0, countersize); - - newinfo->entries = vmalloc(tmp.entries_size); - if (!newinfo->entries) { - ret = -ENOMEM; - goto free_newinfo; - } - if (copy_from_user( - newinfo->entries, tmp.entries, tmp.entries_size) != 0) { - BUGPRINT("Couldn't copy entries from userspace\n"); - ret = -EFAULT; - goto free_entries; - } + struct ebt_table *t; /* the user wants counters back the check on the size is done later, when we have the lock */ - if (tmp.num_counters) { - counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp)); - if (!counterstmp) { - ret = -ENOMEM; - goto free_entries; - } + if (repl->num_counters) { + unsigned long size = repl->num_counters * sizeof(*counterstmp); + counterstmp = vmalloc(size); + if (!counterstmp) + return -ENOMEM; } - else - counterstmp = NULL; - /* this can get initialized by translate_table() */ newinfo->chainstack = NULL; - ret = ebt_verify_pointers(&tmp, newinfo); + ret = ebt_verify_pointers(repl, newinfo); if (ret != 0) goto free_counterstmp; - ret = translate_table(net, tmp.name, newinfo); + ret = translate_table(net, repl->name, newinfo); if (ret != 0) goto free_counterstmp; - t = find_table_lock(net, tmp.name, &ret, &ebt_mutex); + t = find_table_lock(net, repl->name, &ret, &ebt_mutex); if (!t) { ret = -ENOENT; goto free_iterate; } /* the table doesn't like it */ - if (t->check && (ret = t->check(newinfo, tmp.valid_hooks))) + if (t->check && (ret = t->check(newinfo, repl->valid_hooks))) goto free_unlock; - if (tmp.num_counters && tmp.num_counters != t->private->nentries) { + if (repl->num_counters && repl->num_counters != t->private->nentries) { BUGPRINT("Wrong nr. of counters requested\n"); ret = -EINVAL; goto free_unlock; @@ -1059,7 +1013,7 @@ static int do_replace(struct net *net, const void __user *user, module_put(t->me); /* we need an atomic snapshot of the counters */ write_lock_bh(&t->lock); - if (tmp.num_counters) + if (repl->num_counters) get_counters(t->private->counters, counterstmp, t->private->nentries); @@ -1070,10 +1024,9 @@ static int do_replace(struct net *net, const void __user *user, allocation. Only reason why this is done is because this way the lock is held only once, while this doesn't bring the kernel into a dangerous state. */ - if (tmp.num_counters && - copy_to_user(tmp.counters, counterstmp, - tmp.num_counters * sizeof(struct ebt_counter))) { - BUGPRINT("Couldn't copy counters to userspace\n"); + if (repl->num_counters && + copy_to_user(repl->counters, counterstmp, + repl->num_counters * sizeof(struct ebt_counter))) { ret = -EFAULT; } else @@ -1107,6 +1060,59 @@ free_counterstmp: vfree(newinfo->chainstack[i]); vfree(newinfo->chainstack); } + return ret; +} + +/* replace the table */ +static int do_replace(struct net *net, const void __user *user, + unsigned int len) +{ + int ret, countersize; + struct ebt_table_info *newinfo; + struct ebt_replace tmp; + + if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) + return -EFAULT; + + if (len != sizeof(tmp) + tmp.entries_size) { + BUGPRINT("Wrong len argument\n"); + return -EINVAL; + } + + if (tmp.entries_size == 0) { + BUGPRINT("Entries_size never zero\n"); + return -EINVAL; + } + /* overflow check */ + if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / + NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + return -ENOMEM; + + countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; + newinfo = vmalloc(sizeof(*newinfo) + countersize); + if (!newinfo) + return -ENOMEM; + + if (countersize) + memset(newinfo->counters, 0, countersize); + + newinfo->entries = vmalloc(tmp.entries_size); + if (!newinfo->entries) { + ret = -ENOMEM; + goto free_newinfo; + } + if (copy_from_user( + newinfo->entries, tmp.entries, tmp.entries_size) != 0) { + BUGPRINT("Couldn't copy entries from userspace\n"); + ret = -EFAULT; + goto free_entries; + } + + ret = do_replace_finish(net, &tmp, newinfo); + if (ret == 0) + return ret; free_entries: vfree(newinfo->entries); free_newinfo: -- cgit v1.2.3 From 837395aa863142be7c38be0ca780aef21b12b49f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 7 Feb 2010 02:11:34 +0100 Subject: netfilter: ebtables: split copy_everything_to_user into two functions once CONFIG_COMPAT support is added to ebtables, the new copy_counters_to_user function can be called instead of duplicating code. Also remove last use of MEMPRINT, as requested by Bart De Schuymer. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebtables.c | 70 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index a707dbdc0327..46030dc90845 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -33,11 +33,6 @@ #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ "report to author: "format, ## args) /* #define BUGPRINT(format, args...) */ -#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ - ": out of memory: "format, ## args) -/* #define MEMPRINT(format, args...) */ - - /* * Each cpu has its own set of counters, so there is no need for write_lock in @@ -1263,10 +1258,8 @@ static int update_counters(struct net *net, const void __user *user, if (hlp.num_counters == 0) return -EINVAL; - if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { - MEMPRINT("Update_counters && nomemory\n"); + if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) return -ENOMEM; - } t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); if (!t) @@ -1345,14 +1338,46 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) return 0; } +static int copy_counters_to_user(struct ebt_table *t, + const struct ebt_counter *oldcounters, + void __user *user, unsigned int num_counters, + unsigned int nentries) +{ + struct ebt_counter *counterstmp; + int ret = 0; + + /* userspace might not need the counters */ + if (num_counters == 0) + return 0; + + if (num_counters != nentries) { + BUGPRINT("Num_counters wrong\n"); + return -EINVAL; + } + + counterstmp = vmalloc(nentries * sizeof(*counterstmp)); + if (!counterstmp) + return -ENOMEM; + + write_lock_bh(&t->lock); + get_counters(oldcounters, counterstmp, nentries); + write_unlock_bh(&t->lock); + + if (copy_to_user(user, counterstmp, + nentries * sizeof(struct ebt_counter))) + ret = -EFAULT; + vfree(counterstmp); + return ret; +} + /* called with ebt_mutex locked */ static int copy_everything_to_user(struct ebt_table *t, void __user *user, const int *len, int cmd) { struct ebt_replace tmp; - struct ebt_counter *counterstmp; const struct ebt_counter *oldcounters; unsigned int entries_size, nentries; + int ret; char *entries; if (cmd == EBT_SO_GET_ENTRIES) { @@ -1388,29 +1413,10 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, return -EINVAL; } - /* userspace might not need the counters */ - if (tmp.num_counters) { - if (tmp.num_counters != nentries) { - BUGPRINT("Num_counters wrong\n"); - return -EINVAL; - } - counterstmp = vmalloc(nentries * sizeof(*counterstmp)); - if (!counterstmp) { - MEMPRINT("Couldn't copy counters, out of memory\n"); - return -ENOMEM; - } - write_lock_bh(&t->lock); - get_counters(oldcounters, counterstmp, nentries); - write_unlock_bh(&t->lock); - - if (copy_to_user(tmp.counters, counterstmp, - nentries * sizeof(struct ebt_counter))) { - BUGPRINT("Couldn't copy counters to userspace\n"); - vfree(counterstmp); - return -EFAULT; - } - vfree(counterstmp); - } + ret = copy_counters_to_user(t, oldcounters, tmp.counters, + tmp.num_counters, nentries); + if (ret) + return ret; if (copy_to_user(tmp.entries, entries, entries_size)) { BUGPRINT("Couldn't copy entries to userspace\n"); -- cgit v1.2.3 From 49facff9f92508413f3da598f86aaf6c1121ff27 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 7 Feb 2010 02:48:47 +0100 Subject: netfilter: ebtables: split update_counters into two functions allows to call do_update_counters() from upcoming CONFIG_COMPAT code instead of copy&pasting the same code. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebtables.c | 42 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 46030dc90845..76b99d3c1eea 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1242,38 +1242,33 @@ void ebt_unregister_table(struct net *net, struct ebt_table *table) } /* userspace just supplied us with counters */ -static int update_counters(struct net *net, const void __user *user, - unsigned int len) +static int do_update_counters(struct net *net, const char *name, + struct ebt_counter __user *counters, + unsigned int num_counters, + const void __user *user, unsigned int len) { int i, ret; struct ebt_counter *tmp; - struct ebt_replace hlp; struct ebt_table *t; - if (copy_from_user(&hlp, user, sizeof(hlp))) - return -EFAULT; - - if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) - return -EINVAL; - if (hlp.num_counters == 0) + if (num_counters == 0) return -EINVAL; - if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) + tmp = vmalloc(num_counters * sizeof(*tmp)); + if (!tmp) return -ENOMEM; - t = find_table_lock(net, hlp.name, &ret, &ebt_mutex); + t = find_table_lock(net, name, &ret, &ebt_mutex); if (!t) goto free_tmp; - if (hlp.num_counters != t->private->nentries) { + if (num_counters != t->private->nentries) { BUGPRINT("Wrong nr of counters\n"); ret = -EINVAL; goto unlock_mutex; } - if ( copy_from_user(tmp, hlp.counters, - hlp.num_counters * sizeof(struct ebt_counter)) ) { - BUGPRINT("Updata_counters && !cfu\n"); + if (copy_from_user(tmp, counters, num_counters * sizeof(*counters))) { ret = -EFAULT; goto unlock_mutex; } @@ -1282,7 +1277,7 @@ static int update_counters(struct net *net, const void __user *user, write_lock_bh(&t->lock); /* we add to the counters of the first cpu */ - for (i = 0; i < hlp.num_counters; i++) { + for (i = 0; i < num_counters; i++) { t->private->counters[i].pcnt += tmp[i].pcnt; t->private->counters[i].bcnt += tmp[i].bcnt; } @@ -1296,6 +1291,21 @@ free_tmp: return ret; } +static int update_counters(struct net *net, const void __user *user, + unsigned int len) +{ + struct ebt_replace hlp; + + if (copy_from_user(&hlp, user, sizeof(hlp))) + return -EFAULT; + + if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) + return -EINVAL; + + return do_update_counters(net, hlp.name, hlp.counters, + hlp.num_counters, user, len); +} + static inline int ebt_make_matchname(const struct ebt_entry_match *m, const char *base, char __user *ubase) { -- cgit v1.2.3 From 81e675c227ec60a0bdcbb547dc530ebee23ff931 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 5 Jan 2010 16:09:46 +0100 Subject: netfilter: ebtables: add CONFIG_COMPAT support Main code for 32 bit userland ebtables binary with 64 bit kernels support. Tested on x86_64 kernel only, using 64bit ebtables binary for output comparision. At least ebt_mark, m_mark and ebt_limit need CONFIG_COMPAT hooks, too. remaining problem: The ebtables userland makefile has: ifeq ($(shell uname -m),sparc64) CFLAGS+=-DEBT_MIN_ALIGN=8 -DKERNEL_64_USERSPACE_32 endif struct ebt_replace, ebt_entry_match etc. then contain userland-side padding, i.e. even if we are called from a 32 bit userland, the structures may already be in the right format. This problem is addressed in a follow-up patch. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebtables.c | 887 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 886 insertions(+), 1 deletion(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 76b99d3c1eea..fcaefdd6200b 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -51,11 +51,37 @@ static DEFINE_MUTEX(ebt_mutex); +#ifdef CONFIG_COMPAT +static void ebt_standard_compat_from_user(void *dst, const void *src) +{ + int v = *(compat_int_t *)src; + + if (v >= 0) + v += xt_compat_calc_jump(NFPROTO_BRIDGE, v); + memcpy(dst, &v, sizeof(v)); +} + +static int ebt_standard_compat_to_user(void __user *dst, const void *src) +{ + compat_int_t cv = *(int *)src; + + if (cv >= 0) + cv -= xt_compat_calc_jump(NFPROTO_BRIDGE, cv); + return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; +} +#endif + + static struct xt_target ebt_standard_target = { .name = "standard", .revision = 0, .family = NFPROTO_BRIDGE, .targetsize = sizeof(int), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(compat_int_t), + .compat_from_user = ebt_standard_compat_from_user, + .compat_to_user = ebt_standard_compat_to_user, +#endif }; static inline int @@ -1454,7 +1480,7 @@ static int do_ebt_set_ctl(struct sock *sk, break; default: ret = -EINVAL; - } + } return ret; } @@ -1514,15 +1540,874 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) return ret; } +#ifdef CONFIG_COMPAT +/* 32 bit-userspace compatibility definitions. */ +struct compat_ebt_replace { + char name[EBT_TABLE_MAXNAMELEN]; + compat_uint_t valid_hooks; + compat_uint_t nentries; + compat_uint_t entries_size; + /* start of the chains */ + compat_uptr_t hook_entry[NF_BR_NUMHOOKS]; + /* nr of counters userspace expects back */ + compat_uint_t num_counters; + /* where the kernel will put the old counters. */ + compat_uptr_t counters; + compat_uptr_t entries; +}; + +/* struct ebt_entry_match, _target and _watcher have same layout */ +struct compat_ebt_entry_mwt { + union { + char name[EBT_FUNCTION_MAXNAMELEN]; + compat_uptr_t ptr; + } u; + compat_uint_t match_size; + compat_uint_t data[0]; +}; + +/* account for possible padding between match_size and ->data */ +static int ebt_compat_entry_padsize(void) +{ + BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) < + COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt))); + return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) - + COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)); +} + +static int ebt_compat_match_offset(const struct xt_match *match, + unsigned int userlen) +{ + /* + * ebt_among needs special handling. The kernel .matchsize is + * set to -1 at registration time; at runtime an EBT_ALIGN()ed + * value is expected. + * Example: userspace sends 4500, ebt_among.c wants 4504. + */ + if (unlikely(match->matchsize == -1)) + return XT_ALIGN(userlen) - COMPAT_XT_ALIGN(userlen); + return xt_compat_match_offset(match); +} + +static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr, + unsigned int *size) +{ + const struct xt_match *match = m->u.match; + struct compat_ebt_entry_mwt __user *cm = *dstptr; + int off = ebt_compat_match_offset(match, m->match_size); + compat_uint_t msize = m->match_size - off; + + BUG_ON(off >= m->match_size); + + if (copy_to_user(cm->u.name, match->name, + strlen(match->name) + 1) || put_user(msize, &cm->match_size)) + return -EFAULT; + + if (match->compat_to_user) { + if (match->compat_to_user(cm->data, m->data)) + return -EFAULT; + } else if (copy_to_user(cm->data, m->data, msize)) + return -EFAULT; + + *size -= ebt_compat_entry_padsize() + off; + *dstptr = cm->data; + *dstptr += msize; + return 0; +} + +static int compat_target_to_user(struct ebt_entry_target *t, + void __user **dstptr, + unsigned int *size) +{ + const struct xt_target *target = t->u.target; + struct compat_ebt_entry_mwt __user *cm = *dstptr; + int off = xt_compat_target_offset(target); + compat_uint_t tsize = t->target_size - off; + + BUG_ON(off >= t->target_size); + + if (copy_to_user(cm->u.name, target->name, + strlen(target->name) + 1) || put_user(tsize, &cm->match_size)) + return -EFAULT; + + if (target->compat_to_user) { + if (target->compat_to_user(cm->data, t->data)) + return -EFAULT; + } else if (copy_to_user(cm->data, t->data, tsize)) + return -EFAULT; + + *size -= ebt_compat_entry_padsize() + off; + *dstptr = cm->data; + *dstptr += tsize; + return 0; +} + +static int compat_watcher_to_user(struct ebt_entry_watcher *w, + void __user **dstptr, + unsigned int *size) +{ + return compat_target_to_user((struct ebt_entry_target *)w, + dstptr, size); +} + +static int compat_copy_entry_to_user(struct ebt_entry *e, void __user **dstptr, + unsigned int *size) +{ + struct ebt_entry_target *t; + struct ebt_entry __user *ce; + u32 watchers_offset, target_offset, next_offset; + compat_uint_t origsize; + int ret; + + if (e->bitmask == 0) { + if (*size < sizeof(struct ebt_entries)) + return -EINVAL; + if (copy_to_user(*dstptr, e, sizeof(struct ebt_entries))) + return -EFAULT; + + *dstptr += sizeof(struct ebt_entries); + *size -= sizeof(struct ebt_entries); + return 0; + } + + if (*size < sizeof(*ce)) + return -EINVAL; + + ce = (struct ebt_entry __user *)*dstptr; + if (copy_to_user(ce, e, sizeof(*ce))) + return -EFAULT; + + origsize = *size; + *dstptr += sizeof(*ce); + + ret = EBT_MATCH_ITERATE(e, compat_match_to_user, dstptr, size); + if (ret) + return ret; + watchers_offset = e->watchers_offset - (origsize - *size); + + ret = EBT_WATCHER_ITERATE(e, compat_watcher_to_user, dstptr, size); + if (ret) + return ret; + target_offset = e->target_offset - (origsize - *size); + + t = (struct ebt_entry_target *) ((char *) e + e->target_offset); + + ret = compat_target_to_user(t, dstptr, size); + if (ret) + return ret; + next_offset = e->next_offset - (origsize - *size); + + if (put_user(watchers_offset, &ce->watchers_offset) || + put_user(target_offset, &ce->target_offset) || + put_user(next_offset, &ce->next_offset)) + return -EFAULT; + + *size -= sizeof(*ce); + return 0; +} + +static int compat_calc_match(struct ebt_entry_match *m, int *off) +{ + *off += ebt_compat_match_offset(m->u.match, m->match_size); + *off += ebt_compat_entry_padsize(); + return 0; +} + +static int compat_calc_watcher(struct ebt_entry_watcher *w, int *off) +{ + *off += xt_compat_target_offset(w->u.watcher); + *off += ebt_compat_entry_padsize(); + return 0; +} + +static int compat_calc_entry(const struct ebt_entry *e, + const struct ebt_table_info *info, + const void *base, + struct compat_ebt_replace *newinfo) +{ + const struct ebt_entry_target *t; + unsigned int entry_offset; + int off, ret, i; + + if (e->bitmask == 0) + return 0; + + off = 0; + entry_offset = (void *)e - base; + + EBT_MATCH_ITERATE(e, compat_calc_match, &off); + EBT_WATCHER_ITERATE(e, compat_calc_watcher, &off); + + t = (const struct ebt_entry_target *) ((char *) e + e->target_offset); + + off += xt_compat_target_offset(t->u.target); + off += ebt_compat_entry_padsize(); + + newinfo->entries_size -= off; + + ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, off); + if (ret) + return ret; + + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + const void *hookptr = info->hook_entry[i]; + if (info->hook_entry[i] && + (e < (struct ebt_entry *)(base - hookptr))) { + newinfo->hook_entry[i] -= off; + pr_debug("0x%08X -> 0x%08X\n", + newinfo->hook_entry[i] + off, + newinfo->hook_entry[i]); + } + } + + return 0; +} + + +static int compat_table_info(const struct ebt_table_info *info, + struct compat_ebt_replace *newinfo) +{ + unsigned int size = info->entries_size; + const void *entries = info->entries; + + newinfo->entries_size = size; + + return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, + entries, newinfo); +} + +static int compat_copy_everything_to_user(struct ebt_table *t, + void __user *user, int *len, int cmd) +{ + struct compat_ebt_replace repl, tmp; + struct ebt_counter *oldcounters; + struct ebt_table_info tinfo; + int ret; + void __user *pos; + + memset(&tinfo, 0, sizeof(tinfo)); + + if (cmd == EBT_SO_GET_ENTRIES) { + tinfo.entries_size = t->private->entries_size; + tinfo.nentries = t->private->nentries; + tinfo.entries = t->private->entries; + oldcounters = t->private->counters; + } else { + tinfo.entries_size = t->table->entries_size; + tinfo.nentries = t->table->nentries; + tinfo.entries = t->table->entries; + oldcounters = t->table->counters; + } + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + if (tmp.nentries != tinfo.nentries || + (tmp.num_counters && tmp.num_counters != tinfo.nentries)) + return -EINVAL; + + memcpy(&repl, &tmp, sizeof(repl)); + if (cmd == EBT_SO_GET_ENTRIES) + ret = compat_table_info(t->private, &repl); + else + ret = compat_table_info(&tinfo, &repl); + if (ret) + return ret; + + if (*len != sizeof(tmp) + repl.entries_size + + (tmp.num_counters? tinfo.nentries * sizeof(struct ebt_counter): 0)) { + pr_err("wrong size: *len %d, entries_size %u, replsz %d\n", + *len, tinfo.entries_size, repl.entries_size); + return -EINVAL; + } + + /* userspace might not need the counters */ + ret = copy_counters_to_user(t, oldcounters, compat_ptr(tmp.counters), + tmp.num_counters, tinfo.nentries); + if (ret) + return ret; + + pos = compat_ptr(tmp.entries); + return EBT_ENTRY_ITERATE(tinfo.entries, tinfo.entries_size, + compat_copy_entry_to_user, &pos, &tmp.entries_size); +} + +struct ebt_entries_buf_state { + char *buf_kern_start; /* kernel buffer to copy (translated) data to */ + u32 buf_kern_len; /* total size of kernel buffer */ + u32 buf_kern_offset; /* amount of data copied so far */ + u32 buf_user_offset; /* read position in userspace buffer */ +}; + +static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz) +{ + state->buf_kern_offset += sz; + return state->buf_kern_offset >= sz ? 0 : -EINVAL; +} + +static int ebt_buf_add(struct ebt_entries_buf_state *state, + void *data, unsigned int sz) +{ + if (state->buf_kern_start == NULL) + goto count_only; + + BUG_ON(state->buf_kern_offset + sz > state->buf_kern_len); + + memcpy(state->buf_kern_start + state->buf_kern_offset, data, sz); + + count_only: + state->buf_user_offset += sz; + return ebt_buf_count(state, sz); +} + +static int ebt_buf_add_pad(struct ebt_entries_buf_state *state, unsigned int sz) +{ + char *b = state->buf_kern_start; + + BUG_ON(b && state->buf_kern_offset > state->buf_kern_len); + + if (b != NULL && sz > 0) + memset(b + state->buf_kern_offset, 0, sz); + /* do not adjust ->buf_user_offset here, we added kernel-side padding */ + return ebt_buf_count(state, sz); +} + +enum compat_mwt { + EBT_COMPAT_MATCH, + EBT_COMPAT_WATCHER, + EBT_COMPAT_TARGET, +}; + +static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, + enum compat_mwt compat_mwt, + struct ebt_entries_buf_state *state, + const unsigned char *base) +{ + char name[EBT_FUNCTION_MAXNAMELEN]; + struct xt_match *match; + struct xt_target *wt; + void *dst = NULL; + int off, pad = 0, ret = 0; + unsigned int size_kern, entry_offset, match_size = mwt->match_size; + + strlcpy(name, mwt->u.name, sizeof(name)); + + if (state->buf_kern_start) + dst = state->buf_kern_start + state->buf_kern_offset; + + entry_offset = (unsigned char *) mwt - base; + switch (compat_mwt) { + case EBT_COMPAT_MATCH: + match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE, + name, 0), "ebt_%s", name); + if (match == NULL) + return -ENOENT; + if (IS_ERR(match)) + return PTR_ERR(match); + + off = ebt_compat_match_offset(match, match_size); + if (dst) { + if (match->compat_from_user) + match->compat_from_user(dst, mwt->data); + else + memcpy(dst, mwt->data, match_size); + } + + size_kern = match->matchsize; + if (unlikely(size_kern == -1)) + size_kern = match_size; + module_put(match->me); + break; + case EBT_COMPAT_WATCHER: /* fallthrough */ + case EBT_COMPAT_TARGET: + wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE, + name, 0), "ebt_%s", name); + if (wt == NULL) + return -ENOENT; + if (IS_ERR(wt)) + return PTR_ERR(wt); + off = xt_compat_target_offset(wt); + + if (dst) { + if (wt->compat_from_user) + wt->compat_from_user(dst, mwt->data); + else + memcpy(dst, mwt->data, match_size); + } + + size_kern = wt->targetsize; + module_put(wt->me); + break; + } + + if (!dst) { + ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, + off + ebt_compat_entry_padsize()); + if (ret < 0) + return ret; + } + + state->buf_kern_offset += match_size + off; + state->buf_user_offset += match_size; + pad = XT_ALIGN(size_kern) - size_kern; + + if (pad > 0 && dst) { + BUG_ON(state->buf_kern_len <= pad); + BUG_ON(state->buf_kern_offset - (match_size + off) + size_kern > state->buf_kern_len - pad); + memset(dst + size_kern, 0, pad); + } + return off + match_size; +} + +/* + * return size of all matches, watchers or target, including necessary + * alignment and padding. + */ +static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, + unsigned int size_left, enum compat_mwt type, + struct ebt_entries_buf_state *state, const void *base) +{ + int growth = 0; + char *buf; + + if (size_left == 0) + return 0; + + buf = (char *) match32; + + while (size_left >= sizeof(*match32)) { + struct ebt_entry_match *match_kern; + int ret; + + match_kern = (struct ebt_entry_match *) state->buf_kern_start; + if (match_kern) { + char *tmp; + tmp = state->buf_kern_start + state->buf_kern_offset; + match_kern = (struct ebt_entry_match *) tmp; + } + ret = ebt_buf_add(state, buf, sizeof(*match32)); + if (ret < 0) + return ret; + size_left -= sizeof(*match32); + + /* add padding before match->data (if any) */ + ret = ebt_buf_add_pad(state, ebt_compat_entry_padsize()); + if (ret < 0) + return ret; + + if (match32->match_size > size_left) + return -EINVAL; + + size_left -= match32->match_size; + + ret = compat_mtw_from_user(match32, type, state, base); + if (ret < 0) + return ret; + + BUG_ON(ret < match32->match_size); + growth += ret - match32->match_size; + growth += ebt_compat_entry_padsize(); + + buf += sizeof(*match32); + buf += match32->match_size; + + if (match_kern) + match_kern->match_size = ret; + + WARN_ON(type == EBT_COMPAT_TARGET && size_left); + match32 = (struct compat_ebt_entry_mwt *) buf; + } + + return growth; +} + +#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ +({ \ + unsigned int __i; \ + int __ret = 0; \ + struct compat_ebt_entry_mwt *__watcher; \ + \ + for (__i = e->watchers_offset; \ + __i < (e)->target_offset; \ + __i += __watcher->watcher_size + \ + sizeof(struct compat_ebt_entry_mwt)) { \ + __watcher = (void *)(e) + __i; \ + __ret = fn(__watcher , ## args); \ + if (__ret != 0) \ + break; \ + } \ + if (__ret == 0) { \ + if (__i != (e)->target_offset) \ + __ret = -EINVAL; \ + } \ + __ret; \ +}) + +#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ +({ \ + unsigned int __i; \ + int __ret = 0; \ + struct compat_ebt_entry_mwt *__match; \ + \ + for (__i = sizeof(struct ebt_entry); \ + __i < (e)->watchers_offset; \ + __i += __match->match_size + \ + sizeof(struct compat_ebt_entry_mwt)) { \ + __match = (void *)(e) + __i; \ + __ret = fn(__match , ## args); \ + if (__ret != 0) \ + break; \ + } \ + if (__ret == 0) { \ + if (__i != (e)->watchers_offset) \ + __ret = -EINVAL; \ + } \ + __ret; \ +}) + +/* called for all ebt_entry structures. */ +static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, + unsigned int *total, + struct ebt_entries_buf_state *state) +{ + unsigned int i, j, startoff, new_offset = 0; + /* stores match/watchers/targets & offset of next struct ebt_entry: */ + unsigned int offsets[4]; + unsigned int *offsets_update = NULL; + int ret; + char *buf_start; + + if (*total < sizeof(struct ebt_entries)) + return -EINVAL; + + if (!entry->bitmask) { + *total -= sizeof(struct ebt_entries); + return ebt_buf_add(state, entry, sizeof(struct ebt_entries)); + } + if (*total < sizeof(*entry) || entry->next_offset < sizeof(*entry)) + return -EINVAL; + + startoff = state->buf_user_offset; + /* pull in most part of ebt_entry, it does not need to be changed. */ + ret = ebt_buf_add(state, entry, + offsetof(struct ebt_entry, watchers_offset)); + if (ret < 0) + return ret; + + offsets[0] = sizeof(struct ebt_entry); /* matches come first */ + memcpy(&offsets[1], &entry->watchers_offset, + sizeof(offsets) - sizeof(offsets[0])); + + if (state->buf_kern_start) { + buf_start = state->buf_kern_start + state->buf_kern_offset; + offsets_update = (unsigned int *) buf_start; + } + ret = ebt_buf_add(state, &offsets[1], + sizeof(offsets) - sizeof(offsets[0])); + if (ret < 0) + return ret; + buf_start = (char *) entry; + /* + * 0: matches offset, always follows ebt_entry. + * 1: watchers offset, from ebt_entry structure + * 2: target offset, from ebt_entry structure + * 3: next ebt_entry offset, from ebt_entry structure + * + * offsets are relative to beginning of struct ebt_entry (i.e., 0). + */ + for (i = 0, j = 1 ; j < 4 ; j++, i++) { + struct compat_ebt_entry_mwt *match32; + unsigned int size; + char *buf = buf_start; + + buf = buf_start + offsets[i]; + if (offsets[i] > offsets[j]) + return -EINVAL; + + match32 = (struct compat_ebt_entry_mwt *) buf; + size = offsets[j] - offsets[i]; + ret = ebt_size_mwt(match32, size, i, state, base); + if (ret < 0) + return ret; + new_offset += ret; + if (offsets_update && new_offset) { + pr_debug("ebtables: change offset %d to %d\n", + offsets_update[i], offsets[j] + new_offset); + offsets_update[i] = offsets[j] + new_offset; + } + } + + startoff = state->buf_user_offset - startoff; + + BUG_ON(*total < startoff); + *total -= startoff; + return 0; +} + +/* + * repl->entries_size is the size of the ebt_entry blob in userspace. + * It might need more memory when copied to a 64 bit kernel in case + * userspace is 32-bit. So, first task: find out how much memory is needed. + * + * Called before validation is performed. + */ +static int compat_copy_entries(unsigned char *data, unsigned int size_user, + struct ebt_entries_buf_state *state) +{ + unsigned int size_remaining = size_user; + int ret; + + ret = EBT_ENTRY_ITERATE(data, size_user, size_entry_mwt, data, + &size_remaining, state); + if (ret < 0) + return ret; + + WARN_ON(size_remaining); + return state->buf_kern_offset; +} + + +static int compat_copy_ebt_replace_from_user(struct ebt_replace *repl, + void __user *user, unsigned int len) +{ + struct compat_ebt_replace tmp; + int i; + + if (len < sizeof(tmp)) + return -EINVAL; + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + if (len != sizeof(tmp) + tmp.entries_size) + return -EINVAL; + + if (tmp.entries_size == 0) + return -EINVAL; + + if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / + NR_CPUS - SMP_CACHE_BYTES) / sizeof(struct ebt_counter)) + return -ENOMEM; + if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter)) + return -ENOMEM; + + memcpy(repl, &tmp, offsetof(struct ebt_replace, hook_entry)); + + /* starting with hook_entry, 32 vs. 64 bit structures are different */ + for (i = 0; i < NF_BR_NUMHOOKS; i++) + repl->hook_entry[i] = compat_ptr(tmp.hook_entry[i]); + + repl->num_counters = tmp.num_counters; + repl->counters = compat_ptr(tmp.counters); + repl->entries = compat_ptr(tmp.entries); + return 0; +} + +static int compat_do_replace(struct net *net, void __user *user, + unsigned int len) +{ + int ret, i, countersize, size64; + struct ebt_table_info *newinfo; + struct ebt_replace tmp; + struct ebt_entries_buf_state state; + void *entries_tmp; + + ret = compat_copy_ebt_replace_from_user(&tmp, user, len); + if (ret) + return ret; + + countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; + newinfo = vmalloc(sizeof(*newinfo) + countersize); + if (!newinfo) + return -ENOMEM; + + if (countersize) + memset(newinfo->counters, 0, countersize); + + memset(&state, 0, sizeof(state)); + + newinfo->entries = vmalloc(tmp.entries_size); + if (!newinfo->entries) { + ret = -ENOMEM; + goto free_newinfo; + } + if (copy_from_user( + newinfo->entries, tmp.entries, tmp.entries_size) != 0) { + ret = -EFAULT; + goto free_entries; + } + + entries_tmp = newinfo->entries; + + xt_compat_lock(NFPROTO_BRIDGE); + + ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); + if (ret < 0) + goto out_unlock; + + pr_debug("tmp.entries_size %d, kern off %d, user off %d delta %d\n", + tmp.entries_size, state.buf_kern_offset, state.buf_user_offset, + xt_compat_calc_jump(NFPROTO_BRIDGE, tmp.entries_size)); + + size64 = ret; + newinfo->entries = vmalloc(size64); + if (!newinfo->entries) { + vfree(entries_tmp); + ret = -ENOMEM; + goto out_unlock; + } + + memset(&state, 0, sizeof(state)); + state.buf_kern_start = newinfo->entries; + state.buf_kern_len = size64; + + ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); + BUG_ON(ret < 0); /* parses same data again */ + + vfree(entries_tmp); + tmp.entries_size = size64; + + for (i = 0; i < NF_BR_NUMHOOKS; i++) { + char __user *usrptr; + if (tmp.hook_entry[i]) { + unsigned int delta; + usrptr = (char __user *) tmp.hook_entry[i]; + delta = usrptr - tmp.entries; + usrptr += xt_compat_calc_jump(NFPROTO_BRIDGE, delta); + tmp.hook_entry[i] = (struct ebt_entries __user *)usrptr; + } + } + + xt_compat_flush_offsets(NFPROTO_BRIDGE); + xt_compat_unlock(NFPROTO_BRIDGE); + + ret = do_replace_finish(net, &tmp, newinfo); + if (ret == 0) + return ret; +free_entries: + vfree(newinfo->entries); +free_newinfo: + vfree(newinfo); + return ret; +out_unlock: + xt_compat_flush_offsets(NFPROTO_BRIDGE); + xt_compat_unlock(NFPROTO_BRIDGE); + goto free_entries; +} + +static int compat_update_counters(struct net *net, void __user *user, + unsigned int len) +{ + struct compat_ebt_replace hlp; + + if (copy_from_user(&hlp, user, sizeof(hlp))) + return -EFAULT; + + if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) + return -EINVAL; + + return do_update_counters(net, hlp.name, compat_ptr(hlp.counters), + hlp.num_counters, user, len); +} + +static int compat_do_ebt_set_ctl(struct sock *sk, + int cmd, void __user *user, unsigned int len) +{ + int ret; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + switch (cmd) { + case EBT_SO_SET_ENTRIES: + ret = compat_do_replace(sock_net(sk), user, len); + break; + case EBT_SO_SET_COUNTERS: + ret = compat_update_counters(sock_net(sk), user, len); + break; + default: + ret = -EINVAL; + } + return ret; +} + +static int compat_do_ebt_get_ctl(struct sock *sk, int cmd, + void __user *user, int *len) +{ + int ret; + struct compat_ebt_replace tmp; + struct ebt_table *t; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if ((cmd == EBT_SO_GET_INFO || + cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp)) + return -EINVAL; + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + t = find_table_lock(sock_net(sk), tmp.name, &ret, &ebt_mutex); + if (!t) + return ret; + + xt_compat_lock(NFPROTO_BRIDGE); + switch (cmd) { + case EBT_SO_GET_INFO: + tmp.nentries = t->private->nentries; + ret = compat_table_info(t->private, &tmp); + if (ret) + goto out; + tmp.valid_hooks = t->valid_hooks; + + if (copy_to_user(user, &tmp, *len) != 0) { + ret = -EFAULT; + break; + } + ret = 0; + break; + case EBT_SO_GET_INIT_INFO: + tmp.nentries = t->table->nentries; + tmp.entries_size = t->table->entries_size; + tmp.valid_hooks = t->table->valid_hooks; + + if (copy_to_user(user, &tmp, *len) != 0) { + ret = -EFAULT; + break; + } + ret = 0; + break; + case EBT_SO_GET_ENTRIES: + case EBT_SO_GET_INIT_ENTRIES: + ret = compat_copy_everything_to_user(t, user, len, cmd); + break; + default: + ret = -EINVAL; + } + out: + xt_compat_flush_offsets(NFPROTO_BRIDGE); + xt_compat_unlock(NFPROTO_BRIDGE); + mutex_unlock(&ebt_mutex); + return ret; +} +#endif + static struct nf_sockopt_ops ebt_sockopts = { .pf = PF_INET, .set_optmin = EBT_BASE_CTL, .set_optmax = EBT_SO_SET_MAX + 1, .set = do_ebt_set_ctl, +#ifdef CONFIG_COMPAT + .compat_set = compat_do_ebt_set_ctl, +#endif .get_optmin = EBT_BASE_CTL, .get_optmax = EBT_SO_GET_MAX + 1, .get = do_ebt_get_ctl, +#ifdef CONFIG_COMPAT + .compat_get = compat_do_ebt_get_ctl, +#endif .owner = THIS_MODULE, }; -- cgit v1.2.3 From 90b89af7e15143c8ea22f5c8818f5a2eec9e75c1 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 7 Feb 2010 03:19:12 +0100 Subject: netfilter: ebtables: try native set/getsockopt handlers, too ebtables can be compiled to perform userspace-side padding of structures. In that case, all the structures are already in the 'native' format expected by the kernel. This tries to determine what format the userspace program is using. For most set/getsockopts, this can be done by checking the len argument for sizeof(compat_ebt_replace) and re-trying the native handler on error. In case of EBT_SO_GET_ENTRIES, the native handler is tried first, it will error out early when checking the *len argument (the compat version has to defer this check until after iterating over the kernel data set once, to adjust for all the structure size differences). As this would cause error printks, remove those as well, as recommended by Bart de Schuymer. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebtables.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index fcaefdd6200b..dfb58056a89a 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1428,16 +1428,12 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, oldcounters = t->table->counters; } - if (copy_from_user(&tmp, user, sizeof(tmp))) { - BUGPRINT("Cfu didn't work\n"); + if (copy_from_user(&tmp, user, sizeof(tmp))) return -EFAULT; - } if (*len != sizeof(struct ebt_replace) + entries_size + - (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) { - BUGPRINT("Wrong size\n"); + (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) return -EINVAL; - } if (tmp.nentries != nentries) { BUGPRINT("Nentries wrong\n"); @@ -2213,8 +2209,12 @@ static int compat_do_replace(struct net *net, void __user *user, void *entries_tmp; ret = compat_copy_ebt_replace_from_user(&tmp, user, len); - if (ret) + if (ret) { + /* try real handler in case userland supplied needed padding */ + if (ret == -EINVAL && do_replace(net, user, len) == 0) + ret = 0; return ret; + } countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids; newinfo = vmalloc(sizeof(*newinfo) + countersize); @@ -2303,8 +2303,9 @@ static int compat_update_counters(struct net *net, void __user *user, if (copy_from_user(&hlp, user, sizeof(hlp))) return -EFAULT; + /* try real handler in case userland supplied needed padding */ if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter)) - return -EINVAL; + return update_counters(net, user, len); return do_update_counters(net, hlp.name, compat_ptr(hlp.counters), hlp.num_counters, user, len); @@ -2341,9 +2342,10 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd, if (!capable(CAP_NET_ADMIN)) return -EPERM; + /* try real handler in case userland supplied needed padding */ if ((cmd == EBT_SO_GET_INFO || cmd == EBT_SO_GET_INIT_INFO) && *len != sizeof(tmp)) - return -EINVAL; + return do_ebt_get_ctl(sk, cmd, user, len); if (copy_from_user(&tmp, user, sizeof(tmp))) return -EFAULT; @@ -2380,7 +2382,19 @@ static int compat_do_ebt_get_ctl(struct sock *sk, int cmd, break; case EBT_SO_GET_ENTRIES: case EBT_SO_GET_INIT_ENTRIES: - ret = compat_copy_everything_to_user(t, user, len, cmd); + /* + * try real handler first in case of userland-side padding. + * in case we are dealing with an 'ordinary' 32 bit binary + * without 64bit compatibility padding, this will fail right + * after copy_from_user when the *len argument is validated. + * + * the compat_ variant needs to do one pass over the kernel + * data set to adjust for size differences before it the check. + */ + if (copy_everything_to_user(t, user, len, cmd) == 0) + ret = 0; + else + ret = compat_copy_everything_to_user(t, user, len, cmd); break; default: ret = -EINVAL; -- cgit v1.2.3 From 314ddca3b172fdb9c23a25c545505dbde557602e Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 27 Jan 2010 14:38:32 +0100 Subject: netfilter: ebt_limit: add CONFIG_COMPAT support ebt_limit structure is larger on 64 bit systems due to "long" type used in the (kernel-only) data section. Setting .compatsize is enough in this case, these values have no meaning in userspace. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebt_limit.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c index 9dd16e6b10e7..7a8182710eb3 100644 --- a/net/bridge/netfilter/ebt_limit.c +++ b/net/bridge/netfilter/ebt_limit.c @@ -84,6 +84,19 @@ static bool ebt_limit_mt_check(const struct xt_mtchk_param *par) return true; } + +#ifdef CONFIG_COMPAT +/* + * no conversion function needed -- + * only avg/burst have meaningful values in userspace. + */ +struct ebt_compat_limit_info { + compat_uint_t avg, burst; + compat_ulong_t prev; + compat_uint_t credit, credit_cap, cost; +}; +#endif + static struct xt_match ebt_limit_mt_reg __read_mostly = { .name = "limit", .revision = 0, @@ -91,6 +104,9 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = { .match = ebt_limit_mt, .checkentry = ebt_limit_mt_check, .matchsize = sizeof(struct ebt_limit_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct ebt_compat_limit_info), +#endif .me = THIS_MODULE, }; -- cgit v1.2.3 From 6e705f56a181118f6fbd35e6b443eab33df07290 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 27 Jan 2010 14:39:05 +0100 Subject: netfilter: ebtables: mark: add CONFIG_COMPAT support Add the required handlers to convert 32 bit ebtables mark match and match target structs to 64bit layout. Signed-off-by: Florian Westphal --- net/bridge/netfilter/ebt_mark.c | 31 +++++++++++++++++++++++++++++++ net/bridge/netfilter/ebt_mark_m.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c index 153e167374a2..2b5ce533d6b9 100644 --- a/net/bridge/netfilter/ebt_mark.c +++ b/net/bridge/netfilter/ebt_mark.c @@ -52,6 +52,32 @@ static bool ebt_mark_tg_check(const struct xt_tgchk_param *par) return false; return true; } +#ifdef CONFIG_COMPAT +struct compat_ebt_mark_t_info { + compat_ulong_t mark; + compat_uint_t target; +}; + +static void mark_tg_compat_from_user(void *dst, const void *src) +{ + const struct compat_ebt_mark_t_info *user = src; + struct ebt_mark_t_info *kern = dst; + + kern->mark = user->mark; + kern->target = user->target; +} + +static int mark_tg_compat_to_user(void __user *dst, const void *src) +{ + struct compat_ebt_mark_t_info __user *user = dst; + const struct ebt_mark_t_info *kern = src; + + if (put_user(kern->mark, &user->mark) || + put_user(kern->target, &user->target)) + return -EFAULT; + return 0; +} +#endif static struct xt_target ebt_mark_tg_reg __read_mostly = { .name = "mark", @@ -60,6 +86,11 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = { .target = ebt_mark_tg, .checkentry = ebt_mark_tg_check, .targetsize = sizeof(struct ebt_mark_t_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_ebt_mark_t_info), + .compat_from_user = mark_tg_compat_from_user, + .compat_to_user = mark_tg_compat_to_user, +#endif .me = THIS_MODULE, }; diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c index 89abf4030399..8de8c396d913 100644 --- a/net/bridge/netfilter/ebt_mark_m.c +++ b/net/bridge/netfilter/ebt_mark_m.c @@ -35,6 +35,38 @@ static bool ebt_mark_mt_check(const struct xt_mtchk_param *par) return true; } + +#ifdef CONFIG_COMPAT +struct compat_ebt_mark_m_info { + compat_ulong_t mark, mask; + uint8_t invert, bitmask; +}; + +static void mark_mt_compat_from_user(void *dst, const void *src) +{ + const struct compat_ebt_mark_m_info *user = src; + struct ebt_mark_m_info *kern = dst; + + kern->mark = user->mark; + kern->mask = user->mask; + kern->invert = user->invert; + kern->bitmask = user->bitmask; +} + +static int mark_mt_compat_to_user(void __user *dst, const void *src) +{ + struct compat_ebt_mark_m_info __user *user = dst; + const struct ebt_mark_m_info *kern = src; + + if (put_user(kern->mark, &user->mark) || + put_user(kern->mask, &user->mask) || + put_user(kern->invert, &user->invert) || + put_user(kern->bitmask, &user->bitmask)) + return -EFAULT; + return 0; +} +#endif + static struct xt_match ebt_mark_mt_reg __read_mostly = { .name = "mark_m", .revision = 0, @@ -42,6 +74,11 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = { .match = ebt_mark_mt, .checkentry = ebt_mark_mt_check, .matchsize = sizeof(struct ebt_mark_m_info), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_ebt_mark_m_info), + .compat_from_user = mark_mt_compat_from_user, + .compat_to_user = mark_mt_compat_to_user, +#endif .me = THIS_MODULE, }; -- cgit v1.2.3 From 04662360854aefcb6337d93701892ad97411fdd0 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sat, 13 Feb 2010 22:13:06 -0500 Subject: mwl8k: disable softirqs when accessing sta_notify_list Use spin_[un]lock_bh in mwl8k_sta_notify(). The sta_notify handler is required to be atomic, yet it can be called in process context, so make sure one call won't preempt another. Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0cfdb9db66f7..6497c841fb21 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -3784,9 +3784,9 @@ mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, s->cmd = cmd; s->sta = *sta; - spin_lock(&priv->sta_notify_list_lock); + spin_lock_bh(&priv->sta_notify_list_lock); list_add_tail(&s->list, &priv->sta_notify_list); - spin_unlock(&priv->sta_notify_list_lock); + spin_unlock_bh(&priv->sta_notify_list_lock); ieee80211_queue_work(hw, &priv->sta_notify_worker); } -- cgit v1.2.3 From bef5d1c70d132145c0fc75b3586a19841a9a82e4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 16 Feb 2010 11:05:00 +0100 Subject: mac80211: split ieee80211_drop_unencrypted Currently, ieee80211_drop_unencrypted is called from management and data frame context, and the different contexts pass different frames. This could lead to it processing an 802.3 frame as an 802.11 frame when MFP is enabled. Move the MFP part of ieee80211_drop_unencrypted into a new function that is only called for mgmt frames. Cc: Jouni Malinen Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a6080d8d72bb..b5c48de81d8b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1397,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) ieee80211_is_data(fc) && (rx->key || rx->sdata->drop_unencrypted))) return -EACCES; + + return 0; +} + +static int +ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + __le16 fc = hdr->frame_control; + int res; + + res = ieee80211_drop_unencrypted(rx, fc); + if (unlikely(res)) + return res; + if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && rx->key)) @@ -1872,7 +1887,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; - if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) + if (ieee80211_drop_unencrypted_mgmt(rx)) return RX_DROP_UNUSABLE; switch (mgmt->u.action.category) { @@ -2014,14 +2029,13 @@ static ieee80211_rx_result debug_noinline ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) { struct ieee80211_sub_if_data *sdata = rx->sdata; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; ieee80211_rx_result rxs; if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_MONITOR; - if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) - return RX_DROP_MONITOR; + if (ieee80211_drop_unencrypted_mgmt(rx)) + return RX_DROP_UNUSABLE; rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); if (rxs != RX_CONTINUE) -- cgit v1.2.3 From 64b84010f9f85996a219fcc697396e7e11be3459 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 16 Feb 2010 17:56:18 +0200 Subject: ath9k: Use the Beacon TX rate from mac80211 Instead of hardcoding the lowest rate for Beacon frames, use the rate index specified in the mac80211 TX info in AP mode. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index d088ebfe63a6..42171d043c31 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc) * Beacons are always sent out at the lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, - struct ath_buf *bf) + struct ath_buf *bf, int rateidx) { struct sk_buff *skb = bf->bf_mpdu; struct ath_hw *ah = sc->sc_ah; @@ -96,9 +96,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, ds->ds_data = bf->bf_buf_addr; sband = &sc->sbands[common->hw->conf.channel->band]; - rate = sband->bitrates[0].hw_value; + rate = sband->bitrates[rateidx].hw_value; if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - rate |= sband->bitrates[0].hw_value_short; + rate |= sband->bitrates[rateidx].hw_value_short; ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, ATH9K_PKT_TYPE_BEACON, @@ -206,7 +206,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, } } - ath_beacon_setup(sc, avp, bf); + ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); while (skb) { ath_tx_cabq(hw, skb); @@ -237,7 +237,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, bf = avp->av_bcbuf; skb = bf->bf_mpdu; - ath_beacon_setup(sc, avp, bf); + ath_beacon_setup(sc, avp, bf, 0); /* NB: caller is known to have already stopped tx dma */ ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); -- cgit v1.2.3 From c2892f02712e9516d72841d5c019ed6916329794 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 16 Feb 2010 07:57:44 +0000 Subject: gre: fix netns vs proto registration ordering GRE protocol receive hook can be called right after protocol addition is done. If netns stuff is not yet initialized, we're going to oops in net_generic(). This is remotely oopsable if ip_gre is compiled as module and packet comes at unfortunate moment of module loading. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7631b20490f5..a2a5983dbf03 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -1665,14 +1665,15 @@ static int __init ipgre_init(void) printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); - if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) { - printk(KERN_INFO "ipgre init: can't add protocol\n"); - return -EAGAIN; - } - err = register_pernet_device(&ipgre_net_ops); if (err < 0) - goto gen_device_failed; + return err; + + err = inet_add_protocol(&ipgre_protocol, IPPROTO_GRE); + if (err < 0) { + printk(KERN_INFO "ipgre init: can't add protocol\n"); + goto add_proto_failed; + } err = rtnl_link_register(&ipgre_link_ops); if (err < 0) @@ -1688,9 +1689,9 @@ out: tap_ops_failed: rtnl_link_unregister(&ipgre_link_ops); rtnl_link_failed: - unregister_pernet_device(&ipgre_net_ops); -gen_device_failed: inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); +add_proto_failed: + unregister_pernet_device(&ipgre_net_ops); goto out; } @@ -1698,9 +1699,9 @@ static void __exit ipgre_fini(void) { rtnl_link_unregister(&ipgre_tap_ops); rtnl_link_unregister(&ipgre_link_ops); - unregister_pernet_device(&ipgre_net_ops); if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); + unregister_pernet_device(&ipgre_net_ops); } module_init(ipgre_init); -- cgit v1.2.3 From d5aa407f59f5b83d2c50ec88f5bf56d40f1f8978 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 16 Feb 2010 09:05:04 +0000 Subject: tunnels: fix netns vs proto registration ordering Same stuff as in ip_gre patch: receive hook can be called before netns setup is done, oopsing in net_generic(). Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv4/ipip.c | 13 ++++++------ net/ipv6/ip6_tunnel.c | 28 +++++++++++++------------ net/ipv6/sit.c | 13 ++++++------ net/ipv6/xfrm6_tunnel.c | 55 ++++++++++++++++++------------------------------- 4 files changed, 47 insertions(+), 62 deletions(-) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 95db732e542b..2f302d3ac9a3 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -830,15 +830,14 @@ static int __init ipip_init(void) printk(banner); - if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { + err = register_pernet_device(&ipip_net_ops); + if (err < 0) + return err; + err = xfrm4_tunnel_register(&ipip_handler, AF_INET); + if (err < 0) { + unregister_pernet_device(&ipip_net_ops); printk(KERN_INFO "ipip init: can't register tunnel\n"); - return -EAGAIN; } - - err = register_pernet_device(&ipip_net_ops); - if (err) - xfrm4_tunnel_deregister(&ipip_handler, AF_INET); - return err; } diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fbd786981aa9..9b02492d8706 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1461,27 +1461,29 @@ static int __init ip6_tunnel_init(void) { int err; - if (xfrm6_tunnel_register(&ip4ip6_handler, AF_INET)) { + err = register_pernet_device(&ip6_tnl_net_ops); + if (err < 0) + goto out_pernet; + + err = xfrm6_tunnel_register(&ip4ip6_handler, AF_INET); + if (err < 0) { printk(KERN_ERR "ip6_tunnel init: can't register ip4ip6\n"); - err = -EAGAIN; - goto out; + goto out_ip4ip6; } - if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { + err = xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6); + if (err < 0) { printk(KERN_ERR "ip6_tunnel init: can't register ip6ip6\n"); - err = -EAGAIN; - goto unreg_ip4ip6; + goto out_ip6ip6; } - err = register_pernet_device(&ip6_tnl_net_ops); - if (err < 0) - goto err_pernet; return 0; -err_pernet: - xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); -unreg_ip4ip6: + +out_ip6ip6: xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET); -out: +out_ip4ip6: + unregister_pernet_device(&ip6_tnl_net_ops); +out_pernet: return err; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 10207cc8cc0e..52ffd29cb93f 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1227,15 +1227,14 @@ static int __init sit_init(void) printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); - if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) { - printk(KERN_INFO "sit init: Can't add protocol\n"); - return -EAGAIN; - } - err = register_pernet_device(&sit_net_ops); if (err < 0) - xfrm4_tunnel_deregister(&sit_handler, AF_INET6); - + return err; + err = xfrm4_tunnel_register(&sit_handler, AF_INET6); + if (err < 0) { + unregister_pernet_device(&sit_net_ops); + printk(KERN_INFO "sit init: Can't add protocol\n"); + } return err; } diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index d6f9aeec69f7..ddce21e3459b 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -84,23 +84,6 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; } - -static int __init xfrm6_tunnel_spi_init(void) -{ - xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", - sizeof(struct xfrm6_tunnel_spi), - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!xfrm6_tunnel_spi_kmem) - return -ENOMEM; - return 0; -} - -static void xfrm6_tunnel_spi_fini(void) -{ - kmem_cache_destroy(xfrm6_tunnel_spi_kmem); -} - static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) { struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); @@ -375,42 +358,44 @@ static int __init xfrm6_tunnel_init(void) { int rv; + xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi", + sizeof(struct xfrm6_tunnel_spi), + 0, SLAB_HWCACHE_ALIGN, + NULL); + if (!xfrm6_tunnel_spi_kmem) + return -ENOMEM; + rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); + if (rv < 0) + goto out_pernet; rv = xfrm_register_type(&xfrm6_tunnel_type, AF_INET6); if (rv < 0) - goto err; + goto out_type; rv = xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6); if (rv < 0) - goto unreg; + goto out_xfrm6; rv = xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET); if (rv < 0) - goto dereg6; - rv = xfrm6_tunnel_spi_init(); - if (rv < 0) - goto dereg46; - rv = register_pernet_subsys(&xfrm6_tunnel_net_ops); - if (rv < 0) - goto deregspi; + goto out_xfrm46; return 0; -deregspi: - xfrm6_tunnel_spi_fini(); -dereg46: - xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); -dereg6: +out_xfrm46: xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); -unreg: +out_xfrm6: xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); -err: +out_type: + unregister_pernet_subsys(&xfrm6_tunnel_net_ops); +out_pernet: + kmem_cache_destroy(xfrm6_tunnel_spi_kmem); return rv; } static void __exit xfrm6_tunnel_fini(void) { - unregister_pernet_subsys(&xfrm6_tunnel_net_ops); - xfrm6_tunnel_spi_fini(); xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + unregister_pernet_subsys(&xfrm6_tunnel_net_ops); + kmem_cache_destroy(xfrm6_tunnel_spi_kmem); } module_init(xfrm6_tunnel_init); -- cgit v1.2.3 From 496c185c9495629ef1c65387cb2594578393cfe0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 16 Feb 2010 15:16:45 -0800 Subject: atl1c: Add support for Atheros AR8152 and AR8152 AR8151 is a Gigabit Ethernet device. AR8152 devices are Fast Ethernet devices, there are two revisions, a 1.0 and a 2.0 revision. This has been tested against these devices: Driver Model-name vendor:device Type atl1c AR8131 1969:1063 Gigabit Ethernet atl1c AR8132 1969:1062 Fast Ethernet atl1c AR8151(v1.0) 1969:1073 Gigabit Ethernet atl1c AR8152(v1.1) 1969:2060 Fast Ethernet This device has no hardware available yet so it goes untested, but it should work: atl1c AR8152(v2.0) 1969:2062 Fast Ethernet Signed-off-by: Luis R. Rodriguez Signed-off-by: David S. Miller --- drivers/net/atl1c/atl1c.h | 11 +++- drivers/net/atl1c/atl1c_ethtool.c | 2 +- drivers/net/atl1c/atl1c_hw.c | 83 +++++++++++++++++++++++---- drivers/net/atl1c/atl1c_hw.h | 5 ++ drivers/net/atl1c/atl1c_main.c | 115 ++++++++++++++++++++++++++++++++++---- 5 files changed, 191 insertions(+), 25 deletions(-) diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h index efe5435bc3d3..84ae905bf732 100644 --- a/drivers/net/atl1c/atl1c.h +++ b/drivers/net/atl1c/atl1c.h @@ -313,6 +313,9 @@ enum atl1c_rss_type { enum atl1c_nic_type { athr_l1c = 0, athr_l2c = 1, + athr_l2c_b, + athr_l2c_b2, + athr_l1d, }; enum atl1c_trans_queue { @@ -426,8 +429,12 @@ struct atl1c_hw { #define ATL1C_ASPM_L1_SUPPORT 0x0100 #define ATL1C_ASPM_CTRL_MON 0x0200 #define ATL1C_HIB_DISABLE 0x0400 -#define ATL1C_LINK_CAP_1000M 0x0800 -#define ATL1C_FPGA_VERSION 0x8000 +#define ATL1C_APS_MODE_ENABLE 0x0800 +#define ATL1C_LINK_EXT_SYNC 0x1000 +#define ATL1C_CLK_GATING_EN 0x2000 +#define ATL1C_FPGA_VERSION 0x8000 + u16 link_cap_flags; +#define ATL1C_LINK_CAP_1000M 0x0001 u16 cmb_tpd; u16 cmb_rrd; u16 cmb_rx_timer; /* 2us resolution */ diff --git a/drivers/net/atl1c/atl1c_ethtool.c b/drivers/net/atl1c/atl1c_ethtool.c index 9b1e0eaebb5c..61a0f2ff11e9 100644 --- a/drivers/net/atl1c/atl1c_ethtool.c +++ b/drivers/net/atl1c/atl1c_ethtool.c @@ -37,7 +37,7 @@ static int atl1c_get_settings(struct net_device *netdev, SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP); - if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) + if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) ecmd->supported |= SUPPORTED_1000baseT_Full; ecmd->advertising = ADVERTISED_TP; diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c index 3e69b940b8f7..f1389d664a21 100644 --- a/drivers/net/atl1c/atl1c_hw.c +++ b/drivers/net/atl1c/atl1c_hw.c @@ -70,17 +70,39 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) u32 otp_ctrl_data; u32 twsi_ctrl_data; u8 eth_addr[ETH_ALEN]; + u16 phy_data; + bool raise_vol = false; /* init */ addr[0] = addr[1] = 0; AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); if (atl1c_check_eeprom_exist(hw)) { - /* Enable OTP CLK */ - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { - otp_ctrl_data |= OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - AT_WRITE_FLUSH(hw); - msleep(1); + if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c_b) { + /* Enable OTP CLK */ + if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { + otp_ctrl_data |= OTP_CTRL_CLK_EN; + AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); + AT_WRITE_FLUSH(hw); + msleep(1); + } + } + + if (hw->nic_type == athr_l2c_b || + hw->nic_type == athr_l2c_b2 || + hw->nic_type == athr_l1d) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); + if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) + goto out; + phy_data &= 0xFF7F; + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); + + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); + if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) + goto out; + phy_data |= 0x8; + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); + udelay(20); + raise_vol = true; } AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); @@ -96,11 +118,31 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) return -1; } /* Disable OTP_CLK */ - if (otp_ctrl_data & OTP_CTRL_CLK_EN) { - otp_ctrl_data &= ~OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - AT_WRITE_FLUSH(hw); - msleep(1); + if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { + if (otp_ctrl_data & OTP_CTRL_CLK_EN) { + otp_ctrl_data &= ~OTP_CTRL_CLK_EN; + AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); + AT_WRITE_FLUSH(hw); + msleep(1); + } + } + if (raise_vol) { + if (hw->nic_type == athr_l2c_b || + hw->nic_type == athr_l2c_b2 || + hw->nic_type == athr_l1d) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x00); + if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) + goto out; + phy_data |= 0x80; + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); + + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); + if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data)) + goto out; + phy_data &= 0xFFF7; + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); + udelay(20); + } } /* maybe MAC-address is from BIOS */ @@ -114,6 +156,7 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw) return 0; } +out: return -1; } @@ -307,7 +350,7 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw) mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL; - if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) { + if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) { if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half) mii_giga_ctrl_data |= ADVERTISE_1000HALF; if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full) @@ -389,6 +432,7 @@ int atl1c_phy_reset(struct atl1c_hw *hw) { struct atl1c_adapter *adapter = hw->adapter; struct pci_dev *pdev = adapter->pdev; + u16 phy_data; u32 phy_ctrl_data = GPHY_CTRL_DEFAULT; u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN; int err; @@ -404,6 +448,21 @@ int atl1c_phy_reset(struct atl1c_hw *hw) AT_WRITE_FLUSH(hw); msleep(10); + if (hw->nic_type == athr_l2c_b) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x0A); + atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xDFFF); + } + + if (hw->nic_type == athr_l2c_b || + hw->nic_type == athr_l2c_b2 || + hw->nic_type == athr_l1d) { + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x3B); + atl1c_read_phy_reg(hw, MII_DBG_DATA, &phy_data); + atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data & 0xFFF7); + msleep(20); + } + /*Enable PHY LinkChange Interrupt */ err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data); if (err) { diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h index c2c738df5c63..1eeb3ed9f0cb 100644 --- a/drivers/net/atl1c/atl1c_hw.h +++ b/drivers/net/atl1c/atl1c_hw.h @@ -57,6 +57,7 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define REG_LINK_CTRL 0x68 #define LINK_CTRL_L0S_EN 0x01 #define LINK_CTRL_L1_EN 0x02 +#define LINK_CTRL_EXT_SYNC 0x80 #define REG_VPD_CAP 0x6C #define VPD_CAP_ID_MASK 0xff @@ -156,6 +157,8 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define PM_CTRL_PM_REQ_TIMER_SHIFT 20 #define PM_CTRL_LCKDET_TIMER_MASK 0x3F #define PM_CTRL_LCKDET_TIMER_SHIFT 24 +#define PM_CTRL_EN_BUFS_RX_L0S 0x10000000 +#define PM_CTRL_SA_DLY_EN 0x20000000 #define PM_CTRL_MAC_ASPM_CHK 0x40000000 #define PM_CTRL_HOTRST 0x80000000 @@ -314,6 +317,8 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw); #define MAC_CTRL_BC_EN 0x4000000 #define MAC_CTRL_DBG 0x8000000 #define MAC_CTRL_SINGLE_PAUSE_EN 0x10000000 +#define MAC_CTRL_HASH_ALG_CRC32 0x20000000 +#define MAC_CTRL_SPEED_MODE_SW 0x40000000 /* MAC IPG/IFG Control Register */ #define REG_MAC_IPG_IFG 0x1484 diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index d98095df05be..3d4c0a5a77eb 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -21,11 +21,18 @@ #include "atl1c.h" -#define ATL1C_DRV_VERSION "1.0.0.1-NAPI" +#define ATL1C_DRV_VERSION "1.0.0.2-NAPI" char atl1c_driver_name[] = "atl1c"; char atl1c_driver_version[] = ATL1C_DRV_VERSION; #define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 #define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 +#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ +#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ +#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ + +#define L2CB_V10 0xc0 +#define L2CB_V11 0xc1 + /* * atl1c_pci_tbl - PCI Device ID Table * @@ -38,6 +45,9 @@ char atl1c_driver_version[] = ATL1C_DRV_VERSION; static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)}, + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)}, + {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)}, /* required last entry */ { 0 } }; @@ -593,11 +603,18 @@ static void atl1c_set_mac_type(struct atl1c_hw *hw) case PCI_DEVICE_ID_ATTANSIC_L2C: hw->nic_type = athr_l2c; break; - case PCI_DEVICE_ID_ATTANSIC_L1C: hw->nic_type = athr_l1c; break; - + case PCI_DEVICE_ID_ATHEROS_L2C_B: + hw->nic_type = athr_l2c_b; + break; + case PCI_DEVICE_ID_ATHEROS_L2C_B2: + hw->nic_type = athr_l2c_b2; + break; + case PCI_DEVICE_ID_ATHEROS_L1D: + hw->nic_type = athr_l1d; + break; default: break; } @@ -620,10 +637,13 @@ static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT; if (link_ctrl_data & LINK_CTRL_L1_EN) hw->ctrl_flags |= ATL1C_ASPM_L1_SUPPORT; + if (link_ctrl_data & LINK_CTRL_EXT_SYNC) + hw->ctrl_flags |= ATL1C_LINK_EXT_SYNC; - if (hw->nic_type == athr_l1c) { + if (hw->nic_type == athr_l1c || + hw->nic_type == athr_l1d) { hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; - hw->ctrl_flags |= ATL1C_LINK_CAP_1000M; + hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; } return 0; } @@ -1234,21 +1254,92 @@ static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) static void atl1c_set_aspm(struct atl1c_hw *hw, bool linkup) { u32 pm_ctrl_data; + u32 link_ctrl_data; AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - + AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); pm_ctrl_data &= ~PM_CTRL_SERDES_PD_EX_L1; + pm_ctrl_data &= ~(PM_CTRL_L1_ENTRY_TIMER_MASK << PM_CTRL_L1_ENTRY_TIMER_SHIFT); + pm_ctrl_data &= ~(PM_CTRL_LCKDET_TIMER_MASK << + PM_CTRL_LCKDET_TIMER_SHIFT); pm_ctrl_data |= PM_CTRL_MAC_ASPM_CHK; + pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; + pm_ctrl_data |= PM_CTRL_RBER_EN; + pm_ctrl_data |= PM_CTRL_SDES_EN; + + if (hw->nic_type == athr_l2c_b || + hw->nic_type == athr_l1d || + hw->nic_type == athr_l2c_b2) { + link_ctrl_data &= ~LINK_CTRL_EXT_SYNC; + if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) { + if (hw->nic_type == athr_l2c_b && + hw->revision_id == L2CB_V10) + link_ctrl_data |= LINK_CTRL_EXT_SYNC; + } + + AT_WRITE_REG(hw, REG_LINK_CTRL, link_ctrl_data); + + pm_ctrl_data |= PM_CTRL_PCIE_RECV; + pm_ctrl_data |= AT_ASPM_L1_TIMER << PM_CTRL_PM_REQ_TIMER_SHIFT; + pm_ctrl_data &= ~PM_CTRL_EN_BUFS_RX_L0S; + pm_ctrl_data &= ~PM_CTRL_SA_DLY_EN; + pm_ctrl_data &= ~PM_CTRL_HOTRST; + pm_ctrl_data |= 1 << PM_CTRL_L1_ENTRY_TIMER_SHIFT; + pm_ctrl_data |= PM_CTRL_SERDES_PD_EX_L1; + } if (linkup) { - pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; - pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; + pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; + if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) + pm_ctrl_data |= PM_CTRL_ASPM_L1_EN; + if (hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) + pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN; + + if (hw->nic_type == athr_l2c_b || + hw->nic_type == athr_l1d || + hw->nic_type == athr_l2c_b2) { + if (hw->nic_type == athr_l2c_b) + if (!(hw->ctrl_flags & ATL1C_APS_MODE_ENABLE)) + pm_ctrl_data &= PM_CTRL_ASPM_L0S_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_PLL_L1_EN; + pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; + if (hw->adapter->link_speed == SPEED_100 || + hw->adapter->link_speed == SPEED_1000) { + pm_ctrl_data &= + ~(PM_CTRL_L1_ENTRY_TIMER_MASK << + PM_CTRL_L1_ENTRY_TIMER_SHIFT); + if (hw->nic_type == athr_l1d) + pm_ctrl_data |= 0xF << + PM_CTRL_L1_ENTRY_TIMER_SHIFT; + else + pm_ctrl_data |= 7 << + PM_CTRL_L1_ENTRY_TIMER_SHIFT; + } + } else { + pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; + pm_ctrl_data |= PM_CTRL_SERDES_PLL_L1_EN; + pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; + pm_ctrl_data &= ~PM_CTRL_CLK_SWH_L1; + pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; + pm_ctrl_data &= ~PM_CTRL_ASPM_L1_EN; + } + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0x29); + if (hw->adapter->link_speed == SPEED_10) + if (hw->nic_type == athr_l1d) + atl1c_write_phy_reg(hw, MII_DBG_ADDR, 0xB69D); + else + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB6DD); + else if (hw->adapter->link_speed == SPEED_100) + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0xB2DD); + else + atl1c_write_phy_reg(hw, MII_DBG_DATA, 0x96DD); - pm_ctrl_data |= PM_CTRL_SERDES_BUDS_RX_L1_EN; - pm_ctrl_data |= PM_CTRL_SERDES_L1_EN; } else { pm_ctrl_data &= ~PM_CTRL_SERDES_BUDS_RX_L1_EN; pm_ctrl_data &= ~PM_CTRL_SERDES_L1_EN; @@ -1302,6 +1393,10 @@ static void atl1c_setup_mac_ctrl(struct atl1c_adapter *adapter) mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; mac_ctrl_data |= MAC_CTRL_SINGLE_PAUSE_EN; + if (hw->nic_type == athr_l1d || hw->nic_type == athr_l2c_b2) { + mac_ctrl_data |= MAC_CTRL_SPEED_MODE_SW; + mac_ctrl_data |= MAC_CTRL_HASH_ALG_CRC32; + } AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); } -- cgit v1.2.3 From efde73a35c2fc88db26a1583b19e0ab0fdfcd4f8 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 15 Feb 2010 19:42:07 +0000 Subject: bnx2: Check BNX2_FLAG_USING_MSIX flag when setting up MSIX. Checking the flag is more correct than checking bp->irq_nvecs. By accident it is not a problem because we always have more than 1 vectors when using MSIX mode. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c7f5515ddaa4..48bc57803856 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4940,7 +4940,7 @@ bnx2_init_chip(struct bnx2 *bp) BNX2_HC_CONFIG_COLLECT_STATS; } - if (bp->irq_nvecs > 1) { + if (bp->flags & BNX2_FLAG_USING_MSIX) { REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR, BNX2_HC_MSIX_BIT_VECTOR_VAL); -- cgit v1.2.3 From e9f26c49ce790de0064474f97d6402ce1fefac2a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 15 Feb 2010 19:42:08 +0000 Subject: bnx2: Need to call cnic_setup_cnic_irq_info() after MTU change. New status blocks are allocated during MTU change so we need to update this information for the cnic driver. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 48bc57803856..063f28394e3d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7141,6 +7141,13 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) dev_close(bp->dev); return rc; } +#ifdef BCM_CNIC + mutex_lock(&bp->cnic_lock); + /* Let cnic know about the new status block. */ + if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) + bnx2_setup_cnic_irq_info(bp); + mutex_unlock(&bp->cnic_lock); +#endif bnx2_netif_start(bp); } return 0; -- cgit v1.2.3 From 5726026bfffa13e9b1098d7bc177618cbbaa9388 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 15 Feb 2010 19:42:09 +0000 Subject: bnx2: Adjust flow control water marks. The current water marks are too high and can cause unnecessary flow control frames. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- drivers/net/bnx2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 063f28394e3d..dbe487f2915d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1277,7 +1277,7 @@ bnx2_init_rx_context(struct bnx2 *bp, u32 cid) if (lo_water >= bp->rx_ring_size) lo_water = 0; - hi_water = bp->rx_ring_size / 4; + hi_water = min_t(int, bp->rx_ring_size / 4, lo_water + 16); if (hi_water <= lo_water) lo_water = 0; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index b860fbbff355..cd4b0e4637ab 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -349,7 +349,7 @@ struct l2_fhdr { #define BNX2_L2CTX_BD_PRE_READ 0x00000000 #define BNX2_L2CTX_CTX_SIZE 0x00000000 #define BNX2_L2CTX_CTX_TYPE 0x00000000 -#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT 32 +#define BNX2_L2CTX_LO_WATER_MARK_DEFAULT 4 #define BNX2_L2CTX_LO_WATER_MARK_SCALE 4 #define BNX2_L2CTX_LO_WATER_MARK_DIS 0 #define BNX2_L2CTX_HI_WATER_MARK_SHIFT 4 -- cgit v1.2.3 From beb499afe3c9c006bb2d66ceaff0f354d0405ff4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 15 Feb 2010 19:42:10 +0000 Subject: bnx2: Allow user-specified multiple advertisement speed values. Remove unnecessary code that works around older versions of ethtool that can pass down invalid advertisement speed values. This old code prevents the user from specifying multiple advertisement values. The new code uses simple masking to mask out invalid advertisment bits. Reported-by: Vlad Yasevich Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index dbe487f2915d..d1e5e5d9e986 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6751,32 +6751,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_ENABLE) { autoneg |= AUTONEG_SPEED; - cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED; - - /* allow advertising 1 speed */ - if ((cmd->advertising == ADVERTISED_10baseT_Half) || - (cmd->advertising == ADVERTISED_10baseT_Full) || - (cmd->advertising == ADVERTISED_100baseT_Half) || - (cmd->advertising == ADVERTISED_100baseT_Full)) { - - if (cmd->port == PORT_FIBRE) - goto err_out_unlock; - - advertising = cmd->advertising; - - } else if (cmd->advertising == ADVERTISED_2500baseX_Full) { - if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE) || - (cmd->port == PORT_TP)) - goto err_out_unlock; - } else if (cmd->advertising == ADVERTISED_1000baseT_Full) - advertising = cmd->advertising; - else if (cmd->advertising == ADVERTISED_1000baseT_Half) - goto err_out_unlock; - else { - if (cmd->port == PORT_FIBRE) - advertising = ETHTOOL_ALL_FIBRE_SPEED; - else + advertising = cmd->advertising; + if (cmd->port == PORT_TP) { + advertising &= ETHTOOL_ALL_COPPER_SPEED; + if (!advertising) advertising = ETHTOOL_ALL_COPPER_SPEED; + } else { + advertising &= ETHTOOL_ALL_FIBRE_SPEED; + if (!advertising) + advertising = ETHTOOL_ALL_FIBRE_SPEED; } advertising |= ADVERTISED_Autoneg; } -- cgit v1.2.3 From c9885fe5a76dea798543f2938a872bc159e8e69a Mon Sep 17 00:00:00 2001 From: Patrick Rabau Date: Mon, 15 Feb 2010 19:42:11 +0000 Subject: bnx2: Fix bug when saving statistics. This fixes the problem of dropping the carry when adding 2 32-bit values. Switch to use array indexing for better readability. Reported by and fix provided by Patrick Rabau. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d1e5e5d9e986..3fb110edad49 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -6555,16 +6555,16 @@ bnx2_save_stats(struct bnx2 *bp) u32 hi; u64 lo; - hi = *(temp_stats + i) + *(hw_stats + i); - lo = *(temp_stats + i + 1) + *(hw_stats + i + 1); + hi = temp_stats[i] + hw_stats[i]; + lo = (u64) temp_stats[i + 1] + (u64) hw_stats[i + 1]; if (lo > 0xffffffff) hi++; - *(temp_stats + i) = hi; - *(temp_stats + i + 1) = lo & 0xffffffff; + temp_stats[i] = hi; + temp_stats[i + 1] = lo & 0xffffffff; } for ( ; i < sizeof(struct statistics_block) / 4; i++) - *(temp_stats + i) = *(temp_stats + i) + *(hw_stats + i); + temp_stats[i] += hw_stats[i]; } #define GET_64BIT_NET_STATS64(ctr) \ -- cgit v1.2.3 From bec92044b73085ba92aabf973cb5aafc251f3a34 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 16 Feb 2010 15:19:42 -0800 Subject: bnx2: Update firmwares and update version to 2.0.8. - Increase FTQ depth to 256 to ehnabce performance. - Fix RV2P context corruption on 5709 when flow control is enabled. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 14 +- firmware/Makefile | 8 +- firmware/bnx2/bnx2-mips-06-5.0.0.j3.fw.ihex | 5841 ----------------------- firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex | 5908 +++++++++++++++++++++++ firmware/bnx2/bnx2-mips-09-5.0.0.j3.fw.ihex | 6051 ----------------------- firmware/bnx2/bnx2-mips-09-5.0.0.j9.fw.ihex | 6058 ++++++++++++++++++++++++ firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex | 462 ++ firmware/bnx2/bnx2-rv2p-09-5.0.0.j3.fw.ihex | 462 -- firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex | 499 ++ firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw.ihex | 498 -- 10 files changed, 12938 insertions(+), 12863 deletions(-) delete mode 100644 firmware/bnx2/bnx2-mips-06-5.0.0.j3.fw.ihex create mode 100644 firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex delete mode 100644 firmware/bnx2/bnx2-mips-09-5.0.0.j3.fw.ihex create mode 100644 firmware/bnx2/bnx2-mips-09-5.0.0.j9.fw.ihex create mode 100644 firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex delete mode 100644 firmware/bnx2/bnx2-rv2p-09-5.0.0.j3.fw.ihex create mode 100644 firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex delete mode 100644 firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw.ihex diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 3fb110edad49..5f0dda10f20d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1,6 +1,6 @@ /* bnx2.c: Broadcom NX2 network driver. * - * Copyright (c) 2004-2009 Broadcom Corporation + * Copyright (c) 2004-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,13 +58,13 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "2.0.3" -#define DRV_MODULE_RELDATE "Dec 03, 2009" -#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j3.fw" +#define DRV_MODULE_VERSION "2.0.8" +#define DRV_MODULE_RELDATE "Feb 15, 2010" +#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j6.fw" #define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-5.0.0.j3.fw" -#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j3.fw" -#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw" -#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j3.fw" +#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j9.fw" +#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw" +#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j10.fw" #define RUN_AT(x) (jiffies + (x)) diff --git a/firmware/Makefile b/firmware/Makefile index 1c00d05578f7..1c0be73c8082 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -33,10 +33,10 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.2.7.0.fw bnx2x-e1h-5.2.7.0.fw -fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j3.fw \ - bnx2/bnx2-rv2p-09-5.0.0.j3.fw \ - bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw \ - bnx2/bnx2-mips-06-5.0.0.j3.fw \ +fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j9.fw \ + bnx2/bnx2-rv2p-09-5.0.0.j10.fw \ + bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw \ + bnx2/bnx2-mips-06-5.0.0.j6.fw \ bnx2/bnx2-rv2p-06-5.0.0.j3.fw fw-shipped-$(CONFIG_CASSINI) += sun/cassini.bin fw-shipped-$(CONFIG_COMPUTONE) += intelliport2.bin diff --git a/firmware/bnx2/bnx2-mips-06-5.0.0.j3.fw.ihex b/firmware/bnx2/bnx2-mips-06-5.0.0.j3.fw.ihex deleted file mode 100644 index 652e6c8f37e1..000000000000 --- a/firmware/bnx2/bnx2-mips-06-5.0.0.j3.fw.ihex +++ /dev/null @@ -1,5841 +0,0 @@ -:10000000080001100800000000004CC8000000C8F3 -:1000100000000000000000000000000008004CC8C4 -:100020000000001400004D90080000880800000047 -:10003000000058D000004DA408005A400000008481 -:100040000000A674080058D0000001540000A6F873 -:10005000080031D808000000000070F00000A84C33 -:10006000000000000000000000000000080070F028 -:10007000000000240001193C080004880800040066 -:100080000000175C00011960000000000000000083 -:100090000000000000000000000000000000000060 -:1000A000080000A80800000000003B38000130BC38 -:1000B0000000000000000000000000000000000040 -:0800C000000000000000000038 -:0800C8000A00004400000000E2 -:1000D000000000000000000D636F6D352E302E30E3 -:1000E0006A33000005000002000000000000000369 -:1000F00000000014000000320000000300000000B7 -:1001000000000000000000000000000000000000EF -:1001100000000010000001360000EA600000000549 -:1001200000000000000000000000000000000008C7 -:1001300000000000000000000000000000000000BF -:1001400000000000000000000000000000000000AF -:10015000000000000000000000000000000000009F -:10016000000000020000000000000000000000008D -:10017000000000000000000000000000000000007F -:10018000000000000000000000000010000000005F -:10019000000000000000000000000000000000005F -:1001A000000000000000000000000000000000004F -:1001B000000000000000000000000000000000003F -:1001C000000000000000000000000000000000002F -:1001D000000000000000000000000000100000030C -:1001E000000000000000000D0000000D3C020800AF -:1001F00024424D003C03080024634DFCAC40000049 -:100200000043202B1480FFFD244200043C1D080005 -:1002100037BD7FFC03A0F0213C1008002610011020 -:100220003C1C0800279C4D000E000214000000003A -:100230000000000D27BDFFE8AFBF0014AFB00010F5 -:100240009742010830437000240220001062000B26 -:10025000286220011440002F0000102124024000D9 -:1002600010620025000000002402600010620026D9 -:10027000000010210A0000948FBF001427500100D5 -:10028000920200091040001A240300013C020800F9 -:100290008C42002010400016000018210E00052B93 -:1002A00000000000960300083C06080094C64DBEFE -:1002B0008E0400188F8200209605000C00031C009D -:1002C00000661825AC440000AC450004240400017D -:1002D000AC400008AC40000CAC400010AC40001436 -:1002E000AC4000180E000550AC43001C0000182163 -:1002F0000A000093006010210E0003BD0000000002 -:100300000A000093000010210E000F810000000081 -:10031000000010218FBF00148FB0001003E0000810 -:1003200027BD001827BDFFE0AFB00010AFBF001819 -:10033000AFB10014275001009203000B2402001AF1 -:10034000961100081462005B00002821322200018F -:1003500010400008000000008E0200009603001408 -:10036000000211C200021040005A10210A0000DBF6 -:10037000A44300803C0208008C420020104000286A -:10038000000000000E00052B00000000974201084D -:100390009743010C8F8500203042003E3063FFFF01 -:1003A0000002140000431025ACA200008F4201009F -:1003B0003C06080094C64DBEACA20004974301164B -:1003C0009744010E3C02200000031C003084FFFF14 -:1003D00000641825ACA3000800C230259742011024 -:1003E0009743011224040001000214003063FFFF50 -:1003F00000431025ACA2000C974201143042FFFFCD -:10040000ACA200108F420118ACA200149342010B61 -:10041000304200FFACA200180E000550ACA6001C34 -:100420003C0208008C420040244200013C010800CC -:10043000AC2200403C0308008C63004432220002DE -:1004400032240004246300013C010800AC23004472 -:10045000108000180002282B8F4202B804430008C5 -:100460008E0200203C0208008C4200602442000101 -:100470003C010800AC2200600A0000FB24050001DA -:100480009603001600002821AF4202808E0200046D -:10049000A7430284AF4202883C021000AF4202B878 -:1004A0003C0208008C42005C244200013C01080030 -:1004B000AC22005C8FBF00188FB100148FB0001009 -:1004C00000A0102103E0000827BD002027BDFFE0A9 -:1004D000AFB00010AFBF0018AFB10014275001003B -:1004E0009203000B24020003961100081462006DB1 -:1004F000000020213222000110400008000000000E -:100500008E02000096030014000211C20002104087 -:10051000005A10210A000142A44300803C02080056 -:100520008C42002010400025000000000E00052B2A -:1005300000000000974201089743010C8F850020BE -:100540003042003E3063FFFF0002140000431025DC -:10055000ACA200008F4201003C06080094C64DBECC -:10056000ACA20004974301169744010E3C02200000 -:1005700000031C003084FFFF00641825ACA30008B2 -:1005800000C2302597420110974301122404000154 -:10059000000214003063FFFF00431025ACA2000CE2 -:1005A000974201143042FFFFACA20010ACA000142F -:1005B000ACA000180E000550ACA6001C3C020800C0 -:1005C0008C420040244200013C010800AC22004063 -:1005D0003C0208008C420044322300042442000103 -:1005E0003C010800AC2200441060001A32220002D4 -:1005F0008F4202B8044300088E0200203C0208002B -:100600008C420060244200013C010800AC220060E2 -:100610000A0001772404000196030016000020213F -:10062000AF4202808E020004A7430284AF420288D8 -:100630003C021000AF4202B83C0208008C42005C51 -:10064000244200013C010800AC22005C0A00017851 -:100650008FBF001810400013000020218F430104B9 -:100660003C026020AC4300148C420004240301FED1 -:10067000304203FF1443000B000020218F42010091 -:10068000000211C02442FFFC2C420008104000026E -:100690002403000200031F403C026000AC436914C5 -:1006A000000020218FBF00188FB100148FB0001000 -:1006B0000080102103E0000827BD00208F430100C7 -:1006C0002402010050620003000311C20000000D6B -:1006D000000311C200021040005A1021A440008003 -:1006E00003E00008000010219362000003E000080E -:1006F000AF80000003E000080000102103E00008C4 -:1007000000001021240201001482000800000000F3 -:100710003C0208008C4200FC244200013C0108001D -:10072000AC2200FC0A00019F30A200203C0208001D -:100730008C420084244200013C010800AC22008469 -:1007400030A200201040000830A300103C02080036 -:100750008C420108244200013C010800AC2201083F -:1007600003E0000800000000106000080000000026 -:100770003C0208008C420104244200013C010800B4 -:10078000AC22010403E00008000000003C02080065 -:100790008C420100244200013C010800AC2201000F -:1007A00003E000080000000027BDFFE8AFBF001015 -:1007B0002744010094830008306200041040001BAD -:1007C000306600028F4202B804410008240500018F -:1007D0003C0208008C420060244200013C010800F9 -:1007E000AC2200600A0001EB8FBF00108C82002059 -:1007F0009483001600002821AF4202808C820004FE -:10080000A7430284AF4202883C021000AF4202B804 -:100810003C0208008C42005C244200013C010800BC -:10082000AC22005C0A0001EB8FBF001010C0000674 -:10083000006028218F4401000E00018F000000009D -:100840000A0001EA240500018F8200088F43010499 -:1008500050430007000028218F4401000E00018F43 -:10086000000000008F420104AF8200080000282130 -:100870008FBF001000A0102103E0000827BD001862 -:100880003C0208008C420088274301009465000C5C -:10089000244200013C010800AC2200888C6400184E -:1008A0000345102190454000AF4400388C62001C85 -:1008B0002403FFF800052E000043102434420004F6 -:1008C000AF42003C3C020005AF4200300000000097 -:1008D0000000000000000000AF450404000000001C -:1008E00000000000000000003C020006344200014D -:1008F000AF420030000000000000000000000000D7 -:100900008F420000304200101040FFFD0000102117 -:1009100003E000080000000027BDFFE0AFB20018B0 -:100920003C036010AFBF001CAFB10014AFB00010AB -:100930008C6450002402FF7F3C1A80000082202437 -:100940003484380C24020037AC6450003C12080098 -:1009500026524D38AF42000824020C80AF420024DA -:100960003C1B80083C06080024C6062C02401021CF -:100970002404001C2484FFFFAC4600000481FFFD1A -:10098000244200043C0208002442016C3C0108009F -:10099000AC224D403C020800244204043C01080003 -:1009A000AC224D443C020800244207B83C01080038 -:1009B000AC224D883C0208002442025C3C03080043 -:1009C000246306343C040800248406E03C05080047 -:1009D00024A53B503C010800AC224DA03C0208007D -:1009E000244205F43C010800AC264D843C0108007B -:1009F000AC254D943C010800AC234D9C3C01080003 -:100A0000AC244DA43C010800AC224DA83C010800D8 -:100A1000AC234D3C3C010800AC204D483C01080093 -:100A2000AC204D4C3C010800AC204D503C0108006E -:100A3000AC204D543C010800AC204D583C0108004E -:100A4000AC204D5C3C010800AC204D603C0108002E -:100A5000AC244D643C010800AC204D683C0108000A -:100A6000AC204D6C3C010800AC204D703C010800EE -:100A7000AC204D743C010800AC204D783C010800CE -:100A8000AC264D7C3C010800AC264D803C010800A2 -:100A9000AC204D8C3C010800AC254D903C01080079 -:100AA000AC234D980E0006BB000000003C02800005 -:100AB000344200708C420000AF8200143C030800F6 -:100AC0008C6300208F820004104300043C028000ED -:100AD0000E0004F3AF8300043C0280003446007033 -:100AE0003C0308008C6300A03C0208008C4200A478 -:100AF000104300048F8400143C010800AC2300A4C0 -:100B0000A743009E8CCA00003C0308008C6300BC15 -:100B10003C0208008C4200B80144202300641821E4 -:100B2000000040210064202B0048102100441021C7 -:100B30003C010800AC2300BC3C010800AC2200B81A -:100B40008F510000322200071040FFDCAF8A0014F2 -:100B50008CC600003C0508008CA500BC3C040800C5 -:100B60008C8400B800CA302300A628210000102180 -:100B700000A6302B00822021008620213227000190 -:100B80003C010800AC2500BC3C010800AC2400B8C6 -:100B900010E0001F322200028F420100AF4200200D -:100BA0008F420104AF4200A89342010B0E0001885E -:100BB000305000FF2E02001D544000040010108031 -:100BC0000E00018B0A0002C5000000000052102137 -:100BD0008C4200000040F8090000000010400005B1 -:100BE0003C0240008F4301043C026020AC430014EF -:100BF0003C024000AF4201383C0208008C42003405 -:100C0000244200013C010800AC22003432220002E0 -:100C10001040000E322200048F4201400E00018875 -:100C2000AF4200200E00034B000000003C024000D9 -:100C3000AF4201783C0208008C4200382442000197 -:100C40003C010800AC220038322200041040FF981A -:100C50003C0280008F4201800E000188AF420020DC -:100C60008F43018024020F00146200050000000081 -:100C70008F420188A742009C0A0002FA3C02400011 -:100C80009362000024030050304200FF1443000828 -:100C90003C0240000E00032D000000005440000400 -:100CA0003C0240000E000E0D000000003C0240001F -:100CB000AF4201B83C0208008C42003C24420001D3 -:100CC0003C010800AC22003C0A00027A3C02800091 -:100CD0003C0290003442000100822025AF440020F5 -:100CE0008F4200200440FFFE0000000003E00008E7 -:100CF000000000003C0280003442000100822025F8 -:100D000003E00008AF44002027BDFFE0AFB10014AE -:100D1000AFB0001000808821AFBF00180E000302A2 -:100D200030B000FF9362007D022020210202802566 -:100D3000A370007D8F7000743C0280000E00030BD6 -:100D400002028024160000098FBF00188F4201F8AC -:100D50000440FFFE24020002AF5101C0A34201C4BF -:100D60003C021000AF4201F88FBF00188FB1001491 -:100D70008FB0001003E0000827BD002027BDFFE86A -:100D8000AFBF0010974201843042020010400005BE -:100D9000000020210E001042000000000A00034164 -:100DA000240400018F420188044000098FBF001015 -:100DB0008F4201883C03FF00004310243C030400E1 -:100DC00014430003240400019362003E8FBF00100F -:100DD0000080102103E0000827BD00182402000154 -:100DE000A3600022A76200168F4401400A0003108E -:100DF0002405000127BDFFE8AFBF0014AFB000100D -:100E000093620000304400FF3883002038820030B5 -:100E10000003182B0002102B00621824106000033E -:100E200024020050148200628FBF001493420148D4 -:100E3000304200FF2443FFFF2C6200051040005C9D -:100E40008FBF0014000310803C03080024634CC8CB -:100E5000004310218C420000004000080000000008 -:100E60000E0003028F4401408F70000C8F4201443A -:100E70001602000224020001AF62000C0E00030BF8 -:100E80008F4401408F420144145000048FBF00146E -:100E90008FB000100A000FB827BD00188F62000C39 -:100EA0000A0003B300000000976200108F43014462 -:100EB0003042FFFF1462000900000000240200011C -:100EC000A76200108F420140AF4202003C021000B6 -:100ED000AF4202380A0003BA8FBF001497620010B5 -:100EE0000A0003B3000000000E0003028F4401401B -:100EF000976200128F4301443050FFFF1603000237 -:100F000024020001A76200120E00030B8F4401406F -:100F10008F420144160200048FBF00148FB00010EE -:100F20000A00034527BD0018976200120A0003B3A8 -:100F300000000000976200148F4301443042FFFF1D -:100F4000146200068FBF0014240200018FB000104D -:100F5000A76200140A0012E227BD0018976200146D -:100F60000A0003B300000000976200168F4301449B -:100F70003042FFFF14620006240200018FBF0014FC -:100F80008FB00010A76200160A000BAA27BD001838 -:100F900097620016144000068FBF00143C02080040 -:100FA0008C420070244200013C010800AC22007019 -:100FB0008FB0001003E0000827BD001827BDFFE830 -:100FC000AFBF0014AFB000108F500100936200005B -:100FD00093430109304400FF2402001F106200A562 -:100FE0002862002010400018240200382862000AFD -:100FF0001040000C2402000B286200081040002C56 -:1010000000000000046000E528620002144000288F -:1010100024020006106200268FBF00140A0004B7E5 -:101020008FB000101062005E2862000B144000DCDC -:101030008FBF00142402000E106200738FB00010E6 -:101040000A0004B700000000106200C028620039E6 -:101050001040000A2402008024020036106200CAF8 -:1010600028620037104000B424020035106200C12D -:101070008FBF00140A0004B78FB000101062002B5D -:101080002862008110400006240200C824020039B2 -:10109000106200B48FBF00140A0004B78FB00010B4 -:1010A000106200998FBF00140A0004B78FB00010BF -:1010B0003C0208008C420020104000B98FBF001491 -:1010C0000E00052B000000008F4201008F830020DE -:1010D0009745010C97460108AC6200008F4201045D -:1010E0003C04080094844DBE00052C00AC62000452 -:1010F0008F4201180006340000C43025AC6200089D -:101100008F42011C24040001AC62000C9342010ACE -:1011100000A22825AC650010AC600014AC6000187B -:10112000AC66001C0A00048D8FBF00143C0208004E -:101130008C4200201040009A8FBF00140E00052B37 -:1011400000000000974401083C03080094634DBE72 -:101150009745010C000422029746010E8F82002061 -:10116000000426000083202500052C003C0300809D -:1011700000A6282500832025AC400000AC400004D8 -:10118000AC400008AC40000CAC450010AC40001472 -:10119000AC400018AC44001C0A00048C240400017C -:1011A0009742010C144000150000000093620005F6 -:1011B0003042001014400011000000000E00030235 -:1011C0000200202193620005020020213442001019 -:1011D0000E00030BA36200059362000024030020AD -:1011E000304200FF1043006D020020218FBF001429 -:1011F0008FB000100A00105827BD00180000000D25 -:101200000A0004B68FBF00143C0208008C42002084 -:10121000104000638FBF00140E00052B000000007B -:101220008F4201048F8300209744010C3C05080085 -:1012300094A54DBEAC6200009762002C000424000F -:101240003042FFFF008220253C02400E00A22825EC -:10125000AC640004AC600008AC60000CAC60001032 -:10126000AC600014AC600018AC65001C0A00048C73 -:10127000240400010E00030202002021A7600008E0 -:101280000E00030B02002021020020210E0003109B -:10129000240500013C0208008C4200201040004060 -:1012A0008FBF00140E00052B000000009742010CB8 -:1012B0008F8300203C05080094A54DBE0002140059 -:1012C000AC700000AC620004AC6000088F64004C9D -:1012D0003C02401F00A22825AC64000C8F62005025 -:1012E00024040001AC6200108F620054AC62001450 -:1012F000AC600018AC65001C8FBF00148FB00010EC -:101300000A00055027BD0018240200205082002545 -:101310008FB000100E000FA202002021104000200C -:101320008FBF0014020020218FB000100000282180 -:101330000A00031027BD0018020020218FBF0014EF -:101340008FB000100A00061827BD00189745010C41 -:10135000020020218FBF00148FB000100A00063851 -:1013600027BD0018020020218FB000100A00065D82 -:1013700027BD00189345010D020020218FB00010F9 -:101380000A0006A727BD0018020020218FBF001405 -:101390008FB000100A00068327BD00188FBF00140D -:1013A0008FB0001003E0000827BD00188F420278BC -:1013B0000440FFFE2402000234840080AF44024057 -:1013C000A34202443C02100003E00008AF4202784E -:1013D0003C04080094844DCA3C0208008C424DD461 -:1013E0003083FFFF000318C000431021AF42003CD0 -:1013F0003C0208008C424DD0AF4200383C02005005 -:1014000034420008AF42003000000000000000003D -:10141000000000008F420000304200201040FFFD1D -:10142000000000008F4204003C010800AC224DC0C7 -:101430008F4204043C010800AC224DC43C02002051 -:10144000AF420030000000003C02080094424DC84A -:101450003C03080094634DCC3C05080094A54DCE98 -:1014600024840001004310213083FFFF3C01080069 -:10147000A4224DC83C010800A4244DCA14650003F1 -:10148000000000003C010800A4204DCA03E0000851 -:10149000000000003C05000A27BDFFE803452821A5 -:1014A0003C04080024844DB0AFBF00100E0005B509 -:1014B0002406000A3C02080094424DB23C03080096 -:1014C00094634DCE3042000F2442000300431804C1 -:1014D00024027FFF0043102B10400002AF83001C4A -:1014E0000000000D0E0004C2000000003C020800D5 -:1014F00094424DBA8FBF001027BD001803E00008CA -:10150000A74200A23C02000A0342102194430006B5 -:101510003C02080094424DBA3C010800A4234DB699 -:10152000004310238F83001C0002140000021403E8 -:101530000043102B03E000083842000127BDFFE8FC -:10154000AFBF00103C02000A034210219442000683 -:101550003C010800A4224DB60E00050F000000005B -:101560005440FFF93C02000A8FBF001003E000085E -:1015700027BD001827BDFFE8AFBF00100E00050F04 -:101580000000000010400003000000000E00051DD8 -:10159000000000003C0208008C424DC08FBF0010CC -:1015A00027430400AF4200383C0208008C424DC47F -:1015B00027BD0018AF830020AF42003C3C0200056D -:1015C000AF42003003E00008AF8000188F8200189F -:1015D0003C0300060002114000431025AF420030DA -:1015E0000000000000000000000000008F4200002A -:1015F000304200101040FFFD27420400AF8200205F -:1016000003E00008AF8000183C0608008CC64DC4FB -:101610008F8500188F8300203C02080094424DBA49 -:1016200027BDFFE024A5000124630020244200011F -:1016300024C70020AFB10014AFB00010AFBF001836 -:10164000AF850018AF8300203C010800A4224DBAEA -:10165000309000FF3C010800AC274DC404C10008D5 -:101660000000882104E00006000000003C020800A1 -:101670008C424DC0244200013C010800AC224DC008 -:101680003C02080094424DBA3C03080094634DC8E4 -:101690000010202B004310262C420001004410258E -:1016A000144000048F830018240200101462000FFD -:1016B000000000000E000541241100013C03080059 -:1016C00094634DBA3C02080094424DC81462000372 -:1016D000000000000E0004C200000000160000031D -:1016E000000000000E00052B000000003C03080075 -:1016F00094634DBE3C02080094424DBC246300013B -:101700003064FFFF3C010800A4234DBE1482000397 -:10171000000000003C010800A4204DBE120000069D -:10172000000000003C02080094424DBAA74200A20B -:101730000A0005A3022010210E00050F0000000082 -:1017400010400004022010210E00051D00000000C2 -:10175000022010218FBF00188FB100148FB000102D -:1017600003E0000827BD00203084FFFF30A5FFFF05 -:1017700000001821108000070000000030820001E6 -:101780001040000200042042006518210A0005AB49 -:101790000005284003E000080060102110C000068A -:1017A00024C6FFFF8CA2000024A50004AC82000028 -:1017B0000A0005B52484000403E0000800000000CE -:1017C00010A0000824A3FFFFAC860000000000006A -:1017D000000000002402FFFF2463FFFF1462FFFAF1 -:1017E0002484000403E0000800000000240200013B -:1017F000AF62000CA7620010A7620012A76200147B -:1018000003E00008A76200163082007F0342102127 -:101810003C08000E004818213C0208008C420020C1 -:1018200027BDFFD82407FF80AFB3001CAFB200185C -:10183000AFB10014AFB00010AFBF00200080802116 -:1018400030B100FF0087202430D200FF1040002F6D -:1018500000009821AF44002C906200002403005047 -:10186000304200FF1443000E000000003C0208005C -:101870008C4200E00202102100471024AF42002CED -:101880003C0208008C4200E0020210213042007F3E -:101890000342102100481021944200D43053FFFF2E -:1018A0000E00052B000000003C02080094424DBED3 -:1018B0008F8300200011340000C2302500122C005C -:1018C0003C02400000C2302534A50001AC7000008D -:1018D0008FBF0020AC6000048FB20018AC7300080A -:1018E0008FB10014AC60000C8FB3001CAC6500100D -:1018F0008FB00010AC60001424040001AC6000182C -:1019000027BD00280A000550AC66001C8FBF0020D0 -:101910008FB3001C8FB200188FB100148FB000106D -:1019200003E0000827BD00289343010F24020010A4 -:101930001062000E2865001110A00007240200129A -:10194000240200082405003A10620006000030213D -:1019500003E0000800000000240500351462FFFCCD -:10196000000030210A0005D0000000008F42007402 -:1019700024420FA003E00008AF62000C27BDFFE87F -:10198000AFBF00100E000310240500018FBF001030 -:1019900024020001A762001227BD001824020001E2 -:1019A00003E00008A360002227BDFFE0AFB10014F0 -:1019B000AFB00010AFBF001830B1FFFF0E00030240 -:1019C000008080219362003F24030004304200FF26 -:1019D0001443000C02002021122000082402000AF7 -:1019E0000E0005C900000000936200052403FFFEFD -:1019F00000431024A362000524020012A362003FEA -:101A0000020020210E00030BA360008116200003BA -:101A1000020020210E00062D0000000002002021FF -:101A2000322600FF8FBF00188FB100148FB0001056 -:101A3000240500380A0005D027BD002027BDFFE09F -:101A4000AFBF001CAFB20018AFB10014AFB00010B0 -:101A50000E000302008080210E0005C90000000076 -:101A60009362003F24120018305100FF123200032D -:101A70000200202124020012A362003F93620005AD -:101A80002403FFFE004310240E00030BA362000595 -:101A9000020020212405002016320007000030211A -:101AA0008FBF001C8FB200188FB100148FB00010D0 -:101AB0000A00031027BD00208FBF001C8FB2001842 -:101AC0008FB100148FB00010240500390A0005D032 -:101AD00027BD002027BDFFE8AFB00010AFBF001446 -:101AE0009742010C2405003600808021144000102C -:101AF000304600FF0E000302000000002402001226 -:101B0000A362003F93620005344200100E0005C935 -:101B1000A36200050E00030B020020210200202119 -:101B20000E000310240500200A00069C000000009F -:101B30000E0005D0000000000E000302020020216C -:101B4000936200232403FF9F0200202100431024FE -:101B50008FBF00148FB00010A36200230A00030B94 -:101B600027BD001827BDFFE0AFBF0018AFB10014BC -:101B7000AFB0001030B100FF0E00030200808021E2 -:101B8000240200120E0005C9A362003F0E00030BE1 -:101B90000200202102002021022030218FBF0018E6 -:101BA0008FB100148FB00010240500350A0005D055 -:101BB00027BD0020A380002C03E00008A380002D97 -:101BC0008F4202780440FFFE8F820034AF42024011 -:101BD00024020002A34202443C02100003E0000879 -:101BE000AF4202783C0360008C625400304200082F -:101BF0001440FFFD000000008C625408AF82000C0E -:101C000024020052AC605408AC645430AC625434CA -:101C10002402000803E00008AC6254003C026000AB -:101C20008C42540030420008104000053C03600024 -:101C30008C625400304200081440FFFD0000000098 -:101C40008F83000C3C02600003E00008AC435408A2 -:101C500090A3000024020005008040213063003F73 -:101C600000004821146200050000502190A2001CD1 -:101C700094A3001E304900FF306AFFFFAD00000C46 -:101C8000AD000010AD000024950200148D05001C6D -:101C90008D0400183042FFFF00491023000211009C -:101CA000000237C3004038210086202300A2102BF9 -:101CB0000082202300A72823AD05001CAD040018D6 -:101CC000A5090014A5090020A50A001603E00008D4 -:101CD000A50A00228F4201F80440FFFE2402000200 -:101CE000AF4401C0A34201C43C02100003E000085D -:101CF000AF4201F83C0208008C4200B427BDFFE867 -:101D0000AFBF001424420001AFB000103C01080036 -:101D1000AC2200B48F4300243C02001F30AA00FF15 -:101D20003442FF8030D800FF006280240080F82118 -:101D300030EF00FF1158003B01405821240CFF8078 -:101D40003C19000A3163007F000310C000031940F2 -:101D5000006218213C0208008C4200DC256800016A -:101D6000310D007F03E21021004310213043007F3A -:101D700003431821004C102400794821AF4200246D -:101D80008D220024016C1824006C7026AD22000CFA -:101D90008D220024310800FFAD220010952200148E -:101DA000952300208D27001C3042FFFF3063FFFF8A -:101DB0008D2600180043102300021100000227C3E3 -:101DC0000040282100C4302300E2102B00C2302341 -:101DD00000E53823AD27001CAD2600189522002011 -:101DE000A522001495220022154B000AA5220016F8 -:101DF0008D2300248D2200082546000131450080F6 -:101E00001462000430C4007F108F000238AA0080E2 -:101E100000C0502151AF000131C800FF1518FFC9A3 -:101E2000010058218F8400343082007F0342182142 -:101E30003C02000A006218212402FF800082202454 -:101E4000AF440024A06A0079A06A00838C6200502D -:101E50008F840034AC6200708C6500743C027FFF9C -:101E60003442FFFF00A228240E000703AC65007473 -:101E7000AF5000248FBF00148FB0001003E00008A3 -:101E800027BD001827BDFFC0AFBE0038AFB7003474 -:101E9000AFB5002CAFB20020AFB1001CAFB000183E -:101EA000AFBF003CAFB60030AFB40028AFB30024E2 -:101EB0008F4500248F4600288F43002C3C02001FD2 -:101EC0003442FF800062182400C230240080A82120 -:101ED000AFA3001400A2F0240E0006C7AFA60010A6 -:101EE0003C0208008C4200E02410FF80036088213F -:101EF00002A2102100501024AF4200243C0208002E -:101F00008C4200E002A210213042007F03421821DF -:101F10003C02000A00629021924200D29363008446 -:101F2000305700FF306300FF2402000110620034CC -:101F30000360202124020002146200360000000029 -:101F40000E0012AE024028219223008392220083C9 -:101F50003063007F3042007F000210C00003194050 -:101F6000006218213C0208008C4200DC02A2102111 -:101F70000043382100F01024AF4200289225007859 -:101F80009224008330E2007F034218213C02000CBF -:101F900014850007006280212402FFFFA24200F1A5 -:101FA0002402FFFFA64200F20A0007BF2402FFFF3F -:101FB00096020020A24200F196020022A64200F200 -:101FC0008E020024AE4200F492220083A24200F06E -:101FD0008E4200C8AE4200FC8E4200C4AE4200F801 -:101FE0008E220050AE4201008E4200CCAE4201046F -:101FF000922200853042003F0A00081A3442004015 -:102000000E0012D102402821922200850A00081AEF -:102010003042003F936200852403FFDF3042003FDF -:10202000A36200859362008500431024A3620085AB -:102030009363008393620078307400FF304200FFA6 -:1020400010540036240AFF803C0C000C3283007FC1 -:10205000000310C000031940006218213C02080070 -:102060008C4200DC268800013109007F02A2102189 -:102070000043382130E2007F0342182100EA102497 -:10208000AF420028006C80218E020024028A1824AE -:10209000006A5826AE02000C8E020024310800FFB0 -:1020A000AE02001096020014960300208E07001C5A -:1020B0003042FFFF3063FFFF8E06001800431023FD -:1020C00000021100000227C30040282100C4302371 -:1020D00000E2102B00C2302300E53823AE07001CBD -:1020E000AE06001896020020A602001496020022F6 -:1020F000A602001692220079304200FF1054000719 -:102100000000000051370001316800FF9222007882 -:10211000304200FF1448FFCD0100A021922200832D -:10212000A22200798E2200500A00087AAE220070A6 -:10213000A22200858E22004C2405FF80AE42010CB5 -:102140009222008534420020A2220085924200D1D2 -:102150003C0308008C6300DC305400FF3C020800A4 -:102160008C4200E400143140001420C002A3182166 -:1021700000C4202102A21021006438210046102151 -:102180000045182400E52824AF450028AF43002C63 -:102190003042007F924400D030E3007F0342282188 -:1021A000034318213C02000C006280213C02000E17 -:1021B000309600FF00A298211296002A000000002D -:1021C0008E02000C02002021026028211040002510 -:1021D000261000280E0006E2000000009262000DAA -:1021E00026830001307400FF3042007FA262000DA0 -:1021F0002404FF801697FFF0267300203C0208009D -:102200008C4200DC0000A02102A210210044102416 -:10221000AF4200283C0208008C4200E43C03080066 -:102220008C6300DC02A2102100441024AF42002C79 -:102230003C0208008C4200E402A318213063007FB6 -:1022400002A210213042007F0342202103431821C3 -:102250003C02000C006280213C02000E0A00083C97 -:10226000008298218E4200D8AE2200508E4200D8C3 -:10227000AE22007092250083924600D19223008303 -:10228000924400D12402FF8000A228243063007F02 -:10229000308400FF00A628250064182A1060000280 -:1022A00030A500FF38A50080A2250083A225007973 -:1022B0000E0006D5000000009222007E02A0202120 -:1022C000A222007A8E2300743C027FFF3442FFFF7B -:1022D000006218240E000703AE2300748FA20010C2 -:1022E000AF5E00248FBF003CAF4200288FBE003895 -:1022F0008FA200148FB700348FB600308FB5002C3A -:102300008FB400288FB300248FB200208FB1001C3F -:102310008FB0001827BD004003E00008AF42002C3A -:1023200090A2000024420001A0A200003C0308008B -:102330008C6300F4304200FF1443000F0080302112 -:10234000A0A000003C0208008C4200E48F8400340E -:10235000008220213082007F034218213C02000CC1 -:10236000006218212402FF8000822024ACC30000F8 -:1023700003E00008AF4400288C82000024420020C3 -:1023800003E00008AC82000094C200003C08080092 -:10239000950800CA30E7FFFF0080482101021021A4 -:1023A000A4C2000094C200003042FFFF00E2102BE4 -:1023B00054400001A4C7000094A200003C030800A0 -:1023C0008C6300CC24420001A4A2000094A200006F -:1023D0003042FFFF544300078F8600280107102B6F -:1023E000A4A000005440000101003821A4C700004F -:1023F0008F8600288CC4001CAF44003C94A20000CF -:102400008F43003C3042FFFF000210C000621821E1 -:10241000AF43003C8F42003C008220231880000420 -:10242000000000008CC200180A0008DB24420001F2 -:102430008CC20018AF4200383C02005034420010F9 -:10244000AF4200300000000000000000000000006B -:102450008F420000304200201040FFFD00000000CD -:102460008F420404AD2200048F420400AD2200001C -:102470003C020020AF42003003E0000800000000F2 -:1024800027BDFFE0AFB20018AFB10014AFB000102D -:10249000AFBF001C94C2000000C080213C120800A5 -:1024A000965200C624420001A602000096030000D6 -:1024B00094E2000000E03021144300058FB10030A9 -:1024C0000E0008B0024038210A00090D000000008B -:1024D0008C8300048C8200042442004004610007C5 -:1024E000AC8200048C820004044000040000000060 -:1024F0008C82000024420001AC82000096020000A1 -:102500003042FFFF50520001A6000000962200005A -:1025100024420001A62200008F820028962300009A -:1025200094420016144300048FBF001C24020001D3 -:10253000A62200008FBF001C8FB200188FB10014BC -:102540008FB0001003E0000827BD00208F8900280D -:1025500027BDFFE0AFBF00188D22002827480400E8 -:1025600030E700FFAF4200388D22002CAF880030EA -:10257000AF42003C3C020005AF42003000000000CA -:10258000000000000000000000000000000000004B -:10259000000000008C82000C8C82000CAD02000058 -:1025A0008C820010AD0200048C820018AD0200087D -:1025B0008C82001CAD02000C8CA20014AD02001035 -:1025C0008C820020AD02001490820005304200FF92 -:1025D00000021200AD0200188CA20018AD02001C0F -:1025E0008CA2000CAD0200208CA20010AD020024D1 -:1025F0008CA2001CAD0200288CA20020AD02002C91 -:10260000AD060030AD000034978300263402FFFF92 -:1026100014620002006020213404FFFF10E000116A -:10262000AD040038952300369524003624020001BD -:102630003063FFFF000318C2006918219065004055 -:10264000308400070082100400451025A06200407D -:102650008F820028944200563042FFFF0A0009741E -:10266000AD02003C9523003695240036240200017B -:102670003063FFFF000318C2006918219065004015 -:102680003084000700821004000210270045102447 -:10269000A0620040AD00003C00000000000000000F -:1026A000000000003C02000634420040AF4200300F -:1026B0000000000000000000000000008F42000049 -:1026C000304200101040FFFD8F860028AF88003098 -:1026D00024C2005624C7003C24C4002824C500326C -:1026E00024C600360E0008EEAFA200108FBF0018FF -:1026F00003E0000827BD00208F8300243C0608006B -:102700008CC600E88F82003430633FFF00031980DD -:1027100000461021004310212403FF803046007F33 -:1027200000431024AF420028034618213C02000C4D -:102730000062302190C2000D30A500FF000038215A -:1027400034420010A0C2000D8F8900288F8A002417 -:1027500095230036000A138230480003240200014A -:10276000A4C3000E1102000B290200021040000554 -:10277000240200021100000C240300010A0009B821 -:102780000000182111020006000000000A0009B82C -:10279000000018218CC2002C0A0009B82443000153 -:1027A0008CC20014244300018CC200180043102B7B -:1027B00050400009240700012402002714A200034E -:1027C000000000000A0009C4240700019522003E11 -:1027D00024420001A522003E000A13823043000378 -:1027E0002C620002104000090080282114600004BF -:1027F0000000000094C200360A0009D43046FFFFF2 -:102800008CC600380A0009D400802821000030213D -:102810003C04080024844DD80A000921000000006F -:10282000274901008D22000C95230006012020215C -:10283000000216023046003F3063FFFF24020027EB -:1028400000C0282128C7002810C2000EAF83002432 -:1028500010E00008240200312402002110C2000907 -:102860002402002510C200079382002D0A0009F3FC -:102870000000000010C200059382002D0A0009F339 -:10288000000000000A00098C000000000A0006BEDB -:102890000000000095230006912400058D25000C02 -:1028A0008D2600108D2700188D28001C8D290020F2 -:1028B000244200013C010800A4234DDE3C01080035 -:1028C000A0244DDD3C010800AC254DE43C0108008E -:1028D000AC264DE83C010800AC274DF03C01080057 -:1028E000AC284DF43C010800AC294DF803E0000889 -:1028F000A382002D8F87002827BDFFC0AFB300340F -:10290000AFB20030AFB1002CAFB00028AFBF00387D -:102910003C0208008C4200D094E3003030B0FFFF4E -:10292000005010073045FFFF3063FFFF00C09821C3 -:10293000A7A200103C110800963100C614A300069F -:102940003092FFFF8CE2002424420030AF42003C72 -:102950000A000A2C8CE2002094E200323042FFFF91 -:1029600054A2000827A400188CE2002C2442003056 -:10297000AF42003C8CE20028AF4200380A000A3A1D -:102980008F84002827A5001027A6002002203821C8 -:102990000E0008B0A7A000208FA20018244200302B -:1029A000AF4200388FA2001CAF42003C8F84002849 -:1029B0003C020005AF4200309482003427430400FB -:1029C0003042FFFF0202102B14400007AF8300309B -:1029D0009482005494830034020210210043102397 -:1029E0000A000A4E3043FFFF94830054948200345F -:1029F0000223182100501023006218233063FFFFC8 -:102A0000948200163042FFFF1443000300000000D0 -:102A10000A000A5C24030001948200163042FFFF82 -:102A20000043102B104000058F8200309482001666 -:102A3000006210233043FFFF8F820030AC53000050 -:102A4000AC400004AC520008AC43000C3C02000651 -:102A500034420010AF4200300000000000000000CF -:102A6000000000008F420000304200101040FFFDC7 -:102A7000001018C20064182190650040320400075D -:102A8000240200018FBF00388FB300348FB20030B2 -:102A90008FB1002C8FB00028008210040045102553 -:102AA00027BD004003E00008A062004027BDFFA84A -:102AB000AFB60050AFB5004CAFB40048AFB3004460 -:102AC000AFB1003CAFBF0054AFB20040AFB0003870 -:102AD0008C9000003C0208008C4200E88F86003495 -:102AE000960300022413FF8000C2302130633FFFB1 -:102AF0000003198000C3382100F3102490B20000B5 -:102B0000AF42002C9203000230E2007F03423021EA -:102B10003C02000E00C28821306300C02402004045 -:102B20000080A82100A0B021146200260000A0218E -:102B30008E3400388E220018144000022402000156 -:102B4000AE2200189202000D304200201440001501 -:102B50008F8200343C0308008C6300DC001238C014 -:102B6000001231400043102100C7302100463821B7 -:102B700030E300073C02008030E6007800C23025D8 -:102B80000343182100F31024AF4208002463090016 -:102B9000AF4608108E2200188C63000800431021F5 -:102BA000AE2200188E22002C8E2300182442000131 -:102BB0000062182B1060003D000000000A000B109E -:102BC00000000000920300022402FFC00043102412 -:102BD000304200FF1440000524020001AE2200181C -:102BE000962200360A000AF93054FFFF8E220014A4 -:102BF00024420001AE2200189202000000021600DA -:102C000000021603044100290000000096020002A1 -:102C100027A4001000802821A7A200169602000217 -:102C200024070001000030213042FFFFAF82002462 -:102C30000E000921AFA0001C960300023C0408000E -:102C40008C8400E88F82003430633FFF00031980DA -:102C500000441021004310213043007F3C05000C4C -:102C60000053102403431821AF42002800651821A7 -:102C70009062000D001221403042007FA062000DE2 -:102C80003C0308008C6300E48F8200340043102171 -:102C90000044382130E2007F03421021004510211A -:102CA00000F31824AF430028AEA200009222000DCA -:102CB000304200101040001302A020218F83002812 -:102CC0008EA40000028030219462003E2442FFFF67 -:102CD000A462003E948400029625000E3084FFFF1B -:102CE0000E000A0B30A5FFFF8F82002894430034AA -:102CF0009622000E1443000302A0202124020001AA -:102D0000A382002C02C028210E00089600000000BB -:102D10008FBF00548FB600508FB5004C8FB4004861 -:102D20008FB300448FB200408FB1003C8FB00038A9 -:102D300003E0000827BD00588F82002827BDFFD080 -:102D4000AFB40028AFB20020AFBF002CAFB3002457 -:102D5000AFB1001CAFB00018904400D0904300D138 -:102D60000000A021309200FFA3A30010306300FFF9 -:102D70008C5100D88C5300DC1072002B240200010F -:102D80003C0308008C6300E493A400108F8200349D -:102D90002406FF800004214000431021004410213C -:102DA0003043007F00461024AF420028034318211F -:102DB0003C02000C006218218C62000427A400145D -:102DC00027A5001002228021027010230440001564 -:102DD000AFA300149062000D00C21024304200FF27 -:102DE00014400007020088219062000D3442004028 -:102DF0000E000896A062000D0A000B5593A2001069 -:102E00000E000A79241400018F830028AC7000D8CA -:102E100093A20010A06200D193A200101452FFD818 -:102E20000000000024020001168200048FBF002C65 -:102E30000E0006BE000000008FBF002C8FB40028DB -:102E40008FB300248FB200208FB1001C8FB0001808 -:102E500003E0000827BD003027BDFFD8AFB3001C3A -:102E6000AFB20018AFB10014AFB00010AFBF002078 -:102E70000080982100E0802130B1FFFF0E00052B7B -:102E800030D200FF00000000000000000000000041 -:102E90008F820020AC510000AC520004AC530008FB -:102EA000AC40000CAC400010AC400014AC4000182A -:102EB0003C03080094634DBE02038025AC50001C07 -:102EC00000000000000000000000000024040001D9 -:102ED0008FBF00208FB3001C8FB200188FB1001479 -:102EE0008FB000100A00055027BD002827BDFFE85D -:102EF000AFB00010AFBF001430A5FFFF30C600FF19 -:102F00000080802124020C80AF42002400000000D9 -:102F100000000000000000000000000000000000B1 -:102F20000E000B64000000003C040800248400E054 -:102F30008C8200002403FF808FBF00140202102146 -:102F400000431024AF4200248C8200003C03000A9E -:102F5000020280213210007F035010218FB0001038 -:102F60000043102127BD001803E00008AF820028AD -:102F700027BDFFE8AFBF00108F4401403C030800AD -:102F80008C6300E02402FF80AF84003400831821AA -:102F900000621024AF4200243C020008034240219A -:102FA000950500023063007F3C02000A03431821AC -:102FB0000062182130A5FFFF3402FFFF000030211E -:102FC0003C07602010A20006AF8300282402FFFF08 -:102FD000A5020002946500D40E000B8930A5FFFF06 -:102FE0008FBF001024020C8027BD001803E00008EA -:102FF000AF4200243C020008034240219502000237 -:103000003C0A0800954A00C63046FFFF14C000077E -:103010003402FFFF8F8200288F8400343C07602039 -:10302000944500D40A000BF230A5FFFF10C2002423 -:103030008F87002894E2005494E400163045FFFF87 -:1030400000A6102300A6182B3089FFFF1060000493 -:103050003044FFFF00C51023012210233044FFFF3E -:10306000008A102B1040000C012A102324020001BA -:10307000A50200162402FFFFA502000294E500D479 -:103080008F8400340000302130A5FFFF3C07602012 -:103090000A000B89000000000044102A10400008BC -:1030A00000000000950200163042000110400004AC -:1030B000000000009742007E24420014A502001682 -:1030C00003E00008000000008F84002827BDFFE017 -:1030D000AFBF0018948200349483003E1060001A41 -:1030E0003048FFFF9383002C240200011462002764 -:1030F0008FBF00188F820028000818C2310800070F -:10310000006218212447003A244900542444002036 -:10311000244500302446003490620040304200FFD5 -:103120000102100730420001104000168FBF001846 -:103130000E0008EEAFA900108F82002894420034E0 -:103140000A000C0B3048FFFF948300369482003451 -:103150001043000E8FBF001894820036A482003402 -:1031600094820056A48200548C82002CAC820024ED -:1031700094820032A48200309482003CA482003AFF -:103180008FBF00180A000BCB27BD002003E000080A -:1031900027BD002027BDFFE8AFBF00108F4A010008 -:1031A0003C0508008CA500E03C02080090424DE47C -:1031B0003C0C0800958C4DDE01452821304B003F2A -:1031C00030A2007F03424021396900323C02000AEC -:1031D0003963003F2C630001010240212D290001C9 -:1031E0002402FF8000A2282401234825AF8A00344E -:1031F00000801821AF4500240000302100802821E4 -:1032000024070001AF8800283C04080024844DD81E -:10321000AF8C002415200007A380002D240200207D -:103220005562000F006020213402FFFF5582000C20 -:10323000006020212402002015620005000000002B -:103240008C6300142402FFFF1062000700000000DE -:103250000E000921000000000A000C6800000000B8 -:103260000E00098C016028210E000C0000000000F7 -:103270008FBF001024020C8027BD001803E0000857 -:10328000AF4200243C0208008C4200E027BDFFA0B2 -:10329000AFB1003C008210212411FF80AFBE005866 -:1032A000AFB70054AFB20040AFB00038AFBF005C62 -:1032B000AFB60050AFB5004CAFB40048AFB3004458 -:1032C000005110248F4800248F4900288F47002880 -:1032D000AF4200243C0208008C4200E000809021B4 -:1032E00024060006008210213042007F034218218C -:1032F0003C02000A006280213C02001F3442FF8031 -:1033000000E2382427A40010260500F00122F02452 -:103310000102B8240E0005B5AFA700308FA2001837 -:10332000AE0200C48FA2001CAE0200C88FA200240F -:10333000AE0200CC93A40010920300D12402FF80BF -:103340000082102400431025304900FF3083007FA5 -:103350003122007F0062102A10400004000310C0D8 -:1033600001311026304900FF000310C0000319404E -:10337000006218213C0208008C4200DC920400D25A -:10338000024210210043102100511024AF420028B6 -:1033900093A300103063007F000310C000031940A6 -:1033A000006218213C0208008C4200DC024210211D -:1033B000004310213042007F034218213C02000CE0 -:1033C000006240218FA300142402FFFF106200302E -:1033D000309500FF93A2001195030014304400FFC4 -:1033E0003063FFFF0064182B1060000D0000000028 -:1033F000950400148D07001C8D0600183084FFFF13 -:1034000000442023000421000000102100E43821A2 -:1034100000E4202B00C230210A000CE200C430215D -:10342000950400148D07001C8D0600183084FFFFE2 -:1034300000822023000421000000102100801821B8 -:1034400000C2302300E4202B00C4302300E33823E3 -:10345000AD07001CAD06001893A20011A5020014D0 -:1034600097A20012A50200168FA20014AD02001050 -:103470008FA20014AD02000C93A20011A50200203F -:1034800097A20012A50200228FA20014AD02002410 -:103490002406FF80024610243256007FAF420024EB -:1034A000035618213C02000A006280218E02004C63 -:1034B0008FA200203124007F000428C0AE020050FB -:1034C0008FA200200004214000852821AE02007058 -:1034D00093A2001001208821A202008393A2001071 -:1034E000A2020079920200853042003FA2020085CC -:1034F0003C0208008C4200DC0242102100451021F1 -:1035000000461024AF42002C3C0208008C4200E42C -:103510003C0308008C6300DC0242102100441021AF -:1035200000461024AF4200283C0208008C4200E410 -:103530000243182100651821024210210044102185 -:103540003042007F3063007F93A5001003422021AA -:10355000034318213C02000E006240213C02000C93 -:1035600010B1008C008248213233007F16600019B0 -:103570002404FF803C0208008C4200DC024210213F -:1035800000441024AF42002C3C0208008C4200E4AE -:103590003C0308008C6300DC02421021004410242C -:1035A000AF4200283C0208008C4200E4024318218C -:1035B0003063007F024210213042007F034220210D -:1035C000034318213C02000E006240213C02000C23 -:1035D000008248219124000D2414FF800000102156 -:1035E00000942025A124000D9504000295050014E7 -:1035F0008D07001C3084FFFF30A5FFFF8D060018EB -:10360000008520230004210000E4382100C230217D -:1036100000E4202B00C43021AD07001CAD060018CB -:1036200095020002A5020014A50000168D020008F4 -:10363000AD0200108D020008AD02000C95020002E0 -:10364000A5020020A50000228D020008AD02002482 -:103650009122000D3042004010400042262200011D -:103660003C0208008C4200E0A3B300283C10000A92 -:103670000242102100541024AF4200243C020800F2 -:103680008C4200E0A380002C27A4002C02421021D1 -:103690003042007F03421821007018218C6200D84C -:1036A0008D26000427A50028AFA9002C0046102174 -:1036B000AC6200D80E000A79AF83002893A30028DB -:1036C0008F8200280E0006BEA04300D10E000C0021 -:1036D0000000000002541024AF4200243C02080005 -:1036E0008C4200DC00132940001320C000A42021DC -:1036F000024210210044102100541024AF42002C3B -:103700003C0208008C4200E43C0308008C6300DCAF -:10371000035630210242102100451021005410248C -:10372000AF4200283C0208008C4200E4024318210A -:103730000064182102421021004510213042007F10 -:103740003063007F03422021034318213C02000E16 -:10375000006240213C02000C00D080210082482100 -:10376000262200013043007F14750005304400FF1D -:103770002403FF800223102400431026304400FF5E -:1037800093A2001000808821250800281444FF76A9 -:103790002529002093A400108FA300142402FFFF0A -:1037A0001062000A308900FF248200012483000196 -:1037B0003042007F14550005306900FF2403FF806C -:1037C0000083102400431026304900FF9202007845 -:1037D000305300FF11330032012088213C020800E1 -:1037E0008C4200DC3225007F000520C00005294006 -:1037F00000A42021024210212406FF800044102151 -:1038000000461024AF42002C3C0308008C6300DC0F -:103810003C0208008C4200E40243182102421021BD -:103820000045102100641821004610243063007FF9 -:10383000AF420028034318213C02000E00624021E1 -:103840003C0208008C4200E48D06000C010020219F -:1038500002421021004510213042007F034218210E -:103860003C02000C0062482110C0000D01202821FC -:103870000E0006E2000000002402FF80022218244D -:1038800026240001006228263082007F14550002A1 -:10389000308300FF30A300FF1473FFD00060882145 -:1038A0008E0300743C027FFF3442FFFF0062182445 -:1038B000AE0300740E00070302402021AF5700241E -:1038C0008FA20030AF5E00288FBF005C8FBE005813 -:1038D0008FB700548FB600508FB5004C8FB400489E -:1038E0008FB300448FB200408FB1003C8FB00038DE -:1038F00027BD006003E00008AF42002C27BDFFD8C1 -:10390000AFB1001CAFBF0020AFB000182751018835 -:10391000922200032408FF803C03000A3047007F06 -:10392000A3A700108F4601803C0208008C4200E0F3 -:10393000AF86003400C2282100A81024AF42002422 -:103940009224000030A2007F034210210043102186 -:10395000AF8200283084007F2402000214820025F8 -:10396000000719403C0208008C4200E400C210210C -:103970000043282130A2007F0342182100A8102410 -:10398000AF4200283C02000C006218219062000D3A -:10399000AFA3001400481025A062000D8FA30014EF -:1039A0009062000D304200405040006A8FBF0020FE -:1039B0008F860028A380002C27A400148CC200D876 -:1039C0008C63000427A50010004310210E000A7923 -:1039D000ACC200D893A300108F8200280E0006BE50 -:1039E000A04300D10E000C00000000000A000EA34E -:1039F0008FBF00200E0006C700C020210E0006D594 -:103A0000000000003C0200080342802192230001D4 -:103A10009202007B1443004F8FBF002092220000CF -:103A20003044007F24020004108200172882000521 -:103A30001040000624020005240200031082000743 -:103A40008FB1001C0A000EA40000000010820012BA -:103A50008FBF00200A000EA48FB1001C92050083C6 -:103A6000920600788E0700748F84003430A500FF22 -:103A700000073E0230C600FF0E00070B30E7007F54 -:103A80000A000EA38FBF00200E000C6F8F8400343D -:103A90000A000EA38FBF002024020C80AF42002436 -:103AA0009202003E30420040104000200000000022 -:103AB0009202003E000216000002160304410006B6 -:103AC000000000008F8400340E00063824050093A7 -:103AD0000A000EA38FBF00209202003F24030018AB -:103AE000304200FF1443000C8F8400342405003959 -:103AF0000E0005D0000030210E0003028F84003438 -:103B000024020012A202003F0E00030B8F84003437 -:103B10000A000EA38FBF0020240500360E0005D03A -:103B2000000030210A000EA38FBF00200E00030208 -:103B30008F8400349202000534420020A202000566 -:103B40000E00030B8F8400340E0010588F84003455 -:103B50008FBF00208FB1001C8FB0001824020C8092 -:103B600027BD002803E00008AF42002427BDFFE87E -:103B7000AFB00010AFBF00142743010094620008EB -:103B8000000214000002140304410002000080211E -:103B90002410000194620008304200801040001A96 -:103BA00002001021946200083042200010400016EC -:103BB000020010218C6300183C021C2D344219EDC8 -:103BC000240600061062000F3C0760213C0208003A -:103BD0008C4200D4104000078F8200288F83002879 -:103BE000906200623042000F34420040A0620062E6 -:103BF0008F8200288F840034944500D40E000B89F6 -:103C000030A5FFFF020010218FBF00148FB00010FD -:103C100003E0000827BD001827BDFFE0AFB1001486 -:103C2000AFB00010A380002CAFBF00188F4501007B -:103C30003C0308008C6300E02402FF80AF85003461 -:103C400000A318213064007F03442021006218245F -:103C50003C02000A00822021AF43002427500100CB -:103C60008E0200148C8300DCAF84002800431023F4 -:103C700018400004000088218E0200140E000B1C66 -:103C8000AC8200DC9202000B24030002304200FFF1 -:103C90001443002F0000000096020008304300FF8C -:103CA0002402008214620005240200840E0009D65A -:103CB000000000000A000F2F00000000146200093D -:103CC000240200818F8200288F8400343C07602109 -:103CD000944500D49206000530A5FFFF0A000F1E90 -:103CE00030C600FF14620027000000009202000AA4 -:103CF000304300FF3062002010400004306200407A -:103D00008F8400340A000F1A24060040104000047B -:103D1000000316008F8400340A000F1A24060041A5 -:103D200000021603044100178F8400342406004269 -:103D30008F8200283C076019944500D430A5FFFF0E -:103D40000E000B89000000000A000F2F0000000089 -:103D50009202000B24030016304200FF10430006BD -:103D6000000000009202000B24030017304200FF05 -:103D700014430004000000000E000EA90000000023 -:103D8000004088210E000C00000000009202000A92 -:103D9000304200081040000624020C808F85002865 -:103DA0003C0400080E0012860344202124020C80EB -:103DB000AF4200248FBF0018022010218FB00010E6 -:103DC0008FB1001403E0000827BD002027BDFFE8E5 -:103DD000AFBF0014AFB000108F5000243C030800A8 -:103DE0008C6300E08F4501002402FF8000A31821AE -:103DF0003064007F03442021006218243C02000A42 -:103E000000822021AF850034AF43002490820062FD -:103E1000AF8400283042000F34420050A08200627C -:103E20003C02001F3442FF800E0006BE02028024C6 -:103E3000AF5000248FBF00148FB0001003E00008C3 -:103E400027BD00183C0208008C4200201040001DD5 -:103E50002745010090A300093C02000803422021ED -:103E600024020018546200033C0200080A000F708C -:103E700024020008034220212402001614620005D7 -:103E80002402001724020012A082003F0A000F7AC9 -:103E900094A700085462000694A7000893620005E6 -:103EA0002403FFFE00431024A362000594A700082A -:103EB00090A6001B8CA4000094A500060A000B64C9 -:103EC00000073C0003E00008000000002744010058 -:103ED00094820008304500FF38A3008238A2008495 -:103EE0002C6300012C4200010062182510600006BE -:103EF000240200839382002D1040000D000000007A -:103F00000A000C330000000014A2000524A2FF8068 -:103F10008F4301043C02602003E00008AC4300141E -:103F2000304200FF2C420002104000032402002215 -:103F30000A000ED40000000014A2000300000000DC -:103F40000A000F41000000000A000F5F000000009F -:103F50009363007E9362007A1443000900002021DD -:103F60009362000024030050304200FF1443000419 -:103F7000240400019362007E24420001A362007EBB -:103F800003E00008008010218F4201F80440FFFE8A -:103F900024020002AF4401C0A34201C43C0210004D -:103FA00003E00008AF4201F827BDFFE8AFBF0010F3 -:103FB0009362003F2403000A304200FF144300468E -:103FC000000000008F6300548F62004C1062007D7F -:103FD000036030219362000024030050304200FF50 -:103FE0001443002F000000008F4401403C020800F1 -:103FF0008C4200E02403FF80008210210043102443 -:10400000AF4200243C0208008C4200E08F6500545F -:104010003C03000A008220213084007F03441021E9 -:1040200000431021AC4501089762003C8F63004CAF -:104030003042FFFF0002104000621821AF63005CB5 -:104040008F6300548F64004C9762003C0064182317 -:104050003042FFFF00031843000210400043102AC3 -:1040600010400006000000008F6200548F63004C77 -:10407000004310230A000FF0000210439762003C37 -:104080003042FFFF00021040ACC200642402000175 -:10409000A0C0007CA0C2008424020C80AF42002497 -:1040A0000E000FA28F440140104000478FBF001048 -:1040B0008F4301408F4201F80440FFFE24020002BA -:1040C000AF4301C0A34201C43C021000AF4201F85B -:1040D0000A0010408FBF00109362003F24030010BD -:1040E000304200FF14430004000000008F440140F0 -:1040F0000A00102C000028219362003F24030016C0 -:10410000304200FF1443000424020014A362003F65 -:104110000A00103A000000008F62004C8F630050CC -:1041200000431023044100288FBF001093620081D8 -:1041300024420001A3620081936200812C420004AA -:1041400014400010000000009362003F24030004AC -:10415000304200FF14430006000000008F4401407D -:104160008FBF0010240500930A00063827BD0018F1 -:104170008F440140240500938FBF00100A0006A75A -:1041800027BD00188F4401400E000302000000000C -:104190008F6200542442FFFFAF6200548F620050D0 -:1041A0002442FFFFAF6200500E00030B8F4401401A -:1041B0008F4401408FBF0010240500040A00031043 -:1041C00027BD00188FBF001003E0000827BD0018AE -:1041D0008F4201889363007E00021402304400FF86 -:1041E000306300FF1464000D000000009362008043 -:1041F000304200FF1044000900000000A36400806A -:104200009362000024030050304200FF1443000476 -:10421000000000000A00076F8F440180A364008043 -:1042200003E000080000000027BDFFE8AFB0001069 -:10423000AFBF001493620005240300303042003009 -:1042400014430089008080213C0208008C42002039 -:1042500010400080020020210E00052B000000000D -:104260008F850020ACB000009362003E9363003F56 -:10427000304200FF00021200306300FF00431025AF -:10428000ACA2000493620082000216000002160332 -:1042900004410005000000003C0308008C63004856 -:1042A0000A00107E000000009362003E3042004091 -:1042B000144000030000182193620081304300FF86 -:1042C0009362008200031E00304200FF00021400CF -:1042D00000621825ACA300088F620040ACA2000C5D -:1042E0008F620048ACA200108F62004CACA2001498 -:1042F0008F6200508F63004C004310230441000381 -:10430000000000000A0010928F62004C8F62005083 -:10431000ACA200183C02080094424DBE3C03C00B06 -:1043200000002021004310250E000550ACA2001C07 -:104330008F6200548F840020AC8200008F6200588E -:10434000AC8200048F62005CAC8200088F62006067 -:104350008F43007400431021AC82000C8F62006414 -:10436000AC820010976300689762006A00031C002B -:104370003042FFFF00621825AC8300149362008274 -:1043800024030080304200FF1443000300000000BB -:104390000A0010C6AC8000188F63000C24020001D4 -:1043A0001062000E2402FFFF9362003E3042004084 -:1043B0001440000A2402FFFF8F63000C8F42007438 -:1043C000006218233C02080000621024144000021E -:1043D000000028210060282100051043AC8200184D -:1043E0003C02080094424DBE3C03C00C000020215A -:1043F000004310258F8300200E000550AC62001C86 -:104400008F6200188F8300203C05080094A54DBEE4 -:1044100024040001AC620000AC6000048F66006CF4 -:104420003C02400D00A22825AC6600088F6200DC2B -:10443000AC62000CAC600010936200050002160034 -:10444000AC620014AC6000180E000550AC65001C96 -:10445000020020218FBF00148FB00010A360000560 -:104460000A0004B927BD00188FBF00148FB00010D8 -:1044700003E0000827BD00189742007C30C600FF0B -:10448000A08600843047FFFF2402000514C2000B01 -:1044900024E3465090A201122C420007104000076E -:1044A00024E30A0090A30112240200140062100405 -:1044B00000E210210A0010FE3047FFFF3067FFFFC7 -:1044C00003E00008A4870014AC87004C8CA201080C -:1044D0000080402100A0482100E2102330C600FFE8 -:1044E0001840000393AA001324E2FFFCACA20108C9 -:1044F00030C2000110400008000000008D02005092 -:1045000000E2102304410013240600058D0200542C -:1045100010E20010000000008D02005414E2001AA6 -:10452000000000003C0208008C4200D8304200200D -:104530001040000A240200019103007891020083D8 -:10454000144300062402000101002021012028213B -:10455000240600040A0010EC00000000A100008402 -:1045600011400009A50200148F4301008F4201F899 -:104570000440FFFE24020002AF4301C0A34201C475 -:104580003C021000AF4201F803E000080000000008 -:1045900027BDFFE88FA90028AFBF00100080402191 -:1045A00000E918231860007330C600FFA080007C6B -:1045B000A08000818CA2010800E210230440004D7D -:1045C000000000008C8200509483003C8C840064C6 -:1045D000004748233063FFFF012318210083202B6D -:1045E00010800004000000008D0200640A00114FDA -:1045F00000E210219502003C3042FFFF0122102111 -:1046000000E21021AD02005C9502003C8D03005CCD -:104610003042FFFF0002104000E210210043102B47 -:1046200010400003000000000A00115E8D02005CD3 -:104630009502003C3042FFFF0002104000E21021D2 -:10464000AD02005CA1000084AD07004C8CA2010803 -:1046500000E210231840000224E2FFFCACA2010893 -:1046600030C200011040000A000000008D0200501E -:1046700000E2102304410004010020218D020054B7 -:1046800014E20003000000000A0011802406000567 -:104690008D02005414E200478FBF00103C02080056 -:1046A0008C4200D8304200201040000A2402000151 -:1046B0009103007891020083144300062402000154 -:1046C00001002021240600048FBF00100A0010EC16 -:1046D00027BD0018A1000084A50200148F4301002B -:1046E0008F4201F80440FFFE240200020A0011A5D7 -:1046F000000000008C82005C004910230043102B56 -:1047000054400001AC87005C9502003C3042FFFF42 -:104710000062102B14400007240200029502003CA6 -:104720008D03005C3042FFFF00621821AD03005C86 -:1047300024020002AD07004CA10200840E000FA26B -:104740008F4401001040001B8FBF00108F430100F9 -:104750008F4201F80440FFFE24020002AF4301C073 -:10476000A34201C43C021000AF4201F80A0011BB91 -:104770008FBF001030C200101040000E8FBF00101D -:104780008C83005C9482003C006918233042FFFF58 -:10479000006218213C023FFF3444FFFF0083102BCE -:1047A000544000010080182101231021AD02005C5B -:1047B0008FBF001003E0000827BD001827BDFFE8E9 -:1047C0008FAA0028AFBF00100080402100EA4823D4 -:1047D0001920002130C600FF8C83005C8C820064AD -:1047E000006A18230043102B504000100069182164 -:1047F00094A2011001221021A4A2011094A2011080 -:104800003042FFFF0043102B1440000A3C023FFFE0 -:1048100094A2011000431023A4A201109482003C32 -:104820003042FFFF0A0011DA00621821A4A0011033 -:104830003C023FFF3444FFFF0083102B5440000133 -:104840000080182100671021AD02005CA100007CEF -:104850000A001222A100008130C200101040003C6A -:10486000000000008C820050004A102318400038DD -:10487000000000009082007C24420001A082007CA5 -:104880009082007C3C0308008C630024304200FFCF -:104890000043102B1440005C8FBF00108CA2010855 -:1048A00000E2102318400058000000008C830054E0 -:1048B0009482003C006A18233042FFFF0003184333 -:1048C000000210400043102A1040000500000000C4 -:1048D0008C820054004A10230A001209000210437F -:1048E0009482003C3042FFFF00021040AD020064A1 -:1048F0009502003C8D0400649503003C3042FFFFAC -:1049000000021040008220213063FFFF0083182145 -:1049100001431021AD02005C8D020054ACA20108DD -:1049200024020002A10200840E000FA28F440100A5 -:10493000104000358FBF00108F4301008F4201F8F7 -:104940000440FFFE240200020A00124B0000000097 -:10495000AD07004C8CA2010800E2102318400002B1 -:1049600024E2FFFCACA2010830C200011040000AA2 -:10497000000000008D02005000E2102304410004FA -:10498000010020218D02005414E200030000000009 -:104990000A001242240600058D02005414E2001A97 -:1049A0008FBF00103C0208008C4200D8304200202B -:1049B0001040000A24020001910300789102008354 -:1049C00014430006240200010100202124060004F3 -:1049D0008FBF00100A0010EC27BD0018A100008452 -:1049E000A50200148F4301008F4201F80440FFFE2E -:1049F00024020002AF4301C0A34201C43C021000E4 -:104A0000AF4201F88FBF001003E0000827BD001877 -:104A10008FAA00108C8200500080402130C600FF19 -:104A2000004A102300A048211840000700E0182188 -:104A300024020001A0800084A0A00112A48200141E -:104A40000A0011BDAFAA0010A0800081AD07004C84 -:104A50008CA2010800E210231840000224E2FFFCAF -:104A6000ACA2010830C200011040000800000000A4 -:104A70008D0200500062102304410013240600053B -:104A80008D02005410620010000000008D020054DE -:104A900014620011000000003C0208008C4200D8A3 -:104AA000304200201040000A2402000191030078E7 -:104AB000910200831443000624020001010020211A -:104AC00001202821240600040A0010EC0000000048 -:104AD000A1000084A502001403E00008000000000B -:104AE00027BDFFE0AFBF0018274201009046000A33 -:104AF0008C4800148C8B004C9082008430C900FFDD -:104B000001681823304A00FF1C60001A2D46000679 -:104B1000240200010142100410C0001630430003BB -:104B2000012030210100382114600007304C000CB6 -:104B300015800009304200301440000B8FBF001870 -:104B40000A0012AC000000000E0011BDAFAB001057 -:104B50000A0012AC8FBF00180E001132AFAB00106C -:104B60000A0012AC8FBF0018AFAB00100E0012523B -:104B7000AFAA00148FBF001803E0000827BD002073 -:104B800024020003A08200848C82005403E0000809 -:104B9000ACA201083C020008034218219062008187 -:104BA000240600433C07601924420001A0620081F2 -:104BB000906300813C0208008C4200C0306300FF1B -:104BC000146200102403FF803C0208008C4200E0C5 -:104BD0000082102100431024AF4200243C02080050 -:104BE0008C4200E03C03000A008210213042007F2A -:104BF0000342102100431021944500D40A000B8980 -:104C000030A5FFFF03E000080000000027BDFFE023 -:104C1000AFBF0018AFB10014AFB000108F420180D9 -:104C20000080802100A088210E0012B300402021C6 -:104C3000A20000848E0200548FBF00188FB00010B5 -:104C4000AE2201088FB1001403E0000827BD002048 -:104C500027BDFFE03C020008AFB00010AFBF001856 -:104C6000AFB10014034280218F51014092030084B0 -:104C70008E0400508E02004C14820040306600FF0B -:104C80003C0208008C4200E02403FF800222102135 -:104C900000431024AF4200243C0208008C4200E094 -:104CA0009744007C92050081022210213042007F4F -:104CB000034218213C02000A0062182114A0000BD4 -:104CC0003084FFFF2402000554C20014248205DC56 -:104CD0009062011224420001A062011224020C80A1 -:104CE000AF4200240A00130B24020005A060011249 -:104CF0002402000514C20009248205DC920200810E -:104D00002C4200075040000524820A0092030081D3 -:104D10002402001400621004008210213044FFFFBE -:104D2000A60400140E0012B3022020219602003CBB -:104D30008E03004C022020213042FFFF0002104071 -:104D4000006218210E000302AE03005C9202007D97 -:104D500002202021344200400E00030BA202007DFD -:104D60008F4201F80440FFFE24020002AF5101C04F -:104D7000A34201C43C021000AF4201F88FBF0018EB -:104D80008FB100148FB0001003E0000827BD002091 -:104D900008000D9808000DE008000E2008000E6CB9 -:044DA00008000EA059 -:0C4DA4000A0000220000000000000000D7 -:104DB0000000000D6370352E302E306A3300000085 -:104DC00005000004000000000000000000000000DA -:104DD00000000000000000000000000000000000D3 -:104DE00000000000000000000000000000000020A3 -:104DF00000000000000000000000000000000000B3 -:104E000000000000000000000000000000000000A2 -:104E10000000000000000000000000000000000191 -:104E20000000002B00000000000000000000000057 -:104E300010000003000000000000000D0000000D45 -:104E40003C02080024425AC43C03080024636190D9 -:104E5000AC4000000043202B1480FFFD24420004DE -:104E60003C1D080037BD7FFC03A0F0213C1008006A -:104E7000261000883C1C0800279C5AC40E0001A67E -:104E8000000000000000000D27BDFFE83C0960188D -:104E9000AFBF00108D2C5000240DFF7F240800317F -:104EA000018D5824356A380C24070C003C1A800008 -:104EB000AD2A50003C04800AAF4800083C1B800823 -:104EC000AF4700240E000938AF8400100E0008FB25 -:104ED000000000000E000848000000000E0012DF75 -:104EE000000000003C0460168C8500003C06FFFFBB -:104EF0003C02535300A618241062004734867C00FD -:104F000094C201F2A780002C10400003A78000CCBF -:104F100038581E1EA798002C94C201F810400004B7 -:104F2000978300CC38591E1EA79900CC978300CCDC -:104F30002C7F006753E00001240300669784002C57 -:104F40002C82040114400002006028212404040083 -:104F50003C0760008CE904382403103C3128FFFF33 -:104F60001103001F30B9FFFF57200010A38000CEAF -:104F700024020050A38200CE939F00CE53E0000F86 -:104F8000A78500CCA78000CC978500CC8FBF0010F0 -:104F9000A780002CA7800034A78000E63C01080011 -:104FA000AC25008003E0000827BD0018939F00CEC9 -:104FB00057E0FFF5A78000CCA78500CC978500CCF3 -:104FC0008FBF0010A784002CA7800034A78000E6C4 -:104FD0003C010800AC25008003E0000827BD001854 -:104FE000A38000CE8CCB003C316A00011140000E42 -:104FF0000000000030A7FFFF10E0FFDE2402005099 -:105000008CCC00C83186000114C0FFDC939F00CE19 -:105010000A000074240200518C8F00043C0E6000D2 -:105020000A00005701EE30218CEF0808240D5708C4 -:10503000000F740211CD000430B8FFFF2405006694 -:105040000A000075240404001700FFCC939F00CED3 -:105050000A000074240200508F8600103089FFFF80 -:10506000000939408CC300103C08005000E820259E -:10507000AF4300388CC5001427420400AF82001CE7 -:10508000AF45003CAF4400300000000000000000CD -:105090000000000000000000000000000000000010 -:1050A00000000000000000008F4B0000316A00206B -:1050B0001140FFFD0000000003E0000800000000B8 -:1050C0008F840010948A001A8C8700243149FFFFD6 -:1050D000000940C000E83021AF46003C8C85002428 -:1050E0008F43003C00A3102318400029000000005B -:1050F0008C8B0020256200013C0D005035AC00086F -:10510000AF420038AF4C003000000000000000004B -:10511000000000000000000000000000000000008F -:1051200000000000000000008F4F000031EE002062 -:1051300011C0FFFD000000008F4A04003C08002061 -:10514000AC8A00108F490404AC890014AF480030C9 -:1051500000000000948600189487001C00C71821E6 -:10516000A48300189485001A24A20001A482001AC6 -:105170009498001A9499001E133800030000000050 -:1051800003E000080000000003E00008A480001A0B -:105190008C8200200A0000D63C0D00500A0000C797 -:1051A000000000003C0308008C6300208F82001880 -:1051B00027BDFFE810620008AFBF00100E0000FE20 -:1051C000AF8300183C0308008C6300202404000116 -:1051D000106400048F8900108FBF001003E00008E6 -:1051E00027BD00188FBF00103C076012A520000AE1 -:1051F0009528000A34E5001027BD00183106FFFF8E -:1052000003E00008ACA600903C0208008C4200209D -:1052100027BDFFC8AFBF0034AFBE0030AFB7002C12 -:10522000AFB60028AFB50024AFB40020AFB3001C68 -:10523000AFB20018AFB1001410400050AFB0001072 -:105240008F840010948600069483000A00C32823EC -:1052500030B6FFFF12C0004A8FBF00349489001897 -:10526000948A000A012A40233102FFFF02C2382B30 -:1052700014E0000202C02021004020212C8C0005F7 -:10528000158000020080A021241400040E0000AD4F -:10529000028020218F87001002809821AF800014A7 -:1052A00094ED000A028088211280004E31B2FFFF87 -:1052B0003C1770003C1540003C1E60008F8F001CA6 -:1052C0008DEE000001D718245075005002202021D7 -:1052D00002A3802B160000353C18200050780047B0 -:1052E00002202021241000018F8300141460003953 -:1052F000029158230230F8230250C82133F1FFFFF6 -:105300001620FFEE3332FFFF8F8700103C11002084 -:10531000AF5100300000000094E6000A3C1E60120D -:1053200037D5001002662821A4E5000A94E2000A9D -:1053300094F2000A94F400183057FFFF1292003BD9 -:10534000AEB700908CED00148CE400100013714097 -:1053500001AE4021000E5FC3010E502B008B48218F -:10536000012A1821ACE80014ACE3001002D3382362 -:1053700030F6FFFF16C0FFB98F8400108FBF0034D6 -:105380008FBE00308FB7002C8FB600288FB5002459 -:105390008FB400208FB3001C8FB200188FB100149F -:1053A0008FB0001003E0000827BD0038107E001BFE -:1053B000000000001477FFCC241000010E00162A14 -:1053C000000000008F8300141060FFCB0230F82330 -:1053D000029158238F870010017020210A0001914B -:1053E0003093FFFF8F8300141460FFCB3C1100202B -:1053F000AF5100300A00015D000000000E0007A15F -:10540000024028210A000151004080210E00034B78 -:10541000024028210A000151004080210E0014F2B0 -:10542000022020210A000151004080210E0000C707 -:10543000000000000A00017302D3382327BDFFE8F3 -:10544000AFB00010AFBF00140E0000390000000024 -:105450003C028000345000700A0001B48E06000047 -:105460008F4F000039EE000131C2000110400024CE -:105470008F8600A88E0700003C0C08008D8C003C35 -:105480003C0908008D29003800E66823018D282199 -:105490000000502100AD302B012A402101062021BF -:1054A0003C010800AC25003CAF8700A83C01080087 -:1054B000AC2400380E000100000000003C0308008E -:1054C0008C6300701060FFE6006020213C0508003E -:1054D0008CA500683C0608008CC6006C0E0015B94F -:1054E000000000003C010800AC2000708F4F00005D -:1054F00039EE000131C200011440FFDE8F8600A8A2 -:105500008E0A00008F8B00A83C0508008CA5003C8B -:105510003C0408008C840038014B482300A9382142 -:105520000082182100E9402B006810213C0108008E -:10553000AC27003C3C010800AC2200388F5F010022 -:105540002419FF0024180C0003F9202410980012DD -:10555000AF840000AF440020936D0000240C0020B5 -:1055600031A600FF10CC0012240E005010CE000413 -:105570003C194000AF5901380A0001AD000000009D -:105580000E001255000000003C194000AF590138D0 -:105590000A0001AD000000000E000119000000002B -:1055A0003C194000AF5901380A0001AD000000006D -:1055B0008F58010000802821330F00FF01E02021D7 -:1055C0000E0002F8AF8F00043C194000AF590138BB -:1055D0000A0001AD0000000000A4102B240300010C -:1055E00010400009000030210005284000A4102BC5 -:1055F00004A00003000318405440FFFC00052840AD -:105600005060000A0004182B0085382B54E0000479 -:105610000003184200C330250085202300031842F0 -:105620001460FFF9000528420004182B03E000086D -:1056300000C310213084FFFF30A5FFFF8F4201B867 -:105640000440FFFE3C074080008730253C031000EB -:10565000AF400180AF450184AF46018803E00008F8 -:10566000AF4301B83084FFFF8F4201B80440FFFE12 -:105670003C0740388CA60000008728253C0310001A -:10568000AF460180AF45018803E00008AF4301B891 -:105690008F8300388F8600301066000B0080402119 -:1056A0003C07080024E75C38000328C000A710214D -:1056B0008C44000024630001108800053063000F53 -:1056C0005466FFFA000328C003E000080000102120 -:1056D0003C07080024E75C3C00A7302103E00008F9 -:1056E0008CC200003C03900034620001008220253F -:1056F000AF4400208F45002004A0FFFE0000000002 -:1057000003E00008000000003C0380003462000158 -:105710000082202503E00008AF44002027BDFFE001 -:10572000AFB100143091FFFFAFB00010AFBF001851 -:105730001220001500A080218CA5000010A00013ED -:10574000240400020E000C7F24060140AE0000007D -:105750008F4201B80440000D000028213C064000A3 -:10576000022620258FBF00188FB100148FB00010C3 -:105770003C03100027BD0020AF450180AF440188E5 -:1057800003E00008AF4301B88CA500008F4201B8C8 -:105790000440FFFE3C064000022620258FBF001873 -:1057A0008FB100148FB000103C03100027BD002003 -:1057B000AF450180AF44018803E00008AF4301B862 -:1057C0003086FFFF8F4201B80440FFFE3C094006CF -:1057D0008CA8000000C93825AF4801808CA40004C3 -:1057E0003C031000AF440184AF47018803E0000888 -:1057F000AF4301B827BDFFE0AFB00010AFBF001846 -:10580000AFB100149363003E008080210080282106 -:1058100030620040000020211040000F8E11000077 -:105820000E00087402202021936700002404005019 -:1058300030E500FF50A400128E0F0000022020214E -:105840008FBF00188FB100148FB00010A762013C09 -:105850000A00093427BD00200E0002870000000066 -:105860000E000874022020219367000024040050D9 -:1058700030E500FF14A4FFF2022020218E0F00006B -:105880003C1008008E1000503C0D000C240BFF80D3 -:1058900001F05021314E007F01DA6021018D40215D -:1058A000014B4824AF490028022020218FBF001857 -:1058B0008FB100148FB00010A50200D627BD0020C4 -:1058C0000A000934AF8800D027BDFFE0AFBF001841 -:1058D000AFB10014AFB000109366000100808021CA -:1058E0000E00025030D1000493640005001029C25C -:1058F000A765000034830040A36300050E00025931 -:10590000020020210E00093602002021240200019D -:10591000AF62000C02002821A762001024040002DC -:10592000A762001224060140A76200140E000C7F3B -:10593000A76200161620000F8FBF0018978C003446 -:105940003C0B08008D6B00782588FFFF3109FFFFB5 -:10595000256A0001012A382B10E00006A7880034D0 -:105960003C0F6006240E001635ED0010ADAE005061 -:105970008FBF00188FB100148FB0001003E0000833 -:1059800027BD002027BDFFE0AFB10014AFBF001856 -:10599000AFB0001000A088211080000A3C03600016 -:1059A0002402008010820012000000000000000DA0 -:1059B0008FBF00188FB100148FB0001003E00008F3 -:1059C00027BD00208C682BF80500FFFE00000000BA -:1059D000AC712BC08FBF00188FB100148FB00010B6 -:1059E0003C09100027BD002003E00008AC692BF83B -:1059F0000E00025000A02021936500050220202106 -:105A00000E00025930B000FF2403003E1603FFE7EA -:105A1000000000008F4401780480FFFE2407000787 -:105A20003C061000AF51014002202021A347014451 -:105A30008FBF00188FB100148FB00010AF460178EF -:105A40000A0002C927BD002027BDFFE8AFBF001430 -:105A5000AFB000108F500020000000000E0009368B -:105A6000AF440020AF5000208FBF00148FB0001053 -:105A700003E0000827BD00183084FFFF8F4201B803 -:105A80000440FFFE3C074035008730253C031000F2 -:105A9000AF450180AF400184AF46018803E00008B4 -:105AA000AF4301B83084FFFF8F4201B80440FFFECE -:105AB0003C074036008730253C031000AF4501808D -:105AC000AF400184AF46018803E00008AF4301B84E -:105AD00027BDFFD0AFB3001C3093FFFFAFB500244C -:105AE000AFB20018AFBF0028AFB40020AFB10014B0 -:105AF000AFB0001030B5FFFF12600027000090210A -:105B00008F90001C8E0300003C06800024020040A1 -:105B100000033E0200032C0230E4007F006688246C -:105B20001482001D30A500FF8F8300282C68000A16 -:105B3000510000108F910014000358803C0C0800A5 -:105B4000258C58D0016C50218D490000012000089F -:105B50000000000002B218213065FFFF0E00022491 -:105B600024040084162000028F90001CAF800028BF -:105B70008F910014260C0020264B0001018080210B -:105B80003172FFFF16200004AF8C001C0253282B3B -:105B900014A0FFDC00000000024010218FBF00288D -:105BA0008FB500248FB400208FB3001C8FB2001873 -:105BB0008FB100148FB0001003E0000827BD003043 -:105BC000240D003414AD00F600000000920B000E0E -:105BD000240A16803C07000CA36B00219203000DE1 -:105BE0000347F8213C066000A363002096110012D1 -:105BF0003C057FFF34ACFFFFA771003C960200100C -:105C0000240B00053054FFFFAF7400848E19001C74 -:105C1000AF4A00288FF800008CCF44480319702643 -:105C200001EE3021AF66004C8F69004C24CD00019D -:105C30003C197F00AF6900508F640050AF6400547E -:105C4000AF660070AF6D00588F6800582404005094 -:105C5000AF68005CA3600023AF6C0064A36B0037E7 -:105C60008E030014AF6300488F710048AF710024A9 -:105C70008E020018AF62006C9214000CA374003600 -:105C8000936A003E355F0020A37F003E8F7800744A -:105C90000319782435EE4000AF6E0074936900005C -:105CA000313000FF1204022B2418FF803C0408004E -:105CB00024845CB80E000294000000002406000456 -:105CC000240700013C0408008C845CB8A366007DB6 -:105CD000A36700058F4A01780540FFFE24020002F9 -:105CE000AF440140A34201448F90001C3C141000BB -:105CF000AF5401780A000373AF8000282CAD003741 -:105D000051A0FF9C8F9100140005A0803C18080052 -:105D1000271858F8029878218DEE000001C000087D -:105D2000000000002406000614A600110000000078 -:105D30003C1F08008FFF5CB824040005AF5F002003 -:105D40008E190018AF7900188F78004CAF78001CBE -:105D50008F6F0050122000C2AF6F00700A000373F3 -:105D6000AF840028240A000710AA00842403000638 -:105D70003C05080024A55CB80E00025E24040081E6 -:105D80008F90001C0011102B0A000373AF820028B3 -:105D90002402000414A2FFF6240A00503C09080063 -:105DA0008D295CB8AF4900208E040008AF64004024 -:105DB0008E060008AF6600448E07000CAF670048EF -:105DC0008E0D0010AF6D004C8E080010AF6800847F -:105DD0008E050014AF6500508E0C0018AF6C005497 -:105DE0008E0B001CAF6B005893740000328300FFD1 -:105DF000106A01ED000000008F6700488F660040C8 -:105E000000E6682305A000042404008C1620FFDEB1 -:105E100024020003240400823C05080024A55CB889 -:105E20000E000287000000008F90001C000010216F -:105E30000A000373AF8200282404000514A4FFCCD9 -:105E4000240520003C1F08008FFF5CB8AF5F0020D6 -:105E50008E190004AF79005C921800082410000825 -:105E6000A37800218F8F001C91EE0009A36E002003 -:105E70008F86001C90C9000A312400FF109000108A -:105E8000288A00091540006C24020002240C00201E -:105E9000108C000B340580002885002114A0000818 -:105EA0002405400024080040108800053C0500013E -:105EB000240D0080108D00023C05000224054000E6 -:105EC0008F6E00743C0FFF0001CF48240125802510 -:105ED000AF70007490C4000BA36400818F84001C19 -:105EE0009487000C10E0019300000000948E000CD9 -:105EF000241FFFBF24060004A76E003C9089000EFB -:105F0000A369003E8F90001C9204000FA364003F21 -:105F10008F94001C8E8D00108F47007401A74023C2 -:105F2000AF6800608E850014AF650064968C001821 -:105F3000A76C0068968B001AA76B006A8E83001C02 -:105F4000AF63006C96820002A762013E928A000E47 -:105F5000A36A003E9379003E033FC02412200166ED -:105F6000A378003E8F90001C0A000373AF860028C0 -:105F70002414002214B4FF7E240300073C0208000E -:105F80008C425CB81220000CAF4200200A00037360 -:105F9000AF830028240C003310AC00142405002823 -:105FA0003C05080024A55CB80E00023024040081E2 -:105FB0000A0003F88F90001C3C04080024845CB89D -:105FC0000E00029400000000936B000024110050AA -:105FD000316300FF10710150000000008F90001C21 -:105FE000000018210A000373AF8300283C08080052 -:105FF0008D085CB824040081AF480020A3650034FC -:106000003C05080024A55CB80E000230000000002A -:106010008F90001C240200090A000373AF8200283D -:1060200002B288213225FFFF0E00022424040084DE -:106030000A0003738F90001C1082FFA12405040046 -:10604000288300031060016E240B00042414000157 -:106050005494FF9B240540000A00044724050100D6 -:106060003C04080024845CB88F62004C0E0002944B -:106070008F6300508F90001C000020210A000373E2 -:10608000AF8400288E1000042404008AAF50002042 -:10609000936E000531C900021520015D0200282120 -:1060A0009378002302002821330F002015E00158C7 -:1060B0002404008D9362003F24190012305F00FF1A -:1060C00013F90153240400810E0002500200202124 -:1060D00093740023240A0004020020213683004226 -:1060E000A36300230E000259A36A007D8F4B017841 -:1060F0000560FFFE24050002AF500140A3450144A6 -:106100008F90001C3C0C1000AF4C01780A0003F982 -:106110000011102B8E100004AF500020936D00056D -:1061200031A80002550001782404008A9364003FDE -:106130002407000402002821308600FF10C7001049 -:10614000240400810E00025002002021937F0023CE -:1061500024180012240FFFFE37F90020A379002332 -:10616000A378003F936E00050200202101CF482450 -:106170000E000259A3690005020028210000202119 -:106180000E000340000000000A0003F88F90001C7E -:106190008E0500043C0F0008034F4021AF4500204E -:1061A000910E00002406005031C900FF1126017A2B -:1061B000240400888F5901B80720FFFE3C0C400ED4 -:1061C000008C58253C031000AF450180AF4001848E -:1061D000AF4B0188AF4301B891020000240AFF8051 -:1061E00024040004004AF825A11F00000E000C7FC3 -:1061F000240600300A0003F88F90001C8E0F000464 -:106200003C14080026945CB83C010800AC2F5CB834 -:10621000AF4F0020920E000331C90004112000028C -:106220002402001224020006A362003F9203001B16 -:10623000240AFFC03062003F004AF825A37F003ED9 -:1062400092190003333800011700012200000000FA -:106250008E020008AE8200083C0208008C425CC03E -:106260001040012D00000000000221C2A7640008B8 -:106270008E0D000C240B000124140014AF6D002CB3 -:106280008E080010AF68003096050016A76500382C -:10629000960C0014A76C003AAF6B000CA76B0010B3 -:1062A000A76B0012A76B0014A76B00161220014AFF -:1062B000A37400349206000330C700022CF00001E2 -:1062C000260200088F90001C0A000373AF8200288A -:1062D0008E14000424030081AF540020936800232F -:1062E0003105001010A00113000000008F4401B818 -:1062F0000480FFFE3C06401F0011382B006610256D -:106300003C111000AF540180AF870028AF400184DA -:10631000AF420188AF5101B80A0003748F91001495 -:106320008E0600043C19000803592021AF460020C6 -:106330008E07000890980000240F0050331400FFCF -:10634000128F0106240500888F4401B80480FFFEE7 -:106350003C0D40090011602B00AD10253C111000D0 -:10636000AF460180AF8C0028AF470184AF4201885F -:10637000AF5101B80A0003748F9100148E04001C01 -:106380000E00023B00000000104000D700404821F2 -:106390008F90001C240500898F4D01B805A0FFFED9 -:1063A00000000000AF4901808E0F001C3C1440012A -:1063B0000011702B00B448253C111000AF4F018430 -:1063C000AF8E0028AF490188AF5101B80A000374AD -:1063D0008F910014961900023C14080026945CB8B2 -:1063E000333800041300008E3C0260008E1F001C36 -:1063F0003C010800AC3F5CB8AF5F0020920C00107D -:10640000240B0014318400FF148B00AC000000004A -:1064100096090002312D000115A001520000000074 -:106420008E020004AE8200083C0E08008DCE5CC0D7 -:1064300011C00148000000008F6900743C0E80000C -:1064400024040001012E6825AF6D0074A3600005CF -:10645000AF64000C3C0C08008D8C5CC08F88001C65 -:10646000A7640010000C59C2A7640012A7640014AE -:10647000A7640016A76B00088D030008240400021F -:10648000AF63002C8D0A000CAF6A0030910700103A -:10649000A36700348F82001C90450011A36500356E -:1064A0008F86001C90D00012A37000368F9F001CB6 -:1064B00093F90013A37900378F90001C96180014ED -:1064C000A778003896140016A774003A8E0F0018AB -:1064D000AF6F00245620FDA6AF8400283C050800BD -:1064E00024A55CB80E00025E000020218F90001CE5 -:1064F0000A0004B6000020213C05080024A55CB871 -:106500000E000287240400828F90001C00003021BE -:106510000A000373AF8600283C0408008C845CB832 -:106520000E001577000000008F90001C0A000490F8 -:10653000000018213C05080024A55CB80E00028765 -:106540002404008B8F90001C0011302B0A00037371 -:10655000AF8600283C1908008F395CB83C1F080042 -:106560008FFF005024CCFFFE033F782101F87024F8 -:10657000AF4E00283C0408008C845CB83C0908003D -:106580008D2900500089682131A8007F011A282137 -:1065900000A78021AE0600D8AF9000D0AE0000DC8E -:1065A0000A0003C2AE0C0108AF6000843C0508007D -:1065B0008CA55CB83C0808008D080050240CFF80B6 -:1065C0003C02000C00A8A021028C5824AF4B0028EC -:1065D0008E1F00143283007F007A50210142702107 -:1065E000ADDF00D88E190014AF8E00D0ADD900DC1D -:1065F0008E180010270FFFFE0A000415ADCF01080A -:10660000548BFE2F240540000A0004472405100087 -:106610000E000335000000000A0003F88F90001CF4 -:106620008C46442C3C056C6234B079703C01080007 -:10663000AC205CB814D00008240400029788003411 -:10664000978A002C02802821010A382B10E00011C3 -:1066500024040092240400020E000C9D2405014035 -:106660003C010800AC225CB8AF4200203C030800AB -:106670008C635CB810600005240400830E00086879 -:106680000000000010400009240400833C050800BD -:1066900024A55CB80E00025E000000008F90001C74 -:1066A0000011202B0A000373AF8400280E00086C31 -:1066B000000000000A0005968F90001C0E00087074 -:1066C000000000003C05080024A55CB80A00063C58 -:1066D0002404008B8E0400080E00023B0000000022 -:1066E0000A00052DAE820008240400040E000C9D53 -:1066F000240500301440003F004048218F90001CCA -:106700000A00057D240500830E00034002002821B5 -:106710000A0004E2000000003C05080024A55CB863 -:106720000E000230240400878F90001C0A000549E7 -:106730000011102B0E0002500280202193700023C4 -:1067400002802021360D00100E000259A36D002397 -:106750008F90001C0A000552000018219205000CC1 -:1067600030BF000113E00003000000009602000E9D -:10677000A482002C920A000C314800021100FEF2A3 -:1067800000002821960B00128E030014A48B001A1F -:106790000A000569AC83001C8F8300388F870030A6 -:1067A0001067FE84000020213C09080025295C3C7C -:1067B000000320C0008930218CD400001285005EC7 -:1067C000247800013303000F5467FFFA000320C050 -:1067D0000A000504000020213C05080024A55CB83F -:1067E0000E000287240400828F90001C0A000549D5 -:1067F000000010213C0B0008034B20212403005013 -:10680000240A0001AF420020A0830000A08A0001FA -:106810008F88001C91070004A08700188F82001C3D -:1068200090450005A08500198F86001C90DF0006AA -:10683000A09F001A8F99001C93380007A098001B96 -:106840008F94001C928F0008A08F001C8F90001C5A -:10685000920E0009A08E001D8F8D001C91AC000AC5 -:10686000A08C001E8F8B001C3C0C0800258C5C3C0F -:106870009163000B3C0B0800256B5C38A083001F64 -:106880008F8A001C9148000CA08800208F87001C74 -:1068900090E5000DA08500218F82001C240546464E -:1068A0009046000EA08600228F9F001C93F9000FD7 -:1068B000A09900238F98001C93140010A09400242A -:1068C0008F8F001C91F00011A09000258F90001C6C -:1068D0008F8E00308F990038960D0014000E18C06E -:1068E00025C80001A48D0028960A0016006C3021EE -:1068F000006BF821A48A002A960700183108000FBF -:10690000A487002CA485002E8E02001CACC90000B8 -:10691000AF88003011190003AFE200000A00057DC6 -:1069200000002821250C00013184000F00002821DF -:106930000A00057DAF8400383C07080024E75C3876 -:106940000087802100002021ACC000000A0005045F -:10695000AE0000003C05080024A55CB80A00063C17 -:10696000240400878E0400040E00023B0000000097 -:106970000A0005A1AE8200083084FFFF30C600FF88 -:106980008F4201B80440FFFE000644000104302598 -:106990003C07200000C720253C031000AF400180C9 -:1069A000AF450184AF44018803E00008AF4301B85C -:1069B00027BDFFE8AFB00010AFBF00143C07600078 -:1069C000240600021080000600A080210010102B79 -:1069D0008FBF00148FB0001003E0000827BD00181F -:1069E0003C09600EAD2000348CE5201C8F82001C19 -:1069F0002408FFFC00A81824ACE3201C0E0006F5B8 -:106A00008C45000C0010102B8FBF00148FB00010AD -:106A100003E0000827BD00183C02600E3447010067 -:106A200024090018274A04000000000000000000AC -:106A3000000000003C06005034C30200AF440038A0 -:106A4000AF45003CAF430030014018218F4B0000A0 -:106A5000316800201100FFFD2406007F2408FFFF9D -:106A60008C6C000024C6FFFF24630004ACEC000023 -:106A700014C8FFFB24E70004000000000000000031 -:106A8000000000003C0F0020AF4F0030000000006D -:106A900024AD020001A5702B2529FFFF008E2021C7 -:106AA0001520FFE101A0282103E0000800000000FC -:106AB00027BDFFE0AFB10014AFBF0018AFB00010AA -:106AC0003C05600E8CA20034008088211440000632 -:106AD0003C0460008C87201C2408FFFC00E8302464 -:106AE00034C30001AC83201C8F8B001C24090001DF -:106AF000ACA90034956900028D6500148D70000CFE -:106B00002D2400818D6700048D6600081080000729 -:106B10008D6A00102D2C00041580000E30CE000769 -:106B2000312D000311A0000B000000002404008B95 -:106B3000020028210E0006F5240600030011102B88 -:106B40008FBF00188FB100148FB0001003E0000851 -:106B500027BD002015C0FFF62404008B3C03002055 -:106B6000AF4300300000000024020001AF82001497 -:106B70000000000000000000000000003C1F015069 -:106B8000013FC825253800033C0F600EAF47003891 -:106B900000181882AF46003C35E8003CAF59003081 -:106BA000274704008F4400003086002010C0FFFDFE -:106BB00000000000106000082466FFFF2403FFFFB0 -:106BC0008CEB000024C6FFFF24E70004AD0B00009F -:106BD00014C3FFFB250800043C08600EAD09003813 -:106BE0000000000000000000000000003C07002042 -:106BF000AF470030000000000E00071D01402021BB -:106C000002002821000020210E0006F524060003C2 -:106C10000011102B8FBF00188FB100148FB000101F -:106C200003E0000827BD002027BDFFD8AFB2001841 -:106C30003092FFFFAFB10014AFBF0020AFB3001C14 -:106C4000AFB000101240002C000088210A0007B5E8 -:106C50002413000150B300408CE5000C0000000D2F -:106C6000263900013331FFFF24F800200232382B8F -:106C700010E00021AF98001C8F8200141440001E09 -:106C80008F87001C3C0670003C0320008CE4000051 -:106C90000086282414A300188F85003C00044402B9 -:106CA0003C0980000089802414A0FFEA310600FF1F -:106CB000240A000210CA002E28CB0003116000161F -:106CC000240C000314D3FFE7263900010200282119 -:106CD0000E000703240400018F87001CAF82003CD4 -:106CE000263900013331FFFF24F800200232382B0F -:106CF00014E0FFE1AF98001C022010218FBF00209C -:106D00008FB3001C8FB200188FB100148FB0001029 -:106D100003E0000827BD002810CC001A240D000451 -:106D200014CDFFD026390001308EFFFF000E19C0B0 -:106D30008F4401B80480FFFE3C0F10003C1020047B -:106D4000AF430180AF400184AF500188AF4F01B81D -:106D50000A0007B0263900010E0006F5240400845D -:106D60001600FFBF8F87001C0A0007AFAF80003CF2 -:106D7000020028210E000703000020210A0007CE90 -:106D80008F87001C0E000743020020218F87001C04 -:106D90000A0007CFAF82003C3082FFFF144000039F -:106DA000000018210004240224030010308500FF95 -:106DB00014A000053087000F24660008000422029A -:106DC00030C300FF3087000F14E000053089000356 -:106DD0002468000400042102310300FF308900030D -:106DE00015200005388B0001246A0002000420826F -:106DF000314300FF388B0001316400011080000234 -:106E0000246C0001318300FF03E0000800601021C2 -:106E1000308BFFFF000B394230E600FF3C090800D1 -:106E200025295BB800064080010960218D8700009C -:106E30003164001F240A0001008A180430A500FFF5 -:106E400000E3202514A000020003102700E2202404 -:106E5000240F000100CF700401096821000E2827CB -:106E600014800005ADA400008F86000C00A610243D -:106E700003E00008AF82000C8F88000C01C81025C9 -:106E800003E00008AF82000C3C06001F3C036000DA -:106E90003084FFFF34C5FF8024020020AC6020084E -:106EA000AC60200CAC602010AC652014AC642018E1 -:106EB000AC622000000000000000000003E00008B9 -:106EC0000000000027BDFFE82402FFFFAFBF001055 -:106ED000AF82000C000020213C06080024C65BB8ED -:106EE0002405FFFF24890001000440803124FFFFB6 -:106EF000010618212C87002014E0FFFAAC65000081 -:106F00000E00083900002021240200013C0460002A -:106F100024050020AC822018AC8520000000000071 -:106F20000000000000000000244A00013142FFFF81 -:106F30002C46040014C0FFF78FBF001003E00008C8 -:106F400027BD00188F8300082C62040003E00008AE -:106F5000384200018F8300082462000103E000082A -:106F6000AF8200088F8300082462FFFF03E000085F -:106F7000AF82000827BDFFE0AFB10014AFBF00181B -:106F8000AFB000108F6B00303C066000008088219D -:106F9000ACCB20088F6A002C3C0280002403000840 -:106FA000ACCA200C9769003A9768003800092C0099 -:106FB0003107FFFF00A72025ACC42010ACC220146D -:106FC000ACC3200000000000000000000000000032 -:106FD0003C0360008C6D200031AC00081580FFF987 -:106FE000000000008C6E201405C00020000000008E -:106FF0000E0007FD8F84000C000240803C09080051 -:1070000025295BB8010938218CE400000E0007FD3A -:1070100000028140020220213090FFFF0200202167 -:107020000E00081B000028213C0C8000022C582573 -:107030003210FFFF3C116000240A0020AE2B201408 -:10704000AE302018AE2A2000000000000000000032 -:1070500000000000020010218FBF00188FB1001443 -:107060008FB0001003E0000827BD00208C662014BC -:107070003C02001F3443FF803C1FFFE800C3C024D4 -:1070800037F9080003198021001079C23C0C8000F8 -:10709000022C582531F0FFFF3C116000240A00202B -:1070A000AE2B2014AE302018AE2A200000000000C5 -:1070B0000000000000000000020010218FBF001837 -:1070C0008FB100148FB0001003E0000827BD00202E -:1070D00027BDFFE8AFB000103402FFFF3090FFFF84 -:1070E000AFBF001412020006020020210E00083972 -:1070F00000000000020020210E00081B24050001F2 -:107100008F8400088FBF00148FB000102483FFFF0E -:1071100027BD001803E00008AF830008000439C24F -:1071200030E6003F00043B420007184024021000F4 -:107130002CC4002024C8FFE0AF42002C24630001CF -:107140001480000330A900FF00071840310600FF3B -:107150000003608024080001019A58213C0A000EB7 -:1071600000C82804016A38211120000500053027D5 -:107170008CE900000125302503E00008ACE60000A2 -:107180008CEE000001C6682403E00008ACED0000AE -:1071900027BDFFE8AFBF0014AFB000103C04600093 -:1071A0008C8508083403F00030A2F000504300063C -:1071B000240200018C8708083404E00030E6F00067 -:1071C00010C4001E24020002AF8200403C10600088 -:1071D0003C0A0200AE0A0814240910003C08000E04 -:1071E0008E03440003482021AF49002C24050120D0 -:1071F0000E000CE3000030218F830040106000047B -:107200003C021691240B0001106B000E3C023D6CF9 -:10721000344F0090AE0F44088FBF00148FB00010A1 -:107220003C0C6000240E10003C0D020027BD00182D -:10723000AD8E442003E00008AD8D08100A00090A55 -:10724000AF8000403C0218DA344F0090AE0F440883 -:107250008FBF00148FB000103C0C6000240E100093 -:107260003C0D020027BD0018AD8E442003E000084D -:10727000AD8D08100A0008DE240500010A0008DEB2 -:10728000000028213C08080025085FC42404FFFFF3 -:10729000010018212402001E2442FFFFAC640000FC -:1072A0000441FFFD246300043C07080024E760401C -:1072B0008CE5FFFC2404001C24060001308A001F1A -:1072C0000146480424840001000910272C83002073 -:1072D0001460FFFA00A22824ACE5FFFC3C056666BA -:1072E00034A4616E3C06080024C66100AF840058D7 -:1072F000AF88009C2404FFFF00C018212402001F57 -:107300002442FFFFAC6400000441FFFD246300043D -:107310003C0766663C05080024A560C0AF860048AF -:1073200034E6616EAF8600982404FFFF00A01821A8 -:107330002402000F2442FFFFAC6400000441FFFD63 -:10734000246300043C0B66663C06080024C66040CB -:107350003568616EAF8500A4AF8800702404FFFF1C -:1073600000C018212402001F2442FFFFAC6400006B -:107370000441FFFD246300043C0D66663C0A0800DE -:10738000254A618035AC616EAF860090AF8C005CA1 -:107390002404FFFF01401821240200032442FFFFC0 -:1073A000AC6400000441FFFD246300043C090800B4 -:1073B000252961908D27FFFC240400062405000187 -:1073C0003099001F0325C004248400010018782789 -:1073D0002C8E002015C0FFFA00EF3824AD27FFFCEB -:1073E0003C09666624030400240403DC240502002F -:1073F000240600663522616E3C08080025085CC43E -:10740000AF820074AF830044AF83006CAF83005041 -:10741000AF830084AF8A008CAF840064AF85004CDA -:10742000AF860054AF840078AF850060AF860080DF -:1074300001001821240200022442FFFFAC6000007A -:107440000441FFFD24630004240400032403000C12 -:107450003C0A0800254A5CD0AF8A00680A0009B1DE -:107460002405FFFF000418802484000100685821CF -:107470002C8700C014E0FFFBAD6500003C0E666683 -:1074800035CD616E240C17A024081800AF8D00883C -:10749000AF8C009403E00008AF88007C2484007F58 -:1074A000000421C2000040210000302100003821EA -:1074B000000028210A0009C8AF8400A0106000065F -:1074C00024E7000100C4302124A500012CC20BF5E3 -:1074D0001440FFFA2CA300663C09080025296180AE -:1074E00001201821240200032442FFFFAC600000A9 -:1074F0000441FFFD2463000410E0001A24E3FFFFB1 -:107500000003294210A0000A000020212406FFFFEA -:107510003C03080024636180248400010085502B13 -:10752000AC660000250800011540FFFB2463000441 -:1075300030E2001F1040000800086880240C0001A1 -:10754000004C3804000858800169282124E6FFFF18 -:1075500003E00008ACA6000001A940212409FFFFB8 -:10756000AD09000003E0000800000000AF4400285F -:107570003C04000C03442021000528820A000CE38F -:1075800000003021000421803C036000AC6410083E -:107590000000000000052980AC65100C0000000010 -:1075A00003E000088C62100C27BDFFE80080282152 -:1075B00024040038AFBF00140E0009F8AFB000106B -:1075C00024040E00AF4400283C10000C035020217E -:1075D000240500100E000CE30000302103501021A0 -:1075E000AC400000AC400004240400388FBF0014FD -:1075F0008FB0001024053FFF27BD00180A0009F8CE -:107600008C430000000421803C036000AC6410083F -:10761000000000008C62100C03E0000800021182E0 -:1076200027BDFFC8AFB400208F940068AFBE003004 -:10763000AFB7002CAFB600280000B8210080B02101 -:10764000241E00C0AFBF0034AFB50024AFB3001C90 -:10765000AFB20018AFB10014AFB000100A000A3585 -:10766000AFA5003C504000018F94006827DEFFFF6B -:1076700013C00028269400048E9200003C030800EA -:1076800024635FC01240FFF70283102B3C04080004 -:1076900024845CC4028410230002A8C00000982146 -:1076A0000A000A442411000100118840122000261B -:1076B0000000000002B38021025128240200202192 -:1076C00010A0FFF9267300010E000A01000000005F -:1076D0000016684032EC000101AC20210E0009F8D0 -:1076E000020028218F89009426F700018FA6003C14 -:1076F0003AEB0001316A00012528FFFF001138270D -:1077000002CAB021AF88009416E6FFE70247902432 -:10771000AE92000002E010218FBF00348FBE003017 -:107720008FB7002C8FB600288FB500248FB40020AF -:107730008FB3001C8FB200188FB100148FB00010EF -:1077400003E0000827BD00383C0E080025CE5FC0CE -:10775000028E102B0A000A30AE92000027BDFFD81F -:10776000AFB10014AFB00010AFBF0020AFB3001C2A -:10777000AFB2001800A0882110A0001F00048040B4 -:107780003C13080026735CC40A000A7D2412000121 -:1077900012200019261000010E000A1802002021F4 -:1077A000000231422444FFA0000618803045001F2B -:1077B0002C8217A1007318212631FFFF1040FFF41F -:1077C00000B230048C6900000200202124053FFF34 -:1077D000012640241500FFEE012638250E0009F889 -:1077E000AC6700008F8A0094261000012547000135 -:1077F0001620FFE9AF8700948FBF00208FB3001CD5 -:107800008FB200188FB100148FB0001003E0000891 -:1078100027BD00288F85009C008058210000402152 -:1078200000004821240A001F3C0C0800258C603C05 -:107830003C0D080025AD5FC48CA6000050C00014AC -:107840000000402100AD1023000238C024030001D5 -:107850000A000AB6000020211500000300E41021F0 -:10786000244820240000482125290001512B001321 -:107870002506DFDC106000062484000100C37024AC -:1078800015C0FFF5000318400A000AB400004021AB -:1078900010AC002624A3000400602821254AFFFF25 -:1078A0001540FFE5AF85009C512B00042506DFDC69 -:1078B0000000402103E000080100102100066142A1 -:1078C00030C5001F000C50803C07080024E75FC44F -:1078D00024040001014730211120000F00A42004DE -:1078E0003C05080024A56040148000052529FFFF01 -:1078F00024C6000410C5001100000000240400018B -:107900008CCF00000004C0270004204001F8682448 -:107910001520FFF5ACCD00008F99007801001021F3 -:10792000032B482303E00008AF8900783C050800DA -:1079300024A55FC40A000ABE000040213C060800DE -:1079400024C65FC40A000AD724040001308800FF5F -:10795000240200021102000A240300031103005C48 -:107960008F8900A4240400041104005F240500058D -:10797000110500670000182103E0000800601021D5 -:107980008F8900483C0C0800258C61003C040800ED -:1079900024846180240300201060000F000058211F -:1079A000240D0002240E00033C0F080025EF6100A7 -:1079B0008D27000014E0000B30F9FFFF252900049B -:1079C0000124C02B53000001018048212463FFFFE4 -:1079D0005460FFF88D2700000160182103E00008C3 -:1079E00000601021132000323C0500FF30E200FF50 -:1079F00000403021104000420000502124050001C9 -:107A0000000020210005C84000A6C0241700000384 -:107A1000332500FF14A0FFFB24840001012CC023A8 -:107A2000001828C000AA6021008C50213144001F9A -:107A3000240C0001008C18040003102700E23024FD -:107A4000110D0041AD260000110E004C000A184037 -:107A5000110D00368F87006C510E00568F8C006020 -:107A6000240D0004110D005A8F8E0084240E000591 -:107A7000150EFFDA01601821240B143011400006A6 -:107A8000000018218F8400A024630001006A402BAD -:107A90001500FFFD016458218F8A0080AF89008C9A -:107AA000016018212549FFFF0A000B0EAF890080F5 -:107AB00000E52024000736021080FFD0240A0018B9 -:107AC00000075402314600FF0A000B16240A00107A -:107AD0003C0C0800258C60C03C0408002484610034 -:107AE0000A000AFD240300103C0C0800258C6040AD -:107AF0003C040800248460C00A000AFC8F890090BE -:107B000000071A02306600FF0A000B16240A00085C -:107B10008F89008C3C0C0800258C61803C04080097 -:107B2000248461900A000AFD24030004000A4080B6 -:107B3000250B003024E6FFFF01601821AF890048C3 -:107B40000A000B0EAF86006C000AC982001978800B -:107B50003C07080024E760C001E72021000A184222 -:107B60008C8F00003079001F032C38040007C027D9 -:107B700001F860240A000B2BAC8C0000000331429A -:107B80000006288000AF28213062001F8CB800005A -:107B900024630001004CC804000321420019382767 -:107BA0000004108003073024004F20210A000B6FCF -:107BB000ACA60000000A68C025AB0032258AFFFF92 -:107BC00001601821AF8900A40A000B0EAF8A006083 -:107BD000254B1030AF8900900160182125C9FFFFA7 -:107BE0000A000B0EAF890084308600072CC2000605 -:107BF0001040001400000000000640803C03080014 -:107C0000246359D4010338218CE40000008000086B -:107C1000000000002409000310A9000E000000006D -:107C2000240A000510AA000B00000000240B00012C -:107C300010AB0008000000008F8C00A010AC000505 -:107C40000000000003E00008000010210A000A9C68 -:107C500000A020210A000AEA00C0202127BDFFE879 -:107C6000308400FF240300021083000BAFBF00101C -:107C7000240600031086003A2408000410880068D7 -:107C8000240E0005108E007F2CAF14308FBF001023 -:107C900003E0000827BD00182CA200301440FFFCB0 -:107CA0008FBF001024A5FFD0000531C200066880F8 -:107CB0003C07080024E7610001A730218CC90000BF -:107CC0000005288230AC001F240B0001018B5004FA -:107CD0008F840048012A4025ACC800008C83000036 -:107CE00050600001AF8600488F98006C30AE0001F4 -:107CF00024A6FFFF270F000115C00002AF8F006C04 -:107D000024A60001000641420008208000871821B7 -:107D10008C79000030C2001F240600010046F804E0 -:107D2000033F382410E0FFDA8FBF00100005C18246 -:107D3000001870803C0F080025EF60C001CF48217B -:107D40008D2B00000005684231A5001F00A66004CD -:107D5000016C502527BD001803E00008AD2A000083 -:107D60002CA7003014E0FFCA8FBF001030B9000705 -:107D70001723FFC724A8FFCE00086A02000D608009 -:107D80003C0B0800256B60C0018B30218CC40000C7 -:107D9000000828C230AA001F240800010148480436 -:107DA0008F8200A400891825ACC300008C5F0000FE -:107DB00053E00001AF8600A400057040000E794238 -:107DC000000F28803C0408002484610000A41821CE -:107DD0008C6B000025DF000131CD001F001F5142D8 -:107DE00001A86004016C4825000A1080AC690000FD -:107DF000004428218CA600008F98006033F9001FF2 -:107E00008FBF00100328380400C77825270E000113 -:107E100027BD0018ACAF000003E00008AF8E006083 -:107E200024A5EFD02CB804001300FF998FBF0010D9 -:107E300000053142000658803C0A0800254A60408F -:107E4000016A30218CC4000030A3001F2409000106 -:107E5000006910048F9900900082F825ACDF0000C3 -:107E60008F27000050E00001AF8600908F8D0084C6 -:107E70008FBF001027BD001825AC000103E00008EB -:107E8000AF8C008415E0FF828FBF00108F8600A0AA -:107E9000000610400046F821001F210003E4C8211D -:107EA0000019384024F8143000B8402B1100FF7836 -:107EB0008FBF001024A4EBD00E00020D00C02821BB -:107EC00000027942000F70803C0D080025AD6180F2 -:107ED00001CD20218C8B0000304C001F24060001B6 -:107EE000018618048F89008C01635025AC8A00003C -:107EF0008D25000050A00001AF84008C8F98008079 -:107F00008FBF001027BD00182708000103E00008FC -:107F1000AF88008030A500072403000310A30010E1 -:107F200028A20004144000082407000224030004CF -:107F300010A300152408000510A8000F8F8500A0CD -:107F400003E000080000000014A7FFFD00802821C6 -:107F500014C3FFFB240400020A000BAE0000000063 -:107F6000240900050080282110C9FFFB2404000318 -:107F700003E000080000000014C5FFF10080282184 -:107F80000A000BAE24040005240A00010080282109 -:107F900010CAFFF12404000403E000080000000000 -:107FA00027BDFFE0AFB00010000581C22603FFD05F -:107FB00024C5003F2C6223D024C6007FAFB2001836 -:107FC000AFB10014AFBF001C309100FF000691C29A -:107FD0000005298202002021104000082403FFFF31 -:107FE0000E000A6E0000000002002021022028215D -:107FF0000E000C5C02403021000018218FBF001CD5 -:108000008FB200188FB100148FB0001000601021E3 -:1080100003E0000827BD002027BDFFD824A2007F71 -:10802000AFB3001CAFB20018000299C2309200FF3B -:1080300024A3003F0240202102602821AFB1001498 -:10804000AFB00010AFBF00200E000B91000389827B -:1080500000408021004020210220282114400009F6 -:10806000000018218FBF00208FB3001C8FB20018B2 -:108070008FB100148FB000100060102103E00008E1 -:1080800027BD00280E000A1F000000000040282124 -:10809000020020211051FFF3001019C00E000A6EDB -:1080A0000000000002002021024028210E000C5C8C -:1080B000026030218FBF00208FB3001C8FB20018E8 -:1080C0008FB100148FB00010000018210060102143 -:1080D00003E0000827BD00283084FFFF30A5FFFF24 -:1080E00010800007000018213082000110400002BB -:1080F00000042042006518211480FFFB0005284081 -:1081000003E000080060102110C00007000000001C -:108110008CA2000024C6FFFF24A50004AC8200004E -:1081200014C0FFFB2484000403E0000800000000EA -:1081300010A0000824A3FFFFAC8600000000000090 -:10814000000000002402FFFF2463FFFF1462FFFA17 -:108150002484000403E000080000000030A5FFFFB5 -:108160008F4201B80440FFFE3C07601500A7302590 -:108170003C031000AF440180AF400184AF4601884A -:1081800003E00008AF4301B88F8500D02C86400083 -:10819000008018218CA700840087102B1440001049 -:1081A000000000008CA800842D06400050C0000F85 -:1081B000240340008CAA0084008A482B512000012F -:1081C0008CA3008400035A42000B20803C05080069 -:1081D00024A55A400085182103E000088C620000A5 -:1081E00014C0FFF4000000002403400000035A42C2 -:1081F000000B20803C05080024A55A40008518216A -:1082000003E000088C6200008F8300D0906600D0ED -:1082100024C50001A06500D08F8500D0906400D0F7 -:1082200090A200D21044001700000000936C007868 -:108230008F8B00BC318A00FFA16A000C2549000128 -:10824000938700C4312200FF3048007F1107000BE4 -:1082500000026827A36200788F4E017805C0FFFEF8 -:108260008F9900B0241800023C0F1000AF59014054 -:10827000A358014403E00008AF4F01780A000D2C19 -:1082800031A20080A0A000D00A000D220000000052 -:1082900027BDFFD8AFB200188F9200B8AFBF002043 -:1082A000AFB3001CAFB00010AFB100148F9300B497 -:1082B0008E5900283C1000803C0EFFEFAE79000084 -:1082C0008E580024A260000A35CDFFFFAE7800046E -:1082D0009251002C3C0BFF9F356AFFFFA271000CEE -:1082E0008E6F000C3C080040A271000B01F060256D -:1082F000018D4824012A382400E83025AE66000CA0 -:108300008E450004AE6000183C0400FFAE6500140A -:108310008E43002C3482FFFFA66000080062F82420 -:10832000AE7F00108E5900088F9000B0964E00125C -:10833000AE7900208E51000C31D83FFF00187980B3 -:10834000AE7100248E4D001401F0602131CB00018C -:10835000AE6D00288E4A0018000C41C2000B4B8005 -:10836000AE6A002C8E46001C01093821A667001C4D -:10837000AE660030964500028E440020A665001EC1 -:10838000AE64003492430033306200045440000570 -:10839000924600008F8300D08C7F007CAE7F00303F -:1083A000924600008F8500BCA0A6000092440033D6 -:1083B0003082000250400007924E00018F8700BCBF -:1083C000240AFF8090E90000012A4025A0E800006F -:1083D000924E00018F8D00BC2409FFBF2404FFDFF3 -:1083E000A1AE00018F8A00BC914C000D318B007F43 -:1083F000A14B000D8F8600BC90C8000D01093824E8 -:10840000A0C7000D8F9100BC8E6500149223000D53 -:108410002CA200010002F9400064C824033FC025DB -:10842000A238000D8F8800BC965000128F8700D0B4 -:10843000A51000028E45000490ED00BC30AF000393 -:10844000000F702331CC000300AC102131AB0002CF -:1084500015600002244400342444003090F100BC34 -:1084600000B18024320F000415E0000224830004D0 -:10847000008018218F8900AC240A0002AD0300049B -:10848000A12A00009248003F8F8700ACA0E80001BD -:108490008F9100AC9246003F8E440004A626000255 -:1084A0009765003C0E000CF930B0FFFF000213800E -:1084B000005020253C0342000083F825AE3F000415 -:1084C0008F8500AC8E590038ACB900188E58003436 -:1084D000ACB8001CACA0000CACA00010A4A0001410 -:1084E000A4A00016A4A00020A4A00022ACA00024F8 -:1084F0008E62001450400001240200018FBF002052 -:108500008FB3001C8FB200188FB100148FB0001011 -:10851000ACA200080A000D1927BD00288F8600D0E4 -:1085200027BDFFD0AFBF002CAFB60028AFB50024E9 -:10853000AFB40020AFB3001CAFB20018AFB100144D -:10854000AFB0001094C300E094C200E210430041B9 -:108550002405FFFF3C16000E90C400D090C800D147 -:10856000309200FF310400FF0244382B10E0004439 -:1085700026490001108900378F9800B03C0508009B -:108580008CA5005C2414FF8000B86021019468244D -:10859000AF4D002C94CA00E2318B007F017A482154 -:1085A00031447FFF01364021000410400048A821DB -:1085B00096A700003C1F08008FFF005830F53FFFD2 -:1085C0000015198003E3C821031988213233007F85 -:1085D000027A782102348024AF50002C01F69821D1 -:1085E000926E000D31C5000410A00048000000008C -:1085F00094C300E294C300E294D800E22404800013 -:10860000307F7FFF27F9000133317FFF030480248F -:1086100002117825A4CF00E294CE00E23C120800BB -:108620008E52006031D47FFF129200DF0000000004 -:108630008E720018000028212646FFFFAE66002C2F -:108640008F8600D094C800E094C900E21528FFC2CC -:10865000000000008FBF002C8FB600288FB50024CB -:108660008FB400208FB3001C8FB200188FB100149C -:108670008FB0001000A0102103E0000827BD0030DB -:1086800090CD00D2264A000131AC00FF008C582169 -:10869000116AFFF08F9800B03C0508008CA5005CC3 -:1086A0002414FF8000B8602101946824AF4D002C91 -:1086B00094CA00E2318B007F017A482131447FFF68 -:1086C00001364021000410400048A82196A7000070 -:1086D0003C1F08008FFF005830F53FFF0015198040 -:1086E00003E3C821031988213233007F027A7821FD -:1086F00002348024AF50002C01F69821926E000DB8 -:1087000031C5000414A0FFBA000000008E660010FE -:108710000012C0C08E6E00300012914002587821C5 -:10872000036F582100CE6823256C008824020002C4 -:10873000AE6D0010AF8C00ACA1620088976A003C5F -:108740008E6400308F9100AC0E000CF93150FFFFA9 -:1087500000022380009048253C034200012340256D -:10876000AE2800048E6700048F8C00AC8E7F000062 -:10877000240D0008AD87001CAD9F0018AD80000CD3 -:10878000AD8000109265000A30B900FFA599001471 -:10879000967800083C05000CA59800169271000A16 -:1087A000322F00FFA58F00209670000824110005CD -:1087B000A5900022AD800024926E000B2410C00012 -:1087C00031C600FFA5860002A18D00018E6B00302E -:1087D0008F8200AC8F8800B0AC4B00083C0A0800C8 -:1087E0008D4A00540148202100944824AF490028B4 -:1087F0003C0308008C6300540068382130FF007F80 -:1088000003FAC8210325C02102587821AF8F00BC8C -:10881000AF9800C0A1F100008F8B00BC2403FFBF04 -:108820002405FFDF956E000201D0A024029590255B -:10883000A57200029166000230CD003F35AC0040C9 -:10884000A16C00028F8800BC8F8200D03C0C7FFF9F -:10885000AD0000048C4A007C358BFFFF3C02800099 -:10886000AD0A00089104000D3089007FA109000DB8 -:108870008F9F00BC93F5000D02A33824A3E7000DE1 -:108880008F9100BC9239000D0325C024A238000D41 -:108890008E6F00348F8D00BCADAF00108E6E002C3B -:1088A0008E70003001D0A023ADB4001491B2001836 -:1088B0003246007FA1A600188F8700BC8E6A003068 -:1088C0008CE40018014B4824008240240109A825AB -:1088D000ACF500189263000AA0E3001C967F000824 -:1088E0008F8500BC8F9900D0A4BF001E8E70003011 -:1088F0008E6400300E00020D8F2500848F8500D01D -:10890000000289400002C10090AE00BC023878210C -:108910000040302131D4000212800003020F802178 -:108920000002A8800215802190B200BC32540004DD -:10893000128000020006C880021980218E6F00306C -:108940008F8B00BC2406800031EE0003000E6823EC -:1089500031AC0003020C1021AD62000494A400E2CB -:1089600094AA00E294A300E231507FFF26040001A4 -:1089700030897FFF0066402401098825A4B100E208 -:1089800094A700E23C1308008E73006030FF7FFF65 -:1089900013F30012000000000E000D19000000008B -:1089A0000A000E270000282194CD00E201A46024D3 -:1089B000A4CC00E290CB00E290C200E2316A00FF5A -:1089C000000A49C200092027000441C03055007F39 -:1089D00002A838250A000E23A0C700E294B100E2E5 -:1089E00002263824A4A700E290BF00E290B400E27F -:1089F00033F300FF0013C9C2001990273298007F9B -:108A00000012A9C0031530250E000D19A0A600E222 -:108A10000A000E27000028213084FFFF30A5FFFF49 -:108A2000AF440018AF45001C03E000088F4200145B -:108A300027BDFFB0AFB000288F9000D0AFB4003892 -:108A4000AFBF004CAFBE0048AFB70044AFB6004068 -:108A5000AFB5003CAFB30034AFB20030AFB1002CC3 -:108A6000A7A00014920600D1920500D03094FFFF19 -:108A700030C400FF30A300FF0064102BA7A0001E2D -:108A800010400071AFA00010920900D00014982B84 -:108A9000312800FF0088382324F2FFFF0012882BC2 -:108AA0000233782451E000758FB20010961800123E -:108AB000961900100014F4000319B8230017B4002D -:108AC000001614030282A82A16A00002001E240326 -:108AD000004020210244F82B13E0000200801821FE -:108AE000024018210003340000061C033065FFFF1C -:108AF0002CA20009144000020060982124130008F1 -:108B00008E090008001359808E08000C3164FFFFA5 -:108B10003C0A0010008A3825274A0400AF49003873 -:108B2000AF8A00B8AF48003CAF47003000000000FB -:108B30000000000000000000000000000000000035 -:108B40000000000000000000000000008F4D000049 -:108B500031AC00201180FFFD0013702A01D11024D8 -:108B60000000A821104001C0000000008F9800B054 -:108B70003C0B08008D6B00542411FF80921E00D026 -:108B80000178202100911024921900D0AF420028D2 -:108B90008D4500103C0608008CC600583C170800A4 -:108BA0008EF7005430A73FFF0007198000C3402113 -:108BB000030820210091F824920B00D0AF5F002C15 -:108BC0009148000033D600FF332F00FF02F87021D8 -:108BD00000166140000F68C031C9007F018D382147 -:108BE000013A2821316300FF3086007F3C02000CEF -:108BF00000A2B021000389400367C82100DAF821F0 -:108C00003108003F3C1E000E0236B821273800888C -:108C100003FE88212D0F0008AF9800ACAF9700BC71 -:108C2000AF9600C011E0018FAF9100B400086880DA -:108C30003C0E080025CE59EC01AE60218D89000064 -:108C40000120000800000000920E00D2920D00D01A -:108C50000014982B31CA00FF31AC00FF008C582360 -:108C6000014B20212492FFFF0012882B023378242D -:108C700015E0FF8E000000008FB200108FBF004C87 -:108C80008FBE00483A4200018FB700448FB60040C3 -:108C90008FB5003C8FB400388FB300348FB20030F2 -:108CA0008FB1002C8FB0002803E0000827BD0050D2 -:108CB000915800013317002012E00204241600012D -:108CC000921F00BC0000B02133F900011320000DF9 -:108CD000241E00018D4800148E0300840103B02B74 -:108CE00016C00002010030218E0600848E0500644B -:108CF00000C5382B14E0000200C020218E0400645F -:108D00000080B0218D4200148E0B0064004B302B8C -:108D100014C00002004020218E0400640096B82395 -:108D200056E00001241E0002025E202B1480014840 -:108D3000000018218D5900388E2F000C3C1800803F -:108D4000AE3900008D5000343C0EFF9F01F86025C5 -:108D5000AE3000049149003F35CDFFFF018D202446 -:108D60003C0A00203C0BFFEFA229000B008A3825AB -:108D70003562FFFF00E228243C0600088F8700B818 -:108D800000A6C825AE39000C8CE30014AE200018F4 -:108D90003C08FFFBAE2300148CF80018351FFFFFC2 -:108DA000033F7024AE38001C8CEF000802D78021EE -:108DB000AE2F00248CED000CAE30002CAE2E000C3B -:108DC000AE2D0020AE200028A6200038A620003AB4 -:108DD0008CEC0014019648230137502311400011F8 -:108DE000AE2A001090EE003D8E2C00048E24000070 -:108DF000000E6900018D28210000502100AD302BAC -:108E0000008A582101661021AE250004AE22000020 -:108E100090E3003DA223000A8F8800B8951F00064A -:108E2000A63F00088F8B00AC2406000202C0202160 -:108E3000A16600009765003C8F9000AC30A2FFFF58 -:108E40000E000CF9AFA200208FA300200002438087 -:108E50008F8500B80103C8253C1F4200033FC02591 -:108E6000AE1800048F8400AC8CAF0038AC8F0018B3 -:108E70008CB00034AC90001CAC80000CAC800010B6 -:108E8000A4800014A4800016A4800020A4800022E6 -:108E9000AC80002490A7003FA487000212C00210FB -:108EA000240D000152E0000290A2003D90A2003E7D -:108EB000244A0001A08A00018F8400ACAC9600080F -:108EC0008F8300D024070034906F00BC31EE000285 -:108ED00051C00001240700308F8200B88F9900BC78 -:108EE000906800BC905F00002410000432CF0003A3 -:108EF000A33F00008F9800B88F8C00BC020F702336 -:108F0000930D00012405C00031CA0003A18D0001AA -:108F10008F9000BC8F8900B800F6382196040002BB -:108F20009526001200EA38210085582430C33FFFFF -:108F300001631025A6020002921F000231080004FE -:108F400033F9003F37380040A218000212C0000277 -:108F50008F8500BC00E838218F8600D0ACA70004C4 -:108F6000241FFFBF8CC3007C2ECB0001240FFFDF2A -:108F7000ACA3000890A8000D000B69403102007FEF -:108F8000A0A2000D8F9000BC9219000D033FC024D9 -:108F9000A218000D8F8A00BC914E000D01CF6024F5 -:108FA000018D4825A149000D8F8600B88F8B00BC2C -:108FB0008CC70020AD6700108CC50024AD6500147F -:108FC0008CC40028AD6400188CC3002C0E000D1951 -:108FD000AD63001C2408000257C8009C8F9000D08D -:108FE0008F8F00D08F8A00C002E0202191E800D04E -:108FF00091EB00D091E700D0311000FF316E00FFFF -:1090000000106940000E28C001A5182130E900FFBA -:109010000363C8210009314000CAF82127220088D3 -:10902000AF8200ACAF9F00BCA33E00880E000CF9DD -:109030008F9000AC8FB80020000263803C0F42008C -:10904000019840258F8C00B8010F5825AE0B000405 -:109050008D8400388F8B00AC00002821000539007A -:10906000AD6400188D8E00343C0F7FFF35E8FFFFA4 -:10907000AD6E001C9183003E8D69001C8D6600184A -:109080000003510000036F02012AC02100ED1025EA -:10909000030AF82B00C2C821033F8021AD78001CD1 -:1090A000AD700018AD60000CAD6000109184003E02 -:1090B000241F00052410C000A5640014958E000430 -:1090C00002E8402402E02021A56E00169185003EB2 -:1090D000A5650020958D0004A56D0022AD600024DB -:1090E0009187003FA56700029183003E9189003D72 -:1090F0000123502325460001A16600018F8200ACA8 -:109100008F9900BCAC570008A33F00008F8A00BCB9 -:109110008F9800B8954F0002970E00122418FFBFD9 -:10912000020F682431C53FFF01A53825A54700027D -:10913000914C00022405FFDF3189003F35230040B8 -:10914000A14300028F9900BC8F8600D02409FFFF45 -:10915000AF2000048CCB007C2403FF80AF2B0008E1 -:109160009322000D3C0B8000305F007FA33F000D79 -:109170008F8E00BC91D0000D02187824A1CF000D75 -:109180008F8C00BC918D000D01A53824A187000DA6 -:109190008F8600BCACC90010ACD6001490CA001871 -:1091A0000143B025A0D600188F8F00BC8F9800B85F -:1091B0008DE20018004BF82403E8C825ADF900182B -:1091C0009310003EA1F0001C8F8E00B88F8D00BC64 -:1091D0008F8700D095C50004A5A5001E0E00020DC6 -:1091E0008CE500848F8700D00002614000022100DE -:1091F00090EA00BC01844821004028213156000239 -:1092000012C0000302E930210002B08000D63021F4 -:1092100090EC00BC318400041080000332EA0003AB -:109220000005C08000D83021240900048F9700BCBD -:10923000012A1023305F000300DFC821AEF90004CB -:109240000E000D19A62500388F9000D003C01821FC -:10925000146000020060B0210000902156C000861A -:109260008F9700B80012882B9609001002955023A2 -:109270003C14002002A91021A6020010AF540030B7 -:109280003154FFFF0000000096130010961F0012DB -:1092900013F30011000000008E17000C8E0C000864 -:1092A0000015C98002F94021001927C30119B02B0C -:1092B0000184782101F65821AE08000CAE0B00089D -:1092C0000014A82B023580241200FE6B8F9000D072 -:1092D0000A000F4200000000960B00148E050004E7 -:1092E0003163FFFF000370C000AE3821AF47003C80 -:1092F0008E0600048F4D003C00CDF0231BC00036CD -:10930000000000008E080000250200013C1600103D -:1093100036CF0008AF420038AF4F003000000000E9 -:10932000000000000000000000000000000000003D -:109330000000000000000000000000008F4400005A -:10934000308C00201180FFFD000000008F590400C8 -:109350003C170020AE1900088F550404AE15000C10 -:10936000AF570030000000003C0608008CC60044E7 -:109370002418000110D800D3000000009607001246 -:109380003C0508008CA5004000A76821A60D00122E -:10939000961E001427C90001A609001496020014A5 -:1093A0003044FFFF5486FFC70014A82B30A5FFFFF1 -:1093B0000E000F1DA60000143C0308008C6300245F -:1093C000960500120043702300AE3023A60600125B -:1093D0000A0011480014A82B8E0200000A00115B3D -:1093E0003C1600109156000124100001001678422E -:1093F00015F0001C97A8001E8D5F00142411C000FA -:1094000033FE3FFF0111C8243C1808008F1800608C -:10941000033EB82532E53FFF00B8502B1140001144 -:10942000A7B7001E3C1008008E1000588F8F00B0A8 -:1094300000057180240CFF80020F682101AE4821D5 -:109440003124007F012C5824009A28213C02000E70 -:10945000AF4B002C00A2302190C7000D34E3000474 -:10946000A0C3000D0E000D3B000000008F9000D047 -:10947000240300018F9700B826B900010019AC0041 -:10948000024390230015AC0326F8004002B3202AC3 -:109490000012882B240C000103005021009110249D -:1094A000AF9800B80A000F70AFAC001095560012CC -:1094B0008F8400B032C5FFFF0E000CEEA7B600147B -:1094C0008F9000D00A0011B4000018218D59003887 -:1094D000A620000824040003AE3900008D57003494 -:1094E000A220000A8F9800B8AE3700043C0F00801D -:1094F000930C003FA224000C8E28000C3C0BFF9F15 -:10950000A22C000B010F1825356EFFFF3C05FFEF65 -:109510008F9700B8006E682434A7FFFF01A730249E -:10952000AE26000C8EFE001496FF00128F8200B053 -:10953000AE3E00108EF00014AE200018AE200020C9 -:10954000AE300014AE2000248EE9001833F03FFF47 -:1095500000105180AE2900288EF900080142C02178 -:1095600033EC0001AE3900308EEB000C8F8500AC7F -:10957000001879C2000C238001E44021240E00026F -:10958000A628001CA6200036AE2B002CA0AE0000A2 -:109590009767003C8F8A00AC3C03420030EDFFFF30 -:1095A00001A33025AD4600048F9E00B824020001BF -:1095B0002408C0008FD1003824060034AD510018B3 -:1095C0008FC90034AD49001CAD40000CAD40001007 -:1095D000A5400014A5400016A5400020A54000228B -:1095E000AD400024A5560002A14200018F9F00ACAF -:1095F0008F9900B88F9800BCAFF600089337000031 -:10960000A31700008F8C00B88F8F00BC91840001DD -:10961000A1E400018F8D00BC95AB000201687024AD -:1096200001D02825A5A5000291A7000230E3003F44 -:10963000A1A300028F8300D08F8400BC907100BC76 -:10964000323E000253C0000124060030AC86000404 -:109650008C6F007C2403FFBFAC8F00089088000D46 -:10966000310B007FA08B000D8F8700BC90EE000DAA -:1096700001C32824A0E5000D8F9E00BC93CD000DF2 -:1096800035A60020A3C6000D8F8A00B88F9100BCBC -:109690008D500020AE3000108D490024AE290014FA -:1096A0008D420028AE2200188D5F002CAE3F001CBA -:1096B0000E000D19000000008F9000D00A00112E3E -:1096C00002C01821960A00123C1F08008FFF0024D8 -:1096D00003EA9821A61300120A0011480014A82BCF -:1096E000A08D00018F8900AC240C0001AD2C000876 -:1096F0000A0010488F8300D027BDFFE03C18080007 -:109700008F180050AFB00010AFBF0018AFB10014F9 -:10971000AF8400B093710074030478212410FF809B -:1097200031EE007F3225007F01F0582401DA6821F4 -:109730003C0C000AA38500C401AC2821AF4B0024D7 -:1097400094A900109768000690A600620080382156 -:10975000240200300109202330C300F0AF8500D07F -:10976000106200193090FFFF90AE0062240DFFF0F0 -:10977000240A005001AE6024318B00FF116A002FD3 -:109780000000000016000007241F0C00AF5F00243B -:109790008FB100148FBF00188FB0001003E00008D5 -:1097A00027BD00200E000F2302002021241F0C00E3 -:1097B000AF5F00248FB100148FBF00188FB000106E -:1097C00003E0000827BD002094A200E094A400E27A -:1097D00090BF0113008218263079FFFF33E700C0E5 -:1097E00014E000092F3100011600003800000000CD -:1097F0005620FFE6241F0C000E000DDE00000000C6 -:109800000A00127A241F0C001620FFDE0000000060 -:109810000E000DDE000000001440FFDC241F0C00D1 -:10982000160000228F8300D0906901133122003F7F -:10983000A06201130A00127A241F0C0094AF00D416 -:109840008F8600D400E02821240400050E000C7F40 -:1098500031F0FFFF1440000524030003979100E658 -:10986000000018212625FFFFA78500E68F5801B8C4 -:109870000700FFFE3C196013AF400180241F0C005D -:10988000AF500184007938253C101000AF470188A3 -:109890008FB10014AF5001B8AF5F00248FB000103B -:1098A0008FBF001803E0000827BD00200E000F2323 -:1098B000020020215040FFB5241F0C008F8300D0F0 -:1098C000906901130A0012A33122003F0E000F23FA -:1098D000020020211440FFAD241F0C0012200007BD -:1098E0008F8300D0906801133106003F34C20040DE -:1098F000A06201130A00127A241F0C000E000DDE74 -:10990000000000005040FFA1241F0C008F8300D0F6 -:10991000906801133106003F0A0012D334C20040A0 -:10992000AF9B00C803E00008AF8000EC3089FFFF68 -:10993000000940422D020041000929801440000224 -:109940000009504024080040000879400008C0C0C9 -:1099500001F85821256701A800EF702125CC007F70 -:10996000240DFF80018D18240065302100CA2821B4 -:1099700025640088240A00883C010800AC2A004CB9 -:109980003C010800AC240050AF8500D43C01080025 -:10999000AC2900603C010800AC2800643C010800D0 -:1099A000AC2700543C010800AC2300583C010800DF -:1099B000AC26005C03E0000800000000308300FFDC -:1099C00030C6FFFF30E400FF8F4201B80440FFFEC5 -:1099D00000034C00012438253C08600000E82025E5 -:1099E0003C031000AF450180AF460184AF440188BD -:1099F00003E00008AF4301B88F86001C3C096012E9 -:109A0000352700108CCB00043C0C600E358500100F -:109A1000316A00062D480001ACE800C48CC4000483 -:109A2000ACA431808CC2000894C30002ACA2318483 -:109A300003E00008A78300E43C0308008C630050A7 -:109A40008F8400E88F86001C2402FF800064C02100 -:109A50000302C824AF5900288CCD00043305007FD1 -:109A600000BA78213C0E000C01EE2821ACAD005864 -:109A70008CC80008AF8500D03C076012ACA8005C21 -:109A80008CCC001034E80010ACAC000C8CCB000C7B -:109A9000ACAB000894AA00143C0208008C420044BD -:109AA00025490001A4A9001494A400143083FFFFE9 -:109AB000106200178F8400D03C0A08008D4A0040D5 -:109AC000A4AA00128CCE0018AC8E00248CCD0014F9 -:109AD000AC8D00208CC70018AC87002C8CCC0014F7 -:109AE00024060001AC8C00288D0B00BC5166001AC6 -:109AF0008D0200B48D0200B8A482003A948F003A1F -:109B0000A48F003C948800D403E000083102FFFFDA -:109B10003C0908008D290024A4A000148F8400D0E3 -:109B2000A4A900128CCE0018AC8E00248CCD001499 -:109B3000AC8D00208CC70018AC87002C8CCC001496 -:109B400024060001AC8C00288D0B00BC5566FFEA92 -:109B50008D0200B88D0200B4A482003A948F003ABE -:109B6000A48F003C948800D403E000083102FFFF7A -:109B70008F86001C3C0C08008D8C0050240BFF804D -:109B80008CCD00083C03000C000D51C0018A40211F -:109B9000010B4824AF8A00E8AF49002890C70007AE -:109BA0003105007F00BA10210043282130E4000471 -:109BB0001080002FAF8500D090CF000731EE000855 -:109BC00011C0003C000000008CD9000C8CC40014B3 -:109BD0000324C02B13000026000000008CC2000CE0 -:109BE000ACA200648CCD00182402FFF8ACAD006874 -:109BF0008CCC0010ACAC00808CCB000CACAB0084E7 -:109C00008CCA001CACAA007C90A900BC0122402494 -:109C1000A0A800BC90C300073067000810E0000453 -:109C20008F8500D090AF00BC35EE0001A0AE00BC27 -:109C300090D90007333800011300000F8F8400D043 -:109C400024070020908200BC34490002A08900BC97 -:109C50008F8400D090880062310300F01467000602 -:109C6000240A0034AC8A00C00A0013B500000000CA -:109C70000A00138F8CC2001490CB000731660002DB -:109C800010C0000500000000908D00BC35AC000441 -:109C9000A08C00BC8F8400D090980113330F003F3C -:109CA000A08F01138F8E00D095C500D403E000086B -:109CB00030A2FFFFACA000640A0013900000000077 -:109CC00027BDFFD8AFB000108F90001CAFBF00249D -:109CD000AFB40020AFB20018AFB10014AFB3001C96 -:109CE0009613000E3C07600A3C1460063264FFFFC6 -:109CF000369300100E0012E234F404108F8400D466 -:109D00003C11600E0E0009BE36310010920E001597 -:109D10003C0708008CE700603C12601231CD000F58 -:109D2000A38D00F08E0E00048E0D00089608001220 -:109D3000961F00109619001A9618001E960F001C08 -:109D4000310CFFFF33EBFFFF332AFFFF3309FFFF27 -:109D500031E6FFFF3C010800AC2B00403C0108004D -:109D6000AC2C00243C010800AC2A0044AE29317818 -:109D7000AE26317C92020015960300163652001072 -:109D8000304400FF3065FFFF3C0608008CC60064CD -:109D9000AE243188AE4500B492080014961900181C -:109DA000241F0001011FC004332FFFFF3C050800E2 -:109DB0008CA50058AE5800B8AE4F00BC920C0014F1 -:109DC000AF8E00D8AF8D00DC318B00FFAE4B00C0F2 -:109DD000920A0015AE670048AE66004C314900FF9C -:109DE000AE4900C8AE65007C3C0308008C6300509F -:109DF0003C0408008C84004C3C0808008D0800548A -:109E00003C0208008C42005C8FBF0024AE630080DF -:109E10008FB00010AE8300748FB3001CAE22319C53 -:109E2000AE4200DCAE2731A0AE2631A4AE24318C88 -:109E3000AE233190AE283194AE253198AE870050D4 -:109E4000AE860054AE8500708FB10014AE4700E0BE -:109E5000AE4600E4AE4400CCAE4300D0AE4800D4E1 -:109E6000AE4500D88FB400208FB2001803E0000880 -:109E700027BD002827BDFFE0AFB10014AFBF001819 -:109E8000241100010E000868AFB000101051000549 -:109E9000978400E6978300CC0083102B14400008C1 -:109EA0008F8500D4240700028FBF00188FB10014E3 -:109EB0008FB0001000E0102103E0000827BD002053 -:109EC0000E000C9D24040005AF8200E81040FFF650 -:109ED000240700020E00086C8F90001C979F00E67C -:109EE0008F9900E88F8D00C827EF0001240E0050E5 -:109EF000AF590020A78F00E6A1AE00003C0C08007F -:109F00008D8C00648F8600C8240A8000000C5E00DF -:109F1000ACCB0074A4C0000694C9000A241FFF80C3 -:109F20003C0D000C012AC024A4D8000A90C8000AE5 -:109F300024182000011F1825A0C3000A8F8700C81D -:109F4000A0E000788F8500C800003821A0A0008321 -:109F50003C0208008C4200508F8400E800447821C5 -:109F600001FFC824AF590028960B000231EE007F94 -:109F700001DA6021018D3021A4CB00D4960A0002C1 -:109F8000AF8600D03C0E000425492401A4C900E698 -:109F90008E080004ACC800048E030008ACC30000A7 -:109FA000A4C00010A4C00014A0C000D08F8500D0B1 -:109FB0002403FFBFA0A000D13C0408008C840064EF -:109FC0008F8200D0A04400D28E1F000C8F8A00D058 -:109FD000978F00E4AD5F001C8E1900102410003034 -:109FE000AD590018A5400030A5510054A5510056A8 -:109FF000A54F0016AD4E0068AD580080AD580084E6 -:10A00000914D006231AC000F358B0010A14B006206 -:10A010008F8600D090C900633128007FA0C80063FC -:10A020008F8400D02406FFFF9085006300A31024D6 -:10A03000A08200638F9100D000E01021923F00BC0D -:10A0400037F90001A23900BC8F8A00D0938F00F04D -:10A05000AD580064AD5000C0914E00D3000F6900B0 -:10A0600031CC000F018D5825A14B00D38F8500D036 -:10A070008F8900DCACA900E88F8800D88FBF00185A -:10A080008FB100148FB0001027BD0020ACA800ECE9 -:10A09000A4A600D6A4A000E0A4A000E203E000086B -:10A0A0000000000027BDFFE0AFB000108F90001C43 -:10A0B000AFB10014AFBF00188E1900043C1808009F -:10A0C0008F180050240FFF80001989C002387021BA -:10A0D00031CD007F01CF602401BA50213C0B000C30 -:10A0E000AF4C0028014B4021950900D4950400D6BF -:10A0F0008E0700043131FFFFAF8800D00E00093613 -:10A10000000721C08E0600048F8300C8000629C006 -:10A11000AF4500209064003E3082004014400006AD -:10A120008F8400D0341FFFFF948300D63062FFFF7E -:10A13000145F000400000000948400D60E0008CBD9 -:10A140003084FFFF8E050004022030218FBF0018ED -:10A150008FB100148FB000102404002200003821B9 -:10A16000000529C00A00130627BD002027BDFFE017 -:10A17000AFB100143091FFFFAFB00010AFBF0018B7 -:10A180001220001D000080218F86001C8CC500005D -:10A190002403000600053F020005140230E4000716 -:10A1A00014830015304500FF2CA800061100004D57 -:10A1B000000558803C0C0800258C5A0C016C50217D -:10A1C0008D49000001200008000000008F8E00EC87 -:10A1D000240D000111CD005900000000260B0001E4 -:10A1E0003170FFFF24CA00200211202B01403021D2 -:10A1F0001480FFE6AF8A001C020010218FBF0018F8 -:10A200008FB100148FB0001003E0000827BD0020BC -:10A21000938700CE14E00038240400140E0013C706 -:10A22000000000008F86001C240200010A00150EA9 -:10A23000AF8200EC8F8900EC240800021128003B5B -:10A24000240400130000282100003021240700010D -:10A250000E001306000000000A00150E8F86001C79 -:10A260008F8700EC2405000214E5FFF62404001299 -:10A270000E001373000000008F8500E800403021BD -:10A28000240400120E001306000038210A00150EE7 -:10A290008F86001C8F8300EC241F0003147FFFD0E7 -:10A2A000260B00010E001325000000008F8500E83A -:10A2B0000040302124020002240400100000382154 -:10A2C000AF8200EC0E001306000000000A00150E1D -:10A2D0008F86001C8F8F00EC2406000211E6000B15 -:10A2E000000000002404001000002821000030219C -:10A2F0000A00152B24070001000028210E00130678 -:10A30000000030210A00150E8F86001C0E00143448 -:10A3100000000000144000128F99001C8F86001C62 -:10A32000240200030A00150EAF8200EC0E0014C0D8 -:10A33000000000000A00150E8F86001C0E00131589 -:10A340000000000024020002240400140000282160 -:10A3500000003021000038210A001548AF8200ECCF -:10A360000040382124040010973800020000282102 -:10A370000E0013063306FFFF0A00150E8F86001C21 -:10A380008F8400C83C077FFF34E6FFFF8C85007494 -:10A390002402000100A61824AC83007403E0000826 -:10A3A000A082000510A000362CA20080274A0400DD -:10A3B0003C0B0005240900801040000724080080A1 -:10A3C00030A6000F00C540212D030081146000025B -:10A3D00000A0482124080080AF4B0030000000009E -:10A3E00000000000000000001100000900003821FA -:10A3F000014030218C8D000024E7000400E8602B30 -:10A40000ACCD0000248400041580FFFA24C60004AB -:10A410000000000000000000000000003C0E0006EC -:10A42000010E3825AF47003000000000000000009A -:10A43000000000008F4F000031E800101100FFFD08 -:10A44000000000008F42003C8F43003C0049C821BF -:10A450000323C02B13000004000000008F4C0038C1 -:10A4600025860001AF4600388F47003C00A928230D -:10A4700000E96821AF4D003C14A0FFCE2CA2008063 -:10A4800003E000080000000027BDFFD03C020002EE -:10A49000AFB100143C11000CAF450038AFB3001C45 -:10A4A000AF46003C00809821AF4200302405008870 -:10A4B000AF44002803512021AFBF0028AFB50024CE -:10A4C000AFB40020AFB200180E001580AFB000107E -:10A4D0003C1F08008FFF004C3C1808008F180064D8 -:10A4E0002410FF8003F3A82132B9007F02B0782442 -:10A4F0000018A0C0033A70210018914001D120211A -:10A50000AF4F00280E001580025428213C0D080092 -:10A510008DAD00502405012001B35821316C007F1E -:10A5200001705024019A4821013120210E0015802C -:10A53000AF4A00283C0808008D0800543C0508007C -:10A540008CA500640113382130E6007F00F0182448 -:10A5500000DA202100912021AF4300280E00158051 -:10A56000000529403C0208008C4200583C100800BD -:10A570008E1000601200001C005388212415FF80FB -:10A580000A0016033C14000C3226007F0235182402 -:10A5900000DA202102402821AF4300280094202126 -:10A5A0000E0015802610FFC01200000F0232882115 -:10A5B0002E05004110A0FFF4241210003226007F67 -:10A5C000001091800235182400DA20210240282151 -:10A5D000AF430028009420210E0015800000802148 -:10A5E0001600FFF3023288213C0B08008D6B005CE3 -:10A5F000240AFF802405000201734021010A482437 -:10A60000AF4900283C040800948400623110007FA8 -:10A61000021A88213C07000C0E000CCD022798215D -:10A6200000402821026020218FBF00288FB5002420 -:10A630008FB400208FB3001C8FB200188FB10014AC -:10A640008FB000100A00158027BD00308F83001CDA -:10A650008C620004104000030000000003E00008CA -:10A66000000000008C6400108C6500080A0015B919 -:04A670008C66000CE8 -:0CA67400000000000000001B0000000FB0 -:10A680000000000A000000080000000600000005AD -:10A6900000000005000000040000000400000003AA -:10A6A000000000030000000300000003000000039E -:10A6B0000000000200000002000000020000000292 -:10A6C0000000000200000002000000020000000282 -:10A6D0000000000200000002000000020000000272 -:10A6E0000000000200000002000000020000000163 -:08A6F000000000010000000160 -:08A6F80008000F5808000DB026 -:10A7000008000FEC0800109408000F8008000FC02C -:10A71000080011CC08000DCC080011F008000E1C38 -:10A7200008001630080015D808000DCC08000DCC24 -:10A7300008000DCC0800127C0800127C08000DCC2B -:10A7400008000DCC0800157C08000DCC08000DCCCD -:10A7500008000DCC08000DCC080013EC08000DCC4F -:10A7600008000DCC08000DCC08000DCC08000DCC65 -:10A7700008000DCC08000DCC08000DCC08000DCC55 -:10A7800008000DCC08000DCC08000DCC08000DCC45 -:10A7900008000DCC08000FE008000DCC08000DCC1F -:10A7A0000800152C08000DCC08000DCC08000DCCBD -:10A7B00008000DCC08000DCC08000DCC08000DCC15 -:10A7C00008000DCC08000DCC08000DCC08000DCC05 -:10A7D00008000DCC08000DCC08000DCC08000DCCF5 -:10A7E00008000DCC08000DCC0800145808000DCC52 -:10A7F00008000DCC08001370080012E008002EA01D -:10A8000008002EA808002E7008002E7C08002E8854 -:10A8100008002E94080046C008003F0C080046407F -:10A82000080046C0080046C0080044C0080046C0F2 -:10A830000800470808005530080054F0080054BCD0 -:0CA84000080054900800546C08005428D4 -:04A84C000A000C767C -:10A8500000000000000000000000000D727870355C -:10A860002E302E306A330000050000030000000087 -:10A8700000000001000000000000000000000000D7 -:10A8800000000000000000000000000000000000C8 -:10A8900000000000000000000000000000000000B8 -:10A8A00000000000000000000000000000000000A8 -:10A8B0000000000000000000000000000000000098 -:10A8C0000000000000000000000000000000000088 -:10A8D0000000000000000000000000000000000078 -:10A8E0000000000000000000000000000000000068 -:10A8F0000000000000000000000000000000000058 -:10A900000000000000000000000000000000000047 -:10A910000000000000000000000000000000000037 -:10A920000000000000000000000000000000000027 -:10A930000000000000000000000000000000000017 -:10A940000000000000000000000000000000000007 -:10A9500000000000000000000000000000000000F7 -:10A9600000000000000000000000000000000000E7 -:10A9700000000000000000000000000000000000D7 -:10A9800000000000000000000000000000000000C7 -:10A9900000000000000000000000000000000000B7 -:10A9A00000000000000000000000000000000000A7 -:10A9B0000000000000000000000000000000000097 -:10A9C0000000000000000000000000000000000087 -:10A9D0000000000000000000000000000000000077 -:10A9E0000000000000000000000000000000000067 -:10A9F0000000000000000000000000000000000057 -:10AA00000000000000000000000000000000000046 -:10AA10000000000000000000000000000000000036 -:10AA20000000000000000000000000000000000026 -:10AA30000000000000000000000000000000000016 -:10AA40000000000000000000000000000000000006 -:10AA500000000000000000000000000000000000F6 -:10AA600000000000000000000000000000000000E6 -:10AA700000000000000000000000000000000000D6 -:10AA800000000000000000000000000000000000C6 -:10AA900000000000000000000000000000000000B6 -:10AAA00000000000000000000000000000000000A6 -:10AAB0000000000000000000000000000000000096 -:10AAC0000000000000000000000000000000000086 -:10AAD0000000000000000000000000000000000076 -:10AAE0000000000000000000000000000000000066 -:10AAF0000000000000000000000000000000000056 -:10AB00000000000000000000000000000000000045 -:10AB10000000000000000000000000000000000035 -:10AB20000000000000000000000000000000000025 -:10AB30000000000000000000000000000000000015 -:10AB40000000000000000000000000000000000005 -:10AB500000000000000000000000000000000000F5 -:10AB600000000000000000000000000000000000E5 -:10AB700000000000000000000000000000000000D5 -:10AB800000000000000000000000000000000000C5 -:10AB900000000000000000000000000000000000B5 -:10ABA00000000000000000000000000000000000A5 -:10ABB0000000000000000000000000000000000095 -:10ABC0000000000000000000000000000000000085 -:10ABD0000000000000000000000000000000000075 -:10ABE0000000000000000000000000000000000065 -:10ABF0000000000000000000000000000000000055 -:10AC00000000000000000000000000000000000044 -:10AC10000000000000000000000000000000000034 -:10AC20000000000000000000000000000000000024 -:10AC30000000000000000000000000000000000014 -:10AC40000000000000000000000000000000000004 -:10AC500000000000000000000000000000000000F4 -:10AC600000000000000000000000000000000000E4 -:10AC700000000000000000000000000000000000D4 -:10AC800000000000000000000000000000000000C4 -:10AC900000000000000000000000000000000000B4 -:10ACA00000000000000000000000000000000000A4 -:10ACB0000000000000000000000000000000000094 -:10ACC0000000000000000000000000000000000084 -:10ACD0000000000000000000000000000000000074 -:10ACE0000000000000000000000000000000000064 -:10ACF0000000000000000000000000000000000054 -:10AD00000000000000000000000000000000000043 -:10AD10000000000000000000000000000000000033 -:10AD20000000000000000000000000000000000023 -:10AD30000000000000000000000000000000000013 -:10AD40000000000000000000000000000000000003 -:10AD500000000000000000000000000000000000F3 -:10AD600000000000000000000000000000000000E3 -:10AD700000000000000000000000000000000000D3 -:10AD800000000000000000000000000000000000C3 -:10AD900000000000000000000000000000000000B3 -:10ADA00000000000000000000000000000000000A3 -:10ADB0000000000000000000000000000000000093 -:10ADC0000000000000000000000000000000000083 -:10ADD0000000000000000000000000000000000073 -:10ADE0000000000000000000000000000000000063 -:10ADF0000000000000000000000000000000000053 -:10AE00000000000000000000000000000000000042 -:10AE10000000000000000000000000000000000032 -:10AE20000000000000000000000000000000000022 -:10AE30000000000000000000000000000000000012 -:10AE40000000000000000000000000000000000002 -:10AE500000000000000000000000000000000000F2 -:10AE600000000000000000000000000000000000E2 -:10AE700000000000000000000000000000000000D2 -:10AE800000000000000000000000000000000000C2 -:10AE900000000000000000000000000000000000B2 -:10AEA00000000000000000000000000000000000A2 -:10AEB0000000000000000000000000000000000092 -:10AEC0000000000000000000000000000000000082 -:10AED0000000000000000000000000000000000072 -:10AEE0000000000000000000000000000000000062 -:10AEF0000000000000000000000000000000000052 -:10AF00000000000000000000000000000000000041 -:10AF10000000000000000000000000000000000031 -:10AF20000000000000000000000000000000000021 -:10AF30000000000000000000000000000000000011 -:10AF40000000000000000000000000000000000001 -:10AF500000000000000000000000000000000000F1 -:10AF600000000000000000000000000000000000E1 -:10AF700000000000000000000000000000000000D1 -:10AF800000000000000000000000000000000000C1 -:10AF900000000000000000000000000000000000B1 -:10AFA00000000000000000000000000000000000A1 -:10AFB0000000000000000000000000000000000091 -:10AFC0000000000000000000000000000000000081 -:10AFD0000000000000000000000000000000000071 -:10AFE0000000000000000000000000000000000061 -:10AFF0000000000000000000000000000000000051 -:10B000000000000000000000000000000000000040 -:10B010000000000000000000000000000000000030 -:10B020000000000000000000000000000000000020 -:10B030000000000000000000000000000000000010 -:10B040000000000000000000000000000000000000 -:10B0500000000000000000000000000000000000F0 -:10B0600000000000000000000000000000000000E0 -:10B0700000000000000000000000000000000000D0 -:10B0800000000000000000000000000000000000C0 -:10B0900000000000000000000000000000000000B0 -:10B0A00000000000000000000000000000000000A0 -:10B0B0000000000000000000000000000000000090 -:10B0C0000000000000000000000000000000000080 -:10B0D0000000000000000000000000000000000070 -:10B0E0000000000000000000000000000000000060 -:10B0F0000000000000000000000000000000000050 -:10B10000000000000000000000000000000000003F -:10B11000000000000000000000000000000000002F -:10B12000000000000000000000000000000000001F -:10B13000000000000000000000000000000000000F -:10B1400000000000000000000000000000000000FF -:10B1500000000000000000000000000000000000EF -:10B1600000000000000000000000000000000000DF -:10B1700000000000000000000000000000000000CF -:10B1800000000000000000000000000000000000BF -:10B1900000000000000000000000000000000000AF -:10B1A000000000000000000000000000000000009F -:10B1B000000000000000000000000000000000008F -:10B1C000000000000000000000000000000000007F -:10B1D000000000000000000000000000000000006F -:10B1E000000000000000000000000000000000005F -:10B1F000000000000000000000000000000000004F -:10B20000000000000000000000000000000000003E -:10B21000000000000000000000000000000000002E -:10B22000000000000000000000000000000000001E -:10B23000000000000000000000000000000000000E -:10B2400000000000000000000000000000000000FE -:10B2500000000000000000000000000000000000EE -:10B2600000000000000000000000000000000000DE -:10B2700000000000000000000000000000000000CE -:10B2800000000000000000000000000000000000BE -:10B2900000000000000000000000000000000000AE -:10B2A000000000000000000000000000000000009E -:10B2B000000000000000000000000000000000008E -:10B2C000000000000000000000000000000000007E -:10B2D000000000000000000000000000000000006E -:10B2E000000000000000000000000000000000005E -:10B2F000000000000000000000000000000000004E -:10B30000000000000000000000000000000000003D -:10B31000000000000000000000000000000000002D -:10B32000000000000000000000000000000000001D -:10B33000000000000000000000000000000000000D -:10B3400000000000000000000000000000000000FD -:10B3500000000000000000000000000000000000ED -:10B3600000000000000000000000000000000000DD -:10B3700000000000000000000000000000000000CD -:10B3800000000000000000000000000000000000BD -:10B3900000000000000000000000000000000000AD -:10B3A000000000000000000000000000000000009D -:10B3B000000000000000000000000000000000008D -:10B3C000000000000000000000000000000000007D -:10B3D000000000000000000000000000000000006D -:10B3E000000000000000000000000000000000005D -:10B3F000000000000000000000000000000000004D -:10B40000000000000000000000000000000000003C -:10B41000000000000000000000000000000000002C -:10B42000000000000000000000000000000000001C -:10B43000000000000000000000000000000000000C -:10B4400000000000000000000000000000000000FC -:10B4500000000000000000000000000000000000EC -:10B4600000000000000000000000000000000000DC -:10B4700000000000000000000000000000000000CC -:10B4800000000000000000000000000000000000BC -:10B4900000000000000000000000000000000000AC -:10B4A000000000000000000000000000000000009C -:10B4B000000000000000000000000000000000008C -:10B4C000000000000000000000000000000000007C -:10B4D000000000000000000000000000000000006C -:10B4E000000000000000000000000000000000005C -:10B4F000000000000000000000000000000000004C -:10B50000000000000000000000000000000000003B -:10B51000000000000000000000000000000000002B -:10B52000000000000000000000000000000000001B -:10B53000000000000000000000000000000000000B -:10B5400000000000000000000000000000000000FB -:10B5500000000000000000000000000000000000EB -:10B5600000000000000000000000000000000000DB -:10B5700000000000000000000000000000000000CB -:10B5800000000000000000000000000000000000BB -:10B5900000000000000000000000000000000000AB -:10B5A000000000000000000000000000000000009B -:10B5B000000000000000000000000000000000008B -:10B5C000000000000000000000000000000000007B -:10B5D000000000000000000000000000000000006B -:10B5E000000000000000000000000000000000005B -:10B5F000000000000000000000000000000000004B -:10B60000000000000000000000000000000000003A -:10B61000000000000000000000000000000000002A -:10B62000000000000000000000000000000000001A -:10B63000000000000000000000000000000000000A -:10B6400000000000000000000000000000000000FA -:10B6500000000000000000000000000000000000EA -:10B6600000000000000000000000000000000000DA -:10B6700000000000000000000000000000000000CA -:10B6800000000000000000000000000000000000BA -:10B6900000000000000000000000000000000000AA -:10B6A000000000000000000000000000000000009A -:10B6B000000000000000000000000000000000008A -:10B6C000000000000000000000000000000000007A -:10B6D000000000000000000000000000000000006A -:10B6E000000000000000000000000000000000005A -:10B6F000000000000000000000000000000000004A -:10B700000000000000000000000000000000000039 -:10B710000000000000000000000000000000000029 -:10B720000000000000000000000000000000000019 -:10B730000000000000000000000000000000000009 -:10B7400000000000000000000000000000000000F9 -:10B7500000000000000000000000000000000000E9 -:10B7600000000000000000000000000000000000D9 -:10B7700000000000000000000000000000000000C9 -:10B7800000000000000000000000000000000000B9 -:10B7900000000000000000000000000000000000A9 -:10B7A0000000000000000000000000000000000099 -:10B7B0000000000000000000000000000000000089 -:10B7C0000000000000000000000000000000000079 -:10B7D0000000000000000000000000000000000069 -:10B7E0000000000000000000000000000000000059 -:10B7F0000000000000000000000000000000000049 -:10B800000000000000000000000000000000000038 -:10B810000000000000000000000000000000000028 -:10B820000000000000000000000000000000000018 -:10B830000000000000000000000000000000000008 -:10B8400000000000000000000000000000000000F8 -:10B8500000000000000000000000000000000000E8 -:10B8600000000000000000000000000000000000D8 -:10B8700000000000000000000000000000000000C8 -:10B8800000000000000000000000000000000000B8 -:10B8900000000000000000000000000000000000A8 -:10B8A0000000000000000000000000000000000098 -:10B8B0000000000000000000000000000000000088 -:10B8C0000000000000000000000000000000000078 -:10B8D0000000000000000000000000000000000068 -:10B8E0000000000000000000000000000000000058 -:10B8F0000000000000000000000000000000000048 -:10B900000000000000000000000000000000000037 -:10B910000000000000000000000000000000000027 -:10B920000000000000000000000000000000000017 -:10B930000000000000000000000000000000000007 -:10B9400000000000000000000000000000000000F7 -:10B9500000000000000000000000000000000000E7 -:10B9600000000000000000000000000000000000D7 -:10B9700000000000000000000000000000000000C7 -:10B9800000000000000000000000000000000000B7 -:10B9900000000000000000000000000000000000A7 -:10B9A0000000000000000000000000000000000097 -:10B9B0000000000000000000000000000000000087 -:10B9C0000000000000000000000000000000000077 -:10B9D0000000000000000000000000000000000067 -:10B9E0000000000000000000000000000000000057 -:10B9F0000000000000000000000000000000000047 -:10BA00000000000000000000000000000000000036 -:10BA10000000000000000000000000000000000026 -:10BA20000000000000000000000000000000000016 -:10BA30000000000000000000000000000000000006 -:10BA400000000000000000000000000000000000F6 -:10BA500000000000000000000000000000000000E6 -:10BA600000000000000000000000000000000000D6 -:10BA700000000000000000000000000000000000C6 -:10BA800000000000000000000000000000000000B6 -:10BA900000000000000000000000000000000000A6 -:10BAA0000000000000000000000000000000000096 -:10BAB0000000000000000000000000000000000086 -:10BAC0000000000000000000000000000000000076 -:10BAD0000000000000000000000000000000000066 -:10BAE0000000000000000000000000000000000056 -:10BAF0000000000000000000000000000000000046 -:10BB00000000000000000000000000000000000035 -:10BB10000000000000000000000000000000000025 -:10BB20000000000000000000000000000000000015 -:10BB30000000000000000000000000000000000005 -:10BB400000000000000000000000000000000000F5 -:10BB500000000000000000000000000000000000E5 -:10BB600000000000000000000000000000000000D5 -:10BB700000000000000000000000000000000000C5 -:10BB800000000000000000000000000000000000B5 -:10BB900000000000000000000000000000000000A5 -:10BBA0000000000000000000000000000000000095 -:10BBB0000000000000000000000000000000000085 -:10BBC0000000000000000000000000000000000075 -:10BBD0000000000000000000000000000000000065 -:10BBE0000000000000000000000000000000000055 -:10BBF0000000000000000000000000000000000045 -:10BC00000000000000000000000000000000000034 -:10BC10000000000000000000000000000000000024 -:10BC20000000000000000000000000000000000014 -:10BC30000000000000000000000000000000000004 -:10BC400000000000000000000000000000000000F4 -:10BC500000000000000000000000000000000000E4 -:10BC600000000000000000000000000000000000D4 -:10BC700000000000000000000000000000000000C4 -:10BC800000000000000000000000000000000000B4 -:10BC900000000000000000000000000000000000A4 -:10BCA0000000000000000000000000000000000094 -:10BCB0000000000000000000000000000000000084 -:10BCC0000000000000000000000000000000000074 -:10BCD0000000000000000000000000000000000064 -:10BCE0000000000000000000000000000000000054 -:10BCF0000000000000000000000000000000000044 -:10BD00000000000000000000000000000000000033 -:10BD10000000000000000000000000000000000023 -:10BD20000000000000000000000000000000000013 -:10BD30000000000000000000000000000000000003 -:10BD400000000000000000000000000000000000F3 -:10BD500000000000000000000000000000000000E3 -:10BD600000000000000000000000000000000000D3 -:10BD700000000000000000000000000000000000C3 -:10BD800000000000000000000000000000000000B3 -:10BD900000000000000000000000000000000000A3 -:10BDA0000000000000000000000000000000000093 -:10BDB0000000000000000000000000000000000083 -:10BDC0000000000000000000000000000000000073 -:10BDD0000000000000000000000000000000000063 -:10BDE0000000000000000000000000000000000053 -:10BDF0000000000000000000000000000000000043 -:10BE00000000000000000000000000000000000032 -:10BE10000000000000000000000000000000000022 -:10BE20000000000000000000000000000000000012 -:10BE30000000000000000000000000000000000002 -:10BE400000000000000000000000000000000000F2 -:10BE500000000000000000000000000000000000E2 -:10BE600000000000000000000000000000000000D2 -:10BE700000000000000000000000000000000000C2 -:10BE800000000000000000000000000000000000B2 -:10BE900000000000000000000000000000000000A2 -:10BEA0000000000000000000000000000000000092 -:10BEB0000000000000000000000000000000000082 -:10BEC0000000000000000000000000000000000072 -:10BED0000000000000000000000000000000000062 -:10BEE0000000000000000000000000000000000052 -:10BEF0000000000000000000000000000000000042 -:10BF00000000000000000000000000000000000031 -:10BF10000000000000000000000000000000000021 -:10BF20000000000000000000000000000000000011 -:10BF30000000000000000000000000000000000001 -:10BF400000000000000000000000000000000000F1 -:10BF500000000000000000000000000000000000E1 -:10BF600000000000000000000000000000000000D1 -:10BF700000000000000000000000000000000000C1 -:10BF800000000000000000000000000000000000B1 -:10BF900000000000000000000000000000000000A1 -:10BFA0000000000000000000000000000000000091 -:10BFB0000000000000000000000000000000000081 -:10BFC0000000000000000000000000000000000071 -:10BFD0000000000000000000000000000000000061 -:10BFE0000000000000000000000000000000000051 -:10BFF0000000000000000000000000000000000041 -:10C000000000000000000000000000000000000030 -:10C010000000000000000000000000000000000020 -:10C020000000000000000000000000000000000010 -:10C030000000000000000000000000000000000000 -:10C0400000000000000000000000000000000000F0 -:10C0500000000000000000000000000000000000E0 -:10C0600000000000000000000000000000000000D0 -:10C0700000000000000000000000000000000000C0 -:10C0800000000000000000000000000000000000B0 -:10C0900000000000000000000000000000000000A0 -:10C0A0000000000000000000000000000000000090 -:10C0B0000000000000000000000000000000000080 -:10C0C0000000000000000000000000000000000070 -:10C0D0000000000000000000000000000000000060 -:10C0E0000000000000000000000000000000000050 -:10C0F0000000000000000000000000000000000040 -:10C10000000000000000000000000000000000002F -:10C11000000000000000000000000000000000001F -:10C12000000000000000000000000000000000000F -:10C1300000000000000000000000000000000000FF -:10C1400000000000000000000000000000000000EF -:10C1500000000000000000000000000000000000DF -:10C1600000000000000000000000000000000000CF -:10C1700000000000000000000000000000000000BF -:10C1800000000000000000000000000000000000AF -:10C19000000000000000000000000000000000009F -:10C1A000000000000000000000000000000000008F -:10C1B000000000000000000000000000000000007F -:10C1C000000000000000000000000000000000006F -:10C1D000000000000000000000000000000000005F -:10C1E000000000000000000000000000000000004F -:10C1F000000000000000000000000000000000003F -:10C20000000000000000000000000000000000002E -:10C21000000000000000000000000000000000001E -:10C22000000000000000000000000000000000000E -:10C2300000000000000000000000000000000000FE -:10C2400000000000000000000000000000000000EE -:10C2500000000000000000000000000000000000DE -:10C2600000000000000000000000000000000000CE -:10C2700000000000000000000000000000000000BE -:10C2800000000000000000000000000000000000AE -:10C29000000000000000000000000000000000009E -:10C2A000000000000000000000000000000000008E -:10C2B000000000000000000000000000000000007E -:10C2C000000000000000000000000000000000006E -:10C2D000000000000000000000000000000000005E -:10C2E000000000000000000000000000000000004E -:10C2F000000000000000000000000000000000003E -:10C30000000000000000000000000000000000002D -:10C31000000000000000000000000000000000001D -:10C32000000000000000000000000000000000000D -:10C3300000000000000000000000000000000000FD -:10C3400000000000000000000000000000000000ED -:10C3500000000000000000000000000000000000DD -:10C3600000000000000000000000000000000000CD -:10C3700000000000000000000000000000000000BD -:10C3800000000000000000000000000000000000AD -:10C39000000000000000000000000000000000009D -:10C3A000000000000000000000000000000000008D -:10C3B000000000000000000000000000000000007D -:10C3C000000000000000000000000000000000006D -:10C3D000000000000000000000000000000000005D -:10C3E000000000000000000000000000000000004D -:10C3F000000000000000000000000000000000003D -:10C40000000000000000000000000000000000002C -:10C41000000000000000000000000000000000001C -:10C42000000000000000000000000000000000000C -:10C4300000000000000000000000000000000000FC -:10C4400000000000000000000000000000000000EC -:10C4500000000000000000000000000000000000DC -:10C4600000000000000000000000000000000000CC -:10C4700000000000000000000000000000000000BC -:10C4800000000000000000000000000000000000AC -:10C49000000000000000000000000000000000009C -:10C4A000000000000000000000000000000000008C -:10C4B000000000000000000000000000000000007C -:10C4C000000000000000000000000000000000006C -:10C4D000000000000000000000000000000000005C -:10C4E000000000000000000000000000000000004C -:10C4F000000000000000000000000000000000003C -:10C50000000000000000000000000000000000002B -:10C51000000000000000000000000000000000001B -:10C52000000000000000000000000000000000000B -:10C5300000000000000000000000000000000000FB -:10C5400000000000000000000000000000000000EB -:10C5500000000000000000000000000000000000DB -:10C5600000000000000000000000000000000000CB -:10C5700000000000000000000000000000000000BB -:10C5800000000000000000000000000000000000AB -:10C59000000000000000000000000000000000009B -:10C5A000000000000000000000000000000000008B -:10C5B000000000000000000000000000000000007B -:10C5C000000000000000000000000000000000006B -:10C5D000000000000000000000000000000000005B -:10C5E000000000000000000000000000000000004B -:10C5F000000000000000000000000000000000003B -:10C60000000000000000000000000000000000002A -:10C61000000000000000000000000000000000001A -:10C62000000000000000000000000000000000000A -:10C6300000000000000000000000000000000000FA -:10C6400000000000000000000000000000000000EA -:10C6500000000000000000000000000000000000DA -:10C6600000000000000000000000000000000000CA -:10C6700000000000000000000000000000000000BA -:10C6800000000000000000000000000000000000AA -:10C69000000000000000000000000000000000009A -:10C6A000000000000000000000000000000000008A -:10C6B000000000000000000000000000000000007A -:10C6C000000000000000000000000000000000006A -:10C6D000000000000000000000000000000000005A -:10C6E000000000000000000000000000000000004A -:10C6F000000000000000000000000000000000003A -:10C700000000000000000000000000000000000029 -:10C710000000000000000000000000000000000019 -:10C720000000000000000000000000000000000009 -:10C7300000000000000000000000000000000000F9 -:10C7400000000000000000000000000000000000E9 -:10C7500000000000000000000000000000000000D9 -:10C7600000000000000000000000000000000000C9 -:10C7700000000000000000000000000000000000B9 -:10C7800000000000000000000000000000000000A9 -:10C790000000000000000000000000000000000099 -:10C7A0000000000000000000000000000000000089 -:10C7B0000000000000000000000000000000000079 -:10C7C0000000000000000000000000000000000069 -:10C7D0000000000000000000000000000000000059 -:10C7E0000000000000000000000000000000000049 -:10C7F0000000000000000000000000000000000039 -:10C800000000000000000000000000000000000028 -:10C810000000000000000000000000000000000018 -:10C820000000000000000000000000000000000008 -:10C8300000000000000000000000000000000000F8 -:10C8400000000000000000000000000000000000E8 -:10C8500000000000000000000000000000000000D8 -:10C8600000000000000000000000000000000000C8 -:10C8700000000000000000000000000000000000B8 -:10C8800000000000000000000000000000000000A8 -:10C890000000000000000000000000000000000098 -:10C8A0000000000000000000000000000000000088 -:10C8B0000000000000000000000000000000000078 -:10C8C0000000000000000000000000000000000068 -:10C8D0000000000000000000000000000000000058 -:10C8E0000000000000000000000000000000000048 -:10C8F0000000000000000000000000000000000038 -:10C900000000000000000000000000000000000027 -:10C910000000000000000000000000000000000017 -:10C920000000000000000000000000000000000007 -:10C9300000000000000000000000000000000000F7 -:10C9400000000000000000000000000000000000E7 -:10C9500000000000000000000000000000000000D7 -:10C9600000000000000000000000000000000000C7 -:10C9700000000000000000000000000000000000B7 -:10C9800000000000000000000000000000000000A7 -:10C990000000000000000000000000000000000097 -:10C9A0000000000000000000000000000000000087 -:10C9B0000000000000000000000000000000000077 -:10C9C0000000000000000000000000000000000067 -:10C9D0000000000000000000000000000000000057 -:10C9E0000000000000000000000000000000000047 -:10C9F0000000000000000000000000000000000037 -:10CA00000000000000000000000000000000000026 -:10CA10000000000000000000000000000000000016 -:10CA20000000000000000000000000000000000006 -:10CA300000000000000000000000000000000000F6 -:10CA400000000000000000000000000000000000E6 -:10CA500000000000000000000000000000000000D6 -:10CA600000000000000000000000000000000000C6 -:10CA700000000000000000000000000000000000B6 -:10CA800000000000000000000000000000000000A6 -:10CA90000000000000000000000000000000000096 -:10CAA0000000000000000000000000000000000086 -:10CAB0000000000000000000000000000000000076 -:10CAC0000000000000000000000000000000000066 -:10CAD0000000000000000000000000000000000056 -:10CAE0000000000000000000000000000000000046 -:10CAF0000000000000000000000000000000000036 -:10CB00000000000000000000000000000000000025 -:10CB10000000000000000000000000000000000015 -:10CB20000000000000000000000000000000000005 -:10CB300000000000000000000000000000000000F5 -:10CB400000000000000000000000000000000000E5 -:10CB500000000000000000000000000000000000D5 -:10CB600000000000000000000000000000000000C5 -:10CB700000000000000000000000000000000000B5 -:10CB800000000000000000000000000000000000A5 -:10CB90000000000000000000000000000000000095 -:10CBA0000000000000000000000000000000000085 -:10CBB0000000000000000000000000000000000075 -:10CBC0000000000000000000000000000000000065 -:10CBD0000000000000000000000000000000000055 -:10CBE0000000000000000000000000000000000045 -:10CBF0000000000000000000000000000000000035 -:10CC00000000000000000000000000000000000024 -:10CC10000000000000000000000000000000000014 -:10CC20000000000000000000000000000000000004 -:10CC300000000000000000000000000000000000F4 -:10CC400000000000000000000000000000000000E4 -:10CC500000000000000000000000000000000000D4 -:10CC600000000000000000000000000000000000C4 -:10CC700000000000000000000000000000000000B4 -:10CC800000000000000000000000000000000000A4 -:10CC90000000000000000000000000000000000094 -:10CCA0000000000000000000000000000000000084 -:10CCB0000000000000000000000000000000000074 -:10CCC0000000000000000000000000000000000064 -:10CCD0000000000000000000000000000000000054 -:10CCE0000000000000000000000000000000000044 -:10CCF0000000000000000000000000000000000034 -:10CD00000000000000000000000000000000000023 -:10CD10000000000000000000000000000000000013 -:10CD20000000000000000000000000000000000003 -:10CD300000000000000000000000000000000000F3 -:10CD400000000000000000000000000000000000E3 -:10CD500000000000000000000000000000000000D3 -:10CD600000000000000000000000000000000000C3 -:10CD700000000000000000000000000000000000B3 -:10CD800000000000000000000000000000000000A3 -:10CD90000000000000000000000000000000000093 -:10CDA0000000000000000000000000000000000083 -:10CDB0000000000000000000000000000000000073 -:10CDC0000000000000000000000000000000000063 -:10CDD0000000000000000000000000000000000053 -:10CDE0000000000000000000000000000000000043 -:10CDF0000000000000000000000000000000000033 -:10CE00000000000000000000000000000000000022 -:10CE10000000000000000000000000000000000012 -:10CE20000000000000000000000000000000000002 -:10CE300000000000000000000000000000000000F2 -:10CE400000000000000000000000000000000000E2 -:10CE500000000000000000000000000000000000D2 -:10CE600000000000000000000000000000000000C2 -:10CE700000000000000000000000000000000000B2 -:10CE800000000000000000000000000000000000A2 -:10CE90000000000000000000000000000000000092 -:10CEA0000000000000000000000000000000000082 -:10CEB0000000000000000000000000000000000072 -:10CEC0000000000000000000000000000000000062 -:10CED0000000000000000000000000000000000052 -:10CEE0000000000000000000000000000000000042 -:10CEF0000000000000000000000000000000000032 -:10CF00000000000000000000000000000000000021 -:10CF10000000000000000000000000000000000011 -:10CF20000000000000000000000000000000000001 -:10CF300000000000000000000000000000000000F1 -:10CF400000000000000000000000000000000000E1 -:10CF500000000000000000000000000000000000D1 -:10CF600000000000000000000000000000000000C1 -:10CF700000000000000000000000000000000000B1 -:10CF800000000000000000000000000000000000A1 -:10CF90000000000000000000000000000000000091 -:10CFA0000000000000000000000000000000000081 -:10CFB0000000000000000000000000000000000071 -:10CFC0000000000000000000000000000000000061 -:10CFD0000000000000000000000000000000000051 -:10CFE0000000000000000000000000000000000041 -:10CFF0000000000000000000000000000000000031 -:10D000000000000000000000000000000000000020 -:10D010000000000000000000000000000000000010 -:10D020000000000000000000000000000000000000 -:10D0300000000000000000000000000000000000F0 -:10D0400000000000000000000000000000000000E0 -:10D0500000000000000000000000000000000000D0 -:10D0600000000000000000000000000000000000C0 -:10D0700000000000000000000000000000000000B0 -:10D0800000000000000000000000000000000000A0 -:10D090000000000000000000000000000000000090 -:10D0A0000000000000000000000000000000000080 -:10D0B0000000000000000000000000000000000070 -:10D0C0000000000000000000000000000000000060 -:10D0D0000000000000000000000000000000000050 -:10D0E0000000000000000000000000000000000040 -:10D0F0000000000000000000000000000000000030 -:10D10000000000000000000000000000000000001F -:10D11000000000000000000000000000000000000F -:10D1200000000000000000000000000000000000FF -:10D1300000000000000000000000000000000000EF -:10D1400000000000000000000000000000000000DF -:10D1500000000000000000000000000000000000CF -:10D1600000000000000000000000000000000000BF -:10D1700000000000000000000000000000000000AF -:10D18000000000000000000000000000000000009F -:10D19000000000000000000000000000000000008F -:10D1A000000000000000000000000000000000007F -:10D1B000000000000000000000000000000000006F -:10D1C000000000000000000000000000000000005F -:10D1D000000000000000000000000000000000004F -:10D1E000000000000000000000000000000000003F -:10D1F000000000000000000000000000000000002F -:10D20000000000000000000000000000000000001E -:10D21000000000000000000000000000000000000E -:10D2200000000000000000000000000000000000FE -:10D2300000000000000000000000000000000000EE -:10D2400000000000000000000000000000000000DE -:10D2500000000000000000000000000000000000CE -:10D2600000000000000000000000000000000000BE -:10D2700000000000000000000000000000000000AE -:10D28000000000000000000000000000000000009E -:10D29000000000000000000000000000000000008E -:10D2A000000000000000000000000000000000007E -:10D2B000000000000000000000000000000000006E -:10D2C000000000000000000000000000000000005E -:10D2D000000000000000000000000000000000004E -:10D2E000000000000000000000000000000000003E -:10D2F000000000000000000000000000000000002E -:10D30000000000000000000000000000000000001D -:10D31000000000000000000000000000000000000D -:10D3200000000000000000000000000000000000FD -:10D3300000000000000000000000000000000000ED -:10D3400000000000000000000000000000000000DD -:10D3500000000000000000000000000000000000CD -:10D3600000000000000000000000000000000000BD -:10D3700000000000000000000000000000000000AD -:10D38000000000000000000000000000000000009D -:10D39000000000000000000000000000000000008D -:10D3A000000000000000000000000000000000007D -:10D3B000000000000000000000000000000000006D -:10D3C000000000000000000000000000000000005D -:10D3D000000000000000000000000000000000004D -:10D3E000000000000000000000000000000000003D -:10D3F000000000000000000000000000000000002D -:10D40000000000000000000000000000000000001C -:10D41000000000000000000000000000000000000C -:10D4200000000000000000000000000000000000FC -:10D4300000000000000000000000000000000000EC -:10D4400000000000000000000000000000000000DC -:10D4500000000000000000000000000000000000CC -:10D4600000000000000000000000000000000000BC -:10D4700000000000000000000000000000000000AC -:10D48000000000000000000000000000000000009C -:10D49000000000000000000000000000000000008C -:10D4A000000000000000000000000000000000007C -:10D4B000000000000000000000000000000000006C -:10D4C000000000000000000000000000000000005C -:10D4D000000000000000000000000000000000004C -:10D4E000000000000000000000000000000000003C -:10D4F000000000000000000000000000000000002C -:10D50000000000000000000000000000000000001B -:10D51000000000000000000000000000000000000B -:10D5200000000000000000000000000000000000FB -:10D5300000000000000000000000000000000000EB -:10D5400000000000000000000000000000000000DB -:10D5500000000000000000000000000000000000CB -:10D5600000000000000000000000000000000000BB -:10D5700000000000000000000000000000000000AB -:10D58000000000000000000000000000000000009B -:10D59000000000000000000000000000000000008B -:10D5A000000000000000000000000000000000007B -:10D5B000000000000000000000000000000000006B -:10D5C000000000000000000000000000000000005B -:10D5D000000000000000000000000000000000004B -:10D5E000000000000000000000000000000000003B -:10D5F000000000000000000000000000000000002B -:10D60000000000000000000000000000000000001A -:10D61000000000000000000000000000000000000A -:10D6200000000000000000000000000000000000FA -:10D6300000000000000000000000000000000000EA -:10D6400000000000000000000000000000000000DA -:10D6500000000000000000000000000000000000CA -:10D6600000000000000000000000000000000000BA -:10D6700000000000000000000000000000000000AA -:10D68000000000000000000000000000000000009A -:10D69000000000000000000000000000000000008A -:10D6A000000000000000000000000000000000007A -:10D6B000000000000000000000000000000000006A -:10D6C000000000000000000000000000000000005A -:10D6D000000000000000000000000000000000004A -:10D6E000000000000000000000000000000000003A -:10D6F000000000000000000000000000000000002A -:10D700000000000000000000000000000000000019 -:10D710000000000000000000000000000000000009 -:10D7200000000000000000000000000000000000F9 -:10D7300000000000000000000000000000000000E9 -:10D7400000000000000000000000000000000000D9 -:10D7500000000000000000000000000000000000C9 -:10D7600000000000000000000000000000000000B9 -:10D7700000000000000000000000000000000000A9 -:10D780000000000000000000000000000000000099 -:10D790000000000000000000000000000000000089 -:10D7A0000000000000000000000000000000000079 -:10D7B0000000000000000000000000000000000069 -:10D7C0000000000000000000000000000000000059 -:10D7D0000000000000000000000000000000000049 -:10D7E0000000000000000000000000000000000039 -:10D7F0000000000000000000000000000000000029 -:10D800000000000000000000000000000000000018 -:10D810000000000000000000000000000000000008 -:10D8200000000000000000000000000000000000F8 -:10D8300000000000000000000000000000000000E8 -:10D8400000000000000000000000000000000000D8 -:10D8500000000000000000000000000000000000C8 -:10D8600000000000000000000000000000000000B8 -:10D8700000000000000000000000000000000000A8 -:10D880000000000000000000000000000000000098 -:10D890000000000000000000000000000000000088 -:10D8A0000000000000000000000000000000000078 -:10D8B0000000000000000000000000000000000068 -:10D8C0000000000000000000000000000000000058 -:10D8D0000000000000000000000000000000000048 -:10D8E0000000000000000000000000000000000038 -:10D8F0000000000000000000000000000000000028 -:10D900000000000000000000000000000000000017 -:10D910000000000000000000000000000000000007 -:10D9200000000000000000000000000000000000F7 -:10D9300000000000000000000000000000000000E7 -:10D9400000000000000000000000000000000000D7 -:10D9500000000000000000000000000000000000C7 -:10D9600000000000000000000000000000000000B7 -:10D9700000000000000000000000000000000000A7 -:10D980000000000000000000000000000000000097 -:10D990000000000000000000000000000000000087 -:10D9A0000000000000000000000000000000000077 -:10D9B0000000000000000000000000000000000067 -:10D9C0000000000000000000000000000000000057 -:10D9D0000000000000000000000000000000000047 -:10D9E0000000000000000000000000000000000037 -:10D9F0000000000000000000000000000000000027 -:10DA00000000000000000000000000000000000016 -:10DA10000000000000000000000000000000000006 -:10DA200000000000000000001000000300000000E3 -:10DA30000000000D0000000D3C020800244271406F -:10DA40003C030800246375E0AC4000000043202B39 -:10DA50001480FFFD244200043C1D080037BD7FFCFC -:10DA600003A0F0213C100800261031D83C1C08000F -:10DA7000279C71400E0010ED000000000000000D1A -:10DA800030A5FFFF30C600FF274301808F4201B859 -:10DA90000440FFFE24020002AC640000A4650008FC -:10DAA000A066000AA062000B3C021000AC670018E0 -:10DAB00003E00008AF4201B83C0360008C624FF8FD -:10DAC0000440FFFE3C020200AC644FC0AC624FC495 -:10DAD0003C02100003E00008AC624FF89482000C96 -:10DAE0002486001400A038210002130200021080D6 -:10DAF0000082402100C8102B104000570000000099 -:10DB000090C300002C6200095040005190C20001F7 -:10DB1000000310803C030800246370F000431021D0 -:10DB20008C420000004000080000000090C300018B -:10DB30002402000A1462003A0000000001061023CB -:10DB40002C42000A1440003624C600028CE2000079 -:10DB500034420100ACE2000090C2000090C300011A -:10DB600090C4000290C5000300031C0000021600D0 -:10DB70000043102500042200004410250045102514 -:10DB800024C60004ACE2000490C2000090C300016F -:10DB900090C4000290C500030002160000031C00A0 -:10DBA00000431025000422000044102500451025E4 -:10DBB00024C600040A000CAAACE2000890C30001CD -:10DBC000240200041462001624C6000290C2000061 -:10DBD00090C400018CE300000002120000441025F4 -:10DBE0003463000424C60002ACE2000C0A000CAA54 -:10DBF000ACE3000090C3000124020003146200089B -:10DC000024C600028CE2000090C3000024C600017C -:10DC100034420008A0E300100A000CAAACE20000A5 -:10DC200003E000082402000190C300012402000266 -:10DC30001062000224C40002010020210A000CAA84 -:10DC4000008030210A000CAA24C6000190C2000105 -:10DC50000A000CAA00C2302103E0000800001021D5 -:10DC600027BDFFE8AFBF0014AFB000100E0011FEDB -:10DC700000808021936200052403FFFE0200202122 -:10DC8000004310248FBF00148FB00010A362000562 -:10DC90000A00120727BD001827BDFFE8AFB000102B -:10DCA000AFBF00140E000F180080802193620000A7 -:10DCB00024030050304200FF1443000424020100FA -:10DCC000AF4201800A000D2202002021AF400180F6 -:10DCD000020020218FBF00148FB000100A000F79BE -:10DCE00027BD001827BDFF80AFBE0078AFB7007416 -:10DCF000AFB30064AFBF007CAFB60070AFB5006CCF -:10DD0000AFB40068AFB20060AFB1005CAFB0005814 -:10DD10008F5001289363003F936200050000F021BB -:10DD2000307300FF00021027304200010000B821CC -:10DD300014400066AFA000509342011693430112B5 -:10DD4000304200FF306300FF0342202103431021D3 -:10DD5000244540008F820018104000182491400094 -:10DD60008F4201043C0300010043102410400013C3 -:10DD7000000000008CA3000C8F620030146201B51B -:10DD8000240200018CA300108F62002C146201B1E8 -:10DD9000240200019762003A948340003042FFFF62 -:10DDA000146201AC2402000197620038962300023D -:10DDB0003042FFFF146201A72402000193620000B9 -:10DDC000304300FF240200201062000524020050AE -:10DDD00010620006000000000A000D6C0000000048 -:10DDE0000000000D0A000D75AFA000303C1E0800B9 -:10DDF00027DE71A00A000D75AFA000303C020800BC -:10DE00008C4200DC244200013C010800AC2200DC12 -:10DE10000E0012C8000000000A000F038FBF007C34 -:10DE20008F4201043C0300209234000D0043102473 -:10DE30000002202B00042140AFA400308F430104D6 -:10DE40003C02004000621824146000023487004045 -:10DE50000080382132820020AFA700301440000239 -:10DE600034E6008000E0302110C0000BAFA6003087 -:10DE700093C500088F67004C0200202100052B008D -:10DE800034A5008130A5F0810E000C8D30C600FF56 -:10DE90000A000F00000000009362003E3042004084 -:10DEA0001040000E240200045662000624020012F4 -:10DEB000020020210E0013D6022030210A000F0399 -:10DEC0008FBF007C16620005000000000E000D13DD -:10DED000000020210A000F038FBF007C9743011A26 -:10DEE0009624000E93620035328500043076FFFFE1 -:10DEF00000442004AFA400548E32000410A000158A -:10DF00008E3500089362003E30420040104000070A -:10DF1000000000000E001318024020211040000DE8 -:10DF2000000000000A000F00000000008F620044A3 -:10DF30000242102304400145000000008F620048A7 -:10DF40000242102304410141240400160A000E037A -:10DF50008FC200048F620048024210230440000870 -:10DF6000000000003C0208008C4231002442000105 -:10DF70003C010800AC2231000A000EF50000000050 -:10DF80008F62004002421023184000092402000C56 -:10DF90003C0208008C423100329400FC0000B021A9 -:10DFA000244200013C010800AC2231002402000C94 -:10DFB000AFA200308F620040005220231880000D75 -:10DFC00002C4102A14400116000000001496000636 -:10DFD00002C410233A8200013042000114400110B3 -:10DFE0000000000002C41023024490210A000DEB3F -:10DFF0003056FFFF00002021328200021040001A3C -:10E00000328200109362003E3042004050400011C6 -:10E010008FC200040E0011FE02002021240200180D -:10E02000A362003F936200052403FFFE020020214B -:10E03000004310240E001207A362000524040039D7 -:10E04000000028210E001301240600180A000F0208 -:10E0500024020001240400170040F8090000000019 -:10E060000A000F0224020001104000F80000000026 -:10E070008F63004C8F62005402A210231C4000F3F7 -:10E0800002A31023044200010060A821AFA40018DD -:10E09000AFB20010AFB60014934201208F6500406C -:10E0A0009763003C304200FF0342102100441021DE -:10E0B0008FA400543063FFFF244240000083182BDC -:10E0C0008FA40030AFA20020AFA500280083202538 -:10E0D000AFA40030AFA50024AFA0002CAFB5003432 -:10E0E0009362003E30420008504000118FC2000091 -:10E0F0000220202127A500380E000CA4AFA0003874 -:10E100005440000B8FC200008FA200383042010043 -:10E11000504000078FC200008FA3003C8F62006058 -:10E120000062102304430001AF6300608FC200004F -:10E130000040F80927A400108FA2003030420002EE -:10E1400054400001329400FE9362003E3042004091 -:10E15000104000378FA300148F62005416A2001ADB -:10E160003282000124020014126200102A6200159B -:10E1700010400006240200162402000C1262000760 -:10E18000328200010A000E5F0000000012620005EA -:10E19000328200010A000E5F000000000A000E5AE1 -:10E1A0002417000E0A000E5A241700100A000E5EF3 -:10E1B00024170012936200232403FFBD00431024A0 -:10E1C000A362002332820001104000198FA30014C3 -:10E1D0002402000C1262000E2A62000D104000069C -:10E1E0002402000E2402000A126200078FA20024FB -:10E1F0000A000E7724420001126200088FA2002458 -:10E200000A000E77244200010A000E752417000848 -:10E210002402000E16E20002241700162417001034 -:10E220008FA2002424420001AFA200248FA3001477 -:10E230008FA200248F73004000431021AF62004082 -:10E240008FA20054936400368F63004002A288219D -:10E250003402FFFF0082100400621821AF630048FF -:10E260008FA6003030C200081040000E00000000F1 -:10E270008F6200581622000430C600FF9742011A30 -:10E280005040000134C6001093C500088FA7003429 -:10E290000200202100052B0034A500800E000C8D0B -:10E2A00030A5F0808F620040005310231840001703 -:10E2B0008FA200183C0208008C42319830420010B6 -:10E2C0001040000924020001976200681440000613 -:10E2D00024020001A76200689742007A2442000AE3 -:10E2E0000A000EBBA7620012A76200120E0011FE08 -:10E2F000020020219362007D2403000102002021FE -:10E30000344200010A000EB9AFA300501840000AC1 -:10E31000000000000E0011FE020020219362007D2B -:10E320002403000102002021AFA300503442000466 -:10E330000E001207A362007D9362003E304200404F -:10E340001440000C328200011040000A000000005E -:10E350008F6300408FC2000424040018246300016E -:10E360000040F809AF6300408FA200300A000F029E -:10E37000304200048F62005810510010000000006D -:10E380008F620018024210231C4000082404000180 -:10E390008F62001816420009000000008F62001C06 -:10E3A00002A210230440000500000000AF710058D5 -:10E3B000AFA40050AF720018AF75001C12E0000B44 -:10E3C0008FA200500E0011FE02002021A377003F13 -:10E3D0000E0012070200202102E030212404003741 -:10E3E0000E001301000028218FA2005010400003EE -:10E3F000000000000E000C9B0200202112C000054E -:10E40000000018218FA2003030420004504000115B -:10E4100000601021240300010A000F020060102197 -:10E420000E0011FE020020219362007D02002021D7 -:10E43000344200040E001207A362007D0E000C9B04 -:10E44000020020210A000F0224020001AF40004414 -:10E45000240200018FBF007C8FBE00788FB700744C -:10E460008FB600708FB5006C8FB400688FB30064F6 -:10E470008FB200608FB1005C8FB0005803E00008DD -:10E4800027BD00808C8700048C86000000001021CE -:10E4900000E5382100E5282B00C2302100C53021DD -:10E4A000AC87000403E00008AC8600008F4201B88E -:10E4B0000440FFFE24020800AF4201B803E0000858 -:10E4C000000000003C0200080342282194A20048FA -:10E4D0003084FFFF1040001B2484001294A20048E7 -:10E4E0003042FFFF0044102A1040001724020003AE -:10E4F0002402001A93430120A342018B8F82000063 -:10E50000306300FF30424000104000092463FFFEEA -:10E5100094A200483042FFFF0043102B1440000536 -:10E520008F820004A74301940A000F3C344200018B -:10E530008F8200042403FFFE0043102403E0000840 -:10E54000AF8200042402000303E00008A342018B11 -:10E5500027BDFFE0AFB20018AFB10014AFB000109C -:10E56000AFBF001C30B1FFFF30D0FFFF30F2FFFF24 -:10E570008F4201B80440FFFE00000000AF4401805C -:10E58000AF4400200E000F1E020020218F830000E8 -:10E590008F840004A751018CA750018EA7430190DE -:10E5A0008F83000830828000AF4301A8A752018802 -:10E5B0001040000E8F82000493420116304200FC8E -:10E5C00024420004005A10218C4240003042FFFFD8 -:10E5D000144000068F8200043C02FFFF34427FFF9C -:10E5E00000821024AF8200048F8200042403BFFF46 -:10E5F00000431024A74201A69743010C8F42010457 -:10E6000000031C003042FFFF00621825AF4301AC3D -:10E610003C021000AF4201B88FBF001C8FB200183F -:10E620008FB100148FB0001003E0000827BD002058 -:10E630003C0208008C42003827BDFFC8AFB200285A -:10E64000AFBF0030AFB3002CAFB10024AFB000209B -:10E65000000090213C0E080025CE00381440000236 -:10E66000244DFFFF000068218F84000030824000AD -:10E670001040000A308280003C02002000821024FA -:10E6800050400006308280008F8200042403BFFFC8 -:10E69000008318240A000F9D344210001040000A25 -:10E6A0003C02002000821024104000078F820004EA -:10E6B0003C03FFFF34637FFF008318243442800053 -:10E6C000AF820004AF8300008F48007093420112B4 -:10E6D0008F860000304200FF0002288230C2010015 -:10E6E0001040004324A4000330C24000104000103A -:10E6F00030C2200000041080005A10218C434000DA -:10E7000024A4000400041080AFA30010005A1021BC -:10E710008C424000AFA2001493420116304200FC2C -:10E72000005A10218C4240000A000FC4AFA200180A -:10E730001040002F00041080005A10218C4340002C -:10E7400024A4000400041080AFA30010005A10217C -:10E750008C424000AFA00018AFA200148FA900188F -:10E760000000382100002021240C000827AB0010F5 -:10E770003C0A0800254A010001641021148C0003A2 -:10E7800000042A001120000A00000000904200004E -:10E79000248400012C83000C00A2102100021080B0 -:10E7A000004A10218C4200001460FFF300E238267A -:10E7B0003C0408008C8431048F4200702C830020BC -:10E7C00010600009004840233C030800246331081E -:10E7D000000410800043102124830001AC48000095 -:10E7E0003C010800AC2331040A000FEFAF8700089A -:10E7F0009743011E9742011C3063FFFF0002140083 -:10E8000000621825AF8300089742010C8F43400037 -:10E810003044FFFF3402FFFF1462000300000000D9 -:10E820000A000FFB241200208F42400030420100FA -:10E83000544000012412001030C210005040001457 -:10E840003652000130C200201440000B3C02100080 -:10E8500000C210245040000E365200013C030E004E -:10E860003C020DFF00C318243442FFFF0043102B6D -:10E8700050400007365200013C0208008C42002C38 -:10E88000244200013C010800AC22002C3652000555 -:10E890003C0508008CA5003454A000248F8400009F -:10E8A0008F82000C544000218F8400008F8200046E -:10E8B000304240005440001D8F8400003C021F0184 -:10E8C00000C288243C021000562200188F840000E9 -:10E8D00030820200144000158F8400009750010E12 -:10E8E000AF400180AF400020261000043210FFFF2F -:10E8F0000E000F1E020020218F8300042402BFFFA0 -:10E90000364400020062182424020002A742018C4F -:10E910008F820000A750018EA7440188A74301A65B -:10E92000A7420190AF5101B80A0010D93C02000182 -:10E93000008210241040000C3C0210003C02080031 -:10E940008C4200D89746010E240400802442000126 -:10E9500030C6FFFF240500023C010800AC2200D8AD -:10E960000A0010E324070003008210241040004531 -:10E97000000000003C0208008C4200301040000DF6 -:10E980008F820004304240001040000A3C030F0018 -:10E99000008318243C0201000043102B14400005A2 -:10E9A000000000009746010E364700020A0010E002 -:10E9B0002404008010A0000D308201001040000BE4 -:10E9C0003C020F00008210243C03020010430007A9 -:10E9D0008F820008004D1024004E10219042000448 -:10E9E000244200040A00108B000221C00000000035 -:10E9F0008F8600003C0508008CA500D0000616029A -:10EA00003050000F38A200012C4200012E03000CF0 -:10EA10000043102414400018001021C02602FFFCFF -:10EA20002C420004544000140000202138A20002AF -:10EA30002C42000100431024104000030006124243 -:10EA40000A00108B000020210010182B0043102416 -:10EA500050400009001021C09746010E00002021FF -:10EA60002405000224C6000430C6FFFF0E000F413B -:10EA70003247FFFB001021C09746010E0A0010E04C -:10EA8000364700028F4240003C1108008E310024BE -:10EA90003042010010400048322200010220802153 -:10EAA00010A00017325300043082010010400015FE -:10EAB000240200013C020F00008210243C030200EB -:10EAC0001043000F8F8200089746010E0240382144 -:10EAD000004D1024004E10219044000424C6000470 -:10EAE00030C6FFFF24840004000421C00E000F4143 -:10EAF000240500022402FFFE022280243252FFFB82 -:10EB00002402000116020007320200013242000412 -:10EB100050400001365200029746010E0A0010DFF5 -:10EB2000024038211040000A320200049746010ECC -:10EB3000024038210000202124C6000430C6FFFF17 -:10EB40000E000F41240500023252FFFB3202000486 -:10EB50001040000B8F820000304208001040000877 -:10EB6000000000009746010E0240382124040100F5 -:10EB700024C6000430C6FFFF0E000F41240500022A -:10EB8000166000188FBF0030274301808F4201B804 -:10EB90000440FFFE24022000A462000824020002B8 -:10EBA000A062000BA46000103C021000AF4201B84C -:10EBB0000A0010E68FBF00301040000A8FBF0030FF -:10EBC0009746010E364700020000202124C60004AB -:10EBD00030C6FFFF240500020E000F4100000000B8 -:10EBE0008FBF00308FB3002C8FB200288FB100246C -:10EBF0008FB000200000102103E0000827BD00387E -:10EC000027BDFFE8AFB000103C04600CAFBF00149C -:10EC10008C8250002403FF7F3C1A800000431024A4 -:10EC20003442380CAC825000240200033C106000D7 -:10EC3000AF4200088E0208083C1B80083C01080017 -:10EC4000AC2000203042FFF0384200102C4200017E -:10EC50000E001B35AF8200183C04FFFF3C0204008D -:10EC6000348308063442000CAE021948AE03194C36 -:10EC70003C0560168E0219808CA30000344202000D -:10EC800000641824AE0219803C025353146200033E -:10EC900034A47C008CA20004005020218C82007CD3 -:10ECA0008C830078AF820014AF8300103C02800098 -:10ECB000344200708C43000000403821AF83001CB8 -:10ECC000006030218CE800003C0508008CA500FCA9 -:10ECD0003C0408008C8400F8010630230000102159 -:10ECE00000A6282100A6302B0082202100862021AA -:10ECF0003C010800AC2500FC3C010800AC2400F8F5 -:10ED00008F500000320200031040FFEE010030215E -:10ED10008CE600003C0508008CA500FC3C040800C3 -:10ED20008C8400F800C8302300A6282100001021A0 -:10ED300000A6302B0082202100862021320700010E -:10ED40003C010800AC2500FCAF88001C3C01080019 -:10ED5000AC2400F810E00064320200028F42012867 -:10ED6000AF4200208F4201048F430100AF820000B8 -:10ED70000E000F18AF8300048F4340003402FFFFE2 -:10ED800014620006000000009745010E3C040800D4 -:10ED9000248400F00A00115B000000008F42400054 -:10EDA000304201001040000B000000009745010EAA -:10EDB0003C040800248400E80E000F0E30A5FFFF7D -:10EDC0009745010E3C040800248431C80A001172E2 -:10EDD000000000008F4340008F8200101462000A80 -:10EDE000000000008F4340048F820014146200066C -:10EDF000000000009745010E3C040800248431B84F -:10EE00000A001172000000009745010E3C04080042 -:10EE1000248400E00E000F0E30A5FFFF3C02080026 -:10EE20008C4200C0104000088F8400003C020800A3 -:10EE30008C4200C4244200013C010800AC2200C402 -:10EE40000A00119F000000003C0200100082102404 -:10EE50001440000A8F8300043C0208008C4200200A -:10EE6000244200013C010800AC2200200E000F7972 -:10EE7000000020210A00119D000000002402BFFFB5 -:10EE8000006210241040000800000000240287FFE8 -:10EE900000621024144000083C020060008210242C -:10EEA00010400005000000000E000D2600000000CC -:10EEB0000A00119D000000000E0011E80000000093 -:10EEC000104000063C0240008F4301243C026020B9 -:10EED000AC430014000000003C024000AF42013887 -:10EEE00000000000320200021040FF713C0280006E -:10EEF0008F4201403C044000AF4200208F43014854 -:10EF00003C027000006218241064002D0000000014 -:10EF10000083102B144000063C0260003C022000DD -:10EF2000106200073C0240000A0011E400000000EB -:10EF300010620027000000000A0011E43C024000BB -:10EF40008F4201482403000400021402304200FFF3 -:10EF50001443000B274401808F4301408F4201B8C6 -:10EF60000440FFFE2402001CAC830000A082000BC2 -:10EF70003C021000AF4201B80A0011E43C0240001C -:10EF80008F4201B80440FFFE000000008F4201489C -:10EF900000021402A482000824020002A082000BD6 -:10EFA0008F420148A48200108F420144AC820024A9 -:10EFB0003C021000AF4201B80A0011E43C024000DC -:10EFC0000E00120C000000000A0011E43C02400098 -:10EFD0000E001B42000000003C024000AF420178DE -:10EFE000000000000A0011193C0280008F4201005D -:10EFF0003042003E1440001124020001AF4000489E -:10F000008F420100304207C01040000500000000A0 -:10F01000AF40004CAF40005003E000082402000164 -:10F02000AF400054AF4000408F42010030423800F2 -:10F0300054400001AF4000442402000103E00008F6 -:10F04000000000003C0290003442000100822025B4 -:10F05000AF4400208F4200200440FFFE000000006B -:10F0600003E00008000000003C0280003442000180 -:10F070000082202503E00008AF44002027BDFFE008 -:10F08000AFB20018AFBF001CAFB10014AFB000109A -:10F090008F5001408F5101483C02800000119402C2 -:10F0A00002222024324300FF2402000E1062008A54 -:10F0B0002862000F10400012286200372402000668 -:10F0C0001062003B2862000710400007240200097C -:10F0D0001060001A240200011062002500000000E8 -:10F0E0000A0012C1000000001062007B2402000B25 -:10F0F0001062005B3222FFFF0A0012C10000000014 -:10F1000010400008240200382862003510400080BA -:10F110002402001F1062007E000000000A0012C1DD -:10F12000000000001062007A240200801062004299 -:10F13000000000000A0012C1000000008F4201B868 -:10F140000440FFFE24020001AF500180AF40018463 -:10F15000A7520188A342018A24020002A342018B24 -:10F16000A75101908F4201440A0012BCAF4201A492 -:10F170001080000A240200023C010800A0227190C5 -:10F180003C010800AC3071988F4201443C010800FA -:10F19000AC2271940A0012C38FBF001C8F4201B8C9 -:10F1A0000440FFFE240200020A0012A60000000034 -:10F1B0008F4201B80440FFFE00000000AF50018004 -:10F1C0003C0208009042719010400003000018219A -:10F1D0003C0308008C637198AF430184A7520188F7 -:10F1E0003C02080090427190000018213442000156 -:10F1F000A342018A24020002A342018BA75101907D -:10F200008F420144AF4201A43C0208009042719039 -:10F21000104000033C0210003C0308008C63719412 -:10F22000AF4301A8AF4201B83C010800A020719093 -:10F230000A0012C38FBF001C8F4201B80440FFFEBA -:10F2400024020002A342018BA7520188A75101901A -:10F250008F420144A74201920A0012BE3C021000F4 -:10F260001440001D000000009362000530420004BD -:10F2700014400037000000000E0011FE02002021A3 -:10F280009362000502002021344200040E001207A0 -:10F29000A36200059362000530420004144000029E -:10F2A000000000000000000D936200002403002015 -:10F2B000304200FF14430008000000008F4201B8F4 -:10F2C0000440FFFE24020005AF500180A342018BE1 -:10F2D0003C021000AF4201B88F4201B80440FFFE6B -:10F2E00024020002AF400180AF500184A752018880 -:10F2F000A342018AA342018BA7510190AF4001A410 -:10F300008F420144AF4201A80A0012BE3C02100025 -:10F310008F4201B80440FFFE24020001AF5001807B -:10F32000AF400184A7520188A342018A240200024F -:10F33000A342018BA7510190AF4001A4AF4001A8A7 -:10F340003C021000AF4201B80A0012C38FBF001C7C -:10F350000000000D8FBF001C8FB200188FB1001489 -:10F360008FB0001003E0000827BD002027BDFFE894 -:10F37000AFBF00100E000F1800000000AF4001806A -:10F380008FBF0010000020210A000F7927BD001850 -:10F390003084FFFF30A5FFFF000018211080000718 -:10F3A00000000000308200011040000200042042F2 -:10F3B000006518210A0012D40005284003E0000867 -:10F3C0000060102110C0000624C6FFFF8CA20000C0 -:10F3D00024A50004AC8200000A0012DE248400048C -:10F3E00003E000080000000010A0000824A3FFFFB5 -:10F3F000AC86000000000000000000002402FFFFB7 -:10F400002463FFFF1462FFFA2484000403E0000871 -:10F410000000000027BDFFE8AFBF0014AFB0001030 -:10F420000E0011FE008080219362007D02002021E9 -:10F43000344200200E001207A362007D020020214A -:10F440008FBF00148FB000100A000C9B27BD00185E -:10F45000308300FF30A500FF30C600FF2747018042 -:10F460008F4201B80440FFFE000000008F420128D7 -:10F4700034634000ACE2000024020001ACE0000470 -:10F48000A4E30008A0E2000A24020002A0E2000BAC -:10F490003C021000A4E50010ACE00024ACE0002821 -:10F4A000A4E6001203E00008AF4201B827BDFFE860 -:10F4B000AFBF00109362003F24030012304200FFF0 -:10F4C0001043000D008030218F6200440082102321 -:10F4D0000440000A8FBF00108F62004824040039E6 -:10F4E0000000282100C21023044100042406001259 -:10F4F0000E001301000000008FBF00102402000165 -:10F5000003E0000827BD001827BDFFC8AFB1002CDD -:10F5100000A08821AFB2003027A500100080902104 -:10F5200002202021AFBF0034AFB000280E000CA491 -:10F53000AFA0001010400009024020218E220008D8 -:10F54000AF6200840E0012F2AF6000402404003865 -:10F550002405008D0A0013CD240600129362003E9C -:10F56000304200081040000F8FA20010304201000E -:10F57000104000078FA300148F6200600062102308 -:10F5800004430008AF6300600A0013560000000047 -:10F59000AF6000609362003E2403FFF70043102435 -:10F5A000A362003E9362003E304200081440000215 -:10F5B0002406000300003021936200349363003777 -:10F5C0008F640084304200FF306300FF0066182122 -:10F5D000000318800043282100A4202B1080000B7A -:10F5E000000000009763003C8F6200843063FFFFDF -:10F5F000004510230062182B146000040000000076 -:10F600008F6200840A001372004580239762003CD9 -:10F610003050FFFF8FA30010306200041040000440 -:10F62000000628808FA2001C0A00137A0202102B09 -:10F630002E02021850400003240202180A0013830D -:10F6400002051023306300041060000300451023FE -:10F650008FA2001C00451023004080212C42008016 -:10F6600054400001241000800E0011FE02402021B1 -:10F6700024020001AF62000C9362003E00102040A3 -:10F680003042007FA362003E8E220004244200012B -:10F69000AF620040A770003C8F6200509623000EBE -:10F6A00000431021AF6200588F62005000441021C7 -:10F6B000AF62005C8E220004AF6200188E22000848 -:10F6C000AF62001C8FA20010304200085440000AB4 -:10F6D00093A20020A3600036936200362403FFDF6C -:10F6E000A36200359362003E00431024A362003EF3 -:10F6F0000A0013AD8E220008A36200358E22000896 -:10F70000AF62004C8F6200248F63004000431021E1 -:10F71000AF6200489362000024030050304200FFB3 -:10F72000144300122403FF803C0208008C4231A0E5 -:10F730000242102100431024AF4200283C0208007E -:10F740008C4231A08E2400083C03000C02421021A0 -:10F750003042007F0342102100431021AC4400D806 -:10F760008E230008AF820024AC4300DC0E00120799 -:10F770000240202124040038000028212406000A29 -:10F780000E001301000000008FBF00348FB2003064 -:10F790008FB1002C8FB000282402000103E0000884 -:10F7A00027BD003827BDFFE8AFBF001090C7000D90 -:10F7B00000C0282130E6001010C0000A30E200042A -:10F7C0008CA300088F6200541062000630E200042F -:10F7D000144000178FBF0010000020210A000D13F5 -:10F7E00027BD00181040000D30E3001210C00010BB -:10F7F0008FBF00108CA300088F6200541462000DAC -:10F8000024020001240400382405008D0E00130199 -:10F81000240600120A0013F98FBF00102402001200 -:10F82000146200038FBF00100A00132F27BD0018B9 -:10F830002402000103E0000827BD001827BDFFF8DF -:10F8400027420180AFA20000308A00FF8F4201B83A -:10F850000440FFFE000000008F4601283C02080023 -:10F860008C4231A02403FF80AF86004C00C21021DF -:10F8700000431024AF4200243C0208008C4231A017 -:10F880008FA900008FA8000000C210213042007F25 -:10F89000034218213C02000A00621821946400D43B -:10F8A0008FA700008FA5000024020002AF83002470 -:10F8B000A0A2000B8FA30000354260003084FFFF40 -:10F8C000A4E200083C021000AD260000AD040004D4 -:10F8D000AC60002427BD0008AF4201B803E0000877 -:10F8E000240200018C8200048F8300240045102331 -:10F8F000AC820004906200633042007FA06200632B -:10F900008C8200209383002C8F85002434420002D7 -:10F91000AF830040A780003EAC820020A4A000E49A -:10F9200090A200632403FFBF0043102403E00008FB -:10F93000A0A20063274301808F4201B80440FFFE6C -:10F940008F82004CAC6200008F420124AC62000444 -:10F9500024026083A462000824020002A062000B5B -:10F960003C02100003E00008AF4201B88F8800405D -:10F970009382002C8F8300243C07080024E775AC99 -:10F9800000481023304200FF304900FC2465008805 -:10F990008F860044304A0003112000090000202116 -:10F9A000248200048CA30000304400FF0089102A48 -:10F9B000ACE3000024A500041440FFF924E7000490 -:10F9C00011400009000020212482000190A30000C2 -:10F9D000304400FF008A102BA0E3000024A50001A2 -:10F9E0001440FFF924E7000130C200031440000472 -:10F9F0008F850040310200031040000D0000000020 -:10FA000010A00009000020212482000190C3000002 -:10FA1000304400FF0085102BA0E3000024C6000145 -:10FA20001440FFF924E7000103E000080000000093 -:10FA30001100FFFD00002021248200048CC300007F -:10FA4000304400FF0088102BACE3000024C6000403 -:10FA50001440FFF924E7000403E000080000000060 -:10FA60008F8300409382002C30C600FF30A500FF3A -:10FA700000431023304300FF8F8200240080382190 -:10FA80000043102114C0000224480088008338215C -:10FA900030E200031440000530A2000314400003CC -:10FAA000306200031040000D0000000010A00009AB -:10FAB000000020212482000190E30000304400FF78 -:10FAC0000085102BA103000024E700011440FFF97A -:10FAD0002508000103E000080000000010A0FFFD61 -:10FAE00000002021248200048CE30000304400FF49 -:10FAF0000085102BAD03000024E700041440FFF93B -:10FB00002508000403E000080000000027BDFFF8FE -:10FB10002402FFFFAFA20000008038212405002F3F -:10FB20003C090800252971AC240800FF2406FFFFCA -:10FB300090E2000024A3FFFF0006220200C210266C -:10FB4000304200FF00021080004910218C4200006A -:10FB5000306500FF24E7000114A8FFF5008230267D -:10FB600000061027AFA20004AFA200000000282169 -:10FB700027A6000400C510239044000324A200011E -:10FB800000BD1821304500FF2CA200041440FFF9ED -:10FB9000A06400008FA2000003E0000827BD000859 -:10FBA0000080482130AAFFFF30C600FF30E7FFFF8A -:10FBB000274801808F4201B80440FFFE8F82004C2D -:10FBC000AD0200008F420124AD0200048D2200200E -:10FBD000A5070008A102000A24020016A102000BDA -:10FBE000934301208D2200088D240004306300FF20 -:10FBF000004310219783003E004410218D250024EE -:10FC0000004310233C0308008C6331A08F84002440 -:10FC1000A502000C246300E82402FFFFA50A000EE1 -:10FC2000A5030010A5060012AD050018AD020024C2 -:10FC3000948201142403FFF73042FFFFAD02002835 -:10FC40008C820118AD02002C3C021000AD00003087 -:10FC5000AF4201B88D2200200043102403E00008C9 -:10FC6000AD2200208F82002430E7FFFF0080482172 -:10FC7000904200D330A5FFFF30C600FF0002110004 -:10FC800030420F0000E23825274801808F4201B83A -:10FC90000440FFFE8F82004CAD0200008F42012421 -:10FCA000AD0200048D220020A5070008A102000A71 -:10FCB00024020017A102000B934301208D220008AB -:10FCC0008D240004306300FF004310219783003E21 -:10FCD000004410218F840024004310233C030800BB -:10FCE0008C6331A0A502000CA505000E246300E87A -:10FCF000A5030010A5060012AD0000148D220024FB -:10FD0000AD0200188C82005CAD02001C8C82005891 -:10FD1000AD0200202402FFFFAD020024948200E621 -:10FD20003042FFFFAD02002894820060948300BE41 -:10FD300030427FFF3063FFFF0002120000431021BA -:10FD4000AD02002C3C021000AD000030AF4201B803 -:10FD5000948200BE2403FFF700A21021A48200BEFB -:10FD60008D2200200043102403E00008AD22002073 -:10FD7000274301808F4201B80440FFFE240200188F -:10FD8000AC640000A062000B8F820024944200E665 -:10FD9000A46200103C021000AC60003003E00008D8 -:10FDA000AF4201B8274301808F4201B80440FFFEF3 -:10FDB0008F8200289442001C3042FFFF000211C0D5 -:10FDC000AC62000024020019A062000B3C0210008B -:10FDD000AC60003003E00008AF4201B88F8700300C -:10FDE00030C300FF8F4201B80440FFFE8F82004CF9 -:10FDF00034636000ACA2000093820048A0A200051A -:10FE00008CE20010A4A20006A4A300088C820020AB -:10FE10002403FFF7A0A2000A24020002A0A2000B04 -:10FE20008CE20000ACA200108CE20004ACA2001432 -:10FE30008CE2001CACA200248CE20020ACA20028C2 -:10FE40008CE2002CACA2002C8C820024ACA2001806 -:10FE50003C021000AF4201B88C8200200043102405 -:10FE600003E00008AC8200209382004824030001D4 -:10FE700027BDFFE8004330042C420020AFB0001043 -:10FE8000AFBF00142410FFFE10400005274501807D -:10FE90003C0208008C4231900A001598004610245C -:10FEA0003C0208008C4231940046102414400007A4 -:10FEB000240600848F8300242410FFFF90620062D8 -:10FEC0003042000F34420040A06200620E00156410 -:10FED00000000000020010218FBF00148FB000103E -:10FEE00003E0000827BD00188F83002827BDFFE02E -:10FEF000AFB20018AFB10014AFB00010AFBF001C1C -:10FF00009062000D00A0902130D100FF3042007FB0 -:10FF1000A062000D8F8500248E4300180080802190 -:10FF20008CA2007C146200052402000E90A20063E3 -:10FF3000344200200A0015C1A0A200630E001587FC -:10FF4000A38200482403FFFF104300472404FFFF5F -:10FF500052200045000020218E4300003C0200108A -:10FF600000621024504000043C02000802002021DE -:10FF70000A0015D024020015006210245040000928 -:10FF80008E45000002002021240200140E00158777 -:10FF9000A38200482403FFFF104300332404FFFF23 -:10FFA0008E4500003C02000200A210241040001602 -:10FFB0003C0200048F8600288CC200148CC3001001 -:10FFC0008CC40014004310230044102B5040000543 -:10FFD000020020218E43002C8CC20010106200030E -:10FFE000020020210A001601240200123C02000433 -:10FFF00000A210245040001C0000202102002021FB -:020000040001F9 -:100000000A0016012402001300A21024104000066A -:100010008F8300288C6200105040001300002021C4 -:100020000A0015FB020020218C62001050400004E1 -:100030008E42002C020020210A0016012402001129 -:100040005040000900002021020020212402001756 -:100050000E001587A38200482403FFFF104300020F -:100060002404FFFF000020218FBF001C8FB2001866 -:100070008FB100148FB000100080102103E0000841 -:1000800027BD00209383002C27BDFFE0240200340D -:10009000AFB20018AFB10014AFBF001CAFB000107A -:1000A000008088211462000C00A090218F84003011 -:1000B0000E0014B08C9000301202000724020005DC -:1000C000022020210E001587A38200482403FFFF91 -:1000D0001043005F2404FFFF924200041040000917 -:1000E0008F820024022020212402000C0E0015879C -:1000F000A38200482403FFFF104300552404FFFFA0 -:100100008F820024A38000208E4300048C44008052 -:100110003C0200FF3442FFFF006218240083202BC2 -:1001200010800008AF83003802202021240200192B -:100130000E001587A38200482403FFFF10430044EC -:100140002404FFFF9782003E8F8700408F8800388D -:100150000047102311000039A782003E8F8600243B -:100160003045FFFF8F84004C90C300BC3C02080068 -:100170008C4231A0000318823070000100822021DF -:10018000001010800102102100A2282B10A00010E6 -:10019000248200888F8400301082000D3C033F01D0 -:1001A0008E420000004310243C0325001443000647 -:1001B00030E500FF8C820000ACC200888C82001009 -:1001C0000A001661ACC200980E00148500003021B0 -:1001D0008F850038938300208F86002430A200038F -:1001E000000210233042000300433821A38700207F -:1001F00094C400E400A228218F8300408F82004431 -:1002000034841000A4C400E400431021AF820044F1 -:100210001200000EAF85004024E20004A3820020FB -:1002200094C200E424A30004AF83004034422000C1 -:10023000A4C200E40A001681000020218F8200443D -:10024000AF80004000471021AF8200440000202111 -:100250008FBF001C8FB200188FB100148FB0001038 -:100260000080102103E0000827BD00208F860024B5 -:1002700027BDFFE8AFBF0014AFB0001090C200630D -:10028000304200201040000830A500FF8CC2007CE6 -:100290002403FFDF24420001ACC2007C90C2006353 -:1002A00000431024A0C2006310A000238F83002409 -:1002B00027500180020028210E00156424060082C8 -:1002C0008F82002490420063304200405040001969 -:1002D000A38000488F8300308F4201B80440FFFEA6 -:1002E0008F82004CAE02000024026082A602000849 -:1002F00024020002A202000B8C620008AE02001071 -:100300008C62000CAE0200148C620014AE02001865 -:100310008C620018AE0200248C620024AE02002819 -:100320008C620028AE02002C3C021000AF4201B8E3 -:10033000A38000488F8300248FBF00148FB000106B -:100340009062006327BD00183042007FA062006306 -:100350009782003E8F8600408F8500249383002C77 -:1003600000461023A782003EA4A000E490A40063EE -:100370008F820044AF8300402403FFBF004610215A -:1003800000832024AF820044A0A400638F82002455 -:10039000A04000BD8F82002403E00008A44000BEFE -:1003A0008F8A002427BDFFE0AFB10014AFB000106A -:1003B0008F880040AFBF001893890020954200E469 -:1003C00030D100FF0109182B0080802130AC00FFE4 -:1003D0003047FFFF0000582114600003310600FF82 -:1003E00001203021010958239783003E0068102B1B -:1003F00014400032000000001468000724020001CD -:100400008E0200202403FFFB34E780000043102409 -:10041000AE0200202402000134E7088015820005A6 -:100420003165FFFF0E0014D5020020210A001716C7 -:10043000020020210E001506020020210E001549A1 -:100440008F84004C8F840024948200602442000139 -:10045000A4820060948200603C0308008C633188B1 -:1004600030427FFF5443000F02002021948200603D -:100470002403800000431024A48200609082006066 -:1004800090830060304200FF000211C2000210277A -:10049000000211C03063007F00621825A083006055 -:1004A00002002021022028218FBF00188FB10014E4 -:1004B0008FB000100A00168827BD0020914200630B -:1004C0002403FF8000431025A14200639782003E71 -:1004D0003048FFFF11000020938300208F84002408 -:1004E000004B1023304600FF948300E42402EFFF0A -:1004F0000168282B00621824A48300E414A00003E0 -:100500008E02002001005821000030212403FFFB4F -:1005100034E7800000431024AE02002024020001D2 -:10052000158200053165FFFF0E0014D50200202161 -:100530000A00173E9783003E0E0015060200202198 -:100540009783003E8F820040A780003E0043102327 -:10055000AF820040938300208F8200248FBF001859 -:100560008FB100148FB0001027BD002003E00008F9 -:10057000A04300BD8F82002490430088904500BDB9 -:10058000244900883063003F2463FFE02402000117 -:10059000006238042C63002030E80019A385002095 -:1005A00010600010AF8900303C028000344200022D -:1005B00024050001240600011500000800E21824AB -:1005C000000028211460000530E2002010400005E2 -:1005D000240500019126000130C600010A0016D54D -:1005E0000000000003E000080000000027BDFFD865 -:1005F000AFB000108F900030AFB40020AFB1001446 -:10060000AFBF0024AFB3001CAFB200188E050010BE -:100610003C0208008C4231B08F86003430A33FFF8B -:100620000062182B8CD30014008088218CD200200B -:10063000106000780000A02190C3000D2402FF800C -:1006400000431024304200FF50400073022020215C -:1006500000051382304200035440006F0220202125 -:1006600094C3001C8F8200248E050028A44301142B -:100670008CC2001002621823146500072402001FB8 -:100680008F820038006210210262102B1040000897 -:100690008F830028240200180E001587A3820048CB -:1006A0002403FFFF1043006F2404FFFF8F83002803 -:1006B0008F8400388C620010024490210044102383 -:1006C000AC6200108F820024AC7200208C42006863 -:1006D0000052102B104000098F830034022020218B -:1006E0002402001D0E001587A38200482403FFFF8B -:1006F0001043005C2404FFFF8F8300348E0200242B -:100700008C63002410430007022020212402001CD7 -:100710000E001587A38200482403FFFF10430051F9 -:100720002404FFFF8F8400288C82002424420001CF -:10073000AC820024125300048F8200248C42006893 -:100740005642000E8E0200008E0200003C03008024 -:10075000004310241440000D2402001A022020211E -:100760000E001587A38200482403FFFF1043003DBD -:100770002404FFFF0A0017D28E0200143C030080FD -:1007800000431024504000038E020014AC8000206F -:100790008E0200142412FFFF105200062402001BD8 -:1007A000022020210E001587A38200481052002D40 -:1007B0002404FFFF8E0300003C02000100621024AD -:1007C0001040001F3C02008000621024144000080A -:1007D000022020212402001A0E001587A38200485F -:1007E0002403FFFF1043001F2404FFFF02202021E9 -:1007F000020028210E0015A7240600012403FFFF94 -:100800002404FFFF1443000E241400010A001807FB -:100810008FBF0024022020212402000D8FBF00245E -:100820008FB400208FB3001C8FB200188FB100145A -:100830008FB0001027BD00280A001587A38200484A -:100840008F8300280220202102803021946200360C -:1008500024050001244200010E0016D5A4620036D2 -:10086000000020218FBF00248FB400208FB3001C14 -:100870008FB200188FB100148FB0001000801021CB -:1008800003E0000827BD00288F83002427BDFFD880 -:10089000AFB40020AFB3001CAFB20018AFB100146A -:1008A000AFB00010AFBF0024906200638F910030A2 -:1008B0002412FFFF3442004092250000A062006332 -:1008C0008E2200100080982130B0003F10520006A8 -:1008D0000360A0212402000D0E001587A3820048AA -:1008E000105200522404FFFF8F8300248E22001830 -:1008F0008C63007C10430007026020212402000E5C -:100900000E001587A38200482403FFFF1043004711 -:100910002404FFFF24040020120400048F83002419 -:100920009062006334420020A06200638F8500382B -:1009300010A0001E00000000560400048F82002456 -:10094000026020210A0018512402000A9683000A3E -:100950002404FFFD944200603042FFFF1043003446 -:100960008FBF00243C0208008C42318C0045102BC4 -:100970001440000602602021000028210E0016D538 -:10098000240600010A001878000020212402002D0E -:100990000E001587A38200482403FFFF10430023A5 -:1009A0002404FFFF0A001878000020211604000527 -:1009B0008F8400248E2300142402FFFF506200184D -:1009C000026020219482006024420001A482006021 -:1009D000948200603C0308008C63318830427FFFC2 -:1009E0005443000F026020219482006024038000A1 -:1009F00000431024A4820060908200609083006015 -:100A0000304200FF000211C200021027000211C094 -:100A10003063007F00621825A083006002602021FF -:100A20000E00168824050001000020218FBF00243D -:100A30008FB400208FB3001C8FB200188FB1001448 -:100A40008FB000100080102103E0000827BD0028AF -:100A50008F83002427BDFFE8AFB00010AFBF0014A4 -:100A6000906200638F870030008080213442004014 -:100A70008CE60010A06200633C0308008C6331B078 -:100A800030C23FFF0043102B1040004E8F850034D2 -:100A90002402FF8090A3000D00431024304200FF89 -:100AA0005040004902002021000613823048000314 -:100AB00024020002550200440200202194A2001CDE -:100AC0008F85002424030023A4A201148CE60000D7 -:100AD000000616023042003F104300103C03008322 -:100AE0008CE300188CA2007C106200062402000E29 -:100AF0000E001587A38200482403FFFF104300382F -:100B00002404FFFF8F83002490620063344200209E -:100B1000A06200630A0018BD8F83002800C3102460 -:100B2000144300078F83002890A200623042000F18 -:100B300034420020A0A20062A388003C8F830028DA -:100B40009062000D3042007FA062000D8F8300385C -:100B500010600018020020218F8400348C82001065 -:100B60000043102B1040000924020018020020212D -:100B70000E001587A38200482403FFFF10430018CE -:100B80002404FFFF0A0018E5000020218C820010D9 -:100B90002405000102002021004310238F83002838 -:100BA000240600010E0016D5AC6200100A0018E5FC -:100BB000000020210E001688240500010A0018E517 -:100BC00000002021020020212402000D8FBF00140C -:100BD0008FB0001027BD00180A001587A3820048B7 -:100BE0008FBF00148FB000100080102103E00008B8 -:100BF00027BD001827BDFFD8AFB000108F90003080 -:100C0000AFB3001CAFBF0020AFB20018AFB10014EB -:100C10008E1200103C0308008C6331B032423FFF5B -:100C20000043102B1040007C008098218F850034F9 -:100C30002402FF8090A3000D00431024304200FFE7 -:100C400050400076026020210012138230420003DF -:100C500024030001544300710260202190A2000D82 -:100C600030420008544000038F8200380A001915F2 -:100C700024020024504000038E03000C0A001915C2 -:100C8000240200278CA20020146200052402002008 -:100C90008E0300088CA200241062000824020020A9 -:100CA0000E001587A38200482403FFFF1043006A4B -:100CB0002404FFFF0A0019408F8400288E020014CC -:100CC0002411FFFF145100038F8700240A00193BF1 -:100CD000240200258E0300188CE2007C14620016AA -:100CE0002402000E8E0300248CA20028146200123D -:100CF000240200218E0600288CA2002C14C2000EB3 -:100D00002402001F8E03002C1060000B240200231D -:100D10008CE200680043102B1440000724020026D8 -:100D20008CA20014006618210043102B50400007CD -:100D30008F840028240200220E001587A382004819 -:100D4000105100452404FFFF8F8400282403FFF77F -:100D50009082000D00431024A082000D8F86002495 -:100D60003C0308008C6331AC8F82004C94C400E0DB -:100D70008F8500280043102130847FFF000420402D -:100D8000004410213043007F034320213C03000E28 -:100D9000008320212403FF8000431024AF42002C55 -:100DA000A49200008CA2002824420001ACA20028DA -:100DB0008CA2002C8E03002C00431021ACA2002C2E -:100DC0008E02002CACA200308E020014ACA20034C3 -:100DD00094A2003A24420001A4A2003A94C600E082 -:100DE0003C0208008C4231B024C4000130837FFFF4 -:100DF000146200130080302124028000008230241D -:100E000030C2FFFF000213C2304200FF0002102771 -:100E10000A00197D000233C0026020212402000D67 -:100E20008FBF00208FB3001C8FB200188FB1001449 -:100E30008FB0001027BD00280A001587A382004844 -:100E40008F82002402602021240500010E001688F4 -:100E5000A44600E0000020218FBF00208FB3001CBB -:100E60008FB200188FB100148FB0001000801021D5 -:100E700003E0000827BD002827BDFFE0AFB1001444 -:100E80008F910030AFB00010AFBF00188E26001059 -:100E90003C0308008C6331B030C23FFF0043102B8D -:100EA0001040005E008080218F8500342402FF8086 -:100EB00090A3000D00431024304200FF5040005822 -:100EC000020020218F8200381040000800061382A3 -:100ED0008F8200249763000A2404FFFD944200607F -:100EE0003042FFFF104300550006138230420003DA -:100EF0001440000E00000000922200021040000585 -:100F00008E23002450600015922300030A0019B6B6 -:100F1000020020218CA200245062001092230003C2 -:100F2000020020210A0019BE2402000F90A2000D29 -:100F3000304200085440000992230003020020219F -:100F4000240200100E001587A38200482403FFFF2F -:100F50001043003A2404FFFF9223000324020002FE -:100F60005462000C922200038F8200385440000922 -:100F700092220003020020212402002C0E0015877B -:100F8000A38200482403FFFF1043002C2404FFFF2A -:100F9000922200030220282102002021384600105E -:100FA0002CC600012C4200010E0015A7004630257A -:100FB0002411FFFF105100212404FFFF8F8300380C -:100FC00010600012020020213C0208008C42318C8B -:100FD0000043102B144000060000000000002821F0 -:100FE0000E0016D5240600010A0019FC000020217D -:100FF0002402002D0E001587A38200481051000F17 -:101000002404FFFF0A0019FC000020210E001688AE -:10101000240500010A0019FC000020210200202103 -:101020002402000D8FBF00188FB100148FB0001084 -:1010300027BD00200A001587A38200488FBF001833 -:101040008FB100148FB000100080102103E0000861 -:1010500027BD00209383003C27BDFFE0240200024F -:10106000AFB10014AFB0001000808821AFBF0018EE -:10107000000080211062008C2404FFFD9785003E53 -:101080008F83004030A2FFFF0043102B5440007DAF -:101090008F8400440E001448000000003C02080049 -:1010A000244275AC02202021004028210E00160E9B -:1010B000AF8200302409FFFF1049007B2404FFFFAA -:1010C0003C0808008D0875BC3C0208008C4231B019 -:1010D0003C030800906375AC31043FFF0082102B85 -:1010E0001040001B3067003F3C0208008C4231A8D2 -:1010F0008F83004C000421800062182100641821B5 -:101100003062007F034228213C02000C00A228210B -:101110003C020080344200013066007800C2302575 -:101120002402FF8000621024AF42002830640007D0 -:10113000AF4208048F820024034420212484094004 -:10114000AF460814AF850028AF840034AC430118C3 -:101150009383003C240200031462003B240200013C -:101160002402002610E2003D28E200271040001370 -:10117000240200322402002210E2003828E2002378 -:1011800010400008240200242402002010E2002461 -:101190002402002110E2001E022020210A001A7BF6 -:1011A0002402000B10E2002D2402002510E20010A2 -:1011B000022020210A001A7B2402000B10E2001AF0 -:1011C00028E20033104000062402003F24020031D0 -:1011D00010E2000B022020210A001A7B2402000BDF -:1011E00010E20011022020210A001A7B2402000BC9 -:1011F0000E001768022020210A001A960040802164 -:101200000E0018EA022020210A001A9600408021D0 -:101210000E00198B022020210A001A96004080211E -:101220001509000E000000000E00180F02202021FA -:101230000A001A96004080210E001587A3820048FC -:101240000A001A9600408021146200170200202133 -:101250002402002314E200052402000B0E00188172 -:10126000022020210A001A9600408021022020211D -:10127000A38200480E0015872410FFFF0A001A976A -:101280000200202130A500FF0E0014852406000175 -:101290009783003E8F820040A780003E00431023CA -:1012A000AF820040020020218FBF00188FB10014D0 -:1012B0008FB000100080102103E0000827BD00203F -:1012C00027BDFFE0AFB10014AFBF0018AFB00010F2 -:1012D0008F4601283C0308008C6331A02402FF8064 -:1012E000AF86004C00C318213065007F03452821DC -:1012F000006218243C02000AAF43002400A2282107 -:1013000090A2006200808821AF850024304200FF57 -:1013100000021102A382003C90A200BC30420002F5 -:101320001440000224030034240300308F82002480 -:10133000A383002C9383003C8C4200C0A380004810 -:10134000AF82004024020004106200308F8400400D -:101350008E2400045080002D8F8400408E220010C7 -:101360003083FFFFA784003E1060001FAF8200445F -:101370008F8300242405FF800220202190620063D7 -:1013800000A21024304200FF1440000D00000000B5 -:101390000E001A029790003E1040001000401821E5 -:1013A0002402FFFD546200118E2300200200282138 -:1013B0000E001426022020210A001AE88E230020A5 -:1013C0009062006300A21024304200FF104000032E -:1013D000022020210E00174A000000009782003EE4 -:1013E0001440FFE48F8300248E2300203062000429 -:1013F000104000068F8400402402FFFB006210248E -:101400000E00143AAE2200208F8400408F83002407 -:101410008FBF00188FB100148FB00010240200019C -:1014200027BD002003E00008AC6400C030A500FF29 -:101430002403000124A900010069102B1040000CB6 -:1014400000004021240A000100A31023004A3804B0 -:1014500024630001308200010069302B104000023B -:10146000000420420107402554C0FFF800A31023C8 -:1014700003E000080100102127BDFFE03C021EDC54 -:10148000AFB20018AFB10014AFBF001CAFB0001076 -:1014900034526F4100008821240500080E001AF81C -:1014A00002202021001180803C07080024E771AC55 -:1014B0000002160002071821AC620000000028217B -:1014C00024A200013045FFFF8C6200002CA600081A -:1014D00004410002000220400092202614C0FFF8C0 -:1014E000AC640000020780218E0400000E001AF890 -:1014F00024050020262300013071FFFF2E23010068 -:101500001460FFE5AE0200008FBF001C8FB2001810 -:101510008FB100148FB0001003E0000827BD002039 -:101520003C02080024426A743C010800AC2271A00D -:101530003C02080024424FF03C010800AC2271A498 -:10154000240200063C010800A02271A80A001B0B1F -:101550000000000027BDFFD8AFB3001CAFB20018D9 -:10156000AFBF0020AFB10014AFB000108F510140E9 -:101570008F48014800089402324300FF311300FFF6 -:101580008F4201B80440FFFE27500180AE110000D9 -:101590008F420144AE02000424020002A612000899 -:1015A000A202000B24020014AE13002410620025D6 -:1015B00028620015104000082402001524020010C3 -:1015C0001062003024020012106200098FBF002058 -:1015D0000A001C358FB3001C106200702402002228 -:1015E000106200378FBF00200A001C358FB3001C2B -:1015F0003C0208008C4231A02403FF80022210210B -:1016000000431024AF4200243C0208008C4231A069 -:10161000022210213042007F034218213C02000ABE -:1016200000621821166000BCAF8300249062006243 -:101630003042000F34420030A06200620A001C34C5 -:101640008FBF00203C0460008C832C083C02F00318 -:101650003442FFFF00621824AC832C083C020800CF -:101660008C4231A08C832C0824420074000210822A -:101670000002148000621825AC832C080A001C3478 -:101680008FBF00203C0208008C4231A02403FF8061 -:101690000222102100431024AF4200243C02080023 -:1016A0008C4231A03C03000A022210213042007F0C -:1016B00003421021004310210A001C33AF82002492 -:1016C0003C0208008C4231A02405FF800222102138 -:1016D00000451024AF4200243C0208008C4231A097 -:1016E000022210213042007F034218213C02000AEE -:1016F000006218219062006300A21024304200FFB3 -:1017000010400085AF8300242462008894430012B7 -:101710003C0208008C4231A830633FFF000319806F -:1017200002221021004310213043007F0343202177 -:10173000004510243C03000C00832021AF42002808 -:101740009082000D00A21024304200FF1040007271 -:10175000AF8400289082000D304200101440006FCA -:101760008FBF00200E001556000000008F4201B808 -:101770000440FFFE00000000AE1100008F42014453 -:10178000AE02000424020002A6120008A202000B0E -:10179000AE1300240A001C348FBF00202406FF80F3 -:1017A00002261024AF4200203C0208008C4231A0E7 -:1017B00031043FFF00042180022210210046102442 -:1017C000AF4200243C0308008C6331A83C020800AF -:1017D0008C4231A03227007F0223182102221021DF -:1017E000006418213042007F3064007F03422821CA -:1017F0003C02000A0066182400A22821034420218C -:101800003C02000C00822021AF4300283C0200086B -:101810000347182100629021AF850024AF8400287F -:101820000E001556010080218F4201B80440FFFED2 -:101830008F8200288F840024274501809042000D6C -:10184000ACB10000A4B000060002160000021603AE -:1018500000021027000237C214C00016248200883C -:101860009442001232033FFF30423FFF1443001204 -:1018700024026082908300632402FF8000431024CE -:10188000304200FF5040000C2402608290820062CF -:101890003042000F34420040A08200622402608483 -:1018A000A4A200082402000DA0A200050A001C1E2C -:1018B0003C02270024026082A4A20008A0A0000528 -:1018C0003C02270000061C000062182524020002CA -:1018D000A0A2000BACA30010ACA00014ACA000248C -:1018E000ACA00028ACA0002C8E42004C8F840028B5 -:1018F000ACA200189083000D2402FF800043102446 -:10190000304200FF104000058FBF00209082000D84 -:101910003042007FA082000D8FBF00208FB3001CDB -:101920008FB200188FB100148FB000103C0210006D -:0C19300027BD002803E00008AF4201B80A -:04193C00080033F874 -:10194000080033F808003370080033A8080033DCBF -:10195000080034000800340008003400080032E0B9 -:101960000A00012200000000000000000000000D3D -:10197000747061352E302E306A330000050000018E -:101980000000000000000000000000000000000057 -:101990000000000000000000000000000000000047 -:1019A0000000000000000000000000000000000037 -:1019B0000000000000000000000000000000000027 -:1019C0000000000000000000000000000000000017 -:1019D0000000000000000000000000000000000007 -:1019E00000000000000000000000000010000003E4 -:1019F000000000000000000D0000000D3C02080087 -:101A000024421B803C03080024632014AC400000E7 -:101A10000043202B1480FFFD244200043C1D0800DD -:101A200037BD2FFC03A0F0213C10080026100488CD -:101A30003C1C0800279C1B800E00015A000000007F -:101A40000000000D3084FFFF308200078F850018F2 -:101A500010400002248300073064FFF80085302125 -:101A600030C41FFF03441821247B4000AF85001CB5 -:101A7000AF84001803E00008AF4400843084FFFF07 -:101A8000308200078F8500208F86002810400002DA -:101A9000248300073064FFF8008520210086182B7E -:101AA00014600002AF85002400862023034428210F -:101AB00034068000AF840020AF44008000A62021BF -:101AC00003E00008AF84003827BDFFD8AFB3001C87 -:101AD000AFB20018AFB00010AFBF0024AFB4002009 -:101AE000AFB100143C0860088D1450002418FF7F2B -:101AF0003C1A8000029898243672380CAD125000BF -:101B00008F5100083C07601C3C0860003630000123 -:101B1000AF500008AF800018AF400080AF40008495 -:101B20008CE600088D0F08083C0760168CEC00005E -:101B300031EEFFF039CA00103C0DFFFF340B80007E -:101B40003C030080034B48212D440001018D2824D3 -:101B50003C0253533C010800AC230420AF890038F9 -:101B6000AF860028AF840010275B400014A200035A -:101B700034E37C008CF90004032818218C7F007C5E -:101B80008C6500783C02800034520070AF85003CC8 -:101B9000AF9F00403C13080026731BC40240A021E5 -:101BA0008E4800008F46000038C3000130640001F9 -:101BB00010800017AF880034028048218D2D00006E -:101BC0003C1908008F39045C3C1108008E31045820 -:101BD00001A8F823033F7821000040210228382182 -:101BE00001FF802B00F070213C010800AC2F045C49 -:101BF0003C010800AC2E04588F4C0000398B0001CA -:101C0000316A00011540FFED01A04021AF8D003485 -:101C10008E4E00003C0C08008D8C045C3C0A0800D1 -:101C20008D4A045801C86823018D282100005821DD -:101C300000AD302B014B2021008610213C01080013 -:101C4000AC25045C3C010800AC2204588F45010817 -:101C50008F44010030A92000AF850000AF84000C44 -:101C60001120000A00A030213C0708008CE7042C5A -:101C700024EF00013C010800AC2F042C3C10400074 -:101C8000AF5001380A0001900000000030B002009F -:101C90001600001424110F001091001224070D00EB -:101CA0001087023330B000065200FFF53C104000B0 -:101CB000936D0000240C001031A600F010CC0269D6 -:101CC000240E007010CE02DD8F8B001425670001FA -:101CD000AF8700143C104000AF5001380A0001905B -:101CE00000000000974801041100FFE53C1040008F -:101CF00030B84000170000A2000000008F590178A2 -:101D00000720FFFE8F8700382409000824050800FB -:101D10008CE30008AF450178A7490140A740014284 -:101D2000974201048F8600003049FFFF30DF000139 -:101D300013E002D5012040212524FFFE240A0002E1 -:101D4000A74A01463088FFFFA74401483C0B080022 -:101D50008D6B043C156002C48F8F000C30C30020D3 -:101D600014600002240400092404000130CD0C009A -:101D7000240C040051AC000134840004A744014A3F -:101D80003C0508008CA504203C0200483C190001D9 -:101D900000A2F82530D8000203F92825130000041A -:101DA000000018213C04010000A4282524030001A0 -:101DB00030CA000451400005AF8300083C06001003 -:101DC00000A6282524030001AF830008AF451000BA -:101DD0000000000000000000000000000000000003 -:101DE0008F83000810600023000000008F4B10005C -:101DF0000561FFFE000000001060001E00000000F2 -:101E00008F4D10003C03002001A3602411800019B5 -:101E10008F8F000031EE000211C00016000000009C -:101E2000975010141600001300000000974510088A -:101E300030BFFFFF27F800060018C8820019308065 -:101E400000C72821331100013303000312200320AF -:101E50008CA200000000000D00C7F821AFE20000D6 -:101E60003C1908008F390430272600013C01080086 -:101E7000AC2604308F6A00003405FFFFAF8A0004EF -:101E80008CE200001045029A000020218CE5000041 -:101E900030BF010013E0027E010020213C07080052 -:101EA0008CE704743C1008008E10044C00E85821A4 -:101EB0003C1808008F1804700168882B3C08080043 -:101EC0008D0804480000782102046021030F1821C6 -:101ED0000184702B010F68210071502101AE102187 -:101EE0003C010800AC2C044C3C010800AC22044826 -:101EF0003C010800AC2B04743C010800AC2A0470BF -:101F00008F8D0018012030213129000725AE0008EF -:101F100031C21FFF03426021AF8D001CAF82001849 -:101F2000259B4000AF420084112000038F900020C9 -:101F300024C800073106FFF88F84002800D028212C -:101F400000A4782B15E00002AF90002400A4282301 -:101F50000345202134038000008310213C0610003B -:101F6000AF850020AF820038AF450080AF460178D2 -:101F70008F8B0014256700010A0001DDAF87001474 -:101F80008F6200088F670000241100300007C6022E -:101F9000330300F0107100A2241900401479FF4BA4 -:101FA0008F8B00148F4A01780540FFFE30A7020096 -:101FB00014E00003000512820000000D00051282EB -:101FC000305000030010490001307021000E68807D -:101FD00001B06021000C5880017380218E08000040 -:101FE00015000002000000000000000D8F6F0004CB -:101FF00005E202B19203000692070005920F000469 -:102000003C0200010007288000B060218D89001883 -:102010002771000825EE000501226821000E30829C -:10202000AD8D0018022020210E0005802605001429 -:10203000920B00068F7F00043C087FFF000B20807E -:10204000009130218CC30004350AFFFF03EAC82445 -:102050000079C021ACD80004920700059209000461 -:10206000960D00080007288000B1F8218FEF0000CE -:10207000974201043C07FFFF01E75024304EFFFF69 -:1020800001C96021018D58233168FFFF01482025D7 -:10209000AFE40000920300072419000110790269DF -:1020A0002406000310660279000000008E1900105B -:1020B000241F000AA75F0140A759014292030004B0 -:1020C0008F86000024070001A7430144A740014672 -:1020D0009758010430D100023C050041A75801483F -:1020E00000001821A747014A1220000330CA00044B -:1020F0003C0501412403000151400005AF83000865 -:102100003C08001000A8282524030001AF83000824 -:10211000AF451000000000000000000000000000BB -:10212000000000008F8B0008116000040000000018 -:102130008F4410000481FFFE000000008F6A000041 -:10214000920700043C0508008CA50444AF8A0004F3 -:10215000975F01043C0F08008DEF044030E300FF5F -:1021600033F9FFFF0079C02100B868210000102179 -:1021700024E6000A30C8FFFF01B8482B01E27021B5 -:1021800001C96021311000073C010800AC2D044456 -:102190003C010800AC2C0440120000038F8D001895 -:1021A000250B00073168FFF8010D702131CC1FFFAE -:1021B000AF8D001CAF8C0018AF4C00849744010415 -:1021C000034C80213084FFFF30880007110000039A -:1021D000261B4000248900073124FFF88F8200204D -:1021E0008F850028008220210085782B15E00002D1 -:1021F000AF82002400852023034488213405800019 -:10220000022510213C061000AF840020AF82003868 -:10221000AF440080AF4601780A0002858F8B00141E -:102220008F5F017807E0FFFE30AA0200154000032F -:10223000000542820000000D0005428231020003C9 -:102240000002710001C26821000D608001824821F6 -:102250000009288000B380218E0B0000116000026D -:10226000000000000000000D8F6F000C05E001F37E -:102270008F87003824190001AE1900008CE3000894 -:10228000A20000078F78000400181C02306600FFCF -:1022900024D10005001130822CC4004114800002BA -:1022A000A20300040000000D8F6B00043C0EFFFF32 -:1022B00000E028213164FFFF248F000B000F4082D3 -:1022C00000081080004748218D2D000026040014CE -:1022D000A60B000801AE60240E000580AD2C0000A6 -:1022E0008F5F01083C0A100003EA382410E001A3C4 -:1022F00000000000974601049203000724D1FFEC80 -:10230000346500023224FFFFA2050007960600088C -:102310002CC7001354E0000592030007920A00073F -:10232000355F0001A21F000792030007240B000184 -:10233000106B01BA24090003106901CD8F880038A1 -:1023400030CFFFFF25E400020004C883333F00FFC5 -:10235000001F2880A219000500A858218D780000D0 -:10236000975101043C03FFFF030360243222FFFF67 -:10237000004F702325CDFFFE018D4825AD6900007B -:10238000920600053C02FFF6344EFFFF30CA00FF04 -:10239000000A388000F02021909900143C1FFF7F34 -:1023A00037E7FFFF3323000F0066782131F800FF85 -:1023B0000018288000B088218E2D002000A8602100 -:1023C000A20F000601AE4824AE0D000CAD89000C32 -:1023D000920B00068E04000C0127F824000B50809D -:1023E0000150C821972600260148C02100874024BB -:1023F000AF260024AE08000CAF3F0020AF0600104F -:102400008F860000240C001024090002A74C014014 -:10241000A7400142A7400144A7490146974B010448 -:102420002407000130C80002256AFFFEA74A0148C0 -:102430003C050009A747014A1100000300001821CC -:102440003C0501092403000130CD000451A0000522 -:10245000AF8300083C06001000A6282524030001D5 -:10246000AF830008AF45100000000000000000002E -:102470000000000000000000921800042711000274 -:10248000322F0007000F1023304E0007AE0E001051 -:102490008F90000812000004000000008F4310001D -:1024A0000461FFFE000000008F7800008F8F00188D -:1024B0003C1008008E100444AF98000497510104AA -:1024C00025E6001030CA1FFF3222FFFFAF8F001C2D -:1024D000AF8A0018AF4A00842449FFFE3C0B080075 -:1024E0008D6B0440974E010401206821000967C3E9 -:1024F000020D282131C9FFFF00AD402B016C3821AE -:1025000000E82021034AF821313900073C01080086 -:10251000AC2504443C010800AC2404401320000313 -:1025200027FB4000252300073069FFF88F9F00201C -:102530008F840028013F382100E4C82B17200002B7 -:10254000AF9F002400E43823034720213405800096 -:10255000008510213C061000AF870020AF820038B4 -:10256000AF470080AF4601780A0002858F8B0014C8 -:10257000975801041300FDC23C1040008F430178BE -:102580000460FFFE30B94000132000033C04000843 -:102590000000000D3C040008AF440140240808007E -:1025A000AF4801788F8B0000974A0104317F00010A -:1025B00013E000E93146FFFF24D0FFFE240C0002A7 -:1025C000A74C0146A75001488F8F00182405000D25 -:1025D000A745014A8F71000025E2000830491FFF1E -:1025E0000349702130CD0007AF910004AF8F001C6C -:1025F000AF89001800C03821AF49008411A0000342 -:1026000025DB400024C6000730C7FFF88F98002064 -:102610008F84002800F8302100C4382B14E0000219 -:10262000AF98002400C430238F8A00140346582139 -:10263000340880000168F821255900013C0310008E -:102640003C104000AF860020AF9F0038AF460080AE -:10265000AF430178AF990014AF5001380A000190E0 -:10266000000000008F690000974401043127FFFF3C -:102670003088FFFF8F4F017805E0FFFE30FF000735 -:10268000001F18233078000724E6FFFE2419000AF3 -:10269000A7590140A7580142A7460144A740014657 -:1026A000A74801488F42010830510020162000023F -:1026B000240300092403000130AA0002A743014AB1 -:1026C0003C04004111400003000018213C0401417A -:1026D0002403000130AB000451600005AF83000803 -:1026E0003C0500100085202524030001AF8300086D -:1026F000AF441000000000000000000000000000D7 -:10270000000000008F90000812000004000000008C -:102710008F4C10000581FFFE000000008F78000044 -:10272000276200088F8D003CAF9800049446000893 -:102730009451000A944F000C30CEFFFF001124008A -:1027400031E9FFFF11CD00A2008920253C030800DC -:102750008C6304443C1808008F18044000E85021A2 -:10276000255FFFFE007F78210000102101FF302B44 -:1027700003028821022648213C010800AC2F0444B2 -:102780003C010800AC29044024EB00083162FFFF43 -:102790003047000710E000038F8500182450000721 -:1027A0003202FFF83106FFFF30C8000700457021F4 -:1027B00031CD1FFF034D6021AF85001CAF8D001888 -:1027C000259B4000AF4D0084110000038F8F002037 -:1027D00024C400073086FFF88F84002800CF28210A -:1027E00000A4482B15200002AF8F002400A428234A -:1027F000AF850020AF4500803C1108008E310434C5 -:102800000345C0213402800003023021122000055C -:10281000AF860038938300172419000E1079000D3D -:10282000241F043F3C0A1000AF4A01788F8B00142C -:10283000256700010A0001DDAF8700140E0005A620 -:102840003C1040008F8B0014256700010A0001DE58 -:10285000AF8700143C0A1000A75F0148AF4A017817 -:102860000A0004B48F8B0014240E0F0011EE003DFB -:1028700030D10020162000022403000924030001A7 -:102880000A000208A743014A0A0001FBA7400146CB -:1028900094E5000894E2000A94EB000C8F86003C5B -:1028A0000002FC00316AFFFF30B9FFFF132600373A -:1028B00003EA20253C0508008CA504443C1F0800C1 -:1028C0008FFF04400000502100A8382100E8302B81 -:1028D00003EAC8210326C0213C010800AC270444B8 -:1028E0003C010800AC3804400A0002698F8D0018D2 -:1028F0003C1908008F39047C3C0308008C630454A5 -:102900003C0608008CC604783C0F08008DEF04508C -:10291000032838210068682100E8C02B00C4882102 -:1029200001A8402B01E470210238582101C8602120 -:102930003C010800AC2D04543C010800AC2C0450B0 -:102940003C010800AC27047C3C010800AC2B047857 -:102950000A0002698F8D0018A74001460A00041B77 -:102960008F8F001830D000201600FFC52403000D03 -:10297000240300050A000208A743014A97590104ED -:102980002738FFF00A00036B3304FFFF8F8C0040F1 -:10299000148CFFC8000080213C1108008E31046CAB -:1029A0003C0408008C8404680228702101C8782B3C -:1029B00000904021010F68213C010800AC2E046CFE -:1029C0003C010800AC2D04680A0002698F8D0018D4 -:1029D0008F9900401499FF5D000060213C050800BC -:1029E0008CA5046C3C1008008E10046800E82021BF -:1029F000248EFFFE00AEF82103EE582B020C50216E -:102A0000014B18213C010800AC3F046C3C0108005C -:102A1000AC2304680A00048B24EB00088F8800387C -:102A20003C02FFFF8D0E000C01C2682401A460254A -:102A3000AD0C000C0A00037930CFFFFF0A0003A998 -:102A4000AE000000974B0104920400048E2A000C93 -:102A500001644021251FFFF20147182433F9FFFFCD -:102A60000079C025AE38000C0A0002D48E1900107F -:102A70003C03FFFF8D1100100223282400A47825B9 -:102A8000AD0F00100A00037930CFFFFF9745010416 -:102A9000920600048E2F001000A610212449FFEE9C -:102AA00001E76824312EFFFF01AE6025AE2C001037 -:102AB0000A0002D48E1900108E06000CAE00000031 -:102AC0000003C080031088210A0002A6AE26002061 -:102AD0001460000D3050FFFF3C04FFFF00446024F1 -:102AE00001846826000D582B000C502B014B10243C -:102AF00010400002000000000000000D8CA3000048 -:102B00000A00023E006410253A11FFFF0011782BE5 -:102B10000010702B01CF2024108000020000000064 -:102B20000000000D8CB800000A00023E3702FFFFD3 -:102B30003084FFFF30A5FFFF108000070000182140 -:102B4000308200011040000200042042006518217C -:102B50001480FFFB0005284003E0000800601021FE -:102B600010C00007000000008CA2000024C6FFFF78 -:102B700024A50004AC82000014C0FFFB24840004E0 -:102B800003E000080000000010A0000824A3FFFFDD -:102B9000AC86000000000000000000002402FFFFDF -:102BA0002463FFFF1462FFFA2484000403E000089A -:102BB00000000000308EFFFF30D8FFFF00057C00D2 -:102BC00001F8602539CDFFFF01AC5021014C582B95 -:102BD000014B4821000944023127FFFF00E8302162 -:102BE0000006240230C5FFFF00A418213862FFFF51 -:102BF00003E000083042FFFF3C0C08008D8C048489 -:102C0000240BFF8027BDFFD001845021014B4824B5 -:102C1000AF4900203C0808008D080484AFB20020B2 -:102C2000AFB00018AFBF0028AFB30024AFB1001C95 -:102C3000936600040104382130E4007F009A1021DB -:102C40003C0300080043902130C500200360802130 -:102C50003C080111277B000814A0000226460070E2 -:102C60002646006C9213000497510104920F000451 -:102C70003267000F322EFFFF31ED004001C72823DD -:102C800011A0000500004821925900BC333800040F -:102C90001700009000000000924300BC307F000449 -:102CA00013E0000F0000000010A0000D0000000065 -:102CB000960E0002240AFF8000A7602125CDFFFEAA -:102CC000A74D1016920B0004014B2024308200FF08 -:102CD00010400085010C40253C0F0400010F4025E9 -:102CE0008F5301780660FFFE2404000AA7440140C8 -:102CF000960D00022404000931AC0007000C582393 -:102D0000316A0007A74A0142960200022443FFFEEF -:102D1000A7430144A7400146975F0104A75F01480C -:102D20008F590108333800205300000124040001AA -:102D3000920F000431EE001015C000023483001021 -:102D400000801821A743014A000000000000000095 -:102D50000000000000000000AF481000000000006C -:102D60000000000000000000000000008F51100073 -:102D70000621FFFE3113FFFF126000030000000078 -:102D80008F481018ACC8000096030006307FFFFF84 -:102D900027F900020019988200138880023B302135 -:102DA0008CD800001520005700183402920300044C -:102DB0002405FF8000A3F82433F100FF1220002C2B -:102DC00000000000924700BC30F2000212400028D0 -:102DD00000000000974B100C2562FFFEA742101662 -:102DE000000000003C0A040035490030AF491000E3 -:102DF00000000000000000000000000000000000D3 -:102E00008F4C10000581FFFE000000009749100C58 -:102E10008F51101C00C020213127FFFF24F2003009 -:102E2000001218820003288000BBF8213226FFFF21 -:102E3000AFF100000E00059500112C020013C880B0 -:102E4000033B98218E78000000027400AFB8001098 -:102E50008FA80010310FFFFFAFAF00108FA400103C -:102E600001C46825AFAD00108FA60010AE6600004B -:102E700097730008976D000A9766000C8F8A003CD4 -:102E8000000D5C0030CCFFFF3262FFFF104A0036BD -:102E9000016C2025960600023C10100024D3000887 -:102EA0000E0001393264FFFF974C01040E00014708 -:102EB0003184FFFFAF5001788FBF00288FB300240B -:102EC0008FB200208FB1001C8FB0001803E0000803 -:102ED00027BD003010A0FF700000000024A5FFFCFB -:102EE0000A0005CE240900048CD10000AF5110184F -:102EF0008F5301780660FF7A2404000A0A0005E374 -:102F00000000000000A7C8218F8800388F4E101CD9 -:102F10000019C0820018788001E82021AC8E0000E2 -:102F2000000E2C0200C020210E00059531C6FFFFC7 -:102F3000023B28218CAD00000002540000403021EB -:102F4000AFAD00108FAC0010318BFFFFAFAB0010A6 -:102F50008FA2001001424825AFA900108FA70010D2 -:102F60000A000613ACA700008F8F0040148FFFC922 -:102F70000000000097420104960B00023C05080087 -:102F80008CA5046C3049FFFF316AFFFF3C1108003B -:102F90008E310468012A382124F2FFFE00B240215C -:102FA0000012FFC30112C82B023FC02103192021C8 -:102FB0003C010800AC28046C3C010800AC24046807 -:102FC0000A00064D0000000000A4102B104000096C -:102FD000240300010005284000A4102B04A00003D6 -:102FE000000318405440FFFC000528401060000713 -:102FF000000000000085302B14C0000200031842BE -:10300000008520231460FFFB0005284203E0000830 -:10301000008010218F85002C27BDFFE80005302798 -:103020002CC300012CA400020083102510400003D3 -:10303000AFBF00102405007FAF85002C00052827B6 -:1030400030A5FFFF0E000574240426F58F830030A1 -:10305000240402BD004030210083382B10E0000919 -:1030600024050001000420400083102B048000038D -:10307000000528405440FFFC0004204010A0000838 -:1030800000C350210064402B1500000200052842B7 -:103090000064182314A0FFFB0004204200C3502149 -:1030A0008FBF0010000A4C02312200FF27BD00181C -:0C30B000AF8A002C03E00008AF8900305C -:0430BC000A00002ADC -:1030C00000000000000000000000000D7478703562 -:1030D0002E302E306A330000050000000000000A88 -:1030E000000001360000EA6000000000000000005F -:1030F00000000000000000000000000000000000D0 -:1031000000000000000000000000000000000000BF -:103110000000000000000000000000000000001699 -:10312000000000000000000000000000000000009F -:10313000000000000000000000000000000000008F -:10314000000000000000000000000000000000007F -:10315000000000000000138800000000000005DCF3 -:10316000000000000000000010000003000000004C -:103170000000000D0000000D3C02080024423B60EE -:103180003C03080024633D14AC4000000043202BA6 -:103190001480FFFD244200043C1D080037BD7FFC65 -:1031A00003A0F0213C100800261000A83C1C0800D9 -:1031B000279C3B600E0002BA000000000000000DDA -:1031C0008F8300383C088000350700708CE50000D4 -:1031D000008330253C02900000C22025AF850030DE -:1031E000AF4400208F4900200520FFFE3C038000F3 -:1031F000346200708C4500008F8600303C19080056 -:103200008F39007C3C0E08008DCE007800A620236C -:1032100003245821000078210164682B01CF60212C -:10322000018D50213C010800AC2B007C3C010800C2 -:10323000AC2A007803E00008000000000A0000410A -:10324000240400018F8400383C05800034A2000172 -:103250000082182503E00008AF43002003E00008C7 -:10326000000010213084FFFF30A5FFFF1080000711 -:1032700000001821308200011040000200042042AA -:10328000006518211480FFFB0005284003E00008BA -:103290000060102110C00007000000008CA2000098 -:1032A00024C6FFFF24A50004AC82000014C0FFFB6D -:1032B0002484000403E000080000000010A00008BF -:1032C00024A3FFFFAC860000000000000000000007 -:1032D0002402FFFF2463FFFF1462FFFA248400042A -:1032E00003E0000800000000308AFFFF93A80013ED -:1032F000A74A014497490E1630C600FF3C02100051 -:10330000A7490146AF450148A3460152A748015AC3 -:10331000AF4701608FA400188FA30014A744015881 -:10332000AF43015403E00008AF42017803E0000816 -:10333000000000003C038000346200708C490000F3 -:103340008F8800002484000727BDFFF83084FFF831 -:10335000AF890030974D008A31ACFFFFAFAC000061 -:103360008FAB0000016850232547FFFF30E61FFFA9 -:1033700000C4282B14A0FFF73C0C8000358B007094 -:103380008D6A00003C0708008CE700843C060800BA -:103390008CC6008000081082014918230002788042 -:1033A00000E370210000202101C3C82B00C4C0210C -:1033B00001FA4021031948212502400027BD0008D9 -:1033C0003C010800AC2E00843C010800AC290080C0 -:1033D00003E00008000000008F8200002486000740 -:1033E00030C5FFF800A2182130641FFF03E0000879 -:1033F000AF8400008F8700388F8A004027BDFFB858 -:103400008F860044AFB60040AFBF0044AFB5003C6C -:10341000AFB40038AFB30034AFB20030AFB1002C5E -:10342000AFB000288F4501048D4900ACAF47008044 -:103430008CC8002000A938230000B021AF480E102E -:103440008F440E1000004821AF440E148CC200249B -:10345000AF420E188F430E18AF430E1C10E001252B -:103460002D230001936B0008116000D400000000C0 -:10347000976E001031CDFFFF00ED602B158000CF5F -:103480000000000097700010320FFFFFAF4F0E00DA -:103490008F520000325100081220FFFD0000000092 -:1034A00097540E088F460E043285FFFF30B300019B -:1034B00012600132000000000000000D30B8A04092 -:1034C00024150040131500C030A9A0001120012DC3 -:1034D00000000000937F000813E0000800000000D7 -:1034E00097630010306BFFFF00CB402B11000003EF -:1034F00030AC00401180012300000000A785003C93 -:10350000AF8600349366000800E02821AFA70020B2 -:1035100014C0012427B30020AF60000C9782003C48 -:103520003047400014E00002240300162403000E7C -:1035300024194007A363000AAF790014938A003E60 -:103540008F740014315800070018AA400295902586 -:10355000AF7200149784003C8F70001430910010FB -:1035600002117825AF6F0014978E003C31CD000812 -:1035700011A00147000028218F6700143C021000B1 -:103580003C0C810000E22825AF65001497460E0A26 -:103590002408000E3405FFFC30C3FFFF006C5825E3 -:1035A000AF6B0004A3680002937F000A27E90004C0 -:1035B000A369000A9786003C9363000A30CC1F0081 -:1035C000000C598301634021251F0028A37F0009B7 -:1035D00097490E0CA769001093790009272A000269 -:1035E000315800070018A82332B10007A371000B5F -:1035F00093740009976400108F910034978F003CFA -:10360000329200FF024480210205702131ED00401A -:1036100011A0000531C4FFFF0091282B3C1280004F -:1036200010A000140000A0210224382B14E0011B7C -:103630008FA500208F4D0E14AF4D0E108F420E1C23 -:10364000AF420E18AF440E008F4F000031EE00085D -:1036500011C0FFFD0000000097540E080080882173 -:1036600000009021A794003C8F500E042414000108 -:10367000AF900034976400103095FFFF8E68000013 -:103680000111F82317E00009AE7F00008F650014D8 -:103690008F8B004434A60040AF6600148F4C0E1090 -:1036A000AD6C00208F430E18AD63002493670008B3 -:1036B00014E000D2000000000E00009E2404001060 -:1036C0008F8900483C08320000402821312600FF45 -:1036D0000006FC0003E8502525390001AF99004899 -:1036E000AC4A0000937800099370000A330400FF8D -:1036F00000047400320F00FF01CF6825AC4D0004B8 -:103700008F820048064000EAACA20008ACA0000C82 -:103710009783003C306B00081560000226280006E5 -:1037200026280002974E0E148F450E1C8F6700044A -:10373000936D000231C4FFFF31A200FFAFA2001061 -:103740008F6C0014AFA800180E00008BAFAC0014F3 -:10375000240400100E0000C7000000008E7200005C -:1037600016400005000000008F6400142405FFBF10 -:1037700000859824AF7300148F79000C033538212D -:10378000AF67000C9375000816A000080000000049 -:1037900012800006000000008F7F00143C0BEFFF3A -:1037A0003568FFFE03E84824AF690014A3740008DD -:1037B0008FA500200A00024602202021AF470E00FC -:1037C0000A0000F5000000008F5901780720FFFE75 -:1037D000241F08008F840000AF5F0178974B008A98 -:1037E000316AFFFF014448232528FFFF31021FFFF4 -:1037F0002C4300081460FFF9000000008F8E004881 -:103800008F8D003800C048210344202125C60001C7 -:10381000240C0F00AF86004800E9382324864000BE -:1038200031CA00FF11AC0005240800019391003E4D -:103830003230000700107A4035E80001000AAC0081 -:103840003C18010002B8A025AC9440008F930048BA -:1038500030B2003630A40008ACD3000410800097CA -:1038600001123025974E0E0A8F8D00003C02810018 -:1038700031CCFFFF25AB0008018240253C0310003E -:1038800031651FFF25390006241F000EAF48016077 -:1038900000C33025A75F015AAF850000A759015822 -:1038A00014E0000A8F93003824120F0052720002B5 -:1038B0002416000134C600408F580E108F94004427 -:1038C000AE9800208F550E18AE9500248F450E142B -:1038D000AF4501448F590E1CAF590148A34A01520C -:1038E0003C0A1000AF460154AF4A017814E0FEDDF7 -:1038F0002D2300010076A025128000178FBF004401 -:103900008F84003824160F001096008400000000F9 -:103910008F45017804A0FFFE24150F001095006E5E -:10392000000000008F470E14240202403C1F1000CC -:10393000AF4701448F440E1CAF440148A3400152DD -:10394000A740015AAF400160A7400158AF4201545F -:10395000AF5F01788FBF00448FB600408FB5003C49 -:103960008FB400388FB300348FB200308FB1002C89 -:103970008FB0002803E0000827BD004814C0FED027 -:1039800030B8A0408F420E148F84004400004821BC -:10399000AC8200208F510E1CAC9100240A00020E54 -:1039A0002D2300018F910034978A003C3C12800047 -:1039B0000220A821315800401700FF300000A0214C -:1039C000976900108F9200343139FFFF13320035B0 -:1039D00000002021008048211480FEA000A0382192 -:1039E0008F420E148F840044AC8200208F510E1C35 -:1039F000AC9100240A00020E2D230001936A0009F5 -:103A00009378000B315000FF330F00FF020F70213D -:103A100025C2000A3050FFFF0E00009E0200202148 -:103A20008F8600483C1F410024CD0001AF8D004827 -:103A3000936C000930C600FF00064400318300FF8C -:103A4000246B0002010B4825013FC825AC5900003A -:103A50008F67000C97440E1400F22825AC45000433 -:103A60008F450E1C8F670004936A00023084FFFFAD -:103A7000315800FFAFB800108F6F0014AFB10018BD -:103A80000E00008BAFAF00140A0001A60200202137 -:103A9000AF6000040A00013EA36000020A00024673 -:103AA00000002021000090210A0001702414000170 -:103AB0003C1280000A000195ACB2000C8F9100000E -:103AC00025240002A744015826300008320F1FFFAA -:103AD0000A0001F9AF8F0000AF40014C1120002C0B -:103AE000000000008F590E10AF5901448F430E188B -:103AF000240200403C1F1000AF430148A340015284 -:103B0000A740015AAF400160A7400158AF4201549D -:103B1000AF5F01780A0002278FBF00441120000622 -:103B20000000000097460E0830CC004015800002CF -:103B3000000000000000000D8F4D017805A0FFFE81 -:103B40000000000097530E103C120500240E2000C8 -:103B5000326AFFFF0152C025AF58014C8F4F0E143F -:103B60003C021000AF4F01448F500E1CAF50014873 -:103B7000A34001528F840038A740015AAF40016032 -:103B8000A7400158AF4E01540A000215AF42017818 -:103B90008F490E14AF4901448F430E1C0A00028E58 -:103BA000240200403C0E20FF27BDFFE03C1A8000AD -:103BB0003C0F800835CDFFFDAFBF001CAFB2001831 -:103BC000AFB10014AFB00010AF8F0040AF4D0E008A -:103BD00000000000000000000000000000000000E5 -:103BE000000000003C0C00FF358BFFFDAF4B0E00CA -:103BF0003C0660048CC95000240AFF7F3C11600021 -:103C0000012A40243507380CACC750008E240438F4 -:103C100024050009AF4500083083FFFF38622F718B -:103C20002450C0B3AF8000480E000068AF80000091 -:103C300052000001AE20442C0E0004353C118000DF -:103C40000E000EA8363000708F8A00403C1208002B -:103C500026523BC8020088218E0800008F5F0000BA -:103C60003BF900013338000113000017AF88003022 -:103C7000022048218D2700003C0F08008DEF006CCA -:103C80003C0C08008D8C006800E8C02301F8282156 -:103C90000000682100B8302B018D582101664021B9 -:103CA0003C010800AC25006C3C010800AC28006811 -:103CB0008F44000038830001306200011440FFEDA2 -:103CC00000E04021AF8700308E0C00003C0508006A -:103CD0008CA5006C3C0408008C84006801883023AB -:103CE00000A638210000102100E6402B0082182198 -:103CF0000068F8213C010800AC27006C3C0108007A -:103D0000AC3F00688F49010025590088AF990044F5 -:103D1000AF890038AF4900208E070000AF87003020 -:103D20008F4D017805A0FFFE000000008E06000008 -:103D30003C0B08008D6B00743C0408008C84007000 -:103D400000C728230165F8210000102103E5402B5E -:103D50000082382100E8C821240908003C0108003D -:103D6000AC3F00743C010800AC390070AF490178E9 -:103D700093580108A398003E938F003E31EE000156 -:103D800015C000158F830038240E0D00106E001929 -:103D9000240F0F00106F001D00000000915900005B -:103DA00024180050332900FF113800043C1F400044 -:103DB000AF5F01380A0002E7000000000E0008EEC5 -:103DC000000000008F8A00403C1F4000AF5F0138B8 -:103DD0000A0002E700000000938D003E31AC0006AF -:103DE000000C51000E0000CE0152D8210A000343FE -:103DF0008F8A00403C1B0800277B3C480E0000CE09 -:103E0000000000000A0003438F8A00403C1B0800AA -:103E1000277B3C680E0000CE000000000A00034330 -:103E20008F8A004090AA00018FAB00108CAC00106C -:103E30003C0300FF8D680004AD6C00208CAD0014C5 -:103E400000E060213462FFFFAD6D00248CA70018F4 -:103E50003C09FF000109C024AD6700288CAE001C9E -:103E60000182C82403197825AD6F0004AD6E002CC3 -:103E70008CAD0008314A00FFAD6D001C94A9000212 -:103E80003128FFFFAD68001090A70000A560000278 -:103E9000A1600004A167000090A30002306200FF4F -:103EA0000002198210600005240500011065000E53 -:103EB0000000000003E00008A16A00018CD800287F -:103EC000354A0080AD7800188CCF0014AD6F001417 -:103ED0008CCE0030AD6E00088CC4002CA16A0001AD -:103EE00003E00008AD64000C8CCD001CAD6D001823 -:103EF0008CC90014AD6900148CC80024AD6800089A -:103F00008CC70020AD67000C8CC200148C83006449 -:103F10000043C82B13200007000000008CC20014CF -:103F2000144CFFE400000000354A008003E0000864 -:103F3000A16A00018C8200640A000399000000005D -:103F400090AA000027BDFFF88FA9001CA3AA0000BB -:103F50008FAE00003C0FFF808FA8001835E2FFFFF6 -:103F60008CCD002C01C26024AFAC0000A120000465 -:103F700000E06021A7A000028FB800008D27000498 -:103F80000188182100A0582100C05021006D28266A -:103F90003C06FF7F3C0F00FF2CAD000135EEFFFF1C -:103FA00034D9FFFF3C02FF0003193024000D1DC06F -:103FB000010EC82400E2C02400C37025031978252F -:103FC000AD2E0000AD2F00048D450024AFAE0000E3 -:103FD000AD2500088D4D00202405FFFFAD2D000C00 -:103FE000956800023107FFFFAD27001091660018A9 -:103FF00030C200FF000219C2506000018D4500343C -:10400000AD2500148D67000827BD0008AD27001CF2 -:104010008C8B00CCAD2C0028AD20002CAD2B0024C7 -:10402000AD20001803E00008AD20002027BDFFE010 -:10403000AFB20018AFB10014AFB00010AFBF001C9A -:104040009098000000C088213C0D00FF330F007FD6 -:10405000A0CF0000908E000135ACFFFF3C0AFF00AE -:10406000A0CE000194A6001EA22000048CAB001478 -:104070008E29000400A08021016C2824012A4024FC -:104080000080902101052025A6260002AE24000410 -:1040900026050020262400080E00007624060002D3 -:1040A00092470000260500282624001400071E0061 -:1040B0000003160324060004044000032403FFFF4A -:1040C000965900023323FFFF0E000076AE23001046 -:1040D000262400248FBF001C8FB200188FB100145B -:1040E0008FB0001024050003000030210A0000807A -:1040F00027BD002027BDFFD8AFB1001CAFB000180E -:10410000AFBF002090A80000240200018FB0003C47 -:104110003103003F00808821106200148FAA00380C -:10412000240B0005506B0016AFAA001000A0202140 -:1041300000C028210E0003DC02003021922400BCC4 -:10414000308300021060000326060030ACC000007F -:1041500024C600048FBF00208FB1001C8FB0001850 -:1041600000C0102103E0000827BD002801403821CD -:104170000E00035AAFB000100A0004200000000037 -:104180000E0003A1AFB000140A00042000000000DC -:104190003C02000A034218213C04080024843CAC81 -:1041A0002405001A000030210A000080AF8300546B -:1041B0003C038000346200708C48000000A058214D -:1041C00000C04821308A00FFAF8800308F4401785A -:1041D0000480FFFE3C0C8000358600708CC500001A -:1041E0003C0308008C6300743C1808008F180070B2 -:1041F00000A82023006468210000C82101A4782BB6 -:104200000319702101CF60213C010800AC2D00741E -:104210003C010800AC2C00708F480E14AF480144DC -:10422000AF47014CA34A0152A74B015893460108DE -:1042300030C5000854A0000135291000934B090037 -:1042400024070050316A00FF1147000700000000FA -:104250008F450E1CAF450148AF4901543C09100081 -:1042600003E00008AF490178934D010831A8000828 -:104270001100001000000000934F010831EE001003 -:1042800051C00001352900083C04080090843D100D -:10429000A34401508F4309A4AF4301488F4209A0B2 -:1042A000AF420144AF4901543C09100003E000084B -:1042B000AF4901783C1908008F393CCC33380008ED -:1042C0005700FFF1352900080A00047300000000C0 -:1042D00024070040AF470814AF4008108F4209443C -:1042E0008F4309508F4409548F45095C8F46094C10 -:1042F000AF820064AF830050AF84004CAF85005C98 -:1043000003E00008AF8600609346010930C5007FD6 -:10431000000518C0000521400083102103E00008BB -:10432000244200883C0A0800914A3CD13C0908001C -:1043300095293CCA3C051100000A3C0025280002D2 -:1043400000E8302500C5182524820008AC83000051 -:1043500003E00008AC8000048F4A002C974E090847 -:104360003C0F000E034F382131CDFFFF000D41C03F -:10437000AF48002C9743090894EC001A00804021B4 -:1043800024020001318BFFFFAC8B00008CE9001C84 -:1043900000A0582100C06021AC8900048CE40020FA -:1043A000AD04000890E30019306300031062004080 -:1043B000000000002865000214A00073240600021B -:1043C0001066004E0000000024180003107800570B -:1043D000000000003C09080095293CC093450934C1 -:1043E000934609213C0E080095CE3CC630A200FF42 -:1043F0000002C88294E5002A30C400FF9787005865 -:104400000019C60000041C00312FFFFF0303102514 -:1044100001CF6821004DC82500A720213C0640009F -:104420000326C02500044C00AD090004AD180000AF -:10443000934F09203C03000625090014000F760065 -:1044400001C36825AD0D00088F42092C24E5000149 -:1044500030A67FFFAD02000C8F59093025020028DD -:10446000A7860058AD1900108F440938AD04001418 -:10447000AD2B00048F580940AD380008934F093721 -:104480003C0D080091AD3CD0AD20001031EE00FF96 -:1044900001CC182100036700000D44000188582555 -:1044A0003567FFFFAD27000C03E00008AF4A002C82 -:1044B0003C09080095293CC03C05080094A53CCA6D -:1044C0003C0F080095EF3CBC94E400243126FFFF2C -:1044D00000A6702101CF682300041C0025A2FFF272 -:1044E0000062C82524180800AD19000CAD1800148E -:1044F000AD0000100A0004C82508001894E6002446 -:1045000094E500283C09080095293CC000067C0081 -:104510000005740035ED810035C40800AD0D000CB8 -:10452000AD0400100A0004C8250800143C09080066 -:1045300095293CC03C02080094423CCA3C06080055 -:1045400094C63CBC94E400243125FFFF94F8002875 -:104550000045C8210326782300181C0000046C00C5 -:1045600025EEFFEE006EC82535A281002418080054 -:10457000AD02000CAD190010AD180018AD0000140C -:104580000A0004C82508001C1460FF920000000007 -:1045900094E300243C09080095293CC00003140062 -:1045A00034590800AD19000C0A0004C82508001091 -:1045B00003E00008240201F427BDFFE8AFB00010BB -:1045C000AFBF00140E000060008080212405004071 -:1045D000AF4508148F8300508F84004C8F85005C9A -:1045E000007018210064102318400004AF830050AD -:1045F000AF6300548F660054AF86004C1200000C6D -:10460000000000008F440074936800813409FA00B0 -:104610002D07000710E0000500891021936C008130 -:10462000240B01F4018B500401441021AF62000CF3 -:104630008F4E095C01C5682319A000048FBF0014C8 -:104640008F4F095CAF8F005C8FBF00148FB00010DC -:104650000A00006227BD00188F8400648F83005019 -:104660008F82004CAF640044AF63005003E0000849 -:10467000AF6200543C038000346200708C43000041 -:1046800027BDFFF8308700FF30A900FF30C800FFCA -:10469000AF8300308F4401780480FFFE3C0280002D -:1046A000345900708F380000A3A700033C070800AE -:1046B0008CE700748FAC00003C0608008CC60070CC -:1046C000030378233C0E7FFF00EFC82135CDFFFFA9 -:1046D00000005021018D282400CA1821000847C07D -:1046E000032F202B00A810250064C021AFA20000DA -:1046F0003C010800AC3900743C010800AC38007083 -:10470000934F010AA3A000023C0E80FFA3AF00015B -:104710008FAC0000312B007F35CDFFFF018D482489 -:10472000000B5600012A4025240730002406FF8094 -:104730003C05100027BD0008AF48014CAF470154AD -:10474000A7400158A346015203E00008AF45017895 -:1047500027BDFFE8AFBF0014AFB000108F65007435 -:104760003C068000309000FF00A620250E0000606F -:10477000AF64007493630005346200080E000062A9 -:10478000A3620005020020218FBF00148FB000102B -:1047900024050005240600010A00056E27BD001847 -:1047A00027BDFFE03C038000AFB00010AFBF001892 -:1047B000AFB10014346200708C470000309000FFED -:1047C00030A800FFAF8700308F4401780480FFFEDF -:1047D0003C188000371100708E2F00003C0D08003F -:1047E0008DAD00743C0A08008D4A007001E770230B -:1047F00001AE28210000582100AE302B014B48218A -:10480000012638213C010800AC25007400008821F5 -:104810003C010800AC2700701100000F00000000F0 -:104820008F6200742619FFFF3208007F0002FE022B -:1048300033E5007F15000006332200FF2407FF80C8 -:104840000207202624A3FFFF00838025320200FFF9 -:1048500000408021241110080E00006000000000BC -:104860008F4908183125000414A0FFFD3218007F7D -:10487000001878C00018714001CF682125AC00886D -:10488000AF4C0818274A09808D4B0020AF4B0144DC -:104890008D460024AF460148A35001500E0000622F -:1048A000A7400158022010218FBF00188FB10014BB -:1048B0008FB0001003E0000827BD002027BDFFE8EF -:1048C000308400FFAFBF00100E0005B930A500FF17 -:1048D0008F8300508FBF0010344500402404FF90A8 -:1048E0003C02100027BD0018AF43014CA344015205 -:1048F000AF45015403E00008AF4201789343093EFD -:10490000306200081040000D3C0901013528080AFA -:10491000AC8800008F470074AC8700043C06080098 -:1049200090C63CD030C5001050A00006AC800008F6 -:104930008F6A0060AC8A00082484000C03E0000841 -:10494000008010210A0006202484000C27BDFFE807 -:10495000AFBF0014AFB000109346093F00A0502134 -:10496000000528800085382330C200FF240300069C -:104970003C09080095293CC624E8FFD8240500041A -:1049800010430037240600029750093C3C0F0204F4 -:1049900000063400320EFFFF01CF6825AC8D000009 -:1049A000934C093E318B002011600008000000008C -:1049B000934309363C020103345F0300307900FF62 -:1049C000033FC02524050008AC9800049343093434 -:1049D000935909210005F882306200FF0002C0826D -:1049E000332F00FF00186E00000F740001AE602529 -:1049F000018920253C09400000898025ACF0FFD8C2 -:104A0000934309378F4F09488F580940306200FFA0 -:104A1000004AC821033F702101F86023000E6F0097 -:104A200001A650253185FFFF001F5880014548250C -:104A300001683821AD0900200E00006024F0002834 -:104A4000240400040E000062A364003F0200102151 -:104A50008FBF00148FB0001003E0000827BD0018BE -:104A60000A0006332406001227BDFFD024090010D7 -:104A7000AFB60028AFB50024AFB40020AFB100142A -:104A8000AFB000103C010800A0293CD0AFBF002C03 -:104A9000AFB3001CAFB2001897480908309500FF6B -:104AA0003C02000E3107FFFF000731C0AF46002C6B -:104AB000974409089344010B30B400FF034280215E -:104AC000308300300000B021106001070000882111 -:104AD000240C00043C010800A02C3CD0934B093E60 -:104AE000000B5600000A2E0304A0014B000000003A -:104AF000AF400048934F010B31EE002011C000067B -:104B0000000000009358093E00189E000013960311 -:104B10000640016B000000009344010B308300400D -:104B2000106000038F9300508F8200502453FFFFCA -:104B30009347093E30E6000814C000022412000327 -:104B4000000090219619002C93580934934F09378F -:104B5000A7990058330C00FF31EE00FF024E682188 -:104B6000000D5880016C5021015140213C0108008A -:104B7000A4283CC69205001830A900FF010918219D -:104B80003C010800A4233CC8921100181620000321 -:104B90002467000A0000000D2467000A30F0FFFFC0 -:104BA0003C010800A4233CCA3C010800A4203CC0EE -:104BB0003C010800A4203CBC0E00009E0200202105 -:104BC0000E00049A004020218F4B002C974A0908C0 -:104BD0003C0C000E034C38213145FFFF000549C055 -:104BE000AF49002C9743090894F1001A0040402176 -:104BF000241F00013226FFFFAC4600008CE2001C9F -:104C0000AD0200048CE40020AD04000890E300191C -:104C100030630003107F00D6286D000215A0011C30 -:104C2000240E0002106E010E240F0003106F00E32B -:104C3000000000003C09080095293CC0934E09344F -:104C4000935109213C0A0800954A3CC631CD00FF2A -:104C500094F9002A000D188297870058322C00FF23 -:104C600000032E00000C24003126FFFF3142FFFF1D -:104C700000A4F8250046482103E978250327702180 -:104C80003C18400001F86825000E8C00AD0D0000B6 -:104C9000AD110004934C09203C03000625110014BB -:104CA000000C2E0000A31025AD0200088F49092C2E -:104CB00024E40001309F7FFFAD09000C8F460930CE -:104CC00025090028A79F0058AD0600108F59093804 -:104CD00001203021AD190014AE3300048F58094073 -:104CE000AE380008934F09373C0C0800918C3CD03B -:104CF000AE20001031EE00FF01D26821000D2F0020 -:104D0000000C1C0000A310253447FFFFAE27000C49 -:104D1000AF4B002C934B093E317300081260000D1D -:104D20003C0F010135E7080AAD0700288F4B0074DE -:104D3000AD2B00043C13080092733CD03268001085 -:104D400051000003AD2000088F780060AD380008E6 -:104D50002526000C12C0003800000000935F093FB8 -:104D6000241600062407000433F900FF133600D28E -:104D7000240800029743093C3C0C02043064FFFF06 -:104D8000008C2825ACC500009342093E3049002024 -:104D90001120000800000000934B09363C1301036A -:104DA000366E0300316D00FF01AE8825ACD10004E2 -:104DB000240700089349093493590921314BFFFF17 -:104DC000313F00FF001FB082333800FF001656004D -:104DD00000187C00014F982500122880026B68257E -:104DE0003C0E400000C5502301AE8825AD51FFD8D0 -:104DF000934309378F5F09488F490940306C00FFA2 -:104E000001921021000720820044C82103E9782381 -:104E10000019C7000008B4000316402531E7FFFF62 -:104E2000010730250E000060AD46FFF82412000493 -:104E30000E000062A372003F0E0000C70200202196 -:104E40003C12080092523CD0325000031200000F76 -:104E500002A020218F82005024470001AF8700501C -:104E6000AF6700508F6800540107302318C000025C -:104E700000E020218F640054AF6400548F4C007414 -:104E8000258401F4AF64000C02A0202102802821B7 -:104E9000A76000680E0005B93C1410008F8D00500B -:104EA00034550006AF4D014C8F9100488FBF002C48 -:104EB0008FB6002826230001AF8300488FB3001C63 -:104EC000A35101528FB20018AF5501548FB1001495 -:104ED000AF5401788FB500248FB400208FB000103C -:104EE00003E0000827BD00309358093E00189E00DB -:104EF0000013960306420051241100029344092333 -:104F0000308300021060FEFB8F8600608F820050AD -:104F100014C2FEF8000000000E0000600000000057 -:104F20009369003F24070016312800FF1107000C89 -:104F3000240500083C0C0800918C3CD0358B000106 -:104F40003C010800A02B3CD0936A003F314300FF96 -:104F500010650065240D000A106D005E2402000C2F -:104F60000E000062000000000A00068E0000000033 -:104F70003C09080095293CC03C04080094843CCAC4 -:104F80003C1F080097FF3CBC94F800243123FFFF2E -:104F90000083C821033F782300186C0025EEFFF240 -:104FA00001AE6025240A0800AD0C000CAD0A001407 -:104FB000AD0000100A0006E0250800183C090800B2 -:104FC00095293CC03C1F080097FF3CCA3C190800CB -:104FD00097393CBC94EF00243124FFFF94EE002865 -:104FE00003E4C02103196823000F2C00000E5400B5 -:104FF00025ACFFEE014C882534A281002406080070 -:10500000AD02000CAD110010AD060018AD0000148B -:105010000A0006E02508001C8F6E00848F4D0940B1 -:1050200011A0FEB3AF8E0050240F00143C01080005 -:10503000A02F3CD00A00068D000000003C010800B3 -:10504000A0313CD0935F093E2416000133F90020C3 -:105050001720FEA8241100080A00068E241100045F -:1050600094E5002494F100283C09080095293CC0EF -:1050700000051400001134003444810034C30800DA -:10508000AD04000CAD0300100A0006E02508001472 -:105090001460FEE80000000094FF00243C090800B2 -:1050A00095293CC0001FCC0037380800AD18000C13 -:1050B0000A0006E0250800100A00072E2408001246 -:1050C0008F7F004CAF7F00548F7900540A00069701 -:1050D000AF790050A362003F0E00006200000000A4 -:1050E0000A00068E00000000240200140A000807CF -:1050F000A362003F27BDFFE8308400FFAFBF001070 -:105100000E0005B930A500FF9378007E9379007FEB -:10511000936E00809368007A332F00FF00186600BA -:10512000000F6C0031CB00FF018D4825000B5200B1 -:105130008FBF0010012A3825310600FF344470006B -:1051400000E628252402FF813C03100027BD00183B -:10515000AF45014CAF440154A342015203E00008A3 -:10516000AF43017827BDFFD8AFB20018AFB100142C -:10517000AFB00010AFBF0020AFB3001C93420109D5 -:10518000308600FF30B000FF000618C23204000273 -:105190003071000114800005305200FF9367000554 -:1051A00030E5000810A0000D30C80010024020219A -:1051B0000E0005A502202821240400018FBF002035 -:1051C0008FB3001C8FB200188FB100148FB0001085 -:1051D0000080102103E0000827BD002815000032E0 -:1051E0000000000093430109000028213062007F85 -:1051F000000220C00002F94003E4982126790088CB -:10520000033B98218E7800248E6F0008130F004610 -:10521000000000008F640084241800020004FD8256 -:1052200033F900031338007C00000000936600830C -:10523000934A0109514600043205007C10A0006029 -:10524000000000003205007C14A000530240202121 -:1052500016200006320400018E7F00248F590104BD -:1052600017F9FFD600002021320400011080000A47 -:10527000024020218F4209408F93006410530006A2 -:10528000000000000E00066B022028218F43094019 -:10529000AF630044024020210E00060002202821B6 -:1052A0000A000840240400013C0908008D2900641C -:1052B000252600013C010800AC26006416000012FF -:1052C000000000008F6D00843C0E00C001AE602421 -:1052D00015800005024020210E00080E0220282122 -:1052E0000A00084024040001240500040E00056E95 -:1052F00024060001024020210E00080E0220282171 -:105300000A000840240400010E00004124040001AA -:10531000936B007D020B50250E000062A36A007D96 -:105320000A0008838F6D00848F6600748F48010423 -:105330008E67002400064E021507FFB63126007F57 -:10534000936B008326440001308A007F114600439E -:10535000316300FF5464FFB08F6400842645000170 -:1053600030B1007F30A200FF1226000424050001A6 -:10537000004090210A00085624110001240FFF80EC -:10538000024F702401CF9026324200FF004090214E -:105390000A000856241100010E00066B0220282185 -:1053A000321800301300FFAA321000820240202180 -:1053B0000E0005A5022028210A000840240400014F -:1053C0008F6E00743C0F80002405000301CF9025F0 -:1053D000AF72007493710083240600010E00056E05 -:1053E000322400FF0E00004124040001936D007D73 -:1053F000020D60250E000062A36C007D3C0B0800CE -:105400008D6B0054257000013C010800AC30005445 -:105410000A000840240400018F6800743C098000E1 -:105420002405000401093825AF67007493630083E5 -:10543000240600010E00056E306400FF0E000041DE -:10544000240400019362007D020298250E00006290 -:10545000A373007D0A00084024040001324D00803F -:1054600039AC0080546CFF6C8F6400840A0008A97A -:105470002645000127BDFFC83C0A0008AFBF003029 -:10548000AFB5002CAFB40028AFB30024AFB20020FA -:10549000AFB1001CAFB00018034AD8212409004066 -:1054A000AF490814AF4008108F4209448F43095098 -:1054B0008F4609548F47095C8F48094C9344010873 -:1054C0009345010BAF820064308400FF30A500FFDC -:1054D000AF830050AF86004CAF87005C0E00082AF7 -:1054E000AF880060144001748FBF0030A76000686F -:1054F000934D0900240B00503C15080026B53C884C -:1055000031AC00FF3C12080026523C98118B00037E -:10551000000000000000A821000090219351010923 -:105520008F9F005024040010322E007F000E68C0B0 -:10553000000E6140018D282124B40088AF54081862 -:105540008F4901048F4A09A43C0B000E034BC02174 -:10555000012A10233C010800AC223CAC8F430958BF -:105560003C010800A0243CD097470908007F302365 -:105570003C010800AC263CB030E8FFFF0008C9C081 -:105580003C010800AC3F3CD4AF59002C97420908BD -:105590009710002C8EB10000930F0018037498210F -:1055A000A7900058AF9300440220F80931F000FFA3 -:1055B000304E000215C001A9304F000111E0015D1D -:1055C000000000009343093E3066000814C000024A -:1055D000241400030000A0218F5809A42413000103 -:1055E0003C010800AC383CD8934F0934935109373B -:1055F00031EC00FF322E00FF028E6821000D288062 -:1056000000AC5021015058213C010800A42B3CC89B -:105610003C010800A42A3CC693490934312200FF0A -:1056200002022021249000103C010800A4303CC458 -:10563000240700068F9F00503C010800AC273CCC9B -:105640008F88005C8F59095800008021011F282392 -:1056500004A00151033F20230480014F00A4302BFC -:1056600010C00151000000003C010800AC253CB016 -:105670008E4200000040F8090000000030430002A4 -:10568000146000F100408821304400015480001073 -:105690008E4200043C0908008D293CB43C0AC0003D -:1056A000012A8025AF500E008F45000030AB000866 -:1056B0001160FFFD00000000974D0E08241000014E -:1056C000A78D003C8F4C0E04AF8C00348E4200043A -:1056D0000040F8090000000002228825322E000256 -:1056E00015C0016F000000003C09080095293CBC72 -:1056F0003C06080094C63CC83C04080094843CBEA8 -:105700003C1808008F183CB4012658213C0F0800B3 -:105710008DEF3CD83C1F080097FF3CD20164182154 -:105720008F4D09400309C821246E0002033F282140 -:1057300001F860213C010800A42B3CCAAF8D006435 -:105740003C010800AC2C3CD83C010800A4253CC01E -:105750000E00009E31C4FFFF8F87004800402021CB -:105760003C010800A0273CD18E42000824E800013B -:10577000AF8800480040F809000000008F4B002C63 -:10578000974909083C0A000E034A38213124FFFFDB -:10579000000419C08F8A0050AF43002C97430908BA -:1057A00094E6001A0040402130DFFFFFAC5F0000AC -:1057B0008CF9001CAC5900048CF80020AC5800088F -:1057C00090EF001931E30003107300FB00000000AC -:1057D0002862000214400117240500021065010927 -:1057E000240C0003106C00BC000000003C09080001 -:1057F00095293CC0935F0934934C09213C0D080066 -:1058000095AD3CC633F900FF94E5002A0019C0822B -:10581000318F00FF978C005800181600000F74009D -:105820003124FFFF004E382501A4302100E6F82581 -:1058300000ACC8213C03400003E3C02500194C0024 -:10584000AD180000AD090004934F09203C0E00067E -:1058500025090014000F6E0001AE2825AD050008D3 -:105860008F46092C2582000130477FFFAD06000CD2 -:105870008F440930A787005825060028AD04001082 -:105880008F43093800C02021AD030014AD2A000465 -:105890008F5F0940AD3F0008935909373C0E08005F -:1058A00091CE3CD0AD200010333800FF0314782196 -:1058B000000F6700000E6C00018D282534A2FFFF49 -:1058C000AD22000CAF4B002C9347093E30EA000894 -:1058D0005140000F8E58000C3C0301013469080A46 -:1058E000AD0900288F4A0074ACCA00043C0B0800C4 -:1058F000916B3CD03168001051000003ACC000082F -:105900008F650060ACC5000824C4000C8E58000CE4 -:105910000300F809000000003C0F080095EF3CCAA6 -:105920003C02080094423CBE01E2702125C4000202 -:105930000E0000C73084FFFF3C0608008CC63CAC5C -:105940003C0D08008DAD3CB400CD38233C0108006F -:10595000AC273CAC14E00006000000003C19080035 -:105960008F393CCC372C00403C010800AC2C3CCC9F -:10597000120000858F8B00448F480E108F900044DA -:10598000AE0800208F5F0E18AE1F00243C100800E8 -:1059900096103CC00E00006000000000240500408E -:1059A000AF4508148F8300508F89004C0070182178 -:1059B0000069502319400004AF830050AF630054C6 -:1059C0008F670054AF87004C1200000C00000000ED -:1059D0008F440074936D0081340EFA002DA60007E9 -:1059E00010C00005008E182193780081240201F474 -:1059F0000302780401E41821AF63000C8F4C095CAA -:105A00008F99005C0199202318800003000000009A -:105A10008F50095CAF90005C0E0000620000000037 -:105A20008F8B00508E4800103C010800AC2B3CD4FA -:105A30000100F809000000003C1F08008FFF3CAC8B -:105A400017E0FEFC240700068F4500249742090852 -:105A50008F8A00648F9400503C0F001F9787005876 -:105A60008F8300548F93004C304DFFFF35EEFF8045 -:105A700000AE4824000D31C032320010AF46002481 -:105A8000A467002CAF490024AF6A0044AF740050F3 -:105A9000AF7300545640007E8EB80004322400409C -:105AA000548000328EB100088EAC000C0180F809E1 -:105AB000000000008FBF00308FB5002C8FB400288D -:105AC0008FB300248FB200208FB1001C8FB000185C -:105AD00003E0000827BD00383C09080095293CC0B8 -:105AE0003C04080094843CCA3C1F080097FF3CBC5F -:105AF00094F800243123FFFF94EF00280083C8218D -:105B0000033F702300182C00000F640025CDFFEE2A -:105B1000018D302534A2810024030800AD02000C61 -:105B2000AD060010AD030018AD0000140A0009CE48 -:105B30002508001C934701098F8800380007FE00E4 -:105B400003E8C825AF5900808F5809A08F5309A4D6 -:105B5000AFB80010AF580E148FB40010AF540E1031 -:105B6000AF530E1C0A000942AF530E180220F80969 -:105B7000000000008EAC000C0180F809000000005D -:105B80000A000A7F8FBF0030A5600020A5730022A5 -:105B90000A000A34AD7300243C010800AC203CB07C -:105BA0000A00096E8E4200003C010800AC243CB0A3 -:105BB0000A00096E8E4200003C09080095293CC08D -:105BC0003C1F080097FF3CCA3C19080097393CBCB1 -:105BD00094EF00243124FFFF03E4C0210319702354 -:105BE000000F640025CDFFF2018D2825AC45000C87 -:105BF00024020800AD020014AD0000100A0009CE16 -:105C00002508001894E6002494E300283C090800C5 -:105C100095293CC0000624000003FC003499810053 -:105C200037F80800AD19000CAD1800100A0009CEB5 -:105C3000250800141460FEED0000000094EF00241D -:105C40003C09080095293CC0000F740035CD0800C0 -:105C5000AD0D000C0A0009CE250800109352010971 -:105C6000000028210E000600324400FF8FBF0030E4 -:105C70008FB5002C8FB400288FB300248FB2002082 -:105C80008FB1001C8FB0001803E0000827BD00385A -:105C90000300F809000000000A000A7932240040DD -:105CA0001200FF69000000008F540E148F92004410 -:105CB000AE5400208F530E1C0A000A63AE5300241A -:105CC0008F82001C008040213C0401009047008529 -:105CD00030E3002010600009000000003C070800CD -:105CE0008CE73CD48F83001800E320230480000855 -:105CF0009389000414E300030100202103E000085D -:105D0000008010213C04010003E000080080102105 -:105D10001120000B006738238F8C002024090034E9 -:105D2000918B00BC316A000251400001240900300F -:105D300000E9682B15A0FFF10100202100E93823BC -:105D40002419FFFC00B9C02400F9782400F8702B56 -:105D500015C0FFEA01E8202130C200030002182329 -:105D600014C00012306900030000302100A9702126 -:105D700001C6682100ED602B1180FFE03C040100AA -:105D80002D2F00010006482B0105382101E93024A0 -:105D900014C0FFDA24E4FFFC2419FFFC00B9C0247E -:105DA0000308202103E00008008010218F8B0020D1 -:105DB00024060004916A00BC314400041480FFEC06 -:105DC00000A970210A000B2D0000302127BDFFE83B -:105DD000AFBF00108F460100934A01093C1F080025 -:105DE0008FFF00902407FF80314F00FF31E8007FD4 -:105DF0000008614003E6C821032CC02127090120C7 -:105E0000012770243C010800A02F3D10AF4E080C64 -:105E10003C0D08008DAD00903C04008034820003EE -:105E200001A65821016C18212465012030AA0078B0 -:105E300001424025AF48081C3C1F08008FFF00901E -:105E40008F88004003E6C021331900070307482468 -:105E5000033A7821AF49002825E909C0952E0002B0 -:105E60003C0D08008DAD008C3C0A08008D4A009066 -:105E700031CC3FFF01A61821000C5980006B28216E -:105E800000A72024AF44002C952200023C1F0800EC -:105E90008FFF008C9107008530593FFF03E6782182 -:105EA0000019C1800146702101F8682131CC007FC2 -:105EB00031AB007F019A2821017A50213C03000C6C -:105EC0003C04000E00A328210144102130E60020EC -:105ED00027470980AF82002CAF88001CAF890024BF -:105EE000AF85002010C00006AF8700288D0200504B -:105EF0008CA4010C0044302318C00077000000007F -:105F0000910C0085240DFFDF018D3824A107008549 -:105F10008F8B001C8F8900248F8700288D65004C93 -:105F2000AF850018912F000D31EE002011C0001731 -:105F30000000000024090001A3890004AF80000CC8 -:105F40008CE400248F85000C240A0008AF80000830 -:105F5000AF8000103C010800A42A3CBE3C010800B0 -:105F6000A4203CD20E000B01000030218F850024BC -:105F70008FBF0010AF82001490A8000D27BD00183D -:105F80000008394203E0000830E20001913F0002BE -:105F90002418000133F900FF0019218210980039FC -:105FA000240800021088005B8F86002C8CE50024FA -:105FB00014A0001B8F9F002091220000240A0005DE -:105FC0003046003F10CA0047240400018F860008B5 -:105FD000A3840004AF860010AF86000C8CE400247C -:105FE0008F85000C240A00083C010800A42A3CBE4E -:105FF0003C010800A4203CD20E000B010000000070 -:106000008F8500248FBF0010AF82001490A8000D70 -:1060100027BD00180008394203E0000830E2000103 -:106020008CF800088CF900248FEE00C4A3800004D3 -:106030008CE40024AF8E000C8F85000C8F86000846 -:1060400003197823240A0008AF8F00103C010800D0 -:10605000A42A3CBE3C010800A4203CD20E000B0147 -:10606000000000008F8500248FBF0010AF82001455 -:1060700090A8000D27BD00180008394203E0000871 -:1060800030E20001912300003062003F10440027FD -:106090008F8500208CE40024148000210000000083 -:1060A0008D2E00183C187FFF8F850020370FFFFFD3 -:1060B00001CF1824AF8300088F9F00088CA80084AC -:1060C00003E8C82B1720000203E020218CA40084E1 -:1060D0000A000BBCAF8400088CA3010C0A000B9AC9 -:1060E000AF8300188D2C00188F8600083C0D7FFFB1 -:1060F0008F89002035A3FFFF018358242404000169 -:10610000AF8B0010AD2000CCA38400040A000BC8A4 -:10611000AF86000C8CCA00140A000BBCAF8A0008C2 -:106120008CA300C80A000BFFAF8300088F84002CEB -:106130008CAC00648C8D0014018D582B1160000410 -:10614000000000008CA200640A000BFFAF82000870 -:106150008C8200140A000BFFAF8200088F85000CB0 -:1061600027BDFFE0AFBF0018AFB1001414A00007B7 -:10617000AFB000108F8600242402000590C40000F8 -:106180003083003F106200B68F8400208F9100089A -:1061900000A080218F8C00283C0508008CA53CB015 -:1061A0008D8B000431663FFF00C5502B5540000128 -:1061B00000C02821938D000411A0007300B0F82BBB -:1061C0008F98002024040034930F00BC31EE0002AD -:1061D00051C000012404003000A4C82B172000D1B6 -:1061E0000000000000A4282300B0F82B3C010800A8 -:1061F000A4243CBC17E00068020020213C030800F6 -:106200008C633CAC0083102B5440000100801821AB -:106210008F8800243C010800AC233CB400004821D6 -:106220009104000D30830020506000018F490E184A -:106230008F8300140123382B10E000590000000068 -:106240003C0408008C843CB400895821006B502B1E -:10625000114000560090602B0069302300C02021BF -:106260003C010800AC263CB412000003241FFFFCD4 -:106270001090008A32270003009FC8243C010800C8 -:10628000AC393CB43C010800A4203CD28F84000C03 -:10629000120400078F830020AF9100080200202124 -:1062A0008C7100CCAF90000C26300001AC7000CC9B -:1062B0003C0208008C423CB48F8A0010240700186E -:1062C0000082202301422823AF84000C10800002AA -:1062D000AF850010240700108F86001C3C010800C9 -:1062E000A0273CD02407004090CC0085318B00C013 -:1062F000116700408F8D001414A0001500002021AC -:10630000934A01098F420974314500FF00022602B9 -:1063100024A300013090007F3071007F1230007A9A -:106320002407FF80A0C300833C0908008D293CCCD2 -:106330008F880024240D0002352C00083C01080041 -:10634000A02D3D113C010800AC2C3CCC24040010D5 -:10635000910E000D31C6002010C0000500801821EC -:10636000240800013C010800AC283CB4348300013F -:106370008FBF00188FB100148FB000100060102183 -:1063800003E0000827BD00203C010800A4203CBC1D -:1063900013E0FF9A020020210A000C5000A02021E7 -:1063A0003C0408008C843CB40090602B1180FFAE4C -:1063B000000000003C0F080095EF3CBC01E4702198 -:1063C00001C6682B11A000072C8200043C1F60004E -:1063D0008FF954043338003F1700FFE524030042CF -:1063E0002C8200041040FFA0240300420A000CAEDF -:1063F0008FBF0018152DFFC0000000008CDF007457 -:106400003C0380002405FF8003E3C825ACD9007459 -:1064100090D80085240E000424040010330F003FA0 -:1064200001E54025A0C800858F8800243C010800B4 -:10643000A02E3D11240300019106000D30C900205B -:1064400015200003000000003C0308008C633CB4EE -:106450003C010800AC233CAC0A000CA50000000085 -:106460008F8700108C88008400E8282B14A000027D -:1064700000E088218C91008424090001A389000494 -:106480008F440E18022028210E000B01022030211B -:10649000022080210A000C36AF8200140007182366 -:1064A000306600033C010800A4263CD212200005FF -:1064B0008F8C0020918B00BC316A000415400015C0 -:1064C00024CD00043C0F080095EF3CD201E470217C -:1064D00000AE302B50C0FF6E8F84000C2C85000561 -:1064E00014A0FFA324030042309800031700000209 -:1064F000009818232483FFFC3C010800AC233CB423 -:106500000A000C720000000000A758240A000C9A30 -:10651000016718263C010800A42D3CD20A000D0298 -:10652000000000003C010800AC203CB40A000CADA7 -:10653000240300428F830010146000070000102124 -:106540008F880024240500059106000030C400FF58 -:10655000108500030000000003E0000800000000B8 -:10656000910A0018314900FF000939C214E0FFFA0E -:106570008F85001C3C04080094843CBC3C0308004C -:106580008C633CD43C1908008F393CB43C0F0800A4 -:1065900095EF3CD20064C0218CAD005403197021EA -:1065A00001CF6021018D58231960001D00000000FB -:1065B000910E001C8F8C002C974B0E1031CD00FFDC -:1065C0008D850004016D30238D88000030CEFFFFE3 -:1065D000000E510000AAC821000038210107202127 -:1065E000032A182B0083C021AD990004AD98000048 -:1065F000918F000A01CF6821A18D000A8F88002C9D -:10660000974B0E12A50B0008950A0038254900018A -:10661000A50900389107000D34E60008A106000D19 -:1066200003E000080000000027BDFFE0938700049E -:106630008F8F00248FAD00143C0E7FFF8F89000CDC -:1066400035C8FFFFAFBF001CAFB0001801A8182469 -:1066500091EA000D000717C03C1FBFFF00625825DC -:106660002D2E00018F90001837F9FFFF3C1808000D -:106670008F183CD43C0F080095EF3CCA0179682480 -:10668000000E47803C07EFFF3C05F0FF01A81825EE -:106690003149002034E2FFFF34ACFFFF03105823E0 -:1066A00027A500102406000225EA00020062182433 -:1066B0000080802115200002000040218F480E1C20 -:1066C000A7AA0012056000372407000030FF00FF72 -:1066D000001FCF008F8B001C00793825AFA7001456 -:1066E000916F00853C08080091083CD13C18DFFF01 -:1066F00031EE00C0370AFFFF000E182B3C1F0800C8 -:1067000097FF3CC400EA6824A3A8001100031740C7 -:1067100001A248258FB90010AFA900143C0A080057 -:10672000914A3CD3A7BF00168FA80014032CC024A5 -:106730003C0B01003C0F0FFF030B182531470003F2 -:1067400035EEFFFF010C682400071600006EF824E8 -:106750003C09700001A2C82503E95825AFB900140F -:10676000AFAB00100E000076A3A000158F8C0024A4 -:10677000260200089186000D30C40020108000061B -:106780008FBF001C3C05080094A53CC024B0FFFF4F -:106790003C010800A4303CC08FB0001803E00008A2 -:1067A00027BD00208F9800140118502B5540FFC7BB -:1067B000240700010A000D8530FF00FF93820004CA -:1067C00027BDFFE0AFBF00181040000F0080502130 -:1067D0008F880024240B00058F8900089107000092 -:1067E0008F8400200100282130E3003F8F86002C99 -:1067F000106B000800003821AFA900100E00040E35 -:10680000AFAA0014A38000048FBF001803E00008A3 -:1068100027BD00208D1900183C0F08008DEF3CB4F7 -:106820008F9800103C027FFF8D080014345FFFFF3B -:10683000033F682401F8702101AE602301883821EC -:10684000AFA900100E00040EAFAA00140A000DD369 -:10685000A38000048F8700243C05080094A53CD247 -:106860003C0208008C423CCC90E6000D0005240060 -:1068700030C300201060002C004440258F85001C90 -:1068800000006021240B000190A300850000482136 -:10689000240A00013C0F800035EE00708DC7000017 -:1068A000AF8700308F5801780700FFFE3C0380005F -:1068B000347900708F3800003C0508008CA5007406 -:1068C0003C0D08008DAD00700307782300AF382120 -:1068D0000000102100EF302B01A22021008618219A -:1068E0003C010800AC2700743C010800AC23007098 -:1068F000AF4B01483C1908008F393CD4A7490144EB -:10690000A74A0146AF59014C3C0B0800916B3CD1A2 -:10691000A34B0152AF4801543C081000A74C01584A -:1069200003E00008AF4801788F4B0E1C3C0A0800BA -:106930008D4A3CB497490E16974D0E1401456021BF -:10694000312AFFFF0A000DF631A9FFFF8F830024D3 -:106950009064000D308200201040002900000000EB -:106960000000482100005021000040213C07800029 -:1069700034EB00708D670000AF8700308F4C0178DA -:106980000580FFFE3C0D800035AC00708D8B000053 -:106990003C0508008CA500743C0408008C84007041 -:1069A0000167302300A678210000102101E6C82BE2 -:1069B0000082C021031970213C010800AC2F007433 -:1069C0003C010800AC2E0070AF4901483C0D0800A6 -:1069D0008DAD3CD4A748014424090040A74A014694 -:1069E0003C081000240AFF91AF4D014CA34A01520C -:1069F000AF490154A740015803E00008AF480178AF -:106A00008F490E1897460E1297450E1030CAFFFF99 -:106A10000A000E2C30A8FFFF8F83002427BDFFF84B -:106A20009064000D308200201040003A0000000009 -:106A3000240B000100004821240A00013C088000CA -:106A4000350700708CE30000AF8300308F4C017875 -:106A50000580FFFE3C0E80003C04080090843D1041 -:106A600035C700708CEC00003C0508008CA5007454 -:106A7000A3A400033C1908008F3900708FAD0000FB -:106A80000183302300A63821000010210322782141 -:106A900000E6C02B01F8602101AE4025AFA8000040 -:106AA0003C010800AC2700743C010800AC2C0070CD -:106AB0009346010A3C04080090843D11A3A0000203 -:106AC000A3A600018FA300003C0580FF3099007F42 -:106AD00034A2FFFF006278240019C60001F8702577 -:106AE000240D3000AF4E014C27BD0008AF4D0154BE -:106AF000A7400158AF4B0148A7490144A74A0146A6 -:106B00003C091000240AFF80A34A015203E0000858 -:106B1000AF4901788F4B0E1897460E1297450E100D -:106B200030CAFFFF0A000E6030A9FFFF8F85001CEE -:106B30002402008090A40085308300C0106200050C -:106B40008F8600208F8800088F87000CACC800C893 -:106B5000ACC700C403E00008000000003C0A0800C5 -:106B6000254A38903C0908002529395C3C08080072 -:106B700025082D103C07080024E73A703C06080061 -:106B800024C637003C05080024A534783C040800DE -:106B9000248430A03C030800246337983C0208009A -:106BA0002442356C3C010800AC2A3C903C010800B2 -:106BB000AC293C8C3C010800AC283C883C01080016 -:106BC000AC273C943C010800AC263CA43C010800E6 -:106BD000AC253C9C3C010800AC243C983C010800DE -:106BE000AC233CA83C010800AC223CA003E0000818 -:046BF00000000000A1 -:00000001FF -/* - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - */ diff --git a/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex b/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex new file mode 100644 index 000000000000..8d379bffbfef --- /dev/null +++ b/firmware/bnx2/bnx2-mips-06-5.0.0.j6.fw.ihex @@ -0,0 +1,5908 @@ +:10000000080001100800000000004CC8000000C8F3 +:1000100000000000000000000000000008004CC8C4 +:100020000000001400004D90080000880800000047 +:10003000000058C400004DA408005A40000000848D +:100040000000A668080058C4000001540000A6EC97 +:10005000080031D808000000000075340000A840F6 +:1000600000000000000000000000000008007534DF +:100070000000002400011D7408000488080004002A +:100080000000175C00011D98000000000000000047 +:100090000000000000000000000000000000000060 +:1000A000080000A80800000000003B38000134F4FC +:1000B0000000000000000000000000000000000040 +:0800C000000000000000000038 +:0800C8000A00004400000000E2 +:1000D000000000000000000D636F6D352E302E30E3 +:1000E0006A36000005000002000000000000000366 +:1000F00000000014000000320000000300000000B7 +:1001000000000000000000000000000000000000EF +:1001100000000010000001360000EA600000000549 +:1001200000000000000000000000000000000008C7 +:1001300000000000000000000000000000000000BF +:1001400000000000000000000000000000000000AF +:10015000000000000000000000000000000000009F +:10016000000000020000000000000000000000008D +:10017000000000000000000000000000000000007F +:10018000000000000000000000000010000000005F +:10019000000000000000000000000000000000005F +:1001A000000000000000000000000000000000004F +:1001B000000000000000000000000000000000003F +:1001C000000000000000000000000000000000002F +:1001D000000000000000000000000000100000030C +:1001E000000000000000000D0000000D3C020800AF +:1001F00024424D003C03080024634DFCAC40000049 +:100200000043202B1480FFFD244200043C1D080005 +:1002100037BD7FFC03A0F0213C1008002610011020 +:100220003C1C0800279C4D000E000214000000003A +:100230000000000D27BDFFE8AFBF0014AFB00010F5 +:100240009742010830437000240220001062000B26 +:10025000286220011440002F0000102124024000D9 +:1002600010620025000000002402600010620026D9 +:10027000000010210A0000948FBF001427500100D5 +:10028000920200091040001A240300013C020800F9 +:100290008C42002010400016000018210E00052B93 +:1002A00000000000960300083C06080094C64DBEFE +:1002B0008E0400188F8200209605000C00031C009D +:1002C00000661825AC440000AC450004240400017D +:1002D000AC400008AC40000CAC400010AC40001436 +:1002E000AC4000180E000550AC43001C0000182163 +:1002F0000A000093006010210E0003BD0000000002 +:100300000A000093000010210E000F810000000081 +:10031000000010218FBF00148FB0001003E0000810 +:1003200027BD001827BDFFE0AFB00010AFBF001819 +:10033000AFB10014275001009203000B2402001AF1 +:10034000961100081462005B00002821322200018F +:1003500010400008000000008E0200009603001408 +:10036000000211C200021040005A10210A0000DBF6 +:10037000A44300803C0208008C420020104000286A +:10038000000000000E00052B00000000974201084D +:100390009743010C8F8500203042003E3063FFFF01 +:1003A0000002140000431025ACA200008F4201009F +:1003B0003C06080094C64DBEACA20004974301164B +:1003C0009744010E3C02200000031C003084FFFF14 +:1003D00000641825ACA3000800C230259742011024 +:1003E0009743011224040001000214003063FFFF50 +:1003F00000431025ACA2000C974201143042FFFFCD +:10040000ACA200108F420118ACA200149342010B61 +:10041000304200FFACA200180E000550ACA6001C34 +:100420003C0208008C420040244200013C010800CC +:10043000AC2200403C0308008C63004432220002DE +:1004400032240004246300013C010800AC23004472 +:10045000108000180002282B8F4202B804430008C5 +:100460008E0200203C0208008C4200602442000101 +:100470003C010800AC2200600A0000FB24050001DA +:100480009603001600002821AF4202808E0200046D +:10049000A7430284AF4202883C021000AF4202B878 +:1004A0003C0208008C42005C244200013C01080030 +:1004B000AC22005C8FBF00188FB100148FB0001009 +:1004C00000A0102103E0000827BD002027BDFFE0A9 +:1004D000AFB00010AFBF0018AFB10014275001003B +:1004E0009203000B24020003961100081462006DB1 +:1004F000000020213222000110400008000000000E +:100500008E02000096030014000211C20002104087 +:10051000005A10210A000142A44300803C02080056 +:100520008C42002010400025000000000E00052B2A +:1005300000000000974201089743010C8F850020BE +:100540003042003E3063FFFF0002140000431025DC +:10055000ACA200008F4201003C06080094C64DBECC +:10056000ACA20004974301169744010E3C02200000 +:1005700000031C003084FFFF00641825ACA30008B2 +:1005800000C2302597420110974301122404000154 +:10059000000214003063FFFF00431025ACA2000CE2 +:1005A000974201143042FFFFACA20010ACA000142F +:1005B000ACA000180E000550ACA6001C3C020800C0 +:1005C0008C420040244200013C010800AC22004063 +:1005D0003C0208008C420044322300042442000103 +:1005E0003C010800AC2200441060001A32220002D4 +:1005F0008F4202B8044300088E0200203C0208002B +:100600008C420060244200013C010800AC220060E2 +:100610000A0001772404000196030016000020213F +:10062000AF4202808E020004A7430284AF420288D8 +:100630003C021000AF4202B83C0208008C42005C51 +:10064000244200013C010800AC22005C0A00017851 +:100650008FBF001810400013000020218F430104B9 +:100660003C026020AC4300148C420004240301FED1 +:10067000304203FF1443000B000020218F42010091 +:10068000000211C02442FFFC2C420008104000026E +:100690002403000200031F403C026000AC436914C5 +:1006A000000020218FBF00188FB100148FB0001000 +:1006B0000080102103E0000827BD00208F430100C7 +:1006C0002402010050620003000311C20000000D6B +:1006D000000311C200021040005A1021A440008003 +:1006E00003E00008000010219362000003E000080E +:1006F000AF80000003E000080000102103E00008C4 +:1007000000001021240201001482000800000000F3 +:100710003C0208008C4200FC244200013C0108001D +:10072000AC2200FC0A00019F30A200203C0208001D +:100730008C420084244200013C010800AC22008469 +:1007400030A200201040000830A300103C02080036 +:100750008C420108244200013C010800AC2201083F +:1007600003E0000800000000106000080000000026 +:100770003C0208008C420104244200013C010800B4 +:10078000AC22010403E00008000000003C02080065 +:100790008C420100244200013C010800AC2201000F +:1007A00003E000080000000027BDFFE8AFBF001015 +:1007B0002744010094830008306200041040001BAD +:1007C000306600028F4202B804410008240500018F +:1007D0003C0208008C420060244200013C010800F9 +:1007E000AC2200600A0001EB8FBF00108C82002059 +:1007F0009483001600002821AF4202808C820004FE +:10080000A7430284AF4202883C021000AF4202B804 +:100810003C0208008C42005C244200013C010800BC +:10082000AC22005C0A0001EB8FBF001010C0000674 +:10083000006028218F4401000E00018F000000009D +:100840000A0001EA240500018F8200088F43010499 +:1008500050430007000028218F4401000E00018F43 +:10086000000000008F420104AF8200080000282130 +:100870008FBF001000A0102103E0000827BD001862 +:100880003C0208008C420088274301009465000C5C +:10089000244200013C010800AC2200888C6400184E +:1008A0000345102190454000AF4400388C62001C85 +:1008B0002403FFF800052E000043102434420004F6 +:1008C000AF42003C3C020005AF4200300000000097 +:1008D0000000000000000000AF450404000000001C +:1008E00000000000000000003C020006344200014D +:1008F000AF420030000000000000000000000000D7 +:100900008F420000304200101040FFFD0000102117 +:1009100003E000080000000027BDFFE0AFB20018B0 +:100920003C036010AFBF001CAFB10014AFB00010AB +:100930008C6450002402FF7F3C1A80000082202437 +:100940003484380C24020037AC6450003C12080098 +:1009500026524D38AF42000824020C80AF420024DA +:100960003C1B80083C06080024C6062C02401021CF +:100970002404001C2484FFFFAC4600000481FFFD1A +:10098000244200043C0208002442016C3C0108009F +:10099000AC224D403C020800244204043C01080003 +:1009A000AC224D443C020800244207B83C01080038 +:1009B000AC224D883C0208002442025C3C03080043 +:1009C000246306343C040800248406E03C05080047 +:1009D00024A53B503C010800AC224DA03C0208007D +:1009E000244205F43C010800AC264D843C0108007B +:1009F000AC254D943C010800AC234D9C3C01080003 +:100A0000AC244DA43C010800AC224DA83C010800D8 +:100A1000AC234D3C3C010800AC204D483C01080093 +:100A2000AC204D4C3C010800AC204D503C0108006E +:100A3000AC204D543C010800AC204D583C0108004E +:100A4000AC204D5C3C010800AC204D603C0108002E +:100A5000AC244D643C010800AC204D683C0108000A +:100A6000AC204D6C3C010800AC204D703C010800EE +:100A7000AC204D743C010800AC204D783C010800CE +:100A8000AC264D7C3C010800AC264D803C010800A2 +:100A9000AC204D8C3C010800AC254D903C01080079 +:100AA000AC234D980E0006BB000000003C02800005 +:100AB000344200708C420000AF8200143C030800F6 +:100AC0008C6300208F820004104300043C028000ED +:100AD0000E0004F3AF8300043C0280003446007033 +:100AE0003C0308008C6300A03C0208008C4200A478 +:100AF000104300048F8400143C010800AC2300A4C0 +:100B0000A743009E8CCA00003C0308008C6300BC15 +:100B10003C0208008C4200B80144202300641821E4 +:100B2000000040210064202B0048102100441021C7 +:100B30003C010800AC2300BC3C010800AC2200B81A +:100B40008F510000322200071040FFDCAF8A0014F2 +:100B50008CC600003C0508008CA500BC3C040800C5 +:100B60008C8400B800CA302300A628210000102180 +:100B700000A6302B00822021008620213227000190 +:100B80003C010800AC2500BC3C010800AC2400B8C6 +:100B900010E0001F322200028F420100AF4200200D +:100BA0008F420104AF4200A89342010B0E0001885E +:100BB000305000FF2E02001D544000040010108031 +:100BC0000E00018B0A0002C5000000000052102137 +:100BD0008C4200000040F8090000000010400005B1 +:100BE0003C0240008F4301043C026020AC430014EF +:100BF0003C024000AF4201383C0208008C42003405 +:100C0000244200013C010800AC22003432220002E0 +:100C10001040000E322200048F4201400E00018875 +:100C2000AF4200200E00034B000000003C024000D9 +:100C3000AF4201783C0208008C4200382442000197 +:100C40003C010800AC220038322200041040FF981A +:100C50003C0280008F4201800E000188AF420020DC +:100C60008F43018024020F00146200050000000081 +:100C70008F420188A742009C0A0002FA3C02400011 +:100C80009362000024030050304200FF1443000828 +:100C90003C0240000E00032D000000005440000400 +:100CA0003C0240000E000E0D000000003C0240001F +:100CB000AF4201B83C0208008C42003C24420001D3 +:100CC0003C010800AC22003C0A00027A3C02800091 +:100CD0003C0290003442000100822025AF440020F5 +:100CE0008F4200200440FFFE0000000003E00008E7 +:100CF000000000003C0280003442000100822025F8 +:100D000003E00008AF44002027BDFFE0AFB10014AE +:100D1000AFB0001000808821AFBF00180E000302A2 +:100D200030B000FF9362007D022020210202802566 +:100D3000A370007D8F7000743C0280000E00030BD6 +:100D400002028024160000098FBF00188F4201F8AC +:100D50000440FFFE24020002AF5101C0A34201C4BF +:100D60003C021000AF4201F88FBF00188FB1001491 +:100D70008FB0001003E0000827BD002027BDFFE86A +:100D8000AFBF0010974201843042020010400005BE +:100D9000000020210E001042000000000A00034164 +:100DA000240400018F420188044000098FBF001015 +:100DB0008F4201883C03FF00004310243C030400E1 +:100DC00014430003240400019362003E8FBF00100F +:100DD0000080102103E0000827BD00182402000154 +:100DE000A3600022A76200168F4401400A0003108E +:100DF0002405000127BDFFE8AFBF0014AFB000100D +:100E000093620000304400FF3883002038820030B5 +:100E10000003182B0002102B00621824106000033E +:100E200024020050148200628FBF001493420148D4 +:100E3000304200FF2443FFFF2C6200051040005C9D +:100E40008FBF0014000310803C03080024634CC8CB +:100E5000004310218C420000004000080000000008 +:100E60000E0003028F4401408F70000C8F4201443A +:100E70001602000224020001AF62000C0E00030BF8 +:100E80008F4401408F420144145000048FBF00146E +:100E90008FB000100A000FB827BD00188F62000C39 +:100EA0000A0003B300000000976200108F43014462 +:100EB0003042FFFF1462000900000000240200011C +:100EC000A76200108F420140AF4202003C021000B6 +:100ED000AF4202380A0003BA8FBF001497620010B5 +:100EE0000A0003B3000000000E0003028F4401401B +:100EF000976200128F4301443050FFFF1603000237 +:100F000024020001A76200120E00030B8F4401406F +:100F10008F420144160200048FBF00148FB00010EE +:100F20000A00034527BD0018976200120A0003B3A8 +:100F300000000000976200148F4301443042FFFF1D +:100F4000146200068FBF0014240200018FB000104D +:100F5000A76200140A0012E227BD0018976200146D +:100F60000A0003B300000000976200168F4301449B +:100F70003042FFFF14620006240200018FBF0014FC +:100F80008FB00010A76200160A000BAA27BD001838 +:100F900097620016144000068FBF00143C02080040 +:100FA0008C420070244200013C010800AC22007019 +:100FB0008FB0001003E0000827BD001827BDFFE830 +:100FC000AFBF0014AFB000108F500100936200005B +:100FD00093430109304400FF2402001F106200A562 +:100FE0002862002010400018240200382862000AFD +:100FF0001040000C2402000B286200081040002C56 +:1010000000000000046000E528620002144000288F +:1010100024020006106200268FBF00140A0004B7E5 +:101020008FB000101062005E2862000B144000DCDC +:101030008FBF00142402000E106200738FB00010E6 +:101040000A0004B700000000106200C028620039E6 +:101050001040000A2402008024020036106200CAF8 +:1010600028620037104000B424020035106200C12D +:101070008FBF00140A0004B78FB000101062002B5D +:101080002862008110400006240200C824020039B2 +:10109000106200B48FBF00140A0004B78FB00010B4 +:1010A000106200998FBF00140A0004B78FB00010BF +:1010B0003C0208008C420020104000B98FBF001491 +:1010C0000E00052B000000008F4201008F830020DE +:1010D0009745010C97460108AC6200008F4201045D +:1010E0003C04080094844DBE00052C00AC62000452 +:1010F0008F4201180006340000C43025AC6200089D +:101100008F42011C24040001AC62000C9342010ACE +:1011100000A22825AC650010AC600014AC6000187B +:10112000AC66001C0A00048D8FBF00143C0208004E +:101130008C4200201040009A8FBF00140E00052B37 +:1011400000000000974401083C03080094634DBE72 +:101150009745010C000422029746010E8F82002061 +:10116000000426000083202500052C003C0300809D +:1011700000A6282500832025AC400000AC400004D8 +:10118000AC400008AC40000CAC450010AC40001472 +:10119000AC400018AC44001C0A00048C240400017C +:1011A0009742010C144000150000000093620005F6 +:1011B0003042001014400011000000000E00030235 +:1011C0000200202193620005020020213442001019 +:1011D0000E00030BA36200059362000024030020AD +:1011E000304200FF1043006D020020218FBF001429 +:1011F0008FB000100A00105827BD00180000000D25 +:101200000A0004B68FBF00143C0208008C42002084 +:10121000104000638FBF00140E00052B000000007B +:101220008F4201048F8300209744010C3C05080085 +:1012300094A54DBEAC6200009762002C000424000F +:101240003042FFFF008220253C02400E00A22825EC +:10125000AC640004AC600008AC60000CAC60001032 +:10126000AC600014AC600018AC65001C0A00048C73 +:10127000240400010E00030202002021A7600008E0 +:101280000E00030B02002021020020210E0003109B +:10129000240500013C0208008C4200201040004060 +:1012A0008FBF00140E00052B000000009742010CB8 +:1012B0008F8300203C05080094A54DBE0002140059 +:1012C000AC700000AC620004AC6000088F64004C9D +:1012D0003C02401F00A22825AC64000C8F62005025 +:1012E00024040001AC6200108F620054AC62001450 +:1012F000AC600018AC65001C8FBF00148FB00010EC +:101300000A00055027BD0018240200205082002545 +:101310008FB000100E000FA202002021104000200C +:101320008FBF0014020020218FB000100000282180 +:101330000A00031027BD0018020020218FBF0014EF +:101340008FB000100A00061827BD00189745010C41 +:10135000020020218FBF00148FB000100A00063851 +:1013600027BD0018020020218FB000100A00065D82 +:1013700027BD00189345010D020020218FB00010F9 +:101380000A0006A727BD0018020020218FBF001405 +:101390008FB000100A00068327BD00188FBF00140D +:1013A0008FB0001003E0000827BD00188F420278BC +:1013B0000440FFFE2402000234840080AF44024057 +:1013C000A34202443C02100003E00008AF4202784E +:1013D0003C04080094844DCA3C0208008C424DD461 +:1013E0003083FFFF000318C000431021AF42003CD0 +:1013F0003C0208008C424DD0AF4200383C02005005 +:1014000034420008AF42003000000000000000003D +:10141000000000008F420000304200201040FFFD1D +:10142000000000008F4204003C010800AC224DC0C7 +:101430008F4204043C010800AC224DC43C02002051 +:10144000AF420030000000003C02080094424DC84A +:101450003C03080094634DCC3C05080094A54DCE98 +:1014600024840001004310213083FFFF3C01080069 +:10147000A4224DC83C010800A4244DCA14650003F1 +:10148000000000003C010800A4204DCA03E0000851 +:10149000000000003C05000A27BDFFE803452821A5 +:1014A0003C04080024844DB0AFBF00100E0005B509 +:1014B0002406000A3C02080094424DB23C03080096 +:1014C00094634DCE3042000F2442000300431804C1 +:1014D00024027FFF0043102B10400002AF83001C4A +:1014E0000000000D0E0004C2000000003C020800D5 +:1014F00094424DBA8FBF001027BD001803E00008CA +:10150000A74200A23C02000A0342102194430006B5 +:101510003C02080094424DBA3C010800A4234DB699 +:10152000004310238F83001C0002140000021403E8 +:101530000043102B03E000083842000127BDFFE8FC +:10154000AFBF00103C02000A034210219442000683 +:101550003C010800A4224DB60E00050F000000005B +:101560005440FFF93C02000A8FBF001003E000085E +:1015700027BD001827BDFFE8AFBF00100E00050F04 +:101580000000000010400003000000000E00051DD8 +:10159000000000003C0208008C424DC08FBF0010CC +:1015A00027430400AF4200383C0208008C424DC47F +:1015B00027BD0018AF830020AF42003C3C0200056D +:1015C000AF42003003E00008AF8000188F8200189F +:1015D0003C0300060002114000431025AF420030DA +:1015E0000000000000000000000000008F4200002A +:1015F000304200101040FFFD27420400AF8200205F +:1016000003E00008AF8000183C0608008CC64DC4FB +:101610008F8500188F8300203C02080094424DBA49 +:1016200027BDFFE024A5000124630020244200011F +:1016300024C70020AFB10014AFB00010AFBF001836 +:10164000AF850018AF8300203C010800A4224DBAEA +:10165000309000FF3C010800AC274DC404C10008D5 +:101660000000882104E00006000000003C020800A1 +:101670008C424DC0244200013C010800AC224DC008 +:101680003C02080094424DBA3C03080094634DC8E4 +:101690000010202B004310262C420001004410258E +:1016A000144000048F830018240200101462000FFD +:1016B000000000000E000541241100013C03080059 +:1016C00094634DBA3C02080094424DC81462000372 +:1016D000000000000E0004C200000000160000031D +:1016E000000000000E00052B000000003C03080075 +:1016F00094634DBE3C02080094424DBC246300013B +:101700003064FFFF3C010800A4234DBE1482000397 +:10171000000000003C010800A4204DBE120000069D +:10172000000000003C02080094424DBAA74200A20B +:101730000A0005A3022010210E00050F0000000082 +:1017400010400004022010210E00051D00000000C2 +:10175000022010218FBF00188FB100148FB000102D +:1017600003E0000827BD00203084FFFF30A5FFFF05 +:1017700000001821108000070000000030820001E6 +:101780001040000200042042006518210A0005AB49 +:101790000005284003E000080060102110C000068A +:1017A00024C6FFFF8CA2000024A50004AC82000028 +:1017B0000A0005B52484000403E0000800000000CE +:1017C00010A0000824A3FFFFAC860000000000006A +:1017D000000000002402FFFF2463FFFF1462FFFAF1 +:1017E0002484000403E0000800000000240200013B +:1017F000AF62000CA7620010A7620012A76200147B +:1018000003E00008A76200163082007F0342102127 +:101810003C08000E004818213C0208008C420020C1 +:1018200027BDFFD82407FF80AFB3001CAFB200185C +:10183000AFB10014AFB00010AFBF00200080802116 +:1018400030B100FF0087202430D200FF1040002F6D +:1018500000009821AF44002C906200002403005047 +:10186000304200FF1443000E000000003C0208005C +:101870008C4200E00202102100471024AF42002CED +:101880003C0208008C4200E0020210213042007F3E +:101890000342102100481021944200D43053FFFF2E +:1018A0000E00052B000000003C02080094424DBED3 +:1018B0008F8300200011340000C2302500122C005C +:1018C0003C02400000C2302534A50001AC7000008D +:1018D0008FBF0020AC6000048FB20018AC7300080A +:1018E0008FB10014AC60000C8FB3001CAC6500100D +:1018F0008FB00010AC60001424040001AC6000182C +:1019000027BD00280A000550AC66001C8FBF0020D0 +:101910008FB3001C8FB200188FB100148FB000106D +:1019200003E0000827BD00289343010F24020010A4 +:101930001062000E2865001110A00007240200129A +:10194000240200082405003A10620006000030213D +:1019500003E0000800000000240500351462FFFCCD +:10196000000030210A0005D0000000008F42007402 +:1019700024420FA003E00008AF62000C27BDFFE87F +:10198000AFBF00100E000310240500018FBF001030 +:1019900024020001A762001227BD001824020001E2 +:1019A00003E00008A360002227BDFFE0AFB10014F0 +:1019B000AFB00010AFBF001830B1FFFF0E00030240 +:1019C000008080219362003F24030004304200FF26 +:1019D0001443000C02002021122000082402000AF7 +:1019E0000E0005C900000000936200052403FFFEFD +:1019F00000431024A362000524020012A362003FEA +:101A0000020020210E00030BA360008116200003BA +:101A1000020020210E00062D0000000002002021FF +:101A2000322600FF8FBF00188FB100148FB0001056 +:101A3000240500380A0005D027BD002027BDFFE09F +:101A4000AFBF001CAFB20018AFB10014AFB00010B0 +:101A50000E000302008080210E0005C90000000076 +:101A60009362003F24120018305100FF123200032D +:101A70000200202124020012A362003F93620005AD +:101A80002403FFFE004310240E00030BA362000595 +:101A9000020020212405002016320007000030211A +:101AA0008FBF001C8FB200188FB100148FB00010D0 +:101AB0000A00031027BD00208FBF001C8FB2001842 +:101AC0008FB100148FB00010240500390A0005D032 +:101AD00027BD002027BDFFE8AFB00010AFBF001446 +:101AE0009742010C2405003600808021144000102C +:101AF000304600FF0E000302000000002402001226 +:101B0000A362003F93620005344200100E0005C935 +:101B1000A36200050E00030B020020210200202119 +:101B20000E000310240500200A00069C000000009F +:101B30000E0005D0000000000E000302020020216C +:101B4000936200232403FF9F0200202100431024FE +:101B50008FBF00148FB00010A36200230A00030B94 +:101B600027BD001827BDFFE0AFBF0018AFB10014BC +:101B7000AFB0001030B100FF0E00030200808021E2 +:101B8000240200120E0005C9A362003F0E00030BE1 +:101B90000200202102002021022030218FBF0018E6 +:101BA0008FB100148FB00010240500350A0005D055 +:101BB00027BD0020A380002C03E00008A380002D97 +:101BC0008F4202780440FFFE8F820034AF42024011 +:101BD00024020002A34202443C02100003E0000879 +:101BE000AF4202783C0360008C625400304200082F +:101BF0001440FFFD000000008C625408AF82000C0E +:101C000024020052AC605408AC645430AC625434CA +:101C10002402000803E00008AC6254003C026000AB +:101C20008C42540030420008104000053C03600024 +:101C30008C625400304200081440FFFD0000000098 +:101C40008F83000C3C02600003E00008AC435408A2 +:101C500090A3000024020005008040213063003F73 +:101C600000004821146200050000502190A2001CD1 +:101C700094A3001E304900FF306AFFFFAD00000C46 +:101C8000AD000010AD000024950200148D05001C6D +:101C90008D0400183042FFFF00491023000211009C +:101CA000000237C3004038210086202300A2102BF9 +:101CB0000082202300A72823AD05001CAD040018D6 +:101CC000A5090014A5090020A50A001603E00008D4 +:101CD000A50A00228F4201F80440FFFE2402000200 +:101CE000AF4401C0A34201C43C02100003E000085D +:101CF000AF4201F83C0208008C4200B427BDFFE867 +:101D0000AFBF001424420001AFB000103C01080036 +:101D1000AC2200B48F4300243C02001F30AA00FF15 +:101D20003442FF8030D800FF006280240080F82118 +:101D300030EF00FF1158003B01405821240CFF8078 +:101D40003C19000A3163007F000310C000031940F2 +:101D5000006218213C0208008C4200DC256800016A +:101D6000310D007F03E21021004310213043007F3A +:101D700003431821004C102400794821AF4200246D +:101D80008D220024016C1824006C7026AD22000CFA +:101D90008D220024310800FFAD220010952200148E +:101DA000952300208D27001C3042FFFF3063FFFF8A +:101DB0008D2600180043102300021100000227C3E3 +:101DC0000040282100C4302300E2102B00C2302341 +:101DD00000E53823AD27001CAD2600189522002011 +:101DE000A522001495220022154B000AA5220016F8 +:101DF0008D2300248D2200082546000131450080F6 +:101E00001462000430C4007F108F000238AA0080E2 +:101E100000C0502151AF000131C800FF1518FFC9A3 +:101E2000010058218F8400343082007F0342182142 +:101E30003C02000A006218212402FF800082202454 +:101E4000AF440024A06A0079A06A00838C6200502D +:101E50008F840034AC6200708C6500743C027FFF9C +:101E60003442FFFF00A228240E000703AC65007473 +:101E7000AF5000248FBF00148FB0001003E00008A3 +:101E800027BD001827BDFFC0AFBE0038AFB7003474 +:101E9000AFB5002CAFB20020AFB1001CAFB000183E +:101EA000AFBF003CAFB60030AFB40028AFB30024E2 +:101EB0008F4500248F4600288F43002C3C02001FD2 +:101EC0003442FF800062182400C230240080A82120 +:101ED000AFA3001400A2F0240E0006C7AFA60010A6 +:101EE0003C0208008C4200E02410FF80036088213F +:101EF00002A2102100501024AF4200243C0208002E +:101F00008C4200E002A210213042007F03421821DF +:101F10003C02000A00629021924200D29363008446 +:101F2000305700FF306300FF2402000110620034CC +:101F30000360202124020002146200360000000029 +:101F40000E0012AE024028219223008392220083C9 +:101F50003063007F3042007F000210C00003194050 +:101F6000006218213C0208008C4200DC02A2102111 +:101F70000043382100F01024AF4200289225007859 +:101F80009224008330E2007F034218213C02000CBF +:101F900014850007006280212402FFFFA24200F1A5 +:101FA0002402FFFFA64200F20A0007BF2402FFFF3F +:101FB00096020020A24200F196020022A64200F200 +:101FC0008E020024AE4200F492220083A24200F06E +:101FD0008E4200C8AE4200FC8E4200C4AE4200F801 +:101FE0008E220050AE4201008E4200CCAE4201046F +:101FF000922200853042003F0A00081A3442004015 +:102000000E0012D102402821922200850A00081AEF +:102010003042003F936200852403FFDF3042003FDF +:10202000A36200859362008500431024A3620085AB +:102030009363008393620078307400FF304200FFA6 +:1020400010540036240AFF803C0C000C3283007FC1 +:10205000000310C000031940006218213C02080070 +:102060008C4200DC268800013109007F02A2102189 +:102070000043382130E2007F0342182100EA102497 +:10208000AF420028006C80218E020024028A1824AE +:10209000006A5826AE02000C8E020024310800FFB0 +:1020A000AE02001096020014960300208E07001C5A +:1020B0003042FFFF3063FFFF8E06001800431023FD +:1020C00000021100000227C30040282100C4302371 +:1020D00000E2102B00C2302300E53823AE07001CBD +:1020E000AE06001896020020A602001496020022F6 +:1020F000A602001692220079304200FF1054000719 +:102100000000000051370001316800FF9222007882 +:10211000304200FF1448FFCD0100A021922200832D +:10212000A22200798E2200500A00087AAE220070A6 +:10213000A22200858E22004C2405FF80AE42010CB5 +:102140009222008534420020A2220085924200D1D2 +:102150003C0308008C6300DC305400FF3C020800A4 +:102160008C4200E400143140001420C002A3182166 +:1021700000C4202102A21021006438210046102151 +:102180000045182400E52824AF450028AF43002C63 +:102190003042007F924400D030E3007F0342282188 +:1021A000034318213C02000C006280213C02000E17 +:1021B000309600FF00A298211296002A000000002D +:1021C0008E02000C02002021026028211040002510 +:1021D000261000280E0006E2000000009262000DAA +:1021E00026830001307400FF3042007FA262000DA0 +:1021F0002404FF801697FFF0267300203C0208009D +:102200008C4200DC0000A02102A210210044102416 +:10221000AF4200283C0208008C4200E43C03080066 +:102220008C6300DC02A2102100441024AF42002C79 +:102230003C0208008C4200E402A318213063007FB6 +:1022400002A210213042007F0342202103431821C3 +:102250003C02000C006280213C02000E0A00083C97 +:10226000008298218E4200D8AE2200508E4200D8C3 +:10227000AE22007092250083924600D19223008303 +:10228000924400D12402FF8000A228243063007F02 +:10229000308400FF00A628250064182A1060000280 +:1022A00030A500FF38A50080A2250083A225007973 +:1022B0000E0006D5000000009222007E02A0202120 +:1022C000A222007A8E2300743C027FFF3442FFFF7B +:1022D000006218240E000703AE2300748FA20010C2 +:1022E000AF5E00248FBF003CAF4200288FBE003895 +:1022F0008FA200148FB700348FB600308FB5002C3A +:102300008FB400288FB300248FB200208FB1001C3F +:102310008FB0001827BD004003E00008AF42002C3A +:1023200090A2000024420001A0A200003C0308008B +:102330008C6300F4304200FF1443000F0080302112 +:10234000A0A000003C0208008C4200E48F8400340E +:10235000008220213082007F034218213C02000CC1 +:10236000006218212402FF8000822024ACC30000F8 +:1023700003E00008AF4400288C82000024420020C3 +:1023800003E00008AC82000094C200003C08080092 +:10239000950800CA30E7FFFF0080482101021021A4 +:1023A000A4C2000094C200003042FFFF00E2102BE4 +:1023B00054400001A4C7000094A200003C030800A0 +:1023C0008C6300CC24420001A4A2000094A200006F +:1023D0003042FFFF544300078F8600280107102B6F +:1023E000A4A000005440000101003821A4C700004F +:1023F0008F8600288CC4001CAF44003C94A20000CF +:102400008F43003C3042FFFF000210C000621821E1 +:10241000AF43003C8F42003C008220231880000420 +:10242000000000008CC200180A0008DB24420001F2 +:102430008CC20018AF4200383C02005034420010F9 +:10244000AF4200300000000000000000000000006B +:102450008F420000304200201040FFFD00000000CD +:102460008F420404AD2200048F420400AD2200001C +:102470003C020020AF42003003E0000800000000F2 +:1024800027BDFFE0AFB20018AFB10014AFB000102D +:10249000AFBF001C94C2000000C080213C120800A5 +:1024A000965200C624420001A602000096030000D6 +:1024B00094E2000000E03021144300058FB10030A9 +:1024C0000E0008B0024038210A00090D000000008B +:1024D0008C8300048C8200042442004004610007C5 +:1024E000AC8200048C820004044000040000000060 +:1024F0008C82000024420001AC82000096020000A1 +:102500003042FFFF50520001A6000000962200005A +:1025100024420001A62200008F820028962300009A +:1025200094420016144300048FBF001C24020001D3 +:10253000A62200008FBF001C8FB200188FB10014BC +:102540008FB0001003E0000827BD00208F8900280D +:1025500027BDFFE0AFBF00188D22002827480400E8 +:1025600030E700FFAF4200388D22002CAF880030EA +:10257000AF42003C3C020005AF42003000000000CA +:10258000000000000000000000000000000000004B +:10259000000000008C82000C8C82000CAD02000058 +:1025A0008C820010AD0200048C820018AD0200087D +:1025B0008C82001CAD02000C8CA20014AD02001035 +:1025C0008C820020AD02001490820005304200FF92 +:1025D00000021200AD0200188CA20018AD02001C0F +:1025E0008CA2000CAD0200208CA20010AD020024D1 +:1025F0008CA2001CAD0200288CA20020AD02002C91 +:10260000AD060030AD000034978300263402FFFF92 +:1026100014620002006020213404FFFF10E000116A +:10262000AD040038952300369524003624020001BD +:102630003063FFFF000318C2006918219065004055 +:10264000308400070082100400451025A06200407D +:102650008F820028944200563042FFFF0A0009741E +:10266000AD02003C9523003695240036240200017B +:102670003063FFFF000318C2006918219065004015 +:102680003084000700821004000210270045102447 +:10269000A0620040AD00003C00000000000000000F +:1026A000000000003C02000634420040AF4200300F +:1026B0000000000000000000000000008F42000049 +:1026C000304200101040FFFD8F860028AF88003098 +:1026D00024C2005624C7003C24C4002824C500326C +:1026E00024C600360E0008EEAFA200108FBF0018FF +:1026F00003E0000827BD00208F8300243C0608006B +:102700008CC600E88F82003430633FFF00031980DD +:1027100000461021004310212403FF803046007F33 +:1027200000431024AF420028034618213C02000C4D +:102730000062302190C2000D30A500FF000038215A +:1027400034420010A0C2000D8F8900288F8A002417 +:1027500095230036000A138230480003240200014A +:10276000A4C3000E1102000B290200021040000554 +:10277000240200021100000C240300010A0009B821 +:102780000000182111020006000000000A0009B82C +:10279000000018218CC2002C0A0009B82443000153 +:1027A0008CC20014244300018CC200180043102B7B +:1027B00050400009240700012402002714A200034E +:1027C000000000000A0009C4240700019522003E11 +:1027D00024420001A522003E000A13823043000378 +:1027E0002C620002104000090080282114600004BF +:1027F0000000000094C200360A0009D43046FFFFF2 +:102800008CC600380A0009D400802821000030213D +:102810003C04080024844DD80A000921000000006F +:10282000274901008D22000C95230006012020215C +:10283000000216023046003F3063FFFF24020027EB +:1028400000C0282128C7002810C2000EAF83002432 +:1028500010E00008240200312402002110C2000907 +:102860002402002510C200079382002D0A0009F3FC +:102870000000000010C200059382002D0A0009F339 +:10288000000000000A00098C000000000A0006BEDB +:102890000000000095230006912400058D25000C02 +:1028A0008D2600108D2700188D28001C8D290020F2 +:1028B000244200013C010800A4234DDE3C01080035 +:1028C000A0244DDD3C010800AC254DE43C0108008E +:1028D000AC264DE83C010800AC274DF03C01080057 +:1028E000AC284DF43C010800AC294DF803E0000889 +:1028F000A382002D8F87002827BDFFC0AFB300340F +:10290000AFB20030AFB1002CAFB00028AFBF00387D +:102910003C0208008C4200D094E3003030B0FFFF4E +:10292000005010073045FFFF3063FFFF00C09821C3 +:10293000A7A200103C110800963100C614A300069F +:102940003092FFFF8CE2002424420030AF42003C72 +:102950000A000A2C8CE2002094E200323042FFFF91 +:1029600054A2000827A400188CE2002C2442003056 +:10297000AF42003C8CE20028AF4200380A000A3A1D +:102980008F84002827A5001027A6002002203821C8 +:102990000E0008B0A7A000208FA20018244200302B +:1029A000AF4200388FA2001CAF42003C8F84002849 +:1029B0003C020005AF4200309482003427430400FB +:1029C0003042FFFF0202102B14400007AF8300309B +:1029D0009482005494830034020210210043102397 +:1029E0000A000A4E3043FFFF94830054948200345F +:1029F0000223182100501023006218233063FFFFC8 +:102A0000948200163042FFFF1443000300000000D0 +:102A10000A000A5C24030001948200163042FFFF82 +:102A20000043102B104000058F8200309482001666 +:102A3000006210233043FFFF8F820030AC53000050 +:102A4000AC400004AC520008AC43000C3C02000651 +:102A500034420010AF4200300000000000000000CF +:102A6000000000008F420000304200101040FFFDC7 +:102A7000001018C20064182190650040320400075D +:102A8000240200018FBF00388FB300348FB20030B2 +:102A90008FB1002C8FB00028008210040045102553 +:102AA00027BD004003E00008A062004027BDFFA84A +:102AB000AFB60050AFB5004CAFB40048AFB3004460 +:102AC000AFB1003CAFBF0054AFB20040AFB0003870 +:102AD0008C9000003C0208008C4200E88F86003495 +:102AE000960300022413FF8000C2302130633FFFB1 +:102AF0000003198000C3382100F3102490B20000B5 +:102B0000AF42002C9203000230E2007F03423021EA +:102B10003C02000E00C28821306300C02402004045 +:102B20000080A82100A0B021146200260000A0218E +:102B30008E3400388E220018144000022402000156 +:102B4000AE2200189202000D304200201440001501 +:102B50008F8200343C0308008C6300DC001238C014 +:102B6000001231400043102100C7302100463821B7 +:102B700030E300073C02008030E6007800C23025D8 +:102B80000343182100F31024AF4208002463090016 +:102B9000AF4608108E2200188C63000800431021F5 +:102BA000AE2200188E22002C8E2300182442000131 +:102BB0000062182B1060003D000000000A000B109E +:102BC00000000000920300022402FFC00043102412 +:102BD000304200FF1440000524020001AE2200181C +:102BE000962200360A000AF93054FFFF8E220014A4 +:102BF00024420001AE2200189202000000021600DA +:102C000000021603044100290000000096020002A1 +:102C100027A4001000802821A7A200169602000217 +:102C200024070001000030213042FFFFAF82002462 +:102C30000E000921AFA0001C960300023C0408000E +:102C40008C8400E88F82003430633FFF00031980DA +:102C500000441021004310213043007F3C05000C4C +:102C60000053102403431821AF42002800651821A7 +:102C70009062000D001221403042007FA062000DE2 +:102C80003C0308008C6300E48F8200340043102171 +:102C90000044382130E2007F03421021004510211A +:102CA00000F31824AF430028AEA200009222000DCA +:102CB000304200101040001302A020218F83002812 +:102CC0008EA40000028030219462003E2442FFFF67 +:102CD000A462003E948400029625000E3084FFFF1B +:102CE0000E000A0B30A5FFFF8F82002894430034AA +:102CF0009622000E1443000302A0202124020001AA +:102D0000A382002C02C028210E00089600000000BB +:102D10008FBF00548FB600508FB5004C8FB4004861 +:102D20008FB300448FB200408FB1003C8FB00038A9 +:102D300003E0000827BD00588F82002827BDFFD080 +:102D4000AFB40028AFB20020AFBF002CAFB3002457 +:102D5000AFB1001CAFB00018904400D0904300D138 +:102D60000000A021309200FFA3A30010306300FFF9 +:102D70008C5100D88C5300DC1072002B240200010F +:102D80003C0308008C6300E493A400108F8200349D +:102D90002406FF800004214000431021004410213C +:102DA0003043007F00461024AF420028034318211F +:102DB0003C02000C006218218C62000427A400145D +:102DC00027A5001002228021027010230440001564 +:102DD000AFA300149062000D00C21024304200FF27 +:102DE00014400007020088219062000D3442004028 +:102DF0000E000896A062000D0A000B5593A2001069 +:102E00000E000A79241400018F830028AC7000D8CA +:102E100093A20010A06200D193A200101452FFD818 +:102E20000000000024020001168200048FBF002C65 +:102E30000E0006BE000000008FBF002C8FB40028DB +:102E40008FB300248FB200208FB1001C8FB0001808 +:102E500003E0000827BD003027BDFFD8AFB3001C3A +:102E6000AFB20018AFB10014AFB00010AFBF002078 +:102E70000080982100E0802130B1FFFF0E00052B7B +:102E800030D200FF00000000000000000000000041 +:102E90008F820020AC510000AC520004AC530008FB +:102EA000AC40000CAC400010AC400014AC4000182A +:102EB0003C03080094634DBE02038025AC50001C07 +:102EC00000000000000000000000000024040001D9 +:102ED0008FBF00208FB3001C8FB200188FB1001479 +:102EE0008FB000100A00055027BD002827BDFFE85D +:102EF000AFB00010AFBF001430A5FFFF30C600FF19 +:102F00000080802124020C80AF42002400000000D9 +:102F100000000000000000000000000000000000B1 +:102F20000E000B64000000003C040800248400E054 +:102F30008C8200002403FF808FBF00140202102146 +:102F400000431024AF4200248C8200003C03000A9E +:102F5000020280213210007F035010218FB0001038 +:102F60000043102127BD001803E00008AF820028AD +:102F700027BDFFE8AFBF00108F4401403C030800AD +:102F80008C6300E02402FF80AF84003400831821AA +:102F900000621024AF4200243C020008034240219A +:102FA000950500023063007F3C02000A03431821AC +:102FB0000062182130A5FFFF3402FFFF000030211E +:102FC0003C07602010A20006AF8300282402FFFF08 +:102FD000A5020002946500D40E000B8930A5FFFF06 +:102FE0008FBF001024020C8027BD001803E00008EA +:102FF000AF4200243C020008034240219502000237 +:103000003C0A0800954A00C63046FFFF14C000077E +:103010003402FFFF8F8200288F8400343C07602039 +:10302000944500D40A000BF230A5FFFF10C2002423 +:103030008F87002894E2005494E400163045FFFF87 +:1030400000A6102300A6182B3089FFFF1060000493 +:103050003044FFFF00C51023012210233044FFFF3E +:10306000008A102B1040000C012A102324020001BA +:10307000A50200162402FFFFA502000294E500D479 +:103080008F8400340000302130A5FFFF3C07602012 +:103090000A000B89000000000044102A10400008BC +:1030A00000000000950200163042000110400004AC +:1030B000000000009742007E24420014A502001682 +:1030C00003E00008000000008F84002827BDFFE017 +:1030D000AFBF0018948200349483003E1060001A41 +:1030E0003048FFFF9383002C240200011462002764 +:1030F0008FBF00188F820028000818C2310800070F +:10310000006218212447003A244900542444002036 +:10311000244500302446003490620040304200FFD5 +:103120000102100730420001104000168FBF001846 +:103130000E0008EEAFA900108F82002894420034E0 +:103140000A000C0B3048FFFF948300369482003451 +:103150001043000E8FBF001894820036A482003402 +:1031600094820056A48200548C82002CAC820024ED +:1031700094820032A48200309482003CA482003AFF +:103180008FBF00180A000BCB27BD002003E000080A +:1031900027BD002027BDFFE8AFBF00108F4A010008 +:1031A0003C0508008CA500E03C02080090424DE47C +:1031B0003C0C0800958C4DDE01452821304B003F2A +:1031C00030A2007F03424021396900323C02000AEC +:1031D0003963003F2C630001010240212D290001C9 +:1031E0002402FF8000A2282401234825AF8A00344E +:1031F00000801821AF4500240000302100802821E4 +:1032000024070001AF8800283C04080024844DD81E +:10321000AF8C002415200007A380002D240200207D +:103220005562000F006020213402FFFF5582000C20 +:10323000006020212402002015620005000000002B +:103240008C6300142402FFFF1062000700000000DE +:103250000E000921000000000A000C6800000000B8 +:103260000E00098C016028210E000C0000000000F7 +:103270008FBF001024020C8027BD001803E0000857 +:10328000AF4200243C0208008C4200E027BDFFA0B2 +:10329000AFB1003C008210212411FF80AFBE005866 +:1032A000AFB70054AFB20040AFB00038AFBF005C62 +:1032B000AFB60050AFB5004CAFB40048AFB3004458 +:1032C000005110248F4800248F4900288F47002880 +:1032D000AF4200243C0208008C4200E000809021B4 +:1032E00024060006008210213042007F034218218C +:1032F0003C02000A006280213C02001F3442FF8031 +:1033000000E2382427A40010260500F00122F02452 +:103310000102B8240E0005B5AFA700308FA2001837 +:10332000AE0200C48FA2001CAE0200C88FA200240F +:10333000AE0200CC93A40010920300D12402FF80BF +:103340000082102400431025304900FF3083007FA5 +:103350003122007F0062102A10400004000310C0D8 +:1033600001311026304900FF000310C0000319404E +:10337000006218213C0208008C4200DC920400D25A +:10338000024210210043102100511024AF420028B6 +:1033900093A300103063007F000310C000031940A6 +:1033A000006218213C0208008C4200DC024210211D +:1033B000004310213042007F034218213C02000CE0 +:1033C000006240218FA300142402FFFF106200302E +:1033D000309500FF93A2001195030014304400FFC4 +:1033E0003063FFFF0064182B1060000D0000000028 +:1033F000950400148D07001C8D0600183084FFFF13 +:1034000000442023000421000000102100E43821A2 +:1034100000E4202B00C230210A000CE200C430215D +:10342000950400148D07001C8D0600183084FFFFE2 +:1034300000822023000421000000102100801821B8 +:1034400000C2302300E4202B00C4302300E33823E3 +:10345000AD07001CAD06001893A20011A5020014D0 +:1034600097A20012A50200168FA20014AD02001050 +:103470008FA20014AD02000C93A20011A50200203F +:1034800097A20012A50200228FA20014AD02002410 +:103490002406FF80024610243256007FAF420024EB +:1034A000035618213C02000A006280218E02004C63 +:1034B0008FA200203124007F000428C0AE020050FB +:1034C0008FA200200004214000852821AE02007058 +:1034D00093A2001001208821A202008393A2001071 +:1034E000A2020079920200853042003FA2020085CC +:1034F0003C0208008C4200DC0242102100451021F1 +:1035000000461024AF42002C3C0208008C4200E42C +:103510003C0308008C6300DC0242102100441021AF +:1035200000461024AF4200283C0208008C4200E410 +:103530000243182100651821024210210044102185 +:103540003042007F3063007F93A5001003422021AA +:10355000034318213C02000E006240213C02000C93 +:1035600010B1008C008248213233007F16600019B0 +:103570002404FF803C0208008C4200DC024210213F +:1035800000441024AF42002C3C0208008C4200E4AE +:103590003C0308008C6300DC02421021004410242C +:1035A000AF4200283C0208008C4200E4024318218C +:1035B0003063007F024210213042007F034220210D +:1035C000034318213C02000E006240213C02000C23 +:1035D000008248219124000D2414FF800000102156 +:1035E00000942025A124000D9504000295050014E7 +:1035F0008D07001C3084FFFF30A5FFFF8D060018EB +:10360000008520230004210000E4382100C230217D +:1036100000E4202B00C43021AD07001CAD060018CB +:1036200095020002A5020014A50000168D020008F4 +:10363000AD0200108D020008AD02000C95020002E0 +:10364000A5020020A50000228D020008AD02002482 +:103650009122000D3042004010400042262200011D +:103660003C0208008C4200E0A3B300283C10000A92 +:103670000242102100541024AF4200243C020800F2 +:103680008C4200E0A380002C27A4002C02421021D1 +:103690003042007F03421821007018218C6200D84C +:1036A0008D26000427A50028AFA9002C0046102174 +:1036B000AC6200D80E000A79AF83002893A30028DB +:1036C0008F8200280E0006BEA04300D10E000C0021 +:1036D0000000000002541024AF4200243C02080005 +:1036E0008C4200DC00132940001320C000A42021DC +:1036F000024210210044102100541024AF42002C3B +:103700003C0208008C4200E43C0308008C6300DCAF +:10371000035630210242102100451021005410248C +:10372000AF4200283C0208008C4200E4024318210A +:103730000064182102421021004510213042007F10 +:103740003063007F03422021034318213C02000E16 +:10375000006240213C02000C00D080210082482100 +:10376000262200013043007F14750005304400FF1D +:103770002403FF800223102400431026304400FF5E +:1037800093A2001000808821250800281444FF76A9 +:103790002529002093A400108FA300142402FFFF0A +:1037A0001062000A308900FF248200012483000196 +:1037B0003042007F14550005306900FF2403FF806C +:1037C0000083102400431026304900FF9202007845 +:1037D000305300FF11330032012088213C020800E1 +:1037E0008C4200DC3225007F000520C00005294006 +:1037F00000A42021024210212406FF800044102151 +:1038000000461024AF42002C3C0308008C6300DC0F +:103810003C0208008C4200E40243182102421021BD +:103820000045102100641821004610243063007FF9 +:10383000AF420028034318213C02000E00624021E1 +:103840003C0208008C4200E48D06000C010020219F +:1038500002421021004510213042007F034218210E +:103860003C02000C0062482110C0000D01202821FC +:103870000E0006E2000000002402FF80022218244D +:1038800026240001006228263082007F14550002A1 +:10389000308300FF30A300FF1473FFD00060882145 +:1038A0008E0300743C027FFF3442FFFF0062182445 +:1038B000AE0300740E00070302402021AF5700241E +:1038C0008FA20030AF5E00288FBF005C8FBE005813 +:1038D0008FB700548FB600508FB5004C8FB400489E +:1038E0008FB300448FB200408FB1003C8FB00038DE +:1038F00027BD006003E00008AF42002C27BDFFD8C1 +:10390000AFB1001CAFBF0020AFB000182751018835 +:10391000922200032408FF803C03000A3047007F06 +:10392000A3A700108F4601803C0208008C4200E0F3 +:10393000AF86003400C2282100A81024AF42002422 +:103940009224000030A2007F034210210043102186 +:10395000AF8200283084007F2402000214820025F8 +:10396000000719403C0208008C4200E400C210210C +:103970000043282130A2007F0342182100A8102410 +:10398000AF4200283C02000C006218219062000D3A +:10399000AFA3001400481025A062000D8FA30014EF +:1039A0009062000D304200405040006A8FBF0020FE +:1039B0008F860028A380002C27A400148CC200D876 +:1039C0008C63000427A50010004310210E000A7923 +:1039D000ACC200D893A300108F8200280E0006BE50 +:1039E000A04300D10E000C00000000000A000EA34E +:1039F0008FBF00200E0006C700C020210E0006D594 +:103A0000000000003C0200080342802192230001D4 +:103A10009202007B1443004F8FBF002092220000CF +:103A20003044007F24020004108200172882000521 +:103A30001040000624020005240200031082000743 +:103A40008FB1001C0A000EA40000000010820012BA +:103A50008FBF00200A000EA48FB1001C92050083C6 +:103A6000920600788E0700748F84003430A500FF22 +:103A700000073E0230C600FF0E00070B30E7007F54 +:103A80000A000EA38FBF00200E000C6F8F8400343D +:103A90000A000EA38FBF002024020C80AF42002436 +:103AA0009202003E30420040104000200000000022 +:103AB0009202003E000216000002160304410006B6 +:103AC000000000008F8400340E00063824050093A7 +:103AD0000A000EA38FBF00209202003F24030018AB +:103AE000304200FF1443000C8F8400342405003959 +:103AF0000E0005D0000030210E0003028F84003438 +:103B000024020012A202003F0E00030B8F84003437 +:103B10000A000EA38FBF0020240500360E0005D03A +:103B2000000030210A000EA38FBF00200E00030208 +:103B30008F8400349202000534420020A202000566 +:103B40000E00030B8F8400340E0010588F84003455 +:103B50008FBF00208FB1001C8FB0001824020C8092 +:103B600027BD002803E00008AF42002427BDFFE87E +:103B7000AFB00010AFBF00142743010094620008EB +:103B8000000214000002140304410002000080211E +:103B90002410000194620008304200801040001A96 +:103BA00002001021946200083042200010400016EC +:103BB000020010218C6300183C021C2D344219EDC8 +:103BC000240600061062000F3C0760213C0208003A +:103BD0008C4200D4104000078F8200288F83002879 +:103BE000906200623042000F34420040A0620062E6 +:103BF0008F8200288F840034944500D40E000B89F6 +:103C000030A5FFFF020010218FBF00148FB00010FD +:103C100003E0000827BD001827BDFFE0AFB1001486 +:103C2000AFB00010A380002CAFBF00188F4501007B +:103C30003C0308008C6300E02402FF80AF85003461 +:103C400000A318213064007F03442021006218245F +:103C50003C02000A00822021AF43002427500100CB +:103C60008E0200148C8300DCAF84002800431023F4 +:103C700018400004000088218E0200140E000B1C66 +:103C8000AC8200DC9202000B24030002304200FFF1 +:103C90001443002F0000000096020008304300FF8C +:103CA0002402008214620005240200840E0009D65A +:103CB000000000000A000F2F00000000146200093D +:103CC000240200818F8200288F8400343C07602109 +:103CD000944500D49206000530A5FFFF0A000F1E90 +:103CE00030C600FF14620027000000009202000AA4 +:103CF000304300FF3062002010400004306200407A +:103D00008F8400340A000F1A24060040104000047B +:103D1000000316008F8400340A000F1A24060041A5 +:103D200000021603044100178F8400342406004269 +:103D30008F8200283C076019944500D430A5FFFF0E +:103D40000E000B89000000000A000F2F0000000089 +:103D50009202000B24030016304200FF10430006BD +:103D6000000000009202000B24030017304200FF05 +:103D700014430004000000000E000EA90000000023 +:103D8000004088210E000C00000000009202000A92 +:103D9000304200081040000624020C808F85002865 +:103DA0003C0400080E0012860344202124020C80EB +:103DB000AF4200248FBF0018022010218FB00010E6 +:103DC0008FB1001403E0000827BD002027BDFFE8E5 +:103DD000AFBF0014AFB000108F5000243C030800A8 +:103DE0008C6300E08F4501002402FF8000A31821AE +:103DF0003064007F03442021006218243C02000A42 +:103E000000822021AF850034AF43002490820062FD +:103E1000AF8400283042000F34420050A08200627C +:103E20003C02001F3442FF800E0006BE02028024C6 +:103E3000AF5000248FBF00148FB0001003E00008C3 +:103E400027BD00183C0208008C4200201040001DD5 +:103E50002745010090A300093C02000803422021ED +:103E600024020018546200033C0200080A000F708C +:103E700024020008034220212402001614620005D7 +:103E80002402001724020012A082003F0A000F7AC9 +:103E900094A700085462000694A7000893620005E6 +:103EA0002403FFFE00431024A362000594A700082A +:103EB00090A6001B8CA4000094A500060A000B64C9 +:103EC00000073C0003E00008000000002744010058 +:103ED00094820008304500FF38A3008238A2008495 +:103EE0002C6300012C4200010062182510600006BE +:103EF000240200839382002D1040000D000000007A +:103F00000A000C330000000014A2000524A2FF8068 +:103F10008F4301043C02602003E00008AC4300141E +:103F2000304200FF2C420002104000032402002215 +:103F30000A000ED40000000014A2000300000000DC +:103F40000A000F41000000000A000F5F000000009F +:103F50009363007E9362007A1443000900002021DD +:103F60009362000024030050304200FF1443000419 +:103F7000240400019362007E24420001A362007EBB +:103F800003E00008008010218F4201F80440FFFE8A +:103F900024020002AF4401C0A34201C43C0210004D +:103FA00003E00008AF4201F827BDFFE8AFBF0010F3 +:103FB0009362003F2403000A304200FF144300468E +:103FC000000000008F6300548F62004C1062007D7F +:103FD000036030219362000024030050304200FF50 +:103FE0001443002F000000008F4401403C020800F1 +:103FF0008C4200E02403FF80008210210043102443 +:10400000AF4200243C0208008C4200E08F6500545F +:104010003C03000A008220213084007F03441021E9 +:1040200000431021AC4501089762003C8F63004CAF +:104030003042FFFF0002104000621821AF63005CB5 +:104040008F6300548F64004C9762003C0064182317 +:104050003042FFFF00031843000210400043102AC3 +:1040600010400006000000008F6200548F63004C77 +:10407000004310230A000FF0000210439762003C37 +:104080003042FFFF00021040ACC200642402000175 +:10409000A0C0007CA0C2008424020C80AF42002497 +:1040A0000E000FA28F440140104000478FBF001048 +:1040B0008F4301408F4201F80440FFFE24020002BA +:1040C000AF4301C0A34201C43C021000AF4201F85B +:1040D0000A0010408FBF00109362003F24030010BD +:1040E000304200FF14430004000000008F440140F0 +:1040F0000A00102C000028219362003F24030016C0 +:10410000304200FF1443000424020014A362003F65 +:104110000A00103A000000008F62004C8F630050CC +:1041200000431023044100288FBF001093620081D8 +:1041300024420001A3620081936200812C420004AA +:1041400014400010000000009362003F24030004AC +:10415000304200FF14430006000000008F4401407D +:104160008FBF0010240500930A00063827BD0018F1 +:104170008F440140240500938FBF00100A0006A75A +:1041800027BD00188F4401400E000302000000000C +:104190008F6200542442FFFFAF6200548F620050D0 +:1041A0002442FFFFAF6200500E00030B8F4401401A +:1041B0008F4401408FBF0010240500040A00031043 +:1041C00027BD00188FBF001003E0000827BD0018AE +:1041D0008F4201889363007E00021402304400FF86 +:1041E000306300FF1464000D000000009362008043 +:1041F000304200FF1044000900000000A36400806A +:104200009362000024030050304200FF1443000476 +:10421000000000000A00076F8F440180A364008043 +:1042200003E000080000000027BDFFE8AFB0001069 +:10423000AFBF001493620005240300303042003009 +:1042400014430089008080213C0208008C42002039 +:1042500010400080020020210E00052B000000000D +:104260008F850020ACB000009362003E9363003F56 +:10427000304200FF00021200306300FF00431025AF +:10428000ACA2000493620082000216000002160332 +:1042900004410005000000003C0308008C63004856 +:1042A0000A00107E000000009362003E3042004091 +:1042B000144000030000182193620081304300FF86 +:1042C0009362008200031E00304200FF00021400CF +:1042D00000621825ACA300088F620040ACA2000C5D +:1042E0008F620048ACA200108F62004CACA2001498 +:1042F0008F6200508F63004C004310230441000381 +:10430000000000000A0010928F62004C8F62005083 +:10431000ACA200183C02080094424DBE3C03C00B06 +:1043200000002021004310250E000550ACA2001C07 +:104330008F6200548F840020AC8200008F6200588E +:10434000AC8200048F62005CAC8200088F62006067 +:104350008F43007400431021AC82000C8F62006414 +:10436000AC820010976300689762006A00031C002B +:104370003042FFFF00621825AC8300149362008274 +:1043800024030080304200FF1443000300000000BB +:104390000A0010C6AC8000188F63000C24020001D4 +:1043A0001062000E2402FFFF9362003E3042004084 +:1043B0001440000A2402FFFF8F63000C8F42007438 +:1043C000006218233C02080000621024144000021E +:1043D000000028210060282100051043AC8200184D +:1043E0003C02080094424DBE3C03C00C000020215A +:1043F000004310258F8300200E000550AC62001C86 +:104400008F6200188F8300203C05080094A54DBEE4 +:1044100024040001AC620000AC6000048F66006CF4 +:104420003C02400D00A22825AC6600088F6200DC2B +:10443000AC62000CAC600010936200050002160034 +:10444000AC620014AC6000180E000550AC65001C96 +:10445000020020218FBF00148FB00010A360000560 +:104460000A0004B927BD00188FBF00148FB00010D8 +:1044700003E0000827BD00189742007C30C600FF0B +:10448000A08600843047FFFF2402000514C2000B01 +:1044900024E3465090A201122C420007104000076E +:1044A00024E30A0090A30112240200140062100405 +:1044B00000E210210A0010FE3047FFFF3067FFFFC7 +:1044C00003E00008A4870014AC87004C8CA201080C +:1044D0000080402100A0482100E2102330C600FFE8 +:1044E0001840000393AA001324E2FFFCACA20108C9 +:1044F00030C2000110400008000000008D02005092 +:1045000000E2102304410013240600058D0200542C +:1045100010E20010000000008D02005414E2001AA6 +:10452000000000003C0208008C4200D8304200200D +:104530001040000A240200019103007891020083D8 +:10454000144300062402000101002021012028213B +:10455000240600040A0010EC00000000A100008402 +:1045600011400009A50200148F4301008F4201F899 +:104570000440FFFE24020002AF4301C0A34201C475 +:104580003C021000AF4201F803E000080000000008 +:1045900027BDFFE88FA90028AFBF00100080402191 +:1045A00000E918231860007330C600FFA080007C6B +:1045B000A08000818CA2010800E210230440004D7D +:1045C000000000008C8200509483003C8C840064C6 +:1045D000004748233063FFFF012318210083202B6D +:1045E00010800004000000008D0200640A00114FDA +:1045F00000E210219502003C3042FFFF0122102111 +:1046000000E21021AD02005C9502003C8D03005CCD +:104610003042FFFF0002104000E210210043102B47 +:1046200010400003000000000A00115E8D02005CD3 +:104630009502003C3042FFFF0002104000E21021D2 +:10464000AD02005CA1000084AD07004C8CA2010803 +:1046500000E210231840000224E2FFFCACA2010893 +:1046600030C200011040000A000000008D0200501E +:1046700000E2102304410004010020218D020054B7 +:1046800014E20003000000000A0011802406000567 +:104690008D02005414E200478FBF00103C02080056 +:1046A0008C4200D8304200201040000A2402000151 +:1046B0009103007891020083144300062402000154 +:1046C00001002021240600048FBF00100A0010EC16 +:1046D00027BD0018A1000084A50200148F4301002B +:1046E0008F4201F80440FFFE240200020A0011A5D7 +:1046F000000000008C82005C004910230043102B56 +:1047000054400001AC87005C9502003C3042FFFF42 +:104710000062102B14400007240200029502003CA6 +:104720008D03005C3042FFFF00621821AD03005C86 +:1047300024020002AD07004CA10200840E000FA26B +:104740008F4401001040001B8FBF00108F430100F9 +:104750008F4201F80440FFFE24020002AF4301C073 +:10476000A34201C43C021000AF4201F80A0011BB91 +:104770008FBF001030C200101040000E8FBF00101D +:104780008C83005C9482003C006918233042FFFF58 +:10479000006218213C023FFF3444FFFF0083102BCE +:1047A000544000010080182101231021AD02005C5B +:1047B0008FBF001003E0000827BD001827BDFFE8E9 +:1047C0008FAA0028AFBF00100080402100EA4823D4 +:1047D0001920002130C600FF8C83005C8C820064AD +:1047E000006A18230043102B504000100069182164 +:1047F00094A2011001221021A4A2011094A2011080 +:104800003042FFFF0043102B1440000A3C023FFFE0 +:1048100094A2011000431023A4A201109482003C32 +:104820003042FFFF0A0011DA00621821A4A0011033 +:104830003C023FFF3444FFFF0083102B5440000133 +:104840000080182100671021AD02005CA100007CEF +:104850000A001222A100008130C200101040003C6A +:10486000000000008C820050004A102318400038DD +:10487000000000009082007C24420001A082007CA5 +:104880009082007C3C0308008C630024304200FFCF +:104890000043102B1440005C8FBF00108CA2010855 +:1048A00000E2102318400058000000008C830054E0 +:1048B0009482003C006A18233042FFFF0003184333 +:1048C000000210400043102A1040000500000000C4 +:1048D0008C820054004A10230A001209000210437F +:1048E0009482003C3042FFFF00021040AD020064A1 +:1048F0009502003C8D0400649503003C3042FFFFAC +:1049000000021040008220213063FFFF0083182145 +:1049100001431021AD02005C8D020054ACA20108DD +:1049200024020002A10200840E000FA28F440100A5 +:10493000104000358FBF00108F4301008F4201F8F7 +:104940000440FFFE240200020A00124B0000000097 +:10495000AD07004C8CA2010800E2102318400002B1 +:1049600024E2FFFCACA2010830C200011040000AA2 +:10497000000000008D02005000E2102304410004FA +:10498000010020218D02005414E200030000000009 +:104990000A001242240600058D02005414E2001A97 +:1049A0008FBF00103C0208008C4200D8304200202B +:1049B0001040000A24020001910300789102008354 +:1049C00014430006240200010100202124060004F3 +:1049D0008FBF00100A0010EC27BD0018A100008452 +:1049E000A50200148F4301008F4201F80440FFFE2E +:1049F00024020002AF4301C0A34201C43C021000E4 +:104A0000AF4201F88FBF001003E0000827BD001877 +:104A10008FAA00108C8200500080402130C600FF19 +:104A2000004A102300A048211840000700E0182188 +:104A300024020001A0800084A0A00112A48200141E +:104A40000A0011BDAFAA0010A0800081AD07004C84 +:104A50008CA2010800E210231840000224E2FFFCAF +:104A6000ACA2010830C200011040000800000000A4 +:104A70008D0200500062102304410013240600053B +:104A80008D02005410620010000000008D020054DE +:104A900014620011000000003C0208008C4200D8A3 +:104AA000304200201040000A2402000191030078E7 +:104AB000910200831443000624020001010020211A +:104AC00001202821240600040A0010EC0000000048 +:104AD000A1000084A502001403E00008000000000B +:104AE00027BDFFE0AFBF0018274201009046000A33 +:104AF0008C4800148C8B004C9082008430C900FFDD +:104B000001681823304A00FF1C60001A2D46000679 +:104B1000240200010142100410C0001630430003BB +:104B2000012030210100382114600007304C000CB6 +:104B300015800009304200301440000B8FBF001870 +:104B40000A0012AC000000000E0011BDAFAB001057 +:104B50000A0012AC8FBF00180E001132AFAB00106C +:104B60000A0012AC8FBF0018AFAB00100E0012523B +:104B7000AFAA00148FBF001803E0000827BD002073 +:104B800024020003A08200848C82005403E0000809 +:104B9000ACA201083C020008034218219062008187 +:104BA000240600433C07601924420001A0620081F2 +:104BB000906300813C0208008C4200C0306300FF1B +:104BC000146200102403FF803C0208008C4200E0C5 +:104BD0000082102100431024AF4200243C02080050 +:104BE0008C4200E03C03000A008210213042007F2A +:104BF0000342102100431021944500D40A000B8980 +:104C000030A5FFFF03E000080000000027BDFFE023 +:104C1000AFBF0018AFB10014AFB000108F420180D9 +:104C20000080802100A088210E0012B300402021C6 +:104C3000A20000848E0200548FBF00188FB00010B5 +:104C4000AE2201088FB1001403E0000827BD002048 +:104C500027BDFFE03C020008AFB00010AFBF001856 +:104C6000AFB10014034280218F51014092030084B0 +:104C70008E0400508E02004C14820040306600FF0B +:104C80003C0208008C4200E02403FF800222102135 +:104C900000431024AF4200243C0208008C4200E094 +:104CA0009744007C92050081022210213042007F4F +:104CB000034218213C02000A0062182114A0000BD4 +:104CC0003084FFFF2402000554C20014248205DC56 +:104CD0009062011224420001A062011224020C80A1 +:104CE000AF4200240A00130B24020005A060011249 +:104CF0002402000514C20009248205DC920200810E +:104D00002C4200075040000524820A0092030081D3 +:104D10002402001400621004008210213044FFFFBE +:104D2000A60400140E0012B3022020219602003CBB +:104D30008E03004C022020213042FFFF0002104071 +:104D4000006218210E000302AE03005C9202007D97 +:104D500002202021344200400E00030BA202007DFD +:104D60008F4201F80440FFFE24020002AF5101C04F +:104D7000A34201C43C021000AF4201F88FBF0018EB +:104D80008FB100148FB0001003E0000827BD002091 +:104D900008000D9808000DE008000E2008000E6CB9 +:044DA00008000EA059 +:0C4DA4000A0000220000000000000000D7 +:104DB0000000000D6370352E302E306A3600000082 +:104DC00005000004000000000000000000000000DA +:104DD00000000000000000000000000000000000D3 +:104DE00000000000000000000000000000000020A3 +:104DF00000000000000000000000000000000000B3 +:104E000000000000000000000000000000000000A2 +:104E10000000000000000000000000000000000191 +:104E20000000002B00000000000000000000000057 +:104E300010000003000000000000000D0000000D45 +:104E40003C02080024425AC43C03080024636190D9 +:104E5000AC4000000043202B1480FFFD24420004DE +:104E60003C1D080037BD7FFC03A0F0213C1008006A +:104E7000261000883C1C0800279C5AC40E0001A67E +:104E8000000000000000000D27BDFFE83C0960188D +:104E9000AFBF00108D2C5000240DFF7F240800317F +:104EA000018D5824356A380C24070C003C1A800008 +:104EB000AD2A50003C04800AAF4800083C1B800823 +:104EC000AF4700240E000935AF8400100E0008F82B +:104ED000000000000E000845000000000E0012DC7B +:104EE000000000003C0460168C8500003C06FFFFBB +:104EF0003C02535300A618241062004734867C00FD +:104F000094C201F2A780002C10400003A78000CCBF +:104F100038581E1EA798002C94C201F810400004B7 +:104F2000978300CC38591E1EA79900CC978300CCDC +:104F30002C7F006753E00001240300669784002C57 +:104F40002C82040114400002006028212404040083 +:104F50003C0760008CE904382403103C3128FFFF33 +:104F60001103001F30B9FFFF57200010A38000CEAF +:104F700024020050A38200CE939F00CE53E0000F86 +:104F8000A78500CCA78000CC978500CC8FBF0010F0 +:104F9000A780002CA7800034A78000E63C01080011 +:104FA000AC25008003E0000827BD0018939F00CEC9 +:104FB00057E0FFF5A78000CCA78500CC978500CCF3 +:104FC0008FBF0010A784002CA7800034A78000E6C4 +:104FD0003C010800AC25008003E0000827BD001854 +:104FE000A38000CE8CCB003C316A00011140000E42 +:104FF0000000000030A7FFFF10E0FFDE2402005099 +:105000008CCC00C83186000114C0FFDC939F00CE19 +:105010000A000074240200518C8F00043C0E6000D2 +:105020000A00005701EE30218CEF0808240D5708C4 +:10503000000F740211CD000430B8FFFF2405006694 +:105040000A000075240404001700FFCC939F00CED3 +:105050000A000074240200508F8600103089FFFF80 +:10506000000939408CC300103C08005000E820259E +:10507000AF4300388CC5001427420400AF82001CE7 +:10508000AF45003CAF4400300000000000000000CD +:105090000000000000000000000000000000000010 +:1050A00000000000000000008F4B0000316A00206B +:1050B0001140FFFD0000000003E0000800000000B8 +:1050C0008F840010948A001A8C8700243149FFFFD6 +:1050D000000940C000E83021AF46003C8C85002428 +:1050E0008F43003C00A3102318400029000000005B +:1050F0008C8B0020256200013C0D005035AC00086F +:10510000AF420038AF4C003000000000000000004B +:10511000000000000000000000000000000000008F +:1051200000000000000000008F4F000031EE002062 +:1051300011C0FFFD000000008F4A04003C08002061 +:10514000AC8A00108F490404AC890014AF480030C9 +:1051500000000000948600189487001C00C71821E6 +:10516000A48300189485001A24A20001A482001AC6 +:105170009498001A9499001E133800030000000050 +:1051800003E000080000000003E00008A480001A0B +:105190008C8200200A0000D63C0D00500A0000C797 +:1051A000000000003C0308008C6300208F82001880 +:1051B00027BDFFE810620008AFBF00100E0000FE20 +:1051C000AF8300183C0308008C6300202404000116 +:1051D000106400048F8900108FBF001003E00008E6 +:1051E00027BD00188FBF00103C076012A520000AE1 +:1051F0009528000A34E5001027BD00183106FFFF8E +:1052000003E00008ACA600903C0208008C4200209D +:1052100027BDFFC8AFBF0034AFBE0030AFB7002C12 +:10522000AFB60028AFB50024AFB40020AFB3001C68 +:10523000AFB20018AFB1001410400050AFB0001072 +:105240008F840010948600069483000A00C32823EC +:1052500030B6FFFF12C0004A8FBF00349489001897 +:10526000948A000A012A40233102FFFF02C2382B30 +:1052700014E0000202C02021004020212C8C0005F7 +:10528000158000020080A021241400040E0000AD4F +:10529000028020218F87001002809821AF800014A7 +:1052A00094ED000A028088211280004E31B2FFFF87 +:1052B0003C1770003C1540003C1E60008F8F001CA6 +:1052C0008DEE000001D718245075005002202021D7 +:1052D00002A3802B160000353C18200050780047B0 +:1052E00002202021241000018F8300141460003953 +:1052F000029158230230F8230250C82133F1FFFFF6 +:105300001620FFEE3332FFFF8F8700103C11002084 +:10531000AF5100300000000094E6000A3C1E60120D +:1053200037D5001002662821A4E5000A94E2000A9D +:1053300094F2000A94F400183057FFFF1292003BD9 +:10534000AEB700908CED00148CE400100013714097 +:1053500001AE4021000E5FC3010E502B008B48218F +:10536000012A1821ACE80014ACE3001002D3382362 +:1053700030F6FFFF16C0FFB98F8400108FBF0034D6 +:105380008FBE00308FB7002C8FB600288FB5002459 +:105390008FB400208FB3001C8FB200188FB100149F +:1053A0008FB0001003E0000827BD0038107E001BFE +:1053B000000000001477FFCC241000010E00162717 +:1053C000000000008F8300141060FFCB0230F82330 +:1053D000029158238F870010017020210A0001914B +:1053E0003093FFFF8F8300141460FFCB3C1100202B +:1053F000AF5100300A00015D000000000E00079E62 +:10540000024028210A000151004080210E00034B78 +:10541000024028210A000151004080210E0014EFB3 +:10542000022020210A000151004080210E0000C707 +:10543000000000000A00017302D3382327BDFFE8F3 +:10544000AFB00010AFBF00140E0000390000000024 +:105450003C028000345000700A0001B48E06000047 +:105460008F4F000039EE000131C2000110400024CE +:105470008F8600A88E0700003C0C08008D8C003C35 +:105480003C0908008D29003800E66823018D282199 +:105490000000502100AD302B012A402101062021BF +:1054A0003C010800AC25003CAF8700A83C01080087 +:1054B000AC2400380E000100000000003C0308008E +:1054C0008C6300701060FFE6006020213C0508003E +:1054D0008CA500683C0608008CC6006C0E0015B652 +:1054E000000000003C010800AC2000708F4F00005D +:1054F00039EE000131C200011440FFDE8F8600A8A2 +:105500008E0A00008F8B00A83C0508008CA5003C8B +:105510003C0408008C840038014B482300A9382142 +:105520000082182100E9402B006810213C0108008E +:10553000AC27003C3C010800AC2200388F5F010022 +:105540002419FF0024180C0003F9202410980012DD +:10555000AF840000AF440020936D0000240C0020B5 +:1055600031A600FF10CC0012240E005010CE000413 +:105570003C194000AF5901380A0001AD000000009D +:105580000E001252000000003C194000AF590138D3 +:105590000A0001AD000000000E000119000000002B +:1055A0003C194000AF5901380A0001AD000000006D +:1055B0008F58010000802821330F00FF01E02021D7 +:1055C0000E0002F8AF8F00043C194000AF590138BB +:1055D0000A0001AD0000000000A4102B240300010C +:1055E00010400009000030210005284000A4102BC5 +:1055F00004A00003000318405440FFFC00052840AD +:105600005060000A0004182B0085382B54E0000479 +:105610000003184200C330250085202300031842F0 +:105620001460FFF9000528420004182B03E000086D +:1056300000C310213084FFFF30A5FFFF8F4201B867 +:105640000440FFFE3C074080008730253C031000EB +:10565000AF400180AF450184AF46018803E00008F8 +:10566000AF4301B83084FFFF8F4201B80440FFFE12 +:105670003C0740388CA60000008728253C0310001A +:10568000AF460180AF45018803E00008AF4301B891 +:105690008F8300388F8600301066000B0080402119 +:1056A0003C07080024E75C38000328C000A710214D +:1056B0008C44000024630001108800053063000F53 +:1056C0005466FFFA000328C003E000080000102120 +:1056D0003C07080024E75C3C00A7302103E00008F9 +:1056E0008CC200003C03900034620001008220253F +:1056F000AF4400208F45002004A0FFFE0000000002 +:1057000003E00008000000003C0380003462000158 +:105710000082202503E00008AF44002027BDFFE001 +:10572000AFB100143091FFFFAFB00010AFBF001851 +:105730001220001500A080218CA5000010A00013ED +:10574000240400020E000C7C24060140AE00000080 +:105750008F4201B80440000D000028213C064000A3 +:10576000022620258FBF00188FB100148FB00010C3 +:105770003C03100027BD0020AF450180AF440188E5 +:1057800003E00008AF4301B88CA500008F4201B8C8 +:105790000440FFFE3C064000022620258FBF001873 +:1057A0008FB100148FB000103C03100027BD002003 +:1057B000AF450180AF44018803E00008AF4301B862 +:1057C0003086FFFF8F4201B80440FFFE3C094006CF +:1057D0008CA8000000C93825AF4801808CA40004C3 +:1057E0003C031000AF440184AF47018803E0000888 +:1057F000AF4301B827BDFFE0AFB00010AFBF001846 +:10580000AFB100149363003E008080210080282106 +:1058100030620040000020211040000F8E11000077 +:105820000E0008710220202193670000240400501C +:1058300030E500FF50A400128E0F0000022020214E +:105840008FBF00188FB100148FB00010A762013C09 +:105850000A00093127BD00200E0002870000000069 +:105860000E000871022020219367000024040050DC +:1058700030E500FF14A4FFF2022020218E0F00006B +:105880003C1008008E1000503C0D000C240BFF80D3 +:1058900001F05021314E007F01DA6021018D40215D +:1058A000014B4824AF490028022020218FBF001857 +:1058B0008FB100148FB00010A50200D627BD0020C4 +:1058C0000A000931AF8800D027BDFFE0AFBF001844 +:1058D000AFB10014AFB000109366000100808021CA +:1058E0000E00025030D1000493640005001029C25C +:1058F000A765000034830040A36300050E00025931 +:10590000020020210E0009330200202124020001A0 +:10591000AF62000C02002821A762001024040002DC +:10592000A762001224060140A76200140E000C7C3E +:10593000A76200161620000F8FBF0018978C003446 +:105940003C0B08008D6B00782588FFFF3109FFFFB5 +:10595000256A0001012A382B10E00006A7880034D0 +:105960003C0F6006240E001635ED0010ADAE005061 +:105970008FBF00188FB100148FB0001003E0000833 +:1059800027BD002027BDFFE0AFB10014AFBF001856 +:10599000AFB0001000A088211080000A3C03600016 +:1059A0002402008010820012000000000000000DA0 +:1059B0008FBF00188FB100148FB0001003E00008F3 +:1059C00027BD00208C682BF80500FFFE00000000BA +:1059D000AC712BC08FBF00188FB100148FB00010B6 +:1059E0003C09100027BD002003E00008AC692BF83B +:1059F0000E00025000A02021936500050220202106 +:105A00000E00025930B000FF2403003E1603FFE7EA +:105A1000000000008F4401780480FFFE2407000787 +:105A20003C061000AF51014002202021A347014451 +:105A30008FBF00188FB100148FB00010AF460178EF +:105A40000A0002C927BD002027BDFFE8AFBF001430 +:105A5000AFB000108F500020000000000E0009338E +:105A6000AF440020AF5000208FBF00148FB0001053 +:105A700003E0000827BD00183084FFFF8F4201B803 +:105A80000440FFFE3C074035008730253C031000F2 +:105A9000AF450180AF400184AF46018803E00008B4 +:105AA000AF4301B83084FFFF8F4201B80440FFFECE +:105AB0003C074036008730253C031000AF4501808D +:105AC000AF400184AF46018803E00008AF4301B84E +:105AD00027BDFFD0AFB3001C3093FFFFAFB500244C +:105AE000AFB20018AFBF0028AFB40020AFB10014B0 +:105AF000AFB0001030B5FFFF12600027000090210A +:105B00008F90001C8E0300003C06800024020040A1 +:105B100000033E0200032C0230E4007F006688246C +:105B20001482001D30A500FF8F8300282C68000A16 +:105B3000510000108F910014000358803C0C0800A5 +:105B4000258C58C4016C50218D49000001200008AB +:105B50000000000002B218213065FFFF0E00022491 +:105B600024040084162000028F90001CAF800028BF +:105B70008F910014260C0020264B0001018080210B +:105B80003172FFFF16200004AF8C001C0253282B3B +:105B900014A0FFDC00000000024010218FBF00288D +:105BA0008FB500248FB400208FB3001C8FB2001873 +:105BB0008FB100148FB0001003E0000827BD003043 +:105BC000240D003414AD00F600000000920B000E0E +:105BD000240A16803C07000CA36B00219203000DE1 +:105BE0000347F8213C066000A363002096110012D1 +:105BF0003C057FFF34ACFFFFA771003C960200100C +:105C0000240B00053054FFFFAF7400848E19001C74 +:105C1000AF4A00288FF800008CCF44480319702643 +:105C200001EE3021AF66004C8F69004C24CD00019D +:105C30003C197F00AF6900508F640050AF6400547E +:105C4000AF660070AF6D00588F6800582404005094 +:105C5000AF68005CA3600023AF6C0064A36B0037E7 +:105C60008E030014AF6300488F710048AF710024A9 +:105C70008E020018AF62006C9214000CA374003600 +:105C8000936A003E355F0020A37F003E8F7800744A +:105C90000319782435EE4000AF6E0074936900005C +:105CA000313000FF1204022C2418FF803C0408004D +:105CB00024845CB80E000294000000002406000456 +:105CC000240700013C0408008C845CB8A366007DB6 +:105CD000A36700058F4A01780540FFFE24020002F9 +:105CE000AF440140A34201448F90001C3C141000BB +:105CF000AF5401780A000373AF8000282CAD003741 +:105D000051A0FF9C8F9100140005A0803C18080052 +:105D1000271858EC029878218DEE000001C0000889 +:105D2000000000002406000614A600110000000078 +:105D30003C1F08008FFF5CB824040005AF5F002003 +:105D40008E190018AF7900188F78004CAF78001CBE +:105D50008F6F0050122000C2AF6F00700A000373F3 +:105D6000AF840028240A000710AA00842403000638 +:105D70003C05080024A55CB80E00025E24040081E6 +:105D80008F90001C0011102B0A000373AF820028B3 +:105D90002402000414A2FFF6240A00503C09080063 +:105DA0008D295CB8AF4900208E040008AF64004024 +:105DB0008E060008AF6600448E07000CAF670048EF +:105DC0008E0D0010AF6D004C8E080010AF6800847F +:105DD0008E050014AF6500508E0C0018AF6C005497 +:105DE0008E0B001CAF6B005893740000328300FFD1 +:105DF000106A01EE000000008F6700488F660040C7 +:105E000000E6682305A000042404008C1620FFDEB1 +:105E100024020003240400823C05080024A55CB889 +:105E20000E000287000000008F90001C000010216F +:105E30000A000373AF8200282404000514A4FFCCD9 +:105E4000240520003C1F08008FFF5CB8AF5F0020D6 +:105E50008E190004AF79005C921800082410000825 +:105E6000A37800218F8F001C91EE0009A36E002003 +:105E70008F86001C90C9000A312400FF109000108A +:105E8000288A00091540006C24020002240C00201E +:105E9000108C000B340580002885002114A0000818 +:105EA0002405400024080040108800053C0500013E +:105EB000240D0080108D00023C05000224054000E6 +:105EC0008F6E00743C0FFF0001CF48240125802510 +:105ED000AF70007490C4000BA36400818F84001C19 +:105EE0009487000C10E0019400000000948E000CD8 +:105EF000241FFFBF24060004A76E003C9089000EFB +:105F0000A369003E8F90001C9204000FA364003F21 +:105F10008F94001C8E8D00108F47007401A74023C2 +:105F2000AF6800608E850014AF650064968C001821 +:105F3000A76C0068968B001AA76B006A8E83001C02 +:105F4000AF63006C96820002A762013E928A000E47 +:105F5000A36A003E9379003E033FC02412200167EC +:105F6000A378003E8F90001C0A000373AF860028C0 +:105F70002414002214B4FF7E240300073C0208000E +:105F80008C425CB81220000CAF4200200A00037360 +:105F9000AF830028240C003310AC00142405002823 +:105FA0003C05080024A55CB80E00023024040081E2 +:105FB0000A0003F88F90001C3C04080024845CB89D +:105FC0000E00029400000000936B000024110050AA +:105FD000316300FF10710151000000008F90001C20 +:105FE000000018210A000373AF8300283C08080052 +:105FF0008D085CB824040081AF480020A3650034FC +:106000003C05080024A55CB80E000230000000002A +:106010008F90001C240200090A000373AF8200283D +:1060200002B288213225FFFF0E00022424040084DE +:106030000A0003738F90001C1082FFA12405040046 +:10604000288300031060016F240B00042414000156 +:106050005494FF9B240540000A00044724050100D6 +:106060003C04080024845CB88F62004C0E0002944B +:106070008F6300508F90001C000020210A000373E2 +:10608000AF8400288E1000042404008AAF50002042 +:10609000936E000531C900021520015E020028211F +:1060A0009378002302002821330F002015E00159C6 +:1060B0002404008D9362003F24190012305F00FF1A +:1060C00013F90154240400810E0002500200202123 +:1060D00093740023240A0004020020213683004226 +:1060E000A36300230E000259A36A007D8F4B017841 +:1060F0000560FFFE24050002AF500140A3450144A6 +:106100008F90001C3C0C1000AF4C01780A0003F982 +:106110000011102B8E1000042404008AAF500020C0 +:10612000936D000531A80002150000160200282119 +:106130009364003F2407000402002821308600FFFA +:1061400010C70010240400810E000250020020211C +:10615000937F002324180012240FFFFE37F900203C +:10616000A3790023A378003F936E0005020020214D +:1061700001CF48240E000259A3690005020028211E +:10618000000020210E000340000000000A0003F878 +:106190008F90001C8E0500043C0F0008034F402127 +:1061A000AF450020910E00002406005031C900FFC9 +:1061B00011260176240400888F5901B80720FFFEBC +:1061C0003C0C400E008C58253C031000AF4501806C +:1061D000AF400184AF4B0188AF4301B8910200008A +:1061E000240AFF8024040004004AF825A11F0000AF +:1061F0000E000C7C240600300A0003F88F90001C6F +:106200008E0F00043C14080026945CB83C01080082 +:10621000AC2F5CB8AF4F0020920E000331C90004D0 +:10622000112000022402001224020006A362003F93 +:106230009203001B240AFFC03062003F004AF82589 +:10624000A37F003E92190003333800011700011CA0 +:10625000000000008E020008AE8200083C02080028 +:106260008C425CC01040011B00000000000221C2F3 +:10627000A76400088E0D000C240B000124140014E8 +:10628000AF6D002C8E080010AF6800309605001628 +:10629000A7650038960C0014A76C003AAF6B000C91 +:1062A000A76B0010A76B0012A76B0014A76B00165A +:1062B00012200146A37400349206000330C7000286 +:1062C0002CF00001260200088F90001C0A000373C6 +:1062D000AF8200288E14000424030081AF540020F4 +:1062E000936800233105001010A001070000000092 +:1062F0008F4401B80480FFFE3C06401F0011382B7C +:10630000006610253C111000AF540180AF870028B3 +:10631000AF400184AF420188AF5101B80A00037455 +:106320008F9100148E0600043C19000803592021A7 +:10633000AF4600208E07000890980000240F005000 +:10634000331400FF128F0102240500888F4401B826 +:106350000480FFFE3C0D40090011602B00AD1025AC +:106360003C111000AF460180AF8C0028AF4701847C +:10637000AF420188AF5101B80A0003748F91001435 +:106380008E04001C0E00023B00000000104000E8DC +:10639000004048218F90001C240500898F4D01B8D2 +:1063A00005A0FFFE00000000AF4901808E0F001C19 +:1063B0003C1440010011702B00B448253C11100022 +:1063C000AF4F0184AF8E0028AF490188AF5101B8AB +:1063D0000A0003748F910014961900023C140800FF +:1063E00026945CB8333800041300008E3C02600031 +:1063F0008E1F001C3C010800AC3F5CB8AF5F002062 +:10640000920C0010240B0014318400FF148B00B890 +:106410000000000096090002312D000115A0014E78 +:10642000000000008E020004AE8200083C0E08004E +:106430008DCE5CC011C00144000000008F69007463 +:106440003C0E800024040001012E6825AF6D00740D +:10645000A3600005AF64000C3C0C08008D8C5CC090 +:106460008F88001CA7640010000C59C2A76400129A +:10647000A7640014A7640016A76B00088D0300082A +:1064800024040002AF63002C8D0A000CAF6A0030B8 +:1064900091070010A36700348F82001C9045001103 +:1064A000A36500358F86001C90D00012A3700036C3 +:1064B0008F9F001C93F90013A37900378F90001C65 +:1064C00096180014A778003896140016A774003A9E +:1064D0008E0F0018AF6F00245620FDA5AF84002852 +:1064E0003C05080024A55CB80E00025E00002021D7 +:1064F0008F90001C0A0004B6000020213C05080013 +:1065000024A55CB80E000287240400828F90001C32 +:10651000000030210A000373AF8600283C04080005 +:106520008C845CB80E001574000000008F90001C75 +:106530000A000490000018213C05080024A55CB85E +:106540000E0002872404008B8F90001C0011302B5A +:106550000A000373AF8600283C1908008F395CB825 +:106560003C1F08008FFF005024CCFFFE033F782122 +:1065700001F87024AF4E00283C0408008C845CB8FD +:106580003C0908008D2900500089682131A8007F4E +:10659000011A282100A78021AE0600D8AF9000D0B4 +:1065A000AE0000DC0A0003C2AE0C0108AF6000843C +:1065B0003C0508008CA55CB83C0808008D0800501C +:1065C000240CFF803C02000C00A8A021028C58245F +:1065D000AF4B00288E1F00143283007F007A5021B9 +:1065E00001427021ADDF00D88E190014AF8E00D0AB +:1065F000ADD900DC8E180010270FFFFE0A0004152D +:10660000ADCF0108548BFE2E240540000A0004473C +:10661000240510000E000335000000000A0003F8F6 +:106620008F90001C8C46442C3C056C6234B0797011 +:106630003C010800AC205CB814D00008240400021F +:1066400097880034978A002C02802821010A382B71 +:1066500010E0001124040092240400020E000C9AA1 +:10666000240501403C010800AC225CB8AF42002088 +:106670003C0308008C635CB81060000524040083B0 +:106680000E0008650000000010400009240400838B +:106690003C05080024A55CB80E00025E0000000066 +:1066A0008F90001C0011202B0A000373AF84002878 +:1066B0000E000869000000000A0005978F90001C7A +:1066C0008E0400080E00023B000000000A00052EA8 +:1066D000AE8200083C05080024A55CB80E0002301C +:1066E000240400878F90001C0A00054A0011102B1B +:1066F0000E00086D000000003C05080024A55CB8F1 +:106700000A00063D2404008B0E0002500280202166 +:106710009370002302802021360D00100E000259D4 +:10672000A36D00238F90001C0A0005530000182160 +:10673000240400040E000C9A240500301440002AA2 +:10674000004048218F90001C0A00057E240500832C +:106750009205000C30BF000113E0000300000000B0 +:106760009602000EA482002C920A000C314800020E +:106770001100FEF600002821960B00128E03001473 +:10678000A48B001A0A00056AAC83001C8F830038B2 +:106790008F8700301067FE88000020213C09080028 +:1067A00025295C3C000320C0008930218CD40000E6 +:1067B0001285005E247800013303000F5467FFFA4E +:1067C000000320C00A000505000020213C05080048 +:1067D00024A55CB80E000287240400828F90001C60 +:1067E0000A00054A000010213C0B0008034B202141 +:1067F00024030050240A0001AF420020A0830000BF +:10680000A08A00018F88001C91070004A08700184F +:106810008F82001C90450005A08500198F86001C02 +:1068200090DF0006A09F001A8F99001C9338000784 +:10683000A098001B8F94001C928F0008A08F001C52 +:106840008F90001C920E0009A08E001D8F8D001CE1 +:1068500091AC000AA08C001E8F8B001C3C0C080021 +:10686000258C5C3C9163000B3C0B0800256B5C386D +:10687000A083001F8F8A001C9148000CA088002074 +:106880008F87001C90E5000DA08500218F82001CE1 +:10689000240546469046000EA08600228F9F001CCD +:1068A00093F9000FA09900238F98001C93140010F7 +:1068B000A09400248F8F001C91F00011A09000255F +:1068C0008F90001C8F8E00308F990038960D001429 +:1068D000000E18C025C80001A48D0028960A0016D5 +:1068E000006C3021006BF821A48A002A960700185A +:1068F0003108000FA487002CA485002E8E02001CF6 +:10690000ACC90000AF88003011190003AFE20000ED +:106910000A00057E00002821250C00013184000FAB +:10692000000028210A00057EAF8400383C070800DB +:1069300024E75C380087802100002021ACC00000E3 +:106940000A000505AE0000003C05080024A55CB85F +:106950000A00063D240400878E0400040E00023B5A +:10696000000000000A0005A2AE8200083084FFFF8C +:1069700030C600FF8F4201B80440FFFE000644000D +:10698000010430253C07200000C720253C031000EF +:10699000AF400180AF450184AF44018803E00008A7 +:1069A000AF4301B827BDFFE8AFB00010AFBF001480 +:1069B0003C076000240600021080000600A0802131 +:1069C0000010102B8FBF00148FB0001003E00008E0 +:1069D00027BD00183C09600EAD2000348CE5201C5A +:1069E0008F82001C2408FFFC00A81824ACE3201CA4 +:1069F0000E0006F28C45000C0010102B8FBF001407 +:106A00008FB0001003E0000827BD00183C02600EA4 +:106A10003447010024090018274A04000000000040 +:106A200000000000000000003C06005034C30200DB +:106A3000AF440038AF45003CAF430030014018215F +:106A40008F4B0000316800201100FFFD2406007FFD +:106A50002408FFFF8C6C000024C6FFFF24630004A1 +:106A6000ACEC000014C8FFFB24E7000400000000A9 +:106A700000000000000000003C0F0020AF4F00307D +:106A80000000000024AD020001A5702B2529FFFFA6 +:106A9000008E20211520FFE101A0282103E000083D +:106AA0000000000027BDFFE0AFB10014AFBF001829 +:106AB000AFB000103C05600E8CA20034008088212D +:106AC000144000063C0460008C87201C2408FFFC56 +:106AD00000E8302434C30001AC83201C8F8B001CE1 +:106AE00024090001ACA90034956900028D650014E9 +:106AF0008D70000C2D2400818D6700048D660008C8 +:106B0000108000078D6A00102D2C00041580000EE7 +:106B100030CE0007312D000311A0000B0000000053 +:106B20002404008B020028210E0006F22406000334 +:106B30000011102B8FBF00188FB100148FB0001000 +:106B400003E0000827BD002015C0FFF62404008BD9 +:106B50003C030020AF43003000000000240200018D +:106B6000AF820014000000000000000000000000E0 +:106B70003C1F0150013FC825253800033C0F600E23 +:106B8000AF47003800181882AF46003C35E8003C9B +:106B9000AF590030274704008F44000030860020A2 +:106BA00010C0FFFD00000000106000082466FFFF19 +:106BB0002403FFFF8CEB000024C6FFFF24E7000442 +:106BC000AD0B000014C3FFFB250800043C08600E59 +:106BD000AD090038000000000000000000000000C7 +:106BE0003C070020AF470030000000000E00071AED +:106BF0000140202102002821000020210E0006F281 +:106C0000240600030011102B8FBF00188FB1001451 +:106C10008FB0001003E0000827BD002027BDFFD87B +:106C2000AFB200183092FFFFAFB10014AFBF002029 +:106C3000AFB3001CAFB000101240002C0000882140 +:106C40000A0007B22413000150B300408CE5000C89 +:106C50000000000D263900013331FFFF24F8002029 +:106C60000232382B10E00021AF98001C8F820014F4 +:106C70001440001E8F87001C3C0670003C0320005F +:106C80008CE400000086282414A300188F85003CA3 +:106C9000000444023C0980000089802414A0FFEA1B +:106CA000310600FF240A000210CA002E28CB000380 +:106CB00011600016240C000314D3FFE726390001ED +:106CC000020028210E000700240400018F87001C09 +:106CD000AF82003C263900013331FFFF24F8002049 +:106CE0000232382B14E0FFE1AF98001C0220102183 +:106CF0008FBF00208FB3001C8FB200188FB100141B +:106D00008FB0001003E0000827BD002810CC001A47 +:106D1000240D000414CDFFD026390001308EFFFF72 +:106D2000000E19C08F4401B80480FFFE3C0F100014 +:106D30003C102004AF430180AF400184AF50018874 +:106D4000AF4F01B80A0007AD263900010E0006F268 +:106D5000240400841600FFBF8F87001C0A0007ACC4 +:106D6000AF80003C020028210E0007000000202117 +:106D70000A0007CB8F87001C0E000740020020216D +:106D80008F87001C0A0007CCAF82003C3082FFFFD7 +:106D90001440000300001821000424022403001002 +:106DA000308500FF14A000053087000F246600081E +:106DB0000004220230C300FF3087000F14E00005FA +:106DC000308900032468000400042102310300FF1D +:106DD0003089000315200005388B0001246A000269 +:106DE00000042082314300FF388B00013164000130 +:106DF00010800002246C0001318300FF03E00008D2 +:106E000000601021308BFFFF000B394230E600FF9D +:106E10003C09080025295BB8000640800109602173 +:106E20008D8700003164001F240A0001008A1804C5 +:106E300030A500FF00E3202514A000020003102766 +:106E400000E22024240F000100CF70040109682112 +:106E5000000E282714800005ADA400008F86000CCA +:106E600000A6102403E00008AF82000C8F88000CFD +:106E700001C8102503E00008AF82000C3C06001F8B +:106E80003C0360003084FFFF34C5FF8024020020F3 +:106E9000AC602008AC60200CAC602010AC65201405 +:106EA000AC642018AC62200000000000000000006C +:106EB00003E000080000000027BDFFE82402FFFFF8 +:106EC000AFBF0010AF82000C000020213C0608007C +:106ED00024C65BB82405FFFF24890001000440801C +:106EE0003124FFFF010618212C87002014E0FFFA4F +:106EF000AC6500000E0008360000202124020001CD +:106F00003C04600024050020AC822018AC852000E1 +:106F1000000000000000000000000000244A000102 +:106F20003142FFFF2C46040014C0FFF78FBF001052 +:106F300003E0000827BD00188F8300082C620400BE +:106F400003E00008384200018F830008246200013A +:106F500003E00008AF8200088F8300082462FFFF6F +:106F600003E00008AF82000827BDFFE0AFB10014C6 +:106F7000AFBF0018AFB000108F6B00303C06600050 +:106F800000808821ACCB20088F6A002C3C02800056 +:106F900024030008ACCA200C9769003A97680038AF +:106FA00000092C003107FFFF00A72025ACC42010EA +:106FB000ACC22014ACC320000000000000000000A0 +:106FC000000000003C0360008C6D200031AC000824 +:106FD0001580FFF9000000008C6E201405C0002011 +:106FE000000000000E0007FA8F84000C00024080B1 +:106FF0003C09080025295BB8010938218CE4000010 +:107000000E0007FA00028140020220213090FFFFAB +:10701000020020210E000818000028213C0C8000EE +:10702000022C58253210FFFF3C116000240A00207A +:10703000AE2B2014AE302018AE2A20000000000035 +:107040000000000000000000020010218FBF0018A7 +:107050008FB100148FB0001003E0000827BD00209E +:107060008C6620143C02001F3443FF803C1FFFE865 +:1070700000C3C02437F9080003198021001079C229 +:107080003C0C8000022C582531F0FFFF3C116000C1 +:10709000240A0020AE2B2014AE302018AE2A200087 +:1070A00000000000000000000000000002001021AD +:1070B0008FBF00188FB100148FB0001003E00008DC +:1070C00027BD002027BDFFE8AFB000103402FFFF4E +:1070D0003090FFFFAFBF0014120200060200202113 +:1070E0000E00083600000000020020210E000818E3 +:1070F000240500018F8400088FBF00148FB000109A +:107100002483FFFF27BD001803E00008AF830008B9 +:10711000000439C230E6003F00043B42000718403B +:10712000240210002CC4002024C8FFE0AF42002C31 +:10713000246300011480000330A900FF00071840F9 +:10714000310600FF0003608024080001019A5821E5 +:107150003C0A000E00C82804016A382111200005ED +:10716000000530278CE900000125302503E00008E8 +:10717000ACE600008CEE000001C6682403E00008C5 +:10718000ACED000027BDFFE8AFBF0014AFB00010AA +:107190003C0460008C8508083403F00030A2F00045 +:1071A00050430006240200018C8708083404E000E4 +:1071B00030E6F00010C4001E24020002AF8200403E +:1071C0003C1060003C0A0200AE0A081424091000BA +:1071D0003C08000E8E03440003482021AF49002CD8 +:1071E000240501200E000CE0000030218F830040B8 +:1071F000106000043C021691240B0001106B000E7D +:107200003C023D6C344F0090AE0F44088FBF001419 +:107210008FB000103C0C6000240E10003C0D0200EA +:1072200027BD0018AD8E442003E00008AD8D081086 +:107230000A000907AF8000403C0218DA344F009082 +:10724000AE0F44088FBF00148FB000103C0C6000DC +:10725000240E10003C0D020027BD0018AD8E442006 +:1072600003E00008AD8D08100A0008DB24050001CA +:107270000A0008DB000028213C08080025085FC43C +:107280002404FFFF010018212402001E2442FFFFF6 +:10729000AC6400000441FFFD246300043C070800C7 +:1072A00024E760408CE5FFFC2404001C2406000158 +:1072B000308A001F01464804248400010009102779 +:1072C0002C8300201460FFFA00A22824ACE5FFFC08 +:1072D0003C05666634A4616E3C06080024C6610065 +:1072E000AF840058AF88009C2404FFFF00C0182121 +:1072F0002402001F2442FFFFAC6400000441FFFD94 +:10730000246300043C0766663C05080024A560C0B1 +:10731000AF86004834E6616EAF8600982404FFFF14 +:1073200000A018212402000F2442FFFFAC640000DB +:107330000441FFFD246300043C0B66663C06080024 +:1073400024C660403568616EAF8500A4AF880070C8 +:107350002404FFFF00C018212402001F2442FFFF65 +:10736000AC6400000441FFFD246300043C0D66662C +:107370003C0A0800254A618035AC616EAF860090FA +:10738000AF8C005C2404FFFF01401821240200039D +:107390002442FFFFAC6400000441FFFD24630004AD +:1073A0003C090800252961908D27FFFC2404000674 +:1073B000240500013099001F0325C0042484000126 +:1073C000001878272C8E002015C0FFFA00EF382413 +:1073D000AD27FFFC3C09666624030400240403DC9B +:1073E00024050200240600663522616E3C08080070 +:1073F00025085CC4AF820074AF830044AF83006C87 +:10740000AF830050AF830084AF8A008CAF840064E8 +:10741000AF85004CAF860054AF840078AF85006024 +:10742000AF86008001001821240200022442FFFFE1 +:10743000AC6000000441FFFD246300042404000349 +:107440002403000C3C0A0800254A5CD0AF8A00687F +:107450000A0009AE2405FFFF0004188024840001FF +:10746000006858212C8700C014E0FFFBAD650000C8 +:107470003C0E666635CD616E240C17A024081800FA +:10748000AF8D0088AF8C009403E00008AF88007CCB +:107490002484007F000421C200004021000030212C +:1074A00000003821000028210A0009C5AF8400A08F +:1074B0001060000624E7000100C4302124A500016B +:1074C0002CC20BF51440FFFA2CA300663C090800FF +:1074D0002529618001201821240200032442FFFF96 +:1074E000AC6000000441FFFD2463000410E0001ABA +:1074F00024E3FFFF0003294210A0000A000020211E +:107500002406FFFF3C0308002463618024840001FB +:107510000085502BAC660000250800011540FFFBDC +:107520002463000430E2001F104000080008688057 +:10753000240C0001004C38040008588001692821FF +:1075400024E6FFFF03E00008ACA6000001A94021EB +:107550002409FFFFAD09000003E00008000000005F +:10756000AF4400283C04000C03442021000528827D +:107570000A000CE000003021000421803C03600080 +:10758000AC6410080000000000052980AC65100CF8 +:107590000000000003E000088C62100C27BDFFE82B +:1075A0000080282124040038AFBF00140E0009F524 +:1075B000AFB0001024040E00AF4400283C10000CB3 +:1075C00003502021240500100E000CE000003021A3 +:1075D00003501021AC400000AC40000424040038EB +:1075E0008FBF00148FB0001024053FFF27BD001887 +:1075F0000A0009F58C430000000421803C03600070 +:10760000AC641008000000008C62100C03E000085D +:107610000002118227BDFFC8AFB400208F9400681C +:10762000AFBE0030AFB7002CAFB600280000B821C5 +:107630000080B021241E00C0AFBF0034AFB50024CD +:10764000AFB3001CAFB20018AFB10014AFB0001060 +:107650000A000A32AFA5003C504000018F94006838 +:1076600027DEFFFF13C00028269400048E9200003E +:107670003C03080024635FC01240FFF70283102B15 +:107680003C04080024845CC4028410230002A8C0C7 +:10769000000098210A000A412411000100118840CD +:1076A000122000260000000002B38021025128248D +:1076B0000200202110A0FFF9267300010E0009FE30 +:1076C000000000000016684032EC000101AC2021EF +:1076D0000E0009F5020028218F89009426F7000189 +:1076E0008FA6003C3AEB0001316A00012528FFFF1C +:1076F0000011382702CAB021AF88009416E6FFE7D0 +:1077000002479024AE92000002E010218FBF0034A7 +:107710008FBE00308FB7002C8FB600288FB50024A5 +:107720008FB400208FB3001C8FB200188FB10014EB +:107730008FB0001003E0000827BD00383C0E0800A1 +:1077400025CE5FC0028E102B0A000A2DAE920000DB +:1077500027BDFFD8AFB10014AFB00010AFBF0020FD +:10776000AFB3001CAFB2001800A0882110A0001F0A +:10777000000480403C13080026735CC40A000A7AA7 +:107780002412000112200019261000010E000A1513 +:1077900002002021000231422444FFA0000618808C +:1077A0003045001F2C8217A1007318212631FFFFDE +:1077B0001040FFF400B230048C6900000200202168 +:1077C00024053FFF012640241500FFEE0126382541 +:1077D0000E0009F5AC6700008F8A009426100001A6 +:1077E000254700011620FFE9AF8700948FBF0020D6 +:1077F0008FB3001C8FB200188FB100148FB000102F +:1078000003E0000827BD00288F85009C00805821D8 +:107810000000402100004821240A001F3C0C080001 +:10782000258C603C3C0D080025AD5FC48CA6000093 +:1078300050C000140000402100AD1023000238C0E9 +:10784000240300010A000AB30000202115000003F0 +:1078500000E41021244820240000482125290001AB +:10786000512B00132506DFDC106000062484000184 +:1078700000C3702415C0FFF5000318400A000AB1C8 +:107880000000402110AC002624A300040060282141 +:10789000254AFFFF1540FFE5AF85009C512B0004F2 +:1078A0002506DFDC0000402103E000080100102174 +:1078B0000006614230C5001F000C50803C070800E4 +:1078C00024E75FC424040001014730211120000F88 +:1078D00000A420043C05080024A560401480000595 +:1078E0002529FFFF24C6000410C500110000000078 +:1078F000240400018CCF00000004C02700042040B5 +:1079000001F868241520FFF5ACCD00008F990078B0 +:1079100001001021032B482303E00008AF89007801 +:107920003C05080024A55FC40A000ABB00004021F2 +:107930003C06080024C65FC40A000AD424040001DF +:10794000308800FF240200021102000A2403000311 +:107950001103005C8F8900A4240400041104005F5B +:1079600024050005110500670000182103E0000848 +:10797000006010218F8900483C0C0800258C6100B4 +:107980003C04080024846180240300201060000F60 +:1079900000005821240D0002240E00033C0F0800B3 +:1079A00025EF61008D27000014E0000B30F9FFFF88 +:1079B000252900040124C02B530000010180482127 +:1079C0002463FFFF5460FFF88D2700000160182139 +:1079D00003E0000800601021132000323C0500FF86 +:1079E00030E200FF004030211040004200005021F2 +:1079F00024050001000020210005C84000A6C02485 +:107A000017000003332500FF14A0FFFB24840001AE +:107A1000012CC023001828C000AA6021008C50212E +:107A20003144001F240C0001008C180400031027AF +:107A300000E23024110D0041AD260000110E004C73 +:107A4000000A1840110D00368F87006C510E005649 +:107A50008F8C0060240D0004110D005A8F8E00845D +:107A6000240E0005150EFFDA01601821240B1430D6 +:107A700011400006000018218F8400A0246300013B +:107A8000006A402B1500FFFD016458218F8A008099 +:107A9000AF89008C016018212549FFFF0A000B0BFC +:107AA000AF89008000E52024000736021080FFD057 +:107AB000240A001800075402314600FF0A000B1385 +:107AC000240A00103C0C0800258C60C03C0408000F +:107AD000248461000A000AFA240300103C0C080008 +:107AE000258C60403C040800248460C00A000AF928 +:107AF0008F89009000071A02306600FF0A000B13FE +:107B0000240A00088F89008C3C0C0800258C6180B9 +:107B10003C040800248461900A000AFA240300044B +:107B2000000A4080250B003024E6FFFF0160182189 +:107B3000AF8900480A000B0BAF86006C000AC982AF +:107B4000001978803C07080024E760C001E7202185 +:107B5000000A18428C8F00003079001F032C380473 +:107B60000007C02701F860240A000B28AC8C000035 +:107B7000000331420006288000AF28213062001F38 +:107B80008CB8000024630001004CC80400032142AB +:107B9000001938270004108003073024004F2021EB +:107BA0000A000B6CACA60000000A68C025AB0032CE +:107BB000258AFFFF01601821AF8900A40A000B0B82 +:107BC000AF8A0060254B1030AF890090016018210A +:107BD00025C9FFFF0A000B0BAF8900843086000720 +:107BE0002CC2000610400014000000000006408077 +:107BF0003C030800246359C8010338218CE40000C9 +:107C000000800008000000002409000310A9000EF5 +:107C100000000000240A000510AA000B000000006C +:107C2000240B000110AB0008000000008F8C00A0A6 +:107C300010AC00050000000003E000080000102167 +:107C40000A000A9900A020210A000AE700C02021AA +:107C500027BDFFE8308400FF240300021083000BDF +:107C6000AFBF0010240600031086003A2408000469 +:107C700010880068240E0005108E007F2CAF143091 +:107C80008FBF001003E0000827BD00182CA20030B1 +:107C90001440FFFC8FBF001024A5FFD0000531C2A7 +:107CA000000668803C07080024E7610001A7302136 +:107CB0008CC900000005288230AC001F240B000195 +:107CC000018B50048F840048012A4025ACC8000075 +:107CD0008C83000050600001AF8600488F98006CD4 +:107CE00030AE000124A6FFFF270F000115C00002DF +:107CF000AF8F006C24A600010006414200082080DE +:107D0000008718218C79000030C2001F2406000172 +:107D10000046F804033F382410E0FFDA8FBF00105C +:107D20000005C182001870803C0F080025EF60C07C +:107D300001CF48218D2B00000005684231A5001FAE +:107D400000A66004016C502527BD001803E0000860 +:107D5000AD2A00002CA7003014E0FFCA8FBF00102E +:107D600030B900071723FFC724A8FFCE00086A0216 +:107D7000000D60803C0B0800256B60C0018B30213A +:107D80008CC40000000828C230AA001F240800018B +:107D9000014848048F8200A400891825ACC3000064 +:107DA0008C5F000053E00001AF8600A40005704026 +:107DB000000E7942000F28803C04080024846100F2 +:107DC00000A418218C6B000025DF000131CD001FBD +:107DD000001F514201A86004016C4825000A108070 +:107DE000AC690000004428218CA600008F98006038 +:107DF00033F9001F8FBF00100328380400C778250F +:107E0000270E000127BD0018ACAF000003E00008FA +:107E1000AF8E006024A5EFD02CB804001300FF99AA +:107E20008FBF001000053142000658803C0A080050 +:107E3000254A6040016A30218CC4000030A3001F35 +:107E400024090001006910048F9900900082F82530 +:107E5000ACDF00008F27000050E00001AF860090EB +:107E60008F8D00848FBF001027BD001825AC000146 +:107E700003E00008AF8C008415E0FF828FBF001084 +:107E80008F8600A0000610400046F821001F210048 +:107E900003E4C8210019384024F8143000B8402BFE +:107EA0001100FF788FBF001024A4EBD00E00020D4C +:107EB00000C0282100027942000F70803C0D0800AC +:107EC00025AD618001CD20218C8B0000304C001F3E +:107ED00024060001018618048F89008C0163502557 +:107EE000AC8A00008D25000050A00001AF84008CFA +:107EF0008F9800808FBF001027BD00182708000151 +:107F000003E00008AF88008030A5000724030003C9 +:107F100010A3001028A20004144000082407000247 +:107F20002403000410A300152408000510A8000F66 +:107F30008F8500A003E000080000000014A7FFFDEB +:107F40000080282114C3FFFB240400020A000BABAD +:107F500000000000240900050080282110C9FFFB53 +:107F60002404000303E000080000000014C5FFF132 +:107F7000008028210A000BAB24040005240A00011C +:107F80000080282110CAFFF12404000403E0000847 +:107F90000000000027BDFFE0AFB00010000581C267 +:107FA0002603FFD024C5003F2C6223D024C6007FC7 +:107FB000AFB20018AFB10014AFBF001C309100FF8A +:107FC000000691C20005298202002021104000080D +:107FD0002403FFFF0E000A6B0000000002002021B6 +:107FE000022028210E000C590240302100001821E7 +:107FF0008FBF001C8FB200188FB100148FB000101B +:108000000060102103E0000827BD002027BDFFD835 +:1080100024A2007FAFB3001CAFB20018000299C2C7 +:10802000309200FF24A3003F02402021026028215B +:10803000AFB10014AFB00010AFBF00200E000B8E28 +:108040000003898200408021004020210220282155 +:1080500014400009000018218FBF00208FB3001CBE +:108060008FB200188FB100148FB000100060102183 +:1080700003E0000827BD00280E000A1C00000000D5 +:1080800000402821020020211051FFF3001019C0E8 +:108090000E000A6B0000000002002021024028218F +:1080A0000E000C59026030218FBF00208FB3001CDE +:1080B0008FB200188FB100148FB00010000018218B +:1080C0000060102103E0000827BD00283084FFFF76 +:1080D00030A5FFFF1080000700001821308200014A +:1080E0001040000200042042006518211480FFFBAC +:1080F0000005284003E000080060102110C00007C0 +:10810000000000008CA2000024C6FFFF24A500048C +:10811000AC82000014C0FFFB2484000403E00008CC +:108120000000000010A0000824A3FFFFAC860000A0 +:1081300000000000000000002402FFFF2463FFFF96 +:108140001462FFFA2484000403E000080000000029 +:1081500030A5FFFF8F4201B80440FFFE3C076015C9 +:1081600000A730253C031000AF440180AF400184DC +:10817000AF46018803E00008AF4301B88F8500D007 +:108180002C864000008018218CA700840087102BCB +:1081900014400010000000008CA800842D06400050 +:1081A00050C0000F240340008CAA0084008A482B92 +:1081B000512000018CA3008400035A42000B208050 +:1081C0003C05080024A55A400085182103E000085A +:1081D0008C62000014C0FFF4000000002403400083 +:1081E00000035A42000B20803C05080024A55A4099 +:1081F0000085182103E000088C6200008F8300D006 +:10820000906600D024C50001A06500D08F8500D005 +:10821000906400D090A200D210440017000000002B +:10822000936C00788F8B00BC318A00FFA16A000C30 +:1082300025490001938700C4312200FF3048007FA8 +:108240001107000B00026827A36200788F4E0178A7 +:1082500005C0FFFE8F9900B0241800023C0F1000EB +:10826000AF590140A358014403E00008AF4F017823 +:108270000A000D2931A20080A0A000D00A000D1F25 +:108280000000000027BDFFD8AFB200188F9200B8E1 +:10829000AFBF0020AFB3001CAFB00010AFB10014EF +:1082A0008F9300B48E5900283C1000803C0EFFEFE5 +:1082B000AE7900008E580024A260000A35CDFFFF81 +:1082C000AE7800049251002C3C0BFF9F356AFFFFF3 +:1082D000A271000C8E6F000C3C080040A271000BD4 +:1082E00001F06025018D4824012A382400E830255A +:1082F000AE66000C8E450004AE6000183C0400FF22 +:10830000AE6500148E43002C3482FFFFA660000887 +:108310000062F824AE7F00108E5900088F9000B0E4 +:10832000964E0012AE7900208E51000C31D83FFFDE +:1083300000187980AE7100248E4D001401F0602188 +:1083400031CB0001AE6D00288E4A0018000C41C2EE +:10835000000B4B80AE6A002C8E46001C01093821B0 +:10836000A667001CAE660030964500028E440020D1 +:10837000A665001EAE6400349243003330620004F0 +:1083800054400005924600008F8300D08C7F007C13 +:10839000AE7F0030924600008F8500BCA0A6000092 +:1083A000924400333082000250400007924E000198 +:1083B0008F8700BC240AFF8090E90000012A402535 +:1083C000A0E80000924E00018F8D00BC2409FFBF81 +:1083D0002404FFDFA1AE00018F8A00BC914C000D88 +:1083E000318B007FA14B000D8F8600BC90C8000D23 +:1083F00001093824A0C7000D8F9100BC8E650014C0 +:108400009223000D2CA200010002F9400064C82450 +:10841000033FC025A238000D8F8800BC9650001283 +:108420008F8700D0A51000028E45000490ED00BC9F +:1084300030AF0003000F702331CC000300AC1021DB +:1084400031AB0002156000022444003424440030A3 +:1084500090F100BC00B18024320F000415E000024E +:1084600024830004008018218F8900AC240A0002B4 +:10847000AD030004A12A00009248003F8F8700ACA2 +:10848000A0E800018F9100AC9246003F8E440004AA +:10849000A62600029765003C0E000CF630B0FFFFE8 +:1084A00000021380005020253C0342000083F82581 +:1084B000AE3F00048F8500AC8E590038ACB900186F +:1084C0008E580034ACB8001CACA0000CACA000105E +:1084D000A4A00014A4A00016A4A00020A4A0002220 +:1084E000ACA000248E620014504000012402000160 +:1084F0008FBF00208FB3001C8FB200188FB1001403 +:108500008FB00010ACA200080A000D1627BD00288D +:108510008F8600D027BDFFD0AFBF002CAFB600289C +:10852000AFB50024AFB40020AFB3001CAFB2001849 +:10853000AFB10014AFB0001094C300E094C200E2E9 +:10854000104300412405FFFF3C16000E90C400D0EC +:1085500090C800D1309200FF310400FF0244382B54 +:1085600010E0004426490001108900378F9800B0C0 +:108570003C0508008CA5005C2414FF8000B8602135 +:1085800001946824AF4D002C94CA00E2318B007F27 +:10859000017A482131447FFF013640210004104018 +:1085A0000048A82196A700003C1F08008FFF005834 +:1085B00030F53FFF0015198003E3C8210319882116 +:1085C0003233007F027A782102348024AF50002CAD +:1085D00001F69821926E000D31C5000410A00048EC +:1085E0000000000094C300E294C300E294D800E2CB +:1085F00024048000307F7FFF27F9000133317FFFA3 +:108600000304802402117825A4CF00E294CE00E276 +:108610003C1208008E52006031D47FFF129200DFBE +:10862000000000008E720018000028212646FFFF7F +:10863000AE66002C8F8600D094C800E094C900E29A +:108640001528FFC2000000008FBF002C8FB6002845 +:108650008FB500248FB400208FB3001C8FB2001898 +:108660008FB100148FB0001000A0102103E00008AB +:1086700027BD003090CD00D2264A000131AC00FF6A +:10868000008C5821116AFFF08F9800B03C0508005B +:108690008CA5005C2414FF8000B86021019468243C +:1086A000AF4D002C94CA00E2318B007F017A482143 +:1086B00031447FFF01364021000410400048A821CA +:1086C00096A700003C1F08008FFF005830F53FFFC1 +:1086D0000015198003E3C821031988213233007F74 +:1086E000027A782102348024AF50002C01F69821C0 +:1086F000926E000D31C5000414A0FFBA0000000006 +:108700008E6600100012C0C08E6E003000129140C4 +:1087100002587821036F582100CE6823256C008809 +:1087200024020002AE6D0010AF8C00ACA162008884 +:10873000976A003C8E6400308F9100AC0E000CF6FE +:108740003150FFFF00022380009048253C03420087 +:1087500001234025AE2800048E6700048F8C00ACF6 +:108760008E7F0000240D0008AD87001CAD9F00180F +:10877000AD80000CAD8000109265000A30B900FF9A +:10878000A5990014967800083C05000CA5980016E1 +:108790009271000A322F00FFA58F0020967000080A +:1087A00024110005A5900022AD800024926E000BDC +:1087B0002410C00031C600FFA5860002A18D000173 +:1087C0008E6B00308F8200AC8F8800B0AC4B0008FD +:1087D0003C0A08008D4A0054014820210094482496 +:1087E000AF4900283C0308008C630054006838211E +:1087F00030FF007F03FAC8210325C02102587821E9 +:10880000AF8F00BCAF9800C0A1F100008F8B00BCFF +:108810002403FFBF2405FFDF956E000201D0A024D2 +:1088200002959025A57200029166000230CD003FAE +:1088300035AC0040A16C00028F8800BC8F8200D054 +:108840003C0C7FFFAD0000048C4A007C358BFFFFA1 +:108850003C028000AD0A00089104000D3089007FC1 +:10886000A109000D8F9F00BC93F5000D02A33824D1 +:10887000A3E7000D8F9100BC9239000D0325C024A1 +:10888000A238000D8E6F00348F8D00BCADAF00108C +:108890008E6E002C8E70003001D0A023ADB4001479 +:1088A00091B200183246007FA1A600188F8700BC45 +:1088B0008E6A00308CE40018014B4824008240246A +:1088C0000109A825ACF500189263000AA0E3001C7A +:1088D000967F00088F8500BC8F9900D0A4BF001E32 +:1088E0008E7000308E6400300E00020D8F250084E3 +:1088F0008F8500D0000289400002C10090AE00BC0C +:10890000023878210040302131D400021280000367 +:10891000020F80210002A8800215802190B200BCC5 +:1089200032540004128000020006C880021980211F +:108930008E6F00308F8B00BC2406800031EE000368 +:10894000000E682331AC0003020C1021AD6200045C +:1089500094A400E294AA00E294A300E231507FFFC5 +:108960002604000130897FFF006640240109882524 +:10897000A4B100E294A700E23C1308008E730060EB +:1089800030FF7FFF13F30012000000000E000D16F1 +:10899000000000000A000E240000282194CD00E20F +:1089A00001A46024A4CC00E290CB00E290C200E2DB +:1089B000316A00FF000A49C200092027000441C0B3 +:1089C0003055007F02A838250A000E20A0C700E21B +:1089D00094B100E202263824A4A700E290BF00E28E +:1089E00090B400E233F300FF0013C9C200199027CE +:1089F0003298007F0012A9C0031530250E000D1615 +:108A0000A0A600E20A000E24000028213084FFFF07 +:108A100030A5FFFFAF440018AF45001C03E000087D +:108A20008F42001427BDFFB0AFB000288F9000D058 +:108A3000AFB40038AFBF004CAFBE0048AFB7004482 +:108A4000AFB60040AFB5003CAFB30034AFB20030BA +:108A5000AFB1002CA7A00014920600D1920500D05F +:108A60003094FFFF30C400FF30A300FF0064102BE0 +:108A7000A7A0001E10400071AFA00010920900D006 +:108A80000014982B312800FF0088382324F2FFFFC0 +:108A90000012882B0233782451E000758FB2001049 +:108AA00096180012961900100014F4000319B82348 +:108AB0000017B400001614030282A82A16A00002B0 +:108AC000001E2403004020210244F82B13E0000282 +:108AD00000801821024018210003340000061C0306 +:108AE0003065FFFF2CA200091440000200609821AD +:108AF000241300088E090008001359808E08000C0A +:108B00003164FFFF3C0A0010008A3825274A040020 +:108B1000AF490038AF8A00B8AF48003CAF470030DB +:108B20000000000000000000000000000000000045 +:108B30000000000000000000000000000000000035 +:108B40008F4D000031AC00201180FFFD0013702A12 +:108B500001D110240000A821104001C00000000035 +:108B60008F9800B03C0B08008D6B00542411FF80DF +:108B7000921E00D00178202100911024921900D07B +:108B8000AF4200288D4500103C0608008CC60058F6 +:108B90003C1708008EF7005430A73FFF00071980EC +:108BA00000C34021030820210091F824920B00D03B +:108BB000AF5F002C9148000033D600FF332F00FF39 +:108BC00002F8702100166140000F68C031C9007FB3 +:108BD000018D3821013A2821316300FF3086007F62 +:108BE0003C02000C00A2B021000389400367C821A9 +:108BF00000DAF8213108003F3C1E000E0236B82191 +:108C00002738008803FE88212D0F0008AF9800AC9C +:108C1000AF9700BCAF9600C011E0018FAF9100B4D8 +:108C2000000868803C0E080025CE59E001AE6021A6 +:108C30008D8900000120000800000000920E00D283 +:108C4000920D00D00014982B31CA00FF31AC00FF08 +:108C5000008C5823014B20212492FFFF0012882B07 +:108C60000233782415E0FF8E000000008FB2001060 +:108C70008FBF004C8FBE00483A4200018FB70044BE +:108C80008FB600408FB5003C8FB400388FB30034EE +:108C90008FB200308FB1002C8FB0002803E00008A5 +:108CA00027BD0050915800013317002012E0020444 +:108CB00024160001921F00BC0000B02133F900010E +:108CC0001320000D241E00018D4800148E03008423 +:108CD0000103B02B16C00002010030218E06008473 +:108CE0008E05006400C5382B14E0000200C020216E +:108CF0008E0400640080B0218D4200148E0B00644D +:108D0000004B302B14C00002004020218E04006470 +:108D10000096B82356E00001241E0002025E202BBC +:108D200014800148000018218D5900388E2F000C46 +:108D30003C180080AE3900008D5000343C0EFF9F7F +:108D400001F86025AE3000049149003F35CDFFFFAA +:108D5000018D20243C0A00203C0BFFEFA229000BD0 +:108D6000008A38253562FFFF00E228243C0600080F +:108D70008F8700B800A6C825AE39000C8CE300141C +:108D8000AE2000183C08FFFBAE2300148CF800183E +:108D9000351FFFFF033F7024AE38001C8CEF000826 +:108DA00002D78021AE2F00248CED000CAE30002CB9 +:108DB000AE2E000CAE2D0020AE200028A6200038DC +:108DC000A620003A8CEC001401964823013750236A +:108DD00011400011AE2A001090EE003D8E2C0004D0 +:108DE0008E240000000E6900018D28210000502112 +:108DF00000AD302B008A582101661021AE250004F9 +:108E0000AE22000090E3003DA223000A8F8800B844 +:108E1000951F0006A63F00088F8B00AC24060002B9 +:108E200002C02021A16600009765003C8F9000AC35 +:108E300030A2FFFF0E000CF6AFA200208FA300208F +:108E4000000243808F8500B80103C8253C1F420003 +:108E5000033FC025AE1800048F8400AC8CAF0038EF +:108E6000AC8F00188CB00034AC90001CAC80000CAF +:108E7000AC800010A4800014A4800016A480002000 +:108E8000A4800022AC80002490A7003FA4870002A9 +:108E900012C00210240D000152E0000290A2003D19 +:108EA00090A2003E244A0001A08A00018F8400ACF9 +:108EB000AC9600088F8300D024070034906F00BC6C +:108EC00031EE000251C00001240700308F8200B84B +:108ED0008F9900BC906800BC905F000024100004D3 +:108EE00032CF0003A33F00008F9800B88F8C00BCE6 +:108EF000020F7023930D00012405C00031CA000346 +:108F0000A18D00018F9000BC8F8900B800F6382138 +:108F1000960400029526001200EA382100855824A4 +:108F200030C33FFF01631025A6020002921F00021A +:108F30003108000433F9003F37380040A21800021E +:108F400012C000028F8500BC00E838218F8600D057 +:108F5000ACA70004241FFFBF8CC3007C2ECB0001F4 +:108F6000240FFFDFACA3000890A8000D000B6940A0 +:108F70003102007FA0A2000D8F9000BC9219000D5D +:108F8000033FC024A218000D8F8A00BC914E000D33 +:108F900001CF6024018D4825A149000D8F8600B8BE +:108FA0008F8B00BC8CC70020AD6700108CC50024DF +:108FB000AD6500148CC40028AD6400188CC3002C6F +:108FC0000E000D16AD63001C2408000257C8009C5B +:108FD0008F9000D08F8F00D08F8A00C002E02021B8 +:108FE00091E800D091EB00D091E700D0311000FF64 +:108FF000316E00FF00106940000E28C001A5182145 +:1090000030E900FF0363C8210009314000CAF8219C +:1090100027220088AF8200ACAF9F00BCA33E00882F +:109020000E000CF68F9000AC8FB800200002638019 +:109030003C0F4200019840258F8C00B8010F582545 +:10904000AE0B00048D8400388F8B00AC000028210B +:1090500000053900AD6400188D8E00343C0F7FFF91 +:1090600035E8FFFFAD6E001C9183003E8D69001C4A +:109070008D6600180003510000036F02012AC02111 +:1090800000ED1025030AF82B00C2C821033F802100 +:10909000AD78001CAD700018AD60000CAD60001024 +:1090A0009184003E241F00052410C000A564001414 +:1090B000958E000402E8402402E02021A56E0016EF +:1090C0009185003EA5650020958D0004A56D0022C8 +:1090D000AD6000249187003FA56700029183003EA8 +:1090E0009189003D0123502325460001A16600011E +:1090F0008F8200AC8F9900BCAC570008A33F0000E2 +:109100008F8A00BC8F9800B8954F0002970E00120E +:109110002418FFBF020F682431C53FFF01A5382581 +:10912000A5470002914C00022405FFDF3189003F72 +:1091300035230040A14300028F9900BC8F8600D0E8 +:109140002409FFFFAF2000048CCB007C2403FF80A8 +:10915000AF2B00089322000D3C0B8000305F007F96 +:10916000A33F000D8F8E00BC91D0000D0218782413 +:10917000A1CF000D8F8C00BC918D000D01A538246E +:10918000A187000D8F8600BCACC90010ACD60014BE +:1091900090CA00180143B025A0D600188F8F00BCDC +:1091A0008F9800B88DE20018004BF82403E8C8251A +:1091B000ADF900189310003EA1F0001C8F8E00B88E +:1091C0008F8D00BC8F8700D095C50004A5A5001E1B +:1091D0000E00020D8CE500848F8700D000026140F4 +:1091E0000002210090EA00BC0184482100402821AF +:1091F0003156000212C0000302E930210002B080A3 +:1092000000D6302190EC00BC3184000410800003B3 +:1092100032EA00030005C08000D830212409000490 +:109220008F9700BC012A1023305F000300DFC821A4 +:10923000AEF900040E000D16A62500388F9000D060 +:1092400003C01821146000020060B02100009021CA +:1092500056C000868F9700B80012882B9609001020 +:10926000029550233C14002002A91021A6020010F0 +:10927000AF5400303154FFFF00000000961300107F +:10928000961F001213F30011000000008E17000C4F +:109290008E0C00080015C98002F94021001927C36F +:1092A0000119B02B0184782101F65821AE08000C79 +:1092B000AE0B00080014A82B023580241200FE6BB0 +:1092C0008F9000D00A000F3F00000000960B0014A2 +:1092D0008E0500043163FFFF000370C000AE38212B +:1092E000AF47003C8E0600048F4D003C00CDF023BC +:1092F0001BC00036000000008E080000250200019F +:109300003C16001036CF0008AF420038AF4F003097 +:10931000000000000000000000000000000000004D +:10932000000000000000000000000000000000003D +:109330008F440000308C00201180FFFD00000000F1 +:109340008F5904003C170020AE1900088F55040403 +:10935000AE15000CAF570030000000003C060800BE +:109360008CC600442418000110D800D3000000006F +:10937000960700123C0508008CA5004000A7682154 +:10938000A60D0012961E001427C90001A60900149C +:10939000960200143044FFFF5486FFC70014A82B28 +:1093A00030A5FFFF0E000F1AA60000143C030800B2 +:1093B0008C630024960500120043702300AE302316 +:1093C000A60600120A0011450014A82B8E02000008 +:1093D0000A0011583C16001091560001241000019B +:1093E0000016784215F0001C97A8001E8D5F00142F +:1093F0002411C00033FE3FFF0111C8243C180800AF +:109400008F180060033EB82532E53FFF00B8502BAF +:1094100011400011A7B7001E3C1008008E10005824 +:109420008F8F00B000057180240CFF80020F68212F +:1094300001AE48213124007F012C5824009A2821B4 +:109440003C02000EAF4B002C00A2302190C7000D53 +:1094500034E30004A0C3000D0E000D38000000002E +:109460008F9000D0240300018F9700B826B9000127 +:109470000019AC00024390230015AC0326F800400D +:1094800002B3202A0012882B240C00010300502173 +:1094900000911024AF9800B80A000F6DAFAC001017 +:1094A000955600128F8400B032C5FFFF0E000CEB02 +:1094B000A7B600148F9000D00A0011B10000182147 +:1094C0008D590038A620000824040003AE3900009E +:1094D0008D570034A220000A8F9800B8AE370004E0 +:1094E0003C0F0080930C003FA224000C8E28000C3F +:1094F0003C0BFF9FA22C000B010F1825356EFFFFC0 +:109500003C05FFEF8F9700B8006E682434A7FFFF7B +:1095100001A73024AE26000C8EFE001496FF001228 +:109520008F8200B0AE3E00108EF00014AE20001806 +:10953000AE200020AE300014AE2000248EE90018CA +:1095400033F03FFF00105180AE2900288EF900084B +:109550000142C02133EC0001AE3900308EEB000C2B +:109560008F8500AC001879C2000C238001E44021F3 +:10957000240E0002A628001CA6200036AE2B002CCC +:10958000A0AE00009767003C8F8A00AC3C0342000D +:1095900030EDFFFF01A33025AD4600048F9E00B8DB +:1095A000240200012408C0008FD1003824060034B2 +:1095B000AD5100188FC90034AD49001CAD40000CFE +:1095C000AD400010A5400014A5400016A5400020A5 +:1095D000A5400022AD400024A5560002A142000192 +:1095E0008F9F00AC8F9900B88F9800BCAFF6000831 +:1095F00093370000A31700008F8C00B88F8F00BC3A +:1096000091840001A1E400018F8D00BC95AB0002A4 +:109610000168702401D02825A5A5000291A70002A9 +:1096200030E3003FA1A300028F8300D08F8400BCF1 +:10963000907100BC323E000253C00001240600308D +:10964000AC8600048C6F007C2403FFBFAC8F000845 +:109650009088000D310B007FA08B000D8F8700BC20 +:1096600090EE000D01C32824A0E5000D8F9E00BCE4 +:1096700093CD000D35A60020A3C6000D8F8A00B83B +:109680008F9100BC8D500020AE3000108D49002419 +:10969000AE2900148D420028AE2200188D5F002CE8 +:1096A000AE3F001C0E000D16000000008F9000D091 +:1096B0000A00112B02C01821960A00123C1F080054 +:1096C0008FFF002403EA9821A61300120A00114517 +:1096D0000014A82BA08D00018F8900AC240C000180 +:1096E000AD2C00080A0010458F8300D027BDFFE095 +:1096F0003C1808008F180050AFB00010AFBF001822 +:10970000AFB10014AF8400B09371007403047821EA +:109710002410FF8031EE007F3225007F01F05824B5 +:1097200001DA68213C0C000AA38500C401AC2821A1 +:10973000AF4B002494A900109768000690A6006221 +:1097400000803821240200300109202330C300F0BA +:10975000AF8500D0106200193090FFFF90AE00621C +:10976000240DFFF0240A005001AE6024318B00FF6D +:10977000116A002F0000000016000007241F0C00D3 +:10978000AF5F00248FB100148FBF00188FB000109E +:1097900003E0000827BD00200E000F20020020215A +:1097A000241F0C00AF5F00248FB100148FBF00187E +:1097B0008FB0001003E0000827BD002094A200E055 +:1097C00094A400E290BF0113008218263079FFFFB5 +:1097D00033E700C014E000092F3100011600003803 +:1097E000000000005620FFE6241F0C000E000DDBD9 +:1097F000000000000A001277241F0C001620FFDE74 +:10980000000000000E000DDB000000001440FFDC33 +:10981000241F0C00160000228F8300D090690113D2 +:109820003122003FA06201130A001277241F0C00AE +:1098300094AF00D48F8600D400E0282124040005D2 +:109840000E000C7C31F0FFFF1440000524030003E0 +:10985000979100E6000018212625FFFFA78500E666 +:109860008F5801B80700FFFE3C196013AF4001801C +:10987000241F0C00AF500184007938253C101000E3 +:10988000AF4701888FB10014AF5001B8AF5F00241B +:109890008FB000108FBF001803E0000827BD002024 +:1098A0000E000F20020020215040FFB5241F0C00A5 +:1098B0008F8300D0906901130A0012A03122003F6B +:1098C0000E000F20020020211440FFAD241F0C00C9 +:1098D000122000078F8300D0906801133106003FEB +:1098E00034C20040A06201130A001277241F0C004A +:1098F0000E000DDB000000005040FFA1241F0C00F3 +:109900008F8300D0906801133106003F0A0012D007 +:1099100034C20040AF9B00C803E00008AF8000ECF9 +:109920003089FFFF000940422D02004100092980D3 +:10993000144000020009504024080040000879400B +:109940000008C0C001F85821256701A800EF702168 +:1099500025CC007F240DFF80018D18240065302167 +:1099600000CA282125640088240A00883C010800D8 +:10997000AC2A004C3C010800AC240050AF8500D458 +:109980003C010800AC2900603C010800AC280064E0 +:109990003C010800AC2700543C010800AC230058EF +:1099A0003C010800AC26005C03E000080000000059 +:1099B000308300FF30C6FFFF30E400FF8F4201B864 +:1099C0000440FFFE00034C00012438253C086000E1 +:1099D00000E820253C031000AF450180AF4601841C +:1099E000AF44018803E00008AF4301B88F86001C34 +:1099F0003C096012352700108CCB00043C0C600E33 +:109A000035850010316A00062D480001ACE800C41D +:109A10008CC40004ACA431808CC2000894C3000242 +:109A2000ACA2318403E00008A78300E43C030800F3 +:109A30008C6300508F8400E88F86001C2402FF8016 +:109A40000064C0210302C824AF5900288CCD000453 +:109A50003305007F00BA78213C0E000C01EE28216E +:109A6000ACAD00588CC80008AF8500D03C07601230 +:109A7000ACA8005C8CCC001034E80010ACAC000C3E +:109A80008CCB000CACAB000894AA00143C0208007C +:109A90008C42004425490001A4A9001494A4001498 +:109AA0003083FFFF106200178F8400D03C0A08004B +:109AB0008D4A0040A4AA00128CCE0018AC8E00245F +:109AC0008CCD0014AC8D00208CC70018AC87002C06 +:109AD0008CCC001424060001AC8C00288D0B00BC3B +:109AE0005166001A8D0200B48D0200B8A482003ABB +:109AF000948F003AA48F003C948800D403E00008BF +:109B00003102FFFF3C0908008D290024A4A00014A5 +:109B10008F8400D0A4A900128CCE0018AC8E002433 +:109B20008CCD0014AC8D00208CC70018AC87002CA5 +:109B30008CCC001424060001AC8C00288D0B00BCDA +:109B40005566FFEA8D0200B88D0200B4A482003A87 +:109B5000948F003AA48F003C948800D403E000085E +:109B60003102FFFF8F86001C3C0C08008D8C0050DA +:109B7000240BFF808CCD00083C03000C000D51C06D +:109B8000018A4021010B4824AF8A00E8AF49002830 +:109B900090C700073105007F00BA1021004328213B +:109BA00030E400041080002FAF8500D090CF000774 +:109BB00031EE000811C0003C000000008CD9000C00 +:109BC0008CC400140324C02B1300002600000000E6 +:109BD0008CC2000CACA200648CCD00182402FFF8EB +:109BE000ACAD00688CCC0010ACAC00808CCB000C11 +:109BF000ACAB00848CCA001CACAA007C90A900BC51 +:109C000001224024A0A800BC90C3000730670008D0 +:109C100010E000048F8500D090AF00BC35EE00014D +:109C2000A0AE00BC90D90007333800011300000F2C +:109C30008F8400D024070020908200BC34490002A9 +:109C4000A08900BC8F8400D090880062310300F0AE +:109C500014670006240A0034AC8A00C00A0013B25C +:109C6000000000000A00138C8CC2001490CB000787 +:109C70003166000210C0000500000000908D00BC9D +:109C800035AC0004A08C00BC8F8400D090980113E8 +:109C9000330F003FA08F01138F8E00D095C500D4E5 +:109CA00003E0000830A2FFFFACA000640A00138D9F +:109CB0000000000027BDFFD8AFB000108F90001C3F +:109CC000AFBF0024AFB40020AFB20018AFB1001492 +:109CD000AFB3001C9613000E3C07600A3C146006EC +:109CE0003264FFFF369300100E0012DF34F40410CC +:109CF0008F8400D43C11600E0E0009BB3631001079 +:109D0000920E00153C0708008CE700603C126012C0 +:109D100031CD000FA38D00F08E0E00048E0D0008D3 +:109D200096080012961F00109619001A9618001E29 +:109D3000960F001C310CFFFF33EBFFFF332AFFFFB0 +:109D40003309FFFF31E6FFFF3C010800AC2B004068 +:109D50003C010800AC2C00243C010800AC2A004463 +:109D6000AE293178AE26317C92020015960300169A +:109D700036520010304400FF3065FFFF3C060800FB +:109D80008CC60064AE243188AE4500B4920800143D +:109D900096190018241F0001011FC004332FFFFF74 +:109DA0003C0508008CA50058AE5800B8AE4F00BC6A +:109DB000920C0014AF8E00D8AF8D00DC318B00FF09 +:109DC000AE4B00C0920A0015AE670048AE66004C6C +:109DD000314900FFAE4900C8AE65007C3C03080075 +:109DE0008C6300503C0408008C84004C3C08080044 +:109DF0008D0800543C0208008C42005C8FBF002498 +:109E0000AE6300808FB00010AE8300748FB3001C6F +:109E1000AE22319CAE4200DCAE2731A0AE2631A48A +:109E2000AE24318CAE233190AE283194AE253198DA +:109E3000AE870050AE860054AE8500708FB100141E +:109E4000AE4700E0AE4600E4AE4400CCAE4300D0E6 +:109E5000AE4800D4AE4500D88FB400208FB20018B1 +:109E600003E0000827BD002827BDFFE0AFB10014C4 +:109E7000AFBF0018241100010E000865AFB000103C +:109E800010510005978400E6978300CC0083102BC7 +:109E9000144000088F8500D4240700028FBF0018EB +:109EA0008FB100148FB0001000E0102103E0000813 +:109EB00027BD00200E000C9A24040005AF8200E8A4 +:109EC0001040FFF6240700020E0008698F90001C66 +:109ED000979F00E68F9900E88F8D00C827EF00015B +:109EE000240E0050AF590020A78F00E6A1AE00005D +:109EF0003C0C08008D8C00648F8600C8240A80000A +:109F0000000C5E00ACCB0074A4C0000694C9000A2B +:109F1000241FFF803C0D000C012AC024A4D8000A95 +:109F200090C8000A24182000011F1825A0C3000AA9 +:109F30008F8700C8A0E000788F8500C80000382116 +:109F4000A0A000833C0208008C4200508F8400E8EF +:109F50000044782101FFC824AF590028960B000265 +:109F600031EE007F01DA6021018D3021A4CB00D4D5 +:109F7000960A0002AF8600D03C0E00042549240159 +:109F8000A4C900E68E080004ACC800048E030008D3 +:109F9000ACC30000A4C00010A4C00014A0C000D036 +:109FA0008F8500D02403FFBFA0A000D13C0408008F +:109FB0008C8400648F8200D0A04400D28E1F000CDD +:109FC0008F8A00D0978F00E4AD5F001C8E190010BF +:109FD00024100030AD590018A5400030A5510054A0 +:109FE000A5510056A54F0016AD4E0068AD58008033 +:109FF000AD580084914D006231AC000F358B0010DC +:10A00000A14B00628F8600D090C900633128007F89 +:10A01000A0C800638F8400D02406FFFF90850063F2 +:10A0200000A31024A08200638F9100D000E01021D3 +:10A03000923F00BC37F90001A23900BC8F8A00D0E2 +:10A04000938F00F0AD580064AD5000C0914E00D326 +:10A05000000F690031CC000F018D5825A14B00D3B2 +:10A060008F8500D08F8900DCACA900E88F8800D8EC +:10A070008FBF00188FB100148FB0001027BD0020D3 +:10A08000ACA800ECA4A600D6A4A000E0A4A000E226 +:10A0900003E000080000000027BDFFE0AFB00010A3 +:10A0A0008F90001CAFB10014AFBF00188E190004D0 +:10A0B0003C1808008F180050240FFF80001989C039 +:10A0C0000238702131CD007F01CF602401BA5021C8 +:10A0D0003C0B000CAF4C0028014B4021950900D4EB +:10A0E000950400D68E0700043131FFFFAF8800D001 +:10A0F0000E000933000721C08E0600048F8300C8BC +:10A10000000629C0AF4500209064003E3082004028 +:10A11000144000068F8400D0341FFFFF948300D6C4 +:10A120003062FFFF145F000400000000948400D63A +:10A130000E0008C83084FFFF8E0500040220302185 +:10A140008FBF00188FB100148FB0001024040022BC +:10A1500000003821000529C00A00130327BD002094 +:10A1600027BDFFE0AFB100143091FFFFAFB000108A +:10A17000AFBF00181220001D000080218F86001C38 +:10A180008CC500002403000600053F0200051402F0 +:10A1900030E4000714830015304500FF2CA80006AA +:10A1A0001100004D000558803C0C0800258C5A0019 +:10A1B000016C50218D4900000120000800000000C2 +:10A1C0008F8E00EC240D000111CD0059000000001D +:10A1D000260B00013170FFFF24CA00200211202B42 +:10A1E000014030211480FFE6AF8A001C02001021DC +:10A1F0008FBF00188FB100148FB0001003E000086B +:10A2000027BD0020938700CE14E0003824040014FA +:10A210000E0013C4000000008F86001C2402000101 +:10A220000A00150BAF8200EC8F8900EC24080002B5 +:10A230001128003B240400130000282100003021D5 +:10A24000240700010E001303000000000A00150B94 +:10A250008F86001C8F8700EC2405000214E5FFF6B2 +:10A26000240400120E001370000000008F8500E827 +:10A2700000403021240400120E0013030000382196 +:10A280000A00150B8F86001C8F8300EC241F00032F +:10A29000147FFFD0260B00010E00132200000000E7 +:10A2A0008F8500E8004030212402000224040010C1 +:10A2B00000003821AF8200EC0E0013030000000004 +:10A2C0000A00150B8F86001C8F8F00EC24060002FD +:10A2D00011E6000B000000002404001000002821FB +:10A2E000000030210A001528240700010000282161 +:10A2F0000E001303000030210A00150B8F86001C8E +:10A300000E00143100000000144000128F99001C50 +:10A310008F86001C240200030A00150BAF8200EC9C +:10A320000E0014BD000000000A00150B8F86001CF3 +:10A330000E00131200000000240200022404001486 +:10A340000000282100003021000038210A001545B6 +:10A35000AF8200EC0040382124040010973800023E +:10A36000000028210E0013033306FFFF0A00150B1F +:10A370008F86001C8F8400C83C077FFF34E6FFFFF8 +:10A380008C8500742402000100A61824AC8300749C +:10A3900003E00008A082000510A000362CA2008077 +:10A3A000274A04003C0B00052409008010400007E8 +:10A3B0002408008030A6000F00C540212D03008135 +:10A3C0001460000200A0482124080080AF4B003038 +:10A3D0000000000000000000000000001100000963 +:10A3E00000003821014030218C8D000024E700045A +:10A3F00000E8602BACCD0000248400041580FFFA37 +:10A4000024C600040000000000000000000000005E +:10A410003C0E0006010E3825AF470030000000005A +:10A4200000000000000000008F4F000031E8001025 +:10A430001100FFFD000000008F42003C8F43003CF4 +:10A440000049C8210323C02B1300000400000000B2 +:10A450008F4C003825860001AF4600388F47003CFE +:10A4600000A9282300E96821AF4D003C14A0FFCECD +:10A470002CA2008003E000080000000027BDFFD0F0 +:10A480003C020002AFB100143C11000CAF45003893 +:10A49000AFB3001CAF46003C00809821AF420030B3 +:10A4A00024050088AF44002803512021AFBF0028B5 +:10A4B000AFB50024AFB40020AFB200180E00157D78 +:10A4C000AFB000103C1F08008FFF004C3C18080084 +:10A4D0008F1800642410FF8003F3A82132B9007F95 +:10A4E00002B078240018A0C0033A702100189140EF +:10A4F00001D12021AF4F00280E00157D02542821E4 +:10A500003C0D08008DAD00502405012001B35821F9 +:10A51000316C007F01705024019A482101312021C3 +:10A520000E00157DAF4A00283C0808008D08005435 +:10A530003C0508008CA500640113382130E6007F3B +:10A5400000F0182400DA202100912021AF430028D8 +:10A550000E00157D000529403C0208008C42005881 +:10A560003C1008008E1000601200001C005388216F +:10A570002415FF800A0016003C14000C3226007FD0 +:10A580000235182400DA202102402821AF43002898 +:10A59000009420210E00157D2610FFC01200000F30 +:10A5A000023288212E05004110A0FFF42412100071 +:10A5B0003226007F001091800235182400DA202115 +:10A5C00002402821AF430028009420210E00157D71 +:10A5D000000080211600FFF3023288213C0B0800A6 +:10A5E0008D6B005C240AFF8024050002017340216A +:10A5F000010A4824AF4900283C0408009484006202 +:10A600003110007F021A88213C07000C0E000CCA92 +:10A610000227982100402821026020218FBF0028B6 +:10A620008FB500248FB400208FB3001C8FB20018A8 +:10A630008FB100148FB000100A00157D27BD0030C7 +:10A640008F83001C8C620004104000030000000097 +:10A6500003E00008000000008C6400108C65000816 +:08A660000A0015B68C66000C1F +:08A66800000000000000001BCF +:10A670000000000F0000000A0000000800000006B3 +:10A6800000000005000000050000000400000004B8 +:10A6900000000003000000030000000300000003AE +:10A6A00000000003000000020000000200000002A1 +:10A6B0000000000200000002000000020000000292 +:10A6C0000000000200000002000000020000000282 +:10A6D0000000000200000002000000020000000272 +:0CA6E0000000000100000001000000016B +:04A6EC0008000F58FB +:10A6F00008000DB008000FEC0800109408000F804F +:10A7000008000FC0080011CC08000DCC080011F0A3 +:10A7100008000E1C08001634080015DC08000DCCDB +:10A7200008000DCC08000DCC0800127C0800127C3B +:10A7300008000DCC08000DCC0800158008000DCCD9 +:10A7400008000DCC08000DCC08000DCC080013F05B +:10A7500008000DCC08000DCC08000DCC08000DCC75 +:10A7600008000DCC08000DCC08000DCC08000DCC65 +:10A7700008000DCC08000DCC08000DCC08000DCC55 +:10A7800008000DCC08000DCC08000FE008000DCC2F +:10A7900008000DCC0800153008000DCC08000DCCC9 +:10A7A00008000DCC08000DCC08000DCC08000DCC25 +:10A7B00008000DCC08000DCC08000DCC08000DCC15 +:10A7C00008000DCC08000DCC08000DCC08000DCC05 +:10A7D00008000DCC08000DCC08000DCC0800145C5E +:10A7E00008000DCC08000DCC08001370080012E022 +:10A7F00008002E9408002E9C08002E6408002E707D +:10A8000008002E7C08002E88080046B408003F008F +:10A8100008004634080046B4080046B4080044B4B2 +:10A82000080046B4080046FC08005524080054E41B +:10A83000080054B008005484080054600800541CF8 +:10A840000A000C7600000000000000000000000D6F +:10A85000727870352E302E306A3600000500000305 +:10A8600000000000000000010000000000000000E7 +:10A8700000000000000000000000000000000000D8 +:10A8800000000000000000000000000000000000C8 +:10A8900000000000000000000000000000000000B8 +:10A8A00000000000000000000000000000000000A8 +:10A8B0000000000000000000000000000000000098 +:10A8C0000000000000000000000000000000000088 +:10A8D0000000000000000000000000000000000078 +:10A8E0000000000000000000000000000000000068 +:10A8F0000000000000000000000000000000000058 +:10A900000000000000000000000000000000000047 +:10A910000000000000000000000000000000000037 +:10A920000000000000000000000000000000000027 +:10A930000000000000000000000000000000000017 +:10A940000000000000000000000000000000000007 +:10A9500000000000000000000000000000000000F7 +:10A9600000000000000000000000000000000000E7 +:10A9700000000000000000000000000000000000D7 +:10A9800000000000000000000000000000000000C7 +:10A9900000000000000000000000000000000000B7 +:10A9A00000000000000000000000000000000000A7 +:10A9B0000000000000000000000000000000000097 +:10A9C0000000000000000000000000000000000087 +:10A9D0000000000000000000000000000000000077 +:10A9E0000000000000000000000000000000000067 +:10A9F0000000000000000000000000000000000057 +:10AA00000000000000000000000000000000000046 +:10AA10000000000000000000000000000000000036 +:10AA20000000000000000000000000000000000026 +:10AA30000000000000000000000000000000000016 +:10AA40000000000000000000000000000000000006 +:10AA500000000000000000000000000000000000F6 +:10AA600000000000000000000000000000000000E6 +:10AA700000000000000000000000000000000000D6 +:10AA800000000000000000000000000000000000C6 +:10AA900000000000000000000000000000000000B6 +:10AAA00000000000000000000000000000000000A6 +:10AAB0000000000000000000000000000000000096 +:10AAC0000000000000000000000000000000000086 +:10AAD0000000000000000000000000000000000076 +:10AAE0000000000000000000000000000000000066 +:10AAF0000000000000000000000000000000000056 +:10AB00000000000000000000000000000000000045 +:10AB10000000000000000000000000000000000035 +:10AB20000000000000000000000000000000000025 +:10AB30000000000000000000000000000000000015 +:10AB40000000000000000000000000000000000005 +:10AB500000000000000000000000000000000000F5 +:10AB600000000000000000000000000000000000E5 +:10AB700000000000000000000000000000000000D5 +:10AB800000000000000000000000000000000000C5 +:10AB900000000000000000000000000000000000B5 +:10ABA00000000000000000000000000000000000A5 +:10ABB0000000000000000000000000000000000095 +:10ABC0000000000000000000000000000000000085 +:10ABD0000000000000000000000000000000000075 +:10ABE0000000000000000000000000000000000065 +:10ABF0000000000000000000000000000000000055 +:10AC00000000000000000000000000000000000044 +:10AC10000000000000000000000000000000000034 +:10AC20000000000000000000000000000000000024 +:10AC30000000000000000000000000000000000014 +:10AC40000000000000000000000000000000000004 +:10AC500000000000000000000000000000000000F4 +:10AC600000000000000000000000000000000000E4 +:10AC700000000000000000000000000000000000D4 +:10AC800000000000000000000000000000000000C4 +:10AC900000000000000000000000000000000000B4 +:10ACA00000000000000000000000000000000000A4 +:10ACB0000000000000000000000000000000000094 +:10ACC0000000000000000000000000000000000084 +:10ACD0000000000000000000000000000000000074 +:10ACE0000000000000000000000000000000000064 +:10ACF0000000000000000000000000000000000054 +:10AD00000000000000000000000000000000000043 +:10AD10000000000000000000000000000000000033 +:10AD20000000000000000000000000000000000023 +:10AD30000000000000000000000000000000000013 +:10AD40000000000000000000000000000000000003 +:10AD500000000000000000000000000000000000F3 +:10AD600000000000000000000000000000000000E3 +:10AD700000000000000000000000000000000000D3 +:10AD800000000000000000000000000000000000C3 +:10AD900000000000000000000000000000000000B3 +:10ADA00000000000000000000000000000000000A3 +:10ADB0000000000000000000000000000000000093 +:10ADC0000000000000000000000000000000000083 +:10ADD0000000000000000000000000000000000073 +:10ADE0000000000000000000000000000000000063 +:10ADF0000000000000000000000000000000000053 +:10AE00000000000000000000000000000000000042 +:10AE10000000000000000000000000000000000032 +:10AE20000000000000000000000000000000000022 +:10AE30000000000000000000000000000000000012 +:10AE40000000000000000000000000000000000002 +:10AE500000000000000000000000000000000000F2 +:10AE600000000000000000000000000000000000E2 +:10AE700000000000000000000000000000000000D2 +:10AE800000000000000000000000000000000000C2 +:10AE900000000000000000000000000000000000B2 +:10AEA00000000000000000000000000000000000A2 +:10AEB0000000000000000000000000000000000092 +:10AEC0000000000000000000000000000000000082 +:10AED0000000000000000000000000000000000072 +:10AEE0000000000000000000000000000000000062 +:10AEF0000000000000000000000000000000000052 +:10AF00000000000000000000000000000000000041 +:10AF10000000000000000000000000000000000031 +:10AF20000000000000000000000000000000000021 +:10AF30000000000000000000000000000000000011 +:10AF40000000000000000000000000000000000001 +:10AF500000000000000000000000000000000000F1 +:10AF600000000000000000000000000000000000E1 +:10AF700000000000000000000000000000000000D1 +:10AF800000000000000000000000000000000000C1 +:10AF900000000000000000000000000000000000B1 +:10AFA00000000000000000000000000000000000A1 +:10AFB0000000000000000000000000000000000091 +:10AFC0000000000000000000000000000000000081 +:10AFD0000000000000000000000000000000000071 +:10AFE0000000000000000000000000000000000061 +:10AFF0000000000000000000000000000000000051 +:10B000000000000000000000000000000000000040 +:10B010000000000000000000000000000000000030 +:10B020000000000000000000000000000000000020 +:10B030000000000000000000000000000000000010 +:10B040000000000000000000000000000000000000 +:10B0500000000000000000000000000000000000F0 +:10B0600000000000000000000000000000000000E0 +:10B0700000000000000000000000000000000000D0 +:10B0800000000000000000000000000000000000C0 +:10B0900000000000000000000000000000000000B0 +:10B0A00000000000000000000000000000000000A0 +:10B0B0000000000000000000000000000000000090 +:10B0C0000000000000000000000000000000000080 +:10B0D0000000000000000000000000000000000070 +:10B0E0000000000000000000000000000000000060 +:10B0F0000000000000000000000000000000000050 +:10B10000000000000000000000000000000000003F +:10B11000000000000000000000000000000000002F +:10B12000000000000000000000000000000000001F +:10B13000000000000000000000000000000000000F +:10B1400000000000000000000000000000000000FF +:10B1500000000000000000000000000000000000EF +:10B1600000000000000000000000000000000000DF +:10B1700000000000000000000000000000000000CF +:10B1800000000000000000000000000000000000BF +:10B1900000000000000000000000000000000000AF +:10B1A000000000000000000000000000000000009F +:10B1B000000000000000000000000000000000008F +:10B1C000000000000000000000000000000000007F +:10B1D000000000000000000000000000000000006F +:10B1E000000000000000000000000000000000005F +:10B1F000000000000000000000000000000000004F +:10B20000000000000000000000000000000000003E +:10B21000000000000000000000000000000000002E +:10B22000000000000000000000000000000000001E +:10B23000000000000000000000000000000000000E +:10B2400000000000000000000000000000000000FE +:10B2500000000000000000000000000000000000EE +:10B2600000000000000000000000000000000000DE +:10B2700000000000000000000000000000000000CE +:10B2800000000000000000000000000000000000BE +:10B2900000000000000000000000000000000000AE +:10B2A000000000000000000000000000000000009E +:10B2B000000000000000000000000000000000008E +:10B2C000000000000000000000000000000000007E +:10B2D000000000000000000000000000000000006E +:10B2E000000000000000000000000000000000005E +:10B2F000000000000000000000000000000000004E +:10B30000000000000000000000000000000000003D +:10B31000000000000000000000000000000000002D +:10B32000000000000000000000000000000000001D +:10B33000000000000000000000000000000000000D +:10B3400000000000000000000000000000000000FD +:10B3500000000000000000000000000000000000ED +:10B3600000000000000000000000000000000000DD +:10B3700000000000000000000000000000000000CD +:10B3800000000000000000000000000000000000BD +:10B3900000000000000000000000000000000000AD +:10B3A000000000000000000000000000000000009D +:10B3B000000000000000000000000000000000008D +:10B3C000000000000000000000000000000000007D +:10B3D000000000000000000000000000000000006D +:10B3E000000000000000000000000000000000005D +:10B3F000000000000000000000000000000000004D +:10B40000000000000000000000000000000000003C +:10B41000000000000000000000000000000000002C +:10B42000000000000000000000000000000000001C +:10B43000000000000000000000000000000000000C +:10B4400000000000000000000000000000000000FC +:10B4500000000000000000000000000000000000EC +:10B4600000000000000000000000000000000000DC +:10B4700000000000000000000000000000000000CC +:10B4800000000000000000000000000000000000BC +:10B4900000000000000000000000000000000000AC +:10B4A000000000000000000000000000000000009C +:10B4B000000000000000000000000000000000008C +:10B4C000000000000000000000000000000000007C +:10B4D000000000000000000000000000000000006C +:10B4E000000000000000000000000000000000005C +:10B4F000000000000000000000000000000000004C +:10B50000000000000000000000000000000000003B +:10B51000000000000000000000000000000000002B +:10B52000000000000000000000000000000000001B +:10B53000000000000000000000000000000000000B +:10B5400000000000000000000000000000000000FB +:10B5500000000000000000000000000000000000EB +:10B5600000000000000000000000000000000000DB +:10B5700000000000000000000000000000000000CB +:10B5800000000000000000000000000000000000BB +:10B5900000000000000000000000000000000000AB +:10B5A000000000000000000000000000000000009B +:10B5B000000000000000000000000000000000008B +:10B5C000000000000000000000000000000000007B +:10B5D000000000000000000000000000000000006B +:10B5E000000000000000000000000000000000005B +:10B5F000000000000000000000000000000000004B +:10B60000000000000000000000000000000000003A +:10B61000000000000000000000000000000000002A +:10B62000000000000000000000000000000000001A +:10B63000000000000000000000000000000000000A +:10B6400000000000000000000000000000000000FA +:10B6500000000000000000000000000000000000EA +:10B6600000000000000000000000000000000000DA +:10B6700000000000000000000000000000000000CA +:10B6800000000000000000000000000000000000BA +:10B6900000000000000000000000000000000000AA +:10B6A000000000000000000000000000000000009A +:10B6B000000000000000000000000000000000008A +:10B6C000000000000000000000000000000000007A +:10B6D000000000000000000000000000000000006A +:10B6E000000000000000000000000000000000005A +:10B6F000000000000000000000000000000000004A +:10B700000000000000000000000000000000000039 +:10B710000000000000000000000000000000000029 +:10B720000000000000000000000000000000000019 +:10B730000000000000000000000000000000000009 +:10B7400000000000000000000000000000000000F9 +:10B7500000000000000000000000000000000000E9 +:10B7600000000000000000000000000000000000D9 +:10B7700000000000000000000000000000000000C9 +:10B7800000000000000000000000000000000000B9 +:10B7900000000000000000000000000000000000A9 +:10B7A0000000000000000000000000000000000099 +:10B7B0000000000000000000000000000000000089 +:10B7C0000000000000000000000000000000000079 +:10B7D0000000000000000000000000000000000069 +:10B7E0000000000000000000000000000000000059 +:10B7F0000000000000000000000000000000000049 +:10B800000000000000000000000000000000000038 +:10B810000000000000000000000000000000000028 +:10B820000000000000000000000000000000000018 +:10B830000000000000000000000000000000000008 +:10B8400000000000000000000000000000000000F8 +:10B8500000000000000000000000000000000000E8 +:10B8600000000000000000000000000000000000D8 +:10B8700000000000000000000000000000000000C8 +:10B8800000000000000000000000000000000000B8 +:10B8900000000000000000000000000000000000A8 +:10B8A0000000000000000000000000000000000098 +:10B8B0000000000000000000000000000000000088 +:10B8C0000000000000000000000000000000000078 +:10B8D0000000000000000000000000000000000068 +:10B8E0000000000000000000000000000000000058 +:10B8F0000000000000000000000000000000000048 +:10B900000000000000000000000000000000000037 +:10B910000000000000000000000000000000000027 +:10B920000000000000000000000000000000000017 +:10B930000000000000000000000000000000000007 +:10B9400000000000000000000000000000000000F7 +:10B9500000000000000000000000000000000000E7 +:10B9600000000000000000000000000000000000D7 +:10B9700000000000000000000000000000000000C7 +:10B9800000000000000000000000000000000000B7 +:10B9900000000000000000000000000000000000A7 +:10B9A0000000000000000000000000000000000097 +:10B9B0000000000000000000000000000000000087 +:10B9C0000000000000000000000000000000000077 +:10B9D0000000000000000000000000000000000067 +:10B9E0000000000000000000000000000000000057 +:10B9F0000000000000000000000000000000000047 +:10BA00000000000000000000000000000000000036 +:10BA10000000000000000000000000000000000026 +:10BA20000000000000000000000000000000000016 +:10BA30000000000000000000000000000000000006 +:10BA400000000000000000000000000000000000F6 +:10BA500000000000000000000000000000000000E6 +:10BA600000000000000000000000000000000000D6 +:10BA700000000000000000000000000000000000C6 +:10BA800000000000000000000000000000000000B6 +:10BA900000000000000000000000000000000000A6 +:10BAA0000000000000000000000000000000000096 +:10BAB0000000000000000000000000000000000086 +:10BAC0000000000000000000000000000000000076 +:10BAD0000000000000000000000000000000000066 +:10BAE0000000000000000000000000000000000056 +:10BAF0000000000000000000000000000000000046 +:10BB00000000000000000000000000000000000035 +:10BB10000000000000000000000000000000000025 +:10BB20000000000000000000000000000000000015 +:10BB30000000000000000000000000000000000005 +:10BB400000000000000000000000000000000000F5 +:10BB500000000000000000000000000000000000E5 +:10BB600000000000000000000000000000000000D5 +:10BB700000000000000000000000000000000000C5 +:10BB800000000000000000000000000000000000B5 +:10BB900000000000000000000000000000000000A5 +:10BBA0000000000000000000000000000000000095 +:10BBB0000000000000000000000000000000000085 +:10BBC0000000000000000000000000000000000075 +:10BBD0000000000000000000000000000000000065 +:10BBE0000000000000000000000000000000000055 +:10BBF0000000000000000000000000000000000045 +:10BC00000000000000000000000000000000000034 +:10BC10000000000000000000000000000000000024 +:10BC20000000000000000000000000000000000014 +:10BC30000000000000000000000000000000000004 +:10BC400000000000000000000000000000000000F4 +:10BC500000000000000000000000000000000000E4 +:10BC600000000000000000000000000000000000D4 +:10BC700000000000000000000000000000000000C4 +:10BC800000000000000000000000000000000000B4 +:10BC900000000000000000000000000000000000A4 +:10BCA0000000000000000000000000000000000094 +:10BCB0000000000000000000000000000000000084 +:10BCC0000000000000000000000000000000000074 +:10BCD0000000000000000000000000000000000064 +:10BCE0000000000000000000000000000000000054 +:10BCF0000000000000000000000000000000000044 +:10BD00000000000000000000000000000000000033 +:10BD10000000000000000000000000000000000023 +:10BD20000000000000000000000000000000000013 +:10BD30000000000000000000000000000000000003 +:10BD400000000000000000000000000000000000F3 +:10BD500000000000000000000000000000000000E3 +:10BD600000000000000000000000000000000000D3 +:10BD700000000000000000000000000000000000C3 +:10BD800000000000000000000000000000000000B3 +:10BD900000000000000000000000000000000000A3 +:10BDA0000000000000000000000000000000000093 +:10BDB0000000000000000000000000000000000083 +:10BDC0000000000000000000000000000000000073 +:10BDD0000000000000000000000000000000000063 +:10BDE0000000000000000000000000000000000053 +:10BDF0000000000000000000000000000000000043 +:10BE00000000000000000000000000000000000032 +:10BE10000000000000000000000000000000000022 +:10BE20000000000000000000000000000000000012 +:10BE30000000000000000000000000000000000002 +:10BE400000000000000000000000000000000000F2 +:10BE500000000000000000000000000000000000E2 +:10BE600000000000000000000000000000000000D2 +:10BE700000000000000000000000000000000000C2 +:10BE800000000000000000000000000000000000B2 +:10BE900000000000000000000000000000000000A2 +:10BEA0000000000000000000000000000000000092 +:10BEB0000000000000000000000000000000000082 +:10BEC0000000000000000000000000000000000072 +:10BED0000000000000000000000000000000000062 +:10BEE0000000000000000000000000000000000052 +:10BEF0000000000000000000000000000000000042 +:10BF00000000000000000000000000000000000031 +:10BF10000000000000000000000000000000000021 +:10BF20000000000000000000000000000000000011 +:10BF30000000000000000000000000000000000001 +:10BF400000000000000000000000000000000000F1 +:10BF500000000000000000000000000000000000E1 +:10BF600000000000000000000000000000000000D1 +:10BF700000000000000000000000000000000000C1 +:10BF800000000000000000000000000000000000B1 +:10BF900000000000000000000000000000000000A1 +:10BFA0000000000000000000000000000000000091 +:10BFB0000000000000000000000000000000000081 +:10BFC0000000000000000000000000000000000071 +:10BFD0000000000000000000000000000000000061 +:10BFE0000000000000000000000000000000000051 +:10BFF0000000000000000000000000000000000041 +:10C000000000000000000000000000000000000030 +:10C010000000000000000000000000000000000020 +:10C020000000000000000000000000000000000010 +:10C030000000000000000000000000000000000000 +:10C0400000000000000000000000000000000000F0 +:10C0500000000000000000000000000000000000E0 +:10C0600000000000000000000000000000000000D0 +:10C0700000000000000000000000000000000000C0 +:10C0800000000000000000000000000000000000B0 +:10C0900000000000000000000000000000000000A0 +:10C0A0000000000000000000000000000000000090 +:10C0B0000000000000000000000000000000000080 +:10C0C0000000000000000000000000000000000070 +:10C0D0000000000000000000000000000000000060 +:10C0E0000000000000000000000000000000000050 +:10C0F0000000000000000000000000000000000040 +:10C10000000000000000000000000000000000002F +:10C11000000000000000000000000000000000001F +:10C12000000000000000000000000000000000000F +:10C1300000000000000000000000000000000000FF +:10C1400000000000000000000000000000000000EF +:10C1500000000000000000000000000000000000DF +:10C1600000000000000000000000000000000000CF +:10C1700000000000000000000000000000000000BF +:10C1800000000000000000000000000000000000AF +:10C19000000000000000000000000000000000009F +:10C1A000000000000000000000000000000000008F +:10C1B000000000000000000000000000000000007F +:10C1C000000000000000000000000000000000006F +:10C1D000000000000000000000000000000000005F +:10C1E000000000000000000000000000000000004F +:10C1F000000000000000000000000000000000003F +:10C20000000000000000000000000000000000002E +:10C21000000000000000000000000000000000001E +:10C22000000000000000000000000000000000000E +:10C2300000000000000000000000000000000000FE +:10C2400000000000000000000000000000000000EE +:10C2500000000000000000000000000000000000DE +:10C2600000000000000000000000000000000000CE +:10C2700000000000000000000000000000000000BE +:10C2800000000000000000000000000000000000AE +:10C29000000000000000000000000000000000009E +:10C2A000000000000000000000000000000000008E +:10C2B000000000000000000000000000000000007E +:10C2C000000000000000000000000000000000006E +:10C2D000000000000000000000000000000000005E +:10C2E000000000000000000000000000000000004E +:10C2F000000000000000000000000000000000003E +:10C30000000000000000000000000000000000002D +:10C31000000000000000000000000000000000001D +:10C32000000000000000000000000000000000000D +:10C3300000000000000000000000000000000000FD +:10C3400000000000000000000000000000000000ED +:10C3500000000000000000000000000000000000DD +:10C3600000000000000000000000000000000000CD +:10C3700000000000000000000000000000000000BD +:10C3800000000000000000000000000000000000AD +:10C39000000000000000000000000000000000009D +:10C3A000000000000000000000000000000000008D +:10C3B000000000000000000000000000000000007D +:10C3C000000000000000000000000000000000006D +:10C3D000000000000000000000000000000000005D +:10C3E000000000000000000000000000000000004D +:10C3F000000000000000000000000000000000003D +:10C40000000000000000000000000000000000002C +:10C41000000000000000000000000000000000001C +:10C42000000000000000000000000000000000000C +:10C4300000000000000000000000000000000000FC +:10C4400000000000000000000000000000000000EC +:10C4500000000000000000000000000000000000DC +:10C4600000000000000000000000000000000000CC +:10C4700000000000000000000000000000000000BC +:10C4800000000000000000000000000000000000AC +:10C49000000000000000000000000000000000009C +:10C4A000000000000000000000000000000000008C +:10C4B000000000000000000000000000000000007C +:10C4C000000000000000000000000000000000006C +:10C4D000000000000000000000000000000000005C +:10C4E000000000000000000000000000000000004C +:10C4F000000000000000000000000000000000003C +:10C50000000000000000000000000000000000002B +:10C51000000000000000000000000000000000001B +:10C52000000000000000000000000000000000000B +:10C5300000000000000000000000000000000000FB +:10C5400000000000000000000000000000000000EB +:10C5500000000000000000000000000000000000DB +:10C5600000000000000000000000000000000000CB +:10C5700000000000000000000000000000000000BB +:10C5800000000000000000000000000000000000AB +:10C59000000000000000000000000000000000009B +:10C5A000000000000000000000000000000000008B +:10C5B000000000000000000000000000000000007B +:10C5C000000000000000000000000000000000006B +:10C5D000000000000000000000000000000000005B +:10C5E000000000000000000000000000000000004B +:10C5F000000000000000000000000000000000003B +:10C60000000000000000000000000000000000002A +:10C61000000000000000000000000000000000001A +:10C62000000000000000000000000000000000000A +:10C6300000000000000000000000000000000000FA +:10C6400000000000000000000000000000000000EA +:10C6500000000000000000000000000000000000DA +:10C6600000000000000000000000000000000000CA +:10C6700000000000000000000000000000000000BA +:10C6800000000000000000000000000000000000AA +:10C69000000000000000000000000000000000009A +:10C6A000000000000000000000000000000000008A +:10C6B000000000000000000000000000000000007A +:10C6C000000000000000000000000000000000006A +:10C6D000000000000000000000000000000000005A +:10C6E000000000000000000000000000000000004A +:10C6F000000000000000000000000000000000003A +:10C700000000000000000000000000000000000029 +:10C710000000000000000000000000000000000019 +:10C720000000000000000000000000000000000009 +:10C7300000000000000000000000000000000000F9 +:10C7400000000000000000000000000000000000E9 +:10C7500000000000000000000000000000000000D9 +:10C7600000000000000000000000000000000000C9 +:10C7700000000000000000000000000000000000B9 +:10C7800000000000000000000000000000000000A9 +:10C790000000000000000000000000000000000099 +:10C7A0000000000000000000000000000000000089 +:10C7B0000000000000000000000000000000000079 +:10C7C0000000000000000000000000000000000069 +:10C7D0000000000000000000000000000000000059 +:10C7E0000000000000000000000000000000000049 +:10C7F0000000000000000000000000000000000039 +:10C800000000000000000000000000000000000028 +:10C810000000000000000000000000000000000018 +:10C820000000000000000000000000000000000008 +:10C8300000000000000000000000000000000000F8 +:10C8400000000000000000000000000000000000E8 +:10C8500000000000000000000000000000000000D8 +:10C8600000000000000000000000000000000000C8 +:10C8700000000000000000000000000000000000B8 +:10C8800000000000000000000000000000000000A8 +:10C890000000000000000000000000000000000098 +:10C8A0000000000000000000000000000000000088 +:10C8B0000000000000000000000000000000000078 +:10C8C0000000000000000000000000000000000068 +:10C8D0000000000000000000000000000000000058 +:10C8E0000000000000000000000000000000000048 +:10C8F0000000000000000000000000000000000038 +:10C900000000000000000000000000000000000027 +:10C910000000000000000000000000000000000017 +:10C920000000000000000000000000000000000007 +:10C9300000000000000000000000000000000000F7 +:10C9400000000000000000000000000000000000E7 +:10C9500000000000000000000000000000000000D7 +:10C9600000000000000000000000000000000000C7 +:10C9700000000000000000000000000000000000B7 +:10C9800000000000000000000000000000000000A7 +:10C990000000000000000000000000000000000097 +:10C9A0000000000000000000000000000000000087 +:10C9B0000000000000000000000000000000000077 +:10C9C0000000000000000000000000000000000067 +:10C9D0000000000000000000000000000000000057 +:10C9E0000000000000000000000000000000000047 +:10C9F0000000000000000000000000000000000037 +:10CA00000000000000000000000000000000000026 +:10CA10000000000000000000000000000000000016 +:10CA20000000000000000000000000000000000006 +:10CA300000000000000000000000000000000000F6 +:10CA400000000000000000000000000000000000E6 +:10CA500000000000000000000000000000000000D6 +:10CA600000000000000000000000000000000000C6 +:10CA700000000000000000000000000000000000B6 +:10CA800000000000000000000000000000000000A6 +:10CA90000000000000000000000000000000000096 +:10CAA0000000000000000000000000000000000086 +:10CAB0000000000000000000000000000000000076 +:10CAC0000000000000000000000000000000000066 +:10CAD0000000000000000000000000000000000056 +:10CAE0000000000000000000000000000000000046 +:10CAF0000000000000000000000000000000000036 +:10CB00000000000000000000000000000000000025 +:10CB10000000000000000000000000000000000015 +:10CB20000000000000000000000000000000000005 +:10CB300000000000000000000000000000000000F5 +:10CB400000000000000000000000000000000000E5 +:10CB500000000000000000000000000000000000D5 +:10CB600000000000000000000000000000000000C5 +:10CB700000000000000000000000000000000000B5 +:10CB800000000000000000000000000000000000A5 +:10CB90000000000000000000000000000000000095 +:10CBA0000000000000000000000000000000000085 +:10CBB0000000000000000000000000000000000075 +:10CBC0000000000000000000000000000000000065 +:10CBD0000000000000000000000000000000000055 +:10CBE0000000000000000000000000000000000045 +:10CBF0000000000000000000000000000000000035 +:10CC00000000000000000000000000000000000024 +:10CC10000000000000000000000000000000000014 +:10CC20000000000000000000000000000000000004 +:10CC300000000000000000000000000000000000F4 +:10CC400000000000000000000000000000000000E4 +:10CC500000000000000000000000000000000000D4 +:10CC600000000000000000000000000000000000C4 +:10CC700000000000000000000000000000000000B4 +:10CC800000000000000000000000000000000000A4 +:10CC90000000000000000000000000000000000094 +:10CCA0000000000000000000000000000000000084 +:10CCB0000000000000000000000000000000000074 +:10CCC0000000000000000000000000000000000064 +:10CCD0000000000000000000000000000000000054 +:10CCE0000000000000000000000000000000000044 +:10CCF0000000000000000000000000000000000034 +:10CD00000000000000000000000000000000000023 +:10CD10000000000000000000000000000000000013 +:10CD20000000000000000000000000000000000003 +:10CD300000000000000000000000000000000000F3 +:10CD400000000000000000000000000000000000E3 +:10CD500000000000000000000000000000000000D3 +:10CD600000000000000000000000000000000000C3 +:10CD700000000000000000000000000000000000B3 +:10CD800000000000000000000000000000000000A3 +:10CD90000000000000000000000000000000000093 +:10CDA0000000000000000000000000000000000083 +:10CDB0000000000000000000000000000000000073 +:10CDC0000000000000000000000000000000000063 +:10CDD0000000000000000000000000000000000053 +:10CDE0000000000000000000000000000000000043 +:10CDF0000000000000000000000000000000000033 +:10CE00000000000000000000000000000000000022 +:10CE10000000000000000000000000000000000012 +:10CE20000000000000000000000000000000000002 +:10CE300000000000000000000000000000000000F2 +:10CE400000000000000000000000000000000000E2 +:10CE500000000000000000000000000000000000D2 +:10CE600000000000000000000000000000000000C2 +:10CE700000000000000000000000000000000000B2 +:10CE800000000000000000000000000000000000A2 +:10CE90000000000000000000000000000000000092 +:10CEA0000000000000000000000000000000000082 +:10CEB0000000000000000000000000000000000072 +:10CEC0000000000000000000000000000000000062 +:10CED0000000000000000000000000000000000052 +:10CEE0000000000000000000000000000000000042 +:10CEF0000000000000000000000000000000000032 +:10CF00000000000000000000000000000000000021 +:10CF10000000000000000000000000000000000011 +:10CF20000000000000000000000000000000000001 +:10CF300000000000000000000000000000000000F1 +:10CF400000000000000000000000000000000000E1 +:10CF500000000000000000000000000000000000D1 +:10CF600000000000000000000000000000000000C1 +:10CF700000000000000000000000000000000000B1 +:10CF800000000000000000000000000000000000A1 +:10CF90000000000000000000000000000000000091 +:10CFA0000000000000000000000000000000000081 +:10CFB0000000000000000000000000000000000071 +:10CFC0000000000000000000000000000000000061 +:10CFD0000000000000000000000000000000000051 +:10CFE0000000000000000000000000000000000041 +:10CFF0000000000000000000000000000000000031 +:10D000000000000000000000000000000000000020 +:10D010000000000000000000000000000000000010 +:10D020000000000000000000000000000000000000 +:10D0300000000000000000000000000000000000F0 +:10D0400000000000000000000000000000000000E0 +:10D0500000000000000000000000000000000000D0 +:10D0600000000000000000000000000000000000C0 +:10D0700000000000000000000000000000000000B0 +:10D0800000000000000000000000000000000000A0 +:10D090000000000000000000000000000000000090 +:10D0A0000000000000000000000000000000000080 +:10D0B0000000000000000000000000000000000070 +:10D0C0000000000000000000000000000000000060 +:10D0D0000000000000000000000000000000000050 +:10D0E0000000000000000000000000000000000040 +:10D0F0000000000000000000000000000000000030 +:10D10000000000000000000000000000000000001F +:10D11000000000000000000000000000000000000F +:10D1200000000000000000000000000000000000FF +:10D1300000000000000000000000000000000000EF +:10D1400000000000000000000000000000000000DF +:10D1500000000000000000000000000000000000CF +:10D1600000000000000000000000000000000000BF +:10D1700000000000000000000000000000000000AF +:10D18000000000000000000000000000000000009F +:10D19000000000000000000000000000000000008F +:10D1A000000000000000000000000000000000007F +:10D1B000000000000000000000000000000000006F +:10D1C000000000000000000000000000000000005F +:10D1D000000000000000000000000000000000004F +:10D1E000000000000000000000000000000000003F +:10D1F000000000000000000000000000000000002F +:10D20000000000000000000000000000000000001E +:10D21000000000000000000000000000000000000E +:10D2200000000000000000000000000000000000FE +:10D2300000000000000000000000000000000000EE +:10D2400000000000000000000000000000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D29000000000000000000000000000000000008E +:10D2A000000000000000000000000000000000007E +:10D2B000000000000000000000000000000000006E +:10D2C000000000000000000000000000000000005E +:10D2D000000000000000000000000000000000004E +:10D2E000000000000000000000000000000000003E +:10D2F000000000000000000000000000000000002E +:10D30000000000000000000000000000000000001D +:10D31000000000000000000000000000000000000D +:10D3200000000000000000000000000000000000FD +:10D3300000000000000000000000000000000000ED +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000000000000000000088 +:10D8A0000000000000000000000000000000000078 +:10D8B0000000000000000000000000000000000068 +:10D8C0000000000000000000000000000000000058 +:10D8D0000000000000000000000000000000000048 +:10D8E0000000000000000000000000000000000038 +:10D8F0000000000000000000000000000000000028 +:10D900000000000000000000000000000000000017 +:10D910000000000000000000000000000000000007 +:10D9200000000000000000000000000000000000F7 +:10D9300000000000000000000000000000000000E7 +:10D9400000000000000000000000000000000000D7 +:10D9500000000000000000000000000000000000C7 +:10D9600000000000000000000000000000000000B7 +:10D9700000000000000000000000000000000000A7 +:10D980000000000000000000000000000000000097 +:10D990000000000000000000000000000000000087 +:10D9A0000000000000000000000000000000000077 +:10D9B0000000000000000000000000000000000067 +:10D9C0000000000000000000000000000000000057 +:10D9D0000000000000000000000000000000000047 +:10D9E0000000000000000000000000000000000037 +:10D9F0000000000000000000000000000000000027 +:10DA00000000000000000000000000000000000016 +:10DA100000000000000000000000000010000003F3 +:10DA2000000000000000000D0000000D3C02080096 +:10DA3000244275803C03080024637A28AC4000002F +:10DA40000043202B1480FFFD244200043C1D0800ED +:10DA500037BD7FFC03A0F0213C100800261031D810 +:10DA60003C1C0800279C75800E0010EF0000000091 +:10DA70000000000D30A5FFFF30C600FF27430180E6 +:10DA80008F4201B80440FFFE24020002AC64000093 +:10DA9000A4650008A066000AA062000B3C0210000A +:10DAA000AC67001803E00008AF4201B83C03600017 +:10DAB0008C624FF80440FFFE3C020200AC644FC091 +:10DAC000AC624FC43C02100003E00008AC624FF8A7 +:10DAD0009482000C2486001400A038210002130256 +:10DAE000000210800082402100C8102B1040005717 +:10DAF0000000000090C300002C620009504000515B +:10DB000090C20001000310803C03080024637534B8 +:10DB1000004310218C42000000400008000000007B +:10DB200090C300012402000A1462003A00000000C1 +:10DB3000010610232C42000A1440003624C60002BD +:10DB40008CE2000034420100ACE2000090C2000010 +:10DB500090C3000190C4000290C5000300031C00A4 +:10DB60000002160000431025000422000044102586 +:10DB70000045102524C60004ACE2000490C2000059 +:10DB800090C3000190C4000290C50003000216007B +:10DB900000031C000043102500042200004410254F +:10DBA0000045102524C600040A000CAAACE20008B7 +:10DBB00090C30001240200041462001624C600026F +:10DBC00090C2000090C400018CE30000000212002B +:10DBD000004410253463000424C60002ACE2000CAB +:10DBE0000A000CAAACE3000090C300012402000369 +:10DBF0001462000824C600028CE2000090C30000FA +:10DC000024C6000134420008A0E300100A000CAA58 +:10DC1000ACE2000003E000082402000190C3000110 +:10DC2000240200021062000224C40002010020212C +:10DC30000A000CAA008030210A000CAA24C60001A8 +:10DC400090C200010A000CAA00C2302103E00008C3 +:10DC50000000102127BDFFE8AFBF0014AFB00010D7 +:10DC60000E00130E00808021936200052403FFFE46 +:10DC700002002021004310248FBF00148FB0001039 +:10DC8000A36200050A00131727BD001827BDFFE88F +:10DC9000AFB00010AFBF00140E000F0E0080802147 +:10DCA0009362000024030050304200FF144300043C +:10DCB00024020100AF4201800A000D22020020214F +:10DCC000AF400180020020218FBF00148FB00010F0 +:10DCD0000A000FAD27BD001827BDFF80AFBE00783A +:10DCE000AFB70074AFB30064AFBF007CAFB60070D5 +:10DCF000AFB5006CAFB40068AFB20060AFB1005C0C +:10DD0000AFB000588F5001289363003F9362000525 +:10DD10000000F021307300FF0002102730420001A4 +:10DD20000000B82114400066AFA0005093420116D5 +:10DD300093430112304200FF306300FF0342202171 +:10DD400003431021244540008F82001C104000181E +:10DD5000249140008F4201043C0300010043102441 +:10DD600010400013000000008CA3000C8F620030F4 +:10DD7000146201B5240200018CA300108F62002CF4 +:10DD8000146201B1240200019762003A94834000BA +:10DD90003042FFFF146201AC240200019762003898 +:10DDA000962300023042FFFF146201A72402000103 +:10DDB00093620000304300FF24020020106200053F +:10DDC0002402005010620006000000000A000D6CE2 +:10DDD000000000000000000D0A000D75AFA000302B +:10DDE0003C1E080027DE75E80A000D75AFA0003064 +:10DDF0003C0208008C4200DC244200013C01080087 +:10DE0000AC2200DC0E0013D8000000000A000F0353 +:10DE10008FBF007C8F4201043C0300209234000D30 +:10DE2000004310240002202B00042140AFA4003046 +:10DE30008F4301043C020040006218241460000279 +:10DE4000348700400080382132820020AFA70030A4 +:10DE50001440000234E6008000E0302110C0000BC6 +:10DE6000AFA6003093C500088F67004C0200202148 +:10DE700000052B0034A5008130A5F0810E000C8D2B +:10DE800030C600FF0A000F00000000009362003E51 +:10DE9000304200401040000E24020004566200068A +:10DEA00024020012020020210E0014E6022030217C +:10DEB0000A000F038FBF007C1662000500000000FF +:10DEC0000E000D13000020210A000F038FBF007CFD +:10DED0009743011A9624000E9362003532850004A0 +:10DEE0003076FFFF00442004AFA400548E320004BB +:10DEF00010A000158E3500089362003E30420040AD +:10DF000010400007000000000E00142802402021ED +:10DF10001040000D000000000A000F00000000008B +:10DF20008F620044024210230440014500000000BB +:10DF30008F6200480242102304410141240400166C +:10DF40000A000E038FC200048F62004802421023B1 +:10DF500004400008000000003C0208008C42310030 +:10DF6000244200013C010800AC2231000A000EF5F9 +:10DF7000000000008F620040024210231840000998 +:10DF80002402000C3C0208008C423100329400FC58 +:10DF90000000B021244200013C010800AC22310005 +:10DFA0002402000CAFA200308F62004000522023F8 +:10DFB0001880000D02C4102A144001160000000051 +:10DFC0001496000602C410233A8200013042000178 +:10DFD000144001100000000002C4102302449021EC +:10DFE0000A000DEB3056FFFF0000202132820002B4 +:10DFF0001040001A328200109362003E304200400E +:10E00000504000118FC200040E00130E02002021A8 +:10E0100024020018A362003F936200052403FFFE60 +:10E0200002002021004310240E001317A3620005F4 +:10E0300024040039000028210E00141124060018C1 +:10E040000A000F0224020001240400170040F8090E +:10E05000000000000A000F0224020001104000F836 +:10E06000000000008F63004C8F62005402A2102356 +:10E070001C4000F302A31023044200010060A82109 +:10E08000AFA40018AFB20010AFB600149342012045 +:10E090008F6500409763003C304200FF034210212F +:10E0A000004410218FA400543063FFFF244240003D +:10E0B0000083182B8FA40030AFA20020AFA500284A +:10E0C00000832025AFA40030AFA50024AFA0002C12 +:10E0D000AFB500349362003E30420008504000115A +:10E0E0008FC200000220202127A500380E000CA4BA +:10E0F000AFA000385440000B8FC200008FA2003840 +:10E1000030420100504000078FC200008FA3003C46 +:10E110008F6200600062102304430001AF6300605F +:10E120008FC200000040F80927A400108FA2003021 +:10E130003042000254400001329400FE9362003EDF +:10E1400030420040104000378FA300148F6200540B +:10E1500016A2001A3282000124020014126200107A +:10E160002A62001510400006240200162402000C4A +:10E1700012620007328200010A000E5F00000000F8 +:10E1800012620005328200010A000E5F00000000EA +:10E190000A000E5A2417000E0A000E5A2417001007 +:10E1A0000A000E5E24170012936200232403FFBDB1 +:10E1B00000431024A36200233282000110400019A2 +:10E1C0008FA300142402000C1262000E2A62000DBC +:10E1D000104000062402000E2402000A126200070A +:10E1E0008FA200240A000E77244200011262000868 +:10E1F0008FA200240A000E77244200010A000E7547 +:10E20000241700082402000E16E20002241700164C +:10E21000241700108FA2002424420001AFA2002482 +:10E220008FA300148FA200248F730040004310219D +:10E23000AF6200408FA20054936400368F630040A9 +:10E2400002A288213402FFFF00821004006218211C +:10E25000AF6300488FA6003030C200081040000EA7 +:10E26000000000008F6200581622000430C600FF34 +:10E270009742011A5040000134C6001093C50008AF +:10E280008FA700340200202100052B0034A5008058 +:10E290000E000C8D30A5F0808F62004000531023DB +:10E2A000184000178FA200183C0208008C423198D9 +:10E2B00030420010104000092402000197620068FB +:10E2C0001440000624020001A76200689742007A09 +:10E2D0002442000A0A000EBBA7620012A7620012C5 +:10E2E0000E00130E020020219362007D2403000122 +:10E2F00002002021344200010A000EB9AFA30050F1 +:10E300001840000A000000000E00130E0200202139 +:10E310009362007D2403000102002021AFA300507E +:10E32000344200040E001317A362007D9362003E86 +:10E33000304200401440000C328200011040000ABC +:10E34000000000008F6300408FC200042404001806 +:10E35000246300010040F809AF6300408FA2003041 +:10E360000A000F02304200048F6200581051001062 +:10E37000000000008F620018024210231C400008B9 +:10E38000240400018F6200181642000900000000FA +:10E390008F62001C02A21023044000050000000050 +:10E3A000AF710058AFA40050AF720018AF75001CD9 +:10E3B00012E0000B8FA200500E00130E020020216D +:10E3C000A377003F0E0013170200202102E0302146 +:10E3D000240400370E001411000028218FA20050E1 +:10E3E00010400003000000000E000C9B02002021E2 +:10E3F00012C00005000018218FA200303042000436 +:10E400005040001100601021240300010A000F0297 +:10E41000006010210E00130E020020219362007D87 +:10E4200002002021344200040E001317A362007D75 +:10E430000E000C9B020020210A000F0224020001A2 +:10E44000AF400044240200018FBF007C8FBE0078E3 +:10E450008FB700748FB600708FB5006C8FB40068F2 +:10E460008FB300648FB200608FB1005C8FB0005832 +:10E4700003E0000827BD00808F4201B80440FFFE82 +:10E4800024020800AF4201B803E0000800000000C9 +:10E4900030A5FFFF30C6FFFF8F4201B80440FFFEEA +:10E4A0003C020008AF44018003421021AF44002029 +:10E4B000944200483044FFFF1080001924020003FA +:10E4C00024A200120082102B104000152402000329 +:10E4D000934201202403001AA343018B304200FF22 +:10E4E0002447FFFE8F8200000087182B386300014D +:10E4F0000002138200431024104000058F830004A3 +:10E5000034620001A74701940A000F39AF8200046A +:10E510002402FFFE006210240A000F39AF820004BB +:10E52000A342018B24020002A742018C8F820000CB +:10E530008F840004A745018EA74201908F82000CB2 +:10E5400030838000AF4201A8A74601881060000E0A +:10E550008F82000493420116304200FC24420004E2 +:10E56000005A10218C4240003042FFFF1440000648 +:10E570008F8200043C02FFFF34427FFF00821024A0 +:10E58000AF8200048F8200042403BFFF978400023F +:10E5900000431024A74201A69742010C0002140078 +:10E5A00000441025AF4201AC3C021000AF4201B85C +:10E5B00003E00008000000008F4700709342011242 +:10E5C0008F83000027BDFFF0304200FF0002288249 +:10E5D00030620100000030211040004324A40003F9 +:10E5E00030624000104000103062200000041080B3 +:10E5F000005A10218C43400024A400040004108021 +:10E60000AFA30000005A10218C424000AFA20004CA +:10E6100093420116304200FC005A10218C42400007 +:10E620000A000F86AFA200081040002F0000302122 +:10E6300000041080005A10218C43400024A40004E0 +:10E6400000041080AFA30000005A10218C4240004B +:10E65000AFA00008AFA200048FA80008000030217E +:10E6600000002021240A00083C0908002529010097 +:10E6700003A41021148A000300042A001100000AD8 +:10E680000000000090420000248400012C83000C54 +:10E6900000A2102100021080004910218C420000CD +:10E6A0001460FFF300C230263C0408008C8431045F +:10E6B0008F4200702C83002010600009004738232F +:10E6C0003C0308002463310800041080004310213B +:10E6D00024830001AC4700003C010800AC23310456 +:10E6E000AF86000C2406000100C0102103E00008E2 +:10E6F00027BD00103C0208008C42003827BDFFD027 +:10E70000AFB60028AFB40020AFB20018AFBF002CE6 +:10E71000AFB50024AFB3001CAFB10014AFB0001010 +:10E72000000090213C16080026D600381440000254 +:10E730002454FFFF0000A0219742010E8F840000A7 +:10E740003042FFFF308340001060000A2453000471 +:10E750003C020020008210245040000730828000DC +:10E760008F8200042403BFFF008318240A000FD700 +:10E7700034421000308280001040000A3C02002029 +:10E7800000821024104000078F8200043C03FFFF2A +:10E7900034637FFF0083182434428000AF8200047A +:10E7A000AF8300000E000F5E000000001440000761 +:10E7B000000000009743011E9742011C3063FFFFD9 +:10E7C0000002140000621825AF83000C9742010C70 +:10E7D0008F4340003046FFFF3402FFFF1462000306 +:10E7E000000000000A000FEF241200208F424000BA +:10E7F0003042010054400001241200108F840000B8 +:10E800003082100050400014365200013082002047 +:10E810001440000B3C021000008210245040000EF7 +:10E82000365200013C030E003C020DFF0083182409 +:10E830003442FFFF0043102B5040000736520001C6 +:10E840003C0208008C42002C244200013C010800DC +:10E85000AC22002C365200053C0508008CA5003483 +:10E8600054A000408F8400008F8200105440003D6F +:10E870008F8400008F8200043042400054400039F1 +:10E880008F8400003C021F01008210243C03100012 +:10E89000144300348F84000030C202001440003260 +:10E8A0003C0200013265FFFF364600028F4201B88C +:10E8B0000440FFFE3C020008AF40018003421021EB +:10E8C000944200483043FFFF10600019AF830008F6 +:10E8D00024A200120062102B104000162402000334 +:10E8E000934201202403001AA343018B304200FF0E +:10E8F0002443FFFE8F820000304240001040000899 +:10E900008F8200048F8200080043102B1440000403 +:10E910008F820004A74301940A00103A3442000198 +:10E920002403FFFE004310240A00103EAF820004BF +:10E9300024020003A342018B8F8300042402BFFF43 +:10E940000062182424020002A742018C8F8200007A +:10E95000A745018EA7460188A74301A60A0010D942 +:10E96000A74201903C020001008210241040000BDD +:10E970003C0210003C0208008C4200D89745010E72 +:10E98000240400802442000130A5FFFF3C01080060 +:10E99000AC2200D80A0010E22406000300821024F2 +:10E9A00010400041000000003C0208008C42003092 +:10E9B0001040000C8F8200043042400010400009DB +:10E9C0003C030F00008318243C0201000043102B7D +:10E9D00014400004364600023265FFFF0A0010E2D0 +:10E9E0002404008010A0000D308201001040000BB4 +:10E9F0003C020F00008210243C0302001043000779 +:10EA00008F82000C00541024005610219042000404 +:10EA1000244200040A001097000221C000000000F8 +:10EA20008F8600003C0508008CA500D00006160269 +:10EA30003050000F38A200012C4200012E03000CC0 +:10EA40000043102414400015001021C02602FFFCD2 +:10EA50002C420004544000110000202138A2000282 +:10EA60002C42000100431024104000030006124213 +:10EA70000A001097000020210010182B00431024DA +:10EA800050400006001021C0000020213265FFFF29 +:10EA90000E000F143246FFFB001021C03265FFFF4D +:10EAA0000A0010E2364600028F4240003C11080086 +:10EAB0008E310024304201001040003E322200011D +:10EAC0000220802110A00014325500043082010081 +:10EAD00010400012240200013C020F0000821024AA +:10EAE0003C0302001043000C8F82000C02403021D6 +:10EAF0003265FFFF0054102400561021904400049A +:10EB00003252FFFB248400040E000F14000421C0C5 +:10EB10002402FFFE022280242402000116020007C4 +:10EB2000320200013242000450400001365200021D +:10EB30003265FFFF0A0010E102403021104000075B +:10EB40003202000402403021000020210E000F1488 +:10EB50003265FFFF3252FFFB320200041040000713 +:10EB60008F82000030420800104000043265FFFF31 +:10EB7000024030210E000F142404010016A00015DD +:10EB80008FBF002C274301808F4201B80440FFFE55 +:10EB900024022000A462000824020002A062000BEC +:10EBA000A46000103C021000AF4201B80A0010E55A +:10EBB0008FBF002C104000078FBF002C3265FFFF75 +:10EBC00036460002000020210E000F140000000055 +:10EBD0008FBF002C8FB600288FB500248FB4002083 +:10EBE0008FB3001C8FB200188FB100148FB00010CB +:10EBF0000000102103E0000827BD003027BDFFC83A +:10EC0000AFB000103C04600CAFBF0030AFB7002CB9 +:10EC1000AFB60028AFB50024AFB40020AFB3001CDE +:10EC2000AFB20018AFB100148C8250002403FF7FF4 +:10EC30003C1A8000004310243442380CAC8250004F +:10EC4000240200033C106000AF4200088E02080856 +:10EC50003C1B80083C010800AC2000203042FFF043 +:10EC6000384200102C4200010E001C46AF82001CEE +:10EC70003C04FFFF3C020400348308063442000CCD +:10EC8000AE021948AE03194C3C0560168E0219807D +:10EC90008CA300003442020000641824AE021980E4 +:10ECA0003C0253531462000334A47C008CA2000481 +:10ECB000005020218C82007C8C830078AF82001869 +:10ECC000AF8300143C028000344200708C4300008B +:10ECD00000403821AF830020006030218CE8000024 +:10ECE0003C0508008CA500FC3C0408008C8400F85E +:10ECF000010630230000102100A6282100A6302B99 +:10ED000000822021008620213C010800AC2500FC67 +:10ED10003C010800AC2400F88F56000032C200030A +:10ED20001040FFEE010030218CE600003C05080099 +:10ED30008CA500FC3C0408008C8400F800C830233B +:10ED400000A628210000102100A6302B00822021DF +:10ED50000086202132C700013C010800AC2500FCE0 +:10ED6000AF8800203C010800AC2400F810E0016BE3 +:10ED700032C200028F4301283C02000803421021E6 +:10ED8000AF4300208F4301048F44010094420048A8 +:10ED9000AF830000AF8400043042FFFF0E000F0E6F +:10EDA000AF8200083C0208008C4200C010400008FE +:10EDB0008F8400003C0208008C4200C42442000101 +:10EDC0003C010800AC2200C40A0012AF00000000A1 +:10EDD0003C02001000821024144001358F8300048F +:10EDE0003C0208008C4200203C0308008C63003881 +:10EDF00000009021244200013C010800AC220020C8 +:10EE00003C17080026F70038146000022474FFFF46 +:10EE10000000A0219742010E308340003042FFFFE6 +:10EE20001060000A245300043C02002000821024D9 +:10EE300050400007308280008F8200042403BFFF0F +:10EE4000008318240A00118D3442100030828000A3 +:10EE50001040000A3C0200200082102410400007ED +:10EE60008F8200043C03FFFF34637FFF008318247C +:10EE700034428000AF820004AF8300000E000F5EBA +:10EE80000000000014400007000000009743011E2E +:10EE90009742011C3063FFFF000214000062182536 +:10EEA000AF83000C9742010C8F4340003046FFFFB8 +:10EEB0003402FFFF14620003000000000A0011A5E5 +:10EEC000241200208F4240003042010054400001D3 +:10EED000241200108F840000308210005040001473 +:10EEE00036520001308200201440000B3C0210001A +:10EEF000008210245040000E365200013C030E00E8 +:10EF00003C020DFF008318243442FFFF0043102B06 +:10EF100050400007365200013C0208008C42002C91 +:10EF2000244200013C010800AC22002C36520005AE +:10EF30003C0508008CA5003454A000408F840000DC +:10EF40008F8200105440003D8F8400008F820004A7 +:10EF500030424000544000398F8400003C021F01C1 +:10EF6000008210243C031000144300348F840000FE +:10EF700030C20200144000323C0200013265FFFF43 +:10EF8000364600028F4201B80440FFFE3C020008F2 +:10EF9000AF40018003421021944200483043FFFFFC +:10EFA00010600019AF83000824A200120062102B29 +:10EFB0001040001624020003934201202403001A8B +:10EFC000A343018B304200FF2443FFFE8F820000E9 +:10EFD00030424000104000088F8200048F820008F9 +:10EFE0000043102B144000048F820004A7430194B7 +:10EFF0000A0011F0344200012403FFFE00431024F4 +:10F000000A0011F4AF82000424020003A342018B22 +:10F010008F8300042402BFFF006218242402000230 +:10F02000A742018C8F820000A745018EA746018868 +:10F03000A74301A60A00128FA74201903C020001DB +:10F04000008210245040000B3C0210003C020800DB +:10F050008C4200D89745010E240400802442000110 +:10F0600030A5FFFF3C010800AC2200D80A0012982E +:10F07000240600030082102410400041000000001C +:10F080003C0208008C4200301040000C8F820004CB +:10F0900030424000104000093C030F000083182458 +:10F0A0003C0201000043102B1440000436460002CD +:10F0B0003265FFFF0A0012982404008010A0000DA2 +:10F0C000308201001040000B3C020F00008210242F +:10F0D0003C030200104300078F82000C00541024F0 +:10F0E0000057102190420004244200040A00124DEF +:10F0F000000221C0000000008F8600003C050800CF +:10F100008CA500D0000616023050000F38A2000176 +:10F110002C4200012E03000C004310241440001563 +:10F12000001021C02602FFFC2C42000454400011B4 +:10F130000000202138A200022C42000100431024CC +:10F1400050400003000612420A00124D0000202128 +:10F150000010182B0043102450400006001021C05E +:10F16000000020213265FFFF0E000F143246FFFB26 +:10F17000001021C03265FFFF0A00129836460002D7 +:10F180008F4240003C1108008E31002430420100C3 +:10F190001040003E322200010220802110A0001405 +:10F1A0003255000430820100104000122402000198 +:10F1B0003C020F00008210243C0302001043000CAC +:10F1C0008F82000C024030213265FFFF0054102472 +:10F1D00000571021904400043252FFFB24840004A5 +:10F1E0000E000F14000421C02402FFFE022280241E +:10F1F000240200011602000732020001324200041C +:10F2000050400001365200023265FFFF0A0012979B +:10F210000240302110400007320200040240302139 +:10F22000000020210E000F143265FFFF3252FFFB59 +:10F2300032020004104000078F82000030420800B4 +:10F24000104000043265FFFF024030210E000F1411 +:10F250002404010016A0002E3C0240002743018038 +:10F260008F4201B80440FFFE24022000A46200087F +:10F2700024020002A062000BA46000103C021000F7 +:10F28000AF4201B80A0012B43C02400050400020D6 +:10F290003C0240003265FFFF36460002000020219C +:10F2A0000E000F14000000000A0012B43C024000DF +:10F2B0002402BFFF0062102410400008000000007C +:10F2C000240287FF00621024144000083C02006002 +:10F2D0000082102410400005000000000E000D26E2 +:10F2E000000000000A0012AD000000000E0012F83D +:10F2F00000000000104000063C0240008F43012443 +:10F300003C026020AC430014000000003C024000BE +:10F31000AF4201380000000032C200021040FE6A15 +:10F320003C0280008F4201403C044000AF4200207C +:10F330008F4301483C027000006218241064002DC5 +:10F34000000000000083102B144000063C02600007 +:10F350003C022000106200073C0240000A0012F448 +:10F360000000000010620027000000000A0012F4F4 +:10F370003C0240008F4201482403000400021402B2 +:10F38000304200FF1443000B274401808F430140AB +:10F390008F4201B80440FFFE2402001CAC83000031 +:10F3A000A082000B3C021000AF4201B80A0012F428 +:10F3B0003C0240008F4201B80440FFFE0000000004 +:10F3C0008F42014800021402A482000824020002B5 +:10F3D000A082000B8F420148A48200108F4201449A +:10F3E000AC8200243C021000AF4201B80A0012F4C3 +:10F3F0003C0240000E00131C000000000A0012F442 +:10F400003C0240000E001C53000000003C02400083 +:10F41000AF420178000000000A0011223C02800087 +:10F420008F4201003042003E1440001124020001CE +:10F43000AF4000488F420100304207C01040000535 +:10F4400000000000AF40004CAF40005003E0000857 +:10F4500024020001AF400054AF4000408F42010041 +:10F460003042380054400001AF4000442402000103 +:10F4700003E00008000000003C029000344200015C +:10F4800000822025AF4400208F4200200440FFFE70 +:10F490000000000003E00008000000003C028000C3 +:10F4A000344200010082202503E00008AF44002020 +:10F4B00027BDFFE0AFB20018AFBF001CAFB1001412 +:10F4C000AFB000108F5001408F5101483C028000C6 +:10F4D0000011940202222024324300FF2402000E75 +:10F4E0001062008A2862000F104000122862003764 +:10F4F000240200061062003B28620007104000074B +:10F50000240200091060001A240200011062002584 +:10F51000000000000A0013D1000000001062007B10 +:10F520002402000B1062005B3222FFFF0A0013D19D +:10F530000000000010400008240200382862003556 +:10F54000104000802402001F1062007E00000000B6 +:10F550000A0013D1000000001062007A240200802B +:10F5600010620042000000000A0013D100000000F9 +:10F570008F4201B80440FFFE24020001AF50018019 +:10F58000AF400184A7520188A342018A24020002ED +:10F59000A342018BA75101908F4201440A0013CC72 +:10F5A000AF4201A41080000A240200023C010800BE +:10F5B000A02275D83C010800AC3075E08F420144B0 +:10F5C0003C010800AC2275DC0A0013D38FBF001C7D +:10F5D0008F4201B80440FFFE240200020A0013B665 +:10F5E000000000008F4201B80440FFFE0000000050 +:10F5F000AF5001803C020800904275D810400003D3 +:10F60000000018213C0308008C6375E0AF430184BF +:10F61000A75201883C020800904275D800001821CA +:10F6200034420001A342018A24020002A342018B5A +:10F63000A75101908F420144AF4201A43C0208004F +:10F64000904275D8104000033C0210003C030800B3 +:10F650008C6375DCAF4301A8AF4201B83C010800E0 +:10F66000A02075D80A0013D38FBF001C8F4201B8A9 +:10F670000440FFFE24020002A342018BA75201882E +:10F68000A75101908F420144A74201920A0013CE74 +:10F690003C0210001440001D0000000093620005B1 +:10F6A0003042000414400037000000000E00130E2A +:10F6B0000200202193620005020020213442000450 +:10F6C0000E001317A3620005936200053042000488 +:10F6D00014400002000000000000000D93620000D2 +:10F6E00024030020304200FF144300080000000003 +:10F6F0008F4201B80440FFFE24020005AF50018094 +:10F70000A342018B3C021000AF4201B88F4201B806 +:10F710000440FFFE24020002AF400180AF5001848C +:10F72000A7520188A342018AA342018BA7510190ED +:10F73000AF4001A48F420144AF4201A80A0013CE9A +:10F740003C0210008F4201B80440FFFE2402000179 +:10F75000AF500180AF400184A7520188A342018AC3 +:10F7600024020002A342018BA7510190AF4001A4E3 +:10F77000AF4001A83C021000AF4201B80A0013D309 +:10F780008FBF001C0000000D8FBF001C8FB200183F +:10F790008FB100148FB0001003E0000827BD0020D7 +:10F7A00027BDFFE8AFBF00100E000F0E00000000E5 +:10F7B000AF4001808FBF0010000020210A000FAD74 +:10F7C00027BD00183084FFFF30A5FFFF000018217F +:10F7D000108000070000000030820001104000028D +:10F7E00000042042006518210A0013E400052840A7 +:10F7F00003E000080060102110C0000624C6FFFFCF +:10F800008CA2000024A50004AC8200000A0013EEC4 +:10F810002484000403E000080000000010A0000899 +:10F8200024A3FFFFAC8600000000000000000000E1 +:10F830002402FFFF2463FFFF1462FFFA2484000404 +:10F8400003E000080000000027BDFFE8AFBF001480 +:10F85000AFB000100E00130E008080219362007D77 +:10F8600002002021344200200E001317A362007D05 +:10F87000020020218FBF00148FB000100A000C9BE3 +:10F8800027BD0018308300FF30A500FF30C600FF01 +:10F89000274701808F4201B80440FFFE00000000AE +:10F8A0008F42012834634000ACE2000024020001D2 +:10F8B000ACE00004A4E30008A0E2000A2402000275 +:10F8C000A0E2000B3C021000A4E50010ACE0002414 +:10F8D000ACE00028A4E6001203E00008AF4201B843 +:10F8E00027BDFFE8AFBF00109362003F2403001262 +:10F8F000304200FF1043000D008030218F62004431 +:10F90000008210230440000A8FBF00108F6200485D +:10F91000240400390000282100C2102304410004FF +:10F92000240600120E001411000000008FBF00100A +:10F930002402000103E0000827BD001827BDFFC80E +:10F94000AFB1002C00A08821AFB2003027A5001075 +:10F950000080902102202021AFBF0034AFB00028EA +:10F960000E000CA4AFA0001010400009024020219E +:10F970008E220008AF6200840E001402AF600040C7 +:10F98000240400382405008D0A0014DD240600122A +:10F990009362003E304200081040000F8FA200101A +:10F9A00030420100104000078FA300148F620060F6 +:10F9B0000062102304430008AF6300600A0014666D +:10F9C00000000000AF6000609362003E2403FFF778 +:10F9D00000431024A362003E9362003E30420008C0 +:10F9E000144000022406000300003021936200341A +:10F9F000936300378F640084304200FF306300FF60 +:10FA000000661821000318800043282100A4202B41 +:10FA10001080000B000000009763003C8F620084A0 +:10FA20003063FFFF004510230062182B14600004B0 +:10FA3000000000008F6200840A00148200458023C9 +:10FA40009762003C3050FFFF8FA30010306200042B +:10FA500010400004000628808FA2001C0A00148AAF +:10FA60000202102B2E02021850400003240202183A +:10FA70000A00149302051023306300041060000391 +:10FA8000004510238FA2001C004510230040802158 +:10FA90002C42008054400001241000800E00130E00 +:10FAA0000240202124020001AF62000C9362003E5C +:10FAB000001020403042007FA362003E8E220004EE +:10FAC00024420001AF620040A770003C8F620050EA +:10FAD0009623000E00431021AF6200588F62005041 +:10FAE00000441021AF62005C8E220004AF62001857 +:10FAF0008E220008AF62001C8FA200103042000866 +:10FB00005440000A93A20020A3600036936200369E +:10FB10002403FFDFA36200359362003E00431024FC +:10FB2000A362003E0A0014BD8E220008A3620035C5 +:10FB30008E220008AF62004C8F6200248F63004069 +:10FB400000431021AF62004893620000240300507C +:10FB5000304200FF144300122403FF803C020800DF +:10FB60008C4231A00242102100431024AF420028F1 +:10FB70003C0208008C4231A08E2400083C03000C9B +:10FB8000024210213042007F034210210043102125 +:10FB9000AC4400D88E230008AF820028AC4300DCC0 +:10FBA0000E001317024020212404003800002821F1 +:10FBB0002406000A0E001411000000008FBF00345C +:10FBC0008FB200308FB1002C8FB0002824020001CA +:10FBD00003E0000827BD003827BDFFE8AFBF0010D5 +:10FBE00090C7000D00C0282130E6001010C0000AA8 +:10FBF00030E200058CA300088F62005410620006FA +:10FC000030E20005144000178FBF001000002021D3 +:10FC10000A000D1327BD00181040000D30E300123C +:10FC200010C000108FBF00108CA300088F6200541A +:10FC30001462000D24020001240400382405008D04 +:10FC40000E001411240600120A0015098FBF0010BF +:10FC500024020012146200038FBF00100A00143F38 +:10FC600027BD00182402000103E0000827BD00188A +:10FC700027BDFFF827420180AFA20000308A00FFB5 +:10FC80008F4201B80440FFFE000000008F460128AB +:10FC90003C0208008C4231A02403FF80AF86005054 +:10FCA00000C2102100431024AF4200243C0208008F +:10FCB0008C4231A08FA900008FA8000000C2102143 +:10FCC0003042007F034218213C02000A00621821E2 +:10FCD000946400D48FA700008FA5000024020002C6 +:10FCE000AF830028A0A2000B8FA300003542600064 +:10FCF0003084FFFFA4E200083C021000AD260000A3 +:10FD0000AD040004AC60002427BD0008AF4201B878 +:10FD100003E00008240200018C8200048F83002885 +:10FD200000451023AC820004906200633042007FE3 +:10FD3000A06200638C820020938300308F850028AE +:10FD400034420002AF830044A7800042AC8200200E +:10FD5000A4A000E490A200632403FFBF004310248A +:10FD600003E00008A0A20063274301808F4201B88E +:10FD70000440FFFE8F820050AC6200008F420124DD +:10FD8000AC62000424026083A46200082402000222 +:10FD9000A062000B3C02100003E00008AF4201B873 +:10FDA0008F880044938200308F8300283C0708002E +:10FDB00024E779F400481023304200FF304900FC6A +:10FDC000246500888F860048304A0003112000090E +:10FDD00000002021248200048CA30000304400FF96 +:10FDE0000089102AACE3000024A500041440FFF9A8 +:10FDF00024E70004114000090000202124820001B2 +:10FE000090A30000304400FF008A102BA0E3000004 +:10FE100024A500011440FFF924E7000130C20003CB +:10FE2000144000048F850044310200031040000D8F +:10FE30000000000010A00009000020212482000121 +:10FE400090C30000304400FF0085102BA0E30000A9 +:10FE500024C600011440FFF924E7000103E0000874 +:10FE6000000000001100FFFD00002021248200049A +:10FE70008CC30000304400FF0088102BACE300006E +:10FE800024C600041440FFF924E7000403E000083E +:10FE9000000000008F8300449382003030C600FFD2 +:10FEA00030A500FF00431023304300FF8F8200285D +:10FEB000008038210043102114C00002244800882B +:10FEC0000083382130E200031440000530A2000313 +:10FED00014400003306200031040000D00000000D9 +:10FEE00010A00009000020212482000190E30000FE +:10FEF000304400FF0085102BA103000024E700011F +:10FF00001440FFF92508000103E00008000000008C +:10FF100010A0FFFD00002021248200048CE30000DB +:10FF2000304400FF0085102BAD03000024E70004DF +:10FF30001440FFF92508000403E000080000000059 +:10FF400027BDFFF82402FFFFAFA200000080382188 +:10FF50002405002F3C090800252975F4240800FF1A +:10FF60002406FFFF90E2000024A3FFFF0006220208 +:10FF700000C21026304200FF00021080004910210C +:10FF80008C420000306500FF24E7000114A8FFF553 +:10FF90000082302600061027AFA20004AFA20000A6 +:10FFA0000000282127A6000400C510239044000368 +:10FFB00024A2000100BD1821304500FF2CA200043E +:10FFC0001440FFF9A06400008FA2000003E00008C5 +:10FFD00027BD00080080482130AAFFFF30C600FF7F +:10FFE00030E7FFFF274801808F4201B80440FFFE41 +:10FFF0008F820050AD0200008F420124AD02000448 +:020000040001F9 +:100000008D220020A5070008A102000A2402001684 +:10001000A102000B934301208D2200088D240004CF +:10002000306300FF004310219783004200441021F9 +:100030008D250024004310233C0308008C6331A06D +:100040008F840028A502000C246300E82402FFFF2F +:10005000A50A000EA5030010A5060012AD050018A4 +:10006000AD020024948201142403FFF73042FFFF05 +:10007000AD0200288C820118AD02002C3C02100059 +:10008000AD000030AF4201B88D22002000431024A3 +:1000900003E00008AD2200208F82002830E7FFFF38 +:1000A00000804821904200D330A5FFFF30C600FFFA +:1000B0000002110030420F0000E23825274801807D +:1000C0008F4201B80440FFFE8F820050AD02000055 +:1000D0008F420124AD0200048D220020A5070008F4 +:1000E000A102000A24020017A102000B9343012081 +:1000F0008D2200088D240004306300FF004310218E +:1001000097830042004410218F840028004310236D +:100110003C0308008C6331A0A502000CA505000E6D +:10012000246300E8A5030010A5060012AD0000142A +:100130008D220024AD0200188C82005CAD02001CF0 +:100140008C820058AD0200202402FFFFAD02002483 +:10015000948200E63042FFFFAD02002894820060E6 +:10016000948300BE30427FFF3063FFFF0002120025 +:1001700000431021AD02002C3C021000AD00003005 +:10018000AF4201B8948200BE2403FFF700A2102101 +:10019000A48200BE8D2200200043102403E000084A +:1001A000AD220020274301808F4201B80440FFFEAA +:1001B00024020018AC640000A062000B8F820028AB +:1001C000944200E6A46200103C021000AC600030D3 +:1001D00003E00008AF4201B8274301808F4201B815 +:1001E0000440FFFE8F82002C9442001C3042FFFF2F +:1001F000000211C0AC62000024020019A062000BD2 +:100200003C021000AC60003003E00008AF4201B8CF +:100210008F87003430C300FF8F4201B80440FFFED7 +:100220008F82005034636000ACA200009382004CC7 +:10023000A0A200058CE20010A4A20006A4A300085E +:100240008C8200202403FFF7A0A2000A24020002EF +:10025000A0A2000B8CE20000ACA200108CE2000413 +:10026000ACA200148CE2001CACA200248CE20020A2 +:10027000ACA200288CE2002CACA2002C8C820024C2 +:10028000ACA200183C021000AF4201B88C820020E2 +:100290000043102403E00008AC8200209382004C4D +:1002A0002403000127BDFFE8004330042C42002056 +:1002B000AFB00010AFBF00142410FFFE10400005C7 +:1002C000274501803C0208008C4231900A0016A8A4 +:1002D000004610243C0208008C4231940046102451 +:1002E00014400007240600848F8300282410FFFF99 +:1002F000906200623042000F34420040A06200620F +:100300000E00167400000000020010218FBF0014C0 +:100310008FB0001003E0000827BD00188F83002C69 +:1003200027BDFFE0AFB20018AFB10014AFB00010AE +:10033000AFBF001C9062000D00A0902130D100FFE3 +:100340003042007FA062000D8F8500288E43001888 +:10035000008080218CA2007C146200052402000E23 +:1003600090A20063344200200A0016D1A0A20063CC +:100370000E001697A382004C2403FFFF1043004792 +:100380002404FFFF52200045000020218E4300007E +:100390003C02001000621024504000043C0200089F +:1003A000020020210A0016E0240200150062102439 +:1003B000504000098E450000020020212402001454 +:1003C0000E001697A382004C2403FFFF1043003356 +:1003D0002404FFFF8E4500003C02000200A210240E +:1003E000104000163C0200048F86002C8CC20014C2 +:1003F0008CC300108CC40014004310230044102B45 +:1004000050400005020020218E43002C8CC20010B9 +:1004100010620003020020210A00171124020012BA +:100420003C02000400A210245040001C00002021C7 +:10043000020020210A0017112402001300A2102438 +:10044000104000068F83002C8C6200105040001377 +:10045000000020210A00170B020020218C620010EE +:10046000504000048E42002C020020210A00171187 +:100470002402001150400009000020210200202128 +:10048000240200170E001697A382004C2403FFFFDE +:10049000104300022404FFFF000020218FBF001C36 +:1004A0008FB200188FB100148FB00010008010219F +:1004B00003E0000827BD00209383003027BDFFE044 +:1004C00024020034AFB20018AFB10014AFBF001C5B +:1004D000AFB00010008088211462000C00A09021B1 +:1004E0008F8400340E0015C08C900030120200077B +:1004F00024020005022020210E001697A382004C42 +:100500002403FFFF104300602404FFFF9242000415 +:10051000104000098F820028022020212402000CB4 +:100520000E001697A382004C2403FFFF10430056D1 +:100530002404FFFF8F820028A38000248E43000440 +:100540008C4400803C0200FF3442FFFF006218240C +:100550000083202B10800008AF83003C0220202164 +:10056000240200190E001697A382004C2403FFFFFB +:10057000104300452404FFFF978200428F87004408 +:100580008F85003C0047202310A0003AA78400423A +:100590008F86002830A200030002102390C300BC05 +:1005A0003050000300B02821000318823071000190 +:1005B0000011108000A228213C0308008C6331A0A8 +:1005C0008F8200503084FFFF0085202B00431021D4 +:1005D00010800010244200888F8400341082000DA7 +:1005E0003C033F018E420000004310243C032500E1 +:1005F0001443000630E500FF8C820000ACC2008886 +:100600008C8200100A001775ACC200980E00159578 +:1006100000003021938200248F8500288F830048BA +:10062000020238218F820044A387002494A400E4AE +:10063000006218218F82003C34841000AF83004890 +:1006400000503021A4A400E41220000EAF86004424 +:1006500024E20004A382002494A200E424C3000442 +:10066000AF83004434422000A4A200E40A001792A1 +:10067000000020218F820048AF80004400471021F5 +:10068000AF820048000020218FBF001C8FB20018ED +:100690008FB100148FB000100080102103E000081B +:1006A00027BD00208F86002827BDFFE8AFBF0014BC +:1006B000AFB0001090C2006330420020104000082C +:1006C00030A500FF8CC2007C2403FFDF2442000120 +:1006D000ACC2007C90C2006300431024A0C200633F +:1006E00010A000238F8300282750018002002821BA +:1006F0000E001674240600828F8200289042006348 +:100700003042004050400019A380004C8F830034D9 +:100710008F4201B80440FFFE8F820050AE020000FD +:1007200024026082A602000824020002A202000B3A +:100730008C620008AE0200108C62000CAE02001445 +:100740008C620014AE0200188C620018AE02002405 +:100750008C620024AE0200288C620028AE02002CBD +:100760003C021000AF4201B8A380004C8F830028E8 +:100770008FBF00148FB000109062006327BD001877 +:100780003042007FA0620063978200428F8600445F +:100790008F8500289383003000461023A7820042F3 +:1007A000A4A000E490A400638F820048AF830044BB +:1007B0002403FFBF0046102100832024AF8200489D +:1007C000A0A400638F820028A04000BD8F82002873 +:1007D00003E00008A44000BE8F8A002827BDFFE088 +:1007E000AFB10014AFB000108F880044AFBF001845 +:1007F00093890024954200E430D100FF0109182BB1 +:100800000080802130AC00FF3047FFFF00005821FE +:1008100014600003310600FF012030210109582334 +:10082000978300420068102B144000320000000043 +:1008300014680007240200018E0200202403FFFB3D +:1008400034E7800000431024AE020020240200019F +:1008500034E70880158200053165FFFF0E0015E5BD +:10086000020020210A001827020020210E0016167F +:10087000020020210E0016598F8400508F8400281A +:100880009482006024420001A4820060948200608F +:100890003C0308008C63318830427FFF5443000FD3 +:1008A0000200202194820060240380000043102471 +:1008B000A48200609082006090830060304200FF5C +:1008C000000211C200021027000211C03063007F35 +:1008D00000621825A0830060020020210220282148 +:1008E0008FBF00188FB100148FB000100A00179945 +:1008F00027BD0020914200632403FF8000431025A0 +:10090000A1420063978200423048FFFF110000209F +:10091000938300248F840028004B1023304600FF6F +:10092000948300E42402EFFF0168282B006218245E +:10093000A48300E414A000038E02002001005821CB +:10094000000030212403FFFB34E780000043102423 +:10095000AE02002024020001158200053165FFFF70 +:100960000E0015E5020020210A00184F978300426F +:100970000E00161602002021978300428F82004449 +:10098000A780004200431023AF82004493830024D9 +:100990008F8200288FBF00188FB100148FB0001015 +:1009A00027BD002003E00008A04300BD8F8200287F +:1009B00090430088904500BD244900883063003F83 +:1009C0002463FFE024020001006238042C6300204D +:1009D00030E80019A385002410600010AF890034AE +:1009E0003C0280003442000224050001240600017C +:1009F0001500000800E218240000282114600005FA +:100A000030E200201040000524050001912600017D +:100A100030C600010A0017E60000000003E00008ED +:100A20000000000027BDFFD8AFB000108F90003449 +:100A3000AFB40020AFB10014AFBF0024AFB3001CAF +:100A4000AFB200188E0500103C0208008C4231B095 +:100A50008F86003830A33FFF0062182B8CD3001420 +:100A6000008088218CD20020106000780000A02136 +:100A700090C3000D2402FF8000431024304200FF89 +:100A800050400073022020210005138230420003F1 +:100A90005440006F0220202194C3001C8F82002844 +:100AA0008E050028A44301148CC200100262182392 +:100AB000146500072402001F8F82003C0062102191 +:100AC0000262102B104000088F83002C24020018B3 +:100AD0000E001697A382004C2403FFFF1043006F03 +:100AE0002404FFFF8F83002C8F84003C8C62001055 +:100AF0000244902100441023AC6200108F82002831 +:100B0000AC7200208C4200680052102B104000098B +:100B10008F830038022020212402001D0E0016972A +:100B2000A382004C2403FFFF1043005C2404FFFF5A +:100B30008F8300388E0200248C630024104300074A +:100B4000022020212402001C0E001697A382004CD4 +:100B50002403FFFF104300512404FFFF8F84002C67 +:100B60008C82002424420001AC8200241253000431 +:100B70008F8200288C4200685642000E8E020000D0 +:100B80008E0200003C030080004310241440000D3E +:100B90002402001A022020210E001697A382004C86 +:100BA0002403FFFF1043003D2404FFFF0A0018E365 +:100BB0008E0200143C0300800043102450400003C8 +:100BC0008E020014AC8000208E0200142412FFFF5D +:100BD000105200062402001B022020210E0016974E +:100BE000A382004C1052002D2404FFFF8E0300004E +:100BF0003C020001006210241040001F3C020080F3 +:100C00000062102414400008022020212402001A4F +:100C10000E001697A382004C2403FFFF1043001F11 +:100C20002404FFFF02202021020028210E0016B715 +:100C3000240600012403FFFF2404FFFF1443000ED9 +:100C4000241400010A0019188FBF0024022020215B +:100C50002402000D8FBF00248FB400208FB3001C2E +:100C60008FB200188FB100148FB0001027BD00287C +:100C70000A001697A382004C8F83002C02202021AB +:100C800002803021946200362405000124420001D4 +:100C90000E0017E6A4620036000020218FBF00245A +:100CA0008FB400208FB3001C8FB200188FB10014D6 +:100CB0008FB000100080102103E0000827BD00283D +:100CC0008F83002827BDFFD8AFB40020AFB3001C2E +:100CD000AFB20018AFB10014AFB00010AFBF002426 +:100CE000906200638F9100342412FFFF3442004071 +:100CF00092250000A06200638E22001000809821DF +:100D000030B0003F105200060360A0212402000D05 +:100D10000E001697A382004C105200522404FFFFCD +:100D20008F8300288E2200188C63007C10430007FC +:100D3000026020212402000E0E001697A382004CB0 +:100D40002403FFFF104300472404FFFF2404002076 +:100D5000120400048F830028906200633442002054 +:100D6000A06200638F85003C10A0001E0000000000 +:100D7000560400048F820028026020210A001962B4 +:100D80002402000A9683000A2404FFFD94420060B6 +:100D90003042FFFF104300348FBF00243C020800A4 +:100DA0008C42318C0045102B14400006026020213B +:100DB000000028210E0017E6240600010A00198908 +:100DC000000020212402002D0E001697A382004C63 +:100DD0002403FFFF104300232404FFFF0A001989A6 +:100DE00000002021160400058F8400288E230014A3 +:100DF0002402FFFF506200180260202194820060EC +:100E000024420001A4820060948200603C03080038 +:100E10008C63318830427FFF5443000F02602021F1 +:100E2000948200602403800000431024A4820060A8 +:100E30009082006090830060304200FF000211C287 +:100E400000021027000211C03063007F00621825E5 +:100E5000A0830060026020210E0017992405000184 +:100E6000000020218FBF00248FB400208FB3001C0E +:100E70008FB200188FB100148FB0001000801021C5 +:100E800003E0000827BD00288F83002827BDFFE866 +:100E9000AFB00010AFBF0014906200638F870034C2 +:100EA00000808021344200408CE60010A062006384 +:100EB0003C0308008C6331B030C23FFF0043102B6D +:100EC0001040004E8F8500382402FF8090A3000D53 +:100ED00000431024304200FF50400049020020210E +:100EE0000006138230480003240200025502004429 +:100EF0000200202194A2001C8F85002824030023D7 +:100F0000A4A201148CE60000000616023042003F45 +:100F1000104300103C0300838CE300188CA2007C7B +:100F2000106200062402000E0E001697A382004CE9 +:100F30002403FFFF104300382404FFFF8F830028A1 +:100F40009062006334420020A06200630A0019CE60 +:100F50008F83002C00C31024144300078F83002CC0 +:100F600090A200623042000F34420020A0A2006232 +:100F7000A38800408F83002C9062000D3042007FD8 +:100F8000A062000D8F83003C106000180200202139 +:100F90008F8400388C8200100043102B1040000911 +:100FA00024020018020020210E001697A382004C94 +:100FB0002403FFFF104300182404FFFF0A0019F662 +:100FC000000020218C820010240500010200202155 +:100FD000004310238F83002C240600010E0017E627 +:100FE000AC6200100A0019F6000020210E001799CB +:100FF000240500010A0019F600002021020020212A +:101000002402000D8FBF00148FB0001027BD001800 +:101010000A001697A382004C8FBF00148FB00010F7 +:101020000080102103E0000827BD001827BDFFD86D +:10103000AFB000108F900034AFB3001CAFBF0020E2 +:10104000AFB20018AFB100148E1200103C030800BC +:101050008C6331B032423FFF0043102B1040007CC4 +:10106000008098218F8500382402FF8090A3000D16 +:1010700000431024304200FF5040007602602021DF +:101080000012138230420003240300015443007114 +:101090000260202190A2000D30420008544000035D +:1010A0008F82003C0A001A262402002450400003CC +:1010B0008E03000C0A001A26240200278CA20020AE +:1010C00014620005240200208E0300088CA2002474 +:1010D00010620008240200200E001697A382004C24 +:1010E0002403FFFF1043006A2404FFFF0A001A5183 +:1010F0008F84002C8E0200142411FFFF1451000372 +:101100008F8700280A001A4C240200258E0300183D +:101110008CE2007C146200162402000E8E03002470 +:101120008CA2002814620012240200218E060028DE +:101130008CA2002C14C2000E2402001F8E03002C6F +:101140001060000B240200238CE200680043102B87 +:1011500014400007240200268CA200140066182107 +:101160000043102B504000078F84002C24020022E3 +:101170000E001697A382004C105100452404FFFF77 +:101180008F84002C2403FFF79082000D004310246D +:10119000A082000D8F8600283C0308008C6331ACD0 +:1011A0008F82005094C400E08F85002C00431021F2 +:1011B00030847FFF00042040004410213043007F32 +:1011C000034320213C03000E008320212403FF80E1 +:1011D00000431024AF42002CA49200008CA20028EF +:1011E00024420001ACA200288CA2002C8E03002C0B +:1011F00000431021ACA2002C8E02002CACA20030C7 +:101200008E020014ACA2003494A2003A24420001E1 +:10121000A4A2003A94C600E03C0208008C4231B01F +:1012200024C4000130837FFF14620013008030214A +:10123000240280000082302430C2FFFF000213C26B +:10124000304200FF000210270A001A8E000233C04D +:10125000026020212402000D8FBF00208FB3001CEC +:101260008FB200188FB100148FB0001027BD002876 +:101270000A001697A382004C8F820028026020216A +:10128000240500010E001799A44600E0000020216B +:101290008FBF00208FB3001C8FB200188FB10014D5 +:1012A0008FB000100080102103E0000827BD002847 +:1012B00027BDFFE0AFB100148F910034AFB0001034 +:1012C000AFBF00188E2600103C0308008C6331B0BD +:1012D00030C23FFF0043102B1040005E0080802191 +:1012E0008F8500382402FF8090A3000D0043102456 +:1012F000304200FF50400058020020218F82003C05 +:1013000010400008000613828F8200289763000AAD +:101310002404FFFD944200603042FFFF104300555B +:1013200000061382304200031440000E000000004B +:1013300092220002104000058E2300245060001508 +:10134000922300030A001AC7020020218CA2002465 +:101350005062001092230003020020210A001ACFDD +:101360002402000F90A2000D3042000854400009F2 +:101370009223000302002021240200100E00169781 +:10138000A382004C2403FFFF1043003A2404FFFF14 +:1013900092230003240200025462000C92220003F4 +:1013A0008F82003C54400009922200030200202159 +:1013B0002402002C0E001697A382004C2403FFFF8A +:1013C0001043002C2404FFFF922200030220282156 +:1013D00002002021384600102CC600012C420001DA +:1013E0000E0016B7004630252411FFFF10510021D2 +:1013F0002404FFFF8F83003C1060001202002021B4 +:101400003C0208008C42318C0043102B1440000633 +:1014100000000000000028210E0017E6240600014D +:101420000A001B0D000020212402002D0E0016973B +:10143000A382004C1051000F2404FFFF0A001B0D73 +:10144000000020210E001799240500010A001B0D41 +:1014500000002021020020212402000D8FBF00186F +:101460008FB100148FB0001027BD00200A0016971E +:10147000A382004C8FBF00188FB100148FB00010F2 +:101480000080102103E0000827BD00209383004066 +:1014900027BDFFE024020002AFB10014AFB000107E +:1014A00000808821AFBF0018000080211062008CEE +:1014B0002404FFFD978500428F83004430A2FFFF84 +:1014C0000043102B5440007D8F8400480E001558B7 +:1014D000000000003C020800244279F40220202190 +:1014E000004028210E00171EAF8200342409FFFFA0 +:1014F0001049007B2404FFFF3C0808008D087A0493 +:101500003C0208008C4231B03C030800906379F43F +:1015100031043FFF0082102B1040001B3067003F5A +:101520003C0208008C4231A88F83005000042180C7 +:1015300000621821006418213062007F03422821D4 +:101540003C02000C00A228213C0200803442000131 +:101550003066007800C230252402FF80006210242B +:10156000AF42002830640007AF4208048F82002891 +:101570000344202124840940AF460814AF85002C81 +:10158000AF840038AC430118938300402402000369 +:101590001462003B240200012402002610E2003DF8 +:1015A00028E2002710400013240200322402002207 +:1015B00010E2003828E20023104000082402002432 +:1015C0002402002010E200242402002110E2001E68 +:1015D000022020210A001B8C2402000B10E2002DA7 +:1015E0002402002510E20010022020210A001B8C9A +:1015F0002402000B10E2001A28E20033104000061B +:101600002402003F2402003110E2000B02202021BE +:101610000A001B8C2402000B10E200110220202182 +:101620000A001B8C2402000B0E00187902202021D6 +:101630000A001BA7004080210E0019FB0220202178 +:101640000A001BA7004080210E001A9C02202021C6 +:101650000A001BA7004080211509000E00000000B1 +:101660000E001920022020210A001BA70040802123 +:101670000E001697A382004C0A001BA70040802191 +:1016800014620017020020212402002314E2000546 +:101690002402000B0E001992022020210A001BA731 +:1016A0000040802102202021A382004C0E001697CA +:1016B0002410FFFF0A001BA80200202130A500FF14 +:1016C0000E00159524060001978300428F82004486 +:1016D000A780004200431023AF8200440200202173 +:1016E0008FBF00188FB100148FB000100080102140 +:1016F00003E0000827BD002027BDFFE0AFB10014C4 +:10170000AFBF0018AFB000108F4601283C0308009F +:101710008C6331A02402FF80AF86005000C31821E3 +:101720003065007F03452821006218243C02000A2E +:10173000AF43002400A2282190A2006200808821EB +:10174000AF850028304200FF00021102A382004052 +:1017500090A200BC30420002144000022403003476 +:10176000240300308F820028A3830030938300403D +:101770008C4200C0A380004CAF82004424020004CD +:10178000106200308F8400448E2400045080002DAD +:101790008F8400448E2200103083FFFFA784004214 +:1017A0001060001FAF8200488F8300282405FF804F +:1017B000022020219062006300A21024304200FF2A +:1017C0001440000D000000000E001B139790004213 +:1017D00010400010004018212402FFFD5462001147 +:1017E0008E230020020028210E0015360220202121 +:1017F0000A001BF98E2300209062006300A21024CF +:10180000304200FF10400003022020210E00185B30 +:1018100000000000978200421440FFE48F830028FC +:101820008E23002030620004104000068F840044A4 +:101830002402FFFB006210240E00154AAE22002095 +:101840008F8400448F8300288FBF00188FB100144D +:101850008FB000102402000127BD002003E0000823 +:10186000AC6400C030A500FF2403000124A90001DE +:101870000069102B1040000C00004021240A0001D8 +:1018800000A31023004A38042463000130820001C1 +:101890000069302B1040000200042042010740255F +:1018A00054C0FFF800A3102303E00008010010213A +:1018B00027BDFFE03C021EDCAFB20018AFB1001440 +:1018C000AFBF001CAFB0001034526F410000882140 +:1018D000240500080E001C09022020210011808030 +:1018E0003C07080024E775F40002160002071821DF +:1018F000AC6200000000282124A200013045FFFF57 +:101900008C6200002CA60008044100020002204066 +:101910000092202614C0FFF8AC640000020780216A +:101920008E0400000E001C0924050020262300015F +:101930003071FFFF2E2301001460FFE5AE020000AE +:101940008FBF001C8FB200188FB100148FB0001031 +:1019500003E0000827BD00203C02080024426EB8C6 +:101960003C010800AC2275E83C02080024425430D7 +:101970003C010800AC2275EC240200063C01080082 +:10198000A02275F00A001C1C0000000027BDFFD833 +:10199000AFB3001CAFB20018AFBF0020AFB100144E +:1019A000AFB000108F5101408F48014800089402E9 +:1019B000324300FF311300FF8F4201B80440FFFEA5 +:1019C00027500180AE1100008F420144AE02000496 +:1019D00024020002A6120008A202000B2402001436 +:1019E000AE13002410620025286200151040000884 +:1019F000240200152402001010620030240200129C +:101A0000106200098FBF00200A001D468FB3001C22 +:101A10001062007024020022106200378FBF002085 +:101A20000A001D468FB3001C3C0208008C4231A006 +:101A30002403FF800222102100431024AF4200241F +:101A40003C0208008C4231A0022210213042007F6B +:101A5000034218213C02000A00621821166000BCF3 +:101A6000AF830028906200623042000F34420030A1 +:101A7000A06200620A001D458FBF00203C04600088 +:101A80008C832C083C02F0033442FFFF00621824D0 +:101A9000AC832C083C0208008C4231A08C832C08BB +:101AA0002442007400021082000214800062182593 +:101AB000AC832C080A001D458FBF00203C020800A3 +:101AC0008C4231A02403FF80022210210043102405 +:101AD000AF4200243C0208008C4231A03C03000AC3 +:101AE000022210213042007F0342102100431021C6 +:101AF0000A001D44AF8200283C0208008C4231A03D +:101B00002405FF800222102100451024AF4200244A +:101B10003C0208008C4231A0022210213042007F9A +:101B2000034218213C02000A0062182190620063FF +:101B300000A21024304200FF10400085AF8300282F +:101B400024620088944300123C0208008C4231A8B1 +:101B500030633FFF0003198002221021004310214F +:101B60003043007F03432021004510243C03000C38 +:101B700000832021AF4200289082000D00A2102493 +:101B8000304200FF10400072AF84002C9082000DA4 +:101B9000304200101440006F8FBF00200E00166608 +:101BA000000000008F4201B80440FFFE000000006A +:101BB000AE1100008F420144AE0200042402000274 +:101BC000A6120008A202000BAE1300240A001D4555 +:101BD0008FBF00202406FF8002261024AF42002081 +:101BE0003C0208008C4231A031043FFF00042180F8 +:101BF0000222102100461024AF4200243C030800BA +:101C00008C6331A83C0208008C4231A03227007F4F +:101C10000223182102221021006418213042007F83 +:101C20003064007F034228213C02000A0066182429 +:101C300000A22821034420213C02000C0082202124 +:101C4000AF4300283C02000803471821006290219E +:101C5000AF850028AF84002C0E001666010080219D +:101C60008F4201B80440FFFE8F82002C8F84002831 +:101C7000274501809042000DACB10000A4B00006E1 +:101C8000000216000002160300021027000237C2ED +:101C900014C00016248200889442001232033FFFD1 +:101CA00030423FFF1443001224026082908300639D +:101CB0002402FF8000431024304200FF5040000CFB +:101CC00024026082908200623042000F3442004061 +:101CD000A082006224026084A4A200082402000DF5 +:101CE000A0A200050A001D2F3C02270024026082EA +:101CF000A4A20008A0A000053C02270000061C00CA +:101D00000062182524020002A0A2000BACA3001060 +:101D1000ACA00014ACA00024ACA00028ACA0002C07 +:101D20008E42004C8F84002CACA200189083000DD2 +:101D30002402FF8000431024304200FF10400005C1 +:101D40008FBF00209082000D3042007FA082000DE6 +:101D50008FBF00208FB3001C8FB200188FB100140A +:101D60008FB000103C02100027BD002803E00008DF +:041D7000AF4201B8C5 +:0C1D7400080033F8080033F80800337052 +:101D8000080033A8080033DC0800340008003400E1 +:081D900008003400080032E0F5 +:081D98000A0001220000000016 +:101DA000000000000000000D747061352E302E30F0 +:101DB0006A3600000500000100000000000000007D +:101DC0000000000000000000000000000000000013 +:101DD0000000000000000000000000000000000003 +:101DE00000000000000000000000000000000000F3 +:101DF00000000000000000000000000000000000E3 +:101E000000000000000000000000000000000000D2 +:101E100000000000000000000000000000000000C2 +:101E20000000000010000003000000000000000D92 +:101E30000000000D3C02080024421B803C03080007 +:101E400024632014AC4000000043202B1480FFFDCD +:101E5000244200043C1D080037BD2FFC03A0F021E4 +:101E60003C100800261004883C1C0800279C1B809E +:101E70000E00015A000000000000000D3084FFFF3A +:101E8000308200078F85001810400002248300076D +:101E90003064FFF80085302130C41FFF034418214F +:101EA000247B4000AF85001CAF84001803E00008CD +:101EB000AF4400843084FFFF308200078F8500200C +:101EC0008F86002810400002248300073064FFF84A +:101ED000008520210086182B14600002AF850024A5 +:101EE000008620230344282134068000AF8400208C +:101EF000AF44008000A6202103E00008AF84003832 +:101F000027BDFFD8AFB3001CAFB20018AFB00010B0 +:101F1000AFBF0024AFB40020AFB100143C0860088C +:101F20008D1450002418FF7F3C1A800002989824DA +:101F30003672380CAD1250008F5100083C07601CFF +:101F40003C08600036300001AF500008AF80001838 +:101F5000AF400080AF4000848CE600088D0F080879 +:101F60003C0760168CEC000031EEFFF039CA00101F +:101F70003C0DFFFF340B80003C030080034B4821E5 +:101F80002D440001018D28243C0253533C010800DC +:101F9000AC230420AF890038AF860028AF8400103E +:101FA000275B400014A2000334E37C008CF900049A +:101FB000032818218C7F007C8C6500783C0280000F +:101FC00034520070AF85003CAF9F00403C130800C6 +:101FD00026731BC40240A0218E4800008F460000DB +:101FE00038C300013064000110800017AF8800344E +:101FF000028048218D2D00003C1908008F39045CB7 +:102000003C1108008E31045801A8F823033F7821C1 +:10201000000040210228382101FF802B00F07021B0 +:102020003C010800AC2F045C3C010800AC2E0458B5 +:102030008F4C0000398B0001316A00011540FFED23 +:1020400001A04021AF8D00348E4E00003C0C0800F2 +:102050008D8C045C3C0A08008D4A045801C8682332 +:10206000018D28210000582100AD302B014B20218B +:10207000008610213C010800AC25045C3C010800EE +:10208000AC2204588F4501088F44010030A920007C +:10209000AF850000AF84000C1120000A00A03021A1 +:1020A0003C0708008CE7042C24EF00013C010800E9 +:1020B000AC2F042C3C104000AF5001380A000190B6 +:1020C0000000000030B002001600001424110F00C0 +:1020D0001091001224070D001087023330B0000663 +:1020E0005200FFF53C104000936D0000240C0010DE +:1020F00031A600F010CC0269240E007010CE02DD73 +:102100008F8B001425670001AF8700143C1040003E +:10211000AF5001380A000190000000009748010408 +:102120001100FFE53C10400030B84000170000A24D +:10213000000000008F5901780720FFFE8F870038CC +:1021400024090008240508008CE30008AF45017845 +:10215000A7490140A7400142974201048F86000031 +:102160003049FFFF30DF000113E002D5012040219C +:102170002524FFFE240A0002A74A01463088FFFFFB +:10218000A74401483C0B08008D6B043C156002C459 +:102190008F8F000C30C3002014600002240400095B +:1021A0002404000130CD0C00240C040051AC0001CB +:1021B00034840004A744014A3C0508008CA504208F +:1021C0003C0200483C19000100A2F82530D800026A +:1021D00003F9282513000004000018213C04010025 +:1021E00000A428252403000130CA00045140000542 +:1021F000AF8300083C06001000A628252403000138 +:10220000AF830008AF451000000000000000000090 +:1022100000000000000000008F8300081060002311 +:10222000000000008F4B10000561FFFE0000000061 +:102230001060001E000000008F4D10003C030020C5 +:1022400001A36024118000198F8F000031EE00027D +:1022500011C0001600000000975010141600001363 +:10226000000000009745100830BFFFFF27F8000668 +:102270000018C8820019308000C7282133110001DE +:1022800033030003122003208CA200000000000D85 +:1022900000C7F821AFE200003C1908008F39043074 +:1022A000272600013C010800AC2604308F6A00009C +:1022B0003405FFFFAF8A00048CE200001045029A4B +:1022C000000020218CE5000030BF010013E0027EF9 +:1022D000010020213C0708008CE704743C10080032 +:1022E0008E10044C00E858213C1808008F18047028 +:1022F0000168882B3C0808008D08044800007821FC +:1023000002046021030F18210184702B010F682142 +:102310000071502101AE10213C010800AC2C044C8E +:102320003C010800AC2204483C010800AC2B0474BA +:102330003C010800AC2A04708F8D00180120302168 +:102340003129000725AE000831C21FFF034260217A +:10235000AF8D001CAF820018259B4000AF42008467 +:10236000112000038F90002024C800073106FFF8D9 +:102370008F84002800D0282100A4782B15E00002CB +:10238000AF90002400A428230345202134038000BB +:10239000008310213C061000AF850020AF8200387A +:1023A000AF450080AF4601788F8B00142567000190 +:1023B0000A0001DDAF8700148F6200088F670000FC +:1023C000241100300007C602330300F0107100A290 +:1023D000241900401479FF4B8F8B00148F4A017829 +:1023E0000540FFFE30A7020014E000030005128242 +:1023F0000000000D0005128230500003001049005B +:1024000001307021000E688001B06021000C5880FE +:10241000017380218E0800001500000200000000FA +:102420000000000D8F6F000405E202B19203000668 +:1024300092070005920F00043C020001000728806B +:1024400000B060218D8900182771000825EE000575 +:1024500001226821000E3082AD8D0018022020215B +:102460000E00058026050014920B00068F7F0004E5 +:102470003C087FFF000B2080009130218CC30004BA +:10248000350AFFFF03EAC8240079C021ACD8000454 +:102490009207000592090004960D000800072880A5 +:1024A00000B1F8218FEF0000974201043C07FFFFC5 +:1024B00001E75024304EFFFF01C96021018D5823F0 +:1024C0003168FFFF01482025AFE4000092030007B8 +:1024D00024190001107902692406000310660279AC +:1024E000000000008E190010241F000AA75F0140A1 +:1024F000A7590142920300048F86000024070001BF +:10250000A7430144A74001469758010430D1000277 +:102510003C050041A758014800001821A747014A7F +:102520001220000330CA00043C05014124030001CD +:1025300051400005AF8300083C08001000A8282582 +:1025400024030001AF830008AF4510000000000025 +:102550000000000000000000000000008F8B000859 +:1025600011600004000000008F4410000481FFFE91 +:10257000000000008F6A0000920700043C0508007C +:102580008CA50444AF8A0004975F01043C0F080047 +:102590008DEF044030E300FF33F9FFFF0079C021E5 +:1025A00000B868210000102124E6000A30C8FFFFAF +:1025B00001B8482B01E2702101C9602131100007E8 +:1025C0003C010800AC2D04443C010800AC2C044044 +:1025D000120000038F8D0018250B00073168FFF8EB +:1025E000010D702131CC1FFFAF8D001CAF8C001886 +:1025F000AF4C008497440104034C80213084FFFFDA +:102600003088000711000003261B400024890007C2 +:102610003124FFF88F8200208F850028008220213E +:102620000085782B15E00002AF820024008520236E +:102630000344882134058000022510213C06100047 +:10264000AF840020AF820038AF440080AF460178ED +:102650000A0002858F8B00148F5F017807E0FFFE70 +:1026600030AA020015400003000542820000000D60 +:1026700000054282310200030002710001C268219C +:10268000000D6080018248210009288000B380216C +:102690008E0B000011600002000000000000000D21 +:1026A0008F6F000C05E001F38F87003824190001BB +:1026B000AE1900008CE30008A20000078F78000428 +:1026C00000181C02306600FF24D100050011308282 +:1026D0002CC4004114800002A20300040000000D7D +:1026E0008F6B00043C0EFFFF00E028213164FFFFE8 +:1026F000248F000B000F4082000810800047482103 +:102700008D2D000026040014A60B000801AE6024E5 +:102710000E000580AD2C00008F5F01083C0A100000 +:1027200003EA382410E001A30000000097460104EA +:102730009203000724D1FFEC346500023224FFFF2E +:10274000A2050007960600082CC7001354E00005F8 +:1027500092030007920A0007355F0001A21F0007DD +:1027600092030007240B0001106B01BA2409000337 +:10277000106901CD8F88003830CFFFFF25E40002BB +:102780000004C883333F00FF001F2880A219000502 +:1027900000A858218D780000975101043C03FFFFE9 +:1027A000030360243222FFFF004F702325CDFFFE7C +:1027B000018D4825AD690000920600053C02FFF638 +:1027C000344EFFFF30CA00FF000A388000F020219D +:1027D000909900143C1FFF7F37E7FFFF3323000F62 +:1027E0000066782131F800FF0018288000B08821A9 +:1027F0008E2D002000A86021A20F000601AE482403 +:10280000AE0D000CAD89000C920B00068E04000C7E +:102810000127F824000B50800150C821972600267C +:102820000148C02100874024AF260024AE08000CD8 +:10283000AF3F0020AF0600108F860000240C001070 +:1028400024090002A74C0140A7400142A7400144CF +:10285000A7490146974B01042407000130C8000234 +:10286000256AFFFEA74A01483C050009A747014A1F +:1028700011000003000018213C0501092403000198 +:1028800030CD000451A00005AF8300083C060010C5 +:1028900000A6282524030001AF830008AF451000DF +:1028A0000000000000000000000000000000000028 +:1028B0009218000427110002322F0007000F102386 +:1028C000304E0007AE0E00108F900008120000047A +:1028D000000000008F4310000461FFFE00000000B4 +:1028E0008F7800008F8F00183C1008008E10044471 +:1028F000AF9800049751010425E6001030CA1FFF6D +:102900003222FFFFAF8F001CAF8A0018AF4A00844D +:102910002449FFFE3C0B08008D6B0440974E0104D8 +:1029200001206821000967C3020D282131C9FFFF7A +:1029300000AD402B016C382100E82021034AF8212A +:10294000313900073C010800AC2504443C01080073 +:10295000AC2404401320000327FB4000252300077C +:102960003069FFF88F9F00208F840028013F3821B5 +:1029700000E4C82B17200002AF9F002400E4382396 +:102980000347202134058000008510213C061000FB +:10299000AF870020AF820038AF470080AF46017894 +:1029A0000A0002858F8B0014975801041300FDC2A2 +:1029B0003C1040008F4301780460FFFE30B94000B6 +:1029C000132000033C0400080000000D3C04000834 +:1029D000AF44014024080800AF4801788F8B000005 +:1029E000974A0104317F000113E000E93146FFFFFF +:1029F00024D0FFFE240C0002A74C0146A75001483A +:102A00008F8F00182405000DA745014A8F71000023 +:102A100025E2000830491FFF0349702130CD00072F +:102A2000AF910004AF8F001CAF89001800C038219F +:102A3000AF49008411A0000325DB400024C6000735 +:102A400030C7FFF88F9800208F84002800F83021CD +:102A500000C4382B14E00002AF98002400C43023D7 +:102A60008F8A001403465821340880000168F82139 +:102A7000255900013C0310003C104000AF860020A7 +:102A8000AF9F0038AF460080AF430178AF99001484 +:102A9000AF5001380A000190000000008F6900006B +:102AA000974401043127FFFF3088FFFF8F4F0178E3 +:102AB00005E0FFFE30FF0007001F182330780007F5 +:102AC00024E6FFFE2419000AA7590140A758014235 +:102AD000A7460144A7400146A74801488F42010884 +:102AE00030510020162000022403000924030001B5 +:102AF00030AA0002A743014A3C04004111400003F0 +:102B0000000018213C0401412403000130AB000403 +:102B100051600005AF8300083C05001000852025AA +:102B200024030001AF830008AF4410000000000040 +:102B30000000000000000000000000008F9000086E +:102B400012000004000000008F4C10000581FFFE01 +:102B5000000000008F780000276200088F8D003C85 +:102B6000AF980004944600089451000A944F000C5A +:102B700030CEFFFF0011240031E9FFFF11CD00A28C +:102B8000008920253C0308008C6304443C1808009D +:102B90008F18044000E85021255FFFFE007F782158 +:102BA0000000102101FF302B03028821022648215A +:102BB0003C010800AC2F04443C010800AC2904404F +:102BC00024EB00083162FFFF3047000710E00003EC +:102BD0008F850018245000073202FFF83106FFFFEE +:102BE00030C800070045702131CD1FFF034D602123 +:102BF000AF85001CAF8D0018259B4000AF4D0084B1 +:102C0000110000038F8F002024C400073086FFF8D6 +:102C10008F84002800CF282100A4482B1520000213 +:102C2000AF8F002400A42823AF850020AF4500808B +:102C30003C1108008E3104340345C0213402800069 +:102C40000302302112200005AF860038938300175D +:102C50002419000E1079000D241F043F3C0A1000B7 +:102C6000AF4A01788F8B0014256700010A0001DD4F +:102C7000AF8700140E0005A63C1040008F8B001497 +:102C8000256700010A0001DEAF8700143C0A10002E +:102C9000A75F0148AF4A01780A0004B48F8B001483 +:102CA000240E0F0011EE003D30D10020162000024E +:102CB00024030009240300010A000208A743014A73 +:102CC0000A0001FBA740014694E5000894E2000ACF +:102CD00094EB000C8F86003C0002FC00316AFFFF81 +:102CE00030B9FFFF1326003703EA20253C05080012 +:102CF0008CA504443C1F08008FFF044000005021B5 +:102D000000A8382100E8302B03EAC8210326C0219F +:102D10003C010800AC2704443C010800AC380440E6 +:102D20000A0002698F8D00183C1908008F39047C55 +:102D30003C0308008C6304543C0608008CC60478ED +:102D40003C0F08008DEF04500328382100686821EB +:102D500000E8C02B00C4882101A8402B01E47021A9 +:102D60000238582101C860213C010800AC2D0454F0 +:102D70003C010800AC2C04503C010800AC27047C4A +:102D80003C010800AC2B04780A0002698F8D001802 +:102D9000A74001460A00041B8F8F001830D0002086 +:102DA0001600FFC52403000D240300050A000208D5 +:102DB000A743014A975901042738FFF00A00036B23 +:102DC0003304FFFF8F8C0040148CFFC8000080216B +:102DD0003C1108008E31046C3C0408008C840468AB +:102DE0000228702101C8782B00904021010F682132 +:102DF0003C010800AC2E046C3C010800AC2D0468BA +:102E00000A0002698F8D00188F9900401499FF5DA8 +:102E1000000060213C0508008CA5046C3C100800F3 +:102E20008E10046800E82021248EFFFE00AEF821F9 +:102E300003EE582B020C5021014B18213C010800D5 +:102E4000AC3F046C3C010800AC2304680A00048B0E +:102E500024EB00088F8800383C02FFFF8D0E000C29 +:102E600001C2682401A46025AD0C000C0A0003799E +:102E700030CFFFFF0A0003A9AE000000974B01040A +:102E8000920400048E2A000C01644021251FFFF2E9 +:102E90000147182433F9FFFF0079C025AE38000C34 +:102EA0000A0002D48E1900103C03FFFF8D110010A0 +:102EB0000223282400A47825AD0F00100A0003790E +:102EC00030CFFFFF97450104920600048E2F0010BB +:102ED00000A610212449FFEE01E76824312EFFFFF0 +:102EE00001AE6025AE2C00100A0002D48E1900102D +:102EF0008E06000CAE0000000003C0800310882185 +:102F00000A0002A6AE2600201460000D3050FFFF1C +:102F10003C04FFFF0044602401846826000D582B08 +:102F2000000C502B014B1024104000020000000048 +:102F30000000000D8CA300000A00023E0064102572 +:102F40003A11FFFF0011782B0010702B01CF2024C5 +:102F500010800002000000000000000D8CB800008E +:102F60000A00023E3702FFFF3084FFFF30A5FFFF5B +:102F7000108000070000182130820001104000027C +:102F800000042042006518211480FFFB0005284042 +:102F900003E000080060102110C0000700000000DE +:102FA0008CA2000024C6FFFF24A50004AC82000010 +:102FB00014C0FFFB2484000403E0000800000000AC +:102FC00010A0000824A3FFFFAC8600000000000052 +:102FD000000000002402FFFF2463FFFF1462FFFAD9 +:102FE0002484000403E0000800000000308EFFFF8E +:102FF00030D8FFFF00057C0001F8602539CDFFFFC8 +:1030000001AC5021014C582B014B482100094402CE +:103010003127FFFF00E830210006240230C5FFFF02 +:1030200000A418213862FFFF03E000083042FFFFD0 +:103030003C0C08008D8C0484240BFF8027BDFFD03E +:1030400001845021014B4824AF4900203C0808006E +:103050008D080484AFB20020AFB00018AFBF0028C5 +:10306000AFB30024AFB1001C936600040104382103 +:1030700030E4007F009A10213C03000800439021B7 +:1030800030C50020036080213C080111277B000827 +:1030900014A00002264600702646006C921300041D +:1030A00097510104920F00043267000F322EFFFF88 +:1030B00031ED004001C7282311A000050000482180 +:1030C000925900BC33380004170000900000000043 +:1030D000924300BC307F000413E0000F00000000AA +:1030E00010A0000D00000000960E0002240AFF80D0 +:1030F00000A7602125CDFFFEA74D1016920B0004FE +:10310000014B2024308200FF10400085010C402537 +:103110003C0F0400010F40258F5301780660FFFE2D +:103120002404000AA7440140960D0002240400096B +:1031300031AC0007000C5823316A0007A74A01424E +:10314000960200022443FFFEA7430144A740014624 +:10315000975F0104A75F01488F59010833380020A9 +:103160005300000124040001920F000431EE00100E +:1031700015C000023483001000801821A743014AC3 +:10318000000000000000000000000000000000003F +:10319000AF48100000000000000000000000000028 +:1031A000000000008F5110000621FFFE3113FFFFC9 +:1031B00012600003000000008F481018ACC8000027 +:1031C00096030006307FFFFF27F90002001998825E +:1031D00000138880023B30218CD800001520005756 +:1031E00000183402920300042405FF8000A3F82491 +:1031F00033F100FF1220002C00000000924700BCB9 +:1032000030F200021240002800000000974B100C22 +:103210002562FFFEA7421016000000003C0A0400D1 +:1032200035490030AF4910000000000000000000E8 +:1032300000000000000000008F4C10000581FFFE20 +:10324000000000009749100C8F51101C00C0202175 +:103250003127FFFF24F2003000121882000328807B +:1032600000BBF8213226FFFFAFF100000E000595EC +:1032700000112C020013C880033B98218E780000B7 +:1032800000027400AFB800108FA80010310FFFFFCC +:10329000AFAF00108FA4001001C46825AFAD0010BF +:1032A0008FA60010AE66000097730008976D000AA5 +:1032B0009766000C8F8A003C000D5C0030CCFFFF4D +:1032C0003262FFFF104A0036016C2025960600028C +:1032D0003C10100024D300080E0001393264FFFFB7 +:1032E000974C01040E0001473184FFFFAF50017875 +:1032F0008FBF00288FB300248FB200208FB1001C35 +:103300008FB0001803E0000827BD003010A0FF7048 +:103310000000000024A5FFFC0A0005CE24090004DB +:103320008CD10000AF5110188F5301780660FF7ADE +:103330002404000A0A0005E30000000000A7C821D9 +:103340008F8800388F4E101C0019C08200187880BA +:1033500001E82021AC8E0000000E2C0200C02021CC +:103360000E00059531C6FFFF023B28218CAD000001 +:103370000002540000403021AFAD00108FAC0010AF +:10338000318BFFFFAFAB00108FA200100142482528 +:10339000AFA900108FA700100A000613ACA7000009 +:1033A0008F8F0040148FFFC9000000009742010476 +:1033B000960B00023C0508008CA5046C3049FFFF09 +:1033C000316AFFFF3C1108008E310468012A382160 +:1033D00024F2FFFE00B240210012FFC30112C82BED +:1033E000023FC021031920213C010800AC28046CD5 +:1033F0003C010800AC2404680A00064D00000000EF +:1034000000A4102B104000092403000100052840EF +:1034100000A4102B04A00003000318405440FFFC3C +:103420000005284010600007000000000085302BD8 +:1034300014C0000200031842008520231460FFFB23 +:103440000005284203E00008008010218F85002C31 +:1034500027BDFFE8000530272CC300012CA4000283 +:103460000083102510400003AFBF00102405007F2B +:10347000AF85002C0005282730A5FFFF0E0005743E +:10348000240426F58F830030240402BD004030213F +:103490000083382B10E000092405000100042040BF +:1034A0000083102B04800003000528405440FFFCDB +:1034B0000004204010A0000800C350210064402BED +:1034C00015000002000528420064182314A0FFFB29 +:1034D0000004204200C350218FBF0010000A4C029C +:1034E000312200FF27BD0018AF8A002C03E000083E +:0434F000AF89003070 +:0C34F4000A00002A000000000000000098 +:103500000000000D747870352E302E306A360000C1 +:10351000050000000000000A000001360000EA601B +:10352000000000000000000000000000000000009B +:10353000000000000000000000000000000000008B +:10354000000000000000000000000000000000007B +:103550000000000000000016000000000000000055 +:10356000000000000000000000000000000000005B +:10357000000000000000000000000000000000004B +:1035800000000000000000000000000000001388A0 +:1035900000000000000005DC00000000000000004A +:1035A00010000003000000000000000D0000000DEE +:1035B0003C02080024423B603C03080024633D14A5 +:1035C000AC4000000043202B1480FFFD2442000487 +:1035D0003C1D080037BD7FFC03A0F0213C10080013 +:1035E000261000A83C1C0800279C3B600E0002BA75 +:1035F000000000000000000D8F8300383C088000B0 +:10360000350700708CE50000008330253C029000F7 +:1036100000C22025AF850030AF4400208F49002034 +:103620000520FFFE3C038000346200708C450000E2 +:103630008F8600303C1908008F39007C3C0E080052 +:103640008DCE007800A62023032458210000782185 +:103650000164682B01CF6021018D50213C010800DD +:10366000AC2B007C3C010800AC2A007803E0000889 +:10367000000000000A000041240400018F8400388B +:103680003C05800034A200010082182503E00008F8 +:10369000AF43002003E00008000010213084FFFF4A +:1036A00030A5FFFF108000070000182130820001C4 +:1036B0001040000200042042006518211480FFFB26 +:1036C0000005284003E000080060102110C000073A +:1036D000000000008CA2000024C6FFFF24A5000407 +:1036E000AC82000014C0FFFB2484000403E0000847 +:1036F0000000000010A0000824A3FFFFAC8600001B +:1037000000000000000000002402FFFF2463FFFF10 +:103710001462FFFA2484000403E0000800000000A3 +:10372000308AFFFF93A80013A74A014497490E1659 +:1037300030C600FF3C021000A7490146AF450148D2 +:10374000A3460152A748015AAF4701608FA4001851 +:103750008FA30014A7440158AF43015403E00008AD +:10376000AF42017803E00008000000003C03800045 +:10377000346200708C4900008F88000024840007A8 +:1037800027BDFFF83084FFF8AF890030974D008ADD +:1037900031ACFFFFAFAC00008FAB000001685023DD +:1037A0002547FFFF30E61FFF00C4282B14A0FFF7BA +:1037B0003C0C8000358B00708D6A00003C070800CF +:1037C0008CE700843C0608008CC60080000810824C +:1037D000014918230002788000E3702100002021B5 +:1037E00001C3C82B00C4C02101FA4021031948219C +:1037F0002502400027BD00083C010800AC2E0084D3 +:103800003C010800AC29008003E000080000000033 +:103810008F8200002486000730C5FFF800A218211F +:1038200030641FFF03E00008AF8400008F8700387A +:103830008F8A004027BDFFB88F860044AFB6004096 +:10384000AFBF0044AFB5003CAFB40038AFB30034F5 +:10385000AFB20030AFB1002CAFB000288F450104EB +:103860008D4900ACAF4700808CC8002000A93823E8 +:103870000000B021AF480E108F440E100000482108 +:10388000AF440E148CC20024AF420E188F430E18A2 +:10389000AF430E1C10E001252D230001936B00089F +:1038A000116000D400000000976E001031CDFFFFC2 +:1038B00000ED602B158000CF000000009770001015 +:1038C000320FFFFFAF4F0E008F5200003251000841 +:1038D0001220FFFD0000000097540E088F460E04D2 +:1038E0003285FFFF30B3000112600132000000009A +:1038F0000000000D30B8A04024150040131500C092 +:1039000030A9A0001120012D00000000937F0008C5 +:1039100013E000080000000097630010306BFFFF09 +:1039200000CB402B1100000330AC0040118001237C +:1039300000000000A785003CAF86003493660008B5 +:1039400000E02821AFA7002014C0012427B30020E5 +:10395000AF60000C9782003C3047400014E000024A +:10396000240300162403000E24194007A363000A51 +:10397000AF790014938A003E8F7400143158000709 +:103980000018AA4002959025AF7200149784003C5D +:103990008F7000143091001002117825AF6F001461 +:1039A000978E003C31CD000811A00147000028216E +:1039B0008F6700143C0210003C0C810000E22825B7 +:1039C000AF65001497460E0A2408000E3405FFFC6C +:1039D00030C3FFFF006C5825AF6B0004A3680002E2 +:1039E000937F000A27E90004A369000A9786003C38 +:1039F0009363000A30CC1F00000C598301634021FF +:103A0000251F0028A37F000997490E0CA769001005 +:103A100093790009272A0002315800070018A823CB +:103A200032B10007A371000B937400099764001072 +:103A30008F910034978F003C329200FF0244802126 +:103A40000205702131ED004011A0000531C4FFFFD7 +:103A50000091282B3C12800010A000140000A0212F +:103A60000224382B14E0011B8FA500208F4D0E146B +:103A7000AF4D0E108F420E1CAF420E18AF440E0019 +:103A80008F4F000031EE000811C0FFFD0000000064 +:103A900097540E080080882100009021A794003CD4 +:103AA0008F500E0424140001AF900034976400106E +:103AB0003095FFFF8E6800000111F82317E0000920 +:103AC000AE7F00008F6500148F8B004434A6004049 +:103AD000AF6600148F4C0E10AD6C00208F430E1893 +:103AE000AD6300249367000814E000D200000000DA +:103AF0000E00009E240400108F8900483C0832000C +:103B000000402821312600FF0006FC0003E8502574 +:103B100025390001AF990048AC4A000093780009AC +:103B20009370000A330400FF00047400320F00FF9A +:103B300001CF6825AC4D00048F820048064000EAA2 +:103B4000ACA20008ACA0000C9783003C306B0008CE +:103B5000156000022628000626280002974E0E1443 +:103B60008F450E1C8F670004936D000231C4FFFF68 +:103B700031A200FFAFA200108F6C0014AFA8001894 +:103B80000E00008BAFAC0014240400100E0000C720 +:103B9000000000008E7200001640000500000000CA +:103BA0008F6400142405FFBF00859824AF730014B0 +:103BB0008F79000C03353821AF67000C937500082E +:103BC00016A000080000000012800006000000009F +:103BD0008F7F00143C0BEFFF3568FFFE03E848249D +:103BE000AF690014A37400088FA500200A000246E4 +:103BF00002202021AF470E000A0000F5000000005F +:103C00008F5901780720FFFE241F08008F840000D1 +:103C1000AF5F0178974B008A316AFFFF0144482368 +:103C20002528FFFF31021FFF2C4300081460FFF915 +:103C3000000000008F8E00488F8D003800C04821A2 +:103C40000344202125C60001240C0F00AF86004844 +:103C500000E938232486400031CA00FF11AC00057A +:103C6000240800019391003E3230000700107A4092 +:103C700035E80001000AAC003C18010002B8A0259C +:103C8000AC9440008F93004830B2003630A4000856 +:103C9000ACD300041080009701123025974E0E0A15 +:103CA0008F8D00003C02810031CCFFFF25AB000866 +:103CB000018240253C03100031651FFF25390006B5 +:103CC000241F000EAF48016000C33025A75F015AD2 +:103CD000AF850000A759015814E0000A8F930038FF +:103CE00024120F00527200022416000134C6004054 +:103CF0008F580E108F940044AE9800208F550E18E8 +:103D0000AE9500248F450E14AF4501448F590E1C0B +:103D1000AF590148A34A01523C0A1000AF46015472 +:103D2000AF4A017814E0FEDD2D2300010076A025C6 +:103D3000128000178FBF00448F84003824160F00B4 +:103D400010960084000000008F45017804A0FFFE5B +:103D500024150F001095006E000000008F470E1410 +:103D6000240202403C1F1000AF4701448F440E1C48 +:103D7000AF440148A3400152A740015AAF4001603F +:103D8000A7400158AF420154AF5F01788FBF004494 +:103D90008FB600408FB5003C8FB400388FB300342D +:103DA0008FB200308FB1002C8FB0002803E00008E4 +:103DB00027BD004814C0FED030B8A0408F420E147A +:103DC0008F84004400004821AC8200208F510E1CDB +:103DD000AC9100240A00020E2D2300018F910034C3 +:103DE000978A003C3C1280000220A82131580040F4 +:103DF0001700FF300000A021976900108F92003457 +:103E00003139FFFF133200350000202100804821A6 +:103E10001480FEA000A038218F420E148F8400442D +:103E2000AC8200208F510E1CAC9100240A00020EBF +:103E30002D230001936A00099378000B315000FF95 +:103E4000330F00FF020F702125C2000A3050FFFF20 +:103E50000E00009E020020218F8600483C1F41007A +:103E600024CD0001AF8D0048936C000930C600FFDF +:103E700000064400318300FF246B0002010B48253B +:103E8000013FC825AC5900008F67000C97440E1401 +:103E900000F22825AC4500048F450E1C8F670004F6 +:103EA000936A00023084FFFF315800FFAFB8001062 +:103EB0008F6F0014AFB100180E00008BAFAF00146D +:103EC0000A0001A602002021AF6000040A00013EA2 +:103ED000A36000020A000246000020210000902199 +:103EE0000A000170241400013C1280000A000195B0 +:103EF000ACB2000C8F91000025240002A7440158A9 +:103F000026300008320F1FFF0A0001F9AF8F0000B2 +:103F1000AF40014C1120002C000000008F590E1002 +:103F2000AF5901448F430E18240200403C1F10007B +:103F3000AF430148A3400152A740015AAF4001607E +:103F4000A7400158AF420154AF5F01780A00022731 +:103F50008FBF0044112000060000000097460E08A5 +:103F600030CC004015800002000000000000000D71 +:103F70008F4D017805A0FFFE0000000097530E1042 +:103F80003C120500240E2000326AFFFF0152C025BA +:103F9000AF58014C8F4F0E143C021000AF4F01443C +:103FA0008F500E1CAF500148A34001528F8400383F +:103FB000A740015AAF400160A7400158AF4E0154DD +:103FC0000A000215AF4201788F490E14AF4901442F +:103FD0008F430E1C0A00028E240200403C0E20FF7C +:103FE00027BDFFE03C1A80003C0F800835CDFFFD67 +:103FF000AFBF001CAFB20018AFB10014AFB00010DB +:10400000AF8F0040AF4D0E00000000000000000028 +:104010000000000000000000000000003C0C00FF59 +:10402000358BFFFDAF4B0E003C0660048CC9500081 +:10403000240AFF7F3C116000012A40243507380C18 +:10404000ACC750008E24043824050009AF45000891 +:104050003083FFFF38622F712450C0B3AF80004817 +:104060000E000068AF80000052000001AE20442C1A +:104070000E0004353C1180000E000EA83630007092 +:104080008F8A00403C12080026523BC8020088215B +:104090008E0800008F5F00003BF9000133380001FB +:1040A00013000017AF880030022048218D27000040 +:1040B0003C0F08008DEF006C3C0C08008D8C0068F4 +:1040C00000E8C02301F828210000682100B8302B47 +:1040D000018D5821016640213C010800AC25006C8F +:1040E0003C010800AC2800688F44000038830001C0 +:1040F000306200011440FFED00E04021AF87003046 +:104100008E0C00003C0508008CA5006C3C040800E7 +:104110008C8400680188302300A63821000010211B +:1041200000E6402B008218210068F8213C010800BD +:10413000AC27006C3C010800AC3F00688F490100CF +:1041400025590088AF990044AF890038AF49002055 +:104150008E070000AF8700308F4D017805A0FFFE6D +:10416000000000008E0600003C0B08008D6B007400 +:104170003C0408008C84007000C728230165F821E6 +:104180000000102103E5402B0082382100E8C821FF +:10419000240908003C010800AC3F00743C01080001 +:1041A000AC390070AF49017893580108A398003EDC +:1041B000938F003E31EE000115C000158F8300384B +:1041C000240E0D00106E0019240F0F00106F001D3B +:1041D000000000009159000024180050332900FF0E +:1041E000113800043C1F4000AF5F01380A0002E7AD +:1041F000000000000E0008EE000000008F8A004062 +:104200003C1F4000AF5F01380A0002E700000000D9 +:10421000938D003E31AC0006000C51000E0000CE24 +:104220000152D8210A0003438F8A00403C1B08003A +:10423000277B3C480E0000CE000000000A0003432C +:104240008F8A00403C1B0800277B3C680E0000CE94 +:10425000000000000A0003438F8A004090AA00017A +:104260008FAB00108CAC00103C0300FF8D68000485 +:10427000AD6C00208CAD001400E060213462FFFFC3 +:10428000AD6D00248CA700183C09FF000109C02473 +:10429000AD6700288CAE001C0182C8240319782564 +:1042A000AD6F0004AD6E002C8CAD0008314A00FFEC +:1042B000AD6D001C94A900023128FFFFAD6800100D +:1042C00090A70000A5600002A1600004A1670000A3 +:1042D00090A30002306200FF000219821060000506 +:1042E000240500011065000E0000000003E0000836 +:1042F000A16A00018CD80028354A0080AD780018EA +:104300008CCF0014AD6F00148CCE0030AD6E000861 +:104310008CC4002CA16A000103E00008AD64000C0D +:104320008CCD001CAD6D00188CC90014AD69001453 +:104330008CC80024AD6800088CC70020AD67000C55 +:104340008CC200148C8300640043C82B1320000728 +:10435000000000008CC20014144CFFE400000000B8 +:10436000354A008003E00008A16A00018C820064E5 +:104370000A0003990000000090AA000027BDFFF882 +:104380008FA9001CA3AA00008FAE00003C0FFF8085 +:104390008FA8001835E2FFFF8CCD002C01C26024ED +:1043A000AFAC0000A120000400E06021A7A0000243 +:1043B0008FB800008D2700040188182100A0582123 +:1043C00000C05021006D28263C06FF7F3C0F00FFF7 +:1043D0002CAD000135EEFFFF34D9FFFF3C02FF009A +:1043E00003193024000D1DC0010EC82400E2C024B2 +:1043F00000C3702503197825AD2E0000AD2F0004F1 +:104400008D450024AFAE0000AD2500088D4D002085 +:104410002405FFFFAD2D000C956800023107FFFF5A +:10442000AD2700109166001830C200FF000219C2CB +:10443000506000018D450034AD2500148D670008E3 +:1044400027BD0008AD27001C8C8B00CCAD2C0028AC +:10445000AD20002CAD2B0024AD20001803E0000897 +:10446000AD20002027BDFFE0AFB20018AFB10014AF +:10447000AFB00010AFBF001C9098000000C08821B2 +:104480003C0D00FF330F007FA0CF0000908E000195 +:1044900035ACFFFF3C0AFF00A0CE000194A6001E31 +:1044A000A22000048CAB00148E29000400A08021FF +:1044B000016C2824012A4024008090210105202538 +:1044C000A6260002AE2400042605002026240008AB +:1044D0000E00007624060002924700002605002800 +:1044E0002624001400071E000003160324060004FF +:1044F000044000032403FFFF965900023323FFFF0B +:104500000E000076AE230010262400248FBF001C6E +:104510008FB200188FB100148FB000102405000373 +:10452000000030210A00008027BD002027BDFFD8F1 +:10453000AFB1001CAFB00018AFBF002090A80000C2 +:10454000240200018FB0003C3103003F008088212D +:10455000106200148FAA0038240B0005506B00165F +:10456000AFAA001000A0202100C028210E0003DC0B +:1045700002003021922400BC30830002106000034E +:1045800026060030ACC0000024C600048FBF002007 +:104590008FB1001C8FB0001800C0102103E000088C +:1045A00027BD0028014038210E00035AAFB000108B +:1045B0000A000420000000000E0003A1AFB00014A8 +:1045C0000A000420000000003C02000A03421821F7 +:1045D0003C04080024843CAC2405001A000030216F +:1045E0000A000080AF8300543C03800034620070F6 +:1045F0008C48000000A0582100C04821308A00FFEC +:10460000AF8800308F4401780480FFFE3C0C8000AE +:10461000358600708CC500003C0308008C63007474 +:104620003C1808008F18007000A82023006468213F +:104630000000C82101A4782B0319702101CF60214B +:104640003C010800AC2D00743C010800AC2C00704B +:104650008F480E14AF480144AF47014CA34A0152A2 +:10466000A74B01589346010830C5000854A000012B +:1046700035291000934B090024070050316A00FFD0 +:1046800011470007000000008F450E1CAF45014890 +:10469000AF4901543C09100003E00008AF4901781C +:1046A000934D010831A8000811000010000000001F +:1046B000934F010831EE001051C000013529000868 +:1046C0003C04080090843D10A34401508F4309A48A +:1046D000AF4301488F4209A0AF420144AF490154A2 +:1046E0003C09100003E00008AF4901783C190800BC +:1046F0008F393CCC333800085700FFF135290008CA +:104700000A0004730000000024070040AF470814AB +:10471000AF4008108F4209448F4309508F44095419 +:104720008F45095C8F46094CAF820064AF8300500F +:10473000AF84004CAF85005C03E00008AF860060EA +:104740009346010930C5007F000518C000052140CF +:104750000083102103E00008244200883C0A08007E +:10476000914A3CD13C09080095293CCA3C051100FE +:10477000000A3C002528000200E8302500C5182565 +:1047800024820008AC83000003E00008AC80000431 +:104790008F4A002C974E09083C0F000E034F38211A +:1047A00031CDFFFF000D41C0AF48002C97430908F1 +:1047B00094EC001A0080402124020001318BFFFF9D +:1047C000AC8B00008CE9001C00A0582100C06021C7 +:1047D000AC8900048CE40020AD04000890E30019CB +:1047E00030630003106200400000000028650002F2 +:1047F00014A00073240600021066004E00000000A2 +:104800002418000310780057000000003C0908003D +:1048100095293CC093450934934609213C0E080074 +:1048200095CE3CC630A200FF0002C88294E5002A63 +:1048300030C400FF978700580019C60000041C0010 +:10484000312FFFFF0303102501CF6821004DC8253C +:1048500000A720213C0640000326C02500044C0090 +:10486000AD090004AD180000934F09203C03000679 +:1048700025090014000F760001C36825AD0D00085E +:104880008F42092C24E5000130A67FFFAD02000C09 +:104890008F59093025020028A7860058AD1900104D +:1048A0008F440938AD040014AD2B00048F58094023 +:1048B000AD380008934F09373C0D080091AD3CD04E +:1048C000AD20001031EE00FF01CC1821000367007D +:1048D000000D4400018858253567FFFFAD27000C07 +:1048E00003E00008AF4A002C3C09080095293CC0B1 +:1048F0003C05080094A53CCA3C0F080095EF3CBC61 +:1049000094E400243126FFFF00A6702101CF682324 +:1049100000041C0025A2FFF20062C825241808002C +:10492000AD19000CAD180014AD0000100A0004C849 +:104930002508001894E6002494E500283C090800A6 +:1049400095293CC000067C000005740035ED81000F +:1049500035C40800AD0D000CAD0400100A0004C8F9 +:10496000250800143C09080095293CC03C020800B9 +:1049700094423CCA3C06080094C63CBC94E4002423 +:104980003125FFFF94F800280045C821032678232D +:1049900000181C0000046C0025EEFFEE006EC82518 +:1049A00035A2810024180800AD02000CAD190010DA +:1049B000AD180018AD0000140A0004C82508001C3A +:1049C0001460FF920000000094E300243C090800FA +:1049D00095293CC00003140034590800AD19000C9F +:1049E0000A0004C82508001003E00008240201F4AE +:1049F00027BDFFE8AFB00010AFBF00140E0000608D +:104A00000080802124050040AF4508148F830050AA +:104A10008F84004C8F85005C007018210064102387 +:104A200018400004AF830050AF6300548F660054F9 +:104A3000AF86004C1200000C000000008F44007490 +:104A4000936800813409FA002D07000710E0000583 +:104A500000891021936C0081240B01F4018B500418 +:104A600001441021AF62000C8F4E095C01C5682320 +:104A700019A000048FBF00148F4F095CAF8F005C3A +:104A80008FBF00148FB000100A00006227BD00180D +:104A90008F8400648F8300508F82004CAF64004489 +:104AA000AF63005003E00008AF6200543C03800095 +:104AB000346200708C43000027BDFFF8308700FF90 +:104AC00030A900FF30C800FFAF8300308F44017869 +:104AD0000480FFFE3C028000345900708F380000D3 +:104AE000A3A700033C0708008CE700748FAC00000C +:104AF0003C0608008CC60070030378233C0E7FFF41 +:104B000000EFC82135CDFFFF00005021018D282482 +:104B100000CA1821000847C0032F202B00A8102529 +:104B20000064C021AFA200003C010800AC39007451 +:104B30003C010800AC380070934F010AA3A00002AA +:104B40003C0E80FFA3AF00018FAC0000312B007F33 +:104B500035CDFFFF018D4824000B5600012A40256A +:104B6000240730002406FF803C05100027BD000804 +:104B7000AF48014CAF470154A7400158A34601522A +:104B800003E00008AF45017827BDFFE8AFBF001480 +:104B9000AFB000108F6500743C068000309000FFBD +:104BA00000A620250E000060AF640074936300052A +:104BB000346200080E000062A3620005020020219A +:104BC0008FBF00148FB000102405000524060001DB +:104BD0000A00056E27BD001827BDFFE03C038000DA +:104BE000AFB00010AFBF0018AFB100143462007056 +:104BF0008C470000309000FF30A800FFAF870030E6 +:104C00008F4401780480FFFE3C188000371100704B +:104C10008E2F00003C0D08008DAD00743C0A08008A +:104C20008D4A007001E7702301AE28210000582151 +:104C300000AE302B014B4821012638213C010800F1 +:104C4000AC250074000088213C010800AC270070EE +:104C50001100000F000000008F6200742619FFFF92 +:104C60003208007F0002FE0233E5007F15000006D7 +:104C7000332200FF2407FF800207202624A3FFFF22 +:104C800000838025320200FF00408021241110089B +:104C90000E000060000000008F4908183125000454 +:104CA00014A0FFFD3218007F001878C00018714072 +:104CB00001CF682125AC0088AF4C0818274A09802D +:104CC0008D4B0020AF4B01448D460024AF46014878 +:104CD000A35001500E000062A7400158022010218D +:104CE0008FBF00188FB100148FB0001003E00008D0 +:104CF00027BD002027BDFFE8308400FFAFBF0010B4 +:104D00000E0005B930A500FF8F8300508FBF001043 +:104D1000344500402404FF903C02100027BD0018D9 +:104D2000AF43014CA3440152AF45015403E00008D6 +:104D3000AF4201789343093E306200081040000DF5 +:104D40003C0901013528080AAC8800008F4700742F +:104D5000AC8700043C06080090C63CD030C500106B +:104D600050A00006AC8000088F6A0060AC8A000882 +:104D70002484000C03E00008008010210A000620B3 +:104D80002484000C27BDFFE8AFBF0014AFB00010B3 +:104D90009346093F00A05021000528800085382354 +:104DA00030C200FF240300063C09080095293CC6D8 +:104DB00024E8FFD82405000410430037240600022D +:104DC0009750093C3C0F020400063400320EFFFFEE +:104DD00001CF6825AC8D0000934C093E318B00203B +:104DE0001160000800000000934309363C020103F3 +:104DF000345F0300307900FF033FC025240500081D +:104E0000AC98000493430934935909210005F882B2 +:104E1000306200FF0002C082332F00FF00186E00D6 +:104E2000000F740001AE6025018920253C09400077 +:104E300000898025ACF0FFD8934309378F4F09488C +:104E40008F580940306200FF004AC821033F70219B +:104E500001F86023000E6F0001A650253185FFFF89 +:104E6000001F58800145482501683821AD09002000 +:104E70000E00006024F00028240400040E000062EC +:104E8000A364003F020010218FBF00148FB00010F8 +:104E900003E0000827BD00180A00063324060012AC +:104EA00027BDFFD024090010AFB60028AFB50024FD +:104EB000AFB40020AFB10014AFB000103C01080047 +:104EC000A0293CD0AFBF002CAFB3001CAFB200187C +:104ED00097480908309500FF3C02000E3107FFFF9C +:104EE000000731C0AF46002C974409089344010BDA +:104EF00030B400FF03428021308300300000B02135 +:104F00001060010700008821240C00043C01080007 +:104F1000A02C3CD0934B093E000B5600000A2E03F8 +:104F200004A0014B00000000AF400048934F010B6C +:104F300031EE002011C00006000000009358093E29 +:104F400000189E00001396030640016B000000004D +:104F50009344010B30830040106000038F93005096 +:104F60008F8200502453FFFF9347093E30E600082C +:104F700014C0000224120003000090219619002C96 +:104F800093580934934F0937A7990058330C00FF01 +:104F900031EE00FF024E6821000D5880016C502157 +:104FA000015140213C010800A4283CC6920500188C +:104FB00030A900FF010918213C010800A4233CC8C6 +:104FC00092110018162000032467000A0000000D4B +:104FD0002467000A30F0FFFF3C010800A4233CCA0C +:104FE0003C010800A4203CC03C010800A4203CBCBB +:104FF0000E00009E020020210E00049A0040202195 +:105000008F4B002C974A09083C0C000E034C3821AA +:105010003145FFFF000549C0AF49002C97430908FF +:1050200094F1001A00404021241F00013226FFFFA6 +:10503000AC4600008CE2001CAD0200048CE40020B1 +:10504000AD04000890E3001930630003107F00D620 +:10505000286D000215A0011C240E0002106E010E26 +:10506000240F0003106F00E3000000003C0908005B +:1050700095293CC0934E0934935109213C0A0800FC +:10508000954A3CC631CD00FF94F9002A000D1882E4 +:1050900097870058322C00FF00032E00000C2400DC +:1050A0003126FFFF3142FFFF00A4F82500464821CA +:1050B00003E97825032770213C18400001F8682592 +:1050C000000E8C00AD0D0000AD110004934C0920C2 +:1050D0003C03000625110014000C2E0000A310252F +:1050E000AD0200088F49092C24E40001309F7FFFA6 +:1050F000AD09000C8F46093025090028A79F0058EC +:10510000AD0600108F59093801203021AD19001467 +:10511000AE3300048F580940AE380008934F09376A +:105120003C0C0800918C3CD0AE20001031EE00FF0A +:1051300001D26821000D2F00000C1C0000A31025D7 +:105140003447FFFFAE27000CAF4B002C934B093EBA +:10515000317300081260000D3C0F010135E7080AA9 +:10516000AD0700288F4B0074AD2B00043C130800E2 +:1051700092733CD03268001051000003AD2000084B +:105180008F780060AD3800082526000C12C000386A +:1051900000000000935F093F241600062407000466 +:1051A00033F900FF133600D2240800029743093C6C +:1051B0003C0C02043064FFFF008C2825ACC50000C5 +:1051C0009342093E304900201120000800000000F1 +:1051D000934B09363C130103366E0300316D00FF1B +:1051E00001AE8825ACD10004240700089349093496 +:1051F00093590921314BFFFF313F00FF001FB0825F +:10520000333800FF0016560000187C00014F982527 +:1052100000122880026B68253C0E400000C5502318 +:1052200001AE8825AD51FFD8934309378F5F0948F8 +:105230008F490940306C00FF019210210007208245 +:105240000044C82103E978230019C7000008B4000E +:105250000316402531E7FFFF010730250E000060EF +:10526000AD46FFF8241200040E000062A372003F56 +:105270000E0000C7020020213C12080092523CD0D0 +:10528000325000031200000F02A020218F82005034 +:1052900024470001AF870050AF6700508F6800546B +:1052A0000107302318C0000200E020218F64005461 +:1052B000AF6400548F4C0074258401F4AF64000C7B +:1052C00002A0202102802821A76000680E0005B9F5 +:1052D0003C1410008F8D005034550006AF4D014C2A +:1052E0008F9100488FBF002C8FB600282623000125 +:1052F000AF8300488FB3001CA35101528FB2001836 +:10530000AF5501548FB10014AF5401788FB500240C +:105310008FB400208FB0001003E0000827BD0030DC +:105320009358093E00189E00001396030642005150 +:105330002411000293440923308300021060FEFB15 +:105340008F8600608F82005014C2FEF800000000BB +:105350000E000060000000009369003F2407001663 +:10536000312800FF1107000C240500083C0C080040 +:10537000918C3CD0358B00013C010800A02B3CD027 +:10538000936A003F314300FF10650065240D000A59 +:10539000106D005E2402000C0E0000620000000090 +:1053A0000A00068E000000003C09080095293CC058 +:1053B0003C04080094843CCA3C1F080097FF3CBC96 +:1053C00094F800243123FFFF0083C821033F782392 +:1053D00000186C0025EEFFF201AE6025240A0800DB +:1053E000AD0C000CAD0A0014AD0000100A0006E080 +:1053F000250800183C09080095293CC03C1F0800FE +:1054000097FF3CCA3C19080097393CBC94EF002434 +:105410003124FFFF94EE002803E4C0210319682320 +:10542000000F2C00000E540025ACFFEE014C882527 +:1054300034A2810024060800AD02000CAD1100105A +:10544000AD060018AD0000140A0006E02508001C97 +:105450008F6E00848F4D094011A0FEB3AF8E0050B7 +:10546000240F00143C010800A02F3CD00A00068D38 +:10547000000000003C010800A0313CD0935F093ED1 +:105480002416000133F900201720FEA8241100087B +:105490000A00068E2411000494E5002494F10028EB +:1054A0003C09080095293CC0000514000011340097 +:1054B0003444810034C30800AD04000CAD03001077 +:1054C0000A0006E0250800141460FEE80000000051 +:1054D00094FF00243C09080095293CC0001FCC0023 +:1054E00037380800AD18000C0A0006E02508001047 +:1054F0000A00072E240800128F7F004CAF7F005453 +:105500008F7900540A000697AF790050A362003FDC +:105510000E000062000000000A00068E000000007D +:10552000240200140A000807A362003F27BDFFE819 +:10553000308400FFAFBF00100E0005B930A500FF9A +:105540009378007E9379007F936E00809368007A51 +:10555000332F00FF00186600000F6C0031CB00FFF6 +:10556000018D4825000B52008FBF0010012A3825FD +:10557000310600FF3444700000E628252402FF8134 +:105580003C03100027BD0018AF45014CAF44015447 +:10559000A342015203E00008AF43017827BDFFD8C2 +:1055A000AFB20018AFB10014AFB00010AFBF002011 +:1055B000AFB3001C93420109308600FF30B000FFFA +:1055C000000618C232040002307100011480000588 +:1055D000305200FF9367000530E5000810A0000D71 +:1055E00030C80010024020210E0005A5022028210D +:1055F000240400018FBF00208FB3001C8FB200185D +:105600008FB100148FB000100080102103E000085B +:1056100027BD002815000032000000009343010957 +:10562000000028213062007F000220C00002F94003 +:1056300003E4982126790088033B98218E78002482 +:105640008E6F0008130F0046000000008F64008476 +:10565000241800020004FD8233F900031338007C93 +:105660000000000093660083934A0109514600043C +:105670003205007C10A00060000000003205007CB4 +:1056800014A000530240202116200006320400011D +:105690008E7F00248F59010417F9FFD600002021C6 +:1056A000320400011080000A024020218F4209408C +:1056B0008F93006410530006000000000E00066B7C +:1056C000022028218F430940AF630044024020217B +:1056D0000E000600022028210A00084024040001D0 +:1056E0003C0908008D290064252600013C010800C2 +:1056F000AC26006416000012000000008F6D0084CC +:105700003C0E00C001AE602415800005024020213F +:105710000E00080E022028210A000840240400017F +:10572000240500040E00056E24060001024020211D +:105730000E00080E022028210A000840240400015F +:105740000E00004124040001936B007D020B5025E4 +:105750000E000062A36A007D0A0008838F6D00843A +:105760008F6600748F4801048E67002400064E0285 +:105770001507FFB63126007F936B00832644000196 +:10578000308A007F11460043316300FF5464FFB04C +:105790008F6400842645000130B1007F30A200FFF5 +:1057A0001226000424050001004090210A0008563A +:1057B00024110001240FFF80024F702401CF902696 +:1057C000324200FF004090210A00085624110001D7 +:1057D0000E00066B02202821321800301300FFAAA9 +:1057E00032100082024020210E0005A5022028214F +:1057F0000A000840240400018F6E00743C0F8000F2 +:105800002405000301CF9025AF72007493710083CB +:10581000240600010E00056E322400FF0E00004138 +:1058200024040001936D007D020D60250E000062CE +:10583000A36C007D3C0B08008D6B005425700001AB +:105840003C010800AC3000540A0008402404000168 +:105850008F6800743C098000240500040109382584 +:10586000AF67007493630083240600010E00056E89 +:10587000306400FF0E000041240400019362007DAB +:10588000020298250E000062A373007D0A00084002 +:1058900024040001324D008039AC0080546CFF6C50 +:1058A0008F6400840A0008A92645000127BDFFC8AF +:1058B0003C0A0008AFBF0030AFB5002CAFB40028E1 +:1058C000AFB30024AFB20020AFB1001CAFB00018DE +:1058D000034AD82124090040AF490814AF400810FA +:1058E0008F4209448F4309508F4609548F47095C02 +:1058F0008F48094C934401089345010BAF82006423 +:10590000308400FF30A500FFAF830050AF86004C0D +:10591000AF87005C0E00082AAF8800601440017455 +:105920008FBF0030A7600068934D0900240B005022 +:105930003C15080026B53C8831AC00FF3C1208003D +:1059400026523C98118B0003000000000000A821A3 +:1059500000009021935101098F9F005024040010F2 +:10596000322E007F000E68C0000E6140018D28219C +:1059700024B40088AF5408188F4901048F4A09A441 +:105980003C0B000E034BC021012A10233C010800F0 +:10599000AC223CAC8F4309583C010800A0243CD009 +:1059A00097470908007F30233C010800AC263CB033 +:1059B00030E8FFFF0008C9C03C010800AC3F3CD400 +:1059C000AF59002C974209089710002C8EB10000A7 +:1059D000930F001803749821A7900058AF930044C8 +:1059E0000220F80931F000FF304E000215C001A975 +:1059F000304F000111E0015D000000009343093EBB +:105A00003066000814C00002241400030000A02126 +:105A10008F5809A4241300013C010800AC383CD87D +:105A2000934F09349351093731EC00FF322E00FFB8 +:105A3000028E6821000D288000AC502101505821B1 +:105A40003C010800A42B3CC83C010800A42A3CC629 +:105A500093490934312200FF0202202124900010D2 +:105A60003C010800A4303CC4240700068F9F00506E +:105A70003C010800AC273CCC8F88005C8F5909584A +:105A800000008021011F282304A00151033F20238F +:105A90000480014F00A4302B10C001510000000011 +:105AA0003C010800AC253CB08E4200000040F809E3 +:105AB0000000000030430002146000F10040882123 +:105AC00030440001548000108E4200043C0908005C +:105AD0008D293CB43C0AC000012A8025AF500E003D +:105AE0008F45000030AB00081160FFFD0000000092 +:105AF000974D0E0824100001A78D003C8F4C0E041A +:105B0000AF8C00348E4200040040F8090000000011 +:105B100002228825322E000215C0016F000000000D +:105B20003C09080095293CBC3C06080094C63CC8CA +:105B30003C04080094843CBE3C1808008F183CB418 +:105B4000012658213C0F08008DEF3CD83C1F08006F +:105B500097FF3CD2016418218F4D09400309C821E9 +:105B6000246E0002033F282101F860213C01080057 +:105B7000A42B3CCAAF8D00643C010800AC2C3CD87F +:105B80003C010800A4253CC00E00009E31C4FFFF6C +:105B90008F870048004020213C010800A0273CD10D +:105BA0008E42000824E80001AF8800480040F80950 +:105BB000000000008F4B002C974909083C0A000E9A +:105BC000034A38213124FFFF000419C08F8A005096 +:105BD000AF43002C9743090894E6001A0040402187 +:105BE00030DFFFFFAC5F00008CF9001CAC590004F3 +:105BF0008CF80020AC58000890EF001931E3000346 +:105C0000107300FB0000000028620002144001171E +:105C10002405000210650109240C0003106C00BC6F +:105C2000000000003C09080095293CC0935F09343E +:105C3000934C09213C0D080095AD3CC633F900FF9B +:105C400094E5002A0019C082318F00FF978C00581C +:105C500000181600000F74003124FFFF004E382595 +:105C600001A4302100E6F82500ACC8213C03400027 +:105C700003E3C02500194C00AD180000AD09000475 +:105C8000934F09203C0E000625090014000F6E00FA +:105C900001AE2825AD0500088F46092C258200019C +:105CA00030477FFFAD06000C8F440930A7870058AE +:105CB00025060028AD0400108F43093800C02021BC +:105CC000AD030014AD2A00048F5F0940AD3F00080A +:105CD000935909373C0E080091CE3CD0AD200010FE +:105CE000333800FF03147821000F6700000E6C00AA +:105CF000018D282534A2FFFFAD22000CAF4B002CF4 +:105D00009347093E30EA00085140000F8E58000CBE +:105D10003C0301013469080AAD0900288F4A007468 +:105D2000ACCA00043C0B0800916B3CD031680010F9 +:105D300051000003ACC000088F650060ACC50008CE +:105D400024C4000C8E58000C0300F8090000000069 +:105D50003C0F080095EF3CCA3C02080094423CBE50 +:105D600001E2702125C400020E0000C73084FFFF4D +:105D70003C0608008CC63CAC3C0D08008DAD3CB424 +:105D800000CD38233C010800AC273CAC14E00006F1 +:105D9000000000003C1908008F393CCC372C004033 +:105DA0003C010800AC2C3CCC120000858F8B0044D9 +:105DB0008F480E108F900044AE0800208F5F0E18A1 +:105DC000AE1F00243C10080096103CC00E0000607E +:105DD0000000000024050040AF4508148F830050E8 +:105DE0008F89004C0070182100695023194000046D +:105DF000AF830050AF6300548F670054AF87004CEF +:105E00001200000C000000008F440074936D0081AC +:105E1000340EFA002DA6000710C00005008E1821D0 +:105E200093780081240201F40302780401E418212C +:105E3000AF63000C8F4C095C8F99005C01992023A3 +:105E400018800003000000008F50095CAF90005CD8 +:105E50000E000062000000008F8B00508E48001082 +:105E60003C010800AC2B3CD40100F8090000000004 +:105E70003C1F08008FFF3CAC17E0FEFC2407000627 +:105E80008F450024974209088F8A00648F94005040 +:105E90003C0F001F978700588F8300548F93004C4E +:105EA000304DFFFF35EEFF8000AE4824000D31C0BD +:105EB00032320010AF460024A467002CAF49002402 +:105EC000AF6A0044AF740050AF7300545640007E78 +:105ED0008EB8000432240040548000328EB1000895 +:105EE0008EAC000C0180F809000000008FBF00306C +:105EF0008FB5002C8FB400288FB300248FB2002000 +:105F00008FB1001C8FB0001803E0000827BD0038D7 +:105F10003C09080095293CC03C04080094843CCA14 +:105F20003C1F080097FF3CBC94F800243123FFFF7E +:105F300094EF00280083C821033F702300182C0031 +:105F4000000F640025CDFFEE018D302534A28100C5 +:105F500024030800AD02000CAD060010AD030018CC +:105F6000AD0000140A0009CE2508001C9347010962 +:105F70008F8800380007FE0003E8C825AF5900806D +:105F80008F5809A08F5309A4AFB80010AF580E1452 +:105F90008FB40010AF540E10AF530E1C0A0009420C +:105FA000AF530E180220F809000000008EAC000C60 +:105FB0000180F809000000000A000A7F8FBF00304E +:105FC000A5600020A57300220A000A34AD730024E6 +:105FD0003C010800AC203CB00A00096E8E42000073 +:105FE0003C010800AC243CB00A00096E8E4200005F +:105FF0003C09080095293CC03C1F080097FF3CCA9B +:106000003C19080097393CBC94EF00243124FFFF71 +:1060100003E4C02103197023000F640025CDFFF2B3 +:10602000018D2825AC45000C24020800AD020014A7 +:10603000AD0000100A0009CE2508001894E60024DF +:1060400094E300283C09080095293CC00006240080 +:106050000003FC003499810037F80800AD19000CEA +:10606000AD1800100A0009CE250800141460FEEDDA +:106070000000000094EF00243C09080095293CC072 +:10608000000F740035CD0800AD0D000C0A0009CEDC +:106090002508001093520109000028210E00060077 +:1060A000324400FF8FBF00308FB5002C8FB4002822 +:1060B0008FB300248FB200208FB1001C8FB0001866 +:1060C00003E0000827BD00380300F80900000000C5 +:1060D0000A000A79322400401200FF690000000023 +:1060E0008F540E148F920044AE5400208F530E1C18 +:1060F0000A000A63AE5300248F82001C00804021F6 +:106100003C0401009047008530E300201060000946 +:10611000000000003C0708008CE73CD48F83001887 +:1061200000E32023048000089389000414E30003A3 +:106130000100202103E00008008010213C04010040 +:1061400003E00008008010211120000B00673823B5 +:106150008F8C002024090034918B00BC316A00022E +:10616000514000012409003000E9682B15A0FFF11F +:106170000100202100E938232419FFFC00B9C024C4 +:1061800000F9782400F8702B15C0FFEA01E82021FF +:1061900030C200030002182314C00012306900034B +:1061A0000000302100A9702101C6682100ED602B9C +:1061B0001180FFE03C0401002D2F00010006482B58 +:1061C0000105382101E9302414C0FFDA24E4FFFC82 +:1061D0002419FFFC00B9C0240308202103E00008B3 +:1061E000008010218F8B002024060004916A00BCDF +:1061F000314400041480FFEC00A970210A000B2D2B +:106200000000302127BDFFE8AFBF00108F4601001E +:10621000934A01093C1F08008FFF00902407FF806C +:10622000314F00FF31E8007F0008614003E6C821DC +:10623000032CC02127090120012770243C010800FC +:10624000A02F3D10AF4E080C3C0D08008DAD009006 +:106250003C0400803482000301A65821016C1821FF +:106260002465012030AA007801424025AF48081C6F +:106270003C1F08008FFF00908F88004003E6C0217C +:106280003319000703074824033A7821AF4900284F +:1062900025E909C0952E00023C0D08008DAD008C4B +:1062A0003C0A08008D4A009031CC3FFF01A618211E +:1062B000000C5980006B282100A72024AF44002C3B +:1062C000952200023C1F08008FFF008C910700857B +:1062D00030593FFF03E678210019C1800146702143 +:1062E00001F8682131CC007F31AB007F019A282171 +:1062F000017A50213C03000C3C04000E00A328212D +:106300000144102130E6002027470980AF82002C8D +:10631000AF88001CAF890024AF85002010C00006A4 +:10632000AF8700288D0200508CA4010C004430235C +:1063300018C0007700000000910C0085240DFFDFDD +:10634000018D3824A10700858F8B001C8F890024C4 +:106350008F8700288D65004CAF850018912F000DA8 +:1063600031EE002011C000170000000024090001D8 +:10637000A3890004AF80000C8CE400248F85000CFE +:10638000240A0008AF800008AF8000103C0108001C +:10639000A42A3CBE3C010800A4203CD20E000B0104 +:1063A000000030218F8500248FBF0010AF820014C1 +:1063B00090A8000D27BD00180008394203E000082E +:1063C00030E20001913F00022418000133F900FF80 +:1063D0000019218210980039240800021088005BFF +:1063E0008F86002C8CE5002414A0001B8F9F0020BA +:1063F00091220000240A00053046003F10CA0047E1 +:10640000240400018F860008A3840004AF860010D6 +:10641000AF86000C8CE400248F85000C240A000851 +:106420003C010800A42A3CBE3C010800A4203CD248 +:106430000E000B01000000008F8500248FBF0010AC +:10644000AF82001490A8000D27BD00180008394243 +:1064500003E0000830E200018CF800088CF9002409 +:106460008FEE00C4A38000048CE40024AF8E000CE7 +:106470008F85000C8F86000803197823240A0008F2 +:10648000AF8F00103C010800A42A3CBE3C0108006C +:10649000A4203CD20E000B01000000008F850024D8 +:1064A0008FBF0010AF82001490A8000D27BD001808 +:1064B0000008394203E0000830E2000191230000A7 +:1064C0003062003F104400278F8500208CE40024B8 +:1064D00014800021000000008D2E00183C187FFF62 +:1064E0008F850020370FFFFF01CF1824AF830008EE +:1064F0008F9F00088CA8008403E8C82B1720000297 +:1065000003E020218CA400840A000BBCAF840008A7 +:106510008CA3010C0A000B9AAF8300188D2C001875 +:106520008F8600083C0D7FFF8F89002035A3FFFF79 +:106530000183582424040001AF8B0010AD2000CC4F +:10654000A38400040A000BC8AF86000C8CCA001498 +:106550000A000BBCAF8A00088CA300C80A000BFF1E +:10656000AF8300088F84002C8CAC00648C8D0014E9 +:10657000018D582B11600004000000008CA2006403 +:106580000A000BFFAF8200088C8200140A000BFF88 +:10659000AF8200088F85000C27BDFFE0AFBF001859 +:1065A000AFB1001414A00007AFB000108F86002414 +:1065B0002402000590C400003083003F106200B642 +:1065C0008F8400208F91000800A080218F8C0028EC +:1065D0003C0508008CA53CB08D8B000431663FFF64 +:1065E00000C5502B5540000100C02821938D0004A8 +:1065F00011A0007300B0F82B8F9800202404003401 +:10660000930F00BC31EE000251C0000124040030A1 +:1066100000A4C82B172000D10000000000A42823EC +:1066200000B0F82B3C010800A4243CBC17E0006833 +:10663000020020213C0308008C633CAC0083102B3B +:1066400054400001008018218F8800243C0108007C +:10665000AC233CB4000048219104000D308300209D +:10666000506000018F490E188F8300140123382BCE +:1066700010E00059000000003C0408008C843CB489 +:1066800000895821006B502B114000560090602B60 +:106690000069302300C020213C010800AC263CB436 +:1066A00012000003241FFFFC1090008A3227000311 +:1066B000009FC8243C010800AC393CB43C010800F0 +:1066C000A4203CD28F84000C120400078F8300208A +:1066D000AF910008020020218C7100CCAF90000C1B +:1066E00026300001AC7000CC3C0208008C423CB467 +:1066F0008F8A0010240700180082202301422823DB +:10670000AF84000C10800002AF8500102407001039 +:106710008F86001C3C010800A0273CD024070040C5 +:1067200090CC0085318B00C0116700408F8D001424 +:1067300014A0001500002021934A01098F4209741A +:10674000314500FF0002260224A300013090007FA3 +:106750003071007F1230007A2407FF80A0C30083CD +:106760003C0908008D293CCC8F880024240D0002B0 +:10677000352C00083C010800A02D3D113C0108000B +:10678000AC2C3CCC24040010910E000D31C600202E +:1067900010C0000500801821240800013C010800F9 +:1067A000AC283CB4348300018FBF00188FB10014B3 +:1067B0008FB000100060102103E0000827BD00200A +:1067C0003C010800A4203CBC13E0FF9A02002021F9 +:1067D0000A000C5000A020213C0408008C843CB42A +:1067E0000090602B1180FFAE000000003C0F0800FD +:1067F00095EF3CBC01E4702101C6682B11A0000795 +:106800002C8200043C1F60008FF954043338003F91 +:106810001700FFE5240300422C8200041040FFA073 +:10682000240300420A000CAE8FBF0018152DFFC0D4 +:10683000000000008CDF00743C0380002405FF8012 +:1068400003E3C825ACD9007490D80085240E000459 +:1068500024040010330F003F01E54025A0C8008547 +:106860008F8800243C010800A02E3D112403000164 +:106870009106000D30C90020152000030000000023 +:106880003C0308008C633CB43C010800AC233CACE6 +:106890000A000CA5000000008F8700108C8800847F +:1068A00000E8282B14A0000200E088218C910084CD +:1068B00024090001A38900048F440E180220282116 +:1068C0000E000B0102203021022080210A000C362C +:1068D000AF82001400071823306600033C01080053 +:1068E000A4263CD2122000058F8C0020918B00BC86 +:1068F000316A00041540001524CD00043C0F080047 +:1069000095EF3CD201E4702100AE302B50C0FF6EF9 +:106910008F84000C2C85000514A0FFA324030042E3 +:106920003098000317000002009818232483FFFC0E +:106930003C010800AC233CB40A000C7200000000CB +:1069400000A758240A000C9A016718263C01080089 +:10695000A42D3CD20A000D02000000003C010800FA +:10696000AC203CB40A000CAD240300428F8300101D +:1069700014600007000010218F8800242405000502 +:106980009106000030C400FF1085000300000000E5 +:1069900003E0000800000000910A0018314900FFE0 +:1069A000000939C214E0FFFA8F85001C3C0408007E +:1069B00094843CBC3C0308008C633CD43C19080024 +:1069C0008F393CB43C0F080095EF3CD20064C021E5 +:1069D0008CAD00540319702101CF6021018D582323 +:1069E0001960001D00000000910E001C8F8C002C0F +:1069F000974B0E1031CD00FF8D850004016D3023C3 +:106A00008D88000030CEFFFF000E510000AAC82183 +:106A10000000382101072021032A182B0083C02100 +:106A2000AD990004AD980000918F000A01CF682154 +:106A3000A18D000A8F88002C974B0E12A50B000821 +:106A4000950A003825490001A50900389107000D75 +:106A500034E60008A106000D03E000080000000075 +:106A600027BDFFE0938700048F8F00248FAD0014B3 +:106A70003C0E7FFF8F89000C35C8FFFFAFBF001CA5 +:106A8000AFB0001801A8182491EA000D000717C044 +:106A90003C1FBFFF006258252D2E00018F9000186B +:106AA00037F9FFFF3C1808008F183CD43C0F080052 +:106AB00095EF3CCA01796824000E47803C07EFFF40 +:106AC0003C05F0FF01A818253149002034E2FFFF02 +:106AD00034ACFFFF0310582327A500102406000242 +:106AE00025EA00020062182400808021152000029F +:106AF000000040218F480E1CA7AA00120560003735 +:106B00002407000030FF00FF001FCF008F8B001C08 +:106B100000793825AFA70014916F00853C08080064 +:106B200091083CD13C18DFFF31EE00C0370AFFFF6F +:106B3000000E182B3C1F080097FF3CC400EA682495 +:106B4000A3A800110003174001A248258FB9001027 +:106B5000AFA900143C0A0800914A3CD3A7BF001615 +:106B60008FA80014032CC0243C0B01003C0F0FFF26 +:106B7000030B18253147000335EEFFFF010C682495 +:106B800000071600006EF8243C09700001A2C82519 +:106B900003E95825AFB90014AFAB00100E00007622 +:106BA000A3A000158F8C0024260200089186000DFA +:106BB00030C40020108000068FBF001C3C05080078 +:106BC00094A53CC024B0FFFF3C010800A4303CC0A9 +:106BD0008FB0001803E0000827BD00208F98001434 +:106BE0000118502B5540FFC7240700010A000D85EE +:106BF00030FF00FF9382000427BDFFE0AFBF001805 +:106C00001040000F008050218F880024240B0005C5 +:106C10008F890008910700008F840020010028213F +:106C200030E3003F8F86002C106B000800003821F5 +:106C3000AFA900100E00040EAFAA0014A380000438 +:106C40008FBF001803E0000827BD00208D19001831 +:106C50003C0F08008DEF3CB48F9800103C027FFF82 +:106C60008D080014345FFFFF033F682401F8702192 +:106C700001AE602301883821AFA900100E00040E78 +:106C8000AFAA00140A000DD3A38000048F8700244C +:106C90003C05080094A53CD23C0208008C423CCC48 +:106CA00090E6000D0005240030C300201060002C89 +:106CB000004440258F85001C00006021240B00014A +:106CC00090A3008500004821240A00013C0F8000A9 +:106CD00035EE00708DC70000AF8700308F58017807 +:106CE0000700FFFE3C038000347900708F380000FD +:106CF0003C0508008CA500743C0D08008DAD0070AB +:106D00000307782300AF38210000102100EF302B5B +:106D100001A22021008618213C010800AC27007444 +:106D20003C010800AC230070AF4B01483C1908003F +:106D30008F393CD4A7490144A74A0146AF59014CB9 +:106D40003C0B0800916B3CD1A34B0152AF4801545E +:106D50003C081000A74C015803E00008AF48017838 +:106D60008F4B0E1C3C0A08008D4A3CB497490E1606 +:106D7000974D0E1401456021312AFFFF0A000DF6E0 +:106D800031A9FFFF8F8300249064000D3082002022 +:106D900010400029000000000000482100005021A0 +:106DA000000040213C07800034EB00708D6700003C +:106DB000AF8700308F4C01780580FFFE3C0D8000CE +:106DC00035AC00708D8B00003C0508008CA500746C +:106DD0003C0408008C8400700167302300A67821F1 +:106DE0000000102101E6C82B0082C0210319702188 +:106DF0003C010800AC2F00743C010800AC2E007070 +:106E0000AF4901483C0D08008DAD3CD4A748014472 +:106E100024090040A74A01463C081000240AFF91BB +:106E2000AF4D014CA34A0152AF490154A74001584C +:106E300003E00008AF4801788F490E1897460E12FC +:106E400097450E1030CAFFFF0A000E2C30A8FFFF36 +:106E50008F83002427BDFFF89064000D308200204E +:106E60001040003A00000000240B000100004821FF +:106E7000240A00013C088000350700708CE3000004 +:106E8000AF8300308F4C01780580FFFE3C0E800000 +:106E90003C04080090843D1035C700708CEC000065 +:106EA0003C0508008CA50074A3A400033C1908004D +:106EB0008F3900708FAD00000183302300A6382188 +:106EC000000010210322782100E6C02B01F8602188 +:106ED00001AE4025AFA800003C010800AC270074BB +:106EE0003C010800AC2C00709346010A3C040800E9 +:106EF00090843D11A3A00002A3A600018FA300006F +:106F00003C0580FF3099007F34A2FFFF00627824A7 +:106F10000019C60001F87025240D3000AF4E014C59 +:106F200027BD0008AF4D0154A7400158AF4B0148A1 +:106F3000A7490144A74A01463C091000240AFF80E2 +:106F4000A34A015203E00008AF4901788F4B0E18A5 +:106F500097460E1297450E1030CAFFFF0A000E60CA +:106F600030A9FFFF8F85001C2402008090A40085BB +:106F7000308300C0106200058F8600208F880008D3 +:106F80008F87000CACC800C8ACC700C403E0000881 +:106F9000000000003C0A0800254A38903C0908001F +:106FA0002529395C3C08080025082D103C070800FD +:106FB00024E73A703C06080024C637003C05080068 +:106FC00024A534783C040800248430A03C03080045 +:106FD000246337983C0208002442356C3C010800C9 +:106FE000AC2A3C903C010800AC293C8C3C010800D8 +:106FF000AC283C883C010800AC273C943C010800CC +:10700000AC263CA43C010800AC253C9C3C0108009B +:10701000AC243C983C010800AC233CA83C0108008F +:0C702000AC223CA003E0000800000000CF +:00000001FF +/* + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ diff --git a/firmware/bnx2/bnx2-mips-09-5.0.0.j3.fw.ihex b/firmware/bnx2/bnx2-mips-09-5.0.0.j3.fw.ihex deleted file mode 100644 index 92e220473c71..000000000000 --- a/firmware/bnx2/bnx2-mips-09-5.0.0.j3.fw.ihex +++ /dev/null @@ -1,6051 +0,0 @@ -:100000000800011008000000000051C4000000C8F2 -:10001000000000000000000000000000080051C4C3 -:10002000000000380000528C080000880800000022 -:10003000000051B4000052C4080053A00000008426 -:100040000000A478080051B4000001C00000A4FC26 -:10005000080031D808000000000080E40000A6BCC1 -:10006000000000000000000000000000080080E424 -:1000700000000124000127A00800048808000400F3 -:10008000000017EC000128C4000000000000000080 -:100090000000000008001BEC00000004000140B05C -:1000A000080000A80800000000003814000140B457 -:1000B00000000000000000000000000008003814EC -:0800C00000000030000178C8C7 -:0800C8000A00004400000000E2 -:1000D000000000000000000D636F6D352E302E30E3 -:1000E0006A33000005000002000000000000000369 -:1000F00000000014000000320000000300000000B7 -:1001000000000000000000000000000000000000EF -:1001100000000010000001360000EA600000000549 -:1001200000000000000000000000000000000008C7 -:1001300000000000000000000000000000000000BF -:1001400000000000000000000000000000000000AF -:10015000000000000000000000000000000000009F -:10016000000000020000000000000000000000008D -:10017000000000000000000000000000000000007F -:10018000000000000000000000000010000000005F -:10019000000000000000000000000000000000005F -:1001A000000000000000000000000000000000004F -:1001B000000000000000000000000000000000003F -:1001C000000000000000000000000000000000002F -:1001D000000000000000000000000000100000030C -:1001E000000000000000000D0000000D3C020800AF -:1001F000244252203C03080024635354AC400000C6 -:100200000043202B1480FFFD244200043C1D080005 -:1002100037BD9FFC03A0F0213C1008002610011000 -:100220003C1C0800279C52200E00025F00000000CA -:100230000000000D27BDFFE0AFBF0018AFB10014F4 -:10024000AFB000103C04800094820108304370007D -:10025000240220001062000B2862200114400036A6 -:1002600000001021240240001062002C0000000059 -:10027000240260001062002D000010210A00009D81 -:100280008FBF001834910100922400098E300018AD -:1002900010800020240300012402000914820006BB -:1002A0008F82001C3C0280089442001A0002140055 -:1002B000020280258F82001C8C42000C1040001529 -:1002C000000018210E000D45000000008F83001C67 -:1002D000962400088F8200189463001E9625000C57 -:1002E0000004240000832025AC500000AC4500042D -:1002F000AC400008AC40000CAC400010AC40001416 -:10030000AC400018AC44001C0E000D792404000120 -:10031000000018210A00009C006010210E00042E2D -:10032000000000000A00009C000010210E000C6577 -:1003300000000000000010218FBF00188FB10014D2 -:100340008FB0001003E0000827BD00208F82001C42 -:1003500027BDFFE0AFB00010AFBF0018AFB1001471 -:100360008C42000C3C1080008E11010010400034C3 -:100370008FBF00180E000D45000000008F8500188B -:1003800024047FFF0091202BACB100008E030104F8 -:100390009602010800031C003042FFFF006218258E -:1003A000ACA300049202010A96030114304200FF3C -:1003B0003063FFFF0002140000431025ACA20008C8 -:1003C0009603010C9602010E00031C003042FFFF51 -:1003D00000621825ACA3000C9603011096020112CE -:1003E00000031C003042FFFF00621825ACA3001080 -:1003F0008E020118ACA200148E02011CACA20018DF -:10040000148000088F82001C978200003C042005A5 -:100410000044182524420001ACA3001C0A0000DBA4 -:10042000A78200003C0340189442001E00431025A0 -:10043000ACA2001C0E000D79240400018FBF00182F -:100440008FB100148FB000100000102103E00008ED -:1004500027BD00203C0680008CC202B824030001A6 -:1004600004410008008028213C0208008C42006002 -:10047000244200013C010800AC22006003E00008B7 -:10048000006010218C83002094820016ACC302808F -:100490002442FFFCA4C202843C0208008C42005C9F -:1004A0008C84000494A3000E244200013C01080047 -:1004B000AC22005C3C021000A4C30286ACC40288DB -:1004C00000001821ACC202B803E00008006010214F -:1004D00027BDFFE0AFB000103C108000AFB20018A5 -:1004E000AFBF001CAFB10014361201009243000BE5 -:1004F0002402001A965100081462005A00002821B4 -:1005000032220001104000188F82001C8E42000031 -:10051000000223403C02003F3442FFFF0044102B06 -:10052000104000043C030040964200140A000124DD -:10053000008320218E030100240201005462000682 -:10054000964200143C028008904200043042000FA2 -:10055000000225009642001400821025AE020080A1 -:100560000A000157000000008C42000C10400028D7 -:10057000000000000E000D4500000000960201087A -:100580009603010C8F8500183042003E3063FFFF58 -:100590000002140000431025ACA200008E020100EE -:1005A000ACA20004960301169604010E8F82001C73 -:1005B00000031C003084FFFF00641825ACA3000872 -:1005C00096030110960401129446001E00031C00BD -:1005D0003084FFFF00641825ACA3000C3C0220000F -:1005E00000C2302596020114240400013042FFFFAE -:1005F000ACA200108E020118ACA200149202010BF2 -:10060000304200FFACA200180E000D79ACA6001C11 -:100610003C0208008C420040244200013C010800DA -:10062000AC2200403C0308008C63004432220002EC -:1006300032240004246300013C010800AC23004480 -:10064000108000080002282B024020218FBF001CD0 -:100650008FB200188FB100148FB000100A0000E3B1 -:1006600027BD00208FBF001C8FB200188FB100146F -:100670008FB0001000A0102103E0000827BD00206B -:1006800027BDFFE0AFB000103C108000AFB20018F3 -:10069000AFBF001CAFB10014361201009243000B33 -:1006A000240200031462006A9651000832220001FD -:1006B000104000178F82001C8E4300003C02003F58 -:1006C0003442FFFF000323400044102B504000053C -:1006D00024020100964200143C0300400A00018EEF -:1006E0000083202154620006964200143C028008D8 -:1006F000904200043042000F000225009642001490 -:1007000000821025AE0200800A0001BE0000000039 -:100710008C42000C10400025000000000E000D452A -:1007200000000000960201089603010C8F85001856 -:100730003042003E3063FFFF0002140000431025EA -:10074000ACA200008E020100ACA2000496030116C8 -:100750009604010E8F82001C00031C003084FFFFF2 -:1007600000641825ACA3000896030110960401123A -:100770009446001E00031C003084FFFF006418250F -:10078000ACA3000C3C02200000C2302596020114EC -:10079000240400013042FFFFACA20010ACA0001402 -:1007A000ACA000180E000D79ACA6001C3C0208009D -:1007B0008C420040244200013C010800AC22004071 -:1007C0003C0208008C420044322300042442000111 -:1007D0003C010800AC2200441060000832220002F4 -:1007E000024020218FBF001C8FB200188FB100146F -:1007F0008FB000100A0000E327BD00201040001554 -:100800008FBF001C3C0480008C8301043C026020EC -:10081000AC4300148C420004240301FE304203FF69 -:100820001443000C8FBF001C8C820100000219C20F -:100830002462FFFC2C420008104000032404000244 -:100840002462FFFD004420043C026000AC446914B3 -:100850008FBF001C8FB200188FB100148FB0001032 -:100860000000102103E0000827BD00203C048000A8 -:100870008C83010024020100506200033C028008C6 -:100880000000000D3C02800890430004000010218D -:100890003063000F00031D0003E00008AC830080FC -:1008A0002C8407811080000A000028213C0280006F -:1008B00094420108240320003042700014430005D4 -:1008C0002783FFB03C02800890420005304500FFBE -:1008D0002783FFB00005208000832021000510C081 -:1008E000004510238C8400003C030800246352E47C -:1008F000000210C0004310213C038000AC64009053 -:1009000003E00008AF82001C03E000080000102193 -:1009100003E00008000010212402010014820008F6 -:10092000000000003C0208008C4200FC2442000150 -:100930003C010800AC2200FC0A00022430A2002086 -:100940003C0208008C420084244200013C01080063 -:10095000AC22008430A200201040000830A3001018 -:100960003C0208008C420108244200013C010800BE -:10097000AC22010803E0000800000000106000083D -:10098000000000003C0208008C42010424420001E7 -:100990003C010800AC22010403E000080000000054 -:1009A0003C0208008C420100244200013C01080086 -:1009B000AC22010003E000080000000027BDFFE8B2 -:1009C000AFB000103C108000AFBF0014360401002F -:1009D0009483000830620004104000053066000275 -:1009E0008FBF00148FB000100A0000E327BD00186D -:1009F00010C00006006028218E0401000E000214C1 -:100A0000000000000A00025B240200018F8200083F -:100A10008E03010410430007000010218E04010022 -:100A20000E000214000000008E020104AF820008D4 -:100A3000000010218FBF00148FB0001003E00008E9 -:100A400027BD001827BDFFD83C036010AFB3001CC2 -:100A5000AFBF0020AFB20018AFB10014AFB00010AC -:100A60008C6450002402FF7F3C1308002673524818 -:100A7000008220243484380CAC6450003C02800096 -:100A800024030037AC4300083C06080024C6084095 -:100A9000026010212404001C2484FFFFAC460000E7 -:100AA0000481FFFD244200043C0208002442016C42 -:100AB0003C010800AC2252503C020800244205B818 -:100AC0003C010800AC2252543C020800244202843B -:100AD0003C010800AC2252903C0208002442040869 -:100AE0003C030800246308483C040800248408F4FC -:100AF0003C05080024A52C4C3C010800AC2252B057 -:100B00003C020800244207A43C010800AC2652988D -:100B10003C010800AC2552A43C010800AC2352ACB7 -:100B20003C010800AC2452B43C010800AC2252B88D -:100B30003C010800AC23524C3C010800AC20525848 -:100B40003C010800AC20525C3C010800AC20526023 -:100B50003C010800AC2052643C010800AC20526803 -:100B60003C010800AC20526C3C010800AC205270E3 -:100B70003C010800AC2452743C010800AC205278BF -:100B80003C010800AC20527C3C010800AC205280A3 -:100B90003C010800AC2052843C010800AC20528883 -:100BA0003C010800AC26528C3C010800AC26529453 -:100BB0003C010800AC20529C3C010800AC2552A02E -:100BC0003C010800AC2352A80E00055A00000000AA -:100BD0008F8300043C0208008C4200201062001F3A -:100BE000000088212792FFB03C100800261052E434 -:100BF0003C0208008C420020240500010225180454 -:100C0000004320248F820004004310245044000C31 -:100C10002631000110800008AF90001C8E430000B8 -:100C20003C028000AC4300900E000D0CAE05000CA1 -:100C30000A0002DE26310001AE00000C2631000160 -:100C40002E220002261000381440FFE9265200042C -:100C50003C0208008C420020AF8200043C1080005F -:100C60008E110000322200071040FFDA8F8300044B -:100C70003222000110400021322200028E020100C7 -:100C8000AE0200208E020104AE0200A80E0001F6A2 -:100C90008E0401009202010B304300FF2C62001D04 -:100CA00054400004000310800E0002100A0002FFEE -:100CB00000000000005310218C4200000040F809A1 -:100CC00000000000104000043C0280008C4301043E -:100CD0003C026020AC4300143C0208008C4200340B -:100CE0003C0440003C03800024420001AC64013815 -:100CF0003C010800AC2200343222000210400010F7 -:100D0000322200043C1080008E020140AE0200201E -:100D10000E0001F68E0401400E0003970000000053 -:100D20003C024000AE0201783C0208008C420038D0 -:100D3000244200013C010800AC22003832220004A9 -:100D40001040FFA48F8300043C1080008E020180BD -:100D5000AE0200200E0001F68E0401808E03018099 -:100D600024020F00146200073C0280088E020188F2 -:100D70003C0300E03042FFFF004310250A00033B24 -:100D8000AE020080344200809042000024030050F4 -:100D9000304200FF14430007000000000E000374FF -:100DA0000000000014400003000000000E00095D78 -:100DB000000000003C0208008C42003C3C04400063 -:100DC0003C03800024420001AC6401B83C010800EF -:100DD000AC22003C0A0002C38F8300043C02900056 -:100DE00034420001008220253C028000AC440020F7 -:100DF0003C0380008C6200200440FFFE00000000E5 -:100E000003E00008000000003C02800034430001C1 -:100E10000083202503E00008AC44002027BDFFE04C -:100E2000AFB10014AFB0001000808821AFBF001830 -:100E30000E00034530B000FF8F83FFA80220202161 -:100E40009062002502028025A07000258C70001899 -:100E50003C0280000E000350020280241600000AAB -:100E60008FBF00183C0380008C6201F80440FFFE35 -:100E700024020002AC7101C0A06201C43C02100057 -:100E8000AC6201F88FBF00188FB100148FB0001052 -:100E900003E0000827BD002027BDFFE8AFBF00101A -:100EA0003C0380009462018430420200104000053F -:100EB000000020210E000FCD000000000A00038A70 -:100EC000240400018C6201880440000A8FBF0010D6 -:100ED0008C6201883C03FF00004310243C030400A3 -:100EE00014430004240400018F82FFA890420008EC -:100EF0008FBF00100080102103E0000827BD0018FC -:100F00008F82FFAC2403000124050001A040001AD9 -:100F10008F82FFA8A44300163C0280000A000355FC -:100F20008C4401408F85FFA827BDFFE0AFBF001CA8 -:100F3000AFB20018AFB10014AFB0001090A2000023 -:100F4000304400FF38830020388200300003182B23 -:100F50000002102B00621824106000053C02800083 -:100F600024020050148200818FBF001C3C028000CC -:100F700090420148304200FF2443FFFF2C620005ED -:100F80001040007A8FBF001C000310803C03080053 -:100F9000246351DC004310218C4200000040000813 -:100FA000000000003C1180008E2401400E0003452B -:100FB0008F92FFA88E50000C8E2201441602000270 -:100FC00024020001AE42000C0E0003508E240140AA -:100FD0008E220144145000068FBF001C8FB20018EF -:100FE0008FB100148FB000100A000F3927BD002008 -:100FF0008E42000C0A0004220000000094A200109F -:101000003C0480008C8301443042FFFF14620009DD -:101010000000000024020001A4A200108C82014004 -:10102000AC8202003C021000AC8202380A000429A3 -:101030008FBF001C94A200100A00042200000000D0 -:10104000240200201482000E3C11800094A20012A1 -:101050003C0380008C6301443042FFFF14620005B2 -:101060000000000024020001A4A200120A0003FCF8 -:101070008FBF001C94A200120A000422000000008E -:101080008E2401400E0003458F92FFA89642001265 -:101090008E2301443050FFFF16030002240200019A -:1010A000A64200120E0003508E2401408E220144FD -:1010B000160200068FBF001C8FB200188FB10014FB -:1010C0008FB000100A00038E27BD00209642001248 -:1010D0000A0004220000000094A200143C038000D7 -:1010E0008C6301443042FFFF146200088FBF001C74 -:1010F000240200018FB200188FB100148FB00010CD -:10110000A4A200140A00142427BD002094A20014F5 -:101110000A0004220000000094A200163C03800094 -:101120008C6301443042FFFF146200082402000176 -:101130008FBF001C8FB200188FB100148FB0001049 -:10114000A4A200160A000B0027BD002094A20016DE -:10115000144000068FBF001C3C0208008C42007047 -:10116000244200013C010800AC2200708FB200183C -:101170008FB100148FB0001003E0000827BD0020DD -:1011800027BDFFD8AFB200188F92FFA8AFB10014EF -:10119000AFBF0020AFB3001CAFB000103C02800016 -:1011A000345101008C50010092420000922300094A -:1011B000304400FF2402001F106200AB28620020B0 -:1011C00010400019240200382862000A1040000D67 -:1011D0002402000B286200081040002E8F82001CA1 -:1011E00004600103286200021440002A8F82001C60 -:1011F00024020006106200268FBF00200A00054C62 -:101200008FB3001C106200602862000B144000F9CC -:101210008FBF00202402000E106200788F82001C15 -:101220000A00054C8FB3001C106200D128620039FF -:101230001040000A2402008024020036106200E4FC -:1012400028620037104000C224020035106200D826 -:101250008FBF00200A00054C8FB3001C1062002DC8 -:101260002862008110400006240200C824020039D0 -:10127000106200C88FBF00200A00054C8FB3001C0D -:10128000106200A28FBF00200A00054C8FB3001C23 -:101290008F82001C8C42000C104000D68FBF0020B3 -:1012A0000E000D45000000003C0380003463010087 -:1012B0008C6200008F850018946700089466000C0B -:1012C000ACA200008C6400048F82001C0006340075 -:1012D000ACA400049448001E8C62001800073C0077 -:1012E00000E83825ACA200088C62001C2404000130 -:1012F000ACA2000C9062000A00C23025ACA600101F -:10130000ACA00014ACA00018ACA7001C0A00050B90 -:101310008FBF00208F82001C8C42000C104000B553 -:101320008FBF00200E000D45000000008F82001CC2 -:10133000962400089625000C9443001E0004220207 -:101340009626000E8F8200180004260000832025B8 -:1013500000052C003C03008000A6282500832025E2 -:10136000AC400000AC400004AC400008AC40000CB5 -:10137000AC450010AC400014AC400018AC44001C5C -:101380000A00050A240400019622000C14400018EB -:10139000000000009242000530420010144000148A -:1013A000000000000E0003450200202192420005CB -:1013B00002002021344200100E000350A24200051A -:1013C0009242000024030020304200FF10430088B6 -:1013D000020020218FBF00208FB3001C8FB20018A5 -:1013E0008FB100148FB000100A00103627BD0028FE -:1013F0000000000D0A00054B8FBF00208C42000C3E -:101400001040007C8FBF00200E000D450000000042 -:101410008E2200048F8400189623000CAC820000FA -:101420003C0280089445002C8F82001C00031C00A5 -:1014300030A5FFFF9446001E3C02400E00651825B3 -:1014400000C23025AC830004AC800008AC80000CE6 -:10145000AC800010AC800014AC800018AC86001C7E -:101460000A00050A240400010E00034502002021A1 -:101470008F93FFAC020020210E000350A660000CE9 -:10148000020020210E000355240500018F82001C5C -:101490008C42000C104000578FBF00200E000D45FD -:1014A000000000009622000C8F8300180002140038 -:1014B000AC700000AC620004AC6000088E440038E0 -:1014C0008F82001CAC64000C8E46003C9445001ECC -:1014D0003C02401FAC66001000A228258E6200046A -:1014E00024040001AC620014AC600018AC65001C60 -:1014F0008FBF00208FB3001C8FB200188FB1001473 -:101500008FB000100A000D7927BD002824020020AA -:10151000108200398FB3001C0E000F1F0000000066 -:10152000104000348FBF00203C0380008C6201F823 -:101530000440FFFE24020002AC7001C0A06201C49E -:101540003C021000AC6201F80A00054B8FBF00207E -:10155000020020218FBF00208FB3001C8FB2001823 -:101560008FB100148FB000100A000E6827BD00284C -:101570009625000C020020218FBF00208FB3001C95 -:101580008FB200188FB100148FB000100A000E8DBA -:1015900027BD0028020020218FB3001C8FB2001845 -:1015A0008FB100148FB000100A000EB827BD0028BC -:1015B0009225000D020020218FB3001C8FB200186D -:1015C0008FB100148FB000100A000F0927BD00284A -:1015D000020020218FBF00208FB3001C8FB20018A3 -:1015E0008FB100148FB000100A000EE027BD002854 -:1015F0008FBF00208FB3001C8FB200188FB1001472 -:101600008FB0001003E0000827BD00283C038000D5 -:101610008C6202780440FFFE24020002AC640240A7 -:10162000A06202443C02100003E00008AC620278B1 -:10163000A380001003E00008A38000113C03800099 -:101640008C6202780440FFFE8F820014AC6202407C -:1016500024020002A06202443C02100003E00008E1 -:10166000AC6202783C02600003E000088C42540443 -:101670009083003024020005008040213063003F49 -:101680000000482114620005000050219082004CA7 -:101690009483004E304900FF306AFFFFAD00000C1C -:1016A000AD000010AD000024950200148D05001C53 -:1016B0008D0400183042FFFF004910230002110082 -:1016C000000237C3004038210086202300A2102BDF -:1016D0000082202300A72823AD05001CAD040018BC -:1016E000A5090014A5090020A50A001603E00008BA -:1016F000A50A002203E000080000000027BDFFD873 -:10170000AFB200183C128008AFB40020AFB3001C89 -:10171000AFB10014AFBF0024AFB0001036510100CC -:101720003C0260008C4254049222000C3C140800DD -:10173000929400F7304300FF24020001106200324F -:101740000080982124020002146200353650008087 -:101750000E0013FE000000009202004C2403FF80E4 -:101760003C0480003042007F000211C0244202404D -:101770000262102100431824AC83009492450008B3 -:101780009204004C3042007F3C0380061485000721 -:10179000004380212402FFFFA22200112402FFFF48 -:1017A000A62200120A0005BE2402FFFF96020020B6 -:1017B000A222001196020022A62200128E0200240C -:1017C0003C048008AE2200143485008090A2004CB6 -:1017D00034830100A06200108CA2003CAC620018AF -:1017E0008C820068AC6200E48C820064AC6200E031 -:1017F0008C82006CAC6200E824020001A0A20068A8 -:101800000A0005DA3C0480080E00141700000000EE -:1018100036420080A04000680A0005DA3C048008D7 -:10182000A2000068A20000690A0006153C028008B8 -:10183000348300808C62003834850100AC62006C17 -:1018400024020001A062006990A200C590830008F4 -:10185000305100FF3072007F12320019001111C0A8 -:1018600024420240026210212403FF800043182416 -:101870003C048000AC8300943042007F3C0380062F -:10188000004380218E02000C1040000D0200202138 -:101890000E00056A0000000026220001305100FF02 -:1018A0009203003C023410260002102B0002102389 -:1018B0003063007F022288240A0005E4A203003C72 -:1018C0003C088008350401008C8200D03507008078 -:1018D000ACE2003C8C8200D0AD02000090E5004CF0 -:1018E000908600C590E3004C908400C52402FF80E0 -:1018F00000A228243063007F308400FF00A6282542 -:101900000064182A1060000230A500FF38A500808E -:10191000A0E5004CA10500093C0280089043000EA0 -:10192000344400803C058000A043000A8C830018EA -:101930003C027FFF3442FFFF00621824AC83001892 -:101940008CA201F80440FFFE00000000ACB301C00F -:101950008FBF00248FB400208FB3001C8FB20018FB -:101960008FB100148FB0001024020002A0A201C4A5 -:1019700027BD00283C02100003E00008ACA201F8DB -:1019800090A2000024420001A0A200003C03080035 -:101990008C6300F4304200FF1443000200803021C9 -:1019A000A0A0000090A200008F840014000211C0CB -:1019B0002442024024830040008220212402FF8030 -:1019C000008220243063007F3C02800A00621821DC -:1019D0003C028000AC44002403E00008ACC30000DB -:1019E00094820006908300058C85000C8C86001084 -:1019F0008C8700188C88001C8C8400203C01080017 -:101A0000A42252C63C010800A02352C53C01080094 -:101A1000AC2552CC3C010800AC2652D03C01080059 -:101A2000AC2752D83C010800AC2852DC3C0108002D -:101A3000AC2452E003E00008000000003C028008F3 -:101A4000344201008C4400343C03800034650400BF -:101A5000AC6400388C420038AF850020AC62003C9A -:101A60003C020005AC6200300000000000000000F5 -:101A700003E00008000000003C020006308400FF84 -:101A8000008220253C028000AC44003000000000B1 -:101A900000000000000000003C0380008C62000099 -:101AA000304200101040FFFD3462040003E00008E3 -:101AB000AF82002094C200003C080800950800CACC -:101AC00030E7FFFF0080482101021021A4C200007E -:101AD00094C200003042FFFF00E2102B544000018E -:101AE000A4C7000094A200003C0308008C6300CC53 -:101AF00024420001A4A2000094A200003042FFFF93 -:101B0000144300073C0280080107102BA4A000002A -:101B10005440000101003821A4C700003C028008A5 -:101B2000344601008CC3002894A200003C048000CD -:101B30003042FFFE000210C000621021AC82003C67 -:101B40008C82003C00621823186000040000000032 -:101B50008CC200240A0006A6244200018CC2002484 -:101B6000AC8200383C020050344200103C0380003C -:101B7000AC62003000000000000000000000000027 -:101B80008C620000304200201040FFFD0000000089 -:101B900094A200003C04800030420001000210C00A -:101BA000004410218C430400AD2300008C42040447 -:101BB000AD2200043C02002003E00008AC820030AB -:101BC00027BDFFE0AFB20018AFB10014AFB00010F6 -:101BD000AFBF001C94C2000000C080213C1208006E -:101BE000965200C624420001A6020000960300009F -:101BF00094E2000000E03021144300058FB1003072 -:101C00000E00067B024038210A0006DD00000000BD -:101C10008C8300048C82000424420040046100078D -:101C2000AC8200048C820004044000040000000028 -:101C30008C82000024420001AC8200009602000069 -:101C40003042FFFF50520001A60000009622000023 -:101C500024420001A62200003C0280083442010018 -:101C6000962300009442003C144300048FBF001CE4 -:101C700024020001A62200008FBF001C8FB20018B2 -:101C80008FB100148FB0001003E0000827BD0020C2 -:101C900027BDFFE03C028008AFBF001834420100BE -:101CA0008C4800343C03800034690400AC68003880 -:101CB0008C42003830E700FFAF890020AC62003C66 -:101CC0003C020005AC620030000000000000000093 -:101CD0000000000000000000000000000000000004 -:101CE0008C82000C8C82000C9783000EAD220000C9 -:101CF0008C82001000604021AD2200048C8200180C -:101D0000AD2200088C82001CAD22000C8CA20014B5 -:101D1000AD2200108C820020AD22001490820005BC -:101D2000304200FF00021200AD2200188CA2001801 -:101D3000AD22001C8CA2000CAD2200208CA2001051 -:101D4000AD2200248CA2001CAD2200288CA2002011 -:101D5000AD22002C3402FFFFAD260030AD20003450 -:101D6000506200013408FFFFAD28003850E0001138 -:101D70003C0280083C0480083484010094820050B6 -:101D80003042FFFFAD22003C948300449485004420 -:101D9000240200013063FFFF000318C20064182111 -:101DA0009064005430A5000700A210040A00074800 -:101DB0000044102534420100AD20003C944300440F -:101DC000944400443063FFFF000318C200621821EE -:101DD0003084000790650054240200010082100442 -:101DE0000002102700451024A062005400000000EB -:101DF00000000000000000003C02000634420040E9 -:101E00003C038000AC6200300000000000000000D5 -:101E1000000000008C620000304200101040FFFD06 -:101E20003C06800834C201503463040034C7014AC0 -:101E300034C4013434C5014034C60144AFA200109B -:101E40000E0006BEAF8300208FBF001803E000081D -:101E500027BD00208F83000C3C0608008CC600E8DC -:101E60008F82001430633FFF000319800046102169 -:101E7000004310212403FF80004318243C06800007 -:101E8000ACC300283042007F3C03800C004330216B -:101E900090C2000D30A500FF000038213442001030 -:101EA000A0C2000D8F89000C3C0280083442010062 -:101EB00094430044000913823048000324020001C7 -:101EC000A4C3000E1102000B2902000210400005FD -:101ED000240200021100000C240300010A000790F4 -:101EE0000000182111020006000000000A000790FF -:101EF000000018218CC2002C0A0007902443000126 -:101F00008CC20014244300018CC200180043102B23 -:101F10005040000A240700012402002714A20003F5 -:101F20003C0380080A00079D240700013463010078 -:101F30009462004C24420001A462004C0009138208 -:101F4000304300032C620002104000090080282169 -:101F5000146000040000000094C200340A0007ADC1 -:101F60003046FFFF8CC600380A0007AD00802821EC -:101F7000000030213C040800248452C00A0006F20C -:101F80000000000027BDFF90AFB60068AFB5006449 -:101F9000AFB40060AFB3005CAFB20058AFB1005453 -:101FA000AFBF006CAFB000508C9000000080B0213B -:101FB0003C0208008C4200E8960400328F83001433 -:101FC0002414FF8030843FFF006218210004218028 -:101FD00000641821007410243C13800000A090219C -:101FE00090A50000AE620028920400323C02800CF2 -:101FF0003063007F00628821308400C024020040EA -:10200000148200320000A8218E3500388E2200187C -:102010001440000224020001AE2200189202003C8B -:10202000304200201440000E8F830014000511C0C0 -:102030002442024000621821306400783C02008093 -:102040000082202500741824AE630800AE640810D6 -:102050008E2200188E03000800431021AE220018C3 -:102060008E22002C8E230018244200010062182BBF -:102070001060004300000000924200002442000172 -:10208000A24200003C0308008C6300F4304200FFD1 -:1020900050430001A2400000924200008F840014CF -:1020A000000211C024420240248300403063007FBC -:1020B000008220213C02800A009420240062182122 -:1020C000AE6400240A0008BEAEC3000092030032D2 -:1020D0002402FFC000431024304200FF14400005DA -:1020E00024020001AE220018962200340A00082EB5 -:1020F0003055FFFF8E22001424420001AE2200184A -:102100009202003000021600000216030441001C77 -:10211000000000009602003227A400100080282151 -:10212000A7A2001696020032000030212407000109 -:102130003042FFFFAF82000C0E0006F2AFA0001C81 -:10214000960200328F8300143C0408008C8400E85F -:1021500030423FFF00021180006418210062182104 -:1021600000741024AE62002C3063007F3C02800EAD -:10217000006218219062000D3042007FA062000DC5 -:102180009222000D30420010504000789242000030 -:102190003C028008344401009482004C8EC300004D -:1021A0003C130800967300C62442FFFFA482004C33 -:1021B000946200329623000E3054FFFF3070FFFF10 -:1021C0003C0308008C6300D000701807A7A30038F8 -:1021D0009482003E3063FFFF3042FFFF146200072D -:1021E000000000008C8200303C038000244200305C -:1021F000AC62003C0A0008568C82002C948200409D -:102200003042FFFF5462000927A400408C8200384E -:102210003C03800024420030AC62003C8C820034DD -:10222000AC6200380A0008653C03800027A500382E -:1022300027A60048026038210E00067BA7A00048B0 -:102240008FA300403C02800024630030AC43003880 -:102250008FA30044AC43003C3C0380003C020005DB -:10226000AC6200303C028008344401009482004299 -:10227000346304003042FFFF0202102B14400007B9 -:10228000AF8300209482004E94830042020210210A -:10229000004310230A00087B3043FFFF9483004E65 -:1022A0009482004202631821005010230062182318 -:1022B0003063FFFF3C028008344401009482003CFC -:1022C0003042FFFF14430003000000000A00088BA7 -:1022D000240300019482003C3042FFFF0062102B77 -:1022E000144000058F8200209482003C006210237D -:1022F0003043FFFF8F820020AC550000AC4000044B -:10230000AC540008AC43000C3C0200063442001000 -:102310003C038000AC6200300000000000000000C0 -:10232000000000008C620000304200101040FFFDF1 -:102330003C04800834840100001018C20064182195 -:102340009065005432020007240600010046100484 -:1023500000451025A0620054948300429622000E8E -:1023600050430001A3860010924200002442000165 -:10237000A24200003C0308008C6300F4304200FFDE -:1023800050430001A2400000924200008F840014DC -:10239000000211C024420240248300400082202118 -:1023A0002402FF80008220243063007F3C02800AE8 -:1023B000006218213C028000AC440024AEC300003F -:1023C0008FBF006C8FB600688FB500648FB400605B -:1023D0008FB3005C8FB200588FB100548FB00050A3 -:1023E00003E0000827BD007027BDFFD8AFB3001C75 -:1023F000AFB20018AFB10014AFB00010AFBF0020F3 -:102400000080982100E0802130B1FFFF0E000D45D3 -:1024100030D200FF000000000000000000000000BB -:102420008F8200188F83001CAC510000AC52000456 -:10243000AC530008AC40000CAC400010AC400014A1 -:10244000AC4000189463001E02038025AC50001CB1 -:102450000000000000000000000000002404000153 -:102460008FBF00208FB3001C8FB200188FB10014F3 -:102470008FB000100A000D7927BD002830A5FFFF9E -:102480000A0008C830C600FF3C028008344301003F -:102490009462000E3C080800950800C63046FFFF15 -:1024A00014C000043402FFFF946500DA0A00091525 -:1024B0008F84001410C20027000000009462004EB8 -:1024C0009464003C3045FFFF00A6102300A6182BA3 -:1024D0003087FFFF106000043044FFFF00C5102369 -:1024E00000E210233044FFFF0088102B1040000E44 -:1024F00000E810233C02800834440100240300015A -:1025000034420080A44300162402FFFFA482000E80 -:10251000948500DA8F8400140000302130A5FFFF7D -:102520000A0008ED3C0760200044102A1040000912 -:102530003C0280083443008094620016304200015F -:10254000104000043C0280009442007E24420014AB -:10255000A462001603E000080000000027BDFFE0B1 -:102560003C028008AFBF001CAFB00018344201002D -:10257000944300429442004C104000193068FFFF21 -:102580009383001024020001146200298FBF001CF5 -:102590003C06800834D00100000810C20050102111 -:1025A000904200543103000734C70148304200FF15 -:1025B000006210073042000134C9014E34C4012CBE -:1025C00034C5013E1040001634C601420E0006BE5E -:1025D000AFA90010960200420A0009323048FFFFFE -:1025E0003C028008344401009483004494820042F9 -:1025F0001043000F8FBF001C94820044A48200424D -:1026000094820050A482004E8C820038AC8200304C -:1026100094820040A482003E9482004AA482004832 -:102620008FBF001C8FB000180A0008F027BD0020E3 -:102630008FB0001803E0000827BD002027BDFFA0D1 -:10264000AFB1004C3C118000AFBF0058AFB3005495 -:10265000AFB20050AFB000483626018890C20003E8 -:102660003044007FA3A400108E32018090C200008D -:102670003043007F240200031062003BAF9200143D -:102680002862000410400006240200042402000214 -:10269000106200098FBF00580A000AFB8FB3005474 -:1026A0001062004D240200051062014E8FBF0058D9 -:1026B0000A000AFB8FB30054000411C0024210212B -:1026C0002404FF802442024000441024264300409A -:1026D000AE2200243063007F3C02800A0062182191 -:1026E0009062003CAFA3003C00441025A062003C77 -:1026F0008FA3003C9062003C304200401040016CCF -:102700008FBF00583C108008A380001036100100D5 -:102710008E0200D08C63003427A4003C27A5001053 -:10272000004310210E0007AFAE0200D093A20010AC -:102730003C038000A20200C58C6202780440FFFEC8 -:102740008F820014AC62024024020002A0620244A4 -:102750003C021000AC6202780E0009250000000067 -:102760000A000AFA8FBF00583C05800890C3000198 -:1027700090A2000B1443014E8FBF005834A4008078 -:102780008C8200189082004C90A200083C026000ED -:102790008C4254048C8300183C027FFF3442FFFFBC -:1027A000006218243C0208008C4200B4AC8300187C -:1027B0003C038000244200013C010800AC2200B42C -:1027C0008C6201F80440FFFE8F820014AC6201C0ED -:1027D0000A000AC2240200023C10800890C30001D3 -:1027E0009202000B144301328FBF005827A4001837 -:1027F00036050110240600033C0260008C4254049C -:102800000E000E080000000027A40028360501E095 -:102810000E000E08240600038FA2002836030100D4 -:10282000AE0200648FA2002CAE0200688FA20030BE -:10283000AE02006C93A40018906300C52402FF80D0 -:102840000082102400431025304900FF3084007FAF -:102850003122007F0082102A544000013929008073 -:10286000000411C0244202402403FF8002421021D0 -:1028700000431024AE220094264200403042007FE4 -:102880003C038006004340218FA3001C2402FFFF6D -:10289000AFA800403C130800927300F710620033A9 -:1028A00093A2001995030014304400FF3063FFFF2A -:1028B0000064182B10600010000000009504001444 -:1028C0008D07001C8D0600183084FFFF0044202374 -:1028D0000004210000E438210000102100E4202B36 -:1028E00000C2302100C43021AD07001CAD06001825 -:1028F0000A000A1B93A20019950400148D07001CFE -:102900008D0600183084FFFF008220230004210080 -:10291000000010210080182100C2302300E4202B89 -:1029200000C4302300E33823AD07001CAD060018B7 -:1029300093A200198FA30040A462001497A2001A6A -:10294000A46200168FA2001CAC6200108FA2001CB3 -:10295000AC62000C93A20019A462002097A2001A96 -:10296000A46200228FA2001CAC6200243C048008F8 -:10297000348300808C6200388FA2002001208821DF -:10298000AC62003C8FA20020AC82000093A2001831 -:10299000A062004C93A20018A0820009A060006809 -:1029A00093A20018105100512407FF803229007FA4 -:1029B000000911C024420240024210213046007F2B -:1029C0003C03800000471024AC6200943C02800667 -:1029D00000C2302190C2003CAFA600400000202180 -:1029E00000471025A0C2003C8FA8004095020002BD -:1029F000950300148D07001C3042FFFF3063FFFF7A -:102A00008D060018004310230002110000E2382157 -:102A100000E2102B00C4302100C23021AD07001CA1 -:102A2000AD06001895020002A5020014A5000016CC -:102A30008D020008AD0200108D020008AD02000CEE -:102A400095020002A5020020A50000228D020008C8 -:102A5000AD0200249102003C304200401040001AB8 -:102A6000262200013C108008A3A90038A380001092 -:102A7000361001008E0200D08D03003427A40040E0 -:102A800027A50038004310210E0007AFAE0200D08A -:102A900093A200383C038000A20200C58C62027839 -:102AA0000440FFFE8F820014AC6202402402000248 -:102AB000A06202443C021000AC6202780E000925BC -:102AC00000000000262200013043007F1473000440 -:102AD000004020212403FF800223102400432026ED -:102AE00093A200180A000A37309100FF93A400183F -:102AF0008FA3001C2402FFFF1062000A308900FF30 -:102B000024820001248300013042007F1453000519 -:102B1000306900FF2403FF80008310240043102647 -:102B2000304900FF3C0280089042000801208821C3 -:102B3000305000FF123000193222007F000211C015 -:102B400002421021244202402403FF800043182443 -:102B50003C048000AC8300943042007F3C0380063C -:102B6000004310218C43000C004020211060000B1A -:102B7000AFA200400E00056A0000000026230001FD -:102B80002405FF803062007F1453000202252024B8 -:102B9000008518260A000A9B307100FF3C0480085B -:102BA000348400808C8300183C027FFF3442FFFF96 -:102BB00000621824AC8300183C0380008C6201F88A -:102BC0000440FFFE00000000AC7201C024020002BD -:102BD000A06201C43C021000AC6201F80A000AFACB -:102BE0008FBF00583C04800890C300019082000B06 -:102BF0001443002F8FBF00583490008092020008C9 -:102C00003042004010400020000000009202000806 -:102C100000021600000216030441000502402021B4 -:102C20000E000E8D240500930A000AFA8FBF00588B -:102C30009202000924030018304200FF1443000DE3 -:102C400002402021240500390E000E25000030210D -:102C50000E0003458F8400148F82FFA82403001206 -:102C6000A04300090E0003508F8400140A000AFAE2 -:102C70008FBF0058240500360E000E2500003021BD -:102C80000A000AFA8FBF00580E00034502402021B7 -:102C9000920200058F840014344200200E0003507D -:102CA000A20200050E0010368F8400148FBF00585A -:102CB0008FB300548FB200508FB1004C8FB00048DA -:102CC00003E0000827BD00603C0280083445010095 -:102CD0003C0280008C42014094A3000E0000302191 -:102CE00000402021AF8200143063FFFF3402FFFF59 -:102CF000106200063C0760202402FFFFA4A2000E21 -:102D000094A500DA0A0008ED30A5FFFF03E00008F3 -:102D10000000000027BDFFC83C0280003C06800880 -:102D2000AFB5002CAFB1001CAFBF0030AFB400286E -:102D3000AFB30024AFB20020AFB00018345101008F -:102D400034C501008C4301008E2200148CA400D4F1 -:102D50000000A821AF830014004410231840005243 -:102D6000A38000108E22001400005021ACA200D4D9 -:102D700090C3000890A200C53073007FA3A200108A -:102D80008CB200D08CB400D4304200FF1053003B12 -:102D900093A200108F8300142407FF80000211C04B -:102DA00000621021244202402463004000471024A6 -:102DB0003063007F3C0980003C08800A00681821CD -:102DC000AD2200248C62003427A4001427A5001033 -:102DD000024280210290102304400028AFA3001477 -:102DE0009062003C00E21024304200FF14400019C1 -:102DF000020090219062003C34420040A062003CFE -:102E00008F86001493A3001024C200403042007F3C -:102E1000004828213C0208008C4200F42463000191 -:102E2000306400FF14820002A3A30010A3A00010CE -:102E300093A20010AFA50014000211C0244202406A -:102E400000C2102100471024AD2200240A000B31DB -:102E500093A200100E0007AF000000003C028008A3 -:102E600034420100AC5000D093A30010240A0001AA -:102E7000A04300C50A000B3193A2001024020001F8 -:102E8000154200093C0380008C6202780440FFFE7A -:102E90008F820014AC62024024020002A06202444D -:102EA0003C021000AC6202789222000B2403000264 -:102EB000304200FF14430072000000009622000818 -:102EC000304300FF24020082146200402402008488 -:102ED0003C028000344901008D22000C952300063D -:102EE000000216023063FFFF3045003F2402002736 -:102EF00010A2000FAF83000C28A200281040000889 -:102F0000240200312402002110A20009240200251D -:102F100010A20007938200110A000BA90000000014 -:102F200010A20007938200110A000BA90000000004 -:102F30000E000763012020210A000C290000000078 -:102F40003C0380008C6202780440FFFE8F820014F4 -:102F5000AC62024024020002A06202443C02100063 -:102F6000AC6202780A000C290000000095230006DC -:102F7000912400058D25000C8D2600108D2700184A -:102F80008D28001C8D290020244200013C010800EE -:102F9000A42352C63C010800A02452C53C010800ED -:102FA000AC2552CC3C010800AC2652D03C010800B4 -:102FB000AC2752D83C010800AC2852DC3C01080088 -:102FC000AC2952E00A000C29A38200111462000A05 -:102FD000240200813C02800834420100944500DA5A -:102FE000922600058F84001430A5FFFF30C600FF35 -:102FF0000A000BEA3C0760211462005C000000003C -:103000009222000A304300FF306200201040000787 -:10301000306200403C02800834420100944500DAEE -:103020008F8400140A000BE82406004010400007BB -:10303000000316003C02800834420100944500DA87 -:103040008F8400140A000BE82406004100021603D6 -:10305000044100463C02800834420100944500DAF5 -:103060008F8400142406004230A5FFFF3C0760193E -:103070000E0008ED000000000A000C29000000000E -:103080009222000B24040016304200FF1044000678 -:103090003C0680009222000B24030017304200FF00 -:1030A000144300320000000034C5010090A2000B60 -:1030B000304200FF1444000B000080218CA200204D -:1030C0008CA400202403FF80004310240002114040 -:1030D0003084007F004410253C032000004310256D -:1030E000ACC2083094A200080002140000021403CD -:1030F000044200012410000194A200083042008024 -:103100005040001A0200A82194A20008304220007A -:10311000504000160200A8218CA300183C021C2D70 -:10312000344219ED106200110200A8213C0208008F -:103130008C4200D4104000053C02800824030004A7 -:1031400034420100A04300EC3C02800834420100FC -:10315000944500DA8F8400142406000630A5FFFF92 -:103160000E0008ED3C0760210200A8210E00092591 -:10317000000000009222000A3042000810400004C3 -:1031800002A010210E00133A0000000002A010213E -:103190008FBF00308FB5002C8FB400288FB3002470 -:1031A0008FB200208FB1001C8FB0001803E0000820 -:1031B00027BD00382402FF80008220243C029000BA -:1031C00034420007008220253C028000AC440020ED -:1031D0003C0380008C6200200440FFFE00000000E1 -:1031E00003E00008000000003C0380002402FF8090 -:1031F000008220243462000700822025AC64002075 -:103200008C6200200440FFFE0000000003E0000884 -:10321000000000003C028008240300053442010045 -:10322000A04300EC3C0280008C4201003C03800083 -:10323000AF8200148C6202780440FFFE8F8200147B -:10324000AC62024024020002A06202443C02100070 -:10325000AC62027803E000080000000027BDFFE830 -:103260003C068000AFBF001034C7010094E20008A4 -:10327000304400FF38830082388200842C630001D0 -:103280002C420001006218251060002D24020083EA -:1032900093820011504000368FBF00103C0208009E -:1032A000904252CC8CC401003C06080094C652C621 -:1032B0003045003F38A3003238A2003F2C630001A4 -:1032C0002C42000100621825AF840014AF86000C68 -:1032D000A38000111460000700E0202124020020D8 -:1032E00014A20012000000003402FFFF14C2000FFD -:1032F000000000002402002014A2000500E02821A4 -:103300008CE300142402FFFF5062000B8FBF0010FB -:103310003C040800248452C0000030210E0006F254 -:10332000240700010A000C9C8FBF00100E000763E9 -:10333000000000008FBF00100A00092527BD0018FB -:10334000148200062482FF808CC301043C026020AA -:10335000AC4300140A000CD28FBF0010304200FFB3 -:103360002C42000210400004240200228FBF0010F3 -:103370000A000B1327BD0018148200048F82001C62 -:103380008FBF00100A000C5327BD00188C42000CA0 -:103390001040001E00E0282190E3000924020018DC -:1033A00014620003240200160A000CBD2403000866 -:1033B0001462000724020017240300123C02800854 -:1033C00034420080A04300090A000CCA94A70008F8 -:1033D0005462000794A700088F82FFA82404FFFE10 -:1033E0009043000500641824A043000594A700083A -:1033F00090A6001B8CA4000094A500068FBF0010AF -:1034000000073C000A0008C827BD00188FBF001045 -:1034100003E0000827BD00188F85001C3C048000D5 -:1034200094A2002A8CA30034000230C02402FFF0D2 -:1034300000C2102400621821AC83003C8CA2003032 -:103440003C038000AC8200383C0200503442001043 -:10345000AC6200300000000000000000000000002E -:103460008C620000304200201040FFFD30C2000896 -:10347000104000063C0280008C620408ACA20020D0 -:103480008C62040C0A000CF5ACA200248C430400EE -:10349000ACA300208C420404ACA200243C03002016 -:1034A0003C028000AC4300303C0480008C82003041 -:1034B000004310241440FFFD8F86001C3C02004096 -:1034C000AC82003094C3002A94C2002894C4002C1B -:1034D00094C5002E24630001004410213064FFFFD6 -:1034E000A4C2002814850002A4C3002AA4C0002A94 -:1034F00003E00008000000008F84001C27BDFFE8E7 -:103500003C05800424840010AFBF00100E000E089C -:103510002406000A8F84001C948200129483002EDB -:103520003042000F244200030043180424027FFFAE -:103530000043102B10400002AC8300000000000D7F -:103540000E000CD4000000008F83001C8FBF001001 -:1035500027BD0018946200149463001A3042000FD3 -:1035600000021500006218253C02800003E00008FC -:10357000AC4300A08F83001C3C02800494440006EE -:103580009462001A8C650000A464001600441023A5 -:103590003042FFFF0045102B03E0000838420001D5 -:1035A0008F84001C3C0780049486001A8C850000E0 -:1035B00094E20006A482001694E3000600C31023E0 -:1035C0003042FFFF0045102B384200011440FFF845 -:1035D000A483001603E00008000000008F84001C94 -:1035E0003C028004944200069483001A8C850000FB -:1035F000A4820016006210233042FFFF0045102B0A -:10360000384200015040000D8F85001C00603021C1 -:103610003C07800494E20006A482001694E30006AE -:1036200000C310233042FFFF0045102B3842000139 -:103630001440FFF8A48300168F85001C3C03800013 -:10364000346204008CA40020AF820018AC640038FF -:103650008CA20024AC62003C3C020005AC6200304D -:1036600003E00008ACA000048F84001C3C030006AB -:103670008C82000400021140004310253C038000AE -:10368000AC620030000000000000000000000000FC -:103690008C620000304200101040FFFD34620400D4 -:1036A000AC80000403E00008AF8200188F86001C85 -:1036B00027BDFFE0AFB10014AFB00010AFBF0018DE -:1036C0008CC300048CC500248F820018309000FF4A -:1036D00094C4001A246300012442002024840001C1 -:1036E00024A70020ACC30004AF820018A4C4001AB1 -:1036F000ACC7002404A100060000882104E20005F4 -:1037000094C2001A8CC2002024420001ACC20020E6 -:1037100094C2001A94C300282E040001004310260E -:103720002C420001004410245040000594C2001AAD -:1037300024020001ACC2000894C2001A94C30028FD -:103740000010202B004310262C42000100441025BD -:1037500014400007000000008CC200081440000460 -:10376000240200108CC300041462000F8F85001C1B -:103770000E000D68241100018F82001C9443002864 -:103780009442001A14430003000000000E000CD401 -:1037900000000000160000048F85001C0E000D457F -:1037A000000000008F85001C94A2001E94A4001C41 -:1037B000244200013043FFFF14640002A4A2001E53 -:1037C000A4A0001E1200000A3C02800494A200146F -:1037D00094A3001A3042000F000215000062182561 -:1037E0003C028000AC4300A00A000DDFACA0000842 -:1037F0009442000694A3001A8CA40000A4A2001610 -:10380000006210233042FFFF0044102B38420001B9 -:103810001040000D02201021006030213C07800480 -:1038200094E20006A4A2001694E3000600C310234D -:103830003042FFFF0044102B384200011440FFF8D3 -:10384000A4A30016022010218FBF00188FB100140E -:103850008FB0001003E0000827BD002003E000083F -:10386000000000008F8200243C030006000211408B -:10387000004310253C038000AC62003000000000D3 -:1038800000000000000000008C62000030420010C8 -:103890001040FFFD34620400AF82002003E0000806 -:1038A000AF80002403E000080000102103E00008BE -:1038B000000000003084FFFF30A5FFFF000018214A -:1038C000108000070000000030820001104000025C -:1038D00000042042006518210A000DFE0005284062 -:1038E00003E000080060102110C0000624C6FFFF9E -:1038F0008CA2000024A50004AC8200000A000E087F -:103900002484000403E000080000000010A0000868 -:1039100024A3FFFFAC8600000000000000000000B0 -:103920002402FFFF2463FFFF1462FFFA24840004D3 -:1039300003E00008000000003C02800834420080E0 -:1039400024030001AC43000CA4430010A443001264 -:10395000A443001403E00008A44300168F82001C57 -:1039600027BDFFD8AFB3001CAFB20018AFB1001431 -:10397000AFB00010AFBF00208C47000C2482008045 -:103980002409FF803C08800E3043007F00808021A6 -:103990003C0A8000004920240068182130B100FF53 -:1039A00030D200FF10E0002900009821260201001B -:1039B000AD44002C004928243042007F00482021DB -:1039C0009062000024030050304200FF14430004C2 -:1039D00000000000AD45002C948200DA3053FFFF58 -:1039E0000E000D45000000008F82001C8F83001820 -:1039F00000112C009442001E0012240034840001A7 -:103A000000A228253C02400000A22825AC7000003E -:103A10008FBF0020AC6000048FB20018AC730008A8 -:103A20008FB10014AC60000C8FB3001CAC640010AC -:103A30008FB00010AC60001424040001AC600018CA -:103A400027BD00280A000D79AC65001C8FBF00203F -:103A50008FB3001C8FB200188FB100148FB000100C -:103A600003E0000827BD00283C06800034C20100A6 -:103A70009043000F240200101062000E2865001110 -:103A800010A0000724020012240200082405003AB6 -:103A9000106200060000302103E000080000000072 -:103AA000240500351462FFFC000030210A000E25B9 -:103AB000000000008CC200748F83FFA824420FA076 -:103AC00003E00008AC62000C27BDFFE8AFBF0010A8 -:103AD0000E000355240500013C0480088FBF001030 -:103AE0002402000134830080A462001227BD001864 -:103AF0002402000103E00008A080001A27BDFFE0B7 -:103B0000AFB20018AFB10014AFB00010AFBF001CCF -:103B100030B2FFFF0E000345008088213C02800880 -:103B2000345000809202000924030004304200FF58 -:103B30001443000C3C028008124000082402000AD2 -:103B40000E000E1C00000000920200052403FFFE80 -:103B500000431024A202000524020012A202000960 -:103B60003C02800834420080022020210E000350D5 -:103B7000A040002716400003022020210E000E80E6 -:103B80000000000002202021324600FF8FBF001CF1 -:103B90008FB200188FB100148FB0001024050038C8 -:103BA0000A000E2527BD002027BDFFE0AFBF001C87 -:103BB000AFB20018AFB10014AFB000100E00034553 -:103BC000008080210E000E1C000000003C028008D6 -:103BD0003445008090A2000924120018305100FFE3 -:103BE000123200030200202124020012A0A20009C8 -:103BF00090A200052403FFFE004310240E00035092 -:103C0000A0A2000502002021240500201632000792 -:103C1000000030218FBF001C8FB200188FB100143C -:103C20008FB000100A00035527BD00208FBF001C75 -:103C30008FB200188FB100148FB000102405003926 -:103C40000A000E2527BD002027BDFFE83C028000AA -:103C5000AFB00010AFBF0014344201009442000C1A -:103C6000240500360080802114400012304600FFF9 -:103C70000E000345000000003C0280083442008032 -:103C800024030012A0430009904300053463001090 -:103C90000E000E1CA04300050E0003500200202160 -:103CA000020020210E000355240500200A000EFD0D -:103CB000000000000E000E25000000000E0003456D -:103CC000020020213C0280089043001B2405FF9F36 -:103CD00002002021006518248FBF00148FB000104F -:103CE000A043001B0A00035027BD001827BDFFE0BA -:103CF000AFBF0018AFB10014AFB0001030B100FF7B -:103D00000E000345008080213C028008240300123D -:103D1000344200800E000E1CA04300090E00035028 -:103D20000200202102002021022030218FBF001834 -:103D30008FB100148FB00010240500350A000E2545 -:103D400027BD00203C0480089083000E9082000A6A -:103D50001443000B000028218F82FFA82403005089 -:103D60002405000190420000304200FF144300048B -:103D7000000000009082000E24420001A082000E8C -:103D800003E0000800A010213C0380008C6201F8D1 -:103D90000440FFFE24020002AC6401C0A06201C422 -:103DA0003C02100003E00008AC6201F827BDFFE010 -:103DB000AFB200183C128008AFB10014AFBF001CB6 -:103DC000AFB0001036510080922200092403000A8F -:103DD000304200FF1443003E000000008E43000408 -:103DE0008E220038506200808FBF001C922200009B -:103DF00024030050304200FF144300253C028000A1 -:103E00008C4201408E4300043642010002202821EA -:103E1000AC43001C9622005C8E2300383042FFFF2A -:103E20000002104000621821AE23001C8E430004E3 -:103E30008E2400389622005C006418233042FFFF75 -:103E400000031843000210400043102A10400006EF -:103E5000000000008E4200048E230038004310232F -:103E60000A000F6B000220439622005C3042FFFFE5 -:103E7000000220403C0280083443010034420080AC -:103E8000ACA4002CA040002424020001A062000C7D -:103E90000E000F1F00000000104000538FBF001CD9 -:103EA0003C0280008C4401403C0380008C6201F89D -:103EB0000440FFFE24020002AC6401C0A06201C401 -:103EC0003C021000AC6201F80A000FC88FBF001C52 -:103ED0009222000924030010304200FF1443000422 -:103EE0003C0280008C4401400A000FAF00002821F2 -:103EF0009222000924030016304200FF14430006FA -:103F000024020014A22200093C0280008C440140DB -:103F10000A000FC28FBF001C8E2200388E23003C87 -:103F200000431023044100308FBF001C9222002761 -:103F300024420001A2220027922200272C420004E2 -:103F4000144000163C108000922200092403000453 -:103F5000304200FF144300093C0280008C440140C1 -:103F60008FBF001C8FB200188FB100148FB00010EB -:103F7000240500930A000E8D27BD00208C440140CB -:103F8000240500938FBF001C8FB200188FB100145E -:103F90008FB000100A000F0927BD00208E040140D9 -:103FA0000E000345000000008E4200042442FFFF83 -:103FB000AE4200048E22003C2442FFFFAE22003CB1 -:103FC0000E0003508E0401408E0401408FBF001C80 -:103FD0008FB200188FB100148FB0001024050004B8 -:103FE0000A00035527BD00208FB200188FB10014BE -:103FF0008FB0001003E0000827BD00203C068000C1 -:104000008CC201883C038008346500809063000EF8 -:1040100000021402304400FF306300FF1464000EFD -:104020003C02800890A20026304200FF10440009A4 -:104030008F82FFA8A0A40026240300509042000015 -:10404000304200FF14430006000000000A00058D06 -:104050008CC401803C02800834420080A0440026C9 -:1040600003E000080000000027BDFFE030E700FF8C -:10407000AFB20018AFBF001CAFB10014AFB000105A -:104080000080902114E0000630C600FF0000000010 -:104090000000000D000000000A0010212400010EA5 -:1040A0003C0380089062000E304200FF144600235B -:1040B0003462008090420026304200FF1446001F08 -:1040C000000000009062000F304200FF1446001B09 -:1040D000000000009062000A304200FF1446000316 -:1040E0008F90FFA80000000D8F90FFA88F82FFAC7B -:1040F0003C118000AE05003CAC450000A066000A03 -:104100000E0003458E240100A20000240E0003507F -:104110008E2401003C0380008C6201F80440FFFE05 -:1041200024020002AC7201C0A06201C43C02100073 -:10413000AC6201F80A0010228FBF001C00000000D2 -:104140000000000D00000000240001378FBF001C9C -:104150008FB200188FB100148FB0001003E0000878 -:1041600027BD00208F83FFA83C0280008C44010003 -:10417000344201008C65003C9046001B0A000FE8A9 -:10418000240700013C0280089043000E9042000A80 -:1041900000431026304200FF03E000080002102B0D -:1041A00027BDFFE03C028008AFB10014AFB00010A3 -:1041B000AFBF001834500080920200052403003085 -:1041C0003042003014430085008088218F82001C1B -:1041D0008C42000C104000828FBF00180E000D456D -:1041E000000000008F860018ACD100009202000889 -:1041F00092030009304200FF00021200306300FF0A -:1042000000431025ACC200049202004D00021600CB -:104210000002160304410005000000003C030800F2 -:104220008C6300480A0010603C108008920200086D -:104230003042004014400003000018219202002781 -:10424000304300FF3C108008361100809222004D60 -:1042500000031E00304200FF000214000062182517 -:10426000ACC300088E2400308F82001CACC4000C4C -:104270008E2500349443001E3C02C00BACC50010D8 -:10428000006218258E22003800002021ACC20014E4 -:104290008E22003CACC200180E000D79ACC3001C8D -:1042A0008E0200048F8400183C058000AC82000060 -:1042B0008E220020AC8200048E22001CAC820008FA -:1042C0008E2200588CA3007400431021AC82000C95 -:1042D0008E22002CAC8200108E2200408E230044DF -:1042E0000002140000431025AC8200149222004DFD -:1042F00024030080304200FF14430004000000004B -:10430000AC8000180A0010A48F82001C8E23000CC1 -:10431000240200011062000E2402FFFF9222000816 -:10432000304200401440000A2402FFFF8E23000C9C -:104330008CA20074006218233C0208000062102462 -:1043400014400002000028210060282100051043CD -:10435000AC8200188F82001C000020219443001EB4 -:104360003C02C00C006218258F8200180E000D79E7 -:10437000AC43001C3C038008346201008C42000006 -:104380008F850018346300808FBF0018ACA2000036 -:10439000ACA000048C6400488F82001C8FB1001414 -:1043A000ACA40008ACA0000CACA000109063000509 -:1043B0009446001E3C02400D00031E0000C2302542 -:1043C000ACA300148FB00010ACA0001824040001AE -:1043D000ACA6001C0A000D7927BD00208FBF001875 -:1043E0008FB100148FB0001003E0000827BD00203B -:1043F0003C0280009443007C3C028008344601006B -:10440000308400FF3065FFFF2402000524A34650DE -:10441000A0C4000C5482000C3065FFFF90C2000D58 -:104420002C4200071040000724A30A0090C3000D8F -:10443000240200140062100400A210210A0010E0FF -:104440003045FFFF3065FFFF3C02800834420080AA -:1044500003E00008A44500143C0380083468008091 -:10446000AD050038346701008CE2001C308400FF89 -:1044700000A210231840000330C600FF24A2FFFC56 -:10448000ACE2001C30820001504000083C03800870 -:104490008D02003C00A210230441001224040005F8 -:1044A0008C62000410A2000F3C0380088C620004A0 -:1044B00014A2001E000000003C0208008C4200D83C -:1044C00030420020104000093C0280083462008025 -:1044D000906300089042004C144300043C028008A2 -:1044E000240400040A0010CA0000000034430080C5 -:1044F00034420100A040000C24020001A462001418 -:1045000010C0000A3C0280008C4401003C03800083 -:104510008C6201F80440FFFE24020002AC6401C07A -:10452000A06201C43C021000AC6201F803E0000884 -:104530000000000027BDFFE800A61823AFBF001051 -:1045400018600080308800FF3C02800834470080FB -:10455000A0E0002434440100A0E000278C82001C6D -:1045600000A2102304400056000000008CE2003C32 -:1045700094E3005C8CE4002C004530233063FFFFA3 -:1045800000C318210083202B1080000400E01821B4 -:104590008CE2002C0A00113900A2102194E2005C88 -:1045A0003042FFFF00C2102100A21021AC62001CAB -:1045B0003C028008344400809482005C8C83001CA0 -:1045C0003042FFFF0002104000A210210043102BD8 -:1045D00010400004000000008C82001C0A00114CF6 -:1045E0003C0680089482005C3042FFFF00021040CD -:1045F00000A210213C06800834C3010034C70080AB -:10460000AC82001CA060000CACE500388C62001C81 -:1046100000A210231840000224A2FFFCAC62001C80 -:1046200031020001104000083C0380088CE2003C8D -:1046300000A2102304410012240400058CC20004CF -:1046400010A200108FBF00108C62000414A2004F53 -:104650008FBF00103C0208008C4200D8304200207E -:104660001040000A3C028008346200809063000819 -:104670009042004C144300053C02800824040004CE -:104680008FBF00100A0010CA27BD001834430080F5 -:1046900034420100A040000C24020001A462001476 -:1046A0003C0280008C4401003C0380008C6201F8D5 -:1046B0000440FFFE240200020A00119900000000DD -:1046C0008CE2001C004610230043102B54400001D4 -:1046D000ACE5001C94E2005C3042FFFF0062102B4E -:1046E000144000072402000294E2005C8CE3001CEA -:1046F0003042FFFF00621821ACE3001C24020002DC -:10470000ACE500380E000F1FA082000C1040001F07 -:104710008FBF00103C0280008C4401003C038000ED -:104720008C6201F80440FFFE24020002AC6401C068 -:10473000A06201C43C021000AC6201F80A0011B191 -:104740008FBF001031020010104000108FBF00100A -:104750003C028008344500808CA3001C94A2005CBD -:10476000006618233042FFFF006218213C023FFF21 -:104770003444FFFF0083102B5440000100801821B7 -:1047800000C31021ACA2001C8FBF001003E0000882 -:1047900027BD001827BDFFE800C0402100A6302338 -:1047A000AFBF001018C00026308A00FF3C0280080E -:1047B000344900808D24001C8D23002C0088202388 -:1047C0000064182B1060000F344701008CE20020B9 -:1047D00000461021ACE200208CE200200044102BA7 -:1047E0001440000B3C023FFF8CE2002000441023E9 -:1047F000ACE200209522005C3042FFFF0A0011D19C -:1048000000822021ACE00020008620213C023FFFF6 -:104810003443FFFF0064102B54400001006020214E -:104820003C0280083442008000851821AC43001C03 -:10483000A0400024A04000270A0012233C03800867 -:1048400031420010104000433C0380083C068008C1 -:1048500034C400808C82003C004810235840003E45 -:10486000346600809082002424420001A08200244B -:10487000908200243C0308008C630024304200FF37 -:104880000043102B144000688FBF001034C2010099 -:104890008C42001C00A2102318400063000000009E -:1048A0008CC300049482005C006818233042FFFF30 -:1048B00000031843000210400043102A1040000576 -:1048C000000000008CC20004004810230A001206F9 -:1048D000000210439482005C3042FFFF000210404F -:1048E0003C068008AC82002C34C5008094A2005C99 -:1048F0008CA4002C94A3005C3042FFFF0002104007 -:10490000008220213063FFFF008320210104102159 -:10491000ACA2001C8CC2000434C60100ACC2001C56 -:10492000240200020E000F1FA0C2000C1040003E27 -:104930008FBF00103C0280008C4401003C038000CB -:104940008C6201F80440FFFE240200020A001253A8 -:104950000000000034660080ACC5003834640100FB -:104960008C82001C00A210231840000224A2FFFC2D -:10497000AC82001C314200015040000A3C03800818 -:104980008CC2003C00A21023044300142404000540 -:104990008C62000414A200033C0380080A00124544 -:1049A000240400058C62000414A2001F8FBF0010B5 -:1049B0003C0208008C4200D8304200201040000A1F -:1049C0003C02800834620080906300089042004CF2 -:1049D000144300053C028008240400048FBF00102B -:1049E0000A0010CA27BD0018344300803442010079 -:1049F000A040000C24020001A46200143C028000CC -:104A00008C4401003C0380008C6201F80440FFFEEE -:104A100024020002AC6401C0A06201C43C02100088 -:104A2000AC6201F88FBF001003E0000827BD00183A -:104A300027BDFFE83C0A8008AFBF00103549008061 -:104A40008D22003C00C04021308400FF004610232E -:104A50001840009D30E700FF3547010024020001A7 -:104A600000A63023A0E0000CA0E0000DA522001459 -:104A700018C00024308200108D23001C8D22002CD1 -:104A8000006818230043102B1040000F00000000A6 -:104A90008CE2002000461021ACE200208CE20020D5 -:104AA0000043102B1440000B3C023FFF8CE200201F -:104AB00000431023ACE200209522005C3042FFFF4F -:104AC0000A00128200621821ACE000200066182162 -:104AD0003C023FFF3446FFFF00C3102B544000014F -:104AE00000C018213C028008344200800065182173 -:104AF000AC43001CA0400024A04000270A0012D0B4 -:104B00003C038008104000403C0380088D22003C9C -:104B1000004810235840003D346700809122002453 -:104B200024420001A1220024912200243C03080019 -:104B30008C630024304200FF0043102B1440009A85 -:104B40008FBF00108CE2001C00A2102318400096BA -:104B5000000000008D4300049522005C00681823CB -:104B60003042FFFF00031843000210400043102AA8 -:104B700010400005012020218D4200040048102330 -:104B80000A0012B3000210439522005C3042FFFF7E -:104B9000000210403C068008AC82002C34C5008026 -:104BA00094A2005C8CA4002C94A3005C3042FFFF14 -:104BB00000021040008220213063FFFF0083182193 -:104BC00001031021ACA2001C8CC2000434C60100F9 -:104BD000ACC2001C240200020E000F1FA0C2000C79 -:104BE000104000718FBF00103C0280008C44010017 -:104BF0003C0380008C6201F80440FFFE24020002A6 -:104C00000A0012FA0000000034670080ACE50038AA -:104C1000346601008CC2001C00A210231840000260 -:104C200024A2FFFCACC2001C3082000150400008EE -:104C30003C0380088CE2003C00A210230443005196 -:104C4000240400058C62000410A2003E3C0380088E -:104C50008C62000454A200548FBF00103C02080074 -:104C60008C4200D830420020104000063C028008F0 -:104C700034620080906300089042004C1043004072 -:104C80003C0280083443008034420100A040000C04 -:104C900024020001A46200143C0280008C44010044 -:104CA0003C0380008C6201F80440FFFE24020002F5 -:104CB000AC6401C0A06201C43C021000AC6201F807 -:104CC0000A0013388FBF001024020005A12000271E -:104CD00014E2000A3C038008354301009062000D95 -:104CE0002C420006504000053C0380089062000DF5 -:104CF00024420001A062000D3C038008346700805C -:104D0000ACE50038346601008CC2001C00A2102300 -:104D10001840000224A2FFFCACC2001C308200013B -:104D20005040000A3C0380088CE2003C00A21023A3 -:104D300004410014240400058C62000414A2000342 -:104D40003C0380080A00132F240400058C62000431 -:104D500014A200158FBF00103C0208008C4200D83E -:104D6000304200201040000A3C028008346200807B -:104D7000906300089042004C144300053C028008F8 -:104D8000240400048FBF00100A0010CA27BD0018B9 -:104D90003443008034420100A040000C2402000192 -:104DA000A46200148FBF001003E0000827BD0018A4 -:104DB0003C0B800827BDFFE83C028000AFBF00101D -:104DC00034420100356A00809044000A35690100D0 -:104DD0008C4500148D4800389123000C308400FF6E -:104DE000010510231C4000B3306700FF2CE20006D1 -:104DF000504000B18FBF00102402000100E23004D7 -:104E000030C200035440000800A8302330C2000C18 -:104E1000144000A130C20030144000A38FBF001026 -:104E20000A0013FC0000000018C0002430820010AB -:104E30008D43001C8D42002C006818230043102B6A -:104E40001040000F000000008D22002000461021BD -:104E5000AD2200208D2200200043102B1440000BB7 -:104E60003C023FFF8D22002000431023AD22002092 -:104E70009542005C3042FFFF0A0013700062182167 -:104E8000AD200020006618213C023FFF3446FFFFA2 -:104E900000C3102B5440000100C018213C028008C0 -:104EA0003442008000651821AC43001CA04000245F -:104EB000A04000270A0013BE3C03800810400040B9 -:104EC0003C0380088D42003C004810231840003D00 -:104ED000346700809142002424420001A142002452 -:104EE000914200243C0308008C630024304200FF00 -:104EF0000043102B144000708FBF00108D22001C47 -:104F000000A210231840006C000000008D63000414 -:104F10009542005C006818233042FFFF00031843ED -:104F2000000210400043102A1040000501402021DB -:104F30008D620004004810230A0013A100021043F0 -:104F40009542005C3042FFFF000210403C068008A2 -:104F5000AC82002C34C5008094A2005C8CA4002C90 -:104F600094A3005C3042FFFF000210400082202129 -:104F70003063FFFF0083182101031021ACA2001C45 -:104F80008CC2000434C60100ACC2001C2402000222 -:104F90000E000F1FA0C2000C104000478FBF001072 -:104FA0003C0280008C4401003C0380008C6201F8CC -:104FB0000440FFFE240200020A0013EE000000007D -:104FC00034670080ACE50038346601008CC2001CF8 -:104FD00000A210231840000224A2FFFCACC2001C57 -:104FE000308200015040000A3C0380088CE2003C03 -:104FF00000A2102304430014240400058C62000462 -:1050000014A200033C0380080A0013E024040005F6 -:105010008C62000414A200288FBF00103C0208001C -:105020008C4200D8304200201040000A3C02800828 -:1050300034620080906300089042004C14430005E5 -:105040003C028008240400048FBF00100A0010CA2C -:1050500027BD00183443008034420100A040000CFA -:1050600024020001A46200143C0280008C44010070 -:105070003C0380008C6201F80440FFFE2402000221 -:10508000AC6401C0A06201C43C021000AC6201F833 -:105090000A0013FC8FBF00108FBF001001003021E9 -:1050A0000A00111B27BD0018010030210A00125A06 -:1050B00027BD00188FBF001003E0000827BD0018AF -:1050C0003C0380083464010024020003A082000C29 -:1050D0008C62000403E00008AC82001C3C058008E0 -:1050E00034A300809062002734A501002406004309 -:1050F00024420001A0620027906300273C020800C0 -:105100008C420048306300FF146200043C076021B9 -:1051100094A500DA0A0008ED30A5FFFF03E00008BF -:105120000000000027BDFFE8AFBF00103C02800078 -:105130000E0014058C4401803C02800834430100B9 -:10514000A060000C8C4200048FBF001027BD001827 -:1051500003E00008AC62001C27BDFFE03C028008B1 -:10516000AFBF0018AFB10014AFB0001034450080DD -:10517000344601003C0880008D09014090C3000CBA -:105180008CA4003C8CA200381482003B306700FFE6 -:105190009502007C90A30027146000093045FFFFB2 -:1051A0002402000554E200083C04800890C2000D6F -:1051B00024420001A0C2000D0A0014403C048008F3 -:1051C000A0C0000D3C048008348201009042000C15 -:1051D00024030005304200FF1443000A24A205DC2A -:1051E00034830080906200272C4200075040000565 -:1051F00024A20A0090630027240200140062100415 -:1052000000A210213C108008361000803045FFFFBE -:10521000012020210E001405A60500149602005C52 -:105220008E0300383C1180003042FFFF0002104026 -:1052300000621821AE03001C0E0003458E240140BD -:105240009202002534420040A20200250E000350C5 -:105250008E2401408E2401403C0380008C6201F8C2 -:105260000440FFFE24020002AC6401C0A06201C43D -:105270003C021000AC6201F88FBF00188FB100141F -:0C5280008FB0001003E0000827BD0020E4 -:04528C008008010095 -:10529000800800808008000000000C8000003200C0 -:1052A0008008024008000EDC08000F3408000F7868 -:1052B00008001010080010508008010080080080CD -:0452C0008008000062 -:0C52C4000A0000220000000000000000B2 -:1052D0000000000D6370352E302E306A3300000060 -:1052E00005000004000000000000000000000000B5 -:1052F000000000000000000038003C00000000003A -:10530000000000000000000000000000000000207D -:10531000000000000000000000000000000000008D -:10532000000000000000000000000000000000007D -:105330000000000000000000210038000000000113 -:105340000000002B00000000000000000000000032 -:1053500010000003000000000000000D0000000D20 -:105360003C020800244254243C0308002463564CA9 -:10537000AC4000000043202B1480FFFD24420004B9 -:105380003C1D080037BD9FFC03A0F0213C10080025 -:10539000261000883C1C0800279C54240E0002881C -:1053A000000000000000000D00A018210080102166 -:1053B000008028213C0460003C07600024060008AF -:1053C00010600006348420788C420000ACE2200893 -:1053D0008C63000003E00008ACE3200C0A000E2AF6 -:1053E00000000000240300403C02600003E00008CD -:1053F000AC4320003C0760008F8600008CE52074E1 -:105400000086102100A2182B14600007000028213C -:105410008F8AFD9824050001A14400138F890000A4 -:1054200001244021AF88000003E0000800A0102103 -:105430008F84FD988F8500009086001330C300FF95 -:1054400000A31023AF82000003E00008A080001337 -:105450008F84FD9827BDFFE8AFB00010AFBF0014E8 -:10546000908900119087001124020028312800FF44 -:105470003906002830E300FF2485002C2CD00001E1 -:10548000106200162484001C0E0000390000000089 -:105490008F8FFD983C0560002402020495EE003ECB -:1054A00095ED003C000E5C0031ACFFFF016C502517 -:1054B000ACAA20105200000124020004ACA220007B -:1054C0000000000000000000000000008FBF00147A -:1054D0008FB0001003E0000827BD00180A0000711B -:1054E000000028218F85FD9827BDFFD8AFBF002081 -:1054F000AFB3001CAFB20018AFB10014AFB00010D2 -:105500000080982190A4001124B0001C24B1002C2C -:10551000308300FF386200280E00005B2C5200012F -:105520000E00006300000000020020211240000273 -:1055300002202821000028210E0000390000000070 -:105540008F8DFD983C0880003C05600095AC003EC6 -:1055500095AB003C02683025000C4C00316AFFFF1F -:10556000012A3825ACA7201024020202ACA6201480 -:1055700052400001240200028FBF00208FB3001CA4 -:105580008FB200188FB100148FB0001027BD002813 -:1055900003E00008ACA2200027BDFFE0AFB2001876 -:1055A000AFB10014AFB00010AFBF001C3C116000E1 -:1055B0008E2320748F82000030D0FFFF30F2FFFF77 -:1055C0001062000C2406008F0E000039000000005D -:1055D0003C06801F0010440034C5FF00011238252E -:1055E00024040002AE27201000003021AE25201434 -:1055F000AE2420008FBF001C8FB200188FB10014A2 -:105600008FB0001000C0102103E0000827BD00206B -:1056100027BDFFE0AFB0001030D0FFFFAFBF0018D4 -:10562000AFB100140E00003930F1FFFF001024006C -:10563000009180253C036000AC7020108FBF0018E3 -:105640008FB100148FB0001024020004AC6220005F -:1056500027BD002003E000080000102127BDFFE85F -:105660003C0B6018AFBF00108D6F50002418FF7FF7 -:10567000340C807101F8702435CD380C240A0031C7 -:105680003C098000AD6D50003C08800AAD6C53BCF5 -:10569000AD2A00080E00049BAF88002C0E000459B0 -:1056A000000000000E000048000000003C07600001 -:1056B0008CE508082406FFF03C03570900A62024C7 -:1056C0003462F0001082005024190001AF800034D1 -:1056D0000E000BBC000000003C0660168CC40000ED -:1056E0003C0760148CE500A03C03FFFF00831024FE -:1056F0003C1F535300051FC2105F003D34C57C00A2 -:1057000094A201F2A780004C10400003A780005C27 -:10571000384B1E1EA78B004C94A201F810400004C9 -:105720008F8D0034384C1E1EA78C005C8F8D00348A -:1057300011A000049784005C240E0020A78E004C6A -:105740009784005C2C8F008151E0000124040080CC -:105750009785004C2CB80401530000012405040077 -:105760003C0260008C4304382419103C307FFFFF5A -:1057700013F900033087FFFF50E0000F24060050AC -:10578000A380005E9388005E51000010A784005C37 -:10579000A780005C9785005C8FBF0010A780004C3D -:1057A000A7800054A78000723C010800AC2500804F -:1057B00003E0000827BD0018A386005E9388005E02 -:1057C0005500FFF4A780005CA784005CA785004C0F -:1057D0008FBF00109785005CA7800054A7800072DF -:1057E0003C010800AC25008003E0000827BD00183C -:1057F00000035080014648218D2800043C066000CB -:105800000A00010F010628210A000103AF990034A4 -:105810003083FFFF8F88002C8F87002800032140F2 -:105820003C0580003C020050008248253C06600098 -:105830003C0A010034AC04008CCD08E001AA5824D5 -:1058400011600005000000008CCF08E024E7000193 -:1058500001EA7025ACCE08E08D19001001805821B6 -:10586000ACB900388D180014ACB8003CACA90030BD -:105870000000000000000000000000000000000028 -:105880000000000000000000000000000000000018 -:105890003C0380008C640000308200201040FFFD3B -:1058A0003C0F60008DED08E03C0E010001AE1824B5 -:1058B0001460FFE100000000AF87002803E000084B -:1058C000AF8B00388F85002C240BFFF03C06800046 -:1058D00094A7001A8CA9002430ECFFFF000C38C0FC -:1058E00000EB5024012A4021ACC8003C8CA40024C9 -:1058F0008CC3003C008310231840003300000000DC -:105900008CAD002025A200013C0F0050ACC2003835 -:1059100035EE00103C068000ACCE003000000000E8 -:105920000000000000000000000000000000000077 -:105930000000000000000000000000003C048000A7 -:105940008C990000333800201300FFFD30E200087E -:10595000104000173C0980008C880408ACA8001097 -:105960008C83040CACA300143C1900203C1880006C -:10597000AF19003094AE001894AF001C01CF302155 -:10598000A4A6001894AD001A25A70001A4A7001A28 -:1059900094AB001A94AC001E118B000300000000B1 -:1059A00003E000080000000003E00008A4A0001AC3 -:1059B0008D2A0400ACAA00108D240404ACA40014A9 -:1059C0000A0001AA3C1900208CA200200A000192C2 -:1059D0003C0F00500A0001800000000027BDFFE8D6 -:1059E000AFBF00100E0001C4000000008F89002C22 -:1059F0008FBF00103C038000A520000A9528000AF4 -:105A00009527000427BD00183105FFFF30E6000F81 -:105A10000006150000A2202503E00008AC64008009 -:105A20003C0508008CA500208F83000427BDFFE8FB -:105A3000AFB00010AFBF001410A300100000802111 -:105A4000240400010204300400A6202400C3102412 -:105A50005044000626100001001018802787FD9C86 -:105A60001480000A00671821261000012E09000288 -:105A70005520FFF38F830004AF8500048FBF00140F -:105A80008FB0001003E0000827BD00188C680000EC -:105A90003C058000ACA800240E0001C626100001C1 -:105AA0003C0508008CA500200A0001EB2E0900022D -:105AB00024050001008518043C0408008C840020A3 -:105AC00027BDFFC8AFBF003400831024AFBE003035 -:105AD000AFB7002CAFB60028AFB50024AFB400209C -:105AE000AFB3001CAFB20018AFB1001410400051AA -:105AF000AFB000108F84002C948700069488000AB1 -:105B000000E8302330D5FFFF12A0004B8FBF0034D8 -:105B1000948B0018948C000A016C50233142FFFFD3 -:105B200002A2482B1520000202A0202100402021C3 -:105B30002C8F000515E0000200809821241300043A -:105B40000E000153026020218F87002C02609021FB -:105B5000AF80003094F4000A026080211260004E91 -:105B60003291FFFF3C1670003C1440003C1E2000A8 -:105B70003C1760008F9900388F38000003161824F6 -:105B80001074004F0283F82B17E00036000000006D -:105B9000107E00478F86003014C0003A24030001B5 -:105BA00002031023022320213050FFFF1600FFF1D3 -:105BB0003091FFFF8F87002C3C1100203C108000AB -:105BC000AE11003094EB000A3C178000024B5021CC -:105BD000A4EA000A94E9000A94E800043123FFFFD4 -:105BE0003106000F00062D000065F025AEFE008096 -:105BF00094F3000A94F6001812D3003600122140E4 -:105C00008CFF00148CF4001003E468210000C02114 -:105C100001A4782B0298702101CF6021ACED001413 -:105C2000ACEC001002B2382330F5FFFF16A0FFB82D -:105C30008F84002C8FBF00348FBE00308FB7002CB4 -:105C40008FB600288FB500248FB400208FB3001CBE -:105C50008FB200188FB100148FB0001003E000085D -:105C600027BD00381477FFCC8F8600300E000D8BD7 -:105C700002002021004018218F86003010C0FFC98B -:105C800002031023027070238F87002C01C3682148 -:105C90000A00027631B2FFFF8F86003014C0FFC9C0 -:105CA0003C1100203C1080000A000240AE11003080 -:105CB0000E0003C4020020210A00026D00401821DA -:105CC000020020210E0007DB022028210A00026DBD -:105CD000004018210E000180000000000A00025957 -:105CE00002B2382327BDFFD8AFB40020AFB3001CE9 -:105CF000AFB20018AFB10014AFB00010AFBF0024B6 -:105D00000E0000E6241300013C0280083C03200042 -:105D10003C010800AC200070345400803472000351 -:105D20003C1080002411FF800E0001D7000000000D -:105D30008E06000038C5000130A400011480FFFA6F -:105D4000000000008E07010024030C0010E300098E -:105D50003C0580008E0901002D2830805500001080 -:105D60003C0480008E0B01002D6A31811140000C33 -:105D70003C0480008CAC0100118300040000202151 -:105D80008CAE010025CDFF8131A400FF8E0F0100F4 -:105D90000E0001FBAE0F00240A0002C13C0480008B -:105DA0008C9F010024180020AC9F002092990000D5 -:105DB000332300FF1078001F2402005010620022DD -:105DC000000000003C0480008C830100146000038C -:105DD00000000000566000143C0440008C8201006A -:105DE0008C990100000098210051F824001F79408F -:105DF0003338007F01F8702501D26825AC8D08305A -:105E00008C8C01008C890100258B010001715024CC -:105E1000000A39403128007F00E8302500D22825CB -:105E2000AC8508303C044000AE0401380A000299F9 -:105E3000000000008C8501000E00078D2404008006 -:105E40000A0002C13C0480008C8401000E0013EAA9 -:105E5000000000000A0002C13C04800000A4102BD6 -:105E600024030001104000090000302100052840F3 -:105E700000A4102B04A00003000318405440FFFCB2 -:105E8000000528405060000A0004182B0085382BBC -:105E900054E000040003184200C33025008520238D -:105EA000000318421460FFF9000528420004182B73 -:105EB00003E0000800C310213084FFFF30C600FF5C -:105EC0003C0780008CE201B80440FFFE00064C0055 -:105ED000012430253C08200000C820253C03100088 -:105EE000ACE00180ACE50184ACE4018803E000088B -:105EF000ACE301B83C0660008CC5201C2402FFF016 -:105F000030830200308601001060000E00A22824B9 -:105F100034A500013087300010E0000530830C000C -:105F200034A500043C04600003E00008AC85201C9C -:105F30001060FFFD3C04600034A5000803E0000889 -:105F4000AC85201C54C0FFF334A500020A000315E1 -:105F50003087300027BDFFE8AFB00010AFBF00149E -:105F60003C076000240600021080001100A0802180 -:105F70008F8300380E00030C8C6400188F82003869 -:105F800000002021240600018C45000C0E0002FDBB -:105F9000000000001600000224020003000010218F -:105FA0008FBF00148FB0001003E0000827BD001859 -:105FB0008CE8201C2409FFF001092824ACE5201CF2 -:105FC0008F8700380A0003328CE5000C3C02600E1B -:105FD0000080402134460100240900180000000020 -:105FE00000000000000000003C0A00503C0380005C -:105FF00035470200AC68003834640400AC65003CEE -:10600000AC6700308C6C0000318B00201160FFFD0C -:106010002407FFFF2403007F8C8D00002463FFFF13 -:1060200024840004ACCD00001467FFFB24C60004E8 -:1060300000000000000000000000000024A4020096 -:106040000085282B3C0300203C0E80002529FFFF03 -:1060500001054021ADC300301520FFE0008028215C -:1060600003E00008000000008F82003827BDFFD841 -:10607000AFB3001CAFBF0020AFB20018AFB1001427 -:10608000AFB0001094460002008098218C52001896 -:106090002CC300818C4800048C4700088C51000CF4 -:1060A0008C490010106000078C4A00142CC40004B6 -:1060B0001480001330EB000730C5000310A000105F -:1060C000000000002410008B020020210220282163 -:1060D0000E0002FD240600031660000224020003E5 -:1060E000000010218FBF00208FB3001C8FB200185A -:1060F0008FB100148FB0001003E0000827BD002806 -:106100001560FFF12410008B3C0C80003C03002044 -:10611000241F0001AD830030AF9F0030000000005D -:1061200000000000000000002419FFF024D8000F38 -:10613000031978243C1000D0AD88003801F0702598 -:1061400024CD00033C08600EAD87003C358504007B -:10615000AD8E0030000D38823504003C3C038000D9 -:106160008C6B0000316200201040FFFD0000000039 -:1061700010E0000824E3FFFF2407FFFF8CA80000C5 -:106180002463FFFF24A50004AC8800001467FFFB14 -:10619000248400043C04600EAC860038000000003B -:1061A00000000000000000003C0700203C068000CA -:1061B0000120202101402821ACC700300E000342FD -:1061C000000080210E00030C024020210A000382FF -:1061D0000200202127BDFFE0AFB200183092FFFF80 -:1061E000AFB10014AFBF001CAFB000101640000DDF -:1061F000000088210A0003F1022010212405000379 -:10620000508500278CE5000C0000000D262C0001B5 -:106210003191FFFF24EB00200232502B1140001976 -:10622000AF8B00388F820030144000168F87003803 -:106230003C0670003C0320008CE5000000A62024F2 -:10624000148300108F840040000544023C09800044 -:1062500000A980241480FFE9310600FF2CCA000B3E -:106260001140FFEB262C0001000668803C0E080060 -:1062700025CE51C801AE60218D8B00000160000861 -:1062800000000000022010218FBF001C8FB20018F8 -:106290008FB100148FB0001003E0000827BD00206C -:1062A0000E0002FD240400841600FFD88F870038FA -:1062B0000A0003D2AF800040020028210E00032410 -:1062C000240400018F8700380A0003D2AF82004007 -:1062D000020028210E000324000020210A000401EE -:1062E0008F8700380E000369020020218F87003855 -:1062F0000A0003D2AF82004030AFFFFF000F19C089 -:106300003C0480008C9001B80600FFFE3C1920047C -:106310003C181000AC830180AC800184AC990188EA -:10632000AC9801B80A0003D3262C000190E20002C9 -:1063300090FF00030000202100023A0000FF282502 -:10634000240600080E0002FD000000001600FFDD1C -:10635000240200038F870038000010210A0003D2B6 -:10636000AF82004090E50002000020210A000420D6 -:106370002406000994E5000490E9000390E300027C -:10638000000534000009420000C8202500832825AC -:106390002406000A0A0004200000202190E50002E3 -:1063A000000020210A0004202406000B000449C23A -:1063B0003127003F000443423C0280000008204097 -:1063C000240316802CE60020AC43002C24EAFFE0D6 -:1063D0002482000114C0000330A900FF00801021B6 -:1063E000314700FF000260803C0D8000240A00015C -:1063F000018D20213C0B000E00EA2804008B302187 -:1064000011200005000538278CCE000001C5382575 -:1064100003E00008ACC700008CD800000307782414 -:1064200003E00008ACCF000027BDFFE0AFB10014CF -:10643000AFB00010AFBF00183C0760008CE4080844 -:106440003402F0003C1160003083F000240501C0EC -:106450003C04800E00003021106200062410000170 -:106460008CEA08083149F0003928E0000008382B90 -:10647000000780403C0D0200AE2D0814240C16804D -:106480003C0B80008E2744000E000E34AD6C002CB7 -:10649000120000043C0216912405000112050010B0 -:1064A0003C023D6C345800E0AE3844083C11080012 -:1064B0008E31007C8FBF00183C06600000118540C3 -:1064C000360F16808FB100148FB000103C0E020002 -:1064D00027BD0020ACCF442003E00008ACCE08105C -:1064E0003C0218DA345800E0AE3844083C11080089 -:1064F0008E31007C8FBF00183C0660000011854083 -:10650000360F16808FB100148FB000103C0E0200C1 -:1065100027BD0020ACCF442003E00008ACCE08101B -:106520000A00043A240500010A00043A0000282168 -:1065300024020400A7820010A78000080000202188 -:106540003C06080024C654B02405FFFF248900013E -:10655000000440803124FFFF010618212C87002011 -:1065600014E0FFFAAC65000024040400A7840012C4 -:10657000A780000A000020213C06080024C65530F0 -:106580002405FFFF248D00010004608031A4FFFF7B -:10659000018658212C8A00201540FFFAAD650000C5 -:1065A000A7800014A780000CA780000E0000202107 -:1065B0003C06080024C655B02405FFFF24990001BD -:1065C0000004C0803324FFFF030678212C8E0004D2 -:1065D00015C0FFFAADE500003C0560008CA73D004A -:1065E0002403E08F00E310243446014003E0000858 -:1065F000ACA63D002487007F000731C224C5FFFF01 -:10660000000518C2246400013082FFFF000238C078 -:10661000A784001C3C010800AC270030AF800018A4 -:1066200000002821000020210000302124890001E1 -:1066300000A728213124FFFF2CA817011100000317 -:106640002C8300801460FFF924C6000100C02821BB -:10665000AF86001810C0001DA786001624CAFFFFD1 -:10666000000A11423C080800250855B01040000AF5 -:1066700000002021004030212407FFFF248E00016C -:106680000004688031C4FFFF01A860210086582BF8 -:106690001560FFFAAD87000030A2001F50400008CF -:1066A00000043080240300010043C804000410806B -:1066B000004878212738FFFF03E00008ADF800000C -:1066C00000C820212405FFFFAC85000003E000087E -:1066D0000000000030A5FFFF30C6FFFF30A8001FFC -:1066E0000080602130E700FF0005294200005021B2 -:1066F00010C0001D24090001240B00012518000111 -:10670000010B2004330800FF01267826390E0020F3 -:106710002DED00012DC2000101A218251060000D11 -:10672000014450250005C880032C40210100182198 -:1067300010E0000F000A20278D040000008A1825B1 -:10674000AD03000024AD00010000402100005021F5 -:1067500031A5FFFF252E000131C9FFFF00C9102B15 -:106760001040FFE72518000103E0000800000000CA -:106770008D0A0000014440240A000520AC68000096 -:1067800027BDFFE830A5FFFF30C6FFFFAFB0001008 -:10679000AFBF001430E7FFFF000050213410FFFFAF -:1067A0000000602124AF001F00C048212418000110 -:1067B0002419002005E0001601E010210002F94331 -:1067C000019F682A0009702B01AE402411000017B8 -:1067D000000C18800064102110E000058C4B0000B4 -:1067E00000F84004000838230167582400003821CD -:1067F0001540004100004021556000163169FFFF3F -:10680000258B0001316CFFFF05E1FFEC01E0102159 -:1068100024A2003E0002F943019F682A0009702B60 -:1068200001AE40241500FFEB000C18801546000552 -:106830003402FFFF020028210E0005040000382169 -:10684000020010218FBF00148FB0001003E0000879 -:1068500027BD00181520000301601821000B1C0241 -:1068600024080010306A00FF15400005306E000F4C -:10687000250D000800031A0231A800FF306E000F3A -:1068800015C00005307F0003251000040003190225 -:10689000320800FF307F000317E00005386900016F -:1068A0002502000200031882304800FF3869000109 -:1068B0003123000110600004310300FF250A0001AC -:1068C000314800FF310300FF000C694001A3402163 -:1068D000240A000110CAFFD53110FFFF246E000109 -:1068E00031C800FF1119FFC638C900012D1F002053 -:1068F00053E0001C258B0001240D00010A000597C0 -:10690000240E002051460017258B000125090001A7 -:10691000312800FF2D09002051200012258B000195 -:1069200025430001010D5004014B102425090001ED -:106930001440FFF4306AFFFF3127FFFF10EE000C18 -:106940002582FFFF304CFFFF000050213410FFFF75 -:10695000312800FF2D0900205520FFF225430001BA -:10696000258B0001014648260A000551316CFFFFC6 -:1069700000003821000050210A0005A33410FFFF59 -:1069800027BDFFD8AFB0001030F0FFFFAFB100144B -:10699000001039423211FFE000071080AFB3001C35 -:1069A00000B1282330D3FFFFAFB2001830A5FFFF9E -:1069B000008090210260302100442021AFBF0020E0 -:1069C0000E00052F3207001F022288213403FFFF2B -:1069D00002402021020028210260302100003821DD -:1069E000104300093231FFFF022010218FBF002029 -:1069F0008FB3001C8FB200188FB100148FB000103D -:106A000003E0000827BD00280E00052F000000004D -:106A100000408821022010218FBF00208FB3001C6E -:106A20008FB200188FB100148FB0001003E000087F -:106A300027BD0028000424003C036000AC603D0832 -:106A400010A00002348210063482101603E0000801 -:106A5000AC623D0427BDFFE0AFB00010309000FFF6 -:106A60002E020006AFBF001810400008AFB100149E -:106A7000001030803C030800246351F400C3282137 -:106A80008CA400000080000800000000000020210D -:106A90008FBF00188FB100148FB00010008010213C -:106AA00003E0000827BD0020979100161620005132 -:106AB000000020213C020800904200330A00060A30 -:106AC00000000000978D001215A000310000202169 -:106AD0000A00060A240200089787001014E0001A32 -:106AE0000000182100602021240200011080FFE92D -:106AF0008FBF0018000429C20045302100A6582B82 -:106B00001160FFE43C0880003C072000000569C0DC -:106B100001A76025AD0C00203C0380082402001F63 -:106B20002442FFFFAC6000000441FFFD2463000429 -:106B300024A5000100A6702B15C0FFF5000569C053 -:106B40000A0005F48FBF0018978700083C0408006E -:106B5000248454B0240504000E0005AF240600016F -:106B6000978B001024440001308AFFFF2569FFFF46 -:106B70002D4804000040282115000040A78900107E -:106B800024AC3800000C19C00A000608A7800008D1 -:106B90009787000A3C04080024845530240504002B -:106BA0000E0005AF2406000197990012244400014D -:106BB0003098FFFF272FFFFF2F0E04000040882191 -:106BC00015C0002CA78F0012A780000A3A0200030C -:106BD000262401003084FFFF0E0005DC2C45000157 -:106BE0000011F8C027F00100001021C00A00060AB9 -:106BF000240200089785001A9787000E3C040800BD -:106C0000248455B00E0005AF2406000197870016B6 -:106C10008F8900182445000130A8FFFF24E3FFFFFF -:106C20000109302B0040802114C00018A7830016F2 -:106C3000A780000E9785001C0E000E1E020020216A -:106C4000244A05003144FFFF0E0005DC2405000145 -:106C50003C05080094A500320E000E1E0200202103 -:106C6000244521003C020800904200330A00060A35 -:106C7000000521C00A000642A784000A24AC38009F -:106C8000000C19C00A000608A78400080A00065C68 -:106C9000A785000E308400FF27BDFFE82C82000688 -:106CA000AFBF0014AFB000101040001500A0382195 -:106CB000000440803C0308002463520C0103282197 -:106CC0008CA40000008000080000000024CC007F9D -:106CD000000751C2000C59C23170FFFF2547C400A4 -:106CE00030E5FFFF27840008020030210E00050474 -:106CF000240700019786001402062021A7840014AF -:106D00008FBF00148FB0001003E0000827BD0018EB -:106D10003C0508008CA50030000779C20E0002E691 -:106D200025E4DF003045FFFF3C040800248455B013 -:106D3000240600010E00050424070001978E0016AA -:106D40008FBF00148FB0001025CD000127BD0018A3 -:106D500003E00008A78D00160007C9C22738FF000E -:106D6000001878C231F0FFFF3C040800248455303D -:106D700002002821240600010E000504240700015A -:106D8000978D0012260E0100000E840025AC000134 -:106D90003C0B6000A78C0012AD603D083604000675 -:106DA000000030213C0760008CE23D04305F0006AB -:106DB00017E0FFFD24C9000100061B00312600FF7B -:106DC000006440252CC50004ACE83D0414A0FFF687 -:106DD0008FBF00148FB0001003E0000827BD00181B -:106DE000000751C22549C8002406000124070001FC -:106DF0003C040800248454B00E0005043125FFFF34 -:106E0000978700108FBF00148FB0001024E6000198 -:106E100027BD001803E00008A78600103084FFFF9C -:106E200030A5FFFF3C0680008CC201B80440FFFE85 -:106E30003C084080008838253C031000ACC001802D -:106E4000ACC50184ACC7018803E00008ACC301B83D -:106E50003084FFFF3C0680008CC201B80440FFFE76 -:106E60003C0840388CA70000008828253C0310000F -:106E7000ACC70180ACC5018803E00008ACC301B811 -:106E80008F8300588F8600501066000B00804021D1 -:106E90003C07080024E755C0000328C000A71021C4 -:106EA0008C44000024630001108800053063000F4B -:106EB0005466FFFA000328C003E000080000102118 -:106EC0003C07080024E755C400A7302103E0000870 -:106ED0008CC200003C039000346200010082202537 -:106EE0003C038000AC6400208C65002004A0FFFE01 -:106EF0000000000003E00008000000003C028000E9 -:106F0000344300010083202503E00008AC44002046 -:106F100027BDFFE0AFB100143091FFFFAFB000100C -:106F2000AFBF00181220001200A080218CA5000025 -:106F300014A00011240400023C0680008CC201B899 -:106F40000440FFFE3C074000022720258FBF0018A9 -:106F50008FB100148FB000103C03100027BD00203B -:106F6000ACC50180ACC4018803E00008ACC301B823 -:106F70000A00071D8CA500000E00067424060200FE -:106F8000000028210A00071DAE0000003087FFFF27 -:106F90003C0680008CC201B80440FFFE3C0A40065B -:106FA0008CA9000000EA4025ACC901808CA4000433 -:106FB0003C031000ACC40184ACC8018803E00008A5 -:106FC000ACC301B88F83FD9427BDFFE8AFBF0014A9 -:106FD000AFB00010906700080080102100802821C9 -:106FE00030E600400000202110C000088C50000056 -:106FF0000E00008802002021020020218FBF001413 -:107000008FB000100A00049727BD00180E00073249 -:10701000000000000E000088020020210200202154 -:107020008FBF00148FB000100A00049727BD00180E -:1070300027BDFFE0AFB000108F90FD94AFBF001CE4 -:10704000AFB20018AFB10014920600010080882191 -:107050000E00070430D2000492040005001129C27A -:10706000A605000034830040A20300050E00070EB1 -:10707000022020210E000499022020212402000178 -:10708000AE02000C02202821A602001024040002F7 -:10709000A602001224060200A60200140E000674C6 -:1070A000A60200161640000F8FBF001C978C0054DC -:1070B0003C0B08008D6B00782588FFFF3109FFFF2E -:1070C000256A0001012A382B10E00006A788005429 -:1070D0003C0F6006240E001635ED0010ADAE0050DA -:1070E0008FBF001C8FB200188FB100148FB000103A -:1070F00003E0000827BD002027BDFFE0AFB100146A -:10710000AFBF0018AFB000101080000400A08821AD -:107110002402008010820007000000000000000D23 -:107120008FBF00188FB100148FB0001003E000086B -:1071300027BD00200E00070400A020218F86FD94AB -:107140000220202190C500050E00070E30B000FF80 -:107150002403003E1603FFF1000000003C05800000 -:107160008CA401780480FFFE240800073C0710006F -:10717000ACB1014002202021A0A801448FBF00181B -:107180008FB100148FB00010ACA701780A00075B24 -:1071900027BD002027BDFFE0AFB00010AFBF001833 -:1071A000AFB100143C1080008E11002000000000E0 -:1071B0000E000499AE040020AE1100208FBF00180D -:1071C0008FB100148FB0001003E0000827BD00202D -:1071D0003084FFFF3C0680008CC201B80440FFFEF3 -:1071E0003C084035008838253C031000ACC50180C0 -:1071F000ACC00184ACC7018803E00008ACC301B88F -:107200003084FFFF3C0680008CC201B80440FFFEC2 -:107210003C084036008838253C031000ACC501808E -:10722000ACC00184ACC7018803E00008ACC301B85E -:1072300027BDFFD0AFB500243095FFFFAFB60028C3 -:10724000AFB40020AFBF002CAFB3001CAFB200182A -:10725000AFB10014AFB0001030B6FFFF12A000278E -:107260000000A0218F9200388E4300003C06800071 -:107270002402004000033E0200032C0230E4007FA1 -:10728000006698241482001D30A500FF8F830048FB -:107290002C68000A510000108F86003000035880CF -:1072A0003C0C0800258C5228016C50218D490000AF -:1072B000012000080000000002D4702131C5FFFF4A -:1072C0000E0006D624040084166000028F92003857 -:1072D000AF8000488F860030264F002026890001AD -:1072E00001E090213134FFFF14C00004AF8F00385B -:1072F0000295282B14A0FFDC000000000280102162 -:107300008FBF002C8FB600288FB500248FB40020CB -:107310008FB3001C8FB200188FB100148FB0001013 -:1073200003E0000827BD00302407003414A70146FD -:10733000000000009247000E8F98FD988F90FD94FA -:10734000240F1600A30700199244000D3C0880008A -:107350003C07800CA3040018965F00123C096000F3 -:107360003C117FFFA61F005C965900103622FFFFDC -:10737000240400053325FFFFAE0500548E46001C93 -:10738000AD0F00288CEE00008D2D444801C6182654 -:1073900001A33021AE0600388E0C003824CA00014B -:1073A0003C0D7F00AE0C003C8E0B003CAF0B00048C -:1073B000AE0A00208E130020AE13001CA300001B99 -:1073C000AE02002CA30400128E5F001424130050A0 -:1073D000AE1F00348E190034AF1900148E4500180A -:1073E000AE050048924F000CA20F004E9209000813 -:1073F000352E0020A20E00088E030018006D6024B8 -:10740000358B4000AE0B0018920A0000315200FF8D -:10741000125302A62413FF803C0408002484564023 -:107420000E00074000000000240C000424080001A6 -:107430003C0508008CA556403C048000A20C0025A9 -:10744000A20800058C9001780600FFFE8F9200389C -:10745000240D00023C031000AC850140A08D0144C6 -:10746000AC8301780A000804AF8000482CAD0037D7 -:1074700011A0FF998F860030000580803C11080024 -:1074800026315250021178218DEE000001C0000813 -:10749000000000002410000414B0008E3C0780009F -:1074A0003C0B08008D6B56408F86FD94ACEB0020A2 -:1074B0008E4300088F8FFD98240E0050ACC300301F -:1074C0008E4A0008ACCA00508E42000CACC2003498 -:1074D0008E440010ACC400388E5F0010ACDF005446 -:1074E0008E590014ACD9003C8E580018ADF8000439 -:1074F0008E51001CACD1002090C5000030A900FFC7 -:10750000112E0276000000008CC500348CD10030B2 -:1075100000B1302304C000F32404008C126000F09A -:10752000240200030A000804AF820048240F00056B -:1075300014AF00683C0B80003C0308008C6356408D -:107540008F86FD94AD6300208E4A00048F99FD98CC -:1075500024072000ACCA001C924200082412000834 -:10756000A32200198F840038909F0009A33F0018C0 -:107570008F85003890B8000A330400FF1092001085 -:10758000288C0009158000BC24080002240E00206D -:10759000108E000B34078000288900211520000878 -:1075A0002407400024110040109100053C07000111 -:1075B000240F0080108F00023C07000224074000C7 -:1075C0008CDF00183C04FF0003E4C8240327C02517 -:1075D000ACD8001890B2000BA0D200278F830038DF -:1075E0009465000C10A0022A000000009467000CB3 -:1075F0003C198000240BFFBFA4C7005C9062000E02 -:1076000024070004A0C200088F840038909F000F58 -:10761000A0DF00098F8C00388D9200108F38007425 -:1076200002582823ACC500588D8F0014ACCF002C15 -:10763000959100183229FFFFACC90040958E001AC1 -:1076400031D0FFFFACD000448D8D001CACCD004884 -:1076500095880002A4C800789183000EA0C300089A -:1076600090CA0008014B1024126001D4A0C2000887 -:107670008F9200380A000804AF87004824060006ED -:1076800014A600143C0D80003C1008008E105640DB -:107690008F8CFD90ADB000208E4800188F86FD9431 -:1076A0008F8AFD98AD8800008CC300382404000543 -:1076B000AD8300048CCB003C12600081AD4B000018 -:1076C0000A000804AF840048240E000710AE004BE7 -:1076D000240400063C05080024A556400E000713AC -:1076E000240400818F9200380013102B0A00080434 -:1076F000AF8200482419002314B9FFF63C0B800028 -:107700003C0C08008D8C56408F8AFD98AD6C002093 -:107710008F91FD948E4600042544002026450014D8 -:10772000AE260028240600030E000E2A2550003045 -:107730008F87003802002021240600030E000E2A45 -:1077400024E500083C040800248456400E0007404D -:107750000000000092220000241F0050304400FF6F -:10776000549FFFE18F9200380E000E1500000000BC -:107770000A0009098F9200382403003314A3003251 -:107780003C0280003C1108008E3156408F8EFD98DF -:10779000AC5100208E440008240900288F88FD94F5 -:1077A000ADC400308E5F000C24060009ADDF00344C -:1077B0008E590010ADD900388E580014ADD8002075 -:1077C0008E450018ADC500248E4F001CADCF00289B -:1077D000A1C900118E4D000412600031AD0D0028CA -:1077E0008F9200380A000804AF860048240900225E -:1077F00014A9FFB800000000240400073C0F080093 -:107800008DEF56403C118000AE2F00205660FEB137 -:10781000AF8400483C040800248456400E00074012 -:10782000241300508F98FD9493120000324500FFFE -:1078300010B30169000000008F9200380000202181 -:107840000A000804AF8400483C05080024A55640FF -:107850000E0006E3240400810A0009098F92003813 -:1078600002D498213265FFFF0E0006D6240400845E -:107870000A0008048F9200381088FF512407040082 -:107880002887000310E001A324100004240D000148 -:10789000548DFF4B240740000A0008BF2407010055 -:1078A0003C05080024A556400E000732240400823F -:1078B0008F920038000030210A000804AF8600488B -:1078C0003C040800248456408CC200380E00074057 -:1078D0008CC3003C8F9200380A00095F0000202111 -:1078E000240400823C05080024A556400E000732FF -:1078F000000000008F920038000010210A000804E8 -:10790000AF8200488E5000048F91FD943C0A8000A5 -:10791000AD500020922200050200282130460002CE -:1079200014C001802404008A8F92FD98020028214F -:107930002404008D924B001B3163002014600179F8 -:1079400000000000922D0009240C001231A800FF55 -:10795000110C0174240400810E0007040200202190 -:107960009245001B240E00040200202134A900428D -:10797000A249001B0E00070EA22E00253C04800029 -:107980008C9101780620FFFE24180002AC90014083 -:10799000A09801448F9200383C0F1000AC8F017802 -:1079A0000A00090A0013102B8E5000048F91FD94D9 -:1079B0003C1F8000AFF00020923900050200282112 -:1079C0003327000214E000172404008A92240009DF -:1079D0002412000402002821308600FF10D200117A -:1079E000240400810E000704020020218F8CFD98E2 -:1079F000240B00122403FFFE918D001B02002021A6 -:107A000035A80020A188001BA22B0009922A00059E -:107A1000014310240E00070EA222000502002821B7 -:107A2000000020210E0007CF000000000A00090915 -:107A30008F9200388E5100043C0280003C100800F8 -:107A400026105640AC5100203C010800AC31564095 -:107A50009246000330C40004108001658F84FD94B9 -:107A600024020006A0820009924D001B2408FFC0DA -:107A700031AC003F01885825A08B000892430003D9 -:107A8000306A00011540015C000000008E420008D1 -:107A9000AE0200083C0208008C4256481040015BD0 -:107AA0008F8EFD98000281C28F85FD94A5D0000CB9 -:107AB0008E5F000C240F000124090014ADDF002CA0 -:107AC0008E590010ADD9001C96470016A5C7003C82 -:107AD00096580014A5D8003EACAF000CA4AF00101F -:107AE000A4AF0012A4AF0014A4AF00161260015F8F -:107AF000A1C9001192440003309200022E530001EC -:107B00008F920038266200080A000804AF820048FD -:107B10008E4600043C0580003C048008ACA6002092 -:107B20008E4700089089000024110050312200FF88 -:107B3000105100B8240500883C0480008C8F01B8E7 -:107B400005E0FFFE0013802B3C18400900B810250B -:107B5000AF9000483C101000AC860180AC870184D7 -:107B6000AC820188AC9001B80A0008058F8600300D -:107B70008E4500043C0680003C098008ACC500200E -:107B8000913F00002404005033F900FF132400B09B -:107B9000240600883C0480008C8A01B80540FFFE62 -:107BA0003C0E400E00CE68253C081000AC850180DC -:107BB000AC800184AC8D0188AC8801B8912B0000A9 -:107BC000240CFF8024040004016C182524060030D6 -:107BD0000E000674A12300000A0009098F920038E4 -:107BE0008E5000048F91FD983C0F8000ADF0002076 -:107BF0009225001B30A900101120007C2403008175 -:107C00003C0480008C8701B804E0FFFE3C1F401F4D -:107C1000AC900180007F10250013C82B3C10100091 -:107C2000AC800184AF990048AC820188AC9001B867 -:107C30000A0008058F8600308E44001C0E0006EFF7 -:107C400000000000104000F8004038218F920038FA -:107C5000240600893C0580008CAE01B805C0FFFEFB -:107C600000000000ACA701808E50001C3C114001B8 -:107C70000013782B00D138253C131000ACB00184E0 -:107C8000AF8F0048ACA70188ACB301B80A00080563 -:107C90008F860030965900023C100800261056408E -:107CA00033380004130000A33C0460008E5F001C06 -:107CB0003C068000ACDF00203C010800AC3F564091 -:107CC000964F000231E7000114E000E300000000DD -:107CD0008E420004AE0200083C1008008E10564888 -:107CE000120000D93C0680008F85FD94241000010D -:107CF0008CBF00188F91FD988F89FD9003E6C825F1 -:107D0000ACB90018A0A00005ACB0000C3C180800ED -:107D10008F1856488F870038A4B00010001879C219 -:107D2000A4B00012A4B00014A4B00016A62F000C3A -:107D30008CEE00088F8D00388F8C0038AE2E002C12 -:107D40008DA8000C24070002AE28001C918B0010A7 -:107D5000A22B00118F830038906A0011A12A00081D -:107D60008F82003890440012A0A4004E8F920038F9 -:107D700092460013A22600128F920038965F0014DC -:107D8000A63F003C96590016A639003E8E580018B2 -:107D9000AE3800145660FD4FAF8700483C05080020 -:107DA00024A556400E000713000020218F920038B2 -:107DB000000038210A000804AF8700483C0508008D -:107DC00024A556400E000732240400828F9200380A -:107DD0000A0008EC000038210E000E15000000001B -:107DE0008F9200380A00095F000020210E0007046E -:107DF000020020219232001B020020213658001080 -:107E00000E00070EA238001B8F9200380A000A4F9E -:107E1000000018219243000C306A00011140000359 -:107E200000000000964B000EA48B002C9248000C22 -:107E3000310C00021180FF4000002821964E0012F4 -:107E40008E4D0014A48E001A0A000A1DAC8D001C71 -:107E50008F8300588F8700501067FF4E000030213D -:107E60003C080800250855C4000320C000883021C4 -:107E70008CD10000122500C8246200013043000F9D -:107E80001467FFFA000320C00A000A340000302102 -:107E90003C05080024A556400E0007322404008B40 -:107EA0008F9200380A0008EC0013382B3C0B0800B6 -:107EB0008D6B564024D8FFFE25710100322A007FC9 -:107EC0000147902102331024AD020028AE4600D0B5 -:107ED000AE4000D40A000855AE58001CACC0005497 -:107EE0003C0E08008DCE56403C09800C352C01001C -:107EF000ACEE00288E500014AD9000D08E4D0014D2 -:107F0000AD8D00D48E4800102507FFFE0A000891B1 -:107F1000AD87001C5490FDAA240740000A0008BF4A -:107F2000240710000E0007C3000000000A00090922 -:107F30008F9200388C83442C3C05DEAD34B2BEEF0A -:107F40003C010800AC205640107200900000000078 -:107F50003C046C62348279701462000824040002CC -:107F6000978A00549783004C020028210143482B34 -:107F70001120001924040092240400020E0005E4DC -:107F8000240502003C0B8000AD6200203C0108008B -:107F9000AC2256401040000D8F8E0038240C002873 -:107FA0002404000391CD001031A800FF550C0001FE -:107FB000240400010E00004C0000000010400004EA -:107FC000240400830A000A7F8F920038240400836F -:107FD0003C05080024A556400E00071300000000D1 -:107FE0008F9200380013382B0A000804AF8700482E -:107FF0000A0009E8240200128E4400080E0006EF71 -:10800000000000000A0009F4AE0200083C05080068 -:1080100024A556400E0006E3240400878F92003802 -:108020000A000A110013102B240400040E0005E4BA -:108030002405003014400014004038218F9200388D -:108040000A000A64240600833C05080024A5564063 -:108050000A000B45240400878E4400040E0006EF3E -:10806000000000000A000A85AE0200083C05080076 -:1080700024A556400E000732240400828F92003857 -:108080000A000A11000010218F9200383C08800875 -:108090003C0C8000240B0050240A0001AD8200201B -:1080A000A10B0000A10A000192490004A1090018D7 -:1080B00092440005A1040019924300063C04080004 -:1080C000248455C4A103001A924200073C0308000F -:1080D000246355C0A102001B92450008A105001CA5 -:1080E00092460009A106001D925F000AA11F001E12 -:1080F0009259000BA119001F9258000CA1180020E2 -:108100009251000DA11100219250000EA1100022E9 -:10811000924F000FA10F0023924E0010A10E0024D9 -:10812000924D0011A10D0025964C0014A50C0028BD -:10813000964B00168F8A00508F980058A50B002A86 -:1081400096490018000A10C025450001A509002C19 -:108150008E46001C0044C8210043F82130A5000FC2 -:10816000AFE60000AF27000010B80003AF85005055 -:108170000A000A640000302124AD000131A8000F7C -:10818000000030210A000A64AF8800588C83442C18 -:108190000A000B243C046C623C07080024E755C02D -:1081A00000879021ACC00000000030210A000A3492 -:1081B000AE4000003C0482013C03600034820E02A9 -:1081C000AC603D68AF80007803E00008AC623D6CB5 -:1081D00027BDFFE8AFB000103090FFFF001018423D -:1081E0002C620041AFBF0014144000022404008040 -:1081F000240300403C010800AC3000603C01080052 -:10820000AC2300640E000E1E00602821244802BF2B -:108210002409FF8001092824001039800010304013 -:108220008FBF00148FB0001000A7202100861821F6 -:10823000AF8300603C010800AC2500583C010800F9 -:10824000AC24005C03E0000827BD0018308300FF69 -:1082500030C6FFFF30E400FF3C0880008D0201B80B -:108260000440FFFE00035400014438253C0960002F -:1082700000E920253C031000AD050180AD06018416 -:10828000AD04018803E00008AD0301B88F86003813 -:108290003C096012352700108CCB00043C0C600EAA -:1082A00035850010316A00062D480001ACE800C495 -:1082B0008CC40004ACA431808CC2000894C30002BA -:1082C000ACA2318403E00008A78300708F850038DA -:1082D0008F87FF208F86FF288CAE00043C0F601232 -:1082E00035E80010ACEE00688CAD0008ACED006C19 -:1082F0008CAC0010ACCC004C8CAB000CACCB004870 -:1083000094CA00543C0208008C42004425490001F4 -:10831000A4C9005494C400543083FFFF10620017B6 -:10832000000000003C0208008C420040A4C2005241 -:108330008CA30018ACE300308CA20014ACE2002C3B -:108340008CB90018ACF900388CB800142405000171 -:10835000ACF800348D0600BC50C500198D0200B485 -:108360008D0200B8A4E2004894E40048A4E4004A66 -:1083700094E800DA03E000083102FFFF3C02080045 -:108380008C420024A4C00054A4C200528CA3001844 -:10839000ACE300308CA20014ACE2002C8CB90018C5 -:1083A000ACF900388CB8001424050001ACF8003496 -:1083B0008D0600BC54C5FFEB8D0200B88D0200B4E1 -:1083C000A4E2004894E40048A4E4004A94E800DAF7 -:1083D00003E000083102FFFF8F8600383C04800074 -:1083E0008CC900088CC80008000929C0000839C0E1 -:1083F000AC87002090C30007306200041040003AB0 -:10840000AF85007490CB0007316A00081140003935 -:108410008F87FF248CCD000C8CCE001401AE602B16 -:1084200011800032000000008CC2000CACE2007031 -:108430008CCB00188F85FF208F88FF28ACEB007451 -:108440008CCA00102402FFF8ACAA00C88CC9000C2A -:10845000AD0900608CC4001CACA400C090E3007C9B -:108460000062C824A0F9007C90D80007330F0008F0 -:1084700011E000040000000090ED007C35AC00012C -:10848000A0EC007C90CF000731EE000111C0000984 -:108490000000000090E4007C2418000234820002F6 -:1084A000A0E2007C90A300EC307900FF13380013A9 -:1084B0002408003490C900073126000210C00004CF -:1084C0000000000090EB007C356A0004A0EA007C0C -:1084D00090ED007D31AC003FA0EC007D94A700DA68 -:1084E00003E0000830E2FFFF8F87FF240A000C5AE8 -:1084F0008CC200140A000C5BACE000700A000C7C1B -:10850000ACA800CC8F8C003827BDFFD8AFB3001CBF -:10851000AFB20018AFB00010AFBF0020AFB1001471 -:10852000918F00153C13600E3673001031EB000F75 -:10853000A38B007C8D8F00048D8B0008959F00120B -:10854000959900109584001A9598001E958E001C30 -:1085500033EDFFFF332AFFFF3089FFFF3308FFFFB2 -:1085600031C7FFFF3C010800AC2D00243C0108008E -:10857000AC2900443C010800AC2A0040AE683178C8 -:10858000AE67317C91850015959100163C12601202 -:108590003652001030A200FF3230FFFFAE62318849 -:1085A000AE5000B491830014959F0018240600017A -:1085B0000066C80433F8FFFFAE5900B8AE5800BCDF -:1085C000918E0014AF8F00643C08600631CD00FF2F -:1085D000AE4D00C0918A00159584000E3C07600ADC -:1085E000314900FFAF8B00683084FFFFAE4900C8FF -:1085F000351100100E000BC334F004103C020800CB -:108600008C4200603C0308008C6300643C06080058 -:108610008CC600583C0508008CA5005C8F84006067 -:108620008FBF0020AE23004CAE65319CAE030054DA -:10863000AE4500DCAE6231A0AE6331A4AE663198C7 -:10864000AE2200488FB3001CAE0200508FB1001460 -:10865000AE4200E0AE4300E4AE4600D88FB000105A -:108660008FB200180A0004CC27BD0028978500723D -:108670009783005C27BDFFE8AFB0001000A3102B6C -:10868000AFBF0014240400058F900038104000553F -:10869000240900020E0005E48F850060AF8200749B -:1086A000240400031040004F240900023C0680000F -:1086B0000E00004CACC2002024070001240820005A -:1086C0001040004D24040005978E00728F8AFF240D -:1086D0002409005025C50001A7850072A1490000AA -:1086E0003C0D08008DAD0064240380008F84FF20C2 -:1086F000000D6600AD4C0018A5400006954B000A21 -:108700008F85FF282402FF8001633024A546000ADC -:10871000915F000A0000482103E2C825A159000A20 -:10872000A0A00008A140004CA08000C5961800023F -:10873000978300703C020004A49800DA960F0002B0 -:108740002418FFBF25EE2401A48E00AE8E0D000478 -:10875000ACAD00448E0C0008ACAC0040A4A00050AE -:10876000A4A000548E0B000C240C0030AC8B00280D -:108770008E060010AC860024A480003EA487004E24 -:10878000A4870050A483003CAD420074AC8800C8AC -:10879000ACA80060A08700EC909F00C433F9007F74 -:1087A000A09900C4909000C402187824A08F00C43F -:1087B000914E007C35CD0001A14D007C938B007C57 -:1087C000AD480070AC8C00CCA08B00C68F880068D0 -:1087D0008F870064AC8800B4AC8700B8A5400078EF -:1087E000A540007A8FBF00148FB000100120102127 -:1087F00003E0000827BD00188F8500740E00067482 -:108800008F8600600A000D482409000227BDFFE0A2 -:10881000AFB000108F900038AFB10014AFBF001898 -:108820008E0900040E000499000921C08E0800047E -:108830008F84FF208F82FF28000839C03C0680000B -:10884000ACC70020948500DA904300131460001C2C -:1088500030B1FFFF8F8CFF24918B0008316A0040FC -:108860001540000B000000008E0D00040220302196 -:108870008FBF00188FB100148FB0001024040022A5 -:1088800000003821000D29C00A000BE227BD00209E -:108890000E000063000000008E0D00040220302155 -:1088A0008FBF00188FB100148FB000102404002275 -:1088B00000003821000D29C00A000BE227BD00206E -:1088C0000E00005B000000008E0D0004022030212D -:1088D0008FBF00188FB100148FB000102404002245 -:1088E00000003821000D29C00A000BE227BD00203E -:1088F00027BDFFE0AFB200183092FFFFAFB000100D -:10890000AFBF001CAFB100141240001E0000802158 -:108910008F8600388CC500002403000600053F0246 -:108920000005140230E4000714830016304500FFF0 -:108930002CA8000611000040000558803C0C0800DF -:10894000258C532C016C50218D490000012000081A -:10895000000000008F8E0078240D000111CD005022 -:1089600024020002AF820078260900013130FFFFA7 -:1089700024C800200212202B010030211480FFE5C2 -:10898000AF880038020010218FBF001C8FB2001882 -:108990008FB100148FB0001003E0000827BD002045 -:1089A0009387005E54E00034000030210E000C90EC -:1089B000000000008F8600380A000DA82402000184 -:1089C0008F8700782405000210E50031240400138D -:1089D0000000282100003021240700010E000BE2D6 -:1089E000000000000A000DA98F8600388F830078F0 -:1089F000240200021462FFF6240400120E000C454B -:108A0000000000008F850074004030212404001213 -:108A10000E000BE2000038210A000DA98F860038F5 -:108A20008F8300782411000310710029241F000295 -:108A3000107FFFCE26090001240400100000282129 -:108A4000000030210A000DC6240700018F91007834 -:108A5000240600021626FFF9240400100E000CEA7A -:108A600000000000144000238F9800388F860038E3 -:108A70000A000DA824020003240400140E000BE2D7 -:108A8000000028218F8600380A000DA82402000269 -:108A90000E000D52000000000A000DA98F8600385C -:108AA0000E000BF200000000241900022404001440 -:108AB000000028210000302100003821AF99007803 -:108AC0000E000BE2000000000A000DA98F8600389E -:108AD0000E000C02000000008F85007424190002B3 -:108AE0000040302124040010000038210A000DFF4E -:108AF000AF9900780040382124040010970F00023D -:108B0000000028210E000BE231E6FFFF8F860038BF -:108B10000A000DA9AF9100788F84FF243C077FFFE6 -:108B200034E6FFFF8C8500182402000100A61824FB -:108B3000AC83001803E00008A08200053084FFFF2A -:108B400030A5FFFF108000070000182130820001CF -:108B50001040000200042042006518211480FFFB31 -:108B60000005284003E000080060102110C0000745 -:108B7000000000008CA2000024C6FFFF24A5000412 -:108B8000AC82000014C0FFFB2484000403E0000852 -:108B90000000000010A0000824A3FFFFAC86000026 -:108BA00000000000000000002402FFFF2463FFFF1C -:108BB0001462FFFA2484000403E0000800000000AF -:108BC000000411C003E000082442024027BDFFE872 -:108BD000AFB0001000808021AFBF00140E000E3F28 -:108BE00000A0202100504821240AFF808FBF0014DC -:108BF0008FB00010012A30243127007F3C08800A02 -:108C00003C04210000E8102100C428253C0380001A -:108C100027BD0018AC650024AF820024AC400000E2 -:108C2000AC65002403E00008AC4000403C0D0800A7 -:108C30008DAD005800056180240AFF8001A45821F1 -:108C4000016C4821012A30243127007F3C08800C28 -:108C50003C04210000E8102100C428253C038000CA -:108C6000AC650028AF82002003E00008AC4000247F -:108C700030A5FFFF3C0680008CC201B80440FFFE17 -:108C80003C08601500A838253C031000ACC40180E6 -:108C9000ACC00184ACC7018803E00008ACC301B8D4 -:108CA0003C0D08008DAD005800056180240AFF804E -:108CB00001A45821016C4021010A482400093140D7 -:108CC0003107007F00C728253C04200000A4182598 -:108CD0003C028000AC43083003E00008AF80002075 -:108CE00027BDFFE8AFB0001000808021AFBF0014A7 -:108CF0000E000E3F00A0202100504821240BFF80D1 -:108D0000012B5024000A39403128007F3C06200006 -:108D10008FBF00148FB0001000E8282534C2000176 -:108D200000A218253C04800027BD0018AC83083041 -:108D300003E00008AF8000243C0580088CA7006099 -:108D40003C0680080087102B144000112C83400043 -:108D50008CA800602D0340001060000F2403400029 -:108D60008CC900600089282B14A000020080182103 -:108D70008CC3006000035A42000B30803C0A08009C -:108D8000254A53A000CA202103E000088C8200007D -:108D90001460FFF32403400000035A42000B3080AC -:108DA0003C0A0800254A53A000CA202103E000081D -:108DB0008C8200003C05800890A6000893840088FF -:108DC00024C20001304200FF3043007F1064000CD9 -:108DD00000023827A0A200083C0480008C8501789E -:108DE00004A0FFFE8F8A0080240900023C081000C6 -:108DF000AC8A0140A089014403E00008AC880178F6 -:108E00000A000EC430E2008027BDFFD8AFB20018C0 -:108E10008F920084AFBF0020AFB3001CAFB0001032 -:108E2000AFB100148F9300208E5900283C100080B1 -:108E30003C0EFFEFAE7900008E580024A260000ABD -:108E400035CDFFFFAE7800049251002C3C0BFF9F04 -:108E5000356AFFFFA271000C8E6F000C3C080040C9 -:108E6000A271000B01F06025018D4824012A3824ED -:108E700000E83025AE66000C8E450004AE60001898 -:108E80003C0400FFAE6500148E43002C3482FFFFCB -:108E9000A66000080062F824AE7F00108E5900081A -:108EA0008F900080964E0012AE7900208E51000CFB -:108EB00031D83FFF00187980AE7100248E4D001428 -:108EC00001F0602131CB0001AE6D00288E4A001800 -:108ED000000C41C2000B4B80AE6A002C8E46001C79 -:108EE00001093821A667001CAE66003096450002D5 -:108EF0008E440020A665001EAE6400349243003309 -:108F00003062000454400006924700003C02800892 -:108F1000344301008C7F00C0AE7F003092470000D8 -:108F20008F860024A0C700309245003330A4000291 -:108F300050800007925100018F880024240BFF808D -:108F4000910A0030014B4825A109003092510001DF -:108F50008F900024240CFFBF2404FFDFA2110031F6 -:108F60008F8D00243C1880083711008091AF003CA1 -:108F700031EE007FA1AE003C8F890024912B003C94 -:108F8000016C5024A12A003C8F9F00248E6800149D -:108F900093E6003C2D0700010007114000C428247F -:108FA00000A21825A3E3003C8F87002496590012E5 -:108FB000A4F900328E450004922E007C30B00003EC -:108FC0000010782331ED000300AD102131CC0002F8 -:108FD0001580000224460034244600303C028008FC -:108FE00034430080907F007C00BFC82433380004E5 -:108FF0001700000224C2000400C010218F98002432 -:1090000024190002ACE20034A3190000924F003F83 -:109010008F8E00243C0C8008358B0080A1CF00018E -:109020008F910024924D003F8E440004A62D000233 -:10903000956A005C0E000E9D3150FFFF00024B80D0 -:10904000013038253C08420000E82825AE25000400 -:109050008E4400388F850024ACA400188E4600345E -:10906000ACA6001CACA0000CACA00010A4A0001486 -:10907000A4A00016A4A00020A4A00022ACA000245C -:109080008E62001450400001240200018FBF0020B6 -:109090008FB3001C8FB200188FB100148FB0001076 -:1090A000ACA200080A000EBC27BD002827BDFFC8DF -:1090B0003C05800834A40080AFBF0034AFBE003050 -:1090C000AFB7002CAFB60028AFB50024AFB4002076 -:1090D000AFB3001CAFB20018AFB10014AFB00010B6 -:1090E000948300789482007A104300512405FFFF96 -:1090F0000080F0210A000FCC0080B821108B004DB9 -:109100008FBF00348F8600803C1808008F18005CE9 -:109110002411FF803C1680000306782101F1802491 -:10912000AED0002C96EE007A31EC007F3C0D800E24 -:1091300031CB7FFF018D5021000B4840012AA8212F -:1091400096A400003C0808008D0800582405FF8004 -:1091500030953FFF01061821001539800067C821AE -:109160000325F8243C02010003E290253338007FF8 -:109170003C11800CAED20028031190219250000DBA -:10918000320F000411E0003702E0982196E3007AE4 -:1091900096E8007A96E5007A2404800031077FFF84 -:1091A00024E3000130627FFF00A4F82403E2C82515 -:1091B000A6F9007A96E6007A3C1408008E940060C6 -:1091C00030D67FFF12D400C1000000008E58001876 -:1091D0008F84008002A028212713FFFF0E000E7746 -:1091E000AE53002C97D5007897D4007A12950010D2 -:1091F000000028213C098008352401003C0A800831 -:1092000091480008908700C53114007F30E400FFCA -:109210000284302B14C0FFB9268B0001938E008886 -:10922000268C0001008E682115ACFFB78F86008068 -:109230008FBF00348FBE00308FB7002C8FB6002850 -:109240008FB500248FB400208FB3001C8FB200189C -:109250008FB100148FB0001000A0102103E00008AF -:1092600027BD003800C020210E000E4202802821B8 -:109270008E4B00108E4C00308F8400242409000295 -:10928000016C5023AE4A0010A089000096E3005CF8 -:109290008E4400308F9100240E000E9D3070FFFF31 -:1092A00000024380011028253C07420000A710253A -:1092B000AE2200048E5F00048F8A00248E590000C5 -:1092C000240B0008AD5F001CAD590018AD40000C28 -:1092D000AD4000109246000A240400052408C00096 -:1092E00030D000FFA550001496580008A55800166D -:1092F0009251000A3C188008322F00FFA54F002031 -:10930000964E000837110100A54E0022AD40002402 -:10931000924D000B31AC00FFA54C0002A14B0001A7 -:109320008E4900308F830024240BFFBFAC690008F6 -:10933000A06400308F9000242403FFDF96070032E2 -:1093400000E8282400B51025A6020032921F003242 -:1093500033F9003F37260040A20600328F8C0024EC -:10936000AD8000348E2F00C0AD8F0038918E003C50 -:109370003C0F7FFF31CD007FA18D003C8F84002406 -:1093800035EEFFFF908A003C014B4824A089003C49 -:109390008F85002490A8003C01033824A0A7003C3E -:1093A0008E4200348F9100243C038008AE2200409E -:1093B0008E59002C8E5F0030033F3023AE260044D0 -:1093C000923000483218007FA23800488F8800246D -:1093D0008E4D00308D0C004801AE5824019650246B -:1093E000014B4825AD0900489244000AA104004CF5 -:1093F000964700088F850024A4A7004E8E500030A9 -:109400008E4400300E0002E68C65006092F9007C0C -:109410000002F940004028210002110003E230213F -:109420003336000212C00003020680210005B0801E -:1094300002168021926D007C31B30004126000029C -:1094400000057080020E80218E4B003024058000C4 -:10945000316A0003000A4823312400030204182162 -:109460008F900024AE03003496E4007A96E8007AE8 -:1094700096F1007A31077FFF24E20001305F7FFF21 -:109480000225C824033F3025A6E6007A96F8007A24 -:109490003C1208008E520060330F7FFF11F200185B -:1094A000000000008F8400800E000E7702A02821AB -:1094B0008F8400800E000E87028028210E000EBCD3 -:1094C000000000000A000FC80000000096F1007ABA -:1094D00002248024A6F0007A92EF007A92EB007AC0 -:1094E00031EE00FF000E69C2000D6027000C51C074 -:1094F0003169007F012A20250A000FC2A2E4007A08 -:1095000096E6007A00C5C024A6F8007A92EF007AA9 -:1095100092F3007A31F200FF001271C2000E682748 -:10952000000DB1C0326C007F01962825A2E5007ABB -:109530000A0010798F8400803C0380003084FFFF94 -:1095400030A5FFFFAC640018AC65001C03E0000808 -:109550008C62001427BDFFA83C068008AFBE0050F7 -:10956000AFBF0054AFB7004CAFB60048AFB5004432 -:10957000AFB40040AFB3003CAFB20038AFB100347D -:10958000AFB0003034C80100910500C590C7000895 -:10959000309EFFFF30A500FF30E2007F0045182A13 -:1095A000A7A00014A7A0001E10600053AFA00010D9 -:1095B00090C900083126007F00A620232493FFFFD6 -:1095C0000013802B001E882B0211782451E00084A8 -:1095D0008FB300103C19800897360052973700501F -:1095E000001EC40002D7A8230015A4000014140311 -:1095F00003C2902A1640000200182C0300402821C4 -:10960000001314000002240300A4F82A57E000010C -:1096100000A0202128830009146000020080A021FE -:10962000241400083C0A80088D4500480014498035 -:109630008D48004C3C0380003124FFFF3C060010A5 -:109640000086382534710400AC650038AF91008481 -:10965000AC68003CAC670030000000000000000077 -:1096600000000000000000000000000000000000FA -:1096700000000000000000008C6C0000318B002016 -:109680001160FFFD0014682A01B010241040003959 -:109690000000A8213C16800892D700083C128000E8 -:1096A0008E44010032F6007F0E000E4202C02821D7 -:1096B0008E2F00108E4401000000902131F73FFFF3 -:1096C0000E000E5A02E02821922E000031C2003F07 -:1096D0002C50000852000010000088210002F88081 -:1096E0003C0308002463535403E3C8218F3800006F -:1096F000030000080000000090CE0008938B008853 -:1097000031CD007F00AD6023016C50210A0010BFF5 -:109710002553FFFF000088213C1080008E040100CB -:109720000E000E7702E028218E0401000E000E8745 -:1097300002C028211220000F0013802B8F8A008482 -:1097400026A900010009AC00027298230015AC03A1 -:109750002545004002B4B02A0013802B24170001D5 -:1097600000A0882102D01024AF8500841440FFC9D6 -:10977000AFB700103C07800894F100503C05800012 -:109780003C06002002B1C821A4F90050ACA600306C -:1097900094F4005094E3005203D560231074001D2C -:1097A000319EFFFF8CE5004C8CE90048001561807C -:1097B00000ACB0210000A02102CCA82B0134502124 -:1097C0000155B821ACF6004CACF70048001E882BC0 -:1097D0000211782415E0FF803C1980088FB3001037 -:1097E0008FBF00548FBE00503A6200018FB7004C0B -:1097F0008FB600488FB500448FB400408FB3003C53 -:109800008FB200388FB100348FB0003003E0000811 -:1098100027BD005894F200548CEF0044325FFFFEE5 -:10982000001FC0C001F87021ACAE003C8CEB0044BE -:109830008CAD003C016D40231900003B000000008E -:109840008CE20040244200013C07005034E4001048 -:109850003C038000ACA20038AC6400300000000083 -:1098600000000000000000000000000000000000F8 -:109870000000000000000000000000008C760000E6 -:1098800032D7002012E0FFFD3C11800896280054DA -:109890003C0A80003C06800831190001001960C0B4 -:1098A000018AA0218E8304003C0708008CE7004455 -:1098B0003C150020ACC300488E8904042405000137 -:1098C000ACC9004C10E50259AD550030963F00522E -:1098D0003C0508008CA5004000BFC021A6380052FE -:1098E000962F005425EE0001A62E00549626005413 -:1098F00030C4FFFF5487FF34001E882B30A5FFFFC4 -:109900000E00109DA62000543C0408008C84002406 -:10991000962700520044102300E29023A632005202 -:109920000A0010C1001E882B8CE200400A00116260 -:109930003C07005092280001240700013102007FFB -:109940001447001C97AC001E8E2A0014240BC00084 -:1099500031443FFF018B48243C0608008CC6006060 -:109960000124282530A43FFF0086882B12200011F7 -:10997000A7A5001E3C1108008E3100588F82008080 -:10998000000441802407FF80022218210068F8218A -:1099900003E7C82433EF007F3C1880003C12800EA0 -:1099A000AF19002C01F2682191AE000D35D00004F2 -:1099B000A1B0000D0E000ED12412000124110001EF -:1099C0003C1080008E0401000E000E7702E028217A -:1099D0008E0401000E000E8702C028211620FF58B9 -:1099E0008F8A00840A00112C0013802B8F8600843C -:1099F00090C900013125002010A0018A2410000127 -:109A00003C048008348C0080918B007C8F91002076 -:109A100000009021316A00011140000FAFB000201A -:109A20008CD000148C8E0060020E682B15A00003F1 -:109A3000020038218C8700603C0480083483008059 -:109A40008C72007000F2782B15E0000200E02021FB -:109A50008C640070008090213C07800834E5008011 -:109A60008CD900148CBF0070033FC02B170000027C -:109A7000032020218CA400700092182310600003A2 -:109A8000AFA3002824080002AFA800208FA5002063 -:109A90000265102B144000B5000018218CC400385A -:109AA0008E2F000C3C180080AE2400008CCE0034B9 -:109AB0003C10FF9F01F86025AE2E000490CB003FC4 -:109AC000360DFFFF018D48243C0A00203C06FFEFC5 -:109AD000A22B000B012A382534C5FFFF00E54024E6 -:109AE0003C0200088F87008401022025AE24000C70 -:109AF0008CE30014AE2000188FAF0028AE230014B2 -:109B00008CF800183C1FFFFB37F9FFFFAE38001C34 -:109B10008CEE000800996824024F8021AE2E0024AC -:109B20008CEC000CAE2D000CA6200038A620003ACC -:109B3000AE30002CAE2C0020AE2000288CEB0014A0 -:109B40008FAA002801724823012A302310C0001177 -:109B5000AE26001090F0003D8E2C00048E2A0000EE -:109B600000106900018D28210000102100AD302B6C -:109B70000142482101264021AE250004AE28000004 -:109B800090E3003DA223000A8F9F008497F900060E -:109B9000A63900088F8A0024240200023C068008AF -:109BA000A142000034C900809525005C02402021BC -:109BB0008F90002430A8FFFF0E000E9DAFA8002458 -:109BC0008FA300240002FB808F8500843C044200A8 -:109BD00003E3C8250324C025AE1800048F840024A5 -:109BE0008CAF0038AC8F00188CAE0034AC8E001CEB -:109BF000AC80000CAC800010A4800014A48000167F -:109C0000A4800020A4800022AC80002490A7003F04 -:109C1000A48700025240018C240700018FAB00286A -:109C20005160000290A2003D90A2003E244C000131 -:109C3000A08C00018F840024AC9200083C1880089E -:109C400037100080920F007C31EE000215C0000238 -:109C500024070034240700308F8500843C088008E6 -:109C60003509008090A300009128007C3259000340 -:109C7000A08300308F9F00848F9000242404000470 -:109C800093F8000100997823240DC000A218003138 -:109C90008F9900248F8E008431E50003972C0032C9 -:109CA00095CB001200F24821018D502431623FFF14 -:109CB00001423025A72600329323003201253821A6 -:109CC00031080004307F003F37E40040A324003215 -:109CD000124000028F85002400E838213C0C8008E7 -:109CE000ACA70034358B01008D6200C02E4400010A -:109CF0002403FFDFACA2003890AA003C0004C94056 -:109D00003146007FA0A6003C8F8900242405FFBFB8 -:109D10009127003C00E54024A128003C8F8F0024BF -:109D200091FF003C03E3C02403198025A1F0003C0F -:109D30008F8B00848F8A00248D6E0020AD4E0040F2 -:109D40008D6D0024AD4D00448D6C0028AD4C004855 -:109D50008D62002C0E000EBCAD42004C8FA6002080 -:109D60002407000210C700118FA300200003202B3E -:109D700000048023027098240060802100609021FC -:109D80000A0011150010882B962700128F8400807E -:109D90000000902130E5FFFFA7A700140E000E6B16 -:109DA000241100010A0011C03C1080003C19800001 -:109DB0003C0280088F240100905800080E000E42DB -:109DC0003305007F8F8E00248FAF00208FA40028E2 -:109DD000A1CF00000E000E9D8F9000248FAD0024B7 -:109DE00000023B803C0B420000ED40258F87008441 -:109DF000010B2025AE0400048CE500388F90002470 -:109E000000005021000A1900AE0500188CEC003447 -:109E10003C087FFF3504FFFFAE0C001C90E9003EBC -:109E20008E1F001C8E1800180009C9000009370297 -:109E300003F968210066102501B9782B030270210F -:109E400001CF5821AE0D001CAE0B0018AE00000C67 -:109E5000AE00001090E5003E8FAF0028240E0005F4 -:109E6000A605001494EC00042405C00001E4582465 -:109E7000A60C001690EA003E01E02021A60A002070 -:109E800094E60004A6060022AE00002490E3003F02 -:109E9000A603000290E9003E90FF003D03E9C823BD -:109EA00027380001A21800018F8D00243C10800883 -:109EB000ADAF0008A1AE00308F9800248F820084DF -:109EC000360F0100970C0032944A00122410FF80D4 -:109ED00000AC382431463FFF00E61825A7030032C6 -:109EE000930900322405FFBF2403FFDF313F003F09 -:109EF00037F90040A31900328F8C00242418FFFF8B -:109F0000AD8000348DEE00C0AD8E0038918D003CE8 -:109F100031A2007FA182003C8F87002490EA003CA0 -:109F200001453024A0E6003C8F9900249329003C91 -:109F30000123F824A33F003C8F8D00243C1F8008A0 -:109F4000ADB80040ADB2004491AF00483C12800073 -:109F500001F07025A1AE00488F8700248F86008411 -:109F60008CEC004801921024004B5025ACEA0048CC -:109F700090C5003EA0E5004C8F8800848F830024AC -:109F800095090004A469004E8FE500600E0002E60A -:109F9000000000008F99FF2C8FAE00280002814046 -:109FA000932F007C0002C1000218682131F20002E8 -:109FB00000402821164000AA01CD30213C0A80082B -:109FC000354300809069007C313F000413E00003BA -:109FD0008FAE00280005608000CC3021240D0004E5 -:109FE0008F90002431C7000301A758233168000374 -:109FF00000C82021AE0400343C068008A6250038A5 -:10A000003C0580008CA4010090D100080E000E8752 -:10A010003225007F0E000EBC000000000A0012AACC -:10A020008FA300208F8500208CC2003824180003E5 -:10A03000A4A00008ACA200008CDF0034A0A0000A9D -:10A040008F920084ACBF00043C040080924F003F1C -:10A05000A0B8000C8CAE000C3C0DFF9FA0AF000B15 -:10A0600001C4402535ABFFFF3C11FFEF8F98008402 -:10A07000010B30243639FFFF00D96024ACAC000C52 -:10A080008F030014971F00128F870080ACA300106D -:10A090008F090014ACA00018ACA00020ACA90014DB -:10A0A000ACA000248F0A001833E93FFF000911809B -:10A0B000ACAA00288F1200080047782133EE000177 -:10A0C000ACB200308F08000C8F990024000F69C2D9 -:10A0D000000E238001A45821241100023C068008B0 -:10A0E000A4AB001CA4A00034ACA8002CA331000039 -:10A0F00034D90080972C005C8F8F00243C034200F1 -:10A10000318AFFFF01433825ADE700048F820084C8 -:10A11000241800012411C0008C5F0038240700348B -:10A12000ADFF00188C520034ADF2001CADE0000C05 -:10A13000ADE00010A5E00014A5E00016A5E00020A9 -:10A14000A5E00022ADE00024A5F00002A1F8000186 -:10A150008F8B00248F8E0084AD70000891CD00009D -:10A16000A16D00308F8800848F8400249105000148 -:10A17000A08500318F920024964C0032019150242A -:10A1800001491825A6430032925F003233E2003FB6 -:10A19000A24200329338007C330F000215E0000227 -:10A1A0008F840024240700303C028008AC870034F0 -:10A1B000345201008E5F00C0240EFFBF02009021C8 -:10A1C000AC9F00389098003C330F007FA08F003C7C -:10A1D0008F880024910D003C01AE5824A10B003C57 -:10A1E0008F86002490D1003C36390020A0D9003C55 -:10A1F0008F8A00848F8500240010882B8D4C0020CE -:10A20000ACAC00408D430024ACA300448D49002831 -:10A21000ACA900488D47002CACA7004C0E000EBC2A -:10A220003C1080000A0011160000000094CD00527E -:10A230003C0B08008D6B0024016D8821A4D10052D5 -:10A240000A0010C1001E882BA08700018F84002403 -:10A25000240D0001AC8D00080A00125F3C18800834 -:10A26000000290800A00133E00D2302127BDFFE09B -:10A270003C0D8008AFB20018AFB00010AFBF001C9B -:10A28000AFB1001435B200808E4C001835A8010023 -:10A29000964B000695A70050910900EC000C560261 -:10A2A000016728233143007F312600FF2402000389 -:10A2B000A3830088AF84008010C2001B30B0FFFF72 -:10A2C000910600EC2412000530C200FF105200334A -:10A2D00000000000160000098FBF001C8FB200189C -:10A2E0008FB100148FB00010240D0C003C0C8000C6 -:10A2F00027BD002003E00008AD8D00240E0010A44F -:10A30000020020218FBF001C8FB200188FB10014F3 -:10A310008FB00010240D0C003C0C800027BD0020E5 -:10A3200003E00008AD8D0024965800789651007A1D -:10A33000924E007D0238782631E8FFFF31C400C01C -:10A34000148000092D1100011600003700000000E4 -:10A350005620FFE28FBF001C0E000F7A00000000A5 -:10A360000A0014068FBF001C1620FFDA0000000050 -:10A370000E000F7A000000001440FFD88FBF001CB1 -:10A380001600002200000000925F007D33E2003FD3 -:10A39000A242007D0A0014068FBF001C950900DA56 -:10A3A0008F86006000802821240400050E000674BA -:10A3B0003130FFFF978300723C0480002465FFFF6B -:10A3C000A78500728C8A01B80540FFFE00000000DE -:10A3D000AC8001808FBF001CAC9001848FB200184C -:10A3E0008FB100148FB000103C0760133C0B1000BD -:10A3F000240D0C003C0C800027BD0020AC87018898 -:10A40000AC8B01B803E00008AD8D00240E0010A451 -:10A41000020020215040FFB18FBF001C925F007DE1 -:10A420000A00143333E2003F0E0010A40200202182 -:10A430001440FFAA8FBF001C12200007000000007C -:10A440009259007D3330003F36020040A242007D29 -:10A450000A0014068FBF001C0E000F7A00000000D7 -:10A460005040FF9E8FBF001C9259007D3330003F4B -:08A470000A00146236020040EC -:08A47800000000000000001BC1 -:10A480000000000F0000000A0000000800000006A5 -:10A4900000000005000000050000000400000004AA -:10A4A00000000003000000030000000300000003A0 -:10A4B0000000000300000002000000020000000293 -:10A4C0000000000200000002000000020000000284 -:10A4D0000000000200000002000000020000000274 -:10A4E0000000000200000002000000020000000264 -:0CA4F0000000000100000001000000015D -:04A4FC0080080100D3 -:10A50000800800808008000000000C0000003080FF -:10A5100008000F4808000FF40800100C0800102075 -:10A520000800103408000F4808000F4808001068A1 -:10A53000080010A0080010B0080010D8080017C8C4 -:10A54000080017C8080018000800180008001814B0 -:10A55000080017E408001A3C08001A0808001A94BA -:10A5600008001A9408001B1C08001A4C80080240BE -:10A57000080021A808001FF4080021D00800226864 -:10A58000080023B808002404080025280800243007 -:10A59000080024B408002064080029D008002974A9 -:10A5A0000800201008002010080020100800259C3A -:10A5B0000800259C08002010080020100800284CE6 -:10A5C00008002010080020100800201008002010AB -:10A5D000080028AC080020100800201008002010F7 -:10A5E000080020100800201008002010080020108B -:10A5F000080020100800201008002010080020107B -:10A600000800201008002010080020100800242452 -:10A6100008002010080020100800291C0800201045 -:10A62000080020100800201008002010080020104A -:10A63000080020100800201008002010080020103A -:10A64000080020100800201008002010080020102A -:10A65000080020100800201008002010080020101A -:10A66000080027700800201008002010080026E4C9 -:10A6700008002640080037880800375C08003728A3 -:10A68000080036FC080036DC08003690800801001F -:10A69000800800808008000080080080080046F0E4 -:10A6A0000800472808004670080046F0080046F0F9 -:0CA6B00008004450080046F008004AC4AE -:04A6BC000A000C760E -:10A6C00000000000000000000000000D72787035EE -:10A6D0002E302E306A330000050000030000000019 -:10A6E0000000000100000000000000000000000069 -:10A6F000000000000000000000000000000000005A -:10A700000000000000000000000000000000000049 -:10A710000000000000000000000000000000000039 -:10A720000000000000000000000000000000000029 -:10A730000000000000000000000000000000000019 -:10A740000000000000000000000000000000000009 -:10A7500000000000000000000000000000000000F9 -:10A7600000000000000000000000000000000000E9 -:10A7700000000000000000000000000000000000D9 -:10A7800000000000000000000000000000000000C9 -:10A7900000000000000000000000000000000000B9 -:10A7A00000000000000000000000000000000000A9 -:10A7B0000000000000000000000000000000000099 -:10A7C0000000000000000000000000000000000089 -:10A7D0000000000000000000000000000000000079 -:10A7E0000000000000000000000000000000000069 -:10A7F0000000000000000000000000000000000059 -:10A800000000000000000000000000000000000048 -:10A810000000000000000000000000000000000038 -:10A820000000000000000000000000000000000028 -:10A830000000000000000000000000000000000018 -:10A840000000000000000000000000000000000008 -:10A8500000000000000000000000000000000000F8 -:10A8600000000000000000000000000000000000E8 -:10A8700000000000000000000000000000000000D8 -:10A8800000000000000000000000000000000000C8 -:10A8900000000000000000000000000000000000B8 -:10A8A00000000000000000000000000000000000A8 -:10A8B0000000000000000000000000000000000098 -:10A8C0000000000000000000000000000000000088 -:10A8D0000000000000000000000000000000000078 -:10A8E0000000000000000000000000000000000068 -:10A8F0000000000000000000000000000000000058 -:10A900000000000000000000000000000000000047 -:10A910000000000000000000000000000000000037 -:10A920000000000000000000000000000000000027 -:10A930000000000000000000000000000000000017 -:10A940000000000000000000000000000000000007 -:10A9500000000000000000000000000000000000F7 -:10A9600000000000000000000000000000000000E7 -:10A9700000000000000000000000000000000000D7 -:10A9800000000000000000000000000000000000C7 -:10A9900000000000000000000000000000000000B7 -:10A9A00000000000000000000000000000000000A7 -:10A9B0000000000000000000000000000000000097 -:10A9C0000000000000000000000000000000000087 -:10A9D0000000000000000000000000000000000077 -:10A9E0000000000000000000000000000000000067 -:10A9F0000000000000000000000000000000000057 -:10AA00000000000000000000000000000000000046 -:10AA10000000000000000000000000000000000036 -:10AA20000000000000000000000000000000000026 -:10AA30000000000000000000000000000000000016 -:10AA40000000000000000000000000000000000006 -:10AA500000000000000000000000000000000000F6 -:10AA600000000000000000000000000000000000E6 -:10AA700000000000000000000000000000000000D6 -:10AA800000000000000000000000000000000000C6 -:10AA900000000000000000000000000000000000B6 -:10AAA00000000000000000000000000000000000A6 -:10AAB0000000000000000000000000000000000096 -:10AAC0000000000000000000000000000000000086 -:10AAD0000000000000000000000000000000000076 -:10AAE0000000000000000000000000000000000066 -:10AAF0000000000000000000000000000000000056 -:10AB00000000000000000000000000000000000045 -:10AB10000000000000000000000000000000000035 -:10AB20000000000000000000000000000000000025 -:10AB30000000000000000000000000000000000015 -:10AB40000000000000000000000000000000000005 -:10AB500000000000000000000000000000000000F5 -:10AB600000000000000000000000000000000000E5 -:10AB700000000000000000000000000000000000D5 -:10AB800000000000000000000000000000000000C5 -:10AB900000000000000000000000000000000000B5 -:10ABA00000000000000000000000000000000000A5 -:10ABB0000000000000000000000000000000000095 -:10ABC0000000000000000000000000000000000085 -:10ABD0000000000000000000000000000000000075 -:10ABE0000000000000000000000000000000000065 -:10ABF0000000000000000000000000000000000055 -:10AC00000000000000000000000000000000000044 -:10AC10000000000000000000000000000000000034 -:10AC20000000000000000000000000000000000024 -:10AC30000000000000000000000000000000000014 -:10AC40000000000000000000000000000000000004 -:10AC500000000000000000000000000000000000F4 -:10AC600000000000000000000000000000000000E4 -:10AC700000000000000000000000000000000000D4 -:10AC800000000000000000000000000000000000C4 -:10AC900000000000000000000000000000000000B4 -:10ACA00000000000000000000000000000000000A4 -:10ACB0000000000000000000000000000000000094 -:10ACC0000000000000000000000000000000000084 -:10ACD0000000000000000000000000000000000074 -:10ACE0000000000000000000000000000000000064 -:10ACF0000000000000000000000000000000000054 -:10AD00000000000000000000000000000000000043 -:10AD10000000000000000000000000000000000033 -:10AD20000000000000000000000000000000000023 -:10AD30000000000000000000000000000000000013 -:10AD40000000000000000000000000000000000003 -:10AD500000000000000000000000000000000000F3 -:10AD600000000000000000000000000000000000E3 -:10AD700000000000000000000000000000000000D3 -:10AD800000000000000000000000000000000000C3 -:10AD900000000000000000000000000000000000B3 -:10ADA00000000000000000000000000000000000A3 -:10ADB0000000000000000000000000000000000093 -:10ADC0000000000000000000000000000000000083 -:10ADD0000000000000000000000000000000000073 -:10ADE0000000000000000000000000000000000063 -:10ADF0000000000000000000000000000000000053 -:10AE00000000000000000000000000000000000042 -:10AE10000000000000000000000000000000000032 -:10AE20000000000000000000000000000000000022 -:10AE30000000000000000000000000000000000012 -:10AE40000000000000000000000000000000000002 -:10AE500000000000000000000000000000000000F2 -:10AE600000000000000000000000000000000000E2 -:10AE700000000000000000000000000000000000D2 -:10AE800000000000000000000000000000000000C2 -:10AE900000000000000000000000000000000000B2 -:10AEA00000000000000000000000000000000000A2 -:10AEB0000000000000000000000000000000000092 -:10AEC0000000000000000000000000000000000082 -:10AED0000000000000000000000000000000000072 -:10AEE0000000000000000000000000000000000062 -:10AEF0000000000000000000000000000000000052 -:10AF00000000000000000000000000000000000041 -:10AF10000000000000000000000000000000000031 -:10AF20000000000000000000000000000000000021 -:10AF30000000000000000000000000000000000011 -:10AF40000000000000000000000000000000000001 -:10AF500000000000000000000000000000000000F1 -:10AF600000000000000000000000000000000000E1 -:10AF700000000000000000000000000000000000D1 -:10AF800000000000000000000000000000000000C1 -:10AF900000000000000000000000000000000000B1 -:10AFA00000000000000000000000000000000000A1 -:10AFB0000000000000000000000000000000000091 -:10AFC0000000000000000000000000000000000081 -:10AFD0000000000000000000000000000000000071 -:10AFE0000000000000000000000000000000000061 -:10AFF0000000000000000000000000000000000051 -:10B000000000000000000000000000000000000040 -:10B010000000000000000000000000000000000030 -:10B020000000000000000000000000000000000020 -:10B030000000000000000000000000000000000010 -:10B040000000000000000000000000000000000000 -:10B0500000000000000000000000000000000000F0 -:10B0600000000000000000000000000000000000E0 -:10B0700000000000000000000000000000000000D0 -:10B0800000000000000000000000000000000000C0 -:10B0900000000000000000000000000000000000B0 -:10B0A00000000000000000000000000000000000A0 -:10B0B0000000000000000000000000000000000090 -:10B0C0000000000000000000000000000000000080 -:10B0D0000000000000000000000000000000000070 -:10B0E0000000000000000000000000000000000060 -:10B0F0000000000000000000000000000000000050 -:10B10000000000000000000000000000000000003F -:10B11000000000000000000000000000000000002F -:10B12000000000000000000000000000000000001F -:10B13000000000000000000000000000000000000F -:10B1400000000000000000000000000000000000FF -:10B1500000000000000000000000000000000000EF -:10B1600000000000000000000000000000000000DF -:10B1700000000000000000000000000000000000CF -:10B1800000000000000000000000000000000000BF -:10B1900000000000000000000000000000000000AF -:10B1A000000000000000000000000000000000009F -:10B1B000000000000000000000000000000000008F -:10B1C000000000000000000000000000000000007F -:10B1D000000000000000000000000000000000006F -:10B1E000000000000000000000000000000000005F -:10B1F000000000000000000000000000000000004F -:10B20000000000000000000000000000000000003E -:10B21000000000000000000000000000000000002E -:10B22000000000000000000000000000000000001E -:10B23000000000000000000000000000000000000E -:10B2400000000000000000000000000000000000FE -:10B2500000000000000000000000000000000000EE -:10B2600000000000000000000000000000000000DE -:10B2700000000000000000000000000000000000CE -:10B2800000000000000000000000000000000000BE -:10B2900000000000000000000000000000000000AE -:10B2A000000000000000000000000000000000009E -:10B2B000000000000000000000000000000000008E -:10B2C000000000000000000000000000000000007E -:10B2D000000000000000000000000000000000006E -:10B2E000000000000000000000000000000000005E -:10B2F000000000000000000000000000000000004E -:10B30000000000000000000000000000000000003D -:10B31000000000000000000000000000000000002D -:10B32000000000000000000000000000000000001D -:10B33000000000000000000000000000000000000D -:10B3400000000000000000000000000000000000FD -:10B3500000000000000000000000000000000000ED -:10B3600000000000000000000000000000000000DD -:10B3700000000000000000000000000000000000CD -:10B3800000000000000000000000000000000000BD -:10B3900000000000000000000000000000000000AD -:10B3A000000000000000000000000000000000009D -:10B3B000000000000000000000000000000000008D -:10B3C000000000000000000000000000000000007D -:10B3D000000000000000000000000000000000006D -:10B3E000000000000000000000000000000000005D -:10B3F000000000000000000000000000000000004D -:10B40000000000000000000000000000000000003C -:10B41000000000000000000000000000000000002C -:10B42000000000000000000000000000000000001C -:10B43000000000000000000000000000000000000C -:10B4400000000000000000000000000000000000FC -:10B4500000000000000000000000000000000000EC -:10B4600000000000000000000000000000000000DC -:10B4700000000000000000000000000000000000CC -:10B4800000000000000000000000000000000000BC -:10B4900000000000000000000000000000000000AC -:10B4A000000000000000000000000000000000009C -:10B4B000000000000000000000000000000000008C -:10B4C000000000000000000000000000000000007C -:10B4D000000000000000000000000000000000006C -:10B4E000000000000000000000000000000000005C -:10B4F000000000000000000000000000000000004C -:10B50000000000000000000000000000000000003B -:10B51000000000000000000000000000000000002B -:10B52000000000000000000000000000000000001B -:10B53000000000000000000000000000000000000B -:10B5400000000000000000000000000000000000FB -:10B5500000000000000000000000000000000000EB -:10B5600000000000000000000000000000000000DB -:10B5700000000000000000000000000000000000CB -:10B5800000000000000000000000000000000000BB -:10B5900000000000000000000000000000000000AB -:10B5A000000000000000000000000000000000009B -:10B5B000000000000000000000000000000000008B -:10B5C000000000000000000000000000000000007B -:10B5D000000000000000000000000000000000006B -:10B5E000000000000000000000000000000000005B -:10B5F000000000000000000000000000000000004B -:10B60000000000000000000000000000000000003A -:10B61000000000000000000000000000000000002A -:10B62000000000000000000000000000000000001A -:10B63000000000000000000000000000000000000A -:10B6400000000000000000000000000000000000FA -:10B6500000000000000000000000000000000000EA -:10B6600000000000000000000000000000000000DA -:10B6700000000000000000000000000000000000CA -:10B6800000000000000000000000000000000000BA -:10B6900000000000000000000000000000000000AA -:10B6A000000000000000000000000000000000009A -:10B6B000000000000000000000000000000000008A -:10B6C000000000000000000000000000000000007A -:10B6D000000000000000000000000000000000006A -:10B6E000000000000000000000000000000000005A -:10B6F000000000000000000000000000000000004A -:10B700000000000000000000000000000000000039 -:10B710000000000000000000000000000000000029 -:10B720000000000000000000000000000000000019 -:10B730000000000000000000000000000000000009 -:10B7400000000000000000000000000000000000F9 -:10B7500000000000000000000000000000000000E9 -:10B7600000000000000000000000000000000000D9 -:10B7700000000000000000000000000000000000C9 -:10B7800000000000000000000000000000000000B9 -:10B7900000000000000000000000000000000000A9 -:10B7A0000000000000000000000000000000000099 -:10B7B0000000000000000000000000000000000089 -:10B7C0000000000000000000000000000000000079 -:10B7D0000000000000000000000000000000000069 -:10B7E0000000000000000000000000000000000059 -:10B7F0000000000000000000000000000000000049 -:10B800000000000000000000000000000000000038 -:10B810000000000000000000000000000000000028 -:10B820000000000000000000000000000000000018 -:10B830000000000000000000000000000000000008 -:10B8400000000000000000000000000000000000F8 -:10B8500000000000000000000000000000000000E8 -:10B8600000000000000000000000000000000000D8 -:10B8700000000000000000000000000000000000C8 -:10B8800000000000000000000000000000000000B8 -:10B8900000000000000000000000000000000000A8 -:10B8A0000000000000000000000000000000000098 -:10B8B0000000000000000000000000000000000088 -:10B8C0000000000000000000000000000000000078 -:10B8D0000000000000000000000000000000000068 -:10B8E0000000000000000000000000000000000058 -:10B8F0000000000000000000000000000000000048 -:10B900000000000000000000000000000000000037 -:10B910000000000000000000000000000000000027 -:10B920000000000000000000000000000000000017 -:10B930000000000000000000000000000000000007 -:10B9400000000000000000000000000000000000F7 -:10B9500000000000000000000000000000000000E7 -:10B9600000000000000000000000000000000000D7 -:10B9700000000000000000000000000000000000C7 -:10B9800000000000000000000000000000000000B7 -:10B9900000000000000000000000000000000000A7 -:10B9A0000000000000000000000000000000000097 -:10B9B0000000000000000000000000000000000087 -:10B9C0000000000000000000000000000000000077 -:10B9D0000000000000000000000000000000000067 -:10B9E0000000000000000000000000000000000057 -:10B9F0000000000000000000000000000000000047 -:10BA00000000000000000000000000000000000036 -:10BA10000000000000000000000000000000000026 -:10BA20000000000000000000000000000000000016 -:10BA30000000000000000000000000000000000006 -:10BA400000000000000000000000000000000000F6 -:10BA500000000000000000000000000000000000E6 -:10BA600000000000000000000000000000000000D6 -:10BA700000000000000000000000000000000000C6 -:10BA800000000000000000000000000000000000B6 -:10BA900000000000000000000000000000000000A6 -:10BAA0000000000000000000000000000000000096 -:10BAB0000000000000000000000000000000000086 -:10BAC0000000000000000000000000000000000076 -:10BAD0000000000000000000000000000000000066 -:10BAE0000000000000000000000000000000000056 -:10BAF0000000000000000000000000000000000046 -:10BB00000000000000000000000000000000000035 -:10BB10000000000000000000000000000000000025 -:10BB20000000000000000000000000000000000015 -:10BB30000000000000000000000000000000000005 -:10BB400000000000000000000000000000000000F5 -:10BB500000000000000000000000000000000000E5 -:10BB600000000000000000000000000000000000D5 -:10BB700000000000000000000000000000000000C5 -:10BB800000000000000000000000000000000000B5 -:10BB900000000000000000000000000000000000A5 -:10BBA0000000000000000000000000000000000095 -:10BBB0000000000000000000000000000000000085 -:10BBC0000000000000000000000000000000000075 -:10BBD0000000000000000000000000000000000065 -:10BBE0000000000000000000000000000000000055 -:10BBF0000000000000000000000000000000000045 -:10BC00000000000000000000000000000000000034 -:10BC10000000000000000000000000000000000024 -:10BC20000000000000000000000000000000000014 -:10BC30000000000000000000000000000000000004 -:10BC400000000000000000000000000000000000F4 -:10BC500000000000000000000000000000000000E4 -:10BC600000000000000000000000000000000000D4 -:10BC700000000000000000000000000000000000C4 -:10BC800000000000000000000000000000000000B4 -:10BC900000000000000000000000000000000000A4 -:10BCA0000000000000000000000000000000000094 -:10BCB0000000000000000000000000000000000084 -:10BCC0000000000000000000000000000000000074 -:10BCD0000000000000000000000000000000000064 -:10BCE0000000000000000000000000000000000054 -:10BCF0000000000000000000000000000000000044 -:10BD00000000000000000000000000000000000033 -:10BD10000000000000000000000000000000000023 -:10BD20000000000000000000000000000000000013 -:10BD30000000000000000000000000000000000003 -:10BD400000000000000000000000000000000000F3 -:10BD500000000000000000000000000000000000E3 -:10BD600000000000000000000000000000000000D3 -:10BD700000000000000000000000000000000000C3 -:10BD800000000000000000000000000000000000B3 -:10BD900000000000000000000000000000000000A3 -:10BDA0000000000000000000000000000000000093 -:10BDB0000000000000000000000000000000000083 -:10BDC0000000000000000000000000000000000073 -:10BDD0000000000000000000000000000000000063 -:10BDE0000000000000000000000000000000000053 -:10BDF0000000000000000000000000000000000043 -:10BE00000000000000000000000000000000000032 -:10BE10000000000000000000000000000000000022 -:10BE20000000000000000000000000000000000012 -:10BE30000000000000000000000000000000000002 -:10BE400000000000000000000000000000000000F2 -:10BE500000000000000000000000000000000000E2 -:10BE600000000000000000000000000000000000D2 -:10BE700000000000000000000000000000000000C2 -:10BE800000000000000000000000000000000000B2 -:10BE900000000000000000000000000000000000A2 -:10BEA0000000000000000000000000000000000092 -:10BEB0000000000000000000000000000000000082 -:10BEC0000000000000000000000000000000000072 -:10BED0000000000000000000000000000000000062 -:10BEE0000000000000000000000000000000000052 -:10BEF0000000000000000000000000000000000042 -:10BF00000000000000000000000000000000000031 -:10BF10000000000000000000000000000000000021 -:10BF20000000000000000000000000000000000011 -:10BF30000000000000000000000000000000000001 -:10BF400000000000000000000000000000000000F1 -:10BF500000000000000000000000000000000000E1 -:10BF600000000000000000000000000000000000D1 -:10BF700000000000000000000000000000000000C1 -:10BF800000000000000000000000000000000000B1 -:10BF900000000000000000000000000000000000A1 -:10BFA0000000000000000000000000000000000091 -:10BFB0000000000000000000000000000000000081 -:10BFC0000000000000000000000000000000000071 -:10BFD0000000000000000000000000000000000061 -:10BFE0000000000000000000000000000000000051 -:10BFF0000000000000000000000000000000000041 -:10C000000000000000000000000000000000000030 -:10C010000000000000000000000000000000000020 -:10C020000000000000000000000000000000000010 -:10C030000000000000000000000000000000000000 -:10C0400000000000000000000000000000000000F0 -:10C0500000000000000000000000000000000000E0 -:10C0600000000000000000000000000000000000D0 -:10C0700000000000000000000000000000000000C0 -:10C0800000000000000000000000000000000000B0 -:10C0900000000000000000000000000000000000A0 -:10C0A0000000000000000000000000000000000090 -:10C0B0000000000000000000000000000000000080 -:10C0C0000000000000000000000000000000000070 -:10C0D0000000000000000000000000000000000060 -:10C0E0000000000000000000000000000000000050 -:10C0F0000000000000000000000000000000000040 -:10C10000000000000000000000000000000000002F -:10C11000000000000000000000000000000000001F -:10C12000000000000000000000000000000000000F -:10C1300000000000000000000000000000000000FF -:10C1400000000000000000000000000000000000EF -:10C1500000000000000000000000000000000000DF -:10C1600000000000000000000000000000000000CF -:10C1700000000000000000000000000000000000BF -:10C1800000000000000000000000000000000000AF -:10C19000000000000000000000000000000000009F -:10C1A000000000000000000000000000000000008F -:10C1B000000000000000000000000000000000007F -:10C1C000000000000000000000000000000000006F -:10C1D000000000000000000000000000000000005F -:10C1E000000000000000000000000000000000004F -:10C1F000000000000000000000000000000000003F -:10C20000000000000000000000000000000000002E -:10C21000000000000000000000000000000000001E -:10C22000000000000000000000000000000000000E -:10C2300000000000000000000000000000000000FE -:10C2400000000000000000000000000000000000EE -:10C2500000000000000000000000000000000000DE -:10C2600000000000000000000000000000000000CE -:10C2700000000000000000000000000000000000BE -:10C2800000000000000000000000000000000000AE -:10C29000000000000000000000000000000000009E -:10C2A000000000000000000000000000000000008E -:10C2B000000000000000000000000000000000007E -:10C2C000000000000000000000000000000000006E -:10C2D000000000000000000000000000000000005E -:10C2E000000000000000000000000000000000004E -:10C2F000000000000000000000000000000000003E -:10C30000000000000000000000000000000000002D -:10C31000000000000000000000000000000000001D -:10C32000000000000000000000000000000000000D -:10C3300000000000000000000000000000000000FD -:10C3400000000000000000000000000000000000ED -:10C3500000000000000000000000000000000000DD -:10C3600000000000000000000000000000000000CD -:10C3700000000000000000000000000000000000BD -:10C3800000000000000000000000000000000000AD -:10C39000000000000000000000000000000000009D -:10C3A000000000000000000000000000000000008D -:10C3B000000000000000000000000000000000007D -:10C3C000000000000000000000000000000000006D -:10C3D000000000000000000000000000000000005D -:10C3E000000000000000000000000000000000004D -:10C3F000000000000000000000000000000000003D -:10C40000000000000000000000000000000000002C -:10C41000000000000000000000000000000000001C -:10C42000000000000000000000000000000000000C -:10C4300000000000000000000000000000000000FC -:10C4400000000000000000000000000000000000EC -:10C4500000000000000000000000000000000000DC -:10C4600000000000000000000000000000000000CC -:10C4700000000000000000000000000000000000BC -:10C4800000000000000000000000000000000000AC -:10C49000000000000000000000000000000000009C -:10C4A000000000000000000000000000000000008C -:10C4B000000000000000000000000000000000007C -:10C4C000000000000000000000000000000000006C -:10C4D000000000000000000000000000000000005C -:10C4E000000000000000000000000000000000004C -:10C4F000000000000000000000000000000000003C -:10C50000000000000000000000000000000000002B -:10C51000000000000000000000000000000000001B -:10C52000000000000000000000000000000000000B -:10C5300000000000000000000000000000000000FB -:10C5400000000000000000000000000000000000EB -:10C5500000000000000000000000000000000000DB -:10C5600000000000000000000000000000000000CB -:10C5700000000000000000000000000000000000BB -:10C5800000000000000000000000000000000000AB -:10C59000000000000000000000000000000000009B -:10C5A000000000000000000000000000000000008B -:10C5B000000000000000000000000000000000007B -:10C5C000000000000000000000000000000000006B -:10C5D000000000000000000000000000000000005B -:10C5E000000000000000000000000000000000004B -:10C5F000000000000000000000000000000000003B -:10C60000000000000000000000000000000000002A -:10C61000000000000000000000000000000000001A -:10C62000000000000000000000000000000000000A -:10C6300000000000000000000000000000000000FA -:10C6400000000000000000000000000000000000EA -:10C6500000000000000000000000000000000000DA -:10C6600000000000000000000000000000000000CA -:10C6700000000000000000000000000000000000BA -:10C6800000000000000000000000000000000000AA -:10C69000000000000000000000000000000000009A -:10C6A000000000000000000000000000000000008A -:10C6B000000000000000000000000000000000007A -:10C6C000000000000000000000000000000000006A -:10C6D000000000000000000000000000000000005A -:10C6E000000000000000000000000000000000004A -:10C6F000000000000000000000000000000000003A -:10C700000000000000000000000000000000000029 -:10C710000000000000000000000000000000000019 -:10C720000000000000000000000000000000000009 -:10C7300000000000000000000000000000000000F9 -:10C7400000000000000000000000000000000000E9 -:10C7500000000000000000000000000000000000D9 -:10C7600000000000000000000000000000000000C9 -:10C7700000000000000000000000000000000000B9 -:10C7800000000000000000000000000000000000A9 -:10C790000000000000000000000000000000000099 -:10C7A0000000000000000000000000000000000089 -:10C7B0000000000000000000000000000000000079 -:10C7C0000000000000000000000000000000000069 -:10C7D0000000000000000000000000000000000059 -:10C7E0000000000000000000000000000000000049 -:10C7F0000000000000000000000000000000000039 -:10C800000000000000000000000000000000000028 -:10C810000000000000000000000000000000000018 -:10C820000000000000000000000000000000000008 -:10C8300000000000000000000000000000000000F8 -:10C8400000000000000000000000000000000000E8 -:10C8500000000000000000000000000000000000D8 -:10C8600000000000000000000000000000000000C8 -:10C8700000000000000000000000000000000000B8 -:10C8800000000000000000000000000000000000A8 -:10C890000000000000000000000000000000000098 -:10C8A0000000000000000000000000000000000088 -:10C8B0000000000000000000000000000000000078 -:10C8C0000000000000000000000000000000000068 -:10C8D0000000000000000000000000000000000058 -:10C8E0000000000000000000000000000000000048 -:10C8F0000000000000000000000000000000000038 -:10C900000000000000000000000000000000000027 -:10C910000000000000000000000000000000000017 -:10C920000000000000000000000000000000000007 -:10C9300000000000000000000000000000000000F7 -:10C9400000000000000000000000000000000000E7 -:10C9500000000000000000000000000000000000D7 -:10C9600000000000000000000000000000000000C7 -:10C9700000000000000000000000000000000000B7 -:10C9800000000000000000000000000000000000A7 -:10C990000000000000000000000000000000000097 -:10C9A0000000000000000000000000000000000087 -:10C9B0000000000000000000000000000000000077 -:10C9C0000000000000000000000000000000000067 -:10C9D0000000000000000000000000000000000057 -:10C9E0000000000000000000000000000000000047 -:10C9F0000000000000000000000000000000000037 -:10CA00000000000000000000000000000000000026 -:10CA10000000000000000000000000000000000016 -:10CA20000000000000000000000000000000000006 -:10CA300000000000000000000000000000000000F6 -:10CA400000000000000000000000000000000000E6 -:10CA500000000000000000000000000000000000D6 -:10CA600000000000000000000000000000000000C6 -:10CA700000000000000000000000000000000000B6 -:10CA800000000000000000000000000000000000A6 -:10CA90000000000000000000000000000000000096 -:10CAA0000000000000000000000000000000000086 -:10CAB0000000000000000000000000000000000076 -:10CAC0000000000000000000000000000000000066 -:10CAD0000000000000000000000000000000000056 -:10CAE0000000000000000000000000000000000046 -:10CAF0000000000000000000000000000000000036 -:10CB00000000000000000000000000000000000025 -:10CB10000000000000000000000000000000000015 -:10CB20000000000000000000000000000000000005 -:10CB300000000000000000000000000000000000F5 -:10CB400000000000000000000000000000000000E5 -:10CB500000000000000000000000000000000000D5 -:10CB600000000000000000000000000000000000C5 -:10CB700000000000000000000000000000000000B5 -:10CB800000000000000000000000000000000000A5 -:10CB90000000000000000000000000000000000095 -:10CBA0000000000000000000000000000000000085 -:10CBB0000000000000000000000000000000000075 -:10CBC0000000000000000000000000000000000065 -:10CBD0000000000000000000000000000000000055 -:10CBE0000000000000000000000000000000000045 -:10CBF0000000000000000000000000000000000035 -:10CC00000000000000000000000000000000000024 -:10CC10000000000000000000000000000000000014 -:10CC20000000000000000000000000000000000004 -:10CC300000000000000000000000000000000000F4 -:10CC400000000000000000000000000000000000E4 -:10CC500000000000000000000000000000000000D4 -:10CC600000000000000000000000000000000000C4 -:10CC700000000000000000000000000000000000B4 -:10CC800000000000000000000000000000000000A4 -:10CC90000000000000000000000000000000000094 -:10CCA0000000000000000000000000000000000084 -:10CCB0000000000000000000000000000000000074 -:10CCC0000000000000000000000000000000000064 -:10CCD0000000000000000000000000000000000054 -:10CCE0000000000000000000000000000000000044 -:10CCF0000000000000000000000000000000000034 -:10CD00000000000000000000000000000000000023 -:10CD10000000000000000000000000000000000013 -:10CD20000000000000000000000000000000000003 -:10CD300000000000000000000000000000000000F3 -:10CD400000000000000000000000000000000000E3 -:10CD500000000000000000000000000000000000D3 -:10CD600000000000000000000000000000000000C3 -:10CD700000000000000000000000000000000000B3 -:10CD800000000000000000000000000000000000A3 -:10CD90000000000000000000000000000000000093 -:10CDA0000000000000000000000000000000000083 -:10CDB0000000000000000000000000000000000073 -:10CDC0000000000000000000000000000000000063 -:10CDD0000000000000000000000000000000000053 -:10CDE0000000000000000000000000000000000043 -:10CDF0000000000000000000000000000000000033 -:10CE00000000000000000000000000000000000022 -:10CE10000000000000000000000000000000000012 -:10CE20000000000000000000000000000000000002 -:10CE300000000000000000000000000000000000F2 -:10CE400000000000000000000000000000000000E2 -:10CE500000000000000000000000000000000000D2 -:10CE600000000000000000000000000000000000C2 -:10CE700000000000000000000000000000000000B2 -:10CE800000000000000000000000000000000000A2 -:10CE90000000000000000000000000000000000092 -:10CEA0000000000000000000000000000000000082 -:10CEB0000000000000000000000000000000000072 -:10CEC0000000000000000000000000000000000062 -:10CED0000000000000000000000000000000000052 -:10CEE0000000000000000000000000000000000042 -:10CEF0000000000000000000000000000000000032 -:10CF00000000000000000000000000000000000021 -:10CF10000000000000000000000000000000000011 -:10CF20000000000000000000000000000000000001 -:10CF300000000000000000000000000000000000F1 -:10CF400000000000000000000000000000000000E1 -:10CF500000000000000000000000000000000000D1 -:10CF600000000000000000000000000000000000C1 -:10CF700000000000000000000000000000000000B1 -:10CF800000000000000000000000000000000000A1 -:10CF90000000000000000000000000000000000091 -:10CFA0000000000000000000000000000000000081 -:10CFB0000000000000000000000000000000000071 -:10CFC0000000000000000000000000000000000061 -:10CFD0000000000000000000000000000000000051 -:10CFE0000000000000000000000000000000000041 -:10CFF0000000000000000000000000000000000031 -:10D000000000000000000000000000000000000020 -:10D010000000000000000000000000000000000010 -:10D020000000000000000000000000000000000000 -:10D0300000000000000000000000000000000000F0 -:10D0400000000000000000000000000000000000E0 -:10D0500000000000000000000000000000000000D0 -:10D0600000000000000000000000000000000000C0 -:10D0700000000000000000000000000000000000B0 -:10D0800000000000000000000000000000000000A0 -:10D090000000000000000000000000000000000090 -:10D0A0000000000000000000000000000000000080 -:10D0B0000000000000000000000000000000000070 -:10D0C0000000000000000000000000000000000060 -:10D0D0000000000000000000000000000000000050 -:10D0E0000000000000000000000000000000000040 -:10D0F0000000000000000000000000000000000030 -:10D10000000000000000000000000000000000001F -:10D11000000000000000000000000000000000000F -:10D1200000000000000000000000000000000000FF -:10D1300000000000000000000000000000000000EF -:10D1400000000000000000000000000000000000DF -:10D1500000000000000000000000000000000000CF -:10D1600000000000000000000000000000000000BF -:10D1700000000000000000000000000000000000AF -:10D18000000000000000000000000000000000009F -:10D19000000000000000000000000000000000008F -:10D1A000000000000000000000000000000000007F -:10D1B000000000000000000000000000000000006F -:10D1C000000000000000000000000000000000005F -:10D1D000000000000000000000000000000000004F -:10D1E000000000000000000000000000000000003F -:10D1F000000000000000000000000000000000002F -:10D20000000000000000000000000000000000001E -:10D21000000000000000000000000000000000000E -:10D2200000000000000000000000000000000000FE -:10D2300000000000000000000000000000000000EE -:10D2400000000000000000000000000000000000DE -:10D2500000000000000000000000000000000000CE -:10D2600000000000000000000000000000000000BE -:10D2700000000000000000000000000000000000AE -:10D28000000000000000000000000000000000009E -:10D29000000000000000000000000000000000008E -:10D2A000000000000000000000000000000000007E -:10D2B000000000000000000000000000000000006E -:10D2C000000000000000000000000000000000005E -:10D2D000000000000000000000000000000000004E -:10D2E000000000000000000000000000000000003E -:10D2F000000000000000000000000000000000002E -:10D30000000000000000000000000000000000001D -:10D31000000000000000000000000000000000000D -:10D3200000000000000000000000000000000000FD -:10D3300000000000000000000000000000000000ED -:10D3400000000000000000000000000000000000DD -:10D3500000000000000000000000000000000000CD -:10D3600000000000000000000000000000000000BD -:10D3700000000000000000000000000000000000AD -:10D38000000000000000000000000000000000009D -:10D39000000000000000000000000000000000008D -:10D3A000000000000000000000000000000000007D -:10D3B000000000000000000000000000000000006D -:10D3C000000000000000000000000000000000005D -:10D3D000000000000000000000000000000000004D -:10D3E000000000000000000000000000000000003D -:10D3F000000000000000000000000000000000002D -:10D40000000000000000000000000000000000001C -:10D41000000000000000000000000000000000000C -:10D4200000000000000000000000000000000000FC -:10D4300000000000000000000000000000000000EC -:10D4400000000000000000000000000000000000DC -:10D4500000000000000000000000000000000000CC -:10D4600000000000000000000000000000000000BC -:10D4700000000000000000000000000000000000AC -:10D48000000000000000000000000000000000009C -:10D49000000000000000000000000000000000008C -:10D4A000000000000000000000000000000000007C -:10D4B000000000000000000000000000000000006C -:10D4C000000000000000000000000000000000005C -:10D4D000000000000000000000000000000000004C -:10D4E000000000000000000000000000000000003C -:10D4F000000000000000000000000000000000002C -:10D50000000000000000000000000000000000001B -:10D51000000000000000000000000000000000000B -:10D5200000000000000000000000000000000000FB -:10D5300000000000000000000000000000000000EB -:10D5400000000000000000000000000000000000DB -:10D5500000000000000000000000000000000000CB -:10D5600000000000000000000000000000000000BB -:10D5700000000000000000000000000000000000AB -:10D58000000000000000000000000000000000009B -:10D59000000000000000000000000000000000008B -:10D5A000000000000000000000000000000000007B -:10D5B000000000000000000000000000000000006B -:10D5C000000000000000000000000000000000005B -:10D5D000000000000000000000000000000000004B -:10D5E000000000000000000000000000000000003B -:10D5F000000000000000000000000000000000002B -:10D60000000000000000000000000000000000001A -:10D61000000000000000000000000000000000000A -:10D6200000000000000000000000000000000000FA -:10D6300000000000000000000000000000000000EA -:10D6400000000000000000000000000000000000DA -:10D6500000000000000000000000000000000000CA -:10D6600000000000000000000000000000000000BA -:10D6700000000000000000000000000000000000AA -:10D68000000000000000000000000000000000009A -:10D69000000000000000000000000000000000008A -:10D6A000000000000000000000000000000000007A -:10D6B000000000000000000000000000000000006A -:10D6C000000000000000000000000000000000005A -:10D6D000000000000000000000000000000000004A -:10D6E000000000000000000000000000000000003A -:10D6F000000000000000000000000000000000002A -:10D700000000000000000000000000000000000019 -:10D710000000000000000000000000000000000009 -:10D7200000000000000000000000000000000000F9 -:10D7300000000000000000000000000000000000E9 -:10D7400000000000000000000000000000000000D9 -:10D7500000000000000000000000000000000000C9 -:10D7600000000000000000000000000000000000B9 -:10D7700000000000000000000000000000000000A9 -:10D780000000000000000000000000000000000099 -:10D790000000000000000000000000000000000089 -:10D7A0000000000000000000000000000000000079 -:10D7B0000000000000000000000000000000000069 -:10D7C0000000000000000000000000000000000059 -:10D7D0000000000000000000000000000000000049 -:10D7E0000000000000000000000000000000000039 -:10D7F0000000000000000000000000000000000029 -:10D800000000000000000000000000000000000018 -:10D810000000000000000000000000000000000008 -:10D8200000000000000000000000000000000000F8 -:10D8300000000000000000000000000000000000E8 -:10D8400000000000000000000000000000000000D8 -:10D8500000000000000000000000000000000000C8 -:10D8600000000000000000000000000000000000B8 -:10D8700000000000000000000000000000000000A8 -:10D880000000000000000000000000000000000098 -:10D890000000000000000000100000030000000075 -:10D8A0000000000D0000000D3C020801244282200F -:10D8B0003C030801246382E0AC4000000043202BBD -:10D8C0001480FFFD244200043C1D080037BD9FFC6E -:10D8D00003A0F0213C100800261031D83C1C0801A0 -:10D8E000279C82200E0011EA000000000000000DBD -:10D8F0003C02800030A5FFFF30C600FF34430180AA -:10D900003C0880008D0901B80520FFFE00000000E2 -:10D91000AC64000024040002A4650008A066000AAC -:10D92000A064000BAC6700183C03100003E0000883 -:10D93000AD0301B83C0560008CA24FF80440FFFE27 -:10D9400000000000ACA44FC03C0310003C040200E7 -:10D95000ACA44FC403E00008ACA34FF89486000CBD -:10D9600000A050212488001400062B02000510801E -:10D97000004448210109182B10600011000000002C -:10D98000910300002C6400095080000991190001E6 -:10D99000000360803C0D080125AD80E4018D582115 -:10D9A0008D67000000E000080000000091190001F0 -:10D9B000011940210109302B54C0FFF291030000EE -:10D9C00003E00008000010210A000CBE2508000139 -:10D9D000910F0001240E000A15EE00400128C82313 -:10D9E0002F38000A1700003D250D00028D58000059 -:10D9F000250F0006370E0100AD4E0000910C00020D -:10DA000091AB000191A4000291A60003000C2E002E -:10DA1000000B3C0000A7102500041A000043C82595 -:10DA20000326C025AD580004910E000691ED0001BB -:10DA300091E7000291E50003000E5E00000D640016 -:10DA4000016C30250007220000C410250045182570 -:10DA50002508000A0A000CBEAD430008910F000122 -:10DA6000250400022408000255E8000101202021BD -:10DA70000A000CBE00804021910C0001240B000321 -:10DA8000158B0016000000008D580000910E00025A -:10DA900025080003370D0008A14E00100A000CBE37 -:10DAA000AD4D000091190001240F0004172F000B49 -:10DAB0000000000091070002910400038D43000064 -:10DAC00000072A0000A4102534660004250800047D -:10DAD000AD42000C0A000CBEAD46000003E0000899 -:10DAE0002402000127BDFFE8AFBF0014AFB0001053 -:10DAF0000E0014E0008080213C0480083485008002 -:10DB000090A600052403FFFE0200202100C310247C -:10DB10008FBF00148FB00010A0A200050A0014EA05 -:10DB200027BD001827BDFFE8AFB00010AFBF00143D -:10DB30000E000F4E008080213C06800834C5008016 -:10DB400090A4000024020050308300FF1062000700 -:10DB50003C098000020020218FBF00148FB000100C -:10DB6000AD2001800A00101027BD00182408010014 -:10DB70003C078000020020218FBF00148FB00010EE -:10DB8000ACE801800A00101027BD001827BDFF7007 -:10DB90003C088008AFB60080AFB5007CAFB1006C28 -:10DBA000AFBF008CAFBE0088AFB70084AFB40078C1 -:10DBB000AFB30074AFB20070AFB00068350500803D -:10DBC0003C0780008CF2012890A40009ACE000849E -:10DBD00090A60005309100FF0000A821000618273C -:10DBE000306200010000B02114400067AFA0005077 -:10DBF00090A9000024050020312400FF10850016A4 -:10DC0000240A0050108A008C000000003C0C080020 -:10DC10008D8C00DC258B00013C010800AC2B00DC66 -:10DC20000E0015D6000000008FBF008C8FBE00884C -:10DC30008FB700848FB600808FB5007C8FB40078DA -:10DC40008FB300748FB200708FB1006C8FB000681A -:10DC500003E0000827BD00900000000D3C1080008C -:10DC6000AFA00030961F01168E1901043C1E002043 -:10DC700036130C00033EC0240018B82B00173140A7 -:10DC8000AFA600308E0E010433F4FFFF3C0F0040BE -:10DC90000293802101CF68249213000D11A0004847 -:10DCA00034C40040326200201440000234860080F8 -:10DCB0000080302114C00093AFA600303C058008DE -:10DCC00034A800809107000830E6004050C00006EC -:10DCD0003C06800824090004122900A2240A00122C -:10DCE000122A00293C06800834D401003C17800029 -:10DCF00096EF011A960D000E928E0008326B00040A -:10DD000031F7FFFF01CD6004AFAC00548E14000466 -:10DD1000116000318E1E000834C300809079000825 -:10DD20003338004017000028000000008C730050BA -:10DD300002939023064000063C0C80008C7E003449 -:10DD4000029E8023060200838EA200083C0C800005 -:10DD5000AD800044240200018FBF008C8FBE00887C -:10DD60008FB700848FB600808FB5007C8FB40078A9 -:10DD70008FB300748FB200708FB1006C8FB00068E9 -:10DD800003E0000827BD00900E000D1A00002021BE -:10DD90008FBF008C8FBE00888FB700848FB6008045 -:10DDA0008FB5007C8FB400788FB300748FB2007091 -:10DDB0008FB1006C8FB0006803E0000827BD0090B1 -:10DDC0000A000D7A00C020210E00163702802021A3 -:10DDD0001440FFDF3C0C80003C038008346300806B -:10DDE0008C6200340282F82307E000170000000074 -:10DDF0003C1508008EB5310026B100013C01080039 -:10DE0000AC3131000E0014E0024020213C0B8008B0 -:10DE100035700080920A002502402021354200041E -:10DE20000E0014EAA20200250E000C9E02402021E2 -:10DE30000A000DA7240200013C15080126B582D076 -:10DE40000A000D693C1080008C6600300286202399 -:10DE5000188000082409000C3C0808008D083100D7 -:10DE6000327300FC0000B821250700013C010800C6 -:10DE7000AC273100AFA900308C65003000B43823E6 -:10DE800018E000DB02E7502A1540FFDE000000002A -:10DE900012E7002A02E768230287A02131B7FFFFBB -:10DEA000326E000211C00034327F00103C14800832 -:10DEB00036900080920F000831F6004052C000CE2C -:10DEC0008EA20008024020210E0014E02413001846 -:10DED000A2130009921800052419FFFE0240202118 -:10DEE0000319B8240E0014EAA2170005240400390F -:10DEF000000028210E001612240600180A000DA7A3 -:10DF00002402000192B6000C3C0480083483008097 -:10DF10008C6700380016AB0036B10081024020212A -:10DF20003225F0810E000C8D30C600FF3C0C8000C5 -:10DF3000AD8000440A000DA7240200013A6C0001E4 -:10DF4000318B00011560FFAF0287A0210A000DF898 -:10DF5000000000000040F809240400160A000DA784 -:10DF600024020001024020210E0017170200282180 -:10DF70000A000D5C8FBF008C13E0FF743C03800827 -:10DF8000346800808D0400388C66000403C61023BA -:10DF90001C40FF6F3C0C800003C4282304A2000136 -:10DFA0000080F021AFB40010AFB70014AFA7001885 -:10DFB0003C1F800097E301208D0900309506005C2E -:10DFC0008FB900548FAC00303062FFFF30D8FFFFB4 -:10DFD0000047702137EF40000338682B01CF5821EC -:10DFE000018D5025AFAB0020AFA90028AFAA0030AB -:10DFF000AFA90024AFA0002CAFBE003491070008E9 -:10E0000030E400081480008F020020218EA200045A -:10E010000040F80927A400108FA900303128000221 -:10E0200055000001327300FE3C048008348C0080EF -:10E03000918B0008316A0040514000128FA40024E7 -:10E040008C8D000411BE00BE240E00143265000148 -:10E0500010A0000C8FA400242404000C122400D46F -:10E060002A27000D10E000CE2409000E2408000A23 -:10E0700052280001241600088FA200242444000125 -:10E08000AFA400248FA600143C03800834650080F0 -:10E090000086F8218CB10030ACBF003090B9004E42 -:10E0A0008CAE00303418FFFF0338780401CF6821AC -:10E0B000ACAD00348FA600308FAC005430CA0008DD -:10E0C00003CC58211140000CAFAB00588CA40020A9 -:10E0D0008FB000581090009430C600FF92A2000C40 -:10E0E0008FA700340240202100024B003528008019 -:10E0F0000E000C8D3105F0803C0C800835900080BE -:10E100008E0B003001715023194000702659008099 -:10E110003C1808008F183198241FFF80033F782493 -:10E12000332D007F3C0680003C0E8004331100102C -:10E13000ACCF00901220003401AE282190A3006BD8 -:10E14000546000323C10800824070001A0A7006B37 -:10E1500094C4007A2486000AA60600123C0D8008AA -:10E1600035A5008090B10008322C004015800004D5 -:10E170003C038008326E000115C000620000000000 -:10E18000346400808C8F00208FB3005811F3000A94 -:10E19000346301008C7900000299C0231B000077D2 -:10E1A0008FA80058AC880020AC7400002414000133 -:10E1B000AC7E0004AFB4005016C000370000000071 -:10E1C0008FA40050148000300000000012E0000511 -:10E1D000000018218FA900303137000452E0FE9270 -:10E1E00000601021240300010A000D5B0060102173 -:10E1F0000A000DF9000038210040F8092404001736 -:10E200000A000DA7240200013C108008361000808F -:10E2100024090001024020210E0014E0A60900128A -:10E220009208002524050001AFA500503502000129 -:10E23000024020210E0014EAA20200250A000EA9C5 -:10E240003C0D800827A50038AFA800600E000CA880 -:10E25000AFA000381440FF6D8FA800608FA5003874 -:10E2600030B001005200FF6A8EA200048FA3003C70 -:10E270008D070058006720230483FF64AD03005816 -:10E280000A000E558EA200040E000C9E02402021B2 -:10E290000A000EC4000000000E0014E0024020211D -:10E2A0003C05800834A30080024020210E0014EABF -:10E2B000A076000902C03021240400370E00161297 -:10E2C000000028210A000EC28FA400508FA200185F -:10E2D0005840FFA33C0D80080E0014E002402021AE -:10E2E000920A0025240B0001AFAB00503542000418 -:10E2F000024020210E0014EAA20200250A000EA905 -:10E300003C0D80088CB600308EBE00082404001836 -:10E3100026D5000103C0F809ACB500308FB200303B -:10E320000A000D5B324200043C07800094E5011AAC -:10E3300050A0FF6A34C600100A000E8992A2000C99 -:10E34000122E002A2A2F001511E0001E2419001693 -:10E350002418000C5638FF3E326500013C1F80082F -:10E3600093E3001B2410FFBD2416000E0070302420 -:10E37000A3E6001B0A000E65326500018C7F0000D9 -:10E3800017F4FF8D000000008C67000403C73023E2 -:10E3900004C1FF848FA800580A000EBF00000000CF -:10E3A0001629FF368FA200240A000E7024160010D2 -:10E3B0002411000E52D1FF30241600100A000E6FF7 -:10E3C000241600165639FF22326500013C1F8008D2 -:10E3D00093E3001B2410FFBD2416001000703024AE -:10E3E000A3E6001B0A000E65326500010A000E64F8 -:10E3F000241600123C0380008C6201B80440FFFE2A -:10E4000024040800AC6401B803E000080000000028 -:10E4100030A5FFFF30C6FFFF3C0780008CE201B84B -:10E420000440FFFE34E80180AD040000ACE40020AD -:10E430003C048008948300483063FFFF1060001D97 -:10E440003C0B800024AA0012006A482B5120001ABD -:10E45000240A000394F901208F890000240C001A7B -:10E460003338FFFF2707FFFE0067782B39EE0001E6 -:10E4700000096B8201AE5824A10C000B116000470B -:10E480008F830004A50700148F880004350700015E -:10E49000AF87000430CC00405580000F3C0880005E -:10E4A0003C0C800035840180A485000E0A000F9882 -:10E4B0008F8F000C240A00033564018030CC0040AB -:10E4C0008F8900008F870004A08A000B5180FFF520 -:10E4D0003C0C80003C088000950301203C0880082B -:10E4E000951800403079FFFF272EFFFE330FFFFF06 -:10E4F00001CF682B11A0000301C02021950200402C -:10E500003044FFFF3C0B800000A4502335650180A0 -:10E51000A4A4000EA4AA00248F8F000C3C05800048 -:10E5200034AE01802418000230ED8000A5D8000C24 -:10E53000A5C90010ADCF0028A5C6000811A0000E87 -:10E540003C04800094AA01163142FFFC24480004D8 -:10E55000010518218C7940003326FFFF14C0000705 -:10E56000240EBFFF3C0BFFFF35657FFF00E538241D -:10E57000AF8700043C048000240EBFFF348C018070 -:10E5800000EE6824A58D0026AD89002C3C07100004 -:10E59000AC8701B803E00008000000002402FFFE81 -:10E5A000006238240A000F76AF8700043C05800023 -:10E5B00034A400708C8A000090A601128F840000A1 -:10E5C00027BDFFF030C300FF000318823082010036 -:10E5D00000003821104000392466000330874000D5 -:10E5E00050E0003930882000000610800045C82126 -:10E5F0008F2F40002478000400187080AFAF000017 -:10E6000001C568218DAC4000AFAC000494AB01168D -:10E610003169FFFC012540218D054000AFA50008B0 -:10E620008FA9000800003021000028213C070800C5 -:10E6300024E701000A000FE92408000890420000C6 -:10E6400024A500012CAD000C0062C8210019C08077 -:10E65000030778218DEE000011A0000600CE3026C1 -:10E6600003A5102114A8FFF500051A005520FFF49A -:10E67000904200003C048000348700703C05080094 -:10E680008CA531048CE300002CA8002011000009A7 -:10E69000006A3823000558803C0C0800258C31089E -:10E6A000016C482124AA0001AD2700003C010800AC -:10E6B000AC2A3104AF86000C2407000100E01021D1 -:10E6C00003E0000827BD00101100FFFC0000382106 -:10E6D00000066080018558218D6440002469000493 -:10E6E00000093880AFA4000000E518218C664000C6 -:10E6F000AFA000080A000FD9AFA6000427BDFFD8BD -:10E70000AFB20018AFB00010AFBF0024AFB400200C -:10E71000AFB3001CAFB100148F8700003C04800031 -:10E720009483010E30E24000000080211040001070 -:10E730003072FFFF3C06002000E6282410A0000DE8 -:10E7400030EA80008F8800042409BFFF00E93824E4 -:10E7500035031000AF87000030F120001620000BB9 -:10E760003C1400042418FFBF0A001038007810245D -:10E7700030EA8000154000863C0C002030F120007B -:10E780001220FFF88F8300043C14000400F4982446 -:10E790001260FFF52418FFBF3462004030F9010019 -:10E7A0001320000FAF8200043C02002000E2F82496 -:10E7B00013E000053C0B80003C04000400E4182436 -:10E7C000106000CF00000000956A011E9569011CD1 -:10E7D0003146FFFF0009440000C82825AF85000C22 -:10E7E0003C0E800095CD010C8DC44000340CFFFF21 -:10E7F000108C00B031A5FFFF308F010055E0000103 -:10E800002410001030F110005220000836110001D1 -:10E8100030F300201660009F3C18100000F8A02480 -:10E82000168000963C040C003611000130E801000F -:10E830001500000B3C0A00018F88000431094000DC -:10E840001520000800EA30243C0C1F0100EC58247D -:10E850003C0A1000516A00AE30AD02003C0A0001D3 -:10E8600000EA302414C000953C05100000E5202487 -:10E8700000004021108000070000902100079E0248 -:10E880003272000F001278803C0E080125CE828083 -:10E8900001EE40218F940018128000470220802151 -:10E8A00010800091000000003C0980009539010EA5 -:10E8B00091030000022030213338FFFF27050004B8 -:10E8C000106000080000A021241F0003107F013AFF -:10E8D00024040002910C00011184011830EA004068 -:10E8E0000012A1C08F92001C524000013626004049 -:10E8F0003C1380008E6F400031F10100122000CBEC -:10E9000030D1FFFB3C1808008F18002430D20004DF -:10E910003306000414C000CC30B0FFFF56400001A5 -:10E920003631000402802021020028210E000F55FC -:10E93000022030211640000D0000202136650180A4 -:10E940003C0480008C9301B80660FFFE241920006F -:10E9500024140002A4B90008A0B4000BA4A0001065 -:10E960003C051000AC8501B8000020218FBF0024B9 -:10E970008FB400208FB3001C8FB200188FB1001429 -:10E980008FB000100080102103E0000827BD002890 -:10E9900000EC58241160FF7A30F120008F8D0004C4 -:10E9A0003C0FFFFF35EE7FFF00EE382435A38000DB -:10E9B0000A001027AF8700003C0208008C42003894 -:10E9C0003C040800248400381040004B2449FFFF19 -:10E9D0003C038000946C010E318BFFFF110000A0FE -:10E9E000257300043C1008008E1000301200000A4D -:10E9F00030E601008F8A00043143400010600006B9 -:10EA00003C0F0F0000EF70243C0D010001AE402BC5 -:10EA1000110000DF3265FFFF10C000693C140F00D9 -:10EA200000F428243C18020010B800658F99000CEF -:10EA30003270FFFF03299824026490219249000458 -:10EA400025270004000721C00200282136260002E5 -:10EA50000E000F55000000008FBF00248FB400206F -:10EA60008FB3001C8FB200188FB100148FB000104C -:10EA70000000102103E0000827BD00283C020BFF26 -:10EA800000E41824345FFFFF03E3C82B5320FF6723 -:10EA9000361100013C0608008CC6002C361100051A -:10EAA00024D000013C010800AC30002C0A00105DAD -:10EAB00030E801000A0010522410002002402821F2 -:10EAC0003C1208008E5200D824040080264D00011C -:10EAD0003C010800AC2D00D80E000F5524060003A1 -:10EAE0000A0010E88FBF00243C0808012508828036 -:10EAF0000A00107C3C0980000A0010C50000482173 -:10EB00000E000FBC000000000A0010498F870000B3 -:10EB100015A0FF533C0A00012645000430AAFFFF60 -:10EB2000362600023C0380008C7201B80640FFFECE -:10EB30008F85000834690180AD20000010A000AF6F -:10EB40003C048000254F001200AF702B51C000AC78 -:10EB500024030003947801202414001A30F14000AB -:10EB60003313FFFFA134000B122000B62663FFFE13 -:10EB700000A3C82B572000B4241FFFFE3508000156 -:10EB8000A5230014AF8800043C108000240CBFFFB4 -:10EB9000010C4824240B000236080180A50B000C50 -:10EBA000A50A000EA5060008A5090026A507001065 -:10EBB0003C071000AE0701B80A0010E88FBF002420 -:10EBC0003C0308008C6300D02E45000C001221C0CD -:10EBD000386B00012D6200010045F82417E0FF9A10 -:10EBE0003270FFFF264CFFFC2D840004548000503F -:10EBF00000002021386A00022D43000100658024B6 -:10EC00001600004A3270FFFF00076A420012702BA4 -:10EC100001AE40245500006300002021001221C0F5 -:10EC2000020028210A0010E53626000234DF000227 -:10EC30000280202133E6FFFF0E000F5530A5FFFFB5 -:10EC40000A0010AC00002021240401000200282149 -:10EC50000E000F55022030210A001098000000001D -:10EC60008C66400030CF010011E0003D30F801001B -:10EC70003C1208008E5200241300001132340004AC -:10EC80003C1F0F0000FFC8243C0502001325000CA8 -:10EC90008F8C000C022030213265FFFF018958243F -:10ECA00001641021904900043230FFFB2411FFFE63 -:10ECB000252700040E000F55000721C002519024A3 -:10ECC0002404000112440052324300011460005831 -:10ECD00002003021324A0004114000048F8D0000F0 -:10ECE00031A808001500005A3265FFFF1680FF5B4F -:10ECF0008FBF00243C138000366501803C048000F7 -:10ED00008C9001B80600FFFE24062000240F0002AC -:10ED1000A4A60008A0AF000BA4A000103C0E100099 -:10ED2000AC8E01B80A0010E88FBF0024000020213B -:10ED3000020028210A0010E5362600021140FEE9F3 -:10ED40000000A021952E0110950D000231C8FFFF93 -:10ED500051A8FEE40012A1C00A00108B8F92001C83 -:10ED60003C0508008CA5002430B800015300FF3B8F -:10ED70008FBF00243265FFFF3626000200002021ED -:10ED80000E000F55000000000A0010E88FBF00249D -:10ED9000362600020E000F55240400800A0010E8F9 -:10EDA0008FBF0024020028210E000F553226FFFBE2 -:10EDB0000A001159001221C0910300012402000130 -:10EDC0001062FEEA24040001241000021470FEC543 -:10EDD0000000A02130E300401060FEC38F92001CB1 -:10EDE000952B0110950900023167FFFF1127FEE006 -:10EDF0008FBF00240A00108B0000000024030003D2 -:10EE000034820180A043000B0A0011343C108000C2 -:10EE100032140004168000033265FFFF3612000230 -:10EE20003250FFFF020030210A0011B10000202102 -:10EE3000000020210E000F553265FFFF0A001186E9 -:10EE40003210FFFB241FFFFE0A001132011F402475 -:10EE5000020030210E000F55240401000A00118C1D -:10EE60000000000027BDFFC8AFB00010AFBF0034E6 -:10EE70003C10600CAFBE0030AFB7002CAFB600281E -:10EE8000AFB50024AFB40020AFB3001CAFB2001880 -:10EE9000AFB100148E0C5000240DFF7F3C058000A4 -:10EEA000018D5824356A380C24090003AE0A50003D -:10EEB000ACA900083C010800AC2000200E0017435C -:10EEC000000000003C0560168CA700003C08FFFF16 -:10EED0003C06001034C3805100E820243C02535308 -:10EEE000AE03537C1082026134A37C008C74007CDE -:10EEF0008C7500783C116000362420203C05080108 -:10EF000024A581142406000A3C1180003C13000251 -:10EF10003C12600CAF950010AF9400140E0015EC7D -:10EF2000363E0180AE5353FC8E3000003216000393 -:10EF300012C0FFFD3217000116E000583206000231 -:10EF400010C0FFF93C0480008C8F01402410004069 -:10EF5000AC8F00208C9201480012760231C3007001 -:10EF60001070013D2C67004150E00008240400604F -:10EF7000241500201075000E3C0340003C07800063 -:10EF8000ACE301780A00121B000000001464FFFBD0 -:10EF90003C0340000E001F5D000000003C034000E9 -:10EFA0003C078000ACE301780A00121B000000005F -:10EFB0008C830148241400043487018000034C0230 -:10EFC000312500FF8C83014010B4017124BFFFFA8A -:10EFD0002FF90006532000123C0580008C86014466 -:10EFE000241600FF30A500FF30CB00FF30CA00FF21 -:10EFF000115601BC256800042402000910A201AAD0 -:10F0000028AC000A118001962413000A240D000880 -:10F0100010AD00148F850018000819C03C05800051 -:10F020008CA801B80500FFFE24170002ACE3000025 -:10F03000A4E90008A0F7000B8CB401483C091000BB -:10F040003C034000A4F400108CA40144ACE4002470 -:10F050003C078000ACA901B8ACE301780A00121BA0 -:10F060000000000000067A020008A8803C040801A5 -:10F070002484828024AE000102A4902131E500FFA7 -:10F0800024100001A24F000014B0FFE3AF8E00185F -:10F09000000819C00A001258AF85001C8E340128E0 -:10F0A0003C028008AE3400208E2401048E2301002F -:10F0B000945F0048AF840000AF83000433F9FFFF82 -:10F0C0000E000F4EAF9900083C1808008F1800C0C2 -:10F0D000130000248F8700003C0708008CE700C461 -:10F0E00024E600013C010800AC2600C43C0380007B -:10F0F0008C6401243C076020ACE400140000000094 -:10F100003C0680003C154000ACD5013800000000F2 -:10F110005280FF8B32060002268C0140268D008033 -:10F120002409FF800189282401A99824001359404B -:10F1300031A2007F0005B140318A007F3C1F2000D2 -:10F1400037E800020162C02502CAC8250328A025AD -:10F150000308B825ACD70830ACD408300A00122117 -:10F16000320600023C05001000E54024150000A610 -:10F170008F8300043C0C08008D8C00203C0D800027 -:10F1800095AA010E258B000130E940003C010800E2 -:10F19000AC2B00203155FFFF112000B6000090215C -:10F1A0003C0F002000EF702411C000B330F7800046 -:10F1B0008F9300042416BFFF00F638243663100036 -:10F1C000AF87000030E22000104000B62405FFBFEA -:10F1D0003C08000400E8302410C000020065102440 -:10F1E0003462004030E901001120000EAF820004BB -:10F1F0003C0B002000EB5024114000043C0D0004A7 -:10F2000000ED602411800139000000009637011ED6 -:10F210009636011C32EFFFFF00169C0001F37025AB -:10F22000AF8E000C9639010C8E2440003418FFFF7D -:10F23000109800CA3325FFFF309F010057E00001FE -:10F240002412001030E31000106000133653000148 -:10F2500030E400201480000A3C06100000E6102470 -:10F260001040000D3C0C0C003C0B0BFF00EC50243C -:10F270003569FFFF012A402B1100000830EE010024 -:10F280003C0D08008DAD002C3653000525B2000161 -:10F290003C010800AC32002C30EE010015C0000B20 -:10F2A0003C0600018F880004310F400055E0000843 -:10F2B00000E628243C181F0100F8B8243C16100072 -:10F2C00052F6010E30B902003C06000100E6282487 -:10F2D00014A000A43C1F100000FF202400004021C7 -:10F2E000108000070000A82100075E023175000FA2 -:10F2F000001550803C0208012442828001424021D6 -:10F300008F8C001811800069026090211480000326 -:10F310003C0980003C080801250882809532010ED6 -:10F3200091030000026030213244FFFF2485000475 -:10F33000106000080000B821240D0003106D0122A8 -:10F34000241600029117000112F6002630F8004042 -:10F350000015B9C08F82001C504000013666004085 -:10F360003C1680008ECA400031530100126000C775 -:10F3700030D500043C0B08008D6B002430D3FFFB1C -:10F380003166000414C0010A30B2FFFF56A000012C -:10F390003673000402E02021024028210E000F55A0 -:10F3A0000260302116A0000D0000202136C501802A -:10F3B0003C0480008C8C01B80580FFFE240D2000E9 -:10F3C00024120002A4AD0008A0B2000BA4A00010FB -:10F3D0003C051000AC8501B8000020210A00135F35 -:10F3E000008010211300FFDB0000B821953F0110C1 -:10F3F0009519000233E8FFFF5328FFD60015B9C066 -:10F400000A0013278F82001C2413BFFF0073682497 -:10F4100011A00007240E87FF006E48241520000A63 -:10F420003C0F006000EF9024124000070000000035 -:10F430000E000D34000000001040FF323C0680003A -:10F440000A00128D3C0380000E0014C90000000069 -:10F450000A00135F000000000E0014EF000000001F -:10F460003C0340003C078000ACE301780A00121B1B -:10F470000000000030F7800012E0FF528F8300048C -:10F480003C19002000F9C0241300FF4E8F9F000498 -:10F490003C04FFFF34837FFF00E338240A0012C1DD -:10F4A00037E380000A0012CA006510243C040800FB -:10F4B0008C840038148000022489FFFF000048215A -:10F4C0003C038000946F010E31EEFFFF110000EB52 -:10F4D00025D600043C0308008C6300301060000A4D -:10F4E00030EA01008F9800043317400012E0000654 -:10F4F0003C020F0000E2F8243C190100033F402BBE -:10F50000110000D532C5FFFF114000303C0C0F0048 -:10F5100000EC58243C0602001166002C000000009C -:10F520008F95000C3C0D080025AD003832D2FFFF4E -:10F5300002A9282400ADB02192C7000424E90004E8 -:10F54000000921C002402821366600020E000F5536 -:10F55000000000000A00135F000010210A0012E200 -:10F56000241200203C1908008F3900D802A028215D -:10F5700024040080273800013C010800AC3800D882 -:10F580000E000F55240600030A00135F000010212F -:10F590008C84014000E028213C0380008C7701B876 -:10F5A00006E0FFFE2408001CACA40000A0A8000B8D -:10F5B0003C181000AC7801B83C0340003C078000C8 -:10F5C000ACE301780A00121B000000003C030800B5 -:10F5D0008C6300D02EA5000C001521C0386F0001EF -:10F5E0002DF200010245702415C0FFD632D2FFFF74 -:10F5F00026B7FFFC2EE40004148000080000202140 -:10F60000386800022D180001030518241060000658 -:10F610000007FA4232D2FFFF0000202102402821D9 -:10F620000A0013A4366600020015102B03E2C8245A -:10F630001720000532D2FFFF001521C0024028210B -:10F640000A0013A43666000200002021024028218F -:10F650000E000F553266FFFB0A0013E0001521C0B3 -:10F6600010B3006A000860802406000B14A6FE6B2D -:10F67000000819C0000828803C15080126B58280C2 -:10F6800000B530210A001258A0C0000134D5000294 -:10F6900002E0202130A5FFFF0E000F5532A6FFFF2C -:10F6A0000A001348000020210008B8803C0308012C -:10F6B0002463828002E31021905400001280FE57E0 -:10F6C000000819C0A04000008F9900182738FFFFDC -:10F6D0001700FE52AF980018000819C00A0012580F -:10F6E000AF80001C0A00124F240800030E000FBC5C -:10F6F000000000000A0012DA8F8700001720FEF3D6 -:10F700003C06000126BF000433E5FFFF3666000219 -:10F710003C0380008C7501B806A0FFFE8F890008AD -:10F720003C04800034930180AE60000011200099F9 -:10F73000240F000324AA0012012A102B1040009568 -:10F7400000000000946D01203C1280002403001A88 -:10F7500031ACFFFF364A018030EB4000A143000B83 -:10F760001160008F2583FFFE0123702B15C0008DD3 -:10F770002409FFFE35080001A5430014AF880004EA -:10F780002417BFFF0117B02424080002A7C8000CEB -:10F79000A7C5000EA7C60008A7D60026A7C7001059 -:10F7A0003C071000AE2701B80A00135F00001021CB -:10F7B00024040100024028210E000F550260302170 -:10F7C0000A00133400000000910300012415000119 -:10F7D0001075FF0224040001240E0002146EFEDDE9 -:10F7E0000000B82130E300401060FEDB8F82001C77 -:10F7F00095270110950F000230E9FFFF11E9FF0E78 -:10F80000008010210A0013278F82001C3C0F080182 -:10F8100025EF8280018F702100069202A1D20001A3 -:10F820003C1F60008FED1820241000010110980487 -:10F830003C0208012442828201B3B025018250219A -:10F8400000065C02000819C0A54B0000AFF61820A6 -:10F850000A0012593C058000366600020E000F5562 -:10F86000240400800A00135F000010218CAE000405 -:10F870003C0F60000A00120C01CF18218C6640007A -:10F8800030CA01001140003730EB01003C15080080 -:10F890008EB5002411600013327700043C0D0F0078 -:10F8A00000ED28243C0C020010AC000E8F84000CEC -:10F8B0003C0F080025EF00380260302100899024B9 -:10F8C000024F702191C7000432C5FFFF3272FFFB67 -:10F8D00024E90004000921C00E000F552413FFFE87 -:10F8E00002B3A8242403000112A3003032B800019F -:10F8F0001300000732A8000402403021000020213C -:10F900000E000F5532C5FFFF3252FFFB32A8000434 -:10F91000110000048F9F000033F908005720002BCE -:10F9200032C5FFFF16E0FEC4000010213C16800027 -:10F9300036C401803C0580008CA201B80440FFFE63 -:10F94000240B200024060002A48B0008A086000BD4 -:10F95000A48000103C0A1000ACAA01B80A00135F92 -:10F96000000010213C0508008CA5002430AC0001EB -:10F970005180FEB10000102132C5FFFF3666000243 -:10F98000000020210E000F55000000000A00135F48 -:10F9900000001021A3CF000B0A0014322417BFFF70 -:10F9A0002409FFFE0A0014300109402432550004E6 -:10F9B00016A0000332C5FFFF3657000232F2FFFFE8 -:10F9C000024030210A0014B2000020210240302100 -:10F9D0000E000F55240401000A00149A00000000D4 -:10F9E0003C0380008C6401003082003E144000081B -:10F9F00000000000AC6000488C66010030C507C004 -:10FA000010A0000500000000AC60004CAC6000508D -:10FA100003E0000824020001AC600054AC60004028 -:10FA20008C6801003107380010E0FFF90000000089 -:10FA30002402000103E00008AC6000443C03900095 -:10FA400034620001008220253C038000AC64002069 -:10FA50008C65002004A0FFFE0000000003E0000809 -:10FA6000000000003C028000344300010083202598 -:10FA700003E00008AC44002027BDFFD8AFB100145C -:10FA80003C048000AFBF0020AFB3001CAFB2001831 -:10FA9000AFB000108C9201408C9001482402000EFF -:10FAA00000108C02322300FF106200590204282447 -:10FAB0002866000F10C00013286A003724070006CC -:10FAC0001067008E286800075100002D24040009EB -:10FAD000106000783C06800024090001106900B025 -:10FAE000000000000000000D8FBF00208FB3001C3D -:10FAF0008FB200188FB100148FB0001003E000081F -:10FB000027BD002811400059240D0038286B00350E -:10FB1000116000053C058000240C001F146CFFF1EF -:10FB2000000000003C0580008CB801B80700FFFE13 -:10FB300034B90180AF320000241F000124120002FA -:10FB40003C021000AF200004A7310008A33F000AC8 -:10FB5000A332000BA7300010AF200024AF200028F4 -:10FB6000ACA201B88FBF00208FB3001C8FB2001869 -:10FB70008FB100148FB0001003E0000827BD0028EB -:10FB8000106400232405000B1465FFD63218FFFF14 -:10FB9000170000203C0580008F93FEEC927F00054B -:10FBA00033F900041720FFCF000000000E0014E01E -:10FBB00002402021926900050240202135280004DE -:10FBC0000E0014EAA26800059267000530E2000406 -:10FBD00014400002000000000000000D926B0000C5 -:10FBE00024060020316A00FF1546000A3C0580000B -:10FBF0008CA401B80480FFFE34AD0180240E000502 -:10FC00003C0C1000ADB20000A1AE000BACAC01B8D2 -:10FC10003C0580008CA301B80460FFFE34AF018076 -:10FC200024130002ADF20000ADF20004A5F10008BB -:10FC3000A1F3000AA1F3000BA5F00010ADE0002431 -:10FC40008CB101443C101000ADF10028ACB001B8FB -:10FC50008FBF00208FB3001C8FB200188FB100142B -:10FC60008FB0001003E0000827BD0028106DFFAD25 -:10FC7000240E0080146EFF9B000000003C058000F5 -:10FC80008CA301B80460FFFE34AF0180241200028F -:10FC9000A1F2000BA5F10008A5F000108CB30144FF -:10FCA0003C021000A5F30012ACA201B80A00152B0B -:10FCB0008FBF00208CC301B80460FFFE34D30180E5 -:10FCC000AE720000AE60000424120001A6710008AC -:10FCD00024110002A272000AA271000BA67000108B -:10FCE0008CD001443C0F1000AE700024AE600028A0 -:10FCF000ACCF01B80A0015668FBF00203C0380001E -:10FD00008C6601B804C0FFFE346201803C06080125 -:10FD100090C682C0AC52000010C000030000382121 -:10FD20003C0708018CE782C83C05800034AA0180AA -:10FD30002404000234CC0001AC470004A5510008A3 -:10FD4000A14C000AA144000BA55000108CAB01444B -:10FD50000000202101402821AD4B002410C00003E9 -:10FD60008FBF00203C0408018C8482C48FB3001C28 -:10FD70008FB200188FB100148FB000103C0E10002D -:10FD80003C0D800027BD0028ACA40028ADAE01B812 -:10FD90003C010801A02082C003E000080000000030 -:10FDA00010A0000B3C0680008C980144241900022E -:10FDB0003C010801A03982C03C010801AC3282C874 -:10FDC0003C010801AC3882C40A0015668FBF0020D0 -:10FDD0008CDF01B807E0FFFE34C701802409000270 -:10FDE000ACF20000ACF20004A4F10008A0E9000AA3 -:10FDF000A0E9000BA4F00010ACE000248CC8014482 -:10FE00003C021000ACE80028ACC201B80A0015663C -:10FE10008FBF002027BDFFE8AFBF00100E000F4EC0 -:10FE2000000000003C0280008FBF00100000202175 -:10FE3000AC4001800A00101027BD00183084FFFF7D -:10FE400030A5FFFF1080000700001821308200015C -:10FE50001040000200042042006518211480FFFBBE -:10FE60000005284003E000080060102110C00007D2 -:10FE7000000000008CA2000024C6FFFF24A500049F -:10FE8000AC82000014C0FFFB2484000403E00008DF -:10FE90000000000010A0000824A3FFFFAC860000B3 -:10FEA00000000000000000002402FFFF2463FFFFA9 -:10FEB0001462FFFA2484000403E00008000000003C -:10FEC00027BDFFE8AFBF0014AFB000100E0014E074 -:10FED000008080213C0480083483008090650025E8 -:10FEE0000200202134A200200E0014EAA0620025A6 -:10FEF000020020218FBF00148FB000100A000C9E5A -:10FF000027BD00183C03800027BDFFF83462018044 -:10FF1000AFA20000308C00FF30AD00FF30CE00FFFC -:10FF20003C0B80008D6401B80480FFFE00000000DF -:10FF30008FA900008D6801288FAA00008FA70000FC -:10FF40008FA400002405000124020002A085000AFD -:10FF50008FA30000359940003C051000A062000B03 -:10FF60008FB800008FAC00008FA600008FAF00009C -:10FF700027BD0008AD280000AD400004AD8000247E -:10FF8000ACC00028A4F90008A70D0010A5EE0012CF -:10FF900003E00008AD6501B83C06800827BDFFE816 -:10FFA00034C50080AFBF001090A7000924020012E2 -:10FFB00030E300FF1062000B008030218CA800505D -:10FFC00000882023048000088FBF00108CAA003412 -:10FFD000240400390000282100CA48230520000518 -:10FFE000240600128FBF00102402000103E0000865 -:10FFF00027BD00180E001612000000008FBF001071 -:020000040001F9 -:100000002402000103E0000827BD001827BDFFC837 -:10001000AFB1002C00A08821AFB2003027A500109E -:100020000080902102202021AFBF0034AFB0002813 -:100030000E000CA8AFA000101440009B3C078008E5 -:1000400034E400809086000830C5000814A00069E0 -:100050008FA700103C18800837100080920F00080E -:1000600031EE000815C00002240800030000402102 -:100070003C0B800891650011916A00123566008082 -:100080008CDF0054314900FF0128202130A300FFFC -:10009000000410800062282100BFC82B1320000834 -:1000A0000000000094D0005C8CCF0054320DFFFFA4 -:1000B00001E5702301AE602B118000940000000068 -:1000C00094D9005C3323FFFF30FF000413E0007479 -:1000D000000830808FA8001C0068102B5040004F93 -:1000E00030E30004006610232C46008010C000029C -:1000F00000408021241000800E0014E002402021E6 -:100100003C0380083466008024070001ACC7000C63 -:1001100090C800080010684034670100311F007F5C -:10012000A0DF00088E39000427380001ACD8003069 -:10013000A4D0005C8CCF003C9630000E01F0702102 -:10014000ACCE00208CCC003C018D5821ACCB001CE7 -:100150008E2A0004ACEA00008E290008ACE90004F5 -:100160008FA5001030A400085480003293A6002010 -:10017000A0C0004E90C9004E2402FFDF3C1880084A -:10018000A0E9000890C50008370D0080240A00503F -:1001900000A22024A0C400088E390008ADB90038A0 -:1001A0008F0F00148DB0003001F07021ADAE00341F -:1001B00091AC0000318B00FF116A002C2645010034 -:1001C0000E0014EA024020212404003800002821F7 -:1001D0000E0016122406000A8FBF00348FB20030C2 -:1001E0008FB1002C8FB000282402000103E000082A -:1001F00027BD003830E801001100003D8FA3001436 -:100200008C8A0058006A48230520FF933C18800818 -:10021000AC8300580A0016668FA700102407021846 -:100220001060FFB100E610238FA2001C0A00168B9D -:10023000004610233C188008370D0080A0E6000817 -:100240008E390008240A0050ADB900388F0F001411 -:100250008DB0003001F07021ADAE003491AC0000E3 -:10026000318B00FF156AFFD6264501002406FF806A -:1002700000A610243C098000AD2200288E2700082B -:1002800030A3007F3C04800C0064F821AFE700D06D -:100290008E280008AF9F00280A0016C1AFE800D4DE -:1002A0000A0016882C6202188E2300083C0480087D -:1002B00034820080AC430054024020210E0016011D -:1002C000AC400030240400382405008D0E001612C6 -:1002D000240600128FBF00348FB200308FB1002C83 -:1002E0008FB000282402000103E0000827BD003879 -:1002F000AC800058908C0008240DFFF7018D582425 -:10030000A08B00080A0016668FA700108CD8005436 -:100310000A0016830305182327BDFFE8AFBF0010AE -:1003200090A6000D30C7001010E0000C00804021A6 -:100330003C0280088C4400048CA300081064000870 -:1003400030C9000430C5000410A0001C8FBF00108D -:100350002402000103E0000827BD001830C9000492 -:100360001120001030CB001210E0FFF98FBF0010F9 -:100370003C0880088CA700088D06000414E6FFF5F1 -:1003800024020001240400382405008D0E001612FA -:10039000240600128FBF00102402000103E00008B1 -:1003A00027BD0018240A0012156AFFE98FBF00104C -:1003B000010020210A00165427BD0018000020214A -:1003C0000A000D1A27BD00183C05080024A55D5041 -:1003D0003C04080024847B103C02080024425D5841 -:1003E000240300063C010801AC2582D03C01080131 -:1003F000AC2482D43C010801AC2282D83C01080123 -:10040000A02382DC03E000080000000003E00008F5 -:10041000240200013C028000308800FF3447018044 -:100420003C0680008CC301B80460FFFE00000000A1 -:100430008CC501282418FF803C0D800A24AF0100E0 -:1004400001F8702431EC007FACCE0024018D202116 -:10045000ACE50000948B00DA350960002408000246 -:10046000316AFFFFACEA000424020001A4E900089D -:10047000A0E8000BACE000243C071000ACC701B8BA -:10048000AF84002803E00008AF8500588C99000471 -:100490008F8D00282409FFBF0325C023AC980004DA -:1004A00091AF00C42403FFEF31EE007FA1AE00C482 -:1004B0008C8C0020938B00348F860028358A0002B4 -:1004C000AF8B004CA7800048AC8A0020A4C000ACD1 -:1004D00090C800C401093824A0C700C48F84002834 -:1004E000AC8000DC908500C400A3102403E0000869 -:1004F000A08200C43C028000344501803C0480009E -:100500008C8301B80460FFFE8F8900582407608344 -:1005100024060002ACA900008C880124ACA80004C9 -:10052000A4A70008A0A6000B3C05100003E00008EB -:10053000AC8501B8938800348F89004C8F820028E5 -:1005400030C600FF0109382330E900FF01221821DD -:1005500030A500FF2468007810C000020124382173 -:100560000080382130E400031480000330AA000327 -:100570001140000D312B000310A0000900001021D4 -:1005800090ED0000244E000131C200FF0045602BB9 -:10059000A10D000024E700011580FFF925080001E6 -:1005A00003E00008000000001560FFF300000000F9 -:1005B00010A0FFFB000010218CF80000245900045B -:1005C000332200FF0045782BAD18000024E700041B -:1005D00015E0FFF92508000403E000080000000012 -:1005E00093850034938800448F87004C00043200C8 -:1005F0003103007F00E5102B30C47F001040000F56 -:10060000006428258F8400283C0980008C8A00DC47 -:10061000AD2A00A43C03800000A35825AC6B00A0C9 -:100620008C6C00A00580FFFE000000008C6D00AC0B -:10063000AC8D00DC03E000088C6200A80A0017D62D -:100640008F840028938800453C0280000080502160 -:10065000310300FEA383004530ABFFFF30CC00FF29 -:1006600030E7FFFF344801803C0980008D2401B849 -:100670000480FFFE8F8D005824180016AD0D000079 -:100680008D2201248F8D0028AD0200048D59002099 -:10069000A5070008240201B4A119000AA118000B43 -:1006A000952F01208D4E00088D4700049783004848 -:1006B0008D59002401CF302100C7282100A3202319 -:1006C0002418FFFFA504000CA50B000EA5020010C6 -:1006D000A50C0012AD190018AD18002495AF00D874 -:1006E0003C0B10002407FFF731EEFFFFAD0E002892 -:1006F0008DAC0074AD0C002CAD2B01B88D460020E4 -:1007000000C7282403E00008AD4500208F8800289A -:100710000080582130E7FFFF910900C63C028000AD -:1007200030A5FFFF312400FF00041A0000675025A8 -:1007300030C600FF344701803C0980008D2C01B891 -:100740000580FFFE8F820058240F0017ACE20000E6 -:100750008D390124ACF900048D780020A4EA00084A -:10076000241901B4A0F8000AA0EF000B9523012082 -:100770008D6E00088D6D00049784004801C35021E0 -:10078000014D602101841023A4E2000CA4E5000EB9 -:10079000A4F90010A4E60012ACE000148D78002447 -:1007A000240DFFFFACF800188D0F006CACEF001C9F -:1007B0008D0E00683C0F1000ACEE0020ACED002464 -:1007C000950A00AE240DFFF73146FFFFACE6002886 -:1007D000950C00709504007231837FFF0003CA00FE -:1007E0003082FFFF0322C021ACF8002CAD2F01B8EE -:1007F000950E00728D6A002000AE3021014D282434 -:10080000A506007203E00008AD6500203C028000F0 -:10081000344601803C0580008CA301B80460FFFED3 -:1008200024090018ACC40000A0C9000B8F88002860 -:100830003C041000950700AEA4C70010ACC0003007 -:1008400003E00008ACA401B83C02800034450180FC -:100850003C0480008C8301B80460FFFE8F8A003066 -:10086000240600199549001C3128FFFF000839C0F3 -:10087000ACA70000A0A6000B3C05100003E0000898 -:10088000AC8501B88F8700380080402130C400FF5C -:100890003C0680008CC201B80440FFFE8F890058DE -:1008A0009383005434996000ACA90000A0A3000514 -:1008B0008CE20010240F00022403FFF7A4A200061C -:1008C000A4B900088D180020A0B8000AA0AF000B42 -:1008D0008CEE0000ACAE00108CED0004ACAD00144A -:1008E0008CEC001CACAC00248CEB0020ACAB0028E2 -:1008F0008CEA002C3C071000ACAA002C8D090024C7 -:10090000ACA90018ACC701B88D05002000A32024B5 -:1009100003E00008AD040020938500542403000187 -:1009200027BDFFE800A330042CA20020AFB00010C8 -:10093000AFBF001400C01821104000132410FFFEA8 -:100940003C0708008CE7319000E610243C0880004A -:100950003505018014400005240600848F89002895 -:10096000240A00042410FFFFA12A00EC0E001872D4 -:1009700000000000020010218FBF00148FB0001093 -:1009800003E0000827BD00183C0608008CC631941F -:100990000A0018A400C310248F87003027BDFFE091 -:1009A000AFB20018AFB10014AFB00010AFBF001C61 -:1009B00030D000FF90E6000D00A08821008090213B -:1009C00030C5007FA0E5000D8F8500288E2300181C -:1009D0008CA200C01062002E240A000E0E00189790 -:1009E000A38A00542409FFFF104900222404FFFFBA -:1009F00052000020000020218E2600003C0C001038 -:100A000000CC5824156000393C0E000800CE682444 -:100A100055A0003F024020213C18000200D880244D -:100A20001200001F3C0A00048F8700308CE2001483 -:100A30008CE300108CE500140043F82303E5C82B79 -:100A400013200005024020218E24002C8CF1001080 -:100A5000109100310240202124020012A382005490 -:100A60000E0018972412FFFF105200022404FFFF0B -:100A7000000020218FBF001C8FB200188FB100141E -:100A80008FB000100080102103E0000827BD002077 -:100A900090A800C4350400200A0018CDA0A400C40A -:100AA00000CA48241520000B8F8B00308F8D00303A -:100AB0008DAC00101580000B024020218E2E002CE2 -:100AC00051C0FFEC00002021024020210A0018E85C -:100AD000240200178D66001050C0FFE600002021A0 -:100AE000024020210A0018E82402001102402021BF -:100AF000240200150E001897A3820054240FFFFF54 -:100B0000104FFFDC2404FFFF0A0018D78E260000D8 -:100B10000A00190E240200143C08000400C83824FE -:100B200050E0FFD400002021024020210A0018E8F4 -:100B3000240200138F86002827BDFFE0AFB1001408 -:100B4000AFBF0018AFB0001090C300C430A500FFC5 -:100B50003062002010400008008088218CCB00C04B -:100B60002409FFDF256A0001ACCA00C090C800C498 -:100B700001093824A0C700C414A000403C0C800028 -:100B80008F840028908700C42418FFBF2406FFEF3D -:100B900030E3007FA08300C4979F00488F82004C01 -:100BA0008F8D002803E2C823A7990048A5A000ACB8 -:100BB00091AF00C401F87024A1AE00C48F8C00284E -:100BC000A18000C78F8A0028A5400072AD4000DCDC -:100BD000914500C400A65824A14B00C48F90002466 -:100BE0008F84004C978600480204282110C0000F13 -:100BF000AF850024A38000443C0780008E2C0008B1 -:100C000094ED01208E2B0004018D5021014B802199 -:100C1000020620233086FFFF30C8000F390900018B -:100C20003131000116200009A38800449386003466 -:100C30008FBF00188FB100148FB0001027BD0020A7 -:100C4000AF85005003E00008AF86004C00C8702359 -:100C50008FBF0018938600348FB100148FB000103E -:100C600034EF0C00010F282127BD0020ACEE0084DA -:100C7000AF85005003E00008AF86004C359001803E -:100C8000020028210E001872240600828F8400289A -:100C9000908600C430C5004050A0FFBAA380005425 -:100CA0008F8500383C0680008CCD01B805A0FFFE82 -:100CB0008F8900582408608224070002AE090000D2 -:100CC000A6080008A207000B8CA300083C0E100029 -:100CD000AE0300108CA2000CAE0200148CBF0014F6 -:100CE000AE1F00188CB90018AE1900248CB800246F -:100CF000AE1800288CAF0028AE0F002CACCE01B887 -:100D00000A001932A38000548F8A002827BDFFE013 -:100D1000AFB10014AFB000108F88004CAFBF001807 -:100D20009389002C954200AC30D100FF0109182BAB -:100D30000080802130AC00FF3047FFFF00005821C9 -:100D400014600003310600FF0120302101095823FF -:100D5000978300480068202B1480001B00000000CF -:100D600010680043240A0001118A004834E7088013 -:100D70003165FFFF0E001814020020210E001854E8 -:100D80008F8400588F840028948D007025AC00015A -:100D9000A48C0070948B00703C0608008CC63188CF -:100DA00031677FFF10E6004F0000000002002021A5 -:100DB000022028218FBF00188FB100148FB00010BF -:100DC0000A00191E27BD0020914400C42406FF809C -:100DD00000868825A15100C4978400483088FFFF11 -:100DE0001100001C9389002C8F8E00282419EFFF1E -:100DF000008BF82395D800AC0168682B33E900FF1D -:100E000003197824A5CF00AC51A0002A0100582175 -:100E10008E0500202408FFFB2403000100A81024F5 -:100E2000AE0200201183002534E78000020020215B -:100E30003165FFFF0E00181401203021978B004808 -:100E40008F87004CA780004800EB8023AF90004CB8 -:100E50009389002C8F8C00288FBF00188FB100144D -:100E60008FB0001027BD002003E00008A18900C753 -:100E70008E0800202409FFFB34E7800001092824A4 -:100E8000AE050020158AFFBA34E708800200202151 -:100E90000E0017E23165FFFF020020210220282109 -:100EA0008FBF00188FB100148FB000100A00191EF8 -:100EB00027BD00200A0019D500004821020020218A -:100EC0003165FFFF0E0017E201203021978B0048AB -:100ED0008F87004CA780004800EB80230A0019E5AB -:100EE000AF90004C94890070240A8000012A4024AD -:100EF000A4880070908500709099007030A200FF67 -:100F0000000219C20003F827001FC1C0332F007F61 -:100F100001F87025A08E00700A0019BD0200202182 -:100F20008F88002824030001910A0078910500C7EA -:100F3000250900783147003F24E6FFE000C318048C -:100F40002CC2002030670019A385002C1040001A25 -:100F5000AF8900383C0A8000354B000224050001AF -:100F60002406000114E00016006B10240000282164 -:100F70001440000F306300201060000F24050001B2 -:100F80008D0600748D1900742403FF8000C31024A3 -:100F9000000279403338007F01F868253C0E1000CC -:100FA00001AE6025AD4C08309128000131060001EA -:100FB0000A0019930000000003E000080000000090 -:100FC0008D0F00748D0D00742418FF8001F87024BB -:100FD000000E414031AC007F010C50253C0B10004D -:100FE000014B38253C0980000A001993AD270830D1 -:100FF00027BDFFD8AFB000108F900038AFB40020ED -:10100000AFB10014AFBF0024AFB3001CAFB20018E3 -:101010008E0500103C0208008C4231B08F86003CE7 -:1010200030A73FFF00E2182B8CD2001400808821EB -:101030008CD30020106000070000A02190CB000D91 -:10104000240AFF80014B4824312800FF1500000CC2 -:1010500000056382022020212411000DA391005479 -:101060008FBF00248FB400208FB3001C8FB20018F4 -:101070008FB100148FB000100A00189727BD002808 -:101080003185000354A0FFF40220202194CF001CDE -:101090008F8E00288E070028A5CF00D88CCD001099 -:1010A000024D302310E6005C2402001F0E0018974A -:1010B000A3820054241FFFFF105F004E2404FFFF93 -:1010C0008F8300408F880030026398218D090010C3 -:1010D000012310238F830020AD020010AD130020E8 -:1010E0008C67007400F3202B148000620220202102 -:1010F0008F86003C8E0C00248CC5002411850007CF -:1011000002202021240E001C0E001897A38E0054EC -:10111000240DFFFF104D00372404FFFF8F840030A3 -:101120008C980024270F0001AC8F00241272004419 -:101130008F9900208F320074125300413C0A0080C6 -:101140008E090000012A10241440003A000000001B -:101150008E0400142412FFFF10920006240B001BC3 -:10116000022020210E001897A38B0054105200215A -:101170002404FFFF8E0300003C0C0001006C2824B7 -:1011800010A000133C0600800066A0241680000911 -:101190000200282102202021240E001A0E00189798 -:1011A000A38E0054240DFFFF104D00122404FFFFF6 -:1011B00002002821022020210E0018B72406000179 -:1011C0002410FFFF2404FFFF1050000A2414000124 -:1011D0008F8F0030022020210280302195F20034D0 -:1011E00024050001265800010E001993A5F80034CB -:1011F000000020218FBF00248FB400208FB3001C7B -:101200008FB200188FB100148FB000100080102131 -:1012100003E0000827BD00288F83004000E3C821B9 -:101220000259C02B1300FFA88F8800300A001A7CD7 -:1012300024020018AC8000200A001AA68E040014B4 -:101240008E1F00003C07008003E798241660FFF91A -:101250002408001A022020210E001897A3880054A9 -:101260002403FFFF1443FFBA2404FFFF0A001ACF30 -:101270008FBF0024240B001D0E001897A38B005471 -:10128000240AFFFF144AFF9A2404FFFF0A001ACF22 -:101290008FBF00248F85002827BDFFD8AFB3001C67 -:1012A000AFB20018AFB10014AFB00010AFBF002054 -:1012B00090A700C48F9000382412FFFF34E2004052 -:1012C00092060000A0A200C48E03001000809821A6 -:1012D0001072000630D1003F2408000D0E00189750 -:1012E000A3880054105200262406FFFF8F8A00288E -:1012F0008E0900188D4400C011240007240C000E34 -:10130000026020210E001897A38C0054240BFFFFCD -:10131000104B001B2406FFFF2404002012240004AD -:101320008F8D002891AF00C435EE0020A1AE00C41F -:101330008F85004010A0001A000000001224004B0E -:101340008F9800288F92FEEC2406FFFD9710007006 -:101350009651000A1230000B8FBF00203C1F08007E -:101360008FFF318C03E5C82B1720001E026020215F -:10137000000028210E0019932406000100003021EE -:101380008FBF00208FB3001C8FB200188FB10014E4 -:101390008FB0001000C0102103E0000827BD002816 -:1013A0005224002A8E0300148F8400289489007030 -:1013B00025280001A4880070948700703C0508006F -:1013C0008CA5318830E27FFF1045000E0000000040 -:1013D000026020210E00191E240500010A001B31A5 -:1013E000000030212402002DA38200540E00189723 -:1013F0002413FFFF1453FFE12406FFFF0A001B32F2 -:101400008FBF0020949800702419800024050001EB -:1014100003199024A492007090910070908D007038 -:10142000323000FF001079C2000F7027000E61C03B -:1014300031AB007F016C5025A08A00700E00191E90 -:10144000026020210A001B31000030212406FFFF2A -:101450001466FFD68F840028026020210E00191E1A -:10146000240500010A001B31000030210260202108 -:101470000A001B4B2402000A8F88002827BDFFE8C2 -:10148000AFB00010AFBF0014910A00C48F870038BE -:1014900000808021354900408CE60010A10900C47D -:1014A0003C0208008C4231B030C53FFF00A2182B2F -:1014B000106000078F85003C240DFF8090AE000D6A -:1014C00001AE6024318B00FF156000080006C38266 -:1014D000020020212403000D8FBF00148FB00010E4 -:1014E00027BD00180A001897A38300543306000391 -:1014F000240F000254CFFFF70200202194A2001C09 -:101500008F85002824190023A4A200D88CE80000AD -:1015100000081E02307F003F13F900353C0A0083AB -:101520008CE800188CA600C011060008000000001E -:101530002405000E0E001897A38500542407FFFF12 -:10154000104700182404FFFF8F85002890A900C4CD -:1015500035240020A0A400C48F8C0030918E000D93 -:1015600031CD007FA18D000D8F8300401060001CE5 -:10157000020020218F84003C8C9800100303782BFC -:1015800011E0000D2419001802002021A399005435 -:101590000E0018972410FFFF105000022404FFFFD4 -:1015A000000020218FBF00148FB000100080102198 -:1015B00003E0000827BD00188C8600108F9F0030C4 -:1015C0000200202100C31023AFE200102405000117 -:1015D0000E001993240600010A001BBA0000202106 -:1015E0000E00191E240500010A001BBA000020216C -:1015F000010A5824156AFFD98F8C0030A0A600EC90 -:101600000A001BA7A386004627BDFFD8AFB0001075 -:101610008F900038AFB20018AFBF0020AFB3001CEE -:10162000AFB100148E1100103C0308008C6331B080 -:1016300032253FFF00A3102B1040000800809021AE -:101640008F86003C2409FF8090CA000D012A4024A7 -:10165000310700FF14E0000B00116B8202402021D3 -:101660002412000DA39200548FBF00208FB3001CE2 -:101670008FB200188FB100148FB000100A001897B5 -:1016800027BD002831AC0003240B0001558BFFF46B -:101690000240202190CF000D31EE000811C0006003 -:1016A0008F93004016600009240200278E19000C59 -:1016B0008CD8002017380005240200208E02000874 -:1016C0008CDF0024105F0040240200200E001897D9 -:1016D000A38200542406FFFF104600332404FFFFBA -:1016E0008F990030240AFFF73C13800E9329000DD8 -:1016F0002404FF803C0D8000012AF824A33F000D44 -:101700008F9900203C0808008D0831AC8F83005869 -:10171000972700788F9F00300103102130E57FFF6D -:10172000000530400046782131F8007F0313602126 -:1017300001E47024ADAE002CA59100008FEB0028D1 -:10174000256A0001AFEA00288FE3002C8E09002CE7 -:1017500000694021AFE8002C8E07002CAFE7003075 -:101760008E050014AFE5003497E6003A24C200016C -:10177000A7E2003A973300783C1008008E1031B091 -:101780002663000130717FFF123000270060302196 -:101790008F8F002002402021240500010E00191E19 -:1017A000A5E60078000020218FBF00208FB3001C29 -:1017B0008FB200188FB100148FB00010008010217C -:1017C00003E0000827BD00288E0500142413FFFF46 -:1017D00010B3001D8F8300288E0800188C6700C08E -:1017E000150700092402000E8E0A00248CC9002867 -:1017F00015490005240200218E0700288CCB002CFF -:1018000010EB00132402001F0E001897A38200544F -:101810001453FFB32404FFFF0A001C3C8FBF0020B9 -:101820000A001C0424020024240E8000006E682498 -:1018300031ACFFFF000C5BC2317100FF001180274B -:101840000A001C35001033C00A001C532402002576 -:101850008E05002C10A0FFEC240200238F8E0020A8 -:101860008DCD007401A5602B1580FFE724020026B2 -:101870008CCF001400A7C02101F8202B1080FF9905 -:101880008F990030024020210A001C5324020022BC -:1018900027BDFFE0AFB000108F900038AFB100144B -:1018A000AFBF00188E0500103C0308008C6331B0F8 -:1018B0000080882130A43FFF0083102B10400007D8 -:1018C0008F86003C2409FF8090CA000D012A402425 -:1018D000310700FF14E000098F8B00402410000D39 -:1018E00002202021A39000548FBF00188FB1001454 -:1018F0008FB000100A00189727BD00201160000863 -:101900000005C3828F8F00288F8EFEEC2407FFFD19 -:1019100095EC007095CD000A11AC00388FBF00180F -:101920003305000314A0001000000000921900020B -:1019300013200041000000008E06002450C0000F5C -:1019400092040003022020212402000F0E001897A9 -:10195000A38200542408FFFF144800072407FFFF58 -:101960000A001CD08FBF001890C3000D306400081F -:101970001080003702202021920400032407000277 -:10198000308900FF15270005308F00FF8F8A004047 -:1019900011400031240C002C308F00FF39E500107D -:1019A0002CAD00012DEE00010200282101CD3025D3 -:1019B0000E0018B7022020212410FFFF1050000E47 -:1019C0002407FFFF8F8300401060001702202021B2 -:1019D0003C1908008F39318C0323C02B5700000CB1 -:1019E0002411002D02202021000028210E0019932F -:1019F00024060001000038218FBF00188FB10014A9 -:101A00008FB0001000E0102103E0000827BD002087 -:101A10000E001897A39100541450FFF62407FFFFFF -:101A20000A001CD08FBF00180E00191E24050001EB -:101A30000A001CCF000038218CDF00248E02002415 -:101A4000545FFFC1022020210A001CB09204000351 -:101A50000A001CA424020010022020210E00189766 -:101A6000A38C0054240BFFFF104BFFE32407FFFF60 -:101A70000A001CB79204000330A500FF24060001F1 -:101A800024A9000100C9102B1040000C00004021C7 -:101A9000240A000100A61823308B000124C600018F -:101AA000006A3804000420421160000200C9182BAB -:101AB000010740251460FFF800A6182303E0000882 -:101AC0000100102127BDFFD8AFB000188F9000385B -:101AD000AFB1001CAFBF00202403FFFF2411002F73 -:101AE000AFA3001092060000240500082610000194 -:101AF000006620260E001CEF308400FF00021E004E -:101B00003C021EDC34466F410A001D170000102104 -:101B100010A00009008018212445000130A2FFFF19 -:101B20002C4500080461FFFA0003204000862026AF -:101B300014A0FFF9008018210E001CEF24050020DE -:101B40008FA300102629FFFF313100FF000342025E -:101B5000240700FF1627FFE2010218260003502782 -:101B6000AFAA0014AFAA00100000302127A800106F -:101B700027A7001400E6782391ED000324CE00018E -:101B800000C8602131C600FF2CCB00041560FFF9AE -:101B9000A18D00008FA200108FBF00208FB1001C0C -:101BA0008FB0001803E0000827BD0028938300349D -:101BB00027BDFFE024020034AFB10014AFB0001025 -:101BC000AFBF001CAFB20018008088211062006215 -:101BD00000A0802192040004148000458F88002812 -:101BE000A380002C8E0500048D0600C83C0700FF72 -:101BF00034E3FFFF00A3282400C5102B1440004D40 -:101C0000AF850040978A00488F87004C014710231A -:101C100010A00032A78200488F980020304CFFFFB0 -:101C20009312007C0012788231F100010011708063 -:101C300001C56821018D582B116000618F86002835 -:101C40008F8900248F8400501089005E3C023F0180 -:101C50008E1F00003C10250003E2C8241730007AD4 -:101C60008F8400388F8700388F8600288CE300002F -:101C7000ACC300788CE50010ACC500888F87004CA1 -:101C80008F850040938D002C30AE0003000E402362 -:101C9000310A0003014D4021A388002C94CB00ACF5 -:101CA00001276021AF8C002435691000A4C900AC65 -:101CB0001620005101452021AF84004C0000202156 -:101CC0008FBF001C8FB200188FB100148FB00010AE -:101CD0000080102103E0000827BD00208F8400242D -:101CE000AF80004C008730210A001D80AF860024A1 -:101CF000241F000CA39F00540E00189702202021DF -:101D00002419FFFF1059FFEE2404FFFF8F880028DD -:101D1000A380002C8E0500048D0600C83C0700FF40 -:101D200034E3FFFF00A3282400C5102B1040FFB5AB -:101D3000AF8500400220202124090019A389005406 -:101D40000E0018972411FFFF1051FFDD2404FFFF40 -:101D50000A001D528F8500408F8400288F8700382D -:101D60008CF20030908600C430C5001014A0001022 -:101D70008F83004C2C68000515000028000000002F -:101D8000908A00C4246BFFFC314900101520000824 -:101D9000316400FF8F8D00508F8C002411AC000443 -:101DA000388F000131EE000115C0002F0000000047 -:101DB0000E001D02000000000A001DD900000000F6 -:101DC0008F890024938D002C30AE0003000E402339 -:101DD000310A0003014D4021A388002C94CB00ACB4 -:101DE00001276021AF8C002435691000A4C900AC24 -:101DF0001220FFB10145202125180004A398002CD2 -:101E000094CF00AC24920004AF92004C35F1200036 -:101E1000A4D100AC0A001D81000020218C8200DCCE -:101E20001242FF6C0220202124180005A3980054C0 -:101E30000E0018972412FFFF1452FF662404FFFFC0 -:101E40000A001D828FBF001C30E500FF0E00179EA8 -:101E5000000030218F8600288F87004C8F89002456 -:101E60000A001D728F8500400E0017C90000000097 -:101E70000A001DD9000000009383004627BDFFE043 -:101E800024020002AFB20018AFB10014AFBF001CB3 -:101E900000808821AFB00010000090211062005532 -:101EA0002404FFFD978300488F85004C3066FFFFB8 -:101EB00000C5202B1480005B938700343C08800011 -:101EC0009504012010E500528F8A00248F84005071 -:101ED00030A500FF0E00179E240600018F9F0058BA -:101EE0003C0580003C19408027ED017831B0007836 -:101EF000240EFF800219582534AF090031B80007BD -:101F000001AE6024ACAC0800030F8021ACAB08101C -:101F100002202021020028210E001D3CAF90003835 -:101F20002403FFFF104300332404FFFF8E0C001036 -:101F30003C0708008CE731B09206000031843FFF77 -:101F40000087102B1040002330CD003F8F980058A1 -:101F5000000471803C0408008C8431A82409FF80AF -:101F60009390004500984021010E202100897024A3 -:101F7000000E51403C0980003099007F3C0F0080EA -:101F80008F8800283525094035E2000101593825A0 -:101F9000308B0078308600073C0310003C1F800C1B -:101FA00000C5C0210162582500E35025033F782178 -:101FB00036050001AD2E0804AF98003CAD2B081487 -:101FC000AF8F0030AD2E0028AD040074AD2A08306C -:101FD000A38500459383004624100003507000271A -:101FE00025A3FFE0240C0001106C001C2406002334 -:101FF000024020218FBF001C8FB200188FB1001447 -:102000008FB000100080102103E0000827BD0020E1 -:10201000314900035520FFAE8F8400500A001E1581 -:102020008F9000508F840050306500FF0E00179E87 -:1020300024060001938B0034240500341165001838 -:10204000978300488F85004C3062FFFF00A2582321 -:10205000AF8B004C0A001E4DA780004811A6003728 -:1020600000000000022020212411000B0E00189710 -:10207000A39100540A001E4D004090212C720020B4 -:102080001240FFF80003F8803C07080124E7813C78 -:1020900003E7C8218F2D000001A000080000000008 -:1020A0008F85004C2CA200055440001DA7800048DD -:1020B000978A00483148FFFF00A848232D2F0005CC -:1020C00011E00003314400FF24AEFFFC31C400FFE7 -:1020D0008F9000508F980024121800043899000146 -:1020E000332D000115A00029000000008F91002869 -:1020F000922500C434A30010A22300C49783004893 -:102100008F85004C8F8400283062FFFF00A2582387 -:10211000AC8000DCA78000480A001E4DAF8B004C4D -:102120003062FFFF00A258230A001E4DAF8B004C07 -:102130002403FFFF11830005000000000E001B6F49 -:10214000022020210A001E4D004090210E001AF6A8 -:10215000022020210A001E4D004090210E001BD3BA -:10216000022020210A001E4D004090210E001A4D31 -:10217000022020210A001E4D004090210E001C75F7 -:10218000022020210A001E4D004090210E0017C998 -:1021900000000000978300488F85004C306CFFFFE3 -:1021A00000AC38232CFF000553E0FFA83062FFFF8E -:1021B0008F860028A7800048ACC200DC3062FFFF99 -:1021C00000A258230A001E4DAF8B004C27BDFFD044 -:1021D000AFB20018AFB00010AFBF0028AFB50024F9 -:1021E000AFB40020AFB3001CAFB100143C0C8000B2 -:1021F0008D880128240FFF803C07800A25100100EC -:10220000250B0080020F68243205007F016F7024C7 -:10221000AD8E009000A72821AD8D002490A700EC82 -:102220003169007F3C0A8004012A1821A3870046F7 -:102230009066007C00809021AF83002030C20002B5 -:10224000AF880058AF85002800A018211440000274 -:102250002404003424040030A38400348C6600CCB1 -:1022600030F100FF24040004AF86004C1224000467 -:10227000A38000548E5300041660001D3C088000AB -:102280009387004530F200011240000F8FBF0028F5 -:102290008CB800748CA400742419FF80031988245E -:1022A00000117140308F007F01CF60253C0D200070 -:1022B000018D582530F500FE3C0A8000AD4B0830FA -:1022C000A39500458FBF00288FB500248FB4002050 -:1022D0008FB3001C8FB200188FB100148FB00010A4 -:1022E0002402000127BD003003E00008ACA600CCAA -:1022F0008E590008951F01208E460010033FC02113 -:102300003307FFFF30F5000F32B40001AF86002421 -:102310001680003BA395004435060C0002A6102150 -:1023200000F51823AD030084AF8200508E490004ED -:102330003128FFFF1100002BA78900482410FF80DF -:102340003C1580003C1420000A001F3B2413FFFEB4 -:1023500090AE00C4020E682431AC00FF1580002A44 -:10236000024020219384004597860048308F000169 -:1023700011E0000B026428248F8900288D2300744B -:102380008D280074A3850045007010240002C94008 -:10239000311F007F033FC02503148825AEB10830EC -:1023A00010C000108F85002890A700C40207582491 -:1023B000316A00FF1540FFE6024020210E001DEFAC -:1023C000979100481040FFE8938400452405FFFDE5 -:1023D000544500058E430020022028210E0017746A -:1023E000024020218E430020307000041600000AB5 -:1023F0002414FFFB8F8500280A001EF18F86004CF5 -:102400000A001F1CAF8600500E001A1900000000C1 -:102410000A001F2B93840045007498240E00178E29 -:10242000AE5300208F8500280A001EF18F86004CD5 -:1024300027BDFFD8AFB3001CAFB10014AFBF002061 -:10244000AFB20018AFB000103C0280008C520140C7 -:102450008C4B01483C048000000B8C02322300FFAF -:10246000317300FF8C8501B804A0FFFE3490018019 -:10247000AE1200008C8701442464FFF024060002A1 -:102480002C830013AE070004A6110008A206000B5F -:10249000AE1300241060004F8FBF0020000448805E -:1024A0003C0A0801254A81BC012A40218D04000014 -:1024B00000800008000000003C1008008E1031A8C9 -:1024C00031733FFF001389800212C8212405FF8069 -:1024D00003312021264C0100264700803C1F80004C -:1024E00000E51824318F007F30E9007F308A007FBB -:1024F0003C18800A3C0E80043C0D800C00851024A2 -:1025000001853024014D8021AFE6002401F84021EF -:10251000AFE30090012E9821AFE20028AF90003089 -:10252000AF880028AF9300200E001863016080215F -:102530003C0380008C6B01B80560FFFE8F87003084 -:10254000346501808F86002890E3000DACB2000056 -:10255000A4B00006000316000002FE03001F90272F -:10256000001227C21080007A24C2007824196082E9 -:10257000A4B90008A0A00005241F0002A0BF000B02 -:1025800000041C008F8B00203C0227000062902575 -:10259000ACB20010ACA00014ACA00024ACA0002889 -:1025A000ACA0002C8D7300382410FF80ACB3001851 -:1025B00090E4000D02048824322500FF10A00005DD -:1025C0008FBF002090EC000D3188007FA0E8000D47 -:1025D0008FBF00208FB3001C8FB200188FB1001482 -:1025E0008FB000103C0D10003C0A800027BD002871 -:1025F00003E00008AD4D01B8265F01002405FF800F -:1026000033F8007F3C06800003E578243C19800AFB -:1026100003192021ACCF0024908E00C400AE6824A2 -:1026200031AC00FF1180FFEAAF840028248E0078CF -:1026300095CD00123C0C08008D8C31A831AB3FFFCA -:1026400001924821000B5180012A402101052024DC -:10265000ACC400283107007F3C06800C00E6202136 -:102660009083000D00A31024304500FF10A0FFD878 -:10267000AF8400309098000D330F001015E0FFD5A7 -:102680008FBF00200E001863000000003C03800094 -:102690008C7901B80720FFFE00000000AE12000098 -:1026A0008C720144AE120004A6110008241100022D -:1026B000A211000BAE1300240A001FC68FBF00201A -:1026C0003C1260008E452C083C03F0033462FFFF8F -:1026D00000A2F824AE5F2C088E582C083C1901B0DB -:1026E00003199825AE532C080A001FC68FBF00207F -:1026F000264D010031AF007F3C10800A240EFF8080 -:1027000001F0282101AE60243C0B8000AD6C002458 -:102710001660FFAFAF85002824110003A0B100ECC4 -:102720000A001FC68FBF002026480100310A007F23 -:102730003C0B800A2409FF80014B30210109202431 -:102740003C078000ACE400240A001FC5AF860028C7 -:10275000944A001232083FFF314C3FFF1588FF8436 -:102760002419608290CF00C4240EFF8001CF48243A -:10277000312D00FF11A0FF7E00000000240700049F -:10278000A0C700EC8F870030241860842406000D59 -:10279000A4B80008A0A600050A001FB0241F00026C -:1027A0000800330C0800330C080033E8080033BC81 -:1027B000080033A0080032F0080032F0080032F0C0 -:1027C00008003314800801008008008080080000A1 -:1027D0005F865437E4AC62CC50103A4536621985B6 -:1027E000BF14C0E81BC27A1E84F4B556094EA6FE7B -:1027F0007DDA01E7C04D748108007A7408007AC060 -:1028000008007A80080079A808007A8008007AB069 -:1028100008007A80080079A8080079A8080079A83B -:10282000080079A8080079A8080079A8080079A804 -:10283000080079A8080079A8080079A808007AA0FB -:1028400008007A90080079A8080079A8080079A8FB -:10285000080079A8080079A8080079A8080079A8D4 -:10286000080079A8080079A8080079A8080079A8C4 -:10287000080079A808007A900800806C08007F148E -:102880000800803408007F140800800408007DFCE4 -:1028900008007F1408007F1408007F1408007F14CC -:1028A00008007F1408007F1408007F1408007F14BC -:1028B00008007F1408007F1408007F1408007F14AC -:0428C00008007F3C51 -:0C28C4000A0001220000000000000000DB -:1028D0000000000D747061352E302E306A33000018 -:1028E00005000001000000000000000000000000E2 -:1028F00000000000000000000000000000000000D8 -:1029000000000000000000000000000000000000C7 -:1029100000000000000000000000000000000000B7 -:1029200000000000000000000000000000000000A7 -:102930000000000000000000000000000000000097 -:102940000000000000000000000000000000000087 -:1029500010000003000000000000000D0000000D4A -:102960003C02080024421C203C03080024631FA0F2 -:10297000AC4000000043202B1480FFFD24420004E3 -:102980003C1D080037BD2FFC03A0F0213C100800BF -:10299000261004883C1C0800279C1C200E0002E224 -:1029A000000000000000000D2402FF8027BDFFE0B2 -:1029B00000821024AFB00010AF420020AFBF00185B -:1029C000AFB10014936500043084007F03441821E4 -:1029D0003C0200080062182130A50020036080211D -:1029E0003C080111277B000814A000022466005C4B -:1029F00024660058920200049743010492040004E4 -:102A00003047000F3063FFFF308400400067282309 -:102A100010800009000048219202000530420004A5 -:102A2000104000050000000010A00003000000009E -:102A300024A5FFFC24090004920200053042000492 -:102A4000104000120000000010A000100000000064 -:102A50009602000200A72021010440252442FFFE27 -:102A6000A7421016920300042402FF8000431024A2 -:102A7000304200FF104000033C0204000A000172D3 -:102A8000010240258CC20000AF4210188F4201782D -:102A90000440FFFE2402000AA74201409602000201 -:102AA00024040009304200070002102330420007CE -:102AB000A7420142960200022442FFFEA7420144BF -:102AC000A740014697420104A74201488F420108EE -:102AD0003042002050400001240400019202000412 -:102AE000304200101440000234830010008018218E -:102AF000A743014A000000000000000000000000A1 -:102B000000000000AF4810000000000000000000BE -:102B100000000000000000008F4210000441FFFE92 -:102B20003102FFFF10400007000000009202000485 -:102B30003042004014400003000000008F42101893 -:102B4000ACC20000960200063042FFFF24420002A1 -:102B50000002104300021040036288219622000008 -:102B60001120000D3044FFFF00A710218F83003893 -:102B70008F45101C000210820002108000431021BB -:102B8000AC45000030A6FFFF0E0002D100052C026C -:102B900000402021A6220000920300042402FF80AE -:102BA00000431024304200FF1040001F00000000CE -:102BB00092020005304200021040001B000000009D -:102BC0009742100C2442FFFEA7421016000000009E -:102BD0003C02040034420030AF421000000000000C -:102BE0000000000000000000000000008F42100004 -:102BF0000441FFFE000000009742100C8F45101C9E -:102C00003042FFFF24420030000210820002108098 -:102C1000005B1021AC45000030A6FFFF0E0002D182 -:102C200000052C02A622000096040002248400085D -:102C30000E0001E73084FFFF974401040E0001F508 -:102C40003084FFFF8FBF00188FB100148FB00010C9 -:102C50003C02100027BD002003E00008AF420178CD -:102C60003084FFFF308200078F850024104000026F -:102C7000248300073064FFF800A4102130421FFFB6 -:102C800003421821247B4000AF850028AF82002436 -:102C900003E00008AF4200843084FFFF3082000F61 -:102CA0008F85002C8F860034104000022483000F93 -:102CB0003064FFF000A410210046182BAF850030CF -:102CC0000046202314600002AF82002CAF84002C49 -:102CD0008F82002C340480000342182100641821E4 -:102CE000AF83003803E00008AF4200808F820014F9 -:102CF000104000088F8200048F82FFCC1440000532 -:102D00008F8200043C02FFBF3442FFFF0082202478 -:102D10008F82000430430006240200021062000F7C -:102D20003C0201012C620003504000052402000413 -:102D30001060000F3C0200010A00022E000000009B -:102D400010620005240200061462000C3C0201110E -:102D50000A000227008210253C0200110082102583 -:102D6000AF421000240200010A00022EAF82000CC4 -:102D700000821025AF421000AF80000C0000000060 -:102D8000000000000000000003E000080000000058 -:102D90008F82000C10400004000000008F421000E1 -:102DA0000441FFFE0000000003E0000800000000F6 -:102DB0008F8200102443F800000229C224A2FFF0F1 -:102DC0002C63030110600003000210420A00025548 -:102DD000AC8200008F83001800A3102B1440000B5E -:102DE0000000382100A31023244600018F82001C1C -:102DF000006210212442FFFF0045102B54400004C4 -:102E00002402FFFF0A000255AC8600002402FFFFE7 -:102E10000A00025AAC8200008C8200003C030800C9 -:102E200024631C5C000211400043382103E00008C9 -:102E300000E010213C0908008D291D80000451404C -:102E40003C19080027391C5C00C0782100806021F3 -:102E5000240EFFFF000038210159402111200036C7 -:102E6000000030213C18080027181D983C0D080070 -:102E700025AD1D9C000F582B000611800046102127 -:102E8000000218C0007810218C420000158200203A -:102E9000006D20218CA20000544000098D02001812 -:102EA0003C0208008C421D8424420001AC820000D8 -:102EB0003C010800AC221D840A0002CF0000202142 -:102EC0008F47002000003021000211C01160004A2D -:102ED000AF4200208D08001C3C0900088CA30000B4 -:102EE0000066182100031880007A10210049102183 -:102EF0008C44000024C600010068182100CF102B6C -:102F00001440FFF6AC6400000A0002CD000000008F -:102F10008C840000008E102B5040000424C6000159 -:102F20000080702100C0382124C6000100C9102B88 -:102F30001440FFD20006118024020001ACA2000060 -:102F40003C0208008C421D7C3C0308008C631D8001 -:102F50000043102B1440002A2404FFFE01591021C5 -:102F60008C420018104000262404FFFF0007218037 -:102F70003C0508008CA51D84008720218D060018C3 -:102F8000000420C03C02080024421D980082102149 -:102F90003C03080024631D9CAC4C000024A50001E8 -:102FA000008318213C02080024421DA0AC650000EB -:102FB000000631C03C010800AC251D8400822021A0 -:102FC0008F470020AD04001CAF46002011E0000A2E -:102FD000000030213C020008034228218CA200009E -:102FE00024C6000100CF182BAC82000024A50004E9 -:102FF0001460FFFA24840004AF4700200000202161 -:1030000003E00008008010213084FFFF30C6FFFF7E -:1030100000052C0000A628253882FFFF004510215E -:103020000045282B0045102100021C023042FFFF02 -:103030000043102100021C023042FFFF0043102118 -:103040003842FFFF03E000083042FFFF27BDFFC802 -:10305000AFBF0030AFB3002CAFB20028AFB1002437 -:10306000AFB000203C0460088C8250002403FF7F36 -:103070003C066000004310243442380CAC825000FF -:103080008CC24C1C3C1A8000000216023042000F19 -:1030900010400007AF82001C8CC34C1C3C02001F78 -:1030A0003442FC0000621824000319C2AF830018E8 -:1030B0008F420008275B400034420001AF42000805 -:1030C000AF8000243C02601CAF400080AF40008411 -:1030D0008C4500088CC3080834028000034220217C -:1030E0002402FFF0006218243C0200803C0108002A -:1030F000AC2204203C025709AF840038146200045B -:10310000AF850034240200010A000314AF820014CA -:10311000AF8000142403003D240200043C01080099 -:10312000AC221D943C010800AC231D903C0108001A -:10313000AC231D8C3C010800AC231D883C13080007 -:1031400026731C5C240400043C02080024421C7406 -:10315000240300082463FFFFAC400004AC400000DF -:103160000461FFFC24420020000410C00044102130 -:103170002442003D3C010800AC221D9024020001C5 -:103180003C010800AC221D7C2402FFFF3C0108002A -:10319000AC221D983C010800AC201D848F42000029 -:1031A00038420001304200011440FFFC8F820014BD -:1031B0001040001600000000974201041040000576 -:1031C0008F830000146000072462FFFF0A00034B96 -:1031D0002C62000A2C620010504000048F83000013 -:1031E00024620001AF8200008F8300002C62000A7D -:1031F000144000032C6200070A000352AF80FFCC8A -:103200001040000224020001AF82FFCC8F4301086E -:103210008F44010030622000AF830004104000089A -:10322000AF8400103C0208008C42042C24420001B0 -:103230003C010800AC22042C0A0006D73C024000E6 -:103240003065020014A0000324020F001482030959 -:1032500024020D0097420104104003713C0240001B -:1032600030624000144000AD8F8200388C4400086A -:103270008F4201780440FFFE24020800AF4201782B -:1032800024020008A7420140A740014297420104DE -:103290008F8400043051FFFF30820001104000078E -:1032A000022080212623FFFE240200023070FFFF4F -:1032B000A74201460A00037FA7430148A7400146F1 -:1032C0003C0208008C42043C1440000D8F83001027 -:1032D000308200201440000224030009240300016E -:1032E000006020218F830010240209005062000139 -:1032F00034840004A744014A0A00039A0000000035 -:1033000024020F00146200053082002014400006E1 -:103310002403000D0A000399240300051440000251 -:103320002403000924030001A743014A3C020800CA -:103330008C4204203C0400480E00020A0044202570 -:103340000E000233000000008F82000C1040003E8F -:10335000000000008F4210003C03002000431024B6 -:10336000104000398F8200043042000210400036C5 -:1033700000000000974210141440003300000000C9 -:10338000974210088F8800383042FFFF2442000621 -:10339000000218820003388000E830213043000129 -:1033A0008CC4000010600004304200030000000DD7 -:1033B0000A0003DB00E81021544000103084FFFFB6 -:1033C0003C05FFFF00852024008518260003182BEC -:1033D0000004102B004310241040000500000000E2 -:1033E000000000000000000D000000002400021C8E -:1033F0008CC200000A0003DA004520253883FFFF55 -:103400000003182B0004102B00431024104000056B -:1034100000000000000000000000000D000000009F -:10342000240002258CC200003444FFFF00E8102174 -:10343000AC4400003C0208008C42043024420001ED -:103440003C010800AC2204308F6200008F840038F9 -:10345000AF8200088C8300003402FFFF1462000F6B -:10346000000010213C0508008CA504543C04080011 -:103470008C84045000B0282100B0302B0082202121 -:10348000008620213C010800AC2504543C010800C2 -:10349000AC2404500A0006CD240400088C820000ED -:1034A000304201001040000F000010213C050800D0 -:1034B0008CA5044C3C0408008C84044800B02821EE -:1034C00000B0302B00822021008620213C01080022 -:1034D000AC25044C3C010800AC2404480A0006CD8D -:1034E000240400083C0508008CA504443C040800A2 -:1034F0008C84044000B0282100B0302B00822021B1 -:10350000008620213C010800AC2504443C01080051 -:10351000AC2404400A0006CD240400088F62000891 -:103520008F62000000021602304300F024020030D7 -:1035300010620005240200401062016B8F8200209F -:103540000A0006D52442000114A000050000000076 -:10355000000000000000000D0000000024000250E8 -:103560008F4201780440FFFE000000000E00023B85 -:1035700027A4001014400005004080210000000036 -:103580000000000D00000000240002578E02000021 -:103590001040000500000000000000000000000DC9 -:1035A000000000002400025A8F62000C0443000354 -:1035B000240200010A00055DAE000000AE0200001A -:1035C0008F8200388C450008A20000078F65000C30 -:1035D0008F64000430A3FFFF000424020085202331 -:1035E000308200FF0043102124420005000288833E -:1035F0002E220081A605000A14400005A204000442 -:10360000000000000000000D000000002400027215 -:103610003C0708008CE71D808FA800102409FFFFDD -:103620000000502110E00013000030213C0C080085 -:10363000258C1D9C01802821000018218CA2FFFCF4 -:103640005102002F006C18218CA400002463020892 -:103650000089102B1040000324A502080080482197 -:1036600000C0502124C6000100C7102B5440FFF4B5 -:103670008CA2FFFC3C0508008CA51D803C020800C4 -:103680008C421D7C3C09080025291C603C03080075 -:1036900024631D9800A2102B3C0C0800258C1D9C57 -:1036A0003C0408008C841D843C0B0800256B1DA085 -:1036B0001040001A0008314000051180004510211B -:1036C000000210C000C9382124840001004B3021C1 -:1036D0000043182124A50001004C1021AC68000013 -:1036E000ACE600183C010800AC241D84AC4400008A -:1036F0003C010800AC251D800A0004A88E04001CB3 -:103700003C0208008C421D84244200013C01080058 -:10371000AC221D840A0004A7AC620000000A1180DC -:10372000004A1021000210C0004328218CA3000091 -:10373000004C3821248400010003194000C93021C5 -:1037400000691821004B1021ACA80000AC600018E3 -:103750003C010800AC241D84ACC20018ACE400009D -:103760008E04001C8F8500380E0006E702203021F1 -:103770008F6200048F430108A60200083C0210007B -:103780000062182410600008000000009742010445 -:10379000920300072442FFEC346300023045FFFF30 -:1037A0000A0004BCA2030007974201042442FFF070 -:1037B0003045FFFF960600082CC200135440000558 -:1037C000920300079202000734420001A2020007A0 -:1037D0009203000724020001106200052402000386 -:1037E0001062000B30C7FFFF0A0004DB24E2000276 -:1037F0008F8200383C04FFFF8C43000C00641824C7 -:1038000000651825AC43000C0A0004DA30C7FFFF3E -:103810008F8200383C04FFFF8C43001000641824A2 -:1038200000651825AC43001030C7FFFF24E20002FA -:1038300000021083A20200058F830038304200FF8F -:1038400000021080004330218CC500008CC20000B3 -:1038500024030004000217021443001300000000B8 -:10386000974201043C03FFFF00A318243042FFFFEE -:10387000004710232442FFFE00622825ACC500004B -:10388000920400058E03001C308200FF00021080AD -:1038900000431021904200003042000F00441021EC -:1038A0000A000510A20200068CC40004974201041D -:1038B0009603000A3085FFFF3042FFFF00471023C8 -:1038C0002442FFD60002140000A22825ACC5000443 -:1038D0009202000792040005246300280003188365 -:1038E0000064182134420004A2030006A20200076B -:1038F0008F8200042403FFFB3442000200431024A3 -:10390000AF820004920300068E07001C8F860038E9 -:1039100000031880006710218C44000C3C02FFF665 -:103920003442FFFF0082282400661821AE04000CF8 -:10393000AC65000C920300068E04000C3C02FF7F75 -:103940003442FFFF0003188000A2282400822024B4 -:1039500000671821AE04000CAC65000C9202000652 -:10396000000210800047102194450012AC45001061 -:10397000920200060002108000461021AC450010A3 -:103980008FA200109203000500021140000318806E -:1039900000671821005320218C6200048C830018DA -:1039A0001460000EAE0200143C0308008C631D8CF2 -:1039B000AC8300183C0208008C421D900062102B62 -:1039C00010400019000000003C0208008C421D94C9 -:1039D000006210213C010800AC221D8C8E020018F0 -:1039E0008F48002000003021000211C01220000B7F -:1039F000AF4200203C0200080342282100E02021C1 -:103A00008C82000024C6000100D1182BACA200005B -:103A1000248400041460FFFA24A50004AF480020A9 -:103A20000A00055E24020010000000000000000DE6 -:103A300000000000240002D424020010A74201402C -:103A400024020002A7400142A7400144A7420146C8 -:103A5000974201043C0400082442FFFEA7420148AB -:103A6000240200010E00020AA742014A9603000A3E -:103A70009202000400431021244200023042000759 -:103A800000021023304200070E000233AE02001085 -:103A90008F6200003C0308008C630444240400107F -:103AA000AF820008974201043042FFFF2442FFFE2C -:103AB00000403821000237C33C0208008C42044019 -:103AC000006718210067282B0046102100451021AF -:103AD0003C010800AC2304443C010800AC22044033 -:103AE0000A0006620000000014A0000500000000AB -:103AF000000000000000000D00000000240003048E -:103B00008F4201780440FFFE000000000E00023BDF -:103B100027A400141440000500408021000000008C -:103B20000000000D000000002400030B92060004BA -:103B30008FA4001427A50018000630820E00025C36 -:103B4000AFA00018504000068E02000000000000E8 -:103B50000000000D00000000240003118E02000090 -:103B60005440000692020007000000000000000D13 -:103B700000000000240003169202000730420004F7 -:103B8000104000058F8200042403FFFB3442000232 -:103B900000431024AF8200048F6200040443000934 -:103BA00092020007920200068E03001C8E04000C95 -:103BB0000002108000431021AC44000CAE00000055 -:103BC00092020007304200045440000B92030004AC -:103BD000920300058E0400148E05001C000318805B -:103BE0003C0200010082202100651821AE0400146F -:103BF000AC640004920300049602000A00621021E3 -:103C000024420005000290838FA200181040000D8E -:103C1000277100088FA40014000310820242302391 -:103C200027A500180E00025CAFA200185040000645 -:103C30008E05001C000000000000000D00000000C8 -:103C40002400033F8E05001C022020210E0006E701 -:103C500002403021920400068F6500043C027FFF81 -:103C600000042080009120218C8300043442FFFF57 -:103C700000A2282400651821AC83000492020007EA -:103C80009203000492050005304200041040001425 -:103C90009607000830A500FF0005288000B1282104 -:103CA0008CA40004974201049606000A306300FFCA -:103CB0003042FFFF004310210046102130E3FFFF98 -:103CC000004310232442FFD83084FFFF0002140079 -:103CD00000822025ACA400040A0006169203000707 -:103CE00030A500FF0005288000B128218CA4000029 -:103CF00097420104306300FF3042FFFF0043102170 -:103D0000004710233C03FFFF008320243042FFFFC5 -:103D100000822025ACA400009203000724020001C9 -:103D2000106200060000000024020003106200116F -:103D3000000000000A0006398E03001097420104BB -:103D4000920300049605000A8E24000C0043102103 -:103D5000004510212442FFF23C03FFFF0083202492 -:103D60003042FFFF00822025AE24000C0A000639F5 -:103D70008E03001097420104920300049605000A86 -:103D80008E24001000431021004510212442FFEE34 -:103D90003C03FFFF008320243042FFFF00822025E8 -:103DA000AE2400108E0300102402000AA742014036 -:103DB000A74301429603000A920200043C0400401B -:103DC00000431021A7420144A74001469742010445 -:103DD000A7420148240200010E00020AA742014A3C -:103DE0000E000233000000008F6200009203000406 -:103DF00000002021AF820008974201049606000AC5 -:103E00003042FFFF00621821006028213C030800B7 -:103E10008C6304443C0208008C4204400065182175 -:103E2000004410210065382B004710213C01080098 -:103E3000AC2304443C010800AC220440920400047A -:103E4000008620212484000A3084FFFF0E0001E751 -:103E500000000000974401043084FFFF0E0001F5CC -:103E6000000000003C021000AF4201780A0006D4B6 -:103E70008F820020148200273062000697420104DE -:103E8000104000673C0240003062400010400005D6 -:103E900000000000000000000000000D0000000015 -:103EA0002400041A8F4201780440FFFE2402080017 -:103EB000AF42017824020008A7420140A740014216 -:103EC0008F82000497430104304200011040000734 -:103ED0003070FFFF2603FFFE24020002A7420146C6 -:103EE000A74301480A00068C2402000DA7400146A2 -:103EF0002402000DA742014A8F620000240400083A -:103F0000AF8200080E0001E7000000000A0006660C -:103F100002002021104000423C0240009362000059 -:103F2000304300F0240200101062000524020070EB -:103F3000106200358F8200200A0006D5244200015D -:103F40008F620000974301043050FFFF3071FFFF84 -:103F50008F4201780440FFFE320200070002102366 -:103F6000304200072403000A2604FFFEA743014055 -:103F7000A7420142A7440144A7400146A751014876 -:103F80008F4201083042002014400002240300093F -:103F900024030001A743014A0E00020A3C0400402A -:103FA0000E000233000000003C0708008CE70444C8 -:103FB000021110212442FFFE3C0608008CC604407A -:103FC0000040182100E33821000010218F65000017 -:103FD00000E3402B00C230212604000800C8302135 -:103FE0003084FFFFAF8500083C010800AC27044483 -:103FF0003C010800AC2604400E0001E70000000070 -:104000000A000666022020210E000139000000008F -:104010008F82002024420001AF8200203C02400039 -:10402000AF4201380A000336000000003084FFFF71 -:1040300030A5FFFF000018211080000700000000DD -:104040003082000110400002000420420065182167 -:104050000A0006DD0005284003E00008006010218A -:1040600010C0000624C6FFFF8CA2000024A5000497 -:10407000AC8200000A0006E72484000403E0000884 -:104080000000000010A0000824A3FFFFAC86000081 -:1040900000000000000000002402FFFF2463FFFF77 -:1040A0001462FFFA2484000403E00008000000000A -:0440B000000000010B -:0C40B4000A00002A0000000000000000CC -:1040C0000000000D747870352E302E306A330000F9 -:1040D000050000000000000A000001360000EA6050 -:1040E00000000000000000000000000000000000D0 -:1040F00000000000000000000000000000000000C0 -:1041000000000000000000000000000000000000AF -:104110000000000000000016000000000000000089 -:10412000000000000000000000000000000000008F -:10413000000000000000000000000000000000007F -:1041400000000000000000000000000000001388D4 -:1041500000000000000005DC00000000000000007E -:1041600010000003000000000000000D0000000D22 -:104170003C020800244238603C03080024633B14DE -:10418000AC4000000043202B1480FFFD24420004BB -:104190003C1D080037BD7FFC03A0F0213C10080047 -:1041A000261000A83C1C0800279C38600E0004075D -:1041B000000000000000000D8F86003C3C039000D2 -:1041C0003C0280000086282500A32025AC44002066 -:1041D0003C0380008C67002004E0FFFE000000002C -:1041E00003E00008000000000A0000412404000170 -:1041F0008F85003C3C0480003483000100A310251F -:1042000003E00008AC82002003E000080000102159 -:104210003084FFFF30A5FFFF108000070000182149 -:104220003082000110400002000420420065182185 -:104230001480FFFB0005284003E000080060102107 -:1042400010C00007000000008CA2000024C6FFFF81 -:1042500024A50004AC82000014C0FFFB24840004E9 -:1042600003E000080000000010A0000824A3FFFFE6 -:10427000AC86000000000000000000002402FFFFE8 -:104280002463FFFF1462FFFA2484000403E00008A3 -:104290000000000090AA00318FAB00108CAC0040F1 -:1042A0003C0300FF8D680004AD6C00208CAD004421 -:1042B00000E060213462FFFFAD6D00248CA7004850 -:1042C0003C09FF000109C024AD6700288CAE004CFA -:1042D0000182C82403197825AD6F0004AD6E002C4F -:1042E0008CAD0038314A00FFAD6D001C94A900323E -:1042F0003128FFFFAD68001090A70030A5600002D4 -:10430000A1600004A167000090A30032306200FFAA -:104310000002198210600005240500011065000EDE -:104320000000000003E00008A16A00018CD800280A -:10433000354A0080AD7800188CCF0014AD6F0014A2 -:104340008CCE0030AD6E00088CC4002CA16A000138 -:1043500003E00008AD64000C8CCD001CAD6D0018AE -:104360008CC90014AD6900148CC80024AD68000825 -:104370008CC70020AD67000C8CC200148C830070C9 -:104380000043C82B13200007000000008CC200145B -:10439000144CFFE400000000354A008003E00008F0 -:1043A000A16A00018C8200700A0000B700000000C2 -:1043B0009089003027BDFFF88FA8001CA3A900003A -:1043C0008FA300003C0DFF8035A2FFFF8CAC002CBA -:1043D00000625824AFAB0000A100000400C05821C7 -:1043E000A7A000028D06000400A048210167C82193 -:1043F0008FA50000008050213C18FF7F032C202651 -:104400003C0E00FF2C8C0001370FFFFF35CDFFFF66 -:104410003C02FF0000AFC82400EDC02400C2782495 -:10442000000C1DC00323682501F87025AD0D0000A8 -:10443000AD0E00048D240024AFAD0000AD040008D3 -:104440008D2C00202404FFFFAD0C000C954700329A -:1044500030E6FFFFAD0600109145004830A200FF96 -:10446000000219C2506000018D240034AD04001414 -:104470008D4700388FAA001827BD0008AD0B002813 -:10448000AD0A0024AD07001CAD00002CAD000018E3 -:1044900003E00008AD00002027BDFFE0AFB2001828 -:1044A000AFB10014AFB00010AFBF001C9098003047 -:1044B00000C088213C0D00FF330F007FA0CF00001B -:1044C000908E003135ACFFFF3C0AFF00A0CE00010A -:1044D00094A6001EA22000048CAB00148E290004B8 -:1044E00000A08021016C2824012A40240080902112 -:1044F00001052025A6260002AE2400042605002082 -:10450000262400080E0000632406000292470030B3 -:10451000260500282624001400071E0000031603A9 -:1045200024060004044000032403FFFF96590032D0 -:104530003323FFFF0E000063AE2300102624002467 -:104540008FBF001C8FB200188FB100148FB0001005 -:1045500024050003000030210A00006D27BD002063 -:1045600027BDFFD8AFB1001CAFB00018AFBF00200F -:1045700090A900302402000100E050213123003FC7 -:1045800000A040218FB000400080882100C0482159 -:10459000106200148FA70038240B000500A0202112 -:1045A00000C02821106B0013020030210E0000F91A -:1045B000000000009225007C30A40002108000035F -:1045C00026030030AE000030260300348FBF0020E9 -:1045D0008FB1001C8FB000180060102103E00008AC -:1045E00027BD00280E000078AFB000100A0001407F -:1045F000000000008FA3003C0100202101202821A1 -:1046000001403021AFA300100E0000BFAFB0001476 -:104610000A000140000000003C0580008CA30E1041 -:104620008F840044AC8300208CA20E1803E00008A5 -:10463000AC8200243C0580008CA30E148F840044BF -:10464000AC8300208CA20E1C03E00008AC82002486 -:104650009382000C1040001B2483000F2404FFF001 -:104660000064382410E00019978B00109784000E26 -:104670009389000D3C0A601C0A00017B0164402301 -:1046800001037021006428231126000231C2FFFFBC -:1046900030A2FFFF0047302B50C0000E00E448213D -:1046A0008D4D000C31A3FFFF00036400000C2C03B0 -:1046B00004A1FFF30000302130637FFF0A00017383 -:1046C0002406000103E00008000000009784000EAB -:1046D00000E448213123FFFF3168FFFF0068382BD9 -:1046E00054E0FFF8A783000E938A000D11400005E7 -:1046F000240F0001006BC023A380000D03E000081D -:10470000A798000E006BC023A38F000D03E00008E4 -:10471000A798000E03E000080000000027BDFFE896 -:10472000AFB000103084FFFF3C10800093A8002B36 -:10473000AFBF0014A6040144960A0E1630C600FF4F -:104740008FA90030A60A0146AE050148A206015213 -:10475000A608015AAE0701608FA3002CA6090158D4 -:10476000012020210E000167AE0301543C0210001D -:10477000AE0201788FBF00148FB0001003E0000874 -:1047800027BD00188F8500002484000727BDFFF88F -:104790003084FFF83C06800094CB008A316AFFFF2A -:1047A000AFAA00008FA90000012540232507FFFFC5 -:1047B00030E31FFF0064102B1440FFF700056882F0 -:1047C000000D288034CC400000AC102103E000082C -:1047D00027BD00088F8200002486000730C5FFF83F -:1047E00000A2182130641FFF03E00008AF8400001E -:1047F0008F8500448F8A003C27BDFFB03C048000B9 -:10480000AFB70044AFB40038AFB1002CAFBF004821 -:10481000AFB60040AFB5003CAFB30034AFB200302C -:10482000AFB000288C8701048CA90024AC8A0080DA -:104830008CA8002000E988230000B821AC880E1065 -:104840008CA600240000A021AC860E188C820E10CD -:10485000AC820E148C830E18AC830E1C122000FB4D -:104860003C168000936B0008116000F1000000000E -:10487000976E001031CDFFFF022D602B158000ECEC -:104880000000000097700010320FFFFFAECF0E0047 -:104890003C0580008CB30000327200081240FFFD1E -:1048A0000000000094B50E088CA70E0432A5FFFF8F -:1048B00030B40001128000E1000000000000000D93 -:1048C00030B9A040241800401338011730B4A000BC -:1048D000128000DC000000009373000812600008E2 -:1048E00000000000976900103122FFFF00E2202B3A -:1048F0001080000330A6004010C000D2000000006D -:10490000A7850040AF870038936A0008022038214D -:10491000AFB10020154000F127B40020AF60000CBB -:104920009785004030B14000162000022403001695 -:104930002403000E24154007A363000AAF7500147A -:10494000939000428F6F0014321900010019C24089 -:1049500001F84025AF680014978700408F6300146A -:1049600030EE0010006E6825AF6D0014978C00408B -:10497000318B000811600165000000008F65001494 -:104980003C0B10003C0A800000AB8825AF7100147E -:1049900095460E0A3C0981002413000E30C2FFFF29 -:1049A00000492025AF640004A3730002937F000A2E -:1049B0003406FFFC27F20004A372000A978D004022 -:1049C00031AC200011800157000000003C0780003E -:1049D000978D004094EC0E0C97910040000D5842CA -:1049E0003185C000316A000300051303322910002D -:1049F00001429825000922030264F825001F90C097 -:104A0000A7720012979500409379000A00158182E1 -:104A10003218003C0319782125E8003CA3680009FE -:104A200094EE0E0C31C33FFFA76300109763001292 -:104A30009367000900E3702125CD000231AC000727 -:104A4000000C582331650007A365000B9371000922 -:104A500097640012976A0010322200FF8F9100388D -:104A6000979F004000444821012A98210266902126 -:104A700033F5004012A000053246FFFF00D1402B65 -:104A80003C12800011000016000098210226782BAD -:104A900015E001368FA700203C1880008F100E14FF -:104AA0003C058000AF100E108F190E1CAF190E18A8 -:104AB000AF060E008CB200003255000812A0FFFDB8 -:104AC0000000000094BF0E0800C088210000902163 -:104AD000A79F00408CA60E0424130001AF86003867 -:104AE000976900103135FFFF8E8C00000191202363 -:104AF00010800118AE8400009367000814E000D80D -:104B0000000000000E0001B4240400108F8E004845 -:104B10003C0332000040282131C600FF00063C0063 -:104B200000E3602525CD0001AF8D0048AC4C0000AE -:104B30009362000997640012937F000A304A00FFD5 -:104B4000308BFFFF014B48210009CC0033F000FF00 -:104B50000330C025ACB800048F8F00489788004010 -:104B60003103200010600103ACAF0008976F001202 -:104B700031E8FFFF06400101ACA8000C979000400F -:104B80003205000814A0000226280006262800028C -:104B90003C048000948B0E148C850E1C8F670004DF -:104BA000936A00023164FFFF314900FFAFA9001092 -:104BB0008F7F0014AFA80018AFBF00140E00019A39 -:104BC00000000000240400100E0001C800000000D6 -:104BD0008E92000016400005000000008F7900143E -:104BE0002405FFBF0325A024AF7400148F69000CB7 -:104BF0000135F821AF7F000C9375000816A000085E -:104C00000000000012600006000000008F6B00141E -:104C10003C0CEFFF3584FFFE01645024AF6A0014A2 -:104C2000A37300088FA700200A000316022020218A -:104C3000AED10E000A0001F83C05800014E0FF210F -:104C400030B9A0400E0001600000A0212E910001AB -:104C50000237B02512C000178FBF00488F85003C77 -:104C600024170F0010B700CD3C0480008C99017808 -:104C70000720FFFE24150F0050B500EB3C04800018 -:104C80008C890E14240502403C141000AC890144A8 -:104C90008C9F0E1CAC9F0148A0800152A480015A39 -:104CA000AC800160A4800158AC850154AC940178BB -:104CB0008FBF00488FB700448FB600408FB5003CCF -:104CC0008FB400388FB300348FB200308FB1002C16 -:104CD0008FB0002803E0000827BD00508F910038F6 -:104CE000979300403C1280000220A821326A0040C5 -:104CF0001540FF7D00009821976B00108F850038CC -:104D00003162FFFF104500A2000020210080A02199 -:104D1000108000E500E088211620FED2000000008F -:104D20000A0002E72E9100013C0380008C7F01788D -:104D300007E0FFFE240408008F860000AC640178C1 -:104D40003C038000946C008A318BFFFF0166502386 -:104D50002549FFFF31281FFF2D0200081440FFF9ED -:104D6000000000008F8E0048346F40008F83003CAD -:104D700000E0A021240D0F0025C70001AF870048E7 -:104D800000CF3021023488233C08800031D500FF59 -:104D9000106D000524070001939300423272000158 -:104DA0000012824036070001001514003C09010082 -:104DB00000492025ACC400008F9F004830B9003660 -:104DC00030B80008ACDF00041300009000F998250B -:104DD00095070E0A8F8E00003C03810030EDFFFF27 -:104DE00025CB000801A328253C0C1000316A1FFFC9 -:104DF000269200062406000EAD050160026C98257F -:104E0000A506015AAF8A0000A51201581620000815 -:104E10003C1080008F99003C24180F00533800028A -:104E200024170001367300400E0001593C10800029 -:104E30008E1F0E1402402021AE1F01448E120E1C44 -:104E4000AE120148A2150152AE1301540E000167C3 -:104E50003C151000AE1501780A000319000000008F -:104E600093780009976300129368000B330F00FFDB -:104E700001E33821310200FF00E2702125D0000A51 -:104E80003210FFFF0E0001B4020020218F8600487F -:104E90003C1941003C07800024CD0001AF8D004843 -:104EA000936C00099764001230C600FF318A00FF3E -:104EB000308BFFFF014B482100062C00253F0002EC -:104EC00000BFC02503197825AC4F00008F68000C87 -:104ED00094EE0E1401121825AC4300048CE50E1C50 -:104EE0008F670004936D000231C4FFFF31AC00FFF7 -:104EF000AFAC00108F620014AFB100180E00019A21 -:104F0000AFA200140A0002C502002021AF60000415 -:104F1000A3600002978D004031AC20001580FEABED -:104F200000003021A7600012979000409378000A9B -:104F30003C03800032191F000019798301F84021D9 -:104F400025070028A3670009946E0E0C0A00025E74 -:104F5000A76E00108F6E001435CD00400E00015971 -:104F6000AF6D00140A000291000000000A00031651 -:104F7000000020210641FF01ACA0000C8CB8000C01 -:104F80003C198000031990250A0002B2ACB2000C53 -:104F9000000090210A00028D2413000112800005F8 -:104FA0003C0D800095A60E0830D3004012600042F0 -:104FB000000000008C9001780600FFFE0000000059 -:104FC00094920E103C030500240720003258FFFF86 -:104FD00003037825AC8F014C8C880E143C0E100016 -:104FE000AC8801448C820E1CAC820148A080015226 -:104FF000A480015AAC800160A4800158AC870154A0 -:10500000AC8E01780A0002EE3C0480008F90000014 -:1050100026920002A5120158260F000831E81FFF52 -:105020000A000356AF880000AC80014C12800019C2 -:10503000000000008C8A0E10AC8A01448C830E188C -:105040003C0C800024160040AC8301488FBF004810 -:10505000A18001528FB70044A580015A8FB5003C52 -:10506000AD8001608FB40038A58001588FB3003443 -:10507000AD9601548FB200308FB600408FB1002C36 -:105080008FB000283C04100027BD005003E000084A -:10509000AD8401788C8B0E14AC8B01448C830E1C78 -:1050A0000A0003E43C0C80000E0001602E91000118 -:1050B0000A0002E80237B025000000000000000DE1 -:1050C000000000002400033A0A0003C03C048000F2 -:1050D00027BDFFE0AFBF001C3C1F20FF3C07600066 -:1050E0003C0980002402001037F9FFFDACE23008D3 -:1050F000AFB20018AFB10014AFB00010AD390E0060 -:10510000000000000000000000000000000000009F -:10511000000000003C1800FF3712FFFDAD320E000A -:105120003C0B60048D7050002411FF7F3C0E000288 -:105130000211782435EC380C35CD0109ACED4C1852 -:10514000240A0009AD6C50008CE80438AD2A000830 -:10515000AD2000148CE54C1C3106FFFF38C42F71C4 -:1051600000051E023062000F2486C0B31040000705 -:10517000AF8200088CE54C1C3C09001F3528FC0060 -:1051800000A81824000321C2AF8400048CF1080891 -:105190003C0F57092412F0000232702435F0001041 -:1051A00001D0602601CF68262DAA00012D8B0001B9 -:1051B000014B382550E00009A380000C3C02601C24 -:1051C0008C590008241F0001A39F000C33387C0079 -:1051D000A7980010A780000EA380000DAF800048A4 -:1051E00014C00003AF8000003C066000ACC0442C3B -:1051F0000E0004B63C1080000E000DDF0000000021 -:105200003C110800263138C83C12080026523948A3 -:105210008E05000038A30001306400011480FFFCFB -:10522000000000008E0601003C0C800A240AFF806A -:1052300024C7024030EB007F016C482100EA402483 -:10524000AE060020AF890044AE0800243C03800075 -:10525000AF86003C8C6D017805A0FFFE2419080084 -:10526000AC79017890780108A3980042938F0042AE -:1052700031EE000111C0000F240D0D0024C2F80012 -:105280002C5F030113E0001C000629C224A3FFF0D9 -:1052900000032042000431400E0001CF00D1D8218C -:1052A0003C0440003C068000ACC401380A000457AE -:1052B0000000000010CD0026240E0F0010CE002AA2 -:1052C0003C028008345F008093F90000240F0050F6 -:1052D000333800FF170FFFF33C0440000E000912A3 -:1052E000000000003C0440003C068000ACC40138D3 -:1052F0000A000457000000008F83000400A3402B25 -:105300001500000B8F8B0008006B50212547FFFF15 -:1053100000E5482B1520000600A36023000C29405F -:105320000E0001CF00B2D8210A00047C3C044000EA -:10533000000000000000000D00000000240003AD8C -:105340000E0001CF000000000A00047C3C04400075 -:105350003C1B0800277B3A480E0001CF00000000EC -:105360000A00047C3C0440003C1B0800277B3A6890 -:105370000E0001CF000000000A00047C3C04400045 -:10538000000411C003E00008244202403C0408006D -:1053900024843AAC2405001A0A00006D0000302174 -:1053A00027BDFFE0AFBF001CAFB20018AFB10014C3 -:1053B000AFB000103C108000920B01092412FF8056 -:1053C0000E0004B33164007F8F91003C00515021E6 -:1053D00001524024AE080024920301090E0004B3D8 -:1053E0003064007F24060080240700C024040040AD -:1053F000AE000810AE040814AE060818AE07081C6C -:10540000920C01090051F82133F8007F3C19800A01 -:10541000031910213184007F0E0004B3AF820044D1 -:105420008E1101003C0C008035850001022278219C -:1054300001F24824AE0908048E0E010035980002DE -:105440003609090001C2682131AB00780165502599 -:10545000AE0A08208E0501008E080100360509807D -:10546000010218212464004000923024AE0608088E -:105470008E07010000E2F82127F90040333200785E -:1054800002588825AE1108248E040100952F000CC7 -:105490008FBF001C8FB2001831EEFFFF000E69C0F5 -:1054A000AE0D0800AE0C0828952B000C8FB100142F -:1054B000316AFFFF000A41C0AE08002C8CA30050E7 -:1054C0008FB000108CA2003C8D2400048CA6001C20 -:1054D0008CA7003827BD0020AF830060AF8200504A -:1054E000AF84004CAF86005803E00008AF87005C33 -:1054F0003C0A0800914A3AD13C09080095293ACA69 -:105500003C051100000A3C002528000200E8302577 -:1055100000C5182524820008AC83000003E00008C1 -:10552000AC8000043C098000352809009107001177 -:10553000240200280080502130E300FF00A06821F1 -:1055400000C0602110620002340B86DD240B0800CD -:105550003C07800034E20A9A9443000034F80A9C25 -:1055600034E60AA03079FFFFAD5900008F0F00002C -:1055700034E80A8024040001AD4F00048CCE000002 -:10558000AD4E00089105001930A3000310640046D9 -:1055900028690002152000B5240400021064009060 -:1055A000240500031065009B34E40AA43C090800AC -:1055B00095293AC024070800516700503C18800024 -:1055C0003C0280003459090093280012932E0019E0 -:1055D00034580980310F00FF8F06002801EC182194 -:1055E000000338803124FFFF31CB00FF00E410219D -:1055F000000B2D0000A6C02500027C003C086000C6 -:105600000308182535E906FFAD430000AD49000445 -:105610008F2E002C3C0380003478093CAD4E0008EE -:105620008F27003025490028346E0900AD47000C53 -:105630008F2B0034AD4B00108F240038AD44001484 -:105640008F25001CAD4500188F220020AD42001CA4 -:105650008F26002425220014AD4600208F28002824 -:10566000AD4800248F0F0000AD2D0004AD2F0000C9 -:105670008C64010CAD24000891C700123C050800A1 -:1056800090A53AD0AD20001030EB00FF016C302126 -:1056900000066F000005CC0001B96025358AFFFFC8 -:1056A00003E00008AD2A000C3C09080095293AC027 -:1056B0003C19080097393ACA34E20AA43C060800AB -:1056C00094C63ABC944F00003123FFFF0323C0214E -:1056D00003067023000F3C0025C8FFF200E82825D0 -:1056E00024070800AD45000CAD400010AD4B001480 -:1056F0001567FFB3254A00183C18800037080900D9 -:10570000910F00119107001937030A8031EE00FF55 -:105710003C19080097393AC6946F002A000E588247 -:1057200030E400FF97870054000B160000042C00A3 -:105730003126FFFF0326C02100454825013870258A -:1057400001E758213C03400001C32025000B2C0039 -:10575000AD440000AD450004910200183C0600066F -:105760003C0380000002CE000326C025AD5800088F -:105770008D0F002C3478093C24E90001AD4F000C5A -:105780008D0B001C312E7FFF25490014AD4B0010FE -:105790008F0F0000AD2D0004A78E0054AD2F000028 -:1057A0008C64010C346E090025220014AD2400081D -:1057B00091C700123C05080090A53AD0AD2000101A -:1057C00030EB00FF016C302100066F000005CC00BB -:1057D00001B96025358AFFFF03E00008AD2A000CFF -:1057E00034E90AA495240000950200283C09080029 -:1057F00095293AC000041C000002CC0034788100D6 -:10580000032B7825AD58000CAD4F00100A00054061 -:10581000254A00143C09080095293AC03C050800B7 -:1058200094A53ACA3C06080094C63ABC9499000074 -:105830003123FFFF9518002800A31021004678238C -:1058400000193C000018440025EEFFEE010E28254B -:1058500034E48100AD44000CAD450010AD400014AF -:10586000AD4B00180A000540254A001C1460FF4F8C -:1058700034E60AA494CE00003C09080095293AC0F9 -:10588000000E4400010B3825AD47000C0A0005400E -:10589000254A001003E00008240207D027BDFFE0DE -:1058A000AFB20018AFB10014AFB00010AFBF001C12 -:1058B0000E00004D008088218F8800508F87004C9B -:1058C0003C05800834B20080011128213C10800082 -:1058D00024020080240300C000A72023AE02081881 -:1058E0003C068008AE03081C18800004AF850050F9 -:1058F000ACC500048CC90004AF89004C122000091B -:10590000360409800E0005F800000000924C0027C4 -:105910008E0B007401825004014B3021AE46000C06 -:10592000360409808C8E001C8F8F005801CF6823AD -:1059300019A000048FBF001C8C90001CAF90005871 -:105940008FBF001C8FB200188FB100148FB00010F1 -:105950000A00004F27BD00208F8600608F83005013 -:105960008F82004C3C05800834A40080AC86005037 -:10597000AC83003C03E00008ACA200043C03080038 -:105980008C63005427BDFFF8308400FF24620001BF -:1059900030A500FF3C010800AC22005430C600FFD7 -:1059A0003C0780008CE801780500FFFE3C0A7FFF81 -:1059B000A3A400038FA400003549FFFF0089182429 -:1059C000000647C000681025AFA2000090F9010A48 -:1059D000A3A000023C1880FFA3B900018FAE000015 -:1059E00030AD007F370FFFFF01CF5824000D660058 -:1059F0003C090020016C5025352620002405FF803D -:105A00003C04100027BD0008ACEA014CACE6015490 -:105A1000A4E00158A0E5015203E00008ACE40178DD -:105A2000308800FF3C03800030A400FF8C620178C6 -:105A30000440FFFE000000003C03800034660A00C2 -:105A40008CCA0020346709800004482BAC6A0144EA -:105A50008CC5002400091540AC650148A0680150C0 -:105A600090E4004CA064016D03E00008A4600158BC -:105A700027BDFFE8308400FFAFBF00100E00065BBB -:105A800030A500FF8F8300508FBF00103C058000C1 -:105A9000344600402404FF903C02100027BD00184B -:105AA000ACA3014CA0A40152ACA6015403E0000831 -:105AB000ACA2017827BDFFE03C088008AFBF001C06 -:105AC000AFB20018AFB10014AFB0001035100080B5 -:105AD0008E0600183C078000309200FF00C720258A -:105AE000AE0400180E00004D30B100FF9203000517 -:105AF000346200080E00004FA2020005024020217F -:105B00000E00066F02202821024020218FBF001CBA -:105B10008FB200188FB100148FB00010240500055B -:105B2000240600010A00063227BD00203C05800043 -:105B300034A309809066000830C200081040000FAE -:105B40003C0A01013549080AAC8900008CA80074A0 -:105B5000AC8800043C07080090E73AD030E500101C -:105B600050A00008AC8000083C0D800835AC0080D7 -:105B70008D8B0058AC8B00082484000C03E00008D7 -:105B8000008010210A0006B22484000C27BDFFE823 -:105B90003C088000AFB00010AFBF0014350609808C -:105BA00090C70009240200063509090030E300FF10 -:105BB0000080802100A06021240B00041062007985 -:105BC0002407000294CF005C3C0E020431EDFFFF7D -:105BD00001AE5025AE0A000090C5000830A4002098 -:105BE000108000080000000090C2004E3C1F01031E -:105BF00037F90300305800FF03193025240B000843 -:105C0000AE06000491390011912600129124001172 -:105C1000333800FF0018708230CF00FF01CF5021D1 -:105C2000014C6821308800FF31AAFFFF39030028AA -:105C3000000A28801460002B0205402391240012E2 -:105C40003C0E800035D90980308500FF00AC18215A -:105C500000031080004BF821001F8400360906FF66 -:105C6000AD09000435C9090091260011912F0012D9 -:105C7000000BC0828F2B003431ED00FF8DC4010C6E -:105C800001AC282100B810210164F823000784002A -:105C900000021F000070C82533E9FFFF30CF00FC71 -:105CA000032970250158202101E868210004508053 -:105CB000ADAE000C0E00004D010A80213C078008AB -:105CC000240C000434EB00800E00004FA16C00098E -:105CD000020010218FBF00148FB0001003E00008F5 -:105CE00027BD001891250011912300193C180800C8 -:105CF00097183AC630A200FF0002F882307000FF09 -:105D0000001FCE0000104C000329302500D870255C -:105D10003C0F400001CF68253C0E8000AD0D000017 -:105D200035C9090091260011912F001235D909803B -:105D3000000BC08231ED00FF8F2B00348DC4010CAD -:105D400001AC282100B810210164F8230007840069 -:105D500000021F000070C82533E9FFFF30CF00FCB0 -:105D6000032970250158202101E868210004508092 -:105D7000ADAE000C0E00004D010A80213C078008EA -:105D8000240C000434EB00800E00004FA16C0009CD -:105D9000020010218FBF00148FB0001003E0000834 -:105DA00027BD00180A0006C42407001227BDFFD033 -:105DB000AFB50024AFB40020AFB3001CAFB00010EB -:105DC000AFBF0028AFB20018AFB100143C0680008E -:105DD00090C3010B309300FF30B400FF30620030FD -:105DE0000000A821104000820000802134C40980F6 -:105DF0009088000800083E0000072E0304A000A9B8 -:105E0000240400048F8700503C010800A0243AD0ED -:105E10003C0C8000AD8000483C038000906E010B7C -:105E200031C5002010A000073C0C800034780980A8 -:105E30009312000800128E0000117E0305E000AEF0 -:105E40003C028008918B010B3586098090C40008C4 -:105E5000316A0040000A482B3088000824110003F2 -:105E60001500000200E99023000088213C03800017 -:105E700034780A80346A09009707002C9144001195 -:105E80009149001293050018309F00FF312800FF50 -:105E9000022810210002C880930D0018033F7821CA -:105EA00001F0702130B000FF01D01821A787005405 -:105EB0003C010800A42E3AC63C010800A4233AC8BD -:105EC00015A00003246B000A0000000D246B000ADB -:105ED0003170FFFF3C010800A4233ACA3C010800CE -:105EE000A4203AC03C010800A4203ABC0E0001B432 -:105EF000020020210E00050F00402021004020213B -:105F0000024028210E00051C022030210E00069EB2 -:105F10000040202116A0005F004020210E0001C893 -:105F2000020020213C11080092313AD032350003A2 -:105F300012A000163C0A80088F8700503C0E800893 -:105F400035CD008024EC0001ADAC003C3C05800860 -:105F50008CA600040180202100CC90231A4000026E -:105F6000AF8C00508CA400040E0005F8ACA4000413 -:105F70003C1980008F3800743C0F800835F0008099 -:105F800000582821AE05000C3C0A800835420080EC -:105F90000260202102802821A040006B0E00065BD9 -:105FA0003C1380008F840050345F0006AE64014CC7 -:105FB0008F8800483C1410008FB50024250900018B -:105FC000AF8900488FB20018A26801528FB1001447 -:105FD000AE7F01548FB00010AE7401788FBF0028DF -:105FE0008FB400208FB3001C03E0000827BD0030F1 -:105FF00034C30980906F0008000F7600000E6E0316 -:1060000005A0003334C209009059001B241F001062 -:106010003C010800A03F3AD0333800021300FF7E55 -:106020008F8700508F83005C1467FF7C3C038000E7 -:106030000E00004D000000003C098008352500805E -:1060400090A4000924070016308800FF1107000DF6 -:106050000000000090A600093C0C0800918C3AD08A -:10606000240A000830C400FF358B00013C01080001 -:10607000A02B3AD0108A002F240D000A108D002882 -:106080002402000C0E00004F000000000A00075917 -:106090008F8700500E0006B6022028210A00079ABA -:1060A000000000003C0B8008356A00808D470054DA -:1060B0008CC9010C1120FF54AF8700502406001436 -:1060C0003C010800A0263AD00A0007583C0C80008A -:1060D00090710008241200023C010800A0323AD05E -:1060E000323000201200000B241500018F87005071 -:1060F0000A00075924100008345900808F23003803 -:10610000AC4300048C5F0004AF3F003C0A0007640E -:106110003C0C80008F8700500A00075924100004AF -:10612000A0A200090E00004F000000000A0007595D -:106130008F870050240200140A00081CA0A2000946 -:1061400027BDFFE8AFBF0014AFB000103C108000C7 -:1061500092020109240500010E00065B304400FF95 -:106160003C1F800893F8000E37E3008093F9000F7E -:10617000906E002693E9000A332F00FF0018660096 -:10618000000F6C0031CB00FF018D5025000B320059 -:1061900001463825312800FF3445600000E82025FD -:1061A0002402FF813C031000AE04014C8FBF001499 -:1061B000AE050154A2020152AE0301788FB0001067 -:1061C00003E0000827BD001827BDFFE8308400FF6A -:1061D000AFBF00100E00065B30A500FF3446004044 -:1061E0003C0480002405FF92AC860154A085015236 -:1061F0008F8300508FBF00103C02100027BD001895 -:10620000AC83014C03E00008AC82017827BDFFD8C5 -:10621000AFB20018AFB10014AFB00010AFBF002094 -:10622000AFB3001C3C07800090E20109308600FFFC -:1062300030B000FF000618C23204000230710001C5 -:1062400014800007305200FF3C098008353300807D -:10625000926800053105000810A0000C30CA00103B -:10626000024020210E000680022028212402000185 -:106270008FBF00208FB3001C8FB200188FB10014A5 -:106280008FB0001003E0000827BD00281540003043 -:1062900034E50A008CB900248CB800081338004794 -:1062A000000040213C0E800835D30080926D0068CC -:1062B000240B000231AC00FF118B00803C068000F3 -:1062C000927F004C90C40109509F00043213007C5F -:1062D00011000067000000003213007C1660005AB5 -:1062E0000240202116200008320C00013C078000EB -:1062F00034EB0A008D6500248CE8010414A8FFDC4F -:1063000000001021320C00011180000D02402021FC -:106310003C1080008E0E010C8F8D006011CD0008A6 -:10632000000000000E00073E022028218E0F010C05 -:106330003C18800837100080AE0F0050024020212A -:106340000E00066F022028210A00086F24020001B7 -:106350003C0708008CE7006424E600013C010800CB -:10636000AC2600641600000D000000000220282169 -:106370000E00066F02402021926F0068240D00027B -:1063800031EE00FF11CD0022024020210E00082333 -:10639000000000000A00086F240200010E00004106 -:1063A00024040001926C0025020C58250E00004FB9 -:1063B000A26B00250A0008AF022028218E63001876 -:1063C0008CE401048CBF002400031602149FFFB567 -:1063D0003045007F9269004C264400013093007FD5 -:1063E00012650040312300FF1464FFAF3C0E8008AB -:1063F000264800013111007F310200FF1225000BF9 -:1064000024080001004090210A00087C24110001AA -:10641000240500040E000632240600010E000823A5 -:10642000000000000A00086F240200012407FF801A -:106430000247282400A79026324200FF0040902106 -:106440000A00087C241100010E00073E02202821CA -:106450003206003010C0FFA332100082024020211B -:106460000E000680022028210A00086F2402000185 -:106470008E6300180240202102202821006610258A -:106480000E000845AE6200189264004C240500031B -:10649000240600010E000632308400FF0E00004189 -:1064A00024040001926A0025020A48250E00004FCC -:1064B000A26900250A00086F240200018E780018E6 -:1064C0003C19800002402021031978250220282150 -:1064D0000E00066FAE6F00189264004C0A0008F7B9 -:1064E000240500043246008038CA0080146AFF6E1A -:1064F0003C0E80080A0008D02648000127BDFFC0D6 -:10650000AFB000183C108000AFBF0038AFB7003408 -:10651000AFB60030AFB5002CAFB40028AFB3002445 -:10652000AFB200200E0004BBAFB1001C9204010802 -:106530009205010B308400FF0E00085630A500FFC5 -:10654000144000E38FBF00383C09800835280080E4 -:10655000A100006B3607098090E60000240200507D -:106560003C17080026F73A8830C300FF3C130800A8 -:1065700026733A98106200033C1080000000B82196 -:1065800000009821241F001036110A0036140980DB -:106590008E1601048F8D00508E38002436190A8023 -:1065A0008E9200203C010800A03F3AD0972C002C8E -:1065B0008EF50000932B0018024D702302D878232B -:1065C0003C010800AC2F3AAC3C010800AC2E3AB0BC -:1065D0003C010800AC2D3AD4A78C005402A0F80965 -:1065E000317200FF304A0002154000E630450001DC -:1065F00010A000C100000000928A0008315000087D -:1066000016000002241400030000A0213C068000B4 -:1066100034C4090034C30A008C6E00249085001134 -:10662000908200129099001130B800FF305100FFA5 -:106630000291F821001FB080332F00FF02D85821AB -:10664000024FA82126AC0010017268213C15800081 -:106650003C010800AC2E3AD83C010800A42D3AC8F1 -:106660003C010800A42C3AC43C010800A42B3AC603 -:1066700036B609808F8700508F8900588ED200204F -:106680002408000601273023024728233C01080084 -:10669000AC283ACC04C000B30000902104A000B1A3 -:1066A00000C5802B120000B3000000003C01080070 -:1066B000AC263AB08E7100000220F80900000000FC -:1066C000304A00021540007400408021304B000128 -:1066D000556000118E7100043C0D08008DAD3AB478 -:1066E0003C0EC0003C04800001AE6025AEAC0E0044 -:1066F0008C980000330F000811E0FFFD000000003F -:10670000949F0E0824120001A79F00408C990E044C -:10671000AF9900388E7100040220F80900000000D3 -:106720000202802532020002144000A9000000008D -:106730003C08080095083ABC3C11080096313AC85C -:106740003C09080095293ABE3C0308008C633AB422 -:10675000011168213C1F08008FFF3AD83C07080050 -:1067600094E73AD23C11800001A920218E38010C17 -:10677000006828212499000200A7702103E37821F2 -:10678000AF9800603C010800AC2F3AD83C010800EB -:10679000A42E3AC03C010800A42D3ACA0E0001B450 -:1067A0003324FFFF8F8C0048004020213C0108006B -:1067B000A02C3AD18E620008258B0001AF8B0048D7 -:1067C0000040F809000000008F8500500280302151 -:1067D0000E00051C004020210E00069E00402021D6 -:1067E0008E6A000C0140F809004020213C08080096 -:1067F00095083ACA3C09080095293ABE0109382192 -:1068000024E600020E0001C830C4FFFF3C0408006B -:106810008C843AAC3C0308008C633AB40083282390 -:106820003C010800AC253AAC14A0000600000000B2 -:106830003C0A08008D4A3ACC354600403C0108002D -:10684000AC263ACC124000418F8C00448E2B0E10A7 -:106850008F920044AE4B00208E220E18AE420024D0 -:106860003C04080094843AC00E0005FA00000000C1 -:106870008F9900508E7800103C010800AC393AD452 -:106880000300F809000000003C0F08008DEF3AAC4F -:1068900015E0FF798F870050979400543C13800EC9 -:1068A000321500100E000629A674002C56A00044D4 -:1068B0008EF60004321F004057E0001D8EF00008E5 -:1068C0008EE3000C0060F809000000008FBF003864 -:1068D0008FB700348FB600308FB5002C8FB40028EE -:1068E0008FB300248FB200208FB1001C8FB000182E -:1068F00003E0000827BD0040920901098F88003C91 -:1069000000093E0000E83025AE0600808E230020FE -:106910008E240024AFA30010AE030E148FA200102B -:10692000AE020E10AE040E1C0A000951AE040E1881 -:106930000200F809000000008EE3000C0060F80976 -:10694000000000000A000A078FBF0038240E000173 -:10695000240D0001A5800020A58E00220A0009EB6D -:10696000AD8D00243C010800AC203AB00A0009813A -:106970008E7100003C010800AC253AB00A00098184 -:106980008E71000092110109000028210E00066F8F -:10699000322400FF8FBF00388FB700348FB600302D -:1069A0008FB5002C8FB400288FB300248FB2002045 -:1069B0008FB1001C8FB0001803E0000827BD004015 -:1069C00002C0F809000000000A000A01321F00405E -:1069D0005240FFB2979400548EB60E148F93004429 -:1069E000AE7600208EB40E1CAE7400240A0009FAA4 -:1069F000979400548F8200140004218003E0000863 -:106A0000008210213C07800834E200809043006936 -:106A100000804021106000093C0401003C07080090 -:106A20008CE73AD48F83003000E3202304800008F1 -:106A30009389001C14E300030100202103E00008F7 -:106A4000008010213C04010003E0000800801021B8 -:106A50001120000B006738233C0D800035AC098005 -:106A6000918B007C316A000211400020240900341F -:106A700000E9702B15C0FFF10100202100E9382347 -:106A80002403FFFC00A3C82400E3C02400F9782BF2 -:106A900015E0FFEA0308202130C40003000410239E -:106AA00014C00014304900030000302100A97821EF -:106AB00001E6702100EE682B11A0FFE03C0401000C -:106AC0002D3800010006C82B010548210319382480 -:106AD00014E0FFDA2524FFFC2402FFFC00A21824A6 -:106AE0000068202103E00008008010210A000A6FDE -:106AF000240900303C0C80003586098090CB007C56 -:106B0000316A00041540FFE9240600040A000A7EE9 -:106B1000000030213C0308008C63005C8F82001869 -:106B200027BDFFE8AFBF001410620005AFB0001032 -:106B3000000329C024A40280AF840014AF8300188E -:106B40003C10800036030A00946500320E000A50A3 -:106B500030A43FFF8E0401003C180080370F000373 -:106B60000082C8212402FF80032260243329007F91 -:106B7000000CF94003E94025332E00783C0D10004D -:106B8000010D502501CF5825AE0C0028360809808C -:106B9000AE0C080CAE0B082CAE0A0830910300694D -:106BA0003C06800C0126382110600006AF870034B7 -:106BB0008D09003C8D06006C0126382318E0007F0B -:106BC000000000003C0C8008358B00803C0A8000EF -:106BD000A1600069355009808E0200383C068000B3 -:106BE00034C50A0090AD003C31A800201100001906 -:106BF000AF820030240E00013C19800037300A00BB -:106C0000A38E001CAF8000248E0400248F850024F6 -:106C100024180008AF800020AF8000283C01080045 -:106C2000A4383ABE3C010800A4203AD20E000A540F -:106C300000003021920F003C8FBF00148FB0001075 -:106C4000000F7142AF82002C27BD001803E000083E -:106C500031C2000190B90032240F0001333800FF27 -:106C600000182182108F003F241F0002109F006235 -:106C700034C20AC03C03800034640A008C990024AA -:106C80001720001D3466090090830030241F000582 -:106C90003062003F105F004C240500018F86002009 -:106CA000A385001CAF860028AF8600243C19800015 -:106CB00037300A008E0400248F8500242418000831 -:106CC0003C010800A4383ABE3C010800A4203AD296 -:106CD0000E000A5400000000920F003C8FBF001409 -:106CE0008FB00010000F7142AF82002C27BD00183A -:106CF00003E0000831C200018C8800088C8D00245C -:106D00008CCB00643C19800037300A00AF8B002424 -:106D1000A380001C8E0400248F8600208F85002411 -:106D2000010D602324180008AF8C00283C010800E6 -:106D3000A4383ABE3C010800A4203AD20E000A54FE -:106D400000000000920F003C8FBF00148FB00010B5 -:106D5000000F7142AF82002C27BD001803E000082D -:106D600031C2000190A7003030E3003F506400289A -:106D700034C50AC08CAA00241540002234C809007A -:106D80008CAB00483C0C7FFF3585FFFF016510246C -:106D90003C188000AF820020370509008F8E00204C -:106DA0008CAF006001CF682B15A0000201C020212C -:106DB0008CA400600A000AF0AF8400208D02006CF1 -:106DC0000A000ACB3C0680008C8900488F86002090 -:106DD0003C0A7FFF3550FFFF013038243C04800817 -:106DE00024050001AF870028AC80006CA385001C3F -:106DF0000A000AFEAF8600248C4400140A000AF040 -:106E0000AF8400208D0200680A000B383C18800017 -:106E100034C409808C8600708CB0001400D0482BDC -:106E200011200004000000008C8200700A000B3862 -:106E30003C1880008CA200140A000B383C1880001B -:106E40008F85002427BDFFE0AFBF0018AFB100144D -:106E500014A00008AFB000103C04800034870A0082 -:106E600090E600302402000530C3003F106200B7F6 -:106E7000348409008F91002000A080213C04800010 -:106E8000348E0A008DCD00043C0608008CC63AB052 -:106E900031A73FFF00E6602B5580000100E0302164 -:106EA000938F001C11E0007600D0102B34990980DC -:106EB0009338007C330400021080007724030034F0 -:106EC00000C3F82B17E000D600C3302300D0102BEE -:106ED0003C010800A4233ABC1440006D02001821B4 -:106EE0003C0408008C843AAC0064282B54A00001B8 -:106EF000006020213C05800034A90A009128003C54 -:106F00003C010800AC243AB43103002014600002B4 -:106F1000000048218CA90E188F88002C0128502BC6 -:106F20001140005F000000003C0508008CA53AB449 -:106F300000A96021010C582B1160005C00B0682B87 -:106F40000109382300E028213C010800AC273AB4AD -:106F5000120000032402FFFC10B0008C322A000350 -:106F600000A2F8243C010800A4203AD23C01080009 -:106F7000AC3F3AB403E028218F84002412040006B9 -:106F80003C0380088C6A006C02002021AF91002035 -:106F900025500001AC70006C8F8B00280085882381 -:106FA000AF91002401652023AF8400281220000245 -:106FB00024070018240700103C0E800835C6008006 -:106FC00090CD0068240C00013C010800A0273AD0B5 -:106FD00031A700FF10EC00470000000014800018EB -:106FE000000028213C0B8000916501093571098062 -:106FF0008E23001830A500FF0003560224A30001D1 -:107000003146007F3070007F1206007E240CFF8026 -:107010003C0F800835E90080A123004C3C080800A3 -:107020008D083ACC240E00023C010800A02E3B1132 -:10703000350D00083C010800AC2D3ACC24050010A9 -:107040003C1F800037E40A009099003C3338002050 -:107050001300000500A02021240200013C010800CB -:10706000AC223AB434A400018FBF00188FB10014D1 -:107070008FB000100080102103E0000827BD002021 -:107080003C010800A4203ABC1040FF9502001821E2 -:107090000A000B8B00C018210A000B832403003068 -:1070A0003C0508008CA53AB400B0682B11A0FFA8DD -:1070B000000000003C04080094843ABC008578215C -:1070C00001E7702B11C000072CA200043C1F6000D8 -:1070D0008FF954043338003F1700FFE324040042C3 -:1070E0002CA200041040FF9A240400420A000BEE78 -:1070F0008FBF00181528FFB9000000008CC20018CF -:107100003C188000241900020058F825ACDF001854 -:1071100037040A00A0D900689089003C240F0004BD -:1071200000A01021312800203C010800A02F3B11B5 -:107130001100000224050010240200013C01080097 -:10714000AC223AAC0A000BE43C1F80008F88002878 -:107150008C8900600109282B14A0000201008821FD -:107160008C9100603C0B80008D640E18240A000195 -:107170000220282102203021A38A001C0E000A547C -:10718000022080210A000B72AF82002C000A182313 -:1071900012200007306400033C0D800035A70980F1 -:1071A00090EC007C318B000415600019248E0004E3 -:1071B0003C010800A4243AD23C18080097183AD29F -:1071C0000305202100C4782B11E0FF6C8F8400247C -:1071D0002CA6000514C0FFA42404004230B900030B -:1071E0001720000200B9182324A3FFFC3C0108006B -:1071F000AC233AB43C010800A4203AD20A000BB1F7 -:107200000060282100AC38240A000BD700EC1826B7 -:107210003C010800A42E3AD20A000C4100000000F4 -:107220003C010800AC203AB40A000BED24040042F3 -:107230008F8300283C0B8000356A0A00146000062A -:1072400000001021914600302405000530C400FFE5 -:10725000108500030000000003E0000800000000AB -:1072600091490048312800FF000839C214E0FFFAB4 -:107270003C0480083C06080094C63ABC3C03080065 -:107280008C633AD43C0508008CA53AB43C1808003D -:1072900097183AD20066C8218C8E00040325782105 -:1072A00001F8682101AE60231980001D0000000074 -:1072B0009158004C8F8D0034956E0E10330F00FFE7 -:1072C0008DA9000401CF30238DAA000030CFFFFF2D -:1072D000000F6100012C28210000382101472021E6 -:1072E00000AC182B0083C821ADA50004ADB9000087 -:1072F00091B8000A01F87021A1AE000A956C0E1237 -:107300008F8A0034A54C00089549003825280001D3 -:10731000A54800389147000D34EB0008A14B000D43 -:1073200003E000080000000027BDFFD8AFB0001840 -:10733000938F001C8FB000143C087FFF8F870024C0 -:107340003C0C80003518FFFFAFBF0020AFB1001C20 -:1073500035990A0002181824932A003C000F5FC0D8 -:107360003C02BFFF2CF000013449FFFF006BF82501 -:107370003C0808008D083AD48F9900303C1808006A -:1073800097183ACA03E9582400107F803C07EFFFA2 -:107390003C05F0FF016F18253C11800031490020A9 -:1073A00034E2FFFF34ADFFFF362E098027A5001021 -:1073B0002406000201194023270A00020062182453 -:1073C0000080802115200002000058218D8B0E1CAA -:1073D000A7AA00120500003A2407000030EF00FFC2 -:1073E000000F3F00006740253C028008AFA8001452 -:1073F000344B0080916A00683C0F080091EF3AD14D -:107400003C09DFFF353FFFFF000A602B3C0208000C -:1074100094423AC4A3AF0011011FC024000CCF4016 -:10742000031918258FA70010AFA300143C1F0800F4 -:1074300093FF3AD3A7A200168FA8001400ED4824AA -:107440003C0B01003C0A0FFF012BC82533F8000359 -:10745000354CFFFF010D78243C027000032C3824CA -:1074600000181E0000E2482501E35825AFAB0014C8 -:10747000AFA9001091DF007CA3BF00150E000063D0 -:1074800000000000362D0A0091A6003C30C4002008 -:1074900010800006260200083C11080096313AC010 -:1074A000262EFFFF3C010800A42E3AC08FBF00200B -:1074B0008FB1001C8FB0001803E0000827BD002822 -:1074C0008F8A002C016A602B5580FFC424070001BD -:1074D0000A000CCB30EF00FF9383001C3C028000BD -:1074E00027BDFFD834480A0000805021AFBF0020DC -:1074F00034460AC0010028211060000E344409807F -:1075000091070030240B00058F89002030EC003FEC -:10751000118B000B00003821AFA900103C0B800834 -:107520008D69006CAFAA00180E00012BAFA90014E2 -:10753000A380001C8FBF002003E0000827BD0028A7 -:107540008D1F00483C1808008F183AB48F99002806 -:107550003C027FFF8D0800443443FFFFAFA90010B9 -:107560003C0B80088D69006C03E3702403197821BB -:1075700001CF682301A83821AFAA00180E00012B03 -:10758000AFA900140A000D20A380001C3C05800058 -:1075900034A60A0090C7003C3C06080094C63AD2C4 -:1075A0003C0208008C423ACC30E300200006240064 -:1075B0001060001E004438253C0880083505008016 -:1075C00090A3006800003021240800010000202161 -:1075D000240300013C0580008CAC01780580FFFE8F -:1075E00000000000ACA80148A4A40144A4A30146E3 -:1075F0003C0308008C633AD43C188008370F0080A5 -:10760000ACA3014C3C19080093393AD13C0D100051 -:10761000A0B90152ACA70154A4A6015891EE004CA8 -:10762000A0AE016D03E00008ACAD01788CA80E1C83 -:107630003C0B08008D6B3AB494AA0E1694A90E1454 -:10764000016630213143FFFF0A000D483124FFFF5E -:107650003C04800034830A009065003C30A2002086 -:107660001040001C0000000000003021000020211C -:10767000000018213C0580008CA901780520FFFE40 -:1076800000000000ACA601483C0E08008DCE3AD4A4 -:10769000240DFF91240C00403C0B8008A4A301445E -:1076A000356A0080A4A40146ACAE014CA0AD0152E5 -:1076B000ACAC0154A4A0015890A301099144004C22 -:1076C00090A601093C041000A0A6016D03E000088B -:1076D000ACA401788C860E1894880E1294870E1034 -:1076E0003104FFFF0A000D7030E3FFFF3C0480000F -:1076F00034830A009065003C30A200201040002630 -:1077000027BDFFF8240900010000382124080001EA -:107710003C0680008CC401780480FFFE000000005D -:1077200090CA01093C04080090843B113C1880FF7A -:10773000A3AA00038FA300003085007F370FFFFF4F -:1077400000661025AFA2000090D9010AA3A0000294 -:1077500000056E00A3B900018FAE0000240A3000BE -:1077600027BD000801CF6024018D5825ACCB014C0A -:10777000ACCA0154A4C00158ACC90148A4C7014413 -:107780002409FF80A4C801463C081000A0C901528A -:1077900003E00008ACC801788C890E1894870E129B -:1077A00094860E1030E8FFFF0A000D9730C7FFFFE8 -:1077B00027BDFFE8AFB000103C108000AFBF001441 -:1077C00036180A00970F00320E000A5031E43FFFCE -:1077D0008E0E0100240DFF803C04200001C25821C0 -:1077E000016D6024000C4940316A007F012A402568 -:1077F000010438253C048008AE0708303486008038 -:1078000090C500682403000230A200FF104300046A -:107810008F9F00208F990024AC9F0068AC99006472 -:107820008FBF00148FB0001003E0000827BD0018C0 -:107830003C0A0800254A359C3C09080025293638B1 -:107840003C08080025082A603C07080024E736FCAD -:107850003C06080024C634243C05080024A5317CDD -:107860003C04080024842D8C3C030800246334D895 -:107870003C020800244232743C010800AC2A3A90D1 -:107880003C010800AC293A8C3C010800AC283A883D -:107890003C010800AC273A943C010800AC263AA40D -:1078A0003C010800AC253A9C3C010800AC243A9805 -:1078B0003C010800AC233AA83C010800AC223AA0E5 -:0878C00003E0000800000000D5 -:0878C800800009408000090066 -:1078D000800801008008008080080000800E000001 -:1078E000800800808008000080000A8080000A0074 -:0878F0008000098080000900FE -:00000001FF -/* - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - */ diff --git a/firmware/bnx2/bnx2-mips-09-5.0.0.j9.fw.ihex b/firmware/bnx2/bnx2-mips-09-5.0.0.j9.fw.ihex new file mode 100644 index 000000000000..36e922ef61d1 --- /dev/null +++ b/firmware/bnx2/bnx2-mips-09-5.0.0.j9.fw.ihex @@ -0,0 +1,6058 @@ +:100000000800011008000000000051C4000000C8F2 +:10001000000000000000000000000000080051C4C3 +:10002000000000380000528C080000880800000022 +:10003000000051B4000052C4080053A00000008426 +:100040000000A478080051B4000001C00000A4FC26 +:10005000080031D808000000000081540000A6BC50 +:1000600000000000000000000000000008008154B3 +:100070000000012400012810080004880800040082 +:10008000000017EC0001293400000000000000000F +:100090000000000008001BEC0000000400014120EB +:1000A000080000A8080000000000381400014124E6 +:1000B00000000000000000000000000008003814EC +:0800C000000000300001793856 +:0800C8000A00004400000000E2 +:1000D000000000000000000D636F6D352E302E30E3 +:1000E0006A39000005000002000000000000000363 +:1000F00000000014000000320000000300000000B7 +:1001000000000000000000000000000000000000EF +:1001100000000010000001360000EA600000000549 +:1001200000000000000000000000000000000008C7 +:1001300000000000000000000000000000000000BF +:1001400000000000000000000000000000000000AF +:10015000000000000000000000000000000000009F +:10016000000000020000000000000000000000008D +:10017000000000000000000000000000000000007F +:10018000000000000000000000000010000000005F +:10019000000000000000000000000000000000005F +:1001A000000000000000000000000000000000004F +:1001B000000000000000000000000000000000003F +:1001C000000000000000000000000000000000002F +:1001D000000000000000000000000000100000030C +:1001E000000000000000000D0000000D3C020800AF +:1001F000244252203C03080024635354AC400000C6 +:100200000043202B1480FFFD244200043C1D080005 +:1002100037BD9FFC03A0F0213C1008002610011000 +:100220003C1C0800279C52200E00025F00000000CA +:100230000000000D27BDFFE0AFBF0018AFB10014F4 +:10024000AFB000103C04800094820108304370007D +:10025000240220001062000B2862200114400036A6 +:1002600000001021240240001062002C0000000059 +:10027000240260001062002D000010210A00009D81 +:100280008FBF001834910100922400098E300018AD +:1002900010800020240300012402000914820006BB +:1002A0008F82001C3C0280089442001A0002140055 +:1002B000020280258F82001C8C42000C1040001529 +:1002C000000018210E000D45000000008F83001C67 +:1002D000962400088F8200189463001E9625000C57 +:1002E0000004240000832025AC500000AC4500042D +:1002F000AC400008AC40000CAC400010AC40001416 +:10030000AC400018AC44001C0E000D792404000120 +:10031000000018210A00009C006010210E00042E2D +:10032000000000000A00009C000010210E000C6577 +:1003300000000000000010218FBF00188FB10014D2 +:100340008FB0001003E0000827BD00208F82001C42 +:1003500027BDFFE0AFB00010AFBF0018AFB1001471 +:100360008C42000C3C1080008E11010010400034C3 +:100370008FBF00180E000D45000000008F8500188B +:1003800024047FFF0091202BACB100008E030104F8 +:100390009602010800031C003042FFFF006218258E +:1003A000ACA300049202010A96030114304200FF3C +:1003B0003063FFFF0002140000431025ACA20008C8 +:1003C0009603010C9602010E00031C003042FFFF51 +:1003D00000621825ACA3000C9603011096020112CE +:1003E00000031C003042FFFF00621825ACA3001080 +:1003F0008E020118ACA200148E02011CACA20018DF +:10040000148000088F82001C978200003C042005A5 +:100410000044182524420001ACA3001C0A0000DBA4 +:10042000A78200003C0340189442001E00431025A0 +:10043000ACA2001C0E000D79240400018FBF00182F +:100440008FB100148FB000100000102103E00008ED +:1004500027BD00203C0680008CC202B824030001A6 +:1004600004410008008028213C0208008C42006002 +:10047000244200013C010800AC22006003E00008B7 +:10048000006010218C83002094820016ACC302808F +:100490002442FFFCA4C202843C0208008C42005C9F +:1004A0008C84000494A3000E244200013C01080047 +:1004B000AC22005C3C021000A4C30286ACC40288DB +:1004C00000001821ACC202B803E00008006010214F +:1004D00027BDFFE0AFB000103C108000AFB20018A5 +:1004E000AFBF001CAFB10014361201009243000BE5 +:1004F0002402001A965100081462005A00002821B4 +:1005000032220001104000188F82001C8E42000031 +:10051000000223403C02003F3442FFFF0044102B06 +:10052000104000043C030040964200140A000124DD +:10053000008320218E030100240201005462000682 +:10054000964200143C028008904200043042000FA2 +:10055000000225009642001400821025AE020080A1 +:100560000A000157000000008C42000C10400028D7 +:10057000000000000E000D4500000000960201087A +:100580009603010C8F8500183042003E3063FFFF58 +:100590000002140000431025ACA200008E020100EE +:1005A000ACA20004960301169604010E8F82001C73 +:1005B00000031C003084FFFF00641825ACA3000872 +:1005C00096030110960401129446001E00031C00BD +:1005D0003084FFFF00641825ACA3000C3C0220000F +:1005E00000C2302596020114240400013042FFFFAE +:1005F000ACA200108E020118ACA200149202010BF2 +:10060000304200FFACA200180E000D79ACA6001C11 +:100610003C0208008C420040244200013C010800DA +:10062000AC2200403C0308008C63004432220002EC +:1006300032240004246300013C010800AC23004480 +:10064000108000080002282B024020218FBF001CD0 +:100650008FB200188FB100148FB000100A0000E3B1 +:1006600027BD00208FBF001C8FB200188FB100146F +:100670008FB0001000A0102103E0000827BD00206B +:1006800027BDFFE0AFB000103C108000AFB20018F3 +:10069000AFBF001CAFB10014361201009243000B33 +:1006A000240200031462006A9651000832220001FD +:1006B000104000178F82001C8E4300003C02003F58 +:1006C0003442FFFF000323400044102B504000053C +:1006D00024020100964200143C0300400A00018EEF +:1006E0000083202154620006964200143C028008D8 +:1006F000904200043042000F000225009642001490 +:1007000000821025AE0200800A0001BE0000000039 +:100710008C42000C10400025000000000E000D452A +:1007200000000000960201089603010C8F85001856 +:100730003042003E3063FFFF0002140000431025EA +:10074000ACA200008E020100ACA2000496030116C8 +:100750009604010E8F82001C00031C003084FFFFF2 +:1007600000641825ACA3000896030110960401123A +:100770009446001E00031C003084FFFF006418250F +:10078000ACA3000C3C02200000C2302596020114EC +:10079000240400013042FFFFACA20010ACA0001402 +:1007A000ACA000180E000D79ACA6001C3C0208009D +:1007B0008C420040244200013C010800AC22004071 +:1007C0003C0208008C420044322300042442000111 +:1007D0003C010800AC2200441060000832220002F4 +:1007E000024020218FBF001C8FB200188FB100146F +:1007F0008FB000100A0000E327BD00201040001554 +:100800008FBF001C3C0480008C8301043C026020EC +:10081000AC4300148C420004240301FE304203FF69 +:100820001443000C8FBF001C8C820100000219C20F +:100830002462FFFC2C420008104000032404000244 +:100840002462FFFD004420043C026000AC446914B3 +:100850008FBF001C8FB200188FB100148FB0001032 +:100860000000102103E0000827BD00203C048000A8 +:100870008C83010024020100506200033C028008C6 +:100880000000000D3C02800890430004000010218D +:100890003063000F00031D0003E00008AC830080FC +:1008A0002C8407811080000A000028213C0280006F +:1008B00094420108240320003042700014430005D4 +:1008C0002783FFB03C02800890420005304500FFBE +:1008D0002783FFB00005208000832021000510C081 +:1008E000004510238C8400003C030800246352E47C +:1008F000000210C0004310213C038000AC64009053 +:1009000003E00008AF82001C03E000080000102193 +:1009100003E00008000010212402010014820008F6 +:10092000000000003C0208008C4200FC2442000150 +:100930003C010800AC2200FC0A00022430A2002086 +:100940003C0208008C420084244200013C01080063 +:10095000AC22008430A200201040000830A3001018 +:100960003C0208008C420108244200013C010800BE +:10097000AC22010803E0000800000000106000083D +:10098000000000003C0208008C42010424420001E7 +:100990003C010800AC22010403E000080000000054 +:1009A0003C0208008C420100244200013C01080086 +:1009B000AC22010003E000080000000027BDFFE8B2 +:1009C000AFB000103C108000AFBF0014360401002F +:1009D0009483000830620004104000053066000275 +:1009E0008FBF00148FB000100A0000E327BD00186D +:1009F00010C00006006028218E0401000E000214C1 +:100A0000000000000A00025B240200018F8200083F +:100A10008E03010410430007000010218E04010022 +:100A20000E000214000000008E020104AF820008D4 +:100A3000000010218FBF00148FB0001003E00008E9 +:100A400027BD001827BDFFD83C036010AFB3001CC2 +:100A5000AFBF0020AFB20018AFB10014AFB00010AC +:100A60008C6450002402FF7F3C1308002673524818 +:100A7000008220243484380CAC6450003C02800096 +:100A800024030037AC4300083C06080024C6084095 +:100A9000026010212404001C2484FFFFAC460000E7 +:100AA0000481FFFD244200043C0208002442016C42 +:100AB0003C010800AC2252503C020800244205B818 +:100AC0003C010800AC2252543C020800244202843B +:100AD0003C010800AC2252903C0208002442040869 +:100AE0003C030800246308483C040800248408F4FC +:100AF0003C05080024A52C4C3C010800AC2252B057 +:100B00003C020800244207A43C010800AC2652988D +:100B10003C010800AC2552A43C010800AC2352ACB7 +:100B20003C010800AC2452B43C010800AC2252B88D +:100B30003C010800AC23524C3C010800AC20525848 +:100B40003C010800AC20525C3C010800AC20526023 +:100B50003C010800AC2052643C010800AC20526803 +:100B60003C010800AC20526C3C010800AC205270E3 +:100B70003C010800AC2452743C010800AC205278BF +:100B80003C010800AC20527C3C010800AC205280A3 +:100B90003C010800AC2052843C010800AC20528883 +:100BA0003C010800AC26528C3C010800AC26529453 +:100BB0003C010800AC20529C3C010800AC2552A02E +:100BC0003C010800AC2352A80E00055A00000000AA +:100BD0008F8300043C0208008C4200201062001F3A +:100BE000000088212792FFB03C100800261052E434 +:100BF0003C0208008C420020240500010225180454 +:100C0000004320248F820004004310245044000C31 +:100C10002631000110800008AF90001C8E430000B8 +:100C20003C028000AC4300900E000D0CAE05000CA1 +:100C30000A0002DE26310001AE00000C2631000160 +:100C40002E220002261000381440FFE9265200042C +:100C50003C0208008C420020AF8200043C1080005F +:100C60008E110000322200071040FFDA8F8300044B +:100C70003222000110400021322200028E020100C7 +:100C8000AE0200208E020104AE0200A80E0001F6A2 +:100C90008E0401009202010B304300FF2C62001D04 +:100CA00054400004000310800E0002100A0002FFEE +:100CB00000000000005310218C4200000040F809A1 +:100CC00000000000104000043C0280008C4301043E +:100CD0003C026020AC4300143C0208008C4200340B +:100CE0003C0440003C03800024420001AC64013815 +:100CF0003C010800AC2200343222000210400010F7 +:100D0000322200043C1080008E020140AE0200201E +:100D10000E0001F68E0401400E0003970000000053 +:100D20003C024000AE0201783C0208008C420038D0 +:100D3000244200013C010800AC22003832220004A9 +:100D40001040FFA48F8300043C1080008E020180BD +:100D5000AE0200200E0001F68E0401808E03018099 +:100D600024020F00146200073C0280088E020188F2 +:100D70003C0300E03042FFFF004310250A00033B24 +:100D8000AE020080344200809042000024030050F4 +:100D9000304200FF14430007000000000E000374FF +:100DA0000000000014400003000000000E00095D78 +:100DB000000000003C0208008C42003C3C04400063 +:100DC0003C03800024420001AC6401B83C010800EF +:100DD000AC22003C0A0002C38F8300043C02900056 +:100DE00034420001008220253C028000AC440020F7 +:100DF0003C0380008C6200200440FFFE00000000E5 +:100E000003E00008000000003C02800034430001C1 +:100E10000083202503E00008AC44002027BDFFE04C +:100E2000AFB10014AFB0001000808821AFBF001830 +:100E30000E00034530B000FF8F83FFA80220202161 +:100E40009062002502028025A07000258C70001899 +:100E50003C0280000E000350020280241600000AAB +:100E60008FBF00183C0380008C6201F80440FFFE35 +:100E700024020002AC7101C0A06201C43C02100057 +:100E8000AC6201F88FBF00188FB100148FB0001052 +:100E900003E0000827BD002027BDFFE8AFBF00101A +:100EA0003C0380009462018430420200104000053F +:100EB000000020210E000FCD000000000A00038A70 +:100EC000240400018C6201880440000A8FBF0010D6 +:100ED0008C6201883C03FF00004310243C030400A3 +:100EE00014430004240400018F82FFA890420008EC +:100EF0008FBF00100080102103E0000827BD0018FC +:100F00008F82FFAC2403000124050001A040001AD9 +:100F10008F82FFA8A44300163C0280000A000355FC +:100F20008C4401408F85FFA827BDFFE0AFBF001CA8 +:100F3000AFB20018AFB10014AFB0001090A2000023 +:100F4000304400FF38830020388200300003182B23 +:100F50000002102B00621824106000053C02800083 +:100F600024020050148200818FBF001C3C028000CC +:100F700090420148304200FF2443FFFF2C620005ED +:100F80001040007A8FBF001C000310803C03080053 +:100F9000246351DC004310218C4200000040000813 +:100FA000000000003C1180008E2401400E0003452B +:100FB0008F92FFA88E50000C8E2201441602000270 +:100FC00024020001AE42000C0E0003508E240140AA +:100FD0008E220144145000068FBF001C8FB20018EF +:100FE0008FB100148FB000100A000F3927BD002008 +:100FF0008E42000C0A0004220000000094A200109F +:101000003C0480008C8301443042FFFF14620009DD +:101010000000000024020001A4A200108C82014004 +:10102000AC8202003C021000AC8202380A000429A3 +:101030008FBF001C94A200100A00042200000000D0 +:10104000240200201482000E3C11800094A20012A1 +:101050003C0380008C6301443042FFFF14620005B2 +:101060000000000024020001A4A200120A0003FCF8 +:101070008FBF001C94A200120A000422000000008E +:101080008E2401400E0003458F92FFA89642001265 +:101090008E2301443050FFFF16030002240200019A +:1010A000A64200120E0003508E2401408E220144FD +:1010B000160200068FBF001C8FB200188FB10014FB +:1010C0008FB000100A00038E27BD00209642001248 +:1010D0000A0004220000000094A200143C038000D7 +:1010E0008C6301443042FFFF146200088FBF001C74 +:1010F000240200018FB200188FB100148FB00010CD +:10110000A4A200140A00142427BD002094A20014F5 +:101110000A0004220000000094A200163C03800094 +:101120008C6301443042FFFF146200082402000176 +:101130008FBF001C8FB200188FB100148FB0001049 +:10114000A4A200160A000B0027BD002094A20016DE +:10115000144000068FBF001C3C0208008C42007047 +:10116000244200013C010800AC2200708FB200183C +:101170008FB100148FB0001003E0000827BD0020DD +:1011800027BDFFD8AFB200188F92FFA8AFB10014EF +:10119000AFBF0020AFB3001CAFB000103C02800016 +:1011A000345101008C50010092420000922300094A +:1011B000304400FF2402001F106200AB28620020B0 +:1011C00010400019240200382862000A1040000D67 +:1011D0002402000B286200081040002E8F82001CA1 +:1011E00004600103286200021440002A8F82001C60 +:1011F00024020006106200268FBF00200A00054C62 +:101200008FB3001C106200602862000B144000F9CC +:101210008FBF00202402000E106200788F82001C15 +:101220000A00054C8FB3001C106200D128620039FF +:101230001040000A2402008024020036106200E4FC +:1012400028620037104000C224020035106200D826 +:101250008FBF00200A00054C8FB3001C1062002DC8 +:101260002862008110400006240200C824020039D0 +:10127000106200C88FBF00200A00054C8FB3001C0D +:10128000106200A28FBF00200A00054C8FB3001C23 +:101290008F82001C8C42000C104000D68FBF0020B3 +:1012A0000E000D45000000003C0380003463010087 +:1012B0008C6200008F850018946700089466000C0B +:1012C000ACA200008C6400048F82001C0006340075 +:1012D000ACA400049448001E8C62001800073C0077 +:1012E00000E83825ACA200088C62001C2404000130 +:1012F000ACA2000C9062000A00C23025ACA600101F +:10130000ACA00014ACA00018ACA7001C0A00050B90 +:101310008FBF00208F82001C8C42000C104000B553 +:101320008FBF00200E000D45000000008F82001CC2 +:10133000962400089625000C9443001E0004220207 +:101340009626000E8F8200180004260000832025B8 +:1013500000052C003C03008000A6282500832025E2 +:10136000AC400000AC400004AC400008AC40000CB5 +:10137000AC450010AC400014AC400018AC44001C5C +:101380000A00050A240400019622000C14400018EB +:10139000000000009242000530420010144000148A +:1013A000000000000E0003450200202192420005CB +:1013B00002002021344200100E000350A24200051A +:1013C0009242000024030020304200FF10430088B6 +:1013D000020020218FBF00208FB3001C8FB20018A5 +:1013E0008FB100148FB000100A00103627BD0028FE +:1013F0000000000D0A00054B8FBF00208C42000C3E +:101400001040007C8FBF00200E000D450000000042 +:101410008E2200048F8400189623000CAC820000FA +:101420003C0280089445002C8F82001C00031C00A5 +:1014300030A5FFFF9446001E3C02400E00651825B3 +:1014400000C23025AC830004AC800008AC80000CE6 +:10145000AC800010AC800014AC800018AC86001C7E +:101460000A00050A240400010E00034502002021A1 +:101470008F93FFAC020020210E000350A660000CE9 +:10148000020020210E000355240500018F82001C5C +:101490008C42000C104000578FBF00200E000D45FD +:1014A000000000009622000C8F8300180002140038 +:1014B000AC700000AC620004AC6000088E440038E0 +:1014C0008F82001CAC64000C8E46003C9445001ECC +:1014D0003C02401FAC66001000A228258E6200046A +:1014E00024040001AC620014AC600018AC65001C60 +:1014F0008FBF00208FB3001C8FB200188FB1001473 +:101500008FB000100A000D7927BD002824020020AA +:10151000108200398FB3001C0E000F1F0000000066 +:10152000104000348FBF00203C0380008C6201F823 +:101530000440FFFE24020002AC7001C0A06201C49E +:101540003C021000AC6201F80A00054B8FBF00207E +:10155000020020218FBF00208FB3001C8FB2001823 +:101560008FB100148FB000100A000E6827BD00284C +:101570009625000C020020218FBF00208FB3001C95 +:101580008FB200188FB100148FB000100A000E8DBA +:1015900027BD0028020020218FB3001C8FB2001845 +:1015A0008FB100148FB000100A000EB827BD0028BC +:1015B0009225000D020020218FB3001C8FB200186D +:1015C0008FB100148FB000100A000F0927BD00284A +:1015D000020020218FBF00208FB3001C8FB20018A3 +:1015E0008FB100148FB000100A000EE027BD002854 +:1015F0008FBF00208FB3001C8FB200188FB1001472 +:101600008FB0001003E0000827BD00283C038000D5 +:101610008C6202780440FFFE24020002AC640240A7 +:10162000A06202443C02100003E00008AC620278B1 +:10163000A380001003E00008A38000113C03800099 +:101640008C6202780440FFFE8F820014AC6202407C +:1016500024020002A06202443C02100003E00008E1 +:10166000AC6202783C02600003E000088C42540443 +:101670009083003024020005008040213063003F49 +:101680000000482114620005000050219082004CA7 +:101690009483004E304900FF306AFFFFAD00000C1C +:1016A000AD000010AD000024950200148D05001C53 +:1016B0008D0400183042FFFF004910230002110082 +:1016C000000237C3004038210086202300A2102BDF +:1016D0000082202300A72823AD05001CAD040018BC +:1016E000A5090014A5090020A50A001603E00008BA +:1016F000A50A002203E000080000000027BDFFD873 +:10170000AFB200183C128008AFB40020AFB3001C89 +:10171000AFB10014AFBF0024AFB0001036510100CC +:101720003C0260008C4254049222000C3C140800DD +:10173000929400F7304300FF24020001106200324F +:101740000080982124020002146200353650008087 +:101750000E0013FE000000009202004C2403FF80E4 +:101760003C0480003042007F000211C0244202404D +:101770000262102100431824AC83009492450008B3 +:101780009204004C3042007F3C0380061485000721 +:10179000004380212402FFFFA22200112402FFFF48 +:1017A000A62200120A0005BE2402FFFF96020020B6 +:1017B000A222001196020022A62200128E0200240C +:1017C0003C048008AE2200143485008090A2004CB6 +:1017D00034830100A06200108CA2003CAC620018AF +:1017E0008C820068AC6200E48C820064AC6200E031 +:1017F0008C82006CAC6200E824020001A0A20068A8 +:101800000A0005DA3C0480080E00141700000000EE +:1018100036420080A04000680A0005DA3C048008D7 +:10182000A2000068A20000690A0006153C028008B8 +:10183000348300808C62003834850100AC62006C17 +:1018400024020001A062006990A200C590830008F4 +:10185000305100FF3072007F12320019001111C0A8 +:1018600024420240026210212403FF800043182416 +:101870003C048000AC8300943042007F3C0380062F +:10188000004380218E02000C1040000D0200202138 +:101890000E00056A0000000026220001305100FF02 +:1018A0009203003C023410260002102B0002102389 +:1018B0003063007F022288240A0005E4A203003C72 +:1018C0003C088008350401008C8200D03507008078 +:1018D000ACE2003C8C8200D0AD02000090E5004CF0 +:1018E000908600C590E3004C908400C52402FF80E0 +:1018F00000A228243063007F308400FF00A6282542 +:101900000064182A1060000230A500FF38A500808E +:10191000A0E5004CA10500093C0280089043000EA0 +:10192000344400803C058000A043000A8C830018EA +:101930003C027FFF3442FFFF00621824AC83001892 +:101940008CA201F80440FFFE00000000ACB301C00F +:101950008FBF00248FB400208FB3001C8FB20018FB +:101960008FB100148FB0001024020002A0A201C4A5 +:1019700027BD00283C02100003E00008ACA201F8DB +:1019800090A2000024420001A0A200003C03080035 +:101990008C6300F4304200FF1443000200803021C9 +:1019A000A0A0000090A200008F840014000211C0CB +:1019B0002442024024830040008220212402FF8030 +:1019C000008220243063007F3C02800A00621821DC +:1019D0003C028000AC44002403E00008ACC30000DB +:1019E00094820006908300058C85000C8C86001084 +:1019F0008C8700188C88001C8C8400203C01080017 +:101A0000A42252C63C010800A02352C53C01080094 +:101A1000AC2552CC3C010800AC2652D03C01080059 +:101A2000AC2752D83C010800AC2852DC3C0108002D +:101A3000AC2452E003E00008000000003C028008F3 +:101A4000344201008C4400343C03800034650400BF +:101A5000AC6400388C420038AF850020AC62003C9A +:101A60003C020005AC6200300000000000000000F5 +:101A700003E00008000000003C020006308400FF84 +:101A8000008220253C028000AC44003000000000B1 +:101A900000000000000000003C0380008C62000099 +:101AA000304200101040FFFD3462040003E00008E3 +:101AB000AF82002094C200003C080800950800CACC +:101AC00030E7FFFF0080482101021021A4C200007E +:101AD00094C200003042FFFF00E2102B544000018E +:101AE000A4C7000094A200003C0308008C6300CC53 +:101AF00024420001A4A2000094A200003042FFFF93 +:101B0000144300073C0280080107102BA4A000002A +:101B10005440000101003821A4C700003C028008A5 +:101B2000344601008CC3002894A200003C048000CD +:101B30003042FFFE000210C000621021AC82003C67 +:101B40008C82003C00621823186000040000000032 +:101B50008CC200240A0006A6244200018CC2002484 +:101B6000AC8200383C020050344200103C0380003C +:101B7000AC62003000000000000000000000000027 +:101B80008C620000304200201040FFFD0000000089 +:101B900094A200003C04800030420001000210C00A +:101BA000004410218C430400AD2300008C42040447 +:101BB000AD2200043C02002003E00008AC820030AB +:101BC00027BDFFE0AFB20018AFB10014AFB00010F6 +:101BD000AFBF001C94C2000000C080213C1208006E +:101BE000965200C624420001A6020000960300009F +:101BF00094E2000000E03021144300058FB1003072 +:101C00000E00067B024038210A0006DD00000000BD +:101C10008C8300048C82000424420040046100078D +:101C2000AC8200048C820004044000040000000028 +:101C30008C82000024420001AC8200009602000069 +:101C40003042FFFF50520001A60000009622000023 +:101C500024420001A62200003C0280083442010018 +:101C6000962300009442003C144300048FBF001CE4 +:101C700024020001A62200008FBF001C8FB20018B2 +:101C80008FB100148FB0001003E0000827BD0020C2 +:101C900027BDFFE03C028008AFBF001834420100BE +:101CA0008C4800343C03800034690400AC68003880 +:101CB0008C42003830E700FFAF890020AC62003C66 +:101CC0003C020005AC620030000000000000000093 +:101CD0000000000000000000000000000000000004 +:101CE0008C82000C8C82000C9783000EAD220000C9 +:101CF0008C82001000604021AD2200048C8200180C +:101D0000AD2200088C82001CAD22000C8CA20014B5 +:101D1000AD2200108C820020AD22001490820005BC +:101D2000304200FF00021200AD2200188CA2001801 +:101D3000AD22001C8CA2000CAD2200208CA2001051 +:101D4000AD2200248CA2001CAD2200288CA2002011 +:101D5000AD22002C3402FFFFAD260030AD20003450 +:101D6000506200013408FFFFAD28003850E0001138 +:101D70003C0280083C0480083484010094820050B6 +:101D80003042FFFFAD22003C948300449485004420 +:101D9000240200013063FFFF000318C20064182111 +:101DA0009064005430A5000700A210040A00074800 +:101DB0000044102534420100AD20003C944300440F +:101DC000944400443063FFFF000318C200621821EE +:101DD0003084000790650054240200010082100442 +:101DE0000002102700451024A062005400000000EB +:101DF00000000000000000003C02000634420040E9 +:101E00003C038000AC6200300000000000000000D5 +:101E1000000000008C620000304200101040FFFD06 +:101E20003C06800834C201503463040034C7014AC0 +:101E300034C4013434C5014034C60144AFA200109B +:101E40000E0006BEAF8300208FBF001803E000081D +:101E500027BD00208F83000C3C0608008CC600E8DC +:101E60008F82001430633FFF000319800046102169 +:101E7000004310212403FF80004318243C06800007 +:101E8000ACC300283042007F3C03800C004330216B +:101E900090C2000D30A500FF000038213442001030 +:101EA000A0C2000D8F89000C3C0280083442010062 +:101EB00094430044000913823048000324020001C7 +:101EC000A4C3000E1102000B2902000210400005FD +:101ED000240200021100000C240300010A000790F4 +:101EE0000000182111020006000000000A000790FF +:101EF000000018218CC2002C0A0007902443000126 +:101F00008CC20014244300018CC200180043102B23 +:101F10005040000A240700012402002714A20003F5 +:101F20003C0380080A00079D240700013463010078 +:101F30009462004C24420001A462004C0009138208 +:101F4000304300032C620002104000090080282169 +:101F5000146000040000000094C200340A0007ADC1 +:101F60003046FFFF8CC600380A0007AD00802821EC +:101F7000000030213C040800248452C00A0006F20C +:101F80000000000027BDFF90AFB60068AFB5006449 +:101F9000AFB40060AFB3005CAFB20058AFB1005453 +:101FA000AFBF006CAFB000508C9000000080B0213B +:101FB0003C0208008C4200E8960400328F83001433 +:101FC0002414FF8030843FFF006218210004218028 +:101FD00000641821007410243C13800000A090219C +:101FE00090A50000AE620028920400323C02800CF2 +:101FF0003063007F00628821308400C024020040EA +:10200000148200320000A8218E3500388E2200187C +:102010001440000224020001AE2200189202003C8B +:10202000304200201440000E8F830014000511C0C0 +:102030002442024000621821306400783C02008093 +:102040000082202500741824AE630800AE640810D6 +:102050008E2200188E03000800431021AE220018C3 +:102060008E22002C8E230018244200010062182BBF +:102070001060004300000000924200002442000172 +:10208000A24200003C0308008C6300F4304200FFD1 +:1020900050430001A2400000924200008F840014CF +:1020A000000211C024420240248300403063007FBC +:1020B000008220213C02800A009420240062182122 +:1020C000AE6400240A0008BEAEC3000092030032D2 +:1020D0002402FFC000431024304200FF14400005DA +:1020E00024020001AE220018962200340A00082EB5 +:1020F0003055FFFF8E22001424420001AE2200184A +:102100009202003000021600000216030441001C77 +:10211000000000009602003227A400100080282151 +:10212000A7A2001696020032000030212407000109 +:102130003042FFFFAF82000C0E0006F2AFA0001C81 +:10214000960200328F8300143C0408008C8400E85F +:1021500030423FFF00021180006418210062182104 +:1021600000741024AE62002C3063007F3C02800EAD +:10217000006218219062000D3042007FA062000DC5 +:102180009222000D30420010504000789242000030 +:102190003C028008344401009482004C8EC300004D +:1021A0003C130800967300C62442FFFFA482004C33 +:1021B000946200329623000E3054FFFF3070FFFF10 +:1021C0003C0308008C6300D000701807A7A30038F8 +:1021D0009482003E3063FFFF3042FFFF146200072D +:1021E000000000008C8200303C038000244200305C +:1021F000AC62003C0A0008568C82002C948200409D +:102200003042FFFF5462000927A400408C8200384E +:102210003C03800024420030AC62003C8C820034DD +:10222000AC6200380A0008653C03800027A500382E +:1022300027A60048026038210E00067BA7A00048B0 +:102240008FA300403C02800024630030AC43003880 +:102250008FA30044AC43003C3C0380003C020005DB +:10226000AC6200303C028008344401009482004299 +:10227000346304003042FFFF0202102B14400007B9 +:10228000AF8300209482004E94830042020210210A +:10229000004310230A00087B3043FFFF9483004E65 +:1022A0009482004202631821005010230062182318 +:1022B0003063FFFF3C028008344401009482003CFC +:1022C0003042FFFF14430003000000000A00088BA7 +:1022D000240300019482003C3042FFFF0062102B77 +:1022E000144000058F8200209482003C006210237D +:1022F0003043FFFF8F820020AC550000AC4000044B +:10230000AC540008AC43000C3C0200063442001000 +:102310003C038000AC6200300000000000000000C0 +:10232000000000008C620000304200101040FFFDF1 +:102330003C04800834840100001018C20064182195 +:102340009065005432020007240600010046100484 +:1023500000451025A0620054948300429622000E8E +:1023600050430001A3860010924200002442000165 +:10237000A24200003C0308008C6300F4304200FFDE +:1023800050430001A2400000924200008F840014DC +:10239000000211C024420240248300400082202118 +:1023A0002402FF80008220243063007F3C02800AE8 +:1023B000006218213C028000AC440024AEC300003F +:1023C0008FBF006C8FB600688FB500648FB400605B +:1023D0008FB3005C8FB200588FB100548FB00050A3 +:1023E00003E0000827BD007027BDFFD8AFB3001C75 +:1023F000AFB20018AFB10014AFB00010AFBF0020F3 +:102400000080982100E0802130B1FFFF0E000D45D3 +:1024100030D200FF000000000000000000000000BB +:102420008F8200188F83001CAC510000AC52000456 +:10243000AC530008AC40000CAC400010AC400014A1 +:10244000AC4000189463001E02038025AC50001CB1 +:102450000000000000000000000000002404000153 +:102460008FBF00208FB3001C8FB200188FB10014F3 +:102470008FB000100A000D7927BD002830A5FFFF9E +:102480000A0008C830C600FF3C028008344301003F +:102490009462000E3C080800950800C63046FFFF15 +:1024A00014C000043402FFFF946500DA0A00091525 +:1024B0008F84001410C20027000000009462004EB8 +:1024C0009464003C3045FFFF00A6102300A6182BA3 +:1024D0003087FFFF106000043044FFFF00C5102369 +:1024E00000E210233044FFFF0088102B1040000E44 +:1024F00000E810233C02800834440100240300015A +:1025000034420080A44300162402FFFFA482000E80 +:10251000948500DA8F8400140000302130A5FFFF7D +:102520000A0008ED3C0760200044102A1040000912 +:102530003C0280083443008094620016304200015F +:10254000104000043C0280009442007E24420014AB +:10255000A462001603E000080000000027BDFFE0B1 +:102560003C028008AFBF001CAFB00018344201002D +:10257000944300429442004C104000193068FFFF21 +:102580009383001024020001146200298FBF001CF5 +:102590003C06800834D00100000810C20050102111 +:1025A000904200543103000734C70148304200FF15 +:1025B000006210073042000134C9014E34C4012CBE +:1025C00034C5013E1040001634C601420E0006BE5E +:1025D000AFA90010960200420A0009323048FFFFFE +:1025E0003C028008344401009483004494820042F9 +:1025F0001043000F8FBF001C94820044A48200424D +:1026000094820050A482004E8C820038AC8200304C +:1026100094820040A482003E9482004AA482004832 +:102620008FBF001C8FB000180A0008F027BD0020E3 +:102630008FB0001803E0000827BD002027BDFFA0D1 +:10264000AFB1004C3C118000AFBF0058AFB3005495 +:10265000AFB20050AFB000483626018890C20003E8 +:102660003044007FA3A400108E32018090C200008D +:102670003043007F240200031062003BAF9200143D +:102680002862000410400006240200042402000214 +:10269000106200098FBF00580A000AFB8FB3005474 +:1026A0001062004D240200051062014E8FBF0058D9 +:1026B0000A000AFB8FB30054000411C0024210212B +:1026C0002404FF802442024000441024264300409A +:1026D000AE2200243063007F3C02800A0062182191 +:1026E0009062003CAFA3003C00441025A062003C77 +:1026F0008FA3003C9062003C304200401040016CCF +:102700008FBF00583C108008A380001036100100D5 +:102710008E0200D08C63003427A4003C27A5001053 +:10272000004310210E0007AFAE0200D093A20010AC +:102730003C038000A20200C58C6202780440FFFEC8 +:102740008F820014AC62024024020002A0620244A4 +:102750003C021000AC6202780E0009250000000067 +:102760000A000AFA8FBF00583C05800890C3000198 +:1027700090A2000B1443014E8FBF005834A4008078 +:102780008C8200189082004C90A200083C026000ED +:102790008C4254048C8300183C027FFF3442FFFFBC +:1027A000006218243C0208008C4200B4AC8300187C +:1027B0003C038000244200013C010800AC2200B42C +:1027C0008C6201F80440FFFE8F820014AC6201C0ED +:1027D0000A000AC2240200023C10800890C30001D3 +:1027E0009202000B144301328FBF005827A4001837 +:1027F00036050110240600033C0260008C4254049C +:102800000E000E080000000027A40028360501E095 +:102810000E000E08240600038FA2002836030100D4 +:10282000AE0200648FA2002CAE0200688FA20030BE +:10283000AE02006C93A40018906300C52402FF80D0 +:102840000082102400431025304900FF3084007FAF +:102850003122007F0082102A544000013929008073 +:10286000000411C0244202402403FF8002421021D0 +:1028700000431024AE220094264200403042007FE4 +:102880003C038006004340218FA3001C2402FFFF6D +:10289000AFA800403C130800927300F710620033A9 +:1028A00093A2001995030014304400FF3063FFFF2A +:1028B0000064182B10600010000000009504001444 +:1028C0008D07001C8D0600183084FFFF0044202374 +:1028D0000004210000E438210000102100E4202B36 +:1028E00000C2302100C43021AD07001CAD06001825 +:1028F0000A000A1B93A20019950400148D07001CFE +:102900008D0600183084FFFF008220230004210080 +:10291000000010210080182100C2302300E4202B89 +:1029200000C4302300E33823AD07001CAD060018B7 +:1029300093A200198FA30040A462001497A2001A6A +:10294000A46200168FA2001CAC6200108FA2001CB3 +:10295000AC62000C93A20019A462002097A2001A96 +:10296000A46200228FA2001CAC6200243C048008F8 +:10297000348300808C6200388FA2002001208821DF +:10298000AC62003C8FA20020AC82000093A2001831 +:10299000A062004C93A20018A0820009A060006809 +:1029A00093A20018105100512407FF803229007FA4 +:1029B000000911C024420240024210213046007F2B +:1029C0003C03800000471024AC6200943C02800667 +:1029D00000C2302190C2003CAFA600400000202180 +:1029E00000471025A0C2003C8FA8004095020002BD +:1029F000950300148D07001C3042FFFF3063FFFF7A +:102A00008D060018004310230002110000E2382157 +:102A100000E2102B00C4302100C23021AD07001CA1 +:102A2000AD06001895020002A5020014A5000016CC +:102A30008D020008AD0200108D020008AD02000CEE +:102A400095020002A5020020A50000228D020008C8 +:102A5000AD0200249102003C304200401040001AB8 +:102A6000262200013C108008A3A90038A380001092 +:102A7000361001008E0200D08D03003427A40040E0 +:102A800027A50038004310210E0007AFAE0200D08A +:102A900093A200383C038000A20200C58C62027839 +:102AA0000440FFFE8F820014AC6202402402000248 +:102AB000A06202443C021000AC6202780E000925BC +:102AC00000000000262200013043007F1473000440 +:102AD000004020212403FF800223102400432026ED +:102AE00093A200180A000A37309100FF93A400183F +:102AF0008FA3001C2402FFFF1062000A308900FF30 +:102B000024820001248300013042007F1453000519 +:102B1000306900FF2403FF80008310240043102647 +:102B2000304900FF3C0280089042000801208821C3 +:102B3000305000FF123000193222007F000211C015 +:102B400002421021244202402403FF800043182443 +:102B50003C048000AC8300943042007F3C0380063C +:102B6000004310218C43000C004020211060000B1A +:102B7000AFA200400E00056A0000000026230001FD +:102B80002405FF803062007F1453000202252024B8 +:102B9000008518260A000A9B307100FF3C0480085B +:102BA000348400808C8300183C027FFF3442FFFF96 +:102BB00000621824AC8300183C0380008C6201F88A +:102BC0000440FFFE00000000AC7201C024020002BD +:102BD000A06201C43C021000AC6201F80A000AFACB +:102BE0008FBF00583C04800890C300019082000B06 +:102BF0001443002F8FBF00583490008092020008C9 +:102C00003042004010400020000000009202000806 +:102C100000021600000216030441000502402021B4 +:102C20000E000E8D240500930A000AFA8FBF00588B +:102C30009202000924030018304200FF1443000DE3 +:102C400002402021240500390E000E25000030210D +:102C50000E0003458F8400148F82FFA82403001206 +:102C6000A04300090E0003508F8400140A000AFAE2 +:102C70008FBF0058240500360E000E2500003021BD +:102C80000A000AFA8FBF00580E00034502402021B7 +:102C9000920200058F840014344200200E0003507D +:102CA000A20200050E0010368F8400148FBF00585A +:102CB0008FB300548FB200508FB1004C8FB00048DA +:102CC00003E0000827BD00603C0280083445010095 +:102CD0003C0280008C42014094A3000E0000302191 +:102CE00000402021AF8200143063FFFF3402FFFF59 +:102CF000106200063C0760202402FFFFA4A2000E21 +:102D000094A500DA0A0008ED30A5FFFF03E00008F3 +:102D10000000000027BDFFC83C0280003C06800880 +:102D2000AFB5002CAFB1001CAFBF0030AFB400286E +:102D3000AFB30024AFB20020AFB00018345101008F +:102D400034C501008C4301008E2200148CA400D4F1 +:102D50000000A821AF830014004410231840005243 +:102D6000A38000108E22001400005021ACA200D4D9 +:102D700090C3000890A200C53073007FA3A200108A +:102D80008CB200D08CB400D4304200FF1053003B12 +:102D900093A200108F8300142407FF80000211C04B +:102DA00000621021244202402463004000471024A6 +:102DB0003063007F3C0980003C08800A00681821CD +:102DC000AD2200248C62003427A4001427A5001033 +:102DD000024280210290102304400028AFA3001477 +:102DE0009062003C00E21024304200FF14400019C1 +:102DF000020090219062003C34420040A062003CFE +:102E00008F86001493A3001024C200403042007F3C +:102E1000004828213C0208008C4200F42463000191 +:102E2000306400FF14820002A3A30010A3A00010CE +:102E300093A20010AFA50014000211C0244202406A +:102E400000C2102100471024AD2200240A000B31DB +:102E500093A200100E0007AF000000003C028008A3 +:102E600034420100AC5000D093A30010240A0001AA +:102E7000A04300C50A000B3193A2001024020001F8 +:102E8000154200093C0380008C6202780440FFFE7A +:102E90008F820014AC62024024020002A06202444D +:102EA0003C021000AC6202789222000B2403000264 +:102EB000304200FF14430072000000009622000818 +:102EC000304300FF24020082146200402402008488 +:102ED0003C028000344901008D22000C952300063D +:102EE000000216023063FFFF3045003F2402002736 +:102EF00010A2000FAF83000C28A200281040000889 +:102F0000240200312402002110A20009240200251D +:102F100010A20007938200110A000BA90000000014 +:102F200010A20007938200110A000BA90000000004 +:102F30000E000763012020210A000C290000000078 +:102F40003C0380008C6202780440FFFE8F820014F4 +:102F5000AC62024024020002A06202443C02100063 +:102F6000AC6202780A000C290000000095230006DC +:102F7000912400058D25000C8D2600108D2700184A +:102F80008D28001C8D290020244200013C010800EE +:102F9000A42352C63C010800A02452C53C010800ED +:102FA000AC2552CC3C010800AC2652D03C010800B4 +:102FB000AC2752D83C010800AC2852DC3C01080088 +:102FC000AC2952E00A000C29A38200111462000A05 +:102FD000240200813C02800834420100944500DA5A +:102FE000922600058F84001430A5FFFF30C600FF35 +:102FF0000A000BEA3C0760211462005C000000003C +:103000009222000A304300FF306200201040000787 +:10301000306200403C02800834420100944500DAEE +:103020008F8400140A000BE82406004010400007BB +:10303000000316003C02800834420100944500DA87 +:103040008F8400140A000BE82406004100021603D6 +:10305000044100463C02800834420100944500DAF5 +:103060008F8400142406004230A5FFFF3C0760193E +:103070000E0008ED000000000A000C29000000000E +:103080009222000B24040016304200FF1044000678 +:103090003C0680009222000B24030017304200FF00 +:1030A000144300320000000034C5010090A2000B60 +:1030B000304200FF1444000B000080218CA200204D +:1030C0008CA400202403FF80004310240002114040 +:1030D0003084007F004410253C032000004310256D +:1030E000ACC2083094A200080002140000021403CD +:1030F000044200012410000194A200083042008024 +:103100005040001A0200A82194A20008304220007A +:10311000504000160200A8218CA300183C021C2D70 +:10312000344219ED106200110200A8213C0208008F +:103130008C4200D4104000053C02800824030004A7 +:1031400034420100A04300EC3C02800834420100FC +:10315000944500DA8F8400142406000630A5FFFF92 +:103160000E0008ED3C0760210200A8210E00092591 +:10317000000000009222000A3042000810400004C3 +:1031800002A010210E00133A0000000002A010213E +:103190008FBF00308FB5002C8FB400288FB3002470 +:1031A0008FB200208FB1001C8FB0001803E0000820 +:1031B00027BD00382402FF80008220243C029000BA +:1031C00034420007008220253C028000AC440020ED +:1031D0003C0380008C6200200440FFFE00000000E1 +:1031E00003E00008000000003C0380002402FF8090 +:1031F000008220243462000700822025AC64002075 +:103200008C6200200440FFFE0000000003E0000884 +:10321000000000003C028008240300053442010045 +:10322000A04300EC3C0280008C4201003C03800083 +:10323000AF8200148C6202780440FFFE8F8200147B +:10324000AC62024024020002A06202443C02100070 +:10325000AC62027803E000080000000027BDFFE830 +:103260003C068000AFBF001034C7010094E20008A4 +:10327000304400FF38830082388200842C630001D0 +:103280002C420001006218251060002D24020083EA +:1032900093820011504000368FBF00103C0208009E +:1032A000904252CC8CC401003C06080094C652C621 +:1032B0003045003F38A3003238A2003F2C630001A4 +:1032C0002C42000100621825AF840014AF86000C68 +:1032D000A38000111460000700E0202124020020D8 +:1032E00014A20012000000003402FFFF14C2000FFD +:1032F000000000002402002014A2000500E02821A4 +:103300008CE300142402FFFF5062000B8FBF0010FB +:103310003C040800248452C0000030210E0006F254 +:10332000240700010A000C9C8FBF00100E000763E9 +:10333000000000008FBF00100A00092527BD0018FB +:10334000148200062482FF808CC301043C026020AA +:10335000AC4300140A000CD28FBF0010304200FFB3 +:103360002C42000210400004240200228FBF0010F3 +:103370000A000B1327BD0018148200048F82001C62 +:103380008FBF00100A000C5327BD00188C42000CA0 +:103390001040001E00E0282190E3000924020018DC +:1033A00014620003240200160A000CBD2403000866 +:1033B0001462000724020017240300123C02800854 +:1033C00034420080A04300090A000CCA94A70008F8 +:1033D0005462000794A700088F82FFA82404FFFE10 +:1033E0009043000500641824A043000594A700083A +:1033F00090A6001B8CA4000094A500068FBF0010AF +:1034000000073C000A0008C827BD00188FBF001045 +:1034100003E0000827BD00188F85001C3C048000D5 +:1034200094A2002A8CA30034000230C02402FFF0D2 +:1034300000C2102400621821AC83003C8CA2003032 +:103440003C038000AC8200383C0200503442001043 +:10345000AC6200300000000000000000000000002E +:103460008C620000304200201040FFFD30C2000896 +:10347000104000063C0280008C620408ACA20020D0 +:103480008C62040C0A000CF5ACA200248C430400EE +:10349000ACA300208C420404ACA200243C03002016 +:1034A0003C028000AC4300303C0480008C82003041 +:1034B000004310241440FFFD8F86001C3C02004096 +:1034C000AC82003094C3002A94C2002894C4002C1B +:1034D00094C5002E24630001004410213064FFFFD6 +:1034E000A4C2002814850002A4C3002AA4C0002A94 +:1034F00003E00008000000008F84001C27BDFFE8E7 +:103500003C05800424840010AFBF00100E000E089C +:103510002406000A8F84001C948200129483002EDB +:103520003042000F244200030043180424027FFFAE +:103530000043102B10400002AC8300000000000D7F +:103540000E000CD4000000008F83001C8FBF001001 +:1035500027BD0018946200149463001A3042000FD3 +:1035600000021500006218253C02800003E00008FC +:10357000AC4300A08F83001C3C02800494440006EE +:103580009462001A8C650000A464001600441023A5 +:103590003042FFFF0045102B03E0000838420001D5 +:1035A0008F84001C3C0780049486001A8C850000E0 +:1035B00094E20006A482001694E3000600C31023E0 +:1035C0003042FFFF0045102B384200011440FFF845 +:1035D000A483001603E00008000000008F84001C94 +:1035E0003C028004944200069483001A8C850000FB +:1035F000A4820016006210233042FFFF0045102B0A +:10360000384200015040000D8F85001C00603021C1 +:103610003C07800494E20006A482001694E30006AE +:1036200000C310233042FFFF0045102B3842000139 +:103630001440FFF8A48300168F85001C3C03800013 +:10364000346204008CA40020AF820018AC640038FF +:103650008CA20024AC62003C3C020005AC6200304D +:1036600003E00008ACA000048F84001C3C030006AB +:103670008C82000400021140004310253C038000AE +:10368000AC620030000000000000000000000000FC +:103690008C620000304200101040FFFD34620400D4 +:1036A000AC80000403E00008AF8200188F86001C85 +:1036B00027BDFFE0AFB10014AFB00010AFBF0018DE +:1036C0008CC300048CC500248F820018309000FF4A +:1036D00094C4001A246300012442002024840001C1 +:1036E00024A70020ACC30004AF820018A4C4001AB1 +:1036F000ACC7002404A100060000882104E20005F4 +:1037000094C2001A8CC2002024420001ACC20020E6 +:1037100094C2001A94C300282E040001004310260E +:103720002C420001004410245040000594C2001AAD +:1037300024020001ACC2000894C2001A94C30028FD +:103740000010202B004310262C42000100441025BD +:1037500014400007000000008CC200081440000460 +:10376000240200108CC300041462000F8F85001C1B +:103770000E000D68241100018F82001C9443002864 +:103780009442001A14430003000000000E000CD401 +:1037900000000000160000048F85001C0E000D457F +:1037A000000000008F85001C94A2001E94A4001C41 +:1037B000244200013043FFFF14640002A4A2001E53 +:1037C000A4A0001E1200000A3C02800494A200146F +:1037D00094A3001A3042000F000215000062182561 +:1037E0003C028000AC4300A00A000DDFACA0000842 +:1037F0009442000694A3001A8CA40000A4A2001610 +:10380000006210233042FFFF0044102B38420001B9 +:103810001040000D02201021006030213C07800480 +:1038200094E20006A4A2001694E3000600C310234D +:103830003042FFFF0044102B384200011440FFF8D3 +:10384000A4A30016022010218FBF00188FB100140E +:103850008FB0001003E0000827BD002003E000083F +:10386000000000008F8200243C030006000211408B +:10387000004310253C038000AC62003000000000D3 +:1038800000000000000000008C62000030420010C8 +:103890001040FFFD34620400AF82002003E0000806 +:1038A000AF80002403E000080000102103E00008BE +:1038B000000000003084FFFF30A5FFFF000018214A +:1038C000108000070000000030820001104000025C +:1038D00000042042006518210A000DFE0005284062 +:1038E00003E000080060102110C0000624C6FFFF9E +:1038F0008CA2000024A50004AC8200000A000E087F +:103900002484000403E000080000000010A0000868 +:1039100024A3FFFFAC8600000000000000000000B0 +:103920002402FFFF2463FFFF1462FFFA24840004D3 +:1039300003E00008000000003C02800834420080E0 +:1039400024030001AC43000CA4430010A443001264 +:10395000A443001403E00008A44300168F82001C57 +:1039600027BDFFD8AFB3001CAFB20018AFB1001431 +:10397000AFB00010AFBF00208C47000C2482008045 +:103980002409FF803C08800E3043007F00808021A6 +:103990003C0A8000004920240068182130B100FF53 +:1039A00030D200FF10E0002900009821260201001B +:1039B000AD44002C004928243042007F00482021DB +:1039C0009062000024030050304200FF14430004C2 +:1039D00000000000AD45002C948200DA3053FFFF58 +:1039E0000E000D45000000008F82001C8F83001820 +:1039F00000112C009442001E0012240034840001A7 +:103A000000A228253C02400000A22825AC7000003E +:103A10008FBF0020AC6000048FB20018AC730008A8 +:103A20008FB10014AC60000C8FB3001CAC640010AC +:103A30008FB00010AC60001424040001AC600018CA +:103A400027BD00280A000D79AC65001C8FBF00203F +:103A50008FB3001C8FB200188FB100148FB000100C +:103A600003E0000827BD00283C06800034C20100A6 +:103A70009043000F240200101062000E2865001110 +:103A800010A0000724020012240200082405003AB6 +:103A9000106200060000302103E000080000000072 +:103AA000240500351462FFFC000030210A000E25B9 +:103AB000000000008CC200748F83FFA824420FA076 +:103AC00003E00008AC62000C27BDFFE8AFBF0010A8 +:103AD0000E000355240500013C0480088FBF001030 +:103AE0002402000134830080A462001227BD001864 +:103AF0002402000103E00008A080001A27BDFFE0B7 +:103B0000AFB20018AFB10014AFB00010AFBF001CCF +:103B100030B2FFFF0E000345008088213C02800880 +:103B2000345000809202000924030004304200FF58 +:103B30001443000C3C028008124000082402000AD2 +:103B40000E000E1C00000000920200052403FFFE80 +:103B500000431024A202000524020012A202000960 +:103B60003C02800834420080022020210E000350D5 +:103B7000A040002716400003022020210E000E80E6 +:103B80000000000002202021324600FF8FBF001CF1 +:103B90008FB200188FB100148FB0001024050038C8 +:103BA0000A000E2527BD002027BDFFE0AFBF001C87 +:103BB000AFB20018AFB10014AFB000100E00034553 +:103BC000008080210E000E1C000000003C028008D6 +:103BD0003445008090A2000924120018305100FFE3 +:103BE000123200030200202124020012A0A20009C8 +:103BF00090A200052403FFFE004310240E00035092 +:103C0000A0A2000502002021240500201632000792 +:103C1000000030218FBF001C8FB200188FB100143C +:103C20008FB000100A00035527BD00208FBF001C75 +:103C30008FB200188FB100148FB000102405003926 +:103C40000A000E2527BD002027BDFFE83C028000AA +:103C5000AFB00010AFBF0014344201009442000C1A +:103C6000240500360080802114400012304600FFF9 +:103C70000E000345000000003C0280083442008032 +:103C800024030012A0430009904300053463001090 +:103C90000E000E1CA04300050E0003500200202160 +:103CA000020020210E000355240500200A000EFD0D +:103CB000000000000E000E25000000000E0003456D +:103CC000020020213C0280089043001B2405FF9F36 +:103CD00002002021006518248FBF00148FB000104F +:103CE000A043001B0A00035027BD001827BDFFE0BA +:103CF000AFBF0018AFB10014AFB0001030B100FF7B +:103D00000E000345008080213C028008240300123D +:103D1000344200800E000E1CA04300090E00035028 +:103D20000200202102002021022030218FBF001834 +:103D30008FB100148FB00010240500350A000E2545 +:103D400027BD00203C0480089083000E9082000A6A +:103D50001443000B000028218F82FFA82403005089 +:103D60002405000190420000304200FF144300048B +:103D7000000000009082000E24420001A082000E8C +:103D800003E0000800A010213C0380008C6201F8D1 +:103D90000440FFFE24020002AC6401C0A06201C422 +:103DA0003C02100003E00008AC6201F827BDFFE010 +:103DB000AFB200183C128008AFB10014AFBF001CB6 +:103DC000AFB0001036510080922200092403000A8F +:103DD000304200FF1443003E000000008E43000408 +:103DE0008E220038506200808FBF001C922200009B +:103DF00024030050304200FF144300253C028000A1 +:103E00008C4201408E4300043642010002202821EA +:103E1000AC43001C9622005C8E2300383042FFFF2A +:103E20000002104000621821AE23001C8E430004E3 +:103E30008E2400389622005C006418233042FFFF75 +:103E400000031843000210400043102A10400006EF +:103E5000000000008E4200048E230038004310232F +:103E60000A000F6B000220439622005C3042FFFFE5 +:103E7000000220403C0280083443010034420080AC +:103E8000ACA4002CA040002424020001A062000C7D +:103E90000E000F1F00000000104000538FBF001CD9 +:103EA0003C0280008C4401403C0380008C6201F89D +:103EB0000440FFFE24020002AC6401C0A06201C401 +:103EC0003C021000AC6201F80A000FC88FBF001C52 +:103ED0009222000924030010304200FF1443000422 +:103EE0003C0280008C4401400A000FAF00002821F2 +:103EF0009222000924030016304200FF14430006FA +:103F000024020014A22200093C0280008C440140DB +:103F10000A000FC28FBF001C8E2200388E23003C87 +:103F200000431023044100308FBF001C9222002761 +:103F300024420001A2220027922200272C420004E2 +:103F4000144000163C108000922200092403000453 +:103F5000304200FF144300093C0280008C440140C1 +:103F60008FBF001C8FB200188FB100148FB00010EB +:103F7000240500930A000E8D27BD00208C440140CB +:103F8000240500938FBF001C8FB200188FB100145E +:103F90008FB000100A000F0927BD00208E040140D9 +:103FA0000E000345000000008E4200042442FFFF83 +:103FB000AE4200048E22003C2442FFFFAE22003CB1 +:103FC0000E0003508E0401408E0401408FBF001C80 +:103FD0008FB200188FB100148FB0001024050004B8 +:103FE0000A00035527BD00208FB200188FB10014BE +:103FF0008FB0001003E0000827BD00203C068000C1 +:104000008CC201883C038008346500809063000EF8 +:1040100000021402304400FF306300FF1464000EFD +:104020003C02800890A20026304200FF10440009A4 +:104030008F82FFA8A0A40026240300509042000015 +:10404000304200FF14430006000000000A00058D06 +:104050008CC401803C02800834420080A0440026C9 +:1040600003E000080000000027BDFFE030E700FF8C +:10407000AFB20018AFBF001CAFB10014AFB000105A +:104080000080902114E0000630C600FF0000000010 +:104090000000000D000000000A0010212400010EA5 +:1040A0003C0380089062000E304200FF144600235B +:1040B0003462008090420026304200FF1446001F08 +:1040C000000000009062000F304200FF1446001B09 +:1040D000000000009062000A304200FF1446000316 +:1040E0008F90FFA80000000D8F90FFA88F82FFAC7B +:1040F0003C118000AE05003CAC450000A066000A03 +:104100000E0003458E240100A20000240E0003507F +:104110008E2401003C0380008C6201F80440FFFE05 +:1041200024020002AC7201C0A06201C43C02100073 +:10413000AC6201F80A0010228FBF001C00000000D2 +:104140000000000D00000000240001378FBF001C9C +:104150008FB200188FB100148FB0001003E0000878 +:1041600027BD00208F83FFA83C0280008C44010003 +:10417000344201008C65003C9046001B0A000FE8A9 +:10418000240700013C0280089043000E9042000A80 +:1041900000431026304200FF03E000080002102B0D +:1041A00027BDFFE03C028008AFB10014AFB00010A3 +:1041B000AFBF001834500080920200052403003085 +:1041C0003042003014430085008088218F82001C1B +:1041D0008C42000C104000828FBF00180E000D456D +:1041E000000000008F860018ACD100009202000889 +:1041F00092030009304200FF00021200306300FF0A +:1042000000431025ACC200049202004D00021600CB +:104210000002160304410005000000003C030800F2 +:104220008C6300480A0010603C108008920200086D +:104230003042004014400003000018219202002781 +:10424000304300FF3C108008361100809222004D60 +:1042500000031E00304200FF000214000062182517 +:10426000ACC300088E2400308F82001CACC4000C4C +:104270008E2500349443001E3C02C00BACC50010D8 +:10428000006218258E22003800002021ACC20014E4 +:104290008E22003CACC200180E000D79ACC3001C8D +:1042A0008E0200048F8400183C058000AC82000060 +:1042B0008E220020AC8200048E22001CAC820008FA +:1042C0008E2200588CA3007400431021AC82000C95 +:1042D0008E22002CAC8200108E2200408E230044DF +:1042E0000002140000431025AC8200149222004DFD +:1042F00024030080304200FF14430004000000004B +:10430000AC8000180A0010A48F82001C8E23000CC1 +:10431000240200011062000E2402FFFF9222000816 +:10432000304200401440000A2402FFFF8E23000C9C +:104330008CA20074006218233C0208000062102462 +:1043400014400002000028210060282100051043CD +:10435000AC8200188F82001C000020219443001EB4 +:104360003C02C00C006218258F8200180E000D79E7 +:10437000AC43001C3C038008346201008C42000006 +:104380008F850018346300808FBF0018ACA2000036 +:10439000ACA000048C6400488F82001C8FB1001414 +:1043A000ACA40008ACA0000CACA000109063000509 +:1043B0009446001E3C02400D00031E0000C2302542 +:1043C000ACA300148FB00010ACA0001824040001AE +:1043D000ACA6001C0A000D7927BD00208FBF001875 +:1043E0008FB100148FB0001003E0000827BD00203B +:1043F0003C0280009443007C3C028008344601006B +:10440000308400FF3065FFFF2402000524A34650DE +:10441000A0C4000C5482000C3065FFFF90C2000D58 +:104420002C4200071040000724A30A0090C3000D8F +:10443000240200140062100400A210210A0010E0FF +:104440003045FFFF3065FFFF3C02800834420080AA +:1044500003E00008A44500143C0380083468008091 +:10446000AD050038346701008CE2001C308400FF89 +:1044700000A210231840000330C600FF24A2FFFC56 +:10448000ACE2001C30820001504000083C03800870 +:104490008D02003C00A210230441001224040005F8 +:1044A0008C62000410A2000F3C0380088C620004A0 +:1044B00014A2001E000000003C0208008C4200D83C +:1044C00030420020104000093C0280083462008025 +:1044D000906300089042004C144300043C028008A2 +:1044E000240400040A0010CA0000000034430080C5 +:1044F00034420100A040000C24020001A462001418 +:1045000010C0000A3C0280008C4401003C03800083 +:104510008C6201F80440FFFE24020002AC6401C07A +:10452000A06201C43C021000AC6201F803E0000884 +:104530000000000027BDFFE800A61823AFBF001051 +:1045400018600080308800FF3C02800834470080FB +:10455000A0E0002434440100A0E000278C82001C6D +:1045600000A2102304400056000000008CE2003C32 +:1045700094E3005C8CE4002C004530233063FFFFA3 +:1045800000C318210083202B1080000400E01821B4 +:104590008CE2002C0A00113900A2102194E2005C88 +:1045A0003042FFFF00C2102100A21021AC62001CAB +:1045B0003C028008344400809482005C8C83001CA0 +:1045C0003042FFFF0002104000A210210043102BD8 +:1045D00010400004000000008C82001C0A00114CF6 +:1045E0003C0680089482005C3042FFFF00021040CD +:1045F00000A210213C06800834C3010034C70080AB +:10460000AC82001CA060000CACE500388C62001C81 +:1046100000A210231840000224A2FFFCAC62001C80 +:1046200031020001104000083C0380088CE2003C8D +:1046300000A2102304410012240400058CC20004CF +:1046400010A200108FBF00108C62000414A2004F53 +:104650008FBF00103C0208008C4200D8304200207E +:104660001040000A3C028008346200809063000819 +:104670009042004C144300053C02800824040004CE +:104680008FBF00100A0010CA27BD001834430080F5 +:1046900034420100A040000C24020001A462001476 +:1046A0003C0280008C4401003C0380008C6201F8D5 +:1046B0000440FFFE240200020A00119900000000DD +:1046C0008CE2001C004610230043102B54400001D4 +:1046D000ACE5001C94E2005C3042FFFF0062102B4E +:1046E000144000072402000294E2005C8CE3001CEA +:1046F0003042FFFF00621821ACE3001C24020002DC +:10470000ACE500380E000F1FA082000C1040001F07 +:104710008FBF00103C0280008C4401003C038000ED +:104720008C6201F80440FFFE24020002AC6401C068 +:10473000A06201C43C021000AC6201F80A0011B191 +:104740008FBF001031020010104000108FBF00100A +:104750003C028008344500808CA3001C94A2005CBD +:10476000006618233042FFFF006218213C023FFF21 +:104770003444FFFF0083102B5440000100801821B7 +:1047800000C31021ACA2001C8FBF001003E0000882 +:1047900027BD001827BDFFE800C0402100A6302338 +:1047A000AFBF001018C00026308A00FF3C0280080E +:1047B000344900808D24001C8D23002C0088202388 +:1047C0000064182B1060000F344701008CE20020B9 +:1047D00000461021ACE200208CE200200044102BA7 +:1047E0001440000B3C023FFF8CE2002000441023E9 +:1047F000ACE200209522005C3042FFFF0A0011D19C +:1048000000822021ACE00020008620213C023FFFF6 +:104810003443FFFF0064102B54400001006020214E +:104820003C0280083442008000851821AC43001C03 +:10483000A0400024A04000270A0012233C03800867 +:1048400031420010104000433C0380083C068008C1 +:1048500034C400808C82003C004810235840003E45 +:10486000346600809082002424420001A08200244B +:10487000908200243C0308008C630024304200FF37 +:104880000043102B144000688FBF001034C2010099 +:104890008C42001C00A2102318400063000000009E +:1048A0008CC300049482005C006818233042FFFF30 +:1048B00000031843000210400043102A1040000576 +:1048C000000000008CC20004004810230A001206F9 +:1048D000000210439482005C3042FFFF000210404F +:1048E0003C068008AC82002C34C5008094A2005C99 +:1048F0008CA4002C94A3005C3042FFFF0002104007 +:10490000008220213063FFFF008320210104102159 +:10491000ACA2001C8CC2000434C60100ACC2001C56 +:10492000240200020E000F1FA0C2000C1040003E27 +:104930008FBF00103C0280008C4401003C038000CB +:104940008C6201F80440FFFE240200020A001253A8 +:104950000000000034660080ACC5003834640100FB +:104960008C82001C00A210231840000224A2FFFC2D +:10497000AC82001C314200015040000A3C03800818 +:104980008CC2003C00A21023044300142404000540 +:104990008C62000414A200033C0380080A00124544 +:1049A000240400058C62000414A2001F8FBF0010B5 +:1049B0003C0208008C4200D8304200201040000A1F +:1049C0003C02800834620080906300089042004CF2 +:1049D000144300053C028008240400048FBF00102B +:1049E0000A0010CA27BD0018344300803442010079 +:1049F000A040000C24020001A46200143C028000CC +:104A00008C4401003C0380008C6201F80440FFFEEE +:104A100024020002AC6401C0A06201C43C02100088 +:104A2000AC6201F88FBF001003E0000827BD00183A +:104A300027BDFFE83C0A8008AFBF00103549008061 +:104A40008D22003C00C04021308400FF004610232E +:104A50001840009D30E700FF3547010024020001A7 +:104A600000A63023A0E0000CA0E0000DA522001459 +:104A700018C00024308200108D23001C8D22002CD1 +:104A8000006818230043102B1040000F00000000A6 +:104A90008CE2002000461021ACE200208CE20020D5 +:104AA0000043102B1440000B3C023FFF8CE200201F +:104AB00000431023ACE200209522005C3042FFFF4F +:104AC0000A00128200621821ACE000200066182162 +:104AD0003C023FFF3446FFFF00C3102B544000014F +:104AE00000C018213C028008344200800065182173 +:104AF000AC43001CA0400024A04000270A0012D0B4 +:104B00003C038008104000403C0380088D22003C9C +:104B1000004810235840003D346700809122002453 +:104B200024420001A1220024912200243C03080019 +:104B30008C630024304200FF0043102B1440009A85 +:104B40008FBF00108CE2001C00A2102318400096BA +:104B5000000000008D4300049522005C00681823CB +:104B60003042FFFF00031843000210400043102AA8 +:104B700010400005012020218D4200040048102330 +:104B80000A0012B3000210439522005C3042FFFF7E +:104B9000000210403C068008AC82002C34C5008026 +:104BA00094A2005C8CA4002C94A3005C3042FFFF14 +:104BB00000021040008220213063FFFF0083182193 +:104BC00001031021ACA2001C8CC2000434C60100F9 +:104BD000ACC2001C240200020E000F1FA0C2000C79 +:104BE000104000718FBF00103C0280008C44010017 +:104BF0003C0380008C6201F80440FFFE24020002A6 +:104C00000A0012FA0000000034670080ACE50038AA +:104C1000346601008CC2001C00A210231840000260 +:104C200024A2FFFCACC2001C3082000150400008EE +:104C30003C0380088CE2003C00A210230443005196 +:104C4000240400058C62000410A2003E3C0380088E +:104C50008C62000454A200548FBF00103C02080074 +:104C60008C4200D830420020104000063C028008F0 +:104C700034620080906300089042004C1043004072 +:104C80003C0280083443008034420100A040000C04 +:104C900024020001A46200143C0280008C44010044 +:104CA0003C0380008C6201F80440FFFE24020002F5 +:104CB000AC6401C0A06201C43C021000AC6201F807 +:104CC0000A0013388FBF001024020005A12000271E +:104CD00014E2000A3C038008354301009062000D95 +:104CE0002C420006504000053C0380089062000DF5 +:104CF00024420001A062000D3C038008346700805C +:104D0000ACE50038346601008CC2001C00A2102300 +:104D10001840000224A2FFFCACC2001C308200013B +:104D20005040000A3C0380088CE2003C00A21023A3 +:104D300004410014240400058C62000414A2000342 +:104D40003C0380080A00132F240400058C62000431 +:104D500014A200158FBF00103C0208008C4200D83E +:104D6000304200201040000A3C028008346200807B +:104D7000906300089042004C144300053C028008F8 +:104D8000240400048FBF00100A0010CA27BD0018B9 +:104D90003443008034420100A040000C2402000192 +:104DA000A46200148FBF001003E0000827BD0018A4 +:104DB0003C0B800827BDFFE83C028000AFBF00101D +:104DC00034420100356A00809044000A35690100D0 +:104DD0008C4500148D4800389123000C308400FF6E +:104DE000010510231C4000B3306700FF2CE20006D1 +:104DF000504000B18FBF00102402000100E23004D7 +:104E000030C200035440000800A8302330C2000C18 +:104E1000144000A130C20030144000A38FBF001026 +:104E20000A0013FC0000000018C0002430820010AB +:104E30008D43001C8D42002C006818230043102B6A +:104E40001040000F000000008D22002000461021BD +:104E5000AD2200208D2200200043102B1440000BB7 +:104E60003C023FFF8D22002000431023AD22002092 +:104E70009542005C3042FFFF0A0013700062182167 +:104E8000AD200020006618213C023FFF3446FFFFA2 +:104E900000C3102B5440000100C018213C028008C0 +:104EA0003442008000651821AC43001CA04000245F +:104EB000A04000270A0013BE3C03800810400040B9 +:104EC0003C0380088D42003C004810231840003D00 +:104ED000346700809142002424420001A142002452 +:104EE000914200243C0308008C630024304200FF00 +:104EF0000043102B144000708FBF00108D22001C47 +:104F000000A210231840006C000000008D63000414 +:104F10009542005C006818233042FFFF00031843ED +:104F2000000210400043102A1040000501402021DB +:104F30008D620004004810230A0013A100021043F0 +:104F40009542005C3042FFFF000210403C068008A2 +:104F5000AC82002C34C5008094A2005C8CA4002C90 +:104F600094A3005C3042FFFF000210400082202129 +:104F70003063FFFF0083182101031021ACA2001C45 +:104F80008CC2000434C60100ACC2001C2402000222 +:104F90000E000F1FA0C2000C104000478FBF001072 +:104FA0003C0280008C4401003C0380008C6201F8CC +:104FB0000440FFFE240200020A0013EE000000007D +:104FC00034670080ACE50038346601008CC2001CF8 +:104FD00000A210231840000224A2FFFCACC2001C57 +:104FE000308200015040000A3C0380088CE2003C03 +:104FF00000A2102304430014240400058C62000462 +:1050000014A200033C0380080A0013E024040005F6 +:105010008C62000414A200288FBF00103C0208001C +:105020008C4200D8304200201040000A3C02800828 +:1050300034620080906300089042004C14430005E5 +:105040003C028008240400048FBF00100A0010CA2C +:1050500027BD00183443008034420100A040000CFA +:1050600024020001A46200143C0280008C44010070 +:105070003C0380008C6201F80440FFFE2402000221 +:10508000AC6401C0A06201C43C021000AC6201F833 +:105090000A0013FC8FBF00108FBF001001003021E9 +:1050A0000A00111B27BD0018010030210A00125A06 +:1050B00027BD00188FBF001003E0000827BD0018AF +:1050C0003C0380083464010024020003A082000C29 +:1050D0008C62000403E00008AC82001C3C058008E0 +:1050E00034A300809062002734A501002406004309 +:1050F00024420001A0620027906300273C020800C0 +:105100008C420048306300FF146200043C076021B9 +:1051100094A500DA0A0008ED30A5FFFF03E00008BF +:105120000000000027BDFFE8AFBF00103C02800078 +:105130000E0014058C4401803C02800834430100B9 +:10514000A060000C8C4200048FBF001027BD001827 +:1051500003E00008AC62001C27BDFFE03C028008B1 +:10516000AFBF0018AFB10014AFB0001034450080DD +:10517000344601003C0880008D09014090C3000CBA +:105180008CA4003C8CA200381482003B306700FFE6 +:105190009502007C90A30027146000093045FFFFB2 +:1051A0002402000554E200083C04800890C2000D6F +:1051B00024420001A0C2000D0A0014403C048008F3 +:1051C000A0C0000D3C048008348201009042000C15 +:1051D00024030005304200FF1443000A24A205DC2A +:1051E00034830080906200272C4200075040000565 +:1051F00024A20A0090630027240200140062100415 +:1052000000A210213C108008361000803045FFFFBE +:10521000012020210E001405A60500149602005C52 +:105220008E0300383C1180003042FFFF0002104026 +:1052300000621821AE03001C0E0003458E240140BD +:105240009202002534420040A20200250E000350C5 +:105250008E2401408E2401403C0380008C6201F8C2 +:105260000440FFFE24020002AC6401C0A06201C43D +:105270003C021000AC6201F88FBF00188FB100141F +:0C5280008FB0001003E0000827BD0020E4 +:04528C008008010095 +:10529000800800808008000000000C8000003200C0 +:1052A0008008024008000EDC08000F3408000F7868 +:1052B00008001010080010508008010080080080CD +:0452C0008008000062 +:0C52C4000A0000220000000000000000B2 +:1052D0000000000D6370352E302E306A390000005A +:1052E00005000004000000000000000000000000B5 +:1052F000000000000000000038003C00000000003A +:10530000000000000000000000000000000000207D +:10531000000000000000000000000000000000008D +:10532000000000000000000000000000000000007D +:105330000000000000000000210038000000000113 +:105340000000002B00000000000000000000000032 +:1053500010000003000000000000000D0000000D20 +:105360003C020800244254243C0308002463564CA9 +:10537000AC4000000043202B1480FFFD24420004B9 +:105380003C1D080037BD9FFC03A0F0213C10080025 +:10539000261000883C1C0800279C54240E0002881C +:1053A000000000000000000D00A018210080102166 +:1053B000008028213C0460003C07600024060008AF +:1053C00010600006348420788C420000ACE2200893 +:1053D0008C63000003E00008ACE3200C0A000E2AF6 +:1053E00000000000240300403C02600003E00008CD +:1053F000AC4320003C0760008F8600008CE52074E1 +:105400000086102100A2182B14600007000028213C +:105410008F8AFD9824050001A14400138F890000A4 +:1054200001244021AF88000003E0000800A0102103 +:105430008F84FD988F8500009086001330C300FF95 +:1054400000A31023AF82000003E00008A080001337 +:105450008F84FD9827BDFFE8AFB00010AFBF0014E8 +:10546000908900119087001124020028312800FF44 +:105470003906002830E300FF2485002C2CD00001E1 +:10548000106200162484001C0E0000390000000089 +:105490008F8FFD983C0560002402020495EE003ECB +:1054A00095ED003C000E5C0031ACFFFF016C502517 +:1054B000ACAA20105200000124020004ACA220007B +:1054C0000000000000000000000000008FBF00147A +:1054D0008FB0001003E0000827BD00180A0000711B +:1054E000000028218F85FD9827BDFFD8AFBF002081 +:1054F000AFB3001CAFB20018AFB10014AFB00010D2 +:105500000080982190A4001124B0001C24B1002C2C +:10551000308300FF386200280E00005B2C5200012F +:105520000E00006300000000020020211240000273 +:1055300002202821000028210E0000390000000070 +:105540008F8DFD983C0880003C05600095AC003EC6 +:1055500095AB003C02683025000C4C00316AFFFF1F +:10556000012A3825ACA7201024020202ACA6201480 +:1055700052400001240200028FBF00208FB3001CA4 +:105580008FB200188FB100148FB0001027BD002813 +:1055900003E00008ACA2200027BDFFE0AFB2001876 +:1055A000AFB10014AFB00010AFBF001C3C116000E1 +:1055B0008E2320748F82000030D0FFFF30F2FFFF77 +:1055C0001062000C2406008F0E000039000000005D +:1055D0003C06801F0010440034C5FF00011238252E +:1055E00024040002AE27201000003021AE25201434 +:1055F000AE2420008FBF001C8FB200188FB10014A2 +:105600008FB0001000C0102103E0000827BD00206B +:1056100027BDFFE0AFB0001030D0FFFFAFBF0018D4 +:10562000AFB100140E00003930F1FFFF001024006C +:10563000009180253C036000AC7020108FBF0018E3 +:105640008FB100148FB0001024020004AC6220005F +:1056500027BD002003E000080000102127BDFFE85F +:105660003C0B6018AFBF00108D6F50002418FF7FF7 +:10567000340C807101F8702435CD380C240A0031C7 +:105680003C098000AD6D50003C08800AAD6C53BCF5 +:10569000AD2A00080E00049BAF88002C0E000459B0 +:1056A000000000000E000048000000003C07600001 +:1056B0008CE508082406FFF03C03570900A62024C7 +:1056C0003462F0001082005024190001AF800034D1 +:1056D0000E000BBC000000003C0660168CC40000ED +:1056E0003C0760148CE500A03C03FFFF00831024FE +:1056F0003C1F535300051FC2105F003D34C57C00A2 +:1057000094A201F2A780004C10400003A780005C27 +:10571000384B1E1EA78B004C94A201F810400004C9 +:105720008F8D0034384C1E1EA78C005C8F8D00348A +:1057300011A000049784005C240E0020A78E004C6A +:105740009784005C2C8F008151E0000124040080CC +:105750009785004C2CB80401530000012405040077 +:105760003C0260008C4304382419103C307FFFFF5A +:1057700013F900033087FFFF50E0000F24060050AC +:10578000A380005E9388005E51000010A784005C37 +:10579000A780005C9785005C8FBF0010A780004C3D +:1057A000A7800054A78000723C010800AC2500804F +:1057B00003E0000827BD0018A386005E9388005E02 +:1057C0005500FFF4A780005CA784005CA785004C0F +:1057D0008FBF00109785005CA7800054A7800072DF +:1057E0003C010800AC25008003E0000827BD00183C +:1057F00000035080014648218D2800043C066000CB +:105800000A00010F010628210A000103AF990034A4 +:105810003083FFFF8F88002C8F87002800032140F2 +:105820003C0580003C020050008248253C06600098 +:105830003C0A010034AC04008CCD08E001AA5824D5 +:1058400011600005000000008CCF08E024E7000193 +:1058500001EA7025ACCE08E08D19001001805821B6 +:10586000ACB900388D180014ACB8003CACA90030BD +:105870000000000000000000000000000000000028 +:105880000000000000000000000000000000000018 +:105890003C0380008C640000308200201040FFFD3B +:1058A0003C0F60008DED08E03C0E010001AE1824B5 +:1058B0001460FFE100000000AF87002803E000084B +:1058C000AF8B00388F85002C240BFFF03C06800046 +:1058D00094A7001A8CA9002430ECFFFF000C38C0FC +:1058E00000EB5024012A4021ACC8003C8CA40024C9 +:1058F0008CC3003C008310231840003300000000DC +:105900008CAD002025A200013C0F0050ACC2003835 +:1059100035EE00103C068000ACCE003000000000E8 +:105920000000000000000000000000000000000077 +:105930000000000000000000000000003C048000A7 +:105940008C990000333800201300FFFD30E200087E +:10595000104000173C0980008C880408ACA8001097 +:105960008C83040CACA300143C1900203C1880006C +:10597000AF19003094AE001894AF001C01CF302155 +:10598000A4A6001894AD001A25A70001A4A7001A28 +:1059900094AB001A94AC001E118B000300000000B1 +:1059A00003E000080000000003E00008A4A0001AC3 +:1059B0008D2A0400ACAA00108D240404ACA40014A9 +:1059C0000A0001AA3C1900208CA200200A000192C2 +:1059D0003C0F00500A0001800000000027BDFFE8D6 +:1059E000AFBF00100E0001C4000000008F89002C22 +:1059F0008FBF00103C038000A520000A9528000AF4 +:105A00009527000427BD00183105FFFF30E6000F81 +:105A10000006150000A2202503E00008AC64008009 +:105A20003C0508008CA500208F83000427BDFFE8FB +:105A3000AFB00010AFBF001410A300100000802111 +:105A4000240400010204300400A6202400C3102412 +:105A50005044000626100001001018802787FD9C86 +:105A60001480000A00671821261000012E09000288 +:105A70005520FFF38F830004AF8500048FBF00140F +:105A80008FB0001003E0000827BD00188C680000EC +:105A90003C058000ACA800240E0001C626100001C1 +:105AA0003C0508008CA500200A0001EB2E0900022D +:105AB00024050001008518043C0408008C840020A3 +:105AC00027BDFFC8AFBF003400831024AFBE003035 +:105AD000AFB7002CAFB60028AFB50024AFB400209C +:105AE000AFB3001CAFB20018AFB1001410400051AA +:105AF000AFB000108F84002C948700069488000AB1 +:105B000000E8302330D5FFFF12A0004B8FBF0034D8 +:105B1000948B0018948C000A016C50233142FFFFD3 +:105B200002A2482B1520000202A0202100402021C3 +:105B30002C8F000515E0000200809821241300043A +:105B40000E000153026020218F87002C02609021FB +:105B5000AF80003094F4000A026080211260004E91 +:105B60003291FFFF3C1670003C1440003C1E2000A8 +:105B70003C1760008F9900388F38000003161824F6 +:105B80001074004F0283F82B17E00036000000006D +:105B9000107E00478F86003014C0003A24030001B5 +:105BA00002031023022320213050FFFF1600FFF1D3 +:105BB0003091FFFF8F87002C3C1100203C108000AB +:105BC000AE11003094EB000A3C178000024B5021CC +:105BD000A4EA000A94E9000A94E800043123FFFFD4 +:105BE0003106000F00062D000065F025AEFE008096 +:105BF00094F3000A94F6001812D3003600122140E4 +:105C00008CFF00148CF4001003E468210000C02114 +:105C100001A4782B0298702101CF6021ACED001413 +:105C2000ACEC001002B2382330F5FFFF16A0FFB82D +:105C30008F84002C8FBF00348FBE00308FB7002CB4 +:105C40008FB600288FB500248FB400208FB3001CBE +:105C50008FB200188FB100148FB0001003E000085D +:105C600027BD00381477FFCC8F8600300E000D8BD7 +:105C700002002021004018218F86003010C0FFC98B +:105C800002031023027070238F87002C01C3682148 +:105C90000A00027631B2FFFF8F86003014C0FFC9C0 +:105CA0003C1100203C1080000A000240AE11003080 +:105CB0000E0003C4020020210A00026D00401821DA +:105CC000020020210E0007DB022028210A00026DBD +:105CD000004018210E000180000000000A00025957 +:105CE00002B2382327BDFFD8AFB40020AFB3001CE9 +:105CF000AFB20018AFB10014AFB00010AFBF0024B6 +:105D00000E0000E6241300013C0280083C03200042 +:105D10003C010800AC200070345400803472000351 +:105D20003C1080002411FF800E0001D7000000000D +:105D30008E06000038C5000130A400011480FFFA6F +:105D4000000000008E07010024030C0010E300098E +:105D50003C0580008E0901002D2830805500001080 +:105D60003C0480008E0B01002D6A31811140000C33 +:105D70003C0480008CAC0100118300040000202151 +:105D80008CAE010025CDFF8131A400FF8E0F0100F4 +:105D90000E0001FBAE0F00240A0002C13C0480008B +:105DA0008C9F010024180020AC9F002092990000D5 +:105DB000332300FF1078001F2402005010620022DD +:105DC000000000003C0480008C830100146000038C +:105DD00000000000566000143C0440008C8201006A +:105DE0008C990100000098210051F824001F79408F +:105DF0003338007F01F8702501D26825AC8D08305A +:105E00008C8C01008C890100258B010001715024CC +:105E1000000A39403128007F00E8302500D22825CB +:105E2000AC8508303C044000AE0401380A000299F9 +:105E3000000000008C8501000E00078D2404008006 +:105E40000A0002C13C0480008C8401000E0013EAA9 +:105E5000000000000A0002C13C04800000A4102BD6 +:105E600024030001104000090000302100052840F3 +:105E700000A4102B04A00003000318405440FFFCB2 +:105E8000000528405060000A0004182B0085382BBC +:105E900054E000040003184200C33025008520238D +:105EA000000318421460FFF9000528420004182B73 +:105EB00003E0000800C310213084FFFF30C600FF5C +:105EC0003C0780008CE201B80440FFFE00064C0055 +:105ED000012430253C08200000C820253C03100088 +:105EE000ACE00180ACE50184ACE4018803E000088B +:105EF000ACE301B83C0660008CC5201C2402FFF016 +:105F000030830200308601001060000E00A22824B9 +:105F100034A500013087300010E0000530830C000C +:105F200034A500043C04600003E00008AC85201C9C +:105F30001060FFFD3C04600034A5000803E0000889 +:105F4000AC85201C54C0FFF334A500020A000315E1 +:105F50003087300027BDFFE8AFB00010AFBF00149E +:105F60003C076000240600021080001100A0802180 +:105F70008F8300380E00030C8C6400188F82003869 +:105F800000002021240600018C45000C0E0002FDBB +:105F9000000000001600000224020003000010218F +:105FA0008FBF00148FB0001003E0000827BD001859 +:105FB0008CE8201C2409FFF001092824ACE5201CF2 +:105FC0008F8700380A0003328CE5000C3C02600E1B +:105FD0000080402134460100240900180000000020 +:105FE00000000000000000003C0A00503C0380005C +:105FF00035470200AC68003834640400AC65003CEE +:10600000AC6700308C6C0000318B00201160FFFD0C +:106010002407FFFF2403007F8C8D00002463FFFF13 +:1060200024840004ACCD00001467FFFB24C60004E8 +:1060300000000000000000000000000024A4020096 +:106040000085282B3C0300203C0E80002529FFFF03 +:1060500001054021ADC300301520FFE0008028215C +:1060600003E00008000000008F82003827BDFFD841 +:10607000AFB3001CAFBF0020AFB20018AFB1001427 +:10608000AFB0001094460002008098218C52001896 +:106090002CC300818C4800048C4700088C51000CF4 +:1060A0008C490010106000078C4A00142CC40004B6 +:1060B0001480001330EB000730C5000310A000105F +:1060C000000000002410008B020020210220282163 +:1060D0000E0002FD240600031660000224020003E5 +:1060E000000010218FBF00208FB3001C8FB200185A +:1060F0008FB100148FB0001003E0000827BD002806 +:106100001560FFF12410008B3C0C80003C03002044 +:10611000241F0001AD830030AF9F0030000000005D +:1061200000000000000000002419FFF024D8000F38 +:10613000031978243C1000D0AD88003801F0702598 +:1061400024CD00033C08600EAD87003C358504007B +:10615000AD8E0030000D38823504003C3C038000D9 +:106160008C6B0000316200201040FFFD0000000039 +:1061700010E0000824E3FFFF2407FFFF8CA80000C5 +:106180002463FFFF24A50004AC8800001467FFFB14 +:10619000248400043C04600EAC860038000000003B +:1061A00000000000000000003C0700203C068000CA +:1061B0000120202101402821ACC700300E000342FD +:1061C000000080210E00030C024020210A000382FF +:1061D0000200202127BDFFE0AFB200183092FFFF80 +:1061E000AFB10014AFBF001CAFB000101640000DDF +:1061F000000088210A0003F1022010212405000379 +:10620000508500278CE5000C0000000D262C0001B5 +:106210003191FFFF24EB00200232502B1140001976 +:10622000AF8B00388F820030144000168F87003803 +:106230003C0670003C0320008CE5000000A62024F2 +:10624000148300108F840040000544023C09800044 +:1062500000A980241480FFE9310600FF2CCA000B3E +:106260001140FFEB262C0001000668803C0E080060 +:1062700025CE51C801AE60218D8B00000160000861 +:1062800000000000022010218FBF001C8FB20018F8 +:106290008FB100148FB0001003E0000827BD00206C +:1062A0000E0002FD240400841600FFD88F870038FA +:1062B0000A0003D2AF800040020028210E00032410 +:1062C000240400018F8700380A0003D2AF82004007 +:1062D000020028210E000324000020210A000401EE +:1062E0008F8700380E000369020020218F87003855 +:1062F0000A0003D2AF82004030AFFFFF000F19C089 +:106300003C0480008C9001B80600FFFE3C1920047C +:106310003C181000AC830180AC800184AC990188EA +:10632000AC9801B80A0003D3262C000190E20002C9 +:1063300090FF00030000202100023A0000FF282502 +:10634000240600080E0002FD000000001600FFDD1C +:10635000240200038F870038000010210A0003D2B6 +:10636000AF82004090E50002000020210A000420D6 +:106370002406000994E5000490E9000390E300027C +:10638000000534000009420000C8202500832825AC +:106390002406000A0A0004200000202190E50002E3 +:1063A000000020210A0004202406000B000449C23A +:1063B0003127003F000443423C0280000008204097 +:1063C000240316802CE60020AC43002C24EAFFE0D6 +:1063D0002482000114C0000330A900FF00801021B6 +:1063E000314700FF000260803C0D8000240A00015C +:1063F000018D20213C0B000E00EA2804008B302187 +:1064000011200005000538278CCE000001C5382575 +:1064100003E00008ACC700008CD800000307782414 +:1064200003E00008ACCF000027BDFFE0AFB10014CF +:10643000AFB00010AFBF00183C0760008CE4080844 +:106440003402F0003C1160003083F000240501C0EC +:106450003C04800E00003021106200062410000170 +:106460008CEA08083149F0003928E0000008382B90 +:10647000000780403C0D0200AE2D0814240C16804D +:106480003C0B80008E2744000E000E34AD6C002CB7 +:10649000120000043C0216912405000112050010B0 +:1064A0003C023D6C345800E0AE3844083C11080012 +:1064B0008E31007C8FBF00183C06600000118540C3 +:1064C000360F16808FB100148FB000103C0E020002 +:1064D00027BD0020ACCF442003E00008ACCE08105C +:1064E0003C0218DA345800E0AE3844083C11080089 +:1064F0008E31007C8FBF00183C0660000011854083 +:10650000360F16808FB100148FB000103C0E0200C1 +:1065100027BD0020ACCF442003E00008ACCE08101B +:106520000A00043A240500010A00043A0000282168 +:1065300024020400A7820010A78000080000202188 +:106540003C06080024C654B02405FFFF248900013E +:10655000000440803124FFFF010618212C87002011 +:1065600014E0FFFAAC65000024040400A7840012C4 +:10657000A780000A000020213C06080024C65530F0 +:106580002405FFFF248D00010004608031A4FFFF7B +:10659000018658212C8A00201540FFFAAD650000C5 +:1065A000A7800014A780000CA780000E0000202107 +:1065B0003C06080024C655B02405FFFF24990001BD +:1065C0000004C0803324FFFF030678212C8E0004D2 +:1065D00015C0FFFAADE500003C0560008CA73D004A +:1065E0002403E08F00E310243446014003E0000858 +:1065F000ACA63D002487007F000731C224C5FFFF01 +:10660000000518C2246400013082FFFF000238C078 +:10661000A784001C3C010800AC270030AF800018A4 +:1066200000002821000020210000302124890001E1 +:1066300000A728213124FFFF2CA817011100000317 +:106640002C8300801460FFF924C6000100C02821BB +:10665000AF86001810C0001DA786001624CAFFFFD1 +:10666000000A11423C080800250855B01040000AF5 +:1066700000002021004030212407FFFF248E00016C +:106680000004688031C4FFFF01A860210086582BF8 +:106690001560FFFAAD87000030A2001F50400008CF +:1066A00000043080240300010043C804000410806B +:1066B000004878212738FFFF03E00008ADF800000C +:1066C00000C820212405FFFFAC85000003E000087E +:1066D0000000000030A5FFFF30C6FFFF30A8001FFC +:1066E0000080602130E700FF0005294200005021B2 +:1066F00010C0001D24090001240B00012518000111 +:10670000010B2004330800FF01267826390E0020F3 +:106710002DED00012DC2000101A218251060000D11 +:10672000014450250005C880032C40210100182198 +:1067300010E0000F000A20278D040000008A1825B1 +:10674000AD03000024AD00010000402100005021F5 +:1067500031A5FFFF252E000131C9FFFF00C9102B15 +:106760001040FFE72518000103E0000800000000CA +:106770008D0A0000014440240A000520AC68000096 +:1067800027BDFFE830A5FFFF30C6FFFFAFB0001008 +:10679000AFBF001430E7FFFF000050213410FFFFAF +:1067A0000000602124AF001F00C048212418000110 +:1067B0002419002005E0001601E010210002F94331 +:1067C000019F682A0009702B01AE402411000017B8 +:1067D000000C18800064102110E000058C4B0000B4 +:1067E00000F84004000838230167582400003821CD +:1067F0001540004100004021556000163169FFFF3F +:10680000258B0001316CFFFF05E1FFEC01E0102159 +:1068100024A2003E0002F943019F682A0009702B60 +:1068200001AE40241500FFEB000C18801546000552 +:106830003402FFFF020028210E0005040000382169 +:10684000020010218FBF00148FB0001003E0000879 +:1068500027BD00181520000301601821000B1C0241 +:1068600024080010306A00FF15400005306E000F4C +:10687000250D000800031A0231A800FF306E000F3A +:1068800015C00005307F0003251000040003190225 +:10689000320800FF307F000317E00005386900016F +:1068A0002502000200031882304800FF3869000109 +:1068B0003123000110600004310300FF250A0001AC +:1068C000314800FF310300FF000C694001A3402163 +:1068D000240A000110CAFFD53110FFFF246E000109 +:1068E00031C800FF1119FFC638C900012D1F002053 +:1068F00053E0001C258B0001240D00010A000597C0 +:10690000240E002051460017258B000125090001A7 +:10691000312800FF2D09002051200012258B000195 +:1069200025430001010D5004014B102425090001ED +:106930001440FFF4306AFFFF3127FFFF10EE000C18 +:106940002582FFFF304CFFFF000050213410FFFF75 +:10695000312800FF2D0900205520FFF225430001BA +:10696000258B0001014648260A000551316CFFFFC6 +:1069700000003821000050210A0005A33410FFFF59 +:1069800027BDFFD8AFB0001030F0FFFFAFB100144B +:10699000001039423211FFE000071080AFB3001C35 +:1069A00000B1282330D3FFFFAFB2001830A5FFFF9E +:1069B000008090210260302100442021AFBF0020E0 +:1069C0000E00052F3207001F022288213403FFFF2B +:1069D00002402021020028210260302100003821DD +:1069E000104300093231FFFF022010218FBF002029 +:1069F0008FB3001C8FB200188FB100148FB000103D +:106A000003E0000827BD00280E00052F000000004D +:106A100000408821022010218FBF00208FB3001C6E +:106A20008FB200188FB100148FB0001003E000087F +:106A300027BD0028000424003C036000AC603D0832 +:106A400010A00002348210063482101603E0000801 +:106A5000AC623D0427BDFFE0AFB00010309000FFF6 +:106A60002E020006AFBF001810400008AFB100149E +:106A7000001030803C030800246351F400C3282137 +:106A80008CA400000080000800000000000020210D +:106A90008FBF00188FB100148FB00010008010213C +:106AA00003E0000827BD0020979100161620005132 +:106AB000000020213C020800904200330A00060A30 +:106AC00000000000978D001215A000310000202169 +:106AD0000A00060A240200089787001014E0001A32 +:106AE0000000182100602021240200011080FFE92D +:106AF0008FBF0018000429C20045302100A6582B82 +:106B00001160FFE43C0880003C072000000569C0DC +:106B100001A76025AD0C00203C0380082402001F63 +:106B20002442FFFFAC6000000441FFFD2463000429 +:106B300024A5000100A6702B15C0FFF5000569C053 +:106B40000A0005F48FBF0018978700083C0408006E +:106B5000248454B0240504000E0005AF240600016F +:106B6000978B001024440001308AFFFF2569FFFF46 +:106B70002D4804000040282115000040A78900107E +:106B800024AC3800000C19C00A000608A7800008D1 +:106B90009787000A3C04080024845530240504002B +:106BA0000E0005AF2406000197990012244400014D +:106BB0003098FFFF272FFFFF2F0E04000040882191 +:106BC00015C0002CA78F0012A780000A3A0200030C +:106BD000262401003084FFFF0E0005DC2C45000157 +:106BE0000011F8C027F00100001021C00A00060AB9 +:106BF000240200089785001A9787000E3C040800BD +:106C0000248455B00E0005AF2406000197870016B6 +:106C10008F8900182445000130A8FFFF24E3FFFFFF +:106C20000109302B0040802114C00018A7830016F2 +:106C3000A780000E9785001C0E000E1E020020216A +:106C4000244A05003144FFFF0E0005DC2405000145 +:106C50003C05080094A500320E000E1E0200202103 +:106C6000244521003C020800904200330A00060A35 +:106C7000000521C00A000642A784000A24AC38009F +:106C8000000C19C00A000608A78400080A00065C68 +:106C9000A785000E308400FF27BDFFE82C82000688 +:106CA000AFBF0014AFB000101040001500A0382195 +:106CB000000440803C0308002463520C0103282197 +:106CC0008CA40000008000080000000024CC007F9D +:106CD000000751C2000C59C23170FFFF2547C400A4 +:106CE00030E5FFFF27840008020030210E00050474 +:106CF000240700019786001402062021A7840014AF +:106D00008FBF00148FB0001003E0000827BD0018EB +:106D10003C0508008CA50030000779C20E0002E691 +:106D200025E4DF003045FFFF3C040800248455B013 +:106D3000240600010E00050424070001978E0016AA +:106D40008FBF00148FB0001025CD000127BD0018A3 +:106D500003E00008A78D00160007C9C22738FF000E +:106D6000001878C231F0FFFF3C040800248455303D +:106D700002002821240600010E000504240700015A +:106D8000978D0012260E0100000E840025AC000134 +:106D90003C0B6000A78C0012AD603D083604000675 +:106DA000000030213C0760008CE23D04305F0006AB +:106DB00017E0FFFD24C9000100061B00312600FF7B +:106DC000006440252CC50004ACE83D0414A0FFF687 +:106DD0008FBF00148FB0001003E0000827BD00181B +:106DE000000751C22549C8002406000124070001FC +:106DF0003C040800248454B00E0005043125FFFF34 +:106E0000978700108FBF00148FB0001024E6000198 +:106E100027BD001803E00008A78600103084FFFF9C +:106E200030A5FFFF3C0680008CC201B80440FFFE85 +:106E30003C084080008838253C031000ACC001802D +:106E4000ACC50184ACC7018803E00008ACC301B83D +:106E50003084FFFF3C0680008CC201B80440FFFE76 +:106E60003C0840388CA70000008828253C0310000F +:106E7000ACC70180ACC5018803E00008ACC301B811 +:106E80008F8300588F8600501066000B00804021D1 +:106E90003C07080024E755C0000328C000A71021C4 +:106EA0008C44000024630001108800053063000F4B +:106EB0005466FFFA000328C003E000080000102118 +:106EC0003C07080024E755C400A7302103E0000870 +:106ED0008CC200003C039000346200010082202537 +:106EE0003C038000AC6400208C65002004A0FFFE01 +:106EF0000000000003E00008000000003C028000E9 +:106F0000344300010083202503E00008AC44002046 +:106F100027BDFFE0AFB100143091FFFFAFB000100C +:106F2000AFBF00181220001200A080218CA5000025 +:106F300014A00011240400023C0680008CC201B899 +:106F40000440FFFE3C074000022720258FBF0018A9 +:106F50008FB100148FB000103C03100027BD00203B +:106F6000ACC50180ACC4018803E00008ACC301B823 +:106F70000A00071D8CA500000E00067424060200FE +:106F8000000028210A00071DAE0000003087FFFF27 +:106F90003C0680008CC201B80440FFFE3C0A40065B +:106FA0008CA9000000EA4025ACC901808CA4000433 +:106FB0003C031000ACC40184ACC8018803E00008A5 +:106FC000ACC301B88F83FD9427BDFFE8AFBF0014A9 +:106FD000AFB00010906700080080102100802821C9 +:106FE00030E600400000202110C000088C50000056 +:106FF0000E00008802002021020020218FBF001413 +:107000008FB000100A00049727BD00180E00073249 +:10701000000000000E000088020020210200202154 +:107020008FBF00148FB000100A00049727BD00180E +:1070300027BDFFE0AFB000108F90FD94AFBF001CE4 +:10704000AFB20018AFB10014920600010080882191 +:107050000E00070430D2000492040005001129C27A +:10706000A605000034830040A20300050E00070EB1 +:10707000022020210E000499022020212402000178 +:10708000AE02000C02202821A602001024040002F7 +:10709000A602001224060200A60200140E000674C6 +:1070A000A60200161640000F8FBF001C978C0054DC +:1070B0003C0B08008D6B00782588FFFF3109FFFF2E +:1070C000256A0001012A382B10E00006A788005429 +:1070D0003C0F6006240E001635ED0010ADAE0050DA +:1070E0008FBF001C8FB200188FB100148FB000103A +:1070F00003E0000827BD002027BDFFE0AFB100146A +:10710000AFBF0018AFB000101080000400A08821AD +:107110002402008010820007000000000000000D23 +:107120008FBF00188FB100148FB0001003E000086B +:1071300027BD00200E00070400A020218F86FD94AB +:107140000220202190C500050E00070E30B000FF80 +:107150002403003E1603FFF1000000003C05800000 +:107160008CA401780480FFFE240800073C0710006F +:10717000ACB1014002202021A0A801448FBF00181B +:107180008FB100148FB00010ACA701780A00075B24 +:1071900027BD002027BDFFE0AFB00010AFBF001833 +:1071A000AFB100143C1080008E11002000000000E0 +:1071B0000E000499AE040020AE1100208FBF00180D +:1071C0008FB100148FB0001003E0000827BD00202D +:1071D0003084FFFF3C0680008CC201B80440FFFEF3 +:1071E0003C084035008838253C031000ACC50180C0 +:1071F000ACC00184ACC7018803E00008ACC301B88F +:107200003084FFFF3C0680008CC201B80440FFFEC2 +:107210003C084036008838253C031000ACC501808E +:10722000ACC00184ACC7018803E00008ACC301B85E +:1072300027BDFFD0AFB500243095FFFFAFB60028C3 +:10724000AFB40020AFBF002CAFB3001CAFB200182A +:10725000AFB10014AFB0001030B6FFFF12A000278E +:107260000000A0218F9200388E4300003C06800071 +:107270002402004000033E0200032C0230E4007FA1 +:10728000006698241482001D30A500FF8F830048FB +:107290002C68000A510000108F86003000035880CF +:1072A0003C0C0800258C5228016C50218D490000AF +:1072B000012000080000000002D4702131C5FFFF4A +:1072C0000E0006D624040084166000028F92003857 +:1072D000AF8000488F860030264F002026890001AD +:1072E00001E090213134FFFF14C00004AF8F00385B +:1072F0000295282B14A0FFDC000000000280102162 +:107300008FBF002C8FB600288FB500248FB40020CB +:107310008FB3001C8FB200188FB100148FB0001013 +:1073200003E0000827BD00302407003414A70146FD +:10733000000000009247000E8F98FD988F90FD94FA +:10734000240F1600A30700199244000D3C0880008A +:107350003C07800CA3040018965F00123C096000F3 +:107360003C117FFFA61F005C965900103622FFFFDC +:10737000240400053325FFFFAE0500548E46001C93 +:10738000AD0F00288CEE00008D2D444801C6182654 +:1073900001A33021AE0600388E0C003824CA00014B +:1073A0003C0D7F00AE0C003C8E0B003CAF0B00048C +:1073B000AE0A00208E130020AE13001CA300001B99 +:1073C000AE02002CA30400128E5F001424130050A0 +:1073D000AE1F00348E190034AF1900148E4500180A +:1073E000AE050048924F000CA20F004E9209000813 +:1073F000352E0020A20E00088E030018006D6024B8 +:10740000358B4000AE0B0018920A0000315200FF8D +:10741000125302A62413FF803C0408002484564023 +:107420000E00074000000000240C000424080001A6 +:107430003C0508008CA556403C048000A20C0025A9 +:10744000A20800058C9001780600FFFE8F9200389C +:10745000240D00023C031000AC850140A08D0144C6 +:10746000AC8301780A000804AF8000482CAD0037D7 +:1074700011A0FF998F860030000580803C11080024 +:1074800026315250021178218DEE000001C0000813 +:10749000000000002410000414B0008E3C0780009F +:1074A0003C0B08008D6B56408F86FD94ACEB0020A2 +:1074B0008E4300088F8FFD98240E0050ACC300301F +:1074C0008E4A0008ACCA00508E42000CACC2003498 +:1074D0008E440010ACC400388E5F0010ACDF005446 +:1074E0008E590014ACD9003C8E580018ADF8000439 +:1074F0008E51001CACD1002090C5000030A900FFC7 +:10750000112E0276000000008CC500348CD10030B2 +:1075100000B1302304C000F32404008C126000F09A +:10752000240200030A000804AF820048240F00056B +:1075300014AF00683C0B80003C0308008C6356408D +:107540008F86FD94AD6300208E4A00048F99FD98CC +:1075500024072000ACCA001C924200082412000834 +:10756000A32200198F840038909F0009A33F0018C0 +:107570008F85003890B8000A330400FF1092001085 +:10758000288C0009158000BC24080002240E00206D +:10759000108E000B34078000288900211520000878 +:1075A0002407400024110040109100053C07000111 +:1075B000240F0080108F00023C07000224074000C7 +:1075C0008CDF00183C04FF0003E4C8240327C02517 +:1075D000ACD8001890B2000BA0D200278F830038DF +:1075E0009465000C10A0022A000000009467000CB3 +:1075F0003C198000240BFFBFA4C7005C9062000E02 +:1076000024070004A0C200088F840038909F000F58 +:10761000A0DF00098F8C00388D9200108F38007425 +:1076200002582823ACC500588D8F0014ACCF002C15 +:10763000959100183229FFFFACC90040958E001AC1 +:1076400031D0FFFFACD000448D8D001CACCD004884 +:1076500095880002A4C800789183000EA0C300089A +:1076600090CA0008014B1024126001D4A0C2000887 +:107670008F9200380A000804AF87004824060006ED +:1076800014A600143C0D80003C1008008E105640DB +:107690008F8CFD90ADB000208E4800188F86FD9431 +:1076A0008F8AFD98AD8800008CC300382404000543 +:1076B000AD8300048CCB003C12600081AD4B000018 +:1076C0000A000804AF840048240E000710AE004BE7 +:1076D000240400063C05080024A556400E000713AC +:1076E000240400818F9200380013102B0A00080434 +:1076F000AF8200482419002314B9FFF63C0B800028 +:107700003C0C08008D8C56408F8AFD98AD6C002093 +:107710008F91FD948E4600042544002026450014D8 +:10772000AE260028240600030E000E2A2550003045 +:107730008F87003802002021240600030E000E2A45 +:1077400024E500083C040800248456400E0007404D +:107750000000000092220000241F0050304400FF6F +:10776000549FFFE18F9200380E000E1500000000BC +:107770000A0009098F9200382403003314A3003251 +:107780003C0280003C1108008E3156408F8EFD98DF +:10779000AC5100208E440008240900288F88FD94F5 +:1077A000ADC400308E5F000C24060009ADDF00344C +:1077B0008E590010ADD900388E580014ADD8002075 +:1077C0008E450018ADC500248E4F001CADCF00289B +:1077D000A1C900118E4D000412600031AD0D0028CA +:1077E0008F9200380A000804AF860048240900225E +:1077F00014A9FFB800000000240400073C0F080093 +:107800008DEF56403C118000AE2F00205660FEB137 +:10781000AF8400483C040800248456400E00074012 +:10782000241300508F98FD9493120000324500FFFE +:1078300010B30169000000008F9200380000202181 +:107840000A000804AF8400483C05080024A55640FF +:107850000E0006E3240400810A0009098F92003813 +:1078600002D498213265FFFF0E0006D6240400845E +:107870000A0008048F9200381088FF512407040082 +:107880002887000310E001A324100004240D000148 +:10789000548DFF4B240740000A0008BF2407010055 +:1078A0003C05080024A556400E000732240400823F +:1078B0008F920038000030210A000804AF8600488B +:1078C0003C040800248456408CC200380E00074057 +:1078D0008CC3003C8F9200380A00095F0000202111 +:1078E000240400823C05080024A556400E000732FF +:1078F000000000008F920038000010210A000804E8 +:10790000AF8200488E5000048F91FD943C0A8000A5 +:10791000AD500020922200050200282130460002CE +:1079200014C001802404008A8F92FD98020028214F +:107930002404008D924B001B3163002014600179F8 +:1079400000000000922D0009240C001231A800FF55 +:10795000110C0174240400810E0007040200202190 +:107960009245001B240E00040200202134A900428D +:10797000A249001B0E00070EA22E00253C04800029 +:107980008C9101780620FFFE24180002AC90014083 +:10799000A09801448F9200383C0F1000AC8F017802 +:1079A0000A00090A0013102B8E5000048F91FD94D9 +:1079B0003C1F8000AFF00020923900050200282112 +:1079C0003327000214E000172404008A92240009DF +:1079D0002412000402002821308600FF10D200117A +:1079E000240400810E000704020020218F8CFD98E2 +:1079F000240B00122403FFFE918D001B02002021A6 +:107A000035A80020A188001BA22B0009922A00059E +:107A1000014310240E00070EA222000502002821B7 +:107A2000000020210E0007CF000000000A00090915 +:107A30008F9200388E5100043C0280003C100800F8 +:107A400026105640AC5100203C010800AC31564095 +:107A50009246000330C40004108001658F84FD94B9 +:107A600024020006A0820009924D001B2408FFC0DA +:107A700031AC003F01885825A08B000892430003D9 +:107A8000306A00011540015C000000008E420008D1 +:107A9000AE0200083C0208008C4256481040015BD0 +:107AA0008F8EFD98000281C28F85FD94A5D0000CB9 +:107AB0008E5F000C240F000124090014ADDF002CA0 +:107AC0008E590010ADD9001C96470016A5C7003C82 +:107AD00096580014A5D8003EACAF000CA4AF00101F +:107AE000A4AF0012A4AF0014A4AF00161260015F8F +:107AF000A1C9001192440003309200022E530001EC +:107B00008F920038266200080A000804AF820048FD +:107B10008E4600043C0580003C048008ACA6002092 +:107B20008E4700089089000024110050312200FF88 +:107B3000105100B8240500883C0480008C8F01B8E7 +:107B400005E0FFFE0013802B3C18400900B810250B +:107B5000AF9000483C101000AC860180AC870184D7 +:107B6000AC820188AC9001B80A0008058F8600300D +:107B70008E4500043C0680003C098008ACC500200E +:107B8000913F00002404005033F900FF132400B09B +:107B9000240600883C0480008C8A01B80540FFFE62 +:107BA0003C0E400E00CE68253C081000AC850180DC +:107BB000AC800184AC8D0188AC8801B8912B0000A9 +:107BC000240CFF8024040004016C182524060030D6 +:107BD0000E000674A12300000A0009098F920038E4 +:107BE0008E5000048F91FD983C0F8000ADF0002076 +:107BF0009225001B30A900101120007C2403008175 +:107C00003C0480008C8701B804E0FFFE3C1F401F4D +:107C1000AC900180007F10250013C82B3C10100091 +:107C2000AC800184AF990048AC820188AC9001B867 +:107C30000A0008058F8600308E44001C0E0006EFF7 +:107C400000000000104000F8004038218F920038FA +:107C5000240600893C0580008CAE01B805C0FFFEFB +:107C600000000000ACA701808E50001C3C114001B8 +:107C70000013782B00D138253C131000ACB00184E0 +:107C8000AF8F0048ACA70188ACB301B80A00080563 +:107C90008F860030965900023C100800261056408E +:107CA00033380004130000A33C0460008E5F001C06 +:107CB0003C068000ACDF00203C010800AC3F564091 +:107CC000964F000231E7000114E000E300000000DD +:107CD0008E420004AE0200083C1008008E10564888 +:107CE000120000D93C0680008F85FD94241000010D +:107CF0008CBF00188F91FD988F89FD9003E6C825F1 +:107D0000ACB90018A0A00005ACB0000C3C180800ED +:107D10008F1856488F870038A4B00010001879C219 +:107D2000A4B00012A4B00014A4B00016A62F000C3A +:107D30008CEE00088F8D00388F8C0038AE2E002C12 +:107D40008DA8000C24070002AE28001C918B0010A7 +:107D5000A22B00118F830038906A0011A12A00081D +:107D60008F82003890440012A0A4004E8F920038F9 +:107D700092460013A22600128F920038965F0014DC +:107D8000A63F003C96590016A639003E8E580018B2 +:107D9000AE3800145660FD4FAF8700483C05080020 +:107DA00024A556400E000713000020218F920038B2 +:107DB000000038210A000804AF8700483C0508008D +:107DC00024A556400E000732240400828F9200380A +:107DD0000A0008EC000038210E000E15000000001B +:107DE0008F9200380A00095F000020210E0007046E +:107DF000020020219232001B020020213658001080 +:107E00000E00070EA238001B8F9200380A000A4F9E +:107E1000000018219243000C306A00011140000359 +:107E200000000000964B000EA48B002C9248000C22 +:107E3000310C00021180FF4000002821964E0012F4 +:107E40008E4D0014A48E001A0A000A1DAC8D001C71 +:107E50008F8300588F8700501067FF4E000030213D +:107E60003C080800250855C4000320C000883021C4 +:107E70008CD10000122500C8246200013043000F9D +:107E80001467FFFA000320C00A000A340000302102 +:107E90003C05080024A556400E0007322404008B40 +:107EA0008F9200380A0008EC0013382B3C0B0800B6 +:107EB0008D6B564024D8FFFE25710100322A007FC9 +:107EC0000147902102331024AD020028AE4600D0B5 +:107ED000AE4000D40A000855AE58001CACC0005497 +:107EE0003C0E08008DCE56403C09800C352C01001C +:107EF000ACEE00288E500014AD9000D08E4D0014D2 +:107F0000AD8D00D48E4800102507FFFE0A000891B1 +:107F1000AD87001C5490FDAA240740000A0008BF4A +:107F2000240710000E0007C3000000000A00090922 +:107F30008F9200388C83442C3C05DEAD34B2BEEF0A +:107F40003C010800AC205640107200900000000078 +:107F50003C046C62348279701462000824040002CC +:107F6000978A00549783004C020028210143482B34 +:107F70001120001924040092240400020E0005E4DC +:107F8000240502003C0B8000AD6200203C0108008B +:107F9000AC2256401040000D8F8E0038240C002873 +:107FA0002404000391CD001031A800FF550C0001FE +:107FB000240400010E00004C0000000010400004EA +:107FC000240400830A000A7F8F920038240400836F +:107FD0003C05080024A556400E00071300000000D1 +:107FE0008F9200380013382B0A000804AF8700482E +:107FF0000A0009E8240200128E4400080E0006EF71 +:10800000000000000A0009F4AE0200083C05080068 +:1080100024A556400E0006E3240400878F92003802 +:108020000A000A110013102B240400040E0005E4BA +:108030002405003014400014004038218F9200388D +:108040000A000A64240600833C05080024A5564063 +:108050000A000B45240400878E4400040E0006EF3E +:10806000000000000A000A85AE0200083C05080076 +:1080700024A556400E000732240400828F92003857 +:108080000A000A11000010218F9200383C08800875 +:108090003C0C8000240B0050240A0001AD8200201B +:1080A000A10B0000A10A000192490004A1090018D7 +:1080B00092440005A1040019924300063C04080004 +:1080C000248455C4A103001A924200073C0308000F +:1080D000246355C0A102001B92450008A105001CA5 +:1080E00092460009A106001D925F000AA11F001E12 +:1080F0009259000BA119001F9258000CA1180020E2 +:108100009251000DA11100219250000EA1100022E9 +:10811000924F000FA10F0023924E0010A10E0024D9 +:10812000924D0011A10D0025964C0014A50C0028BD +:10813000964B00168F8A00508F980058A50B002A86 +:1081400096490018000A10C025450001A509002C19 +:108150008E46001C0044C8210043F82130A5000FC2 +:10816000AFE60000AF27000010B80003AF85005055 +:108170000A000A640000302124AD000131A8000F7C +:10818000000030210A000A64AF8800588C83442C18 +:108190000A000B243C046C623C07080024E755C02D +:1081A00000879021ACC00000000030210A000A3492 +:1081B000AE4000003C0482013C03600034820E02A9 +:1081C000AC603D68AF80007803E00008AC623D6CB5 +:1081D00027BDFFE8AFB000103090FFFF001018423D +:1081E0002C620041AFBF0014144000022404008040 +:1081F000240300403C010800AC3000603C01080052 +:10820000AC2300640E000E1E00602821244802BF2B +:108210002409FF8001092824001039800010304013 +:108220008FBF00148FB0001000A7202100861821F6 +:10823000AF8300603C010800AC2500583C010800F9 +:10824000AC24005C03E0000827BD0018308300FF69 +:1082500030C6FFFF30E400FF3C0880008D0201B80B +:108260000440FFFE00035400014438253C0960002F +:1082700000E920253C031000AD050180AD06018416 +:10828000AD04018803E00008AD0301B88F86003813 +:108290003C096012352700108CCB00043C0C600EAA +:1082A00035850010316A00062D480001ACE800C495 +:1082B0008CC40004ACA431808CC2000894C30002BA +:1082C000ACA2318403E00008A78300708F850038DA +:1082D0008F87FF208F86FF288CAE00043C0F601232 +:1082E00035E80010ACEE00688CAD0008ACED006C19 +:1082F0008CAC0010ACCC004C8CAB000CACCB004870 +:1083000094CA00543C0208008C42004425490001F4 +:10831000A4C9005494C400543083FFFF10620017B6 +:10832000000000003C0208008C420040A4C2005241 +:108330008CA30018ACE300308CA20014ACE2002C3B +:108340008CB90018ACF900388CB800142405000171 +:10835000ACF800348D0600BC50C500198D0200B485 +:108360008D0200B8A4E2004894E40048A4E4004A66 +:1083700094E800DA03E000083102FFFF3C02080045 +:108380008C420024A4C00054A4C200528CA3001844 +:10839000ACE300308CA20014ACE2002C8CB90018C5 +:1083A000ACF900388CB8001424050001ACF8003496 +:1083B0008D0600BC54C5FFEB8D0200B88D0200B4E1 +:1083C000A4E2004894E40048A4E4004A94E800DAF7 +:1083D00003E000083102FFFF8F8600383C04800074 +:1083E0008CC900088CC80008000929C0000839C0E1 +:1083F000AC87002090C30007306200041040003AB0 +:10840000AF85007490CB0007316A00081140003935 +:108410008F87FF248CCD000C8CCE001401AE602B16 +:1084200011800032000000008CC2000CACE2007031 +:108430008CCB00188F85FF208F88FF28ACEB007451 +:108440008CCA00102402FFF8ACAA00C88CC9000C2A +:10845000AD0900608CC4001CACA400C090E3007C9B +:108460000062C824A0F9007C90D80007330F0008F0 +:1084700011E000040000000090ED007C35AC00012C +:10848000A0EC007C90CF000731EE000111C0000984 +:108490000000000090E4007C2418000234820002F6 +:1084A000A0E2007C90A300EC307900FF13380013A9 +:1084B0002408003490C900073126000210C00004CF +:1084C0000000000090EB007C356A0004A0EA007C0C +:1084D00090ED007D31AC003FA0EC007D94A700DA68 +:1084E00003E0000830E2FFFF8F87FF240A000C5AE8 +:1084F0008CC200140A000C5BACE000700A000C7C1B +:10850000ACA800CC8F8C003827BDFFD8AFB3001CBF +:10851000AFB20018AFB00010AFBF0020AFB1001471 +:10852000918F00153C13600E3673001031EB000F75 +:10853000A38B007C8D8F00048D8B0008959F00120B +:10854000959900109584001A9598001E958E001C30 +:1085500033EDFFFF332AFFFF3089FFFF3308FFFFB2 +:1085600031C7FFFF3C010800AC2D00243C0108008E +:10857000AC2900443C010800AC2A0040AE683178C8 +:10858000AE67317C91850015959100163C12601202 +:108590003652001030A200FF3230FFFFAE62318849 +:1085A000AE5000B491830014959F0018240600017A +:1085B0000066C80433F8FFFFAE5900B8AE5800BCDF +:1085C000918E0014AF8F00643C08600631CD00FF2F +:1085D000AE4D00C0918A00159584000E3C07600ADC +:1085E000314900FFAF8B00683084FFFFAE4900C8FF +:1085F000351100100E000BC334F004103C020800CB +:108600008C4200603C0308008C6300643C06080058 +:108610008CC600583C0508008CA5005C8F84006067 +:108620008FBF0020AE23004CAE65319CAE030054DA +:10863000AE4500DCAE6231A0AE6331A4AE663198C7 +:10864000AE2200488FB3001CAE0200508FB1001460 +:10865000AE4200E0AE4300E4AE4600D88FB000105A +:108660008FB200180A0004CC27BD0028978500723D +:108670009783005C27BDFFE8AFB0001000A3102B6C +:10868000AFBF0014240400058F900038104000553F +:10869000240900020E0005E48F850060AF8200749B +:1086A000240400031040004F240900023C0680000F +:1086B0000E00004CACC2002024070001240820005A +:1086C0001040004D24040005978E00728F8AFF240D +:1086D0002409005025C50001A7850072A1490000AA +:1086E0003C0D08008DAD0064240380008F84FF20C2 +:1086F000000D6600AD4C0018A5400006954B000A21 +:108700008F85FF282402FF8001633024A546000ADC +:10871000915F000A0000482103E2C825A159000A20 +:10872000A0A00008A140004CA08000C5961800023F +:10873000978300703C020004A49800DA960F0002B0 +:108740002418FFBF25EE2401A48E00AE8E0D000478 +:10875000ACAD00448E0C0008ACAC0040A4A00050AE +:10876000A4A000548E0B000C240C0030AC8B00280D +:108770008E060010AC860024A480003EA487004E24 +:10878000A4870050A483003CAD420074AC8800C8AC +:10879000ACA80060A08700EC909F00C433F9007F74 +:1087A000A09900C4909000C402187824A08F00C43F +:1087B000914E007C35CD0001A14D007C938B007C57 +:1087C000AD480070AC8C00CCA08B00C68F880068D0 +:1087D0008F870064AC8800B4AC8700B8A5400078EF +:1087E000A540007A8FBF00148FB000100120102127 +:1087F00003E0000827BD00188F8500740E00067482 +:108800008F8600600A000D482409000227BDFFE0A2 +:10881000AFB000108F900038AFB10014AFBF001898 +:108820008E0900040E000499000921C08E0800047E +:108830008F84FF208F82FF28000839C03C0680000B +:10884000ACC70020948500DA904300131460001C2C +:1088500030B1FFFF8F8CFF24918B0008316A0040FC +:108860001540000B000000008E0D00040220302196 +:108870008FBF00188FB100148FB0001024040022A5 +:1088800000003821000D29C00A000BE227BD00209E +:108890000E000063000000008E0D00040220302155 +:1088A0008FBF00188FB100148FB000102404002275 +:1088B00000003821000D29C00A000BE227BD00206E +:1088C0000E00005B000000008E0D0004022030212D +:1088D0008FBF00188FB100148FB000102404002245 +:1088E00000003821000D29C00A000BE227BD00203E +:1088F00027BDFFE0AFB200183092FFFFAFB000100D +:10890000AFBF001CAFB100141240001E0000802158 +:108910008F8600388CC500002403000600053F0246 +:108920000005140230E4000714830016304500FFF0 +:108930002CA8000611000040000558803C0C0800DF +:10894000258C532C016C50218D490000012000081A +:10895000000000008F8E0078240D000111CD005022 +:1089600024020002AF820078260900013130FFFFA7 +:1089700024C800200212202B010030211480FFE5C2 +:10898000AF880038020010218FBF001C8FB2001882 +:108990008FB100148FB0001003E0000827BD002045 +:1089A0009387005E54E00034000030210E000C90EC +:1089B000000000008F8600380A000DA82402000184 +:1089C0008F8700782405000210E50031240400138D +:1089D0000000282100003021240700010E000BE2D6 +:1089E000000000000A000DA98F8600388F830078F0 +:1089F000240200021462FFF6240400120E000C454B +:108A0000000000008F850074004030212404001213 +:108A10000E000BE2000038210A000DA98F860038F5 +:108A20008F8300782411000310710029241F000295 +:108A3000107FFFCE26090001240400100000282129 +:108A4000000030210A000DC6240700018F91007834 +:108A5000240600021626FFF9240400100E000CEA7A +:108A600000000000144000238F9800388F860038E3 +:108A70000A000DA824020003240400140E000BE2D7 +:108A8000000028218F8600380A000DA82402000269 +:108A90000E000D52000000000A000DA98F8600385C +:108AA0000E000BF200000000241900022404001440 +:108AB000000028210000302100003821AF99007803 +:108AC0000E000BE2000000000A000DA98F8600389E +:108AD0000E000C02000000008F85007424190002B3 +:108AE0000040302124040010000038210A000DFF4E +:108AF000AF9900780040382124040010970F00023D +:108B0000000028210E000BE231E6FFFF8F860038BF +:108B10000A000DA9AF9100788F84FF243C077FFFE6 +:108B200034E6FFFF8C8500182402000100A61824FB +:108B3000AC83001803E00008A08200053084FFFF2A +:108B400030A5FFFF108000070000182130820001CF +:108B50001040000200042042006518211480FFFB31 +:108B60000005284003E000080060102110C0000745 +:108B7000000000008CA2000024C6FFFF24A5000412 +:108B8000AC82000014C0FFFB2484000403E0000852 +:108B90000000000010A0000824A3FFFFAC86000026 +:108BA00000000000000000002402FFFF2463FFFF1C +:108BB0001462FFFA2484000403E0000800000000AF +:108BC000000411C003E000082442024027BDFFE872 +:108BD000AFB0001000808021AFBF00140E000E3F28 +:108BE00000A0202100504821240AFF808FBF0014DC +:108BF0008FB00010012A30243127007F3C08800A02 +:108C00003C04210000E8102100C428253C0380001A +:108C100027BD0018AC650024AF820024AC400000E2 +:108C2000AC65002403E00008AC4000403C0D0800A7 +:108C30008DAD005800056180240AFF8001A45821F1 +:108C4000016C4821012A30243127007F3C08800C28 +:108C50003C04210000E8102100C428253C038000CA +:108C6000AC650028AF82002003E00008AC4000247F +:108C700030A5FFFF3C0680008CC201B80440FFFE17 +:108C80003C08601500A838253C031000ACC40180E6 +:108C9000ACC00184ACC7018803E00008ACC301B8D4 +:108CA0003C0D08008DAD005800056180240AFF804E +:108CB00001A45821016C4021010A482400093140D7 +:108CC0003107007F00C728253C04200000A4182598 +:108CD0003C028000AC43083003E00008AF80002075 +:108CE00027BDFFE8AFB0001000808021AFBF0014A7 +:108CF0000E000E3F00A0202100504821240BFF80D1 +:108D0000012B5024000A39403128007F3C06200006 +:108D10008FBF00148FB0001000E8282534C2000176 +:108D200000A218253C04800027BD0018AC83083041 +:108D300003E00008AF8000243C0580088CA7006099 +:108D40003C0680080087102B144000112C83400043 +:108D50008CA800602D0340001060000F2403400029 +:108D60008CC900600089282B14A000020080182103 +:108D70008CC3006000035A42000B30803C0A08009C +:108D8000254A53A000CA202103E000088C8200007D +:108D90001460FFF32403400000035A42000B3080AC +:108DA0003C0A0800254A53A000CA202103E000081D +:108DB0008C8200003C05800890A6000893840088FF +:108DC00024C20001304200FF3043007F1064000CD9 +:108DD00000023827A0A200083C0480008C8501789E +:108DE00004A0FFFE8F8A0080240900023C081000C6 +:108DF000AC8A0140A089014403E00008AC880178F6 +:108E00000A000EC430E2008027BDFFD8AFB20018C0 +:108E10008F920084AFBF0020AFB3001CAFB0001032 +:108E2000AFB100148F9300208E5900283C100080B1 +:108E30003C0EFFEFAE7900008E580024A260000ABD +:108E400035CDFFFFAE7800049251002C3C0BFF9F04 +:108E5000356AFFFFA271000C8E6F000C3C080040C9 +:108E6000A271000B01F06025018D4824012A3824ED +:108E700000E83025AE66000C8E450004AE60001898 +:108E80003C0400FFAE6500148E43002C3482FFFFCB +:108E9000A66000080062F824AE7F00108E5900081A +:108EA0008F900080964E0012AE7900208E51000CFB +:108EB00031D83FFF00187980AE7100248E4D001428 +:108EC00001F0602131CB0001AE6D00288E4A001800 +:108ED000000C41C2000B4B80AE6A002C8E46001C79 +:108EE00001093821A667001CAE66003096450002D5 +:108EF0008E440020A665001EAE6400349243003309 +:108F00003062000454400006924700003C02800892 +:108F1000344301008C7F00C0AE7F003092470000D8 +:108F20008F860024A0C700309245003330A4000291 +:108F300050800007925100018F880024240BFF808D +:108F4000910A0030014B4825A109003092510001DF +:108F50008F900024240CFFBF2404FFDFA2110031F6 +:108F60008F8D00243C1880083711008091AF003CA1 +:108F700031EE007FA1AE003C8F890024912B003C94 +:108F8000016C5024A12A003C8F9F00248E6800149D +:108F900093E6003C2D0700010007114000C428247F +:108FA00000A21825A3E3003C8F87002496590012E5 +:108FB000A4F900328E450004922E007C30B00003EC +:108FC0000010782331ED000300AD102131CC0002F8 +:108FD0001580000224460034244600303C028008FC +:108FE00034430080907F007C00BFC82433380004E5 +:108FF0001700000224C2000400C010218F98002432 +:1090000024190002ACE20034A3190000924F003F83 +:109010008F8E00243C0C8008358B0080A1CF00018E +:109020008F910024924D003F8E440004A62D000233 +:10903000956A005C0E000E9D3150FFFF00024B80D0 +:10904000013038253C08420000E82825AE25000400 +:109050008E4400388F850024ACA400188E4600345E +:10906000ACA6001CACA0000CACA00010A4A0001486 +:10907000A4A00016A4A00020A4A00022ACA000245C +:109080008E62001450400001240200018FBF0020B6 +:109090008FB3001C8FB200188FB100148FB0001076 +:1090A000ACA200080A000EBC27BD002827BDFFC8DF +:1090B0003C05800834A40080AFBF0034AFBE003050 +:1090C000AFB7002CAFB60028AFB50024AFB4002076 +:1090D000AFB3001CAFB20018AFB10014AFB00010B6 +:1090E000948300789482007A104300512405FFFF96 +:1090F0000080F0210A000FCC0080B821108B004DB9 +:109100008FBF00348F8600803C1808008F18005CE9 +:109110002411FF803C1680000306782101F1802491 +:10912000AED0002C96EE007A31EC007F3C0D800E24 +:1091300031CB7FFF018D5021000B4840012AA8212F +:1091400096A400003C0808008D0800582405FF8004 +:1091500030953FFF01061821001539800067C821AE +:109160000325F8243C02010003E290253338007FF8 +:109170003C11800CAED20028031190219250000DBA +:10918000320F000411E0003702E0982196E3007AE4 +:1091900096E8007A96E5007A2404800031077FFF84 +:1091A00024E3000130627FFF00A4F82403E2C82515 +:1091B000A6F9007A96E6007A3C1408008E940060C6 +:1091C00030D67FFF12D400C1000000008E58001876 +:1091D0008F84008002A028212713FFFF0E000E7746 +:1091E000AE53002C97D5007897D4007A12950010D2 +:1091F000000028213C098008352401003C0A800831 +:1092000091480008908700C53114007F30E400FFCA +:109210000284302B14C0FFB9268B0001938E008886 +:10922000268C0001008E682115ACFFB78F86008068 +:109230008FBF00348FBE00308FB7002C8FB6002850 +:109240008FB500248FB400208FB3001C8FB200189C +:109250008FB100148FB0001000A0102103E00008AF +:1092600027BD003800C020210E000E4202802821B8 +:109270008E4B00108E4C00308F8400242409000295 +:10928000016C5023AE4A0010A089000096E3005CF8 +:109290008E4400308F9100240E000E9D3070FFFF31 +:1092A00000024380011028253C07420000A710253A +:1092B000AE2200048E5F00048F8A00248E590000C5 +:1092C000240B0008AD5F001CAD590018AD40000C28 +:1092D000AD4000109246000A240400052408C00096 +:1092E00030D000FFA550001496580008A55800166D +:1092F0009251000A3C188008322F00FFA54F002031 +:10930000964E000837110100A54E0022AD40002402 +:10931000924D000B31AC00FFA54C0002A14B0001A7 +:109320008E4900308F830024240BFFBFAC690008F6 +:10933000A06400308F9000242403FFDF96070032E2 +:1093400000E8282400B51025A6020032921F003242 +:1093500033F9003F37260040A20600328F8C0024EC +:10936000AD8000348E2F00C0AD8F0038918E003C50 +:109370003C0F7FFF31CD007FA18D003C8F84002406 +:1093800035EEFFFF908A003C014B4824A089003C49 +:109390008F85002490A8003C01033824A0A7003C3E +:1093A0008E4200348F9100243C038008AE2200409E +:1093B0008E59002C8E5F0030033F3023AE260044D0 +:1093C000923000483218007FA23800488F8800246D +:1093D0008E4D00308D0C004801AE5824019650246B +:1093E000014B4825AD0900489244000AA104004CF5 +:1093F000964700088F850024A4A7004E8E500030A9 +:109400008E4400300E0002E68C65006092F9007C0C +:109410000002F940004028210002110003E230213F +:109420003336000212C00003020680210005B0801E +:1094300002168021926D007C31B30004126000029C +:1094400000057080020E80218E4B003024058000C4 +:10945000316A0003000A4823312400030204182162 +:109460008F900024AE03003496E4007A96E8007AE8 +:1094700096F1007A31077FFF24E20001305F7FFF21 +:109480000225C824033F3025A6E6007A96F8007A24 +:109490003C1208008E520060330F7FFF11F200185B +:1094A000000000008F8400800E000E7702A02821AB +:1094B0008F8400800E000E87028028210E000EBCD3 +:1094C000000000000A000FC80000000096F1007ABA +:1094D00002248024A6F0007A92EF007A92EB007AC0 +:1094E00031EE00FF000E69C2000D6027000C51C074 +:1094F0003169007F012A20250A000FC2A2E4007A08 +:1095000096E6007A00C5C024A6F8007A92EF007AA9 +:1095100092F3007A31F200FF001271C2000E682748 +:10952000000DB1C0326C007F01962825A2E5007ABB +:109530000A0010798F8400803C0380003084FFFF94 +:1095400030A5FFFFAC640018AC65001C03E0000808 +:109550008C62001427BDFFA83C068008AFBE0050F7 +:10956000AFBF0054AFB7004CAFB60048AFB5004432 +:10957000AFB40040AFB3003CAFB20038AFB100347D +:10958000AFB0003034C80100910500C590C7000895 +:10959000309EFFFF30A500FF30E2007F0045182A13 +:1095A000A7A00014A7A0001E10600053AFA00010D9 +:1095B00090C900083126007F00A620232493FFFFD6 +:1095C0000013802B001E882B0211782451E00084A8 +:1095D0008FB300103C19800897360052973700501F +:1095E000001EC40002D7A8230015A4000014140311 +:1095F00003C2902A1640000200182C0300402821C4 +:10960000001314000002240300A4F82A57E000010C +:1096100000A0202128830009146000020080A021FE +:10962000241400083C0A80088D4500480014498035 +:109630008D48004C3C0380003124FFFF3C060010A5 +:109640000086382534710400AC650038AF91008481 +:10965000AC68003CAC670030000000000000000077 +:1096600000000000000000000000000000000000FA +:1096700000000000000000008C6C0000318B002016 +:109680001160FFFD0014682A01B010241040003959 +:109690000000A8213C16800892D700083C128000E8 +:1096A0008E44010032F6007F0E000E4202C02821D7 +:1096B0008E2F00108E4401000000902131F73FFFF3 +:1096C0000E000E5A02E02821922E000031C2003F07 +:1096D0002C50000852000010000088210002F88081 +:1096E0003C0308002463535403E3C8218F3800006F +:1096F000030000080000000090CE0008938B008853 +:1097000031CD007F00AD6023016C50210A0010BFF5 +:109710002553FFFF000088213C1080008E040100CB +:109720000E000E7702E028218E0401000E000E8745 +:1097300002C028211220000F0013802B8F8A008482 +:1097400026A900010009AC00027298230015AC03A1 +:109750002545004002B4B02A0013802B24170001D5 +:1097600000A0882102D01024AF8500841440FFC9D6 +:10977000AFB700103C07800894F100503C05800012 +:109780003C06002002B1C821A4F90050ACA600306C +:1097900094F4005094E3005203D560231074001D2C +:1097A000319EFFFF8CE5004C8CE90048001561807C +:1097B00000ACB0210000A02102CCA82B0134502124 +:1097C0000155B821ACF6004CACF70048001E882BC0 +:1097D0000211782415E0FF803C1980088FB3001037 +:1097E0008FBF00548FBE00503A6200018FB7004C0B +:1097F0008FB600488FB500448FB400408FB3003C53 +:109800008FB200388FB100348FB0003003E0000811 +:1098100027BD005894F200548CEF0044325FFFFEE5 +:10982000001FC0C001F87021ACAE003C8CEB0044BE +:109830008CAD003C016D40231900003B000000008E +:109840008CE20040244200013C07005034E4001048 +:109850003C038000ACA20038AC6400300000000083 +:1098600000000000000000000000000000000000F8 +:109870000000000000000000000000008C760000E6 +:1098800032D7002012E0FFFD3C11800896280054DA +:109890003C0A80003C06800831190001001960C0B4 +:1098A000018AA0218E8304003C0708008CE7004455 +:1098B0003C150020ACC300488E8904042405000137 +:1098C000ACC9004C10E50259AD550030963F00522E +:1098D0003C0508008CA5004000BFC021A6380052FE +:1098E000962F005425EE0001A62E00549626005413 +:1098F00030C4FFFF5487FF34001E882B30A5FFFFC4 +:109900000E00109DA62000543C0408008C84002406 +:10991000962700520044102300E29023A632005202 +:109920000A0010C1001E882B8CE200400A00116260 +:109930003C07005092280001240700013102007FFB +:109940001447001C97AC001E8E2A0014240BC00084 +:1099500031443FFF018B48243C0608008CC6006060 +:109960000124282530A43FFF0086882B12200011F7 +:10997000A7A5001E3C1108008E3100588F82008080 +:10998000000441802407FF80022218210068F8218A +:1099900003E7C82433EF007F3C1880003C12800EA0 +:1099A000AF19002C01F2682191AE000D35D00004F2 +:1099B000A1B0000D0E000ED12412000124110001EF +:1099C0003C1080008E0401000E000E7702E028217A +:1099D0008E0401000E000E8702C028211620FF58B9 +:1099E0008F8A00840A00112C0013802B8F8600843C +:1099F00090C900013125002010A0018A2410000127 +:109A00003C048008348C0080918B007C8F91002076 +:109A100000009021316A00011140000FAFB000201A +:109A20008CD000148C8E0060020E682B15A00003F1 +:109A3000020038218C8700603C0480083483008059 +:109A40008C72007000F2782B15E0000200E02021FB +:109A50008C640070008090213C07800834E5008011 +:109A60008CD900148CBF0070033FC02B170000027C +:109A7000032020218CA400700092182310600003A2 +:109A8000AFA3002824080002AFA800208FA5002063 +:109A90000265102B144000B5000018218CC400385A +:109AA0008E2F000C3C180080AE2400008CCE0034B9 +:109AB0003C10FF9F01F86025AE2E000490CB003FC4 +:109AC000360DFFFF018D48243C0A00203C06FFEFC5 +:109AD000A22B000B012A382534C5FFFF00E54024E6 +:109AE0003C0200088F87008401022025AE24000C70 +:109AF0008CE30014AE2000188FAF0028AE230014B2 +:109B00008CF800183C1FFFFB37F9FFFFAE38001C34 +:109B10008CEE000800996824024F8021AE2E0024AC +:109B20008CEC000CAE2D000CA6200038A620003ACC +:109B3000AE30002CAE2C0020AE2000288CEB0014A0 +:109B40008FAA002801724823012A302310C0001177 +:109B5000AE26001090F0003D8E2C00048E2A0000EE +:109B600000106900018D28210000102100AD302B6C +:109B70000142482101264021AE250004AE28000004 +:109B800090E3003DA223000A8F9F008497F900060E +:109B9000A63900088F8A0024240200023C068008AF +:109BA000A142000034C900809525005C02402021BC +:109BB0008F90002430A8FFFF0E000E9DAFA8002458 +:109BC0008FA300240002FB808F8500843C044200A8 +:109BD00003E3C8250324C025AE1800048F840024A5 +:109BE0008CAF0038AC8F00188CAE0034AC8E001CEB +:109BF000AC80000CAC800010A4800014A48000167F +:109C0000A4800020A4800022AC80002490A7003F04 +:109C1000A48700025240018C240700018FAB00286A +:109C20005160000290A2003D90A2003E244C000131 +:109C3000A08C00018F840024AC9200083C1880089E +:109C400037100080920F007C31EE000215C0000238 +:109C500024070034240700308F8500843C088008E6 +:109C60003509008090A300009128007C3259000340 +:109C7000A08300308F9F00848F9000242404000470 +:109C800093F8000100997823240DC000A218003138 +:109C90008F9900248F8E008431E50003972C0032C9 +:109CA00095CB001200F24821018D502431623FFF14 +:109CB00001423025A72600329323003201253821A6 +:109CC00031080004307F003F37E40040A324003215 +:109CD000124000028F85002400E838213C0C8008E7 +:109CE000ACA70034358B01008D6200C02E4400010A +:109CF0002403FFDFACA2003890AA003C0004C94056 +:109D00003146007FA0A6003C8F8900242405FFBFB8 +:109D10009127003C00E54024A128003C8F8F0024BF +:109D200091FF003C03E3C02403198025A1F0003C0F +:109D30008F8B00848F8A00248D6E0020AD4E0040F2 +:109D40008D6D0024AD4D00448D6C0028AD4C004855 +:109D50008D62002C0E000EBCAD42004C8FA6002080 +:109D60002407000210C700118FA300200003202B3E +:109D700000048023027098240060802100609021FC +:109D80000A0011150010882B962700128F8400807E +:109D90000000902130E5FFFFA7A700140E000E6B16 +:109DA000241100010A0011C03C1080003C19800001 +:109DB0003C0280088F240100905800080E000E42DB +:109DC0003305007F8F8E00248FAF00208FA40028E2 +:109DD000A1CF00000E000E9D8F9000248FAD0024B7 +:109DE00000023B803C0B420000ED40258F87008441 +:109DF000010B2025AE0400048CE500388F90002470 +:109E000000005021000A1900AE0500188CEC003447 +:109E10003C087FFF3504FFFFAE0C001C90E9003EBC +:109E20008E1F001C8E1800180009C9000009370297 +:109E300003F968210066102501B9782B030270210F +:109E400001CF5821AE0D001CAE0B0018AE00000C67 +:109E5000AE00001090E5003E8FAF0028240E0005F4 +:109E6000A605001494EC00042405C00001E4582465 +:109E7000A60C001690EA003E01E02021A60A002070 +:109E800094E60004A6060022AE00002490E3003F02 +:109E9000A603000290E9003E90FF003D03E9C823BD +:109EA00027380001A21800018F8D00243C10800883 +:109EB000ADAF0008A1AE00308F9800248F820084DF +:109EC000360F0100970C0032944A00122410FF80D4 +:109ED00000AC382431463FFF00E61825A7030032C6 +:109EE000930900322405FFBF2403FFDF313F003F09 +:109EF00037F90040A31900328F8C00242418FFFF8B +:109F0000AD8000348DEE00C0AD8E0038918D003CE8 +:109F100031A2007FA182003C8F87002490EA003CA0 +:109F200001453024A0E6003C8F9900249329003C91 +:109F30000123F824A33F003C8F8D00243C1F8008A0 +:109F4000ADB80040ADB2004491AF00483C12800073 +:109F500001F07025A1AE00488F8700248F86008411 +:109F60008CEC004801921024004B5025ACEA0048CC +:109F700090C5003EA0E5004C8F8800848F830024AC +:109F800095090004A469004E8FE500600E0002E60A +:109F9000000000008F99FF2C8FAE00280002814046 +:109FA000932F007C0002C1000218682131F20002E8 +:109FB00000402821164000AA01CD30213C0A80082B +:109FC000354300809069007C313F000413E00003BA +:109FD0008FAE00280005608000CC3021240D0004E5 +:109FE0008F90002431C7000301A758233168000374 +:109FF00000C82021AE0400343C068008A6250038A5 +:10A000003C0580008CA4010090D100080E000E8752 +:10A010003225007F0E000EBC000000000A0012AACC +:10A020008FA300208F8500208CC2003824180003E5 +:10A03000A4A00008ACA200008CDF0034A0A0000A9D +:10A040008F920084ACBF00043C040080924F003F1C +:10A05000A0B8000C8CAE000C3C0DFF9FA0AF000B15 +:10A0600001C4402535ABFFFF3C11FFEF8F98008402 +:10A07000010B30243639FFFF00D96024ACAC000C52 +:10A080008F030014971F00128F870080ACA300106D +:10A090008F090014ACA00018ACA00020ACA90014DB +:10A0A000ACA000248F0A001833E93FFF000911809B +:10A0B000ACAA00288F1200080047782133EE000177 +:10A0C000ACB200308F08000C8F990024000F69C2D9 +:10A0D000000E238001A45821241100023C068008B0 +:10A0E000A4AB001CA4A00034ACA8002CA331000039 +:10A0F00034D90080972C005C8F8F00243C034200F1 +:10A10000318AFFFF01433825ADE700048F820084C8 +:10A11000241800012411C0008C5F0038240700348B +:10A12000ADFF00188C520034ADF2001CADE0000C05 +:10A13000ADE00010A5E00014A5E00016A5E00020A9 +:10A14000A5E00022ADE00024A5F00002A1F8000186 +:10A150008F8B00248F8E0084AD70000891CD00009D +:10A16000A16D00308F8800848F8400249105000148 +:10A17000A08500318F920024964C0032019150242A +:10A1800001491825A6430032925F003233E2003FB6 +:10A19000A24200329338007C330F000215E0000227 +:10A1A0008F840024240700303C028008AC870034F0 +:10A1B000345201008E5F00C0240EFFBF02009021C8 +:10A1C000AC9F00389098003C330F007FA08F003C7C +:10A1D0008F880024910D003C01AE5824A10B003C57 +:10A1E0008F86002490D1003C36390020A0D9003C55 +:10A1F0008F8A00848F8500240010882B8D4C0020CE +:10A20000ACAC00408D430024ACA300448D49002831 +:10A21000ACA900488D47002CACA7004C0E000EBC2A +:10A220003C1080000A0011160000000094CD00527E +:10A230003C0B08008D6B0024016D8821A4D10052D5 +:10A240000A0010C1001E882BA08700018F84002403 +:10A25000240D0001AC8D00080A00125F3C18800834 +:10A26000000290800A00133E00D2302127BDFFE09B +:10A270003C0D8008AFB20018AFB00010AFBF001C9B +:10A28000AFB1001435B200808E4C001835A8010023 +:10A29000964B000695A70050910900EC000C560261 +:10A2A000016728233143007F312600FF2402000389 +:10A2B000A3830088AF84008010C2001B30B0FFFF72 +:10A2C000910600EC2412000530C200FF105200334A +:10A2D00000000000160000098FBF001C8FB200189C +:10A2E0008FB100148FB00010240D0C003C0C8000C6 +:10A2F00027BD002003E00008AD8D00240E0010A44F +:10A30000020020218FBF001C8FB200188FB10014F3 +:10A310008FB00010240D0C003C0C800027BD0020E5 +:10A3200003E00008AD8D0024965800789651007A1D +:10A33000924E007D0238782631E8FFFF31C400C01C +:10A34000148000092D1100011600003700000000E4 +:10A350005620FFE28FBF001C0E000F7A00000000A5 +:10A360000A0014068FBF001C1620FFDA0000000050 +:10A370000E000F7A000000001440FFD88FBF001CB1 +:10A380001600002200000000925F007D33E2003FD3 +:10A39000A242007D0A0014068FBF001C950900DA56 +:10A3A0008F86006000802821240400050E000674BA +:10A3B0003130FFFF978300723C0480002465FFFF6B +:10A3C000A78500728C8A01B80540FFFE00000000DE +:10A3D000AC8001808FBF001CAC9001848FB200184C +:10A3E0008FB100148FB000103C0760133C0B1000BD +:10A3F000240D0C003C0C800027BD0020AC87018898 +:10A40000AC8B01B803E00008AD8D00240E0010A451 +:10A41000020020215040FFB18FBF001C925F007DE1 +:10A420000A00143333E2003F0E0010A40200202182 +:10A430001440FFAA8FBF001C12200007000000007C +:10A440009259007D3330003F36020040A242007D29 +:10A450000A0014068FBF001C0E000F7A00000000D7 +:10A460005040FF9E8FBF001C9259007D3330003F4B +:08A470000A00146236020040EC +:08A47800000000000000001BC1 +:10A480000000000F0000000A0000000800000006A5 +:10A4900000000005000000050000000400000004AA +:10A4A00000000003000000030000000300000003A0 +:10A4B0000000000300000002000000020000000293 +:10A4C0000000000200000002000000020000000284 +:10A4D0000000000200000002000000020000000274 +:10A4E0000000000200000002000000020000000264 +:0CA4F0000000000100000001000000015D +:04A4FC0080080100D3 +:10A50000800800808008000000000C0000003080FF +:10A5100008000F4808000FF40800100C0800102075 +:10A520000800103408000F4808000F4808001068A1 +:10A53000080010A0080010B0080010D8080017C8C4 +:10A54000080017C8080018000800180008001814B0 +:10A55000080017E408001A3C08001A0808001A94BA +:10A5600008001A9408001B1C08001A4C80080240BE +:10A57000080021A808001FF4080021D00800226864 +:10A58000080023B808002404080025280800243007 +:10A59000080024B408002064080029D008002974A9 +:10A5A0000800201008002010080020100800259C3A +:10A5B0000800259C08002010080020100800284CE6 +:10A5C00008002010080020100800201008002010AB +:10A5D000080028AC080020100800201008002010F7 +:10A5E000080020100800201008002010080020108B +:10A5F000080020100800201008002010080020107B +:10A600000800201008002010080020100800242452 +:10A6100008002010080020100800291C0800201045 +:10A62000080020100800201008002010080020104A +:10A63000080020100800201008002010080020103A +:10A64000080020100800201008002010080020102A +:10A65000080020100800201008002010080020101A +:10A66000080027700800201008002010080026E4C9 +:10A6700008002640080037880800375C08003728A3 +:10A68000080036FC080036DC08003690800801001F +:10A69000800800808008000080080080080046F0E4 +:10A6A0000800472808004670080046F0080046F0F9 +:0CA6B00008004450080046F008004AC4AE +:04A6BC000A000C760E +:10A6C00000000000000000000000000D72787035EE +:10A6D0002E302E306A390000050000030000000013 +:10A6E0000000000100000000000000000000000069 +:10A6F000000000000000000000000000000000005A +:10A700000000000000000000000000000000000049 +:10A710000000000000000000000000000000000039 +:10A720000000000000000000000000000000000029 +:10A730000000000000000000000000000000000019 +:10A740000000000000000000000000000000000009 +:10A7500000000000000000000000000000000000F9 +:10A7600000000000000000000000000000000000E9 +:10A7700000000000000000000000000000000000D9 +:10A7800000000000000000000000000000000000C9 +:10A7900000000000000000000000000000000000B9 +:10A7A00000000000000000000000000000000000A9 +:10A7B0000000000000000000000000000000000099 +:10A7C0000000000000000000000000000000000089 +:10A7D0000000000000000000000000000000000079 +:10A7E0000000000000000000000000000000000069 +:10A7F0000000000000000000000000000000000059 +:10A800000000000000000000000000000000000048 +:10A810000000000000000000000000000000000038 +:10A820000000000000000000000000000000000028 +:10A830000000000000000000000000000000000018 +:10A840000000000000000000000000000000000008 +:10A8500000000000000000000000000000000000F8 +:10A8600000000000000000000000000000000000E8 +:10A8700000000000000000000000000000000000D8 +:10A8800000000000000000000000000000000000C8 +:10A8900000000000000000000000000000000000B8 +:10A8A00000000000000000000000000000000000A8 +:10A8B0000000000000000000000000000000000098 +:10A8C0000000000000000000000000000000000088 +:10A8D0000000000000000000000000000000000078 +:10A8E0000000000000000000000000000000000068 +:10A8F0000000000000000000000000000000000058 +:10A900000000000000000000000000000000000047 +:10A910000000000000000000000000000000000037 +:10A920000000000000000000000000000000000027 +:10A930000000000000000000000000000000000017 +:10A940000000000000000000000000000000000007 +:10A9500000000000000000000000000000000000F7 +:10A9600000000000000000000000000000000000E7 +:10A9700000000000000000000000000000000000D7 +:10A9800000000000000000000000000000000000C7 +:10A9900000000000000000000000000000000000B7 +:10A9A00000000000000000000000000000000000A7 +:10A9B0000000000000000000000000000000000097 +:10A9C0000000000000000000000000000000000087 +:10A9D0000000000000000000000000000000000077 +:10A9E0000000000000000000000000000000000067 +:10A9F0000000000000000000000000000000000057 +:10AA00000000000000000000000000000000000046 +:10AA10000000000000000000000000000000000036 +:10AA20000000000000000000000000000000000026 +:10AA30000000000000000000000000000000000016 +:10AA40000000000000000000000000000000000006 +:10AA500000000000000000000000000000000000F6 +:10AA600000000000000000000000000000000000E6 +:10AA700000000000000000000000000000000000D6 +:10AA800000000000000000000000000000000000C6 +:10AA900000000000000000000000000000000000B6 +:10AAA00000000000000000000000000000000000A6 +:10AAB0000000000000000000000000000000000096 +:10AAC0000000000000000000000000000000000086 +:10AAD0000000000000000000000000000000000076 +:10AAE0000000000000000000000000000000000066 +:10AAF0000000000000000000000000000000000056 +:10AB00000000000000000000000000000000000045 +:10AB10000000000000000000000000000000000035 +:10AB20000000000000000000000000000000000025 +:10AB30000000000000000000000000000000000015 +:10AB40000000000000000000000000000000000005 +:10AB500000000000000000000000000000000000F5 +:10AB600000000000000000000000000000000000E5 +:10AB700000000000000000000000000000000000D5 +:10AB800000000000000000000000000000000000C5 +:10AB900000000000000000000000000000000000B5 +:10ABA00000000000000000000000000000000000A5 +:10ABB0000000000000000000000000000000000095 +:10ABC0000000000000000000000000000000000085 +:10ABD0000000000000000000000000000000000075 +:10ABE0000000000000000000000000000000000065 +:10ABF0000000000000000000000000000000000055 +:10AC00000000000000000000000000000000000044 +:10AC10000000000000000000000000000000000034 +:10AC20000000000000000000000000000000000024 +:10AC30000000000000000000000000000000000014 +:10AC40000000000000000000000000000000000004 +:10AC500000000000000000000000000000000000F4 +:10AC600000000000000000000000000000000000E4 +:10AC700000000000000000000000000000000000D4 +:10AC800000000000000000000000000000000000C4 +:10AC900000000000000000000000000000000000B4 +:10ACA00000000000000000000000000000000000A4 +:10ACB0000000000000000000000000000000000094 +:10ACC0000000000000000000000000000000000084 +:10ACD0000000000000000000000000000000000074 +:10ACE0000000000000000000000000000000000064 +:10ACF0000000000000000000000000000000000054 +:10AD00000000000000000000000000000000000043 +:10AD10000000000000000000000000000000000033 +:10AD20000000000000000000000000000000000023 +:10AD30000000000000000000000000000000000013 +:10AD40000000000000000000000000000000000003 +:10AD500000000000000000000000000000000000F3 +:10AD600000000000000000000000000000000000E3 +:10AD700000000000000000000000000000000000D3 +:10AD800000000000000000000000000000000000C3 +:10AD900000000000000000000000000000000000B3 +:10ADA00000000000000000000000000000000000A3 +:10ADB0000000000000000000000000000000000093 +:10ADC0000000000000000000000000000000000083 +:10ADD0000000000000000000000000000000000073 +:10ADE0000000000000000000000000000000000063 +:10ADF0000000000000000000000000000000000053 +:10AE00000000000000000000000000000000000042 +:10AE10000000000000000000000000000000000032 +:10AE20000000000000000000000000000000000022 +:10AE30000000000000000000000000000000000012 +:10AE40000000000000000000000000000000000002 +:10AE500000000000000000000000000000000000F2 +:10AE600000000000000000000000000000000000E2 +:10AE700000000000000000000000000000000000D2 +:10AE800000000000000000000000000000000000C2 +:10AE900000000000000000000000000000000000B2 +:10AEA00000000000000000000000000000000000A2 +:10AEB0000000000000000000000000000000000092 +:10AEC0000000000000000000000000000000000082 +:10AED0000000000000000000000000000000000072 +:10AEE0000000000000000000000000000000000062 +:10AEF0000000000000000000000000000000000052 +:10AF00000000000000000000000000000000000041 +:10AF10000000000000000000000000000000000031 +:10AF20000000000000000000000000000000000021 +:10AF30000000000000000000000000000000000011 +:10AF40000000000000000000000000000000000001 +:10AF500000000000000000000000000000000000F1 +:10AF600000000000000000000000000000000000E1 +:10AF700000000000000000000000000000000000D1 +:10AF800000000000000000000000000000000000C1 +:10AF900000000000000000000000000000000000B1 +:10AFA00000000000000000000000000000000000A1 +:10AFB0000000000000000000000000000000000091 +:10AFC0000000000000000000000000000000000081 +:10AFD0000000000000000000000000000000000071 +:10AFE0000000000000000000000000000000000061 +:10AFF0000000000000000000000000000000000051 +:10B000000000000000000000000000000000000040 +:10B010000000000000000000000000000000000030 +:10B020000000000000000000000000000000000020 +:10B030000000000000000000000000000000000010 +:10B040000000000000000000000000000000000000 +:10B0500000000000000000000000000000000000F0 +:10B0600000000000000000000000000000000000E0 +:10B0700000000000000000000000000000000000D0 +:10B0800000000000000000000000000000000000C0 +:10B0900000000000000000000000000000000000B0 +:10B0A00000000000000000000000000000000000A0 +:10B0B0000000000000000000000000000000000090 +:10B0C0000000000000000000000000000000000080 +:10B0D0000000000000000000000000000000000070 +:10B0E0000000000000000000000000000000000060 +:10B0F0000000000000000000000000000000000050 +:10B10000000000000000000000000000000000003F +:10B11000000000000000000000000000000000002F +:10B12000000000000000000000000000000000001F +:10B13000000000000000000000000000000000000F +:10B1400000000000000000000000000000000000FF +:10B1500000000000000000000000000000000000EF +:10B1600000000000000000000000000000000000DF +:10B1700000000000000000000000000000000000CF +:10B1800000000000000000000000000000000000BF +:10B1900000000000000000000000000000000000AF +:10B1A000000000000000000000000000000000009F +:10B1B000000000000000000000000000000000008F +:10B1C000000000000000000000000000000000007F +:10B1D000000000000000000000000000000000006F +:10B1E000000000000000000000000000000000005F +:10B1F000000000000000000000000000000000004F +:10B20000000000000000000000000000000000003E +:10B21000000000000000000000000000000000002E +:10B22000000000000000000000000000000000001E +:10B23000000000000000000000000000000000000E +:10B2400000000000000000000000000000000000FE +:10B2500000000000000000000000000000000000EE +:10B2600000000000000000000000000000000000DE +:10B2700000000000000000000000000000000000CE +:10B2800000000000000000000000000000000000BE +:10B2900000000000000000000000000000000000AE +:10B2A000000000000000000000000000000000009E +:10B2B000000000000000000000000000000000008E +:10B2C000000000000000000000000000000000007E +:10B2D000000000000000000000000000000000006E +:10B2E000000000000000000000000000000000005E +:10B2F000000000000000000000000000000000004E +:10B30000000000000000000000000000000000003D +:10B31000000000000000000000000000000000002D +:10B32000000000000000000000000000000000001D +:10B33000000000000000000000000000000000000D +:10B3400000000000000000000000000000000000FD +:10B3500000000000000000000000000000000000ED +:10B3600000000000000000000000000000000000DD +:10B3700000000000000000000000000000000000CD +:10B3800000000000000000000000000000000000BD +:10B3900000000000000000000000000000000000AD +:10B3A000000000000000000000000000000000009D +:10B3B000000000000000000000000000000000008D +:10B3C000000000000000000000000000000000007D +:10B3D000000000000000000000000000000000006D +:10B3E000000000000000000000000000000000005D +:10B3F000000000000000000000000000000000004D +:10B40000000000000000000000000000000000003C +:10B41000000000000000000000000000000000002C +:10B42000000000000000000000000000000000001C +:10B43000000000000000000000000000000000000C +:10B4400000000000000000000000000000000000FC +:10B4500000000000000000000000000000000000EC +:10B4600000000000000000000000000000000000DC +:10B4700000000000000000000000000000000000CC +:10B4800000000000000000000000000000000000BC +:10B4900000000000000000000000000000000000AC +:10B4A000000000000000000000000000000000009C +:10B4B000000000000000000000000000000000008C +:10B4C000000000000000000000000000000000007C +:10B4D000000000000000000000000000000000006C +:10B4E000000000000000000000000000000000005C +:10B4F000000000000000000000000000000000004C +:10B50000000000000000000000000000000000003B +:10B51000000000000000000000000000000000002B +:10B52000000000000000000000000000000000001B +:10B53000000000000000000000000000000000000B +:10B5400000000000000000000000000000000000FB +:10B5500000000000000000000000000000000000EB +:10B5600000000000000000000000000000000000DB +:10B5700000000000000000000000000000000000CB +:10B5800000000000000000000000000000000000BB +:10B5900000000000000000000000000000000000AB +:10B5A000000000000000000000000000000000009B +:10B5B000000000000000000000000000000000008B +:10B5C000000000000000000000000000000000007B +:10B5D000000000000000000000000000000000006B +:10B5E000000000000000000000000000000000005B +:10B5F000000000000000000000000000000000004B +:10B60000000000000000000000000000000000003A +:10B61000000000000000000000000000000000002A +:10B62000000000000000000000000000000000001A +:10B63000000000000000000000000000000000000A +:10B6400000000000000000000000000000000000FA +:10B6500000000000000000000000000000000000EA +:10B6600000000000000000000000000000000000DA +:10B6700000000000000000000000000000000000CA +:10B6800000000000000000000000000000000000BA +:10B6900000000000000000000000000000000000AA +:10B6A000000000000000000000000000000000009A +:10B6B000000000000000000000000000000000008A +:10B6C000000000000000000000000000000000007A +:10B6D000000000000000000000000000000000006A +:10B6E000000000000000000000000000000000005A +:10B6F000000000000000000000000000000000004A +:10B700000000000000000000000000000000000039 +:10B710000000000000000000000000000000000029 +:10B720000000000000000000000000000000000019 +:10B730000000000000000000000000000000000009 +:10B7400000000000000000000000000000000000F9 +:10B7500000000000000000000000000000000000E9 +:10B7600000000000000000000000000000000000D9 +:10B7700000000000000000000000000000000000C9 +:10B7800000000000000000000000000000000000B9 +:10B7900000000000000000000000000000000000A9 +:10B7A0000000000000000000000000000000000099 +:10B7B0000000000000000000000000000000000089 +:10B7C0000000000000000000000000000000000079 +:10B7D0000000000000000000000000000000000069 +:10B7E0000000000000000000000000000000000059 +:10B7F0000000000000000000000000000000000049 +:10B800000000000000000000000000000000000038 +:10B810000000000000000000000000000000000028 +:10B820000000000000000000000000000000000018 +:10B830000000000000000000000000000000000008 +:10B8400000000000000000000000000000000000F8 +:10B8500000000000000000000000000000000000E8 +:10B8600000000000000000000000000000000000D8 +:10B8700000000000000000000000000000000000C8 +:10B8800000000000000000000000000000000000B8 +:10B8900000000000000000000000000000000000A8 +:10B8A0000000000000000000000000000000000098 +:10B8B0000000000000000000000000000000000088 +:10B8C0000000000000000000000000000000000078 +:10B8D0000000000000000000000000000000000068 +:10B8E0000000000000000000000000000000000058 +:10B8F0000000000000000000000000000000000048 +:10B900000000000000000000000000000000000037 +:10B910000000000000000000000000000000000027 +:10B920000000000000000000000000000000000017 +:10B930000000000000000000000000000000000007 +:10B9400000000000000000000000000000000000F7 +:10B9500000000000000000000000000000000000E7 +:10B9600000000000000000000000000000000000D7 +:10B9700000000000000000000000000000000000C7 +:10B9800000000000000000000000000000000000B7 +:10B9900000000000000000000000000000000000A7 +:10B9A0000000000000000000000000000000000097 +:10B9B0000000000000000000000000000000000087 +:10B9C0000000000000000000000000000000000077 +:10B9D0000000000000000000000000000000000067 +:10B9E0000000000000000000000000000000000057 +:10B9F0000000000000000000000000000000000047 +:10BA00000000000000000000000000000000000036 +:10BA10000000000000000000000000000000000026 +:10BA20000000000000000000000000000000000016 +:10BA30000000000000000000000000000000000006 +:10BA400000000000000000000000000000000000F6 +:10BA500000000000000000000000000000000000E6 +:10BA600000000000000000000000000000000000D6 +:10BA700000000000000000000000000000000000C6 +:10BA800000000000000000000000000000000000B6 +:10BA900000000000000000000000000000000000A6 +:10BAA0000000000000000000000000000000000096 +:10BAB0000000000000000000000000000000000086 +:10BAC0000000000000000000000000000000000076 +:10BAD0000000000000000000000000000000000066 +:10BAE0000000000000000000000000000000000056 +:10BAF0000000000000000000000000000000000046 +:10BB00000000000000000000000000000000000035 +:10BB10000000000000000000000000000000000025 +:10BB20000000000000000000000000000000000015 +:10BB30000000000000000000000000000000000005 +:10BB400000000000000000000000000000000000F5 +:10BB500000000000000000000000000000000000E5 +:10BB600000000000000000000000000000000000D5 +:10BB700000000000000000000000000000000000C5 +:10BB800000000000000000000000000000000000B5 +:10BB900000000000000000000000000000000000A5 +:10BBA0000000000000000000000000000000000095 +:10BBB0000000000000000000000000000000000085 +:10BBC0000000000000000000000000000000000075 +:10BBD0000000000000000000000000000000000065 +:10BBE0000000000000000000000000000000000055 +:10BBF0000000000000000000000000000000000045 +:10BC00000000000000000000000000000000000034 +:10BC10000000000000000000000000000000000024 +:10BC20000000000000000000000000000000000014 +:10BC30000000000000000000000000000000000004 +:10BC400000000000000000000000000000000000F4 +:10BC500000000000000000000000000000000000E4 +:10BC600000000000000000000000000000000000D4 +:10BC700000000000000000000000000000000000C4 +:10BC800000000000000000000000000000000000B4 +:10BC900000000000000000000000000000000000A4 +:10BCA0000000000000000000000000000000000094 +:10BCB0000000000000000000000000000000000084 +:10BCC0000000000000000000000000000000000074 +:10BCD0000000000000000000000000000000000064 +:10BCE0000000000000000000000000000000000054 +:10BCF0000000000000000000000000000000000044 +:10BD00000000000000000000000000000000000033 +:10BD10000000000000000000000000000000000023 +:10BD20000000000000000000000000000000000013 +:10BD30000000000000000000000000000000000003 +:10BD400000000000000000000000000000000000F3 +:10BD500000000000000000000000000000000000E3 +:10BD600000000000000000000000000000000000D3 +:10BD700000000000000000000000000000000000C3 +:10BD800000000000000000000000000000000000B3 +:10BD900000000000000000000000000000000000A3 +:10BDA0000000000000000000000000000000000093 +:10BDB0000000000000000000000000000000000083 +:10BDC0000000000000000000000000000000000073 +:10BDD0000000000000000000000000000000000063 +:10BDE0000000000000000000000000000000000053 +:10BDF0000000000000000000000000000000000043 +:10BE00000000000000000000000000000000000032 +:10BE10000000000000000000000000000000000022 +:10BE20000000000000000000000000000000000012 +:10BE30000000000000000000000000000000000002 +:10BE400000000000000000000000000000000000F2 +:10BE500000000000000000000000000000000000E2 +:10BE600000000000000000000000000000000000D2 +:10BE700000000000000000000000000000000000C2 +:10BE800000000000000000000000000000000000B2 +:10BE900000000000000000000000000000000000A2 +:10BEA0000000000000000000000000000000000092 +:10BEB0000000000000000000000000000000000082 +:10BEC0000000000000000000000000000000000072 +:10BED0000000000000000000000000000000000062 +:10BEE0000000000000000000000000000000000052 +:10BEF0000000000000000000000000000000000042 +:10BF00000000000000000000000000000000000031 +:10BF10000000000000000000000000000000000021 +:10BF20000000000000000000000000000000000011 +:10BF30000000000000000000000000000000000001 +:10BF400000000000000000000000000000000000F1 +:10BF500000000000000000000000000000000000E1 +:10BF600000000000000000000000000000000000D1 +:10BF700000000000000000000000000000000000C1 +:10BF800000000000000000000000000000000000B1 +:10BF900000000000000000000000000000000000A1 +:10BFA0000000000000000000000000000000000091 +:10BFB0000000000000000000000000000000000081 +:10BFC0000000000000000000000000000000000071 +:10BFD0000000000000000000000000000000000061 +:10BFE0000000000000000000000000000000000051 +:10BFF0000000000000000000000000000000000041 +:10C000000000000000000000000000000000000030 +:10C010000000000000000000000000000000000020 +:10C020000000000000000000000000000000000010 +:10C030000000000000000000000000000000000000 +:10C0400000000000000000000000000000000000F0 +:10C0500000000000000000000000000000000000E0 +:10C0600000000000000000000000000000000000D0 +:10C0700000000000000000000000000000000000C0 +:10C0800000000000000000000000000000000000B0 +:10C0900000000000000000000000000000000000A0 +:10C0A0000000000000000000000000000000000090 +:10C0B0000000000000000000000000000000000080 +:10C0C0000000000000000000000000000000000070 +:10C0D0000000000000000000000000000000000060 +:10C0E0000000000000000000000000000000000050 +:10C0F0000000000000000000000000000000000040 +:10C10000000000000000000000000000000000002F +:10C11000000000000000000000000000000000001F +:10C12000000000000000000000000000000000000F +:10C1300000000000000000000000000000000000FF +:10C1400000000000000000000000000000000000EF +:10C1500000000000000000000000000000000000DF +:10C1600000000000000000000000000000000000CF +:10C1700000000000000000000000000000000000BF +:10C1800000000000000000000000000000000000AF +:10C19000000000000000000000000000000000009F +:10C1A000000000000000000000000000000000008F +:10C1B000000000000000000000000000000000007F +:10C1C000000000000000000000000000000000006F +:10C1D000000000000000000000000000000000005F +:10C1E000000000000000000000000000000000004F +:10C1F000000000000000000000000000000000003F +:10C20000000000000000000000000000000000002E +:10C21000000000000000000000000000000000001E +:10C22000000000000000000000000000000000000E +:10C2300000000000000000000000000000000000FE +:10C2400000000000000000000000000000000000EE +:10C2500000000000000000000000000000000000DE +:10C2600000000000000000000000000000000000CE +:10C2700000000000000000000000000000000000BE +:10C2800000000000000000000000000000000000AE +:10C29000000000000000000000000000000000009E +:10C2A000000000000000000000000000000000008E +:10C2B000000000000000000000000000000000007E +:10C2C000000000000000000000000000000000006E +:10C2D000000000000000000000000000000000005E +:10C2E000000000000000000000000000000000004E +:10C2F000000000000000000000000000000000003E +:10C30000000000000000000000000000000000002D +:10C31000000000000000000000000000000000001D +:10C32000000000000000000000000000000000000D +:10C3300000000000000000000000000000000000FD +:10C3400000000000000000000000000000000000ED +:10C3500000000000000000000000000000000000DD +:10C3600000000000000000000000000000000000CD +:10C3700000000000000000000000000000000000BD +:10C3800000000000000000000000000000000000AD +:10C39000000000000000000000000000000000009D +:10C3A000000000000000000000000000000000008D +:10C3B000000000000000000000000000000000007D +:10C3C000000000000000000000000000000000006D +:10C3D000000000000000000000000000000000005D +:10C3E000000000000000000000000000000000004D +:10C3F000000000000000000000000000000000003D +:10C40000000000000000000000000000000000002C +:10C41000000000000000000000000000000000001C +:10C42000000000000000000000000000000000000C +:10C4300000000000000000000000000000000000FC +:10C4400000000000000000000000000000000000EC +:10C4500000000000000000000000000000000000DC +:10C4600000000000000000000000000000000000CC +:10C4700000000000000000000000000000000000BC +:10C4800000000000000000000000000000000000AC +:10C49000000000000000000000000000000000009C +:10C4A000000000000000000000000000000000008C +:10C4B000000000000000000000000000000000007C +:10C4C000000000000000000000000000000000006C +:10C4D000000000000000000000000000000000005C +:10C4E000000000000000000000000000000000004C +:10C4F000000000000000000000000000000000003C +:10C50000000000000000000000000000000000002B +:10C51000000000000000000000000000000000001B +:10C52000000000000000000000000000000000000B +:10C5300000000000000000000000000000000000FB +:10C5400000000000000000000000000000000000EB +:10C5500000000000000000000000000000000000DB +:10C5600000000000000000000000000000000000CB +:10C5700000000000000000000000000000000000BB +:10C5800000000000000000000000000000000000AB +:10C59000000000000000000000000000000000009B +:10C5A000000000000000000000000000000000008B +:10C5B000000000000000000000000000000000007B +:10C5C000000000000000000000000000000000006B +:10C5D000000000000000000000000000000000005B +:10C5E000000000000000000000000000000000004B +:10C5F000000000000000000000000000000000003B +:10C60000000000000000000000000000000000002A +:10C61000000000000000000000000000000000001A +:10C62000000000000000000000000000000000000A +:10C6300000000000000000000000000000000000FA +:10C6400000000000000000000000000000000000EA +:10C6500000000000000000000000000000000000DA +:10C6600000000000000000000000000000000000CA +:10C6700000000000000000000000000000000000BA +:10C6800000000000000000000000000000000000AA +:10C69000000000000000000000000000000000009A +:10C6A000000000000000000000000000000000008A +:10C6B000000000000000000000000000000000007A +:10C6C000000000000000000000000000000000006A +:10C6D000000000000000000000000000000000005A +:10C6E000000000000000000000000000000000004A +:10C6F000000000000000000000000000000000003A +:10C700000000000000000000000000000000000029 +:10C710000000000000000000000000000000000019 +:10C720000000000000000000000000000000000009 +:10C7300000000000000000000000000000000000F9 +:10C7400000000000000000000000000000000000E9 +:10C7500000000000000000000000000000000000D9 +:10C7600000000000000000000000000000000000C9 +:10C7700000000000000000000000000000000000B9 +:10C7800000000000000000000000000000000000A9 +:10C790000000000000000000000000000000000099 +:10C7A0000000000000000000000000000000000089 +:10C7B0000000000000000000000000000000000079 +:10C7C0000000000000000000000000000000000069 +:10C7D0000000000000000000000000000000000059 +:10C7E0000000000000000000000000000000000049 +:10C7F0000000000000000000000000000000000039 +:10C800000000000000000000000000000000000028 +:10C810000000000000000000000000000000000018 +:10C820000000000000000000000000000000000008 +:10C8300000000000000000000000000000000000F8 +:10C8400000000000000000000000000000000000E8 +:10C8500000000000000000000000000000000000D8 +:10C8600000000000000000000000000000000000C8 +:10C8700000000000000000000000000000000000B8 +:10C8800000000000000000000000000000000000A8 +:10C890000000000000000000000000000000000098 +:10C8A0000000000000000000000000000000000088 +:10C8B0000000000000000000000000000000000078 +:10C8C0000000000000000000000000000000000068 +:10C8D0000000000000000000000000000000000058 +:10C8E0000000000000000000000000000000000048 +:10C8F0000000000000000000000000000000000038 +:10C900000000000000000000000000000000000027 +:10C910000000000000000000000000000000000017 +:10C920000000000000000000000000000000000007 +:10C9300000000000000000000000000000000000F7 +:10C9400000000000000000000000000000000000E7 +:10C9500000000000000000000000000000000000D7 +:10C9600000000000000000000000000000000000C7 +:10C9700000000000000000000000000000000000B7 +:10C9800000000000000000000000000000000000A7 +:10C990000000000000000000000000000000000097 +:10C9A0000000000000000000000000000000000087 +:10C9B0000000000000000000000000000000000077 +:10C9C0000000000000000000000000000000000067 +:10C9D0000000000000000000000000000000000057 +:10C9E0000000000000000000000000000000000047 +:10C9F0000000000000000000000000000000000037 +:10CA00000000000000000000000000000000000026 +:10CA10000000000000000000000000000000000016 +:10CA20000000000000000000000000000000000006 +:10CA300000000000000000000000000000000000F6 +:10CA400000000000000000000000000000000000E6 +:10CA500000000000000000000000000000000000D6 +:10CA600000000000000000000000000000000000C6 +:10CA700000000000000000000000000000000000B6 +:10CA800000000000000000000000000000000000A6 +:10CA90000000000000000000000000000000000096 +:10CAA0000000000000000000000000000000000086 +:10CAB0000000000000000000000000000000000076 +:10CAC0000000000000000000000000000000000066 +:10CAD0000000000000000000000000000000000056 +:10CAE0000000000000000000000000000000000046 +:10CAF0000000000000000000000000000000000036 +:10CB00000000000000000000000000000000000025 +:10CB10000000000000000000000000000000000015 +:10CB20000000000000000000000000000000000005 +:10CB300000000000000000000000000000000000F5 +:10CB400000000000000000000000000000000000E5 +:10CB500000000000000000000000000000000000D5 +:10CB600000000000000000000000000000000000C5 +:10CB700000000000000000000000000000000000B5 +:10CB800000000000000000000000000000000000A5 +:10CB90000000000000000000000000000000000095 +:10CBA0000000000000000000000000000000000085 +:10CBB0000000000000000000000000000000000075 +:10CBC0000000000000000000000000000000000065 +:10CBD0000000000000000000000000000000000055 +:10CBE0000000000000000000000000000000000045 +:10CBF0000000000000000000000000000000000035 +:10CC00000000000000000000000000000000000024 +:10CC10000000000000000000000000000000000014 +:10CC20000000000000000000000000000000000004 +:10CC300000000000000000000000000000000000F4 +:10CC400000000000000000000000000000000000E4 +:10CC500000000000000000000000000000000000D4 +:10CC600000000000000000000000000000000000C4 +:10CC700000000000000000000000000000000000B4 +:10CC800000000000000000000000000000000000A4 +:10CC90000000000000000000000000000000000094 +:10CCA0000000000000000000000000000000000084 +:10CCB0000000000000000000000000000000000074 +:10CCC0000000000000000000000000000000000064 +:10CCD0000000000000000000000000000000000054 +:10CCE0000000000000000000000000000000000044 +:10CCF0000000000000000000000000000000000034 +:10CD00000000000000000000000000000000000023 +:10CD10000000000000000000000000000000000013 +:10CD20000000000000000000000000000000000003 +:10CD300000000000000000000000000000000000F3 +:10CD400000000000000000000000000000000000E3 +:10CD500000000000000000000000000000000000D3 +:10CD600000000000000000000000000000000000C3 +:10CD700000000000000000000000000000000000B3 +:10CD800000000000000000000000000000000000A3 +:10CD90000000000000000000000000000000000093 +:10CDA0000000000000000000000000000000000083 +:10CDB0000000000000000000000000000000000073 +:10CDC0000000000000000000000000000000000063 +:10CDD0000000000000000000000000000000000053 +:10CDE0000000000000000000000000000000000043 +:10CDF0000000000000000000000000000000000033 +:10CE00000000000000000000000000000000000022 +:10CE10000000000000000000000000000000000012 +:10CE20000000000000000000000000000000000002 +:10CE300000000000000000000000000000000000F2 +:10CE400000000000000000000000000000000000E2 +:10CE500000000000000000000000000000000000D2 +:10CE600000000000000000000000000000000000C2 +:10CE700000000000000000000000000000000000B2 +:10CE800000000000000000000000000000000000A2 +:10CE90000000000000000000000000000000000092 +:10CEA0000000000000000000000000000000000082 +:10CEB0000000000000000000000000000000000072 +:10CEC0000000000000000000000000000000000062 +:10CED0000000000000000000000000000000000052 +:10CEE0000000000000000000000000000000000042 +:10CEF0000000000000000000000000000000000032 +:10CF00000000000000000000000000000000000021 +:10CF10000000000000000000000000000000000011 +:10CF20000000000000000000000000000000000001 +:10CF300000000000000000000000000000000000F1 +:10CF400000000000000000000000000000000000E1 +:10CF500000000000000000000000000000000000D1 +:10CF600000000000000000000000000000000000C1 +:10CF700000000000000000000000000000000000B1 +:10CF800000000000000000000000000000000000A1 +:10CF90000000000000000000000000000000000091 +:10CFA0000000000000000000000000000000000081 +:10CFB0000000000000000000000000000000000071 +:10CFC0000000000000000000000000000000000061 +:10CFD0000000000000000000000000000000000051 +:10CFE0000000000000000000000000000000000041 +:10CFF0000000000000000000000000000000000031 +:10D000000000000000000000000000000000000020 +:10D010000000000000000000000000000000000010 +:10D020000000000000000000000000000000000000 +:10D0300000000000000000000000000000000000F0 +:10D0400000000000000000000000000000000000E0 +:10D0500000000000000000000000000000000000D0 +:10D0600000000000000000000000000000000000C0 +:10D0700000000000000000000000000000000000B0 +:10D0800000000000000000000000000000000000A0 +:10D090000000000000000000000000000000000090 +:10D0A0000000000000000000000000000000000080 +:10D0B0000000000000000000000000000000000070 +:10D0C0000000000000000000000000000000000060 +:10D0D0000000000000000000000000000000000050 +:10D0E0000000000000000000000000000000000040 +:10D0F0000000000000000000000000000000000030 +:10D10000000000000000000000000000000000001F +:10D11000000000000000000000000000000000000F +:10D1200000000000000000000000000000000000FF +:10D1300000000000000000000000000000000000EF +:10D1400000000000000000000000000000000000DF +:10D1500000000000000000000000000000000000CF +:10D1600000000000000000000000000000000000BF +:10D1700000000000000000000000000000000000AF +:10D18000000000000000000000000000000000009F +:10D19000000000000000000000000000000000008F +:10D1A000000000000000000000000000000000007F +:10D1B000000000000000000000000000000000006F +:10D1C000000000000000000000000000000000005F +:10D1D000000000000000000000000000000000004F +:10D1E000000000000000000000000000000000003F +:10D1F000000000000000000000000000000000002F +:10D20000000000000000000000000000000000001E +:10D21000000000000000000000000000000000000E +:10D2200000000000000000000000000000000000FE +:10D2300000000000000000000000000000000000EE +:10D2400000000000000000000000000000000000DE +:10D2500000000000000000000000000000000000CE +:10D2600000000000000000000000000000000000BE +:10D2700000000000000000000000000000000000AE +:10D28000000000000000000000000000000000009E +:10D29000000000000000000000000000000000008E +:10D2A000000000000000000000000000000000007E +:10D2B000000000000000000000000000000000006E +:10D2C000000000000000000000000000000000005E +:10D2D000000000000000000000000000000000004E +:10D2E000000000000000000000000000000000003E +:10D2F000000000000000000000000000000000002E +:10D30000000000000000000000000000000000001D +:10D31000000000000000000000000000000000000D +:10D3200000000000000000000000000000000000FD +:10D3300000000000000000000000000000000000ED +:10D3400000000000000000000000000000000000DD +:10D3500000000000000000000000000000000000CD +:10D3600000000000000000000000000000000000BD +:10D3700000000000000000000000000000000000AD +:10D38000000000000000000000000000000000009D +:10D39000000000000000000000000000000000008D +:10D3A000000000000000000000000000000000007D +:10D3B000000000000000000000000000000000006D +:10D3C000000000000000000000000000000000005D +:10D3D000000000000000000000000000000000004D +:10D3E000000000000000000000000000000000003D +:10D3F000000000000000000000000000000000002D +:10D40000000000000000000000000000000000001C +:10D41000000000000000000000000000000000000C +:10D4200000000000000000000000000000000000FC +:10D4300000000000000000000000000000000000EC +:10D4400000000000000000000000000000000000DC +:10D4500000000000000000000000000000000000CC +:10D4600000000000000000000000000000000000BC +:10D4700000000000000000000000000000000000AC +:10D48000000000000000000000000000000000009C +:10D49000000000000000000000000000000000008C +:10D4A000000000000000000000000000000000007C +:10D4B000000000000000000000000000000000006C +:10D4C000000000000000000000000000000000005C +:10D4D000000000000000000000000000000000004C +:10D4E000000000000000000000000000000000003C +:10D4F000000000000000000000000000000000002C +:10D50000000000000000000000000000000000001B +:10D51000000000000000000000000000000000000B +:10D5200000000000000000000000000000000000FB +:10D5300000000000000000000000000000000000EB +:10D5400000000000000000000000000000000000DB +:10D5500000000000000000000000000000000000CB +:10D5600000000000000000000000000000000000BB +:10D5700000000000000000000000000000000000AB +:10D58000000000000000000000000000000000009B +:10D59000000000000000000000000000000000008B +:10D5A000000000000000000000000000000000007B +:10D5B000000000000000000000000000000000006B +:10D5C000000000000000000000000000000000005B +:10D5D000000000000000000000000000000000004B +:10D5E000000000000000000000000000000000003B +:10D5F000000000000000000000000000000000002B +:10D60000000000000000000000000000000000001A +:10D61000000000000000000000000000000000000A +:10D6200000000000000000000000000000000000FA +:10D6300000000000000000000000000000000000EA +:10D6400000000000000000000000000000000000DA +:10D6500000000000000000000000000000000000CA +:10D6600000000000000000000000000000000000BA +:10D6700000000000000000000000000000000000AA +:10D68000000000000000000000000000000000009A +:10D69000000000000000000000000000000000008A +:10D6A000000000000000000000000000000000007A +:10D6B000000000000000000000000000000000006A +:10D6C000000000000000000000000000000000005A +:10D6D000000000000000000000000000000000004A +:10D6E000000000000000000000000000000000003A +:10D6F000000000000000000000000000000000002A +:10D700000000000000000000000000000000000019 +:10D710000000000000000000000000000000000009 +:10D7200000000000000000000000000000000000F9 +:10D7300000000000000000000000000000000000E9 +:10D7400000000000000000000000000000000000D9 +:10D7500000000000000000000000000000000000C9 +:10D7600000000000000000000000000000000000B9 +:10D7700000000000000000000000000000000000A9 +:10D780000000000000000000000000000000000099 +:10D790000000000000000000000000000000000089 +:10D7A0000000000000000000000000000000000079 +:10D7B0000000000000000000000000000000000069 +:10D7C0000000000000000000000000000000000059 +:10D7D0000000000000000000000000000000000049 +:10D7E0000000000000000000000000000000000039 +:10D7F0000000000000000000000000000000000029 +:10D800000000000000000000000000000000000018 +:10D810000000000000000000000000000000000008 +:10D8200000000000000000000000000000000000F8 +:10D8300000000000000000000000000000000000E8 +:10D8400000000000000000000000000000000000D8 +:10D8500000000000000000000000000000000000C8 +:10D8600000000000000000000000000000000000B8 +:10D8700000000000000000000000000000000000A8 +:10D880000000000000000000000000000000000098 +:10D890000000000000000000100000030000000075 +:10D8A0000000000D0000000D3C020801244282A08F +:10D8B0003C03080124638360AC4000000043202B3C +:10D8C0001480FFFD244200043C1D080037BD9FFC6E +:10D8D00003A0F0213C100800261031D83C1C0801A0 +:10D8E000279C82A00E0011EA000000000000000D3D +:10D8F0003C02800030A5FFFF30C600FF34430180AA +:10D900003C0880008D0901B80520FFFE00000000E2 +:10D91000AC64000024040002A4650008A066000AAC +:10D92000A064000BAC6700183C03100003E0000883 +:10D93000AD0301B83C0560008CA24FF80440FFFE27 +:10D9400000000000ACA44FC03C0310003C040200E7 +:10D95000ACA44FC403E00008ACA34FF89486000CBD +:10D9600000A050212488001400062B02000510801E +:10D97000004448210109182B10600011000000002C +:10D98000910300002C6400095080000991190001E6 +:10D99000000360803C0D080125AD8154018D5821A4 +:10D9A0008D67000000E000080000000091190001F0 +:10D9B000011940210109302B54C0FFF291030000EE +:10D9C00003E00008000010210A000CBE2508000139 +:10D9D000910F0001240E000A15EE00400128C82313 +:10D9E0002F38000A1700003D250D00028D58000059 +:10D9F000250F0006370E0100AD4E0000910C00020D +:10DA000091AB000191A4000291A60003000C2E002E +:10DA1000000B3C0000A7102500041A000043C82595 +:10DA20000326C025AD580004910E000691ED0001BB +:10DA300091E7000291E50003000E5E00000D640016 +:10DA4000016C30250007220000C410250045182570 +:10DA50002508000A0A000CBEAD430008910F000122 +:10DA6000250400022408000255E8000101202021BD +:10DA70000A000CBE00804021910C0001240B000321 +:10DA8000158B0016000000008D580000910E00025A +:10DA900025080003370D0008A14E00100A000CBE37 +:10DAA000AD4D000091190001240F0004172F000B49 +:10DAB0000000000091070002910400038D43000064 +:10DAC00000072A0000A4102534660004250800047D +:10DAD000AD42000C0A000CBEAD46000003E0000899 +:10DAE0002402000127BDFFE8AFBF0014AFB0001053 +:10DAF0000E0014FC008080213C04800834850080E6 +:10DB000090A600052403FFFE0200202100C310247C +:10DB10008FBF00148FB00010A0A200050A001506E8 +:10DB200027BD001827BDFFE8AFB00010AFBF00143D +:10DB30000E000F4E008080213C06800834C5008016 +:10DB400090A4000024020050308300FF1062000700 +:10DB50003C098000020020218FBF00148FB000100C +:10DB6000AD2001800A00101027BD00182408010014 +:10DB70003C078000020020218FBF00148FB00010EE +:10DB8000ACE801800A00101027BD001827BDFF7007 +:10DB90003C088008AFB60080AFB5007CAFB1006C28 +:10DBA000AFBF008CAFBE0088AFB70084AFB40078C1 +:10DBB000AFB30074AFB20070AFB00068350500803D +:10DBC0003C0780008CF2012890A40009ACE000849E +:10DBD00090A60005309100FF0000A821000618273C +:10DBE000306200010000B02114400067AFA0005077 +:10DBF00090A9000024050020312400FF10850016A4 +:10DC0000240A0050108A008C000000003C0C080020 +:10DC10008D8C00DC258B00013C010800AC2B00DC66 +:10DC20000E0015F2000000008FBF008C8FBE008830 +:10DC30008FB700848FB600808FB5007C8FB40078DA +:10DC40008FB300748FB200708FB1006C8FB000681A +:10DC500003E0000827BD00900000000D3C1080008C +:10DC6000AFA00030961F01168E1901043C1E002043 +:10DC700036130C00033EC0240018B82B00173140A7 +:10DC8000AFA600308E0E010433F4FFFF3C0F0040BE +:10DC90000293802101CF68249213000D11A0004847 +:10DCA00034C40040326200201440000234860080F8 +:10DCB0000080302114C00093AFA600303C058008DE +:10DCC00034A800809107000830E6004050C00006EC +:10DCD0003C06800824090004122900A2240A00122C +:10DCE000122A00293C06800834D401003C17800029 +:10DCF00096EF011A960D000E928E0008326B00040A +:10DD000031F7FFFF01CD6004AFAC00548E14000466 +:10DD1000116000318E1E000834C300809079000825 +:10DD20003338004017000028000000008C730050BA +:10DD300002939023064000063C0C80008C7E003449 +:10DD4000029E8023060200838EA200083C0C800005 +:10DD5000AD800044240200018FBF008C8FBE00887C +:10DD60008FB700848FB600808FB5007C8FB40078A9 +:10DD70008FB300748FB200708FB1006C8FB00068E9 +:10DD800003E0000827BD00900E000D1A00002021BE +:10DD90008FBF008C8FBE00888FB700848FB6008045 +:10DDA0008FB5007C8FB400788FB300748FB2007091 +:10DDB0008FB1006C8FB0006803E0000827BD0090B1 +:10DDC0000A000D7A00C020210E0016530280202187 +:10DDD0001440FFDF3C0C80003C038008346300806B +:10DDE0008C6200340282F82307E000170000000074 +:10DDF0003C1508008EB5310026B100013C01080039 +:10DE0000AC3131000E0014FC024020213C0B800894 +:10DE100035700080920A002502402021354200041E +:10DE20000E001506A20200250E000C9E02402021C5 +:10DE30000A000DA7240200013C15080126B58350F5 +:10DE40000A000D693C1080008C6600300286202399 +:10DE5000188000082409000C3C0808008D083100D7 +:10DE6000327300FC0000B821250700013C010800C6 +:10DE7000AC273100AFA900308C65003000B43823E6 +:10DE800018E000DB02E7502A1540FFDE000000002A +:10DE900012E7002A02E768230287A02131B7FFFFBB +:10DEA000326E000211C00034327F00103C14800832 +:10DEB00036900080920F000831F6004052C000CE2C +:10DEC0008EA20008024020210E0014FC241300182A +:10DED000A2130009921800052419FFFE0240202118 +:10DEE0000319B8240E001506A217000524040039F2 +:10DEF000000028210E00162E240600180A000DA787 +:10DF00002402000192B6000C3C0480083483008097 +:10DF10008C6700380016AB0036B10081024020212A +:10DF20003225F0810E000C8D30C600FF3C0C8000C5 +:10DF3000AD8000440A000DA7240200013A6C0001E4 +:10DF4000318B00011560FFAF0287A0210A000DF898 +:10DF5000000000000040F809240400160A000DA784 +:10DF600024020001024020210E0017330200282164 +:10DF70000A000D5C8FBF008C13E0FF743C03800827 +:10DF8000346800808D0400388C66000403C61023BA +:10DF90001C40FF6F3C0C800003C4282304A2000136 +:10DFA0000080F021AFB40010AFB70014AFA7001885 +:10DFB0003C1F800097E301208D0900309506005C2E +:10DFC0008FB900548FAC00303062FFFF30D8FFFFB4 +:10DFD0000047702137EF40000338682B01CF5821EC +:10DFE000018D5025AFAB0020AFA90028AFAA0030AB +:10DFF000AFA90024AFA0002CAFBE003491070008E9 +:10E0000030E400081480008F020020218EA200045A +:10E010000040F80927A400108FA900303128000221 +:10E0200055000001327300FE3C048008348C0080EF +:10E03000918B0008316A0040514000128FA40024E7 +:10E040008C8D000411BE00BE240E00143265000148 +:10E0500010A0000C8FA400242404000C122400D46F +:10E060002A27000D10E000CE2409000E2408000A23 +:10E0700052280001241600088FA200242444000125 +:10E08000AFA400248FA600143C03800834650080F0 +:10E090000086F8218CB10030ACBF003090B9004E42 +:10E0A0008CAE00303418FFFF0338780401CF6821AC +:10E0B000ACAD00348FA600308FAC005430CA0008DD +:10E0C00003CC58211140000CAFAB00588CA40020A9 +:10E0D0008FB000581090009430C600FF92A2000C40 +:10E0E0008FA700340240202100024B003528008019 +:10E0F0000E000C8D3105F0803C0C800835900080BE +:10E100008E0B003001715023194000702659008099 +:10E110003C1808008F183198241FFF80033F782493 +:10E12000332D007F3C0680003C0E8004331100102C +:10E13000ACCF00901220003401AE282190A3006BD8 +:10E14000546000323C10800824070001A0A7006B37 +:10E1500094C4007A2486000AA60600123C0D8008AA +:10E1600035A5008090B10008322C004015800004D5 +:10E170003C038008326E000115C000620000000000 +:10E18000346400808C8F00208FB3005811F3000A94 +:10E19000346301008C7900000299C0231B000077D2 +:10E1A0008FA80058AC880020AC7400002414000133 +:10E1B000AC7E0004AFB4005016C000370000000071 +:10E1C0008FA40050148000300000000012E0000511 +:10E1D000000018218FA900303137000452E0FE9270 +:10E1E00000601021240300010A000D5B0060102173 +:10E1F0000A000DF9000038210040F8092404001736 +:10E200000A000DA7240200013C108008361000808F +:10E2100024090001024020210E0014FCA60900126E +:10E220009208002524050001AFA500503502000129 +:10E23000024020210E001506A20200250A000EA9A8 +:10E240003C0D800827A50038AFA800600E000CA880 +:10E25000AFA000381440FF6D8FA800608FA5003874 +:10E2600030B001005200FF6A8EA200048FA3003C70 +:10E270008D070058006720230483FF64AD03005816 +:10E280000A000E558EA200040E000C9E02402021B2 +:10E290000A000EC4000000000E0014FC0240202101 +:10E2A0003C05800834A30080024020210E001506A2 +:10E2B000A076000902C03021240400370E00162E7B +:10E2C000000028210A000EC28FA400508FA200185F +:10E2D0005840FFA33C0D80080E0014FC0240202192 +:10E2E000920A0025240B0001AFAB00503542000418 +:10E2F000024020210E001506A20200250A000EA9E8 +:10E300003C0D80088CB600308EBE00082404001836 +:10E3100026D5000103C0F809ACB500308FB200303B +:10E320000A000D5B324200043C07800094E5011AAC +:10E3300050A0FF6A34C600100A000E8992A2000C99 +:10E34000122E002A2A2F001511E0001E2419001693 +:10E350002418000C5638FF3E326500013C1F80082F +:10E3600093E3001B2410FFBD2416000E0070302420 +:10E37000A3E6001B0A000E65326500018C7F0000D9 +:10E3800017F4FF8D000000008C67000403C73023E2 +:10E3900004C1FF848FA800580A000EBF00000000CF +:10E3A0001629FF368FA200240A000E7024160010D2 +:10E3B0002411000E52D1FF30241600100A000E6FF7 +:10E3C000241600165639FF22326500013C1F8008D2 +:10E3D00093E3001B2410FFBD2416001000703024AE +:10E3E000A3E6001B0A000E65326500010A000E64F8 +:10E3F000241600123C0380008C6201B80440FFFE2A +:10E4000024040800AC6401B803E000080000000028 +:10E4100030A5FFFF30C6FFFF3C0780008CE201B84B +:10E420000440FFFE34E80180AD040000ACE40020AD +:10E430003C048008948300483063FFFF1060001D97 +:10E440003C0B800024AA0012006A482B5120001ABD +:10E45000240A000394F901208F890000240C001A7B +:10E460003338FFFF2707FFFE0067782B39EE0001E6 +:10E4700000096B8201AE5824A10C000B116000470B +:10E480008F830004A50700148F880004350700015E +:10E49000AF87000430CC00405580000F3C0880005E +:10E4A0003C0C800035840180A485000E0A000F9882 +:10E4B0008F8F000C240A00033564018030CC0040AB +:10E4C0008F8900008F870004A08A000B5180FFF520 +:10E4D0003C0C80003C088000950301203C0880082B +:10E4E000951800403079FFFF272EFFFE330FFFFF06 +:10E4F00001CF682B11A0000301C02021950200402C +:10E500003044FFFF3C0B800000A4502335650180A0 +:10E51000A4A4000EA4AA00248F8F000C3C05800048 +:10E5200034AE01802418000230ED8000A5D8000C24 +:10E53000A5C90010ADCF0028A5C6000811A0000E87 +:10E540003C04800094AA01163142FFFC24480004D8 +:10E55000010518218C7940003326FFFF14C0000705 +:10E56000240EBFFF3C0BFFFF35657FFF00E538241D +:10E57000AF8700043C048000240EBFFF348C018070 +:10E5800000EE6824A58D0026AD89002C3C07100004 +:10E59000AC8701B803E00008000000002402FFFE81 +:10E5A000006238240A000F76AF8700043C05800023 +:10E5B00034A400708C8A000090A601128F840000A1 +:10E5C00027BDFFF030C300FF000318823082010036 +:10E5D00000003821104000392466000330874000D5 +:10E5E00050E0003930882000000610800045C82126 +:10E5F0008F2F40002478000400187080AFAF000017 +:10E6000001C568218DAC4000AFAC000494AB01168D +:10E610003169FFFC012540218D054000AFA50008B0 +:10E620008FA9000800003021000028213C070800C5 +:10E6300024E701000A000FE92408000890420000C6 +:10E6400024A500012CAD000C0062C8210019C08077 +:10E65000030778218DEE000011A0000600CE3026C1 +:10E6600003A5102114A8FFF500051A005520FFF49A +:10E67000904200003C048000348700703C05080094 +:10E680008CA531048CE300002CA8002011000009A7 +:10E69000006A3823000558803C0C0800258C31089E +:10E6A000016C482124AA0001AD2700003C010800AC +:10E6B000AC2A3104AF86000C2407000100E01021D1 +:10E6C00003E0000827BD00101100FFFC0000382106 +:10E6D00000066080018558218D6440002469000493 +:10E6E00000093880AFA4000000E518218C664000C6 +:10E6F000AFA000080A000FD9AFA6000427BDFFD8BD +:10E70000AFB20018AFB00010AFBF0024AFB400200C +:10E71000AFB3001CAFB100148F8700003C04800031 +:10E720009483010E30E24000000080211040001070 +:10E730003072FFFF3C06002000E6282410A0000DE8 +:10E7400030EA80008F8800042409BFFF00E93824E4 +:10E7500035031000AF87000030F120001620000BB9 +:10E760003C1400042418FFBF0A001038007810245D +:10E7700030EA8000154000863C0C002030F120007B +:10E780001220FFF88F8300043C14000400F4982446 +:10E790001260FFF52418FFBF3462004030F9010019 +:10E7A0001320000FAF8200043C02002000E2F82496 +:10E7B00013E000053C0B80003C04000400E4182436 +:10E7C000106000CF00000000956A011E9569011CD1 +:10E7D0003146FFFF0009440000C82825AF85000C22 +:10E7E0003C0E800095CD010C8DC44000340CFFFF21 +:10E7F000108C00B031A5FFFF308F010055E0000103 +:10E800002410001030F110005220000836110001D1 +:10E8100030F300201660009F3C18100000F8A02480 +:10E82000168000963C040C003611000130E801000F +:10E830001500000B3C0A00018F88000431094000DC +:10E840001520000800EA30243C0C1F0100EC58247D +:10E850003C0A1000516A00AE30AD02003C0A0001D3 +:10E8600000EA302414C000953C05100000E5202487 +:10E8700000004021108000070000902100079E0248 +:10E880003272000F001278803C0E080125CE830002 +:10E8900001EE40218F94001C12800047022080214D +:10E8A00010800091000000003C0980009539010EA5 +:10E8B00091030000022030213338FFFF27050004B8 +:10E8C000106000080000A021241F0003107F013AFF +:10E8D00024040002910C00011184011830EA004068 +:10E8E0000012A1C08F920020524000013626004045 +:10E8F0003C1380008E6F400031F10100122000CBEC +:10E9000030D1FFFB3C1808008F18002430D20004DF +:10E910003306000414C000CC30B0FFFF56400001A5 +:10E920003631000402802021020028210E000F55FC +:10E93000022030211640000D0000202136650180A4 +:10E940003C0480008C9301B80660FFFE241920006F +:10E9500024140002A4B90008A0B4000BA4A0001065 +:10E960003C051000AC8501B8000020218FBF0024B9 +:10E970008FB400208FB3001C8FB200188FB1001429 +:10E980008FB000100080102103E0000827BD002890 +:10E9900000EC58241160FF7A30F120008F8D0004C4 +:10E9A0003C0FFFFF35EE7FFF00EE382435A38000DB +:10E9B0000A001027AF8700003C0208008C42003894 +:10E9C0003C040800248400381040004B2449FFFF19 +:10E9D0003C038000946C010E318BFFFF110000A0FE +:10E9E000257300043C1008008E1000301200000A4D +:10E9F00030E601008F8A00043143400010600006B9 +:10EA00003C0F0F0000EF70243C0D010001AE402BC5 +:10EA1000110000DF3265FFFF10C000693C140F00D9 +:10EA200000F428243C18020010B800658F99000CEF +:10EA30003270FFFF03299824026490219249000458 +:10EA400025270004000721C00200282136260002E5 +:10EA50000E000F55000000008FBF00248FB400206F +:10EA60008FB3001C8FB200188FB100148FB000104C +:10EA70000000102103E0000827BD00283C020BFF26 +:10EA800000E41824345FFFFF03E3C82B5320FF6723 +:10EA9000361100013C0608008CC6002C361100051A +:10EAA00024D000013C010800AC30002C0A00105DAD +:10EAB00030E801000A0010522410002002402821F2 +:10EAC0003C1208008E5200D824040080264D00011C +:10EAD0003C010800AC2D00D80E000F5524060003A1 +:10EAE0000A0010E88FBF00243C08080125088300B5 +:10EAF0000A00107C3C0980000A0010C50000482173 +:10EB00000E000FBC000000000A0010498F870000B3 +:10EB100015A0FF533C0A00012645000430AAFFFF60 +:10EB2000362600023C0380008C7201B80640FFFECE +:10EB30008F85000834690180AD20000010A000AF6F +:10EB40003C048000254F001200AF702B51C000AC78 +:10EB500024030003947801202414001A30F14000AB +:10EB60003313FFFFA134000B122000B62663FFFE13 +:10EB700000A3C82B572000B4241FFFFE3508000156 +:10EB8000A5230014AF8800043C108000240CBFFFB4 +:10EB9000010C4824240B000236080180A50B000C50 +:10EBA000A50A000EA5060008A5090026A507001065 +:10EBB0003C071000AE0701B80A0010E88FBF002420 +:10EBC0003C0308008C6300D02E45000C001221C0CD +:10EBD000386B00012D6200010045F82417E0FF9A10 +:10EBE0003270FFFF264CFFFC2D840004548000503F +:10EBF00000002021386A00022D43000100658024B6 +:10EC00001600004A3270FFFF00076A420012702BA4 +:10EC100001AE40245500006300002021001221C0F5 +:10EC2000020028210A0010E53626000234DF000227 +:10EC30000280202133E6FFFF0E000F5530A5FFFFB5 +:10EC40000A0010AC00002021240401000200282149 +:10EC50000E000F55022030210A001098000000001D +:10EC60008C66400030CF010011E0003D30F801001B +:10EC70003C1208008E5200241300001132340004AC +:10EC80003C1F0F0000FFC8243C0502001325000CA8 +:10EC90008F8C000C022030213265FFFF018958243F +:10ECA00001641021904900043230FFFB2411FFFE63 +:10ECB000252700040E000F55000721C002519024A3 +:10ECC0002404000112440052324300011460005831 +:10ECD00002003021324A0004114000048F8D0000F0 +:10ECE00031A808001500005A3265FFFF1680FF5B4F +:10ECF0008FBF00243C138000366501803C048000F7 +:10ED00008C9001B80600FFFE24062000240F0002AC +:10ED1000A4A60008A0AF000BA4A000103C0E100099 +:10ED2000AC8E01B80A0010E88FBF0024000020213B +:10ED3000020028210A0010E5362600021140FEE9F3 +:10ED40000000A021952E0110950D000231C8FFFF93 +:10ED500051A8FEE40012A1C00A00108B8F9200207F +:10ED60003C0508008CA5002430B800015300FF3B8F +:10ED70008FBF00243265FFFF3626000200002021ED +:10ED80000E000F55000000000A0010E88FBF00249D +:10ED9000362600020E000F55240400800A0010E8F9 +:10EDA0008FBF0024020028210E000F553226FFFBE2 +:10EDB0000A001159001221C0910300012402000130 +:10EDC0001062FEEA24040001241000021470FEC543 +:10EDD0000000A02130E300401060FEC38F920020AD +:10EDE000952B0110950900023167FFFF1127FEE006 +:10EDF0008FBF00240A00108B0000000024030003D2 +:10EE000034820180A043000B0A0011343C108000C2 +:10EE100032140004168000033265FFFF3612000230 +:10EE20003250FFFF020030210A0011B10000202102 +:10EE3000000020210E000F553265FFFF0A001186E9 +:10EE40003210FFFB241FFFFE0A001132011F402475 +:10EE5000020030210E000F55240401000A00118C1D +:10EE60000000000027BDFFC8AFB00010AFBF0034E6 +:10EE70003C10600CAFBE0030AFB7002CAFB600281E +:10EE8000AFB50024AFB40020AFB3001CAFB2001880 +:10EE9000AFB100148E0E5000240FFF7F3C0680009F +:10EEA00001CF682435AC380C240B0003AE0C5000A5 +:10EEB000ACCB00083C010800AC2000200E00175F1E +:10EEC000000000003C0A001035498051AE09537C17 +:10EED0003C0660168CC700003C0860148D0500A03D +:10EEE0003C03FFFF00E320243C02535300052FC2E4 +:10EEF0001482000634D07C000005A0800286982190 +:10EF00008E7200043C116000025180218E1E007838 +:10EF10008E17007C3C0260003C05080124A581841A +:10EF2000344420202406000AAF9E00100E0016086C +:10EF3000AF9700143C180098260503883C1F00106A +:10EF40003C19600C371600C03C158000AF3F53FCE5 +:10EF50003C1E080027DE00383C17080126F7830214 +:10EF6000AEB6013CAF8500183C047FFF3488FFFF3C +:10EF70003C0780000A0012373C0660008CAB0000A2 +:10EF8000316A00011540000235630001ACA30000A6 +:10EF900054800009320500018CF000008CC9180C67 +:10EFA000320400030521FFF501281824ACC3180C16 +:10EFB0000A0012300000000014A000553C1180002F +:10EFC0003206000210C0FFE88F8500183C04800064 +:10EFD0008C99014024100040AC9900208C98014885 +:10EFE00000187E0231E300701070022C0000000057 +:10EFF0002C67004150E000782404006024110020B8 +:10F00000107100063C1F40003C138000AE7F017869 +:10F01000000000000A00122B8F8500188C93014815 +:10F02000241600043488018000134C02312500FFAF +:10F030008C83014010B6017324B2FFFA2E4B0006F8 +:10F04000516000133C0580008C86014430A400FF11 +:10F0500030D400FF30C300FF2E85000814A000024A +:10F060002467000424070003240C0009108C01AC61 +:10F07000288D000A11A001982415000A240E00080A +:10F08000108E00158F91001C000719C03C058000F0 +:10F090008CA701B804E0FFFE24160002AD030000B7 +:10F0A000A5090008A116000B8CA401483C1F4000D4 +:10F0B0003C138000A50400108CA90144AD09002474 +:10F0C0003C081000ACA801B8AE7F01780000000039 +:10F0D0000A00122B8F8500180006CA020007208044 +:10F0E0003C16080126D683000096C021262F000179 +:10F0F000332500FF24100001A319000014B0FFE223 +:10F10000AF8F001C000719C00A001274AF850020E1 +:10F110008E3301283C0D8008AE3300208E2C010474 +:10F120008E26010095A80048AF8C0000AF86000431 +:10F130003103FFFF0E000F4EAF8300083C070800AD +:10F140008CE700C010E0002D8F8700003C0F080006 +:10F150008DEF00C425EE00013C010800AC2E00C478 +:10F160003C0480008C9101243C076020ACF1001429 +:10F17000000000003C0680003C164000ACD6013880 +:10F18000000000005260FF8F320600022669014035 +:10F19000266D00802415FF800135602401B57024A0 +:10F1A000000E194031B4007F000C91403128007FDF +:10F1B0003C05200034A20002007450250248582566 +:10F1C000016298250142F825ACDF0830ACD3083045 +:10F1D0000A001242320600021464FF8B3C1F4000FA +:10F1E0000E001F793C1380003C1F4000AE7F017869 +:10F1F000000000000A00122B8F8500183C1400103C +:10F2000000F49024164000A78F8300043C180800E7 +:10F210008F1800209636010E30F5400027110001AE +:10F220003C010800AC31002032D2FFFF12A000B335 +:10F23000000088213C1F002000FFC824132000B0DC +:10F2400030E980008F8200042404BFFF00E43824EA +:10F2500034431000AF87000030E6200010C000A546 +:10F26000240EFFBF3C0D000400ED6024118000025D +:10F27000006E10243462004030EF010011E0000FF6 +:10F28000AF8200043C15002000F5A0241280000588 +:10F290003C0480003C18000400F8B02412C0012F88 +:10F2A00000000000948A011E9489011C315FFFFF59 +:10F2B0000009140003E2C825AF99000C3C0580004A +:10F2C00094A3010C8CA44000340BFFFF108B00CBE7 +:10F2D0003065FFFF30880100550000012411001047 +:10F2E00030E6100010C000133635000130EC00206D +:10F2F0001580000A3C0E100000EE682411A0000DDD +:10F300003C180C003C160BFF00F8A82436D4FFFF75 +:10F310000295782B11E00007363500013C190800F2 +:10F320008F39002C36350005273100013C010800DB +:10F33000AC31002C30FF010017E0000B3C0A00014B +:10F340008F880004310240001440000800EA302495 +:10F350003C041F0100E450243C0910001149010342 +:10F3600030AB02003C0A000100EA302414C00098CF +:10F370003C03100000E3202400004021108000071F +:10F380000000A02100076E0231B4000F001460805D +:10F390003C12080126528300019240218F8E001CEE +:10F3A00011C0006202A08821148000033C09800083 +:10F3B0003C08080125088300952F010E91030000E9 +:10F3C00002A0302131E4FFFF248500041060000812 +:10F3D0000000B0212416000310760109240A00025F +:10F3E000910B0001116A002630E300400014B1C007 +:10F3F0008F9200205240000136A600403C1480004D +:10F400008E8C40003195010012A000BE30D5000462 +:10F410003C0D08008DAD002430D2FFFB31A6000466 +:10F4200014C000F130B1FFFF56A0000136520004B5 +:10F4300002C02021022028210E000F550240302159 +:10F4400016A0000D00002021368401803C058000BC +:10F450008CAE01B805C0FFFE24162000240F000268 +:10F46000A4960008A08F000BA48000103C0410009C +:10F47000ACA401B8000020210A00138600801021EE +:10F480001060FFDB0000B0219527011095090002F4 +:10F4900030E8FFFF5128FFD60014B1C00A00134E18 +:10F4A0008F920020240EBFFF006E682411A0000779 +:10F4B000240F87FF006FA82416A0000A3C190060E3 +:10F4C00000F9C02413000007000000000E000D34F6 +:10F4D000000000001040FF283C0680000A0012AA2D +:10F4E0003C0480000E0014E5000000000A001386B2 +:10F4F000000000000A0012EF006E102430E98000C6 +:10F500001120FF558F8300043C0B002000EB50249A +:10F510001140FF518F8500043C08FFFF35037FFF3A +:10F5200000E338240A0012E634A380003C050800FA +:10F530008CA5003814A0000224A4FFFF00002021A5 +:10F540003C0380009479010E3338FFFF110000DA8C +:10F55000271200043C1108008E3100301220000AEE +:10F5600030E901008F820004305F400013E00006A4 +:10F570003C080F0000E818243C0B01000163502BED +:10F58000114000C13245FFFF1120002E3C0D0F003D +:10F5900000ED30243C0C020010CC002A8F96000CA9 +:10F5A0003251FFFF02C4782401FE702191D2000481 +:10F5B00026470004000721C00220282136A60002A9 +:10F5C0000E000F55000000000A00138600001021F5 +:10F5D0003C0B08008D6B00D80240282124040080D9 +:10F5E000256700013C010800AC2700D80E000F552C +:10F5F000240600030A001386000010210A001309E4 +:10F60000241100208C840140010028213C0380004B +:10F610008C7F01B807E0FFFE2402001CACA40000B0 +:10F62000A0A2000B3C0A1000AC6A01B83C1F4000CD +:10F630003C138000AE7F0178000000000A00122B0E +:10F640008F8500183C0308008C6300D02E85000CC9 +:10F65000001421C0387100012E3900010325C02497 +:10F660001700FFD53251FFFF269FFFFC2FE4000457 +:10F670001480000800002021386B00022D6A000170 +:10F680000145102410400006000742423251FFFF9E +:10F6900000002021022028210A0013C136A6000202 +:10F6A0000014182B0103282414A000053251FFFF79 +:10F6B000001421C0022028210A0013C136A600022E +:10F6C00000002021022028210E000F5532A6FFFB4A +:10F6D0000A0013FE001421C01095005A000768802C +:10F6E0002406000B1486FE69000719C00007C880B5 +:10F6F0003C11080126318300033130210A001274C5 +:10F70000A0C0000134D4000202C0202130A5FFFFB8 +:10F710000E000F553286FFFF0A00136F00002021F4 +:10F720000007F8803C0A0801254A830003EA1021FB +:10F73000905300001260FE55000719C0A040000061 +:10F740008F8B001C2562FFFF1440FE50AF82001C0F +:10F75000000719C00A001274AF8000200E000FBC11 +:10F76000000000000A0013008F8700001560FEFEF5 +:10F770003C0A000126430004306AFFFF36A600025F +:10F780003C0380008C7201B80640FFFE34690180A2 +:10F790008F850008AD20000010A0008B3C19800070 +:10F7A000254D001200AD602B11800088241100034C +:10F7B000947501202414001A30EE400032AFFFFF90 +:10F7C000A134000B11C0009125E3FFFE00A3B02B74 +:10F7D00016C0008F2405FFFE35080001A523001484 +:10F7E0000A0014C6AF880004240401000220282166 +:10F7F0000E000F55024030210A00135B000000008C +:10F8000091030001241400011074FF1B2404000163 +:10F81000241800021478FEF60000B02130F10040F8 +:10F820001220FEF48F92002095220110951F0002F5 +:10F830003059FFFF13F9FF27008010210A00134EF3 +:10F84000000000003C1808012718830001B880213F +:10F8500000067A02A20F00013C1260008E431820BD +:10F860002415000100F57004006E282501B7A021C1 +:10F8700000066402000719C0A68C0000AE451820DF +:10F880000A0012753C05800036A600020E000F55D6 +:10F89000240400800A001386000010210E00150BBE +:10F8A0003C1380003C1F4000AE7F01780000000048 +:10F8B0000A00122B8F8500188C694000313401003A +:10F8C0001280003530EC01003C1408008E940024B6 +:10F8D0001180001132B600043C0E0F0000EE6824C7 +:10F8E0003C06020011A6000C02A030218F91000CF2 +:10F8F0003245FFFF0224C824033EC021930F0004B9 +:10F9000032B1FFFB2415FFFE25E700040E000F5562 +:10F91000000721C00295A024240400011284003FA6 +:10F920003282000110400007328A00040220302198 +:10F93000000020210E000F553245FFFF3231FFFB42 +:10F94000328A0004114000048F85000030AB0800AB +:10F950001560003A3245FFFF16C0FEDE00001021A0 +:10F960003C128000364401803C0580008CA801B820 +:10F970000500FFFE2414200024030002A4940008C4 +:10F98000A083000BA48000103C091000ACA901B8B2 +:10F990000A001386000010213C0608008CC60024D3 +:10F9A00030CC00015180FECB000010213245FFFF1A +:10F9B00036A60002000020210E000F5500000000B6 +:10F9C0000A0013860000102124110003373801803B +:10F9D000A311000B3C0580002409BFFF0109F82496 +:10F9E0002402000234A80180A502000CA50A000E22 +:10F9F000A5060008A51F0026A50700103C09100059 +:10FA0000ACA901B80A001386000010212405FFFEEE +:10FA1000010540240A0014C6AF88000432360004F1 +:10FA200016C000033245FFFF363F000233F1FFFFEF +:10FA3000022030210A0014BF0000202102203021C2 +:10FA40000E000F55240401000A0014A70000000056 +:10FA50003C0380008C6401003082003E14400008AA +:10FA600000000000AC6000488C66010030C507C093 +:10FA700010A0000500000000AC60004CAC6000501D +:10FA800003E0000824020001AC600054AC600040B8 +:10FA90008C6801003107380010E0FFF90000000019 +:10FAA0002402000103E00008AC6000443C03900025 +:10FAB00034620001008220253C038000AC640020F9 +:10FAC0008C65002004A0FFFE0000000003E0000899 +:10FAD000000000003C028000344300010083202528 +:10FAE00003E00008AC44002027BDFFD8AFB10014EC +:10FAF0003C048000AFBF0020AFB3001CAFB20018C1 +:10FB0000AFB000108C9201408C9001482402000E8E +:10FB100000108C02322300FF1062005902042824D6 +:10FB20002866000F10C00013286A0037240700065B +:10FB30001067008E286800075100002D240400097A +:10FB4000106000783C06800024090001106900B0B4 +:10FB5000000000000000000D8FBF00208FB3001CCC +:10FB60008FB200188FB100148FB0001003E00008AE +:10FB700027BD002811400059240D0038286B00359E +:10FB8000116000053C058000240C001F146CFFF17F +:10FB9000000000003C0580008CB801B80700FFFEA3 +:10FBA00034B90180AF320000241F0001241200028A +:10FBB0003C021000AF200004A7310008A33F000A58 +:10FBC000A332000BA7300010AF200024AF20002884 +:10FBD000ACA201B88FBF00208FB3001C8FB20018F9 +:10FBE0008FB100148FB0001003E0000827BD00287B +:10FBF000106400232405000B1465FFD63218FFFFA4 +:10FC0000170000203C0580008F93FEDC927F0005EA +:10FC100033F900041720FFCF000000000E0014FC91 +:10FC2000024020219269000502402021352800046D +:10FC30000E001506A26800059267000530E2000478 +:10FC400014400002000000000000000D926B000054 +:10FC500024060020316A00FF1546000A3C0580009A +:10FC60008CA401B80480FFFE34AD0180240E000591 +:10FC70003C0C1000ADB20000A1AE000BACAC01B862 +:10FC80003C0580008CA301B80460FFFE34AF018006 +:10FC900024130002ADF20000ADF20004A5F100084B +:10FCA000A1F3000AA1F3000BA5F00010ADE00024C1 +:10FCB0008CB101443C101000ADF10028ACB001B88B +:10FCC0008FBF00208FB3001C8FB200188FB10014BB +:10FCD0008FB0001003E0000827BD0028106DFFADB5 +:10FCE000240E0080146EFF9B000000003C05800085 +:10FCF0008CA301B80460FFFE34AF0180241200021F +:10FD0000A1F2000BA5F10008A5F000108CB301448E +:10FD10003C021000A5F30012ACA201B80A0015477E +:10FD20008FBF00208CC301B80460FFFE34D3018074 +:10FD3000AE720000AE60000424120001A67100083B +:10FD400024110002A272000AA271000BA67000101A +:10FD50008CD001443C0F1000AE700024AE6000282F +:10FD6000ACCF01B80A0015828FBF00203C03800091 +:10FD70008C6601B804C0FFFE346201803C060801B5 +:10FD800090C68340AC52000010C000030000382130 +:10FD90003C0708018CE783483C05800034AA0180B9 +:10FDA0002404000234CC0001AC470004A551000833 +:10FDB000A14C000AA144000BA55000108CAB0144DB +:10FDC0000000202101402821AD4B002410C0000379 +:10FDD0008FBF00203C0408018C8483448FB3001C37 +:10FDE0008FB200188FB100148FB000103C0E1000BD +:10FDF0003C0D800027BD0028ACA40028ADAE01B8A2 +:10FE00003C010801A020834003E00008000000003E +:10FE100010A0000B3C0680008C98014424190002BD +:10FE20003C010801A03983403C010801AC32834801 +:10FE30003C010801AC3883440A0015828FBF0020C2 +:10FE40008CDF01B807E0FFFE34C7018024090002FF +:10FE5000ACF20000ACF20004A4F10008A0E9000A32 +:10FE6000A0E9000BA4F00010ACE000248CC8014411 +:10FE70003C021000ACE80028ACC201B80A001582B0 +:10FE80008FBF002027BDFFE8AFBF00100E000F4E50 +:10FE9000000000003C0280008FBF00100000202105 +:10FEA000AC4001800A00101027BD00183084FFFF0D +:10FEB00030A5FFFF108000070000182130820001EC +:10FEC0001040000200042042006518211480FFFB4E +:10FED0000005284003E000080060102110C0000762 +:10FEE000000000008CA2000024C6FFFF24A500042F +:10FEF000AC82000014C0FFFB2484000403E000086F +:10FF00000000000010A0000824A3FFFFAC86000042 +:10FF100000000000000000002402FFFF2463FFFF38 +:10FF20001462FFFA2484000403E0000800000000CB +:10FF300027BDFFE8AFBF0014AFB000100E0014FCE7 +:10FF4000008080213C048008348300809065002577 +:10FF50000200202134A200200E001506A062002518 +:10FF6000020020218FBF00148FB000100A000C9EE9 +:10FF700027BD00183C03800027BDFFF834620180D4 +:10FF8000AFA20000308C00FF30AD00FF30CE00FF8C +:10FF90003C0B80008D6401B80480FFFE000000006F +:10FFA0008FA900008D6801288FAA00008FA700008C +:10FFB0008FA400002405000124020002A085000A8D +:10FFC0008FA30000359940003C051000A062000B93 +:10FFD0008FB800008FAC00008FA600008FAF00002C +:10FFE00027BD0008AD280000AD400004AD8000240E +:10FFF000ACC00028A4F90008A70D0010A5EE00125F +:020000040001F9 +:1000000003E00008AD6501B83C06800827BDFFE8A5 +:1000100034C50080AFBF001090A700092402001271 +:1000200030E300FF1062000B008030218CA80050EC +:1000300000882023048000088FBF00108CAA0034A1 +:10004000240400390000282100CA482305200005A7 +:10005000240600128FBF00102402000103E00008F4 +:1000600027BD00180E00162E000000008FBF0010E4 +:100070002402000103E0000827BD001827BDFFC8C7 +:10008000AFB1002C00A08821AFB2003027A500102E +:100090000080902102202021AFBF0034AFB00028A3 +:1000A0000E000CA8AFA000101440009B3C07800875 +:1000B00034E400809086000830C5000814A0006970 +:1000C0008FA700103C18800837100080920F00089E +:1000D00031EE000815C00002240800030000402192 +:1000E0003C0B800891650011916A00123566008012 +:1000F0008CDF0054314900FF0128202130A300FF8C +:10010000000410800062282100BFC82B13200008C3 +:100110000000000094D0005C8CCF0054320DFFFF33 +:1001200001E5702301AE602B1180009400000000F7 +:1001300094D9005C3323FFFF30FF000413E0007408 +:10014000000830808FA8001C0068102B5040004F22 +:1001500030E30004006610232C46008010C000022B +:1001600000408021241000800E0014FC0240202159 +:100170003C0380083466008024070001ACC7000CF3 +:1001800090C800080010684034670100311F007FEC +:10019000A0DF00088E39000427380001ACD80030F9 +:1001A000A4D0005C8CCF003C9630000E01F0702192 +:1001B000ACCE00208CCC003C018D5821ACCB001C77 +:1001C0008E2A0004ACEA00008E290008ACE9000485 +:1001D0008FA5001030A400085480003293A60020A0 +:1001E000A0C0004E90C9004E2402FFDF3C188008DA +:1001F000A0E9000890C50008370D0080240A0050CF +:1002000000A22024A0C400088E390008ADB900382F +:100210008F0F00148DB0003001F07021ADAE0034AE +:1002200091AC0000318B00FF116A002C26450100C3 +:100230000E00150602402021240400380000282169 +:100240000E00162E2406000A8FBF00348FB2003035 +:100250008FB1002C8FB000282402000103E00008B9 +:1002600027BD003830E801001100003D8FA30014C5 +:100270008C8A0058006A48230520FF933C188008A8 +:10028000AC8300580A0016828FA7001024070218BA +:100290001060FFB100E610238FA2001C0A0016A711 +:1002A000004610233C188008370D0080A0E60008A7 +:1002B0008E390008240A0050ADB900388F0F0014A1 +:1002C0008DB0003001F07021ADAE003491AC000073 +:1002D000318B00FF156AFFD6264501002406FF80FA +:1002E00000A610243C098000AD2200288E270008BB +:1002F00030A3007F3C04800C0064F821AFE700D0FD +:100300008E280008AF9F002C0A0016DDAFE800D44D +:100310000A0016A42C6202188E2300083C048008F0 +:1003200034820080AC430054024020210E00161D90 +:10033000AC400030240400382405008D0E00162E39 +:10034000240600128FBF00348FB200308FB1002C12 +:100350008FB000282402000103E0000827BD003808 +:10036000AC800058908C0008240DFFF7018D5824B4 +:10037000A08B00080A0016828FA700108CD80054AA +:100380000A00169F0305182327BDFFE8AFBF001022 +:1003900090A6000D30C7001010E0000C0080402136 +:1003A0003C0280088C4400048CA300081064000800 +:1003B00030C9000530C5000510A0001C8FBF00101B +:1003C0002402000103E0000827BD001830C9000521 +:1003D0001120001030CB001210E0FFF98FBF001089 +:1003E0003C0880088CA700088D06000414E6FFF581 +:1003F00024020001240400382405008D0E00162E6E +:10040000240600128FBF00102402000103E0000840 +:1004100027BD0018240A0012156AFFE98FBF0010DB +:10042000010020210A00167027BD001800002021BD +:100430000A000D1A27BD00183C05080024A55DC060 +:100440003C04080024847B803C02080024425DC8F0 +:10045000240300063C010801AC2583503C0108013F +:10046000AC2483543C010801AC2283583C010801B0 +:10047000A023835C03E000080000000003E0000804 +:10048000240200013C028000308800FF34470180D4 +:100490003C0680008CC301B80460FFFE0000000031 +:1004A0008CC501282418FF803C0D800A24AF010070 +:1004B00001F8702431EC007FACCE0024018D2021A6 +:1004C000ACE50000948B00DA3509600024080002D6 +:1004D000316AFFFFACEA000424020001A4E900082D +:1004E000A0E8000BACE000243C071000ACC701B84A +:1004F000AF84002C03E00008AF85005C8C990004F9 +:100500008F8D002C2409FFBF0325C023AC98000465 +:1005100091AF00C42403FFEF31EE007FA1AE00C411 +:100520008C8C0020938B00388F86002C358A00023B +:10053000AF8B0050A780004CAC8A0020A4C000AC58 +:1005400090C800C401093824A0C700C48F84002CBF +:10055000AC8000DC908500C400A3102403E00008F8 +:10056000A08200C43C028000344501803C0480002D +:100570008C8301B80460FFFE8F89005C24076083D0 +:1005800024060002ACA900008C880124ACA8000459 +:10059000A4A70008A0A6000B3C05100003E000087B +:1005A000AC8501B8938800388F8900508F82002C69 +:1005B00030C600FF0109382330E900FF012218216D +:1005C00030A500FF2468007810C000020124382103 +:1005D0000080382130E400031480000330AA0003B7 +:1005E0001140000D312B000310A000090000102164 +:1005F00090ED0000244E000131C200FF0045602B49 +:10060000A10D000024E700011580FFF92508000175 +:1006100003E00008000000001560FFF30000000088 +:1006200010A0FFFB000010218CF8000024590004EA +:10063000332200FF0045782BAD18000024E70004AA +:1006400015E0FFF92508000403E0000800000000A1 +:1006500093850038938800488F870050000432004B +:100660003103007F00E5102B30C47F001040000FE5 +:10067000006428258F84002C3C0980008C8A00DCD3 +:10068000AD2A00A43C03800000A35825AC6B00A059 +:100690008C6C00A00580FFFE000000008C6D00AC9B +:1006A000AC8D00DC03E000088C6200A80A0017F2A1 +:1006B0008F84002C938800493C02800000805021E8 +:1006C000310300FEA383004930ABFFFF30CC00FFB5 +:1006D00030E7FFFF344801803C0980008D2401B8D9 +:1006E0000480FFFE8F8D005C24180016AD0D000005 +:1006F0008D2201248F8D002CAD0200048D59002025 +:10070000A5070008240201B4A119000AA118000BD2 +:10071000952F01208D4E00088D4700049783004CD3 +:100720008D59002401CF302100C7282100A32023A8 +:100730002418FFFFA504000CA50B000EA502001055 +:10074000A50C0012AD190018AD18002495AF00D803 +:100750003C0B10002407FFF731EEFFFFAD0E002821 +:100760008DAC0074AD0C002CAD2B01B88D46002073 +:1007700000C7282403E00008AD4500208F88002C26 +:100780000080582130E7FFFF910900C63C0280003D +:1007900030A5FFFF312400FF00041A000067502538 +:1007A00030C600FF344701803C0980008D2C01B821 +:1007B0000580FFFE8F82005C240F0017ACE2000072 +:1007C0008D390124ACF900048D780020A4EA0008DA +:1007D000241901B4A0F8000AA0EF000B9523012012 +:1007E0008D6E00088D6D00049784004C01C350216C +:1007F000014D602101841023A4E2000CA4E5000E49 +:10080000A4F90010A4E60012ACE000148D780024D6 +:10081000240DFFFFACF800188D0F006CACEF001C2E +:100820008D0E00683C0F1000ACEE0020ACED0024F3 +:10083000950A00AE240DFFF73146FFFFACE6002815 +:10084000950C00709504007231837FFF0003CA008D +:100850003082FFFF0322C021ACF8002CAD2F01B87D +:10086000950E00728D6A002000AE3021014D2824C3 +:10087000A506007203E00008AD6500203C02800080 +:10088000344601803C0580008CA301B80460FFFE63 +:1008900024090018ACC40000A0C9000B8F88002CEC +:1008A0003C041000950700AEA4C70010ACC0003097 +:1008B00003E00008ACA401B83C028000344501808C +:1008C0003C0480008C8301B80460FFFE8F8A0034F2 +:1008D000240600199549001C3128FFFF000839C083 +:1008E000ACA70000A0A6000B3C05100003E0000828 +:1008F000AC8501B88F87003C0080402130C400FFE8 +:100900003C0680008CC201B80440FFFE8F89005C69 +:100910009383005834996000ACA90000A0A300059F +:100920008CE20010240F00022403FFF7A4A20006AB +:10093000A4B900088D180020A0B8000AA0AF000BD1 +:100940008CEE0000ACAE00108CED0004ACAD0014D9 +:100950008CEC001CACAC00248CEB0020ACAB002871 +:100960008CEA002C3C071000ACAA002C8D09002456 +:10097000ACA90018ACC701B88D05002000A3202445 +:1009800003E00008AD040020938500582403000113 +:1009900027BDFFE800A330042CA20020AFB0001058 +:1009A000AFBF001400C01821104000132410FFFE38 +:1009B0003C0708008CE7319000E610243C088000DA +:1009C0003505018014400005240600848F89002C21 +:1009D000240A00042410FFFFA12A00EC0E00188E48 +:1009E00000000000020010218FBF00148FB0001023 +:1009F00003E0000827BD00183C0608008CC63194AF +:100A00000A0018C000C310248F87003427BDFFE000 +:100A1000AFB20018AFB10014AFB00010AFBF001CF0 +:100A200030D000FF90E6000D00A0882100809021CA +:100A300030C5007FA0E5000D8F85002C8E230018A7 +:100A40008CA200C01062002E240A000E0E0018B303 +:100A5000A38A00582409FFFF104900222404FFFF45 +:100A600052000020000020218E2600003C0C0010C7 +:100A700000CC5824156000393C0E000800CE6824D4 +:100A800055A0003F024020213C18000200D88024DD +:100A90001200001F3C0A00048F8700348CE200140F +:100AA0008CE300108CE500140043F82303E5C82B09 +:100AB00013200005024020218E24002C8CF1001010 +:100AC000109100310240202124020012A38200581C +:100AD0000E0018B32412FFFF105200022404FFFF7F +:100AE000000020218FBF001C8FB200188FB10014AE +:100AF0008FB000100080102103E0000827BD002007 +:100B000090A800C4350400200A0018E9A0A400C47D +:100B100000CA48241520000B8F8B00348F8D0034C1 +:100B20008DAC00101580000B024020218E2E002C71 +:100B300051C0FFEC00002021024020210A001904CE +:100B4000240200178D66001050C0FFE6000020212F +:100B5000024020210A001904240200110240202131 +:100B6000240200150E0018B3A3820058240FFFFFC3 +:100B7000104FFFDC2404FFFF0A0018F38E2600004C +:100B80000A00192A240200143C08000400C8382472 +:100B900050E0FFD400002021024020210A00190467 +:100BA000240200138F86002C27BDFFE0AFB1001494 +:100BB000AFBF0018AFB0001090C300C430A500FF55 +:100BC0003062002010400008008088218CCB00C0DB +:100BD0002409FFDF256A0001ACCA00C090C800C428 +:100BE00001093824A0C700C414A000403C0C8000B8 +:100BF0008F84002C908700C42418FFBF2406FFEFC9 +:100C000030E3007FA08300C4979F004C8F82005088 +:100C10008F8D002C03E2C823A799004CA5A000AC3F +:100C200091AF00C401F87024A1AE00C48F8C002CD9 +:100C3000A18000C78F8A002CA5400072AD4000DC67 +:100C4000914500C400A65824A14B00C48F900028F1 +:100C50008F8400509786004C0204282110C0000F9A +:100C6000AF850028A38000483C0780008E2C000838 +:100C700094ED01208E2B0004018D5021014B802129 +:100C8000020620233086FFFF30C8000F390900011B +:100C90003131000116200009A388004893860038EE +:100CA0008FBF00188FB100148FB0001027BD002037 +:100CB000AF85005403E00008AF86005000C87023E1 +:100CC0008FBF0018938600388FB100148FB00010CA +:100CD00034EF0C00010F282127BD0020ACEE00846A +:100CE000AF85005403E00008AF86005035900180C6 +:100CF000020028210E00188E240600828F84002C0A +:100D0000908600C430C5004050A0FFBAA3800058B0 +:100D10008F85003C3C0680008CCD01B805A0FFFE0D +:100D20008F89005C2408608224070002AE0900005D +:100D3000A6080008A207000B8CA300083C0E1000B8 +:100D4000AE0300108CA2000CAE0200148CBF001485 +:100D5000AE1F00188CB90018AE1900248CB80024FE +:100D6000AE1800288CAF0028AE0F002CACCE01B816 +:100D70000A00194EA38000588F8A002C27BDFFE07F +:100D8000AFB10014AFB000108F880050AFBF001893 +:100D900093890030954200AC30D100FF0109182B37 +:100DA0000080802130AC00FF3047FFFF0000582159 +:100DB00014600003310600FF01203021010958238F +:100DC0009783004C0068202B1480001B000000005B +:100DD00010680043240A0001118A004834E70880A3 +:100DE0003165FFFF0E001830020020210E00187040 +:100DF0008F84005C8F84002C948D007025AC0001E2 +:100E0000A48C0070948B00703C0608008CC631885E +:100E100031677FFF10E6004F000000000200202134 +:100E2000022028218FBF00188FB100148FB000104E +:100E30000A00193A27BD0020914400C42406FF800F +:100E400000868825A15100C49784004C3088FFFF9C +:100E50001100001C938900308F8E002C2419EFFFA5 +:100E6000008BF82395D800AC0168682B33E900FFAC +:100E700003197824A5CF00AC51A0002A0100582105 +:100E80008E0500202408FFFB2403000100A8102485 +:100E9000AE0200201183002534E7800002002021EB +:100EA0003165FFFF0E00183001203021978B004C78 +:100EB0008F870050A780004C00EB8023AF9000503C +:100EC000938900308F8C002C8FBF00188FB10014D5 +:100ED0008FB0001027BD002003E00008A18900C7E3 +:100EE0008E0800202409FFFB34E780000109282434 +:100EF000AE050020158AFFBA34E7088002002021E1 +:100F00000E0017FE3165FFFF02002021022028217C +:100F10008FBF00188FB100148FB000100A00193A6B +:100F200027BD00200A0019F10000482102002021FD +:100F30003165FFFF0E0017FE01203021978B004C1A +:100F40008F870050A780004C00EB80230A001A0115 +:100F5000AF90005094890070240A8000012A402438 +:100F6000A4880070908500709099007030A200FFF6 +:100F7000000219C20003F827001FC1C0332F007FF1 +:100F800001F87025A08E00700A0019D902002021F6 +:100F90008F88002C24030001910A0078910500C776 +:100FA000250900783147003F24E6FFE000C318041C +:100FB0002CC2002030670019A38500301040001AB1 +:100FC000AF89003C3C0A8000354B0002240500013B +:100FD0002406000114E00016006B102400002821F4 +:100FE0001440000F306300201060000F2405000142 +:100FF0008D0600748D1900742403FF8000C3102433 +:10100000000279403338007F01F868253C0E10005B +:1010100001AE6025AD4C0830912800013106000179 +:101020000A0019AF0000000003E000080000000003 +:101030008D0F00748D0D00742418FF8001F870244A +:10104000000E414031AC007F010C50253C0B1000DC +:10105000014B38253C0980000A0019AFAD27083044 +:1010600027BDFFD8AFB000108F90003CAFB4002078 +:10107000AFB10014AFBF0024AFB3001CAFB2001873 +:101080008E0500103C0208008C4231B08F86004073 +:1010900030A73FFF00E2182B8CD20014008088217B +:1010A0008CD30020106000070000A02190CB000D21 +:1010B000240AFF80014B4824312800FF1500000C52 +:1010C00000056382022020212411000DA391005805 +:1010D0008FBF00248FB400208FB3001C8FB2001884 +:1010E0008FB100148FB000100A0018B327BD00287C +:1010F0003185000354A0FFF40220202194CF001C6E +:101100008F8E002C8E070028A5CF00D88CCD001024 +:10111000024D302310E6005C2402001F0E0018B3BD +:10112000A3820058241FFFFF105F004E2404FFFF1E +:101130008F8300448F880034026398218D0900104A +:10114000012310238F830024AD020010AD13002073 +:101150008C67007400F3202B148000620220202191 +:101160008F8600408E0C00248CC50024118500075A +:1011700002202021240E001C0E0018B3A38E00585C +:10118000240DFFFF104D00372404FFFF8F8400342F +:101190008C980024270F0001AC8F002412720044A9 +:1011A0008F9900248F320074125300413C0A008052 +:1011B0008E090000012A10241440003A00000000AB +:1011C0008E0400142412FFFF10920006240B001B53 +:1011D000022020210E0018B3A38B005810520021CA +:1011E0002404FFFF8E0300003C0C0001006C282447 +:1011F00010A000133C0600800066A02416800009A1 +:101200000200282102202021240E001A0E0018B30B +:10121000A38E0058240DFFFF104D00122404FFFF81 +:1012200002002821022020210E0018D324060001EC +:101230002410FFFF2404FFFF1050000A24140001B3 +:101240008F8F0034022020210280302195F200345B +:1012500024050001265800010E0019AFA5F800343E +:10126000000020218FBF00248FB400208FB3001C0A +:101270008FB200188FB100148FB0001000801021C1 +:1012800003E0000827BD00288F83004400E3C82145 +:101290000259C02B1300FFA88F8800340A001A9847 +:1012A00024020018AC8000200A001AC28E04001428 +:1012B0008E1F00003C07008003E798241660FFF9AA +:1012C0002408001A022020210E0018B3A388005819 +:1012D0002403FFFF1443FFBA2404FFFF0A001AEBA4 +:1012E0008FBF0024240B001D0E0018B3A38B0058E1 +:1012F000240AFFFF144AFF9A2404FFFF0A001AEB96 +:101300008FBF00248F85002C27BDFFD8AFB3001CF2 +:10131000AFB20018AFB10014AFB00010AFBF0020E3 +:1013200090A700C48F90003C2412FFFF34E20040DD +:1013300092060000A0A200C48E0300100080982135 +:101340001072000630D1003F2408000D0E0018B3C3 +:10135000A3880058105200262406FFFF8F8A002C15 +:101360008E0900188D4400C011240007240C000EC3 +:10137000026020210E0018B3A38C0058240BFFFF3D +:10138000104B001B2406FFFF24040020122400043D +:101390008F8D002C91AF00C435EE0020A1AE00C4AB +:1013A0008F85004410A0001A000000001224004B9A +:1013B0008F98002C8F92FEDC2406FFFD97100070A2 +:1013C0009651000A1230000B8FBF00203C1F08000E +:1013D0008FFF318C03E5C82B1720001E02602021EF +:1013E000000028210E0019AF240600010000302162 +:1013F0008FBF00208FB3001C8FB200188FB1001474 +:101400008FB0001000C0102103E0000827BD0028A5 +:101410005224002A8E0300148F84002C94890070BB +:1014200025280001A4880070948700703C050800FE +:101430008CA5318830E27FFF1045000E00000000CF +:10144000026020210E00193A240500010A001B4DFC +:10145000000030212402002DA38200580E0018B392 +:101460002413FFFF1453FFE12406FFFF0A001B4E65 +:101470008FBF00209498007024198000240500017B +:1014800003199024A492007090910070908D0070C8 +:10149000323000FF001079C2000F7027000E61C0CB +:1014A00031AB007F016C5025A08A00700E00193A04 +:1014B000026020210A001B4D000030212406FFFF9E +:1014C0001466FFD68F84002C026020210E00193A8A +:1014D000240500010A001B4D00003021026020217C +:1014E0000A001B672402000A8F88002C27BDFFE832 +:1014F000AFB00010AFBF0014910A00C48F87003C4A +:1015000000808021354900408CE60010A10900C40C +:101510003C0208008C4231B030C53FFF00A2182BBE +:10152000106000078F850040240DFF8090AE000DF5 +:1015300001AE6024318B00FF156000080006C382F5 +:10154000020020212403000D8FBF00148FB0001073 +:1015500027BD00180A0018B3A38300583306000300 +:10156000240F000254CFFFF70200202194A2001C98 +:101570008F85002C24190023A4A200D88CE8000039 +:1015800000081E02307F003F13F900353C0A00833B +:101590008CE800188CA600C01106000800000000AE +:1015A0002405000E0E0018B3A38500582407FFFF82 +:1015B000104700182404FFFF8F85002C90A900C459 +:1015C00035240020A0A400C48F8C0034918E000D1F +:1015D00031CD007FA18D000D8F8300441060001C71 +:1015E000020020218F8400408C9800100303782B88 +:1015F00011E0000D2419001802002021A3990058C1 +:101600000E0018B32410FFFF105000022404FFFF47 +:10161000000020218FBF00148FB000100080102127 +:1016200003E0000827BD00188C8600108F9F00344F +:101630000200202100C31023AFE2001024050001A6 +:101640000E0019AF240600010A001BD6000020215D +:101650000E00193A240500010A001BD600002021C3 +:10166000010A5824156AFFD98F8C0034A0A600EC1B +:101670000A001BC3A386004A27BDFFD8AFB00010E5 +:101680008F90003CAFB20018AFBF0020AFB3001C7A +:10169000AFB100148E1100103C0308008C6331B010 +:1016A00032253FFF00A3102B10400008008090213E +:1016B0008F8600402409FF8090CA000D012A402433 +:1016C000310700FF14E0000B00116B820240202163 +:1016D0002412000DA39200588FBF00208FB3001C6E +:1016E0008FB200188FB100148FB000100A0018B329 +:1016F00027BD002831AC0003240B0001558BFFF4FB +:101700000240202190CF000D31EE000811C0006092 +:101710008F93004416600009240200278E19000CE4 +:101720008CD8002017380005240200208E02000803 +:101730008CDF0024105F0040240200200E0018B34C +:10174000A38200582406FFFF104600332404FFFF45 +:101750008F990034240AFFF73C13800E9329000D63 +:101760002404FF803C0D8000012AF824A33F000DD3 +:101770008F9900243C0808008D0831AC8F83005CF1 +:10178000972700788F9F00340103102130E57FFFF9 +:10179000000530400046782131F8007F03136021B6 +:1017A00001E47024ADAE002CA59100008FEB002861 +:1017B000256A0001AFEA00288FE3002C8E09002C77 +:1017C00000694021AFE8002C8E07002CAFE7003005 +:1017D0008E050014AFE5003497E6003A24C20001FC +:1017E000A7E2003A973300783C1008008E1031B021 +:1017F0002663000130717FFF123000270060302126 +:101800008F8F002402402021240500010E00193A88 +:10181000A5E60078000020218FBF00208FB3001CB8 +:101820008FB200188FB100148FB00010008010210B +:1018300003E0000827BD00288E0500142413FFFFD5 +:1018400010B3001D8F83002C8E0800188C6700C019 +:10185000150700092402000E8E0A00248CC90028F6 +:1018600015490005240200218E0700288CCB002C8E +:1018700010EB00132402001F0E0018B3A3820058BF +:101880001453FFB32404FFFF0A001C588FBF00202D +:101890000A001C2024020024240E8000006E68240C +:1018A00031ACFFFF000C5BC2317100FF00118027DB +:1018B0000A001C51001033C00A001C6F24020025CE +:1018C0008E05002C10A0FFEC240200238F8E002434 +:1018D0008DCD007401A5602B1580FFE72402002642 +:1018E0008CCF001400A7C02101F8202B1080FF9995 +:1018F0008F990034024020210A001C6F240200222C +:1019000027BDFFE0AFB000108F90003CAFB10014D6 +:10191000AFBF00188E0500103C0308008C6331B087 +:101920000080882130A43FFF0083102B1040000767 +:101930008F8600402409FF8090CA000D012A4024B0 +:10194000310700FF14E000098F8B00442410000DC4 +:1019500002202021A39000588FBF00188FB10014DF +:101960008FB000100A0018B327BD002011600008D6 +:101970000005C3828F8F002C8F8EFEDC2407FFFDB5 +:1019800095EC007095CD000A11AC00388FBF00189F +:101990003305000314A0001000000000921900029B +:1019A00013200041000000008E06002450C0000FEC +:1019B00092040003022020212402000F0E0018B31D +:1019C000A38200582408FFFF144800072407FFFFE4 +:1019D0000A001CEC8FBF001890C3000D3064000893 +:1019E0001080003702202021920400032407000207 +:1019F000308900FF15270005308F00FF8F8A0044D3 +:101A000011400031240C002C308F00FF39E500100C +:101A10002CAD00012DEE00010200282101CD302562 +:101A20000E0018D3022020212410FFFF1050000EBA +:101A30002407FFFF8F83004410600017022020213D +:101A40003C1908008F39318C0323C02B5700000C40 +:101A50002411002D02202021000028210E0019AFA2 +:101A600024060001000038218FBF00188FB1001438 +:101A70008FB0001000E0102103E0000827BD002017 +:101A80000E0018B3A39100581450FFF62407FFFF6F +:101A90000A001CEC8FBF00180E00193A2405000143 +:101AA0000A001CEB000038218CDF00248E02002489 +:101AB000545FFFC1022020210A001CCC92040003C5 +:101AC0000A001CC024020010022020210E0018B3BE +:101AD000A38C0058240BFFFF104BFFE32407FFFFEC +:101AE0000A001CD39204000330A500FF2406000165 +:101AF00024A9000100C9102B1040000C0000402157 +:101B0000240A000100A61823308B000124C600011E +:101B1000006A3804000420421160000200C9182B3A +:101B2000010740251460FFF800A6182303E0000811 +:101B30000100102127BDFFD8AFB000188F90003CE6 +:101B4000AFB1001CAFBF00202403FFFF2411002F02 +:101B5000AFA3001092060000240500082610000123 +:101B6000006620260E001D0B308400FF00021E00C0 +:101B70003C021EDC34466F410A001D330000102178 +:101B800010A00009008018212445000130A2FFFFA9 +:101B90002C4500080461FFFA00032040008620263F +:101BA00014A0FFF9008018210E001D0B2405002051 +:101BB0008FA300102629FFFF313100FF00034202EE +:101BC000240700FF1627FFE2010218260003502712 +:101BD000AFAA0014AFAA00100000302127A80010FF +:101BE00027A7001400E6782391ED000324CE00011E +:101BF00000C8602131C600FF2CCB00041560FFF93E +:101C0000A18D00008FA200108FBF00208FB1001C9B +:101C10008FB0001803E0000827BD00289383003828 +:101C200027BDFFE024020034AFB10014AFB00010B4 +:101C3000AFBF001CAFB200180080802110620064AA +:101C400000A0882192240004148000478F88002C73 +:101C5000A38000308E2500048D0700C83C0600FFDD +:101C600034C3FFFF00A3302400E6102B1440004FC4 +:101C7000AF860044978A004C8F8800500148382373 +:101C800010C00034A787004C8F99002430DF000378 +:101C9000001F20239332007C309000030206702145 +:101CA0000012C082331200010012788001CF682137 +:101CB00030ECFFFF018D582B1160005F8F87002CE7 +:101CC0008F8900288F8200541049005C3C033F013B +:101CD0008E2500003C11250000A3382414F1007665 +:101CE0008F84003C8F88003C8F87002C8D0A000079 +:101CF000ACEA00788D060010ACE600888F880050B2 +:101D00008F860044938B0030012860210206282131 +:101D1000020B1821A383003094E900ACAF8C00289B +:101D200035301000A4F000AC1640005024780004B8 +:101D3000AF850050000020218FBF001C8FB200181B +:101D40008FB100148FB000100080102103E0000854 +:101D500027BD00208F840028AF800050008890218C +:101D60000A001D9EAF920028241F000CA39F00585C +:101D70000E0018B3020020212419FFFF1059FFEEB6 +:101D80002404FFFF8F88002CA38000308E250004E0 +:101D90008D0700C83C0600FF34C3FFFF00A33024BA +:101DA00000E6102B1040FFB3AF8600440200202154 +:101DB00024090019A38900580E0018B32410FFFF4E +:101DC0001050FFDD2404FFFF0A001D6E8F860044C3 +:101DD0008F84002C8F87003C8CF20030908600C4EA +:101DE00030C5001014A000108F8300502C6800052F +:101DF0001500002600000000908A00C4246BFFFC40 +:101E00003149001015200008316400FF8F8D005407 +:101E10008F8C002811AC0004388F000131EE0001D6 +:101E200015C0002D000000000E001D1E0000000067 +:101E30000A001DF5000000008F890028938B0030F8 +:101E40000128602102062821020B1821A3830030FB +:101E500094E900ACAF8C002835301000A4F000AC41 +:101E60005240FFB4AF85005024780004A39800309E +:101E700094EE00AC24AF0004AF8F005035CD2000AD +:101E8000A4ED00AC0A001D9F000020218C8200DC24 +:101E90001242FF6C0200202124180005A39800586C +:101EA0000E0018B32412FFFF1452FF662404FFFF34 +:101EB0000A001DA08FBF001C310500FF0E0017BADD +:101EC000000030218F87002C8F8800508F890028D8 +:101ED0000A001D928F8600440E0017E500000000E6 +:101EE0000A001DF5000000009383004A27BDFFE0B3 +:101EF00024020002AFB20018AFB10014AFBF001C43 +:101F000000808821AFB000100000902110620055C1 +:101F10002404FFFD9783004C8F8500503066FFFF3F +:101F200000C5202B1480005B938700383C0880009C +:101F30009504012010E500528F8A00288F840054F8 +:101F400030A500FF0E0017BA240600018F9F005C29 +:101F50003C0580003C19408027ED017831B00078C5 +:101F6000240EFF800219582534AF090031B800074C +:101F700001AE6024ACAC0800030F8021ACAB0810AC +:101F800002202021020028210E001D58AF90003CA5 +:101F90002403FFFF104300332404FFFF8E0C0010C6 +:101FA0003C0708008CE731B09206000031843FFF07 +:101FB0000087102B1040002330CD003F8F98005C2D +:101FC000000471803C0408008C8431A82409FF803F +:101FD0009390004900984021010E2021008970242F +:101FE000000E51403C0980003099007F3C0F00807A +:101FF0008F88002C3525094035E20001015938252C +:10200000308B0078308600073C0310003C1F800CAA +:1020100000C5C0210162582500E35025033F782107 +:1020200036050001AD2E0804AF980040AD2B081412 +:10203000AF8F0034AD2E0028AD040074AD2A0830F7 +:10204000A38500499383004A2410000350700027A1 +:1020500025A3FFE0240C0001106C001C24060023C3 +:10206000024020218FBF001C8FB200188FB10014D6 +:102070008FB000100080102103E0000827BD002071 +:10208000314900035520FFAE8F8400540A001E31F1 +:102090008F9000548F840054306500FF0E0017BAF3 +:1020A00024060001938B00382405003411650018C4 +:1020B0009783004C8F8500503062FFFF00A25823A9 +:1020C000AF8B00500A001E69A780004C11A6003794 +:1020D00000000000022020212411000B0E0018B384 +:1020E000A39100580A001E69004090212C72002024 +:1020F0001240FFF80003F8803C07080124E781AC98 +:1021000003E7C8218F2D000001A000080000000097 +:102110008F8500502CA200055440001DA780004C64 +:10212000978A004C3148FFFF00A848232D2F000557 +:1021300011E00003314400FF24AEFFFC31C400FF76 +:102140008F9000548F9800281218000438990001CD +:10215000332D000115A00029000000008F91002CF4 +:10216000922500C434A30010A22300C49783004C1E +:102170008F8500508F84002C3062FFFF00A258230F +:10218000AC8000DCA780004C0A001E69AF8B0050B9 +:102190003062FFFF00A258230A001E69AF8B005077 +:1021A0002403FFFF11830005000000000E001B8BBD +:1021B000022020210A001E69004090210E001B12FF +:1021C000022020210A001E69004090210E001BEF12 +:1021D000022020210A001E69004090210E001A6989 +:1021E000022020210A001E69004090210E001C914F +:1021F000022020210A001E69004090210E0017E5F0 +:10220000000000009783004C8F850050306CFFFF6A +:1022100000AC38232CFF000553E0FFA83062FFFF1D +:102220008F86002CA780004CACC200DC3062FFFF20 +:1022300000A258230A001E69AF8B005027BDFFD0B3 +:10224000AFB20018AFB00010AFBF0028AFB5002488 +:10225000AFB40020AFB3001CAFB100143C0C800041 +:102260008D880128240FFF803C07800A251001007B +:10227000250B0080020F68243205007F016F702457 +:10228000AD8E009000A72821AD8D002490A700EC12 +:102290003169007F3C0A8004012A1821A387004A83 +:1022A0009066007C00809021AF83002430C2000241 +:1022B000AF88005CAF85002C00A0182114400002FC +:1022C0002404003424040030A38400388C6600CC3D +:1022D00030F100FF24040004AF86005012240004F3 +:1022E000A38000588E5300041660001D3C08800037 +:1022F0009387004930F200011240000F8FBF002881 +:102300008CB800748CA400742419FF8003198824ED +:1023100000117140308F007F01CF60253C0D2000FF +:10232000018D582530F500FE3C0A8000AD4B083089 +:10233000A39500498FBF00288FB500248FB40020DB +:102340008FB3001C8FB200188FB100148FB0001033 +:102350002402000127BD003003E00008ACA600CC39 +:102360008E590008951F01208E460010033FC021A2 +:102370003307FFFF30F5000F32B40001AF860028AD +:102380001680003BA395004835060C0002A61021DC +:1023900000F51823AD030084AF8200548E49000479 +:1023A0003128FFFF1100002BA789004C2410FF806B +:1023B0003C1580003C1420000A001F572413FFFE28 +:1023C00090AE00C4020E682431AC00FF1580002AD4 +:1023D00002402021938400499786004C308F0001F1 +:1023E00011E0000B026428248F89002C8D230074D7 +:1023F0008D280074A3850049007010240002C94094 +:10240000311F007F033FC02503148825AEB108307B +:1024100010C000108F85002C90A700C4020758241C +:10242000316A00FF1540FFE6024020210E001E0B1E +:102430009791004C1040FFE8938400492405FFFD6C +:10244000544500058E430020022028210E001790DD +:10245000024020218E430020307000041600000A44 +:102460002414FFFB8F85002C0A001F0D8F8600505F +:102470000A001F38AF8600540E001A350000000015 +:102480000A001F4793840049007498240E0017AA7D +:10249000AE5300208F85002C0A001F0D8F86005040 +:1024A00027BDFFD8AFB3001CAFB10014AFBF0020F1 +:1024B000AFB20018AFB000103C0280008C52014057 +:1024C0008C4B01483C048000000B8C02322300FF3F +:1024D000317300FF8C8501B804A0FFFE34900180A9 +:1024E000AE1200008C8701442464FFF02406000231 +:1024F0002C830013AE070004A6110008A206000BEF +:10250000AE1300241060004F8FBF002000044880ED +:102510003C0A0801254A822C012A40218D04000032 +:1025200000800008000000003C1008008E1031A858 +:1025300031733FFF001389800212C8212405FF80F8 +:1025400003312021264C0100264700803C1F8000DB +:1025500000E51824318F007F30E9007F308A007F4A +:102560003C18800A3C0E80043C0D800C0085102431 +:1025700001853024014D8021AFE6002401F840217F +:10258000AFE30090012E9821AFE20028AF90003415 +:10259000AF88002CAF9300240E00187F01608021CB +:1025A0003C0380008C6B01B80560FFFE8F87003410 +:1025B000346501808F86002C90E3000DACB20000E2 +:1025C000A4B00006000316000002FE03001F9027BF +:1025D000001227C21080007A24C200782419608279 +:1025E000A4B90008A0A00005241F0002A0BF000B92 +:1025F00000041C008F8B00243C0227000062902501 +:10260000ACB20010ACA00014ACA00024ACA0002818 +:10261000ACA0002C8D7300382410FF80ACB30018E0 +:1026200090E4000D02048824322500FF10A000056C +:102630008FBF002090EC000D3188007FA0E8000DD6 +:102640008FBF00208FB3001C8FB200188FB1001411 +:102650008FB000103C0D10003C0A800027BD002800 +:1026600003E00008AD4D01B8265F01002405FF809E +:1026700033F8007F3C06800003E578243C19800A8B +:1026800003192021ACCF0024908E00C400AE682432 +:1026900031AC00FF1180FFEAAF84002C248E00785B +:1026A00095CD00123C0C08008D8C31A831AB3FFF5A +:1026B00001924821000B5180012A4021010520246C +:1026C000ACC400283107007F3C06800C00E62021C6 +:1026D0009083000D00A31024304500FF10A0FFD808 +:1026E000AF8400349098000D330F001015E0FFD533 +:1026F0008FBF00200E00187F000000003C03800008 +:102700008C7901B80720FFFE00000000AE12000027 +:102710008C720144AE120004A611000824110002BC +:10272000A211000BAE1300240A001FE28FBF00208D +:102730003C1260008E452C083C03F0033462FFFF1E +:1027400000A2F824AE5F2C088E582C083C1901B06A +:1027500003199825AE532C080A001FE28FBF0020F2 +:10276000264D010031AF007F3C10800A240EFF800F +:1027700001F0282101AE60243C0B8000AD6C0024E8 +:102780001660FFAFAF85002C24110003A0B100EC50 +:102790000A001FE28FBF002026480100310A007F97 +:1027A0003C0B800A2409FF80014B302101092024C1 +:1027B0003C078000ACE400240A001FE1AF86002C37 +:1027C000944A001232083FFF314C3FFF1588FF84C6 +:1027D0002419608290CF00C4240EFF8001CF4824CA +:1027E000312D00FF11A0FF7E00000000240700042F +:1027F000A0C700EC8F870034241860842406000DE5 +:10280000A4B80008A0A600050A001FCC241F0002DF +:102810000800330C0800330C080033E8080033BC10 +:10282000080033A0080032F0080032F0080032F04F +:102830000800331480080100800800808008000030 +:102840005F865437E4AC62CC50103A453662198545 +:10285000BF14C0E81BC27A1E84F4B556094EA6FE0A +:102860007DDA01E7C04D748108007AE408007B300E +:1028700008007AF008007A1808007AF008007B2037 +:1028800008007AF008007A1808007A1808007A1808 +:1028900008007A1808007A1808007A1808007A18D0 +:1028A00008007A1808007A1808007A1808007B10C7 +:1028B00008007B0008007A1808007A1808007A18C7 +:1028C00008007A1808007A1808007A1808007A18A0 +:1028D00008007A1808007A1808007A1808007A1890 +:1028E00008007A1808007B00080080DC08007F845C +:1028F000080080A408007F840800807408007E6CB3 +:1029000008007F8408007F8408007F8408007F849B +:1029100008007F8408007F8408007F8408007F848B +:1029200008007F8408007F8408007F8408007F847B +:0429300008007FAC70 +:0C2934000A00012200000000000000006A +:102940000000000D747061352E302E306A390000A1 +:102950000500000100000000000000000000000071 +:102960000000000000000000000000000000000067 +:102970000000000000000000000000000000000057 +:102980000000000000000000000000000000000047 +:102990000000000000000000000000000000000037 +:1029A0000000000000000000000000000000000027 +:1029B0000000000000000000000000000000000017 +:1029C00010000003000000000000000D0000000DDA +:1029D0003C02080024421C203C03080024631FA082 +:1029E000AC4000000043202B1480FFFD2442000473 +:1029F0003C1D080037BD2FFC03A0F0213C1008004F +:102A0000261004883C1C0800279C1C200E0002E2B3 +:102A1000000000000000000D2402FF8027BDFFE041 +:102A200000821024AFB00010AF420020AFBF0018EA +:102A3000AFB10014936500043084007F0344182173 +:102A40003C0200080062182130A5002003608021AC +:102A50003C080111277B000814A000022466005CDA +:102A60002466005892020004974301049204000473 +:102A70003047000F3063FFFF308400400067282399 +:102A80001080000900004821920200053042000435 +:102A9000104000050000000010A00003000000002E +:102AA00024A5FFFC24090004920200053042000422 +:102AB000104000120000000010A0001000000000F4 +:102AC0009602000200A72021010440252442FFFEB7 +:102AD000A7421016920300042402FF800043102432 +:102AE000304200FF104000033C0204000A00017263 +:102AF000010240258CC20000AF4210188F420178BD +:102B00000440FFFE2402000AA74201409602000290 +:102B1000240400093042000700021023304200075D +:102B2000A7420142960200022442FFFEA74201444E +:102B3000A740014697420104A74201488F4201087D +:102B400030420020504000012404000192020004A1 +:102B5000304200101440000234830010008018211D +:102B6000A743014A00000000000000000000000030 +:102B700000000000AF48100000000000000000004E +:102B800000000000000000008F4210000441FFFE22 +:102B90003102FFFF10400007000000009202000415 +:102BA0003042004014400003000000008F42101823 +:102BB000ACC20000960200063042FFFF2442000231 +:102BC0000002104300021040036288219622000098 +:102BD0001120000D3044FFFF00A710218F83003823 +:102BE0008F45101C0002108200021080004310214B +:102BF000AC45000030A6FFFF0E0002D100052C02FC +:102C000000402021A6220000920300042402FF803D +:102C100000431024304200FF1040001F000000005D +:102C200092020005304200021040001B000000002C +:102C30009742100C2442FFFEA7421016000000002D +:102C40003C02040034420030AF421000000000009B +:102C50000000000000000000000000008F42100093 +:102C60000441FFFE000000009742100C8F45101C2D +:102C70003042FFFF24420030000210820002108028 +:102C8000005B1021AC45000030A6FFFF0E0002D112 +:102C900000052C02A62200009604000224840008ED +:102CA0000E0001E73084FFFF974401040E0001F598 +:102CB0003084FFFF8FBF00188FB100148FB0001059 +:102CC0003C02100027BD002003E00008AF4201785D +:102CD0003084FFFF308200078F85002410400002FF +:102CE000248300073064FFF800A4102130421FFF46 +:102CF00003421821247B4000AF850028AF820024C6 +:102D000003E00008AF4200843084FFFF3082000FF0 +:102D10008F85002C8F860034104000022483000F22 +:102D20003064FFF000A410210046182BAF8500305E +:102D30000046202314600002AF82002CAF84002CD8 +:102D40008F82002C34048000034218210064182173 +:102D5000AF83003803E00008AF4200808F82001488 +:102D6000104000088F8200048F82FFCC14400005C1 +:102D70008F8200043C02FFBF3442FFFF0082202408 +:102D80008F82000430430006240200021062000F0C +:102D90003C0201012C6200035040000524020004A3 +:102DA0001060000F3C0200010A00022E000000002B +:102DB00010620005240200061462000C3C0201119E +:102DC0000A000227008210253C0200110082102513 +:102DD000AF421000240200010A00022EAF82000C54 +:102DE00000821025AF421000AF80000C00000000F0 +:102DF000000000000000000003E0000800000000E8 +:102E00008F82000C10400004000000008F42100070 +:102E10000441FFFE0000000003E000080000000085 +:102E20008F8200102443F800000229C224A2FFF080 +:102E30002C63030110600003000210420A000255D7 +:102E4000AC8200008F83001800A3102B1440000BED +:102E50000000382100A31023244600018F82001CAB +:102E6000006210212442FFFF0045102B5440000453 +:102E70002402FFFF0A000255AC8600002402FFFF77 +:102E80000A00025AAC8200008C8200003C03080059 +:102E900024631C5C000211400043382103E0000859 +:102EA00000E010213C0908008D291D8000045140DC +:102EB0003C19080027391C5C00C078210080602183 +:102EC000240EFFFF00003821015940211120003657 +:102ED000000030213C18080027181D983C0D080000 +:102EE00025AD1D9C000F582B0006118000461021B7 +:102EF000000218C0007810218C42000015820020CA +:102F0000006D20218CA20000544000098D020018A1 +:102F10003C0208008C421D8424420001AC82000067 +:102F20003C010800AC221D840A0002CF00002021D1 +:102F30008F47002000003021000211C01160004ABC +:102F4000AF4200208D08001C3C0900088CA3000043 +:102F50000066182100031880007A10210049102112 +:102F60008C44000024C600010068182100CF102BFB +:102F70001440FFF6AC6400000A0002CD000000001F +:102F80008C840000008E102B5040000424C60001E9 +:102F90000080702100C0382124C6000100C9102B18 +:102FA0001440FFD20006118024020001ACA20000F0 +:102FB0003C0208008C421D7C3C0308008C631D8091 +:102FC0000043102B1440002A2404FFFE0159102155 +:102FD0008C420018104000262404FFFF00072180C7 +:102FE0003C0508008CA51D84008720218D06001853 +:102FF000000420C03C02080024421D9800821021D9 +:103000003C03080024631D9CAC4C000024A5000177 +:10301000008318213C02080024421DA0AC6500007A +:10302000000631C03C010800AC251D84008220212F +:103030008F470020AD04001CAF46002011E0000ABD +:10304000000030213C020008034228218CA200002D +:1030500024C6000100CF182BAC82000024A5000478 +:103060001460FFFA24840004AF47002000002021F0 +:1030700003E00008008010213084FFFF30C6FFFF0E +:1030800000052C0000A628253882FFFF00451021EE +:103090000045282B0045102100021C023042FFFF92 +:1030A0000043102100021C023042FFFF00431021A8 +:1030B0003842FFFF03E000083042FFFF27BDFFC892 +:1030C000AFBF0030AFB3002CAFB20028AFB10024C7 +:1030D000AFB000203C0460088C8250002403FF7FC6 +:1030E0003C066000004310243442380CAC8250008F +:1030F0008CC24C1C3C1A8000000216023042000FA9 +:1031000010400007AF82001C8CC34C1C3C02001F07 +:103110003442FC0000621824000319C2AF83001877 +:103120008F420008275B400034420001AF42000894 +:10313000AF8000243C02601CAF400080AF400084A0 +:103140008C4500088CC3080834028000034220210B +:103150002402FFF0006218243C0200803C010800B9 +:10316000AC2204203C025709AF84003814620004EA +:10317000AF850034240200010A000314AF8200145A +:10318000AF8000142403003D240200043C01080029 +:10319000AC221D943C010800AC231D903C010800AA +:1031A000AC231D8C3C010800AC231D883C13080097 +:1031B00026731C5C240400043C02080024421C7496 +:1031C000240300082463FFFFAC400004AC4000006F +:1031D0000461FFFC24420020000410C000441021C0 +:1031E0002442003D3C010800AC221D902402000155 +:1031F0003C010800AC221D7C2402FFFF3C010800BA +:10320000AC221D983C010800AC201D848F420000B8 +:1032100038420001304200011440FFFC8F8200144C +:103220001040001600000000974201041040000505 +:103230008F830000146000072462FFFF0A00034B25 +:103240002C62000A2C620010504000048F830000A2 +:1032500024620001AF8200008F8300002C62000A0C +:10326000144000032C6200070A000352AF80FFCC19 +:103270001040000224020001AF82FFCC8F430108FE +:103280008F44010030622000AF830004104000082A +:10329000AF8400103C0208008C42042C2442000140 +:1032A0003C010800AC22042C0A0006D73C02400076 +:1032B0003065020014A0000324020F0014820309E9 +:1032C00024020D0097420104104003713C024000AB +:1032D00030624000144000AD8F8200388C440008FA +:1032E0008F4201780440FFFE24020800AF420178BB +:1032F00024020008A7420140A7400142974201046E +:103300008F8400043051FFFF30820001104000071D +:10331000022080212623FFFE240200023070FFFFDE +:10332000A74201460A00037FA7430148A740014680 +:103330003C0208008C42043C1440000D8F830010B6 +:1033400030820020144000022403000924030001FD +:10335000006020218F8300102402090050620001C8 +:1033600034840004A744014A0A00039A00000000C4 +:1033700024020F0014620005308200201440000671 +:103380002403000D0A0003992403000514400002E1 +:103390002403000924030001A743014A3C0208005A +:1033A0008C4204203C0400480E00020A0044202500 +:1033B0000E000233000000008F82000C1040003E1F +:1033C000000000008F4210003C0300200043102446 +:1033D000104000398F820004304200021040003655 +:1033E0000000000097421014144000330000000059 +:1033F000974210088F8800383042FFFF24420006B1 +:10340000000218820003388000E8302130430001B8 +:103410008CC4000010600004304200030000000D66 +:103420000A0003DB00E81021544000103084FFFF45 +:103430003C05FFFF00852024008518260003182B7B +:103440000004102B00431024104000050000000071 +:10345000000000000000000D000000002400021C1D +:103460008CC200000A0003DA004520253883FFFFE4 +:103470000003182B0004102B0043102410400005FB +:1034800000000000000000000000000D000000002F +:10349000240002258CC200003444FFFF00E8102104 +:1034A000AC4400003C0208008C420430244200017D +:1034B0003C010800AC2204308F6200008F84003889 +:1034C000AF8200088C8300003402FFFF1462000FFB +:1034D000000010213C0508008CA504543C040800A1 +:1034E0008C84045000B0282100B0302B00822021B1 +:1034F000008620213C010800AC2504543C01080052 +:10350000AC2404500A0006CD240400088C8200007C +:10351000304201001040000F000010213C0508005F +:103520008CA5044C3C0408008C84044800B028217D +:1035300000B0302B00822021008620213C010800B1 +:10354000AC25044C3C010800AC2404480A0006CD1C +:10355000240400083C0508008CA504443C04080031 +:103560008C84044000B0282100B0302B0082202140 +:10357000008620213C010800AC2504443C010800E1 +:10358000AC2404400A0006CD240400088F62000821 +:103590008F62000000021602304300F02402003067 +:1035A00010620005240200401062016B8F8200202F +:1035B0000A0006D52442000114A000050000000006 +:1035C000000000000000000D000000002400025078 +:1035D0008F4201780440FFFE000000000E00023B15 +:1035E00027A40010144000050040802100000000C6 +:1035F0000000000D00000000240002578E020000B1 +:103600001040000500000000000000000000000D58 +:10361000000000002400025A8F62000C04430003E3 +:10362000240200010A00055DAE000000AE020000A9 +:103630008F8200388C450008A20000078F65000CBF +:103640008F64000430A3FFFF0004240200852023C0 +:10365000308200FF004310212442000500028883CD +:103660002E220081A605000A14400005A2040004D1 +:10367000000000000000000D0000000024000272A5 +:103680003C0708008CE71D808FA800102409FFFF6D +:103690000000502110E00013000030213C0C080015 +:1036A000258C1D9C01802821000018218CA2FFFC84 +:1036B0005102002F006C18218CA400002463020822 +:1036C0000089102B1040000324A502080080482127 +:1036D00000C0502124C6000100C7102B5440FFF445 +:1036E0008CA2FFFC3C0508008CA51D803C02080054 +:1036F0008C421D7C3C09080025291C603C03080005 +:1037000024631D9800A2102B3C0C0800258C1D9CE6 +:103710003C0408008C841D843C0B0800256B1DA014 +:103720001040001A000831400005118000451021AA +:10373000000210C000C9382124840001004B302150 +:103740000043182124A50001004C1021AC680000A2 +:10375000ACE600183C010800AC241D84AC44000019 +:103760003C010800AC251D800A0004A88E04001C42 +:103770003C0208008C421D84244200013C010800E8 +:10378000AC221D840A0004A7AC620000000A11806C +:10379000004A1021000210C0004328218CA3000021 +:1037A000004C3821248400010003194000C9302155 +:1037B00000691821004B1021ACA80000AC60001873 +:1037C0003C010800AC241D84ACC20018ACE400002D +:1037D0008E04001C8F8500380E0006E70220302181 +:1037E0008F6200048F430108A60200083C0210000B +:1037F00000621824106000080000000097420104D5 +:10380000920300072442FFEC346300023045FFFFBF +:103810000A0004BCA2030007974201042442FFF0FF +:103820003045FFFF960600082CC2001354400005E7 +:10383000920300079202000734420001A20200072F +:103840009203000724020001106200052402000315 +:103850001062000B30C7FFFF0A0004DB24E2000205 +:103860008F8200383C04FFFF8C43000C0064182456 +:1038700000651825AC43000C0A0004DA30C7FFFFCE +:103880008F8200383C04FFFF8C4300100064182432 +:1038900000651825AC43001030C7FFFF24E200028A +:1038A00000021083A20200058F830038304200FF1F +:1038B00000021080004330218CC500008CC2000043 +:1038C0002403000400021702144300130000000048 +:1038D000974201043C03FFFF00A318243042FFFF7E +:1038E000004710232442FFFE00622825ACC50000DB +:1038F000920400058E03001C308200FF000210803D +:1039000000431021904200003042000F004410217B +:103910000A000510A20200068CC4000497420104AC +:103920009603000A3085FFFF3042FFFF0047102357 +:103930002442FFD60002140000A22825ACC50004D2 +:1039400092020007920400052463002800031883F4 +:103950000064182134420004A2030006A2020007FA +:103960008F8200042403FFFB344200020043102432 +:10397000AF820004920300068E07001C8F86003879 +:1039800000031880006710218C44000C3C02FFF6F5 +:103990003442FFFF0082282400661821AE04000C88 +:1039A000AC65000C920300068E04000C3C02FF7F05 +:1039B0003442FFFF0003188000A228240082202444 +:1039C00000671821AE04000CAC65000C92020006E2 +:1039D000000210800047102194450012AC450010F1 +:1039E000920200060002108000461021AC45001033 +:1039F0008FA20010920300050002114000031880FE +:103A000000671821005320218C6200048C83001869 +:103A10001460000EAE0200143C0308008C631D8C81 +:103A2000AC8300183C0208008C421D900062102BF1 +:103A300010400019000000003C0208008C421D9458 +:103A4000006210213C010800AC221D8C8E0200187F +:103A50008F48002000003021000211C01220000B0E +:103A6000AF4200203C0200080342282100E0202150 +:103A70008C82000024C6000100D1182BACA20000EB +:103A8000248400041460FFFA24A50004AF48002039 +:103A90000A00055E24020010000000000000000D76 +:103AA00000000000240002D424020010A7420140BC +:103AB00024020002A7400142A7400144A742014658 +:103AC000974201043C0400082442FFFEA74201483B +:103AD000240200010E00020AA742014A9603000ACE +:103AE00092020004004310212442000230420007E9 +:103AF00000021023304200070E000233AE02001015 +:103B00008F6200003C0308008C630444240400100E +:103B1000AF820008974201043042FFFF2442FFFEBB +:103B200000403821000237C33C0208008C420440A8 +:103B3000006718210067282B00461021004510213E +:103B40003C010800AC2304443C010800AC220440C2 +:103B50000A0006620000000014A00005000000003A +:103B6000000000000000000D00000000240003041D +:103B70008F4201780440FFFE000000000E00023B6F +:103B800027A400141440000500408021000000001C +:103B90000000000D000000002400030B920600044A +:103BA0008FA4001427A50018000630820E00025CC6 +:103BB000AFA00018504000068E0200000000000078 +:103BC0000000000D00000000240003118E02000020 +:103BD0005440000692020007000000000000000DA3 +:103BE0000000000024000316920200073042000487 +:103BF000104000058F8200042403FFFB34420002C2 +:103C000000431024AF8200048F62000404430009C3 +:103C100092020007920200068E03001C8E04000C24 +:103C20000002108000431021AC44000CAE000000E4 +:103C300092020007304200045440000B920300043B +:103C4000920300058E0400148E05001C00031880EA +:103C50003C0200010082202100651821AE040014FE +:103C6000AC640004920300049602000A0062102172 +:103C700024420005000290838FA200181040000D1E +:103C8000277100088FA40014000310820242302321 +:103C900027A500180E00025CAFA2001850400006D5 +:103CA0008E05001C000000000000000D0000000058 +:103CB0002400033F8E05001C022020210E0006E791 +:103CC00002403021920400068F6500043C027FFF11 +:103CD00000042080009120218C8300043442FFFFE7 +:103CE00000A2282400651821AC830004920200077A +:103CF00092030004920500053042000410400014B5 +:103D00009607000830A500FF0005288000B1282193 +:103D10008CA40004974201049606000A306300FF59 +:103D20003042FFFF004310210046102130E3FFFF27 +:103D3000004310232442FFD83084FFFF0002140008 +:103D400000822025ACA400040A0006169203000796 +:103D500030A500FF0005288000B128218CA40000B8 +:103D600097420104306300FF3042FFFF00431021FF +:103D7000004710233C03FFFF008320243042FFFF55 +:103D800000822025ACA40000920300072402000159 +:103D900010620006000000002402000310620011FF +:103DA000000000000A0006398E030010974201044B +:103DB000920300049605000A8E24000C0043102193 +:103DC000004510212442FFF23C03FFFF0083202422 +:103DD0003042FFFF00822025AE24000C0A00063985 +:103DE0008E03001097420104920300049605000A16 +:103DF0008E24001000431021004510212442FFEEC4 +:103E00003C03FFFF008320243042FFFF0082202577 +:103E1000AE2400108E0300102402000AA7420140C5 +:103E2000A74301429603000A920200043C040040AA +:103E300000431021A7420144A740014697420104D4 +:103E4000A7420148240200010E00020AA742014ACB +:103E50000E000233000000008F6200009203000495 +:103E600000002021AF820008974201049606000A54 +:103E70003042FFFF00621821006028213C03080047 +:103E80008C6304443C0208008C4204400065182105 +:103E9000004410210065382B004710213C01080028 +:103EA000AC2304443C010800AC220440920400040A +:103EB000008620212484000A3084FFFF0E0001E7E1 +:103EC00000000000974401043084FFFF0E0001F55C +:103ED000000000003C021000AF4201780A0006D446 +:103EE0008F8200201482002730620006974201046E +:103EF000104000673C024000306240001040000566 +:103F000000000000000000000000000D00000000A4 +:103F10002400041A8F4201780440FFFE24020800A6 +:103F2000AF42017824020008A7420140A7400142A5 +:103F30008F820004974301043042000110400007C3 +:103F40003070FFFF2603FFFE24020002A742014655 +:103F5000A74301480A00068C2402000DA740014631 +:103F60002402000DA742014A8F62000024040008C9 +:103F7000AF8200080E0001E7000000000A0006669C +:103F800002002021104000423C02400093620000E9 +:103F9000304300F02402001010620005240200707B +:103FA000106200358F8200200A0006D524420001ED +:103FB0008F620000974301043050FFFF3071FFFF14 +:103FC0008F4201780440FFFE3202000700021023F6 +:103FD000304200072403000A2604FFFEA7430140E5 +:103FE000A7420142A7440144A7400146A751014806 +:103FF0008F420108304200201440000224030009CF +:1040000024030001A743014A0E00020A3C040040B9 +:104010000E000233000000003C0708008CE7044457 +:10402000021110212442FFFE3C0608008CC6044009 +:104030000040182100E33821000010218F650000A6 +:1040400000E3402B00C230212604000800C83021C4 +:104050003084FFFFAF8500083C010800AC27044412 +:104060003C010800AC2604400E0001E700000000FF +:104070000A000666022020210E000139000000001F +:104080008F82002024420001AF8200203C024000C9 +:10409000AF4201380A000336000000003084FFFF01 +:1040A00030A5FFFF0000182110800007000000006D +:1040B00030820001104000020004204200651821F7 +:1040C0000A0006DD0005284003E00008006010211A +:1040D00010C0000624C6FFFF8CA2000024A5000427 +:1040E000AC8200000A0006E72484000403E0000814 +:1040F0000000000010A0000824A3FFFFAC86000011 +:1041000000000000000000002402FFFF2463FFFF06 +:104110001462FFFA2484000403E000080000000099 +:04412000000000019A +:0C4124000A00002A00000000000000005B +:104130000000000D747870352E302E306A39000082 +:10414000050000000000000A000001360000EA60DF +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:10417000000000000000000000000000000000003F +:104180000000000000000016000000000000000019 +:10419000000000000000000000000000000000001F +:1041A000000000000000000000000000000000000F +:1041B0000000000000000000000000000000138864 +:1041C00000000000000005DC00000000000000000E +:1041D00010000003000000000000000D0000000DB2 +:1041E0003C020800244238603C03080024633B146E +:1041F000AC4000000043202B1480FFFD244200044B +:104200003C1D080037BD7FFC03A0F0213C100800D6 +:10421000261000A83C1C0800279C38600E000407EC +:10422000000000000000000D8F86003C3C03900061 +:104230003C0280000086282500A32025AC440020F5 +:104240003C0380008C67002004E0FFFE00000000BB +:1042500003E00008000000000A00004124040001FF +:104260008F85003C3C0480003483000100A31025AE +:1042700003E00008AC82002003E0000800001021E9 +:104280003084FFFF30A5FFFF1080000700001821D9 +:104290003082000110400002000420420065182115 +:1042A0001480FFFB0005284003E000080060102197 +:1042B00010C00007000000008CA2000024C6FFFF11 +:1042C00024A50004AC82000014C0FFFB2484000479 +:1042D00003E000080000000010A0000824A3FFFF76 +:1042E000AC86000000000000000000002402FFFF78 +:1042F0002463FFFF1462FFFA2484000403E0000833 +:104300000000000090AA00318FAB00108CAC004080 +:104310003C0300FF8D680004AD6C00208CAD0044B0 +:1043200000E060213462FFFFAD6D00248CA70048DF +:104330003C09FF000109C024AD6700288CAE004C89 +:104340000182C82403197825AD6F0004AD6E002CDE +:104350008CAD0038314A00FFAD6D001C94A90032CD +:104360003128FFFFAD68001090A70030A560000263 +:10437000A1600004A167000090A30032306200FF3A +:104380000002198210600005240500011065000E6E +:104390000000000003E00008A16A00018CD800289A +:1043A000354A0080AD7800188CCF0014AD6F001432 +:1043B0008CCE0030AD6E00088CC4002CA16A0001C8 +:1043C00003E00008AD64000C8CCD001CAD6D00183E +:1043D0008CC90014AD6900148CC80024AD680008B5 +:1043E0008CC70020AD67000C8CC200148C83007059 +:1043F0000043C82B13200007000000008CC20014EB +:10440000144CFFE400000000354A008003E000087F +:10441000A16A00018C8200700A0000B70000000051 +:104420009089003027BDFFF88FA8001CA3A90000C9 +:104430008FA300003C0DFF8035A2FFFF8CAC002C49 +:1044400000625824AFAB0000A100000400C0582156 +:10445000A7A000028D06000400A048210167C82122 +:104460008FA50000008050213C18FF7F032C2026E0 +:104470003C0E00FF2C8C0001370FFFFF35CDFFFFF6 +:104480003C02FF0000AFC82400EDC02400C2782425 +:10449000000C1DC00323682501F87025AD0D000038 +:1044A000AD0E00048D240024AFAD0000AD04000863 +:1044B0008D2C00202404FFFFAD0C000C954700322A +:1044C00030E6FFFFAD0600109145004830A200FF26 +:1044D000000219C2506000018D240034AD040014A4 +:1044E0008D4700388FAA001827BD0008AD0B0028A3 +:1044F000AD0A0024AD07001CAD00002CAD00001873 +:1045000003E00008AD00002027BDFFE0AFB20018B7 +:10451000AFB10014AFB00010AFBF001C90980030D6 +:1045200000C088213C0D00FF330F007FA0CF0000AA +:10453000908E003135ACFFFF3C0AFF00A0CE000199 +:1045400094A6001EA22000048CAB00148E29000447 +:1045500000A08021016C2824012A402400809021A1 +:1045600001052025A6260002AE2400042605002011 +:10457000262400080E000063240600029247003043 +:10458000260500282624001400071E000003160339 +:1045900024060004044000032403FFFF9659003260 +:1045A0003323FFFF0E000063AE23001026240024F7 +:1045B0008FBF001C8FB200188FB100148FB0001095 +:1045C00024050003000030210A00006D27BD0020F3 +:1045D00027BDFFD8AFB1001CAFB00018AFBF00209F +:1045E00090A900302402000100E050213123003F57 +:1045F00000A040218FB000400080882100C04821E9 +:10460000106200148FA70038240B000500A02021A1 +:1046100000C02821106B0013020030210E0000F9A9 +:10462000000000009225007C30A4000210800003EE +:1046300026030030AE000030260300348FBF002078 +:104640008FB1001C8FB000180060102103E000083B +:1046500027BD00280E000078AFB000100A0001400E +:10466000000000008FA3003C010020210120282130 +:1046700001403021AFA300100E0000BFAFB0001406 +:104680000A000140000000003C0580008CA30E10D1 +:104690008F840044AC8300208CA20E1803E0000835 +:1046A000AC8200243C0580008CA30E148F8400444F +:1046B000AC8300208CA20E1C03E00008AC82002416 +:1046C0009382000C1040001B2483000F2404FFF091 +:1046D0000064382410E00019978B00109784000EB6 +:1046E0009389000D3C0A601C0A00017B0164402391 +:1046F00001037021006428231126000231C2FFFF4C +:1047000030A2FFFF0047302B50C0000E00E44821CC +:104710008D4D000C31A3FFFF00036400000C2C033F +:1047200004A1FFF30000302130637FFF0A00017312 +:104730002406000103E00008000000009784000E3A +:1047400000E448213123FFFF3168FFFF0068382B68 +:1047500054E0FFF8A783000E938A000D1140000576 +:10476000240F0001006BC023A380000D03E00008AC +:10477000A798000E006BC023A38F000D03E0000874 +:10478000A798000E03E000080000000027BDFFE826 +:10479000AFB000103084FFFF3C10800093A8002BC6 +:1047A000AFBF0014A6040144960A0E1630C600FFDF +:1047B0008FA90030A60A0146AE050148A2060152A3 +:1047C000A608015AAE0701608FA3002CA609015864 +:1047D000012020210E000167AE0301543C021000AD +:1047E000AE0201788FBF00148FB0001003E0000804 +:1047F00027BD00188F8500002484000727BDFFF81F +:104800003084FFF83C06800094CB008A316AFFFFB9 +:10481000AFAA00008FA90000012540232507FFFF54 +:1048200030E31FFF0064102B1440FFF7000568827F +:10483000000D288034CC400000AC102103E00008BB +:1048400027BD00088F8200002486000730C5FFF8CE +:1048500000A2182130641FFF03E00008AF840000AD +:104860008F8500448F8A003C27BDFFB03C04800048 +:10487000AFB70044AFB40038AFB1002CAFBF0048B1 +:10488000AFB60040AFB5003CAFB30034AFB20030BC +:10489000AFB000288C8701048CA90024AC8A00806A +:1048A0008CA8002000E988230000B821AC880E10F5 +:1048B0008CA600240000A021AC860E188C820E105D +:1048C000AC820E148C830E18AC830E1C122000FBDD +:1048D0003C168000936B0008116000F1000000009E +:1048E000976E001031CDFFFF022D602B158000EC7C +:1048F0000000000097700010320FFFFFAECF0E00D7 +:104900003C0580008CB30000327200081240FFFDAD +:104910000000000094B50E088CA70E0432A5FFFF1E +:1049200030B40001128000E1000000000000000D22 +:1049300030B9A040241800401338011730B4A0004B +:10494000128000DC00000000937300081260000871 +:1049500000000000976900103122FFFF00E2202BC9 +:104960001080000330A6004010C000D200000000FC +:10497000A7850040AF870038936A000802203821DD +:10498000AFB10020154000F127B40020AF60000C4B +:104990009785004030B14000162000022403001625 +:1049A0002403000E24154007A363000AAF7500140A +:1049B000939000428F6F0014321900010019C24019 +:1049C00001F84025AF680014978700408F630014FA +:1049D00030EE0010006E6825AF6D0014978C00401B +:1049E000318B000811600165000000008F65001424 +:1049F0003C0B10003C0A800000AB8825AF7100140E +:104A000095460E0A3C0981002413000E30C2FFFFB8 +:104A100000492025AF640004A3730002937F000ABD +:104A20003406FFFC27F20004A372000A978D0040B1 +:104A300031AC200011800157000000003C078000CD +:104A4000978D004094EC0E0C97910040000D584259 +:104A50003185C000316A00030005130332291000BC +:104A600001429825000922030264F825001F90C026 +:104A7000A7720012979500409379000A0015818271 +:104A80003218003C0319782125E8003CA36800098E +:104A900094EE0E0C31C33FFFA76300109763001222 +:104AA0009367000900E3702125CD000231AC0007B7 +:104AB000000C582331650007A365000B93710009B2 +:104AC00097640012976A0010322200FF8F9100381D +:104AD000979F004000444821012A982102669021B6 +:104AE00033F5004012A000053246FFFF00D1402BF5 +:104AF0003C12800011000016000098210226782B3D +:104B000015E001368FA700203C1880008F100E148E +:104B10003C058000AF100E108F190E1CAF190E1837 +:104B2000AF060E008CB200003255000812A0FFFD47 +:104B30000000000094BF0E0800C0882100009021F2 +:104B4000A79F00408CA60E0424130001AF860038F6 +:104B5000976900103135FFFF8E8C000001912023F2 +:104B600010800118AE8400009367000814E000D89C +:104B7000000000000E0001B4240400108F8E0048D5 +:104B80003C0332000040282131C600FF00063C00F3 +:104B900000E3602525CD0001AF8D0048AC4C00003E +:104BA0009362000997640012937F000A304A00FF65 +:104BB000308BFFFF014B48210009CC0033F000FF90 +:104BC0000330C025ACB800048F8F004897880040A0 +:104BD0003103200010600103ACAF0008976F001292 +:104BE00031E8FFFF06400101ACA8000C979000409F +:104BF0003205000814A0000226280006262800021C +:104C00003C048000948B0E148C850E1C8F6700046E +:104C1000936A00023164FFFF314900FFAFA9001021 +:104C20008F7F0014AFA80018AFBF00140E00019AC8 +:104C300000000000240400100E0001C80000000065 +:104C40008E92000016400005000000008F790014CD +:104C50002405FFBF0325A024AF7400148F69000C46 +:104C60000135F821AF7F000C9375000816A00008ED +:104C70000000000012600006000000008F6B0014AE +:104C80003C0CEFFF3584FFFE01645024AF6A001432 +:104C9000A37300088FA700200A000316022020211A +:104CA000AED10E000A0001F83C05800014E0FF219F +:104CB00030B9A0400E0001600000A0212E9100013B +:104CC0000237B02512C000178FBF00488F85003C07 +:104CD00024170F0010B700CD3C0480008C99017898 +:104CE0000720FFFE24150F0050B500EB3C048000A8 +:104CF0008C890E14240502403C141000AC89014438 +:104D00008C9F0E1CAC9F0148A0800152A480015AC8 +:104D1000AC800160A4800158AC850154AC9401784A +:104D20008FBF00488FB700448FB600408FB5003C5E +:104D30008FB400388FB300348FB200308FB1002CA5 +:104D40008FB0002803E0000827BD00508F91003885 +:104D5000979300403C1280000220A821326A004054 +:104D60001540FF7D00009821976B00108F8500385B +:104D70003162FFFF104500A2000020210080A02129 +:104D8000108000E500E088211620FED2000000001F +:104D90000A0002E72E9100013C0380008C7F01781D +:104DA00007E0FFFE240408008F860000AC64017851 +:104DB0003C038000946C008A318BFFFF0166502316 +:104DC0002549FFFF31281FFF2D0200081440FFF97D +:104DD000000000008F8E0048346F40008F83003C3D +:104DE00000E0A021240D0F0025C70001AF87004877 +:104DF00000CF3021023488233C08800031D500FFE9 +:104E0000106D0005240700019393004232720001E7 +:104E10000012824036070001001514003C09010011 +:104E200000492025ACC400008F9F004830B90036EF +:104E300030B80008ACDF00041300009000F998259A +:104E400095070E0A8F8E00003C03810030EDFFFFB6 +:104E500025CB000801A328253C0C1000316A1FFF58 +:104E6000269200062406000EAD050160026C98250E +:104E7000A506015AAF8A0000A512015816200008A5 +:104E80003C1080008F99003C24180F00533800021A +:104E900024170001367300400E0001593C108000B9 +:104EA0008E1F0E1402402021AE1F01448E120E1CD4 +:104EB000AE120148A2150152AE1301540E00016753 +:104EC0003C151000AE1501780A000319000000001F +:104ED00093780009976300129368000B330F00FF6B +:104EE00001E33821310200FF00E2702125D0000AE1 +:104EF0003210FFFF0E0001B4020020218F8600480F +:104F00003C1941003C07800024CD0001AF8D0048D2 +:104F1000936C00099764001230C600FF318A00FFCD +:104F2000308BFFFF014B482100062C00253F00027B +:104F300000BFC02503197825AC4F00008F68000C16 +:104F400094EE0E1401121825AC4300048CE50E1CDF +:104F50008F670004936D000231C4FFFF31AC00FF86 +:104F6000AFAC00108F620014AFB100180E00019AB0 +:104F7000AFA200140A0002C502002021AF600004A5 +:104F8000A3600002978D004031AC20001580FEAB7D +:104F900000003021A7600012979000409378000A2B +:104FA0003C03800032191F000019798301F8402169 +:104FB00025070028A3670009946E0E0C0A00025E04 +:104FC000A76E00108F6E001435CD00400E00015901 +:104FD000AF6D00140A000291000000000A000316E1 +:104FE000000020210641FF01ACA0000C8CB8000C91 +:104FF0003C198000031990250A0002B2ACB2000CE3 +:10500000000090210A00028D241300011280000587 +:105010003C0D800095A60E0830D30040126000427F +:10502000000000008C9001780600FFFE00000000E8 +:1050300094920E103C030500240720003258FFFF15 +:1050400003037825AC8F014C8C880E143C0E1000A5 +:10505000AC8801448C820E1CAC820148A0800152B5 +:10506000A480015AAC800160A4800158AC8701542F +:10507000AC8E01780A0002EE3C0480008F900000A4 +:1050800026920002A5120158260F000831E81FFFE2 +:105090000A000356AF880000AC80014C1280001952 +:1050A000000000008C8A0E10AC8A01448C830E181C +:1050B0003C0C800024160040AC8301488FBF0048A0 +:1050C000A18001528FB70044A580015A8FB5003CE2 +:1050D000AD8001608FB40038A58001588FB30034D3 +:1050E000AD9601548FB200308FB600408FB1002CC6 +:1050F0008FB000283C04100027BD005003E00008DA +:10510000AD8401788C8B0E14AC8B01448C830E1C07 +:105110000A0003E43C0C80000E0001602E910001A7 +:105120000A0002E80237B025000000000000000D70 +:10513000000000002400033A0A0003C03C04800081 +:1051400027BDFFE0AFBF001C3C1F20FF3C076000F5 +:105150003C0980002402001037F9FFFDACE2300862 +:10516000AFB20018AFB10014AFB00010AD390E00EF +:10517000000000000000000000000000000000002F +:10518000000000003C1800FF3712FFFDAD320E009A +:105190003C0B60048D7050002411FF7F3C0E000218 +:1051A0000211782435EC380C35CD0109ACED4C18E2 +:1051B000240A0009AD6C50008CE80438AD2A0008C0 +:1051C000AD2000148CE54C1C3106FFFF38C42F7154 +:1051D00000051E023062000F2486C0B31040000795 +:1051E000AF8200088CE54C1C3C09001F3528FC00F0 +:1051F00000A81824000321C2AF8400048CF1080821 +:105200003C0F57092412F0000232702435F00010D0 +:1052100001D0602601CF68262DAA00012D8B000148 +:10522000014B382550E00009A380000C3C02601CB3 +:105230008C590008241F0001A39F000C33387C0008 +:10524000A7980010A780000EA380000DAF80004833 +:1052500014C00003AF8000003C066000ACC0442CCA +:105260000E0004B63C1080000E000DDF00000000B0 +:105270003C110800263138C83C1208002652394833 +:105280008E05000038A30001306400011480FFFC8B +:10529000000000008E0601003C0C800A240AFF80FA +:1052A00024C7024030EB007F016C482100EA402413 +:1052B000AE060020AF890044AE0800243C03800005 +:1052C000AF86003C8C6D017805A0FFFE2419080014 +:1052D000AC79017890780108A3980042938F00423E +:1052E00031EE000111C0000F240D0D0024C2F800A2 +:1052F0002C5F030113E0001C000629C224A3FFF069 +:1053000000032042000431400E0001CF00D1D8211B +:105310003C0440003C068000ACC401380A0004573D +:105320000000000010CD0026240E0F0010CE002A31 +:105330003C028008345F008093F90000240F005085 +:10534000333800FF170FFFF33C0440000E00091232 +:10535000000000003C0440003C068000ACC4013862 +:105360000A000457000000008F83000400A3402BB4 +:105370001500000B8F8B0008006B50212547FFFFA5 +:1053800000E5482B1520000600A36023000C2940EF +:105390000E0001CF00B2D8210A00047C3C0440007A +:1053A000000000000000000D00000000240003AD1C +:1053B0000E0001CF000000000A00047C3C04400005 +:1053C0003C1B0800277B3A480E0001CF000000007C +:1053D0000A00047C3C0440003C1B0800277B3A6820 +:1053E0000E0001CF000000000A00047C3C044000D5 +:1053F000000411C003E00008244202403C040800FD +:1054000024843AAC2405001A0A00006D0000302103 +:1054100027BDFFE0AFBF001CAFB20018AFB1001452 +:10542000AFB000103C108000920B01092412FF80E5 +:105430000E0004B33164007F8F91003C0051502175 +:1054400001524024AE080024920301090E0004B367 +:105450003064007F24060080240700C0240400403C +:10546000AE000810AE040814AE060818AE07081CFB +:10547000920C01090051F82133F8007F3C19800A91 +:10548000031910213184007F0E0004B3AF82004461 +:105490008E1101003C0C008035850001022278212C +:1054A00001F24824AE0908048E0E0100359800026E +:1054B0003609090001C2682131AB00780165502529 +:1054C000AE0A08208E0501008E080100360509800D +:1054D000010218212464004000923024AE0608081E +:1054E0008E07010000E2F82127F9004033320078EE +:1054F00002588825AE1108248E040100952F000C57 +:105500008FBF001C8FB2001831EEFFFF000E69C084 +:10551000AE0D0800AE0C0828952B000C8FB10014BE +:10552000316AFFFF000A41C0AE08002C8CA3005076 +:105530008FB000108CA2003C8D2400048CA6001CAF +:105540008CA7003827BD0020AF830060AF820050D9 +:10555000AF84004CAF86005803E00008AF87005CC2 +:105560003C0A0800914A3AD13C09080095293ACAF8 +:105570003C051100000A3C002528000200E8302507 +:1055800000C5182524820008AC83000003E0000851 +:10559000AC8000043C098000352809009107001107 +:1055A000240200280080502130E300FF00A0682181 +:1055B00000C0602110620002340B86DD240B08005D +:1055C0003C07800034E20A9A9443000034F80A9CB5 +:1055D00034E60AA03079FFFFAD5900008F0F0000BC +:1055E00034E80A8024040001AD4F00048CCE000092 +:1055F000AD4E00089105001930A300031064004669 +:1056000028690002152000B52404000210640090EF +:10561000240500031065009B34E40AA43C0908003B +:1056200095293AC024070800516700503C188000B3 +:105630003C0280003459090093280012932E00196F +:1056400034580980310F00FF8F06002801EC182123 +:10565000000338803124FFFF31CB00FF00E410212C +:10566000000B2D0000A6C02500027C003C08600055 +:105670000308182535E906FFAD430000AD490004D5 +:105680008F2E002C3C0380003478093CAD4E00087E +:105690008F27003025490028346E0900AD47000CE3 +:1056A0008F2B0034AD4B00108F240038AD44001414 +:1056B0008F25001CAD4500188F220020AD42001C34 +:1056C0008F26002425220014AD4600208F280028B4 +:1056D000AD4800248F0F0000AD2D0004AD2F000059 +:1056E0008C64010CAD24000891C700123C05080031 +:1056F00090A53AD0AD20001030EB00FF016C3021B6 +:1057000000066F000005CC0001B96025358AFFFF57 +:1057100003E00008AD2A000C3C09080095293AC0B6 +:105720003C19080097393ACA34E20AA43C0608003A +:1057300094C63ABC944F00003123FFFF0323C021DD +:1057400003067023000F3C0025C8FFF200E828255F +:1057500024070800AD45000CAD400010AD4B00140F +:105760001567FFB3254A00183C1880003708090068 +:10577000910F00119107001937030A8031EE00FFE5 +:105780003C19080097393AC6946F002A000E5882D7 +:1057900030E400FF97870054000B160000042C0033 +:1057A0003126FFFF0326C02100454825013870251A +:1057B00001E758213C03400001C32025000B2C00C9 +:1057C000AD440000AD450004910200183C060006FF +:1057D0003C0380000002CE000326C025AD5800081F +:1057E0008D0F002C3478093C24E90001AD4F000CEA +:1057F0008D0B001C312E7FFF25490014AD4B00108E +:105800008F0F0000AD2D0004A78E0054AD2F0000B7 +:105810008C64010C346E090025220014AD240008AC +:1058200091C700123C05080090A53AD0AD200010A9 +:1058300030EB00FF016C302100066F000005CC004A +:1058400001B96025358AFFFF03E00008AD2A000C8E +:1058500034E90AA495240000950200283C090800B8 +:1058600095293AC000041C000002CC003478810065 +:10587000032B7825AD58000CAD4F00100A000540F1 +:10588000254A00143C09080095293AC03C05080047 +:1058900094A53ACA3C06080094C63ABC9499000004 +:1058A0003123FFFF9518002800A31021004678231C +:1058B00000193C000018440025EEFFEE010E2825DB +:1058C00034E48100AD44000CAD450010AD4000143F +:1058D000AD4B00180A000540254A001C1460FF4F1C +:1058E00034E60AA494CE00003C09080095293AC089 +:1058F000000E4400010B3825AD47000C0A0005409E +:10590000254A001003E00008240207D027BDFFE06D +:10591000AFB20018AFB10014AFB00010AFBF001CA1 +:105920000E00004D008088218F8800508F87004C2A +:105930003C05800834B20080011128213C10800011 +:1059400024020080240300C000A72023AE02081810 +:105950003C068008AE03081C18800004AF85005088 +:10596000ACC500048CC90004AF89004C12200009AA +:10597000360409800E0005F800000000924C002754 +:105980008E0B007401825004014B3021AE46000C96 +:10599000360409808C8E001C8F8F005801CF68233D +:1059A00019A000048FBF001C8C90001CAF90005801 +:1059B0008FBF001C8FB200188FB100148FB0001081 +:1059C0000A00004F27BD00208F8600608F830050A3 +:1059D0008F82004C3C05800834A40080AC860050C7 +:1059E000AC83003C03E00008ACA200043C030800C8 +:1059F0008C63005427BDFFF8308400FF246200014F +:105A000030A500FF3C010800AC22005430C600FF66 +:105A10003C0780008CE801780500FFFE3C0A7FFF10 +:105A2000A3A400038FA400003549FFFF00891824B8 +:105A3000000647C000681025AFA2000090F9010AD7 +:105A4000A3A000023C1880FFA3B900018FAE0000A4 +:105A500030AD007F370FFFFF01CF5824000D6600E7 +:105A60003C090020016C5025352620002405FF80CC +:105A70003C04100027BD0008ACEA014CACE6015420 +:105A8000A4E00158A0E5015203E00008ACE401786D +:105A9000308800FF3C03800030A400FF8C62017856 +:105AA0000440FFFE000000003C03800034660A0052 +:105AB0008CCA0020346709800004482BAC6A01447A +:105AC0008CC5002400091540AC650148A068015050 +:105AD00090E4004CA064016D03E00008A46001584C +:105AE00027BDFFE8308400FFAFBF00100E00065B4B +:105AF00030A500FF8F8300508FBF00103C05800051 +:105B0000344600402404FF903C02100027BD0018DA +:105B1000ACA3014CA0A40152ACA6015403E00008C0 +:105B2000ACA2017827BDFFE03C088008AFBF001C95 +:105B3000AFB20018AFB10014AFB000103510008044 +:105B40008E0600183C078000309200FF00C7202519 +:105B5000AE0400180E00004D30B100FF92030005A6 +:105B6000346200080E00004FA2020005024020210E +:105B70000E00066F02202821024020218FBF001C4A +:105B80008FB200188FB100148FB0001024050005EB +:105B9000240600010A00063227BD00203C058000D3 +:105BA00034A309809066000830C200081040000F3E +:105BB0003C0A01013549080AAC8900008CA8007430 +:105BC000AC8800043C07080090E73AD030E50010AC +:105BD00050A00008AC8000083C0D800835AC008067 +:105BE0008D8B0058AC8B00082484000C03E0000867 +:105BF000008010210A0006B22484000C27BDFFE8B3 +:105C00003C088000AFB00010AFBF0014350609801B +:105C100090C70009240200063509090030E300FF9F +:105C20000080802100A06021240B00041062007914 +:105C30002407000294CF005C3C0E020431EDFFFF0C +:105C400001AE5025AE0A000090C5000830A4002027 +:105C5000108000080000000090C2004E3C1F0103AD +:105C600037F90300305800FF03193025240B0008D2 +:105C7000AE06000491390011912600129124001102 +:105C8000333800FF0018708230CF00FF01CF502161 +:105C9000014C6821308800FF31AAFFFF390300283A +:105CA000000A28801460002B020540239124001272 +:105CB0003C0E800035D90980308500FF00AC1821EA +:105CC00000031080004BF821001F8400360906FFF6 +:105CD000AD09000435C9090091260011912F001269 +:105CE000000BC0828F2B003431ED00FF8DC4010CFE +:105CF00001AC282100B810210164F82300078400BA +:105D000000021F000070C82533E9FFFF30CF00FC00 +:105D1000032970250158202101E8682100045080E2 +:105D2000ADAE000C0E00004D010A80213C0780083A +:105D3000240C000434EB00800E00004FA16C00091D +:105D4000020010218FBF00148FB0001003E0000884 +:105D500027BD001891250011912300193C18080057 +:105D600097183AC630A200FF0002F882307000FF98 +:105D7000001FCE0000104C000329302500D87025EC +:105D80003C0F400001CF68253C0E8000AD0D0000A7 +:105D900035C9090091260011912F001235D90980CB +:105DA000000BC08231ED00FF8F2B00348DC4010C3D +:105DB00001AC282100B810210164F82300078400F9 +:105DC00000021F000070C82533E9FFFF30CF00FC40 +:105DD000032970250158202101E868210004508022 +:105DE000ADAE000C0E00004D010A80213C0780087A +:105DF000240C000434EB00800E00004FA16C00095D +:105E0000020010218FBF00148FB0001003E00008C3 +:105E100027BD00180A0006C42407001227BDFFD0C2 +:105E2000AFB50024AFB40020AFB3001CAFB000107A +:105E3000AFBF0028AFB20018AFB100143C0680001D +:105E400090C3010B309300FF30B400FF306200308C +:105E50000000A821104000820000802134C4098085 +:105E60009088000800083E0000072E0304A000A947 +:105E7000240400048F8700503C010800A0243AD07D +:105E80003C0C8000AD8000483C038000906E010B0C +:105E900031C5002010A000073C0C80003478098038 +:105EA0009312000800128E0000117E0305E000AE80 +:105EB0003C028008918B010B3586098090C4000854 +:105EC000316A0040000A482B308800082411000382 +:105ED0001500000200E99023000088213C038000A7 +:105EE00034780A80346A09009707002C9144001125 +:105EF0009149001293050018309F00FF312800FFE0 +:105F0000022810210002C880930D0018033F782159 +:105F100001F0702130B000FF01D01821A787005494 +:105F20003C010800A42E3AC63C010800A4233AC84C +:105F300015A00003246B000A0000000D246B000A6A +:105F40003170FFFF3C010800A4233ACA3C0108005D +:105F5000A4203AC03C010800A4203ABC0E0001B4C1 +:105F6000020020210E00050F0040202100402021CA +:105F7000024028210E00051C022030210E00069E42 +:105F80000040202116A0005F004020210E0001C823 +:105F9000020020213C11080092313AD03235000332 +:105FA00012A000163C0A80088F8700503C0E800823 +:105FB00035CD008024EC0001ADAC003C3C058008F0 +:105FC0008CA600040180202100CC90231A400002FE +:105FD000AF8C00508CA400040E0005F8ACA40004A3 +:105FE0003C1980008F3800743C0F800835F0008029 +:105FF00000582821AE05000C3C0A8008354200807C +:106000000260202102802821A040006B0E00065B68 +:106010003C1380008F840050345F0006AE64014C56 +:106020008F8800483C1410008FB50024250900011A +:10603000AF8900488FB20018A26801528FB10014D6 +:10604000AE7F01548FB00010AE7401788FBF00286E +:106050008FB400208FB3001C03E0000827BD003080 +:1060600034C30980906F0008000F7600000E6E03A5 +:1060700005A0003334C209009059001B241F0010F2 +:106080003C010800A03F3AD0333800021300FF7EE5 +:106090008F8700508F83005C1467FF7C3C03800077 +:1060A0000E00004D000000003C09800835250080EE +:1060B00090A4000924070016308800FF1107000D86 +:1060C0000000000090A600093C0C0800918C3AD01A +:1060D000240A000830C400FF358B00013C01080091 +:1060E000A02B3AD0108A002F240D000A108D002812 +:1060F0002402000C0E00004F000000000A000759A7 +:106100008F8700500E0006B6022028210A00079A49 +:10611000000000003C0B8008356A00808D47005469 +:106120008CC9010C1120FF54AF87005024060014C5 +:106130003C010800A0263AD00A0007583C0C800019 +:1061400090710008241200023C010800A0323AD0ED +:10615000323000201200000B241500018F87005000 +:106160000A00075924100008345900808F23003892 +:10617000AC4300048C5F0004AF3F003C0A0007649E +:106180003C0C80008F8700500A000759241000043F +:10619000A0A200090E00004F000000000A000759ED +:1061A0008F870050240200140A00081CA0A20009D6 +:1061B00027BDFFE8AFBF0014AFB000103C10800057 +:1061C00092020109240500010E00065B304400FF25 +:1061D0003C1F800893F8000E37E3008093F9000F0E +:1061E000906E002693E9000A332F00FF0018660026 +:1061F000000F6C0031CB00FF018D5025000B3200E9 +:1062000001463825312800FF3445600000E820258C +:106210002402FF813C031000AE04014C8FBF001428 +:10622000AE050154A2020152AE0301788FB00010F6 +:1062300003E0000827BD001827BDFFE8308400FFF9 +:10624000AFBF00100E00065B30A500FF34460040D3 +:106250003C0480002405FF92AC860154A0850152C5 +:106260008F8300508FBF00103C02100027BD001824 +:10627000AC83014C03E00008AC82017827BDFFD855 +:10628000AFB20018AFB10014AFB00010AFBF002024 +:10629000AFB3001C3C07800090E20109308600FF8C +:1062A00030B000FF000618C2320400023071000155 +:1062B00014800007305200FF3C098008353300800D +:1062C000926800053105000810A0000C30CA0010CB +:1062D000024020210E000680022028212402000115 +:1062E0008FBF00208FB3001C8FB200188FB1001435 +:1062F0008FB0001003E0000827BD002815400030D3 +:1063000034E50A008CB900248CB800081338004723 +:10631000000040213C0E800835D30080926D00685B +:10632000240B000231AC00FF118B00803C06800082 +:10633000927F004C90C40109509F00043213007CEE +:1063400011000067000000003213007C1660005A44 +:106350000240202116200008320C00013C0780007A +:1063600034EB0A008D6500248CE8010414A8FFDCDE +:1063700000001021320C00011180000D024020218C +:106380003C1080008E0E010C8F8D006011CD000836 +:10639000000000000E00073E022028218E0F010C95 +:1063A0003C18800837100080AE0F005002402021BA +:1063B0000E00066F022028210A00086F2402000147 +:1063C0003C0708008CE7006424E600013C0108005B +:1063D000AC2600641600000D0000000002202821F9 +:1063E0000E00066F02402021926F0068240D00020B +:1063F00031EE00FF11CD0022024020210E000823C3 +:10640000000000000A00086F240200010E00004195 +:1064100024040001926C0025020C58250E00004F48 +:10642000A26B00250A0008AF022028218E63001805 +:106430008CE401048CBF002400031602149FFFB5F6 +:106440003045007F9269004C264400013093007F64 +:1064500012650040312300FF1464FFAF3C0E80083A +:10646000264800013111007F310200FF1225000B88 +:1064700024080001004090210A00087C241100013A +:10648000240500040E000632240600010E00082335 +:10649000000000000A00086F240200012407FF80AA +:1064A0000247282400A79026324200FF0040902196 +:1064B0000A00087C241100010E00073E022028215A +:1064C0003206003010C0FFA33210008202402021AB +:1064D0000E000680022028210A00086F2402000115 +:1064E0008E6300180240202102202821006610251A +:1064F0000E000845AE6200189264004C24050003AB +:10650000240600010E000632308400FF0E00004118 +:1065100024040001926A0025020A48250E00004F5B +:10652000A26900250A00086F240200018E78001875 +:106530003C198000024020210319782502202821DF +:106540000E00066FAE6F00189264004C0A0008F748 +:10655000240500043246008038CA0080146AFF6EA9 +:106560003C0E80080A0008D02648000127BDFFC065 +:10657000AFB000183C108000AFBF0038AFB7003498 +:10658000AFB60030AFB5002CAFB40028AFB30024D5 +:10659000AFB200200E0004BBAFB1001C9204010892 +:1065A0009205010B308400FF0E00085630A500FF55 +:1065B000144000E38FBF00383C0980083528008074 +:1065C000A100006B3607098090E60000240200500D +:1065D0003C17080026F73A8830C300FF3C13080038 +:1065E00026733A98106200033C1080000000B82126 +:1065F00000009821241F001036110A00361409806B +:106600008E1601048F8D00508E38002436190A80B2 +:106610008E9200203C010800A03F3AD0972C002C1D +:106620008EF50000932B0018024D702302D87823BA +:106630003C010800AC2F3AAC3C010800AC2E3AB04B +:106640003C010800AC2D3AD4A78C005402A0F809F4 +:10665000317200FF304A0002154000E6304500016B +:1066600010A000C100000000928A0008315000080C +:1066700016000002241400030000A0213C06800044 +:1066800034C4090034C30A008C6E002490850011C4 +:10669000908200129099001130B800FF305100FF35 +:1066A0000291F821001FB080332F00FF02D858213B +:1066B000024FA82126AC0010017268213C15800011 +:1066C0003C010800AC2E3AD83C010800A42D3AC881 +:1066D0003C010800A42C3AC43C010800A42B3AC693 +:1066E00036B609808F8700508F8900588ED20020DF +:1066F0002408000601273023024728233C01080014 +:10670000AC283ACC04C000B30000902104A000B132 +:1067100000C5802B120000B3000000003C010800FF +:10672000AC263AB08E7100000220F809000000008B +:10673000304A00021540007400408021304B0001B7 +:10674000556000118E7100043C0D08008DAD3AB407 +:106750003C0EC0003C04800001AE6025AEAC0E00D3 +:106760008C980000330F000811E0FFFD00000000CE +:10677000949F0E0824120001A79F00408C990E04DC +:10678000AF9900388E7100040220F8090000000063 +:106790000202802532020002144000A9000000001D +:1067A0003C08080095083ABC3C11080096313AC8EC +:1067B0003C09080095293ABE3C0308008C633AB4B2 +:1067C000011168213C1F08008FFF3AD83C070800E0 +:1067D00094E73AD23C11800001A920218E38010CA7 +:1067E000006828212499000200A7702103E3782182 +:1067F000AF9800603C010800AC2F3AD83C0108007B +:10680000A42E3AC03C010800A42D3ACA0E0001B4DF +:106810003324FFFF8F8C0048004020213C010800FA +:10682000A02C3AD18E620008258B0001AF8B004866 +:106830000040F809000000008F85005002803021E0 +:106840000E00051C004020210E00069E0040202165 +:106850008E6A000C0140F809004020213C08080025 +:1068600095083ACA3C09080095293ABE0109382121 +:1068700024E600020E0001C830C4FFFF3C040800FB +:106880008C843AAC3C0308008C633AB40083282320 +:106890003C010800AC253AAC14A000060000000042 +:1068A0003C0A08008D4A3ACC354600403C010800BD +:1068B000AC263ACC124000418F8C00448E2B0E1037 +:1068C0008F920044AE4B00208E220E18AE42002460 +:1068D0003C04080094843AC00E0005FA0000000051 +:1068E0008F9900508E7800103C010800AC393AD4E2 +:1068F0000300F809000000003C0F08008DEF3AACDF +:1069000015E0FF798F870050979400543C13800E58 +:10691000321500100E000629A674002C56A0004463 +:106920008EF60004321F004057E0001D8EF0000874 +:106930008EE3000C0060F809000000008FBF0038F3 +:106940008FB700348FB600308FB5002C8FB400287D +:106950008FB300248FB200208FB1001C8FB00018BD +:1069600003E0000827BD0040920901098F88003C20 +:1069700000093E0000E83025AE0600808E2300208E +:106980008E240024AFA30010AE030E148FA20010BB +:10699000AE020E10AE040E1C0A000951AE040E1811 +:1069A0000200F809000000008EE3000C0060F80906 +:1069B000000000000A000A078FBF0038240E000103 +:1069C000240D0001A5800020A58E00220A0009EBFD +:1069D000AD8D00243C010800AC203AB00A000981CA +:1069E0008E7100003C010800AC253AB00A00098114 +:1069F0008E71000092110109000028210E00066F1F +:106A0000322400FF8FBF00388FB700348FB60030BC +:106A10008FB5002C8FB400288FB300248FB20020D4 +:106A20008FB1001C8FB0001803E0000827BD0040A4 +:106A300002C0F809000000000A000A01321F0040ED +:106A40005240FFB2979400548EB60E148F930044B8 +:106A5000AE7600208EB40E1CAE7400240A0009FA33 +:106A6000979400548F8200140004218003E00008F2 +:106A7000008210213C07800834E2008090430069C6 +:106A800000804021106000093C0401003C07080020 +:106A90008CE73AD48F83003000E320230480000881 +:106AA0009389001C14E300030100202103E0000887 +:106AB000008010213C04010003E000080080102148 +:106AC0001120000B006738233C0D800035AC098095 +:106AD000918B007C316A00021140002024090034AF +:106AE00000E9702B15C0FFF10100202100E93823D7 +:106AF0002403FFFC00A3C82400E3C02400F9782B82 +:106B000015E0FFEA0308202130C40003000410232D +:106B100014C00014304900030000302100A978217E +:106B200001E6702100EE682B11A0FFE03C0401009B +:106B30002D3800010006C82B01054821031938240F +:106B400014E0FFDA2524FFFC2402FFFC00A2182435 +:106B50000068202103E00008008010210A000A6F6D +:106B6000240900303C0C80003586098090CB007CE5 +:106B7000316A00041540FFE9240600040A000A7E79 +:106B8000000030213C0308008C63005C8F820018F9 +:106B900027BDFFE8AFBF001410620005AFB00010C2 +:106BA000000329C024A40280AF840014AF8300181E +:106BB0003C10800036030A00946500320E000A5033 +:106BC00030A43FFF8E0401003C180080370F000303 +:106BD0000082C8212402FF80032260243329007F21 +:106BE000000CF94003E94025332E00783C0D1000DD +:106BF000010D502501CF5825AE0C0028360809801C +:106C0000AE0C080CAE0B082CAE0A083091030069DC +:106C10003C06800C0126382110600006AF87003446 +:106C20008D09003C8D06006C0126382318E0007F9A +:106C3000000000003C0C8008358B00803C0A80007E +:106C4000A1600069355009808E0200383C06800042 +:106C500034C50A0090AD003C31A800201100001995 +:106C6000AF820030240E00013C19800037300A004A +:106C7000A38E001CAF8000248E0400248F85002486 +:106C800024180008AF800020AF8000283C010800D5 +:106C9000A4383ABE3C010800A4203AD20E000A549F +:106CA00000003021920F003C8FBF00148FB0001005 +:106CB000000F7142AF82002C27BD001803E00008CE +:106CC00031C2000190B90032240F0001333800FFB7 +:106CD00000182182108F003F241F0002109F0062C5 +:106CE00034C20AC03C03800034640A008C9900243A +:106CF0001720001D3466090090830030241F000512 +:106D00003062003F105F004C240500018F86002098 +:106D1000A385001CAF860028AF8600243C198000A4 +:106D200037300A008E0400248F85002424180008C0 +:106D30003C010800A4383ABE3C010800A4203AD225 +:106D40000E000A5400000000920F003C8FBF001498 +:106D50008FB00010000F7142AF82002C27BD0018C9 +:106D600003E0000831C200018C8800088C8D0024EB +:106D70008CCB00643C19800037300A00AF8B0024B4 +:106D8000A380001C8E0400248F8600208F850024A1 +:106D9000010D602324180008AF8C00283C01080076 +:106DA000A4383ABE3C010800A4203AD20E000A548E +:106DB00000000000920F003C8FBF00148FB0001045 +:106DC000000F7142AF82002C27BD001803E00008BD +:106DD00031C2000190A7003030E3003F506400282A +:106DE00034C50AC08CAA00241540002234C809000A +:106DF0008CAB00483C0C7FFF3585FFFF01651024FC +:106E00003C188000AF820020370509008F8E0020DB +:106E10008CAF006001CF682B15A0000201C02021BB +:106E20008CA400600A000AF0AF8400208D02006C80 +:106E30000A000ACB3C0680008C8900488F8600201F +:106E40003C0A7FFF3550FFFF013038243C048008A6 +:106E500024050001AF870028AC80006CA385001CCE +:106E60000A000AFEAF8600248C4400140A000AF0CF +:106E7000AF8400208D0200680A000B383C188000A7 +:106E800034C409808C8600708CB0001400D0482B6C +:106E900011200004000000008C8200700A000B38F2 +:106EA0003C1880008CA200140A000B383C188000AB +:106EB0008F85002427BDFFE0AFBF0018AFB10014DD +:106EC00014A00008AFB000103C04800034870A0012 +:106ED00090E600302402000530C3003F106200B786 +:106EE000348409008F91002000A080213C048000A0 +:106EF000348E0A008DCD00043C0608008CC63AB0E2 +:106F000031A73FFF00E6602B5580000100E03021F3 +:106F1000938F001C11E0007600D0102B349909806B +:106F20009338007C3304000210800077240300347F +:106F300000C3F82B17E000D600C3302300D0102B7D +:106F40003C010800A4233ABC1440006D0200182143 +:106F50003C0408008C843AAC0064282B54A0000147 +:106F6000006020213C05800034A90A009128003CE3 +:106F70003C010800AC243AB4310300201460000244 +:106F8000000048218CA90E188F88002C0128502B56 +:106F90001140005F000000003C0508008CA53AB4D9 +:106FA00000A96021010C582B1160005C00B0682B17 +:106FB0000109382300E028213C010800AC273AB43D +:106FC000120000032402FFFC10B0008C322A0003E0 +:106FD00000A2F8243C010800A4203AD23C01080099 +:106FE000AC3F3AB403E028218F8400241204000649 +:106FF0003C0380088C6A006C02002021AF910020C5 +:1070000025500001AC70006C8F8B00280085882310 +:10701000AF91002401652023AF84002812200002D4 +:1070200024070018240700103C0E800835C6008095 +:1070300090CD0068240C00013C010800A0273AD044 +:1070400031A700FF10EC004700000000148000187A +:10705000000028213C0B80009165010935710980F1 +:107060008E23001830A500FF0003560224A3000160 +:107070003146007F3070007F1206007E240CFF80B6 +:107080003C0F800835E90080A123004C3C08080033 +:107090008D083ACC240E00023C010800A02E3B11C2 +:1070A000350D00083C010800AC2D3ACC2405001039 +:1070B0003C1F800037E40A009099003C33380020E0 +:1070C0001300000500A02021240200013C0108005B +:1070D000AC223AB434A400018FBF00188FB1001461 +:1070E0008FB000100080102103E0000827BD0020B1 +:1070F0003C010800A4203ABC1040FF950200182172 +:107100000A000B8B00C018210A000B8324030030F7 +:107110003C0508008CA53AB400B0682B11A0FFA86C +:10712000000000003C04080094843ABC00857821EB +:1071300001E7702B11C000072CA200043C1F600067 +:107140008FF954043338003F1700FFE32404004252 +:107150002CA200041040FF9A240400420A000BEE07 +:107160008FBF00181528FFB9000000008CC200185E +:107170003C188000241900020058F825ACDF0018E4 +:1071800037040A00A0D900689089003C240F00044D +:1071900000A01021312800203C010800A02F3B1145 +:1071A0001100000224050010240200013C01080027 +:1071B000AC223AAC0A000BE43C1F80008F88002808 +:1071C0008C8900600109282B14A00002010088218D +:1071D0008C9100603C0B80008D640E18240A000125 +:1071E0000220282102203021A38A001C0E000A540C +:1071F000022080210A000B72AF82002C000A1823A3 +:1072000012200007306400033C0D800035A7098080 +:1072100090EC007C318B000415600019248E000472 +:107220003C010800A4243AD23C18080097183AD22E +:107230000305202100C4782B11E0FF6C8F8400240B +:107240002CA6000514C0FFA42404004230B900039A +:107250001720000200B9182324A3FFFC3C010800FA +:10726000AC233AB43C010800A4203AD20A000BB186 +:107270000060282100AC38240A000BD700EC182647 +:107280003C010800A42E3AD20A000C410000000084 +:107290003C010800AC203AB40A000BED2404004283 +:1072A0008F8300283C0B8000356A0A0014600006BA +:1072B00000001021914600302405000530C400FF75 +:1072C000108500030000000003E00008000000003B +:1072D00091490048312800FF000839C214E0FFFA44 +:1072E0003C0480083C06080094C63ABC3C030800F5 +:1072F0008C633AD43C0508008CA53AB43C180800CD +:1073000097183AD20066C8218C8E00040325782194 +:1073100001F8682101AE60231980001D0000000003 +:107320009158004C8F8D0034956E0E10330F00FF76 +:107330008DA9000401CF30238DAA000030CFFFFFBC +:10734000000F6100012C2821000038210147202175 +:1073500000AC182B0083C821ADA50004ADB9000016 +:1073600091B8000A01F87021A1AE000A956C0E12C6 +:107370008F8A0034A54C0008954900382528000163 +:10738000A54800389147000D34EB0008A14B000DD3 +:1073900003E000080000000027BDFFD8AFB00018D0 +:1073A000938F001C8FB000143C087FFF8F87002450 +:1073B0003C0C80003518FFFFAFBF0020AFB1001CB0 +:1073C00035990A0002181824932A003C000F5FC068 +:1073D0003C02BFFF2CF000013449FFFF006BF82591 +:1073E0003C0808008D083AD48F9900303C180800FA +:1073F00097183ACA03E9582400107F803C07EFFF32 +:107400003C05F0FF016F18253C1180003149002038 +:1074100034E2FFFF34ADFFFF362E098027A50010B0 +:107420002406000201194023270A000200621824E2 +:107430000080802115200002000058218D8B0E1C39 +:10744000A7AA00120500003A2407000030EF00FF51 +:10745000000F3F00006740253C028008AFA80014E1 +:10746000344B0080916A00683C0F080091EF3AD1DC +:107470003C09DFFF353FFFFF000A602B3C0208009C +:1074800094423AC4A3AF0011011FC024000CCF40A6 +:10749000031918258FA70010AFA300143C1F080084 +:1074A00093FF3AD3A7A200168FA8001400ED48243A +:1074B0003C0B01003C0A0FFF012BC82533F80003E9 +:1074C000354CFFFF010D78243C027000032C38245A +:1074D00000181E0000E2482501E35825AFAB001458 +:1074E000AFA9001091DF007CA3BF00150E00006360 +:1074F00000000000362D0A0091A6003C30C4002098 +:1075000010800006260200083C11080096313AC09F +:10751000262EFFFF3C010800A42E3AC08FBF00209A +:107520008FB1001C8FB0001803E0000827BD0028B1 +:107530008F8A002C016A602B5580FFC4240700014C +:107540000A000CCB30EF00FF9383001C3C0280004C +:1075500027BDFFD834480A0000805021AFBF00206B +:1075600034460AC0010028211060000E344409800E +:1075700091070030240B00058F89002030EC003F7C +:10758000118B000B00003821AFA900103C0B8008C4 +:107590008D69006CAFAA00180E00012BAFA9001472 +:1075A000A380001C8FBF002003E0000827BD002837 +:1075B0008D1F00483C1808008F183AB48F99002896 +:1075C0003C027FFF8D0800443443FFFFAFA9001049 +:1075D0003C0B80088D69006C03E37024031978214B +:1075E00001CF682301A83821AFAA00180E00012B93 +:1075F000AFA900140A000D20A380001C3C058000E8 +:1076000034A60A0090C7003C3C06080094C63AD253 +:107610003C0208008C423ACC30E3002000062400F3 +:107620001060001E004438253C08800835050080A5 +:1076300090A30068000030212408000100002021F0 +:10764000240300013C0580008CAC01780580FFFE1E +:1076500000000000ACA80148A4A40144A4A3014672 +:107660003C0308008C633AD43C188008370F008034 +:10767000ACA3014C3C19080093393AD13C0D1000E1 +:10768000A0B90152ACA70154A4A6015891EE004C38 +:10769000A0AE016D03E00008ACAD01788CA80E1C13 +:1076A0003C0B08008D6B3AB494AA0E1694A90E14E4 +:1076B000016630213143FFFF0A000D483124FFFFEE +:1076C0003C04800034830A009065003C30A2002016 +:1076D0001040001C000000000000302100002021AC +:1076E000000018213C0580008CA901780520FFFED0 +:1076F00000000000ACA601483C0E08008DCE3AD434 +:10770000240DFF91240C00403C0B8008A4A30144ED +:10771000356A0080A4A40146ACAE014CA0AD015274 +:10772000ACAC0154A4A0015890A301099144004CB1 +:1077300090A601093C041000A0A6016D03E000081A +:10774000ACA401788C860E1894880E1294870E10C3 +:107750003104FFFF0A000D7030E3FFFF3C0480009E +:1077600034830A009065003C30A2002010400026BF +:1077700027BDFFF82409000100003821240800017A +:107780003C0680008CC401780480FFFE00000000ED +:1077900090CA01093C04080090843B113C1880FF0A +:1077A000A3AA00038FA300003085007F370FFFFFDF +:1077B00000661025AFA2000090D9010AA3A0000224 +:1077C00000056E00A3B900018FAE0000240A30004E +:1077D00027BD000801CF6024018D5825ACCB014C9A +:1077E000ACCA0154A4C00158ACC90148A4C70144A3 +:1077F0002409FF80A4C801463C081000A0C901521A +:1078000003E00008ACC801788C890E1894870E122A +:1078100094860E1030E8FFFF0A000D9730C7FFFF77 +:1078200027BDFFE8AFB000103C108000AFBF0014D0 +:1078300036180A00970F00320E000A5031E43FFF5D +:107840008E0E0100240DFF803C04200001C258214F +:10785000016D6024000C4940316A007F012A4025F7 +:10786000010438253C048008AE07083034860080C7 +:1078700090C500682403000230A200FF10430004FA +:107880008F9F00208F990024AC9F0068AC99006402 +:107890008FBF00148FB0001003E0000827BD001850 +:1078A0003C0A0800254A359C3C0908002529363841 +:1078B0003C08080025082A603C07080024E736FC3D +:1078C0003C06080024C634243C05080024A5317C6D +:1078D0003C04080024842D8C3C030800246334D825 +:1078E0003C020800244232743C010800AC2A3A9061 +:1078F0003C010800AC293A8C3C010800AC283A88CD +:107900003C010800AC273A943C010800AC263AA49C +:107910003C010800AC253A9C3C010800AC243A9894 +:107920003C010800AC233AA83C010800AC223AA074 +:0879300003E000080000000064 +:087938008000094080000900F5 +:10794000800801008008008080080000800E000090 +:10795000800800808008000080000A8080000A0003 +:0879600080000980800009008D +:00000001FF +/* + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ diff --git a/firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex b/firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex new file mode 100644 index 000000000000..fe59d16b594e --- /dev/null +++ b/firmware/bnx2/bnx2-rv2p-09-5.0.0.j10.fw.ihex @@ -0,0 +1,462 @@ +:100000000000000000000E08000000580000000979 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000DD800000E60000000050000000068 +:1000400000000000000000000000000000000000B0 +:080050000000000000000000A8 +:0800580000000010B180000659 +:100060000000001F05030300000000080500FFFF5B +:10007000000000180002000000000008050000FF5A +:10008000000000180002000000000008AC000001A1 +:1000900000000000050000000000000C2F8000019F +:1000A000000000002B000000000000002B8000007A +:1000B0000000001091E0000200000008AC00000108 +:1000C00000000010203F006B00000010213F0003E3 +:1000D0000000001020BF003A000000188000FFFD63 +:1000E00000000010B1B8B0150000000B2FDF0002B7 +:1000F0000000000003D80000000000002C380000C1 +:10010000000000082C800000000000082D00000006 +:100110000000001091D400000000000806005555B2 +:10012000000000188000007C000000082D80011CE9 +:1001300000000008020000010000001091DE000035 +:100140000000000F42E0001C0000001091840A161D +:1001500000000018800000830000000C29800002CD +:100160000000000C1F800002000000002ADF0000D9 +:10017000000000082A00000F000000000500000039 +:10018000000000188000FFE60000000802000001E7 +:100190000000000F42E0001C0000001091840A18CB +:1001A000000000082C800006000000082D0000065A +:1001B0000000001091D40000000000082D8001060E +:1001C0000000001880000072000000188000FFF19D +:1001D00000000008B1000001000000082C80010CA4 +:1001E000000000082D000008000000082D8000011C +:1001F000000000188000006C0000000B2FDF0002E0 +:100200000000000C1F800002000000002C0700000E +:100210000000001091DE00000000000805005555A8 +:10022000000000188000FFD20000000B2FDF00024A +:100230000000000C1F800000000000002C070000E0 +:100240000000001091DE0000000000080500555578 +:10025000000000188000FFCC0000000C1F8000028E +:100260000000000805005555000000188000FFC977 +:100270000000000C298000020000000C1F8000021A +:10028000000000002ADF0000000000082A0000052E +:100290000000000805005555000000188000FFC34D +:1002A000000000080224004A0000001800040000BA +:1002B000000000188000001C000000188000001ED4 +:1002C000000000188000006500000018800000BCDD +:1002D00000000018800000BB000000188000000033 +:1002E00000000018800000000000001880000000DE +:1002F00000000018800000000000001880000000CE +:1003000000000018800000000000001880000000BD +:1003100000000018800000000000001880000107A5 +:10032000000000188000000000000018800000009D +:100330000000001880000015000000188000001B5D +:10034000000000188000000000000018800000D2AB +:10035000000000188000002F000000188000010736 +:10036000000000188000013200000018800000FD2D +:100370000000001880000156000000188000004EA8 +:100380000000001880000000000000188000008FAE +:100390000000000C1F8000010000000005000000AC +:1003A000000000188000FFA20000001091D400009F +:1003B0000000000C298000010000000C1F800001DB +:1003C000000000082A0000020000000005000000F4 +:1003D000000000188000FF9C0000001091D4000075 +:1003E0000000000C298000010000000C1F800001AB +:1003F0000000000029420000000000082A0000025E +:100400000000000005000000000000188000FF95BB +:10041000000000188000FF9400000010B1BCB00A7A +:100420000000000B2FDF00020000000003D80000D6 +:10043000000000002C3C00000000001091D40000DF +:100440000000000806005555000000188000001745 +:1004500000000018800000CB000000102C6201BAE0 +:100460000000001880000006000000082C80010D2C +:10047000000000082D0000090000001091D40000C9 +:10048000000000082D8001070000001880000024F3 +:100490000000000C298000000000000C1F800000FC +:1004A0000000001091DE0000000000002ADF0000C4 +:1004B000000000082A00000600000008050055554D +:1004C000000000188000FF7E0000001091D40000A2 +:1004D0000000000C298000010000000C1F800001BA +:1004E000000000082A00000B0000000005000000CA +:1004F000000000188000FF780000001800020000D3 +:10050000000000000682000000000010B18A000810 +:1005100000000010B18C14070000000B050AFFFF5B +:1005200000000010B18A000300000000860A1800D5 +:1005300000000010918C0000000000082A0000015B +:100540000000001091D4000000000018000D000011 +:1005500000000000050200000000001091DE000015 +:1005600000000018000A00000000000006820000E1 +:100570000000001091DE000000000010BEE1000548 +:10058000000000188000FF5F0000000105611400FA +:1005900000000010918A000200000008B0E1000194 +:1005A00000000018000D000000000000068200009E +:1005B0000000001091DE000000000010BEE2000507 +:1005C000000000188000FF570000000105621400C1 +:1005D00000000010918A000200000008B1620001D2 +:1005E00000000018000D000000000010B1A0B013C2 +:1005F0000000000B2FDF0002000000002C20000094 +:10060000000000082C800000000000082D00000001 +:100610000000001091D400000000000806005555AD +:10062000000000188000FFDC000000082D80011C85 +:1006300000000010001F0000000000188000FFE60E +:100640000000000F476000080000000F060E0001C8 +:10065000000000000F580000000000000A640000C5 +:10066000000000000AE50000000000090B66FFFF23 +:10067000000000000D610000000000188000001361 +:100680000000000F476000080000000B2FDF000291 +:10069000000000082C800000000000082D00000071 +:1006A0000000001091D40000000000082D80011C03 +:1006B0000000000F060E000100000010001F0000E7 +:1006C000000000000F580000000000188000FFD458 +:1006D000000000000A640000000000000AE50000BD +:1006E000000000090B66FFFF000000000D61000024 +:1006F00000000000026200000000000B2FDF00027B +:10070000000000003104000000000000309A0000EA +:10071000000000090560000F00000010B18A000B06 +:100720000000000005634C0000000008050A0012EC +:1007300000000010B9621403000000000300000074 +:100740000000001880000006000000188000FF2450 +:1007500000000010B60614040000000803060001A3 +:10076000000000082A000001000000188000FF2996 +:10077000000000000C961800000000090C99FFFF13 +:1007800000000004CC99340000000010B196320241 +:10079000000000080F8000000000000C298000010C +:1007A0000000000C295200010000000C295200003A +:1007B000000000080200000E000000080280001A7D +:1007C00000000010B1C40A0200000008020000038B +:1007D00000000008220000010000000C1F80000142 +:1007E000000000002ADF0000000000002A000800CE +:1007F0000000000805005555000000188000FF1794 +:100800000000000B2FDF00020000001091D4000058 +:10081000000000082A000001000000002C20000059 +:100820000000001091D40000000000082C8000009F +:10083000000000082D000000000000082D80011CB1 +:10084000000000188000FFA2000000082C800006B5 +:10085000000000082D0000060000000030800000AD +:100860000000000031000000000000082D8000069C +:100870000000000C298000010000000C1F80000116 +:100880000000001091DE0000000000002ADF0000E0 +:10089000000000082A000010000000000500000011 +:1008A000000000188000FF020000001091A0B009B5 +:1008B000000000082C80010D000000082D00000938 +:1008C0000000001091D40000000000082D800107F6 +:1008D000000000188000FF9B00000018800000103E +:1008E00000000008AC000001000000188000000BB0 +:1008F000000000000380B0000000000B2FDF0002AA +:10090000000000002C0040000000001091D4000006 +:100910000000000806005555000000188000FF7D0B +:100920000000001880000031000000188000000660 +:100930000000000B2FDF0002000000002C000E0062 +:10094000000000082A0000070000000805005555B7 +:10095000000000188000FEEC00000000068200008D +:100960000000000C298000010000000C1F80000125 +:10097000000000100CE70007000000090562FFFFFF +:1009800000000010BA6C1405000000002ADF00000F +:100990000000000021000000000000082A000005FF +:1009A0000000001091D40000000000082C80010C11 +:1009B000000000082D0000080000000C3162001843 +:1009C000000000082D800001000000188000FF7169 +:1009D00000000018000D000000000010B1A0B00ED3 +:1009E0000000000B2FDF00020000000003D8000011 +:1009F000000000002C2000000000001091D4000036 +:100A00000000001880000015000000102C62000299 +:100A1000000000188000000C0000000B2FDF000217 +:100A2000000000002C0700000000000C1F800001E7 +:100A30000000001091DE0000000000080500FFFF2C +:100A4000000000188000FECE000000082C80010D80 +:100A5000000000082D0000090000001091D40000E3 +:100A6000000000082D800107000000188000FF68CA +:100A70000000000C298000010000000C1F80000114 +:100A80000000001091DE0000000000002ADF0000DE +:100A9000000000082A00000A000000000500000015 +:100AA000000000188000FEC2000000000682000066 +:100AB000000000082C80010C000000082D00000838 +:100AC000000000082D80013400000000000000003C +:100AD00000000010205F0000000000082C80014092 +:100AE000000000082D00003C000000082D800124BB +:100AF00000000000000000000000001091DE000077 +:100B0000000000082C800080000000082D0000007C +:100B1000000000082D80010500000010BEE2000565 +:100B2000000000188000FEAB000000010562140008 +:100B300000000010918A000200000008B16200016C +:100B40000000001091DE000000000018000D000001 +:100B50000000001091D40000000000080600AAAABE +:100B6000000000188000FF340000000C2980000104 +:100B70000000000C1F800001000000082A0000098E +:100B8000000000080500AAAA000000188000FEA5C9 +:100B90000000001091D40000000000080600555528 +:100BA000000000188000FF2C0000001091A03C0203 +:100BB00000000010B1E662070000000B2FDF00020A +:100BC000000000002C310000000000092CB1007F63 +:100BD000000000082CD90000000000082D000000D3 +:100BE000000000082D80010D00000010B1A80006D3 +:100BF00000000010205F0000000000002C2000001A +:100C0000000000002CA70000000000082D000010CC +:100C1000000000082D800108000000188000FF2758 +:100C200000000010B1A6001000000010001F00001E +:100C30000000000F0F300007000000000A600000F5 +:100C4000000000000AE100000000000F4B620008F5 +:100C5000000000090B1600FF000000000D620000FC +:100C6000000000090D1A00FF00000010073000030B +:100C70000000000C0D1A00080000000C0B16000804 +:100C80000000000F4CE30018000000000C992C003D +:100C900000000004CC993400000000080F80000020 +:100CA0000000000C2980000100000000333100002A +:100CB0000000000822000016000000002ADF0000EB +:100CC000000000082A00000C00000010009F000037 +:100CD000000000000F2000000000000C1F80000139 +:100CE0000000000805005555000000188000FE793E +:100CF0000000001091D40000000000080600AAAA1D +:100D0000000000188000FF000000000F47220008CC +:100D100000000009070E000F00000008070E000881 +:100D200000000008028000010000000702851C008E +:100D300000000008828500010000000002854C00D0 +:100D40000000000742851C0000000003C3AA5200F7 +:100D50000000000003B10E00000000074B071C005C +:100D60000000000F0F3000070000000F0A9600037C +:100D7000000000000A955C00000000004A005A00D4 +:100D8000000000000C960A00000000090C99FFFF0B +:100D9000000000080D00FFFF00000010B1963202B5 +:100DA000000000080F80000500000010B1A8000836 +:100DB00000000010205F00000000000B2FDF000289 +:100DC000000000002C200000000000002CA7000004 +:100DD000000000082D000010000000082D80010810 +:100DE000000000188000FEEE0000000C29800001C9 +:100DF00000000010001F00000000000C1F80000118 +:100E0000000000002ADF0000000000082A00000D9A +:100E1000000000080500AAAA000000188000FE5388 +:100E20000000001091D40000000000080600555595 +:100E3000000000188000FEDA0000000C298000018C +:100E40000000000C1F800001000000082A000007BD +:100E50000000000805005555000000188000FE4BFA +:100E600000000010B18000040000001F0503030013 +:100E700000000008050000FF00000018000200004C +:100E8000000000002A00000000000010B1D40000A3 +:100E90000000001091DE0000000000102053000050 +:100EA00000000010001F0000000000002F80AA00BA +:100EB0000000000C29800001000000080254000E10 +:100EC000000000002C400000000000092952003FF3 +:100ED000000000180004000000000018800000104E +:100EE0000000001880000011000000188000003988 +:100EF00000000018800000FD00000018800000FCC9 +:100F000000000018800000FB00000018800000FBBB +:100F1000000000188000000000000018800001138D +:100F200000000018800000F7000000188000000B8F +:100F30000000001880000117000000188000016503 +:100F4000000000188000006300000018800000CE40 +:100F500000000018800000DE000000002A000000F1 +:100F6000000000188000FFE5000000002A000000DB +:100F70000000000C29800000000000188000FFE243 +:100F8000000000002A000000000000188000FFE0C0 +:100F90000000001800020000000000000502000030 +:100FA000000000109196342100000010205F000026 +:100FB000000000002C1E0000000000082C8000062D +:100FC000000000082D000006000000082D8001022E +:100FD00000000000000000000000001091DE000092 +:100FE000000000000D61000000000018000A000071 +:100FF0000000000005020000000000109196341669 +:1010000000000010205F00000000000009D8000070 +:10101000000000002C1E0000000000082C80010EC3 +:10102000000000082D00000A000000082D800102C9 +:1010300000000000000000000000001091DE000031 +:10104000000000000D620000000000002C130000F2 +:1010500000000018000A0000000000000502000067 +:10106000000000109196340900000010205F00007D +:10107000000000002C1E0000000000082C8000066C +:10108000000000082D00006A000000082D80010209 +:1010900000000000000000000000001091DE0000D1 +:1010A000000000000D7A000000000018000A000097 +:1010B000000000002A000000000000000D61000098 +:1010C000000000000362000000000010234200C185 +:1010D0000000000002638C000000000026460000B3 +:1010E000000000080204001200000010B9060827E2 +:1010F000000000000F580000000000000A6400001B +:10110000000000000AE50000000000090B66FFFF78 +:10111000000000000C000000000000000B80000038 +:10112000000000080CC60012000000188000FFCE6E +:10113000000000080F800003000000000000000015 +:1011400000000010009F000000000008271100129E +:10115000000000006690000000000008A31B0012C1 +:1011600000000010B198000300000010001F0000F4 +:10117000000000080F8000040000000822000003A7 +:10118000000000082C80000C000000082D00000C5E +:1011900000000010009F00000000000025960000E5 +:1011A0000000000C2980000000000000066600001E +:1011B0000000000086611800000000090260000FB6 +:1011C0000000000F0204000200000010B60C080529 +:1011D0000000000C1FBF0000000000102866000384 +:1011E00000000008078F00010000000C33660010AB +:1011F00000000000321400000000000032950000E2 +:101200000000000573662C000000000031E32E0092 +:10121000000000082D800010000000188000FF8EE4 +:1012200000000000230000000000000925E6FFFF89 +:10123000000000082200000B0000000C69520000B2 +:101240000000000C298000000000001028660075D6 +:10125000000000188000FF87000000002A00000046 +:10126000000000082C800040000000082D00002035 +:10127000000000082D80011C00000000000000009C +:101280000000001091DE00000000000F42EA001094 +:1012900000000010004F000400000010B74692004C +:1012A000000000080249001200000010B5840A0086 +:1012B000000000000D61000000000010BA66345705 +:1012C000000000088305001200000010004F00021B +:1012D00000000000034900000000000183068C00AC +:1012E0000000000083C60C0000000010B187001150 +:1012F000000000000B6E000000000010BEE90005B9 +:10130000000000188000FF6E000000010569140055 +:1013100000000010918A000200000008B4E90001FA +:1013200000000010B1E92C4A0000000086692C0082 +:1013300000000000020000000000000902EAFFFFB8 +:1013400000000010000C00020000000002040A006F +:101350000000000F460C00010000000F0285000194 +:1013600000000010918C01FC00000010B7040E4139 +:10137000000000000F400000000000000D610000B0 +:10138000000000000A640000000000000AE5000000 +:10139000000000090B66FFFF000000000C000000C9 +:1013A000000000000B800000000000080C86001206 +:1013B000000000080F8000030000000C295200000C +:1013C00000000010009F000000000008271100121C +:1013D00000000000669000000000000026460000AB +:1013E000000000002306000000000010B198000576 +:1013F00000000010001F0000000000080F80000423 +:10140000000000000000000000000010001F0000AD +:1014100000000000321400000000000032950000BF +:101420000000000031E32E000000000573662C0070 +:10143000000000002596000000000010B187001693 +:101440000000000C298000000000000F0F6B000757 +:10145000000000000D690000000000000A6C0000A0 +:10146000000000000AED0000000000000B6E00000C +:10147000000000000B800000000000000C8700004E +:10148000000000080F80000300000010205300003F +:101490000000000C6952000100000010001F000055 +:1014A0000000000022C58C0000000000231B00008B +:1014B000000000002711000000000000269000003E +:1014C00000000010B8170E030000000C2980000077 +:1014D000000000188000FFF600000010B198000224 +:1014E000000000080F800004000000082200001A1D +:1014F000000000082C80000C000000082D00000CEB +:10150000000000082D80001000000010001F0000E7 +:10151000000000000D6E000000000003E7CF340063 +:101520000000000C298000000000001091DE000087 +:1015300000000010B1870007000000003614000012 +:101540000000000036950000000000003716000083 +:10155000000000082C800050000000082D00003022 +:10156000000000082D80000C000000188000FF24FF +:1015700000000000264600000000000023000000DC +:101580000000000925E6FFFF000000000B6E0000D0 +:1015900000000003E7CF2C00000000082200001B21 +:1015A0000000000C695200000000000C29800000BF +:1015B000000000188000FF1B000000002A0000004F +:1015C000000000100866000500000000066600002C +:1015D000000000008661180000000009026000F0B1 +:1015E00000000010B60C0802000000188000FF1474 +:1015F000000000000682000000000010B18F000013 +:1016000000000008878F00010000000C73660010C6 +:10161000000000082C800018000000082D000018B1 +:10162000000000082D8000020000000C5FBF0000D9 +:101630000000001091DE000000000018000D000006 +:10164000000000002A00000000000010286601F5DC +:10165000000000082C800003000000082D0000039B +:10166000000000093060FFF0000000082D8000013C +:101670000000000C298000000000001091DE000036 +:10168000000000082C80001A000000082D00001A3D +:101690000000000573660000000000082D800002B5 +:1016A00000000000318000000000001091DE00000A +:1016B000000000082C80000C000000082D00000C29 +:1016C000000000082D800004000000188000FEF8D3 +:1016D0000000001800020000000000188000FEF664 +:1016E000000000002A00000000000010001F0000A1 +:1016F000000000000F008000000000080F800007BD +:10170000000000188000001A00000000280A0000F5 +:10171000000000000502000000000008220000098F +:1017200000000000290000000000000F65680010A4 +:1017300000000003F66C940000000010B972A004D1 +:101740000000000C73E700190000000C21420004A7 +:10175000000000003CF800000000000C29800000A0 +:1017600000000010205300000000000822000008C4 +:101770000000000C6142000400000018000A000094 +:1017800000000000050200000000000C61420000A3 +:1017900000000010014200030000000C33E7001DB0 +:1017A0000000000C6142000200000018000A000066 +:1017B000000000002A00000000000010001F0000D0 +:1017C0000000000F0F470007000000080F8000080E +:1017D0000000000C2980000000000010009F0000A5 +:1017E000000000188000FED500000000335100000A +:1017F000000000002A00000000000010B1C6002315 +:101800000000000F0F500007000000000A600000F9 +:10181000000000000AE100000000000F4B62000819 +:10182000000000090B1600FF0000000F4C620010C2 +:10183000000000000D620000000000090D1A00FF0A +:1018400000000010075000030000000C0D1A0008F3 +:101850000000000C0B160008000000000CC6000081 +:10186000000000000B80000000000000069800004F +:10187000000000080F8000030000001006C20004F2 +:101880000000000C290000020000001026420002A7 +:101890000000000C29520003000000082200000193 +:1018A00000000010009F000000000000231B00004B +:1018B0000000000027111A000000000066900000E0 +:1018C0000000000C2952000000000010B1973209FE +:1018D0000000000C298000000000000006980000B5 +:1018E00000000010205300000000000C29520003EB +:1018F0000000000022C58C0000000010001F000046 +:10190000000000080F800003000000188000FFF3B3 +:1019100000000010B1C8001300000010B1C60003A1 +:101920000000000C2980000000000010205300007F +:101930000000000C295200000000000C2952000396 +:101940000000001006C200020000000C2952000234 +:101950000000000022C58C00000000002765000088 +:101960000000000026E4000000000008220000162D +:1019700000000010B1C60003000000002348000072 +:1019800000000010B18000050000000023480000A6 +:101990000000000C298000000000000F0F5000071D +:1019A000000000188000001200000008220000164D +:1019B0000000000C2980000000000000301400002E +:1019C00000000000309500000000001007500003E8 +:1019D000000000090B1600FF000000090D1A00FFAF +:1019E0000000000F311600080000000031623400D2 +:1019F00000000003F162300000000010205F0000D2 +:101A0000000000002C510000000000092CD1007FD4 +:101A1000000000082CD90000000000082D00000084 +:101A2000000000082D80000C0000000000000000F5 +:101A30000000001091DE00000000001005C200044C +:101A4000000000080F8000070000000033000000C5 +:101A500000000010009F0000000000188000FE86BB +:101A6000000000002A0000000000000F0F500007D7 +:101A700000000010B1C6002D0000000F4742000812 +:101A800000000009070E000F00000008070E000804 +:101A900000000010001F0000000000080900000105 +:101AA0000000000709121C0000000003CBCA9200CE +:101AB000000000000B97A2000000000742171C0066 +:101AC000000000000B0400000000000F0A84000367 +:101AD000000000000A959C00000000004A009A00E7 +:101AE0000000000882120001000000010C1708002D +:101AF000000000000C978C0000000000021800009D +:101B0000000000080D00FFFF000000080F80000625 +:101B10000000000C290000000000001006C20004B4 +:101B20000000000C295200020000001026420002B2 +:101B30000000000C295200030000000822000001F0 +:101B400000000010009F000000000010B197320C50 +:101B500000000000231B0000000000002711080007 +:101B600000000000669000000000000C29800000CA +:101B700000000000021800000000001020530000C8 +:101B80000000000C295200030000000022C53600AE +:101B900000000010001F0000000000080F80000679 +:101BA000000000188000FFF400000000231B00006C +:101BB00000000000271108000000000066900000EF +:101BC00000000010B1C8000B0000000C29800000CC +:101BD00000000010205300000000000C29520000FB +:101BE0000000000C295200030000001006C2000291 +:101BF0000000000C295200020000000022C58C00E9 +:101C000000000000276500000000000026E400003E +:101C10000000000023480000000000082200001718 +:101C20000000000C2980000000000010001F0000D0 +:081C3000000000188000FE4BCB +:00000001FF +/* + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ diff --git a/firmware/bnx2/bnx2-rv2p-09-5.0.0.j3.fw.ihex b/firmware/bnx2/bnx2-rv2p-09-5.0.0.j3.fw.ihex deleted file mode 100644 index 69f5e952cbf4..000000000000 --- a/firmware/bnx2/bnx2-rv2p-09-5.0.0.j3.fw.ihex +++ /dev/null @@ -1,462 +0,0 @@ -:100000000000000000000E00000000580000000981 -:1000100000000000000000000000000000000000E0 -:1000200000000000000000000000000000000000D0 -:1000300000000DD800000E58000000050000000070 -:1000400000000000000000000000000000000000B0 -:080050000000000000000000A8 -:0800580000000010B180000659 -:100060000000001F05030300000000080500FFFF5B -:10007000000000180002000000000008050000FF5A -:10008000000000180002000000000008AC000001A1 -:1000900000000000050000000000000C2F8000019F -:1000A000000000002B000000000000002B8000007A -:1000B0000000001091E0000200000008AC00000108 -:1000C00000000010203F006B00000010213F0003E3 -:1000D0000000001020BF003A000000188000FFFD63 -:1000E00000000010B1B8B0150000000B2FDF0002B7 -:1000F0000000000003D80000000000002C380000C1 -:10010000000000082C800000000000082D00000006 -:100110000000001091D400000000000806005555B2 -:10012000000000188000007C000000082D80011CE9 -:1001300000000008020000010000001091DE000035 -:100140000000000F42E0001C0000001091840A161D -:1001500000000018800000830000000C29800002CD -:100160000000000C1F800002000000002ADF0000D9 -:10017000000000082A00000F000000000500000039 -:10018000000000188000FFE60000000802000001E7 -:100190000000000F42E0001C0000001091840A18CB -:1001A000000000082C800006000000082D0000065A -:1001B0000000001091D40000000000082D8001060E -:1001C0000000001880000072000000188000FFF19D -:1001D00000000008B1000001000000082C80010CA4 -:1001E000000000082D000008000000082D8000011C -:1001F000000000188000006C0000000B2FDF0002E0 -:100200000000000C1F800002000000002C0700000E -:100210000000001091DE00000000000805005555A8 -:10022000000000188000FFD20000000B2FDF00024A -:100230000000000C1F800000000000002C070000E0 -:100240000000001091DE0000000000080500555578 -:10025000000000188000FFCC0000000C1F8000028E -:100260000000000805005555000000188000FFC977 -:100270000000000C298000020000000C1F8000021A -:10028000000000002ADF0000000000082A0000052E -:100290000000000805005555000000188000FFC34D -:1002A000000000080224004A0000001800040000BA -:1002B000000000188000001C000000188000001ED4 -:1002C000000000188000006500000018800000BBDE -:1002D00000000018800000BA000000188000000034 -:1002E00000000018800000000000001880000000DE -:1002F00000000018800000000000001880000000CE -:1003000000000018800000000000001880000000BD -:1003100000000018800000000000001880000106A6 -:10032000000000188000000000000018800000009D -:100330000000001880000015000000188000001B5D -:10034000000000188000000000000018800000D1AC -:10035000000000188000002F000000188000010637 -:10036000000000188000013100000018800000FC2F -:100370000000001880000155000000188000004EA9 -:100380000000001880000000000000188000008EAF -:100390000000000C1F8000010000000005000000AC -:1003A000000000188000FFA20000001091D400009F -:1003B0000000000C298000010000000C1F800001DB -:1003C000000000082A0000020000000005000000F4 -:1003D000000000188000FF9C0000001091D4000075 -:1003E0000000000C298000010000000C1F800001AB -:1003F0000000000029420000000000082A0000025E -:100400000000000005000000000000188000FF95BB -:10041000000000188000FF9400000010B1BCB00A7A -:100420000000000B2FDF00020000000003D80000D6 -:10043000000000002C3C00000000001091D40000DF -:100440000000000806005555000000188000001745 -:1004500000000018800000CA000000102C6201BAE1 -:100460000000001880000006000000082C80010D2C -:10047000000000082D0000090000001091D40000C9 -:10048000000000082D8001070000001880000024F3 -:100490000000000C298000000000000C1F800000FC -:1004A0000000001091DE0000000000002ADF0000C4 -:1004B000000000082A00000600000008050055554D -:1004C000000000188000FF7E0000001091D40000A2 -:1004D0000000000C298000010000000C1F800001BA -:1004E000000000082A00000B0000000005000000CA -:1004F000000000188000FF780000001800020000D3 -:10050000000000000682000000000010B18A000810 -:1005100000000010B18C14070000000B050AFFFF5B -:1005200000000010B18A000300000000860A1800D5 -:1005300000000010918C0000000000082A0000015B -:100540000000001091D4000000000018000D000011 -:1005500000000000050200000000001091DE000015 -:1005600000000018000A00000000000006820000E1 -:100570000000001091DE000000000010BEE1000548 -:10058000000000188000FF5F0000000105611400FA -:1005900000000010918A000200000008B0E1000194 -:1005A00000000018000D000000000000068200009E -:1005B0000000001091DE000000000010BEE2000507 -:1005C000000000188000FF570000000105621400C1 -:1005D00000000010918A000200000008B1620001D2 -:1005E00000000018000D000000000010B1A0B013C2 -:1005F0000000000B2FDF0002000000002C20000094 -:10060000000000082C800000000000082D00000001 -:100610000000001091D400000000000806005555AD -:10062000000000188000FFDC000000082D80011C85 -:1006300000000010001F0000000000188000FFE60E -:100640000000000F476000080000000F060E0001C8 -:10065000000000000F580000000000000A640000C5 -:10066000000000000AE50000000000090B66FFFF23 -:10067000000000000D610000000000188000001361 -:100680000000000F476000080000000B2FDF000291 -:10069000000000082C800000000000082D00000071 -:1006A0000000001091D40000000000082D80011C03 -:1006B0000000000F060E000100000010001F0000E7 -:1006C000000000000F580000000000188000FFD458 -:1006D000000000000A640000000000000AE50000BD -:1006E000000000090B66FFFF000000000D61000024 -:1006F00000000000026200000000000B2FDF00027B -:10070000000000003104000000000000309A0000EA -:10071000000000090560000F00000010B18A000A07 -:100720000000000005634C0000000008050A0012EC -:1007300000000010B9621403000000000300000074 -:100740000000001880000005000000188000FF2451 -:1007500000000010B60614030000000803060001A4 -:10076000000000188000FF2A000000000C9618000E -:10077000000000090C99FFFF00000004CC99340030 -:1007800000000010B1963202000000080F80000047 -:100790000000000C298000010000000C295200011B -:1007A0000000000C29520000000000080200000EAA -:1007B000000000080280001A00000010B1C40A0204 -:1007C00000000008020000030000000822000001F1 -:1007D0000000000C1F800001000000002ADF000064 -:1007E000000000002A000800000000080500555520 -:1007F000000000188000FF180000000B2FDF00022F -:100800000000001091D40000000000082A00000140 -:10081000000000002C2000000000001091D4000017 -:10082000000000082C800000000000082D000000DF -:10083000000000082D80011C000000188000FFA3AC -:10084000000000082C800006000000082D000006B3 -:1008500000000000308000000000000031000000B7 -:10086000000000082D8000060000000C2980000117 -:100870000000000C1F8000010000001091DE00004D -:10088000000000002ADF0000000000082A0000101D -:100890000000000005000000000000188000FF03B9 -:1008A0000000001091A0B009000000082C80010D8C -:1008B000000000082D0000090000001091D4000085 -:1008C000000000082D800107000000188000FF9C38 -:1008D000000000188000001000000008AC000001BB -:1008E000000000188000000B000000000380B00032 -:1008F0000000000B2FDF0002000000002C00400071 -:100900000000001091D400000000000806005555BA -:10091000000000188000FF7E0000001880000031F9 -:1009200000000018800000060000000B2FDF00020E -:10093000000000002C000E00000000082A00000744 -:100940000000000805005555000000188000FEED6D -:1009500000000000068200000000000C2980000159 -:100960000000000C1F800001000000100CE70007D1 -:10097000000000090562FFFF00000010BA6C1405BA -:10098000000000002ADF000000000000210000003D -:10099000000000082A0000050000001091D40000AB -:1009A000000000082C80010C000000082D00000849 -:1009B0000000000C31620018000000082D800001CA -:1009C000000000188000FF7200000018000D0000F9 -:1009D00000000010B1A0B00E0000000B2FDF0002DD -:1009E0000000000003D80000000000002C200000E0 -:1009F0000000001091D400000000001880000015D5 -:100A0000000000102C620002000000188000000CA2 -:100A10000000000B2FDF0002000000002C07000088 -:100A20000000000C1F8000010000001091DE00009B -:100A3000000000080500FFFF000000188000FECF46 -:100A4000000000082C80010D000000082D000009A6 -:100A50000000001091D40000000000082D80010764 -:100A6000000000188000FF690000000C29800001D0 -:100A70000000000C1F8000010000001091DE00004B -:100A8000000000002ADF0000000000082A00000A21 -:100A90000000000005000000000000188000FEC3F8 -:100AA0000000000006820000000000082C80010CFD -:100AB000000000082D000008000000082D8001340F -:100AC000000000000000000000000010205F000097 -:100AD000000000082C800140000000082D00003CB0 -:100AE000000000082D80012400000000000000002C -:100AF0000000001091DE0000000000082C80008043 -:100B0000000000082D000000000000082D800105F5 -:100B100000000010BEE20005000000188000FEACDE -:100B2000000000010562140000000010918A00021C -:100B300000000008B16200010000001091DE00001A -:100B400000000018000D00000000001091D400000B -:100B5000000000080600AAAA000000188000FF3567 -:100B60000000000C298000010000000C1F80000123 -:100B7000000000082A000009000000080500AAAAD9 -:100B8000000000188000FEA60000001091D40000B4 -:100B90000000000806005555000000188000FF2DD9 -:100BA0000000001091A03C0200000010B1E66207B6 -:100BB0000000000B2FDF0002000000002C310000BD -:100BC000000000092CB1007F000000082CD90000B3 -:100BD000000000082D000000000000082D80010D1D -:100BE00000000010B1A8000600000010205F000007 -:100BF000000000002C200000000000002CA70000D6 -:100C0000000000082D000010000000082D800108E1 -:100C1000000000188000FF2800000010B1A600109E -:100C200000000010001F00000000000F0F30000740 -:100C3000000000000A600000000000000AE100005F -:100C40000000000F4B620008000000090B1600FFB7 -:100C5000000000000D620000000000090D1A00FFF6 -:100C600000000010073000030000000C0D1A0008FF -:100C70000000000C0B1600080000000F4CE30018E9 -:100C8000000000000C992C0000000004CC993400F6 -:100C9000000000080F8000000000000C2980000107 -:100CA00000000000333100000000000822000016A0 -:100CB000000000002ADF0000000000082A00000CED -:100CC00000000010009F0000000000000F20000046 -:100CD0000000000C1F8000010000000805005555B1 -:100CE000000000188000FE7A0000001091D400007F -:100CF000000000080600AAAA000000188000FF01FA -:100D00000000000F4722000800000009070E000F36 -:100D100000000008070E0008000000080280000123 -:100D20000000000702851C00000000088285000109 -:100D30000000000002854C000000000742851C00F6 -:100D400000000003C3AA52000000000003B10E001F -:100D5000000000074B071C000000000F0F300007C9 -:100D60000000000F0A960003000000000A955C00D6 -:100D7000000000004A005A00000000000C960A0023 -:100D8000000000090C99FFFF000000080D00FFFFA4 -:100D900000000010B1963202000000080F8000052C -:100DA00000000010B1A8000800000010205F000043 -:100DB0000000000B2FDF0002000000002C200000CC -:100DC000000000002CA70000000000082D0000100B -:100DD000000000082D800108000000188000FEEFD0 -:100DE0000000000C2980000100000010001F00001E -:100DF0000000000C1F800001000000002ADF00003E -:100E0000000000082A00000D000000080500AAAA42 -:100E1000000000188000FE540000001091D4000073 -:100E20000000000806005555000000188000FEDB99 -:100E30000000000C298000010000000C1F80000150 -:100E4000000000082A0000070000000805005555B2 -:080E5000000000188000FE4CB8 -:080E580000000010B18000044D -:100E60000000001F0503030000000008050000FF4C -:100E70000000001800020000000000002A0000002E -:100E800000000010B1D400000000001091DE00004E -:100E9000000000102053000000000010001F0000A0 -:100EA000000000002F80AA000000000C2980000133 -:100EB000000000080254000E000000002C4000005A -:100EC000000000092952003F000000180004000043 -:100ED00000000018800000100000001880000011C1 -:100EE000000000188000003900000018800000FD9C -:100EF00000000018800000FC00000018800000FBCB -:100F000000000018800000FB0000001880000000B6 -:100F1000000000188000011300000018800000F796 -:100F2000000000188000000B00000018800001176E -:100F300000000018800001650000001880000063B8 -:100F400000000018800000CE00000018800000DEC5 -:100F5000000000002A000000000000188000FFE5EB -:100F6000000000002A0000000000000C29800000A2 -:100F7000000000188000FFE2000000002A000000CE -:100F8000000000188000FFE00000001800020000D0 -:100F900000000000050200000000001091963421BE -:100FA00000000010205F0000000000002C1E000068 -:100FB000000000082C800006000000082D0000063C -:100FC000000000082D800102000000000000000069 -:100FD0000000001091DE0000000000000D61000024 -:100FE00000000018000A00000000000005020000D8 -:100FF000000000109196341600000010205F0000E1 -:101000000000000009D80000000000002C1E0000B5 -:10101000000000082C80010E000000082D00000ACE -:10102000000000082D800102000000000000000008 -:101030000000001091DE0000000000000D620000C2 -:10104000000000002C13000000000018000A00003F -:101050000000000005020000000000109196340915 -:1010600000000010205F0000000000002C1E0000A7 -:10107000000000082C800006000000082D00006A17 -:10108000000000082D8001020000000000000000A8 -:101090000000001091DE0000000000000D7A00004A -:1010A00000000018000A0000000000002A000000F4 -:1010B000000000000D61000000000000036200005D -:1010C00000000010234200C10000000002638C00F9 -:1010D0000000000026460000000000080204001284 -:1010E00000000010B9060827000000000F5800009B -:1010F000000000000A640000000000000AE5000093 -:10110000000000090B66FFFF000000000C0000005B -:10111000000000000B800000000000080CC6001258 -:10112000000000188000FFCE000000080F800003C0 -:10113000000000000000000000000010009F000000 -:101140000000000827110012000000006690000057 -:1011500000000008A31B001200000010B19800035B -:1011600000000010001F0000000000080F800004B5 -:101170000000000822000003000000082C80000C82 -:10118000000000082D00000C00000010009F00006F -:1011900000000000259600000000000C29800000DF -:1011A00000000000066600000000000086611800D4 -:1011B000000000090260000F0000000F020400029E -:1011C00000000010B60C08050000000C1FBF000056 -:1011D000000000102866000300000008078F0001CF -:1011E0000000000C33660010000000003214000004 -:1011F00000000000329500000000000573662C001E -:101200000000000031E32E00000000082D800010D7 -:10121000000000188000FF8E000000002300000086 -:101220000000000925E6FFFF000000082200000B77 -:101230000000000C695200000000000C2980000032 -:101240000000001028660075000000188000FF876D -:10125000000000002A000000000000082C80004070 -:10126000000000082D000020000000082D80011C57 -:1012700000000000000000000000001091DE0000EF -:101280000000000F42EA001000000010004F0004B0 -:1012900000000010B746920000000008024900124A -:1012A00000000010B5840A00000000000D6100007D -:1012B00000000010BA6634570000000883050012D1 -:1012C00000000010004F0002000000000349000071 -:1012D0000000000183068C000000000083C60C00A3 -:1012E00000000010B1870011000000000B6E00002C -:1012F00000000010BEE90005000000188000FF6E2D -:10130000000000010569140000000010918A00022D -:1013100000000008B4E9000100000010B1E92C4A07 -:101320000000000086692C000000000002000000A0 -:101330000000000902EAFFFF00000010000C00029C -:101340000000000002040A000000000F460C00012B -:101350000000000F0285000100000010918C01FCCC -:1013600000000010B7040E41000000000F40000014 -:10137000000000000D610000000000000A64000091 -:10138000000000000AE50000000000090B66FFFFF6 -:10139000000000000C000000000000000B800000B6 -:1013A000000000080C860012000000080F800003F7 -:1013B0000000000C2952000000000010009F0000F7 -:1013C00000000008271100120000000066900000D5 -:1013D0000000000026460000000000002306000078 -:1013E00000000010B198000500000010001F000070 -:1013F000000000080F800004000000000000000052 -:1014000000000010001F0000000000003214000067 -:1014100000000000329500000000000031E32E00C3 -:101420000000000573662C000000000025960000F7 -:1014300000000010B18700160000000C2980000099 -:101440000000000F0F6B0007000000000D69000096 -:10145000000000000A6C0000000000000AED00001F -:10146000000000000B6E0000000000000B80000078 -:10147000000000000C870000000000080F8000033F -:1014800000000010205300000000000C6952000111 -:1014900000000010001F00000000000022C58C00AA -:1014A00000000000231B00000000000027110000C6 -:1014B000000000002690000000000010B8170E0386 -:1014C0000000000C29800000000000188000FFF6DA -:1014D00000000010B1980002000000080F80000416 -:1014E000000000082200001A000000082C80000CF8 -:1014F000000000082D00000C000000082D800010E6 -:1015000000000010001F0000000000000D6E000031 -:1015100000000003E7CF34000000000C2980000029 -:101520000000001091DE000000000010B1870007ED -:101530000000000036140000000000003695000096 -:101540000000000037160000000000082C8000504A -:10155000000000082D000030000000082D80000C65 -:10156000000000188000FF24000000002646000054 -:1015700000000000230000000000000925E6FFFF36 -:10158000000000000B6E000000000003E7CF2C00FD -:10159000000000082200001B0000000C695200003F -:1015A0000000000C29800000000000188000FF1BD4 -:1015B000000000002A00000000000010086600057E -:1015C00000000000066600000000000086611800B0 -:1015D00000000009026000F000000010B60C0802D4 -:1015E000000000188000FF140000000006820000C8 -:1015F00000000010B18F000000000008878F00017C -:101600000000000C73660010000000082C80001819 -:10161000000000082D000018000000082D800002C6 -:101620000000000C5FBF00000000001091DE000011 -:1016300000000018000D0000000000002A0000005B -:1016400000000010286601F5000000082C8000034F -:10165000000000082D000003000000093060FFF0CA -:10166000000000082D8000010000000C298000000F -:101670000000001091DE0000000000082C80001A1D -:10168000000000082D00001A00000005736600002D -:10169000000000082D8000020000000031800000E2 -:1016A0000000001091DE0000000000082C80000CFB -:1016B000000000082D00000C000000082D80000430 -:1016C000000000188000FEF8000000180002000072 -:1016D000000000188000FEF6000000002A00000054 -:1016E00000000010001F0000000000000F0080003C -:1016F000000000080F800007000000188000001A9A -:1017000000000000280A00000000000005020000A0 -:10171000000000082200000900000000290000006D -:101720000000000F6568001000000003F66C9400D4 -:1017300000000010B972A0040000000C73E700194B -:101740000000000C21420004000000003CF80000F2 -:101750000000000C29800000000000102053000051 -:1017600000000008220000080000000C6142000494 -:1017700000000018000A0000000000000502000040 -:101780000000000C61420000000000100142000354 -:101790000000000C33E7001D0000000C6142000255 -:1017A00000000018000A0000000000002A000000ED -:1017B00000000010001F00000000000F0F4700078E -:1017C000000000080F8000080000000C29800000C5 -:1017D00000000010009F0000000000188000FED5EF -:1017E0000000000033510000000000002A0000004B -:1017F00000000010B1C600230000000F0F500007CA -:10180000000000000A600000000000000AE1000083 -:101810000000000F4B620008000000090B1600FFDB -:101820000000000F4C620010000000000D6200007C -:10183000000000090D1A00FF00000010075000030F -:101840000000000C0D1A00080000000C0B16000828 -:10185000000000000CC60000000000000B8000002B -:101860000000000006980000000000080F80000340 -:101870000000001006C200040000000C2900000255 -:1018800000000010264200020000000C2952000354 -:10189000000000082200000100000010009F00006E -:1018A00000000000231B00000000000027111A00A8 -:1018B00000000000669000000000000C29520000AB -:1018C00000000010B19732090000000C29800000D0 -:1018D00000000000069800000000001020530000E7 -:1018E0000000000C295200030000000022C58C00FB -:1018F00000000010001F0000000000080F8000031F -:10190000000000188000FFF300000010B1C80013B1 -:1019100000000010B1C600030000000C2980000088 -:1019200000000010205300000000000C29520000AD -:101930000000000C295200030000001006C2000243 -:101940000000000C295200020000000022C58C009B -:1019500000000000276500000000000026E40000F1 -:10196000000000082200001600000010B1C60003AD -:10197000000000002348000000000010B1800005B6 -:1019800000000000234800000000000C2980000037 -:101990000000000F0F500007000000188000001228 -:1019A00000000008220000160000000C2980000042 -:1019B000000000003014000000000000309500001E -:1019C0000000001007500003000000090B1600FF84 -:1019D000000000090D1A00FF0000000F311600087A -:1019E000000000003162340000000003F1623000AA -:1019F00000000010205F0000000000002C510000DB -:101A0000000000092CD1007F000000082CD9000044 -:101A1000000000082D000000000000082D80000CD0 -:101A200000000000000000000000001091DE000037 -:101A30000000001005C20004000000080F8000072D -:101A4000000000003300000000000010009F0000B4 -:101A5000000000188000FE86000000002A00000040 -:101A60000000000F0F50000700000010B1C6002D4D -:101A70000000000F4742000800000009070E000F99 -:101A800000000008070E000800000010001F000002 -:101A900000000008090000010000000709121C00F6 -:101AA00000000003CBCA9200000000000B97A200C8 -:101AB0000000000742171C00000000000B0400009B -:101AC0000000000F0A840003000000000A959C003B -:101AD000000000004A009A00000000088212000185 -:101AE000000000010C170800000000000C978C009B -:101AF0000000000002180000000000080D00FFFFB9 -:101B0000000000080F8000060000000C2900000003 -:101B10000000001006C200040000000C2952000260 -:101B200000000010264200020000000C29520003B1 -:101B3000000000082200000100000010009F0000CB -:101B400000000010B197320C00000000231B0000C1 -:101B5000000000002711080000000000669000004F -:101B60000000000C298000000000000002180000A6 -:101B700000000010205300000000000C2952000358 -:101B80000000000022C5360000000010001F000009 -:101B9000000000080F800006000000188000FFF41D -:101BA00000000000231B00000000000027110800B7 -:101BB000000000006690000000000010B1C8000B9B -:101BC0000000000C298000000000001020530000DD -:101BD0000000000C295200000000000C29520003F4 -:101BE0000000001006C200020000000C2952000292 -:101BF0000000000022C58C000000000027650000E6 -:101C00000000000026E4000000000000234800005F -:101C100000000008220000170000000C29800000CE -:101C200000000010001F0000000000188000FE4BA4 -:00000001FF -/* - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - */ diff --git a/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex b/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex new file mode 100644 index 000000000000..f325e6904edb --- /dev/null +++ b/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw.ihex @@ -0,0 +1,499 @@ +:100000000000000000000E80000000580000000901 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000FA800000ED800000005000000001E +:1000400000000000000000000000000000000000B0 +:080050000000000000000000A8 +:0800580000000010B180000659 +:100060000000001F03030300000000080500FFFF5D +:10007000000000180002000000000008050000FF5A +:10008000000000180002000000000008AC000001A1 +:1000900000000000050000000000000C2F8000019F +:1000A000000000002B000000000000002B8000007A +:1000B0000000001091E0000200000008AC00000108 +:1000C00000000010203F006B00000010213F0003E3 +:1000D0000000001020BF003A000000188000FFFD63 +:1000E00000000010B1B8B0150000000B2FDF0002B7 +:1000F0000000000003D80000000000002C380000C1 +:10010000000000082C800000000000082D00000006 +:100110000000001091D400000000000806005555B2 +:10012000000000188000008F000000082D80011CD6 +:1001300000000008020000010000001091DE000035 +:100140000000000F42E0001C0000001091840A161D +:1001500000000018800000960000000C29800002BA +:100160000000000C1F800002000000002ADF0000D9 +:10017000000000082A00000F000000000500000039 +:10018000000000188000FFE60000000802000001E7 +:100190000000000F42E0001C0000001091840A18CB +:1001A000000000082C800006000000082D0000065A +:1001B0000000001091D40000000000082D8001060E +:1001C0000000001880000085000000188000FFF18A +:1001D00000000008B1000001000000082C80010CA4 +:1001E000000000082D000008000000082D8000011C +:1001F000000000188000007F0000000B2FDF0002CD +:100200000000000C1F800002000000002C0700000E +:100210000000001091DE00000000000805005555A8 +:10022000000000188000FFD20000000B2FDF00024A +:100230000000000C1F800000000000002C070000E0 +:100240000000001091DE0000000000080500555578 +:10025000000000188000FFCC0000000C1F8000028E +:100260000000000805005555000000188000FFC977 +:100270000000000C298000020000000C1F8000021A +:10028000000000002ADF0000000000082A0000052E +:100290000000000805005555000000188000FFC34D +:1002A000000000080224004A0000001800040000BA +:1002B000000000188000001C000000188000001ED4 +:1002C000000000188000007800000018800000CBBB +:1002D00000000018800000CA000000188000000024 +:1002E00000000018800000000000001880000000DE +:1002F00000000018800000000000001880000000CE +:1003000000000018800000000000001880000000BD +:100310000000001880000000000000188000011696 +:10032000000000188000000000000018800000009D +:100330000000001880000015000000188000001B5D +:10034000000000188000000000000018800000E19C +:10035000000000188000002F000000188000011627 +:100360000000001880000141000000188000010C0E +:100370000000001880000165000000188000006186 +:100380000000001880000000000000188000009E9F +:100390000000000C1F8000010000000005000000AC +:1003A000000000188000FFA20000001091D400009F +:1003B0000000000C298000010000000C1F800001DB +:1003C000000000082A0000020000000005000000F4 +:1003D000000000188000FF9C0000001091D4000075 +:1003E0000000000C298000010000000C1F800001AB +:1003F0000000000029420000000000082A0000025E +:100400000000000005000000000000188000FF95BB +:10041000000000188000FF9400000010B1BCB00A7A +:100420000000000B2FDF00020000000003D80000D6 +:10043000000000002C3C00000000001091D40000DF +:100440000000000806005555000000188000002A32 +:1004500000000018800000DA000000102C6201BAD1 +:100460000000001880000006000000082C80010D2C +:10047000000000082D0000090000001091D40000C9 +:10048000000000082D8001070000001880000037E0 +:100490000000000C298000000000000C1F800000FC +:1004A0000000001091DE0000000000002ADF0000C4 +:1004B000000000082A00000600000008050055554D +:1004C000000000188000FF7E0000001091D40000A2 +:1004D0000000000C298000010000000C1F800001BA +:1004E000000000082A00000B0000000005000000CA +:1004F000000000188000FF780000000002020000E9 +:1005000000000000029A000000000000060C2C0011 +:1005100000000004C60C340000000010001F0000A2 +:1005200000000010B196180C0000000806960004A8 +:1005300000000009068DFFFC00000004CD051A0034 +:1005400000000004CC9A18000000001020D7000022 +:100550000000000C2B56000000000000000000000E +:1005600000000000000000000000001020D7000084 +:10057000000000080F80000100000010B18001F4AD +:1005800000000010001F00000000000C6B5600006F +:1005900000000018000400000000000006820000B7 +:1005A00000000010B18A000800000010B18C140790 +:1005B0000000000B050AFFFF00000010B18A0003D5 +:1005C00000000000860A180000000010918C000056 +:1005D000000000082A0000010000001091D4000073 +:1005E00000000018000D00000000000005020000DF +:1005F0000000001091DE000000000018000A00005A +:1006000000000000068200000000001091DE0000E3 +:1006100000000010BEE10005000000188000FF4C43 +:10062000000000010561140000000010918A000222 +:1006300000000008B0E1000100000018000D0000FB +:1006400000000000068200000000001091DE0000A3 +:1006500000000010BEE20005000000188000FF440A +:10066000000000010562140000000010918A0002E1 +:1006700000000008B162000100000018000D000039 +:1006800000000010B1A0B0130000000B2FDF00022B +:10069000000000002C200000000000082C8000005A +:1006A000000000082D0000000000001091D40000A0 +:1006B0000000000806005555000000188000FFDC0F +:1006C000000000082D80011C00000010001F000029 +:1006D000000000188000FFE60000000F47600008DF +:1006E0000000000F060E0001000000000F5800007F +:1006F000000000000A640000000000000AE500009D +:10070000000000090B66FFFF000000000D61000003 +:1007100000000018800000130000000F4760000870 +:100720000000000B2FDF0002000000082C800000FA +:10073000000000082D0000000000001091D400000F +:10074000000000082D80011C0000000F060E0001B3 +:1007500000000010001F0000000000000F58000003 +:10076000000000188000FFD4000000000A640000B0 +:10077000000000000AE50000000000090B66FFFF12 +:10078000000000000D610000000000000262000097 +:100790000000000B2FDF0002000000003104000009 +:1007A00000000000309A0000000000090560000F02 +:1007B00000000010B18A000B0000000005634C002F +:1007C00000000008050A001200000010B9621403BE +:1007D0000000000003000000000000188000000678 +:1007E000000000188000FF1100000010B60614047D +:1007F0000000000803060001000000082A000001B4 +:10080000000000188000FF16000000188000FF9E06 +:100810000000000C298000010000000C295200019A +:100820000000000C29520000000000080200000E29 +:10083000000000080280001A00000010B1C40A0283 +:100840000000000802000003000000082200000170 +:100850000000000C1F800001000000002ADF0000E3 +:10086000000000002A00080000000008050055559F +:10087000000000188000FF080000000B2FDF0002BE +:100880000000001091D40000000000082A000001C0 +:10089000000000002C2000000000001091D4000097 +:1008A000000000082C800000000000082D0000005F +:1008B000000000082D80011C000000188000FFA629 +:1008C000000000082C800006000000082D00000633 +:1008D0000000000030800000000000003100000037 +:1008E000000000082D8000060000000C2980000197 +:1008F0000000000C1F8000010000001091DE0000CD +:10090000000000002ADF0000000000082A0000109C +:100910000000000005000000000000188000FEF349 +:100920000000001091A0B009000000082C80010D0B +:10093000000000082D0000090000001091D4000004 +:10094000000000082D800107000000188000FF9FB4 +:10095000000000188000001000000008AC0000013A +:10096000000000188000000B000000000380B000B1 +:100970000000000B2FDF0002000000002C004000F0 +:100980000000001091D4000000000008060055553A +:10099000000000188000FF81000000188000003176 +:1009A00000000018800000060000000B2FDF00028E +:1009B000000000002C000E00000000082A000007C4 +:1009C0000000000805005555000000188000FEDDFD +:1009D00000000000068200000000000C29800001D9 +:1009E0000000000C1F800001000000100CE7000751 +:1009F000000000090562FFFF00000010BA6C14053A +:100A0000000000002ADF00000000000021000000BC +:100A1000000000082A0000050000001091D400002A +:100A2000000000082C80010C000000082D000008C8 +:100A30000000000C31620018000000082D80000149 +:100A4000000000188000FF7500000018000D000075 +:100A500000000010B1A0B00E0000000B2FDF00025C +:100A60000000000003D80000000000002C2000005F +:100A70000000001091D40000000000188000001554 +:100A8000000000102C620002000000188000000C22 +:100A90000000000B2FDF0002000000002C07000008 +:100AA0000000000C1F8000010000001091DE00001B +:100AB000000000080500FFFF000000188000FEBFD6 +:100AC000000000082C80010D000000082D00000926 +:100AD0000000001091D40000000000082D800107E4 +:100AE000000000188000FF6C0000000C298000014D +:100AF0000000000C1F8000010000001091DE0000CB +:100B0000000000002ADF0000000000082A00000AA0 +:100B10000000000005000000000000188000FEB387 +:100B20000000000006820000000000082C80010C7C +:100B3000000000082D000008000000082D8001348E +:100B4000000000000000000000000010205F000016 +:100B5000000000082C800140000000082D00003C2F +:100B6000000000082D80011C0000000000000000B3 +:100B70000000001091DE0000000000082C800080C2 +:100B8000000000082D000000000000082D80010575 +:100B900000000010BEE20005000000188000FE9C6E +:100BA000000000010562140000000010918A00029C +:100BB00000000008B16200010000001091DE00009A +:100BC00000000018000D00000000001091D400008B +:100BD000000000080600AAAA000000188000FF38E4 +:100BE0000000000C298000010000000C1F800001A3 +:100BF000000000082A000009000000080500AAAA59 +:100C0000000000188000FE960000001091D4000043 +:100C10000000000806005555000000188000FF3055 +:100C20000000001091A03C0200000010B1E6620735 +:100C30000000000B2FDF0002000000002C3100003C +:100C4000000000092CB1007F000000082CD9000032 +:100C5000000000082D000000000000082D80010D9C +:100C600000000010B1A8000600000010205F000086 +:100C7000000000002C200000000000002CA7000055 +:100C8000000000082D000010000000082D80010861 +:100C9000000000188000FF2B00000010B1A600101B +:100CA00000000010001F00000000000F0F300007C0 +:100CB000000000000A600000000000000AE10000DF +:100CC0000000000F4B620008000000090B1600FF37 +:100CD000000000000D620000000000090D1A00FF76 +:100CE00000000010073000030000000C0D1A00087F +:100CF0000000000C0B1600080000000F4CE3001869 +:100D0000000000000C992C0000000004CC99340075 +:100D1000000000080F8000000000000C2980000186 +:100D2000000000003331000000000008220000161F +:100D3000000000002ADF0000000000082A00000C6C +:100D400000000010009F0000000000000F200000C5 +:100D50000000000C1F800001000000080500555530 +:100D6000000000188000FE6A0000001091D400000E +:100D7000000000080600AAAA000000188000FF0476 +:100D80000000000F4722000800000009070E000FB6 +:100D900000000008070E00080000000802800001A3 +:100DA0000000000702851C00000000088285000189 +:100DB0000000000002854C000000000742851C0076 +:100DC00000000003C3AA52000000000003B10E009F +:100DD000000000074B071C000000000F0F30000749 +:100DE0000000000F0A960003000000000A955C0056 +:100DF000000000004A005A00000000000C960A00A3 +:100E0000000000090C99FFFF000000080D00FFFF23 +:100E100000000010B1963202000000080F800005AB +:100E200000000010B1A8000800000010205F0000C2 +:100E30000000000B2FDF0002000000002C2000004B +:100E4000000000002CA70000000000082D0000108A +:100E5000000000082D800108000000188000FEF24C +:100E60000000000C2980000100000010001F00009D +:100E70000000000C1F800001000000002ADF0000BD +:100E8000000000082A00000D000000080500AAAAC2 +:100E9000000000188000FE440000001091D4000003 +:100EA0000000000806005555000000188000FEDE16 +:100EB0000000000C298000010000000C1F800001D0 +:100EC000000000082A000007000000080500555532 +:080ED000000000188000FE3C48 +:080ED80000000010B1800004CD +:100EE0000000001F0303030000000008050000FFCE +:100EF0000000001800020000000000002A000000AE +:100F000000000010B1D400000000001091DE0000CD +:100F1000000000102053000000000010001F00001F +:100F20000000000C6BD70001000000002F80AA0019 +:100F30000000000C29800001000000080254000F8E +:100F4000000000002C400000000000092952003F72 +:100F500000000018000400000000001880000010CD +:100F60000000001880000011000000188000004AF6 +:100F700000000018800001280000001880000127F0 +:100F800000000018800001260000001880000126E3 +:100F90000000001880000000000000188000013FE1 +:100FA0000000001880000122000000188000000BE3 +:100FB0000000001880000145000000188000019A20 +:100FC000000000188000007B00000018800000F97D +:100FD0000000001880000109000000002A00000045 +:100FE000000000188000FFE4000000002A0000005C +:100FF0000000000C29800000000000188000FFE1C4 +:10100000000000002A000000000000188000FFDF40 +:101010000000000003820000000000188000FFDADA +:10102000000000010C161400000000008C181400D1 +:101030000000001091980003000000080C960002C8 +:1010400000000010B1800003000000080C960001B1 +:10105000000000000C000000000000000D1900005E +:1010600000000010205600000000000C2BD70001EB +:10107000000000080F8000010000000000000000D8 +:1010800000000010001F00000000000C6BD70001E2 +:1010900000000010011301F100000018000700001B +:1010A00000000000050200000000001091963421AD +:1010B00000000010205F0000000000002C1E000057 +:1010C000000000082C800006000000082D0000062B +:1010D000000000082D800102000000000000000058 +:1010E0000000001091DE0000000000000D61000013 +:1010F00000000018000A00000000000005020000C7 +:10110000000000109196341600000010205F0000CF +:101110000000000009D80000000000002C1E0000A4 +:10112000000000082C80010E000000082D00000ABD +:10113000000000082D8001020000000000000000F7 +:101140000000001091DE0000000000000D620000B1 +:10115000000000002C13000000000018000A00002E +:101160000000000005020000000000109196340904 +:1011700000000010205F0000000000002C1E000096 +:10118000000000082C800006000000082D00006A06 +:10119000000000082D800102000000000000000097 +:1011A0000000001091DE0000000000000D7A000039 +:1011B00000000018000A0000000000002A000000E3 +:1011C000000000000D61000000000000036200004C +:1011D00000000010234200DB0000000002638C00CE +:1011E0000000000026460000000000080204001273 +:1011F00000000010B906082E000000000F58000083 +:10120000000000000A640000000000000AE5000081 +:10121000000000090B66FFFF000000000C0000004A +:10122000000000000B800000000000080CC6001247 +:10123000000000188000FFCE0000001020560000C3 +:101240000000000C2BD70001000000080F800003F5 +:10125000000000000000000000000010001F00005F +:101260000000000C6BD700010000000827110012DD +:10127000000000006690000000000008A31B0012A0 +:1012800000000010B198000600000010001F0000D0 +:101290000000000C6BD70001000000102056000079 +:1012A0000000000C2BD70001000000080F80000494 +:1012B0000000000822000003000000082C80000C41 +:1012C000000000082D00000C00000010001F0000AE +:1012D0000000000C6BD70001000000002596000004 +:1012E0000000000C298000000000000006660000DD +:1012F0000000000086611800000000090260000F75 +:101300000000000F0204000200000010B60C0805E7 +:101310000000000C1FBF0000000000102866000342 +:1013200000000008078F00010000000C3366001069 +:1013300000000000321400000000000032950000A0 +:101340000000000573662C000000000031E32E0051 +:10135000000000082D800010000000188000FF75BC +:1013600000000000230000000000000925E6FFFF48 +:10137000000000082200000B0000000C6952000071 +:101380000000000C29800000000000102866008882 +:10139000000000188000FF6E000000002A0000001E +:1013A000000000082C800040000000082D000020F4 +:1013B000000000082D80011C00000000000000005B +:1013C0000000001091DE00000000000F42EA001053 +:1013D00000000010004F000400000010B74692000B +:1013E000000000080249001200000010B5840A0045 +:1013F000000000000D61000000000010BA66346AB1 +:10140000000000088305001200000010004F0002D9 +:1014100000000000034900000000000183068C006A +:101420000000000083C60C0000000010B18700110E +:10143000000000000B6E000000000010BEE9000577 +:10144000000000188000FF5500000001056914002D +:1014500000000010918A000200000008B4E90001B9 +:1014600000000010B1E92C5D0000000086692C002E +:1014700000000000020000000000000902EAFFFF77 +:1014800000000010000C00020000000002040A002E +:101490000000000F460C00010000000F0285000153 +:1014A00000000010918C01FC00000010B7040E54E5 +:1014B000000000000F400000000000000D6100006F +:1014C000000000000A640000000000000AE50000BF +:1014D000000000090B66FFFF000000000C00000088 +:1014E000000000000B800000000000080C860012C5 +:1014F00000000010205600000000000C2BD7000157 +:10150000000000080F8000030000000C29520000BA +:1015100000000010001F00000000000C6BD700014D +:101520000000000827110012000000006690000073 +:101530000000000026460000000000002306000016 +:1015400000000010B198000900000010001F00000A +:101550000000000C6BD700010000001020560000B6 +:101560000000000C2BD70001000000080F800004D1 +:10157000000000000000000000000010001F00003C +:101580000000000C6BD700010000000032140000C6 +:1015900000000000329500000000000031E32E0042 +:1015A0000000000573662C00000000002596000076 +:1015B00000000010B18700210000000C298000000D +:1015C0000000000F0F6B0007000000000D69000015 +:1015D000000000000A6C0000000000000AED00009E +:1015E000000000000B6E0000000000000B800000F7 +:1015F000000000000C870000000000188000FF1EA3 +:10160000000000010C161400000000008C181400EB +:10161000000000080C9600010000001091980002E4 +:10162000000000080C990001000000000D190000E6 +:10163000000000000C000000000000102056000018 +:101640000000000C2BD70001000000080F800001F3 +:1016500000000010205300000000000C695200013F +:1016600000000010001F00000000000C6BD70001FC +:101670000000000022C58C000000000023120000C2 +:10168000000000002711000000000000269000006C +:1016900000000010B8170E030000000C29800000A5 +:1016A000000000188000FFEB0000000082970E0091 +:1016B00000000000A3120A00000000082200001A27 +:1016C000000000082C80000C000000082D00000C19 +:1016D000000000082D80001000000010001F000016 +:1016E0000000000C6BD70001000000000D6E000030 +:1016F00000000003E7CF34000000000C2980000048 +:101700000000001091DE000000000010B18700070B +:1017100000000000361400000000000036950000B4 +:101720000000000037160000000000082C80005068 +:10173000000000082D000030000000082D80000C83 +:10174000000000188000FEF800000000264600009F +:1017500000000000230000000000000925E6FFFF54 +:10176000000000000B6E000000000003E7CF2C001B +:10177000000000082200001B0000000C695200005D +:101780000000000C29800000000000188000FEEF1F +:10179000000000002A00000000000010086600059C +:1017A00000000000066600000000000086611800CE +:1017B00000000009026000F000000010B60C0802F2 +:1017C000000000188000FEE8000000000682000013 +:1017D00000000010B18F000000000008878F00019A +:1017E0000000000C73660010000000082C80001838 +:1017F000000000082D000018000000082D800002E5 +:101800000000000C5FBF00000000001091DE00002F +:1018100000000018000D0000000000002A00000079 +:1018200000000010286601F5000000082C8000036D +:10183000000000082D000003000000093060FFF0E8 +:10184000000000082D8000010000000C298000002D +:101850000000001091DE0000000000082C80001A3B +:10186000000000082D00001A00000005736600004B +:10187000000000082D800002000000003180000000 +:101880000000001091DE0000000000082C80000C19 +:10189000000000082D00000C000000082D8000044E +:1018A000000000188000FECC0000001800020000BC +:1018B000000000188000FECA000000002A0000009E +:1018C00000000010001F00000000000C6BD700019A +:1018D000000000000F008000000000080F800007DB +:1018E000000000188000001B00000000280A000013 +:1018F00000000000050200000000000822000009AE +:1019000000000000290000000000000F65680010C2 +:1019100000000003F66C940000000010B972A004EF +:101920000000000C73E700190000000C21420004C5 +:10193000000000003CF800000000000C29800000BE +:1019400000000010205300000000000822000008E2 +:101950000000000C6142000400000018000A0000B2 +:1019600000000000050200000000000C61420000C1 +:1019700000000010014200030000000C33E7001DCE +:101980000000000C6142000200000018000A000084 +:10199000000000002A00000000000010001F0000EE +:1019A0000000000C6BD700010000000F0F4700077C +:1019B000000000080F8000080000000C29800000D3 +:1019C00000000010001F00000000000C6BD7000199 +:1019D000000000188000FEA6000000003351000047 +:1019E000000000002A00000000000010B1C600291D +:1019F0000000000F0F500007000000000A60000008 +:101A0000000000000AE100000000000F4B62000827 +:101A1000000000090B1600FF0000000F4C620010D0 +:101A2000000000000D620000000000090D1A00FF18 +:101A300000000010075000030000000C0D1A000801 +:101A40000000000C0B160008000000000CC600008F +:101A5000000000000B80000000000000069800005D +:101A600000000010205600000000000C2BD70001E1 +:101A7000000000080F8000030000001006C20004F0 +:101A80000000000C290000020000001026420002A5 +:101A90000000000C29520003000000082200000191 +:101AA00000000010001F00000000000C6BD70001B8 +:101AB00000000000231B00000000000027111A0096 +:101AC00000000000669000000000000C2952000099 +:101AD00000000010B197320C0000000C29800000BB +:101AE00000000000069800000000001020530000D5 +:101AF0000000000C295200030000000022C58C00E9 +:101B000000000010001F00000000000C6BD7000157 +:101B100000000010205600000000000C2BD7000130 +:101B2000000000080F800003000000188000FFEF95 +:101B300000000010B1C8001300000010B1C600037F +:101B40000000000C2980000000000010205300005D +:101B50000000000C295200000000000C2952000374 +:101B60000000001006C200020000000C2952000212 +:101B70000000000022C58C00000000002765000066 +:101B80000000000026E4000000000008220000160B +:101B900000000010B1C60003000000002348000050 +:101BA00000000010B1800005000000002348000084 +:101BB0000000000C298000000000000F0F500007FB +:101BC000000000188000001200000008220000162B +:101BD0000000000C2980000000000000301400000C +:101BE00000000000309500000000001007500003C6 +:101BF000000000090B1600FF000000090D1A00FF8D +:101C00000000000F311600080000000031623400AF +:101C100000000003F162300000000010205F0000AF +:101C2000000000002C510000000000092CD1007FB2 +:101C3000000000082CD90000000000082D00000062 +:101C4000000000082D80000C0000000000000000D3 +:101C50000000001091DE00000000001005C2000529 +:101C6000000000080F8000070000000033000000A3 +:101C700000000010001F00000000000C6BD70001E6 +:101C8000000000188000FE50000000002A00000044 +:101C90000000000F0F50000700000010B1C6003018 +:101CA0000000000F4742000800000009070E000F67 +:101CB00000000008070E000800000010001F0000D0 +:101CC0000000000C6BD700010000000809000001B3 +:101CD0000000000709121C0000000003CBCA92009C +:101CE000000000000B97A2000000000742171C0034 +:101CF000000000000B0400000000000F0A84000335 +:101D0000000000000A959C00000000004A009A00B4 +:101D10000000000882120001000000010C170800FA +:101D2000000000000C978C0000000000021800006A +:101D3000000000080D00FFFF000000080F800006F3 +:101D40000000000C290000000000001006C2000482 +:101D50000000000C29520002000000102642000280 +:101D60000000000C295200030000000822000001BE +:101D700000000010001F00000000000C6BD70001E5 +:101D800000000010B197320D00000000231B00007E +:101D9000000000002711080000000000669000000D +:101DA0000000000C29800000000000000218000064 +:101DB00000000010205300000000000C2952000316 +:101DC0000000000022C5360000000010001F0000C7 +:101DD0000000000C6BD70001000000080F80000617 +:101DE000000000188000FFF200000000231B00002C +:101DF00000000000271108000000000066900000AD +:101E000000000010B1C8000B0000000C2980000089 +:101E100000000010205300000000000C29520000B8 +:101E20000000000C295200030000001006C200024E +:101E30000000000C295200020000000022C58C00A6 +:101E400000000000276500000000000026E40000FC +:101E500000000000234800000000000822000017D6 +:101E60000000000C2980000000000010001F00008E +:101E70000000000C6BD70001000000188000FE116C +:00000001FF +/* + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ diff --git a/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw.ihex b/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw.ihex deleted file mode 100644 index 533dbeaebd30..000000000000 --- a/firmware/bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw.ihex +++ /dev/null @@ -1,498 +0,0 @@ -:100000000000000000000E78000000580000000909 -:1000100000000000000000000000000000000000E0 -:1000200000000000000000000000000000000000D0 -:1000300000000FA800000ED0000000050000000026 -:1000400000000000000000000000000000000000B0 -:080050000000000000000000A8 -:0800580000000010B180000659 -:100060000000001F03030300000000080500FFFF5D -:10007000000000180002000000000008050000FF5A -:10008000000000180002000000000008AC000001A1 -:1000900000000000050000000000000C2F8000019F -:1000A000000000002B000000000000002B8000007A -:1000B0000000001091E0000200000008AC00000108 -:1000C00000000010203F006B00000010213F0003E3 -:1000D0000000001020BF003A000000188000FFFD63 -:1000E00000000010B1B8B0150000000B2FDF0002B7 -:1000F0000000000003D80000000000002C380000C1 -:10010000000000082C800000000000082D00000006 -:100110000000001091D400000000000806005555B2 -:10012000000000188000008F000000082D80011CD6 -:1001300000000008020000010000001091DE000035 -:100140000000000F42E0001C0000001091840A161D -:1001500000000018800000960000000C29800002BA -:100160000000000C1F800002000000002ADF0000D9 -:10017000000000082A00000F000000000500000039 -:10018000000000188000FFE60000000802000001E7 -:100190000000000F42E0001C0000001091840A18CB -:1001A000000000082C800006000000082D0000065A -:1001B0000000001091D40000000000082D8001060E -:1001C0000000001880000085000000188000FFF18A -:1001D00000000008B1000001000000082C80010CA4 -:1001E000000000082D000008000000082D8000011C -:1001F000000000188000007F0000000B2FDF0002CD -:100200000000000C1F800002000000002C0700000E -:100210000000001091DE00000000000805005555A8 -:10022000000000188000FFD20000000B2FDF00024A -:100230000000000C1F800000000000002C070000E0 -:100240000000001091DE0000000000080500555578 -:10025000000000188000FFCC0000000C1F8000028E -:100260000000000805005555000000188000FFC977 -:100270000000000C298000020000000C1F8000021A -:10028000000000002ADF0000000000082A0000052E -:100290000000000805005555000000188000FFC34D -:1002A000000000080224004A0000001800040000BA -:1002B000000000188000001C000000188000001ED4 -:1002C000000000188000007800000018800000CABC -:1002D00000000018800000C9000000188000000025 -:1002E00000000018800000000000001880000000DE -:1002F00000000018800000000000001880000000CE -:1003000000000018800000000000001880000000BD -:100310000000001880000000000000188000011597 -:10032000000000188000000000000018800000009D -:100330000000001880000015000000188000001B5D -:10034000000000188000000000000018800000E09D -:10035000000000188000002F000000188000011528 -:100360000000001880000140000000188000010B10 -:100370000000001880000164000000188000006187 -:100380000000001880000000000000188000009DA0 -:100390000000000C1F8000010000000005000000AC -:1003A000000000188000FFA20000001091D400009F -:1003B0000000000C298000010000000C1F800001DB -:1003C000000000082A0000020000000005000000F4 -:1003D000000000188000FF9C0000001091D4000075 -:1003E0000000000C298000010000000C1F800001AB -:1003F0000000000029420000000000082A0000025E -:100400000000000005000000000000188000FF95BB -:10041000000000188000FF9400000010B1BCB00A7A -:100420000000000B2FDF00020000000003D80000D6 -:10043000000000002C3C00000000001091D40000DF -:100440000000000806005555000000188000002A32 -:1004500000000018800000D9000000102C6201BAD2 -:100460000000001880000006000000082C80010D2C -:10047000000000082D0000090000001091D40000C9 -:10048000000000082D8001070000001880000037E0 -:100490000000000C298000000000000C1F800000FC -:1004A0000000001091DE0000000000002ADF0000C4 -:1004B000000000082A00000600000008050055554D -:1004C000000000188000FF7E0000001091D40000A2 -:1004D0000000000C298000010000000C1F800001BA -:1004E000000000082A00000B0000000005000000CA -:1004F000000000188000FF780000000002020000E9 -:1005000000000000029A000000000000060C2C0011 -:1005100000000004C60C340000000010001F0000A2 -:1005200000000010B196180C0000000806960004A8 -:1005300000000009068DFFFC00000004CD051A0034 -:1005400000000004CC9A18000000001020D7000022 -:100550000000000C2B56000000000000000000000E -:1005600000000000000000000000001020D7000084 -:10057000000000080F80000100000010B18001F4AD -:1005800000000010001F00000000000C6B5600006F -:1005900000000018000400000000000006820000B7 -:1005A00000000010B18A000800000010B18C140790 -:1005B0000000000B050AFFFF00000010B18A0003D5 -:1005C00000000000860A180000000010918C000056 -:1005D000000000082A0000010000001091D4000073 -:1005E00000000018000D00000000000005020000DF -:1005F0000000001091DE000000000018000A00005A -:1006000000000000068200000000001091DE0000E3 -:1006100000000010BEE10005000000188000FF4C43 -:10062000000000010561140000000010918A000222 -:1006300000000008B0E1000100000018000D0000FB -:1006400000000000068200000000001091DE0000A3 -:1006500000000010BEE20005000000188000FF440A -:10066000000000010562140000000010918A0002E1 -:1006700000000008B162000100000018000D000039 -:1006800000000010B1A0B0130000000B2FDF00022B -:10069000000000002C200000000000082C8000005A -:1006A000000000082D0000000000001091D40000A0 -:1006B0000000000806005555000000188000FFDC0F -:1006C000000000082D80011C00000010001F000029 -:1006D000000000188000FFE60000000F47600008DF -:1006E0000000000F060E0001000000000F5800007F -:1006F000000000000A640000000000000AE500009D -:10070000000000090B66FFFF000000000D61000003 -:1007100000000018800000130000000F4760000870 -:100720000000000B2FDF0002000000082C800000FA -:10073000000000082D0000000000001091D400000F -:10074000000000082D80011C0000000F060E0001B3 -:1007500000000010001F0000000000000F58000003 -:10076000000000188000FFD4000000000A640000B0 -:10077000000000000AE50000000000090B66FFFF12 -:10078000000000000D610000000000000262000097 -:100790000000000B2FDF0002000000003104000009 -:1007A00000000000309A0000000000090560000F02 -:1007B00000000010B18A000A0000000005634C0030 -:1007C00000000008050A001200000010B9621403BE -:1007D0000000000003000000000000188000000579 -:1007E000000000188000FF1100000010B60614037E -:1007F0000000000803060001000000188000FF1739 -:10080000000000188000FF9F0000000C29800001FC -:100810000000000C295200010000000C29520000C9 -:10082000000000080200000E000000080280001A0C -:1008300000000010B1C40A0200000008020000031A -:1008400000000008220000010000000C1F800001D1 -:10085000000000002ADF0000000000002A0008005D -:100860000000000805005555000000188000FF0931 -:100870000000000B2FDF00020000001091D40000E8 -:10088000000000082A000001000000002C200000E9 -:100890000000001091D40000000000082C8000002F -:1008A000000000082D000000000000082D80011C41 -:1008B000000000188000FFA7000000082C80000640 -:1008C000000000082D00000600000000308000003D -:1008D0000000000031000000000000082D8000062C -:1008E0000000000C298000010000000C1F800001A6 -:1008F0000000001091DE0000000000002ADF000070 -:10090000000000082A0000100000000005000000A0 -:10091000000000188000FEF40000001091A0B00953 -:10092000000000082C80010D000000082D000009C7 -:100930000000001091D40000000000082D80010785 -:10094000000000188000FFA00000001880000010C8 -:1009500000000008AC000001000000188000000B3F -:10096000000000000380B0000000000B2FDF000239 -:10097000000000002C0040000000001091D4000096 -:100980000000000806005555000000188000FF8296 -:1009900000000018800000310000001880000006F0 -:1009A0000000000B2FDF0002000000002C000E00F2 -:1009B000000000082A000007000000080500555547 -:1009C000000000188000FEDE00000000068200002B -:1009D0000000000C298000010000000C1F800001B5 -:1009E000000000100CE70007000000090562FFFF8F -:1009F00000000010BA6C1405000000002ADF00009F -:100A00000000000021000000000000082A0000058E -:100A10000000001091D40000000000082C80010CA0 -:100A2000000000082D0000080000000C31620018D2 -:100A3000000000082D800001000000188000FF76F3 -:100A400000000018000D000000000010B1A0B00E62 -:100A50000000000B2FDF00020000000003D80000A0 -:100A6000000000002C2000000000001091D40000C5 -:100A70000000001880000015000000102C62000229 -:100A8000000000188000000C0000000B2FDF0002A7 -:100A9000000000002C0700000000000C1F80000177 -:100AA0000000001091DE0000000000080500FFFFBC -:100AB000000000188000FEC0000000082C80010D1E -:100AC000000000082D0000090000001091D4000073 -:100AD000000000082D800107000000188000FF6D55 -:100AE0000000000C298000010000000C1F800001A4 -:100AF0000000001091DE0000000000002ADF00006E -:100B0000000000082A00000A0000000005000000A4 -:100B1000000000188000FEB4000000000682000003 -:100B2000000000082C80010C000000082D000008C7 -:100B3000000000082D8001340000000000000000CB -:100B400000000010205F0000000000082C80014021 -:100B5000000000082D00003C000000082D80011C52 -:100B600000000000000000000000001091DE000006 -:100B7000000000082C800080000000082D0000000C -:100B8000000000082D80010500000010BEE20005F5 -:100B9000000000188000FE9D0000000105621400A6 -:100BA00000000010918A000200000008B1620001FC -:100BB0000000001091DE000000000018000D000091 -:100BC0000000001091D40000000000080600AAAA4E -:100BD000000000188000FF390000000C298000018F -:100BE0000000000C1F800001000000082A0000091E -:100BF000000000080500AAAA000000188000FE9767 -:100C00000000001091D400000000000806005555B7 -:100C1000000000188000FF310000001091A03C028D -:100C200000000010B1E662070000000B2FDF000299 -:100C3000000000002C310000000000092CB1007FF2 -:100C4000000000082CD90000000000082D00000062 -:100C5000000000082D80010D00000010B1A8000662 -:100C600000000010205F0000000000002C200000A9 -:100C7000000000002CA70000000000082D0000105C -:100C8000000000082D800108000000188000FF2CE3 -:100C900000000010B1A6001000000010001F0000AE -:100CA0000000000F0F300007000000000A60000085 -:100CB000000000000AE100000000000F4B62000885 -:100CC000000000090B1600FF000000000D6200008C -:100CD000000000090D1A00FF00000010073000039B -:100CE0000000000C0D1A00080000000C0B16000894 -:100CF0000000000F4CE30018000000000C992C00CD -:100D000000000004CC993400000000080F800000AF -:100D10000000000C298000010000000033310000B9 -:100D20000000000822000016000000002ADF00007A -:100D3000000000082A00000C00000010009F0000C6 -:100D4000000000000F2000000000000C1F800001C8 -:100D50000000000805005555000000188000FE6BDB -:100D60000000001091D40000000000080600AAAAAC -:100D7000000000188000FF050000000F4722000857 -:100D800000000009070E000F00000008070E000811 -:100D900000000008028000010000000702851C001E -:100DA00000000008828500010000000002854C0060 -:100DB0000000000742851C0000000003C3AA520087 -:100DC0000000000003B10E00000000074B071C00EC -:100DD0000000000F0F3000070000000F0A9600030C -:100DE000000000000A955C00000000004A005A0064 -:100DF000000000000C960A00000000090C99FFFF9B -:100E0000000000080D00FFFF00000010B196320244 -:100E1000000000080F80000500000010B1A80008C5 -:100E200000000010205F00000000000B2FDF000218 -:100E3000000000002C200000000000002CA7000093 -:100E4000000000082D000010000000082D8001089F -:100E5000000000188000FEF30000000C2980000153 -:100E600000000010001F00000000000C1F800001A7 -:100E7000000000002ADF0000000000082A00000D2A -:100E8000000000080500AAAA000000188000FE4526 -:100E90000000001091D40000000000080600555525 -:100EA000000000188000FEDF0000000C2980000117 -:100EB0000000000C1F800001000000082A0000074D -:100EC0000000000805005555000000188000FE3D98 -:100ED00000000010B18000040000001F03030300A5 -:100EE00000000008050000FF0000001800020000DC -:100EF000000000002A00000000000010B1D4000033 -:100F00000000001091DE00000000001020530000DF -:100F100000000010001F00000000000C6BD7000153 -:100F2000000000002F80AA000000000C29800001B2 -:100F3000000000080254000F000000002C400000D8 -:100F4000000000092952003F0000001800040000C2 -:100F50000000001880000010000000188000001140 -:100F6000000000188000004A0000001880000128DE -:100F700000000018800001270000001880000126F2 -:100F8000000000188000012600000018800000000A -:100F9000000000188000013F0000001880000122BE -:100FA000000000188000000B0000001880000145C0 -:100FB000000000188000019A000000188000007BEB -:100FC00000000018800000F90000001880000109EE -:100FD000000000002A000000000000188000FFE46C -:100FE000000000002A0000000000000C2980000022 -:100FF000000000188000FFE1000000002A0000004F -:10100000000000188000FFDF0000000003820000E5 -:10101000000000188000FFDA000000010C16140028 -:10102000000000008C1814000000001091980003CC -:10103000000000080C96000200000010B1800003C0 -:10104000000000080C960001000000000C000000E9 -:10105000000000000D1900000000001020560000E4 -:101060000000000C2BD70001000000080F800001D9 -:10107000000000000000000000000010001F000041 -:101080000000000C6BD7000100000010011301F1FB -:10109000000000180007000000000000050200002A -:1010A000000000109196342100000010205F000025 -:1010B000000000002C1E0000000000082C8000062C -:1010C000000000082D000006000000082D8001022D -:1010D00000000000000000000000001091DE000091 -:1010E000000000000D61000000000018000A000070 -:1010F0000000000005020000000000109196341668 -:1011000000000010205F00000000000009D800006F -:10111000000000002C1E0000000000082C80010EC2 -:10112000000000082D00000A000000082D800102C8 -:1011300000000000000000000000001091DE000030 -:10114000000000000D620000000000002C130000F1 -:1011500000000018000A0000000000000502000066 -:10116000000000109196340900000010205F00007C -:10117000000000002C1E0000000000082C8000066B -:10118000000000082D00006A000000082D80010208 -:1011900000000000000000000000001091DE0000D0 -:1011A000000000000D7A000000000018000A000096 -:1011B000000000002A000000000000000D61000097 -:1011C000000000000362000000000010234200DB6A -:1011D0000000000002638C000000000026460000B2 -:1011E000000000080204001200000010B906082EDA -:1011F000000000000F580000000000000A6400001A -:10120000000000000AE50000000000090B66FFFF77 -:10121000000000000C000000000000000B80000037 -:10122000000000080CC60012000000188000FFCE6D -:1012300000000010205600000000000C2BD7000119 -:10124000000000080F800003000000000000000004 -:1012500000000010001F00000000000C6BD7000110 -:101260000000000827110012000000006690000036 -:1012700000000008A31B001200000010B198000637 -:1012800000000010001F00000000000C6BD70001E0 -:1012900000000010205600000000000C2BD70001B9 -:1012A000000000080F800004000000082200000376 -:1012B000000000082C80000C000000082D00000C2D -:1012C00000000010001F00000000000C6BD70001A0 -:1012D00000000000259600000000000C298000009E -:1012E0000000000006660000000000008661180093 -:1012F000000000090260000F0000000F020400025D -:1013000000000010B60C08050000000C1FBF000014 -:10131000000000102866000300000008078F00018D -:101320000000000C336600100000000032140000C2 -:1013300000000000329500000000000573662C00DC -:101340000000000031E32E00000000082D80001096 -:10135000000000188000FF7500000000230000005E -:101360000000000925E6FFFF000000082200000B36 -:101370000000000C695200000000000C29800000F1 -:101380000000001028660088000000188000FF6E32 -:10139000000000002A000000000000082C8000402F -:1013A000000000082D000020000000082D80011C16 -:1013B00000000000000000000000001091DE0000AE -:1013C0000000000F42EA001000000010004F00046F -:1013D00000000010B7469200000000080249001209 -:1013E00000000010B5840A00000000000D6100003C -:1013F00000000010BA66346A00000008830500127D -:1014000000000010004F000200000000034900002F -:101410000000000183068C000000000083C60C0061 -:1014200000000010B1870011000000000B6E0000EA -:1014300000000010BEE90005000000188000FF5504 -:10144000000000010569140000000010918A0002EC -:1014500000000008B4E9000100000010B1E92C5DB3 -:101460000000000086692C0000000000020000005F -:101470000000000902EAFFFF00000010000C00025B -:101480000000000002040A000000000F460C0001EA -:101490000000000F0285000100000010918C01FC8B -:1014A00000000010B7040E54000000000F400000C0 -:1014B000000000000D610000000000000A64000050 -:1014C000000000000AE50000000000090B66FFFFB5 -:1014D000000000000C000000000000000B80000075 -:1014E000000000080C8600120000001020560000CA -:1014F0000000000C2BD70001000000080F80000343 -:101500000000000C2952000000000010001F000025 -:101510000000000C6BD7000100000008271100122A -:101520000000000066900000000000002646000059 -:10153000000000002306000000000010B198000920 -:1015400000000010001F00000000000C6BD700011D -:1015500000000010205600000000000C2BD70001F6 -:10156000000000080F8000040000000000000000E0 -:1015700000000010001F00000000000C6BD70001ED -:10158000000000003214000000000000329500004E -:101590000000000031E32E000000000573662C00FF -:1015A000000000002596000000000010B187002117 -:1015B0000000000C298000000000000F0F6B0007E6 -:1015C000000000000D690000000000000A6C00002F -:1015D000000000000AED0000000000000B6E00009B -:1015E000000000000B800000000000000C870000DD -:1015F000000000188000FF1E000000010C161400FF -:10160000000000008C181400000000080C96000177 -:101610000000001091980002000000080C990001E1 -:10162000000000000D190000000000000C00000088 -:1016300000000010205600000000000C2BD7000115 -:10164000000000080F80000100000010205300007F -:101650000000000C6952000100000010001F000093 -:101660000000000C6BD700010000000022C58C00B8 -:1016700000000000231200000000000027110000FD -:10168000000000002690000000000010B8170E03B4 -:101690000000000C29800000000000188000FFEB13 -:1016A0000000000082970E0000000000A3120A0054 -:1016B000000000082200001A000000082C80000C26 -:1016C000000000082D00000C000000082D80001014 -:1016D00000000010001F00000000000C6BD700018C -:1016E000000000000D6E000000000003E7CF340092 -:1016F0000000000C298000000000001091DE0000B6 -:1017000000000010B1870007000000003614000040 -:1017100000000000369500000000000037160000B1 -:10172000000000082C800050000000082D00003050 -:10173000000000082D80000C000000188000FEF85A -:10174000000000002646000000000000230000000A -:101750000000000925E6FFFF000000000B6E0000FE -:1017600000000003E7CF2C00000000082200001B4F -:101770000000000C695200000000000C29800000ED -:10178000000000188000FEEF000000002A000000AA -:10179000000000100866000500000000066600005A -:1017A000000000008661180000000009026000F0DF -:1017B00000000010B60C0802000000188000FEE8CF -:1017C000000000000682000000000010B18F000041 -:1017D00000000008878F00010000000C73660010F5 -:1017E000000000082C800018000000082D000018E0 -:1017F000000000082D8000020000000C5FBF000008 -:101800000000001091DE000000000018000D000034 -:10181000000000002A00000000000010286601F50A -:10182000000000082C800003000000082D000003C9 -:10183000000000093060FFF0000000082D8000016A -:101840000000000C298000000000001091DE000064 -:10185000000000082C80001A000000082D00001A6B -:101860000000000573660000000000082D800002E3 -:1018700000000000318000000000001091DE000038 -:10188000000000082C80000C000000082D00000C57 -:10189000000000082D800004000000188000FECC2D -:1018A0000000001800020000000000188000FECABE -:1018B000000000002A00000000000010001F0000CF -:1018C0000000000C6BD70001000000000F0080003A -:1018D000000000080F800007000000188000001BB7 -:1018E00000000000280A00000000000005020000BF -:1018F000000000082200000900000000290000008C -:101900000000000F6568001000000003F66C9400F2 -:1019100000000010B972A0040000000C73E7001969 -:101920000000000C21420004000000003CF8000010 -:101930000000000C2980000000000010205300006F -:1019400000000008220000080000000C61420004B2 -:1019500000000018000A000000000000050200005E -:101960000000000C61420000000000100142000372 -:101970000000000C33E7001D0000000C6142000273 -:1019800000000018000A0000000000002A0000000B -:1019900000000010001F00000000000C6BD70001C9 -:1019A0000000000F0F470007000000080F8000082C -:1019B0000000000C2980000000000010001F000043 -:1019C0000000000C6BD70001000000188000FEA68C -:1019D0000000000033510000000000002A00000059 -:1019E00000000010B1C600290000000F0F500007D2 -:1019F000000000000A600000000000000AE1000092 -:101A00000000000F4B620008000000090B1600FFE9 -:101A10000000000F4C620010000000000D6200008A -:101A2000000000090D1A00FF00000010075000031D -:101A30000000000C0D1A00080000000C0B16000836 -:101A4000000000000CC60000000000000B80000039 -:101A50000000000006980000000000102056000062 -:101A60000000000C2BD70001000000080F800003CD -:101A70000000001006C200040000000C2900000253 -:101A800000000010264200020000000C2952000352 -:101A9000000000082200000100000010001F0000EC -:101AA0000000000C6BD7000100000000231B0000A9 -:101AB0000000000027111A000000000066900000DE -:101AC0000000000C2952000000000010B197320CF9 -:101AD0000000000C298000000000000006980000B3 -:101AE00000000010205300000000000C29520003E9 -:101AF0000000000022C58C0000000010001F000044 -:101B00000000000C6BD70001000000102056000000 -:101B10000000000C2BD70001000000080F8000031C -:101B2000000000188000FFEF00000010B1C8001393 -:101B300000000010B1C600030000000C2980000066 -:101B400000000010205300000000000C295200008B -:101B50000000000C295200030000001006C2000221 -:101B60000000000C295200020000000022C58C0079 -:101B700000000000276500000000000026E40000CF -:101B8000000000082200001600000010B1C600038B -:101B9000000000002348000000000010B180000594 -:101BA00000000000234800000000000C2980000015 -:101BB0000000000F0F500007000000188000001206 -:101BC00000000008220000160000000C2980000020 -:101BD00000000000301400000000000030950000FC -:101BE0000000001007500003000000090B1600FF62 -:101BF000000000090D1A00FF0000000F3116000858 -:101C0000000000003162340000000003F162300087 -:101C100000000010205F0000000000002C510000B8 -:101C2000000000092CD1007F000000082CD9000022 -:101C3000000000082D000000000000082D80000CAE -:101C400000000000000000000000001091DE000015 -:101C50000000001005C20005000000080F8000070A -:101C6000000000003300000000000010001F000012 -:101C70000000000C6BD70001000000188000FE502F -:101C8000000000002A0000000000000F0F500007B5 -:101C900000000010B1C600300000000F47420008ED -:101CA00000000009070E000F00000008070E0008E2 -:101CB00000000010001F00000000000C6BD70001A6 -:101CC00000000008090000010000000709121C00C4 -:101CD00000000003CBCA9200000000000B97A20096 -:101CE0000000000742171C00000000000B04000069 -:101CF0000000000F0A840003000000000A959C0009 -:101D0000000000004A009A00000000088212000152 -:101D1000000000010C170800000000000C978C0068 -:101D20000000000002180000000000080D00FFFF86 -:101D3000000000080F8000060000000C29000000D1 -:101D40000000001006C200040000000C295200022E -:101D500000000010264200020000000C295200037F -:101D6000000000082200000100000010001F000019 -:101D70000000000C6BD7000100000010B197320D7D -:101D800000000000231B00000000000027110800D5 -:101D900000000000669000000000000C2980000098 -:101DA0000000000002180000000000102053000096 -:101DB0000000000C295200030000000022C536007C -:101DC00000000010001F00000000000C6BD7000195 -:101DD000000000080F800006000000188000FFF2DD -:101DE00000000000231B0000000000002711080075 -:101DF000000000006690000000000010B1C8000B59 -:101E00000000000C2980000000000010205300009A -:101E10000000000C295200000000000C29520003B1 -:101E20000000001006C200020000000C295200024F -:101E30000000000022C58C000000000027650000A3 -:101E40000000000026E4000000000000234800001D -:101E500000000008220000170000000C298000008C -:101E600000000010001F00000000000C6BD70001F4 -:081E7000000000188000FE11C3 -:00000001FF -/* - * This file contains firmware data derived from proprietary unpublished - * source code, Copyright (c) 2004 - 2009 Broadcom Corporation. - * - * Permission is hereby granted for the distribution of this firmware data - * in hexadecimal or equivalent format, provided this copyright notice is - * accompanying it. - */ -- cgit v1.2.3 From 177867ce08f2756fa361e37086fc1792d7b4cf29 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 16 Feb 2010 15:23:23 -0800 Subject: sparc64: Kill bogus ip_tables.h include. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following build failure: CC arch/sparc/kernel/sys_sparc32.o In file included from include/linux/netfilter_ipv4/ip_tables.h:28, from arch/sparc/kernel/sys_sparc32.c:46: include/linux/netfilter/x_tables.h:525: error: expected declaration specifiers or ‘...’ before ‘nf_hookfn’ Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc32.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index dc0ac197e7e2..daded3b96398 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 6909c66dfbbab99dbbd9931627c9f6e8c45bfbdb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:20 +0000 Subject: drivers/net/ixgb: Use netif_printk macros Convert private DPRINTK macro uses to netif_ equivalents Remove #define DPRINTK Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ixgb/ixgb.h | 11 ++---- drivers/net/ixgb/ixgb_main.c | 89 ++++++++++++++++++++++++-------------------- 2 files changed, 51 insertions(+), 49 deletions(-) diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 5257ae08b9f9..92d2e71d0c8b 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h @@ -75,19 +75,14 @@ struct ixgb_adapter; #include "ixgb_ee.h" #include "ixgb_ids.h" +#define PFX "ixgb: " + #ifdef _DEBUG_DRIVER_ -#define IXGB_DBG(args...) printk(KERN_DEBUG "ixgb: " args) +#define IXGB_DBG(args...) printk(KERN_DEBUG PFX args) #else #define IXGB_DBG(args...) #endif -#define PFX "ixgb: " -#define DPRINTK(nlevel, klevel, fmt, args...) \ - (void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ - __func__ , ## args)) - - /* TX/RX descriptor defines */ #define DEFAULT_TXD 256 #define MAX_TXD 4096 diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 6a7b2ccef72c..93d018505ebb 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -238,8 +238,8 @@ ixgb_up(struct ixgb_adapter *adapter) if (err) { if (adapter->have_msi) pci_disable_msi(adapter->pdev); - DPRINTK(PROBE, ERR, - "Unable to allocate interrupt Error: %d\n", err); + netif_err(adapter, probe, adapter->netdev, + "Unable to allocate interrupt Error: %d\n", err); return err; } @@ -310,7 +310,7 @@ ixgb_reset(struct ixgb_adapter *adapter) ixgb_adapter_stop(hw); if (!ixgb_init_hw(hw)) - DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n"); + netif_err(adapter, probe, adapter->netdev, "ixgb_init_hw failed\n"); /* restore frame size information */ IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT); @@ -447,7 +447,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* make sure the EEPROM is good */ if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { - DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n"); + netif_err(adapter, probe, adapter->netdev, + "The EEPROM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; } @@ -456,7 +457,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { - DPRINTK(PROBE, ERR, "Invalid MAC Address\n"); + netif_err(adapter, probe, adapter->netdev, "Invalid MAC Address\n"); err = -EIO; goto err_eeprom; } @@ -477,7 +478,8 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* carrier off reporting is important to ethtool even BEFORE open */ netif_carrier_off(netdev); - DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n"); + netif_info(adapter, probe, adapter->netdev, + "Intel(R) PRO/10GbE Network Connection\n"); ixgb_check_options(adapter); /* reset the hardware with the new settings */ @@ -552,14 +554,14 @@ ixgb_sw_init(struct ixgb_adapter *adapter) hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH; adapter->rx_buffer_len = hw->max_frame_size + 8; /* + 8 for errata */ - if ((hw->device_id == IXGB_DEVICE_ID_82597EX) - || (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4) - || (hw->device_id == IXGB_DEVICE_ID_82597EX_LR) - || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR)) + if ((hw->device_id == IXGB_DEVICE_ID_82597EX) || + (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4) || + (hw->device_id == IXGB_DEVICE_ID_82597EX_LR) || + (hw->device_id == IXGB_DEVICE_ID_82597EX_SR)) hw->mac_type = ixgb_82597; else { /* should never have loaded on this device */ - DPRINTK(PROBE, ERR, "unsupported device id\n"); + netif_err(adapter, probe, adapter->netdev, "unsupported device id\n"); } /* enable flow control to be programmed */ @@ -661,8 +663,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter) size = sizeof(struct ixgb_buffer) * txdr->count; txdr->buffer_info = vmalloc(size); if (!txdr->buffer_info) { - DPRINTK(PROBE, ERR, - "Unable to allocate transmit descriptor ring memory\n"); + netif_err(adapter, probe, adapter->netdev, + "Unable to allocate transmit descriptor ring memory\n"); return -ENOMEM; } memset(txdr->buffer_info, 0, size); @@ -675,8 +677,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter) txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if (!txdr->desc) { vfree(txdr->buffer_info); - DPRINTK(PROBE, ERR, - "Unable to allocate transmit descriptor memory\n"); + netif_err(adapter, probe, adapter->netdev, + "Unable to allocate transmit descriptor memory\n"); return -ENOMEM; } memset(txdr->desc, 0, txdr->size); @@ -750,8 +752,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter) size = sizeof(struct ixgb_buffer) * rxdr->count; rxdr->buffer_info = vmalloc(size); if (!rxdr->buffer_info) { - DPRINTK(PROBE, ERR, - "Unable to allocate receive descriptor ring\n"); + netif_err(adapter, probe, adapter->netdev, + "Unable to allocate receive descriptor ring\n"); return -ENOMEM; } memset(rxdr->buffer_info, 0, size); @@ -765,8 +767,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter) if (!rxdr->desc) { vfree(rxdr->buffer_info); - DPRINTK(PROBE, ERR, - "Unable to allocate receive descriptors\n"); + netif_err(adapter, probe, adapter->netdev, + "Unable to allocate receive descriptors\n"); return -ENOMEM; } memset(rxdr->desc, 0, rxdr->size); @@ -1580,7 +1582,8 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu) /* MTU < 68 is an error for IPv4 traffic, just don't allow it */ if ((new_mtu < 68) || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) { - DPRINTK(PROBE, ERR, "Invalid MTU setting %d\n", new_mtu); + netif_err(adapter, probe, adapter->netdev, + "Invalid MTU setting %d\n", new_mtu); return -EINVAL; } @@ -1854,24 +1857,25 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter) && !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF)) { /* detected Tx unit hang */ - DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n" - " TDH <%x>\n" - " TDT <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " next_to_watch <%x>\n" - " jiffies <%lx>\n" - " next_to_watch.status <%x>\n", - IXGB_READ_REG(&adapter->hw, TDH), - IXGB_READ_REG(&adapter->hw, TDT), - tx_ring->next_to_use, - tx_ring->next_to_clean, - tx_ring->buffer_info[eop].time_stamp, - eop, - jiffies, - eop_desc->status); + netif_err(adapter, drv, adapter->netdev, + "Detected Tx Unit Hang\n" + " TDH <%x>\n" + " TDT <%x>\n" + " next_to_use <%x>\n" + " next_to_clean <%x>\n" + "buffer_info[next_to_clean]\n" + " time_stamp <%lx>\n" + " next_to_watch <%x>\n" + " jiffies <%lx>\n" + " next_to_watch.status <%x>\n", + IXGB_READ_REG(&adapter->hw, TDH), + IXGB_READ_REG(&adapter->hw, TDT), + tx_ring->next_to_use, + tx_ring->next_to_clean, + tx_ring->buffer_info[eop].time_stamp, + eop, + jiffies, + eop_desc->status); netif_stop_queue(netdev); } } @@ -2269,7 +2273,8 @@ static pci_ers_result_t ixgb_io_slot_reset(struct pci_dev *pdev) struct ixgb_adapter *adapter = netdev_priv(netdev); if (pci_enable_device(pdev)) { - DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n"); + netif_err(adapter, probe, adapter->netdev, + "Cannot re-enable PCI device after reset\n"); return PCI_ERS_RESULT_DISCONNECT; } @@ -2285,14 +2290,16 @@ static pci_ers_result_t ixgb_io_slot_reset(struct pci_dev *pdev) /* Make sure the EEPROM is good */ if (!ixgb_validate_eeprom_checksum(&adapter->hw)) { - DPRINTK(PROBE, ERR, "After reset, the EEPROM checksum is not valid.\n"); + netif_err(adapter, probe, adapter->netdev, + "After reset, the EEPROM checksum is not valid\n"); return PCI_ERS_RESULT_DISCONNECT; } ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr); memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { - DPRINTK(PROBE, ERR, "After reset, invalid MAC address.\n"); + netif_err(adapter, probe, adapter->netdev, + "After reset, invalid MAC address\n"); return PCI_ERS_RESULT_DISCONNECT; } -- cgit v1.2.3 From 6c35abaedc191e2c7c8fa40a2b4c2b01d553b768 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:21 +0000 Subject: drivers/net/sky2: Convert to use netif_printk macros Some unlikely(netif_msg_(sky2)) tests are also removed by this change. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/sky2.c | 65 +++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index dfff8e56a51e..a1198f141996 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1613,8 +1613,7 @@ static int sky2_up(struct net_device *dev) sky2_write32(hw, B0_IMSK, imask); sky2_read32(hw, B0_IMSK); - if (netif_msg_ifup(sky2)) - printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); + netif_info(sky2, ifup, dev, "enabling interface\n"); return 0; @@ -1697,9 +1696,8 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb, goto mapping_error; slot = sky2->tx_prod; - if (unlikely(netif_msg_tx_queued(sky2))) - printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n", - dev->name, slot, skb->len); + netif_printk(sky2, tx_queued, KERN_DEBUG, dev, + "tx queued, slot %u, len %d\n", slot, skb->len); /* Send high bits if needed */ upper = upper_32_bits(mapping); @@ -1864,9 +1862,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) sky2_tx_unmap(sky2->hw->pdev, re); if (skb) { - if (unlikely(netif_msg_tx_done(sky2))) - printk(KERN_DEBUG "%s: tx done %u\n", - dev->name, idx); + netif_printk(sky2, tx_done, KERN_DEBUG, dev, + "tx done %u\n", idx); dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -1961,8 +1958,7 @@ static int sky2_down(struct net_device *dev) if (!sky2->tx_le) return 0; - if (netif_msg_ifdown(sky2)) - printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); + netif_info(sky2, ifdown, dev, "disabling interface\n"); /* Disable port IRQ */ sky2_write32(hw, B0_IMSK, @@ -2028,12 +2024,11 @@ static void sky2_link_up(struct sky2_port *sky2) sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); - if (netif_msg_link(sky2)) - printk(KERN_INFO PFX - "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", - sky2->netdev->name, sky2->speed, - sky2->duplex == DUPLEX_FULL ? "full" : "half", - fc_name[sky2->flow_status]); + netif_info(sky2, link, sky2->netdev, + "Link is up at %d Mbps, %s duplex, flow control %s\n", + sky2->speed, + sky2->duplex == DUPLEX_FULL ? "full" : "half", + fc_name[sky2->flow_status]); } static void sky2_link_down(struct sky2_port *sky2) @@ -2053,8 +2048,7 @@ static void sky2_link_down(struct sky2_port *sky2) /* Turn off link LED */ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - if (netif_msg_link(sky2)) - printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name); + netif_info(sky2, link, sky2->netdev, "Link is down\n"); sky2_phy_init(hw, port); } @@ -2144,9 +2138,8 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - if (netif_msg_intr(sky2)) - printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", - sky2->netdev->name, istatus, phystat); + netif_info(sky2, intr, sky2->netdev, "phy interrupt status 0x%x 0x%x\n", + istatus, phystat); if (istatus & PHY_M_IS_AN_COMPL) { if (sky2_autoneg_done(sky2, phystat) == 0) @@ -2200,8 +2193,7 @@ static void sky2_tx_timeout(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; - if (netif_msg_timer(sky2)) - printk(KERN_ERR PFX "%s: tx timeout\n", dev->name); + netif_err(sky2, timer, dev, "tx timeout\n"); printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", dev->name, sky2->tx_cons, sky2->tx_prod, @@ -2396,9 +2388,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev, count -= VLAN_HLEN; #endif - if (unlikely(netif_msg_rx_status(sky2))) - printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n", - dev->name, sky2->rx_next, status, length); + netif_printk(sky2, rx_status, KERN_DEBUG, dev, + "rx slot %u status 0x%x len %d\n", + sky2->rx_next, status, length); sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending; prefetch(sky2->rx_ring + sky2->rx_next); @@ -2439,9 +2431,10 @@ len_error: /* Truncation of overlength packets causes PHY length to not match MAC length */ ++dev->stats.rx_length_errors; - if (netif_msg_rx_err(sky2) && net_ratelimit()) - pr_info(PFX "%s: rx length error: status %#x length %d\n", - dev->name, status, length); + if (net_ratelimit()) + netif_info(sky2, rx_err, dev, + "rx length error: status %#x length %d\n", + status, length); goto resubmit; error: @@ -2451,9 +2444,9 @@ error: goto resubmit; } - if (netif_msg_rx_err(sky2) && net_ratelimit()) - printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n", - dev->name, status, length); + if (net_ratelimit()) + netif_info(sky2, rx_err, dev, + "rx error, status 0x%x length %d\n", status, length); if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE)) dev->stats.rx_length_errors++; @@ -2733,9 +2726,7 @@ static void sky2_mac_intr(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(dev); u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); - if (netif_msg_intr(sky2)) - printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n", - dev->name, status); + netif_info(sky2, intr, dev, "mac interrupt status 0x%x\n", status); if (status & GM_IS_RX_CO_OV) gma_read16(hw, port, GM_RX_IRQ_SRC); @@ -4529,9 +4520,7 @@ static void __devinit sky2_show_addr(struct net_device *dev) { const struct sky2_port *sky2 = netdev_priv(dev); - if (netif_msg_probe(sky2)) - printk(KERN_INFO PFX "%s: addr %pM\n", - dev->name, dev->dev_addr); + netif_info(sky2, probe, dev, "addr %pM\n", dev->dev_addr); } /* Handle software interrupt used during MSI test */ -- cgit v1.2.3 From 865a21a5e3d1b384c559a44c898fcad93e187b82 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:22 +0000 Subject: drivers/net/tehuti.c: Use (pr|netdev|netif)_ macro helpers Make the output logging messages a bit more consistent. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 88 ++++++++++++++++++++++++---------------------------- drivers/net/tehuti.h | 30 +++++++++++------- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index ab9b0280317e..82e522a114d2 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -62,9 +62,11 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "tehuti.h" -static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = { +static struct pci_device_id __devinitdata bdx_pci_tbl[] = { {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, @@ -105,26 +107,24 @@ static void print_hw_id(struct pci_dev *pdev) pci_read_config_word(pdev, PCI_LINK_STATUS_REG, &pci_link_status); pci_read_config_word(pdev, PCI_DEV_CTRL_REG, &pci_ctrl); - printk(KERN_INFO "tehuti: %s%s\n", BDX_NIC_NAME, - nic->port_num == 1 ? "" : ", 2-Port"); - printk(KERN_INFO - "tehuti: srom 0x%x fpga %d build %u lane# %d" - " max_pl 0x%x mrrs 0x%x\n", - readl(nic->regs + SROM_VER), readl(nic->regs + FPGA_VER) & 0xFFF, - readl(nic->regs + FPGA_SEED), - GET_LINK_STATUS_LANES(pci_link_status), - GET_DEV_CTRL_MAXPL(pci_ctrl), GET_DEV_CTRL_MRRS(pci_ctrl)); + pr_info("%s%s\n", BDX_NIC_NAME, + nic->port_num == 1 ? "" : ", 2-Port"); + pr_info("srom 0x%x fpga %d build %u lane# %d max_pl 0x%x mrrs 0x%x\n", + readl(nic->regs + SROM_VER), readl(nic->regs + FPGA_VER) & 0xFFF, + readl(nic->regs + FPGA_SEED), + GET_LINK_STATUS_LANES(pci_link_status), + GET_DEV_CTRL_MAXPL(pci_ctrl), GET_DEV_CTRL_MRRS(pci_ctrl)); } static void print_fw_id(struct pci_nic *nic) { - printk(KERN_INFO "tehuti: fw 0x%x\n", readl(nic->regs + FW_VER)); + pr_info("fw 0x%x\n", readl(nic->regs + FW_VER)); } static void print_eth_id(struct net_device *ndev) { - printk(KERN_INFO "%s: %s, Port %c\n", ndev->name, BDX_NIC_NAME, - (ndev->if_port == 0) ? 'A' : 'B'); + netdev_info(ndev, "%s, Port %c\n", + BDX_NIC_NAME, (ndev->if_port == 0) ? 'A' : 'B'); } @@ -160,7 +160,7 @@ bdx_fifo_init(struct bdx_priv *priv, struct fifo *f, int fsz_type, f->va = pci_alloc_consistent(priv->pdev, memsz + FIFO_EXTRA_SPACE, &f->da); if (!f->va) { - ERR("pci_alloc_consistent failed\n"); + pr_err("pci_alloc_consistent failed\n"); RET(-ENOMEM); } f->reg_CFG0 = reg_CFG0; @@ -204,13 +204,13 @@ static void bdx_link_changed(struct bdx_priv *priv) if (netif_carrier_ok(priv->ndev)) { netif_stop_queue(priv->ndev); netif_carrier_off(priv->ndev); - ERR("%s: Link Down\n", priv->ndev->name); + netdev_err(priv->ndev, "Link Down\n"); } } else { if (!netif_carrier_ok(priv->ndev)) { netif_wake_queue(priv->ndev); netif_carrier_on(priv->ndev); - ERR("%s: Link Up\n", priv->ndev->name); + netdev_err(priv->ndev, "Link Up\n"); } } } @@ -226,10 +226,10 @@ static void bdx_isr_extra(struct bdx_priv *priv, u32 isr) bdx_link_changed(priv); if (isr & IR_PCIE_LINK) - ERR("%s: PCI-E Link Fault\n", priv->ndev->name); + netdev_err(priv->ndev, "PCI-E Link Fault\n"); if (isr & IR_PCIE_TOUT) - ERR("%s: PCI-E Time Out\n", priv->ndev->name); + netdev_err(priv->ndev, "PCI-E Time Out\n"); } @@ -345,7 +345,7 @@ out: release_firmware(fw); if (rc) { - ERR("%s: firmware loading failed\n", priv->ndev->name); + netdev_err(priv->ndev, "firmware loading failed\n"); if (rc == -EIO) DBG("VPC = 0x%x VIC = 0x%x INIT_STATUS = 0x%x i=%d\n", READ_REG(priv, regVPC), @@ -462,7 +462,7 @@ static int bdx_hw_reset_direct(void __iomem *regs) readl(regs + regRXD_CFG0_0); return 0; } - ERR("tehuti: HW reset failed\n"); + pr_err("HW reset failed\n"); return 1; /* failure */ } @@ -486,7 +486,7 @@ static int bdx_hw_reset(struct bdx_priv *priv) READ_REG(priv, regRXD_CFG0_0); return 0; } - ERR("tehuti: HW reset failed\n"); + pr_err("HW reset failed\n"); return 1; /* failure */ } @@ -510,8 +510,7 @@ static int bdx_sw_reset(struct bdx_priv *priv) mdelay(10); } if (i == 50) - ERR("%s: SW reset timeout. continuing anyway\n", - priv->ndev->name); + netdev_err(priv->ndev, "SW reset timeout. continuing anyway\n"); /* 6. disable intrs */ WRITE_REG(priv, regRDINTCM0, 0); @@ -647,7 +646,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd) if (cmd != SIOCDEVPRIVATE) { error = copy_from_user(data, ifr->ifr_data, sizeof(data)); if (error) { - ERR("cant copy from user\n"); + pr_err("cant copy from user\n"); RET(error); } DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); @@ -708,7 +707,7 @@ static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable) ENTER; DBG2("vid=%d value=%d\n", (int)vid, enable); if (unlikely(vid >= 4096)) { - ERR("tehuti: invalid VID: %u (> 4096)\n", vid); + pr_err("invalid VID: %u (> 4096)\n", vid); RET(); } reg = regVLAN_0 + (vid / 32) * 4; @@ -776,8 +775,8 @@ static int bdx_change_mtu(struct net_device *ndev, int new_mtu) /* enforce minimum frame size */ if (new_mtu < ETH_ZLEN) { - ERR("%s: %s mtu %d is less then minimal %d\n", - BDX_DRV_NAME, ndev->name, new_mtu, ETH_ZLEN); + netdev_err(ndev, "mtu %d is less then minimal %d\n", + new_mtu, ETH_ZLEN); RET(-EINVAL); } @@ -1038,7 +1037,7 @@ static int bdx_rx_init(struct bdx_priv *priv) return 0; err_mem: - ERR("%s: %s: Rx init failed\n", BDX_DRV_NAME, priv->ndev->name); + netdev_err(priv->ndev, "Rx init failed\n"); return -ENOMEM; } @@ -1116,7 +1115,7 @@ static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f) dno = bdx_rxdb_available(db) - 1; while (dno > 0) { if (!(skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN))) { - ERR("NO MEM: dev_alloc_skb failed\n"); + pr_err("NO MEM: dev_alloc_skb failed\n"); break; } skb->dev = priv->ndev; @@ -1337,9 +1336,7 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget) static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len, u16 rxd_vlan) { - DBG("ERROR: rxdd bc %d rxfq %d to %d type %d err %d rxp %d " - "pkt_id %d vtag %d len %d vlan_id %d cfi %d prio %d " - "va_lo %d va_hi %d\n", + DBG("ERROR: rxdd bc %d rxfq %d to %d type %d err %d rxp %d pkt_id %d vtag %d len %d vlan_id %d cfi %d prio %d va_lo %d va_hi %d\n", GET_RXD_BC(rxd_val1), GET_RXD_RXFQ(rxd_val1), GET_RXD_TO(rxd_val1), GET_RXD_TYPE(rxd_val1), GET_RXD_ERR(rxd_val1), GET_RXD_RXP(rxd_val1), GET_RXD_PKT_ID(rxd_val1), @@ -1591,7 +1588,7 @@ static int bdx_tx_init(struct bdx_priv *priv) return 0; err_mem: - ERR("tehuti: %s: Tx init failed\n", priv->ndev->name); + netdev_err(priv->ndev, "Tx init failed\n"); return -ENOMEM; } @@ -1946,8 +1943,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } else { if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { - printk(KERN_ERR "tehuti: No usable DMA configuration" - ", aborting\n"); + pr_err("No usable DMA configuration, aborting\n"); goto err_dma; } pci_using_dac = 0; @@ -1961,25 +1957,25 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pciaddr = pci_resource_start(pdev, 0); if (!pciaddr) { err = -EIO; - ERR("tehuti: no MMIO resource\n"); + pr_err("no MMIO resource\n"); goto err_out_res; } if ((regionSize = pci_resource_len(pdev, 0)) < BDX_REGS_SIZE) { err = -EIO; - ERR("tehuti: MMIO resource (%x) too small\n", regionSize); + pr_err("MMIO resource (%x) too small\n", regionSize); goto err_out_res; } nic->regs = ioremap(pciaddr, regionSize); if (!nic->regs) { err = -EIO; - ERR("tehuti: ioremap failed\n"); + pr_err("ioremap failed\n"); goto err_out_res; } if (pdev->irq < 2) { err = -EIO; - ERR("tehuti: invalid irq (%d)\n", pdev->irq); + pr_err("invalid irq (%d)\n", pdev->irq); goto err_out_iomap; } pci_set_drvdata(pdev, nic); @@ -1997,7 +1993,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #ifdef BDX_MSI if ((readl(nic->regs + FPGA_VER) & 0xFFF) >= 378) { if ((err = pci_enable_msi(pdev))) - ERR("Tehuti: Can't eneble msi. error is %d\n", err); + pr_err("Can't eneble msi. error is %d\n", err); else nic->irq_type = IRQ_MSI; } else @@ -2008,7 +2004,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (port = 0; port < nic->port_num; port++) { if (!(ndev = alloc_etherdev(sizeof(struct bdx_priv)))) { err = -ENOMEM; - printk(KERN_ERR "tehuti: alloc_etherdev failed\n"); + pr_err("alloc_etherdev failed\n"); goto err_out_iomap; } @@ -2075,12 +2071,12 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /*bdx_hw_reset(priv); */ if (bdx_read_mac(priv)) { - printk(KERN_ERR "tehuti: load MAC address failed\n"); + pr_err("load MAC address failed\n"); goto err_out_iomap; } SET_NETDEV_DEV(ndev, &pdev->dev); if ((err = register_netdev(ndev))) { - printk(KERN_ERR "tehuti: register_netdev failed\n"); + pr_err("register_netdev failed\n"); goto err_out_free; } netif_carrier_off(ndev); @@ -2493,10 +2489,8 @@ static struct pci_driver bdx_pci_driver = { */ static void __init print_driver_id(void) { - printk(KERN_INFO "%s: %s, %s\n", BDX_DRV_NAME, BDX_DRV_DESC, - BDX_DRV_VERSION); - printk(KERN_INFO "%s: Options: hw_csum %s\n", BDX_DRV_NAME, - BDX_MSI_STRING); + pr_info("%s, %s\n", BDX_DRV_DESC, BDX_DRV_VERSION); + pr_info("Options: hw_csum %s\n", BDX_MSI_STRING); } static int __init bdx_module_init(void) diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index 124141909e42..a19dcf8b6b56 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -529,28 +529,34 @@ struct txd_desc { /* Debugging Macros */ -#define ERR(fmt, args...) printk(KERN_ERR fmt, ## args) -#define DBG2(fmt, args...) \ - printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args) +#define DBG2(fmt, args...) \ + pr_err("%s:%-5d: " fmt, __func__, __LINE__, ## args) #define BDX_ASSERT(x) BUG_ON(x) #ifdef DEBUG -#define ENTER do { \ - printk(KERN_ERR "%s:%-5d: ENTER\n", __func__, __LINE__); \ +#define ENTER \ +do { \ + pr_err("%s:%-5d: ENTER\n", __func__, __LINE__); \ } while (0) -#define RET(args...) do { \ - printk(KERN_ERR "%s:%-5d: RETURN\n", __func__, __LINE__); \ -return args; } while (0) +#define RET(args...) \ +do { \ + pr_err("%s:%-5d: RETURN\n", __func__, __LINE__); \ + return args; \ +} while (0) -#define DBG(fmt, args...) \ - printk(KERN_ERR "%s:%-5d: " fmt, __func__, __LINE__, ## args) +#define DBG(fmt, args...) \ + pr_err("%s:%-5d: " fmt, __func__, __LINE__, ## args) #else -#define ENTER do { } while (0) +#define ENTER do { } while (0) #define RET(args...) return args -#define DBG(fmt, args...) do { } while (0) +#define DBG(fmt, args...) \ +do { \ + if (0) \ + pr_err(fmt, ##args); \ +} while (0) #endif #endif /* _BDX__H */ -- cgit v1.2.3 From cb001a1f7db6ffb0fff0796c60853c2bf2e512c3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:23 +0000 Subject: drivers/net/tehuti.c: Hoist assigns out of ifs Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 82e522a114d2..fdf87ea7bc4e 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -420,8 +420,10 @@ static int bdx_hw_start(struct bdx_priv *priv) GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB); #define BDX_IRQ_TYPE ((priv->nic->irq_type == IRQ_MSI)?0:IRQF_SHARED) - if ((rc = request_irq(priv->pdev->irq, bdx_isr_napi, BDX_IRQ_TYPE, - ndev->name, ndev))) + + rc = request_irq(priv->pdev->irq, bdx_isr_napi, BDX_IRQ_TYPE, + ndev->name, ndev); + if (rc) goto err_irq; bdx_enable_interrupts(priv); @@ -603,18 +605,15 @@ static int bdx_open(struct net_device *ndev) if (netif_running(ndev)) netif_stop_queue(priv->ndev); - if ((rc = bdx_tx_init(priv))) - goto err; - - if ((rc = bdx_rx_init(priv))) - goto err; - - if ((rc = bdx_fw_load(priv))) + if ((rc = bdx_tx_init(priv)) || + (rc = bdx_rx_init(priv)) || + (rc = bdx_fw_load(priv))) goto err; bdx_rx_alloc_skbs(priv, &priv->rxf_fifo0); - if ((rc = bdx_hw_start(priv))) + rc = bdx_hw_start(priv); + if (rc) goto err; napi_enable(&priv->napi); @@ -1027,10 +1026,9 @@ static int bdx_rx_init(struct bdx_priv *priv) regRXF_CFG0_0, regRXF_CFG1_0, regRXF_RPTR_0, regRXF_WPTR_0)) goto err_mem; - if (! - (priv->rxdb = - bdx_rxdb_create(priv->rxf_fifo0.m.memsz / - sizeof(struct rxf_desc)))) + priv->rxdb = bdx_rxdb_create(priv->rxf_fifo0.m.memsz / + sizeof(struct rxf_desc)); + if (!priv->rxdb) goto err_mem; priv->rxf_fifo0.m.pktsz = priv->ndev->mtu + VLAN_ETH_HLEN; @@ -1114,7 +1112,8 @@ static void bdx_rx_alloc_skbs(struct bdx_priv *priv, struct rxf_fifo *f) ENTER; dno = bdx_rxdb_available(db) - 1; while (dno > 0) { - if (!(skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN))) { + skb = dev_alloc_skb(f->m.pktsz + NET_IP_ALIGN); + if (!skb) { pr_err("NO MEM: dev_alloc_skb failed\n"); break; } @@ -1934,8 +1933,9 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) RET(-ENOMEM); /************** pci *****************/ - if ((err = pci_enable_device(pdev))) /* it trigers interrupt, dunno why. */ - goto err_pci; /* it's not a problem though */ + err = pci_enable_device(pdev); + if (err) /* it triggers interrupt, dunno why. */ + goto err_pci; /* it's not a problem though */ if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) && !(err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))) { @@ -1949,7 +1949,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_using_dac = 0; } - if ((err = pci_request_regions(pdev, BDX_DRV_NAME))) + err = pci_request_regions(pdev, BDX_DRV_NAME); + if (err) goto err_dma; pci_set_master(pdev); @@ -1960,7 +1961,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pr_err("no MMIO resource\n"); goto err_out_res; } - if ((regionSize = pci_resource_len(pdev, 0)) < BDX_REGS_SIZE) { + regionSize = pci_resource_len(pdev, 0); + if (regionSize < BDX_REGS_SIZE) { err = -EIO; pr_err("MMIO resource (%x) too small\n", regionSize); goto err_out_res; @@ -1992,7 +1994,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) nic->irq_type = IRQ_INTX; #ifdef BDX_MSI if ((readl(nic->regs + FPGA_VER) & 0xFFF) >= 378) { - if ((err = pci_enable_msi(pdev))) + err = pci_enable_msi(pdev); + if (err) pr_err("Can't eneble msi. error is %d\n", err); else nic->irq_type = IRQ_MSI; @@ -2002,7 +2005,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /************** netdev **************/ for (port = 0; port < nic->port_num; port++) { - if (!(ndev = alloc_etherdev(sizeof(struct bdx_priv)))) { + ndev = alloc_etherdev(sizeof(struct bdx_priv)); + if (!ndev) { err = -ENOMEM; pr_err("alloc_etherdev failed\n"); goto err_out_iomap; @@ -2075,7 +2079,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_iomap; } SET_NETDEV_DEV(ndev, &pdev->dev); - if ((err = register_netdev(ndev))) { + err = register_netdev(ndev); + if (err) { pr_err("register_netdev failed\n"); goto err_out_free; } -- cgit v1.2.3 From 249658d5c24e42f19b3721b654d64a46816e9b0e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:24 +0000 Subject: drivers/net/tehuti.c: trivial checkpatch cleanups Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index fdf87ea7bc4e..b295b926bc45 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -419,7 +419,7 @@ static int bdx_hw_start(struct bdx_priv *priv) WRITE_REG(priv, regGMAC_RXF_A, GMAC_RX_FILTER_OSEN | GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB); -#define BDX_IRQ_TYPE ((priv->nic->irq_type == IRQ_MSI)?0:IRQF_SHARED) +#define BDX_IRQ_TYPE ((priv->nic->irq_type == IRQ_MSI) ? 0 : IRQF_SHARED) rc = request_irq(priv->pdev->irq, bdx_isr_napi, BDX_IRQ_TYPE, ndev->name, ndev); @@ -1605,7 +1605,7 @@ static inline int bdx_tx_space(struct bdx_priv *priv) fsize = f->m.rptr - f->m.wptr; if (fsize <= 0) fsize = f->m.memsz + fsize; - return (fsize); + return fsize; } /* bdx_tx_transmit - send packet to NIC @@ -2295,13 +2295,13 @@ bdx_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecoal) /* Convert RX fifo size to number of pending packets */ static inline int bdx_rx_fifo_size_to_packets(int rx_size) { - return ((FIFO_SIZE * (1 << rx_size)) / sizeof(struct rxf_desc)); + return (FIFO_SIZE * (1 << rx_size)) / sizeof(struct rxf_desc); } /* Convert TX fifo size to number of pending packets */ static inline int bdx_tx_fifo_size_to_packets(int tx_size) { - return ((FIFO_SIZE * (1 << tx_size)) / BDX_TXF_DESC_SZ); + return (FIFO_SIZE * (1 << tx_size)) / BDX_TXF_DESC_SZ; } /* @@ -2393,10 +2393,10 @@ static int bdx_get_sset_count(struct net_device *netdev, int stringset) case ETH_SS_STATS: BDX_ASSERT(ARRAY_SIZE(bdx_stat_names) != sizeof(struct bdx_stats) / sizeof(u64)); - return ((priv->stats_flag) ? ARRAY_SIZE(bdx_stat_names) : 0); - default: - return -EINVAL; + return (priv->stats_flag) ? ARRAY_SIZE(bdx_stat_names) : 0; } + + return -EINVAL; } /* -- cgit v1.2.3 From 13ff83b90f1dfae1068a250e8d99d3f9991cfa9d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:25 +0000 Subject: drivers/net/pcnet32.c: Use (pr|netdev|netif)_ macro helpers Make the output logging messages a bit more consistent. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/pcnet32.c | 347 +++++++++++++++++++------------------------------- 1 file changed, 130 insertions(+), 217 deletions(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 3522794550dd..9194abc11eef 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -21,6 +21,8 @@ * *************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "pcnet32" #define DRV_VERSION "1.35" #define DRV_RELDATE "21.Apr.2008" @@ -487,10 +489,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, (1 << size), &new_ring_dma_addr); if (new_tx_ring == NULL) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Consistent memory allocation failed.\n", - dev->name); + netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); return; } memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size)); @@ -498,18 +497,14 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t), GFP_ATOMIC); if (!new_dma_addr_list) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory allocation failed.\n", dev->name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); goto free_new_tx_ring; } new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *), GFP_ATOMIC); if (!new_skb_list) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory allocation failed.\n", dev->name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); goto free_new_lists; } @@ -565,10 +560,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, (1 << size), &new_ring_dma_addr); if (new_rx_ring == NULL) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Consistent memory allocation failed.\n", - dev->name); + netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); return; } memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size)); @@ -576,18 +568,14 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t), GFP_ATOMIC); if (!new_dma_addr_list) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory allocation failed.\n", dev->name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); goto free_new_rx_ring; } new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *), GFP_ATOMIC); if (!new_skb_list) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory allocation failed.\n", dev->name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); goto free_new_lists; } @@ -604,10 +592,8 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB); if (!(rx_skbuff = new_skb_list[new])) { /* keep the original lists and buffers */ - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: pcnet32_realloc_rx_ring dev_alloc_skb failed.\n", - dev->name); + netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", + __func__); goto free_all_new; } skb_reserve(rx_skbuff, NET_IP_ALIGN); @@ -838,10 +824,8 @@ static int pcnet32_set_ringparam(struct net_device *dev, spin_unlock_irqrestore(&lp->lock, flags); - if (netif_msg_drv(lp)) - printk(KERN_INFO - "%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name, - lp->rx_ring_size, lp->tx_ring_size); + netif_info(lp, drv, dev, "Ring Param Settings: RX: %d, TX: %d\n", + lp->rx_ring_size, lp->tx_ring_size); return 0; } @@ -871,17 +855,15 @@ static void pcnet32_ethtool_test(struct net_device *dev, if (test->flags == ETH_TEST_FL_OFFLINE) { rc = pcnet32_loopback_test(dev, data); if (rc) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Loopback test failed.\n", - dev->name); + netif_printk(lp, hw, KERN_DEBUG, dev, + "Loopback test failed\n"); test->flags |= ETH_TEST_FL_FAILED; - } else if (netif_msg_hw(lp)) - printk(KERN_DEBUG "%s: Loopback test passed.\n", - dev->name); - } else if (netif_msg_hw(lp)) - printk(KERN_DEBUG - "%s: No tests to run (specify 'Offline' on ethtool).", - dev->name); + } else + netif_printk(lp, hw, KERN_DEBUG, dev, + "Loopback test passed\n"); + } else + netif_printk(lp, hw, KERN_DEBUG, dev, + "No tests to run (specify 'Offline' on ethtool)\n"); } /* end pcnet32_ethtool_test */ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) @@ -927,10 +909,9 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) size = data_len + 15; for (x = 0; x < numbuffs; x++) { if (!(skb = dev_alloc_skb(size))) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG - "%s: Cannot allocate skb at line: %d!\n", - dev->name, __LINE__); + netif_printk(lp, hw, KERN_DEBUG, dev, + "Cannot allocate skb at line: %d!\n", + __LINE__); goto clean_up; } else { packet = skb->data; @@ -984,9 +965,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) ticks++; } if (ticks == 200) { - if (netif_msg_hw(lp)) - printk("%s: Desc %d failed to reset!\n", - dev->name, x); + netif_err(lp, hw, dev, "Desc %d failed to reset!\n", x); break; } } @@ -994,15 +973,15 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */ wmb(); if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { - printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); + netdev_printk(KERN_DEBUG, dev, "RX loopback packets:\n"); for (x = 0; x < numbuffs; x++) { - printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x); + netdev_printk(KERN_DEBUG, dev, "Packet %d: ", x); skb = lp->rx_skbuff[x]; for (i = 0; i < size; i++) { - printk("%02x ", *(skb->data + i)); + pr_cont(" %02x", *(skb->data + i)); } - printk("\n"); + pr_cont("\n"); } } @@ -1013,11 +992,9 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) packet = lp->tx_skbuff[x]->data; for (i = 0; i < size; i++) { if (*(skb->data + i) != packet[i]) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG - "%s: Error in compare! %2x - %02x %02x\n", - dev->name, i, *(skb->data + i), - packet[i]); + netif_printk(lp, hw, KERN_DEBUG, dev, + "Error in compare! %2x - %02x %02x\n", + i, *(skb->data + i), packet[i]); rc = 1; break; } @@ -1136,10 +1113,8 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, spin_lock_irqsave(&lp->lock, *flags); ticks++; if (ticks > 200) { - if (netif_msg_hw(lp)) - printk(KERN_DEBUG - "%s: Error getting into suspend!\n", - dev->name); + netif_printk(lp, hw, KERN_DEBUG, dev, + "Error getting into suspend!\n"); return 0; } } @@ -1184,15 +1159,13 @@ static void pcnet32_rx_entry(struct net_device *dev, /* Discard oversize frames. */ if (unlikely(pkt_len > PKT_BUF_SIZE)) { - if (netif_msg_drv(lp)) - printk(KERN_ERR "%s: Impossible packet size %d!\n", - dev->name, pkt_len); + netif_err(lp, drv, dev, "Impossible packet size %d!\n", + pkt_len); dev->stats.rx_errors++; return; } if (pkt_len < 60) { - if (netif_msg_rx_err(lp)) - printk(KERN_ERR "%s: Runt packet!\n", dev->name); + netif_err(lp, rx_err, dev, "Runt packet!\n"); dev->stats.rx_errors++; return; } @@ -1223,10 +1196,7 @@ static void pcnet32_rx_entry(struct net_device *dev, } if (skb == NULL) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Memory squeeze, dropping packet.\n", - dev->name); + netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -1297,11 +1267,9 @@ static int pcnet32_tx(struct net_device *dev) /* There was a major error, log it. */ int err_status = le32_to_cpu(lp->tx_ring[entry].misc); dev->stats.tx_errors++; - if (netif_msg_tx_err(lp)) - printk(KERN_ERR - "%s: Tx error status=%04x err_status=%08x\n", - dev->name, status, - err_status); + netif_err(lp, tx_err, dev, + "Tx error status=%04x err_status=%08x\n", + status, err_status); if (err_status & 0x04000000) dev->stats.tx_aborted_errors++; if (err_status & 0x08000000) @@ -1313,10 +1281,7 @@ static int pcnet32_tx(struct net_device *dev) dev->stats.tx_fifo_errors++; /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */ - if (netif_msg_tx_err(lp)) - printk(KERN_ERR - "%s: Tx FIFO error!\n", - dev->name); + netif_err(lp, tx_err, dev, "Tx FIFO error!\n"); must_restart = 1; } #else @@ -1325,10 +1290,7 @@ static int pcnet32_tx(struct net_device *dev) if (!lp->dxsuflo) { /* If controller doesn't recover ... */ /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */ - if (netif_msg_tx_err(lp)) - printk(KERN_ERR - "%s: Tx FIFO error!\n", - dev->name); + netif_err(lp, tx_err, dev, "Tx FIFO error!\n"); must_restart = 1; } } @@ -1354,11 +1316,8 @@ static int pcnet32_tx(struct net_device *dev) delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size); if (delta > lp->tx_ring_size) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, lp->cur_tx, - lp->tx_full); + netif_err(lp, drv, dev, "out-of-sync dirty pointer, %d vs. %d, full=%d\n", + dirty_tx, lp->cur_tx, lp->tx_full); dirty_tx += lp->tx_ring_size; delta -= lp->tx_ring_size; } @@ -1535,8 +1494,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_enable_device(pdev); if (err < 0) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX - "failed to enable device -- err=%d\n", err); + pr_err("failed to enable device -- err=%d\n", err); return err; } pci_set_master(pdev); @@ -1544,22 +1502,19 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) ioaddr = pci_resource_start(pdev, 0); if (!ioaddr) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX - "card has no PCI IO resources, aborting\n"); + pr_err("card has no PCI IO resources, aborting\n"); return -ENODEV; } if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX - "architecture does not support 32bit PCI busmaster DMA\n"); + pr_err("architecture does not support 32bit PCI busmaster DMA\n"); return -ENODEV; } if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX - "io address range already allocated\n"); + pr_err("io address range already allocated\n"); return -EBUSY; } @@ -1616,7 +1571,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) a = &pcnet32_dwio; } else { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "No access methods\n"); + pr_err("No access methods\n"); goto err_release_region; } } @@ -1624,11 +1579,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr, 89) << 16); if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW)) - printk(KERN_INFO " PCnet chip version is %#x.\n", - chip_version); + pr_info(" PCnet chip version is %#x\n", chip_version); if ((chip_version & 0xfff) != 0x003) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "Unsupported chip version.\n"); + pr_info("Unsupported chip version\n"); goto err_release_region; } @@ -1681,7 +1635,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) if (cards_found < MAX_UNITS && homepna[cards_found]) media |= 1; /* switch to home wiring mode */ if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", + printk(KERN_DEBUG PFX "media set to %sMbit mode\n", (media & 1) ? "1" : "10"); a->write_bcr(ioaddr, 49, media); break; @@ -1697,9 +1651,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) break; default: if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX - "PCnet version %#x, no PCnet32 chip.\n", - chip_version); + pr_info("PCnet version %#x, no PCnet32 chip\n", + chip_version); goto err_release_region; } @@ -1721,7 +1674,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dev = alloc_etherdev(sizeof(*lp)); if (!dev) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX "Memory allocation failed.\n"); + pr_err("Memory allocation failed\n"); ret = -ENOMEM; goto err_release_region; } @@ -1730,7 +1683,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) SET_NETDEV_DEV(dev, &pdev->dev); if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr); + pr_info("%s at %#3lx,", chipname, ioaddr); /* In most chips, after a chip reset, the ethernet address is read from the * station address PROM at the base address and programmed into the @@ -1755,9 +1708,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) !is_valid_ether_addr(dev->dev_addr)) { if (is_valid_ether_addr(promaddr)) { if (pcnet32_debug & NETIF_MSG_PROBE) { - printk(" warning: CSR address invalid,\n"); - printk(KERN_INFO - " using instead PROM address of"); + pr_cont(" warning: CSR address invalid,\n"); + pr_info(" using instead PROM address of"); } memcpy(dev->dev_addr, promaddr, 6); } @@ -1769,43 +1721,43 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) memset(dev->dev_addr, 0, ETH_ALEN); if (pcnet32_debug & NETIF_MSG_PROBE) { - printk(" %pM", dev->dev_addr); + pr_cont(" %pM", dev->dev_addr); /* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) { i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk(KERN_INFO " tx_start_pt(0x%04x):", i); + pr_info(" tx_start_pt(0x%04x):", i); switch (i >> 10) { case 0: - printk(KERN_CONT " 20 bytes,"); + pr_cont(" 20 bytes,"); break; case 1: - printk(KERN_CONT " 64 bytes,"); + pr_cont(" 64 bytes,"); break; case 2: - printk(KERN_CONT " 128 bytes,"); + pr_cont(" 128 bytes,"); break; case 3: - printk(KERN_CONT "~220 bytes,"); + pr_cont("~220 bytes,"); break; } i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(KERN_CONT " BCR18(%x):", i & 0xffff); + pr_cont(" BCR18(%x):", i & 0xffff); if (i & (1 << 5)) - printk(KERN_CONT "BurstWrEn "); + pr_cont("BurstWrEn "); if (i & (1 << 6)) - printk(KERN_CONT "BurstRdEn "); + pr_cont("BurstRdEn "); if (i & (1 << 7)) - printk(KERN_CONT "DWordIO "); + pr_cont("DWordIO "); if (i & (1 << 11)) - printk(KERN_CONT "NoUFlow "); + pr_cont("NoUFlow "); i = a->read_bcr(ioaddr, 25); - printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8); + pr_info(" SRAMSIZE=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 26); - printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8); + pr_cont(" SRAM_BND=0x%04x,", i << 8); i = a->read_bcr(ioaddr, 27); if (i & (1 << 14)) - printk(KERN_CONT "LowLatRx"); + pr_cont("LowLatRx"); } } @@ -1815,8 +1767,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) if ((lp->init_block = pci_alloc_consistent(pdev, sizeof(*lp->init_block), &lp->init_dma_addr)) == NULL) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_ERR PFX - "Consistent memory allocation failed.\n"); + pr_err("Consistent memory allocation failed\n"); ret = -ENOMEM; goto err_free_netdev; } @@ -1890,7 +1841,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) if (pdev) { /* use the IRQ provided by PCI */ dev->irq = pdev->irq; if (pcnet32_debug & NETIF_MSG_PROBE) - printk(" assigned IRQ %d.\n", dev->irq); + pr_cont(" assigned IRQ %d\n", dev->irq); } else { unsigned long irq_mask = probe_irq_on(); @@ -1906,12 +1857,12 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dev->irq = probe_irq_off(irq_mask); if (!dev->irq) { if (pcnet32_debug & NETIF_MSG_PROBE) - printk(", failed to detect IRQ line.\n"); + pr_cont(", failed to detect IRQ line\n"); ret = -ENODEV; goto err_free_ring; } if (pcnet32_debug & NETIF_MSG_PROBE) - printk(", probed IRQ %d.\n", dev->irq); + pr_cont(", probed IRQ %d\n", dev->irq); } /* Set the mii phy_id so that we can query the link state */ @@ -1935,9 +1886,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->phymask |= (1 << i); lp->mii_if.phy_id = i; if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO PFX - "Found PHY %04x:%04x at address %d.\n", - id1, id2, i); + pr_info("Found PHY %04x:%04x at address %d\n", + id1, id2, i); } lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); if (lp->phycount > 1) { @@ -1966,7 +1916,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) } if (pcnet32_debug & NETIF_MSG_PROBE) - printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name); + pr_info("%s: registered as %s\n", dev->name, lp->name); cards_found++; /* enable LED writes */ @@ -1995,10 +1945,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) lp->tx_ring_size, &lp->tx_ring_dma_addr); if (lp->tx_ring == NULL) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Consistent memory allocation failed.\n", - name); + netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); return -ENOMEM; } @@ -2007,46 +1954,35 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name) lp->rx_ring_size, &lp->rx_ring_dma_addr); if (lp->rx_ring == NULL) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Consistent memory allocation failed.\n", - name); + netif_err(lp, drv, dev, "Consistent memory allocation failed\n"); return -ENOMEM; } lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t), GFP_ATOMIC); if (!lp->tx_dma_addr) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Memory allocation failed.\n", name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); return -ENOMEM; } lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t), GFP_ATOMIC); if (!lp->rx_dma_addr) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Memory allocation failed.\n", name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); return -ENOMEM; } lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *), GFP_ATOMIC); if (!lp->tx_skbuff) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Memory allocation failed.\n", name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); return -ENOMEM; } lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *), GFP_ATOMIC); if (!lp->rx_skbuff) { - if (netif_msg_drv(lp)) - printk(KERN_ERR PFX - "%s: Memory allocation failed.\n", name); + netif_err(lp, drv, dev, "Memory allocation failed\n"); return -ENOMEM; } @@ -2115,12 +2051,11 @@ static int pcnet32_open(struct net_device *dev) /* switch pcnet32 to 32bit mode */ lp->a.write_bcr(ioaddr, 20, 2); - if (netif_msg_ifup(lp)) - printk(KERN_DEBUG - "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", - dev->name, dev->irq, (u32) (lp->tx_ring_dma_addr), - (u32) (lp->rx_ring_dma_addr), - (u32) (lp->init_dma_addr)); + netif_printk(lp, ifup, KERN_DEBUG, dev, + "%s() irq %d tx/rx rings %#x/%#x init %#x\n", + __func__, dev->irq, (u32) (lp->tx_ring_dma_addr), + (u32) (lp->rx_ring_dma_addr), + (u32) (lp->init_dma_addr)); /* set/reset autoselect bit */ val = lp->a.read_bcr(ioaddr, 2) & ~2; @@ -2155,10 +2090,8 @@ static int pcnet32_open(struct net_device *dev) pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) { if (lp->options & PCNET32_PORT_ASEL) { lp->options = PCNET32_PORT_FD | PCNET32_PORT_100; - if (netif_msg_link(lp)) - printk(KERN_DEBUG - "%s: Setting 100Mb-Full Duplex.\n", - dev->name); + netif_printk(lp, link, KERN_DEBUG, dev, + "Setting 100Mb-Full Duplex\n"); } } if (lp->phycount < 2) { @@ -2246,9 +2179,7 @@ static int pcnet32_open(struct net_device *dev) } } lp->mii_if.phy_id = first_phy; - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: Using PHY number %d.\n", - dev->name, first_phy); + netif_info(lp, link, dev, "Using PHY number %d\n", first_phy); } #ifdef DO_DXSUFLO @@ -2295,12 +2226,11 @@ static int pcnet32_open(struct net_device *dev) */ lp->a.write_csr(ioaddr, CSR0, CSR0_NORMAL); - if (netif_msg_ifup(lp)) - printk(KERN_DEBUG - "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, - (u32) (lp->init_dma_addr), - lp->a.read_csr(ioaddr, CSR0)); + netif_printk(lp, ifup, KERN_DEBUG, dev, + "pcnet32 open after %d ticks, init block %#x csr0 %4.4x\n", + i, + (u32) (lp->init_dma_addr), + lp->a.read_csr(ioaddr, CSR0)); spin_unlock_irqrestore(&lp->lock, flags); @@ -2371,10 +2301,8 @@ static int pcnet32_init_ring(struct net_device *dev) (rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb(PKT_BUF_SKB))) { /* there is not much, we can do at this point */ - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: pcnet32_init_ring dev_alloc_skb failed.\n", - dev->name); + netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", + __func__); return -1; } skb_reserve(rx_skbuff, NET_IP_ALIGN); @@ -2424,10 +2352,9 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) if (lp->a.read_csr(ioaddr, CSR0) & CSR0_STOP) break; - if (i >= 100 && netif_msg_drv(lp)) - printk(KERN_ERR - "%s: pcnet32_restart timed out waiting for stop.\n", - dev->name); + if (i >= 100) + netif_err(lp, drv, dev, "%s timed out waiting for stop\n", + __func__); pcnet32_purge_tx_ring(dev); if (pcnet32_init_ring(dev)) @@ -2451,8 +2378,7 @@ static void pcnet32_tx_timeout(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); /* Transmitter timeout, serious problems. */ if (pcnet32_debug & NETIF_MSG_DRV) - printk(KERN_ERR - "%s: transmit timed out, status %4.4x, resetting.\n", + pr_err("%s: transmit timed out, status %4.4x, resetting\n", dev->name, lp->a.read_csr(ioaddr, CSR0)); lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); dev->stats.tx_errors++; @@ -2495,11 +2421,9 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb, spin_lock_irqsave(&lp->lock, flags); - if (netif_msg_tx_queued(lp)) { - printk(KERN_DEBUG - "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, CSR0)); - } + netif_printk(lp, tx_queued, KERN_DEBUG, dev, + "%s() called, csr0 %4.4x\n", + __func__, lp->a.read_csr(ioaddr, CSR0)); /* Default status -- will not enable Successful-TxDone * interrupt when that option is available to us. @@ -2564,10 +2488,9 @@ pcnet32_interrupt(int irq, void *dev_id) /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); - if (netif_msg_intr(lp)) - printk(KERN_DEBUG - "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", - dev->name, csr0, lp->a.read_csr(ioaddr, CSR0)); + netif_printk(lp, intr, KERN_DEBUG, dev, + "interrupt csr0=%#2.2x new csr=%#2.2x\n", + csr0, lp->a.read_csr(ioaddr, CSR0)); /* Log misc errors. */ if (csr0 & 0x4000) @@ -2587,10 +2510,8 @@ pcnet32_interrupt(int irq, void *dev_id) dev->stats.rx_errors++; /* Missed a Rx frame. */ } if (csr0 & 0x0800) { - if (netif_msg_drv(lp)) - printk(KERN_ERR - "%s: Bus master arbitration failure, status %4.4x.\n", - dev->name, csr0); + netif_err(lp, drv, dev, "Bus master arbitration failure, status %4.4x\n", + csr0); /* unlike for the lance, there is no restart needed */ } if (napi_schedule_prep(&lp->napi)) { @@ -2606,9 +2527,9 @@ pcnet32_interrupt(int irq, void *dev_id) csr0 = lp->a.read_csr(ioaddr, CSR0); } - if (netif_msg_intr(lp)) - printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", - dev->name, lp->a.read_csr(ioaddr, CSR0)); + netif_printk(lp, intr, KERN_DEBUG, dev, + "exiting interrupt, csr0=%#4.4x\n", + lp->a.read_csr(ioaddr, CSR0)); spin_unlock(&lp->lock); @@ -2630,10 +2551,9 @@ static int pcnet32_close(struct net_device *dev) dev->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112); - if (netif_msg_ifdown(lp)) - printk(KERN_DEBUG - "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, lp->a.read_csr(ioaddr, CSR0)); + netif_printk(lp, ifdown, KERN_DEBUG, dev, + "Shutting down ethercard, status was %2.2x\n", + lp->a.read_csr(ioaddr, CSR0)); /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); @@ -2730,9 +2650,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev) csr15 = lp->a.read_csr(ioaddr, CSR15); if (dev->flags & IFF_PROMISC) { /* Log any net taps. */ - if (netif_msg_hw(lp)) - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", - dev->name); + netif_info(lp, hw, dev, "Promiscuous mode enabled\n"); lp->init_block->mode = cpu_to_le16(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7); @@ -2819,10 +2737,8 @@ static int pcnet32_check_otherphy(struct net_device *dev) mii.phy_id = i; if (mii_link_ok(&mii)) { /* found PHY with active link */ - if (netif_msg_link(lp)) - printk(KERN_INFO - "%s: Using PHY number %d.\n", - dev->name, i); + netif_info(lp, link, dev, "Using PHY number %d\n", + i); /* isolate inactive phy */ bmcr = @@ -2868,8 +2784,7 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) if (!curr_link) { if (prev_link || verbose) { netif_carrier_off(dev); - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: link down\n", dev->name); + netif_info(lp, link, dev, "link down\n"); } if (lp->phycount > 1) { curr_link = pcnet32_check_otherphy(dev); @@ -2881,12 +2796,11 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) if (netif_msg_link(lp)) { struct ethtool_cmd ecmd; mii_ethtool_gset(&lp->mii_if, &ecmd); - printk(KERN_INFO - "%s: link up, %sMbps, %s-duplex\n", - dev->name, - (ecmd.speed == SPEED_100) ? "100" : "10", - (ecmd.duplex == - DUPLEX_FULL) ? "full" : "half"); + netdev_info(dev, "link up, %sMbps, %s-duplex\n", + (ecmd.speed == SPEED_100) + ? "100" : "10", + (ecmd.duplex == DUPLEX_FULL) + ? "full" : "half"); } bcr9 = lp->a.read_bcr(dev->base_addr, 9); if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) { @@ -2897,8 +2811,7 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) lp->a.write_bcr(dev->base_addr, 9, bcr9); } } else { - if (netif_msg_link(lp)) - printk(KERN_INFO "%s: link up\n", dev->name); + netif_info(lp, link, dev, "link up\n"); } } } @@ -3010,7 +2923,7 @@ MODULE_LICENSE("GPL"); static int __init pcnet32_init_module(void) { - printk(KERN_INFO "%s", version); + pr_info("%s", version); pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT); @@ -3026,7 +2939,7 @@ static int __init pcnet32_init_module(void) pcnet32_probe_vlbus(pcnet32_portlist); if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE)) - printk(KERN_INFO PFX "%d cards_found.\n", cards_found); + pr_info("%d cards_found\n", cards_found); return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; } -- cgit v1.2.3 From 9e3f8063a72a946f2ba29068b34190436573dffe Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 15 Feb 2010 08:34:26 +0000 Subject: drivers/net/pcnet32.c: Checkpatch cleaning Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/pcnet32.c | 153 ++++++++++++++++++++++++-------------------------- 1 file changed, 73 insertions(+), 80 deletions(-) diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9194abc11eef..63e03159daf7 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -52,10 +52,10 @@ static const char *const version = #include #include #include +#include +#include #include -#include -#include #include /* @@ -85,7 +85,7 @@ static int cards_found; static unsigned int pcnet32_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0 }; -static int pcnet32_debug = 0; +static int pcnet32_debug; static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ static int pcnet32vlb; /* check for VLB cards ? */ @@ -392,7 +392,7 @@ static struct pcnet32_access pcnet32_wio = { static u16 pcnet32_dwio_read_csr(unsigned long addr, int index) { outl(index, addr + PCNET32_DWIO_RAP); - return (inl(addr + PCNET32_DWIO_RDP) & 0xffff); + return inl(addr + PCNET32_DWIO_RDP) & 0xffff; } static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val) @@ -404,7 +404,7 @@ static void pcnet32_dwio_write_csr(unsigned long addr, int index, u16 val) static u16 pcnet32_dwio_read_bcr(unsigned long addr, int index) { outl(index, addr + PCNET32_DWIO_RAP); - return (inl(addr + PCNET32_DWIO_BDP) & 0xffff); + return inl(addr + PCNET32_DWIO_BDP) & 0xffff; } static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val) @@ -415,7 +415,7 @@ static void pcnet32_dwio_write_bcr(unsigned long addr, int index, u16 val) static u16 pcnet32_dwio_read_rap(unsigned long addr) { - return (inl(addr + PCNET32_DWIO_RAP) & 0xffff); + return inl(addr + PCNET32_DWIO_RAP) & 0xffff; } static void pcnet32_dwio_write_rap(unsigned long addr, u16 val) @@ -524,15 +524,14 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev, lp->tx_skbuff = new_skb_list; return; - free_new_lists: +free_new_lists: kfree(new_dma_addr_list); - free_new_tx_ring: +free_new_tx_ring: pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_tx_head) * (1 << size), new_tx_ring, new_ring_dma_addr); - return; } /* @@ -587,10 +586,11 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, new_skb_list[new] = lp->rx_skbuff[new]; } /* now allocate any new buffers needed */ - for (; new < size; new++ ) { + for (; new < size; new++) { struct sk_buff *rx_skbuff; new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB); - if (!(rx_skbuff = new_skb_list[new])) { + rx_skbuff = new_skb_list[new]; + if (!rx_skbuff) { /* keep the original lists and buffers */ netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", __func__); @@ -630,8 +630,8 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, lp->rx_skbuff = new_skb_list; return; - free_all_new: - for (; --new >= lp->rx_ring_size; ) { +free_all_new: + while (--new >= lp->rx_ring_size) { if (new_skb_list[new]) { pci_unmap_single(lp->pci_dev, new_dma_addr_list[new], PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); @@ -639,9 +639,9 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, } } kfree(new_skb_list); - free_new_lists: +free_new_lists: kfree(new_dma_addr_list); - free_new_rx_ring: +free_new_rx_ring: pci_free_consistent(lp->pci_dev, sizeof(struct pcnet32_rx_head) * (1 << size), @@ -831,7 +831,7 @@ static int pcnet32_set_ringparam(struct net_device *dev, } static void pcnet32_get_strings(struct net_device *dev, u32 stringset, - u8 * data) + u8 *data) { memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); } @@ -908,39 +908,39 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) /* Initialize Transmit buffers. */ size = data_len + 15; for (x = 0; x < numbuffs; x++) { - if (!(skb = dev_alloc_skb(size))) { + skb = dev_alloc_skb(size); + if (!skb) { netif_printk(lp, hw, KERN_DEBUG, dev, "Cannot allocate skb at line: %d!\n", __LINE__); goto clean_up; - } else { - packet = skb->data; - skb_put(skb, size); /* create space for data */ - lp->tx_skbuff[x] = skb; - lp->tx_ring[x].length = cpu_to_le16(-skb->len); - lp->tx_ring[x].misc = 0; - - /* put DA and SA into the skb */ - for (i = 0; i < 6; i++) - *packet++ = dev->dev_addr[i]; - for (i = 0; i < 6; i++) - *packet++ = dev->dev_addr[i]; - /* type */ - *packet++ = 0x08; - *packet++ = 0x06; - /* packet number */ - *packet++ = x; - /* fill packet with data */ - for (i = 0; i < data_len; i++) - *packet++ = i; - - lp->tx_dma_addr[x] = - pci_map_single(lp->pci_dev, skb->data, skb->len, - PCI_DMA_TODEVICE); - lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]); - wmb(); /* Make sure owner changes after all others are visible */ - lp->tx_ring[x].status = cpu_to_le16(status); } + packet = skb->data; + skb_put(skb, size); /* create space for data */ + lp->tx_skbuff[x] = skb; + lp->tx_ring[x].length = cpu_to_le16(-skb->len); + lp->tx_ring[x].misc = 0; + + /* put DA and SA into the skb */ + for (i = 0; i < 6; i++) + *packet++ = dev->dev_addr[i]; + for (i = 0; i < 6; i++) + *packet++ = dev->dev_addr[i]; + /* type */ + *packet++ = 0x08; + *packet++ = 0x06; + /* packet number */ + *packet++ = x; + /* fill packet with data */ + for (i = 0; i < data_len; i++) + *packet++ = i; + + lp->tx_dma_addr[x] = + pci_map_single(lp->pci_dev, skb->data, skb->len, + PCI_DMA_TODEVICE); + lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]); + wmb(); /* Make sure owner changes after all others are visible */ + lp->tx_ring[x].status = cpu_to_le16(status); } x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */ @@ -978,9 +978,8 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) for (x = 0; x < numbuffs; x++) { netdev_printk(KERN_DEBUG, dev, "Packet %d: ", x); skb = lp->rx_skbuff[x]; - for (i = 0; i < size; i++) { + for (i = 0; i < size; i++) pr_cont(" %02x", *(skb->data + i)); - } pr_cont("\n"); } } @@ -1002,7 +1001,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) x++; } - clean_up: +clean_up: *data1 = rc; pcnet32_purge_tx_ring(dev); @@ -1021,7 +1020,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) } spin_unlock_irqrestore(&lp->lock, flags); - return (rc); + return rc; } /* end pcnet32_loopback_test */ static void pcnet32_led_blink_callback(struct net_device *dev) @@ -1033,9 +1032,8 @@ static void pcnet32_led_blink_callback(struct net_device *dev) int i; spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) { + for (i = 4; i < 8; i++) a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); - } spin_unlock_irqrestore(&lp->lock, flags); mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); @@ -1057,9 +1055,8 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) /* Save the current value of the bcrs */ spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) { + for (i = 4; i < 8; i++) regs[i - 4] = a->read_bcr(ioaddr, i); - } spin_unlock_irqrestore(&lp->lock, flags); mod_timer(&lp->blink_timer, jiffies); @@ -1074,9 +1071,8 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) /* Restore the original value of the bcrs */ spin_lock_irqsave(&lp->lock, flags); - for (i = 4; i < 8; i++) { + for (i = 4; i < 8; i++) a->write_bcr(ioaddr, i, regs[i - 4]); - } spin_unlock_irqrestore(&lp->lock, flags); return 0; @@ -1173,7 +1169,8 @@ static void pcnet32_rx_entry(struct net_device *dev, if (pkt_len > rx_copybreak) { struct sk_buff *newskb; - if ((newskb = dev_alloc_skb(PKT_BUF_SKB))) { + newskb = dev_alloc_skb(PKT_BUF_SKB); + if (newskb) { skb_reserve(newskb, NET_IP_ALIGN); skb = lp->rx_skbuff[entry]; pci_unmap_single(lp->pci_dev, @@ -1191,9 +1188,8 @@ static void pcnet32_rx_entry(struct net_device *dev, rx_in_place = 1; } else skb = NULL; - } else { + } else skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN); - } if (skb == NULL) { netif_err(lp, drv, dev, "Memory squeeze, dropping packet\n"); @@ -1380,7 +1376,7 @@ static int pcnet32_get_regs_len(struct net_device *dev) struct pcnet32_private *lp = netdev_priv(dev); int j = lp->phycount * PCNET32_REGS_PER_PHY; - return ((PCNET32_NUM_REGS + j) * sizeof(u16)); + return (PCNET32_NUM_REGS + j) * sizeof(u16); } static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, @@ -1404,21 +1400,20 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, *buff++ = inw(ioaddr + i); /* read control and status registers */ - for (i = 0; i < 90; i++) { + for (i = 0; i < 90; i++) *buff++ = a->read_csr(ioaddr, i); - } *buff++ = a->read_csr(ioaddr, 112); *buff++ = a->read_csr(ioaddr, 114); /* read bus configuration registers */ - for (i = 0; i < 30; i++) { + for (i = 0; i < 30; i++) *buff++ = a->read_bcr(ioaddr, i); - } + *buff++ = 0; /* skip bcr30 so as not to hang 79C976 */ - for (i = 31; i < 36; i++) { + + for (i = 31; i < 36; i++) *buff++ = a->read_bcr(ioaddr, i); - } /* read mii phy registers */ if (lp->mii) { @@ -1511,17 +1506,16 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) pr_err("architecture does not support 32bit PCI busmaster DMA\n"); return -ENODEV; } - if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == - NULL) { + if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("io address range already allocated\n"); return -EBUSY; } err = pcnet32_probe1(ioaddr, 1, pdev); - if (err < 0) { + if (err < 0) pci_disable_device(pdev); - } + return err; } @@ -1764,8 +1758,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) dev->base_addr = ioaddr; lp = netdev_priv(dev); /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ - if ((lp->init_block = - pci_alloc_consistent(pdev, sizeof(*lp->init_block), &lp->init_dma_addr)) == NULL) { + lp->init_block = pci_alloc_consistent(pdev, sizeof(*lp->init_block), + &lp->init_dma_addr); + if (!lp->init_block) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("Consistent memory allocation failed\n"); ret = -ENOMEM; @@ -1890,9 +1885,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) id1, id2, i); } lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); - if (lp->phycount > 1) { + if (lp->phycount > 1) lp->options |= PCNET32_PORT_MII; - } } init_timer(&lp->watchdog_timer); @@ -2236,7 +2230,7 @@ static int pcnet32_open(struct net_device *dev) return 0; /* Always succeed */ - err_free_ring: +err_free_ring: /* free any allocated skbuffs */ pcnet32_purge_rx_ring(dev); @@ -2246,7 +2240,7 @@ static int pcnet32_open(struct net_device *dev) */ lp->a.write_bcr(ioaddr, 20, 4); - err_free_irq: +err_free_irq: spin_unlock_irqrestore(&lp->lock, flags); free_irq(dev->irq, dev); return rc; @@ -2297,10 +2291,10 @@ static int pcnet32_init_ring(struct net_device *dev) for (i = 0; i < lp->rx_ring_size; i++) { struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; if (rx_skbuff == NULL) { - if (! - (rx_skbuff = lp->rx_skbuff[i] = - dev_alloc_skb(PKT_BUF_SKB))) { - /* there is not much, we can do at this point */ + lp->rx_skbuff[i] = dev_alloc_skb(PKT_BUF_SKB); + rx_skbuff = lp->rx_skbuff[i]; + if (!rx_skbuff) { + /* there is not much we can do at this point */ netif_err(lp, drv, dev, "%s dev_alloc_skb failed\n", __func__); return -1; @@ -2482,9 +2476,8 @@ pcnet32_interrupt(int irq, void *dev_id) csr0 = lp->a.read_csr(ioaddr, CSR0); while ((csr0 & 0x8f00) && --boguscnt >= 0) { - if (csr0 == 0xffff) { + if (csr0 == 0xffff) break; /* PCMCIA remove happened */ - } /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); -- cgit v1.2.3 From 02291680ffba92e5b5865bc0c5e7d1f3056b80ec Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 14 Feb 2010 03:25:51 +0000 Subject: net ipv4: Decouple ipv4 interface parameters from binary sysctl numbers Stop using the binary sysctl enumeartion in sysctl.h as an index into a per interface array. This leads to unnecessary binary sysctl number allocation, and a fragility in data structure and implementation because of unnecessary coupling. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- include/linux/inetdevice.h | 42 ++++++++++++++++++++++++++++++++++++------ include/linux/sysctl.h | 4 ---- net/ipv4/devinet.c | 26 +++++++++++++------------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index cf257809771b..2be1a1a2beb9 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -10,10 +10,40 @@ #include #include +enum +{ + IPV4_DEVCONF_FORWARDING=1, + IPV4_DEVCONF_MC_FORWARDING, + IPV4_DEVCONF_PROXY_ARP, + IPV4_DEVCONF_ACCEPT_REDIRECTS, + IPV4_DEVCONF_SECURE_REDIRECTS, + IPV4_DEVCONF_SEND_REDIRECTS, + IPV4_DEVCONF_SHARED_MEDIA, + IPV4_DEVCONF_RP_FILTER, + IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE, + IPV4_DEVCONF_BOOTP_RELAY, + IPV4_DEVCONF_LOG_MARTIANS, + IPV4_DEVCONF_TAG, + IPV4_DEVCONF_ARPFILTER, + IPV4_DEVCONF_MEDIUM_ID, + IPV4_DEVCONF_NOXFRM, + IPV4_DEVCONF_NOPOLICY, + IPV4_DEVCONF_FORCE_IGMP_VERSION, + IPV4_DEVCONF_ARP_ANNOUNCE, + IPV4_DEVCONF_ARP_IGNORE, + IPV4_DEVCONF_PROMOTE_SECONDARIES, + IPV4_DEVCONF_ARP_ACCEPT, + IPV4_DEVCONF_ARP_NOTIFY, + IPV4_DEVCONF_ACCEPT_LOCAL, + IPV4_DEVCONF_SRC_VMARK, + IPV4_DEVCONF_PROXY_ARP_PVLAN, + __IPV4_DEVCONF_MAX +}; + struct ipv4_devconf { void *sysctl; - int data[__NET_IPV4_CONF_MAX - 1]; - DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1); + int data[__IPV4_DEVCONF_MAX - 1]; + DECLARE_BITMAP(state, __IPV4_DEVCONF_MAX - 1); }; struct in_device { @@ -40,7 +70,7 @@ struct in_device { struct rcu_head rcu_head; }; -#define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1]) +#define IPV4_DEVCONF(cnf, attr) ((cnf).data[IPV4_DEVCONF_ ## attr - 1]) #define IPV4_DEVCONF_ALL(net, attr) \ IPV4_DEVCONF((*(net)->ipv4.devconf_all), attr) @@ -60,13 +90,13 @@ static inline void ipv4_devconf_set(struct in_device *in_dev, int index, static inline void ipv4_devconf_setall(struct in_device *in_dev) { - bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1); + bitmap_fill(in_dev->cnf.state, __IPV4_DEVCONF_MAX - 1); } #define IN_DEV_CONF_GET(in_dev, attr) \ - ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr) + ipv4_devconf_get((in_dev), IPV4_DEVCONF_ ## attr) #define IN_DEV_CONF_SET(in_dev, attr, val) \ - ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val)) + ipv4_devconf_set((in_dev), IPV4_DEVCONF_ ## attr, (val)) #define IN_DEV_ANDCONF(in_dev, attr) \ (IPV4_DEVCONF_ALL(dev_net(in_dev->dev), attr) && \ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 9f236cdcf3fe..7c74e919cabe 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -481,10 +481,6 @@ enum NET_IPV4_CONF_PROMOTE_SECONDARIES=20, NET_IPV4_CONF_ARP_ACCEPT=21, NET_IPV4_CONF_ARP_NOTIFY=22, - NET_IPV4_CONF_ACCEPT_LOCAL=23, - NET_IPV4_CONF_SRC_VMARK=24, - NET_IPV4_CONF_PROXY_ARP_PVLAN=25, - __NET_IPV4_CONF_MAX }; /* /proc/sys/net/ipv4/netfilter */ diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cd71a3908391..b1eddee9bf94 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -64,20 +64,20 @@ static struct ipv4_devconf ipv4_devconf = { .data = { - [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1, + [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, }, }; static struct ipv4_devconf ipv4_devconf_dflt = { .data = { - [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1, - [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1, - [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1, + [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, + [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, + [IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] = 1, }, }; @@ -1360,7 +1360,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, { \ .procname = name, \ .data = ipv4_devconf.data + \ - NET_IPV4_CONF_ ## attr - 1, \ + IPV4_DEVCONF_ ## attr - 1, \ .maxlen = sizeof(int), \ .mode = mval, \ .proc_handler = proc, \ @@ -1381,7 +1381,7 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; - struct ctl_table devinet_vars[__NET_IPV4_CONF_MAX]; + struct ctl_table devinet_vars[__IPV4_DEVCONF_MAX]; char *dev_name; } devinet_sysctl = { .devinet_vars = { @@ -1503,7 +1503,7 @@ static struct ctl_table ctl_forward_entry[] = { { .procname = "ip_forward", .data = &ipv4_devconf.data[ - NET_IPV4_CONF_FORWARDING - 1], + IPV4_DEVCONF_FORWARDING - 1], .maxlen = sizeof(int), .mode = 0644, .proc_handler = devinet_sysctl_forward, @@ -1547,7 +1547,7 @@ static __net_init int devinet_init_net(struct net *net) if (tbl == NULL) goto err_alloc_ctl; - tbl[0].data = &all->data[NET_IPV4_CONF_FORWARDING - 1]; + tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; tbl[0].extra1 = all; tbl[0].extra2 = net; #endif -- cgit v1.2.3 From 54716e3beb0ab20c49471348dfe399a71bfc8fd3 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 14 Feb 2010 03:27:03 +0000 Subject: net neigh: Decouple per interface neighbour table controls from binary sysctls Stop computing the number of neighbour table settings we have by counting the number of binary sysctls. This behaviour was silly and meant that we could not add another neighbour table setting without also adding another binary sysctl. Don't pass the binary sysctl path for neighour table entries into neigh_sysctl_register. These parameters are no longer used and so are just dead code. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- include/linux/sysctl.h | 1 - include/net/neighbour.h | 1 - net/core/neighbour.c | 7 ++++--- net/ipv4/arp.c | 3 +-- net/ipv4/devinet.c | 3 +-- net/ipv6/addrconf.c | 3 +-- net/ipv6/ndisc.c | 3 +-- 7 files changed, 8 insertions(+), 13 deletions(-) diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 7c74e919cabe..f66014c90c9f 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -596,7 +596,6 @@ enum { NET_NEIGH_GC_THRESH3=16, NET_NEIGH_RETRANS_TIME_MS=17, NET_NEIGH_REACHABLE_TIME_MS=18, - __NET_NEIGH_MAX }; /* /proc/sys/net/dccp */ diff --git a/include/net/neighbour.h b/include/net/neighbour.h index b0173202cad9..7834f470d14a 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -251,7 +251,6 @@ extern void neigh_seq_stop(struct seq_file *, void *); extern int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, - int p_id, int pdev_id, char *p_name, proc_handler *proc_handler); extern void neigh_sysctl_unregister(struct neigh_parms *p); diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f2efd72da799..d102f6d9abdc 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2556,9 +2556,11 @@ EXPORT_SYMBOL(neigh_app_ns); #ifdef CONFIG_SYSCTL +#define NEIGH_VARS_MAX 19 + static struct neigh_sysctl_table { struct ctl_table_header *sysctl_header; - struct ctl_table neigh_vars[__NET_NEIGH_MAX]; + struct ctl_table neigh_vars[NEIGH_VARS_MAX]; char *dev_name; } neigh_sysctl_template __read_mostly = { .neigh_vars = { @@ -2675,8 +2677,7 @@ static struct neigh_sysctl_table { }; int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, - int p_id, int pdev_id, char *p_name, - proc_handler *handler) + char *p_name, proc_handler *handler) { struct neigh_sysctl_table *t; const char *dev_name_source = NULL; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 1940b4df7699..c4dd13542802 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1284,8 +1284,7 @@ void __init arp_init(void) dev_add_pack(&arp_packet_type); arp_proc_init(); #ifdef CONFIG_SYSCTL - neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, - NET_IPV4_NEIGH, "ipv4", NULL); + neigh_sysctl_register(NULL, &arp_tbl.parms, "ipv4", NULL); #endif register_netdevice_notifier(&arp_netdev_notifier); } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index b1eddee9bf94..014982b61564 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1487,8 +1487,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) static void devinet_sysctl_register(struct in_device *idev) { - neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4, - NET_IPV4_NEIGH, "ipv4", NULL); + neigh_sysctl_register(idev->dev, idev->arp_parms, "ipv4", NULL); __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, &idev->cnf); } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 764ad37ca070..c79cbff54370 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4416,8 +4416,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) static void addrconf_sysctl_register(struct inet6_dev *idev) { - neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, - NET_IPV6_NEIGH, "ipv6", + neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6", &ndisc_ifinfo_sysctl_change); __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, idev, &idev->cnf); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2dfec6bb8ada..8bcc4b7db3bf 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1820,8 +1820,7 @@ int __init ndisc_init(void) neigh_table_init(&nd_tbl); #ifdef CONFIG_SYSCTL - err = neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, - NET_IPV6_NEIGH, "ipv6", + err = neigh_sysctl_register(NULL, &nd_tbl.parms, "ipv6", &ndisc_ifinfo_sysctl_change); if (err) goto out_unregister_pernet; -- cgit v1.2.3 From c947862f9126983537a4cc11e07d26882d60b7e7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:05 +0000 Subject: CAPI: Fix leaks in capifs_new_ncci When something went wrong during capifs_new_ncci, the looked up dentry was not properly released. Neither was the allocated inode. Refactor the function to avoid leaks. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 9f8f67b6c07f..dc68fcb122a0 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -152,22 +152,33 @@ static struct dentry *get_node(int num) void capifs_new_ncci(unsigned int number, dev_t device) { struct dentry *dentry; - struct inode *inode = new_inode(capifs_mnt->mnt_sb); - if (!inode) - return; - inode->i_ino = number+2; + struct inode *inode; dentry = get_node(number); + if (IS_ERR(dentry)) + goto unlock_out; + + if (dentry->d_inode) { + dput(dentry); + goto unlock_out; + } + + inode = new_inode(capifs_mnt->mnt_sb); + if (!inode) { + dput(dentry); + goto unlock_out; + } /* config contents is protected by root's i_mutex */ inode->i_uid = config.setuid ? config.uid : current_fsuid(); inode->i_gid = config.setgid ? config.gid : current_fsgid(); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_ino = number + 2; init_special_inode(inode, S_IFCHR|config.mode, device); - //inode->i_op = &capifs_file_inode_operations; - if (!IS_ERR(dentry) && !dentry->d_inode) - d_instantiate(dentry, inode); + d_instantiate(dentry, inode); + +unlock_out: mutex_unlock(&capifs_root->d_inode->i_mutex); } -- cgit v1.2.3 From 90926f0e58dcd9f4ca877961000568a3be787f2f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:06 +0000 Subject: CAPI: Sanitize capifs API Instead of looking up the dentry of an NCCI node again in capifs_free_ncci pass the pointer via the capifs user. This patch also reduces the #ifdef mess in capi.c a bit as far as capifs was causing it. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 14 ++++++------- drivers/isdn/capi/capifs.c | 50 +++++++++++++++++++++++++++------------------- drivers/isdn/capi/capifs.h | 21 +++++++++++++++++-- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 79f9364aded6..dc5ac52986ee 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -42,9 +42,8 @@ #include #include #include -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) + #include "capifs.h" -#endif static char *revision = "$Revision: 1.1.2.7 $"; @@ -96,6 +95,7 @@ struct capiminor { struct list_head list; struct capincci *nccip; unsigned int minor; + struct dentry *capifs_dentry; struct capi20_appl *ap; u32 ncci; @@ -328,9 +328,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "set mp->nccip\n"); #endif -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); -#endif + mp->capifs_dentry = + capifs_new_ncci(mp->minor, + MKDEV(capi_ttymajor, mp->minor)); } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) @@ -353,9 +353,7 @@ static void capincci_free(struct capidev *cdev, u32 ncci) *pp = (*pp)->next; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if ((mp = np->minorp) != NULL) { -#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_free_ncci(mp->minor); -#endif + capifs_free_ncci(mp->capifs_dentry); if (mp->tty) { mp->nccip = NULL; #ifdef _DEBUG_REFCOUNT diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index dc68fcb122a0..91aafadd413f 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -141,31 +141,32 @@ static struct file_system_type capifs_fs_type = { .kill_sb = kill_anon_super, }; -static struct dentry *get_node(int num) -{ - char s[10]; - struct dentry *root = capifs_root; - mutex_lock(&root->d_inode->i_mutex); - return lookup_one_len(s, root, sprintf(s, "%d", num)); -} - -void capifs_new_ncci(unsigned int number, dev_t device) +struct dentry *capifs_new_ncci(unsigned int number, dev_t device) { struct dentry *dentry; struct inode *inode; + char name[10]; + int namelen; - dentry = get_node(number); - if (IS_ERR(dentry)) + mutex_lock(&capifs_root->d_inode->i_mutex); + + namelen = sprintf(name, "%d", number); + dentry = lookup_one_len(name, capifs_root, namelen); + if (IS_ERR(dentry)) { + dentry = NULL; goto unlock_out; + } if (dentry->d_inode) { dput(dentry); + dentry = NULL; goto unlock_out; } inode = new_inode(capifs_mnt->mnt_sb); if (!inode) { dput(dentry); + dentry = NULL; goto unlock_out; } @@ -177,24 +178,31 @@ void capifs_new_ncci(unsigned int number, dev_t device) init_special_inode(inode, S_IFCHR|config.mode, device); d_instantiate(dentry, inode); + dget(dentry); unlock_out: mutex_unlock(&capifs_root->d_inode->i_mutex); + + return dentry; } -void capifs_free_ncci(unsigned int number) +void capifs_free_ncci(struct dentry *dentry) { - struct dentry *dentry = get_node(number); - - if (!IS_ERR(dentry)) { - struct inode *inode = dentry->d_inode; - if (inode) { - inode->i_nlink--; - d_delete(dentry); - dput(dentry); - } + struct inode *inode; + + if (!dentry) + return; + + mutex_lock(&capifs_root->d_inode->i_mutex); + + inode = dentry->d_inode; + if (inode) { + drop_nlink(inode); + d_delete(dentry); dput(dentry); } + dput(dentry); + mutex_unlock(&capifs_root->d_inode->i_mutex); } diff --git a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h index d0bd4c3c430a..e193d1189531 100644 --- a/drivers/isdn/capi/capifs.h +++ b/drivers/isdn/capi/capifs.h @@ -7,5 +7,22 @@ * */ -void capifs_new_ncci(unsigned int num, dev_t device); -void capifs_free_ncci(unsigned int num); +#include + +#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) + +struct dentry *capifs_new_ncci(unsigned int num, dev_t device); +void capifs_free_ncci(struct dentry *dentry); + +#else + +static inline struct dentry *capifs_new_ncci(unsigned int num, dev_t device) +{ + return NULL; +} + +static inline void capifs_free_ncci(struct dentry *dentry) +{ +} + +#endif -- cgit v1.2.3 From 07ad603ab8e3cc35762c15043b59a6ef76542454 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:07 +0000 Subject: CAPI: Eliminate capifs_root variable capifs_mnt->mnt_sb->s_root already contains what we need. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 91aafadd413f..6ae0edf29c85 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -32,7 +32,6 @@ static char *revision = "$Revision: 1.1.2.3 $"; #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; -static struct dentry *capifs_root; static struct { int setuid; @@ -118,7 +117,7 @@ capifs_fill_super(struct super_block *s, void *data, int silent) inode->i_fop = &simple_dir_operations; inode->i_nlink = 2; - capifs_root = s->s_root = d_alloc_root(inode); + s->s_root = d_alloc_root(inode); if (s->s_root) return 0; @@ -143,15 +142,17 @@ static struct file_system_type capifs_fs_type = { struct dentry *capifs_new_ncci(unsigned int number, dev_t device) { + struct super_block *s = capifs_mnt->mnt_sb; + struct dentry *root = s->s_root; struct dentry *dentry; struct inode *inode; char name[10]; int namelen; - mutex_lock(&capifs_root->d_inode->i_mutex); + mutex_lock(&root->d_inode->i_mutex); namelen = sprintf(name, "%d", number); - dentry = lookup_one_len(name, capifs_root, namelen); + dentry = lookup_one_len(name, root, namelen); if (IS_ERR(dentry)) { dentry = NULL; goto unlock_out; @@ -163,7 +164,7 @@ struct dentry *capifs_new_ncci(unsigned int number, dev_t device) goto unlock_out; } - inode = new_inode(capifs_mnt->mnt_sb); + inode = new_inode(s); if (!inode) { dput(dentry); dentry = NULL; @@ -181,19 +182,20 @@ struct dentry *capifs_new_ncci(unsigned int number, dev_t device) dget(dentry); unlock_out: - mutex_unlock(&capifs_root->d_inode->i_mutex); + mutex_unlock(&root->d_inode->i_mutex); return dentry; } void capifs_free_ncci(struct dentry *dentry) { + struct dentry *root = capifs_mnt->mnt_sb->s_root; struct inode *inode; if (!dentry) return; - mutex_lock(&capifs_root->d_inode->i_mutex); + mutex_lock(&root->d_inode->i_mutex); inode = dentry->d_inode; if (inode) { @@ -203,7 +205,7 @@ void capifs_free_ncci(struct dentry *dentry) } dput(dentry); - mutex_unlock(&capifs_root->d_inode->i_mutex); + mutex_unlock(&root->d_inode->i_mutex); } static int __init capifs_init(void) -- cgit v1.2.3 From e11e7ac1ecac6b25439c003c5ca661cd399ec35d Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:08 +0000 Subject: CAPI: Pin capifs instead of mounting it Auto-mounting the capifs during module init prevents unloading its module. Instead, pin the filesystem as long as some NCCI node exists. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capifs.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 6ae0edf29c85..51c01efe2fe4 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -32,6 +32,7 @@ static char *revision = "$Revision: 1.1.2.3 $"; #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; +static int capifs_mnt_count; static struct { int setuid; @@ -140,7 +141,7 @@ static struct file_system_type capifs_fs_type = { .kill_sb = kill_anon_super, }; -struct dentry *capifs_new_ncci(unsigned int number, dev_t device) +static struct dentry *new_ncci(unsigned int number, dev_t device) { struct super_block *s = capifs_mnt->mnt_sb; struct dentry *root = s->s_root; @@ -187,6 +188,20 @@ unlock_out: return dentry; } +struct dentry *capifs_new_ncci(unsigned int number, dev_t device) +{ + struct dentry *dentry; + + if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0) + return NULL; + + dentry = new_ncci(number, device); + if (!dentry) + simple_release_fs(&capifs_mnt, &capifs_mnt_count); + + return dentry; +} + void capifs_free_ncci(struct dentry *dentry) { struct dentry *root = capifs_mnt->mnt_sb->s_root; @@ -206,6 +221,8 @@ void capifs_free_ncci(struct dentry *dentry) dput(dentry); mutex_unlock(&root->d_inode->i_mutex); + + simple_release_fs(&capifs_mnt, &capifs_mnt_count); } static int __init capifs_init(void) @@ -222,13 +239,6 @@ static int __init capifs_init(void) strcpy(rev, "1.0"); err = register_filesystem(&capifs_fs_type); - if (!err) { - capifs_mnt = kern_mount(&capifs_fs_type); - if (IS_ERR(capifs_mnt)) { - err = PTR_ERR(capifs_mnt); - unregister_filesystem(&capifs_fs_type); - } - } if (!err) printk(KERN_NOTICE "capifs: Rev %s\n", rev); return err; @@ -237,7 +247,6 @@ static int __init capifs_init(void) static void __exit capifs_exit(void) { unregister_filesystem(&capifs_fs_type); - mntput(capifs_mnt); } EXPORT_SYMBOL(capifs_new_ncci); -- cgit v1.2.3 From 88549d6b76346e677da8d2d52b37615df18a4345 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:09 +0000 Subject: CAPI: Reduce chattiness during module loading/removal The CVS revisions dumped by all CAPI modules are meaningless today. And that some CAPI module is loaded or removed does not necessarily deserve a message. Just keep the message of the central module, capi.ko, drop the rest. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++---------------- drivers/isdn/capi/capidrv.c | 26 -------------------------- drivers/isdn/capi/capifs.c | 20 +------------------- drivers/isdn/capi/kcapi.c | 27 +++++---------------------- 4 files changed, 9 insertions(+), 83 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index dc5ac52986ee..3b077978c496 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -45,8 +45,6 @@ #include "capifs.h" -static char *revision = "$Revision: 1.1.2.7 $"; - MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -1489,21 +1487,11 @@ static void __exit proc_exit(void) /* -------- init function and module interface ---------------------- */ -static char rev[32]; - static int __init capi_init(void) { - char *p; - char *compileinfo; + const char *compileinfo; int major_ret; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - major_ret = register_chrdev(capi_major, "capi20", &capi_fops); if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); @@ -1537,8 +1525,8 @@ static int __init capi_init(void) #else compileinfo = " (no middleware)"; #endif - printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", - rev, capi_major, compileinfo); + printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n", + capi_major, compileinfo); return 0; } @@ -1554,7 +1542,6 @@ static void __exit capi_exit(void) #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); #endif - printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev); } module_init(capi_init); diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index bb450152fb74..7d8899ad5796 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -35,7 +35,6 @@ #include #include "capidrv.h" -static char *revision = "$Revision: 1.1.2.2 $"; static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); @@ -2266,19 +2265,9 @@ static void __exit proc_exit(void) static int __init capidrv_init(void) { capi_profile profile; - char rev[32]; - char *p; u32 ncontr, contr; u16 errcode; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strncpy(rev, p + 2, sizeof(rev)); - rev[sizeof(rev)-1] = 0; - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - global.ap.rparam.level3cnt = -2; /* number of bchannels twice */ global.ap.rparam.datablkcnt = 16; global.ap.rparam.datablklen = 2048; @@ -2306,29 +2295,14 @@ static int __init capidrv_init(void) } proc_init(); - printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev); return 0; } static void __exit capidrv_exit(void) { - char rev[32]; - char *p; - - if ((p = strchr(revision, ':')) != NULL) { - strncpy(rev, p + 1, sizeof(rev)); - rev[sizeof(rev)-1] = 0; - if ((p = strchr(rev, '$')) != NULL) - *p = 0; - } else { - strcpy(rev, " ??? "); - } - capi20_release(&global.ap); proc_exit(); - - printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); } module_init(capidrv_init); diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 51c01efe2fe4..8596bd1a4d26 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -25,10 +25,6 @@ MODULE_LICENSE("GPL"); /* ------------------------------------------------------------------ */ -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------------ */ - #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') static struct vfsmount *capifs_mnt; @@ -227,21 +223,7 @@ void capifs_free_ncci(struct dentry *dentry) static int __init capifs_init(void) { - char rev[32]; - char *p; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - - err = register_filesystem(&capifs_fs_type); - if (!err) - printk(KERN_NOTICE "capifs: Rev %s\n", rev); - return err; + return register_filesystem(&capifs_fs_type); } static void __exit capifs_exit(void) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index b0bacf377c18..ef564ee1c06c 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -35,10 +35,6 @@ #endif #include -static char *revision = "$Revision: 1.1.2.8 $"; - -/* ------------------------------------------------------------- */ - static int showcapimsgs = 0; MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); @@ -1165,25 +1161,12 @@ EXPORT_SYMBOL(capi20_set_callback); static int __init kcapi_init(void) { - char *p; - char rev[32]; - int ret; - - ret = cdebug_init(); - if (ret) - return ret; - kcapi_proc_init(); + int err; - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p-1) = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_NOTICE "CAPI Subsystem Rev %s\n", rev); - - return 0; + err = cdebug_init(); + if (!err) + kcapi_proc_init(); + return err; } static void __exit kcapi_exit(void) -- cgit v1.2.3 From 522530311b35ec8fc4785062441dd2d63967ac55 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:10 +0000 Subject: CAPI: Call a controller 'controller', not 'card' At least for our internal use, fix the misnomers that refer to a CAPI controller as 'card'. No functional changes. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 320 +++++++++++++++++++++-------------------- drivers/isdn/capi/kcapi.h | 8 +- drivers/isdn/capi/kcapi_proc.c | 17 ++- include/linux/isdn/capilli.h | 2 +- 4 files changed, 178 insertions(+), 169 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index ef564ee1c06c..f37c13b4ddc7 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -67,24 +67,24 @@ static DEFINE_RWLOCK(application_lock); static DEFINE_MUTEX(controller_mutex); struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -struct capi_ctr *capi_cards[CAPI_MAXCONTR]; +struct capi_ctr *capi_controller[CAPI_MAXCONTR]; -static int ncards; +static int ncontrollers; /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * -capi_ctr_get(struct capi_ctr *card) +capi_ctr_get(struct capi_ctr *ctr) { - if (!try_module_get(card->owner)) + if (!try_module_get(ctr->owner)) return NULL; - return card; + return ctr; } static inline void -capi_ctr_put(struct capi_ctr *card) +capi_ctr_put(struct capi_ctr *ctr) { - module_put(card->owner); + module_put(ctr->owner); } /* ------------------------------------------------------------- */ @@ -94,7 +94,7 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) if (contr - 1 >= CAPI_MAXCONTR) return NULL; - return capi_cards[contr - 1]; + return capi_controller[contr - 1]; } static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) @@ -144,46 +144,48 @@ static inline int capi_subcmd_valid(u8 subcmd) /* ------------------------------------------------------------ */ -static void register_appl(struct capi_ctr *card, u16 applid, capi_register_params *rparam) +static void +register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam) { - card = capi_ctr_get(card); + ctr = capi_ctr_get(ctr); - if (card) - card->register_appl(card, applid, rparam); + if (ctr) + ctr->register_appl(ctr, applid, rparam); else - printk(KERN_WARNING "%s: cannot get card resources\n", __func__); + printk(KERN_WARNING "%s: cannot get controller resources\n", + __func__); } -static void release_appl(struct capi_ctr *card, u16 applid) +static void release_appl(struct capi_ctr *ctr, u16 applid) { DBG("applid %#x", applid); - card->release_appl(card, applid); - capi_ctr_put(card); + ctr->release_appl(ctr, applid); + capi_ctr_put(ctr); } /* -------- KCI_CONTRUP --------------------------------------- */ static void notify_up(u32 contr) { - struct capi_ctr *card = get_capi_ctr_by_nr(contr); + struct capi_ctr *ctr = get_capi_ctr_by_nr(contr); struct capi20_appl *ap; u16 applid; if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); } - if (!card) { + if (!ctr) { printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); return; } for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); if (!ap || ap->release_in_progress) continue; - register_appl(card, applid, &ap->rparam); + register_appl(ctr, applid, &ap->rparam); if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, &card->profile); + ap->callback(KCI_CONTRUP, contr, &ctr->profile); } } @@ -269,14 +271,15 @@ static void recv_handler(struct work_struct *work) /** * capi_ctr_handle_message() - handle incoming CAPI message - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * @appl: application ID. * @skb: message. * * Called by hardware driver to pass a CAPI message to the application. */ -void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) +void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, + struct sk_buff *skb) { struct capi20_appl *ap; int showctl = 0; @@ -284,43 +287,45 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s unsigned long flags; _cdebbuf *cdb; - if (card->cardstate != CARD_RUNNING) { + if (ctr->state != CAPI_CTR_RUNNING) { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", - card->cnr, cdb->buf); + ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", - card->cnr); + ctr->cnr); goto error; } cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { - card->nrecvdatapkt++; - if (card->traceflag > 2) showctl |= 2; + ctr->nrecvdatapkt++; + if (ctr->traceflag > 2) + showctl |= 2; } else { - card->nrecvctlpkt++; - if (card->traceflag) showctl |= 2; + ctr->nrecvctlpkt++; + if (ctr->traceflag) + showctl |= 2; } - showctl |= (card->traceflag & 1); + showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", - card->cnr, CAPIMSG_APPID(skb->data), + ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_DEBUG "kcapi: got [%03d] %s\n", - card->cnr, cdb->buf); + ctr->cnr, cdb->buf); cdebbuf_free(cdb); } else printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", - card->cnr, CAPIMSG_APPID(skb->data), + ctr->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } @@ -356,74 +361,75 @@ EXPORT_SYMBOL(capi_ctr_handle_message); /** * capi_ctr_ready() - signal CAPI controller ready - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is up and running. */ -void capi_ctr_ready(struct capi_ctr * card) +void capi_ctr_ready(struct capi_ctr *ctr) { - card->cardstate = CARD_RUNNING; + ctr->state = CAPI_CTR_RUNNING; - printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", - card->cnr, card->name); + printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", + ctr->cnr, ctr->name); - notify_push(KCI_CONTRUP, card->cnr, 0, 0); + notify_push(KCI_CONTRUP, ctr->cnr, 0, 0); } EXPORT_SYMBOL(capi_ctr_ready); /** * capi_ctr_down() - signal CAPI controller not ready - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to signal that the controller is down and * unavailable for use. */ -void capi_ctr_down(struct capi_ctr * card) +void capi_ctr_down(struct capi_ctr *ctr) { u16 appl; DBG(""); - if (card->cardstate == CARD_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED) return; - card->cardstate = CARD_DETECTED; + ctr->state = CAPI_CTR_DETECTED; - memset(card->manu, 0, sizeof(card->manu)); - memset(&card->version, 0, sizeof(card->version)); - memset(&card->profile, 0, sizeof(card->profile)); - memset(card->serial, 0, sizeof(card->serial)); + memset(ctr->manu, 0, sizeof(ctr->manu)); + memset(&ctr->version, 0, sizeof(ctr->version)); + memset(&ctr->profile, 0, sizeof(ctr->profile)); + memset(ctr->serial, 0, sizeof(ctr->serial)); for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { struct capi20_appl *ap = get_capi_appl_by_nr(appl); if (!ap || ap->release_in_progress) continue; - capi_ctr_put(card); + capi_ctr_put(ctr); } - printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); + printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); - notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); + notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); } EXPORT_SYMBOL(capi_ctr_down); /** * capi_ctr_suspend_output() - suspend controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to stop data flow. */ -void capi_ctr_suspend_output(struct capi_ctr *card) +void capi_ctr_suspend_output(struct capi_ctr *ctr) { - if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); - card->blocked = 1; + if (!ctr->blocked) { + printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", + ctr->cnr); + ctr->blocked = 1; } } @@ -431,16 +437,17 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); /** * capi_ctr_resume_output() - resume controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to resume data flow. */ -void capi_ctr_resume_output(struct capi_ctr *card) +void capi_ctr_resume_output(struct capi_ctr *ctr) { - if (card->blocked) { - printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); - card->blocked = 0; + if (ctr->blocked) { + printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", + ctr->cnr); + ctr->blocked = 0; } } @@ -450,21 +457,20 @@ EXPORT_SYMBOL(capi_ctr_resume_output); /** * attach_capi_ctr() - register CAPI controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to register a controller with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */ -int -attach_capi_ctr(struct capi_ctr *card) +int attach_capi_ctr(struct capi_ctr *ctr) { int i; mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (capi_cards[i] == NULL) + if (!capi_controller[i]) break; } if (i == CAPI_MAXCONTR) { @@ -472,25 +478,25 @@ attach_capi_ctr(struct capi_ctr *card) printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } - capi_cards[i] = card; + capi_controller[i] = ctr; mutex_unlock(&controller_mutex); - card->nrecvctlpkt = 0; - card->nrecvdatapkt = 0; - card->nsentctlpkt = 0; - card->nsentdatapkt = 0; - card->cnr = i + 1; - card->cardstate = CARD_DETECTED; - card->blocked = 0; - card->traceflag = showcapimsgs; - - sprintf(card->procfn, "capi/controllers/%d", card->cnr); - card->procent = proc_create_data(card->procfn, 0, NULL, card->proc_fops, card); - - ncards++; - printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", - card->cnr, card->name); + ctr->nrecvctlpkt = 0; + ctr->nrecvdatapkt = 0; + ctr->nsentctlpkt = 0; + ctr->nsentdatapkt = 0; + ctr->cnr = i + 1; + ctr->state = CAPI_CTR_DETECTED; + ctr->blocked = 0; + ctr->traceflag = showcapimsgs; + + sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); + ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); + + ncontrollers++; + printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", + ctr->cnr, ctr->name); return 0; } @@ -498,27 +504,27 @@ EXPORT_SYMBOL(attach_capi_ctr); /** * detach_capi_ctr() - unregister CAPI controller - * @card: controller descriptor structure. + * @ctr: controller descriptor structure. * * Called by hardware driver to remove the registration of a controller * with the CAPI subsystem. * Return value: 0 on success, error code < 0 on error */ -int detach_capi_ctr(struct capi_ctr *card) +int detach_capi_ctr(struct capi_ctr *ctr) { - if (card->cardstate != CARD_DETECTED) - capi_ctr_down(card); + if (ctr->state != CAPI_CTR_DETECTED) + capi_ctr_down(ctr); - ncards--; + ncontrollers--; - if (card->procent) { - remove_proc_entry(card->procfn, NULL); - card->procent = NULL; + if (ctr->procent) { + remove_proc_entry(ctr->procfn, NULL); + ctr->procent = NULL; } - capi_cards[card->cnr - 1] = NULL; - printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", - card->cnr, card->name); + capi_controller[ctr->cnr - 1] = NULL; + printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", + ctr->cnr, ctr->name); return 0; } @@ -576,7 +582,8 @@ u16 capi20_isinstalled(void) { int i; for (i = 0; i < CAPI_MAXCONTR; i++) { - if (capi_cards[i] && capi_cards[i]->cardstate == CARD_RUNNING) + if (capi_controller[i] && + capi_controller[i]->state == CAPI_CTR_RUNNING) return CAPI_NOERROR; } return CAPI_REGNOTINSTALLED; @@ -635,9 +642,10 @@ u16 capi20_register(struct capi20_appl *ap) mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) + if (!capi_controller[i] || + capi_controller[i]->state != CAPI_CTR_RUNNING) continue; - register_appl(capi_cards[i], applid, &ap->rparam); + register_appl(capi_controller[i], applid, &ap->rparam); } mutex_unlock(&controller_mutex); @@ -674,9 +682,10 @@ u16 capi20_release(struct capi20_appl *ap) mutex_lock(&controller_mutex); for (i = 0; i < CAPI_MAXCONTR; i++) { - if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) + if (!capi_controller[i] || + capi_controller[i]->state != CAPI_CTR_RUNNING) continue; - release_appl(capi_cards[i], ap->applid); + release_appl(capi_controller[i], ap->applid); } mutex_unlock(&controller_mutex); @@ -703,13 +712,13 @@ EXPORT_SYMBOL(capi20_release); u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) { - struct capi_ctr *card; + struct capi_ctr *ctr; int showctl = 0; u8 cmd, subcmd; DBG("applid %#x", ap->applid); - if (ncards == 0) + if (ncontrollers == 0) return CAPI_REGNOTINSTALLED; if ((ap->applid == 0) || ap->release_in_progress) return CAPI_ILLAPPNR; @@ -717,28 +726,30 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - card = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); - if (!card || card->cardstate != CARD_RUNNING) { - card = get_capi_ctr_by_nr(1); // XXX why? - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) { + ctr = get_capi_ctr_by_nr(1); /* XXX why? */ + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; } - if (card->blocked) + if (ctr->blocked) return CAPI_SENDQUEUEFULL; cmd = CAPIMSG_COMMAND(skb->data); subcmd = CAPIMSG_SUBCOMMAND(skb->data); if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { - card->nsentdatapkt++; + ctr->nsentdatapkt++; ap->nsentdatapkt++; - if (card->traceflag > 2) showctl |= 2; + if (ctr->traceflag > 2) + showctl |= 2; } else { - card->nsentctlpkt++; + ctr->nsentctlpkt++; ap->nsentctlpkt++; - if (card->traceflag) showctl |= 2; + if (ctr->traceflag) + showctl |= 2; } - showctl |= (card->traceflag & 1); + showctl |= (ctr->traceflag & 1); if (showctl & 2) { if (showctl & 1) { printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", @@ -761,7 +772,7 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) CAPIMSG_LEN(skb->data)); } } - return card->send_message(card, skb); + return ctr->send_message(ctr, skb); } EXPORT_SYMBOL(capi20_put_message); @@ -778,16 +789,16 @@ EXPORT_SYMBOL(capi20_put_message); u16 capi20_get_manufacturer(u32 contr, u8 *buf) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN); + strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } @@ -805,17 +816,17 @@ EXPORT_SYMBOL(capi20_get_manufacturer); u16 capi20_get_version(u32 contr, struct capi_version *verp) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - memcpy((void *) verp, &card->version, sizeof(capi_version)); + memcpy(verp, &ctr->version, sizeof(capi_version)); return CAPI_NOERROR; } @@ -833,17 +844,17 @@ EXPORT_SYMBOL(capi20_get_version); u16 capi20_get_serial(u32 contr, u8 *serial) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN); + strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } @@ -861,18 +872,17 @@ EXPORT_SYMBOL(capi20_get_serial); u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { - struct capi_ctr *card; + struct capi_ctr *ctr; if (contr == 0) { - profp->ncontroller = ncards; + profp->ncontroller = ncontrollers; return CAPI_NOERROR; } - card = get_capi_ctr_by_nr(contr); - if (!card || card->cardstate != CARD_RUNNING) + ctr = get_capi_ctr_by_nr(contr); + if (!ctr || ctr->state != CAPI_CTR_RUNNING) return CAPI_REGNOTINSTALLED; - memcpy((void *) profp, &card->profile, - sizeof(struct capi_profile)); + memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); return CAPI_NOERROR; } @@ -885,7 +895,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) avmb1_extcarddef cdef; avmb1_resetdef rdef; capicardparams cparams; - struct capi_ctr *card; + struct capi_ctr *ctr; struct capi_driver *driver = NULL; capiloaddata ldata; struct list_head *l; @@ -958,26 +968,26 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) sizeof(avmb1_loadandconfigdef))) return -EFAULT; } - card = get_capi_ctr_by_nr(ldef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(ldef.contr); + if (!ctr) return -EINVAL; - card = capi_ctr_get(card); - if (!card) + ctr = capi_ctr_get(ctr); + if (!ctr) return -ESRCH; - if (card->load_firmware == NULL) { + if (ctr->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); - capi_ctr_put(card); + capi_ctr_put(ctr); return -ESRCH; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINVAL; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINVAL; } @@ -988,46 +998,46 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) ldata.configuration.data = ldef.t4config.data; ldata.configuration.len = ldef.t4config.len; - if (card->cardstate != CARD_DETECTED) { + if (ctr->state != CAPI_CTR_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - capi_ctr_put(card); + capi_ctr_put(ctr); return -EBUSY; } - card->cardstate = CARD_LOADING; + ctr->state = CAPI_CTR_LOADING; - retval = card->load_firmware(card, &ldata); + retval = ctr->load_firmware(ctr, &ldata); if (retval) { - card->cardstate = CARD_DETECTED; - capi_ctr_put(card); + ctr->state = CAPI_CTR_DETECTED; + capi_ctr_put(ctr); return retval; } - while (card->cardstate != CARD_RUNNING) { + while (ctr->state != CAPI_CTR_RUNNING) { msleep_interruptible(100); /* 0.1 sec */ if (signal_pending(current)) { - capi_ctr_put(card); + capi_ctr_put(ctr); return -EINTR; } } - capi_ctr_put(card); + capi_ctr_put(ctr); return 0; case AVMB1_RESETCARD: if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) return -EFAULT; - card = get_capi_ctr_by_nr(rdef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(rdef.contr); + if (!ctr) return -ESRCH; - if (card->cardstate == CARD_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED) return 0; - card->reset_ctr(card); + ctr->reset_ctr(ctr); - while (card->cardstate > CARD_DETECTED) { + while (ctr->state > CAPI_CTR_DETECTED) { msleep_interruptible(100); /* 0.1 sec */ @@ -1052,7 +1062,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) int capi20_manufacturer(unsigned int cmd, void __user *data) { - struct capi_ctr *card; + struct capi_ctr *ctr; switch (cmd) { #ifdef AVMB1_COMPAT @@ -1070,13 +1080,13 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) return -EFAULT; - card = get_capi_ctr_by_nr(fdef.contr); - if (!card) + ctr = get_capi_ctr_by_nr(fdef.contr); + if (!ctr) return -ESRCH; - card->traceflag = fdef.flag; + ctr->traceflag = fdef.flag; printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", - card->cnr, card->traceflag); + ctr->cnr, ctr->traceflag); return 0; } case KCAPI_CMD_ADDCARD: diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 244711f7f838..f62c53bd6a97 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -24,16 +24,16 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ #endif enum { - CARD_DETECTED = 1, - CARD_LOADING = 2, - CARD_RUNNING = 3, + CAPI_CTR_DETECTED = 1, + CAPI_CTR_LOADING = 2, + CAPI_CTR_RUNNING = 3, }; extern struct list_head capi_drivers; extern rwlock_t capi_drivers_list_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -extern struct capi_ctr *capi_cards[CAPI_MAXCONTR]; +extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 09d4db764d22..59fd16a4ad8e 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -15,13 +15,12 @@ #include #include -static char * -cardstate2str(unsigned short cardstate) +static char *state2str(unsigned short state) { - switch (cardstate) { - case CARD_DETECTED: return "detected"; - case CARD_LOADING: return "loading"; - case CARD_RUNNING: return "running"; + switch (state) { + case CAPI_CTR_DETECTED: return "detected"; + case CAPI_CTR_LOADING: return "loading"; + case CAPI_CTR_RUNNING: return "running"; default: return "???"; } } @@ -38,7 +37,7 @@ cardstate2str(unsigned short cardstate) static void *controller_start(struct seq_file *seq, loff_t *pos) { if (*pos < CAPI_MAXCONTR) - return &capi_cards[*pos]; + return &capi_controller[*pos]; return NULL; } @@ -47,7 +46,7 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; if (*pos < CAPI_MAXCONTR) - return &capi_cards[*pos]; + return &capi_controller[*pos]; return NULL; } @@ -65,7 +64,7 @@ static int controller_show(struct seq_file *seq, void *v) seq_printf(seq, "%d %-10s %-8s %-16s %s\n", ctr->cnr, ctr->driver_name, - cardstate2str(ctr->cardstate), + state2str(ctr->state), ctr->name, ctr->procinfo ? ctr->procinfo(ctr) : ""); diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index d3e5e9da0c82..856f38eddd78 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -66,7 +66,7 @@ struct capi_ctr { unsigned long nsentdatapkt; int cnr; /* controller number */ - volatile unsigned short cardstate; /* controller state */ + volatile unsigned short state; /* controller state */ volatile int blocked; /* output blocked */ int traceflag; /* capi trace */ -- cgit v1.2.3 From 9717fb8b64ed41be9dd074bc8010bafd33046f1a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:11 +0000 Subject: CAPI: Convert capi drivers rwlock into mutex Turn the lock protecting registered capi drivers into a mutex and apply it consistently. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 49 +++++++++++++++++++----------------------- drivers/isdn/capi/kcapi.h | 2 +- drivers/isdn/capi/kcapi_proc.c | 8 +++---- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index f37c13b4ddc7..c46964fc17c7 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -61,7 +61,7 @@ static char capi_manufakturer[64] = "AVM Berlin"; #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) LIST_HEAD(capi_drivers); -DEFINE_RWLOCK(capi_drivers_list_lock); +DEFINE_MUTEX(capi_drivers_lock); static DEFINE_RWLOCK(application_lock); static DEFINE_MUTEX(controller_mutex); @@ -540,11 +540,9 @@ EXPORT_SYMBOL(detach_capi_ctr); void register_capi_driver(struct capi_driver *driver) { - unsigned long flags; - - write_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); list_add_tail(&driver->list, &capi_drivers); - write_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); } EXPORT_SYMBOL(register_capi_driver); @@ -558,11 +556,9 @@ EXPORT_SYMBOL(register_capi_driver); void unregister_capi_driver(struct capi_driver *driver) { - unsigned long flags; - - write_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); list_del(&driver->list); - write_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); } EXPORT_SYMBOL(unregister_capi_driver); @@ -899,7 +895,6 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) struct capi_driver *driver = NULL; capiloaddata ldata; struct list_head *l; - unsigned long flags; int retval; switch (cmd) { @@ -919,7 +914,8 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) cparams.irq = cdef.irq; cparams.cardnr = cdef.cardnr; - read_lock_irqsave(&capi_drivers_list_lock, flags); + mutex_lock(&capi_drivers_lock); + switch (cdef.cardtype) { case AVM_CARDTYPE_B1: list_for_each(l, &capi_drivers) { @@ -940,18 +936,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) break; } if (!driver) { - read_unlock_irqrestore(&capi_drivers_list_lock, flags); printk(KERN_ERR "kcapi: driver not loaded.\n"); - return -EIO; - } - if (!driver->add_card) { - read_unlock_irqrestore(&capi_drivers_list_lock, flags); + retval = -EIO; + } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver has no add card function.\n"); - return -EIO; - } + retval = -EIO; + } else + retval = driver->add_card(driver, &cparams); - retval = driver->add_card(driver, &cparams); - read_unlock_irqrestore(&capi_drivers_list_lock, flags); + mutex_unlock(&capi_drivers_lock); return retval; case AVMB1_LOAD: @@ -1107,6 +1100,8 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) cparams.cardtype = 0; cdef.driver[sizeof(cdef.driver)-1] = 0; + mutex_lock(&capi_drivers_lock); + list_for_each(l, &capi_drivers) { driver = list_entry(l, struct capi_driver, list); if (strcmp(driver->name, cdef.driver) == 0) @@ -1115,15 +1110,15 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (driver == NULL) { printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", cdef.driver); - return -ESRCH; - } - - if (!driver->add_card) { + retval = -ESRCH; + } else if (!driver->add_card) { printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - return -EIO; - } + retval = -EIO; + } else + retval = driver->add_card(driver, &cparams); - return driver->add_card(driver, &cparams); + mutex_unlock(&capi_drivers_lock); + return retval; } default: diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index f62c53bd6a97..07c58500fe48 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -30,7 +30,7 @@ enum { }; extern struct list_head capi_drivers; -extern rwlock_t capi_drivers_list_lock; +extern struct mutex capi_drivers_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 59fd16a4ad8e..71b07610ff31 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -238,9 +238,9 @@ static const struct file_operations proc_applstats_ops = { // --------------------------------------------------------------------------- static void *capi_driver_start(struct seq_file *seq, loff_t *pos) - __acquires(&capi_drivers_list_lock) + __acquires(&capi_drivers_lock) { - read_lock(&capi_drivers_list_lock); + mutex_lock(&capi_drivers_lock); return seq_list_start(&capi_drivers, *pos); } @@ -250,9 +250,9 @@ static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) } static void capi_driver_stop(struct seq_file *seq, void *v) - __releases(&capi_drivers_list_lock) + __releases(&capi_drivers_lock) { - read_unlock(&capi_drivers_list_lock); + mutex_unlock(&capi_drivers_lock); } static int capi_driver_show(struct seq_file *seq, void *v) -- cgit v1.2.3 From 3efecf7a49cde47e5f2deb1d5504951ff4bede53 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:12 +0000 Subject: CAPI: Rework capi_ctr_ready/down This step prepares the application of proper controller locking: Push all state changing work into the notify handler that are called by capi_ctr_ready and capi_ctr_down, switch detach_capi_ctr to issue a synchronous ctr_down. Also ensure that we do not go through any action if the state did not change. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 95 +++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index c46964fc17c7..9362a7a66aa1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -169,44 +169,74 @@ static void release_appl(struct capi_ctr *ctr, u16 applid) static void notify_up(u32 contr) { - struct capi_ctr *ctr = get_capi_ctr_by_nr(contr); struct capi20_appl *ap; + struct capi_ctr *ctr; u16 applid; - if (showcapimsgs & 1) { + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); - } - if (!ctr) { + + ctr = get_capi_ctr_by_nr(contr); + if (ctr) { + if (ctr->state == CAPI_CTR_RUNNING) + return; + + ctr->state = CAPI_CTR_RUNNING; + + for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { + ap = get_capi_appl_by_nr(applid); + if (!ap || ap->release_in_progress) + continue; + register_appl(ctr, applid, &ap->rparam); + if (ap->callback && !ap->release_in_progress) + ap->callback(KCI_CONTRUP, contr, + &ctr->profile); + } + } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); - return; - } - for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { - ap = get_capi_appl_by_nr(applid); - if (!ap || ap->release_in_progress) continue; - register_appl(ctr, applid, &ap->rparam); - if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, &ctr->profile); - } } /* -------- KCI_CONTRDOWN ------------------------------------- */ -static void notify_down(u32 contr) +static void ctr_down(struct capi_ctr *ctr) { struct capi20_appl *ap; u16 applid; - if (showcapimsgs & 1) { - printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); - } + if (ctr->state == CAPI_CTR_DETECTED) + return; + + ctr->state = CAPI_CTR_DETECTED; + + memset(ctr->manu, 0, sizeof(ctr->manu)); + memset(&ctr->version, 0, sizeof(ctr->version)); + memset(&ctr->profile, 0, sizeof(ctr->profile)); + memset(ctr->serial, 0, sizeof(ctr->serial)); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRDOWN, contr, NULL); + if (ap && !ap->release_in_progress) { + if (ap->callback) + ap->callback(KCI_CONTRDOWN, ctr->cnr, NULL); + capi_ctr_put(ctr); + } } } +static void notify_down(u32 contr) +{ + struct capi_ctr *ctr; + + if (showcapimsgs & 1) + printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); + + ctr = get_capi_ctr_by_nr(contr); + if (ctr) + ctr_down(ctr); + else + printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); +} + static void notify_handler(struct work_struct *work) { struct capi_notifier *np = @@ -368,8 +398,6 @@ EXPORT_SYMBOL(capi_ctr_handle_message); void capi_ctr_ready(struct capi_ctr *ctr) { - ctr->state = CAPI_CTR_RUNNING; - printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", ctr->cnr, ctr->name); @@ -388,28 +416,6 @@ EXPORT_SYMBOL(capi_ctr_ready); void capi_ctr_down(struct capi_ctr *ctr) { - u16 appl; - - DBG(""); - - if (ctr->state == CAPI_CTR_DETECTED) - return; - - ctr->state = CAPI_CTR_DETECTED; - - memset(ctr->manu, 0, sizeof(ctr->manu)); - memset(&ctr->version, 0, sizeof(ctr->version)); - memset(&ctr->profile, 0, sizeof(ctr->profile)); - memset(ctr->serial, 0, sizeof(ctr->serial)); - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - struct capi20_appl *ap = get_capi_appl_by_nr(appl); - if (!ap || ap->release_in_progress) - continue; - - capi_ctr_put(ctr); - } - printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); @@ -513,8 +519,7 @@ EXPORT_SYMBOL(attach_capi_ctr); int detach_capi_ctr(struct capi_ctr *ctr) { - if (ctr->state != CAPI_CTR_DETECTED) - capi_ctr_down(ctr); + ctr_down(ctr); ncontrollers--; -- cgit v1.2.3 From ef69bb2ec6036945da1d3d3f07b75253f484f693 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:13 +0000 Subject: CAPI: Rework controller state notifier Another step towards proper locking: Rework the callback provided to capidrv for controller state changes. This is so far attached to an application, which would require us to hold the corresponding lock across notification calls. But there is no direct relation between a controller up/down event and an application, so let's decouple them and provide a notifier call chain for those events instead. This notifier chain is first of all used internally. Here we request the highest priority to unsure that housekeeping work is done before any other notifications. The chain is exported via [un]register_capictr_notifier to our only user, capidrv, to replace the racy and unfixable capi20_set_callback. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capidrv.c | 22 ++++++--- drivers/isdn/capi/kcapi.c | 112 ++++++++++++++++++++------------------------ include/linux/kernelcapi.h | 17 ++----- 3 files changed, 72 insertions(+), 79 deletions(-) diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 7d8899ad5796..bf55ed5f38e3 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -2210,19 +2210,24 @@ static int capidrv_delcontr(u16 contr) } -static void lower_callback(unsigned int cmd, u32 contr, void *data) +static int +lower_callback(struct notifier_block *nb, unsigned long val, void *v) { + capi_profile profile; + u32 contr = (long)v; - switch (cmd) { - case KCI_CONTRUP: + switch (val) { + case CAPICTR_UP: printk(KERN_INFO "capidrv: controller %hu up\n", contr); - (void) capidrv_addcontr(contr, (capi_profile *) data); + if (capi20_get_profile(contr, &profile) == CAPI_NOERROR) + (void) capidrv_addcontr(contr, &profile); break; - case KCI_CONTRDOWN: + case CAPICTR_DOWN: printk(KERN_INFO "capidrv: controller %hu down\n", contr); (void) capidrv_delcontr(contr); break; } + return NOTIFY_OK; } /* @@ -2262,6 +2267,10 @@ static void __exit proc_exit(void) remove_proc_entry("capi/capidrv", NULL); } +static struct notifier_block capictr_nb = { + .notifier_call = lower_callback, +}; + static int __init capidrv_init(void) { capi_profile profile; @@ -2278,7 +2287,7 @@ static int __init capidrv_init(void) return -EIO; } - capi20_set_callback(&global.ap, lower_callback); + register_capictr_notifier(&capictr_nb); errcode = capi20_get_profile(0, &profile); if (errcode != CAPI_NOERROR) { @@ -2300,6 +2309,7 @@ static int __init capidrv_init(void) static void __exit capidrv_exit(void) { + unregister_capictr_notifier(&capictr_nb); capi20_release(&global.ap); proc_exit(); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 9362a7a66aa1..e08914d33be1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -44,12 +44,10 @@ module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ -struct capi_notifier { +struct capictr_event { struct work_struct work; - unsigned int cmd; + unsigned int type; u32 controller; - u16 applid; - u32 ncci; }; /* ------------------------------------------------------------- */ @@ -71,6 +69,8 @@ struct capi_ctr *capi_controller[CAPI_MAXCONTR]; static int ncontrollers; +static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); + /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * @@ -165,8 +165,6 @@ static void release_appl(struct capi_ctr *ctr, u16 applid) capi_ctr_put(ctr); } -/* -------- KCI_CONTRUP --------------------------------------- */ - static void notify_up(u32 contr) { struct capi20_appl *ap; @@ -188,16 +186,11 @@ static void notify_up(u32 contr) if (!ap || ap->release_in_progress) continue; register_appl(ctr, applid, &ap->rparam); - if (ap->callback && !ap->release_in_progress) - ap->callback(KCI_CONTRUP, contr, - &ctr->profile); } } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); } -/* -------- KCI_CONTRDOWN ------------------------------------- */ - static void ctr_down(struct capi_ctr *ctr) { struct capi20_appl *ap; @@ -215,11 +208,8 @@ static void ctr_down(struct capi_ctr *ctr) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && !ap->release_in_progress) { - if (ap->callback) - ap->callback(KCI_CONTRDOWN, ctr->cnr, NULL); + if (ap && !ap->release_in_progress) capi_ctr_put(ctr); - } } } @@ -237,45 +227,63 @@ static void notify_down(u32 contr) printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); } -static void notify_handler(struct work_struct *work) +static int +notify_handler(struct notifier_block *nb, unsigned long val, void *v) { - struct capi_notifier *np = - container_of(work, struct capi_notifier, work); + u32 contr = (long)v; - switch (np->cmd) { - case KCI_CONTRUP: - notify_up(np->controller); + switch (val) { + case CAPICTR_UP: + notify_up(contr); break; - case KCI_CONTRDOWN: - notify_down(np->controller); + case CAPICTR_DOWN: + notify_down(contr); break; } + return NOTIFY_OK; +} + +static void do_notify_work(struct work_struct *work) +{ + struct capictr_event *event = + container_of(work, struct capictr_event, work); - kfree(np); + blocking_notifier_call_chain(&ctr_notifier_list, event->type, + (void *)(long)event->controller); + kfree(event); } /* * The notifier will result in adding/deleteing of devices. Devices can * only removed in user process, not in bh. */ -static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) +static int notify_push(unsigned int event_type, u32 controller) { - struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC); + struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); - if (!np) + if (!event) return -ENOMEM; - INIT_WORK(&np->work, notify_handler); - np->cmd = cmd; - np->controller = controller; - np->applid = applid; - np->ncci = ncci; + INIT_WORK(&event->work, do_notify_work); + event->type = event_type; + event->controller = controller; - schedule_work(&np->work); + schedule_work(&event->work); return 0; } - +int register_capictr_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&ctr_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(register_capictr_notifier); + +int unregister_capictr_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_capictr_notifier); + /* -------- Receiver ------------------------------------------ */ static void recv_handler(struct work_struct *work) @@ -401,7 +409,7 @@ void capi_ctr_ready(struct capi_ctr *ctr) printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", ctr->cnr, ctr->name); - notify_push(KCI_CONTRUP, ctr->cnr, 0, 0); + notify_push(CAPICTR_UP, ctr->cnr); } EXPORT_SYMBOL(capi_ctr_ready); @@ -418,7 +426,7 @@ void capi_ctr_down(struct capi_ctr *ctr) { printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); - notify_push(KCI_CONTRDOWN, ctr->cnr, 0, 0); + notify_push(CAPICTR_DOWN, ctr->cnr); } EXPORT_SYMBOL(capi_ctr_down); @@ -633,7 +641,6 @@ u16 capi20_register(struct capi20_appl *ap) ap->nrecvdatapkt = 0; ap->nsentctlpkt = 0; ap->nsentdatapkt = 0; - ap->callback = NULL; mutex_init(&ap->recv_mtx); skb_queue_head_init(&ap->recv_queue); INIT_WORK(&ap->recv_work, recv_handler); @@ -1137,30 +1144,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) EXPORT_SYMBOL(capi20_manufacturer); -/* temporary hack */ - -/** - * capi20_set_callback() - set CAPI application notification callback function - * @ap: CAPI application descriptor structure. - * @callback: callback function (NULL to remove). - * - * If not NULL, the callback function will be called to notify the - * application of the addition or removal of a controller. - * The first argument (cmd) will tell whether the controller was added - * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). - * The second argument (contr) will be the controller number. - * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the - * new controller's capability profile structure. - */ - -void capi20_set_callback(struct capi20_appl *ap, - void (*callback) (unsigned int cmd, __u32 contr, void *data)) -{ - ap->callback = callback; -} - -EXPORT_SYMBOL(capi20_set_callback); - /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ @@ -1169,10 +1152,17 @@ EXPORT_SYMBOL(capi20_set_callback); * init / exit functions */ +static struct notifier_block capictr_nb = { + .notifier_call = notify_handler, + .priority = INT_MAX, +}; + static int __init kcapi_init(void) { int err; + register_capictr_notifier(&capictr_nb); + err = cdebug_init(); if (!err) kcapi_proc_init(); diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h index a53e932f80fb..9c2683929fd3 100644 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h @@ -48,9 +48,7 @@ typedef struct kcapi_carddef { #include #include #include - -#define KCI_CONTRUP 0 /* arg: struct capi_profile */ -#define KCI_CONTRDOWN 1 /* arg: NULL */ +#include struct capi20_appl { u16 applid; @@ -67,11 +65,6 @@ struct capi20_appl { struct sk_buff_head recv_queue; struct work_struct recv_work; int release_in_progress; - - /* ugly hack to allow for notification of added/removed - * controllers. The Right Way (tm) is known. XXX - */ - void (*callback) (unsigned int cmd, __u32 contr, void *data); }; u16 capi20_isinstalled(void); @@ -84,11 +77,11 @@ u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); u16 capi20_get_profile(u32 contr, struct capi_profile *profp); int capi20_manufacturer(unsigned int cmd, void __user *data); -/* temporary hack XXX */ -void capi20_set_callback(struct capi20_appl *ap, - void (*callback) (unsigned int cmd, __u32 contr, void *data)); - +#define CAPICTR_UP 0 +#define CAPICTR_DOWN 1 +int register_capictr_notifier(struct notifier_block *nb); +int unregister_capictr_notifier(struct notifier_block *nb); #define CAPI_NOERROR 0x0000 -- cgit v1.2.3 From 0ca3a017a7373a4545dd7b345a8a0cecc16bc7e2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:14 +0000 Subject: CAPI: Rework locking of controller data structures This patch applies the mutex so far only protecting the controller list to (almost) all accesses of controller data structures. It also reworks waiting on state changes in old_capi_manufacturer so that it no longer poll and holds a module reference to the controller owner while waiting (the latter was partly done already). Modification and checking of the blocked state remains racy by design, the caller is responsible for dealing with this. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 291 +++++++++++++++++++++++++++++------------ drivers/isdn/capi/kcapi.h | 5 +- drivers/isdn/capi/kcapi_proc.c | 5 + include/linux/isdn/capilli.h | 5 +- 4 files changed, 217 insertions(+), 89 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index e08914d33be1..a99f7e3f8f51 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -61,11 +61,12 @@ static char capi_manufakturer[64] = "AVM Berlin"; LIST_HEAD(capi_drivers); DEFINE_MUTEX(capi_drivers_lock); +struct capi_ctr *capi_controller[CAPI_MAXCONTR]; +DEFINE_MUTEX(capi_controller_lock); + static DEFINE_RWLOCK(application_lock); -static DEFINE_MUTEX(controller_mutex); struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -struct capi_ctr *capi_controller[CAPI_MAXCONTR]; static int ncontrollers; @@ -171,13 +172,15 @@ static void notify_up(u32 contr) struct capi_ctr *ctr; u16 applid; + mutex_lock(&capi_controller_lock); + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) { if (ctr->state == CAPI_CTR_RUNNING) - return; + goto unlock_out; ctr->state = CAPI_CTR_RUNNING; @@ -187,19 +190,24 @@ static void notify_up(u32 contr) continue; register_appl(ctr, applid, &ap->rparam); } + + wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); + +unlock_out: + mutex_unlock(&capi_controller_lock); } -static void ctr_down(struct capi_ctr *ctr) +static void ctr_down(struct capi_ctr *ctr, int new_state) { struct capi20_appl *ap; u16 applid; - if (ctr->state == CAPI_CTR_DETECTED) + if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED) return; - ctr->state = CAPI_CTR_DETECTED; + ctr->state = new_state; memset(ctr->manu, 0, sizeof(ctr->manu)); memset(&ctr->version, 0, sizeof(ctr->version)); @@ -211,20 +219,26 @@ static void ctr_down(struct capi_ctr *ctr) if (ap && !ap->release_in_progress) capi_ctr_put(ctr); } + + wake_up_interruptible_all(&ctr->state_wait_queue); } static void notify_down(u32 contr) { struct capi_ctr *ctr; + mutex_lock(&capi_controller_lock); + if (showcapimsgs & 1) printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); ctr = get_capi_ctr_by_nr(contr); if (ctr) - ctr_down(ctr); + ctr_down(ctr, CAPI_CTR_DETECTED); else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); + + mutex_unlock(&capi_controller_lock); } static int @@ -436,6 +450,9 @@ EXPORT_SYMBOL(capi_ctr_down); * @ctr: controller descriptor structure. * * Called by hardware driver to stop data flow. + * + * Note: The caller is responsible for synchronizing concurrent state changes + * as well as invocations of capi_ctr_handle_message. */ void capi_ctr_suspend_output(struct capi_ctr *ctr) @@ -454,6 +471,9 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); * @ctr: controller descriptor structure. * * Called by hardware driver to resume data flow. + * + * Note: The caller is responsible for synchronizing concurrent state changes + * as well as invocations of capi_ctr_handle_message. */ void capi_ctr_resume_output(struct capi_ctr *ctr) @@ -481,21 +501,19 @@ int attach_capi_ctr(struct capi_ctr *ctr) { int i; - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i]) break; } if (i == CAPI_MAXCONTR) { - mutex_unlock(&controller_mutex); + mutex_unlock(&capi_controller_lock); printk(KERN_ERR "kcapi: out of controller slots\n"); return -EBUSY; } capi_controller[i] = ctr; - mutex_unlock(&controller_mutex); - ctr->nrecvctlpkt = 0; ctr->nrecvdatapkt = 0; ctr->nsentctlpkt = 0; @@ -504,11 +522,15 @@ int attach_capi_ctr(struct capi_ctr *ctr) ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; + init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); ncontrollers++; + + mutex_unlock(&capi_controller_lock); + printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", ctr->cnr, ctr->name); return 0; @@ -527,19 +549,29 @@ EXPORT_SYMBOL(attach_capi_ctr); int detach_capi_ctr(struct capi_ctr *ctr) { - ctr_down(ctr); + int err = 0; - ncontrollers--; + mutex_lock(&capi_controller_lock); - if (ctr->procent) { - remove_proc_entry(ctr->procfn, NULL); - ctr->procent = NULL; + ctr_down(ctr, CAPI_CTR_DETACHED); + + if (capi_controller[ctr->cnr - 1] != ctr) { + err = -EINVAL; + goto unlock_out; } capi_controller[ctr->cnr - 1] = NULL; + ncontrollers--; + + if (ctr->procent) + remove_proc_entry(ctr->procfn, NULL); + printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", ctr->cnr, ctr->name); - return 0; +unlock_out: + mutex_unlock(&capi_controller_lock); + + return err; } EXPORT_SYMBOL(detach_capi_ctr); @@ -589,13 +621,21 @@ EXPORT_SYMBOL(unregister_capi_driver); u16 capi20_isinstalled(void) { + u16 ret = CAPI_REGNOTINSTALLED; int i; - for (i = 0; i < CAPI_MAXCONTR; i++) { + + mutex_lock(&capi_controller_lock); + + for (i = 0; i < CAPI_MAXCONTR; i++) if (capi_controller[i] && - capi_controller[i]->state == CAPI_CTR_RUNNING) - return CAPI_NOERROR; - } - return CAPI_REGNOTINSTALLED; + capi_controller[i]->state == CAPI_CTR_RUNNING) { + ret = CAPI_NOERROR; + break; + } + + mutex_unlock(&capi_controller_lock); + + return ret; } EXPORT_SYMBOL(capi20_isinstalled); @@ -648,14 +688,16 @@ u16 capi20_register(struct capi20_appl *ap) write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); + for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; register_appl(capi_controller[i], applid, &ap->rparam); } - mutex_unlock(&controller_mutex); + + mutex_unlock(&capi_controller_lock); if (showcapimsgs & 1) { printk(KERN_DEBUG "kcapi: appl %d up\n", applid); @@ -688,14 +730,16 @@ u16 capi20_release(struct capi20_appl *ap) capi_applications[ap->applid - 1] = NULL; write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&controller_mutex); + mutex_lock(&capi_controller_lock); + for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) continue; release_appl(capi_controller[i], ap->applid); } - mutex_unlock(&controller_mutex); + + mutex_unlock(&capi_controller_lock); flush_scheduled_work(); skb_queue_purge(&ap->recv_queue); @@ -734,6 +778,12 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; + + /* + * The controller reference is protected by the existence of the + * application passed to us. We assume that the caller properly + * synchronizes this service with capi20_release. + */ ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); if (!ctr || ctr->state != CAPI_CTR_RUNNING) { ctr = get_capi_ctr_by_nr(1); /* XXX why? */ @@ -798,16 +848,24 @@ EXPORT_SYMBOL(capi20_put_message); u16 capi20_get_manufacturer(u32 contr, u8 *buf) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; - strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; + + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_manufacturer); @@ -825,17 +883,24 @@ EXPORT_SYMBOL(capi20_get_manufacturer); u16 capi20_get_version(u32 contr, struct capi_version *verp) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + memcpy(verp, &ctr->version, sizeof(capi_version)); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - memcpy(verp, &ctr->version, sizeof(capi_version)); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_version); @@ -853,17 +918,24 @@ EXPORT_SYMBOL(capi20_get_version); u16 capi20_get_serial(u32 contr, u8 *serial) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_serial); @@ -881,21 +953,64 @@ EXPORT_SYMBOL(capi20_get_serial); u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { struct capi_ctr *ctr; + u16 ret; if (contr == 0) { profp->ncontroller = ncontrollers; return CAPI_NOERROR; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(contr); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; + if (ctr && ctr->state == CAPI_CTR_RUNNING) { + memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); + ret = CAPI_NOERROR; + } else + ret = CAPI_REGNOTINSTALLED; - memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); - return CAPI_NOERROR; + mutex_unlock(&capi_controller_lock); + return ret; } EXPORT_SYMBOL(capi20_get_profile); +/* Must be called with capi_controller_lock held. */ +static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) +{ + DEFINE_WAIT(wait); + int retval = 0; + + ctr = capi_ctr_get(ctr); + if (!ctr) + return -ESRCH; + + for (;;) { + prepare_to_wait(&ctr->state_wait_queue, &wait, + TASK_INTERRUPTIBLE); + + if (ctr->state == state) + break; + if (ctr->state == CAPI_CTR_DETACHED) { + retval = -ESRCH; + break; + } + if (signal_pending(current)) { + retval = -EINTR; + break; + } + + mutex_unlock(&capi_controller_lock); + schedule(); + mutex_lock(&capi_controller_lock); + } + finish_wait(&ctr->state_wait_queue, &wait); + + capi_ctr_put(ctr); + + return retval; +} + #ifdef AVMB1_COMPAT static int old_capi_manufacturer(unsigned int cmd, void __user *data) { @@ -973,27 +1088,30 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) sizeof(avmb1_loadandconfigdef))) return -EFAULT; } + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(ldef.contr); - if (!ctr) - return -EINVAL; - ctr = capi_ctr_get(ctr); - if (!ctr) - return -ESRCH; + if (!ctr) { + retval = -EINVAL; + goto load_unlock_out; + } + if (ctr->load_firmware == NULL) { printk(KERN_DEBUG "kcapi: load: no load function\n"); - capi_ctr_put(ctr); - return -ESRCH; + retval = -ESRCH; + goto load_unlock_out; } if (ldef.t4file.len <= 0) { printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - capi_ctr_put(ctr); - return -EINVAL; + retval = -EINVAL; + goto load_unlock_out; } if (ldef.t4file.data == NULL) { printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - capi_ctr_put(ctr); - return -EINVAL; + retval = -EINVAL; + goto load_unlock_out; } ldata.firmware.user = 1; @@ -1005,52 +1123,47 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) if (ctr->state != CAPI_CTR_DETECTED) { printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - capi_ctr_put(ctr); - return -EBUSY; + retval = -EBUSY; + goto load_unlock_out; } ctr->state = CAPI_CTR_LOADING; retval = ctr->load_firmware(ctr, &ldata); - if (retval) { ctr->state = CAPI_CTR_DETECTED; - capi_ctr_put(ctr); - return retval; + goto load_unlock_out; } - while (ctr->state != CAPI_CTR_RUNNING) { - - msleep_interruptible(100); /* 0.1 sec */ + retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); - if (signal_pending(current)) { - capi_ctr_put(ctr); - return -EINTR; - } - } - capi_ctr_put(ctr); - return 0; +load_unlock_out: + mutex_unlock(&capi_controller_lock); + return retval; case AVMB1_RESETCARD: if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) return -EFAULT; + + retval = 0; + + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(rdef.contr); - if (!ctr) - return -ESRCH; + if (!ctr) { + retval = -ESRCH; + goto reset_unlock_out; + } if (ctr->state == CAPI_CTR_DETECTED) - return 0; + goto reset_unlock_out; ctr->reset_ctr(ctr); - while (ctr->state > CAPI_CTR_DETECTED) { - - msleep_interruptible(100); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; + retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); +reset_unlock_out: + mutex_unlock(&capi_controller_lock); + return retval; } return -EINVAL; } @@ -1068,6 +1181,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) int capi20_manufacturer(unsigned int cmd, void __user *data) { struct capi_ctr *ctr; + int retval; switch (cmd) { #ifdef AVMB1_COMPAT @@ -1085,14 +1199,20 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) return -EFAULT; + mutex_lock(&capi_controller_lock); + ctr = get_capi_ctr_by_nr(fdef.contr); - if (!ctr) - return -ESRCH; + if (ctr) { + ctr->traceflag = fdef.flag; + printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", + ctr->cnr, ctr->traceflag); + retval = 0; + } else + retval = -ESRCH; + + mutex_unlock(&capi_controller_lock); - ctr->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", - ctr->cnr, ctr->traceflag); - return 0; + return retval; } case KCAPI_CMD_ADDCARD: { @@ -1100,7 +1220,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) struct capi_driver *driver = NULL; capicardparams cparams; kcapi_carddef cdef; - int retval; if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) return retval; diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 07c58500fe48..f4620b38ec51 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -24,6 +24,7 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ #endif enum { + CAPI_CTR_DETACHED = 0, CAPI_CTR_DETECTED = 1, CAPI_CTR_LOADING = 2, CAPI_CTR_RUNNING = 3, @@ -32,8 +33,10 @@ enum { extern struct list_head capi_drivers; extern struct mutex capi_drivers_lock; -extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; +extern struct mutex capi_controller_lock; + +extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 71b07610ff31..3e6e17a24389 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -35,7 +35,10 @@ static char *state2str(unsigned short state) // --------------------------------------------------------------------------- static void *controller_start(struct seq_file *seq, loff_t *pos) + __acquires(capi_controller_lock) { + mutex_lock(&capi_controller_lock); + if (*pos < CAPI_MAXCONTR) return &capi_controller[*pos]; @@ -52,7 +55,9 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) } static void controller_stop(struct seq_file *seq, void *v) + __releases(capi_controller_lock) { + mutex_unlock(&capi_controller_lock); } static int controller_show(struct seq_file *seq, void *v) diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index 856f38eddd78..11b57c485854 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -66,9 +66,10 @@ struct capi_ctr { unsigned long nsentdatapkt; int cnr; /* controller number */ - volatile unsigned short state; /* controller state */ - volatile int blocked; /* output blocked */ + unsigned short state; /* controller state */ + int blocked; /* output blocked */ int traceflag; /* capi trace */ + wait_queue_head_t state_wait_queue; struct proc_dir_entry *procent; char procfn[128]; -- cgit v1.2.3 From 88c896ef87fd0dd4dbf36e8e86e019c74b1f6649 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:15 +0000 Subject: CAPI: Rework application locking Drop the application rw-lock in favour of RCU. This synchronizes capi20_release against capi_ctr_handle_message which may dereference an application from (soft-)IRQ context. Any other access to the application list is now protected by the capi_controller_lock as well. This also allows to safely inspect applications for /proc dumping by holding capi_controller_lock. At this chance, drop some useless release_in_progress checks where we obtained the application pointer from the list (which becomes NULL on release_in_progress). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 52 ++++++++++++++++++------------------------ drivers/isdn/capi/kcapi_proc.c | 11 +++++---- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index a99f7e3f8f51..0b4c8a7396bc 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -34,6 +34,7 @@ #include #endif #include +#include static int showcapimsgs = 0; @@ -64,8 +65,6 @@ DEFINE_MUTEX(capi_drivers_lock); struct capi_ctr *capi_controller[CAPI_MAXCONTR]; DEFINE_MUTEX(capi_controller_lock); -static DEFINE_RWLOCK(application_lock); - struct capi20_appl *capi_applications[CAPI_MAXAPPL]; static int ncontrollers; @@ -103,7 +102,7 @@ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) if (applid - 1 >= CAPI_MAXAPPL) return NULL; - return capi_applications[applid - 1]; + return rcu_dereference(capi_applications[applid - 1]); } /* -------- util functions ------------------------------------ */ @@ -186,7 +185,7 @@ static void notify_up(u32 contr) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (!ap || ap->release_in_progress) + if (!ap) continue; register_appl(ctr, applid, &ap->rparam); } @@ -216,7 +215,7 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { ap = get_capi_appl_by_nr(applid); - if (ap && !ap->release_in_progress) + if (ap) capi_ctr_put(ctr); } @@ -336,7 +335,6 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, struct capi20_appl *ap; int showctl = 0; u8 cmd, subcmd; - unsigned long flags; _cdebbuf *cdb; if (ctr->state != CAPI_CTR_RUNNING) { @@ -384,10 +382,10 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, } - read_lock_irqsave(&application_lock, flags); + rcu_read_lock(); ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); - if ((!ap) || (ap->release_in_progress)) { - read_unlock_irqrestore(&application_lock, flags); + if (!ap) { + rcu_read_unlock(); cdb = capi_message2str(skb->data); if (cdb) { printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", @@ -401,7 +399,7 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, } skb_queue_tail(&ap->recv_queue, skb); schedule_work(&ap->recv_work); - read_unlock_irqrestore(&application_lock, flags); + rcu_read_unlock(); return; @@ -656,40 +654,35 @@ u16 capi20_register(struct capi20_appl *ap) { int i; u16 applid; - unsigned long flags; DBG(""); if (ap->rparam.datablklen < 128) return CAPI_LOGBLKSIZETOSMALL; - write_lock_irqsave(&application_lock, flags); + ap->nrecvctlpkt = 0; + ap->nrecvdatapkt = 0; + ap->nsentctlpkt = 0; + ap->nsentdatapkt = 0; + mutex_init(&ap->recv_mtx); + skb_queue_head_init(&ap->recv_queue); + INIT_WORK(&ap->recv_work, recv_handler); + ap->release_in_progress = 0; + + mutex_lock(&capi_controller_lock); for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { if (capi_applications[applid - 1] == NULL) break; } if (applid > CAPI_MAXAPPL) { - write_unlock_irqrestore(&application_lock, flags); + mutex_unlock(&capi_controller_lock); return CAPI_TOOMANYAPPLS; } ap->applid = applid; capi_applications[applid - 1] = ap; - ap->nrecvctlpkt = 0; - ap->nrecvdatapkt = 0; - ap->nsentctlpkt = 0; - ap->nsentdatapkt = 0; - mutex_init(&ap->recv_mtx); - skb_queue_head_init(&ap->recv_queue); - INIT_WORK(&ap->recv_work, recv_handler); - ap->release_in_progress = 0; - - write_unlock_irqrestore(&application_lock, flags); - - mutex_lock(&capi_controller_lock); - for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || capi_controller[i]->state != CAPI_CTR_RUNNING) @@ -721,16 +714,15 @@ EXPORT_SYMBOL(capi20_register); u16 capi20_release(struct capi20_appl *ap) { int i; - unsigned long flags; DBG("applid %#x", ap->applid); - write_lock_irqsave(&application_lock, flags); + mutex_lock(&capi_controller_lock); + ap->release_in_progress = 1; capi_applications[ap->applid - 1] = NULL; - write_unlock_irqrestore(&application_lock, flags); - mutex_lock(&capi_controller_lock); + synchronize_rcu(); for (i = 0; i < CAPI_MAXCONTR; i++) { if (!capi_controller[i] || diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 3e6e17a24389..ea2dff602e49 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -139,9 +139,11 @@ static const struct file_operations proc_contrstats_ops = { // applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt // --------------------------------------------------------------------------- -static void * -applications_start(struct seq_file *seq, loff_t *pos) +static void *applications_start(struct seq_file *seq, loff_t *pos) + __acquires(capi_controller_lock) { + mutex_lock(&capi_controller_lock); + if (*pos < CAPI_MAXAPPL) return &capi_applications[*pos]; @@ -158,9 +160,10 @@ applications_next(struct seq_file *seq, void *v, loff_t *pos) return NULL; } -static void -applications_stop(struct seq_file *seq, void *v) +static void applications_stop(struct seq_file *seq, void *v) + __releases(capi_controller_lock) { + mutex_unlock(&capi_controller_lock); } static int -- cgit v1.2.3 From 501c87a91909efaad91425635b29b01f1473c659 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:16 +0000 Subject: CAPI: Reduce #ifdef mess around CONFIG_ISDN_CAPI_MIDDLEWARE Make the code a bit more readable be providing stub functions for the !CONFIG_ISDN_CAPI_MIDDLEWARE case. Though a few lines are moved around, this comes with no functional changes. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 150 ++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 67 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3b077978c496..7d2ca6b2564c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -23,14 +23,10 @@ #include #include #include -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #include -#ifdef CONFIG_PPP #include #include #include -#endif /* CONFIG_PPP */ -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include #include #include @@ -56,17 +52,17 @@ MODULE_LICENSE("GPL"); /* -------- driver information -------------------------------------- */ static struct class *capi_class; - static int capi_major = 68; /* allocated */ + +module_param_named(major, capi_major, uint, 0); + #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -#define CAPINC_NR_PORTS 32 +#define CAPINC_NR_PORTS 32 #define CAPINC_MAX_PORTS 256 + static int capi_ttymajor = 191; static int capi_ttyminors = CAPINC_NR_PORTS; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -module_param_named(major, capi_major, uint, 0); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE module_param_named(ttymajor, capi_ttymajor, uint, 0); module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -81,7 +77,6 @@ module_param_named(ttyminors, capi_ttyminors, uint, 0); struct capidev; struct capincci; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE struct capiminor; struct datahandle_queue { @@ -116,7 +111,6 @@ struct capiminor { int nack; spinlock_t ackqlock; }; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* FIXME: The following lock is a sledgehammer-workaround to a * locking issue with the capiminor (and maybe other) data structure(s). @@ -156,14 +150,13 @@ static DEFINE_RWLOCK(capidev_list_lock); static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE + static DEFINE_RWLOCK(capiminor_list_lock); static LIST_HEAD(capiminor_list); -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- datahandles --------------------------------------------- */ -static int capincci_add_ack(struct capiminor *mp, u16 datahandle) +static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { struct datahandle_queue *n; unsigned long flags; @@ -301,26 +294,17 @@ static struct capiminor *capiminor_find(unsigned int minor) return p; } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- struct capincci ----------------------------------------- */ -static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) +static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { - struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp = NULL; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + struct capiminor *mp; - np = kzalloc(sizeof(*np), GFP_ATOMIC); - if (!np) - return NULL; - np->ncci = ncci; - np->cdev = cdev; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - mp = NULL; - if (cdev->userflags & CAPIFLAG_HIGHJACKING) - mp = np->minorp = capiminor_alloc(&cdev->ap, ncci); + if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) + return; + + mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); if (mp) { mp->nccip = np; #ifdef _DEBUG_REFCOUNT @@ -330,7 +314,58 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +} + +static void capincci_free_minor(struct capincci *np) +{ + struct capiminor *mp = np->minorp; + + if (mp) { + capifs_free_ncci(mp->capifs_dentry); + if (mp->tty) { + mp->nccip = NULL; +#ifdef _DEBUG_REFCOUNT + printk(KERN_DEBUG "reset mp->nccip\n"); +#endif + tty_hangup(mp->tty); + } else { + capiminor_free(mp); + } + } +} + +static inline unsigned int capincci_minor_opencount(struct capincci *np) +{ + struct capiminor *mp = np->minorp; + + return mp ? atomic_read(&mp->ttyopencount) : 0; +} + +#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static inline void +capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { } +static inline void capincci_free_minor(struct capincci *np) { } + +static inline unsigned int capincci_minor_opencount(struct capincci *np) +{ + return 0; +} + +#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) +{ + struct capincci *np, **pp; + + np = kzalloc(sizeof(*np), GFP_ATOMIC); + if (!np) + return NULL; + np->ncci = ncci; + np->cdev = cdev; + + capincci_alloc_minor(cdev, np); + for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) ; *pp = np; @@ -340,29 +375,13 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) static void capincci_free(struct capidev *cdev, u32 ncci) { struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ pp=&cdev->nccis; while (*pp) { np = *pp; if (ncci == 0xffffffff || np->ncci == ncci) { *pp = (*pp)->next; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = np->minorp) != NULL) { - capifs_free_ncci(mp->capifs_dentry); - if (mp->tty) { - mp->nccip = NULL; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif - tty_hangup(mp->tty); - } else { - capiminor_free(mp); - } - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + capincci_free_minor(np); kfree(np); if (*pp == NULL) return; } else { @@ -552,7 +571,7 @@ static int handle_minor_send(struct capiminor *mp) capimsg_setu16(skb->data, 18, datahandle); capimsg_setu16(skb->data, 20, 0); /* Flags */ - if (capincci_add_ack(mp, datahandle) < 0) { + if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); skb_queue_head(&mp->outqueue, skb); return count; @@ -628,10 +647,13 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) spin_unlock_irqrestore(&workaround_lock, flags); return; } + #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); + #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + mp = np->minorp; if (!mp) { skb_queue_tail(&cdev->recvqueue, skb); @@ -639,10 +661,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) spin_unlock_irqrestore(&workaround_lock, flags); return; } - - if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { - datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", @@ -672,6 +691,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) wake_up_interruptible(&cdev->recvwait); } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + spin_unlock_irqrestore(&workaround_lock, flags); } @@ -929,9 +949,6 @@ capi_ioctl(struct inode *inode, struct file *file, case CAPI_NCCI_OPENCOUNT: { struct capincci *nccip; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ unsigned ncci; int count = 0; if (copy_from_user(&ncci, argp, sizeof(ncci))) @@ -942,11 +959,7 @@ capi_ioctl(struct inode *inode, struct file *file, mutex_unlock(&cdev->ncci_list_mtx); return 0; } -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = nccip->minorp) != NULL) { - count += atomic_read(&mp->ttyopencount); - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + count += capincci_minor_opencount(nccip); mutex_unlock(&cdev->ncci_list_mtx); return count; } @@ -1396,7 +1409,16 @@ static void capinc_tty_exit(void) put_tty_driver(drv); } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ + +static inline int capinc_tty_init(void) +{ + return 0; +} + +static inline void capinc_tty_exit(void) { } + +#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- /proc functions ----------------------------------------- */ @@ -1505,23 +1527,19 @@ static int __init capi_init(void) device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); return -ENOMEM; } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ proc_init(); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) compileinfo = " (middleware+capifs)"; -#else +#elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE) compileinfo = " (no capifs)"; -#endif #else compileinfo = " (no middleware)"; #endif @@ -1539,9 +1557,7 @@ static void __exit capi_exit(void) class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE capinc_tty_exit(); -#endif } module_init(capi_init); -- cgit v1.2.3 From b8f433dc5cd9b910c12ef5cca351bf720d3e68c1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:17 +0000 Subject: CAPI: Convert capidev_list_lock into a mutex No need for anything "harder" here (specifically no need for irqsave...). Also, make the list removal the first operation of capidev_free to avoid dumping half-released devices via /proc. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 7d2ca6b2564c..623412e22c14 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -146,7 +146,7 @@ struct capidev { /* -------- global variables ---------------------------------------- */ -static DEFINE_RWLOCK(capidev_list_lock); +static DEFINE_MUTEX(capidev_list_lock); static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -406,7 +406,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) static struct capidev *capidev_alloc(void) { struct capidev *cdev; - unsigned long flags; cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) @@ -415,15 +414,19 @@ static struct capidev *capidev_alloc(void) mutex_init(&cdev->ncci_list_mtx); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); - write_lock_irqsave(&capidev_list_lock, flags); + + mutex_lock(&capidev_list_lock); list_add_tail(&cdev->list, &capidev_list); - write_unlock_irqrestore(&capidev_list_lock, flags); + mutex_unlock(&capidev_list_lock); + return cdev; } static void capidev_free(struct capidev *cdev) { - unsigned long flags; + mutex_lock(&capidev_list_lock); + list_del(&cdev->list); + mutex_unlock(&capidev_list_lock); if (cdev->ap.applid) { capi20_release(&cdev->ap); @@ -435,9 +438,6 @@ static void capidev_free(struct capidev *cdev) capincci_free(cdev, 0xffffffff); mutex_unlock(&cdev->ncci_list_mtx); - write_lock_irqsave(&capidev_list_lock, flags); - list_del(&cdev->list); - write_unlock_irqrestore(&capidev_list_lock, flags); kfree(cdev); } @@ -1431,7 +1431,7 @@ static int capi20_proc_show(struct seq_file *m, void *v) struct capidev *cdev; struct list_head *l; - read_lock(&capidev_list_lock); + mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); seq_printf(m, "0 %d %lu %lu %lu %lu\n", @@ -1441,7 +1441,7 @@ static int capi20_proc_show(struct seq_file *m, void *v) cdev->ap.nsentctlpkt, cdev->ap.nsentdatapkt); } - read_unlock(&capidev_list_lock); + mutex_unlock(&capidev_list_lock); return 0; } @@ -1468,7 +1468,7 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) struct capincci *np; struct list_head *l; - read_lock(&capidev_list_lock); + mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); for (np=cdev->nccis; np; np = np->next) { @@ -1477,7 +1477,7 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) np->ncci); } } - read_unlock(&capidev_list_lock); + mutex_unlock(&capidev_list_lock); return 0; } -- cgit v1.2.3 From eca39dd830dbc58061aa6cd68853c39055236be3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:18 +0000 Subject: CAPI: Clean up capi_open/release Fold capidev_alloc and capidev_free into capi_open and capi_release - there are no other users. Someone pushed a lock_kernel into capi_open. Drop it, we don't need it. Also remove the useless test from open that checks for private_data == NULL. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 93 ++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 59 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 623412e22c14..9d7c3692c7d7 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -401,46 +401,6 @@ static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) return p; } -/* -------- struct capidev ------------------------------------------ */ - -static struct capidev *capidev_alloc(void) -{ - struct capidev *cdev; - - cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); - if (!cdev) - return NULL; - - mutex_init(&cdev->ncci_list_mtx); - skb_queue_head_init(&cdev->recvqueue); - init_waitqueue_head(&cdev->recvwait); - - mutex_lock(&capidev_list_lock); - list_add_tail(&cdev->list, &capidev_list); - mutex_unlock(&capidev_list_lock); - - return cdev; -} - -static void capidev_free(struct capidev *cdev) -{ - mutex_lock(&capidev_list_lock); - list_del(&cdev->list); - mutex_unlock(&capidev_list_lock); - - if (cdev->ap.applid) { - capi20_release(&cdev->ap); - cdev->ap.applid = 0; - } - skb_queue_purge(&cdev->recvqueue); - - mutex_lock(&cdev->ncci_list_mtx); - capincci_free(cdev, 0xffffffff); - mutex_unlock(&cdev->ncci_list_mtx); - - kfree(cdev); -} - #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- handle data queue --------------------------------------- */ @@ -991,30 +951,45 @@ capi_ioctl(struct inode *inode, struct file *file, return -EINVAL; } -static int -capi_open(struct inode *inode, struct file *file) +static int capi_open(struct inode *inode, struct file *file) { - int ret; - - lock_kernel(); - if (file->private_data) - ret = -EEXIST; - else if ((file->private_data = capidev_alloc()) == NULL) - ret = -ENOMEM; - else - ret = nonseekable_open(inode, file); - unlock_kernel(); - return ret; + struct capidev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + mutex_init(&cdev->ncci_list_mtx); + skb_queue_head_init(&cdev->recvqueue); + init_waitqueue_head(&cdev->recvwait); + file->private_data = cdev; + + mutex_lock(&capidev_list_lock); + list_add_tail(&cdev->list, &capidev_list); + mutex_unlock(&capidev_list_lock); + + return nonseekable_open(inode, file); } -static int -capi_release(struct inode *inode, struct file *file) +static int capi_release(struct inode *inode, struct file *file) { - struct capidev *cdev = (struct capidev *)file->private_data; + struct capidev *cdev = file->private_data; - capidev_free(cdev); - file->private_data = NULL; - + mutex_lock(&capidev_list_lock); + list_del(&cdev->list); + mutex_unlock(&capidev_list_lock); + + if (cdev->ap.applid) { + capi20_release(&cdev->ap); + cdev->ap.applid = 0; + } + skb_queue_purge(&cdev->recvqueue); + + mutex_lock(&cdev->ncci_list_mtx); + capincci_free(cdev, 0xffffffff); + mutex_unlock(&cdev->ncci_list_mtx); + + kfree(cdev); return 0; } -- cgit v1.2.3 From 05b4149433ffae789edaf569da8d998c93eed1aa Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:19 +0000 Subject: CAPI: Rework locking of capidev members Rename 'ncci_list_mtx' to 'lock', expressing that it now protects a larger set of capidev members: the NCCI list, ap.applid (ie. the registration of the application), and modifications of userflags. We do not need to protect each and every check for ap.applid because, once an application is registered, it will stay for the whole lifetime of the device. Also, there is no need to apply the capidev mutex during release (if there could be concurrent users, we would crash them anyway by freeing the device at the end of capi_release). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 181 +++++++++++++++++++++++------------------------ 1 file changed, 88 insertions(+), 93 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 9d7c3692c7d7..403bf8fcb285 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -141,7 +141,7 @@ struct capidev { struct capincci *nccis; - struct mutex ncci_list_mtx; + struct mutex lock; }; /* -------- global variables ---------------------------------------- */ @@ -574,38 +574,31 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ struct capincci *np; - u32 ncci; unsigned long flags; + mutex_lock(&cdev->lock); + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { u16 info = CAPIMSG_U16(skb->data, 12); // Info field - if ((info & 0xff00) == 0) { - mutex_lock(&cdev->ncci_list_mtx); + if ((info & 0xff00) == 0) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); - } } - if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) { - mutex_lock(&cdev->ncci_list_mtx); + if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); - } + spin_lock_irqsave(&workaround_lock, flags); if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } - ncci = CAPIMSG_CONTROL(skb->data); - for (np = cdev->nccis; np && np->ncci != ncci; np = np->next) - ; + + np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data)); if (!np) { printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -618,8 +611,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (!mp) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); - spin_unlock_irqrestore(&workaround_lock, flags); - return; + goto unlock_out; } if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); @@ -652,7 +644,9 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ +unlock_out: spin_unlock_irqrestore(&workaround_lock, flags); + mutex_unlock(&cdev->lock); } /* -------- file_operations for capidev ----------------------------- */ @@ -730,9 +724,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { - mutex_lock(&cdev->ncci_list_mtx); + mutex_lock(&cdev->lock); capincci_free(cdev, CAPIMSG_NCCI(skb->data)); - mutex_unlock(&cdev->ncci_list_mtx); + mutex_unlock(&cdev->lock); } cdev->errcode = capi20_put_message(&cdev->ap, skb); @@ -765,30 +759,35 @@ capi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct capidev *cdev = file->private_data; - struct capi20_appl *ap = &cdev->ap; capi_ioctl_struct data; int retval = -EINVAL; void __user *argp = (void __user *)arg; switch (cmd) { case CAPI_REGISTER: - { - if (ap->applid) - return -EEXIST; + mutex_lock(&cdev->lock); - if (copy_from_user(&cdev->ap.rparam, argp, - sizeof(struct capi_register_params))) - return -EFAULT; - - cdev->ap.private = cdev; - cdev->ap.recv_message = capi_recv_message; - cdev->errcode = capi20_register(ap); - if (cdev->errcode) { - ap->applid = 0; - return -EIO; - } + if (cdev->ap.applid) { + retval = -EEXIST; + goto register_out; + } + if (copy_from_user(&cdev->ap.rparam, argp, + sizeof(struct capi_register_params))) { + retval = -EFAULT; + goto register_out; + } + cdev->ap.private = cdev; + cdev->ap.recv_message = capi_recv_message; + cdev->errcode = capi20_register(&cdev->ap); + retval = (int)cdev->ap.applid; + if (cdev->errcode) { + cdev->ap.applid = 0; + retval = -EIO; } - return (int)ap->applid; + +register_out: + mutex_unlock(&cdev->lock); + return retval; case CAPI_GET_VERSION: { @@ -887,68 +886,67 @@ capi_ioctl(struct inode *inode, struct file *file, return 0; case CAPI_SET_FLAGS: - case CAPI_CLR_FLAGS: - { - unsigned userflags; - if (copy_from_user(&userflags, argp, - sizeof(userflags))) - return -EFAULT; - if (cmd == CAPI_SET_FLAGS) - cdev->userflags |= userflags; - else - cdev->userflags &= ~userflags; - } - return 0; + case CAPI_CLR_FLAGS: { + unsigned userflags; + + if (copy_from_user(&userflags, argp, sizeof(userflags))) + return -EFAULT; + mutex_lock(&cdev->lock); + if (cmd == CAPI_SET_FLAGS) + cdev->userflags |= userflags; + else + cdev->userflags &= ~userflags; + mutex_unlock(&cdev->lock); + return 0; + } case CAPI_GET_FLAGS: if (copy_to_user(argp, &cdev->userflags, sizeof(cdev->userflags))) return -EFAULT; return 0; - case CAPI_NCCI_OPENCOUNT: - { - struct capincci *nccip; - unsigned ncci; - int count = 0; - if (copy_from_user(&ncci, argp, sizeof(ncci))) - return -EFAULT; + case CAPI_NCCI_OPENCOUNT: { + struct capincci *nccip; + unsigned ncci; + int count = 0; - mutex_lock(&cdev->ncci_list_mtx); - if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) { - mutex_unlock(&cdev->ncci_list_mtx); - return 0; - } - count += capincci_minor_opencount(nccip); - mutex_unlock(&cdev->ncci_list_mtx); - return count; - } - return 0; + if (copy_from_user(&ncci, argp, sizeof(ncci))) + return -EFAULT; + + mutex_lock(&cdev->lock); + nccip = capincci_find(cdev, (u32)ncci); + if (nccip) + count = capincci_minor_opencount(nccip); + mutex_unlock(&cdev->lock); + return count; + } #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - case CAPI_NCCI_GETUNIT: - { - struct capincci *nccip; - struct capiminor *mp; - unsigned ncci; - int unit = 0; - if (copy_from_user(&ncci, argp, - sizeof(ncci))) - return -EFAULT; - mutex_lock(&cdev->ncci_list_mtx); - nccip = capincci_find(cdev, (u32) ncci); - if (!nccip || (mp = nccip->minorp) == NULL) { - mutex_unlock(&cdev->ncci_list_mtx); - return -ESRCH; - } - unit = mp->minor; - mutex_unlock(&cdev->ncci_list_mtx); - return unit; + case CAPI_NCCI_GETUNIT: { + struct capincci *nccip; + struct capiminor *mp; + unsigned ncci; + int unit = -ESRCH; + + if (copy_from_user(&ncci, argp, sizeof(ncci))) + return -EFAULT; + + mutex_lock(&cdev->lock); + nccip = capincci_find(cdev, (u32)ncci); + if (nccip) { + mp = nccip->minorp; + if (mp) + unit = mp->minor; } - return 0; + mutex_unlock(&cdev->lock); + return unit; + } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ + + default: + return -EINVAL; } - return -EINVAL; } static int capi_open(struct inode *inode, struct file *file) @@ -959,7 +957,7 @@ static int capi_open(struct inode *inode, struct file *file) if (!cdev) return -ENOMEM; - mutex_init(&cdev->ncci_list_mtx); + mutex_init(&cdev->lock); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); file->private_data = cdev; @@ -979,15 +977,10 @@ static int capi_release(struct inode *inode, struct file *file) list_del(&cdev->list); mutex_unlock(&capidev_list_lock); - if (cdev->ap.applid) { + if (cdev->ap.applid) capi20_release(&cdev->ap); - cdev->ap.applid = 0; - } skb_queue_purge(&cdev->recvqueue); - - mutex_lock(&cdev->ncci_list_mtx); capincci_free(cdev, 0xffffffff); - mutex_unlock(&cdev->ncci_list_mtx); kfree(cdev); return 0; @@ -1446,11 +1439,13 @@ static int capi20ncci_proc_show(struct seq_file *m, void *v) mutex_lock(&capidev_list_lock); list_for_each(l, &capidev_list) { cdev = list_entry(l, struct capidev, list); + mutex_lock(&cdev->lock); for (np=cdev->nccis; np; np = np->next) { seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); } + mutex_unlock(&cdev->lock); } mutex_unlock(&capidev_list_lock); return 0; -- cgit v1.2.3 From 54f0fad3d8414cf770c1cf25a1d98fcaec899b5a Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:20 +0000 Subject: CAPI: Use non-atomic allocation during NCCI setup Both capincci_alloc and capiminor_alloc run in non-atomic context, update their memory allocations accordingly. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 403bf8fcb285..f8f86602c57e 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -217,7 +217,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) unsigned int minor = 0; unsigned long flags; - mp = kzalloc(sizeof(*mp), GFP_ATOMIC); + mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); return NULL; @@ -358,7 +358,7 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) { struct capincci *np, **pp; - np = kzalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return NULL; np->ncci = ncci; -- cgit v1.2.3 From 28a1dbb6f7feade304f43798feb15f6978516624 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:21 +0000 Subject: CAPI: Fix racy capi_read capi_read still used interruptible_sleep_on, risking to miss a wakeup this way. Convert it to wait_event_interruptible. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index f8f86602c57e..8abec9655e1a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -657,24 +657,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) struct capidev *cdev = (struct capidev *)file->private_data; struct sk_buff *skb; size_t copied; + int err; if (!cdev->ap.applid) return -ENODEV; - if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) { - + skb = skb_dequeue(&cdev->recvqueue); + if (!skb) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; - - for (;;) { - interruptible_sleep_on(&cdev->recvwait); - if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL) - break; - if (signal_pending(current)) - break; - } - if (skb == NULL) - return -ERESTARTNOHAND; + err = wait_event_interruptible(cdev->recvwait, + (skb = skb_dequeue(&cdev->recvqueue))); + if (err) + return err; } if (skb->len > count) { skb_queue_head(&cdev->recvqueue, skb); -- cgit v1.2.3 From 884f5c447901ca9da75432fe8a7a2c2a00327d22 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:22 +0000 Subject: CAPI: Switch NCCI list to standard doubly linked list Replace open-coded NCCI list management with standard mechanisms. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 52 +++++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 8abec9655e1a..6704b2b004aa 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -122,7 +122,7 @@ struct capiminor { static DEFINE_SPINLOCK(workaround_lock); struct capincci { - struct capincci *next; + struct list_head list; u32 ncci; struct capidev *cdev; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -139,7 +139,7 @@ struct capidev { struct sk_buff_head recvqueue; wait_queue_head_t recvwait; - struct capincci *nccis; + struct list_head nccis; struct mutex lock; }; @@ -356,7 +356,7 @@ static inline unsigned int capincci_minor_opencount(struct capincci *np) static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) { - struct capincci *np, **pp; + struct capincci *np; np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) @@ -366,39 +366,31 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) capincci_alloc_minor(cdev, np); - for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) - ; - *pp = np; - return np; + list_add_tail(&np->list, &cdev->nccis); + + return np; } static void capincci_free(struct capidev *cdev, u32 ncci) { - struct capincci *np, **pp; + struct capincci *np, *tmp; - pp=&cdev->nccis; - while (*pp) { - np = *pp; + list_for_each_entry_safe(np, tmp, &cdev->nccis, list) if (ncci == 0xffffffff || np->ncci == ncci) { - *pp = (*pp)->next; capincci_free_minor(np); + list_del(&np->list); kfree(np); - if (*pp == NULL) return; - } else { - pp = &(*pp)->next; } - } } static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) { - struct capincci *p; + struct capincci *np; - for (p=cdev->nccis; p ; p = p->next) { - if (p->ncci == ncci) - break; - } - return p; + list_for_each_entry(np, &cdev->nccis, list) + if (np->ncci == ncci) + return np; + return NULL; } #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -955,6 +947,7 @@ static int capi_open(struct inode *inode, struct file *file) mutex_init(&cdev->lock); skb_queue_head_init(&cdev->recvqueue); init_waitqueue_head(&cdev->recvwait); + INIT_LIST_HEAD(&cdev->nccis); file->private_data = cdev; mutex_lock(&capidev_list_lock); @@ -1427,19 +1420,14 @@ static const struct file_operations capi20_proc_fops = { */ static int capi20ncci_proc_show(struct seq_file *m, void *v) { - struct capidev *cdev; - struct capincci *np; - struct list_head *l; + struct capidev *cdev; + struct capincci *np; mutex_lock(&capidev_list_lock); - list_for_each(l, &capidev_list) { - cdev = list_entry(l, struct capidev, list); + list_for_each_entry(cdev, &capidev_list, list) { mutex_lock(&cdev->lock); - for (np=cdev->nccis; np; np = np->next) { - seq_printf(m, "%d 0x%x\n", - cdev->ap.applid, - np->ncci); - } + list_for_each_entry(np, &cdev->nccis, list) + seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); mutex_unlock(&cdev->lock); } mutex_unlock(&capidev_list_lock); -- cgit v1.2.3 From 81d17fe5e29d863027824928e1c336baa9abfee9 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:23 +0000 Subject: CAPI: Switch capiminor list to array Using a plain array of pointers simplifies the management of capiminors. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 75 ++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 6704b2b004aa..46f85ae85f5f 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -85,7 +85,6 @@ struct datahandle_queue { }; struct capiminor { - struct list_head list; struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -151,8 +150,8 @@ static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -static DEFINE_RWLOCK(capiminor_list_lock); -static LIST_HEAD(capiminor_list); +static DEFINE_RWLOCK(capiminors_lock); +static struct capiminor **capiminors; /* -------- datahandles --------------------------------------------- */ @@ -213,8 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp) static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { - struct capiminor *mp, *p; - unsigned int minor = 0; + struct capiminor *mp; + unsigned int minor; unsigned long flags; mp = kzalloc(sizeof(*mp), GFP_KERNEL); @@ -233,31 +232,23 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); - /* Allocate the least unused minor number. - */ - write_lock_irqsave(&capiminor_list_lock, flags); - if (list_empty(&capiminor_list)) - list_add(&mp->list, &capiminor_list); - else { - list_for_each_entry(p, &capiminor_list, list) { - if (p->minor > minor) - break; - minor++; - } - - if (minor < capi_ttyminors) { - mp->minor = minor; - list_add(&mp->list, p->list.prev); + /* Allocate the least unused minor number. */ + write_lock_irqsave(&capiminors_lock, flags); + for (minor = 0; minor < capi_ttyminors; minor++) + if (!capiminors[minor]) { + capiminors[minor] = mp; + break; } - } - write_unlock_irqrestore(&capiminor_list_lock, flags); + write_unlock_irqrestore(&capiminors_lock, flags); - if (!(minor < capi_ttyminors)) { + if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); - kfree(mp); + kfree(mp); return NULL; } + mp->minor = minor; + return mp; } @@ -265,9 +256,9 @@ static void capiminor_free(struct capiminor *mp) { unsigned long flags; - write_lock_irqsave(&capiminor_list_lock, flags); - list_del(&mp->list); - write_unlock_irqrestore(&capiminor_list_lock, flags); + write_lock_irqsave(&capiminors_lock, flags); + capiminors[mp->minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); kfree_skb(mp->ttyskb); mp->ttyskb = NULL; @@ -279,20 +270,16 @@ static void capiminor_free(struct capiminor *mp) static struct capiminor *capiminor_find(unsigned int minor) { - struct list_head *l; - struct capiminor *p = NULL; + struct capiminor *mp; - read_lock(&capiminor_list_lock); - list_for_each(l, &capiminor_list) { - p = list_entry(l, struct capiminor, list); - if (p->minor == minor) - break; - } - read_unlock(&capiminor_list_lock); - if (l == &capiminor_list) + if (minor >= capi_ttyminors) return NULL; - return p; + read_lock(&capiminors_lock); + mp = capiminors[minor]; + read_unlock(&capiminors_lock); + + return mp; } /* -------- struct capincci ----------------------------------------- */ @@ -1329,10 +1316,16 @@ static int capinc_tty_init(void) if (capi_ttyminors <= 0) capi_ttyminors = CAPINC_NR_PORTS; - drv = alloc_tty_driver(capi_ttyminors); - if (!drv) + capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors, + GFP_KERNEL); + if (!capiminors) return -ENOMEM; + drv = alloc_tty_driver(capi_ttyminors); + if (!drv) { + kfree(capiminors); + return -ENOMEM; + } drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi"; @@ -1349,6 +1342,7 @@ static int capinc_tty_init(void) tty_set_operations(drv, &capinc_ops); if (tty_register_driver(drv)) { put_tty_driver(drv); + kfree(capiminors); printk(KERN_ERR "Couldn't register capi_nc driver\n"); return -1; } @@ -1363,6 +1357,7 @@ static void capinc_tty_exit(void) if ((retval = tty_unregister_driver(drv))) printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); put_tty_driver(drv); + kfree(capiminors); } #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ -- cgit v1.2.3 From e76b1544074b5fc7983a21fb1f51a7faf03d3179 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:24 +0000 Subject: CAPI: Clean up capinc_tty_init/exit Return proper error code if tty_register_driver fails. In contrast, tty_unregister_driver cannot practically fail, so drop that error handling. Finally, mark capinc_tty_init/exit with __init/__exit. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 46f85ae85f5f..c22b34976c24 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1307,10 +1307,11 @@ static const struct tty_operations capinc_ops = { .send_xchar = capinc_tty_send_xchar, }; -static int capinc_tty_init(void) +static int __init capinc_tty_init(void) { struct tty_driver *drv; - + int err; + if (capi_ttyminors > CAPINC_MAX_PORTS) capi_ttyminors = CAPINC_MAX_PORTS; if (capi_ttyminors <= 0) @@ -1340,23 +1341,22 @@ static int capinc_tty_init(void) drv->init_termios.c_lflag = 0; drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; tty_set_operations(drv, &capinc_ops); - if (tty_register_driver(drv)) { + + err = tty_register_driver(drv); + if (err) { put_tty_driver(drv); kfree(capiminors); printk(KERN_ERR "Couldn't register capi_nc driver\n"); - return -1; + return err; } capinc_tty_driver = drv; return 0; } -static void capinc_tty_exit(void) +static void __exit capinc_tty_exit(void) { - struct tty_driver *drv = capinc_tty_driver; - int retval; - if ((retval = tty_unregister_driver(drv))) - printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); - put_tty_driver(drv); + tty_unregister_driver(capinc_tty_driver); + put_tty_driver(capinc_tty_driver); kfree(capiminors); } -- cgit v1.2.3 From 40fb2d0da77df5d39f1ba8878502725ebb806554 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:25 +0000 Subject: CAPI: Dynamically register minor devices Register capiminors dynamically with the TTY core so that udev can make them show up as the NCCIs appear or disappear. This removes the need to check if the capiminor requested in capinc_tty_open actually exists. And this completely obsoletes capifs which will be scheduled for removal in a later patch. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c22b34976c24..901b79bc3b56 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -153,6 +153,8 @@ static LIST_HEAD(capidev_list); static DEFINE_RWLOCK(capiminors_lock); static struct capiminor **capiminors; +static struct tty_driver *capinc_tty_driver; + /* -------- datahandles --------------------------------------------- */ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) @@ -213,6 +215,7 @@ static void capiminor_del_all_ack(struct capiminor *mp) static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { struct capiminor *mp; + struct device *dev; unsigned int minor; unsigned long flags; @@ -243,19 +246,33 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); - kfree(mp); - return NULL; + goto err_out1; } mp->minor = minor; + dev = tty_register_device(capinc_tty_driver, minor, NULL); + if (IS_ERR(dev)) + goto err_out2; + return mp; + +err_out2: + write_lock_irqsave(&capiminors_lock, flags); + capiminors[minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); + +err_out1: + kfree(mp); + return NULL; } static void capiminor_free(struct capiminor *mp) { unsigned long flags; + tty_unregister_device(capinc_tty_driver, mp->minor); + write_lock_irqsave(&capiminors_lock, flags); capiminors[mp->minor] = NULL; write_unlock_irqrestore(&capiminors_lock, flags); @@ -268,13 +285,10 @@ static void capiminor_free(struct capiminor *mp) kfree(mp); } -static struct capiminor *capiminor_find(unsigned int minor) +static struct capiminor *capiminor_get(unsigned int minor) { struct capiminor *mp; - if (minor >= capi_ttyminors) - return NULL; - read_lock(&capiminors_lock); mp = capiminors[minor]; read_unlock(&capiminors_lock); @@ -981,8 +995,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) struct capiminor *mp; unsigned long flags; - if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL) - return -ENXIO; + mp = capiminor_get(iminor(file->f_path.dentry->d_inode)); if (mp->nccip == NULL) return -ENXIO; @@ -1284,8 +1297,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) #endif } -static struct tty_driver *capinc_tty_driver; - static const struct tty_operations capinc_ops = { .open = capinc_tty_open, .close = capinc_tty_close, @@ -1339,7 +1350,9 @@ static int __init capinc_tty_init(void) drv->init_termios.c_oflag = OPOST | ONLCR; drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; drv->init_termios.c_lflag = 0; - drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; + drv->flags = + TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | + TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(drv, &capinc_ops); err = tty_register_driver(drv); -- cgit v1.2.3 From e95ac143868752ad30d93068a6fc0b39cf3a1bf4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:26 +0000 Subject: CAPI: Use dynamic major for NCCI TTYs by default No need to allocate a fixed major for this TTY, both capifs and udev make this transparent to the user. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 901b79bc3b56..b1de0cbea69e 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -60,10 +60,8 @@ module_param_named(major, capi_major, uint, 0); #define CAPINC_NR_PORTS 32 #define CAPINC_MAX_PORTS 256 -static int capi_ttymajor = 191; static int capi_ttyminors = CAPINC_NR_PORTS; -module_param_named(ttymajor, capi_ttymajor, uint, 0); module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -301,6 +299,7 @@ static struct capiminor *capiminor_get(unsigned int minor) static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { struct capiminor *mp; + dev_t device; if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) return; @@ -311,9 +310,8 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "set mp->nccip\n"); #endif - mp->capifs_dentry = - capifs_new_ncci(mp->minor, - MKDEV(capi_ttymajor, mp->minor)); + device = MKDEV(capinc_tty_driver->major, mp->minor); + mp->capifs_dentry = capifs_new_ncci(mp->minor, device); } } @@ -1341,7 +1339,7 @@ static int __init capinc_tty_init(void) drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi"; - drv->major = capi_ttymajor; + drv->major = 0; drv->minor_start = 0; drv->type = TTY_DRIVER_TYPE_SERIAL; drv->subtype = SERIAL_TYPE_NORMAL; -- cgit v1.2.3 From 0159d5491fef4acadd116a989b671e1cd350382f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:27 +0000 Subject: CAPI: Use kref on capiminor Install a reference counter for capiminor objects. Acquire it when obtaining a capiminor from the array during capinc_tty_open, drop it when closing the tty again. Another reference is held for the hook-up with capincci. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index b1de0cbea69e..732cdb585b2d 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -83,6 +83,8 @@ struct datahandle_queue { }; struct capiminor { + struct kref kref; + struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) return NULL; } + kref_init(&mp->kref); + mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; @@ -265,18 +269,11 @@ err_out1: return NULL; } -static void capiminor_free(struct capiminor *mp) +static void capiminor_destroy(struct kref *kref) { - unsigned long flags; - - tty_unregister_device(capinc_tty_driver, mp->minor); - - write_lock_irqsave(&capiminors_lock, flags); - capiminors[mp->minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + struct capiminor *mp = container_of(kref, struct capiminor, kref); kfree_skb(mp->ttyskb); - mp->ttyskb = NULL; skb_queue_purge(&mp->inqueue); skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); @@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor) read_lock(&capiminors_lock); mp = capiminors[minor]; + if (mp) + kref_get(&mp->kref); read_unlock(&capiminors_lock); return mp; } +static inline void capiminor_put(struct capiminor *mp) +{ + kref_put(&mp->kref, capiminor_destroy); +} + +static void capiminor_free(struct capiminor *mp) +{ + unsigned long flags; + + tty_unregister_device(capinc_tty_driver, mp->minor); + + write_lock_irqsave(&capiminors_lock, flags); + capiminors[mp->minor] = NULL; + write_unlock_irqrestore(&capiminors_lock, flags); + + capiminor_put(mp); +} + /* -------- struct capincci ----------------------------------------- */ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) @@ -1029,6 +1046,8 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #endif if (mp->nccip == NULL) capiminor_free(mp); + + capiminor_put(mp); } #ifdef _DEBUG_REFCOUNT -- cgit v1.2.3 From 46324511809251adbedb874cc08692e247f7ed68 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:28 +0000 Subject: CAPI: Establish install/cleanup handlers for capiminor TTYs Properly associate/disassociate a capiminor object with its TTY via the install/cleanup handlers instead of trying to guess first open and last close. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 732cdb585b2d..3e4997ac67ae 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1005,16 +1005,34 @@ static const struct file_operations capi_fops = #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE /* -------- tty_operations for capincci ----------------------------- */ -static int capinc_tty_open(struct tty_struct * tty, struct file * file) +static int +capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) { - struct capiminor *mp; - unsigned long flags; + int idx = tty->index; + struct capiminor *mp = capiminor_get(idx); + int ret = tty_init_termios(tty); + + if (ret == 0) { + tty_driver_kref_get(driver); + tty->count++; + tty->driver_data = mp; + driver->ttys[idx] = tty; + } else + capiminor_put(mp); + return ret; +} - mp = capiminor_get(iminor(file->f_path.dentry->d_inode)); - if (mp->nccip == NULL) - return -ENXIO; +static void capinc_tty_cleanup(struct tty_struct *tty) +{ + struct capiminor *mp = tty->driver_data; + tty->driver_data = NULL; + capiminor_put(mp); +} - tty->driver_data = (void *)mp; +static int capinc_tty_open(struct tty_struct * tty, struct file * file) +{ + struct capiminor *mp = tty->driver_data; + unsigned long flags; spin_lock_irqsave(&workaround_lock, flags); if (atomic_read(&mp->ttyopencount) == 0) @@ -1030,15 +1048,12 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) static void capinc_tty_close(struct tty_struct * tty, struct file * file) { - struct capiminor *mp; + struct capiminor *mp = tty->driver_data; - mp = (struct capiminor *)tty->driver_data; - if (mp) { if (atomic_dec_and_test(&mp->ttyopencount)) { #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close lastclose\n"); #endif - tty->driver_data = NULL; mp->tty = NULL; } #ifdef _DEBUG_REFCOUNT @@ -1047,9 +1062,6 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) if (mp->nccip == NULL) capiminor_free(mp); - capiminor_put(mp); - } - #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close\n"); #endif @@ -1333,6 +1345,8 @@ static const struct tty_operations capinc_ops = { .flush_buffer = capinc_tty_flush_buffer, .set_ldisc = capinc_tty_set_ldisc, .send_xchar = capinc_tty_send_xchar, + .install = capinc_tty_install, + .cleanup = capinc_tty_cleanup, }; static int __init capinc_tty_init(void) -- cgit v1.2.3 From fb4b4881ef951f6ed8fb8564ca1821dea10778c4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:29 +0000 Subject: CAPI: Use tty_port to keep track of capiminor's tty Use the reference management features of tty_port to look up and drop again the tty_struct associated with a capiminor. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 94 +++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3e4997ac67ae..e164a8fb9693 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -94,7 +94,7 @@ struct capiminor { u16 datahandle; u16 msgid; - struct tty_struct *tty; + struct tty_port port; int ttyinstop; int ttyoutstop; struct sk_buff *ttyskb; @@ -212,6 +212,8 @@ static void capiminor_del_all_ack(struct capiminor *mp) /* -------- struct capiminor ---------------------------------------- */ +static const struct tty_port_operations capiminor_port_ops; /* we have none */ + static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) { struct capiminor *mp; @@ -237,6 +239,9 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); + tty_port_init(&mp->port); + mp->port.ops = &capiminor_port_ops; + /* Allocate the least unused minor number. */ write_lock_irqsave(&capiminors_lock, flags); for (minor = 0; minor < capi_ttyminors; minor++) @@ -335,18 +340,22 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) static void capincci_free_minor(struct capincci *np) { struct capiminor *mp = np->minorp; + struct tty_struct *tty; if (mp) { capifs_free_ncci(mp->capifs_dentry); - if (mp->tty) { + + tty = tty_port_tty_get(&mp->port); + if (tty) { mp->nccip = NULL; #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "reset mp->nccip\n"); #endif - tty_hangup(mp->tty); - } else { - capiminor_free(mp); + tty_hangup(tty); + tty_kref_put(tty); } + + capiminor_free(mp); } } @@ -433,44 +442,48 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { + struct tty_struct *tty; struct sk_buff *nskb; int datalen; u16 errcode, datahandle; struct tty_ldisc *ld; - + int ret = -1; + datalen = skb->len - CAPIMSG_LEN(skb->data); - if (mp->tty == NULL) - { + + tty = tty_port_tty_get(&mp->port); + if (!tty) { #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: currently no receiver\n"); #endif return -1; } - ld = tty_ldisc_ref(mp->tty); - if (ld == NULL) - return -1; + ld = tty_ldisc_ref(tty); + if (!ld) + goto out1; + if (ld->ops->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - goto bad; + goto out2; } if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - goto bad; + goto out2; } - if (mp->tty->receive_room < datalen) { + if (tty->receive_room < datalen) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: no room in tty\n"); #endif - goto bad; + goto out2; } if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - goto bad; + goto out2; } datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); errcode = capi20_put_message(mp->ap, nskb); @@ -478,20 +491,21 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", errcode); kfree_skb(nskb); - goto bad; + goto out2; } (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", datahandle, skb->len); #endif - ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len); + ld->ops->receive_buf(tty, skb->data, NULL, skb->len); kfree_skb(skb); + ret = 0; +out2: tty_ldisc_deref(ld); - return 0; -bad: - tty_ldisc_deref(ld); - return -1; +out1: + tty_kref_put(tty); + return ret; } static void handle_minor_recv(struct capiminor *mp) @@ -510,16 +524,22 @@ static void handle_minor_recv(struct capiminor *mp) static int handle_minor_send(struct capiminor *mp) { + struct tty_struct *tty; struct sk_buff *skb; u16 len; int count = 0; u16 errcode; u16 datahandle; - if (mp->tty && mp->ttyoutstop) { + tty = tty_port_tty_get(&mp->port); + if (!tty) + return 0; + + if (mp->ttyoutstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: send: tty stopped\n"); #endif + tty_kref_put(tty); return 0; } @@ -542,6 +562,7 @@ static int handle_minor_send(struct capiminor *mp) if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); skb_queue_head(&mp->outqueue, skb); + tty_kref_put(tty); return count; } errcode = capi20_put_message(mp->ap, skb); @@ -568,6 +589,7 @@ static int handle_minor_send(struct capiminor *mp) mp->outbytes -= len; kfree_skb(skb); } + tty_kref_put(tty); return count; } @@ -578,6 +600,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { struct capidev *cdev = ap->private; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE + struct tty_struct *tty; struct capiminor *mp; u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -641,8 +664,11 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif kfree_skb(skb); (void)capiminor_del_ack(mp, datahandle); - if (mp->tty) - tty_wakeup(mp->tty); + tty = tty_port_tty_get(&mp->port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } (void)handle_minor_send(mp); } else { @@ -1029,14 +1055,17 @@ static void capinc_tty_cleanup(struct tty_struct *tty) capiminor_put(mp); } -static int capinc_tty_open(struct tty_struct * tty, struct file * file) +static int capinc_tty_open(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; unsigned long flags; + int err; + + err = tty_port_open(&mp->port, tty, filp); + if (err) + return err; spin_lock_irqsave(&workaround_lock, flags); - if (atomic_read(&mp->ttyopencount) == 0) - mp->tty = tty; atomic_inc(&mp->ttyopencount); #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); @@ -1046,7 +1075,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) return 0; } -static void capinc_tty_close(struct tty_struct * tty, struct file * file) +static void capinc_tty_close(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; @@ -1054,17 +1083,15 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close lastclose\n"); #endif - mp->tty = NULL; } #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); #endif - if (mp->nccip == NULL) - capiminor_free(mp); #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "capinc_tty_close\n"); #endif + tty_port_close(&mp->port, tty, filp); } static int capinc_tty_write(struct tty_struct * tty, @@ -1292,9 +1319,12 @@ static void capinc_tty_start(struct tty_struct *tty) static void capinc_tty_hangup(struct tty_struct *tty) { + struct capiminor *mp = tty->driver_data; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_hangup\n"); #endif + tty_port_hangup(&mp->port); } static int capinc_tty_break_ctl(struct tty_struct *tty, int state) -- cgit v1.2.3 From 2c8df72259d550ed6dc0b391feb5c2fc13892fb6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:30 +0000 Subject: CAPI: Drop remaining NULL checks on tty->driver_data tty_struct's driver_data cannot be NULL, no need to test for it. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 64 +++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index e164a8fb9693..acc811bfe8e0 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1097,7 +1097,7 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; @@ -1105,7 +1105,7 @@ static int capinc_tty_write(struct tty_struct * tty, printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); #endif @@ -1140,7 +1140,7 @@ static int capinc_tty_write(struct tty_struct * tty, static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; int ret = 1; @@ -1149,7 +1149,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); #endif @@ -1184,7 +1184,7 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) static void capinc_tty_flush_chars(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; struct sk_buff *skb; unsigned long flags; @@ -1192,7 +1192,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - if (!mp || !mp->nccip) { + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); #endif @@ -1213,9 +1213,10 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) static int capinc_tty_write_room(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; int room; - if (!mp || !mp->nccip) { + + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); #endif @@ -1231,8 +1232,9 @@ static int capinc_tty_write_room(struct tty_struct *tty) static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; - if (!mp || !mp->nccip) { + struct capiminor *mp = tty->driver_data; + + if (!mp->nccip) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); #endif @@ -1266,55 +1268,51 @@ static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old #endif } -static void capinc_tty_throttle(struct tty_struct * tty) +static void capinc_tty_throttle(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_throttle\n"); #endif - if (mp) - mp->ttyinstop = 1; + mp->ttyinstop = 1; } -static void capinc_tty_unthrottle(struct tty_struct * tty) +static void capinc_tty_unthrottle(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; unsigned long flags; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_unthrottle\n"); #endif - if (mp) { - spin_lock_irqsave(&workaround_lock, flags); - mp->ttyinstop = 0; - handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); - } + spin_lock_irqsave(&workaround_lock, flags); + mp->ttyinstop = 0; + handle_minor_recv(mp); + spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_stop(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_stop\n"); #endif - if (mp) { - mp->ttyoutstop = 1; - } + mp->ttyoutstop = 1; } static void capinc_tty_start(struct tty_struct *tty) { - struct capiminor *mp = (struct capiminor *)tty->driver_data; + struct capiminor *mp = tty->driver_data; unsigned long flags; + #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_start\n"); #endif - if (mp) { - spin_lock_irqsave(&workaround_lock, flags); - mp->ttyoutstop = 0; - (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); - } + spin_lock_irqsave(&workaround_lock, flags); + mp->ttyoutstop = 0; + (void)handle_minor_send(mp); + spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.3 From 30bced91d93f7523bf23432d71d882d6b5d6cff6 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:31 +0000 Subject: CAPI: Issue synchronous hangup on capincci_free_minor capincci_free and, thus, capincci_free_minor runs in process context, so we can issue the hangup of the associated TTY synchronously. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index acc811bfe8e0..b382edeeee18 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -351,7 +351,7 @@ static void capincci_free_minor(struct capincci *np) #ifdef _DEBUG_REFCOUNT printk(KERN_DEBUG "reset mp->nccip\n"); #endif - tty_hangup(tty); + tty_vhangup(tty); tty_kref_put(tty); } -- cgit v1.2.3 From 6576c2891adacad81ea0b24f0704ecac9fc727cb Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:32 +0000 Subject: CAPI: Drop obsolete nccip from capiminor struct The nccip in capiminor used to serve as an indicator that the NCCI was close. But we don't need this, we issue a hangup on capincci_free_minor. So drop this legacy. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 44 +------------------------------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index b382edeeee18..cf5e996ac448 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -85,7 +85,6 @@ struct datahandle_queue { struct capiminor { struct kref kref; - struct capincci *nccip; unsigned int minor; struct dentry *capifs_dentry; @@ -328,10 +327,6 @@ static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); if (mp) { - mp->nccip = np; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "set mp->nccip\n"); -#endif device = MKDEV(capinc_tty_driver->major, mp->minor); mp->capifs_dentry = capifs_new_ncci(mp->minor, device); } @@ -347,10 +342,6 @@ static void capincci_free_minor(struct capincci *np) tty = tty_port_tty_get(&mp->port); if (tty) { - mp->nccip = NULL; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif tty_vhangup(tty); tty_kref_put(tty); } @@ -1094,7 +1085,7 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) tty_port_close(&mp->port, tty, filp); } -static int capinc_tty_write(struct tty_struct * tty, +static int capinc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct capiminor *mp = tty->driver_data; @@ -1105,13 +1096,6 @@ static int capinc_tty_write(struct tty_struct * tty, printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); -#endif - return 0; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1149,13 +1133,6 @@ static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); -#endif - return 0; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1192,13 +1169,6 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); -#endif - return; - } - spin_lock_irqsave(&workaround_lock, flags); skb = mp->ttyskb; if (skb) { @@ -1216,12 +1186,6 @@ static int capinc_tty_write_room(struct tty_struct *tty) struct capiminor *mp = tty->driver_data; int room; - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); -#endif - return 0; - } room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); room *= CAPI_MAX_BLKSIZE; #ifdef _DEBUG_TTYFUNCS @@ -1234,12 +1198,6 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - if (!mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); -#endif - return 0; - } #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", mp->outbytes, mp->nack, -- cgit v1.2.3 From 3d5d30fe7a6aa4c9d63dc4fe6b6da6abac423bc2 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:33 +0000 Subject: CAPI: Clean up capiminors_lock Use a plain spin lock for capiminors_lock, drop inconsistent irqsafe acquisitions (it's only used in process context anyway). Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index cf5e996ac448..0b264b4565c8 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -149,7 +149,7 @@ static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -static DEFINE_RWLOCK(capiminors_lock); +static DEFINE_SPINLOCK(capiminors_lock); static struct capiminor **capiminors; static struct tty_driver *capinc_tty_driver; @@ -218,7 +218,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) struct capiminor *mp; struct device *dev; unsigned int minor; - unsigned long flags; mp = kzalloc(sizeof(*mp), GFP_KERNEL); if (!mp) { @@ -242,13 +241,13 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->port.ops = &capiminor_port_ops; /* Allocate the least unused minor number. */ - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); for (minor = 0; minor < capi_ttyminors; minor++) if (!capiminors[minor]) { capiminors[minor] = mp; break; } - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); if (minor == capi_ttyminors) { printk(KERN_NOTICE "capi: out of minors\n"); @@ -264,9 +263,9 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) return mp; err_out2: - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); capiminors[minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); err_out1: kfree(mp); @@ -288,11 +287,11 @@ static struct capiminor *capiminor_get(unsigned int minor) { struct capiminor *mp; - read_lock(&capiminors_lock); + spin_lock(&capiminors_lock); mp = capiminors[minor]; if (mp) kref_get(&mp->kref); - read_unlock(&capiminors_lock); + spin_unlock(&capiminors_lock); return mp; } @@ -304,13 +303,11 @@ static inline void capiminor_put(struct capiminor *mp) static void capiminor_free(struct capiminor *mp) { - unsigned long flags; - tty_unregister_device(capinc_tty_driver, mp->minor); - write_lock_irqsave(&capiminors_lock, flags); + spin_lock(&capiminors_lock); capiminors[mp->minor] = NULL; - write_unlock_irqrestore(&capiminors_lock, flags); + spin_unlock(&capiminors_lock); capiminor_put(mp); } -- cgit v1.2.3 From a84fdf41b25ad4c2b83e7c8ca87268fdbe6207d1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:34 +0000 Subject: CAPI: Drop atomic ttyopencount Not needed, tty->count keeps track of this information. At this chance, drop traces of ancient attempts to debug this logic via _DEBUG_REFCOUNT. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 0b264b4565c8..867589a5916a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -45,7 +45,6 @@ MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -#undef _DEBUG_REFCOUNT /* alloc/free and open/close debug */ #undef _DEBUG_TTYFUNCS /* call to tty_driver */ #undef _DEBUG_DATAFLOW /* data flow */ @@ -97,7 +96,6 @@ struct capiminor { int ttyinstop; int ttyoutstop; struct sk_buff *ttyskb; - atomic_t ttyopencount; struct sk_buff_head inqueue; int inbytes; @@ -230,7 +228,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; - atomic_set(&mp->ttyopencount,0); INIT_LIST_HEAD(&mp->ackqueue); spin_lock_init(&mp->ackqlock); @@ -350,8 +347,17 @@ static void capincci_free_minor(struct capincci *np) static inline unsigned int capincci_minor_opencount(struct capincci *np) { struct capiminor *mp = np->minorp; + unsigned int count = 0; + struct tty_struct *tty; - return mp ? atomic_read(&mp->ttyopencount) : 0; + if (mp) { + tty = tty_port_tty_get(&mp->port); + if (tty) { + count = tty->count; + tty_kref_put(tty); + } + } + return count; } #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -1054,10 +1060,6 @@ static int capinc_tty_open(struct tty_struct *tty, struct file *filp) return err; spin_lock_irqsave(&workaround_lock, flags); - atomic_inc(&mp->ttyopencount); -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif handle_minor_recv(mp); spin_unlock_irqrestore(&workaround_lock, flags); return 0; @@ -1067,18 +1069,6 @@ static void capinc_tty_close(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; - if (atomic_dec_and_test(&mp->ttyopencount)) { -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close lastclose\n"); -#endif - } -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif - -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close\n"); -#endif tty_port_close(&mp->port, tty, filp); } -- cgit v1.2.3 From b75b2eedcbf6458c68713c772c2ade83ab7a55f0 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:35 +0000 Subject: CAPI: Drop handle_minor_recv from capinc_tty_write Sending a message down the CAPI stack may trigger the reception of an answer, but this will go through capi_recv_message and call handle_minor_recv from there. There is no need to walk the receive queue on capinc_tty_write. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 867589a5916a..554fa1b36d13 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -1104,7 +1104,6 @@ static int capinc_tty_write(struct tty_struct *tty, skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; (void)handle_minor_send(mp); - (void)handle_minor_recv(mp); spin_unlock_irqrestore(&workaround_lock, flags); return count; } -- cgit v1.2.3 From a11ef7be8e982426e9fbbfc84fa0c01d23ce05c3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:36 +0000 Subject: CAPI: Rework capiminor RX handler Avoid re-queuing skbs unless the error detected in handle_recv_skb is expected to be recoverable such as lacking memory, a full CAPI queue, a full TTY input buffer, or a not yet existing TTY. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 60 ++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 554fa1b36d13..c5c54fab50eb 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -436,15 +436,13 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) { + unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data); struct tty_struct *tty; struct sk_buff *nskb; - int datalen; u16 errcode, datahandle; struct tty_ldisc *ld; int ret = -1; - datalen = skb->len - CAPIMSG_LEN(skb->data); - tty = tty_port_tty_get(&mp->port); if (!tty) { #ifdef _DEBUG_DATAFLOW @@ -454,50 +452,68 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) } ld = tty_ldisc_ref(tty); - if (!ld) - goto out1; + if (!ld) { + /* fatal error, do not requeue */ + ret = 0; + kfree_skb(skb); + goto deref_tty; + } if (ld->ops->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - goto out2; + /* fatal error, do not requeue */ + goto free_skb; } if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - goto out2; + goto deref_ldisc; } + if (tty->receive_room < datalen) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: no room in tty\n"); #endif - goto out2; + goto deref_ldisc; } - if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { + + nskb = gen_data_b3_resp_for(mp, skb); + if (!nskb) { printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - goto out2; + goto deref_ldisc; } - datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); + + datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4); + errcode = capi20_put_message(mp->ap, nskb); - if (errcode != CAPI_NOERROR) { + + if (errcode == CAPI_NOERROR) { + skb_pull(skb, CAPIMSG_LEN(skb->data)); +#ifdef _DEBUG_DATAFLOW + printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); +#endif + ld->ops->receive_buf(tty, skb->data, NULL, skb->len); + } else { printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", errcode); kfree_skb(nskb); - goto out2; + + if (errcode == CAPI_SENDQUEUEFULL) + goto deref_ldisc; } - (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); -#endif - ld->ops->receive_buf(tty, skb->data, NULL, skb->len); - kfree_skb(skb); + +free_skb: ret = 0; -out2: + kfree_skb(skb); + +deref_ldisc: tty_ldisc_deref(ld); -out1: + +deref_tty: tty_kref_put(tty); return ret; } -- cgit v1.2.3 From 42651b5c1aabf5eb60fbe98375ba127f4f6eb943 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:37 +0000 Subject: CAPI: Rename datahandle_queue -> ackqueue_entry This struct is describing a queue entry, not the queue itself. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index c5c54fab50eb..9d4750a0aece 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -76,7 +76,7 @@ struct capidev; struct capincci; struct capiminor; -struct datahandle_queue { +struct ackqueue_entry { struct list_head list; u16 datahandle; }; @@ -156,7 +156,7 @@ static struct tty_driver *capinc_tty_driver; static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue *n; + struct ackqueue_entry *n; unsigned long flags; n = kmalloc(sizeof(*n), GFP_ATOMIC); @@ -175,7 +175,7 @@ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) { - struct datahandle_queue *p, *tmp; + struct ackqueue_entry *p, *tmp; unsigned long flags; spin_lock_irqsave(&mp->ackqlock, flags); @@ -194,7 +194,7 @@ static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) static void capiminor_del_all_ack(struct capiminor *mp) { - struct datahandle_queue *p, *tmp; + struct ackqueue_entry *p, *tmp; unsigned long flags; spin_lock_irqsave(&mp->ackqlock, flags); -- cgit v1.2.3 From 42792713f7f2664cf07501e1244d6da33a73ffc1 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:38 +0000 Subject: CAPI: Use atomics for capiminor's datahandle and msgid The capiminor members datahandle and msgid are incremented outside any lock, so better do this atomically. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 9d4750a0aece..08d5a8aa2fec 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -87,10 +87,10 @@ struct capiminor { unsigned int minor; struct dentry *capifs_dentry; - struct capi20_appl *ap; - u32 ncci; - u16 datahandle; - u16 msgid; + struct capi20_appl *ap; + u32 ncci; + atomic_t datahandle; + atomic_t msgid; struct tty_port port; int ttyinstop; @@ -227,7 +227,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) mp->ap = ap; mp->ncci = ncci; - mp->msgid = 0; INIT_LIST_HEAD(&mp->ackqueue); spin_lock_init(&mp->ackqlock); @@ -427,7 +426,7 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) capimsg_setu16(s, 2, mp->ap->applid); capimsg_setu8 (s, 4, CAPI_DATA_B3); capimsg_setu8 (s, 5, CAPI_RESP); - capimsg_setu16(s, 6, mp->msgid++); + capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid)); capimsg_setu32(s, 8, mp->ncci); capimsg_setu16(s, 12, datahandle); } @@ -554,7 +553,7 @@ static int handle_minor_send(struct capiminor *mp) } while ((skb = skb_dequeue(&mp->outqueue)) != NULL) { - datahandle = mp->datahandle; + datahandle = atomic_inc_return(&mp->datahandle); len = (u16)skb->len; skb_push(skb, CAPI_DATA_B3_REQ_LEN); memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); @@ -562,7 +561,7 @@ static int handle_minor_send(struct capiminor *mp) capimsg_setu16(skb->data, 2, mp->ap->applid); capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); capimsg_setu8 (skb->data, 5, CAPI_REQ); - capimsg_setu16(skb->data, 6, mp->msgid++); + capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid)); capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */ capimsg_setu16(skb->data, 16, len); /* Data length */ @@ -577,7 +576,6 @@ static int handle_minor_send(struct capiminor *mp) } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { - mp->datahandle++; count++; mp->outbytes -= len; #ifdef _DEBUG_DATAFLOW -- cgit v1.2.3 From 68d7347b280b4c1f8253c0676a520fb754f213c7 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:39 +0000 Subject: CAPI: Drop capiminor's unused inbytes counter The inbytes counter was only updated but never read. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 08d5a8aa2fec..be85c8c1e8b4 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -98,7 +98,6 @@ struct capiminor { struct sk_buff *ttyskb; struct sk_buff_head inqueue; - int inbytes; struct sk_buff_head outqueue; int outbytes; @@ -520,15 +519,12 @@ deref_tty: static void handle_minor_recv(struct capiminor *mp) { struct sk_buff *skb; - while ((skb = skb_dequeue(&mp->inqueue)) != NULL) { - unsigned int len = skb->len; - mp->inbytes -= len; + + while ((skb = skb_dequeue(&mp->inqueue)) != NULL) if (handle_recv_skb(mp, skb) < 0) { skb_queue_head(&mp->inqueue, skb); - mp->inbytes += len; return; } - } } static int handle_minor_send(struct capiminor *mp) @@ -659,7 +655,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) datahandle, skb->len-CAPIMSG_LEN(skb->data)); #endif skb_queue_tail(&mp->inqueue, skb); - mp->inbytes += skb->len; + handle_minor_recv(mp); } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { -- cgit v1.2.3 From dfbb84ffe94e75e2d56250fa948db40f6c62093f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:40 +0000 Subject: CAPI: Fix locking around capiminor's output queue and drop workaround_lock Introduce outlock as a spin lock that protects capiminor's outqueue, outbytes and outskb (formerly known as ttyskb). outlock can be acquired from soft-IRQ context via capinc_write, so make it bh-safe. This finally removes the last reason for keeping the workaround lock around (which was incomplete and partly broken anyway). And as we no longer call handle_recv_skb in atomic context, gen_data_b3_resp_for can use non-atomic allocation now. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 126 +++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index be85c8c1e8b4..074496fae8da 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -95,11 +95,13 @@ struct capiminor { struct tty_port port; int ttyinstop; int ttyoutstop; - struct sk_buff *ttyskb; - struct sk_buff_head inqueue; - struct sk_buff_head outqueue; - int outbytes; + struct sk_buff_head inqueue; + + struct sk_buff_head outqueue; + int outbytes; + struct sk_buff *outskb; + spinlock_t outlock; /* transmit path */ struct list_head ackqueue; @@ -107,15 +109,6 @@ struct capiminor { spinlock_t ackqlock; }; -/* FIXME: The following lock is a sledgehammer-workaround to a - * locking issue with the capiminor (and maybe other) data structure(s). - * Access to this data is done in a racy way and crashes the machine with - * a FritzCard DSL driver; sooner or later. This is a workaround - * which trades scalability vs stability, so it doesn't crash the kernel anymore. - * The correct (and scalable) fix for the issue seems to require - * an API change to the drivers... . */ -static DEFINE_SPINLOCK(workaround_lock); - struct capincci { struct list_head list; u32 ncci; @@ -231,6 +224,7 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) skb_queue_head_init(&mp->inqueue); skb_queue_head_init(&mp->outqueue); + spin_lock_init(&mp->outlock); tty_port_init(&mp->port); mp->port.ops = &capiminor_port_ops; @@ -271,7 +265,7 @@ static void capiminor_destroy(struct kref *kref) { struct capiminor *mp = container_of(kref, struct capiminor, kref); - kfree_skb(mp->ttyskb); + kfree_skb(mp->outskb); skb_queue_purge(&mp->inqueue); skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); @@ -417,7 +411,7 @@ static struct sk_buff * gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) { struct sk_buff *nskb; - nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC); + nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_KERNEL); if (nskb) { u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2); unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN); @@ -548,9 +542,18 @@ static int handle_minor_send(struct capiminor *mp) return 0; } - while ((skb = skb_dequeue(&mp->outqueue)) != NULL) { - datahandle = atomic_inc_return(&mp->datahandle); + while (1) { + spin_lock_bh(&mp->outlock); + skb = __skb_dequeue(&mp->outqueue); + if (!skb) { + spin_unlock_bh(&mp->outlock); + break; + } len = (u16)skb->len; + mp->outbytes -= len; + spin_unlock_bh(&mp->outlock); + + datahandle = atomic_inc_return(&mp->datahandle); skb_push(skb, CAPI_DATA_B3_REQ_LEN); memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); @@ -566,14 +569,18 @@ static int handle_minor_send(struct capiminor *mp) if (capiminor_add_ack(mp, datahandle) < 0) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); + + spin_lock_bh(&mp->outlock); + __skb_queue_head(&mp->outqueue, skb); + mp->outbytes += len; + spin_unlock_bh(&mp->outlock); + tty_kref_put(tty); return count; } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { count++; - mp->outbytes -= len; #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", datahandle, len); @@ -584,13 +591,17 @@ static int handle_minor_send(struct capiminor *mp) if (errcode == CAPI_SENDQUEUEFULL) { skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); + + spin_lock_bh(&mp->outlock); + __skb_queue_head(&mp->outqueue, skb); + mp->outbytes += len; + spin_unlock_bh(&mp->outlock); + break; } /* ups, drop packet */ printk(KERN_ERR "capi: put_message = %x\n", errcode); - mp->outbytes -= len; kfree_skb(skb); } tty_kref_put(tty); @@ -609,7 +620,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) u16 datahandle; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ struct capincci *np; - unsigned long flags; mutex_lock(&cdev->lock); @@ -621,7 +631,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); - spin_lock_irqsave(&workaround_lock, flags); if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { skb_queue_tail(&cdev->recvqueue, skb); wake_up_interruptible(&cdev->recvwait); @@ -683,7 +692,6 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ unlock_out: - spin_unlock_irqrestore(&workaround_lock, flags); mutex_unlock(&cdev->lock); } @@ -1062,16 +1070,13 @@ static void capinc_tty_cleanup(struct tty_struct *tty) static int capinc_tty_open(struct tty_struct *tty, struct file *filp) { struct capiminor *mp = tty->driver_data; - unsigned long flags; int err; err = tty_port_open(&mp->port, tty, filp); if (err) return err; - spin_lock_irqsave(&workaround_lock, flags); handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); return 0; } @@ -1087,71 +1092,78 @@ static int capinc_tty_write(struct tty_struct *tty, { struct capiminor *mp = tty->driver_data; struct sk_buff *skb; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; } skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); if (!skb) { printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); - spin_unlock_irqrestore(&workaround_lock, flags); + spin_unlock_bh(&mp->outlock); return -ENOMEM; } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); memcpy(skb_put(skb, count), buf, count); - skb_queue_tail(&mp->outqueue, skb); + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; + spin_unlock_bh(&mp->outlock); + (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); + return count; } static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) { struct capiminor *mp = tty->driver_data; + bool invoke_send = false; struct sk_buff *skb; - unsigned long flags; int ret = 1; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { if (skb_tailroom(skb) > 0) { *(skb_put(skb, 1)) = ch; - spin_unlock_irqrestore(&workaround_lock, flags); - return 1; + goto unlock_out; } - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; - (void)handle_minor_send(mp); + invoke_send = true; } + skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); if (skb) { skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); *(skb_put(skb, 1)) = ch; - mp->ttyskb = skb; + mp->outskb = skb; } else { printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); ret = 0; } - spin_unlock_irqrestore(&workaround_lock, flags); + +unlock_out: + spin_unlock_bh(&mp->outlock); + + if (invoke_send) + (void)handle_minor_send(mp); + return ret; } @@ -1159,22 +1171,24 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; struct sk_buff *skb; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_flush_chars\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); - skb = mp->ttyskb; + spin_lock_bh(&mp->outlock); + skb = mp->outskb; if (skb) { - mp->ttyskb = NULL; - skb_queue_tail(&mp->outqueue, skb); + mp->outskb = NULL; + __skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; + spin_unlock_bh(&mp->outlock); + (void)handle_minor_send(mp); - } - (void)handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); + } else + spin_unlock_bh(&mp->outlock); + + handle_minor_recv(mp); } static int capinc_tty_write_room(struct tty_struct *tty) @@ -1234,15 +1248,12 @@ static void capinc_tty_throttle(struct tty_struct *tty) static void capinc_tty_unthrottle(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_unthrottle\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); mp->ttyinstop = 0; handle_minor_recv(mp); - spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_stop(struct tty_struct *tty) @@ -1258,15 +1269,12 @@ static void capinc_tty_stop(struct tty_struct *tty) static void capinc_tty_start(struct tty_struct *tty) { struct capiminor *mp = tty->driver_data; - unsigned long flags; #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_start\n"); #endif - spin_lock_irqsave(&workaround_lock, flags); mp->ttyoutstop = 0; (void)handle_minor_send(mp); - spin_unlock_irqrestore(&workaround_lock, flags); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.3 From 2b72b5bd65f00bce786ca080aca27e91e90af6df Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:41 +0000 Subject: CAPI: Clean up capiminor_*_ack No need for irqsave acquisition of acklock, bh-safe is sufficient. Moverover, move kfree out of the lock and do not take acklock at all in capiminor_del_all_ack as we are the last user of the list here. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 074496fae8da..40b81b460e81 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -149,7 +149,6 @@ static struct tty_driver *capinc_tty_driver; static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) { struct ackqueue_entry *n; - unsigned long flags; n = kmalloc(sizeof(*n), GFP_ATOMIC); if (unlikely(!n)) { @@ -158,44 +157,40 @@ static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) } n->datahandle = datahandle; INIT_LIST_HEAD(&n->list); - spin_lock_irqsave(&mp->ackqlock, flags); + spin_lock_bh(&mp->ackqlock); list_add_tail(&n->list, &mp->ackqueue); mp->nack++; - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); return 0; } static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) { struct ackqueue_entry *p, *tmp; - unsigned long flags; - spin_lock_irqsave(&mp->ackqlock, flags); + spin_lock_bh(&mp->ackqlock); list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { if (p->datahandle == datahandle) { list_del(&p->list); - kfree(p); mp->nack--; - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); + kfree(p); return 0; } } - spin_unlock_irqrestore(&mp->ackqlock, flags); + spin_unlock_bh(&mp->ackqlock); return -1; } static void capiminor_del_all_ack(struct capiminor *mp) { struct ackqueue_entry *p, *tmp; - unsigned long flags; - spin_lock_irqsave(&mp->ackqlock, flags); list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { list_del(&p->list); kfree(p); mp->nack--; } - spin_unlock_irqrestore(&mp->ackqlock, flags); } @@ -676,7 +671,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); #endif kfree_skb(skb); - (void)capiminor_del_ack(mp, datahandle); + capiminor_del_ack(mp, datahandle); tty = tty_port_tty_get(&mp->port); if (tty) { tty_wakeup(tty); -- cgit v1.2.3 From eef0ced02840cdbc9045b24e73378401aae04d4c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:42 +0000 Subject: CAPI: Drop return value of handle_minor_send We did not evaluate handle_minor_send's return value, just (void)'ed it away. Time for a cleanup. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/capi.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 40b81b460e81..ee5837522f5a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -516,25 +516,24 @@ static void handle_minor_recv(struct capiminor *mp) } } -static int handle_minor_send(struct capiminor *mp) +static void handle_minor_send(struct capiminor *mp) { struct tty_struct *tty; struct sk_buff *skb; u16 len; - int count = 0; u16 errcode; u16 datahandle; tty = tty_port_tty_get(&mp->port); if (!tty) - return 0; + return; if (mp->ttyoutstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) printk(KERN_DEBUG "capi: send: tty stopped\n"); #endif tty_kref_put(tty); - return 0; + return; } while (1) { @@ -570,12 +569,10 @@ static int handle_minor_send(struct capiminor *mp) mp->outbytes += len; spin_unlock_bh(&mp->outlock); - tty_kref_put(tty); - return count; + break; } errcode = capi20_put_message(mp->ap, skb); if (errcode == CAPI_NOERROR) { - count++; #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", datahandle, len); @@ -600,7 +597,6 @@ static int handle_minor_send(struct capiminor *mp) kfree_skb(skb); } tty_kref_put(tty); - return count; } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -677,7 +673,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) tty_wakeup(tty); tty_kref_put(tty); } - (void)handle_minor_send(mp); + handle_minor_send(mp); } else { /* ups, let capi application handle it :-) */ @@ -1114,7 +1110,7 @@ static int capinc_tty_write(struct tty_struct *tty, mp->outbytes += skb->len; spin_unlock_bh(&mp->outlock); - (void)handle_minor_send(mp); + handle_minor_send(mp); return count; } @@ -1157,7 +1153,7 @@ unlock_out: spin_unlock_bh(&mp->outlock); if (invoke_send) - (void)handle_minor_send(mp); + handle_minor_send(mp); return ret; } @@ -1179,7 +1175,7 @@ static void capinc_tty_flush_chars(struct tty_struct *tty) mp->outbytes += skb->len; spin_unlock_bh(&mp->outlock); - (void)handle_minor_send(mp); + handle_minor_send(mp); } else spin_unlock_bh(&mp->outlock); @@ -1269,7 +1265,7 @@ static void capinc_tty_start(struct tty_struct *tty) printk(KERN_DEBUG "capinc_tty_start\n"); #endif mp->ttyoutstop = 0; - (void)handle_minor_send(mp); + handle_minor_send(mp); } static void capinc_tty_hangup(struct tty_struct *tty) -- cgit v1.2.3 From c6af0437941c92179eeb51579f19423eacc5516c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:43 +0000 Subject: CAPI: Drop special controller lookup from capi20_put_message This strange special rule to fall back to controller 1 cannot be derived from the CAPI specs and looks a lot like it was once dedicated to some out-of-tree driver, probably AVM's broken fcdsl2 (FRITZ!Card DSL v2.0). I found no in-tree user that needs this check, and I'm now taking care of the fcdsl2. So drop these bits from our stack. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/kcapi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 0b4c8a7396bc..ce9b05b9e93a 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -777,11 +777,8 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) * synchronizes this service with capi20_release. */ ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); - if (!ctr || ctr->state != CAPI_CTR_RUNNING) { - ctr = get_capi_ctr_by_nr(1); /* XXX why? */ - if (!ctr || ctr->state != CAPI_CTR_RUNNING) - return CAPI_REGNOTINSTALLED; - } + if (!ctr || ctr->state != CAPI_CTR_RUNNING) + return CAPI_REGNOTINSTALLED; if (ctr->blocked) return CAPI_SENDQUEUEFULL; -- cgit v1.2.3 From 79e95f4717767e9ddc4dbec5d778f0c9970eed34 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:44 +0000 Subject: CAPI: Schedule capifs for removal With dynamic TTY nodes and the help of udev, we no longer need this special filesystem. Schedule it for removal in one year from now. As a last duty to this feature, move its help to right option so that users can read the rationale. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 10 ++++++++++ drivers/isdn/capi/Kconfig | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 2f93ac06c414..721a2aa80a1d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -521,3 +521,13 @@ Why: Duplicate functionality with the gspca_zc3xx driver, zc0301 only sensors) wich are also supported by the gspca_zc3xx driver (which supports 53 USB-ID's in total) Who: Hans de Goede + +---------------------------- + +What: capifs +When: February 2011 +Files: drivers/isdn/capi/capifs.* +Why: udev fully replaces this special file system that only contains CAPI + NCCI TTY device nodes. User space (pppdcapiplugin) works without + noticing the difference. +Who: Jan Kiszka diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index b2a04755c96a..d607d465786e 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -35,18 +35,19 @@ config ISDN_CAPI_CAPI20 Y/M here. config ISDN_CAPI_CAPIFS_BOOL - bool "CAPI2.0 filesystem support" + bool "CAPI2.0 filesystem support (DEPRECATED)" depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20 + help + This option provides a special file system, similar to /dev/pts with + device nodes for the special ttys established by using the + middleware extension above. + You no longer need this, udev fully replaces it. This feature is + scheduled for removal. config ISDN_CAPI_CAPIFS tristate depends on ISDN_CAPI_CAPIFS_BOOL default ISDN_CAPI_CAPI20 - help - This option provides a special file system, similar to /dev/pts with - device nodes for the special ttys established by using the - middleware extension above. If you want to use pppd with - pppdcapiplugin to dial up to your ISP, say Y here. config ISDN_CAPI_CAPIDRV tristate "CAPI2.0 capidrv interface support" -- cgit v1.2.3 From 771f4c87be909ad9feb6af26424485b02deed244 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 8 Feb 2010 10:12:45 +0000 Subject: CAPI: Remove experimental tag from middleware feature Despite all its bugs, the middleware support of our CAPI stack was already in use for many, many moons. And after going through its code, fixing all issues I found, I feel it deserves to officially become a non-experimental feature. Signed-off-by: Jan Kiszka Signed-off-by: David S. Miller --- drivers/isdn/capi/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index d607d465786e..a168e8a891be 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -17,8 +17,7 @@ config CAPI_TRACE If unsure, say Y. config ISDN_CAPI_MIDDLEWARE - bool "CAPI2.0 Middleware support (EXPERIMENTAL)" - depends on EXPERIMENTAL + bool "CAPI2.0 Middleware support" help This option will enhance the capabilities of the /dev/capi20 interface. It will provide a means of moving a data connection, -- cgit v1.2.3 From e06d41d09f314a1664ad60e46934b0ac131c6fa2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Feb 2010 14:32:50 +0000 Subject: netdev: bfin_mac: drop experimental markings on RMII support The code has been around for a long time now and is known to work on a bunch of different parts/boards. Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index b711d5416100..069057796bd7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -880,8 +880,8 @@ config BFIN_RX_DESC_NUM Set the number of buffer packets used in driver. config BFIN_MAC_RMII - bool "RMII PHY Interface (EXPERIMENTAL)" - depends on BFIN_MAC && EXPERIMENTAL + bool "RMII PHY Interface" + depends on BFIN_MAC default y if BFIN527_EZKIT default n if BFIN537_STAMP help -- cgit v1.2.3 From 6836b9bdd98e3b500cd49512484df68f46e14659 Mon Sep 17 00:00:00 2001 From: jamal Date: Tue, 16 Feb 2010 02:01:22 +0000 Subject: xfrm: avoid spinlock in get_acqseq() used by xfrm user Eric's version fixed it for pfkey. This one is for xfrm user. I thought about amortizing those two get_acqseq()s but it seems reasonable to have two of these sequence spaces for the two different interfaces. cheers, jamal commit d5168d5addbc999c94aacda8f28a4a173756a72b Author: Jamal Hadi Salim Date: Tue Feb 16 06:51:22 2010 -0500 xfrm: avoid spinlock in get_acqseq() used by xfrm user This is in the same spirit as commit 28aecb9d7728dc26bf03ce7925fe622023a83a2a by Eric Dumazet. Use atomic_inc_return() in get_acqseq() to avoid taking a spinlock Signed-off-by: Jamal Hadi Salim Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f50ee9badf47..96f2088e7448 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1462,12 +1462,12 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq); u32 xfrm_get_acqseq(void) { u32 res; - static u32 acqseq; - static DEFINE_SPINLOCK(acqseq_lock); + static atomic_t acqseq; + + do { + res = atomic_inc_return(&acqseq); + } while (!res); - spin_lock_bh(&acqseq_lock); - res = (++acqseq ? : ++acqseq); - spin_unlock_bh(&acqseq_lock); return res; } EXPORT_SYMBOL(xfrm_get_acqseq); -- cgit v1.2.3 From 7d720c3e4f0c4fc152a6bf17e24244a3c85412d2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 16 Feb 2010 15:20:26 +0000 Subject: percpu: add __percpu sparse annotations to net Add __percpu sparse annotations to net. These annotations are to make sparse consider percpu variables to be in a different address space and warn if accessed without going through percpu accessors. This patch doesn't affect normal builds. The macro and type tricks around snmp stats make things a bit interesting. DEFINE/DECLARE_SNMP_STAT() macros mark the target field as __percpu and SNMP_UPD_PO_STATS() macro is updated accordingly. All snmp_mib_*() users which used to cast the argument to (void **) are updated to cast it to (void __percpu **). Signed-off-by: Tejun Heo Acked-by: David S. Miller Cc: Patrick McHardy Cc: Arnaldo Carvalho de Melo Cc: Vlad Yasevich Cc: netdev@vger.kernel.org Signed-off-by: David S. Miller --- include/net/ip.h | 6 +++--- include/net/ipcomp.h | 2 +- include/net/neighbour.h | 2 +- include/net/netns/conntrack.h | 2 +- include/net/netns/core.h | 2 +- include/net/route.h | 2 +- include/net/snmp.h | 12 +++++++---- include/net/tcp.h | 2 +- net/8021q/vlan.h | 2 +- net/dccp/proto.c | 5 +++-- net/ipv4/af_inet.c | 46 +++++++++++++++++++++---------------------- net/ipv4/proc.c | 28 +++++++++++++------------- net/ipv4/route.c | 2 +- net/ipv4/tcp.c | 21 +++++++++++--------- net/ipv6/addrconf.c | 24 +++++++++++----------- net/ipv6/af_inet6.c | 28 +++++++++++++------------- net/ipv6/proc.c | 23 ++++++++++++---------- net/sctp/proc.c | 2 +- net/sctp/protocol.c | 5 +++-- net/xfrm/xfrm_ipcomp.c | 16 +++++++-------- net/xfrm/xfrm_policy.c | 6 +++--- net/xfrm/xfrm_proc.c | 3 ++- 22 files changed, 127 insertions(+), 114 deletions(-) diff --git a/include/net/ip.h b/include/net/ip.h index 7bc47873e3fc..503994a38ed1 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -174,9 +174,9 @@ extern struct ipv4_config ipv4_config; #define NET_ADD_STATS_BH(net, field, adnd) SNMP_ADD_STATS_BH((net)->mib.net_statistics, field, adnd) #define NET_ADD_STATS_USER(net, field, adnd) SNMP_ADD_STATS_USER((net)->mib.net_statistics, field, adnd) -extern unsigned long snmp_fold_field(void *mib[], int offt); -extern int snmp_mib_init(void *ptr[2], size_t mibsize); -extern void snmp_mib_free(void *ptr[2]); +extern unsigned long snmp_fold_field(void __percpu *mib[], int offt); +extern int snmp_mib_init(void __percpu *ptr[2], size_t mibsize); +extern void snmp_mib_free(void __percpu *ptr[2]); extern struct local_ports { seqlock_t lock; diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h index 2a1092abaa07..cc4f30cd7315 100644 --- a/include/net/ipcomp.h +++ b/include/net/ipcomp.h @@ -9,7 +9,7 @@ struct crypto_comp; struct ipcomp_data { u16 threshold; - struct crypto_comp **tfms; + struct crypto_comp * __percpu *tfms; }; struct ip_comp_hdr; diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 7834f470d14a..da1d58be31b7 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -164,7 +164,7 @@ struct neigh_table { rwlock_t lock; unsigned long last_rand; struct kmem_cache *kmem_cachep; - struct neigh_statistics *stats; + struct neigh_statistics __percpu *stats; struct neighbour **hash_buckets; unsigned int hash_mask; __u32 hash_rnd; diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 63d449807d9b..d4958d4c6574 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -17,7 +17,7 @@ struct netns_ct { struct hlist_head *expect_hash; struct hlist_nulls_head unconfirmed; struct hlist_nulls_head dying; - struct ip_conntrack_stat *stat; + struct ip_conntrack_stat __percpu *stat; int sysctl_events; unsigned int sysctl_events_retry_timeout; int sysctl_acct; diff --git a/include/net/netns/core.h b/include/net/netns/core.h index 24d4be76bbd1..78eb1ff75475 100644 --- a/include/net/netns/core.h +++ b/include/net/netns/core.h @@ -10,7 +10,7 @@ struct netns_core { int sysctl_somaxconn; - struct prot_inuse *inuse; + struct prot_inuse __percpu *inuse; }; #endif diff --git a/include/net/route.h b/include/net/route.h index bce6dd68d27b..2c9fba7f7731 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -101,7 +101,7 @@ struct rt_cache_stat { unsigned int out_hlist_search; }; -extern struct ip_rt_acct *ip_rt_acct; +extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; extern int ip_rt_init(void); diff --git a/include/net/snmp.h b/include/net/snmp.h index da02ee027d69..692ee0061dc4 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -129,9 +129,9 @@ struct linux_xfrm_mib { * nonlocked_atomic_inc() primitives -AK */ #define DEFINE_SNMP_STAT(type, name) \ - __typeof__(type) *name[2] + __typeof__(type) __percpu *name[2] #define DECLARE_SNMP_STAT(type, name) \ - extern __typeof__(type) *name[2] + extern __typeof__(type) __percpu *name[2] #define SNMP_STAT_BHPTR(name) (name[0]) #define SNMP_STAT_USRPTR(name) (name[1]) @@ -148,9 +148,13 @@ struct linux_xfrm_mib { __this_cpu_add(mib[0]->mibs[field], addend) #define SNMP_ADD_STATS_USER(mib, field, addend) \ this_cpu_add(mib[1]->mibs[field], addend) +/* + * Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr" + * to make @ptr a non-percpu pointer. + */ #define SNMP_UPD_PO_STATS(mib, basefield, addend) \ do { \ - __typeof__(mib[0]) ptr; \ + __typeof__(*mib[0]) *ptr; \ preempt_disable(); \ ptr = this_cpu_ptr((mib)[!in_softirq()]); \ ptr->mibs[basefield##PKTS]++; \ @@ -159,7 +163,7 @@ struct linux_xfrm_mib { } while (0) #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \ do { \ - __typeof__(mib[0]) ptr = \ + __typeof__(*mib[0]) *ptr = \ __this_cpu_ptr((mib)[!in_softirq()]); \ ptr->mibs[basefield##PKTS]++; \ ptr->mibs[basefield##OCTETS] += addend;\ diff --git a/include/net/tcp.h b/include/net/tcp.h index 87d164b9bd8f..75a00c80bdda 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1189,7 +1189,7 @@ extern int tcp_v4_md5_do_del(struct sock *sk, #define tcp_twsk_md5_key(twsk) NULL #endif -extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *); +extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *); extern void tcp_free_md5sig_pool(void); extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5685296017e9..6abdcac1b2e8 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -61,7 +61,7 @@ struct vlan_dev_info { struct proc_dir_entry *dent; unsigned long cnt_inc_headroom_on_tx; unsigned long cnt_encap_on_xmit; - struct vlan_rx_stats *vlan_rx_stats; + struct vlan_rx_stats __percpu *vlan_rx_stats; }; static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 85ec1cb7fd41..0ef7061920c0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1005,12 +1005,13 @@ EXPORT_SYMBOL_GPL(dccp_shutdown); static inline int dccp_mib_init(void) { - return snmp_mib_init((void**)dccp_statistics, sizeof(struct dccp_mib)); + return snmp_mib_init((void __percpu **)dccp_statistics, + sizeof(struct dccp_mib)); } static inline void dccp_mib_exit(void) { - snmp_mib_free((void**)dccp_statistics); + snmp_mib_free((void __percpu **)dccp_statistics); } static int thash_entries; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 7d12c6a9b19b..33b7dffa7732 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1385,7 +1385,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family, } EXPORT_SYMBOL_GPL(inet_ctl_sock_create); -unsigned long snmp_fold_field(void *mib[], int offt) +unsigned long snmp_fold_field(void __percpu *mib[], int offt) { unsigned long res = 0; int i; @@ -1398,7 +1398,7 @@ unsigned long snmp_fold_field(void *mib[], int offt) } EXPORT_SYMBOL_GPL(snmp_fold_field); -int snmp_mib_init(void *ptr[2], size_t mibsize) +int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) { BUG_ON(ptr == NULL); ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); @@ -1416,7 +1416,7 @@ err0: } EXPORT_SYMBOL_GPL(snmp_mib_init); -void snmp_mib_free(void *ptr[2]) +void snmp_mib_free(void __percpu *ptr[2]) { BUG_ON(ptr == NULL); free_percpu(ptr[0]); @@ -1460,25 +1460,25 @@ static const struct net_protocol icmp_protocol = { static __net_init int ipv4_mib_init_net(struct net *net) { - if (snmp_mib_init((void **)net->mib.tcp_statistics, + if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics, sizeof(struct tcp_mib)) < 0) goto err_tcp_mib; - if (snmp_mib_init((void **)net->mib.ip_statistics, + if (snmp_mib_init((void __percpu **)net->mib.ip_statistics, sizeof(struct ipstats_mib)) < 0) goto err_ip_mib; - if (snmp_mib_init((void **)net->mib.net_statistics, + if (snmp_mib_init((void __percpu **)net->mib.net_statistics, sizeof(struct linux_mib)) < 0) goto err_net_mib; - if (snmp_mib_init((void **)net->mib.udp_statistics, + if (snmp_mib_init((void __percpu **)net->mib.udp_statistics, sizeof(struct udp_mib)) < 0) goto err_udp_mib; - if (snmp_mib_init((void **)net->mib.udplite_statistics, + if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics, sizeof(struct udp_mib)) < 0) goto err_udplite_mib; - if (snmp_mib_init((void **)net->mib.icmp_statistics, + if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics, sizeof(struct icmp_mib)) < 0) goto err_icmp_mib; - if (snmp_mib_init((void **)net->mib.icmpmsg_statistics, + if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics, sizeof(struct icmpmsg_mib)) < 0) goto err_icmpmsg_mib; @@ -1486,30 +1486,30 @@ static __net_init int ipv4_mib_init_net(struct net *net) return 0; err_icmpmsg_mib: - snmp_mib_free((void **)net->mib.icmp_statistics); + snmp_mib_free((void __percpu **)net->mib.icmp_statistics); err_icmp_mib: - snmp_mib_free((void **)net->mib.udplite_statistics); + snmp_mib_free((void __percpu **)net->mib.udplite_statistics); err_udplite_mib: - snmp_mib_free((void **)net->mib.udp_statistics); + snmp_mib_free((void __percpu **)net->mib.udp_statistics); err_udp_mib: - snmp_mib_free((void **)net->mib.net_statistics); + snmp_mib_free((void __percpu **)net->mib.net_statistics); err_net_mib: - snmp_mib_free((void **)net->mib.ip_statistics); + snmp_mib_free((void __percpu **)net->mib.ip_statistics); err_ip_mib: - snmp_mib_free((void **)net->mib.tcp_statistics); + snmp_mib_free((void __percpu **)net->mib.tcp_statistics); err_tcp_mib: return -ENOMEM; } static __net_exit void ipv4_mib_exit_net(struct net *net) { - snmp_mib_free((void **)net->mib.icmpmsg_statistics); - snmp_mib_free((void **)net->mib.icmp_statistics); - snmp_mib_free((void **)net->mib.udplite_statistics); - snmp_mib_free((void **)net->mib.udp_statistics); - snmp_mib_free((void **)net->mib.net_statistics); - snmp_mib_free((void **)net->mib.ip_statistics); - snmp_mib_free((void **)net->mib.tcp_statistics); + snmp_mib_free((void __percpu **)net->mib.icmpmsg_statistics); + snmp_mib_free((void __percpu **)net->mib.icmp_statistics); + snmp_mib_free((void __percpu **)net->mib.udplite_statistics); + snmp_mib_free((void __percpu **)net->mib.udp_statistics); + snmp_mib_free((void __percpu **)net->mib.net_statistics); + snmp_mib_free((void __percpu **)net->mib.ip_statistics); + snmp_mib_free((void __percpu **)net->mib.tcp_statistics); } static __net_initdata struct pernet_operations ipv4_mib_ops = { diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 1b09a6dde7c0..242ed2307370 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -280,7 +280,7 @@ static void icmpmsg_put(struct seq_file *seq) count = 0; for (i = 0; i < ICMPMSG_MIB_MAX; i++) { - val = snmp_fold_field((void **) net->mib.icmpmsg_statistics, i); + val = snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, i); if (val) { type[count] = i; vals[count++] = val; @@ -307,18 +307,18 @@ static void icmp_put(struct seq_file *seq) for (i=0; icmpmibmap[i].name != NULL; i++) seq_printf(seq, " Out%s", icmpmibmap[i].name); seq_printf(seq, "\nIcmp: %lu %lu", - snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), - snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INMSGS), + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_INERRORS)); for (i=0; icmpmibmap[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **) net->mib.icmpmsg_statistics, + snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, icmpmibmap[i].index)); seq_printf(seq, " %lu %lu", - snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS), - snmp_fold_field((void **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS)); + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTMSGS), + snmp_fold_field((void __percpu **) net->mib.icmp_statistics, ICMP_MIB_OUTERRORS)); for (i=0; icmpmibmap[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **) net->mib.icmpmsg_statistics, + snmp_fold_field((void __percpu **) net->mib.icmpmsg_statistics, icmpmibmap[i].index | 0x100)); } @@ -341,7 +341,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) for (i = 0; snmp4_ipstats_list[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.ip_statistics, + snmp_fold_field((void __percpu **)net->mib.ip_statistics, snmp4_ipstats_list[i].entry)); icmp_put(seq); /* RFC 2011 compatibility */ @@ -356,11 +356,11 @@ static int snmp_seq_show(struct seq_file *seq, void *v) /* MaxConn field is signed, RFC 2012 */ if (snmp4_tcp_list[i].entry == TCP_MIB_MAXCONN) seq_printf(seq, " %ld", - snmp_fold_field((void **)net->mib.tcp_statistics, + snmp_fold_field((void __percpu **)net->mib.tcp_statistics, snmp4_tcp_list[i].entry)); else seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.tcp_statistics, + snmp_fold_field((void __percpu **)net->mib.tcp_statistics, snmp4_tcp_list[i].entry)); } @@ -371,7 +371,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) seq_puts(seq, "\nUdp:"); for (i = 0; snmp4_udp_list[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.udp_statistics, + snmp_fold_field((void __percpu **)net->mib.udp_statistics, snmp4_udp_list[i].entry)); /* the UDP and UDP-Lite MIBs are the same */ @@ -382,7 +382,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v) seq_puts(seq, "\nUdpLite:"); for (i = 0; snmp4_udp_list[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.udplite_statistics, + snmp_fold_field((void __percpu **)net->mib.udplite_statistics, snmp4_udp_list[i].entry)); seq_putc(seq, '\n'); @@ -419,7 +419,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) seq_puts(seq, "\nTcpExt:"); for (i = 0; snmp4_net_list[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.net_statistics, + snmp_fold_field((void __percpu **)net->mib.net_statistics, snmp4_net_list[i].entry)); seq_puts(seq, "\nIpExt:"); @@ -429,7 +429,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v) seq_puts(seq, "\nIpExt:"); for (i = 0; snmp4_ipextstats_list[i].name != NULL; i++) seq_printf(seq, " %lu", - snmp_fold_field((void **)net->mib.ip_statistics, + snmp_fold_field((void __percpu **)net->mib.ip_statistics, snmp4_ipextstats_list[i].entry)); seq_putc(seq, '\n'); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b16dfadbe6d6..04762d3bef71 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -3334,7 +3334,7 @@ static __net_initdata struct pernet_operations rt_secret_timer_ops = { #ifdef CONFIG_NET_CLS_ROUTE -struct ip_rt_acct *ip_rt_acct __read_mostly; +struct ip_rt_acct __percpu *ip_rt_acct __read_mostly; #endif /* CONFIG_NET_CLS_ROUTE */ static __initdata unsigned long rhash_entries; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d5d69ea8f249..e471d037fcc9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2788,10 +2788,10 @@ EXPORT_SYMBOL(tcp_gro_complete); #ifdef CONFIG_TCP_MD5SIG static unsigned long tcp_md5sig_users; -static struct tcp_md5sig_pool **tcp_md5sig_pool; +static struct tcp_md5sig_pool * __percpu *tcp_md5sig_pool; static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); -static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) +static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) { int cpu; for_each_possible_cpu(cpu) { @@ -2808,7 +2808,7 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) void tcp_free_md5sig_pool(void) { - struct tcp_md5sig_pool **pool = NULL; + struct tcp_md5sig_pool * __percpu *pool = NULL; spin_lock_bh(&tcp_md5sig_pool_lock); if (--tcp_md5sig_users == 0) { @@ -2822,10 +2822,11 @@ void tcp_free_md5sig_pool(void) EXPORT_SYMBOL(tcp_free_md5sig_pool); -static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(struct sock *sk) +static struct tcp_md5sig_pool * __percpu * +__tcp_alloc_md5sig_pool(struct sock *sk) { int cpu; - struct tcp_md5sig_pool **pool; + struct tcp_md5sig_pool * __percpu *pool; pool = alloc_percpu(struct tcp_md5sig_pool *); if (!pool) @@ -2852,9 +2853,9 @@ out_free: return NULL; } -struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(struct sock *sk) +struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *sk) { - struct tcp_md5sig_pool **pool; + struct tcp_md5sig_pool * __percpu *pool; int alloc = 0; retry: @@ -2873,7 +2874,9 @@ retry: if (alloc) { /* we cannot hold spinlock here because this may sleep. */ - struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(sk); + struct tcp_md5sig_pool * __percpu *p; + + p = __tcp_alloc_md5sig_pool(sk); spin_lock_bh(&tcp_md5sig_pool_lock); if (!p) { tcp_md5sig_users--; @@ -2897,7 +2900,7 @@ EXPORT_SYMBOL(tcp_alloc_md5sig_pool); struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) { - struct tcp_md5sig_pool **p; + struct tcp_md5sig_pool * __percpu *p; spin_lock_bh(&tcp_md5sig_pool_lock); p = tcp_md5sig_pool; if (p) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c79cbff54370..b0d4a4b23db5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -278,31 +278,31 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, static int snmp6_alloc_dev(struct inet6_dev *idev) { - if (snmp_mib_init((void **)idev->stats.ipv6, + if (snmp_mib_init((void __percpu **)idev->stats.ipv6, sizeof(struct ipstats_mib)) < 0) goto err_ip; - if (snmp_mib_init((void **)idev->stats.icmpv6, + if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, sizeof(struct icmpv6_mib)) < 0) goto err_icmp; - if (snmp_mib_init((void **)idev->stats.icmpv6msg, + if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, sizeof(struct icmpv6msg_mib)) < 0) goto err_icmpmsg; return 0; err_icmpmsg: - snmp_mib_free((void **)idev->stats.icmpv6); + snmp_mib_free((void __percpu **)idev->stats.icmpv6); err_icmp: - snmp_mib_free((void **)idev->stats.ipv6); + snmp_mib_free((void __percpu **)idev->stats.ipv6); err_ip: return -ENOMEM; } static void snmp6_free_dev(struct inet6_dev *idev) { - snmp_mib_free((void **)idev->stats.icmpv6msg); - snmp_mib_free((void **)idev->stats.icmpv6); - snmp_mib_free((void **)idev->stats.ipv6); + snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); + snmp_mib_free((void __percpu **)idev->stats.icmpv6); + snmp_mib_free((void __percpu **)idev->stats.ipv6); } /* Nobody refers to this device, we may destroy it. */ @@ -3766,8 +3766,8 @@ static inline size_t inet6_if_nlmsg_size(void) ); } -static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, - int bytes) +static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, + int items, int bytes) { int i; int pad = bytes - sizeof(u64) * items; @@ -3786,10 +3786,10 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, { switch(attrtype) { case IFLA_INET6_STATS: - __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); + __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); break; case IFLA_INET6_ICMP6STATS: - __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); + __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); break; } } diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e29160ff4a0f..37d14e735c27 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -971,41 +971,41 @@ static void ipv6_packet_cleanup(void) static int __net_init ipv6_init_mibs(struct net *net) { - if (snmp_mib_init((void **)net->mib.udp_stats_in6, + if (snmp_mib_init((void __percpu **)net->mib.udp_stats_in6, sizeof (struct udp_mib)) < 0) return -ENOMEM; - if (snmp_mib_init((void **)net->mib.udplite_stats_in6, + if (snmp_mib_init((void __percpu **)net->mib.udplite_stats_in6, sizeof (struct udp_mib)) < 0) goto err_udplite_mib; - if (snmp_mib_init((void **)net->mib.ipv6_statistics, + if (snmp_mib_init((void __percpu **)net->mib.ipv6_statistics, sizeof(struct ipstats_mib)) < 0) goto err_ip_mib; - if (snmp_mib_init((void **)net->mib.icmpv6_statistics, + if (snmp_mib_init((void __percpu **)net->mib.icmpv6_statistics, sizeof(struct icmpv6_mib)) < 0) goto err_icmp_mib; - if (snmp_mib_init((void **)net->mib.icmpv6msg_statistics, + if (snmp_mib_init((void __percpu **)net->mib.icmpv6msg_statistics, sizeof(struct icmpv6msg_mib)) < 0) goto err_icmpmsg_mib; return 0; err_icmpmsg_mib: - snmp_mib_free((void **)net->mib.icmpv6_statistics); + snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); err_icmp_mib: - snmp_mib_free((void **)net->mib.ipv6_statistics); + snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); err_ip_mib: - snmp_mib_free((void **)net->mib.udplite_stats_in6); + snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); err_udplite_mib: - snmp_mib_free((void **)net->mib.udp_stats_in6); + snmp_mib_free((void __percpu **)net->mib.udp_stats_in6); return -ENOMEM; } static void ipv6_cleanup_mibs(struct net *net) { - snmp_mib_free((void **)net->mib.udp_stats_in6); - snmp_mib_free((void **)net->mib.udplite_stats_in6); - snmp_mib_free((void **)net->mib.ipv6_statistics); - snmp_mib_free((void **)net->mib.icmpv6_statistics); - snmp_mib_free((void **)net->mib.icmpv6msg_statistics); + snmp_mib_free((void __percpu **)net->mib.udp_stats_in6); + snmp_mib_free((void __percpu **)net->mib.udplite_stats_in6); + snmp_mib_free((void __percpu **)net->mib.ipv6_statistics); + snmp_mib_free((void __percpu **)net->mib.icmpv6_statistics); + snmp_mib_free((void __percpu **)net->mib.icmpv6msg_statistics); } static int __net_init inet6_net_init(struct net *net) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index bfe2598dd563..58344c0fbd13 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -136,7 +136,7 @@ static const struct snmp_mib snmp6_udplite6_list[] = { SNMP_MIB_SENTINEL }; -static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) +static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) { char name[32]; int i; @@ -170,7 +170,7 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void **mib) return; } -static void snmp6_seq_show_item(struct seq_file *seq, void **mib, +static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, const struct snmp_mib *itemlist) { int i; @@ -183,14 +183,15 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) { struct net *net = (struct net *)seq->private; - snmp6_seq_show_item(seq, (void **)net->mib.ipv6_statistics, + snmp6_seq_show_item(seq, (void __percpu **)net->mib.ipv6_statistics, snmp6_ipstats_list); - snmp6_seq_show_item(seq, (void **)net->mib.icmpv6_statistics, + snmp6_seq_show_item(seq, (void __percpu **)net->mib.icmpv6_statistics, snmp6_icmp6_list); - snmp6_seq_show_icmpv6msg(seq, (void **)net->mib.icmpv6msg_statistics); - snmp6_seq_show_item(seq, (void **)net->mib.udp_stats_in6, + snmp6_seq_show_icmpv6msg(seq, + (void __percpu **)net->mib.icmpv6msg_statistics); + snmp6_seq_show_item(seq, (void __percpu **)net->mib.udp_stats_in6, snmp6_udp6_list); - snmp6_seq_show_item(seq, (void **)net->mib.udplite_stats_in6, + snmp6_seq_show_item(seq, (void __percpu **)net->mib.udplite_stats_in6, snmp6_udplite6_list); return 0; } @@ -213,9 +214,11 @@ static int snmp6_dev_seq_show(struct seq_file *seq, void *v) struct inet6_dev *idev = (struct inet6_dev *)seq->private; seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); - snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); - snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); - snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg); + snmp6_seq_show_item(seq, (void __percpu **)idev->stats.ipv6, + snmp6_ipstats_list); + snmp6_seq_show_item(seq, (void __percpu **)idev->stats.icmpv6, + snmp6_icmp6_list); + snmp6_seq_show_icmpv6msg(seq, (void __percpu **)idev->stats.icmpv6msg); return 0; } diff --git a/net/sctp/proc.c b/net/sctp/proc.c index a5ac6e0a8d9c..784bcc9a979d 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -83,7 +83,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v) for (i = 0; sctp_snmp_list[i].name != NULL; i++) seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, - snmp_fold_field((void **)sctp_statistics, + snmp_fold_field((void __percpu **)sctp_statistics, sctp_snmp_list[i].entry)); return 0; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a3c8988758b1..9687177b026b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -996,12 +996,13 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family) static inline int init_sctp_mibs(void) { - return snmp_mib_init((void**)sctp_statistics, sizeof(struct sctp_mib)); + return snmp_mib_init((void __percpu **)sctp_statistics, + sizeof(struct sctp_mib)); } static inline void cleanup_sctp_mibs(void) { - snmp_mib_free((void**)sctp_statistics); + snmp_mib_free((void __percpu **)sctp_statistics); } static void sctp_v4_pf_init(void) diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c index 42cd18391f46..0fc5ff66d1fa 100644 --- a/net/xfrm/xfrm_ipcomp.c +++ b/net/xfrm/xfrm_ipcomp.c @@ -30,12 +30,12 @@ struct ipcomp_tfms { struct list_head list; - struct crypto_comp **tfms; + struct crypto_comp * __percpu *tfms; int users; }; static DEFINE_MUTEX(ipcomp_resource_mutex); -static void **ipcomp_scratches; +static void * __percpu *ipcomp_scratches; static int ipcomp_scratch_users; static LIST_HEAD(ipcomp_tfms_list); @@ -200,7 +200,7 @@ EXPORT_SYMBOL_GPL(ipcomp_output); static void ipcomp_free_scratches(void) { int i; - void **scratches; + void * __percpu *scratches; if (--ipcomp_scratch_users) return; @@ -215,10 +215,10 @@ static void ipcomp_free_scratches(void) free_percpu(scratches); } -static void **ipcomp_alloc_scratches(void) +static void * __percpu *ipcomp_alloc_scratches(void) { int i; - void **scratches; + void * __percpu *scratches; if (ipcomp_scratch_users++) return ipcomp_scratches; @@ -239,7 +239,7 @@ static void **ipcomp_alloc_scratches(void) return scratches; } -static void ipcomp_free_tfms(struct crypto_comp **tfms) +static void ipcomp_free_tfms(struct crypto_comp * __percpu *tfms) { struct ipcomp_tfms *pos; int cpu; @@ -267,10 +267,10 @@ static void ipcomp_free_tfms(struct crypto_comp **tfms) free_percpu(tfms); } -static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name) +static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name) { struct ipcomp_tfms *pos; - struct crypto_comp **tfms; + struct crypto_comp * __percpu *tfms; int cpu; /* This can be any valid CPU ID so we don't need locking. */ diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index eb870fcc29cc..cfceb6616ec1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2428,19 +2428,19 @@ static int __net_init xfrm_statistics_init(struct net *net) { int rv; - if (snmp_mib_init((void **)net->mib.xfrm_statistics, + if (snmp_mib_init((void __percpu **)net->mib.xfrm_statistics, sizeof(struct linux_xfrm_mib)) < 0) return -ENOMEM; rv = xfrm_proc_init(net); if (rv < 0) - snmp_mib_free((void **)net->mib.xfrm_statistics); + snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); return rv; } static void xfrm_statistics_fini(struct net *net) { xfrm_proc_fini(net); - snmp_mib_free((void **)net->mib.xfrm_statistics); + snmp_mib_free((void __percpu **)net->mib.xfrm_statistics); } #else static int __net_init xfrm_statistics_init(struct net *net) diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index c083a4e4e796..003f2c437ac3 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -50,7 +50,8 @@ static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) int i; for (i=0; xfrm_mib_list[i].name; i++) seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, - snmp_fold_field((void **)net->mib.xfrm_statistics, + snmp_fold_field((void __percpu **) + net->mib.xfrm_statistics, xfrm_mib_list[i].entry)); return 0; } -- cgit v1.2.3 From 47d742752df4c1088589d4424840bc761613ab2a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 16 Feb 2010 15:21:08 +0000 Subject: percpu: add __percpu sparse annotations to net drivers Add __percpu sparse annotations to net drivers. These annotations are to make sparse consider percpu variables to be in a different address space and warn if accessed without going through percpu accessors. This patch doesn't affect normal builds. Signed-off-by: Tejun Heo Acked-by: David S. Miller Cc: Eric Dumazet Cc: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/chelsio/sge.c | 2 +- drivers/net/loopback.c | 16 +++++++++------- drivers/net/veth.c | 4 ++-- include/linux/if_macvlan.h | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 109d2783e4d8..8e12505ac3aa 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -267,7 +267,7 @@ struct sge { struct sk_buff *espibug_skb[MAX_NPORTS]; u32 sge_control; /* shadow value of sge control reg */ struct sge_intr_counts stats; - struct sge_port_stats *port_stats[MAX_NPORTS]; + struct sge_port_stats __percpu *port_stats[MAX_NPORTS]; struct sched *tx_sched; struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp; }; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index b9fcc9819837..72b7949c91b1 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -72,7 +72,8 @@ struct pcpu_lstats { static netdev_tx_t loopback_xmit(struct sk_buff *skb, struct net_device *dev) { - struct pcpu_lstats *pcpu_lstats, *lb_stats; + struct pcpu_lstats __percpu *pcpu_lstats; + struct pcpu_lstats *lb_stats; int len; skb_orphan(skb); @@ -80,7 +81,7 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ - pcpu_lstats = dev->ml_priv; + pcpu_lstats = (void __percpu __force *)dev->ml_priv; lb_stats = this_cpu_ptr(pcpu_lstats); len = skb->len; @@ -95,14 +96,14 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, static struct net_device_stats *loopback_get_stats(struct net_device *dev) { - const struct pcpu_lstats *pcpu_lstats; + const struct pcpu_lstats __percpu *pcpu_lstats; struct net_device_stats *stats = &dev->stats; unsigned long bytes = 0; unsigned long packets = 0; unsigned long drops = 0; int i; - pcpu_lstats = dev->ml_priv; + pcpu_lstats = (void __percpu __force *)dev->ml_priv; for_each_possible_cpu(i) { const struct pcpu_lstats *lb_stats; @@ -135,19 +136,20 @@ static const struct ethtool_ops loopback_ethtool_ops = { static int loopback_dev_init(struct net_device *dev) { - struct pcpu_lstats *lstats; + struct pcpu_lstats __percpu *lstats; lstats = alloc_percpu(struct pcpu_lstats); if (!lstats) return -ENOMEM; - dev->ml_priv = lstats; + dev->ml_priv = (void __force *)lstats; return 0; } static void loopback_dev_free(struct net_device *dev) { - struct pcpu_lstats *lstats = dev->ml_priv; + struct pcpu_lstats __percpu *lstats = + (void __percpu __force *)dev->ml_priv; free_percpu(lstats); free_netdev(dev); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 3a15de56df9c..35609e64f6fd 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -34,7 +34,7 @@ struct veth_net_stats { struct veth_priv { struct net_device *peer; - struct veth_net_stats *stats; + struct veth_net_stats __percpu *stats; unsigned ip_summed; }; @@ -263,7 +263,7 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu) static int veth_dev_init(struct net_device *dev) { - struct veth_net_stats *stats; + struct veth_net_stats __percpu *stats; struct veth_priv *priv; stats = alloc_percpu(struct veth_net_stats); diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 51f1512045e9..f9cb9ba1475d 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -30,7 +30,7 @@ struct macvlan_dev { struct hlist_node hlist; struct macvlan_port *port; struct net_device *lowerdev; - struct macvlan_rx_stats *rx_stats; + struct macvlan_rx_stats __percpu *rx_stats; enum macvlan_mode mode; int (*receive)(struct sk_buff *skb); int (*forward)(struct net_device *dev, struct sk_buff *skb); -- cgit v1.2.3 From f6ca057f1bfe251d944505fc5ba4df3762802539 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Fri, 12 Feb 2010 10:11:54 +0000 Subject: b44: Ratelimit timeout error message. Signed-off-by: Jochen Friedrich Signed-off-by: David S. Miller --- drivers/net/b44.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 9091c6574b1c..f21cbe63c7b1 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -189,11 +189,13 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg, udelay(10); } if (i == timeout) { - printk(KERN_ERR PFX "%s: BUG! Timeout waiting for bit %08x of register " - "%lx to %s.\n", - bp->dev->name, - bit, reg, - (clear ? "clear" : "set")); + if (net_ratelimit()) + printk(KERN_ERR PFX "%s: BUG! Timeout waiting for bit " + "%08x of register " + "%lx to %s.\n", + bp->dev->name, + bit, reg, + (clear ? "clear" : "set")); return -ENODEV; } return 0; -- cgit v1.2.3 From dc4c2c31053ba5bf685d273cd62ecca406dddb2d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 12 Feb 2010 11:41:39 +0000 Subject: net: remove INIT_RCU_HEAD() usage call_rcu() will unconditionally reinitialize RCU head anyway. Signed-off-by: Alexey Dobriyan Acked-by: Paul E. McKenney Signed-off-by: David S. Miller --- net/core/drop_monitor.c | 1 - net/ipv6/sit.c | 1 - net/ipv6/xfrm6_tunnel.c | 1 - net/netlabel/netlabel_domainhash.c | 1 - net/netlabel/netlabel_unlabeled.c | 3 --- net/sctp/bind_addr.c | 1 - net/sctp/ipv6.c | 1 - net/sctp/protocol.c | 1 - 8 files changed, 10 deletions(-) diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b8e9d3a86887..f8c874975350 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -296,7 +296,6 @@ static int dropmon_net_event(struct notifier_block *ev_block, new_stat->dev = dev; new_stat->last_rx = jiffies; - INIT_RCU_HEAD(&new_stat->rcu); spin_lock(&trace_state_lock); list_add_rcu(&new_stat->list, &hw_stats_list); spin_unlock(&trace_state_lock); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 52ffd29cb93f..96eb2d4641c4 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -363,7 +363,6 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) goto out; } - INIT_RCU_HEAD(&p->rcu_head); p->next = t->prl; p->addr = a->addr; p->flags = a->flags; diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index ddce21e3459b..fa85a7d22dc4 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c @@ -161,7 +161,6 @@ alloc_spi: if (!x6spi) goto out; - INIT_RCU_HEAD(&x6spi->rcu_head); memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr)); x6spi->spi = spi; atomic_set(&x6spi->refcnt, 1); diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index c5d9f97ef217..0bfeaab88ef5 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -315,7 +315,6 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, entry_old = netlbl_domhsh_search_def(entry->domain); if (entry_old == NULL) { entry->valid = 1; - INIT_RCU_HEAD(&entry->rcu); if (entry->domain != NULL) { u32 bkt = netlbl_domhsh_hash(entry->domain); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 98ed22ee2ff4..852d9d7976b9 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -327,7 +327,6 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, entry->list.addr = addr->s_addr & mask->s_addr; entry->list.mask = mask->s_addr; entry->list.valid = 1; - INIT_RCU_HEAD(&entry->rcu); entry->secid = secid; spin_lock(&netlbl_unlhsh_lock); @@ -373,7 +372,6 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; ipv6_addr_copy(&entry->list.mask, mask); entry->list.valid = 1; - INIT_RCU_HEAD(&entry->rcu); entry->secid = secid; spin_lock(&netlbl_unlhsh_lock); @@ -410,7 +408,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) INIT_LIST_HEAD(&iface->addr4_list); INIT_LIST_HEAD(&iface->addr6_list); iface->valid = 1; - INIT_RCU_HEAD(&iface->rcu); spin_lock(&netlbl_unlhsh_lock); if (ifindex > 0) { diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 13a6fba41077..bef133731683 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -186,7 +186,6 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, addr->valid = 1; INIT_LIST_HEAD(&addr->list); - INIT_RCU_HEAD(&addr->rcu); /* We always hold a socket lock when calling this function, * and that acts as a writer synchronizing lock. diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index cc50fbe99291..1d7ac70ba39f 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -381,7 +381,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, addr->a.v6.sin6_scope_id = dev->ifindex; addr->valid = 1; INIT_LIST_HEAD(&addr->list); - INIT_RCU_HEAD(&addr->rcu); list_add_tail(&addr->list, addrlist); } } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 9687177b026b..e771690f6d5d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -188,7 +188,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, addr->a.v4.sin_addr.s_addr = ifa->ifa_local; addr->valid = 1; INIT_LIST_HEAD(&addr->list); - INIT_RCU_HEAD(&addr->rcu); list_add_tail(&addr->list, addrlist); } } -- cgit v1.2.3 From 9874c41cd5e70bfc97bcd52a8b6c98c2a6ba7299 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 16 Feb 2010 18:40:04 +0000 Subject: ipv6.h: reassembly: replace calculated magic number with multiplication On Tue, 2010-02-16 at 16:47 +0100, Patrick McHardy wrote: > Joe Perches wrote: > >> @@ -246,6 +246,8 @@ extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); > >> int ip6_frag_nqueues(struct net *net); > >> int ip6_frag_mem(struct net *net); > >> > >> +#define IPV6_FRAG_HIGH_THRESH 262144 /* == 256*1024 */ > >> +#define IPV6_FRAG_LOW_THRESH 196608 /* == 192*1024 */ > >> #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ > > > > 196608 isn't a number I want to remember. > > Is this better as: > > > > #define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */ > > #define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */ > > Please send a patch, I'll apply it once these patches are in Dave's > tree. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- include/net/ipv6.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 639ec53ea081..d067db1f88c7 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -246,9 +246,9 @@ extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); int ip6_frag_nqueues(struct net *net); int ip6_frag_mem(struct net *net); -#define IPV6_FRAG_HIGH_THRESH 262144 /* == 256*1024 */ -#define IPV6_FRAG_LOW_THRESH 196608 /* == 192*1024 */ -#define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ +#define IPV6_FRAG_HIGH_THRESH (256 * 1024) /* 262144 */ +#define IPV6_FRAG_LOW_THRESH (192 * 1024) /* 196608 */ +#define IPV6_FRAG_TIMEOUT (60 * HZ) /* 60 seconds */ extern int __ipv6_addr_type(const struct in6_addr *addr); static inline int ipv6_addr_type(const struct in6_addr *addr) -- cgit v1.2.3 From 26b39276ca5ff4dbf3c07704e34fd820fd97decf Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 17 Feb 2010 01:00:41 +0000 Subject: igb: remove unecessary q_vector declarations and remove itr_shift This change removes the use of itr_shift since a mac type call can be used just as easily to identify the only HW that needs to have the itr shifted. In addition it removes two unecessary declarations of a q_vector pointer from the initialization path. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 1 - drivers/net/igb/igb_main.c | 25 +++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 83ea11701f45..0efd28515e6e 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -176,7 +176,6 @@ struct igb_q_vector { u16 itr_val; u8 set_itr; - u8 itr_shift; void __iomem *itr_register; char name[IFNAMSIZ + 9]; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 4fe7b0ba6310..677b5f5ab49c 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -504,6 +504,12 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) BUG(); break; } + + /* add q_vector eims value to global eims_enable_mask */ + adapter->eims_enable_mask |= q_vector->eims_value; + + /* configure q_vector to set itr on first interrupt */ + q_vector->set_itr = 1; } /** @@ -561,11 +567,8 @@ static void igb_configure_msix(struct igb_adapter *adapter) adapter->eims_enable_mask |= adapter->eims_other; - for (i = 0; i < adapter->num_q_vectors; i++) { - struct igb_q_vector *q_vector = adapter->q_vector[i]; - igb_assign_vector(q_vector, vector++); - adapter->eims_enable_mask |= q_vector->eims_value; - } + for (i = 0; i < adapter->num_q_vectors; i++) + igb_assign_vector(adapter->q_vector[i], vector++); wrfl(); } @@ -756,10 +759,8 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) if (!q_vector) goto err_out; q_vector->adapter = adapter; - q_vector->itr_shift = (hw->mac.type == e1000_82575) ? 16 : 0; q_vector->itr_register = hw->hw_addr + E1000_EITR(0); q_vector->itr_val = IGB_START_ITR; - q_vector->set_itr = 1; netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64); adapter->q_vector[v_idx] = q_vector; } @@ -4142,6 +4143,7 @@ static irqreturn_t igb_msix_other(int irq, void *data) static void igb_write_itr(struct igb_q_vector *q_vector) { + struct igb_adapter *adapter = q_vector->adapter; u32 itr_val = q_vector->itr_val & 0x7FFC; if (!q_vector->set_itr) @@ -4150,8 +4152,8 @@ static void igb_write_itr(struct igb_q_vector *q_vector) if (!itr_val) itr_val = 0x4; - if (q_vector->itr_shift) - itr_val |= itr_val << q_vector->itr_shift; + if (adapter->hw.mac.type == e1000_82575) + itr_val |= itr_val << 16; else itr_val |= 0x8000000; @@ -4228,9 +4230,8 @@ static void igb_setup_dca(struct igb_adapter *adapter) wr32(E1000_DCA_CTRL, E1000_DCA_CTRL_DCA_MODE_CB2); for (i = 0; i < adapter->num_q_vectors; i++) { - struct igb_q_vector *q_vector = adapter->q_vector[i]; - q_vector->cpu = -1; - igb_update_dca(q_vector); + adapter->q_vector[i]->cpu = -1; + igb_update_dca(adapter->q_vector[i]); } } -- cgit v1.2.3 From 22939f0606e515799d83e1a29250917f94c8d07b Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:01:01 +0000 Subject: igb: add support for wake-on-link This adds support for wake-on-link/phy activity to the ethtool interface. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index f771a6c08777..145a8eb55fab 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1812,7 +1812,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct igb_adapter *adapter = netdev_priv(netdev); wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC; + WAKE_BCAST | WAKE_MAGIC | + WAKE_PHY; wol->wolopts = 0; /* this function will set ->supported = 0 and return 1 if wol is not @@ -1835,15 +1836,15 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) wol->wolopts |= WAKE_BCAST; if (adapter->wol & E1000_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; - - return; + if (adapter->wol & E1000_WUFC_LNKC) + wol->wolopts |= WAKE_PHY; } static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct igb_adapter *adapter = netdev_priv(netdev); - if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) + if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; if (igb_wol_exclusion(adapter, wol) || @@ -1861,6 +1862,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) adapter->wol |= E1000_WUFC_BC; if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; + if (wol->wolopts & WAKE_PHY) + adapter->wol |= E1000_WUFC_LNKC; device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); return 0; -- cgit v1.2.3 From 3145535ac6e4769e587a38a67d888a10f24a7af9 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:01:21 +0000 Subject: igb: Report link status in ethtool when interface is down With this change ethtool will correctly report link status when the interface is down. Currently ethtool reports the link as not detected when the interface is down. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 1 + drivers/net/igb/igb_ethtool.c | 20 +++++++++++++++++++- drivers/net/igb/igb_main.c | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 0efd28515e6e..452a4dee87f8 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -356,6 +356,7 @@ extern void igb_unmap_and_free_tx_resource(struct igb_ring *, struct igb_buffer *); extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int); extern void igb_update_stats(struct igb_adapter *); +extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); static inline s32 igb_reset_phy(struct e1000_hw *hw) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 145a8eb55fab..4eea03b428c4 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -234,6 +234,24 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return 0; } +static u32 igb_get_link(struct net_device *netdev) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct e1000_mac_info *mac = &adapter->hw.mac; + + /* + * If the link is not reported up to netdev, interrupts are disabled, + * and so the physical link state may have changed since we last + * looked. Set get_link_status to make sure that the true link + * state is interrogated, rather than pulling a cached and possibly + * stale link state from the driver. + */ + if (!netif_carrier_ok(netdev)) + mac->get_link_status = 1; + + return igb_has_link(adapter); +} + static void igb_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { @@ -2077,7 +2095,7 @@ static const struct ethtool_ops igb_ethtool_ops = { .get_msglevel = igb_get_msglevel, .set_msglevel = igb_set_msglevel, .nway_reset = igb_nway_reset, - .get_link = ethtool_op_get_link, + .get_link = igb_get_link, .get_eeprom_len = igb_get_eeprom_len, .get_eeprom = igb_get_eeprom, .set_eeprom = igb_set_eeprom, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 677b5f5ab49c..e40319e2ec25 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3020,7 +3020,7 @@ static void igb_update_phy_info(unsigned long data) * igb_has_link - check shared code for link and determine up/down * @adapter: pointer to driver private info **/ -static bool igb_has_link(struct igb_adapter *adapter) +bool igb_has_link(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; bool link_active = false; -- cgit v1.2.3 From 53c992fa8497286f24f279ebec5a8c7a58d4e68c Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:01:40 +0000 Subject: igb: ignore EEPROM APME check when shutting down serdes link Checking the EEPROM APME state unnecessarily prevents the link from shutting down. The standard power down routines should be sufficient to determine whether the serdes link can power down when going into D3. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index c505b50d1fa3..59817bcc7169 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -791,27 +791,12 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed, void igb_shutdown_serdes_link_82575(struct e1000_hw *hw) { u32 reg; - u16 eeprom_data = 0; - if (hw->phy.media_type != e1000_media_type_internal_serdes || + if (hw->phy.media_type != e1000_media_type_internal_serdes && igb_sgmii_active_82575(hw)) return; - if (hw->bus.func == E1000_FUNC_0) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - else if (hw->mac.type == e1000_82580) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + - NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, - &eeprom_data); - else if (hw->bus.func == E1000_FUNC_1) - hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - - /* - * If APM is not enabled in the EEPROM and management interface is - * not enabled, then power down. - */ - if (!(eeprom_data & E1000_NVM_APME_82575) && - !igb_enable_mng_pass_thru(hw)) { + if (!igb_enable_mng_pass_thru(hw)) { /* Disable PCS to turn off link */ reg = rd32(E1000_PCS_CFG0); reg &= ~E1000_PCS_CFG_PCS_EN; @@ -826,8 +811,6 @@ void igb_shutdown_serdes_link_82575(struct e1000_hw *hw) wrfl(); msleep(1); } - - return; } /** -- cgit v1.2.3 From 88a268c1a11a2e94b7c55a8cfe97892d845887c8 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:01:59 +0000 Subject: igb: Power down link when interface is down This changes the behavior of the driver to power down the link when the associated interface is down, unless management is enabled. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_82575.c | 44 +++++++++++++++++++++++++++++++++++++++++ drivers/net/igb/e1000_82575.h | 2 ++ drivers/net/igb/e1000_defines.h | 1 + drivers/net/igb/e1000_phy.c | 35 ++++++++++++++++++++++++++++++++ drivers/net/igb/e1000_phy.h | 2 ++ drivers/net/igb/igb.h | 1 + drivers/net/igb/igb_ethtool.c | 16 ++++++++++++--- drivers/net/igb/igb_main.c | 39 ++++++++++++++++++++++++++++-------- 8 files changed, 129 insertions(+), 11 deletions(-) diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index 59817bcc7169..9d7fa2fb85ea 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -726,6 +726,34 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw) return ret_val; } +/** + * igb_power_up_serdes_link_82575 - Power up the serdes link after shutdown + * @hw: pointer to the HW structure + **/ +void igb_power_up_serdes_link_82575(struct e1000_hw *hw) +{ + u32 reg; + + + if ((hw->phy.media_type != e1000_media_type_internal_serdes) && + !igb_sgmii_active_82575(hw)) + return; + + /* Enable PCS to turn on link */ + reg = rd32(E1000_PCS_CFG0); + reg |= E1000_PCS_CFG_PCS_EN; + wr32(E1000_PCS_CFG0, reg); + + /* Power up the laser */ + reg = rd32(E1000_CTRL_EXT); + reg &= ~E1000_CTRL_EXT_SDP3_DATA; + wr32(E1000_CTRL_EXT, reg); + + /* flush the write to verify completion */ + wrfl(); + msleep(1); +} + /** * igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex * @hw: pointer to the HW structure @@ -1165,6 +1193,22 @@ out: return ret_val; } +/** + * igb_power_down_phy_copper_82575 - Remove link during PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, or wake on lan is not enabled, remove the link. + **/ +void igb_power_down_phy_copper_82575(struct e1000_hw *hw) +{ + /* If the management interface is not enabled, then power down */ + if (!(igb_enable_mng_pass_thru(hw) || igb_check_reset_block(hw))) + igb_power_down_phy_copper(hw); + + return; +} + /** * igb_clear_hw_cntrs_82575 - Clear device specific hardware counters * @hw: pointer to the HW structure diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h index bb53083ec61f..fbe1c99c193c 100644 --- a/drivers/net/igb/e1000_82575.h +++ b/drivers/net/igb/e1000_82575.h @@ -29,6 +29,8 @@ #define _E1000_82575_H_ extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); +extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw); +extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw); extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); #define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index 6e036ae3138f..c01715070764 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -481,6 +481,7 @@ /* PHY Control Register */ #define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ #define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ #define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ #define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ #define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c index 3670a66401b8..cf1f32300923 100644 --- a/drivers/net/igb/e1000_phy.c +++ b/drivers/net/igb/e1000_phy.c @@ -1930,6 +1930,41 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw) return 0; } +/** + * igb_power_up_phy_copper - Restore copper link in case of PHY power down + * @hw: pointer to the HW structure + * + * In the case of a PHY power down to save power, or to turn off link during a + * driver unload, restore the link to previous settings. + **/ +void igb_power_up_phy_copper(struct e1000_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg &= ~MII_CR_POWER_DOWN; + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); +} + +/** + * igb_power_down_phy_copper - Power down copper PHY + * @hw: pointer to the HW structure + * + * Power down PHY to save power when interface is down and wake on lan + * is not enabled. + **/ +void igb_power_down_phy_copper(struct e1000_hw *hw) +{ + u16 mii_reg = 0; + + /* The PHY will retain its settings across a power down/up cycle */ + hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); + mii_reg |= MII_CR_POWER_DOWN; + hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); + msleep(1); +} + /** * igb_check_polarity_82580 - Checks the polarity. * @hw: pointer to the HW structure diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h index 555eb54bb6ed..565a6dbb3714 100644 --- a/drivers/net/igb/e1000_phy.h +++ b/drivers/net/igb/e1000_phy.h @@ -60,6 +60,8 @@ s32 igb_setup_copper_link(struct e1000_hw *hw); s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, u32 usec_interval, bool *success); +void igb_power_up_phy_copper(struct e1000_hw *hw); +void igb_power_down_phy_copper(struct e1000_hw *hw); s32 igb_phy_init_script_igp3(struct e1000_hw *hw); s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 452a4dee87f8..0e0800dc801d 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -358,6 +358,7 @@ extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int); extern void igb_update_stats(struct igb_adapter *); extern bool igb_has_link(struct igb_adapter *adapter); extern void igb_set_ethtool_ops(struct net_device *); +extern void igb_power_up_link(struct igb_adapter *); static inline s32 igb_reset_phy(struct e1000_hw *hw) { diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 4eea03b428c4..485288303f32 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1722,6 +1722,9 @@ static void igb_diag_test(struct net_device *netdev, dev_info(&adapter->pdev->dev, "offline testing starting\n"); + /* power up link for link test */ + igb_power_up_link(adapter); + /* Link test performed before hardware reset so autoneg doesn't * interfere with test result */ if (igb_link_test(adapter, &data[4])) @@ -1745,6 +1748,8 @@ static void igb_diag_test(struct net_device *netdev, eth_test->flags |= ETH_TEST_FL_FAILED; igb_reset(adapter); + /* power up link for loopback test */ + igb_power_up_link(adapter); if (igb_loopback_test(adapter, &data[3])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1763,9 +1768,14 @@ static void igb_diag_test(struct net_device *netdev, dev_open(netdev); } else { dev_info(&adapter->pdev->dev, "online testing starting\n"); - /* Online tests */ - if (igb_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; + + /* PHY is powered down when interface is down */ + if (!netif_carrier_ok(netdev)) { + data[4] = 0; + } else { + if (igb_link_test(adapter, &data[4])) + eth_test->flags |= ETH_TEST_FL_FAILED; + } /* Online tests aren't run; pass by default */ data[0] = 0; diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e40319e2ec25..0427e7c10295 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1114,6 +1114,29 @@ static void igb_configure(struct igb_adapter *adapter) adapter->tx_queue_len = netdev->tx_queue_len; } +/** + * igb_power_up_link - Power up the phy/serdes link + * @adapter: address of board private structure + **/ +void igb_power_up_link(struct igb_adapter *adapter) +{ + if (adapter->hw.phy.media_type == e1000_media_type_copper) + igb_power_up_phy_copper(&adapter->hw); + else + igb_power_up_serdes_link_82575(&adapter->hw); +} + +/** + * igb_power_down_link - Power down the phy/serdes link + * @adapter: address of board private structure + */ +static void igb_power_down_link(struct igb_adapter *adapter) +{ + if (adapter->hw.phy.media_type == e1000_media_type_copper) + igb_power_down_phy_copper_82575(&adapter->hw); + else + igb_shutdown_serdes_link_82575(&adapter->hw); +} /** * igb_up - Open the interface and prepare it to handle traffic @@ -1335,6 +1358,9 @@ void igb_reset(struct igb_adapter *adapter) wr32(E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); } + if (!netif_running(adapter->netdev)) + igb_power_down_link(adapter); + igb_update_mng_vlan(adapter); /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ @@ -1717,9 +1743,6 @@ static void __devexit igb_remove(struct pci_dev *pdev) unregister_netdev(netdev); - if (!igb_check_reset_block(hw)) - igb_reset_phy(hw); - igb_clear_interrupt_scheme(adapter); #ifdef CONFIG_PCI_IOV @@ -1995,7 +2018,7 @@ static int igb_open(struct net_device *netdev) if (err) goto err_setup_rx; - /* e1000_power_up_phy(adapter); */ + igb_power_up_link(adapter); /* before we allocate an interrupt, we must be ready to handle it. * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt @@ -2037,7 +2060,7 @@ static int igb_open(struct net_device *netdev) err_req_irq: igb_release_hw_control(adapter); - /* e1000_power_down_phy(adapter); */ + igb_power_down_link(adapter); igb_free_all_rx_resources(adapter); err_setup_rx: igb_free_all_tx_resources(adapter); @@ -5820,7 +5843,9 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) *enable_wake = wufc || adapter->en_mng_pt; if (!*enable_wake) - igb_shutdown_serdes_link_82575(hw); + igb_power_down_link(adapter); + else + igb_power_up_link(adapter); /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ @@ -5877,8 +5902,6 @@ static int igb_resume(struct pci_dev *pdev) return -ENOMEM; } - /* e1000_power_up_phy(adapter); */ - igb_reset(adapter); /* let the f/w know that the h/w is now under the control of the -- cgit v1.2.3 From b94f2d775a71ed09dc8ca2bf24c611bdce9e82e7 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:02:19 +0000 Subject: igb: call pci_save_state after pci_restore_state This patch adds calls to pci_save_state() immediately after calls to pci_restore_state(). Due to a change in the behavior of pci_restore_state() it is necessary to call pci_save_state() to keep the state_saved flag. This patch is based on a similar patch for ixgbe. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0427e7c10295..089a7c3f4c69 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -5885,6 +5885,7 @@ static int igb_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); + pci_save_state(pdev); err = pci_enable_device_mem(pdev); if (err) { @@ -6010,6 +6011,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) } else { pci_set_master(pdev); pci_restore_state(pdev); + pci_save_state(pdev); pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); -- cgit v1.2.3 From 3025a446b6d0255ae4399ca5f9b259bd1b51539e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 17 Feb 2010 01:02:39 +0000 Subject: igb: Allocate rings seperately instead of as a block This change makes it so that the rings are allocated seperately. As a result we can allocate them on seperate nodes at some point in the future if we so desire. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 5 +- drivers/net/igb/igb_ethtool.c | 46 +++++++++-------- drivers/net/igb/igb_main.c | 113 +++++++++++++++++++++--------------------- 3 files changed, 83 insertions(+), 81 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 0e0800dc801d..8f07bc0a1d4c 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -240,7 +240,6 @@ static inline int igb_desc_unused(struct igb_ring *ring) } /* board specific private data structure */ - struct igb_adapter { struct timer_list watchdog_timer; struct timer_list phy_info_timer; @@ -266,12 +265,12 @@ struct igb_adapter { unsigned long led_status; /* TX */ - struct igb_ring *tx_ring; /* One per active queue */ + struct igb_ring *tx_ring[16]; unsigned long tx_queue_len; u32 tx_timeout_count; /* RX */ - struct igb_ring *rx_ring; /* One per active queue */ + struct igb_ring *rx_ring[16]; int num_tx_queues; int num_rx_queues; diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 485288303f32..a4cead12fd98 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -314,7 +314,7 @@ static int igb_set_pauseparam(struct net_device *netdev, static u32 igb_get_rx_csum(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); - return !!(adapter->rx_ring[0].flags & IGB_RING_FLAG_RX_CSUM); + return !!(adapter->rx_ring[0]->flags & IGB_RING_FLAG_RX_CSUM); } static int igb_set_rx_csum(struct net_device *netdev, u32 data) @@ -324,9 +324,9 @@ static int igb_set_rx_csum(struct net_device *netdev, u32 data) for (i = 0; i < adapter->num_rx_queues; i++) { if (data) - adapter->rx_ring[i].flags |= IGB_RING_FLAG_RX_CSUM; + adapter->rx_ring[i]->flags |= IGB_RING_FLAG_RX_CSUM; else - adapter->rx_ring[i].flags &= ~IGB_RING_FLAG_RX_CSUM; + adapter->rx_ring[i]->flags &= ~IGB_RING_FLAG_RX_CSUM; } return 0; @@ -789,9 +789,9 @@ static int igb_set_ringparam(struct net_device *netdev, if (!netif_running(adapter->netdev)) { for (i = 0; i < adapter->num_tx_queues; i++) - adapter->tx_ring[i].count = new_tx_count; + adapter->tx_ring[i]->count = new_tx_count; for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].count = new_rx_count; + adapter->rx_ring[i]->count = new_rx_count; adapter->tx_ring_count = new_tx_count; adapter->rx_ring_count = new_rx_count; goto clear_reset; @@ -815,10 +815,10 @@ static int igb_set_ringparam(struct net_device *netdev, * to the tx and rx ring structs. */ if (new_tx_count != adapter->tx_ring_count) { - memcpy(temp_ring, adapter->tx_ring, - adapter->num_tx_queues * sizeof(struct igb_ring)); - for (i = 0; i < adapter->num_tx_queues; i++) { + memcpy(&temp_ring[i], adapter->tx_ring[i], + sizeof(struct igb_ring)); + temp_ring[i].count = new_tx_count; err = igb_setup_tx_resources(&temp_ring[i]); if (err) { @@ -830,20 +830,21 @@ static int igb_set_ringparam(struct net_device *netdev, } } - for (i = 0; i < adapter->num_tx_queues; i++) - igb_free_tx_resources(&adapter->tx_ring[i]); + for (i = 0; i < adapter->num_tx_queues; i++) { + igb_free_tx_resources(adapter->tx_ring[i]); - memcpy(adapter->tx_ring, temp_ring, - adapter->num_tx_queues * sizeof(struct igb_ring)); + memcpy(adapter->tx_ring[i], &temp_ring[i], + sizeof(struct igb_ring)); + } adapter->tx_ring_count = new_tx_count; } - if (new_rx_count != adapter->rx_ring->count) { - memcpy(temp_ring, adapter->rx_ring, - adapter->num_rx_queues * sizeof(struct igb_ring)); - + if (new_rx_count != adapter->rx_ring_count) { for (i = 0; i < adapter->num_rx_queues; i++) { + memcpy(&temp_ring[i], adapter->rx_ring[i], + sizeof(struct igb_ring)); + temp_ring[i].count = new_rx_count; err = igb_setup_rx_resources(&temp_ring[i]); if (err) { @@ -856,11 +857,12 @@ static int igb_set_ringparam(struct net_device *netdev, } - for (i = 0; i < adapter->num_rx_queues; i++) - igb_free_rx_resources(&adapter->rx_ring[i]); + for (i = 0; i < adapter->num_rx_queues; i++) { + igb_free_rx_resources(adapter->rx_ring[i]); - memcpy(adapter->rx_ring, temp_ring, - adapter->num_rx_queues * sizeof(struct igb_ring)); + memcpy(adapter->rx_ring[i], &temp_ring[i], + sizeof(struct igb_ring)); + } adapter->rx_ring_count = new_rx_count; } @@ -2036,12 +2038,12 @@ static void igb_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } for (j = 0; j < adapter->num_tx_queues; j++) { - queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats; + queue_stat = (u64 *)&adapter->tx_ring[j]->tx_stats; for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++) data[i] = queue_stat[k]; } for (j = 0; j < adapter->num_rx_queues; j++) { - queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats; + queue_stat = (u64 *)&adapter->rx_ring[j]->rx_stats; for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++) data[i] = queue_stat[k]; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 089a7c3f4c69..30fb5a89c42d 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -318,31 +318,35 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) */ if (adapter->vfs_allocated_count) { for (; i < adapter->rss_queues; i++) - adapter->rx_ring[i].reg_idx = rbase_offset + - Q_IDX_82576(i); + adapter->rx_ring[i]->reg_idx = rbase_offset + + Q_IDX_82576(i); for (; j < adapter->rss_queues; j++) - adapter->tx_ring[j].reg_idx = rbase_offset + - Q_IDX_82576(j); + adapter->tx_ring[j]->reg_idx = rbase_offset + + Q_IDX_82576(j); } case e1000_82575: case e1000_82580: default: for (; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].reg_idx = rbase_offset + i; + adapter->rx_ring[i]->reg_idx = rbase_offset + i; for (; j < adapter->num_tx_queues; j++) - adapter->tx_ring[j].reg_idx = rbase_offset + j; + adapter->tx_ring[j]->reg_idx = rbase_offset + j; break; } } static void igb_free_queues(struct igb_adapter *adapter) { - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - adapter->tx_ring = NULL; - adapter->rx_ring = NULL; + int i; + for (i = 0; i < adapter->num_tx_queues; i++) { + kfree(adapter->tx_ring[i]); + adapter->tx_ring[i] = NULL; + } + for (i = 0; i < adapter->num_rx_queues; i++) { + kfree(adapter->rx_ring[i]); + adapter->rx_ring[i] = NULL; + } adapter->num_rx_queues = 0; adapter->num_tx_queues = 0; } @@ -356,20 +360,13 @@ static void igb_free_queues(struct igb_adapter *adapter) **/ static int igb_alloc_queues(struct igb_adapter *adapter) { + struct igb_ring *ring; int i; - adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct igb_ring), GFP_KERNEL); - if (!adapter->tx_ring) - goto err; - - adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct igb_ring), GFP_KERNEL); - if (!adapter->rx_ring) - goto err; - for (i = 0; i < adapter->num_tx_queues; i++) { - struct igb_ring *ring = &(adapter->tx_ring[i]); + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + if (!ring) + goto err; ring->count = adapter->tx_ring_count; ring->queue_index = i; ring->pdev = adapter->pdev; @@ -377,10 +374,13 @@ static int igb_alloc_queues(struct igb_adapter *adapter) /* For 82575, context index must be unique per ring. */ if (adapter->hw.mac.type == e1000_82575) ring->flags = IGB_RING_FLAG_TX_CTX_IDX; + adapter->tx_ring[i] = ring; } for (i = 0; i < adapter->num_rx_queues; i++) { - struct igb_ring *ring = &(adapter->rx_ring[i]); + ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL); + if (!ring) + goto err; ring->count = adapter->rx_ring_count; ring->queue_index = i; ring->pdev = adapter->pdev; @@ -390,6 +390,7 @@ static int igb_alloc_queues(struct igb_adapter *adapter) /* set flag indicating ring supports SCTP checksum offload */ if (adapter->hw.mac.type >= e1000_82576) ring->flags |= IGB_RING_FLAG_RX_SCTP_CSUM; + adapter->rx_ring[i] = ring; } igb_cache_ring_register(adapter); @@ -780,10 +781,9 @@ err_out: static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter, int ring_idx, int v_idx) { - struct igb_q_vector *q_vector; + struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; - q_vector = adapter->q_vector[v_idx]; - q_vector->rx_ring = &adapter->rx_ring[ring_idx]; + q_vector->rx_ring = adapter->rx_ring[ring_idx]; q_vector->rx_ring->q_vector = q_vector; q_vector->itr_val = adapter->rx_itr_setting; if (q_vector->itr_val && q_vector->itr_val <= 3) @@ -793,10 +793,9 @@ static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter, static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter, int ring_idx, int v_idx) { - struct igb_q_vector *q_vector; + struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; - q_vector = adapter->q_vector[v_idx]; - q_vector->tx_ring = &adapter->tx_ring[ring_idx]; + q_vector->tx_ring = adapter->tx_ring[ring_idx]; q_vector->tx_ring->q_vector = q_vector; q_vector->itr_val = adapter->tx_itr_setting; if (q_vector->itr_val && q_vector->itr_val <= 3) @@ -1106,7 +1105,7 @@ static void igb_configure(struct igb_adapter *adapter) * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ for (i = 0; i < adapter->num_rx_queues; i++) { - struct igb_ring *ring = &adapter->rx_ring[i]; + struct igb_ring *ring = adapter->rx_ring[i]; igb_alloc_rx_buffers_adv(ring, igb_desc_unused(ring)); } @@ -2148,19 +2147,19 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { - err = igb_setup_tx_resources(&adapter->tx_ring[i]); + err = igb_setup_tx_resources(adapter->tx_ring[i]); if (err) { dev_err(&pdev->dev, "Allocation for Tx Queue %u failed\n", i); for (i--; i >= 0; i--) - igb_free_tx_resources(&adapter->tx_ring[i]); + igb_free_tx_resources(adapter->tx_ring[i]); break; } } for (i = 0; i < IGB_ABS_MAX_TX_QUEUES; i++) { int r_idx = i % adapter->num_tx_queues; - adapter->multi_tx_table[i] = &adapter->tx_ring[r_idx]; + adapter->multi_tx_table[i] = adapter->tx_ring[r_idx]; } return err; } @@ -2243,7 +2242,7 @@ static void igb_configure_tx(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - igb_configure_tx_ring(adapter, &adapter->tx_ring[i]); + igb_configure_tx_ring(adapter, adapter->tx_ring[i]); } /** @@ -2301,12 +2300,12 @@ static int igb_setup_all_rx_resources(struct igb_adapter *adapter) int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - err = igb_setup_rx_resources(&adapter->rx_ring[i]); + err = igb_setup_rx_resources(adapter->rx_ring[i]); if (err) { dev_err(&pdev->dev, "Allocation for Rx Queue %u failed\n", i); for (i--; i >= 0; i--) - igb_free_rx_resources(&adapter->rx_ring[i]); + igb_free_rx_resources(adapter->rx_ring[i]); break; } } @@ -2634,7 +2633,7 @@ static void igb_configure_rx(struct igb_adapter *adapter) /* Setup the HW Rx Head and Tail Descriptor Pointers and * the Base and Length of the Rx Descriptor Ring */ for (i = 0; i < adapter->num_rx_queues; i++) - igb_configure_rx_ring(adapter, &adapter->rx_ring[i]); + igb_configure_rx_ring(adapter, adapter->rx_ring[i]); } /** @@ -2671,7 +2670,7 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - igb_free_tx_resources(&adapter->tx_ring[i]); + igb_free_tx_resources(adapter->tx_ring[i]); } void igb_unmap_and_free_tx_resource(struct igb_ring *tx_ring, @@ -2738,7 +2737,7 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_tx_queues; i++) - igb_clean_tx_ring(&adapter->tx_ring[i]); + igb_clean_tx_ring(adapter->tx_ring[i]); } /** @@ -2775,7 +2774,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - igb_free_rx_resources(&adapter->rx_ring[i]); + igb_free_rx_resources(adapter->rx_ring[i]); } /** @@ -2839,7 +2838,7 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) int i; for (i = 0; i < adapter->num_rx_queues; i++) - igb_clean_rx_ring(&adapter->rx_ring[i]); + igb_clean_rx_ring(adapter->rx_ring[i]); } /** @@ -3163,7 +3162,7 @@ static void igb_watchdog_task(struct work_struct *work) igb_update_adaptive(hw); for (i = 0; i < adapter->num_tx_queues; i++) { - struct igb_ring *tx_ring = &adapter->tx_ring[i]; + struct igb_ring *tx_ring = adapter->tx_ring[i]; if (!netif_carrier_ok(netdev)) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going @@ -3359,13 +3358,13 @@ static void igb_set_itr(struct igb_adapter *adapter) adapter->rx_itr = igb_update_itr(adapter, adapter->rx_itr, - adapter->rx_ring->total_packets, - adapter->rx_ring->total_bytes); + q_vector->rx_ring->total_packets, + q_vector->rx_ring->total_bytes); adapter->tx_itr = igb_update_itr(adapter, adapter->tx_itr, - adapter->tx_ring->total_packets, - adapter->tx_ring->total_bytes); + q_vector->tx_ring->total_packets, + q_vector->tx_ring->total_bytes); current_itr = max(adapter->rx_itr, adapter->tx_itr); /* conservative mode (itr 3) eliminates the lowest_latency setting */ @@ -3388,10 +3387,10 @@ static void igb_set_itr(struct igb_adapter *adapter) } set_itr_now: - adapter->rx_ring->total_bytes = 0; - adapter->rx_ring->total_packets = 0; - adapter->tx_ring->total_bytes = 0; - adapter->tx_ring->total_packets = 0; + q_vector->rx_ring->total_bytes = 0; + q_vector->rx_ring->total_packets = 0; + q_vector->tx_ring->total_bytes = 0; + q_vector->tx_ring->total_packets = 0; if (new_itr != q_vector->itr_val) { /* this attempts to bias the interrupt rate towards Bulk @@ -3950,7 +3949,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; for (i = 0; i < adapter->num_rx_queues; i++) - adapter->rx_ring[i].rx_buffer_len = rx_buffer_len; + adapter->rx_ring[i]->rx_buffer_len = rx_buffer_len; if (netif_running(netdev)) igb_up(adapter); @@ -3992,10 +3991,11 @@ void igb_update_stats(struct igb_adapter *adapter) packets = 0; for (i = 0; i < adapter->num_rx_queues; i++) { u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; - adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp; + struct igb_ring *ring = adapter->rx_ring[i]; + ring->rx_stats.drops += rqdpc_tmp; net_stats->rx_fifo_errors += rqdpc_tmp; - bytes += adapter->rx_ring[i].rx_stats.bytes; - packets += adapter->rx_ring[i].rx_stats.packets; + bytes += ring->rx_stats.bytes; + packets += ring->rx_stats.packets; } net_stats->rx_bytes = bytes; @@ -4004,8 +4004,9 @@ void igb_update_stats(struct igb_adapter *adapter) bytes = 0; packets = 0; for (i = 0; i < adapter->num_tx_queues; i++) { - bytes += adapter->tx_ring[i].tx_stats.bytes; - packets += adapter->tx_ring[i].tx_stats.packets; + struct igb_ring *ring = adapter->tx_ring[i]; + bytes += ring->tx_stats.bytes; + packets += ring->tx_stats.packets; } net_stats->tx_bytes = bytes; net_stats->tx_packets = packets; -- cgit v1.2.3 From 2d0b0f693578109aff347e055d47f2797c802261 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:02:59 +0000 Subject: igb: remove adaptive IFS from driver Adaptive IFS support has been included in the igb driver since its initial release, but it is not a feature on any igb NICs. This patch removes it from the driver. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/e1000_defines.h | 6 ---- drivers/net/igb/e1000_hw.h | 7 ----- drivers/net/igb/e1000_mac.c | 70 ----------------------------------------- drivers/net/igb/e1000_mac.h | 2 -- drivers/net/igb/igb_main.c | 10 ++---- 5 files changed, 2 insertions(+), 93 deletions(-) diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h index c01715070764..fe6cf1b696c7 100644 --- a/drivers/net/igb/e1000_defines.h +++ b/drivers/net/igb/e1000_defines.h @@ -313,12 +313,6 @@ #define E1000_PBA_34K 0x0022 #define E1000_PBA_64K 0x0040 /* 64KB */ -#define IFS_MAX 80 -#define IFS_MIN 40 -#define IFS_RATIO 4 -#define IFS_STEP 10 -#define MIN_NUM_XMITS 1000 - /* SW Semaphore Register */ #define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index dbaeb5f5e0c7..448005276b26 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -339,19 +339,12 @@ struct e1000_mac_info { enum e1000_mac_type type; - u32 collision_delta; u32 ledctl_default; u32 ledctl_mode1; u32 ledctl_mode2; u32 mc_filter_type; - u32 tx_packet_delta; u32 txcw; - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; u16 mta_reg_count; u16 uta_reg_count; diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c index 2ad358a240bf..2a8a886b37eb 100644 --- a/drivers/net/igb/e1000_mac.c +++ b/drivers/net/igb/e1000_mac.c @@ -1303,76 +1303,6 @@ out: return ret_val; } -/** - * igb_reset_adaptive - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void igb_reset_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - hw_dbg("Not in Adaptive IFS mode!\n"); - goto out; - } - - if (!mac->ifs_params_forced) { - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - } - - mac->in_ifs_mode = false; - wr32(E1000_AIT, 0); -out: - return; -} - -/** - * igb_update_adaptive - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void igb_update_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - hw_dbg("Not in Adaptive IFS mode!\n"); - goto out; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - wr32(E1000_AIT, - mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - wr32(E1000_AIT, 0); - } - } -out: - return; -} - /** * igb_validate_mdi_setting - Verify MDI/MDIx settings * @hw: pointer to the HW structure diff --git a/drivers/net/igb/e1000_mac.h b/drivers/net/igb/e1000_mac.h index bca17d882417..601be99711c2 100644 --- a/drivers/net/igb/e1000_mac.h +++ b/drivers/net/igb/e1000_mac.h @@ -67,8 +67,6 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value); void igb_put_hw_semaphore(struct e1000_hw *hw); void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index); s32 igb_check_alt_mac_addr(struct e1000_hw *hw); -void igb_reset_adaptive(struct e1000_hw *hw); -void igb_update_adaptive(struct e1000_hw *hw); bool igb_enable_mng_pass_thru(struct e1000_hw *hw); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 30fb5a89c42d..eb48e1a084dd 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1365,7 +1365,6 @@ void igb_reset(struct igb_adapter *adapter) /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE); - igb_reset_adaptive(hw); igb_get_phy_info(hw); } @@ -1508,7 +1507,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, igb_get_bus_info_pcie(hw); hw->phy.autoneg_wait_to_complete = false; - hw->mac.adaptive_ifs = true; /* Copper options */ if (hw->phy.media_type == e1000_media_type_copper) { @@ -3159,7 +3157,6 @@ static void igb_watchdog_task(struct work_struct *work) } igb_update_stats(adapter); - igb_update_adaptive(hw); for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; @@ -4064,11 +4061,8 @@ void igb_update_stats(struct igb_adapter *adapter) adapter->stats.mptc += rd32(E1000_MPTC); adapter->stats.bptc += rd32(E1000_BPTC); - /* used for adaptive IFS */ - hw->mac.tx_packet_delta = rd32(E1000_TPT); - adapter->stats.tpt += hw->mac.tx_packet_delta; - hw->mac.collision_delta = rd32(E1000_COLC); - adapter->stats.colc += hw->mac.collision_delta; + adapter->stats.tpt += rd32(E1000_TPT); + adapter->stats.colc += rd32(E1000_COLC); adapter->stats.algnerrc += rd32(E1000_ALGNERRC); adapter->stats.rxerrc += rd32(E1000_RXERRC); -- cgit v1.2.3 From abe1c3638ccf8b68536afb52b111f6ad46d1cf71 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:03:19 +0000 Subject: igb: cap interrupts at 20K per queue when in itr mode 3 In order to maintain similar performance between MSI-X and legacy/MSI interrupts, this patch reduces the number of interrupts when receiving small packets to 20K when in interrupt throttle rate mode 3. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index eb48e1a084dd..4ccc7fc70f53 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3260,6 +3260,10 @@ static void igb_update_ring_itr(struct igb_q_vector *q_vector) else new_val = avg_wire_size / 2; + /* when in itr mode 3 do not exceed 20K ints/sec */ + if (adapter->rx_itr_setting == 3 && new_val < 196) + new_val = 196; + set_itr_val: if (new_val != q_vector->itr_val) { q_vector->itr_val = new_val; -- cgit v1.2.3 From e6bdb6fefc590ad2fb5f79e1d1d3660afbc7c8ff Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:03:38 +0000 Subject: igb: only support SRRCTL_DROP_EN when using multiple queues The SRRCTL.DROP_EN bit should only be set when we are supporting multiple queues. This bit is meant to prevent head of line blocking and is unnecessary in the single queue case. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 4ccc7fc70f53..b989b34a4adb 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2595,6 +2595,9 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, E1000_SRRCTL_BSIZEPKT_SHIFT; srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; } + /* Only set Drop Enable if we are supporting multiple queues */ + if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1) + srrctl |= E1000_SRRCTL_DROP_EN; wr32(E1000_SRRCTL(reg_idx), srrctl); -- cgit v1.2.3 From 43915c7c9a99e38406103d9c72b73edeaa19d0ff Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:03:58 +0000 Subject: igb: only read phy specific stats if in internal phy mode There are a couple statistics registers that are not meant to be read when in SGMII/serdes mode. This patch adds a check to verify mode before reading and updating these statistics. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b989b34a4adb..cba0115a6a57 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3975,7 +3975,7 @@ void igb_update_stats(struct igb_adapter *adapter) struct net_device_stats *net_stats = igb_get_stats(adapter->netdev); struct e1000_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; - u32 rnbc; + u32 rnbc, reg; u16 phy_tmp; int i; u64 bytes, packets; @@ -4072,8 +4072,13 @@ void igb_update_stats(struct igb_adapter *adapter) adapter->stats.colc += rd32(E1000_COLC); adapter->stats.algnerrc += rd32(E1000_ALGNERRC); - adapter->stats.rxerrc += rd32(E1000_RXERRC); - adapter->stats.tncrs += rd32(E1000_TNCRS); + /* read internal phy specific stats */ + reg = rd32(E1000_CTRL_EXT); + if (!(reg & E1000_CTRL_EXT_LINK_MODE_MASK)) { + adapter->stats.rxerrc += rd32(E1000_RXERRC); + adapter->stats.tncrs += rd32(E1000_TNCRS); + } + adapter->stats.tsctc += rd32(E1000_TSCTC); adapter->stats.tsctfc += rd32(E1000_TSCTFC); -- cgit v1.2.3 From 717ba0893508c2c8706c1408c152aa6d286d5d80 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:04:18 +0000 Subject: igb: inline igb_maybe_stop_tx igb_maybe_stop_tx() is extremely small and appears in several spots in the tx hotpath. This change inlines the function for a possible performance boost. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index cba0115a6a57..a1fe581febc0 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3758,7 +3758,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) return 0; } -static int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) +static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, int size) { if (igb_desc_unused(tx_ring) >= size) return 0; -- cgit v1.2.3 From 40e90c26f573fa5082be6e046b346e19ab0cd25f Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:04:37 +0000 Subject: igb: move gso_segs into buffer_info structure This change moves gso_segs into the buffer_info structure to avoid a possible cache line miss in clean_tx_irq. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 1 + drivers/net/igb/igb_main.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 8f07bc0a1d4c..7854b66648c7 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -141,6 +141,7 @@ struct igb_buffer { u16 length; u16 next_to_watch; u16 mapped_as_page; + u16 gso_segs; }; /* RX */ struct { diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a1fe581febc0..91c123f9df92 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3641,6 +3641,7 @@ static inline int igb_tx_map_adv(struct igb_ring *tx_ring, struct sk_buff *skb, } tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[i].gso_segs = skb_shinfo(skb)->gso_segs ?: 1; tx_ring->buffer_info[first].next_to_watch = i; return ++count; @@ -5032,7 +5033,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) if (skb) { unsigned int segs, bytecount; /* gso_segs is currently only valid for tcp */ - segs = skb_shinfo(skb)->gso_segs ?: 1; + segs = buffer_info->gso_segs; /* multiply data chunks by size of headers */ bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; -- cgit v1.2.3 From 91d4ee3382e78bd78e0251a56e2fa96b20c26e30 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:04:56 +0000 Subject: igb: minor type cleanups This change cleans up some instances where unsigned int and u32 were being used interchangeably, and cleans up hdr_len which was being set to 0 twice. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 91c123f9df92..ff392e999ffc 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3434,8 +3434,8 @@ static inline int igb_tso_adv(struct igb_ring *tx_ring, int err; struct igb_buffer *buffer_info; u32 info = 0, tu_cmd = 0; - u32 mss_l4len_idx, l4len; - *hdr_len = 0; + u32 mss_l4len_idx; + u8 l4len; if (skb_header_cloned(skb)) { err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); @@ -3671,7 +3671,7 @@ dma_error: } static inline void igb_tx_queue_adv(struct igb_ring *tx_ring, - int tx_flags, int count, u32 paylen, + u32 tx_flags, int count, u32 paylen, u8 hdr_len) { union e1000_adv_tx_desc *tx_desc; @@ -3770,10 +3770,10 @@ netdev_tx_t igb_xmit_frame_ring_adv(struct sk_buff *skb, struct igb_ring *tx_ring) { struct igb_adapter *adapter = netdev_priv(tx_ring->netdev); - unsigned int first; - unsigned int tx_flags = 0; - u8 hdr_len = 0; int tso = 0, count; + u32 tx_flags = 0; + u16 first; + u8 hdr_len = 0; union skb_shared_tx *shtx = skb_tx(skb); /* need: 1 descriptor per page, -- cgit v1.2.3 From d3eeb62ddd06ea20a054213cface92d328709285 Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:05:15 +0000 Subject: igb: remove unused vmolr value In an earlier version of igb_write_mc_addr_list() the vmolr register was modified. This register is no longer accessed, although the variable still exists. This patch removes it from the function. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ff392e999ffc..a9f4e0288409 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2883,7 +2883,6 @@ static int igb_write_mc_addr_list(struct net_device *netdev) struct e1000_hw *hw = &adapter->hw; struct dev_mc_list *mc_ptr = netdev->mc_list; u8 *mta_list; - u32 vmolr = 0; int i; if (netdev_mc_empty(netdev)) { @@ -2897,9 +2896,6 @@ static int igb_write_mc_addr_list(struct net_device *netdev) if (!mta_list) return -ENOMEM; - /* set vmolr receive overflow multicast bit */ - vmolr |= E1000_VMOLR_ROMPE; - /* The shared function expects a packed array of only addresses. */ mc_ptr = netdev->mc_list; -- cgit v1.2.3 From fe0592b4be0ce362e87cefd4f6dbf12cb5704d1b Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:05:35 +0000 Subject: igb: use igb_free_q_vectors to cleanup failure in igb_alloc_q_vectors This change makes it so that igb_free_q_vectors is reused in igb_alloc_q_vectors to handle the cleanup instead of unwinding through the allocations. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a9f4e0288409..ab7c5e97ed02 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -649,6 +649,8 @@ static void igb_free_q_vectors(struct igb_adapter *adapter) for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) { struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; adapter->q_vector[v_idx] = NULL; + if (!q_vector) + continue; netif_napi_del(&q_vector->napi); kfree(q_vector); } @@ -768,13 +770,7 @@ static int igb_alloc_q_vectors(struct igb_adapter *adapter) return 0; err_out: - while (v_idx) { - v_idx--; - q_vector = adapter->q_vector[v_idx]; - netif_napi_del(&q_vector->napi); - kfree(q_vector); - adapter->q_vector[v_idx] = NULL; - } + igb_free_q_vectors(adapter); return -ENOMEM; } -- cgit v1.2.3 From 58fd62f525e1182fbb2f7566aecb4545720d9aad Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:05:56 +0000 Subject: igb: change descriptor control thresholds This change simplifies the code by setting RX_PTHRESH to 8 for all devices, as it was unlikely that there was any advantage to set it at 16 for earlier cards. Additionally TX_WTHRESH is set to 1 for the 82576 NIC to improve performance by enabling a minimal amount of write combining when writing back descriptors. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h index 7854b66648c7..a1775705b24c 100644 --- a/drivers/net/igb/igb.h +++ b/drivers/net/igb/igb.h @@ -95,13 +95,13 @@ struct vf_data_storage { * descriptors until either it has this many to write back, or the * ITR timer expires. */ -#define IGB_RX_PTHRESH (hw->mac.type <= e1000_82576 ? 16 : 8) +#define IGB_RX_PTHRESH 8 #define IGB_RX_HTHRESH 8 #define IGB_RX_WTHRESH 1 #define IGB_TX_PTHRESH 8 #define IGB_TX_HTHRESH 1 #define IGB_TX_WTHRESH ((hw->mac.type == e1000_82576 && \ - adapter->msix_entries) ? 0 : 16) + adapter->msix_entries) ? 1 : 16) /* this is the size past which hardware will drop packets when setting LPE=0 */ #define MAXIMUM_ETHERNET_VLAN_SIZE 1522 -- cgit v1.2.3 From a77ff709dd30a263f8154b05a8514b46098b42ba Mon Sep 17 00:00:00 2001 From: Nick Nunley Date: Wed, 17 Feb 2010 01:06:16 +0000 Subject: igb: update tx DMA mapping error handling This updates the tx DMA mapping error handling code to resemble e1000e/ixgbe. Signed-off-by: Nicholas Nunley Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ab7c5e97ed02..f588e49c65f1 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -3647,14 +3647,12 @@ dma_error: buffer_info->length = 0; buffer_info->next_to_watch = 0; buffer_info->mapped_as_page = false; - count--; /* clear timestamp and dma mappings for remaining portion of packet */ - while (count >= 0) { - count--; + while (count--) { + if (i == 0) + i = tx_ring->count; i--; - if (i < 0) - i += tx_ring->count; buffer_info = &tx_ring->buffer_info[i]; igb_unmap_and_free_tx_resource(tx_ring, buffer_info); } -- cgit v1.2.3 From 9f0beba9f90847db7ba6ed894f7c87b6038a5bce Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 17 Feb 2010 01:19:32 +0000 Subject: ipmr: remove useless checks from ipmr_device_event The net being checked there is dev_net(dev) and thus this if is always false. Fits both net and net-next trees. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv4/ipmr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 54596f73eff5..8582e12e4a62 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1163,9 +1163,6 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v int ct; LIST_HEAD(list); - if (!net_eq(dev_net(dev), net)) - return NOTIFY_DONE; - if (event != NETDEV_UNREGISTER) return NOTIFY_DONE; v = &net->ipv4.vif_table[0]; -- cgit v1.2.3 From 8a5ce54562f296b1996813a413b0f2307ec9351a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 17 Feb 2010 06:43:47 +0000 Subject: xt_hashlimit: fix locking Commit 2eff25c18c3d332d3c4dd98f2ac9b7114e9771b0 (netfilter: xt_hashlimit: fix race condition and simplify locking) added a mutex deadlock : htable_create() is called with hashlimit_mutex already locked Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/netfilter/xt_hashlimit.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index e47fb805ffb4..d952806b6469 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -262,9 +262,7 @@ static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_ hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); - mutex_lock(&hashlimit_mutex); hlist_add_head(&hinfo->node, &hashlimit_net->htables); - mutex_unlock(&hashlimit_mutex); return 0; } @@ -327,9 +325,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); add_timer(&hinfo->timer); - mutex_lock(&hashlimit_mutex); hlist_add_head(&hinfo->node, &hashlimit_net->htables); - mutex_unlock(&hashlimit_mutex); return 0; } -- cgit v1.2.3 From faf234220fb79a05891477a75180e1d9f7ab4105 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 17 Feb 2010 09:34:12 +0000 Subject: net: use kasprintf() for socket cache names kasprintf() makes code smaller. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/core/sock.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/net/core/sock.c b/net/core/sock.c index ceef50bd131b..472a59f205b0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2228,13 +2228,10 @@ int proto_register(struct proto *prot, int alloc_slab) } if (prot->rsk_prot != NULL) { - static const char mask[] = "request_sock_%s"; - - prot->rsk_prot->slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); + prot->rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", prot->name); if (prot->rsk_prot->slab_name == NULL) goto out_free_sock_slab; - sprintf(prot->rsk_prot->slab_name, mask, prot->name); prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name, prot->rsk_prot->obj_size, 0, SLAB_HWCACHE_ALIGN, NULL); @@ -2247,14 +2244,11 @@ int proto_register(struct proto *prot, int alloc_slab) } if (prot->twsk_prot != NULL) { - static const char mask[] = "tw_sock_%s"; - - prot->twsk_prot->twsk_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL); + prot->twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s", prot->name); if (prot->twsk_prot->twsk_slab_name == NULL) goto out_free_request_sock_slab; - sprintf(prot->twsk_prot->twsk_slab_name, mask, prot->name); prot->twsk_prot->twsk_slab = kmem_cache_create(prot->twsk_prot->twsk_slab_name, prot->twsk_prot->twsk_obj_size, -- cgit v1.2.3 From d7b855c2dcc89587f36338bd383203322efb9903 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 10:43:33 +0000 Subject: cassini: convert to use netdev_for_each_mc_addr Introduced a new function to do the mc list processing, makes code clearer after transition. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/cassini.c | 72 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index ad47e5126fde..f90cac43130d 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2999,6 +2999,40 @@ static inline void cas_init_dma(struct cas *cp) cas_init_rx_dma(cp); } +static void cas_process_mc_list(struct cas *cp) +{ + u16 hash_table[16]; + u32 crc; + struct dev_mc_list *dmi; + int i = 1; + + memset(hash_table, 0, sizeof(hash_table)); + netdev_for_each_mc_addr(dmi, cp->dev) { + if (i <= CAS_MC_EXACT_MATCH_SIZE) { + /* use the alternate mac address registers for the + * first 15 multicast addresses + */ + writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], + cp->regs + REG_MAC_ADDRN(i*3 + 0)); + writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], + cp->regs + REG_MAC_ADDRN(i*3 + 1)); + writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], + cp->regs + REG_MAC_ADDRN(i*3 + 2)); + i++; + } + else { + /* use hw hash table for the next series of + * multicast addresses + */ + crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); + crc >>= 24; + hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); + } + } + for (i = 0; i < 16; i++) + writel(hash_table[i], cp->regs + REG_MAC_HASH_TABLEN(i)); +} + /* Must be invoked under cp->lock. */ static u32 cas_setup_multicast(struct cas *cp) { @@ -3014,43 +3048,7 @@ static u32 cas_setup_multicast(struct cas *cp) rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; } else { - u16 hash_table[16]; - u32 crc; - struct dev_mc_list *dmi = cp->dev->mc_list; - int i; - - /* use the alternate mac address registers for the - * first 15 multicast addresses - */ - for (i = 1; i <= CAS_MC_EXACT_MATCH_SIZE; i++) { - if (!dmi) { - writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 0)); - writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 1)); - writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 2)); - continue; - } - writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], - cp->regs + REG_MAC_ADDRN(i*3 + 0)); - writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], - cp->regs + REG_MAC_ADDRN(i*3 + 1)); - writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], - cp->regs + REG_MAC_ADDRN(i*3 + 2)); - dmi = dmi->next; - } - - /* use hw hash table for the next series of - * multicast addresses - */ - memset(hash_table, 0, sizeof(hash_table)); - while (dmi) { - crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); - crc >>= 24; - hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); - dmi = dmi->next; - } - for (i=0; i < 16; i++) - writel(hash_table[i], cp->regs + - REG_MAC_HASH_TABLEN(i)); + cas_process_mc_list(cp); rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; } -- cgit v1.2.3 From e1d444771e0895c7706bc99857d69e4f2a58a531 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 11:09:31 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/cpmac.c | 4 +--- drivers/net/cris/eth_v10.c | 6 ++---- drivers/net/cs89x0.c | 2 +- drivers/net/declance.c | 6 ++---- drivers/net/defxx.c | 11 +++++------ drivers/net/depca.c | 3 +-- drivers/net/dl2k.c | 5 +---- drivers/net/dm9000.c | 5 ++--- 8 files changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index c9c537be4ab9..0074f3bf17be 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -320,7 +320,6 @@ static int cpmac_config(struct net_device *dev, struct ifmap *map) static void cpmac_set_multicast_list(struct net_device *dev) { struct dev_mc_list *iter; - int i; u8 tmp; u32 mbp, bit, hash[2] = { 0, }; struct cpmac_priv *priv = netdev_priv(dev); @@ -340,8 +339,7 @@ static void cpmac_set_multicast_list(struct net_device *dev) * cpmac uses some strange mac address hashing * (not crc32) */ - for (i = 0, iter = dev->mc_list; i < netdev_mc_count(dev); - i++, iter = iter->next) { + netdev_for_each_mc_addr(iter, dev) { bit = 0; tmp = iter->dmi_addr[0]; bit ^= (tmp >> 2) ^ (tmp << 4); diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index c9309eadebc1..dd24aadb778c 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1596,13 +1596,12 @@ set_multicast_list(struct net_device *dev) } else { /* MC mode, receive normal and MC packets */ char hash_ix; - struct dev_mc_list *dmi = dev->mc_list; - int i; + struct dev_mc_list *dmi; char *baddr; lo_bits = 0x00000000ul; hi_bits = 0x00000000ul; - for (i = 0; i < num_addr; i++) { + netdev_for_each_mc_addr(dmi, dev) { /* Calculate the hash index for the GA registers */ hash_ix = 0; @@ -1632,7 +1631,6 @@ set_multicast_list(struct net_device *dev) } else { lo_bits |= (1 << hash_ix); } - dmi = dmi->next; } /* Disable individual receive */ SETS(network_rec_config_shadow, R_NETWORK_REC_CONFIG, individual, discard); diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 0e79cef95c0a..14624019ce71 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -1785,7 +1785,7 @@ static void set_multicast_list(struct net_device *dev) { lp->rx_mode = RX_ALL_ACCEPT; } - else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) + else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { /* The multicast-accept list is initialized to accept-all, and we rely on higher-level filtering for now. */ diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 76e0de6a4263..8cf3cc6f20e2 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -940,9 +940,8 @@ static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile u16 *ib = (volatile u16 *)dev->mem_start; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; /* set all multicast bits */ @@ -960,9 +959,8 @@ static void lance_load_multicast(struct net_device *dev) *lib_ptr(ib, filter[3], lp->type) = 0; /* Add addresses */ - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 5adb1e03956d..ed53a8d45f4e 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -2240,12 +2240,11 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev) /* Copy addresses to multicast address table, then update adapter CAM */ - dmi = dev->mc_list; /* point to first multicast addr */ - for (i=0; i < bp->mc_count; i++) - { - memcpy(&bp->mc_table[i*FDDI_K_ALEN], dmi->dmi_addr, FDDI_K_ALEN); - dmi = dmi->next; /* point to next multicast addr */ - } + i = 0; + netdev_for_each_mc_addr(dmi, dev) + memcpy(&bp->mc_table[i++ * FDDI_K_ALEN], + dmi->dmi_addr, FDDI_K_ALEN); + if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS) { DBG_printk("%s: Could not update multicast address table!\n", dev->name); diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 314bc96689f4..64a569bc92a6 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1287,9 +1287,8 @@ static void SetMulticastFilter(struct net_device *dev) lp->init_block.mcast_table[i] = 0; } /* Add multicast addresses */ - for (i = 0; i < netdev_mc_count(dev); i++) { /* for each address in the list */ + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc(ETH_ALEN, addrs); hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c index dea40953ed1b..b05bad829827 100644 --- a/drivers/net/dl2k.c +++ b/drivers/net/dl2k.c @@ -1132,15 +1132,12 @@ set_multicast (struct net_device *dev) /* Receive broadcast and multicast frames */ rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast; } else if (!netdev_mc_empty(dev)) { - int i; struct dev_mc_list *mclist; /* Receive broadcast frames and multicast frames filtering by Hashtable */ rx_mode = ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast; - for (i=0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist=mclist->next) - { + netdev_for_each_mc_addr(mclist, dev) { int bit, index = 0; int crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); /* The inverted high significant 6 bits of CRC are diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index da0985a7a87a..1c67f1138ca7 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -724,8 +724,7 @@ static void dm9000_hash_table(struct net_device *dev) { board_info_t *db = netdev_priv(dev); - struct dev_mc_list *mcptr = dev->mc_list; - int mc_cnt = netdev_mc_count(dev); + struct dev_mc_list *mcptr; int i, oft; u32 hash_val; u16 hash_table[4]; @@ -753,7 +752,7 @@ dm9000_hash_table(struct net_device *dev) rcr |= RCR_ALL; /* the multicast address in Hash Table : 64 bits */ - for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { + netdev_for_each_mc_addr(mcptr, dev) { hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } -- cgit v1.2.3 From c3b7c12cd78d5c8264c87c29dcd9a8f1819f8313 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Wed, 17 Feb 2010 07:14:20 +0000 Subject: ll_temac: Add support for V2 LLTEMAC core LLTEMAC V1 cores place only received packet length in the app4 word. V2 cores place additional information in app4. Mask out the additional information when retrieving the packet length. Signed-off-by: Steven J. Magnani Signed-off-by: David S. Miller --- drivers/net/ll_temac_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 8442c47e93e8..d7eb24cc2648 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -615,7 +615,7 @@ static void ll_temac_recv(struct net_device *ndev) while ((bdstat & STS_CTRL_APP0_CMPLT)) { skb = lp->rx_skb[lp->rx_bd_ci]; - length = cur_p->app4; + length = cur_p->app4 & 0x3FFF; skb_vaddr = virt_to_bus(skb->data); dma_unmap_single(ndev->dev.parent, skb_vaddr, length, @@ -938,6 +938,9 @@ static int __devexit temac_of_remove(struct of_device *op) static struct of_device_id temac_of_match[] __devinitdata = { { .compatible = "xlnx,xps-ll-temac-1.01.b", }, + { .compatible = "xlnx,xps-ll-temac-2.00.a", }, + { .compatible = "xlnx,xps-ll-temac-2.02.a", }, + { .compatible = "xlnx,xps-ll-temac-2.03.a", }, {}, }; MODULE_DEVICE_TABLE(of, temac_of_match); -- cgit v1.2.3 From 8ea7a37c5a312bfee51ff7f12f78efe4fbc901cc Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Wed, 17 Feb 2010 07:55:07 +0000 Subject: ll_temac: Fix MAC address configuration from userland A userland command to set the LLTEMAC MAC address, i.e. "ifconfig eth0 hw addr xx:yy:zz:pp:dd:qq", results in a device address of 00:01:xx:yy:zz:pp. Correct this. Signed-off-by: Steven J. Magnani Signed-off-by: David S. Miller --- drivers/net/ll_temac_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index d7eb24cc2648..e53440253748 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -224,6 +224,13 @@ static int temac_set_mac_address(struct net_device *ndev, void *address) return 0; } +static int netdev_set_mac_address(struct net_device *ndev, void *p) +{ + struct sockaddr *addr = p; + + return temac_set_mac_address(ndev, addr->sa_data); +} + static void temac_set_multicast_list(struct net_device *ndev) { struct temac_local *lp = netdev_priv(ndev); @@ -768,7 +775,7 @@ static const struct net_device_ops temac_netdev_ops = { .ndo_open = temac_open, .ndo_stop = temac_stop, .ndo_start_xmit = temac_start_xmit, - .ndo_set_mac_address = temac_set_mac_address, + .ndo_set_mac_address = netdev_set_mac_address, //.ndo_set_multicast_list = temac_set_multicast_list, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = temac_poll_controller, -- cgit v1.2.3 From c0c56955e7325ba2f910c760111457adc21ef0d4 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 17 Feb 2010 06:41:21 +0000 Subject: qlge: Fix dropping of large non-TCP/UDP frames. This was found with pings that were large enough to span multiple rx buffers. The split frame logic handles this case nicely. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 2c052caee884..0541e777694d 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2066,21 +2066,11 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, ql_process_mac_rx_page(qdev, rx_ring, ib_mac_rsp, length, vlan_id); } else { - struct bq_desc *lbq_desc; - - /* Free small buffer that holds the IAL */ - lbq_desc = ql_get_curr_sbuf(rx_ring); - netif_err(qdev, rx_err, qdev->ndev, - "Dropping frame, len %d > mtu %d\n", - length, qdev->ndev->mtu); - - /* Unwind the large buffers for this frame. */ - while (length > 0) { - lbq_desc = ql_get_curr_lchunk(qdev, rx_ring); - length -= (length < rx_ring->lbq_buf_size) ? - length : rx_ring->lbq_buf_size; - put_page(lbq_desc->p.pg_chunk.page); - } + /* Non-TCP/UDP large frames that span multiple buffers + * can be processed corrrectly by the split frame logic. + */ + ql_process_mac_split_rx_intr(qdev, rx_ring, ib_mac_rsp, + vlan_id); } return (unsigned long)length; -- cgit v1.2.3 From 801e9096c566d40d2e7c9903dc902fa01a5a0b36 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 17 Feb 2010 06:41:22 +0000 Subject: qlge: Fix bonding mac address bug. Use local copy of current mac address when initializing. In bonding testing we saw cases where dev_addr was out of data causing failover errors. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 2 ++ drivers/net/qlge/qlge_main.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 57d135e3bfaf..8b742b639ceb 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -2139,6 +2139,8 @@ struct ql_adapter { u16 device_id; struct timer_list timer; atomic_t lb_count; + /* Keep local copy of current mac address. */ + char current_mac_addr[6]; }; /* diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 0541e777694d..c170349717c5 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -463,7 +463,7 @@ static int ql_set_mac_addr(struct ql_adapter *qdev, int set) char *addr; if (set) { - addr = &qdev->ndev->dev_addr[0]; + addr = &qdev->current_mac_addr[0]; netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev, "Set Mac addr %pM\n", addr); } else { @@ -4301,6 +4301,8 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); + /* Update local copy of current mac address. */ + memcpy(qdev->current_mac_addr, ndev->dev_addr, ndev->addr_len); status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) @@ -4542,6 +4544,8 @@ static int __devinit ql_init_device(struct pci_dev *pdev, } memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); + /* Keep local copy of current mac address. */ + memcpy(qdev->current_mac_addr, ndev->dev_addr, ndev->addr_len); /* Set up the default ring sizes. */ qdev->tx_ring_size = NUM_TX_RING_ENTRIES; -- cgit v1.2.3 From aa13bd6ef4ddd81080f972220fae30eb28f65b17 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 17 Feb 2010 06:41:23 +0000 Subject: qlge: Fix occasional loopback test failure. On some servers we see the cleaning of the RX queue finish before all the loopback packets are sent out. This delay allows the queues to settle before checking for successful completion. Also, delay completion so link has time to come back up. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_ethtool.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index 4f26afeb0f38..05b8bde9980d 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c @@ -503,7 +503,8 @@ static int ql_run_loopback_test(struct ql_adapter *qdev) return -EPIPE; atomic_inc(&qdev->lb_count); } - + /* Give queue time to settle before testing results. */ + msleep(2); ql_clean_lb_rx_ring(&qdev->rx_ring[0], 128); return atomic_read(&qdev->lb_count) ? -EIO : 0; } @@ -536,6 +537,10 @@ static void ql_self_test(struct net_device *ndev, data[0] = 0; } clear_bit(QL_SELFTEST, &qdev->flags); + /* Give link time to come up after + * port configuration changes. + */ + msleep_interruptible(4 * 1000); } else { netif_err(qdev, drv, qdev->ndev, "is down, Loopback test will fail.\n"); -- cgit v1.2.3 From a058a632747dd0f1799b12f4ecd54e43f5b5f10d Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:34:22 +0000 Subject: be2net: a mini optimization in rx_compl_process() code Introduce unlikely() for skb alloc failure and vlanf checks... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index cbfaa3feb7c4..7bf1900df665 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -768,16 +768,8 @@ static void be_rx_compl_process(struct be_adapter *adapter, u32 vlanf, vid; u8 vtm; - vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); - vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); - - /* vlanf could be wrongly set in some cards. - * ignore if vtm is not set */ - if ((adapter->cap & 0x400) && !vtm) - vlanf = 0; - skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); - if (!skb) { + if (unlikely(!skb)) { if (net_ratelimit()) dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); be_rx_compl_discard(adapter, rxcp); @@ -795,7 +787,15 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->netdev); skb->dev = adapter->netdev; - if (vlanf) { + vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); + + /* vlanf could be wrongly set in some cards. + * ignore if vtm is not set */ + if ((adapter->cap & 0x400) && !vtm) + vlanf = 0; + + if (unlikely(vlanf)) { if (!adapter->vlan_grp || adapter->vlans_added == 0) { kfree_skb(skb); return; -- cgit v1.2.3 From 7a1e9b2059d147461cff3dfbabbfb43f296a1eef Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:11 +0000 Subject: be2net: don't rearm mcc cq when device is not open When an MCC cmd is issued (via a netdev/ethtool op) while the device is not open, the MCC CQ gets processed but the EQ is not processed (as isr is not registered.) This can cause the EQ to become full. So, while the device is not open, CQ must not be re-armed to prevent EQ entries. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_cmds.c | 20 ++++++++++++++++++-- drivers/net/benet/be_cmds.h | 2 ++ drivers/net/benet/be_main.c | 5 +++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 5038c16bfe9b..2734a41a4627 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -151,6 +151,7 @@ struct be_eq_obj { struct be_mcc_obj { struct be_queue_info q; struct be_queue_info cq; + bool rearm_cq; }; struct be_drvr_stats { diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 477f82bc647e..d7546b450505 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -104,10 +104,26 @@ static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter) return NULL; } +void be_async_mcc_enable(struct be_adapter *adapter) +{ + spin_lock_bh(&adapter->mcc_cq_lock); + + be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, 0); + adapter->mcc_obj.rearm_cq = true; + + spin_unlock_bh(&adapter->mcc_cq_lock); +} + +void be_async_mcc_disable(struct be_adapter *adapter) +{ + adapter->mcc_obj.rearm_cq = false; +} + int be_process_mcc(struct be_adapter *adapter) { struct be_mcc_compl *compl; int num = 0, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; spin_lock_bh(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { @@ -120,14 +136,14 @@ int be_process_mcc(struct be_adapter *adapter) (struct be_async_event_link_state *) compl); } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { status = be_mcc_compl_process(adapter, compl); - atomic_dec(&adapter->mcc_obj.q.used); + atomic_dec(&mcc_obj->q.used); } be_mcc_compl_use(compl); num++; } if (num) - be_cq_notify(adapter, adapter->mcc_obj.cq.id, true, num); + be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); spin_unlock_bh(&adapter->mcc_cq_lock); return status; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 7297b5a47657..01501dbae00a 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -937,6 +937,8 @@ extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_dma_mem *nonemb_cmd); extern int be_cmd_fw_init(struct be_adapter *adapter); extern int be_cmd_fw_clean(struct be_adapter *adapter); +extern void be_async_mcc_enable(struct be_adapter *adapter); +extern void be_async_mcc_disable(struct be_adapter *adapter); extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7bf1900df665..43dbe288a5ef 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1655,6 +1655,9 @@ static int be_open(struct net_device *netdev) /* Rx compl queue may be in unarmed state; rearm it */ be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0); + /* Now that interrupts are on we can process async mcc */ + be_async_mcc_enable(adapter); + status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); if (status) @@ -1780,6 +1783,8 @@ static int be_close(struct net_device *netdev) cancel_delayed_work_sync(&adapter->work); + be_async_mcc_disable(adapter); + netif_stop_queue(netdev); netif_carrier_off(netdev); adapter->link_up = false; -- cgit v1.2.3 From 89420424fce28769c338909393518087befe8b37 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:26 +0000 Subject: be2net: fix rx-path to ignore a flush completion The flush compl (compl with numfrags == 0; no data) is rcvd from hw to indicate completion of RXQ destory operation. Fix the RX path to not process it as RX data. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 43dbe288a5ef..2c3deadd2d83 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -680,17 +680,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter, * indicated by rxcp. */ static void skb_fill_rx_data(struct be_adapter *adapter, - struct sk_buff *skb, struct be_eth_rx_compl *rxcp) + struct sk_buff *skb, struct be_eth_rx_compl *rxcp, + u16 num_rcvd) { struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_rx_page_info *page_info; - u16 rxq_idx, i, num_rcvd, j; + u16 rxq_idx, i, j; u32 pktsize, hdr_len, curr_frag_len, size; u8 *start; rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); - num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); page_info = get_rx_page_info(adapter, rxq_idx); @@ -766,8 +766,14 @@ static void be_rx_compl_process(struct be_adapter *adapter, { struct sk_buff *skb; u32 vlanf, vid; + u16 num_rcvd; u8 vtm; + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + /* Is it a flush compl that has no data */ + if (unlikely(num_rcvd == 0)) + return; + skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); if (unlikely(!skb)) { if (net_ratelimit()) @@ -776,7 +782,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, return; } - skb_fill_rx_data(adapter, skb, rxcp); + skb_fill_rx_data(adapter, skb, rxcp, num_rcvd); if (do_pkt_csum(rxcp, adapter->rx_csum)) skb->ip_summed = CHECKSUM_NONE; @@ -823,6 +829,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, u8 vtm; num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + /* Is it a flush compl that has no data */ + if (unlikely(num_rcvd == 0)) + return; + pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); @@ -1273,6 +1283,11 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) q = &adapter->rx_obj.q; if (q->created) { be_cmd_q_destroy(adapter, q, QTYPE_RXQ); + + /* After the rxq is invalidated, wait for a grace time + * of 1ms for all dma to end and the flush compl to arrive + */ + mdelay(1); be_rx_q_clean(adapter); } be_queue_free(adapter, q); -- cgit v1.2.3 From 82456b031e3c3b5bf95a7e49bd9b68b146446e76 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:37 +0000 Subject: be2net: implement pci shutdown handler Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 2c3deadd2d83..68e7848ac0b0 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2449,6 +2449,26 @@ static int be_resume(struct pci_dev *pdev) return 0; } +/* + * An FLR will stop BE from DMAing any data. + */ +static void be_shutdown(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + be_cmd_reset_function(adapter); + + if (adapter->wol) + be_setup_wol(adapter, true); + + pci_disable_device(pdev); + + return; +} + static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, pci_channel_state_t state) { @@ -2544,6 +2564,7 @@ static struct pci_driver be_driver = { .remove = be_remove, .suspend = be_suspend, .resume = be_resume, + .shutdown = be_shutdown, .err_handler = &be_eeh_handlers }; -- cgit v1.2.3 From 60b86755929e1a7e9038c8d860a8491cfdf8d93a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 10:30:23 +0000 Subject: usbnet: Convert dev(dbg|err|warn|info) macros to netdev_ These macros are too similar to the dev_ equivalents but take a usbnet * argument. Convert them to the recently introduced netdev_ macros and remove the old macros. The old macros had "\n" appended to the format string. Add the "\n" to the converted uses. Some existing uses of the dev macros in cdc_eem.c probably mistakenly had trailing "\n". No "\n" added there. Fix net1080 this/other log message inversion. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 97 ++++++------ drivers/net/usb/cdc_eem.c | 10 +- drivers/net/usb/cdc_ether.c | 18 +-- drivers/net/usb/dm9601.c | 49 +++--- drivers/net/usb/int51x1.c | 15 +- drivers/net/usb/net1080.c | 101 ++++++------ drivers/net/usb/rndis_host.c | 10 +- drivers/net/usb/smsc95xx.c | 188 +++++++++++----------- drivers/net/usb/usbnet.c | 162 +++++++++---------- drivers/net/wireless/rndis_wlan.c | 325 ++++++++++++++++++++------------------ include/linux/usb/usbnet.h | 21 --- 11 files changed, 507 insertions(+), 489 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index f02551713b13..f605204de3e5 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -184,8 +184,8 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, void *buf; int err = -ENOMEM; - devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", - cmd, value, index, size); + netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); buf = kmalloc(size, GFP_KERNEL); if (!buf) @@ -217,8 +217,8 @@ static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, void *buf = NULL; int err = -ENOMEM; - devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", - cmd, value, index, size); + netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); if (data) { buf = kmalloc(size, GFP_KERNEL); @@ -264,15 +264,15 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, int status; struct urb *urb; - devdbg(dev,"asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d", - cmd, value, index, size); + netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n", + cmd, value, index, size); if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { - deverr(dev, "Error allocating URB in write_cmd_async!"); + netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n"); return; } if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { - deverr(dev, "Failed to allocate memory for control request"); + netdev_err(dev->net, "Failed to allocate memory for control request\n"); usb_free_urb(urb); return; } @@ -289,8 +289,8 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, asix_async_cmd_callback, req); if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - deverr(dev, "Error submitting the control message: status=%d", - status); + netdev_err(dev->net, "Error submitting the control message: status=%d\n", + status); kfree(req); usb_free_urb(urb); } @@ -314,7 +314,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) while (skb->len > 0) { if ((short)(header & 0x0000ffff) != ~((short)((header & 0xffff0000) >> 16))) { - deverr(dev,"asix_rx_fixup() Bad Header Length"); + netdev_err(dev->net, "asix_rx_fixup() Bad Header Length\n"); } /* get the packet length */ size = (u16) (header & 0x0000ffff); @@ -322,7 +322,8 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if ((skb->len) - ((size + 1) & 0xfffe) == 0) return 2; if (size > ETH_FRAME_LEN) { - deverr(dev,"asix_rx_fixup() Bad RX Length %d", size); + netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", + size); return 0; } ax_skb = skb_clone(skb, GFP_ATOMIC); @@ -348,7 +349,8 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } if (skb->len < 0) { - deverr(dev,"asix_rx_fixup() Bad SKB Length %d", skb->len); + netdev_err(dev->net, "asix_rx_fixup() Bad SKB Length %d\n", + skb->len); return 0; } return 1; @@ -409,7 +411,7 @@ static void asix_status(struct usbnet *dev, struct urb *urb) usbnet_defer_kevent (dev, EVENT_LINK_RESET ); } else netif_carrier_off(dev->net); - devdbg(dev, "Link Status is: %d", link); + netdev_dbg(dev->net, "Link Status is: %d\n", link); } } @@ -418,7 +420,7 @@ static inline int asix_set_sw_mii(struct usbnet *dev) int ret; ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); if (ret < 0) - deverr(dev, "Failed to enable software MII access"); + netdev_err(dev->net, "Failed to enable software MII access\n"); return ret; } @@ -427,7 +429,7 @@ static inline int asix_set_hw_mii(struct usbnet *dev) int ret; ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); if (ret < 0) - deverr(dev, "Failed to enable hardware MII access"); + netdev_err(dev->net, "Failed to enable hardware MII access\n"); return ret; } @@ -436,13 +438,14 @@ static inline int asix_get_phy_addr(struct usbnet *dev) u8 buf[2]; int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); - devdbg(dev, "asix_get_phy_addr()"); + netdev_dbg(dev->net, "asix_get_phy_addr()\n"); if (ret < 0) { - deverr(dev, "Error reading PHYID register: %02x", ret); + netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret); goto out; } - devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((__le16 *)buf)); + netdev_dbg(dev->net, "asix_get_phy_addr() returning 0x%04x\n", + *((__le16 *)buf)); ret = buf[1]; out: @@ -455,7 +458,7 @@ static int asix_sw_reset(struct usbnet *dev, u8 flags) ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); if (ret < 0) - deverr(dev,"Failed to send software reset: %02x", ret); + netdev_err(dev->net, "Failed to send software reset: %02x\n", ret); return ret; } @@ -466,7 +469,7 @@ static u16 asix_read_rx_ctl(struct usbnet *dev) int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); if (ret < 0) { - deverr(dev, "Error reading RX_CTL register: %02x", ret); + netdev_err(dev->net, "Error reading RX_CTL register: %02x\n", ret); goto out; } ret = le16_to_cpu(v); @@ -478,11 +481,11 @@ static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) { int ret; - devdbg(dev,"asix_write_rx_ctl() - mode = 0x%04x", mode); + netdev_dbg(dev->net, "asix_write_rx_ctl() - mode = 0x%04x\n", mode); ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); if (ret < 0) - deverr(dev, "Failed to write RX_CTL mode to 0x%04x: %02x", - mode, ret); + netdev_err(dev->net, "Failed to write RX_CTL mode to 0x%04x: %02x\n", + mode, ret); return ret; } @@ -493,7 +496,8 @@ static u16 asix_read_medium_status(struct usbnet *dev) int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); if (ret < 0) { - deverr(dev, "Error reading Medium Status register: %02x", ret); + netdev_err(dev->net, "Error reading Medium Status register: %02x\n", + ret); goto out; } ret = le16_to_cpu(v); @@ -505,11 +509,11 @@ static int asix_write_medium_mode(struct usbnet *dev, u16 mode) { int ret; - devdbg(dev,"asix_write_medium_mode() - mode = 0x%04x", mode); + netdev_dbg(dev->net, "asix_write_medium_mode() - mode = 0x%04x\n", mode); ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); if (ret < 0) - deverr(dev, "Failed to write Medium Mode mode to 0x%04x: %02x", - mode, ret); + netdev_err(dev->net, "Failed to write Medium Mode mode to 0x%04x: %02x\n", + mode, ret); return ret; } @@ -518,11 +522,11 @@ static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) { int ret; - devdbg(dev,"asix_write_gpio() - value = 0x%04x", value); + netdev_dbg(dev->net, "asix_write_gpio() - value = 0x%04x\n", value); ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); if (ret < 0) - deverr(dev, "Failed to write GPIO value 0x%04x: %02x", - value, ret); + netdev_err(dev->net, "Failed to write GPIO value 0x%04x: %02x\n", + value, ret); if (sleep) msleep(sleep); @@ -588,7 +592,8 @@ static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) asix_set_hw_mii(dev); mutex_unlock(&dev->phy_mutex); - devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res)); + netdev_dbg(dev->net, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", + phy_id, loc, le16_to_cpu(res)); return le16_to_cpu(res); } @@ -599,7 +604,8 @@ asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) struct usbnet *dev = netdev_priv(netdev); __le16 res = cpu_to_le16(val); - devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val); + netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", + phy_id, loc, val); mutex_lock(&dev->phy_mutex); asix_set_sw_mii(dev); asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); @@ -800,7 +806,8 @@ static int ax88172_link_reset(struct usbnet *dev) if (ecmd.duplex != DUPLEX_FULL) mode |= ~AX88172_MEDIUM_FD; - devdbg(dev, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", + ecmd.speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -902,7 +909,8 @@ static int ax88772_link_reset(struct usbnet *dev) if (ecmd.duplex != DUPLEX_FULL) mode &= ~AX_MEDIUM_FD; - devdbg(dev, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", + ecmd.speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -1059,10 +1067,10 @@ static int marvell_phy_init(struct usbnet *dev) struct asix_data *data = (struct asix_data *)&dev->data; u16 reg; - devdbg(dev,"marvell_phy_init()"); + netdev_dbg(dev->net, "marvell_phy_init()\n"); reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS); - devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg); + netdev_dbg(dev->net, "MII_MARVELL_STATUS = 0x%04x\n", reg); asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL, MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY); @@ -1070,7 +1078,7 @@ static int marvell_phy_init(struct usbnet *dev) if (data->ledmode) { reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_LED_CTRL); - devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg); + netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (1) = 0x%04x\n", reg); reg &= 0xf8ff; reg |= (1 + 0x0100); @@ -1079,7 +1087,7 @@ static int marvell_phy_init(struct usbnet *dev) reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_LED_CTRL); - devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg); + netdev_dbg(dev->net, "MII_MARVELL_LED_CTRL (2) = 0x%04x\n", reg); reg &= 0xfc0f; } @@ -1090,7 +1098,7 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) { u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); - devdbg(dev, "marvell_led_status() read 0x%04x", reg); + netdev_dbg(dev->net, "marvell_led_status() read 0x%04x\n", reg); /* Clear out the center LED bits - 0x03F0 */ reg &= 0xfc0f; @@ -1106,7 +1114,7 @@ static int marvell_led_status(struct usbnet *dev, u16 speed) reg |= 0x02f0; } - devdbg(dev, "marvell_led_status() writing 0x%04x", reg); + netdev_dbg(dev->net, "marvell_led_status() writing 0x%04x\n", reg); asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg); return 0; @@ -1118,7 +1126,7 @@ static int ax88178_link_reset(struct usbnet *dev) struct ethtool_cmd ecmd; struct asix_data *data = (struct asix_data *)&dev->data; - devdbg(dev,"ax88178_link_reset()"); + netdev_dbg(dev->net, "ax88178_link_reset()\n"); mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); @@ -1138,7 +1146,8 @@ static int ax88178_link_reset(struct usbnet *dev) else mode &= ~AX_MEDIUM_FD; - devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); + netdev_dbg(dev->net, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x\n", + ecmd.speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); @@ -1188,7 +1197,7 @@ static int ax88178_change_mtu(struct net_device *net, int new_mtu) struct usbnet *dev = netdev_priv(net); int ll_mtu = new_mtu + net->hard_header_len + 4; - devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu); + netdev_dbg(dev->net, "ax88178_change_mtu() new_mtu=%d\n", new_mtu); if (new_mtu <= 0 || ll_mtu > 16384) return -EINVAL; diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index c337ffc3304a..a4a85a6ed86d 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -73,7 +73,7 @@ static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb) usb_free_urb(urb); fail: dev_kfree_skb(skb); - devwarn(dev, "link cmd failure\n"); + netdev_warn(dev->net, "link cmd failure\n"); return; } } @@ -212,7 +212,8 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) * b15: 1 (EEM command) */ if (header & BIT(14)) { - devdbg(dev, "reserved command %04x\n", header); + netdev_dbg(dev->net, "reserved command %04x\n", + header); continue; } @@ -255,8 +256,9 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) case 1: /* Echo response */ case 5: /* Tickle */ default: /* reserved */ - devwarn(dev, "unexpected link command %d\n", - bmEEMCmd); + netdev_warn(dev->net, + "unexpected link command %d\n", + bmEEMCmd); continue; } diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 4f27f022fbf7..7e5a75269cc5 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -340,9 +340,9 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); static void dumpspeed(struct usbnet *dev, __le32 *speeds) { if (netif_msg_timer(dev)) - devinfo(dev, "link speeds: %u kbps up, %u kbps down", - __le32_to_cpu(speeds[0]) / 1000, - __le32_to_cpu(speeds[1]) / 1000); + netdev_info(dev->net, "link speeds: %u kbps up, %u kbps down\n", + __le32_to_cpu(speeds[0]) / 1000, + __le32_to_cpu(speeds[1]) / 1000); } static void cdc_status(struct usbnet *dev, struct urb *urb) @@ -362,8 +362,8 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) switch (event->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: if (netif_msg_timer(dev)) - devdbg(dev, "CDC: carrier %s", - event->wValue ? "on" : "off"); + netdev_dbg(dev->net, "CDC: carrier %s\n", + event->wValue ? "on" : "off"); if (event->wValue) netif_carrier_on(dev->net); else @@ -371,8 +371,8 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) break; case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ if (netif_msg_timer(dev)) - devdbg(dev, "CDC: speed change (len %d)", - urb->actual_length); + netdev_dbg(dev->net, "CDC: speed change (len %d)\n", + urb->actual_length); if (urb->actual_length != (sizeof *event + 8)) set_bit(EVENT_STS_SPLIT, &dev->flags); else @@ -382,8 +382,8 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) * but there are no standard formats for the response data. */ default: - deverr(dev, "CDC: unexpected notification %02x!", - event->bNotificationType); + netdev_err(dev->net, "CDC: unexpected notification %02x!\n", + event->bNotificationType); break; } } diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index c820fec62041..269339769f47 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -58,7 +58,7 @@ static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) void *buf; int err = -ENOMEM; - devdbg(dev, "dm_read() reg=0x%02x length=%d", reg, length); + netdev_dbg(dev->net, "dm_read() reg=0x%02x length=%d\n", reg, length); buf = kmalloc(length, GFP_KERNEL); if (!buf) @@ -89,7 +89,7 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) void *buf = NULL; int err = -ENOMEM; - devdbg(dev, "dm_write() reg=0x%02x, length=%d", reg, length); + netdev_dbg(dev->net, "dm_write() reg=0x%02x, length=%d\n", reg, length); if (data) { buf = kmalloc(length, GFP_KERNEL); @@ -112,7 +112,8 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) { - devdbg(dev, "dm_write_reg() reg=0x%02x, value=0x%02x", reg, value); + netdev_dbg(dev->net, "dm_write_reg() reg=0x%02x, value=0x%02x\n", + reg, value); return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), DM_WRITE_REG, @@ -142,13 +143,13 @@ static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - deverr(dev, "Error allocating URB in dm_write_async_helper!"); + netdev_err(dev->net, "Error allocating URB in dm_write_async_helper!\n"); return; } req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); if (!req) { - deverr(dev, "Failed to allocate memory for control request"); + netdev_err(dev->net, "Failed to allocate memory for control request\n"); usb_free_urb(urb); return; } @@ -166,8 +167,8 @@ static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { - deverr(dev, "Error submitting the control message: status=%d", - status); + netdev_err(dev->net, "Error submitting the control message: status=%d\n", + status); kfree(req); usb_free_urb(urb); } @@ -175,15 +176,15 @@ static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) { - devdbg(dev, "dm_write_async() reg=0x%02x length=%d", reg, length); + netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); dm_write_async_helper(dev, reg, 0, length, data); } static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) { - devdbg(dev, "dm_write_reg_async() reg=0x%02x value=0x%02x", - reg, value); + netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n", + reg, value); dm_write_async_helper(dev, reg, value, 0, NULL); } @@ -211,7 +212,7 @@ static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *valu } if (i == DM_TIMEOUT) { - deverr(dev, "%s read timed out!", phy ? "phy" : "eeprom"); + netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom"); ret = -EIO; goto out; } @@ -219,8 +220,8 @@ static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *valu dm_write_reg(dev, DM_SHARED_CTRL, 0x0); ret = dm_read(dev, DM_SHARED_DATA, 2, value); - devdbg(dev, "read shared %d 0x%02x returned 0x%04x, %d", - phy, reg, *value, ret); + netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n", + phy, reg, *value, ret); out: mutex_unlock(&dev->phy_mutex); @@ -254,7 +255,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu } if (i == DM_TIMEOUT) { - deverr(dev, "%s write timed out!", phy ? "phy" : "eeprom"); + netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom"); ret = -EIO; goto out; } @@ -304,15 +305,15 @@ static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc) __le16 res; if (phy_id) { - devdbg(dev, "Only internal phy supported"); + netdev_dbg(dev->net, "Only internal phy supported\n"); return 0; } dm_read_shared_word(dev, 1, loc, &res); - devdbg(dev, - "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", - phy_id, loc, le16_to_cpu(res)); + netdev_dbg(dev->net, + "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", + phy_id, loc, le16_to_cpu(res)); return le16_to_cpu(res); } @@ -324,12 +325,12 @@ static void dm9601_mdio_write(struct net_device *netdev, int phy_id, int loc, __le16 res = cpu_to_le16(val); if (phy_id) { - devdbg(dev, "Only internal phy supported"); + netdev_dbg(dev->net, "Only internal phy supported\n"); return; } - devdbg(dev,"dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", - phy_id, loc, val); + netdev_dbg(dev->net, "dm9601_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", + phy_id, loc, val); dm_write_shared_word(dev, 1, loc, res); } @@ -592,7 +593,7 @@ static void dm9601_status(struct usbnet *dev, struct urb *urb) } else netif_carrier_off(dev->net); - devdbg(dev, "Link Status is: %d", link); + netdev_dbg(dev->net, "Link Status is: %d\n", link); } } @@ -603,8 +604,8 @@ static int dm9601_link_reset(struct usbnet *dev) mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); - devdbg(dev, "link_reset() speed: %d duplex: %d", - ecmd.speed, ecmd.duplex); + netdev_dbg(dev->net, "link_reset() speed: %d duplex: %d\n", + ecmd.speed, ecmd.duplex); return 0; } diff --git a/drivers/net/usb/int51x1.c b/drivers/net/usb/int51x1.c index 9ab5c1983a7d..3c228df57062 100644 --- a/drivers/net/usb/int51x1.c +++ b/drivers/net/usb/int51x1.c @@ -51,7 +51,7 @@ static int int51x1_rx_fixup(struct usbnet *dev, struct sk_buff *skb) int len; if (!(pskb_may_pull(skb, INT51X1_HEADER_SIZE))) { - deverr(dev, "unexpected tiny rx frame"); + netdev_err(dev->net, "unexpected tiny rx frame\n"); return 0; } @@ -138,25 +138,25 @@ static void int51x1_set_multicast(struct net_device *netdev) if (netdev->flags & IFF_PROMISC) { /* do not expect to see traffic of other PLCs */ filter |= PACKET_TYPE_PROMISCUOUS; - devinfo(dev, "promiscuous mode enabled"); + netdev_info(dev->net, "promiscuous mode enabled\n"); } else if (!netdev_mc_empty(netdev) || (netdev->flags & IFF_ALLMULTI)) { filter |= PACKET_TYPE_ALL_MULTICAST; - devdbg(dev, "receive all multicast enabled"); + netdev_dbg(dev->net, "receive all multicast enabled\n"); } else { /* ~PROMISCUOUS, ~MULTICAST */ - devdbg(dev, "receive own packets only"); + netdev_dbg(dev->net, "receive own packets only\n"); } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - devwarn(dev, "Error allocating URB"); + netdev_warn(dev->net, "Error allocating URB\n"); return; } req = kmalloc(sizeof(*req), GFP_ATOMIC); if (!req) { - devwarn(dev, "Error allocating control msg"); + netdev_warn(dev->net, "Error allocating control msg\n"); goto out; } @@ -173,7 +173,8 @@ static void int51x1_set_multicast(struct net_device *netdev) status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { - devwarn(dev, "Error submitting control msg, sts=%d", status); + netdev_warn(dev->net, "Error submitting control msg, sts=%d\n", + status); goto out1; } return; diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index aeb1ab03a9ee..f6994053c101 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -205,23 +205,24 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl) { if (!netif_msg_link(dev)) return; - devdbg(dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" - " this%s%s;" - " other%s%s; r/o 0x%x", - dev->udev->bus->bus_name, dev->udev->devpath, - usbctl, - (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", - (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", - (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", - (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", - (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", - - (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", - (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", - usbctl & ~USBCTL_WRITABLE_MASK - ); + netdev_dbg(dev->net, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" + " this%s%s;" + " other%s%s; r/o 0x%x\n", + dev->udev->bus->bus_name, dev->udev->devpath, + usbctl, + (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", + (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", + (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", + (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", + (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", + + (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", + + (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", + + usbctl & ~USBCTL_WRITABLE_MASK); } /*-------------------------------------------------------------------------*/ @@ -250,28 +251,25 @@ static inline void nc_dump_status(struct usbnet *dev, u16 status) { if (!netif_msg_link(dev)) return; - devdbg(dev, "net1080 %s-%s status 0x%x:" - " this (%c) PKT=%d%s%s%s;" - " other PKT=%d%s%s%s; unspec 0x%x", - dev->udev->bus->bus_name, dev->udev->devpath, - status, - - // XXX the packet counts don't seem right - // (1 at reset, not 0); maybe UNSPEC too - - (status & STATUS_PORT_A) ? 'A' : 'B', - STATUS_PACKETS_THIS(status), - (status & STATUS_CONN_THIS) ? " CON" : "", - (status & STATUS_SUSPEND_THIS) ? " SUS" : "", - (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", - - STATUS_PACKETS_OTHER(status), - (status & STATUS_CONN_OTHER) ? " CON" : "", - (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", - (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", - - status & STATUS_UNSPEC_MASK - ); + netdev_dbg(dev->net, "net1080 %s-%s status 0x%x: this (%c) PKT=%d%s%s%s; other PKT=%d%s%s%s; unspec 0x%x\n", + dev->udev->bus->bus_name, dev->udev->devpath, + status, + + // XXX the packet counts don't seem right + // (1 at reset, not 0); maybe UNSPEC too + + (status & STATUS_PORT_A) ? 'A' : 'B', + STATUS_PACKETS_THIS(status), + (status & STATUS_CONN_THIS) ? " CON" : "", + (status & STATUS_SUSPEND_THIS) ? " SUS" : "", + (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", + + STATUS_PACKETS_OTHER(status), + (status & STATUS_CONN_OTHER) ? " CON" : "", + (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", + (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", + + status & STATUS_UNSPEC_MASK); } /*-------------------------------------------------------------------------*/ @@ -287,9 +285,9 @@ static inline void nc_dump_status(struct usbnet *dev, u16 status) static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl) { if (netif_msg_link(dev)) - devdbg(dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d", - dev->udev->bus->bus_name, dev->udev->devpath, - ttl, TTL_THIS(ttl), TTL_OTHER(ttl)); + netdev_dbg(dev->net, "net1080 %s-%s ttl 0x%x this = %d, other = %d\n", + dev->udev->bus->bus_name, dev->udev->devpath, + ttl, TTL_THIS(ttl), TTL_OTHER(ttl)); } /*-------------------------------------------------------------------------*/ @@ -335,10 +333,9 @@ static int net1080_reset(struct usbnet *dev) dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS); if (netif_msg_link(dev)) - devinfo(dev, "port %c, peer %sconnected", - (status & STATUS_PORT_A) ? 'A' : 'B', - (status & STATUS_CONN_OTHER) ? "" : "dis" - ); + netdev_info(dev->net, "port %c, peer %sconnected\n", + (status & STATUS_PORT_A) ? 'A' : 'B', + (status & STATUS_CONN_OTHER) ? "" : "dis"); retval = 0; done: @@ -416,7 +413,7 @@ static void nc_ensure_sync(struct usbnet *dev) } if (netif_msg_rx_err(dev)) - devdbg(dev, "flush net1080; too many framing errors"); + netdev_dbg(dev->net, "flush net1080; too many framing errors\n"); dev->frame_errors = 0; } } @@ -486,8 +483,8 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 0; } #if 0 - devdbg(dev, "frame hdr_len, - header->packet_len, header->packet_id); + netdev_dbg(dev->net, "frame hdr_len, + header->packet_len, header->packet_id); #endif dev->frame_errors = 0; return 1; @@ -547,9 +544,9 @@ encapsulate: trailer = (struct nc_trailer *) skb_put(skb, sizeof *trailer); put_unaligned(header->packet_id, &trailer->packet_id); #if 0 - devdbg(dev, "frame >tx h %d p %d id %d", - header->hdr_len, header->packet_len, - header->packet_id); + netdev_dbg(dev->net, "frame >tx h %d p %d id %d\n", + header->hdr_len, header->packet_len, + header->packet_id); #endif return skb; } diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 490fa8f55424..f01f02401856 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -57,8 +57,8 @@ */ void rndis_status(struct usbnet *dev, struct urb *urb) { - devdbg(dev, "rndis status urb, len %d stat %d", - urb->actual_length, urb->status); + netdev_dbg(dev->net, "rndis status urb, len %d stat %d\n", + urb->actual_length, urb->status); // FIXME for keepalives, respond immediately (asynchronously) // if not an RNDIS status, do like cdc_status(dev,urb) does } @@ -497,9 +497,9 @@ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb->len < msg_len || (data_offset + data_len + 8) > msg_len)) { dev->net->stats.rx_frame_errors++; - devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d", - le32_to_cpu(hdr->msg_type), - msg_len, data_offset, data_len, skb->len); + netdev_dbg(dev->net, "bad rndis message %d/%d/%d/%d, len %d\n", + le32_to_cpu(hdr->msg_type), + msg_len, data_offset, data_len, skb->len); return 0; } skb_pull(skb, 8 + data_offset); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 48555d0e374d..d4cbcefbff38 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -78,7 +78,7 @@ static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) 00, index, buf, 4, USB_CTRL_GET_TIMEOUT); if (unlikely(ret < 0)) - devwarn(dev, "Failed to read register index 0x%08x", index); + netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index); le32_to_cpus(buf); *data = *buf; @@ -106,7 +106,7 @@ static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data) 00, index, buf, 4, USB_CTRL_SET_TIMEOUT); if (unlikely(ret < 0)) - devwarn(dev, "Failed to write register index 0x%08x", index); + netdev_warn(dev->net, "Failed to write register index 0x%08x\n", index); kfree(buf); @@ -138,7 +138,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) /* confirm MII not busy */ if (smsc95xx_phy_wait_not_busy(dev)) { - devwarn(dev, "MII is busy in smsc95xx_mdio_read"); + netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n"); mutex_unlock(&dev->phy_mutex); return -EIO; } @@ -150,7 +150,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) smsc95xx_write_reg(dev, MII_ADDR, addr); if (smsc95xx_phy_wait_not_busy(dev)) { - devwarn(dev, "Timed out reading MII reg %02X", idx); + netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx); mutex_unlock(&dev->phy_mutex); return -EIO; } @@ -172,7 +172,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, /* confirm MII not busy */ if (smsc95xx_phy_wait_not_busy(dev)) { - devwarn(dev, "MII is busy in smsc95xx_mdio_write"); + netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n"); mutex_unlock(&dev->phy_mutex); return; } @@ -187,7 +187,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, smsc95xx_write_reg(dev, MII_ADDR, addr); if (smsc95xx_phy_wait_not_busy(dev)) - devwarn(dev, "Timed out writing MII reg %02X", idx); + netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx); mutex_unlock(&dev->phy_mutex); } @@ -205,7 +205,7 @@ static int smsc95xx_wait_eeprom(struct usbnet *dev) } while (!time_after(jiffies, start_time + HZ)); if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) { - devwarn(dev, "EEPROM read operation timeout"); + netdev_warn(dev->net, "EEPROM read operation timeout\n"); return -EIO; } @@ -226,7 +226,7 @@ static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev) udelay(40); } while (!time_after(jiffies, start_time + HZ)); - devwarn(dev, "EEPROM is busy"); + netdev_warn(dev->net, "EEPROM is busy\n"); return -EIO; } @@ -308,7 +308,7 @@ static void smsc95xx_async_cmd_callback(struct urb *urb) int status = urb->status; if (status < 0) - devwarn(dev, "async callback failed with %d", status); + netdev_warn(dev->net, "async callback failed with %d\n", status); kfree(usb_context); usb_free_urb(urb); @@ -323,13 +323,13 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - devwarn(dev, "Error allocating URB"); + netdev_warn(dev->net, "Error allocating URB\n"); return -ENOMEM; } usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC); if (usb_context == NULL) { - devwarn(dev, "Error allocating control msg"); + netdev_warn(dev->net, "Error allocating control msg\n"); usb_free_urb(urb); return -ENOMEM; } @@ -348,7 +348,8 @@ static int smsc95xx_write_reg_async(struct usbnet *dev, u16 index, u32 *data) status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { - devwarn(dev, "Error submitting control msg, sts=%d", status); + netdev_warn(dev->net, "Error submitting control msg, sts=%d\n", + status); kfree(usb_context); usb_free_urb(urb); } @@ -376,12 +377,12 @@ static void smsc95xx_set_multicast(struct net_device *netdev) if (dev->net->flags & IFF_PROMISC) { if (netif_msg_drv(dev)) - devdbg(dev, "promiscuous mode enabled"); + netdev_dbg(dev->net, "promiscuous mode enabled\n"); pdata->mac_cr |= MAC_CR_PRMS_; pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_); } else if (dev->net->flags & IFF_ALLMULTI) { if (netif_msg_drv(dev)) - devdbg(dev, "receive all multicast enabled"); + netdev_dbg(dev->net, "receive all multicast enabled\n"); pdata->mac_cr |= MAC_CR_MCPAS_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev->net)) { @@ -401,20 +402,20 @@ static void smsc95xx_set_multicast(struct net_device *netdev) else hash_lo |= mask; } else { - devwarn(dev, "dmi_addrlen != 6"); + netdev_warn(dev->net, "dmi_addrlen != 6\n"); } mc_list = mc_list->next; } if (count != ((u32) netdev_mc_count(dev->net))) - devwarn(dev, "mc_count != dev->mc_count"); + netdev_warn(dev->net, "mc_count != dev->mc_count\n"); if (netif_msg_drv(dev)) - devdbg(dev, "HASHH=0x%08X, HASHL=0x%08X", hash_hi, - hash_lo); + netdev_dbg(dev->net, "HASHH=0x%08X, HASHL=0x%08X\n", + hash_hi, hash_lo); } else { if (netif_msg_drv(dev)) - devdbg(dev, "receive own packets only"); + netdev_dbg(dev->net, "receive own packets only\n"); pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_); } @@ -434,7 +435,7 @@ static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); if (ret < 0) { - devwarn(dev, "error reading AFC_CFG"); + netdev_warn(dev->net, "error reading AFC_CFG\n"); return; } @@ -452,12 +453,12 @@ static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, afc_cfg &= ~0xF; if (netif_msg_link(dev)) - devdbg(dev, "rx pause %s, tx pause %s", - (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), - (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); + netdev_dbg(dev->net, "rx pause %s, tx pause %s\n", + cap & FLOW_CTRL_RX ? "enabled" : "disabled", + cap & FLOW_CTRL_TX ? "enabled" : "disabled"); } else { if (netif_msg_link(dev)) - devdbg(dev, "half duplex"); + netdev_dbg(dev->net, "half duplex\n"); flow = 0; afc_cfg |= 0xF; } @@ -486,8 +487,8 @@ static int smsc95xx_link_reset(struct usbnet *dev) rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); if (netif_msg_link(dev)) - devdbg(dev, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x", - ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netdev_dbg(dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", + ecmd.speed, ecmd.duplex, lcladv, rmtadv); spin_lock_irqsave(&pdata->mac_cr_lock, flags); if (ecmd.duplex != DUPLEX_FULL) { @@ -511,7 +512,8 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) u32 intdata; if (urb->actual_length != 4) { - devwarn(dev, "unexpected urb length %d", urb->actual_length); + netdev_warn(dev->net, "unexpected urb length %d\n", + urb->actual_length); return; } @@ -519,12 +521,13 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) le32_to_cpus(&intdata); if (netif_msg_link(dev)) - devdbg(dev, "intdata: 0x%08X", intdata); + netdev_dbg(dev->net, "intdata: 0x%08X\n", intdata); if (intdata & INT_ENP_PHY_INT_) usbnet_defer_kevent(dev, EVENT_LINK_RESET); else - devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata); + netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n", + intdata); } /* Enable or disable Tx & Rx checksum offload engines */ @@ -534,7 +537,7 @@ static int smsc95xx_set_csums(struct usbnet *dev) u32 read_buf; int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read COE_CR: %d", ret); + netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret); return ret; } @@ -550,12 +553,12 @@ static int smsc95xx_set_csums(struct usbnet *dev) ret = smsc95xx_write_reg(dev, COE_CR, read_buf); if (ret < 0) { - devwarn(dev, "Failed to write COE_CR: %d", ret); + netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret); return ret; } if (netif_msg_hw(dev)) - devdbg(dev, "COE_CR = 0x%08x", read_buf); + netdev_dbg(dev->net, "COE_CR = 0x%08x\n", read_buf); return 0; } @@ -580,8 +583,8 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, struct usbnet *dev = netdev_priv(netdev); if (ee->magic != LAN95XX_EEPROM_MAGIC) { - devwarn(dev, "EEPROM: magic value mismatch, magic = 0x%x", - ee->magic); + netdev_warn(dev->net, "EEPROM: magic value mismatch, magic = 0x%x\n", + ee->magic); return -EINVAL; } @@ -660,7 +663,7 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) if (is_valid_ether_addr(dev->net->dev_addr)) { /* eeprom values are valid so use them */ if (netif_msg_ifup(dev)) - devdbg(dev, "MAC address read from EEPROM"); + netdev_dbg(dev->net, "MAC address read from EEPROM\n"); return; } } @@ -668,7 +671,7 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) /* no eeprom, or eeprom values are invalid. generate random MAC */ random_ether_addr(dev->net->dev_addr); if (netif_msg_ifup(dev)) - devdbg(dev, "MAC address set to random_ether_addr"); + netdev_dbg(dev->net, "MAC address set to random_ether_addr\n"); } static int smsc95xx_set_mac_address(struct usbnet *dev) @@ -680,13 +683,13 @@ static int smsc95xx_set_mac_address(struct usbnet *dev) ret = smsc95xx_write_reg(dev, ADDRL, addr_lo); if (ret < 0) { - devwarn(dev, "Failed to write ADDRL: %d", ret); + netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret); return ret; } ret = smsc95xx_write_reg(dev, ADDRH, addr_hi); if (ret < 0) { - devwarn(dev, "Failed to write ADDRH: %d", ret); + netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret); return ret; } @@ -748,7 +751,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev) mii_nway_restart(&dev->mii); if (netif_msg_ifup(dev)) - devdbg(dev, "phy initialised successfully"); + netdev_dbg(dev->net, "phy initialised successfully\n"); return 0; } @@ -760,13 +763,13 @@ static int smsc95xx_reset(struct usbnet *dev) int ret = 0, timeout; if (netif_msg_ifup(dev)) - devdbg(dev, "entering smsc95xx_reset"); + netdev_dbg(dev->net, "entering smsc95xx_reset\n"); write_buf = HW_CFG_LRST_; ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write HW_CFG_LRST_ bit in HW_CFG " - "register, ret = %d", ret); + netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = %d\n", + ret); return ret; } @@ -774,7 +777,7 @@ static int smsc95xx_reset(struct usbnet *dev) do { ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read HW_CFG: %d", ret); + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } msleep(10); @@ -782,14 +785,14 @@ static int smsc95xx_reset(struct usbnet *dev) } while ((read_buf & HW_CFG_LRST_) && (timeout < 100)); if (timeout >= 100) { - devwarn(dev, "timeout waiting for completion of Lite Reset"); + netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n"); return ret; } write_buf = PM_CTL_PHY_RST_; ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write PM_CTRL: %d", ret); + netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret); return ret; } @@ -797,7 +800,7 @@ static int smsc95xx_reset(struct usbnet *dev) do { ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read PM_CTRL: %d", ret); + netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret); return ret; } msleep(10); @@ -805,7 +808,7 @@ static int smsc95xx_reset(struct usbnet *dev) } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100)); if (timeout >= 100) { - devwarn(dev, "timeout waiting for PHY Reset"); + netdev_warn(dev->net, "timeout waiting for PHY Reset\n"); return ret; } @@ -816,34 +819,34 @@ static int smsc95xx_reset(struct usbnet *dev) return ret; if (netif_msg_ifup(dev)) - devdbg(dev, "MAC Address: %pM", dev->net->dev_addr); + netdev_dbg(dev->net, "MAC Address: %pM\n", dev->net->dev_addr); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read HW_CFG: %d", ret); + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from HW_CFG : 0x%08x", read_buf); + netdev_dbg(dev->net, "Read Value from HW_CFG : 0x%08x\n", read_buf); read_buf |= HW_CFG_BIR_; ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); if (ret < 0) { - devwarn(dev, "Failed to write HW_CFG_BIR_ bit in HW_CFG " - "register, ret = %d", ret); + netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG register, ret = %d\n", + ret); return ret; } ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read HW_CFG: %d", ret); + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from HW_CFG after writing " - "HW_CFG_BIR_: 0x%08x", read_buf); + netdev_dbg(dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n", + read_buf); if (!turbo_mode) { burst_cap = 0; @@ -857,46 +860,46 @@ static int smsc95xx_reset(struct usbnet *dev) } if (netif_msg_ifup(dev)) - devdbg(dev, "rx_urb_size=%ld", (ulong)dev->rx_urb_size); + netdev_dbg(dev->net, "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size); ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); if (ret < 0) { - devwarn(dev, "Failed to write BURST_CAP: %d", ret); + netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret); return ret; } ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read BURST_CAP: %d", ret); + netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from BURST_CAP after writing: 0x%08x", - read_buf); + netdev_dbg(dev->net, "Read Value from BURST_CAP after writing: 0x%08x\n", + read_buf); read_buf = DEFAULT_BULK_IN_DELAY; ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); if (ret < 0) { - devwarn(dev, "ret = %d", ret); + netdev_warn(dev->net, "ret = %d\n", ret); return ret; } ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read BULK_IN_DLY: %d", ret); + netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from BULK_IN_DLY after writing: " - "0x%08x", read_buf); + netdev_dbg(dev->net, "Read Value from BULK_IN_DLY after writing: 0x%08x\n", + read_buf); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read HW_CFG: %d", ret); + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from HW_CFG: 0x%08x", read_buf); + netdev_dbg(dev->net, "Read Value from HW_CFG: 0x%08x\n", read_buf); if (turbo_mode) read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_); @@ -908,41 +911,43 @@ static int smsc95xx_reset(struct usbnet *dev) ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); if (ret < 0) { - devwarn(dev, "Failed to write HW_CFG register, ret=%d", ret); + netdev_warn(dev->net, "Failed to write HW_CFG register, ret=%d\n", + ret); return ret; } ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read HW_CFG: %d", ret); + netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "Read Value from HW_CFG after writing: 0x%08x", - read_buf); + netdev_dbg(dev->net, "Read Value from HW_CFG after writing: 0x%08x\n", + read_buf); write_buf = 0xFFFFFFFF; ret = smsc95xx_write_reg(dev, INT_STS, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write INT_STS register, ret=%d", ret); + netdev_warn(dev->net, "Failed to write INT_STS register, ret=%d\n", + ret); return ret; } ret = smsc95xx_read_reg(dev, ID_REV, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read ID_REV: %d", ret); + netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret); return ret; } if (netif_msg_ifup(dev)) - devdbg(dev, "ID_REV = 0x%08x", read_buf); + netdev_dbg(dev->net, "ID_REV = 0x%08x\n", read_buf); /* Configure GPIO pins as LED outputs */ write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | LED_GPIO_CFG_FDX_LED; ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write LED_GPIO_CFG register, ret=%d", - ret); + netdev_warn(dev->net, "Failed to write LED_GPIO_CFG register, ret=%d\n", + ret); return ret; } @@ -950,21 +955,21 @@ static int smsc95xx_reset(struct usbnet *dev) write_buf = 0; ret = smsc95xx_write_reg(dev, FLOW, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write FLOW: %d", ret); + netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret); return ret; } read_buf = AFC_CFG_DEFAULT; ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf); if (ret < 0) { - devwarn(dev, "Failed to write AFC_CFG: %d", ret); + netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret); return ret; } /* Don't need mac_cr_lock during initialisation */ ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr); if (ret < 0) { - devwarn(dev, "Failed to read MAC_CR: %d", ret); + netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret); return ret; } @@ -973,7 +978,7 @@ static int smsc95xx_reset(struct usbnet *dev) write_buf = (u32)ETH_P_8021Q; ret = smsc95xx_write_reg(dev, VLAN1, write_buf); if (ret < 0) { - devwarn(dev, "Failed to write VAN1: %d", ret); + netdev_warn(dev->net, "Failed to write VAN1: %d\n", ret); return ret; } @@ -981,7 +986,7 @@ static int smsc95xx_reset(struct usbnet *dev) ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum); ret = smsc95xx_set_csums(dev); if (ret < 0) { - devwarn(dev, "Failed to set csum offload: %d", ret); + netdev_warn(dev->net, "Failed to set csum offload: %d\n", ret); return ret; } @@ -992,7 +997,7 @@ static int smsc95xx_reset(struct usbnet *dev) ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf); if (ret < 0) { - devwarn(dev, "Failed to read INT_EP_CTL: %d", ret); + netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret); return ret; } @@ -1001,7 +1006,7 @@ static int smsc95xx_reset(struct usbnet *dev) ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf); if (ret < 0) { - devwarn(dev, "Failed to write INT_EP_CTL: %d", ret); + netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret); return ret; } @@ -1009,7 +1014,7 @@ static int smsc95xx_reset(struct usbnet *dev) smsc95xx_start_rx_path(dev); if (netif_msg_ifup(dev)) - devdbg(dev, "smsc95xx_reset, return 0"); + netdev_dbg(dev->net, "smsc95xx_reset, return 0\n"); return 0; } @@ -1034,7 +1039,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) ret = usbnet_get_endpoints(dev, intf); if (ret < 0) { - devwarn(dev, "usbnet_get_endpoints failed: %d", ret); + netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret); return ret; } @@ -1043,7 +1048,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) pdata = (struct smsc95xx_priv *)(dev->data[0]); if (!pdata) { - devwarn(dev, "Unable to allocate struct smsc95xx_priv"); + netdev_warn(dev->net, "Unable to allocate struct smsc95xx_priv\n"); return -ENOMEM; } @@ -1067,7 +1072,7 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); if (pdata) { if (netif_msg_ifdown(dev)) - devdbg(dev, "free pdata"); + netdev_dbg(dev->net, "free pdata\n"); kfree(pdata); pdata = NULL; dev->data[0] = 0; @@ -1102,7 +1107,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (unlikely(header & RX_STS_ES_)) { if (netif_msg_rx_err(dev)) - devdbg(dev, "Error header=0x%08x", header); + netdev_dbg(dev->net, "Error header=0x%08x\n", + header); dev->net->stats.rx_errors++; dev->net->stats.rx_dropped++; @@ -1120,8 +1126,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ if (unlikely(size > (ETH_FRAME_LEN + 12))) { if (netif_msg_rx_err(dev)) - devdbg(dev, "size err header=0x%08x", - header); + netdev_dbg(dev->net, "size err header=0x%08x\n", + header); return 0; } @@ -1137,7 +1143,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) ax_skb = skb_clone(skb, GFP_ATOMIC); if (unlikely(!ax_skb)) { - devwarn(dev, "Error allocating skb"); + netdev_warn(dev->net, "Error allocating skb\n"); return 0; } @@ -1161,7 +1167,7 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } if (unlikely(skb->len < 0)) { - devwarn(dev, "invalid rx length<0 %d", skb->len); + netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len); return 0; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 035fab04c0a0..8e732930d249 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -243,12 +243,12 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) dev->net->stats.rx_bytes += skb->len; if (netif_msg_rx_status (dev)) - devdbg (dev, "< rx, len %zu, type 0x%x", - skb->len + sizeof (struct ethhdr), skb->protocol); + netdev_dbg(dev->net, "< rx, len %zu, type 0x%x\n", + skb->len + sizeof (struct ethhdr), skb->protocol); memset (skb->cb, 0, sizeof (struct skb_data)); status = netif_rx (skb); if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev)) - devdbg (dev, "netif_rx status %d", status); + netdev_dbg(dev->net, "netif_rx status %d\n", status); } EXPORT_SYMBOL_GPL(usbnet_skb_return); @@ -313,9 +313,9 @@ void usbnet_defer_kevent (struct usbnet *dev, int work) { set_bit (work, &dev->flags); if (!schedule_work (&dev->kevent)) - deverr (dev, "kevent %d may have been dropped", work); + netdev_err(dev->net, "kevent %d may have been dropped\n", work); else - devdbg (dev, "kevent %d scheduled", work); + netdev_dbg(dev->net, "kevent %d scheduled\n", work); } EXPORT_SYMBOL_GPL(usbnet_defer_kevent); @@ -333,7 +333,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { if (netif_msg_rx_err (dev)) - devdbg (dev, "no rx skb"); + netdev_dbg(dev->net, "no rx skb\n"); usbnet_defer_kevent (dev, EVENT_RX_MEMORY); usb_free_urb (urb); return; @@ -364,12 +364,12 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) break; case -ENODEV: if (netif_msg_ifdown (dev)) - devdbg (dev, "device gone"); + netdev_dbg(dev->net, "device gone\n"); netif_device_detach (dev->net); break; default: if (netif_msg_rx_err (dev)) - devdbg (dev, "rx submit, %d", retval); + netdev_dbg(dev->net, "rx submit, %d\n", retval); tasklet_schedule (&dev->bh); break; case 0: @@ -377,7 +377,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) } } else { if (netif_msg_ifdown (dev)) - devdbg (dev, "rx: stopped"); + netdev_dbg(dev->net, "rx: stopped\n"); retval = -ENOLINK; } spin_unlock_irqrestore (&dev->rxq.lock, lockflags); @@ -401,7 +401,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) usbnet_skb_return (dev, skb); else { if (netif_msg_rx_err (dev)) - devdbg (dev, "drop"); + netdev_dbg(dev->net, "drop\n"); error: dev->net->stats.rx_errors++; skb_queue_tail (&dev->done, skb); @@ -429,7 +429,7 @@ static void rx_complete (struct urb *urb) dev->net->stats.rx_errors++; dev->net->stats.rx_length_errors++; if (netif_msg_rx_err (dev)) - devdbg (dev, "rx length %d", skb->len); + netdev_dbg(dev->net, "rx length %d\n", skb->len); } break; @@ -447,7 +447,7 @@ static void rx_complete (struct urb *urb) case -ECONNRESET: /* async unlink */ case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) - devdbg (dev, "rx shutdown, code %d", urb_status); + netdev_dbg(dev->net, "rx shutdown, code %d\n", urb_status); goto block; /* we get controller i/o faults during khubd disconnect() delays. @@ -461,7 +461,7 @@ static void rx_complete (struct urb *urb) if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); if (netif_msg_link (dev)) - devdbg (dev, "rx throttle %d", urb_status); + netdev_dbg(dev->net, "rx throttle %d\n", urb_status); } block: entry->state = rx_cleanup; @@ -478,7 +478,7 @@ block: entry->state = rx_cleanup; dev->net->stats.rx_errors++; if (netif_msg_rx_err (dev)) - devdbg (dev, "rx status %d", urb_status); + netdev_dbg(dev->net, "rx status %d\n", urb_status); break; } @@ -493,7 +493,7 @@ block: usb_free_urb (urb); } if (netif_msg_rx_err (dev)) - devdbg (dev, "no read resubmitted"); + netdev_dbg(dev->net, "no read resubmitted\n"); } static void intr_complete (struct urb *urb) @@ -511,14 +511,14 @@ static void intr_complete (struct urb *urb) case -ENOENT: /* urb killed */ case -ESHUTDOWN: /* hardware gone */ if (netif_msg_ifdown (dev)) - devdbg (dev, "intr shutdown, code %d", status); + netdev_dbg(dev->net, "intr shutdown, code %d\n", status); return; /* NOTE: not throttling like RX/TX, since this endpoint * already polls infrequently */ default: - devdbg (dev, "intr status %d", status); + netdev_dbg(dev->net, "intr status %d\n", status); break; } @@ -528,7 +528,7 @@ static void intr_complete (struct urb *urb) memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); status = usb_submit_urb (urb, GFP_ATOMIC); if (status != 0 && netif_msg_timer (dev)) - deverr(dev, "intr resubmit --> %d", status); + netdev_err(dev->net, "intr resubmit --> %d\n", status); } /*-------------------------------------------------------------------------*/ @@ -537,7 +537,7 @@ void usbnet_pause_rx(struct usbnet *dev) set_bit(EVENT_RX_PAUSED, &dev->flags); if (netif_msg_rx_status(dev)) - devdbg(dev, "paused rx queue enabled"); + netdev_dbg(dev->net, "paused rx queue enabled\n"); } EXPORT_SYMBOL_GPL(usbnet_pause_rx); @@ -556,7 +556,8 @@ void usbnet_resume_rx(struct usbnet *dev) tasklet_schedule(&dev->bh); if (netif_msg_rx_status(dev)) - devdbg(dev, "paused rx queue disabled, %d skbs requeued", num); + netdev_dbg(dev->net, "paused rx queue disabled, %d skbs requeued\n", + num); } EXPORT_SYMBOL_GPL(usbnet_resume_rx); @@ -589,7 +590,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) // these (async) unlinks complete immediately retval = usb_unlink_urb (urb); if (retval != -EINPROGRESS && retval != 0) - devdbg (dev, "unlink urb err, %d", retval); + netdev_dbg(dev->net, "unlink urb err, %d\n", retval); else count++; } @@ -632,8 +633,8 @@ static void usbnet_terminate_urbs(struct usbnet *dev) schedule_timeout(UNLINK_TIMEOUT_MS); set_current_state(TASK_UNINTERRUPTIBLE); if (netif_msg_ifdown(dev)) - devdbg(dev, "waited for %d urb completions", - temp); + netdev_dbg(dev->net, "waited for %d urb completions\n", + temp); } set_current_state(TASK_RUNNING); dev->wait = NULL; @@ -649,21 +650,20 @@ int usbnet_stop (struct net_device *net) netif_stop_queue (net); if (netif_msg_ifdown (dev)) - devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", - net->stats.rx_packets, net->stats.tx_packets, - net->stats.rx_errors, net->stats.tx_errors - ); + netdev_info(dev->net, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", + net->stats.rx_packets, net->stats.tx_packets, + net->stats.rx_errors, net->stats.tx_errors); /* allow minidriver to stop correctly (wireless devices to turn off * radio etc) */ if (info->stop) { retval = info->stop(dev); if (retval < 0 && netif_msg_ifdown(dev)) - devinfo(dev, - "stop fail (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); + netdev_info(dev->net, + "stop fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, dev->udev->devpath, + info->description); } if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) @@ -703,29 +703,31 @@ int usbnet_open (struct net_device *net) if ((retval = usb_autopm_get_interface(dev->intf)) < 0) { if (netif_msg_ifup (dev)) - devinfo (dev, - "resumption fail (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); + netdev_info(dev->net, + "resumption fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, + dev->udev->devpath, + info->description); goto done_nopm; } // put into "known safe" state if (info->reset && (retval = info->reset (dev)) < 0) { if (netif_msg_ifup (dev)) - devinfo (dev, - "open reset fail (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); + netdev_info(dev->net, + "open reset fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, + dev->udev->devpath, + info->description); goto done; } // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { if (netif_msg_ifup (dev)) - devdbg (dev, "can't open; %d", retval); + netdev_dbg(dev->net, "can't open; %d\n", retval); goto done; } @@ -734,7 +736,7 @@ int usbnet_open (struct net_device *net) retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); if (retval < 0) { if (netif_msg_ifup (dev)) - deverr (dev, "intr submit %d", retval); + netdev_err(dev->net, "intr submit %d\n", retval); goto done; } } @@ -756,10 +758,9 @@ int usbnet_open (struct net_device *net) else framing = "simple"; - devinfo (dev, "open: enable queueing " - "(rx %d, tx %d) mtu %d %s framing", - (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu, - framing); + netdev_info(dev->net, "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", + (int)RX_QLEN(dev), (int)TX_QLEN(dev), + dev->net->mtu, framing); } // delay posting reads until we're fully open @@ -908,8 +909,8 @@ kevent (struct work_struct *work) status != -ESHUTDOWN) { if (netif_msg_tx_err (dev)) fail_pipe: - deverr (dev, "can't clear tx halt, status %d", - status); + netdev_err(dev->net, "can't clear tx halt, status %d\n", + status); } else { clear_bit (EVENT_TX_HALT, &dev->flags); if (status != -ESHUTDOWN) @@ -928,8 +929,8 @@ fail_pipe: status != -ESHUTDOWN) { if (netif_msg_rx_err (dev)) fail_halt: - deverr (dev, "can't clear rx halt, status %d", - status); + netdev_err(dev->net, "can't clear rx halt, status %d\n", + status); } else { clear_bit (EVENT_RX_HALT, &dev->flags); tasklet_schedule (&dev->bh); @@ -967,18 +968,18 @@ fail_lowmem: if(info->link_reset && (retval = info->link_reset(dev)) < 0) { usb_autopm_put_interface(dev->intf); skip_reset: - devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); + netdev_info(dev->net, "link reset failed (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, + dev->udev->devpath, + info->description); } else { usb_autopm_put_interface(dev->intf); } } if (dev->flags) - devdbg (dev, "kevent done, flags = 0x%lx", - dev->flags); + netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags); } /*-------------------------------------------------------------------------*/ @@ -1015,14 +1016,15 @@ static void tx_complete (struct urb *urb) mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); if (netif_msg_link (dev)) - devdbg (dev, "tx throttle %d", - urb->status); + netdev_dbg(dev->net, "tx throttle %d\n", + urb->status); } netif_stop_queue (dev->net); break; default: if (netif_msg_tx_err (dev)) - devdbg (dev, "tx err %d", entry->urb->status); + netdev_dbg(dev->net, "tx err %d\n", + entry->urb->status); break; } } @@ -1065,7 +1067,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, skb = info->tx_fixup (dev, skb, GFP_ATOMIC); if (!skb) { if (netif_msg_tx_err (dev)) - devdbg (dev, "can't tx_fixup skb"); + netdev_dbg(dev->net, "can't tx_fixup skb\n"); goto drop; } } @@ -1073,7 +1075,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { if (netif_msg_tx_err (dev)) - devdbg (dev, "no urb"); + netdev_dbg(dev->net, "no urb\n"); goto drop; } @@ -1113,7 +1115,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, /* no use to process more packets */ netif_stop_queue(net); spin_unlock_irqrestore(&dev->txq.lock, flags); - devdbg(dev, "Delaying transmission for resumption"); + netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; } #endif @@ -1127,7 +1129,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, default: usb_autopm_put_interface_async(dev->intf); if (netif_msg_tx_err (dev)) - devdbg (dev, "tx: submit urb err %d", retval); + netdev_dbg(dev->net, "tx: submit urb err %d\n", retval); break; case 0: net->trans_start = jiffies; @@ -1139,15 +1141,15 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, if (retval) { if (netif_msg_tx_err (dev)) - devdbg (dev, "drop, code %d", retval); + netdev_dbg(dev->net, "drop, code %d\n", retval); drop: dev->net->stats.tx_dropped++; if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb); } else if (netif_msg_tx_queued (dev)) { - devdbg (dev, "> tx, len %d, type 0x%x", - length, skb->protocol); + netdev_dbg(dev->net, "> tx, len %d, type 0x%x\n", + length, skb->protocol); } #ifdef CONFIG_PM deferred: @@ -1179,7 +1181,7 @@ static void usbnet_bh (unsigned long param) dev_kfree_skb (skb); continue; default: - devdbg (dev, "bogus skb state %d", entry->state); + netdev_dbg(dev->net, "bogus skb state %d\n", entry->state); } } @@ -1208,8 +1210,8 @@ static void usbnet_bh (unsigned long param) rx_submit (dev, urb, GFP_ATOMIC); } if (temp != dev->rxq.qlen && netif_msg_link (dev)) - devdbg (dev, "rxqlen %d --> %d", - temp, dev->rxq.qlen); + netdev_dbg(dev->net, "rxqlen %d --> %d\n", + temp, dev->rxq.qlen); if (dev->rxq.qlen < qlen) tasklet_schedule (&dev->bh); } @@ -1241,10 +1243,10 @@ void usbnet_disconnect (struct usb_interface *intf) xdev = interface_to_usbdev (intf); if (netif_msg_probe (dev)) - devinfo (dev, "unregister '%s' usb-%s-%s, %s", - intf->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description); + netdev_info(dev->net, "unregister '%s' usb-%s-%s, %s\n", + intf->dev.driver->name, + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description); net = dev->net; unregister_netdev (net); @@ -1408,11 +1410,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) if (status) goto out3; if (netif_msg_probe (dev)) - devinfo (dev, "register '%s' at usb-%s-%s, %s, %pM", - udev->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description, - net->dev_addr); + netdev_info(dev->net, "register '%s' at usb-%s-%s, %s, %pM\n", + udev->dev.driver->name, + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description, + net->dev_addr); // ok, it's ready to go. usb_set_intfdata (udev, dev); diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 14692bc51b51..65cbd060cc30 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -728,9 +728,9 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) ret = rndis_command(dev, u.header, buflen); priv->current_command_oid = 0; if (ret < 0) - devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d " - "(%08x)", oid_to_string(oid), ret, - le32_to_cpu(u.get_c->status)); + netdev_dbg(dev->net, "%s(%s): rndis_command() failed, %d (%08x)\n", + __func__, oid_to_string(oid), ret, + le32_to_cpu(u.get_c->status)); if (ret == 0) { memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); @@ -741,9 +741,9 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) ret = rndis_error_status(u.get_c->status); if (ret < 0) - devdbg(dev, "rndis_query_oid(%s): device returned " - "error, 0x%08x (%d)", oid_to_string(oid), - le32_to_cpu(u.get_c->status), ret); + netdev_dbg(dev->net, "%s(%s): device returned error, 0x%08x (%d)\n", + __func__, oid_to_string(oid), + le32_to_cpu(u.get_c->status), ret); } mutex_unlock(&priv->command_lock); @@ -791,17 +791,17 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) ret = rndis_command(dev, u.header, buflen); priv->current_command_oid = 0; if (ret < 0) - devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d " - "(%08x)", oid_to_string(oid), ret, - le32_to_cpu(u.set_c->status)); + netdev_dbg(dev->net, "%s(%s): rndis_command() failed, %d (%08x)\n", + __func__, oid_to_string(oid), ret, + le32_to_cpu(u.set_c->status)); if (ret == 0) { ret = rndis_error_status(u.set_c->status); if (ret < 0) - devdbg(dev, "rndis_set_oid(%s): device returned error, " - "0x%08x (%d)", oid_to_string(oid), - le32_to_cpu(u.set_c->status), ret); + netdev_dbg(dev->net, "%s(%s): device returned error, 0x%08x (%d)\n", + __func__, oid_to_string(oid), + le32_to_cpu(u.set_c->status), ret); } mutex_unlock(&priv->command_lock); @@ -870,11 +870,11 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param, #endif if (value_type == 2) - devdbg(dev, "setting config parameter: %s, value: %s", - param, (u8 *)value); + netdev_dbg(dev->net, "setting config parameter: %s, value: %s\n", + param, (u8 *)value); else - devdbg(dev, "setting config parameter: %s, value: %d", - param, *(u32 *)value); + netdev_dbg(dev->net, "setting config parameter: %s, value: %d\n", + param, *(u32 *)value); infobuf->name_offs = cpu_to_le32(sizeof(*infobuf)); infobuf->name_length = cpu_to_le32(param_len); @@ -897,20 +897,21 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param, } #ifdef DEBUG - devdbg(dev, "info buffer (len: %d):", info_len); + netdev_dbg(dev->net, "info buffer (len: %d)\n", info_len); for (i = 0; i < info_len; i += 12) { u32 *tmp = (u32 *)((u8 *)infobuf + i); - devdbg(dev, "%08X:%08X:%08X", - cpu_to_be32(tmp[0]), - cpu_to_be32(tmp[1]), - cpu_to_be32(tmp[2])); + netdev_dbg(dev->net, "%08X:%08X:%08X\n", + cpu_to_be32(tmp[0]), + cpu_to_be32(tmp[1]), + cpu_to_be32(tmp[2])); } #endif ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER, infobuf, info_len); if (ret != 0) - devdbg(dev, "setting rndis config parameter failed, %d.", ret); + netdev_dbg(dev->net, "setting rndis config parameter failed, %d\n", + ret); kfree(infobuf); return ret; @@ -945,13 +946,13 @@ static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid)); if (ret < 0) { - devwarn(usbdev, "setting SSID failed (%08X)", ret); + netdev_warn(usbdev->net, "setting SSID failed (%08X)\n", ret); return ret; } if (ret == 0) { memcpy(&priv->essid, ssid, sizeof(priv->essid)); priv->radio_on = true; - devdbg(usbdev, "set_essid: radio_on = true"); + netdev_dbg(usbdev->net, "%s(): radio_on = true\n", __func__); } return ret; @@ -963,7 +964,8 @@ static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN); if (ret < 0) { - devwarn(usbdev, "setting BSSID[%pM] failed (%08X)", bssid, ret); + netdev_warn(usbdev->net, "setting BSSID[%pM] failed (%08X)\n", + bssid, ret); return ret; } @@ -1021,7 +1023,8 @@ static int disassociate(struct usbnet *usbdev, bool reset_ssid) ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0); if (ret == 0) { priv->radio_on = false; - devdbg(usbdev, "disassociate: radio_on = false"); + netdev_dbg(usbdev->net, "%s(): radio_on = false\n", + __func__); if (reset_ssid) msleep(100); @@ -1054,8 +1057,8 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version, __le32 tmp; int auth_mode, ret; - devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x " - "keymgmt=0x%x", wpa_version, auth_type, keymgmt); + netdev_dbg(usbdev->net, "%s(): wpa_version=0x%x authalg=0x%x keymgmt=0x%x\n", + __func__, wpa_version, auth_type, keymgmt); if (wpa_version & NL80211_WPA_VERSION_2) { if (keymgmt & RNDIS_WLAN_KEY_MGMT_802_1X) @@ -1082,7 +1085,8 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version, ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp, sizeof(tmp)); if (ret != 0) { - devwarn(usbdev, "setting auth mode failed (%08X)", ret); + netdev_warn(usbdev->net, "setting auth mode failed (%08X)\n", + ret); return ret; } @@ -1098,7 +1102,8 @@ static int set_priv_filter(struct usbnet *usbdev) struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); __le32 tmp; - devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version); + netdev_dbg(usbdev->net, "%s(): wpa_version=0x%x\n", + __func__, priv->wpa_version); if (priv->wpa_version & NL80211_WPA_VERSION_2 || priv->wpa_version & NL80211_WPA_VERSION_1) @@ -1116,8 +1121,8 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) __le32 tmp; int encr_mode, ret; - devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x", - pairwise, groupwise); + netdev_dbg(usbdev->net, "%s(): cipher_pair=0x%x cipher_group=0x%x\n", + __func__, pairwise, groupwise); if (pairwise & RNDIS_WLAN_ALG_CCMP) encr_mode = NDIS_80211_ENCR_CCMP_ENABLED; @@ -1136,7 +1141,8 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp, sizeof(tmp)); if (ret != 0) { - devwarn(usbdev, "setting encr mode failed (%08X)", ret); + netdev_warn(usbdev->net, "setting encr mode failed (%08X)\n", + ret); return ret; } @@ -1151,13 +1157,15 @@ static int set_infra_mode(struct usbnet *usbdev, int mode) __le32 tmp; int ret; - devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); + netdev_dbg(usbdev->net, "%s(): infra_mode=0x%x\n", + __func__, priv->infra_mode); tmp = cpu_to_le32(mode); ret = rndis_set_oid(usbdev, OID_802_11_INFRASTRUCTURE_MODE, &tmp, sizeof(tmp)); if (ret != 0) { - devwarn(usbdev, "setting infra mode failed (%08X)", ret); + netdev_warn(usbdev->net, "setting infra mode failed (%08X)\n", + ret); return ret; } @@ -1174,7 +1182,7 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold) { __le32 tmp; - devdbg(usbdev, "set_rts_threshold %i", rts_threshold); + netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold); if (rts_threshold < 0 || rts_threshold > 2347) rts_threshold = 2347; @@ -1188,7 +1196,7 @@ static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold) { __le32 tmp; - devdbg(usbdev, "set_frag_threshold %i", frag_threshold); + netdev_dbg(usbdev->net, "%s(): %i\n", __func__, frag_threshold); if (frag_threshold < 256 || frag_threshold > 2346) frag_threshold = 2346; @@ -1222,7 +1230,7 @@ static int set_channel(struct usbnet *usbdev, int channel) unsigned int dsconfig; int len, ret; - devdbg(usbdev, "set_channel(%d)", channel); + netdev_dbg(usbdev->net, "%s(%d)\n", __func__, channel); /* this OID is valid only when not associated */ if (is_associated(usbdev)) @@ -1233,7 +1241,8 @@ static int set_channel(struct usbnet *usbdev, int channel) len = sizeof(config); ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); if (ret < 0) { - devdbg(usbdev, "set_channel: querying configuration failed"); + netdev_dbg(usbdev->net, "%s(): querying configuration failed\n", + __func__); return ret; } @@ -1241,7 +1250,7 @@ static int set_channel(struct usbnet *usbdev, int channel) ret = rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config, sizeof(config)); - devdbg(usbdev, "set_channel: %d -> %d", channel, ret); + netdev_dbg(usbdev->net, "%s(): %d -> %d\n", __func__, channel, ret); return ret; } @@ -1255,7 +1264,8 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, u32 cipher; int ret; - devdbg(usbdev, "add_wep_key(idx: %d, len: %d)", index, key_len); + netdev_dbg(usbdev->net, "%s(idx: %d, len: %d)\n", + __func__, index, key_len); if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) return -EINVAL; @@ -1277,15 +1287,15 @@ static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, ret = set_encr_mode(usbdev, RNDIS_WLAN_ALG_WEP, RNDIS_WLAN_ALG_NONE); if (ret) - devwarn(usbdev, "encryption couldn't be enabled (%08X)", - ret); + netdev_warn(usbdev->net, "encryption couldn't be enabled (%08X)\n", + ret); } ret = rndis_set_oid(usbdev, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key)); if (ret != 0) { - devwarn(usbdev, "adding encryption key %d failed (%08X)", - index+1, ret); + netdev_warn(usbdev->net, "adding encryption key %d failed (%08X)\n", + index + 1, ret); return ret; } @@ -1307,22 +1317,23 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, int ret; if (index < 0 || index >= 4) { - devdbg(usbdev, "add_wpa_key: index out of range (%i)", index); + netdev_dbg(usbdev->net, "%s(): index out of range (%i)\n", + __func__, index); return -EINVAL; } if (key_len > sizeof(ndis_key.material) || key_len < 0) { - devdbg(usbdev, "add_wpa_key: key length out of range (%i)", - key_len); + netdev_dbg(usbdev->net, "%s(): key length out of range (%i)\n", + __func__, key_len); return -EINVAL; } if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) { if (!rx_seq || seq_len <= 0) { - devdbg(usbdev, "add_wpa_key: recv seq flag without" - "buffer"); + netdev_dbg(usbdev->net, "%s(): recv seq flag without buffer\n", + __func__); return -EINVAL; } if (rx_seq && seq_len > sizeof(ndis_key.rsc)) { - devdbg(usbdev, "add_wpa_key: too big recv seq buffer"); + netdev_dbg(usbdev->net, "%s(): too big recv seq buffer\n", __func__); return -EINVAL; } } @@ -1330,15 +1341,16 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, is_addr_ok = addr && !is_zero_ether_addr(addr) && !is_broadcast_ether_addr(addr); if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) { - devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)", - addr); + netdev_dbg(usbdev->net, "%s(): pairwise but bssid invalid (%pM)\n", + __func__, addr); return -EINVAL; } - devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, - !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), - !!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY), - !!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)); + netdev_dbg(usbdev->net, "%s(%i): flags:%i%i%i\n", + __func__, index, + !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), + !!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY), + !!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)); memset(&ndis_key, 0, sizeof(ndis_key)); @@ -1372,7 +1384,8 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, le32_to_cpu(ndis_key.size)); - devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret); + netdev_dbg(usbdev->net, "%s(): OID_802_11_ADD_KEY -> %08X\n", + __func__, ret); if (ret != 0) return ret; @@ -1401,7 +1414,7 @@ static int restore_key(struct usbnet *usbdev, int key_idx) key = priv->encr_keys[key_idx]; - devdbg(usbdev, "restore_key: %i:%i", key_idx, key.len); + netdev_dbg(usbdev->net, "%s(): %i:%i\n", __func__, key_idx, key.len); if (key.len == 0) return 0; @@ -1436,8 +1449,9 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) is_wpa = is_wpa_key(priv, index); - devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep", - priv->encr_keys[index].len); + netdev_dbg(usbdev->net, "%s(): %i:%s:%i\n", + __func__, index, is_wpa ? "wpa" : "wep", + priv->encr_keys[index].len); clear_key(priv, index); @@ -1464,9 +1478,9 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_WEP, &keyindex, sizeof(keyindex)); if (ret != 0) { - devwarn(usbdev, - "removing encryption key %d failed (%08X)", - index, ret); + netdev_warn(usbdev->net, + "removing encryption key %d failed (%08X)\n", + index, ret); return ret; } } @@ -1498,9 +1512,9 @@ static void set_multicast_list(struct usbnet *usbdev) size = min(priv->multicast_size, netdev_mc_count(usbdev->net)); buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); if (!buf) { - devwarn(usbdev, - "couldn't alloc %d bytes of memory", - size * ETH_ALEN); + netdev_warn(usbdev->net, + "couldn't alloc %d bytes of memory\n", + size * ETH_ALEN); return; } @@ -1520,8 +1534,8 @@ static void set_multicast_list(struct usbnet *usbdev) else filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - devdbg(usbdev, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d", - i, priv->multicast_size, ret); + netdev_dbg(usbdev->net, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d\n", + i, priv->multicast_size, ret); kfree(buf); } @@ -1529,12 +1543,12 @@ static void set_multicast_list(struct usbnet *usbdev) ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter)); if (ret < 0) { - devwarn(usbdev, "couldn't set packet filter: %08x", - le32_to_cpu(filter)); + netdev_warn(usbdev->net, "couldn't set packet filter: %08x\n", + le32_to_cpu(filter)); } - devdbg(usbdev, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d", - le32_to_cpu(filter), ret); + netdev_dbg(usbdev->net, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d\n", + le32_to_cpu(filter), ret); } /* @@ -1592,7 +1606,8 @@ static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; - devdbg(usbdev, "rndis_set_tx_power type:0x%x dbm:%i", type, dbm); + netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n", + __func__, type, dbm); /* Device doesn't support changing txpower after initialization, only * turn off/on radio. Support 'auto' mode and setting same dBm that is @@ -1615,7 +1630,7 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm) *dbm = get_bcm4320_power_dbm(priv); - devdbg(usbdev, "rndis_get_tx_power dbm:%i", *dbm); + netdev_dbg(usbdev->net, "%s(): dbm:%i\n", __func__, *dbm); return 0; } @@ -1629,7 +1644,7 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, int ret; __le32 tmp; - devdbg(usbdev, "cfg80211.scan"); + netdev_dbg(usbdev->net, "cfg80211.scan\n"); /* Get current bssid list from device before new scan, as new scan * clears internal bssid list. @@ -1669,8 +1684,8 @@ static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, int ie_len, bssid_len; u8 *ie; - devdbg(usbdev, " found bssid: '%.32s' [%pM]", bssid->ssid.essid, - bssid->mac); + netdev_dbg(usbdev->net, " found bssid: '%.32s' [%pM]\n", + bssid->ssid.essid, bssid->mac); /* parse bssid structure */ bssid_len = le32_to_cpu(bssid->length); @@ -1712,7 +1727,7 @@ static int rndis_check_bssid_list(struct usbnet *usbdev) int ret = -EINVAL, len, count, bssid_len; bool resized = false; - devdbg(usbdev, "check_bssid_list"); + netdev_dbg(usbdev->net, "check_bssid_list\n"); len = CONTROL_BUFFER_SIZE; resize_buf: @@ -1736,8 +1751,8 @@ resize_buf: bssid = bssid_list->bssid; bssid_len = le32_to_cpu(bssid->length); count = le32_to_cpu(bssid_list->num_items); - devdbg(usbdev, "check_bssid_list: %d BSSIDs found (buflen: %d)", count, - len); + netdev_dbg(usbdev->net, "check_bssid_list: %d BSSIDs found (buflen: %d)\n", + count, len); while (count && ((void *)bssid + bssid_len) <= (buf + len)) { rndis_bss_info_update(usbdev, bssid); @@ -1759,7 +1774,7 @@ static void rndis_get_scan_results(struct work_struct *work) struct usbnet *usbdev = priv->usbdev; int ret; - devdbg(usbdev, "get_scan_results"); + netdev_dbg(usbdev->net, "get_scan_results\n"); if (!priv->scan_request) return; @@ -1793,7 +1808,7 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, if (sme->crypto.n_ciphers_pairwise > 0 && pairwise == RNDIS_WLAN_ALG_NONE) { - deverr(usbdev, "Unsupported pairwise cipher"); + netdev_err(usbdev->net, "Unsupported pairwise cipher\n"); return -ENOTSUPP; } @@ -1803,28 +1818,30 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, if (sme->crypto.n_akm_suites > 0 && keymgmt == RNDIS_WLAN_KEY_MGMT_NONE) { - deverr(usbdev, "Invalid keymgmt"); + netdev_err(usbdev->net, "Invalid keymgmt\n"); return -ENOTSUPP; } - devdbg(usbdev, "cfg80211.connect('%.32s':[%pM]:%d:[%d,0x%x:0x%x]:[0x%x:" - "0x%x]:0x%x)", sme->ssid, sme->bssid, chan, - sme->privacy, sme->crypto.wpa_versions, sme->auth_type, - groupwise, pairwise, keymgmt); + netdev_dbg(usbdev->net, "cfg80211.connect('%.32s':[%pM]:%d:[%d,0x%x:0x%x]:[0x%x:0x%x]:0x%x)\n", + sme->ssid, sme->bssid, chan, + sme->privacy, sme->crypto.wpa_versions, sme->auth_type, + groupwise, pairwise, keymgmt); if (is_associated(usbdev)) disassociate(usbdev, false); ret = set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA); if (ret < 0) { - devdbg(usbdev, "connect: set_infra_mode failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_infra_mode failed, %d\n", + ret); goto err_turn_radio_on; } ret = set_auth_mode(usbdev, sme->crypto.wpa_versions, sme->auth_type, keymgmt); if (ret < 0) { - devdbg(usbdev, "connect: set_auth_mode failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_auth_mode failed, %d\n", + ret); goto err_turn_radio_on; } @@ -1832,14 +1849,16 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, ret = set_encr_mode(usbdev, pairwise, groupwise); if (ret < 0) { - devdbg(usbdev, "connect: set_encr_mode failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_encr_mode failed, %d\n", + ret); goto err_turn_radio_on; } if (channel) { ret = set_channel(usbdev, chan); if (ret < 0) { - devdbg(usbdev, "connect: set_channel failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_channel failed, %d\n", + ret); goto err_turn_radio_on; } } @@ -1848,8 +1867,8 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, priv->encr_tx_key_index = sme->key_idx; ret = add_wep_key(usbdev, sme->key, sme->key_len, sme->key_idx); if (ret < 0) { - devdbg(usbdev, "connect: add_wep_key failed, %d " - "(%d, %d)", ret, sme->key_len, sme->key_idx); + netdev_dbg(usbdev->net, "connect: add_wep_key failed, %d (%d, %d)\n", + ret, sme->key_len, sme->key_idx); goto err_turn_radio_on; } } @@ -1858,7 +1877,8 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, !is_broadcast_ether_addr(sme->bssid)) { ret = set_bssid(usbdev, sme->bssid); if (ret < 0) { - devdbg(usbdev, "connect: set_bssid failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_bssid failed, %d\n", + ret); goto err_turn_radio_on; } } else @@ -1880,7 +1900,7 @@ static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, ret = set_essid(usbdev, &ssid); if (ret < 0) - devdbg(usbdev, "connect: set_essid failed, %d", ret); + netdev_dbg(usbdev->net, "connect: set_essid failed, %d\n", ret); return ret; err_turn_radio_on: @@ -1895,7 +1915,7 @@ static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev, struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; - devdbg(usbdev, "cfg80211.disconnect(%d)", reason_code); + netdev_dbg(usbdev->net, "cfg80211.disconnect(%d)\n", reason_code); priv->connected = false; memset(priv->bssid, 0, ETH_ALEN); @@ -1929,21 +1949,23 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, alg = RNDIS_WLAN_ALG_NONE; } - devdbg(usbdev, "cfg80211.join_ibss('%.32s':[%pM]:%d:%d)", params->ssid, - params->bssid, chan, params->privacy); + netdev_dbg(usbdev->net, "cfg80211.join_ibss('%.32s':[%pM]:%d:%d)\n", + params->ssid, params->bssid, chan, params->privacy); if (is_associated(usbdev)) disassociate(usbdev, false); ret = set_infra_mode(usbdev, NDIS_80211_INFRA_ADHOC); if (ret < 0) { - devdbg(usbdev, "join_ibss: set_infra_mode failed, %d", ret); + netdev_dbg(usbdev->net, "join_ibss: set_infra_mode failed, %d\n", + ret); goto err_turn_radio_on; } ret = set_auth_mode(usbdev, 0, auth_type, RNDIS_WLAN_KEY_MGMT_NONE); if (ret < 0) { - devdbg(usbdev, "join_ibss: set_auth_mode failed, %d", ret); + netdev_dbg(usbdev->net, "join_ibss: set_auth_mode failed, %d\n", + ret); goto err_turn_radio_on; } @@ -1951,15 +1973,16 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, ret = set_encr_mode(usbdev, alg, RNDIS_WLAN_ALG_NONE); if (ret < 0) { - devdbg(usbdev, "join_ibss: set_encr_mode failed, %d", ret); + netdev_dbg(usbdev->net, "join_ibss: set_encr_mode failed, %d\n", + ret); goto err_turn_radio_on; } if (channel) { ret = set_channel(usbdev, chan); if (ret < 0) { - devdbg(usbdev, "join_ibss: set_channel failed, %d", - ret); + netdev_dbg(usbdev->net, "join_ibss: set_channel failed, %d\n", + ret); goto err_turn_radio_on; } } @@ -1968,7 +1991,8 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, !is_broadcast_ether_addr(params->bssid)) { ret = set_bssid(usbdev, params->bssid); if (ret < 0) { - devdbg(usbdev, "join_ibss: set_bssid failed, %d", ret); + netdev_dbg(usbdev->net, "join_ibss: set_bssid failed, %d\n", + ret); goto err_turn_radio_on; } } else @@ -1988,7 +2012,8 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, ret = set_essid(usbdev, &ssid); if (ret < 0) - devdbg(usbdev, "join_ibss: set_essid failed, %d", ret); + netdev_dbg(usbdev->net, "join_ibss: set_essid failed, %d\n", + ret); return ret; err_turn_radio_on: @@ -2002,7 +2027,7 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev) struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; - devdbg(usbdev, "cfg80211.leave_ibss()"); + netdev_dbg(usbdev->net, "cfg80211.leave_ibss()\n"); priv->connected = false; memset(priv->bssid, 0, ETH_ALEN); @@ -2028,8 +2053,8 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, struct usbnet *usbdev = priv->usbdev; __le32 flags; - devdbg(usbdev, "rndis_add_key(%i, %pM, %08x)", key_index, mac_addr, - params->cipher); + netdev_dbg(usbdev->net, "%s(%i, %pM, %08x)\n", + __func__, key_index, mac_addr, params->cipher); switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: @@ -2050,8 +2075,8 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, key_index, mac_addr, params->seq, params->seq_len, params->cipher, flags); default: - devdbg(usbdev, "rndis_add_key: unsupported cipher %08x", - params->cipher); + netdev_dbg(usbdev->net, "%s(): unsupported cipher %08x\n", + __func__, params->cipher); return -ENOTSUPP; } } @@ -2062,7 +2087,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, struct rndis_wlan_private *priv = wiphy_priv(wiphy); struct usbnet *usbdev = priv->usbdev; - devdbg(usbdev, "rndis_del_key(%i, %pM)", key_index, mac_addr); + netdev_dbg(usbdev->net, "%s(%i, %pM)\n", __func__, key_index, mac_addr); return remove_key(usbdev, key_index, mac_addr); } @@ -2074,7 +2099,7 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, struct usbnet *usbdev = priv->usbdev; struct rndis_wlan_encr_key key; - devdbg(usbdev, "rndis_set_default_key(%i)", key_index); + netdev_dbg(usbdev->net, "%s(%i)\n", __func__, key_index); priv->encr_tx_key_index = key_index; @@ -2188,7 +2213,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) if (ret < 0) memset(bssid, 0, sizeof(bssid)); - devdbg(usbdev, "link up work: [%pM] %s", bssid, roamed ? "roamed" : ""); + netdev_dbg(usbdev->net, "link up work: [%pM]%s\n", + bssid, roamed ? " roamed" : ""); /* Internal bss list in device always contains at least the currently * connected bss and we can get it to cfg80211 with @@ -2270,8 +2296,8 @@ static void rndis_wlan_auth_indication(struct usbnet *usbdev, /* must have at least one array entry */ if (len < offsetof(struct ndis_80211_status_indication, u) + sizeof(struct ndis_80211_auth_request)) { - devinfo(usbdev, "authentication indication: " - "too short message (%i)", len); + netdev_info(usbdev->net, "authentication indication: too short message (%i)\n", + len); return; } @@ -2298,8 +2324,8 @@ static void rndis_wlan_auth_indication(struct usbnet *usbdev, type = "group_error"; } - devinfo(usbdev, "authentication indication: %s (0x%08x)", type, - le32_to_cpu(auth_req->flags)); + netdev_info(usbdev->net, "authentication indication: %s (0x%08x)\n", + type, le32_to_cpu(auth_req->flags)); if (pairwise_error) { key_type = NL80211_KEYTYPE_PAIRWISE; @@ -2335,8 +2361,8 @@ static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, if (len < offsetof(struct ndis_80211_status_indication, u) + sizeof(struct ndis_80211_pmkid_cand_list)) { - devinfo(usbdev, "pmkid candidate list indication: " - "too short message (%i)", len); + netdev_info(usbdev->net, "pmkid candidate list indication: too short message (%i)\n", + len); return; } @@ -2346,18 +2372,16 @@ static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, offsetof(struct ndis_80211_status_indication, u); if (len < expected_len) { - devinfo(usbdev, "pmkid candidate list indication: " - "list larger than buffer (%i < %i)", - len, expected_len); + netdev_info(usbdev->net, "pmkid candidate list indication: list larger than buffer (%i < %i)\n", + len, expected_len); return; } cand_list = &indication->u.cand_list; - devinfo(usbdev, "pmkid candidate list indication: " - "version %i, candidates %i", - le32_to_cpu(cand_list->version), - le32_to_cpu(cand_list->num_candidates)); + netdev_info(usbdev->net, "pmkid candidate list indication: version %i, candidates %i\n", + le32_to_cpu(cand_list->version), + le32_to_cpu(cand_list->num_candidates)); if (le32_to_cpu(cand_list->version) != 1) return; @@ -2366,8 +2390,8 @@ static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, struct ndis_80211_pmkid_candidate *cand = &cand_list->candidate_list[i]; - devdbg(usbdev, "cand[%i]: flags: 0x%08x, bssid: %pM", - i, le32_to_cpu(cand->flags), cand->bssid); + netdev_dbg(usbdev->net, "cand[%i]: flags: 0x%08x, bssid: %pM\n", + i, le32_to_cpu(cand->flags), cand->bssid); #if 0 struct iw_pmkid_cand pcand; @@ -2398,15 +2422,14 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, len = le32_to_cpu(msg->length); if (len < 8) { - devinfo(usbdev, "media specific indication, " - "ignore too short message (%i < 8)", len); + netdev_info(usbdev->net, "media specific indication, ignore too short message (%i < 8)\n", + len); return; } if (offset + len > buflen) { - devinfo(usbdev, "media specific indication, " - "too large to fit to buffer (%i > %i)", - offset + len, buflen); + netdev_info(usbdev->net, "media specific indication, too large to fit to buffer (%i > %i)\n", + offset + len, buflen); return; } @@ -2414,13 +2437,13 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, switch (le32_to_cpu(indication->status_type)) { case NDIS_80211_STATUSTYPE_RADIOSTATE: - devinfo(usbdev, "radio state indication: %i", - le32_to_cpu(indication->u.radio_status)); + netdev_info(usbdev->net, "radio state indication: %i\n", + le32_to_cpu(indication->u.radio_status)); return; case NDIS_80211_STATUSTYPE_MEDIASTREAMMODE: - devinfo(usbdev, "media stream mode indication: %i", - le32_to_cpu(indication->u.media_stream_mode)); + netdev_info(usbdev->net, "media stream mode indication: %i\n", + le32_to_cpu(indication->u.media_stream_mode)); return; case NDIS_80211_STATUSTYPE_AUTHENTICATION: @@ -2432,9 +2455,8 @@ static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, return; default: - devinfo(usbdev, "media specific indication: " - "unknown status type 0x%08x", - le32_to_cpu(indication->status_type)); + netdev_info(usbdev->net, "media specific indication: unknown status type 0x%08x\n", + le32_to_cpu(indication->status_type)); } } @@ -2451,14 +2473,13 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) * and userspace to think that device is * roaming/reassociating when it isn't. */ - devdbg(usbdev, "ignored OID_802_11_ADD_KEY triggered " - "'media connect'"); + netdev_dbg(usbdev->net, "ignored OID_802_11_ADD_KEY triggered 'media connect'\n"); return; } usbnet_pause_rx(usbdev); - devinfo(usbdev, "media connect"); + netdev_info(usbdev->net, "media connect\n"); /* queue work to avoid recursive calls into rndis_command */ set_bit(WORK_LINK_UP, &priv->work_pending); @@ -2466,7 +2487,7 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) break; case RNDIS_STATUS_MEDIA_DISCONNECT: - devinfo(usbdev, "media disconnect"); + netdev_info(usbdev->net, "media disconnect\n"); /* queue work to avoid recursive calls into rndis_command */ set_bit(WORK_LINK_DOWN, &priv->work_pending); @@ -2478,8 +2499,8 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) break; default: - devinfo(usbdev, "indication: 0x%08x", - le32_to_cpu(msg->status)); + netdev_info(usbdev->net, "indication: 0x%08x\n", + le32_to_cpu(msg->status)); break; } } @@ -2544,8 +2565,8 @@ static void rndis_device_poller(struct work_struct *work) if (ret == 0) priv->last_qual = level_to_qual(le32_to_cpu(rssi)); - devdbg(usbdev, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d", - ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); + netdev_dbg(usbdev->net, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d\n", + ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); /* Workaround transfer stalls on poor quality links. * TODO: find right way to fix these stalls (as stalls do not happen @@ -2838,11 +2859,11 @@ static int rndis_wlan_reset(struct usbnet *usbdev) struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); int retval; - devdbg(usbdev, "rndis_wlan_reset"); + netdev_dbg(usbdev->net, "%s()\n", __func__); retval = rndis_reset(usbdev); if (retval) - devwarn(usbdev, "rndis_reset() failed: %d", retval); + netdev_warn(usbdev->net, "rndis_reset failed: %d\n", retval); /* rndis_reset cleared multicast list, so restore here. (set_multicast_list() also turns on current packet filter) */ @@ -2860,7 +2881,7 @@ static int rndis_wlan_stop(struct usbnet *usbdev) int retval; __le32 filter; - devdbg(usbdev, "rndis_wlan_stop"); + netdev_dbg(usbdev->net, "%s()\n", __func__); retval = disassociate(usbdev, false); diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index 8ce61359bf73..df1e83dd9a54 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -214,25 +214,4 @@ extern void usbnet_set_msglevel (struct net_device *, u32); extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *); extern int usbnet_nway_reset(struct net_device *net); -/* messaging support includes the interface name, so it must not be - * used before it has one ... notably, in minidriver bind() calls. - */ -#ifdef DEBUG -#define devdbg(usbnet, fmt, arg...) \ - printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg) -#else -#define devdbg(usbnet, fmt, arg...) \ - ({ if (0) printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , \ - ## arg); 0; }) -#endif - -#define deverr(usbnet, fmt, arg...) \ - printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg) -#define devwarn(usbnet, fmt, arg...) \ - printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg) - -#define devinfo(usbnet, fmt, arg...) \ - printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \ - - #endif /* __LINUX_USB_USBNET_H */ -- cgit v1.2.3 From a475f603d23392f386e45cf377b17c30ed3bbb80 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 10:30:24 +0000 Subject: drivers/net/usb: Use netif_ logging facilities Convert from: if (netif_msg_(priv)) dev_(dev... to netif_(priv, foo, dev... Also convert a few: if (i < REG_TIMEOUT) { etc... return ret; } to if (i >= REG_TIMEOUT) goto fail; etc... return ret; Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 18 ++-- drivers/net/usb/net1080.c | 96 ++++++++++---------- drivers/net/usb/pegasus.c | 170 +++++++++++++++-------------------- drivers/net/usb/rndis_host.c | 14 ++- drivers/net/usb/smsc95xx.c | 99 +++++++++----------- drivers/net/usb/usbnet.c | 208 +++++++++++++++++++------------------------ 6 files changed, 264 insertions(+), 341 deletions(-) diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 7e5a75269cc5..3486e8ca039a 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -339,10 +339,10 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); static void dumpspeed(struct usbnet *dev, __le32 *speeds) { - if (netif_msg_timer(dev)) - netdev_info(dev->net, "link speeds: %u kbps up, %u kbps down\n", - __le32_to_cpu(speeds[0]) / 1000, - __le32_to_cpu(speeds[1]) / 1000); + netif_info(dev, timer, dev->net, + "link speeds: %u kbps up, %u kbps down\n", + __le32_to_cpu(speeds[0]) / 1000, + __le32_to_cpu(speeds[1]) / 1000); } static void cdc_status(struct usbnet *dev, struct urb *urb) @@ -361,18 +361,16 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) event = urb->transfer_buffer; switch (event->bNotificationType) { case USB_CDC_NOTIFY_NETWORK_CONNECTION: - if (netif_msg_timer(dev)) - netdev_dbg(dev->net, "CDC: carrier %s\n", - event->wValue ? "on" : "off"); + netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n", + event->wValue ? "on" : "off"); if (event->wValue) netif_carrier_on(dev->net); else netif_carrier_off(dev->net); break; case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ - if (netif_msg_timer(dev)) - netdev_dbg(dev->net, "CDC: speed change (len %d)\n", - urb->actual_length); + netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n", + urb->actual_length); if (urb->actual_length != (sizeof *event + 8)) set_bit(EVENT_STS_SPLIT, &dev->flags); else diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index f6994053c101..bdcad45954a3 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -203,26 +203,23 @@ static void nc_dump_registers(struct usbnet *dev) static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl) { - if (!netif_msg_link(dev)) - return; - netdev_dbg(dev->net, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" - " this%s%s;" - " other%s%s; r/o 0x%x\n", - dev->udev->bus->bus_name, dev->udev->devpath, - usbctl, - (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", - (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", - (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", - (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", - (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", - - (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", - - (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", - - usbctl & ~USBCTL_WRITABLE_MASK); + netif_dbg(dev, link, dev->net, + "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s; this%s%s; other%s%s; r/o 0x%x\n", + dev->udev->bus->bus_name, dev->udev->devpath, + usbctl, + (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", + (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", + (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", + (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", + (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", + + (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", + + (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", + (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", + + usbctl & ~USBCTL_WRITABLE_MASK); } /*-------------------------------------------------------------------------*/ @@ -249,27 +246,26 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl) static inline void nc_dump_status(struct usbnet *dev, u16 status) { - if (!netif_msg_link(dev)) - return; - netdev_dbg(dev->net, "net1080 %s-%s status 0x%x: this (%c) PKT=%d%s%s%s; other PKT=%d%s%s%s; unspec 0x%x\n", - dev->udev->bus->bus_name, dev->udev->devpath, - status, - - // XXX the packet counts don't seem right - // (1 at reset, not 0); maybe UNSPEC too - - (status & STATUS_PORT_A) ? 'A' : 'B', - STATUS_PACKETS_THIS(status), - (status & STATUS_CONN_THIS) ? " CON" : "", - (status & STATUS_SUSPEND_THIS) ? " SUS" : "", - (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", - - STATUS_PACKETS_OTHER(status), - (status & STATUS_CONN_OTHER) ? " CON" : "", - (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", - (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", - - status & STATUS_UNSPEC_MASK); + netif_dbg(dev, link, dev->net, + "net1080 %s-%s status 0x%x: this (%c) PKT=%d%s%s%s; other PKT=%d%s%s%s; unspec 0x%x\n", + dev->udev->bus->bus_name, dev->udev->devpath, + status, + + // XXX the packet counts don't seem right + // (1 at reset, not 0); maybe UNSPEC too + + (status & STATUS_PORT_A) ? 'A' : 'B', + STATUS_PACKETS_THIS(status), + (status & STATUS_CONN_THIS) ? " CON" : "", + (status & STATUS_SUSPEND_THIS) ? " SUS" : "", + (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", + + STATUS_PACKETS_OTHER(status), + (status & STATUS_CONN_OTHER) ? " CON" : "", + (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", + (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", + + status & STATUS_UNSPEC_MASK); } /*-------------------------------------------------------------------------*/ @@ -284,10 +280,9 @@ static inline void nc_dump_status(struct usbnet *dev, u16 status) static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl) { - if (netif_msg_link(dev)) - netdev_dbg(dev->net, "net1080 %s-%s ttl 0x%x this = %d, other = %d\n", - dev->udev->bus->bus_name, dev->udev->devpath, - ttl, TTL_THIS(ttl), TTL_OTHER(ttl)); + netif_dbg(dev, link, dev->net, "net1080 %s-%s ttl 0x%x this = %d, other = %d\n", + dev->udev->bus->bus_name, dev->udev->devpath, + ttl, TTL_THIS(ttl), TTL_OTHER(ttl)); } /*-------------------------------------------------------------------------*/ @@ -332,10 +327,9 @@ static int net1080_reset(struct usbnet *dev) MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) ); dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS); - if (netif_msg_link(dev)) - netdev_info(dev->net, "port %c, peer %sconnected\n", - (status & STATUS_PORT_A) ? 'A' : 'B', - (status & STATUS_CONN_OTHER) ? "" : "dis"); + netif_info(dev, link, dev->net, "port %c, peer %sconnected\n", + (status & STATUS_PORT_A) ? 'A' : 'B', + (status & STATUS_CONN_OTHER) ? "" : "dis"); retval = 0; done: @@ -412,8 +406,8 @@ static void nc_ensure_sync(struct usbnet *dev) return; } - if (netif_msg_rx_err(dev)) - netdev_dbg(dev->net, "flush net1080; too many framing errors\n"); + netif_dbg(dev, rx_err, dev->net, + "flush net1080; too many framing errors\n"); dev->frame_errors = 0; } } diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 44ae8f6d3135..41838773b568 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -132,9 +132,10 @@ static void ctrl_callback(struct urb *urb) case -ENOENT: break; default: - if (netif_msg_drv(pegasus) && printk_ratelimit()) - dev_dbg(&pegasus->intf->dev, "%s, status %d\n", - __func__, status); + if (net_ratelimit()) + netif_dbg(pegasus, drv, pegasus->net, + "%s, status %d\n", __func__, status); + break; } pegasus->flags &= ~ETH_REGS_CHANGED; wake_up(&pegasus->ctrl_wait); @@ -149,9 +150,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __func__); + netif_warn(pegasus, drv, pegasus->net, + "out of memory in %s\n", __func__); return -ENOMEM; } add_wait_queue(&pegasus->ctrl_wait, &wait); @@ -181,9 +181,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, set_current_state(TASK_RUNNING); if (ret == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_drv(pegasus) && printk_ratelimit()) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __func__, ret); + if (net_ratelimit()) + netif_err(pegasus, drv, pegasus->net, + "%s, status %d\n", __func__, ret); goto out; } @@ -205,9 +205,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __func__); + netif_warn(pegasus, drv, pegasus->net, + "out of memory in %s\n", __func__); return -ENOMEM; } memcpy(buffer, data, size); @@ -237,9 +236,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { if (ret == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __func__, ret); + netif_err(pegasus, drv, pegasus->net, + "%s, status %d\n", __func__, ret); goto out; } @@ -259,9 +257,8 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) tmp = kmalloc(1, GFP_KERNEL); if (!tmp) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __func__); + netif_warn(pegasus, drv, pegasus->net, + "out of memory in %s\n", __func__); return -ENOMEM; } memcpy(tmp, &data, 1); @@ -290,9 +287,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { if (ret == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_drv(pegasus) && printk_ratelimit()) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __func__, ret); + if (net_ratelimit()) + netif_err(pegasus, drv, pegasus->net, + "%s, status %d\n", __func__, ret); goto out; } @@ -323,9 +320,8 @@ static int update_eth_regs_async(pegasus_t * pegasus) if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { if (ret == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __func__, ret); + netif_err(pegasus, drv, pegasus->net, + "%s, status %d\n", __func__, ret); } return ret; @@ -349,14 +345,16 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) if (data[0] & PHY_DONE) break; } - if (i < REG_TIMEOUT) { - ret = get_registers(pegasus, PhyData, 2, ®di); - *regd = le16_to_cpu(regdi); - return ret; - } + + if (i >= REG_TIMEOUT) + goto fail; + + ret = get_registers(pegasus, PhyData, 2, ®di); + *regd = le16_to_cpu(regdi); + return ret; + fail: - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); + netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); return ret; } @@ -388,12 +386,14 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) if (data[0] & PHY_DONE) break; } - if (i < REG_TIMEOUT) - return ret; + + if (i >= REG_TIMEOUT) + goto fail; + + return ret; fail: - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); + netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); return -ETIMEDOUT; } @@ -422,15 +422,15 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) if (ret == -ESHUTDOWN) goto fail; } - if (i < REG_TIMEOUT) { - ret = get_registers(pegasus, EpromData, 2, &retdatai); - *retdata = le16_to_cpu(retdatai); - return ret; - } + if (i >= REG_TIMEOUT) + goto fail; + + ret = get_registers(pegasus, EpromData, 2, &retdatai); + *retdata = le16_to_cpu(retdatai); + return ret; fail: - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); + netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); return -ETIMEDOUT; } @@ -475,11 +475,13 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) break; } disable_eprom_write(pegasus); - if (i < REG_TIMEOUT) - return ret; + if (i >= REG_TIMEOUT) + goto fail; + + return ret; + fail: - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "%s failed\n", __func__); + netif_warn(pegasus, drv, pegasus->net, "%s failed\n", __func__); return -ETIMEDOUT; } #endif /* PEGASUS_WRITE_EEPROM */ @@ -642,25 +644,20 @@ static void read_bulk_callback(struct urb *urb) case 0: break; case -ETIME: - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: reset MAC\n", net->name); + netif_dbg(pegasus, rx_err, net, "reset MAC\n"); pegasus->flags &= ~PEGASUS_RX_BUSY; break; case -EPIPE: /* stall, or disconnect from TT */ /* FIXME schedule work to clear the halt */ - if (netif_msg_rx_err(pegasus)) - printk(KERN_WARNING "%s: no rx stall recovery\n", - net->name); + netif_warn(pegasus, rx_err, net, "no rx stall recovery\n"); return; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: - if (netif_msg_ifdown(pegasus)) - pr_debug("%s: rx unlink, %d\n", net->name, status); + netif_dbg(pegasus, ifdown, net, "rx unlink, %d\n", status); return; default: - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: RX status %d\n", net->name, status); + netif_dbg(pegasus, rx_err, net, "RX status %d\n", status); goto goon; } @@ -669,9 +666,8 @@ static void read_bulk_callback(struct urb *urb) rx_status = buf[count - 2]; if (rx_status & 0x1e) { - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: RX packet error %x\n", - net->name, rx_status); + netif_dbg(pegasus, rx_err, net, + "RX packet error %x\n", rx_status); pegasus->stats.rx_errors++; if (rx_status & 0x06) // long or runt pegasus->stats.rx_length_errors++; @@ -758,9 +754,7 @@ static void rx_fixup(unsigned long data) pegasus->rx_skb = pull_skb(pegasus); } if (pegasus->rx_skb == NULL) { - if (netif_msg_rx_err(pegasus)) - printk(KERN_WARNING "%s: low on memory\n", - pegasus->net->name); + netif_warn(pegasus, rx_err, pegasus->net, "low on memory\n"); tasklet_schedule(&pegasus->rx_tl); goto done; } @@ -800,19 +794,15 @@ static void write_bulk_callback(struct urb *urb) case -EPIPE: /* FIXME schedule_work() to clear the tx halt */ netif_stop_queue(net); - if (netif_msg_tx_err(pegasus)) - printk(KERN_WARNING "%s: no tx stall recovery\n", - net->name); + netif_warn(pegasus, tx_err, net, "no tx stall recovery\n"); return; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: - if (netif_msg_ifdown(pegasus)) - pr_debug("%s: tx unlink, %d\n", net->name, status); + netif_dbg(pegasus, ifdown, net, "tx unlink, %d\n", status); return; default: - if (netif_msg_tx_err(pegasus)) - pr_info("%s: TX status %d\n", net->name, status); + netif_info(pegasus, tx_err, net, "TX status %d\n", status); /* FALL THROUGH */ case 0: break; @@ -843,9 +833,7 @@ static void intr_callback(struct urb *urb) /* some Pegasus-I products report LOTS of data * toggle errors... avoid log spamming */ - if (netif_msg_timer(pegasus)) - pr_debug("%s: intr status %d\n", net->name, - status); + netif_dbg(pegasus, timer, net, "intr status %d\n", status); } if (urb->actual_length >= 6) { @@ -875,16 +863,15 @@ static void intr_callback(struct urb *urb) res = usb_submit_urb(urb, GFP_ATOMIC); if (res == -ENODEV) netif_device_detach(pegasus->net); - if (res && netif_msg_timer(pegasus)) - printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", - net->name, res); + if (res) + netif_err(pegasus, timer, net, + "can't resubmit interrupt urb, %d\n", res); } static void pegasus_tx_timeout(struct net_device *net) { pegasus_t *pegasus = netdev_priv(net); - if (netif_msg_timer(pegasus)) - printk(KERN_WARNING "%s: tx timeout\n", net->name); + netif_warn(pegasus, timer, net, "tx timeout\n"); usb_unlink_urb(pegasus->tx_urb); pegasus->stats.tx_errors++; } @@ -906,9 +893,7 @@ static netdev_tx_t pegasus_start_xmit(struct sk_buff *skb, pegasus->tx_buff, count, write_bulk_callback, pegasus); if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { - if (netif_msg_tx_err(pegasus)) - printk(KERN_WARNING "%s: fail tx, %d\n", - net->name, res); + netif_warn(pegasus, tx_err, net, "fail tx, %d\n", res); switch (res) { case -EPIPE: /* stall, or disconnect from TT */ /* cleanup should already have been scheduled */ @@ -952,10 +937,9 @@ static inline void get_interrupt_interval(pegasus_t * pegasus) interval = data >> 8; if (pegasus->usb->speed != USB_SPEED_HIGH) { if (interval < 0x80) { - if (netif_msg_timer(pegasus)) - dev_info(&pegasus->intf->dev, "intr interval " - "changed from %ums to %ums\n", - interval, 0x80); + netif_info(pegasus, timer, pegasus->net, + "intr interval changed from %ums to %ums\n", + interval, 0x80); interval = 0x80; data = (data & 0x00FF) | ((u16)interval << 8); #ifdef PEGASUS_WRITE_EEPROM @@ -1046,8 +1030,7 @@ static int pegasus_open(struct net_device *net) if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { if (res == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_ifup(pegasus)) - pr_debug("%s: failed rx_urb, %d", net->name, res); + netif_dbg(pegasus, ifup, net, "failed rx_urb, %d\n", res); goto exit; } @@ -1058,15 +1041,13 @@ static int pegasus_open(struct net_device *net) if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { if (res == -ENODEV) netif_device_detach(pegasus->net); - if (netif_msg_ifup(pegasus)) - pr_debug("%s: failed intr_urb, %d\n", net->name, res); + netif_dbg(pegasus, ifup, net, "failed intr_urb, %d\n", res); usb_kill_urb(pegasus->rx_urb); goto exit; } if ((res = enable_net_traffic(net, pegasus->usb))) { - if (netif_msg_ifup(pegasus)) - pr_debug("%s: can't enable_net_traffic() - %d\n", - net->name, res); + netif_dbg(pegasus, ifup, net, + "can't enable_net_traffic() - %d\n", res); res = -EIO; usb_kill_urb(pegasus->rx_urb); usb_kill_urb(pegasus->intr_urb); @@ -1075,8 +1056,7 @@ static int pegasus_open(struct net_device *net) } set_carrier(net); netif_start_queue(net); - if (netif_msg_ifup(pegasus)) - pr_debug("%s: open\n", net->name); + netif_dbg(pegasus, ifup, net, "open\n"); res = 0; exit: return res; @@ -1230,13 +1210,11 @@ static void pegasus_set_multicast(struct net_device *net) if (net->flags & IFF_PROMISC) { pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; - if (netif_msg_link(pegasus)) - pr_info("%s: Promiscuous mode enabled.\n", net->name); + netif_info(pegasus, link, net, "Promiscuous mode enabled\n"); } else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) { pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; - if (netif_msg_link(pegasus)) - pr_debug("%s: set allmulti\n", net->name); + netif_dbg(pegasus, link, net, "set allmulti\n"); } else { pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST; pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index f01f02401856..4ce331fb1e1e 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -335,8 +335,8 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) dev->maxpacket = usb_maxpacket(dev->udev, dev->out, 1); if (dev->maxpacket == 0) { - if (netif_msg_probe(dev)) - dev_dbg(&intf->dev, "dev->maxpacket can't be 0\n"); + netif_dbg(dev, probe, dev->net, + "dev->maxpacket can't be 0\n"); retval = -EINVAL; goto fail_and_release; } @@ -394,17 +394,15 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) } if ((flags & FLAG_RNDIS_PHYM_WIRELESS) && *phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) { - if (netif_msg_probe(dev)) - dev_dbg(&intf->dev, "driver requires wireless " - "physical medium, but device is not.\n"); + netif_dbg(dev, probe, dev->net, + "driver requires wireless physical medium, but device is not\n"); retval = -ENODEV; goto halt_fail_and_release; } if ((flags & FLAG_RNDIS_PHYM_NOT_WIRELESS) && *phym == RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) { - if (netif_msg_probe(dev)) - dev_dbg(&intf->dev, "driver requires non-wireless " - "physical medium, but device is wireless.\n"); + netif_dbg(dev, probe, dev->net, + "driver requires non-wireless physical medium, but device is wireless.\n"); retval = -ENODEV; goto halt_fail_and_release; } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index d4cbcefbff38..1ada51eb71f7 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -376,13 +376,11 @@ static void smsc95xx_set_multicast(struct net_device *netdev) spin_lock_irqsave(&pdata->mac_cr_lock, flags); if (dev->net->flags & IFF_PROMISC) { - if (netif_msg_drv(dev)) - netdev_dbg(dev->net, "promiscuous mode enabled\n"); + netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n"); pdata->mac_cr |= MAC_CR_PRMS_; pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_); } else if (dev->net->flags & IFF_ALLMULTI) { - if (netif_msg_drv(dev)) - netdev_dbg(dev->net, "receive all multicast enabled\n"); + netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n"); pdata->mac_cr |= MAC_CR_MCPAS_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev->net)) { @@ -410,12 +408,10 @@ static void smsc95xx_set_multicast(struct net_device *netdev) if (count != ((u32) netdev_mc_count(dev->net))) netdev_warn(dev->net, "mc_count != dev->mc_count\n"); - if (netif_msg_drv(dev)) - netdev_dbg(dev->net, "HASHH=0x%08X, HASHL=0x%08X\n", + netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n", hash_hi, hash_lo); } else { - if (netif_msg_drv(dev)) - netdev_dbg(dev->net, "receive own packets only\n"); + netif_dbg(dev, drv, dev->net, "receive own packets only\n"); pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_); } @@ -452,13 +448,11 @@ static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, else afc_cfg &= ~0xF; - if (netif_msg_link(dev)) - netdev_dbg(dev->net, "rx pause %s, tx pause %s\n", + netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n", cap & FLOW_CTRL_RX ? "enabled" : "disabled", cap & FLOW_CTRL_TX ? "enabled" : "disabled"); } else { - if (netif_msg_link(dev)) - netdev_dbg(dev->net, "half duplex\n"); + netif_dbg(dev, link, dev->net, "half duplex\n"); flow = 0; afc_cfg |= 0xF; } @@ -486,9 +480,8 @@ static int smsc95xx_link_reset(struct usbnet *dev) lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); - if (netif_msg_link(dev)) - netdev_dbg(dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", - ecmd.speed, ecmd.duplex, lcladv, rmtadv); + netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x\n", + ecmd.speed, ecmd.duplex, lcladv, rmtadv); spin_lock_irqsave(&pdata->mac_cr_lock, flags); if (ecmd.duplex != DUPLEX_FULL) { @@ -520,8 +513,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb) memcpy(&intdata, urb->transfer_buffer, 4); le32_to_cpus(&intdata); - if (netif_msg_link(dev)) - netdev_dbg(dev->net, "intdata: 0x%08X\n", intdata); + netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata); if (intdata & INT_ENP_PHY_INT_) usbnet_defer_kevent(dev, EVENT_LINK_RESET); @@ -557,8 +549,7 @@ static int smsc95xx_set_csums(struct usbnet *dev) return ret; } - if (netif_msg_hw(dev)) - netdev_dbg(dev->net, "COE_CR = 0x%08x\n", read_buf); + netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf); return 0; } @@ -662,16 +653,14 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) dev->net->dev_addr) == 0) { if (is_valid_ether_addr(dev->net->dev_addr)) { /* eeprom values are valid so use them */ - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "MAC address read from EEPROM\n"); + netif_dbg(dev, ifup, dev->net, "MAC address read from EEPROM\n"); return; } } /* no eeprom, or eeprom values are invalid. generate random MAC */ random_ether_addr(dev->net->dev_addr); - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "MAC address set to random_ether_addr\n"); + netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); } static int smsc95xx_set_mac_address(struct usbnet *dev) @@ -750,8 +739,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev) PHY_INT_MASK_DEFAULT_); mii_nway_restart(&dev->mii); - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "phy initialised successfully\n"); + netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n"); return 0; } @@ -762,8 +750,7 @@ static int smsc95xx_reset(struct usbnet *dev) u32 read_buf, write_buf, burst_cap; int ret = 0, timeout; - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "entering smsc95xx_reset\n"); + netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n"); write_buf = HW_CFG_LRST_; ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); @@ -818,8 +805,8 @@ static int smsc95xx_reset(struct usbnet *dev) if (ret < 0) return ret; - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "MAC Address: %pM\n", dev->net->dev_addr); + netif_dbg(dev, ifup, dev->net, + "MAC Address: %pM\n", dev->net->dev_addr); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { @@ -827,8 +814,8 @@ static int smsc95xx_reset(struct usbnet *dev) return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from HW_CFG : 0x%08x\n", read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from HW_CFG : 0x%08x\n", read_buf); read_buf |= HW_CFG_BIR_; @@ -844,9 +831,9 @@ static int smsc95xx_reset(struct usbnet *dev) netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n", - read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n", + read_buf); if (!turbo_mode) { burst_cap = 0; @@ -859,8 +846,8 @@ static int smsc95xx_reset(struct usbnet *dev) dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size); + netif_dbg(dev, ifup, dev->net, + "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size); ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); if (ret < 0) { @@ -873,9 +860,9 @@ static int smsc95xx_reset(struct usbnet *dev) netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from BURST_CAP after writing: 0x%08x\n", - read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from BURST_CAP after writing: 0x%08x\n", + read_buf); read_buf = DEFAULT_BULK_IN_DELAY; ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); @@ -889,17 +876,17 @@ static int smsc95xx_reset(struct usbnet *dev) netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from BULK_IN_DLY after writing: 0x%08x\n", - read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from BULK_IN_DLY after writing: 0x%08x\n", + read_buf); ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); if (ret < 0) { netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from HW_CFG: 0x%08x\n", read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from HW_CFG: 0x%08x\n", read_buf); if (turbo_mode) read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_); @@ -921,9 +908,8 @@ static int smsc95xx_reset(struct usbnet *dev) netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "Read Value from HW_CFG after writing: 0x%08x\n", - read_buf); + netif_dbg(dev, ifup, dev->net, + "Read Value from HW_CFG after writing: 0x%08x\n", read_buf); write_buf = 0xFFFFFFFF; ret = smsc95xx_write_reg(dev, INT_STS, write_buf); @@ -938,8 +924,7 @@ static int smsc95xx_reset(struct usbnet *dev) netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret); return ret; } - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "ID_REV = 0x%08x\n", read_buf); + netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf); /* Configure GPIO pins as LED outputs */ write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | @@ -1013,8 +998,7 @@ static int smsc95xx_reset(struct usbnet *dev) smsc95xx_start_tx_path(dev); smsc95xx_start_rx_path(dev); - if (netif_msg_ifup(dev)) - netdev_dbg(dev->net, "smsc95xx_reset, return 0\n"); + netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n"); return 0; } @@ -1071,8 +1055,7 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) { struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); if (pdata) { - if (netif_msg_ifdown(dev)) - netdev_dbg(dev->net, "free pdata\n"); + netif_dbg(dev, ifdown, dev->net, "free pdata\n"); kfree(pdata); pdata = NULL; dev->data[0] = 0; @@ -1106,9 +1089,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4; if (unlikely(header & RX_STS_ES_)) { - if (netif_msg_rx_err(dev)) - netdev_dbg(dev->net, "Error header=0x%08x\n", - header); + netif_dbg(dev, rx_err, dev->net, + "Error header=0x%08x\n", header); dev->net->stats.rx_errors++; dev->net->stats.rx_dropped++; @@ -1125,9 +1107,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } else { /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ if (unlikely(size > (ETH_FRAME_LEN + 12))) { - if (netif_msg_rx_err(dev)) - netdev_dbg(dev->net, "size err header=0x%08x\n", - header); + netif_dbg(dev, rx_err, dev->net, + "size err header=0x%08x\n", header); return 0; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 8e732930d249..17b6a62d206e 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -242,13 +242,13 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) dev->net->stats.rx_packets++; dev->net->stats.rx_bytes += skb->len; - if (netif_msg_rx_status (dev)) - netdev_dbg(dev->net, "< rx, len %zu, type 0x%x\n", - skb->len + sizeof (struct ethhdr), skb->protocol); + netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n", + skb->len + sizeof (struct ethhdr), skb->protocol); memset (skb->cb, 0, sizeof (struct skb_data)); status = netif_rx (skb); - if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "netif_rx status %d\n", status); + if (status != NET_RX_SUCCESS) + netif_dbg(dev, rx_err, dev->net, + "netif_rx status %d\n", status); } EXPORT_SYMBOL_GPL(usbnet_skb_return); @@ -332,8 +332,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) size_t size = dev->rx_urb_size; if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "no rx skb\n"); + netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); usbnet_defer_kevent (dev, EVENT_RX_MEMORY); usb_free_urb (urb); return; @@ -363,21 +362,19 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) usbnet_defer_kevent (dev, EVENT_RX_MEMORY); break; case -ENODEV: - if (netif_msg_ifdown (dev)) - netdev_dbg(dev->net, "device gone\n"); + netif_dbg(dev, ifdown, dev->net, "device gone\n"); netif_device_detach (dev->net); break; default: - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "rx submit, %d\n", retval); + netif_dbg(dev, rx_err, dev->net, + "rx submit, %d\n", retval); tasklet_schedule (&dev->bh); break; case 0: __skb_queue_tail (&dev->rxq, skb); } } else { - if (netif_msg_ifdown (dev)) - netdev_dbg(dev->net, "rx: stopped\n"); + netif_dbg(dev, ifdown, dev->net, "rx: stopped\n"); retval = -ENOLINK; } spin_unlock_irqrestore (&dev->rxq.lock, lockflags); @@ -400,8 +397,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) if (skb->len) usbnet_skb_return (dev, skb); else { - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "drop\n"); + netif_dbg(dev, rx_err, dev->net, "drop\n"); error: dev->net->stats.rx_errors++; skb_queue_tail (&dev->done, skb); @@ -428,8 +424,8 @@ static void rx_complete (struct urb *urb) entry->state = rx_cleanup; dev->net->stats.rx_errors++; dev->net->stats.rx_length_errors++; - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "rx length %d\n", skb->len); + netif_dbg(dev, rx_err, dev->net, + "rx length %d\n", skb->len); } break; @@ -446,8 +442,8 @@ static void rx_complete (struct urb *urb) /* software-driven interface shutdown */ case -ECONNRESET: /* async unlink */ case -ESHUTDOWN: /* hardware gone */ - if (netif_msg_ifdown (dev)) - netdev_dbg(dev->net, "rx shutdown, code %d\n", urb_status); + netif_dbg(dev, ifdown, dev->net, + "rx shutdown, code %d\n", urb_status); goto block; /* we get controller i/o faults during khubd disconnect() delays. @@ -460,8 +456,8 @@ static void rx_complete (struct urb *urb) dev->net->stats.rx_errors++; if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); - if (netif_msg_link (dev)) - netdev_dbg(dev->net, "rx throttle %d\n", urb_status); + netif_dbg(dev, link, dev->net, + "rx throttle %d\n", urb_status); } block: entry->state = rx_cleanup; @@ -477,8 +473,7 @@ block: default: entry->state = rx_cleanup; dev->net->stats.rx_errors++; - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "rx status %d\n", urb_status); + netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status); break; } @@ -492,8 +487,7 @@ block: } usb_free_urb (urb); } - if (netif_msg_rx_err (dev)) - netdev_dbg(dev->net, "no read resubmitted\n"); + netif_dbg(dev, rx_err, dev->net, "no read resubmitted\n"); } static void intr_complete (struct urb *urb) @@ -510,8 +504,8 @@ static void intr_complete (struct urb *urb) /* software-driven interface shutdown */ case -ENOENT: /* urb killed */ case -ESHUTDOWN: /* hardware gone */ - if (netif_msg_ifdown (dev)) - netdev_dbg(dev->net, "intr shutdown, code %d\n", status); + netif_dbg(dev, ifdown, dev->net, + "intr shutdown, code %d\n", status); return; /* NOTE: not throttling like RX/TX, since this endpoint @@ -527,8 +521,9 @@ static void intr_complete (struct urb *urb) memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); status = usb_submit_urb (urb, GFP_ATOMIC); - if (status != 0 && netif_msg_timer (dev)) - netdev_err(dev->net, "intr resubmit --> %d\n", status); + if (status != 0) + netif_err(dev, timer, dev->net, + "intr resubmit --> %d\n", status); } /*-------------------------------------------------------------------------*/ @@ -536,8 +531,7 @@ void usbnet_pause_rx(struct usbnet *dev) { set_bit(EVENT_RX_PAUSED, &dev->flags); - if (netif_msg_rx_status(dev)) - netdev_dbg(dev->net, "paused rx queue enabled\n"); + netif_dbg(dev, rx_status, dev->net, "paused rx queue enabled\n"); } EXPORT_SYMBOL_GPL(usbnet_pause_rx); @@ -555,9 +549,8 @@ void usbnet_resume_rx(struct usbnet *dev) tasklet_schedule(&dev->bh); - if (netif_msg_rx_status(dev)) - netdev_dbg(dev->net, "paused rx queue disabled, %d skbs requeued\n", - num); + netif_dbg(dev, rx_status, dev->net, + "paused rx queue disabled, %d skbs requeued\n", num); } EXPORT_SYMBOL_GPL(usbnet_resume_rx); @@ -632,9 +625,8 @@ static void usbnet_terminate_urbs(struct usbnet *dev) && !skb_queue_empty(&dev->done)) { schedule_timeout(UNLINK_TIMEOUT_MS); set_current_state(TASK_UNINTERRUPTIBLE); - if (netif_msg_ifdown(dev)) - netdev_dbg(dev->net, "waited for %d urb completions\n", - temp); + netif_dbg(dev, ifdown, dev->net, + "waited for %d urb completions\n", temp); } set_current_state(TASK_RUNNING); dev->wait = NULL; @@ -649,21 +641,21 @@ int usbnet_stop (struct net_device *net) netif_stop_queue (net); - if (netif_msg_ifdown (dev)) - netdev_info(dev->net, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", - net->stats.rx_packets, net->stats.tx_packets, - net->stats.rx_errors, net->stats.tx_errors); + netif_info(dev, ifdown, dev->net, + "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", + net->stats.rx_packets, net->stats.tx_packets, + net->stats.rx_errors, net->stats.tx_errors); /* allow minidriver to stop correctly (wireless devices to turn off * radio etc) */ if (info->stop) { retval = info->stop(dev); - if (retval < 0 && netif_msg_ifdown(dev)) - netdev_info(dev->net, - "stop fail (%d) usbnet usb-%s-%s, %s\n", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); + if (retval < 0) + netif_info(dev, ifdown, dev->net, + "stop fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, dev->udev->devpath, + info->description); } if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) @@ -702,32 +694,29 @@ int usbnet_open (struct net_device *net) struct driver_info *info = dev->driver_info; if ((retval = usb_autopm_get_interface(dev->intf)) < 0) { - if (netif_msg_ifup (dev)) - netdev_info(dev->net, - "resumption fail (%d) usbnet usb-%s-%s, %s\n", - retval, - dev->udev->bus->bus_name, - dev->udev->devpath, - info->description); + netif_info(dev, ifup, dev->net, + "resumption fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, + dev->udev->devpath, + info->description); goto done_nopm; } // put into "known safe" state if (info->reset && (retval = info->reset (dev)) < 0) { - if (netif_msg_ifup (dev)) - netdev_info(dev->net, - "open reset fail (%d) usbnet usb-%s-%s, %s\n", - retval, - dev->udev->bus->bus_name, - dev->udev->devpath, - info->description); + netif_info(dev, ifup, dev->net, + "open reset fail (%d) usbnet usb-%s-%s, %s\n", + retval, + dev->udev->bus->bus_name, + dev->udev->devpath, + info->description); goto done; } // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { - if (netif_msg_ifup (dev)) - netdev_dbg(dev->net, "can't open; %d\n", retval); + netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval); goto done; } @@ -735,33 +724,23 @@ int usbnet_open (struct net_device *net) if (dev->interrupt) { retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); if (retval < 0) { - if (netif_msg_ifup (dev)) - netdev_err(dev->net, "intr submit %d\n", retval); + netif_err(dev, ifup, dev->net, + "intr submit %d\n", retval); goto done; } } netif_start_queue (net); - if (netif_msg_ifup (dev)) { - char *framing; - - if (dev->driver_info->flags & FLAG_FRAMING_NC) - framing = "NetChip"; - else if (dev->driver_info->flags & FLAG_FRAMING_GL) - framing = "GeneSys"; - else if (dev->driver_info->flags & FLAG_FRAMING_Z) - framing = "Zaurus"; - else if (dev->driver_info->flags & FLAG_FRAMING_RN) - framing = "RNDIS"; - else if (dev->driver_info->flags & FLAG_FRAMING_AX) - framing = "ASIX"; - else - framing = "simple"; - - netdev_info(dev->net, "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", - (int)RX_QLEN(dev), (int)TX_QLEN(dev), - dev->net->mtu, framing); - } + netif_info(dev, ifup, dev->net, + "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", + (int)RX_QLEN(dev), (int)TX_QLEN(dev), + dev->net->mtu, + (dev->driver_info->flags & FLAG_FRAMING_NC) ? "NetChip" : + (dev->driver_info->flags & FLAG_FRAMING_GL) ? "GeneSys" : + (dev->driver_info->flags & FLAG_FRAMING_Z) ? "Zaurus" : + (dev->driver_info->flags & FLAG_FRAMING_RN) ? "RNDIS" : + (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" : + "simple"); // delay posting reads until we're fully open tasklet_schedule (&dev->bh); @@ -772,6 +751,7 @@ int usbnet_open (struct net_device *net) usb_autopm_put_interface(dev->intf); } return retval; + done: usb_autopm_put_interface(dev->intf); done_nopm: @@ -1015,16 +995,14 @@ static void tx_complete (struct urb *urb) if (!timer_pending (&dev->delay)) { mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); - if (netif_msg_link (dev)) - netdev_dbg(dev->net, "tx throttle %d\n", - urb->status); + netif_dbg(dev, link, dev->net, + "tx throttle %d\n", urb->status); } netif_stop_queue (dev->net); break; default: - if (netif_msg_tx_err (dev)) - netdev_dbg(dev->net, "tx err %d\n", - entry->urb->status); + netif_dbg(dev, tx_err, dev->net, + "tx err %d\n", entry->urb->status); break; } } @@ -1066,16 +1044,14 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, if (info->tx_fixup) { skb = info->tx_fixup (dev, skb, GFP_ATOMIC); if (!skb) { - if (netif_msg_tx_err (dev)) - netdev_dbg(dev->net, "can't tx_fixup skb\n"); + netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); goto drop; } } length = skb->len; if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { - if (netif_msg_tx_err (dev)) - netdev_dbg(dev->net, "no urb\n"); + netif_dbg(dev, tx_err, dev->net, "no urb\n"); goto drop; } @@ -1128,8 +1104,8 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, break; default: usb_autopm_put_interface_async(dev->intf); - if (netif_msg_tx_err (dev)) - netdev_dbg(dev->net, "tx: submit urb err %d\n", retval); + netif_dbg(dev, tx_err, dev->net, + "tx: submit urb err %d\n", retval); break; case 0: net->trans_start = jiffies; @@ -1140,17 +1116,15 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, spin_unlock_irqrestore (&dev->txq.lock, flags); if (retval) { - if (netif_msg_tx_err (dev)) - netdev_dbg(dev->net, "drop, code %d\n", retval); + netif_dbg(dev, tx_err, dev->net, "drop, code %d\n", retval); drop: dev->net->stats.tx_dropped++; if (skb) dev_kfree_skb_any (skb); usb_free_urb (urb); - } else if (netif_msg_tx_queued (dev)) { - netdev_dbg(dev->net, "> tx, len %d, type 0x%x\n", - length, skb->protocol); - } + } else + netif_dbg(dev, tx_queued, dev->net, + "> tx, len %d, type 0x%x\n", length, skb->protocol); #ifdef CONFIG_PM deferred: #endif @@ -1209,9 +1183,10 @@ static void usbnet_bh (unsigned long param) if (urb != NULL) rx_submit (dev, urb, GFP_ATOMIC); } - if (temp != dev->rxq.qlen && netif_msg_link (dev)) - netdev_dbg(dev->net, "rxqlen %d --> %d\n", - temp, dev->rxq.qlen); + if (temp != dev->rxq.qlen) + netif_dbg(dev, link, dev->net, + "rxqlen %d --> %d\n", + temp, dev->rxq.qlen); if (dev->rxq.qlen < qlen) tasklet_schedule (&dev->bh); } @@ -1242,11 +1217,10 @@ void usbnet_disconnect (struct usb_interface *intf) xdev = interface_to_usbdev (intf); - if (netif_msg_probe (dev)) - netdev_info(dev->net, "unregister '%s' usb-%s-%s, %s\n", - intf->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description); + netif_info(dev, probe, dev->net, "unregister '%s' usb-%s-%s, %s\n", + intf->dev.driver->name, + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description); net = dev->net; unregister_netdev (net); @@ -1409,12 +1383,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) status = register_netdev (net); if (status) goto out3; - if (netif_msg_probe (dev)) - netdev_info(dev->net, "register '%s' at usb-%s-%s, %s, %pM\n", - udev->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description, - net->dev_addr); + netif_info(dev, probe, dev->net, + "register '%s' at usb-%s-%s, %s, %pM\n", + udev->dev.driver->name, + xdev->bus->bus_name, xdev->devpath, + dev->driver_info->description, + net->dev_addr); // ok, it's ready to go. usb_set_intfdata (udev, dev); -- cgit v1.2.3 From 6cbe5065bb367d4c8db0a71d2e828995bcfae336 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 02:03:27 +0000 Subject: bnx2x: Properly release allocated MSI-X/MSI vectors Bug fix: Properly release allocated MSI-X/MSI vectors if ifup failed due to lack of memory. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 6d8559052ee6..d7aef840a1d5 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6938,19 +6938,21 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp) } } -static void bnx2x_free_irq(struct bnx2x *bp) +static void bnx2x_free_irq(struct bnx2x *bp, bool disable_only) { if (bp->flags & USING_MSIX_FLAG) { - bnx2x_free_msix_irqs(bp); + if (!disable_only) + bnx2x_free_msix_irqs(bp); pci_disable_msix(bp->pdev); bp->flags &= ~USING_MSIX_FLAG; } else if (bp->flags & USING_MSI_FLAG) { - free_irq(bp->pdev->irq, bp->dev); + if (!disable_only) + free_irq(bp->pdev->irq, bp->dev); pci_disable_msi(bp->pdev); bp->flags &= ~USING_MSI_FLAG; - } else + } else if (!disable_only) free_irq(bp->pdev->irq, bp->dev); } @@ -7443,8 +7445,10 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_set_num_queues(bp); - if (bnx2x_alloc_mem(bp)) + if (bnx2x_alloc_mem(bp)) { + bnx2x_free_irq(bp, true); return -ENOMEM; + } for_each_queue(bp, i) bnx2x_fp(bp, i, disable_tpa) = @@ -7459,7 +7463,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (bp->flags & USING_MSIX_FLAG) { rc = bnx2x_req_msix_irqs(bp); if (rc) { - pci_disable_msix(bp->pdev); + bnx2x_free_irq(bp, true); goto load_error1; } } else { @@ -7471,8 +7475,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_req_irq(bp); if (rc) { BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); - if (bp->flags & USING_MSI_FLAG) - pci_disable_msi(bp->pdev); + bnx2x_free_irq(bp, true); goto load_error1; } if (bp->flags & USING_MSI_FLAG) { @@ -7664,7 +7667,7 @@ load_error3: bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); load_error2: /* Release IRQs */ - bnx2x_free_irq(bp); + bnx2x_free_irq(bp, false); load_error1: bnx2x_napi_disable(bp); for_each_queue(bp, i) @@ -7855,7 +7858,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_stats_handle(bp, STATS_EVENT_STOP); /* Release IRQs */ - bnx2x_free_irq(bp); + bnx2x_free_irq(bp, false); /* Wait until tx fastpath tasks complete */ for_each_queue(bp, i) { @@ -12299,7 +12302,7 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp) DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n"); /* Release IRQs */ - bnx2x_free_irq(bp); + bnx2x_free_irq(bp, false); if (CHIP_IS_E1(bp)) { struct mac_configuration_cmd *config = -- cgit v1.2.3 From f1e1a199f3a68a32cf86095b3650d761ee8798b9 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 02:03:33 +0000 Subject: bnx2x: clean up in case of error in bnx2x_init_hw() Bug fix: clean up MCP state in case of error in bnx2x_init_hw(). Author: Dmitry Kravkov Signed-off-by: Dmitry Kravkov Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d7aef840a1d5..16685a153c10 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -7530,6 +7530,9 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); + bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); goto load_error2; } -- cgit v1.2.3 From d43a7e67ae2f911765b3d5b6cbb85221a9ffd0a4 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 02:03:40 +0000 Subject: bnx2x: Do not allow enabling LRO if disable_tpa=1 Bug fix: Do not allow enabling LRO if disable_tpa=1. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 16685a153c10..ccdc3fe13414 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9968,12 +9968,14 @@ static int bnx2x_set_flags(struct net_device *dev, u32 data) /* TPA requires Rx CSUM offloading */ if ((data & ETH_FLAG_LRO) && bp->rx_csum) { - if (!(dev->features & NETIF_F_LRO)) { - dev->features |= NETIF_F_LRO; - bp->flags |= TPA_ENABLE_FLAG; - changed = 1; - } - + if (!disable_tpa) { + if (!(dev->features & NETIF_F_LRO)) { + dev->features |= NETIF_F_LRO; + bp->flags |= TPA_ENABLE_FLAG; + changed = 1; + } + } else + rc = -EINVAL; } else if (dev->features & NETIF_F_LRO) { dev->features &= ~NETIF_F_LRO; bp->flags &= ~TPA_ENABLE_FLAG; -- cgit v1.2.3 From 0c43f43f48c5c60d62c4d26917da3ee71df464ea Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 02:04:00 +0000 Subject: bnx2x: fix in 57710 self-test Bug fix: Use the last unicast entry in CAM in bnx2x_test_int(). Relevant for 57710 only. Author: Dmitry Kravkov Signed-off-by: Dmitry Kravkov Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index ccdc3fe13414..24fe083ee1be 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10433,7 +10433,8 @@ static int bnx2x_test_intr(struct bnx2x *bp) config->hdr.length = 0; if (CHIP_IS_E1(bp)) - config->hdr.offset = (BP_PORT(bp) ? 32 : 0); + /* use last unicast entries */ + config->hdr.offset = (BP_PORT(bp) ? 63 : 31); else config->hdr.offset = BP_FUNC(bp); config->hdr.client_id = bp->fp->cl_id; -- cgit v1.2.3 From 2db29fc71b7e6af41aa1fadb67f588846dc461cf Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 13:33:02 -0800 Subject: bnx2x: FW 5.2.13 New firmware version (5.2.13). Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- firmware/bnx2x-e1-5.2.13.0.fw.ihex | 10191 +++++++++++++++++++++++++++ firmware/bnx2x-e1h-5.2.13.0.fw.ihex | 12849 ++++++++++++++++++++++++++++++++++ 2 files changed, 23040 insertions(+) create mode 100644 firmware/bnx2x-e1-5.2.13.0.fw.ihex create mode 100644 firmware/bnx2x-e1h-5.2.13.0.fw.ihex diff --git a/firmware/bnx2x-e1-5.2.13.0.fw.ihex b/firmware/bnx2x-e1-5.2.13.0.fw.ihex new file mode 100644 index 000000000000..651f4346d89e --- /dev/null +++ b/firmware/bnx2x-e1-5.2.13.0.fw.ihex @@ -0,0 +1,10191 @@ +:10000000000028B0000000600000068800002918E9 +:100010000000161400002FA800000098000045C042 +:10002000000073C400004660000000CC0000BA2845 +:1000300000009A700000BAF80000009400015570AA +:10004000000057BC00015608000000B80001ADC810 +:100050000000CE200001AE880000000400027CB049 +:10006000020400480000000F020400540000004594 +:1000700002040058000000840204005C0000000636 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000060400CC0000000418 +:10010000020400DC00100000020400E012140000F1 +:10011000020400E422140000020400E8321400008B +:10012000060400EC000000040104012400000000AB +:1001300001040128000000000104012C000000005F +:10014000010401300000000002040004000000FF70 +:1001500002040008000000FF0204000C000000FF81 +:1001600002040010000000FF02040014000000FF61 +:1001700002040018000000FF0204001C000000FF41 +:1001800002040020000000FF020400240000003EE2 +:1001900002040028000000000204002C0000003FC0 +:1001A000020400300000003F020400340000003F61 +:1001B00002040038000000000204003C0000003F80 +:1001C000020400400000003F020400440000003F21 +:1001D00002042008000004110204200C00000400A6 +:1001E000020420100000040402042014000004197A +:1001F0000204201C0000FFFF020420200000FFFF7B +:10020000020420240000FFFF020420280000FFFF5A +:1002100006042038000000020204204000000034E0 +:100220000204204400000035060420480000007C41 +:100230000204223807FFFFFF0204223C0000003FB7 +:100240000204224007FFFFFF020422440000000FC7 +:1002500001042248000000000104224C00000000BC +:10026000010422500000000001042254000000009C +:1002700001042258000000000104225C000000007C +:10028000010422600000000001042264000000005C +:1002900001042268000000000104226C000000003C +:1002A000010422700000000001042274000000001C +:1002B00001042278000000000104227C00000000FC +:1002C000020424BC000000010C042000000003E82C +:1002D0000A042000000000010B0420000000000AB6 +:1002E0000205004400000020020500480000003222 +:1002F000020500900215002002050094021500205E +:1003000002050098000000300205009C0810000063 +:10031000020500A000000033020500A40000003028 +:10032000020500A800000031020500AC0000000238 +:10033000020500B000000005020500B40000000640 +:10034000020500B800000002020500BC0000000227 +:10035000020500C000000000020500C40000000506 +:10036000020500C800000002020500CC00000002E7 +:10037000020500D000000002020500D400000001C8 +:1003800002050114000000010205011C000000012B +:100390000205012000000002020502040000000125 +:1003A0000205020C0000004002050210000000409F +:1003B0000205021C000000200205022000000013BC +:1003C0000205022400000020060502400000000A89 +:1003D0000405028000200000020500500000000714 +:1003E0000205005400000007020500580000000844 +:1003F0000205005C00000008060500600000000423 +:10040000020500D800000006020500E00000000D13 +:10041000020500E40000002D020500E800000007CE +:10042000020500EC00000027020500F000000007B4 +:10043000020500F400000027020500F80000000794 +:10044000020500FC00000027020500040000000176 +:1004500002050008000000010205000C0000000178 +:100460000205001000000001020500140000000158 +:1004700002050018000000010205001C0000000138 +:100480000205002000000001020500240000000118 +:1004900002050028000000010205002C00000001F8 +:1004A00002050030000000010205003400000001D8 +:1004B00002050038000000010205003C00000001B8 +:1004C00002050040000000010406100002000020A8 +:1004D000020600DC00000001010600D80000000058 +:1004E0000406020000030220020600DC00000000F7 +:1004F00002060068000000B802060078000001143F +:10050000010600B800000000010600C8000000005D +:100510000206006C000000B80206007C0000011416 +:10052000010600BC00000000010600CC0000000035 +:100530000718040000950000081807600014022343 +:10054000071C000034D40000071C800034CF0D3697 +:10055000071D00000A191A6A081D14605D7402253F +:100560000118000000000000011800040000000055 +:1005700001180008000000000118000C0000000035 +:100580000118001000000000011800140000000015 +:1005900002180020000000010218002400000002E0 +:1005A00002180028000000030218002C00000000C0 +:1005B000021800300000000402180034000000019E +:1005C00002180038000000000218003C0000000182 +:1005D000021800400000000402180044000000005F +:1005E00002180048000000010218004C000000033F +:1005F0000218005000000000021800540000000122 +:1006000002180058000000040218005C00000000FE +:1006100002180060000000010218006400000003DE +:1006200002180068000000000218006C00000001C1 +:10063000021800700000000402180074000000009E +:1006400002180078000000040218007C000000037B +:100650000618008000000002021800A400003FFFFE +:10066000021800A8000003FF021802240000000086 +:1006700002180234000000000218024C00000000C2 +:10068000021802E4000000FF061810000000040039 +:10069000021B8BC000000001021B80000000003420 +:1006A000021B804000000018021B80800000000C2C +:1006B000021B80C0000000200C1B83000007A1204B +:1006C0000A1B8300000001380B1B83000000138805 +:1006D000021B83C0000001F4061A2000000000B2D3 +:1006E000061A23C800000181041A29CC0001022740 +:1006F000061A1020000000C8061A100000000002B0 +:10070000061A1E3800000002061A1E300000000201 +:10071000061A080000000002061A0808000000027D +:10072000061A081000000004041A1FB00005022871 +:10073000041A4CB00008022D061A22C8000000203E +:10074000061A400000000124021A4920000000009F +:10075000061A14000000000A061A145000000006D1 +:10076000061A150000000002041A150800050235DB +:10077000061A151C00000009061A15800000001456 +:10078000061A09C000000048061A0800000000020E +:10079000061A08200000000E041A1FB00002023AD8 +:1007A000061A2C2800000002061A23480000002028 +:1007B000061A449000000124021A49240000000097 +:1007C000061A14280000000A061A14680000000621 +:1007D000061A154000000002041A15480005023CE4 +:1007E000061A155C00000009061A15D00000001456 +:1007F000061A0AE000000048061A08080000000275 +:10080000061A08580000000E041A1FB80002024120 +:10081000061A2C30000000020200A2800000000135 +:100820000200A294071D29110200A29800000000F6 +:100830000200A29C009C04240200A2A00000000070 +:100840000200A2A4000002090200A4FCFF000000B4 +:10085000020100B400000001020100B80000000124 +:10086000020100DC000000010201010000000001A3 +:1008700002010104000000010201007C00300000C0 +:1008800002010084000000280201008C000000002A +:1008900002010130000000040201025C00000001BE +:1008A000020103280000000002010554000000308E +:1008B000020100C400000001020100CC00000001A0 +:1008C000020100F800000001020100F00000000138 +:1008D00002010080003000000201008800000028B2 +:1008E0000201009000000000020101340000000439 +:1008F000020102DC000000010201032C00000000E4 +:100900000201056400000030020100C8000000017F +:10091000020100D000000001020100FC0000000103 +:10092000020100F400000001020C10000000002091 +:10093000020C200800000A11020C200C00000A0022 +:10094000020C201000000A04020C201C0000FFFF13 +:10095000020C20200000FFFF020C20240000FFFFFB +:10096000020C20280000FFFF060C203800000002C7 +:10097000020C204000000034020C2044000000352E +:10098000020C204800000020020C204C0000002136 +:10099000020C205000000022020C20540000002312 +:1009A000020C205800000024020C205C00000025EE +:1009B000020C206000000026020C206400000027CA +:1009C000020C206800000028020C206C00000029A6 +:1009D000020C20700000002A020C20740000002B82 +:1009E000060C207800000056020C21D00000000107 +:1009F000020C21D400000001020C21D800000001EB +:100A0000020C21DC00000001020C21E000000001CA +:100A1000020C21E400000001020C21E800000001AA +:100A2000020C21EC00000001020C21F0000000018A +:100A3000020C21F400000001060C21F80000001057 +:100A4000020C223807FFFFFF020C223C0000003F8F +:100A5000020C224007FFFFFF020C22440000000F9F +:100A6000010C224800000000010C224C0000000094 +:100A7000010C225000000000010C22540000000074 +:100A8000010C225800000000010C225C0000000054 +:100A9000010C226000000000010C22640000000034 +:100AA000010C226800000000010C226C0000000014 +:100AB000010C227000000000010C227400000000F4 +:100AC000010C227800000000010C227C00000000D4 +:100AD000020C24BC000000010C0C2000000003E804 +:100AE0000A0C2000000000010B0C20000000000A8E +:100AF000020C400800000365020C400C0000035487 +:100B0000020C401000000358020C40140000037552 +:100B1000020C401C0000FFFF020C40200000FFFF01 +:100B2000020C40240000FFFF020C40280000FFFFE1 +:100B3000020C403800000046020C403C000000055A +:100B4000060C40400000005E020C41B800000001AD +:100B5000060C41BC0000001F020C423807FFFFFFDB +:100B6000020C423C0000003F020C424007FFFFFF26 +:100B7000020C42440000000F010C4248000000003B +:100B8000010C424C00000000010C4250000000002B +:100B9000010C425400000000010C4258000000000B +:100BA000010C425C00000000010C426000000000EB +:100BB000010C426400000000010C426800000000CB +:100BC000010C426C00000000010C427000000000AB +:100BD000010C427400000000010C4278000000008B +:100BE000010C427C00000000010C4280000000006B +:100BF000020C44C0000000010C0C4000000003E89F +:100C00000A0C4000000000010B0C40000000000A2C +:100C1000020D004400000032020D008C021500207D +:100C2000020D009002150020020D00940810000033 +:100C3000020D009800000033020D009C000000022D +:100C4000020D00A000000000020D00A4000000053D +:100C5000020D00A800000005060D00AC0000000217 +:100C6000020D00B400000002020D00B800000003F5 +:100C7000020D00BC00000002020D00C000000001D7 +:100C8000020D00C800000002020D00CC00000002AE +:100C9000020D010800000001020D015C00000001CE +:100CA000020D016400000001020D01680000000255 +:100CB000020D020400000001020D020C00000020E1 +:100CC000020D021000000040020D0214000000405E +:100CD000020D022000000003020D02240000001893 +:100CE000060D028000000012040D030000240243E0 +:100CF000020D004C00000001020D00500000000237 +:100D0000020D005400000008020D00580000000809 +:100D1000060D005C00000004020D00C40000000489 +:100D2000020D011400000009020D01180000002945 +:100D3000020D011C0000000A020D01200000002A23 +:100D4000020D012400000007020D01280000002709 +:100D5000020D012C00000007020D013000000027E9 +:100D6000020D01340000000C020D01380000002CBF +:100D7000020D013C0000000C020D01400000002C9F +:100D8000020D01440000000C020D01480000002C7F +:100D9000020D000400000001020D00080000000127 +:100DA000020D000C00000001020D00100000000107 +:100DB000020D001400000001020D001800000001E7 +:100DC000020D001C00000001020D002000000001C7 +:100DD000020D002400000001020D002800000001A7 +:100DE000020D002C00000001020D00300000000187 +:100DF000020D003400000001020D00380000000167 +:100E0000020D003C00000001020E004C0000003208 +:100E1000020E009402150020020E00980215002018 +:100E2000020E009C00000030020E00A0081000001E +:100E3000020E00A400000033020E00A800000030E3 +:100E4000020E00AC00000031020E00B000000002F3 +:100E5000020E00B400000004020E00B80000000002 +:100E6000020E00BC00000002020E00C000000002E2 +:100E7000020E00C400000000020E00C800000002C4 +:100E8000020E00CC00000007020E00D0000000029D +:100E9000020E00D400000002020E00D80000000183 +:100EA000020E00E400000001020E014400000001F7 +:100EB000020E014C00000001020E01500000000271 +:100EC000020E020400000001020E020C00000040AD +:100ED000020E021000000040020E021C000000047E +:100EE000020E022000000020020E02240000000E6C +:100EF000020E02280000001B060E03000000001274 +:100F0000040E0280001B0267020E00540000000C59 +:100F1000020E005800000009020E005C0000000FE5 +:100F2000020E006000000010060E006400000004C5 +:100F3000020E00DC00000003020E01100000000F92 +:100F4000020E01140000002F020E01180000000E16 +:100F5000020E011C0000002E020E00040000000121 +:100F6000020E000800000001020E000C000000014B +:100F7000020E001000000001020E0014000000012B +:100F8000020E001800000001020E001C000000010B +:100F9000020E002000000001020E002400000001EB +:100FA000020E002800000001020E002C00000001CB +:100FB000020E003000000001020E003400000001AB +:100FC000020E003800000001020E003C000000018B +:100FD000020E004000000001020E0044000000016B +:100FE0000730040000C900000830076800130282BF +:100FF00007340000334B00000734800037090CD35E +:101000000735000030161A96083572F051A2028496 +:10101000013000000000000001300004000000006A +:1010200001300008000000000130000C000000004A +:10103000013000100000000001300014000000002A +:1010400002300020000000010230002400000002F5 +:1010500002300028000000030230002C00000000D5 +:1010600002300030000000040230003400000001B3 +:1010700002300038000000000230003C0000000197 +:101080000230004000000004023000440000000074 +:1010900002300048000000010230004C0000000354 +:1010A0000230005000000000023000540000000137 +:1010B00002300058000000040230005C0000000014 +:1010C00002300060000000010230006400000003F4 +:1010D00002300068000000000230006C00000001D7 +:1010E00002300070000000040230007400000000B4 +:1010F00002300078000000040230007C0000000391 +:101100000630008000000002023000A400003FFF13 +:10111000023000A8000003FF02300224000000009B +:1011200002300234000000000230024C00000000D7 +:10113000023002E40000FFFF06302000000008003B +:1011400002338BC000000001023380000000001A4F +:10115000023380400000004E023380800000001007 +:10116000023380C0000000200C3383000007A12060 +:101170000A338300000001380B338300000013881A +:10118000023383C0000001F40C3383801DCD650061 +:101190000A3383800004C4B40B338380004C4B407B +:1011A00006321AA0000000C206321020000000C85B +:1011B0000632100000000002063214000000004059 +:1011C00006325098000000040632508000000005EE +:1011D00004325094000102860632500000000020C4 +:1011E00004322830000202870233080001000000A8 +:1011F00004330C00001002890233080000000000D4 +:1012000004330C400010029906321500000000B4AF +:1012100002321DC80000000006324000000000D865 +:10122000063217D0000000B402321DCC00000000CE +:1012300006324360000000D807200400009200003E +:1012400008200780001002A9072400002CD100000C +:10125000072480002AE50B350824DC6062DA02AB43 +:101260000120000000000000012000040000000038 +:1012700001200008000000000120000C0000000018 +:1012800001200010000000000120001400000000F8 +:1012900002200020000000010220002400000002C3 +:1012A00002200028000000030220002C00000000A3 +:1012B0000220003000000004022000340000000181 +:1012C00002200038000000000220003C0000000165 +:1012D0000220004000000004022000440000000042 +:1012E00002200048000000010220004C0000000322 +:1012F0000220005000000000022000540000000105 +:1013000002200058000000040220005C00000000E1 +:1013100002200060000000010220006400000003C1 +:1013200002200068000000000220006C00000001A4 +:101330000220007000000004022000740000000081 +:1013400002200078000000040220007C000000035E +:101350000620008000000002022000A400003FFFE1 +:10136000022000A8000003FF022002240000000069 +:1013700002200234000000000220024C00000000A5 +:10138000022002E40000FFFF062020000000080009 +:1013900002238BC000000001022380000000001027 +:1013A00002238040000000120223808000000030F1 +:1013B000022380C00000000E022383C0000001F45D +:1013C000062250000000004206221020000000C843 +:1013D000062210000000000206222000000000C0CB +:1013E000062225C00000024004222EC8000802ADDB +:1013F00002230800013FFFFF04230C00001002B588 +:10140000022308000000000004230C40001002C565 +:1014100006223040000000A00622354000000010E7 +:10142000062236C000000030062240000000020004 +:10143000062235C00000002006223840000000309F +:1014400006223000000000080222511800000000AF +:10145000062223000000000E0622241000000030A7 +:10146000062232C0000000A00622358000000010D5 +:1014700006223780000000300622480000000200EB +:10148000062236400000002006223900000000300D +:1014900006223020000000080222511C000000003B +:1014A000062223380000000E062224D0000000305F +:1014B00002161000000000280217000800000002B9 +:1014C0000217002C000000030217003C000000047B +:1014D0000217004400000008021700480000000244 +:1014E0000217004C0000009002170050000000900E +:1014F00002170054008000900217005808140000E2 +:10150000021700600000008A0217006400000080DB +:1015100002170068000000810217006C00000080C4 +:10152000021700700000000602170078000007D0C4 +:101530000217007C0000076C02170038007C1004C2 +:10154000021700040000000F0616402400000002ED +:10155000021640700000001C021642080000000144 +:101560000216421000000001021642200000000195 +:10157000021642280000000102164230000000015D +:10158000021642380000000102164260000000010D +:101590000C16401C0003D0900A16401C0000009C52 +:1015A0000B16401C000009C4021640300000000861 +:1015B000021640340000000C0216403800000010F3 +:1015C0000216404400000020021640000000000106 +:1015D000021640D800000001021640080000000179 +:1015E0000216400C0000000102164010000000012D +:1015F00002164240000000000216424800000000AF +:101600000616427000000002021642500000000060 +:101610000216425800000000061642800000000238 +:1016200002166008000006140216600C0000060096 +:1016300002166010000006040216601C0000FFFF86 +:10164000021660200000FFFF021660240000FFFF6A +:10165000021660280000FFFF02166038000000201C +:101660000216603C000000200216604000000034BA +:101670000216604400000035021660480000002396 +:101680000216604C00000024021660500000002585 +:101690000216605400000026021660580000002761 +:1016A0000216605C00000029021660600000002A3B +:1016B000021660640000002B021660680000002C17 +:1016C0000216606C0000002D0616607000000052CB +:1016D000021661B800000001061661BC0000001F80 +:1016E0000216623807FFFFFF0216623C0000003F4F +:1016F0000216624007FFFFFF021662440000000F5F +:1017000001166248000000000116624C0000000053 +:101710000116625000000000011662540000000033 +:1017200001166258000000000116625C0000000013 +:1017300001166260000000000116626400000000F3 +:1017400001166268000000000116626C00000000D3 +:1017500001166270000000000116627400000000B3 +:1017600001166278000000000116627C0000000093 +:10177000021664BC000000010C166000000003E8C3 +:101780000A166000000000010B1660000000000A4D +:10179000021680400000000602168044000000058A +:1017A000021680480000000A0216804C0000000566 +:1017B0000216805400000002021680CC00000004D3 +:1017C000021680D000000004021680D4000000043D +:1017D000021680D800000004021680DC000000041D +:1017E000021680E000000004021680E400000004FD +:1017F000021680E8000000040216880400000004BD +:10180000021680300000007C021680340000003D8B +:10181000021680380000003F0216803C0000009C49 +:10182000021680F000000007061680F40000000594 +:101830000216880C01010101021681080000000057 +:101840000216810C00000004021681100000000442 +:1018500002168114000000020216881008012004FC +:1018600002168118000000050216811C0000000508 +:1018700002168120000000050216812400000005E8 +:101880000216882C2008100102168128000000088A +:101890000216812C000000060216813000000007AD +:1018A0000216813400000000021688300101012078 +:1018B0000616813800000004021688340101010177 +:1018C0000616814800000004021688380101010153 +:1018D00006168158000000040216883C010101012F +:1018E00006168168000000030216817400000001E2 +:1018F00002168840010101010216817800000001F2 +:101900000216817C000000010216818000000001A7 +:1019100002168184000000010216884401010101C1 +:1019200002168188000000010216818C000000046C +:10193000021681900000000402168194000000024B +:10194000021688480801200402168198000000054C +:101950000216819C00000005021681A0000000050F +:10196000021681A400000005021688142008100148 +:10197000021681A800000008021681AC00000006D3 +:10198000021681B000000007021681B400000001B9 +:101990000216881801010120021681B8000000011A +:1019A000021681BC00000001021681C00000000187 +:1019B000021681C4000000010216881C0101010109 +:1019C000021681C800000001021681CC000000014F +:1019D000021681D000000001021681D4000000012F +:1019E0000216882001010101021681D800000001C1 +:1019F000021681DC00000001021681E000000001F7 +:101A0000021681E400000001021688240101010190 +:101A1000021681E800000001021681EC00000001BE +:101A2000021681F000000001021688280101010160 +:101A300002168240FFFF003F0616824400000002AB +:101A40000216824CFFFF003F021682500000010088 +:101A5000021682540000010006168258000000029F +:101A600002168260000000C002168264000000C0FE +:101A70000216826800001E000216826C00001E0022 +:101A800002168270000040000216827400004000BE +:101A900002168278000080000216827C000080001E +:101AA00002168280000020000216828400002000BE +:101AB0000616828800000007021682A400000001BA +:101AC000061682A80000000A021681F400000C0825 +:101AD000021681F800000040021681FC000001009F +:101AE0000216820000000020021682040000001787 +:101AF00002168208000000800216820C000002001C +:101B0000021682100000000002168218FFFF01FF7B +:101B100002168214FFFF01FF0216823C0000001330 +:101B2000021680900000013F021680600000014014 +:101B30000216806400000140061680680000000262 +:101B400002168070000000C00616807400000007B6 +:101B50000216809C00000048021680A00000004889 +:101B6000061680A400000002021680AC00000048A7 +:101B7000061680B0000000070216823800008000C0 +:101B800002168234000025E40216809400007FFFD4 +:101B900002168220000000070216821C00000007C7 +:101BA000021682280000000002168224FFFFFFFFB9 +:101BB00002168230000000000216822CFFFFFFFF99 +:101BC000021680EC000000FF02140000000000017B +:101BD0000214000C0000000102140040000000018B +:101BE0000214004400007FFF0214000C00000000FB +:101BF00002140000000000000214006C000000004D +:101C00000214000400000001021400300000000172 +:101C100002140004000000000214005C0000000038 +:101C2000021400080000000102140034000000014A +:101C30000214000800000000021400600000000010 +:101C40000202005800000032020200A0031500202A +:101C5000020200A403150020020200A801000030C7 +:101C6000020200AC08100000020200B000000033C5 +:101C7000020200B400000030020200B8000000318F +:101C8000020200BC00000003020200C000000006C7 +:101C9000020200C400000003020200C800000003AA +:101CA000020200CC00000002020200D0000000008E +:101CB000020200D400000002020200DC000000006A +:101CC000020200E000000006020200E4000000043E +:101CD000020200E800000002020200EC0000000224 +:101CE000020200F000000001020200FC00000006F9 +:101CF0000202012000000000020201340000000284 +:101D0000020201B0000000010202020C000000010A +:101D10000202021400000001020202180000000288 +:101D200002020404000000010202040C0000004052 +:101D300002020410000000400202041C0000000423 +:101D4000020204200000002002020424000000021D +:101D5000020204280000001F060205000000001215 +:101D600004020480001F02D5020200600000000F80 +:101D70000202006400000007020200680000000B7D +:101D80000202006C0000000E060200700000000459 +:101D9000020200F40000000402020004000000013E +:101DA00002020008000000010202000C0000000115 +:101DB00002020010000000010202001400000001F5 +:101DC00002020018000000010202001C00000001D5 +:101DD00002020020000000010202002400000001B5 +:101DE00002020028000000010202002C0000000195 +:101DF0000202003000000001020200340000000175 +:101E000002020038000000010202003C0000000154 +:101E10000202004000000001020200440000000134 +:101E200002020048000000010202004C0000000114 +:101E3000020200500000000102020108000000C878 +:101E40000202011800000002020201C400000000AA +:101E5000020201CC00000000020201D400000002D6 +:101E6000020201DC00000002020201E4000000FFA7 +:101E7000020201EC000000FF0202010C000000C899 +:101E80000202011C00000002020201C80000000062 +:101E9000020201D000000000020201D8000000028E +:101EA000020201E000000002020201E8000000FF5F +:101EB000020201F0000000FF0728040000B5000046 +:101EC00008280768001302F4072C000035D500002D +:101ED000072C80003A3E0D76072D00003B471C067C +:101EE000072D800022BC2AD8082DC770471202F6A1 +:101EF000012800000000000001280004000000008C +:101F000001280008000000000128000C000000006B +:101F1000012800100000000001280014000000004B +:101F20000228002000000001022800240000000216 +:101F300002280028000000030228002C00000000F6 +:101F400002280030000000040228003400000001D4 +:101F500002280038000000000228003C00000001B8 +:101F60000228004000000004022800440000000095 +:101F700002280048000000010228004C0000000375 +:101F80000228005000000000022800540000000158 +:101F900002280058000000040228005C0000000035 +:101FA0000228006000000001022800640000000315 +:101FB00002280068000000000228006C00000001F8 +:101FC00002280070000000040228007400000000D5 +:101FD00002280078000000040228007C00000003B2 +:101FE0000628008000000002022800A400003FFF35 +:101FF000022800A8000003FF0228022400000000BD +:1020000002280234000000000228024C00000000F8 +:10201000022802E40000FFFF06282000000008005C +:10202000022B8BC000000001022B8000000000008A +:10203000022B804000000018022B80800000000C62 +:10204000022B80C0000000660C2B83000007A1203B +:102050000A2B8300000001380B2B8300000013883B +:10206000022B83C0000001F40C2B8340000001F41C +:102070000A2B8340000000000B2B8340000000056A +:102080000A2B83800004C4B40C2B83801DCD650013 +:102090000B2B8380004C4B40062A3C400000000480 +:1020A000042A3C50000202F8062A300000000048D2 +:1020B000062A1020000000C8062A100000000002B6 +:1020C000062A31280000008E022A33680000000032 +:1020D000042A3370000202FA042A3A70000402FC57 +:1020E000042A3D0000020300042A15000002030236 +:1020F000062A150800000100022A197000000000DD +:10210000022A197800000000042A19600002030462 +:10211000062A4AC000000002062A4B000000000404 +:10212000042A1F4800020306022B080000000000DA +:10213000042B0C0000100308022B08000100000013 +:10214000042B0C4000080318022B080002000000BA +:10215000042B0C6000080320062A3A8000000014BB +:10216000062A3B2000000024062A14000000000A72 +:10217000062A145000000006062A3378000000D812 +:10218000022A3A3800000000042A3C5800020328C2 +:10219000042A3C680010032A062A5020000000028E +:1021A000062A503000000002062A500000000002FB +:1021B000062A501000000002022A504000000000D1 +:1021C000062A50480000000E022A50B80000000104 +:1021D000042A4AC80002033A062A4B1000000042B3 +:1021E000062A4D2000000004062A3AD00000001400 +:1021F000062A3BB000000024062A14280000000A2A +:10220000062A146800000006062A36D8000000D806 +:10221000022A3A3C00000000042A3C600002033C11 +:10222000042A3CA80010033E062A502800000002A1 +:10223000062A503800000002062A5008000000025A +:10224000062A501800000002022A50440000000034 +:10225000062A50800000000E022A50BC0000000137 +:10226000042A4AD00002034E062A4C1800000042FD +:10227000062A4D3000000004021010080000000182 +:102280000210101000000264021010000003D000C1 +:10229000021010040000003D091018000200035055 +:1022A00009101100002005500610118000000002E6 +:1022B0000910118800060570061011A00000001812 +:1022C000021010100000000006102400000000E0C2 +:1022D0000210201C0000000002102020000000015D +:1022E000021020C0000000010210200400000001C4 +:1022F000021020080000000109103C0000050576CE +:1023000009103C200005057B0910380000050580F8 +:1023100002104028000000100210404400003FFF5F +:102320000210405800280000021040840084924AA5 +:1023300002104058000000000610806800000004F1 +:1023400002108000000010800610802800000002AB +:102350000210803800000010021080400000FFFFD3 +:10236000021080440000FFFF0210805000000000B7 +:102370000210810000000000061081200000000211 +:1023800002108008000002B502108010000000005A +:10239000061082000000004A021081080001FFFFC1 +:1023A00006108140000000020210800000001A8028 +:1023B0000610900000000024061091200000004A42 +:1023C000061093700000004A061095C00000004AF5 +:1023D000021080040000108006108030000000020F +:1023E0000210803C00000010021080480000FFFF37 +:1023F0000210804C0000FFFF02108054000000001B +:102400000210810400000000061081280000000274 +:102410000210800C000002B50210801400000000C1 +:10242000061084000000004A0210810C0001FFFF2A +:1024300006108148000000020210800400001A808B +:102440000610909000000024061092480000004AF8 +:10245000061094980000004A061096E80000004A12 +:102460000212049000E383400212051400003C10A5 +:10247000021205200000000202120494FFFFFFFF79 +:1024800002120498FFFFFFFF0212049CFFFFFFFFF0 +:10249000021204A0FFFFFFFF021204A4FFFFFFFFD0 +:1024A000021204A8FFFFFFFF021204ACFFFFFFFFB0 +:1024B000021204B0FFFFFFFF021204B8FFFFFFFF8C +:1024C000021204BCFFFFFFFF021204C0FFFFFFFF68 +:1024D000021204C4FFFFFFFF021204C8FFFFFFFF48 +:1024E000021204CCFFFFFFFF021204D0FFFFFFFF28 +:1024F000021204DCFFFFFFFF021204E0FFFFFFFFF8 +:10250000021204E4FFFFFFFF021204E8FFFFFFFFD7 +:10251000021204ECFFFFFFFF021204F0FFFFFFFFB7 +:10252000021204F4FFFFFFFF021204F8FFFFFFFF97 +:10253000021204FCFFFFFFFF02120500FFFFFFFF76 +:1025400002120504FFFFFFFF02120508FFFFFFFF55 +:102550000212050CFFFFFFFF02120510FFFFFFFF35 +:10256000021204D4FFFF3330021204D8FFFF3340BD +:10257000021204B4F00030000212039000000008C0 +:102580000212039C00000008061203A000000002D3 +:10259000021203BC00000004021203C40000000485 +:1025A000021203D000000000021203DC0000000051 +:1025B0000212036C00000001021203680000003FD9 +:1025C000021201BC00000040021201C00000180805 +:1025D000021201C400000803021201C8000008032F +:1025E000021201CC00000040021201D000000003E2 +:1025F000021201D400000803021201D800000803EF +:10260000021201DC00000803021201E000010003D5 +:10261000021201E400000803021201E800000803AE +:10262000021201EC00000003021201F0000000039E +:10263000021201F400000003021201F8000000037E +:10264000021201FC0000000302120200000000035D +:10265000021202040000000302120208000000033C +:102660000212020C0000000302120210000000031C +:1026700002120214000000030212021800000003FC +:102680000212021C000000030212022000000003DC +:102690000212022400000003021202280000240398 +:1026A0000212022C0000002F02120230000000096A +:1026B00002120234000000190212023800000184E4 +:1026C0000212023C000001830212024000000306D5 +:1026D0000212024400000019021202480000000623 +:1026E0000212024C00000306021202500000030610 +:1026F00002120254000003060212025800000C8667 +:102700000212025C000003060212026000000306CF +:1027100002120264000000060212026800000006B5 +:102720000212026C00000006021202700000000695 +:102730000212027400000006021202780000000675 +:102740000212027C00000006021202800000000655 +:102750000212028400000006021202880000000635 +:102760000212028C00000006021202900000000615 +:1027700002120294000000060212029800000006F5 +:102780000212029C00000006021202A000000306D2 +:10279000021202A400000013021202A800000006A8 +:1027A000021202B000001004021202B40000100471 +:1027B0000212032400106440021203280010644037 +:1027C000021201B0000000010600A0000000001687 +:1027D0000200A06CBF5C00000200A070FFF51FEFBC +:1027E0000200A0740000FFFF0200A078500003E088 +:1027F0000200A07C000000000200A0800000A000F9 +:102800000600A084000000050200A0980FE0000070 +:102810000600A09C000000140200A0EC555400002B +:102820000200A0F0555555550200A0F40000555582 +:102830000200A0F8000000000200A0FC55540000B7 +:102840000200A100555555550200A1040000555540 +:102850000200A108000000000200A22C00000000FD +:102860000600A230000000030200A0600000000784 +:102870000200A10CBF5C00000200A110FFF51FEFD9 +:102880000200A1140000FFFF0200A118500003E0A5 +:102890000200A11C000000000200A1200000A00016 +:1028A0000600A124000000050200A1380FE000008E +:1028B0000600A13C000000140200A18C5554000049 +:1028C0000200A190555555550200A19400005555A0 +:1028D0000200A198000000000200A19C55540000D5 +:1028E0000200A1A0555555550200A1A40000555560 +:1028F0000200A1A8000000000200A23C00000000AD +:102900000600A240000000030200A06400000007CF +:1029100000000000000000000000002E0000000089 +:1029200000000000000000000000000000000000A7 +:102930000000000000000000000000000000000097 +:102940000000000000000000000000000000000087 +:102950000000000000000000000000000000000077 +:102960000000000000000000000000000000000067 +:10297000002E0050000000000000000000000000D9 +:102980000000000000000000000000000000000047 +:102990000000000000000000000000000050008D5A +:1029A0000000000000000000000000000000000027 +:1029B0000000000000000000000000000000000017 +:1029C0000000000000000000008D009200920096C0 +:1029D0000096009A000000000000000000000000C7 +:1029E00000000000000000000000000000000000E7 +:1029F00000000000009A00DB00DB00E900E900F7BE +:102A000000000000000000000000000000000000C6 +:102A100000000000000000000000000000000000B6 +:102A200000000000000000000000000000000000A6 +:102A30000000000000000000000000000000000096 +:102A40000000000000000000000000000000000086 +:102A50000000000000000000000000000000000076 +:102A60000000000000000000000000000000000066 +:102A70000000000000000000000000000000000056 +:102A80000000000000000000000000000000000046 +:102A90000000000000000000000000000000000036 +:102AA0000000000000000000000000000000000026 +:102AB0000000000000000000000000000000000016 +:102AC0000000000000000000000000000000000006 +:102AD00000F700FE00000000000000000000000001 +:102AE00000000000000000000000000000000000E6 +:102AF00000000000000000000000000000000000D6 +:102B000000000000000000000000000000000000C5 +:102B100000000000000000000000000000000000B5 +:102B2000000000000000000000FE01030103010E90 +:102B3000010E01190000000000000000000000006C +:102B40000000000000000000000000000000000085 +:102B50000000000000000000000000000000000075 +:102B60000000000000000000000000000000000065 +:102B70000000000000000000000000000000000055 +:102B80000119011A00000000000000000000000010 +:102B90000000000000000000000000000000000035 +:102BA000000000000000000000000000011A0152B7 +:102BB0000000000000000000000000000000000015 +:102BC0000000000000000000000000000000000005 +:102BD000000000000000000001520176000000002B +:102BE00000000000000000000000000000000000E5 +:102BF00000000000000000000000000000000000D5 +:102C000000000000017601B5000000000000000097 +:102C100000000000000000000000000000000000B4 +:102C200000000000000000000000000000000000A4 +:102C300001B501F0000000000000000000000000ED +:102C40000000000000000000000000000000000084 +:102C500000000000000000000000000001F002354C +:102C6000023502380238023B00000000000000007C +:102C70000000000000000000000000000000000054 +:102C80000000000000000000023B02760276028095 +:102C90000280028A00000000000000000000000026 +:102CA0000000000000000000000000000000000024 +:102CB00000000000028A028B0000000000000000FB +:102CC0000000000000000000000000000000000004 +:102CD00000000000000000000000000000000000F4 +:102CE000028B029D000000000000000000000000B8 +:102CF00000000000000000000000000000000000D4 +:102D0000000000000000000000000000029D02B270 +:102D100002B202B502B502B80000000000000000D7 +:102D200000000000000000000000000000000000A3 +:102D3000000000000000000002B802E600000000F1 +:102D40000000000000000000000000000000000083 +:102D50000000000000000000000000000000000073 +:102D60000000000002E6036D00000000000000000B +:102D70000000000000000000000000000000000053 +:102D80000000000000000000000000000000000043 +:102D9000036D0374037403780378037C0000000060 +:102DA0000000000000000000000000000000000023 +:102DB000000000000000000000000000037C03BBD6 +:102DC00003BB03C303C303CB0000000000000000EB +:102DD00000000000000000000000000000000000F3 +:102DE000000000000000000003CB041F041F04319A +:102DF0000431044300000000000000000000000057 +:102E000000000000000000000000000000000000C2 +:102E1000000000000443044D00000000000000001A +:102E200000000000000000000000000000000000A2 +:102E30000000000000000000000000000000000092 +:102E4000044D0453000000000000000000000000DA +:102E50000000000000000000000000000000000072 +:102E600000000000000000000000000004530456B1 +:102E70000000000000000000000000000000000052 +:102E80000000000000000000000000000000000042 +:102E900000000000000000000456045B0000000079 +:102EA0000000000000000000000000000000000022 +:102EB0000000000000000000000000000000000012 +:102EC00000000000045B045C045C046E046E04807B +:102ED00000000000000000000000000000000000F2 +:102EE00000000000000000000000000000000000E2 +:102EF000048004ED0000000000000000000000005D +:102F000000000000000000000000000000000000C1 +:102F100000000000000000000000000004ED04EECE +:102F200004EE050205020516000000000000000086 +:102F30000000000000000000000000000000000091 +:102F40000000000000000000000000000000000081 +:102F50000000000000000000000000000000000071 +:102F60000000000000000000000000000000000061 +:102F70000000000000000000000000000000000051 +:102F80000000000000000000000000000000000041 +:102F90000000000000000000000000000000000031 +:102FA000000000000000000000010000000204C05A +:102FB0000003098000040E4000051300000617C03E +:102FC00000071C800008214000092600000A2AC0D2 +:102FD000000B2F80000C3440000D3900000E3DC066 +:102FE000000F42800010474000114C00001250C0FA +:102FF0000013558000145A4000155F00001663C08E +:103000000017688000186D4000197200001A76C021 +:10301000001B7B80001C8040001D8500001E89C0B5 +:10302000001F8E8000209340000020000000400020 +:1030300000006000000080000000A0000000C00050 +:103040000000E0000001000000012000000140003D +:1030500000016000000180000001A0000001C0002C +:103060000001E00000020000000220000002400019 +:1030700000026000000280000002A0000002C00008 +:103080000002E000000300000003200000034000F5 +:1030900000036000000380000003A0000003C000E4 +:1030A0000003E000000400000004200000044000D1 +:1030B00000046000000480000004A0000004C000C0 +:1030C0000004E000000500000005200000054000AD +:1030D00000056000000580000005A0000005C0009C +:1030E0000005E00000060000000620000006400089 +:1030F00000066000000680000006A0000006C00078 +:103100000006E00000070000000720000007400064 +:1031100000076000000780000007A0000007C00053 +:103120000007E00000080000000820000008400040 +:1031300000086000000880000008A0000008C0002F +:103140000008E0000009000000092000000940001C +:1031500000096000000980000009A0000009C0000B +:103160000009E000000A0000000A2000000A4000F8 +:10317000000A6000000A8000000AA000000AC000E7 +:10318000000AE000000B0000000B2000000B4000D4 +:10319000000B6000000B8000000BA000000BC000C3 +:1031A000000BE000000C0000000C2000000C4000B0 +:1031B000000C6000000C8000000CA000000CC0009F +:1031C000000CE000000D0000000D2000000D40008C +:1031D000000D6000000D8000000DA000000DC0007B +:1031E000000DE000000E0000000E2000000E400068 +:1031F000000E6000000E8000000EA000000EC00057 +:10320000000EE000000F0000000F2000000F400043 +:10321000000F6000000F8000000FA000000FC00032 +:10322000000FE0000010000000102000001040001F +:1032300000106000001080000010A0000010C0000E +:103240000010E000001100000011200000114000FB +:1032500000116000001180000011A0000011C000EA +:103260000011E000001200000012200000124000D7 +:1032700000126000001280000012A0000012C000C6 +:103280000012E000001300000013200000134000B3 +:1032900000136000001380000013A0000013C000A2 +:1032A0000013E0000014000000142000001440008F +:1032B00000146000001480000014A0000014C0007E +:1032C0000014E0000015000000152000001540006B +:1032D00000156000001580000015A0000015C0005A +:1032E0000015E00000160000001620000016400047 +:1032F00000166000001680000016A0000016C00036 +:103300000016E00000170000001720000017400022 +:1033100000176000001780000017A0000017C00011 +:103320000017E000001800000018200000184000FE +:1033300000186000001880000018A0000018C000ED +:103340000018E000001900000019200000194000DA +:1033500000196000001980000019A0000019C000C9 +:103360000019E000001A0000001A2000001A4000B6 +:10337000001A6000001A8000001AA000001AC000A5 +:10338000001AE000001B0000001B2000001B400092 +:10339000001B6000001B8000001BA000001BC00081 +:1033A000001BE000001C0000001C2000001C40006E +:1033B000001C6000001C8000001CA000001CC0005D +:1033C000001CE000001D0000001D2000001D40004A +:1033D000001D6000001D8000001DA000001DC00039 +:1033E000001DE000001E0000001E2000001E400026 +:1033F000001E6000001E8000001EA000001EC00015 +:10340000001EE000001F0000001F2000001F400001 +:10341000001F6000001F8000001FA000001FC000F0 +:10342000001FE000002000000020200000204000DD +:1034300000206000002080000020A0000020C000CC +:103440000020E000002100000021200000214000B9 +:1034500000216000002180000021A0000021C000A8 +:103460000021E00000220000002220000022400095 +:1034700000226000002280000022A0000022C00084 +:103480000022E00000230000002320000023400071 +:1034900000236000002380000023A0000023C00060 +:1034A0000023E0000024000000242000002440004D +:1034B00000246000002480000024A0000024C0003C +:1034C0000024E00000250000002520000025400029 +:1034D00000256000002580000025A0000025C00018 +:1034E0000025E00000260000002620000026400005 +:1034F00000266000002680000026A0000026C000F4 +:103500000026E000002700000027200000274000E0 +:1035100000276000002780000027A0000027C000CF +:103520000027E000002800000028200000284000BC +:1035300000286000002880000028A0000028C000AB +:103540000028E00000290000002920000029400098 +:1035500000296000002980000029A0000029C00087 +:103560000029E000002A0000002A2000002A400074 +:10357000002A6000002A8000002AA000002AC00063 +:10358000002AE000002B0000002B2000002B400050 +:10359000002B6000002B8000002BA000002BC0003F +:1035A000002BE000002C0000002C2000002C40002C +:1035B000002C6000002C8000002CA000002CC0001B +:1035C000002CE000002D0000002D2000002D400008 +:1035D000002D6000002D8000002DA000002DC000F7 +:1035E000002DE000002E0000002E2000002E4000E4 +:1035F000002E6000002E8000002EA000002EC000D3 +:10360000002EE000002F0000002F2000002F4000BF +:10361000002F6000002F8000002FA000002FC000AE +:10362000002FE0000030000000302000003040009B +:1036300000306000003080000030A0000030C0008A +:103640000030E00000310000003120000031400077 +:1036500000316000003180000031A0000031C00066 +:103660000031E00000320000003220000032400053 +:1036700000326000003280000032A0000032C00042 +:103680000032E0000033000000332000003340002F +:1036900000336000003380000033A0000033C0001E +:1036A0000033E0000034000000342000003440000B +:1036B00000346000003480000034A0000034C000FA +:1036C0000034E000003500000035200000354000E7 +:1036D00000356000003580000035A0000035C000D6 +:1036E0000035E000003600000036200000364000C3 +:1036F00000366000003680000036A0000036C000B2 +:103700000036E0000037000000372000003740009E +:1037100000376000003780000037A0000037C0008D +:103720000037E0000038000000382000003840007A +:1037300000386000003880000038A0000038C00069 +:103740000038E00000390000003920000039400056 +:1037500000396000003980000039A0000039C00045 +:103760000039E000003A0000003A2000003A400032 +:10377000003A6000003A8000003AA000003AC00021 +:10378000003AE000003B0000003B2000003B40000E +:10379000003B6000003B8000003BA000003BC000FD +:1037A000003BE000003C0000003C2000003C4000EA +:1037B000003C6000003C8000003CA000003CC000D9 +:1037C000003CE000003D0000003D2000003D4000C6 +:1037D000003D6000003D8000003DA000003DC000B5 +:1037E000003DE000003E0000003E2000003E4000A2 +:1037F000003E6000003E8000003EA000003EC00091 +:10380000003EE000003F0000003F2000003F40007D +:10381000003F6000003F8000003FA000003FC0006C +:10382000003FE000003FE00100000000000001FF59 +:103830000000020000007FF800007FF80000026F27 +:1038400000001500000000010000000300BEBC20C5 +:103850000000000300BEBC2000000001FFFFFFFFCE +:10386000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 +:10387000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 +:1038800000000000FFFFFFFF00000000FFFFFFFF40 +:103890000000000300BEBC20FFFFFFFF000000008F +:1038A000FFFFFFFF00000000FFFFFFFF000000031D +:1038B00000BEBC2000002000000040C0000061806D +:1038C000000082400000A3000000C3C00000E480AC +:1038D0000001054000012600000146C0000167808C +:1038E000000188400001A9000001C9C00001EA8070 +:1038F00000020B4000022C0000024CC000026D8050 +:1039000000028E400002AF000002CFC00002F08033 +:103910000003114000033200000352C00003738013 +:10392000000394400003B5000003D5C00003F680F7 +:103930000004174000043800000458C000047980D7 +:1039400000049A400000800000010380000187000D +:1039500000020A8000028E0000031180000395001F +:103960000004188000049C0000051F800005A300CF +:10397000000626800006AA0000072D800007B1007F +:10398000000834800008B80000093B800009BF002F +:10399000000A4280000AC600000B4980000BCD00DF +:1039A000000C5080000CD400000D5780000DDB008F +:1039B00000007FF800007FF800000174000015008F +:1039C0000000190000000000FFFFFFFF40000000A2 +:1039D00040000000400000004000000040000000E7 +:1039E00040000000400000004000000040000000D7 +:1039F00040000000400000004000000040000000C7 +:103A000040000000400000004000000040000000B6 +:103A100040000000400000004000000040000000A6 +:103A20004000000040000000400000004000000096 +:103A30004000000040000000400000004000000086 +:103A400040000000400000004000000000007FF83F +:103A500000007FF80000050900003500FFFFFFFFB0 +:103A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66 +:103A7000FFFFFFFFFFFFFFFFFFFFFFFF4000000012 +:103A80004000000040000000400000004000000036 +:103A90004000000040000000400000004000000026 +:103AA0004000000040000000400000004000000016 +:103AB0004000000040000000400000004000000006 +:103AC00040000000400000004000000040000000F6 +:103AD00040000000400000004000000040000000E6 +:103AE00040000000400000004000000040000000D6 +:103AF00040000000400000004000000000001000F6 +:103B000000002080000031000000418000005200D1 +:103B100000006280000073000000838000009400B9 +:103B20000000A4800000B5000000C5800000D600A1 +:103B30000000E6800000F700000107800001180087 +:103B400000012880000139000001498000015A006D +:103B500000016A8000017B0000018B8000019C0055 +:103B60000001AC800001BD000001CD800001DE003D +:103B70000001EE800001FF0000007FF800007FF8E8 +:103B8000000004480000150010000000000028ADEF +:103B90000000000000010001000D0205CCCCCCC1EA +:103BA000FFFFFFFFFFFFFFFF7058103C0000000009 +:103BB0000000000000000001CCCC0201CCCCCCCC39 +:103BC00000000000FFFFFFFF400000004000000079 +:103BD00040000000400000004000000040000000E5 +:103BE00040000000400000004000000040000000D5 +:103BF00040000000400000004000000040000000C5 +:103C000040000000400000004000000040000000B4 +:103C100040000000400000004000000040000000A4 +:103C20004000000040000000400000004000000094 +:103C30004000000040000000400000004000000084 +:103C40004000000040000000000E01B7011600D641 +:103C50000000FFFF000000000000FFFF0000000068 +:103C60000000FFFF000000000000FFFF0000000058 +:103C70000000FFFF000000000000FFFF0000000048 +:103C80000000FFFF000000000000FFFF0000000038 +:103C90000010000000000000007201BB012300F3CF +:103CA0000000FFFF000000000000FFFF0000000018 +:103CB0000000FFFF000000000000FFFF0000000008 +:103CC0000000FFFF000000000000FFFF00000000F8 +:103CD0000000FFFF000000000000FFFF00000000E8 +:103CE0000010000000000000FFFFFFF3318FFFFF16 +:103CF0000C30C30CC30C30C3CF3CF300F3CF3CF308 +:103D00000000CF3CCDCDCDCDFFFFFFF130EFFFFF69 +:103D10000C30C30CC30C30C3CF3CF300F3CF3CF3E7 +:103D20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD3 +:103D30000C30C30CC30C30C3CF3CF300F3CF3CF3C7 +:103D40000002CF3CCDCDCDCDFFFFF4061CBFFFFF61 +:103D50000C30C305C30C30C3CF300014F3CF3CF399 +:103D60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA4 +:103D70000C30C30CC30C30C3CF3CF300F3CF3CF387 +:103D80000008CF3CCDCDCDCDFFFFFFFA302FFFFF98 +:103D90000C30C30CC30C30C3CF3CF300F3CF3CF367 +:103DA0000010CF3CCDCDCDCDFFFFFFF731EFFFFFB2 +:103DB0000C30C30CC30C30C3CF3CF300F3CF3CF347 +:103DC0000020CF3CCDCDCDCDFFFFFFF5302FFFFF45 +:103DD0000C30C30CC30C30C3CF3CF300F3CF3CF327 +:103DE0000040CF3CCDCDCDCDFFFFFFF3318FFFFFA6 +:103DF0000C30C30CC30C30C3CF3CF300F3CF3CF307 +:103E00000000CF3CCDCDCDCDFFFFFFF1310FFFFF47 +:103E10000C30C30CC30C30C3CF3CF300F3CF3CF3E6 +:103E20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD2 +:103E30000C30C30CC30C30C3CF3CF300F3CF3CF3C6 +:103E40000002CF3CCDCDCDCDFFFFF4061CBFFFFF60 +:103E50000C30C305C30C30C3CF300014F3CF3CF398 +:103E60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA3 +:103E70000C30C30CC30C30C3CF3CF300F3CF3CF386 +:103E80000008CF3CCDCDCDCDFFFFFFFA302FFFFF97 +:103E90000C30C30CC30C30C3CF3CF300F3CF3CF366 +:103EA0000010CF3CCDCDCDCDFFFFFFF730EFFFFFB2 +:103EB0000C30C30CC30C30C3CF3CF300F3CF3CF346 +:103EC0000020CF3CCDCDCDCDFFFFFFF5304FFFFF24 +:103ED0000C30C30CC30C30C3CF3CF300F3CF3CF326 +:103EE0000040CF3CCDCDCDCDFFFFFFF331EFFFFF45 +:103EF0000C30C30CC30C30C3CF3CF300F3CF3CF306 +:103F00000000CF3CCDCDCDCDFFFFFFF1310FFFFF46 +:103F10000C30C30CC30C30C3CF3CF300F3CF3CF3E5 +:103F20000001CF3CCDCDCDCDFFFFFFF6305FFFFFD1 +:103F30000C30C30CC30C30C3CF3CF300F3CF3CF3C5 +:103F40000002CF3CCDCDCDCDFFFFF4061CBFFFFF5F +:103F50000C30C305C30C30C3CF300014F3CF3CF397 +:103F60000004CF3CCDCDCDCDFFFFFFF2304FFFFFA2 +:103F70000C30C30CC30C30C3CF3CF300F3CF3CF385 +:103F80000008CF3CCDCDCDCDFFFFFFFA302FFFFF96 +:103F90000C30C30CC30C30C3CF3CF300F3CF3CF365 +:103FA0000010CF3CCDCDCDCDFFFFFF97056FFFFFBC +:103FB0000C30C30CC30C30C3CF3CC000F3CF3CF378 +:103FC0000020CF3CCDCDCDCDFFFFFFF5310FFFFF62 +:103FD0000C30C30CC30C30C3CF3CF300F3CF3CF325 +:103FE0000040CF3CCDCDCDCDFFFFFFF3320FFFFF23 +:103FF0000C30C30CC30C30C3CF3CF300F3CF3CF305 +:104000000000CF3CCDCDCDCDFFFFFFF1310FFFFF45 +:104010000C30C30CC30C30C3CF3CF300F3CF3CF3E4 +:104020000001CF3CCDCDCDCDFFFFFFF6305FFFFFD0 +:104030000C30C30CC30C30C3CF3CF300F3CF3CF3C4 +:104040000002CF3CCDCDCDCDFFFFF4061CBFFFFF5E +:104050000C30C305C30C30C3CF300014F3CF3CF396 +:104060000004CF3CCDCDCDCDFFFFFFF2304FFFFFA1 +:104070000C30C30CC30C30C3CF3CF300F3CF3CF384 +:104080000008CF3CCDCDCDCDFFFFFF8A042FFFFF31 +:104090000C30C30CC30C30C3CF3CC000F3CF3CF397 +:1040A0000010CF3CCDCDCDCDFFFFFF9705CFFFFF5B +:1040B0000C30C30CC30C30C3CF3CC000F3CF3CF377 +:1040C0000020CF3CCDCDCDCDFFFFFFF5310FFFFF61 +:1040D0000C30C30CC30C30C3CF3CF300F3CF3CF324 +:1040E0000040CF3CCDCDCDCDFFFFFFF3300FFFFF24 +:1040F0000C30C30CC30C30C3CF3CF300F3CF3CF304 +:104100000000CF3CCDCDCDCDFFFFFFF1300FFFFF45 +:104110000C30C30CC30C30C3CF3CF300F3CF3CF3E3 +:104120000001CF3CCDCDCDCDFFFFFFF6305FFFFFCF +:104130000C30C30CC30C30C3CF3CF300F3CF3CF3C3 +:104140000002CF3CCDCDCDCDFFFFF4061CBFFFFF5D +:104150000C30C305C30C30C3CF300014F3CF3CF395 +:104160000004CF3CCDCDCDCDFFFFFFF2304FFFFFA0 +:104170000C30C30CC30C30C3CF3CF300F3CF3CF383 +:104180000008CF3CCDCDCDCDFFFFFFFA302FFFFF94 +:104190000C30C30CC30C30C3CF3CF300F3CF3CF363 +:1041A0000010CF3CCDCDCDCDFFFFFF97040FFFFF1B +:1041B0000C30C30CC30C30C3CF3CC000F3CF3CF376 +:1041C0000020CF3CCDCDCDCDFFFFFFF5300FFFFF61 +:1041D0000C30C30CC30C30C3CF3CF300F3CF3CF323 +:1041E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF57 +:1041F0000C30C30CC30C30C3CF3CF3CCF3CF3CF337 +:104200000000CF3CCDCDCDCDFFFFFFFF30CFFFFF76 +:104210000C30C30CC30C30C3CF3CF3CCF3CF3CF316 +:104220000001CF3CCDCDCDCDFFFFFFFF30CFFFFF55 +:104230000C30C30CC30C30C3CF3CF3CCF3CF3CF3F6 +:104240000002CF3CCDCDCDCDFFFFFFFF30CFFFFF34 +:104250000C30C30CC30C30C3CF3CF3CCF3CF3CF3D6 +:104260000004CF3CCDCDCDCDFFFFFFFF30CFFFFF12 +:104270000C30C30CC30C30C3CF3CF3CCF3CF3CF3B6 +:104280000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEE +:104290000C30C30CC30C30C3CF3CF3CCF3CF3CF396 +:1042A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC6 +:1042B0000C30C30CC30C30C3CF3CF3CCF3CF3CF376 +:1042C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF96 +:1042D0000C30C30CC30C30C3CF3CF3CCF3CF3CF356 +:1042E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF56 +:1042F0000C30C30CC30C30C3CF3CF3CCF3CF3CF336 +:104300000000CF3CCDCDCDCDFFFFFFFF30CFFFFF75 +:104310000C30C30CC30C30C3CF3CF3CCF3CF3CF315 +:104320000001CF3CCDCDCDCDFFFFFFFF30CFFFFF54 +:104330000C30C30CC30C30C3CF3CF3CCF3CF3CF3F5 +:104340000002CF3CCDCDCDCDFFFFFFFF30CFFFFF33 +:104350000C30C30CC30C30C3CF3CF3CCF3CF3CF3D5 +:104360000004CF3CCDCDCDCDFFFFFFFF30CFFFFF11 +:104370000C30C30CC30C30C3CF3CF3CCF3CF3CF3B5 +:104380000008CF3CCDCDCDCDFFFFFFFF30CFFFFFED +:104390000C30C30CC30C30C3CF3CF3CCF3CF3CF395 +:1043A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC5 +:1043B0000C30C30CC30C30C3CF3CF3CCF3CF3CF375 +:1043C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF95 +:1043D0000C30C30CC30C30C3CF3CF3CCF3CF3CF355 +:1043E0000040CF3CCDCDCDCDFFFFFFFF30CFFFFF55 +:1043F0000C30C30CC30C30C3CF3CF3CCF3CF3CF335 +:104400000000CF3CCDCDCDCDFFFFFFFF30CFFFFF74 +:104410000C30C30CC30C30C3CF3CF3CCF3CF3CF314 +:104420000001CF3CCDCDCDCDFFFFFFFF30CFFFFF53 +:104430000C30C30CC30C30C3CF3CF3CCF3CF3CF3F4 +:104440000002CF3CCDCDCDCDFFFFFFFF30CFFFFF32 +:104450000C30C30CC30C30C3CF3CF3CCF3CF3CF3D4 +:104460000004CF3CCDCDCDCDFFFFFFFF30CFFFFF10 +:104470000C30C30CC30C30C3CF3CF3CCF3CF3CF3B4 +:104480000008CF3CCDCDCDCDFFFFFFFF30CFFFFFEC +:104490000C30C30CC30C30C3CF3CF3CCF3CF3CF394 +:1044A0000010CF3CCDCDCDCDFFFFFFFF30CFFFFFC4 +:1044B0000C30C30CC30C30C3CF3CF3CCF3CF3CF374 +:1044C0000020CF3CCDCDCDCDFFFFFFFF30CFFFFF94 +:1044D0000C30C30CC30C30C3CF3CF3CCF3CF3CF354 +:1044E0000040CF3CCDCDCDCD000C0000000700C07A +:1044F00000028130000B81580002021000010230DE +:10450000000F024000010330000C0000000800C052 +:1045100000028140000B816800020220000102407D +:1045200000070250000202C0000F0000000800F067 +:1045300000028170000B819800020250000102709D +:10454000000B828000080338001000000008010002 +:1045500000028180000B81A80002026000018280BD +:10456000000E82980008038000028000000B802863 +:10457000000200E0000101000000811000000118AD +:10458000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC6B +:1045900000002000CCCCCCCCCCCCCCCCCCCCCCCC6B +:1045A000CCCCCCCC00002000CCCCCCCCCCCCCCCC5B +:1045B000CCCCCCCCCCCCCCCC00002000000000007B +:1045C0001F8B080000000000000BFB51CFC0F00360 +:1045D0008A7BD81818F67020F843015F646260B8CF +:1045E0000CC45781588099812198918121849178B8 +:1045F000FD71A208F61321A019C240330419184E08 +:104600000B23C40F02D5988830307C878A5503D994 +:104610000CA2D471FF40E375529862AB2510ECF503 +:1046200058E491F10634792E4954FE4602FA071AED +:10463000DF5744E50B2940E86CA8F803347961A8FA +:10464000FC79A8BF1E2A6237F702541E005BBBD25A +:1046500053600300000000000000000000000000A4 +:104660001F8B080000000000000BED7D0B7854D577 +:10467000B5F03E73CE9C9949662627214F1E6112E4 +:1046800020028638BC0228B74E480850691D6C5578 +:10469000B468070810F296A297D6F6CB04428C8035 +:1046A00036F8FB408B3ABC2A2A6AC048510187A7DA +:1046B000E8F5F606AB9656EB8D68519147E456A5A2 +:1046C000FF6DAFFF5A6BEF9D39673201ECD77BFF6F +:1046D000FBDFEF8F9FDF619FBDCFDE6BAFD75E6BE0 +:1046E000EDB5F7D86D1EA65FCDD8D7F807CF7A1BEA +:1046F000632C23F67CC4CE7E18743356B0CEB7C27A +:104700009D0EEF77E56D4FF63196B37BAD3205DE4A +:10471000E7AC6F53E615C6BE0FB8A0723CBCDFB560 +:10472000562981F7396FB42973F1E9B0B14E68CFDA +:10473000345F0AC3270B3096C9D890894CFC05DC3E +:1047400039C58C0DC47F4217E78C64C6C63196B755 +:10475000D216092BF03E5439937919DB0470E5A485 +:10476000C177EA5FF6D9B16D8376BCCBC998537334 +:104770006A5FE733963B9BD9183C072FE3EFF1EFD5 +:104780006BF83F2F6C2D0F61A6721E963DE92760D6 +:1047900048E6619EAFD544F076EBC151B179CAE7E6 +:1047A000FA465FA65BEBFD5E3E97DCF6897E177CE2 +:1047B000FD18B61BCA5824AE7D6D58D7D815F00425 +:1047C00004B417F6FE7E262B29463ADCCAA6D0B3DF +:1047D0005EF3DD8878A93F62676180BBBEE1443942 +:1047E00096D92E850DCBEBFDFD2866277A943045B2 +:1047F0003B81F3F5322FCE4FADF13D540E786E482C +:104800000E9461BF0F2787E829DF67CF9B9E1D02AB +:10481000784A17158619D0FDDC3AC5EF80CF3F5690 +:1048200022BA1DE851FDFD86A269D0EE6D3D740DE2 +:104830007EB7488DB6D861FCDA390D054001D6A99E +:1048400073FE19BCABE4530DE83698B1704A1AD226 +:1048500085B1E3263AE0DFF1E1A2ACF68DC78B3DEE +:104860002BB01F0D7B89D07CE5FBBCF0912143E38D +:10487000C663C5040F433819EB5212D175F08B256E +:1048800047B4A2BEC7FBCF9F4798CB21E00EE95BA0 +:10489000EBD123CB01BFA52FD8A357033D6A3728FF +:1048A0001107946D7B5D01A4CF99CD5006BA443DAC +:1048B0003AB53F6D38A95CEFE8BCF72A2877BFA06E +:1048C000B28DD8EDF0241BCADD09013B1B0765C082 +:1048D000C742172FD66ED8772BF657B9CBC15C4895 +:1048E000CF17177DF72A282F027EC326B55B9AF4CF +:1048F000FE505E1C51DAB17C760A23FE08A7E991CE +:104900002D30DE596F67E6F5202F271B9DCC07A0C1 +:10491000ACF074667E1FF8A82AB2BD1CBFABDAA645 +:10492000F811EDA52F6C399C83F37A12F80AF8A8D8 +:104930007A6B32F349FCC1FF27602A5743FD129876 +:1049400027CAFF22D656CE541C7FADEEF3C4F075B5 +:10495000B2D1A0717AE4E9491807BEAB7B56F1E306 +:1049600014EB6C2C847275E645D7EC4D6E9C5F930E +:104970005EE0C179DDA563BB4591B93B5165554505 +:1049800036E8E5505FB57E83BEB010F1067AAF1011 +:10499000E1EA67856B9D1A40FC2E49756E54013F14 +:1049A000CC1DC8BE2E01FF9C6C043556102B57A1A0 +:1049B0007C933E89E8B34CEDCB9554E2D7EAAD2A1F +:1049C000F359F889D33F7C94D33FBCC713D99217CE +:1049D000A3DF1283EB4949BF25A9829E5A77712232 +:1049E00078EE457A003C6D882F78AE11F07927B3C8 +:1049F000120DE8E20D30436117E7CF363B9BCB60E9 +:104A0000EC37D982803609CA3ABB8DF91933B4DA4A +:104A1000401994FFC2826FE07C18F3FB8280E71696 +:104A200085CDC6791F4260613E2D393AE1AF6D6A8E +:104A3000F126551130A76379E12F57E5D1F76FD1F2 +:104A4000F71A7C3FAAEFEF8DF28996EF8DF24AF9C3 +:104A5000FD7BD88E392FFC7D5BF995D6F1CBABE48D +:104A6000F71FD1F8EE0BC36F4C9B6C1D7F5A0D7D69 +:104A70005FEFE0F4EA4E75463642B9D9E50F684873 +:104A8000378D45F1BD9656B011DBA9921F5867408E +:104A900085EFDDDB52C7AC6266BE98F2271CCF0300 +:104AA000D262E68B948949167E4C0DA459CAD093E4 +:104AB00071E2F2981E0A789D048FDE5F277D51D245 +:104AC000DF49F0DEB1D745E53BAEE4F0DED1DF4DA6 +:104AD000728630B01C28EBA12B0CD37A04702A2CE0 +:104AE0009BB12F94904B196F7EEFB3E1FB2495356A +:104AF000E07C921C8CF4D15D79C59BC226FCB40E7F +:104B000002FA42395DD1391E055EEF1AB4307BAE30 +:104B1000699C9641FAEC8D85FCFD7C378E17CC5450 +:104B2000500FEADD0586BBF7388EFC8996719CB97B +:104B300095344E5EDC388EDCCAB8719CB3378AF788 +:104B4000629C21171AE7AEFC2BADF3C9ADA2718AA6 +:104B5000E2E7935B15374E129F0FBC17E3F8117F06 +:104B60007DCE67C864EB7C06D7D03857E138E34D7B +:104B7000F3195C13378E9BC6C1F7380E18523E9658 +:104B8000057477742F24FABFE2227B4177849EC09C +:104B90007ED9BB2E46FAC407E366A15E81C519E43F +:104BA0005753D2689C2F9380FE6E339DB93EA22747 +:104BB000E89F05024416018840FFD4091EADD8368F +:104BC0002BB7099FBB4AB3E7A25D72BFC73F0C4436 +:104BD000E7CCAE527D7E02FB66419BFD4497857F0C +:104BE00085DE9BC28637C0F81DA86C4CE513A0BFBC +:104BF00018E8ADE3A0BFF0F9B1B04F3F02FDC674B5 +:104C000033BC4D348F131AC7E389F57C1DF972ED5F +:104C1000513B187B38CC5B8500F70D621A0BDAC06C +:104C2000F833C959BDA047F78B8EC846A2476080AC +:104C30000DF89CADEB07B812EDC0CEFC83B047E198 +:104C40006F800D6CD99B5BB71FC266EF2873072D71 +:104C500081F9CEEE586B1F00E533F6AE5BFD6E5367 +:104C60003FB3EDC771DE4EF80FFBB92964B7D8A783 +:104C70003FA8B4966F89B3576B947C410F31AE2F28 +:104C800062477ADD90C9E1B9059F63B0DA207ADD29 +:104C90006AF06F253CF577DA5994D6A3AE0C5688A6 +:104CA000F8C820BB2824D79538F86EB53B0341A03F +:104CB000E7AD3F56098FF1F076ED4D0ED8C05EEAB4 +:104CC0005AF76F76B4BF2F06FF0F9759EB59988F9D +:104CD00027F12AF9E0C6D925FD3E32B5BB2934A318 +:104CE000DF47267EF941E52C4BF996869B2CED7F1C +:104CF000B86CAEA57E6E78B1A57E7EEB6D96F28225 +:104D0000B61F5BDA2F5AD764A95F1CB9DB525FBDAF +:104D100075ADA55CDBFEB0A57DFDAE0D967ADBDE44 +:104D200011D7A23CAE785B65689F7DE13E712FDABA +:104D3000575F189A1FDBD421AF811C7ED2984DFC9F +:104D40007DB2D147CF33BBC63AD11EAF4F02798671 +:104D5000B57EAFF28770EB64D423D01E74F87EE585 +:104D6000C370189CA7D7141FF1BDBA4E6751605588 +:104D700085A5F5F075B71AABD7BAA07E6CDFF5EA5A +:104D80003A2D61BDD6A525ECF7ACD25D80F65DF875 +:104D9000770E8676605FF603FC0DC0F5A2AFFA537E +:104DA0003656D96ED23B27141BF1C10DCA9413A8F5 +:104DB0009F6B742EEF353B72A6A03F58A3470B1A8A +:104DC000DC1718AF1D80C9C27EF2695E8B230362B7 +:104DD000F24BF41B6291FBA52CF447D4CFA7F6A9A4 +:104DE000A46759F440EEF746E1F88113F89EEDCA46 +:104DF000A0F5F19DC640BF8FC09F3BD6389D9EBF9A +:104E00006F0CF6FB0874CD7B8DB3A9FC7E63889E86 +:104E10005D8D95F43CDED840F51F352EA3F289C692 +:104E2000303D3F696CA5E7C9C636AA3FD5B88ECAE2 +:104E3000671A23F4ECF103843DCAD285FD27EC7593 +:104E40005839A87C4ECC41857F73BFD59F8D727D2C +:104E5000CEFD6501DAB9E78E816192C03F94CF78CB +:104E60007EEB9B7E015AEF174680FE637BD7BB9299 +:104E7000387D5C36369D81FEB97B98CE34183FE98B +:104E800095CBC95E86F71A237D19F1CFF224E81F6E +:104E9000E79C75713AF5F0C723FF5E8CF1871B84A0 +:104EA0003E4C3AA03670BA6DF223DD4CF8E376D969 +:104EB0000B429FC7E1916CB99CDEF83C9D21F1D972 +:104EC000998B7180FB95E0081BF0C1B90E07CDEB03 +:104ED000DCEEE408C36F313832E94278E370546F96 +:104EE000751966FD50DB9E6A58F5458E61D617E749 +:104EF0008E6CF2A2DC2FC9B6191F8D45FE0808FE84 +:104F0000E07C27FBAF6DCF33DC967EACE5736DCADA +:104F100074F48340B9A77C3F817F209F4BB275E337 +:104F20002390EF935B87A4E0B8E0C71938CEA94679 +:104F3000C3E0E3661B66BEAC599644ED257C7DF567 +:104F4000FBF7860F2D830F9D8C50FFF5906FEE675A +:104F500033ED4F14CF61BBED5FE2BAE380FFBFA634 +:104F600078804665D96F7DBB1A765C81EFB759C6EC +:104F700083EF7CD287C6F5AA6FBA6BEC84292E50DA +:104F80008763907FE4243A87A0C714E8EFACE66E0D +:104F900055609CE9361FD5D70B7EAC7576E9217834 +:104FA00075BA83D3A3AF714E361EF169A03F2A9D17 +:104FB000E091C13895ED23CA503F9EEE58911902F9 +:104FC000BEAD56CFDD114CF07DAB4DE1F044ECDDD4 +:104FD0005DA6F9C8380A63D0AF33063F72FA0953A9 +:104FE000395E5FCBE77DD82FF047DDB6A3E55701EB +:104FF000FC75BB3ED7118EE9B6D07DB68CD8FC15BA +:105000009C3FF453B5F5031DE7F7893D5C70E70558 +:10501000F4546F38DDD914B793F0855927DA31F39A +:105020007AE28ABE1BDF05D1FCF49FEC6C15C0C18F +:10503000FE02ADA0DE2E6A2B58D08BF89AD7514DC8 +:10504000F1C54F6DD26E6A2B46FE38CD6CD3717EA2 +:10505000A7D99BDEB126FC75D8B8DDCF5AB91D1390 +:1050600086FF101EB0672D76CDA275D6F242765D12 +:1050700026EA8D85F7DB590450B418ED22C91F309C +:10508000EFCD366EEF2E620D2D68CF690EEE1FCC80 +:1050900033983600E0AAFDD5A3C568F7BF6CB311FD +:1050A0007D649C61711A87BB2A3DA207A0FEC38E56 +:1050B000B1375C85DCE788B4E0BACC52987F0BEB63 +:1050C0008DCFF9AD56F82E067F3CBC8C2DB7C02194 +:1050D000FB9570A85B95402401DFBD26F94EE89151 +:1050E00034D56AE767C595DFB389F8A5CA54A4F338 +:1050F00069C319B6A550BD3F8AF1911D0EFF0AA0E4 +:10510000EFEDB66017EA67B00B8A98A9DDEDB6102F +:10511000BD3FA5BCB110ED53A6458BD0BF8735452B +:10512000437ED0053FA849DE228CC77A18AC9F2069 +:10513000970E840FFA69F154CE6445187F053985BE +:10514000FEEEF1961F51A0EC727730ECCF916D8D91 +:105150002FBB7CD6723DFE03E9309C511C2779B8E9 +:10516000B51E162C86FCE6F15BDFFFEF1E3C458981 +:105170006FBDC4D2F074BAA32A8CCF266AA7CC76AE +:10518000739D93C34F7E39B45F2AECF93AE60B5313 +:105190009C389BF3C1D219368267A9C7E70F43BD7C +:1051A000A20518CA1FC6AACDEB58FD7910B97EA674 +:1051B000B2D6AD235FD69FD75804F47D912DE4512C +:1051C000C723FE0264E73A01595F03C89A7BBAC558 +:1051D000EE6503D3C4FA3AD030CBEB40A4F3F81811 +:1051E0009DA55EB00BBD08FA224BCD403DD85D4E6B +:1051F0007E09EB223D21DBE9B17603118EBEDAB9DF +:1052000062EDF212F557FBAB67768601FF55CF3D95 +:10521000E005E2B34FB5B64C3FBCAFD9B2D28B7C00 +:10522000FC8916F6E2BC3F8DA8D313F1F30DAA2238 +:10523000FCB1805B417F58D0E9E453ABBF8B78FF72 +:10524000728BDDC026F55B1D510710B1AE6331E7EF +:10525000A7AD8E0F78F9AECF919EF5BBACF256F5A7 +:10526000C4039918EF040C71BF9145C97EAEDBFCF5 +:10527000C772B447EA5937E989F8EF70FCF369B4AB +:105280007ECDD5537AD7CBFD977AC1F7F51DAB3FCD +:1052900057BD58B6CA77A5F047A6A99E748A2B4D6C +:1052A0006013906E120F2CC2EDE1154F3E54F401C5 +:1052B000C0716AF33F79154BDC88EB8773EDF31F00 +:1052C0007FC9D7B75E3F23FCF9D87711FACEB78BE9 +:1052D000DBEF6C377FD6D8A35EF4976A36D8FD2013 +:1052E00099ACE6994DBF7C04F9FA770E8A33543FA6 +:1052F00073E89D2BA15CBDDD9E3E934FC3AD64C69C +:10530000E8510FFF2F1B13C37FD5F38774DF28FEEF +:10531000FEA769313A546FDFA7B351BDF156DABE2B +:105320004FEF7227A047FB07E5686FAF78F22B1DA0 +:10533000E5EAD3BD0ACBCAEBFD7DE5864364CF2108 +:105340009E887E823E3DF4EA45A7E8775F1A47EDE6 +:105350000C5CBFFAA2D3485CFB32888F9F7D09E3C7 +:10536000F7BF77F871FE95CFFEC88BF3F8586BE066 +:10537000FCFCE8CACC008C5B690F671AF4E4EF2BE5 +:105380001FBB9DF86CD1D1DB33291EC00239365AC0 +:1053900043C33938BF05EBAFA7F92D6421E2B7CA83 +:1053A00047D56004E3591A9BBE3D813CBC21E4E132 +:1053B000E38D0E5C7BD8C7A860D13F7C53A57D02EE +:1053C000C66EA378C3ED721F822DA1F2174E4EA7B1 +:1053D0004DAA4DC6379C163EDD7C5727D2E7E4A088 +:1053E0004016C627010F61812F05F58E7A746A1663 +:1053F000A70FF369C5E23BD08BA5F81EDB77DA0374 +:10540000AE22CB77621DE3E32F15E303DC49688FFF +:105410007D9C09F64D82F97DA54ABD0CF68689BFB3 +:105420004C72CDE57CF3DD5CAEA59C47664DC7FABA +:105430003FBDC5E507BFC3751DE08A6651FDBEEFE0 +:105440002BA4071C2C9A489E37DB853C5BEBE5FEC2 +:1054500024C0ADE1FA14E313E83F8DF04F76DAC2D1 +:10546000FBE13B935EAEC7F1A89D1E7B6F5AD71739 +:1054700009F97F5515FBA342FED97A2EF77DDBBDD6 +:1054800061EE1FD823BF7C04E515E413D7999A6712 +:10549000EC419CF767DB0EBC7333F0F567ED524EC1 +:1054A000AD7A335E4E2B778C6789E4F433B79F2552 +:1054B0009453789F504EDD5DC4C7FFD97A53E2ED17 +:1054C0004C9CDE947AB02FFCC5EBC135AA2FA11EEF +:1054D00084BFB758716FBE93FC26F9ACEAE9DAC114 +:1054E000143792FC28F9AD871F25BFC5CFD38AB7E3 +:1054F000F8FA1785BE9174B62F67610FC64BF7A8EF +:10550000E45F9F05985A80BE67B7E54530EEBCD290 +:10551000C5E317678D6E6F1A3C57A6F2727786DE69 +:1055200082FA41BEEF76F1F8F6D960B737D5E45785 +:105530007CB05BF5FAA0BE2BC2A627F23740F3126F +:105540001C5DACAF7A1E0F9EAABA7397A1DFDEA6D0 +:10555000D27E7645D38D5EDC073EBB7BC8CF513F04 +:105560002D780D0C4C80F72CDA812938BD80867996 +:1055700009F305BD3F61E10727C3FCE6EFE6FE4204 +:10558000C59A38FBDEBD54477D03F6FD716B5C9B0D +:10559000F34D95E8A772BDB5BE8AAD21BA55C5F1E8 +:1055A0005148F8811334C147A3D968E187F1F885E0 +:1055B000D05753D5C29FA39D71F6088F2B9EDBADAC +:1055C00012FECF6D532218F7A1F8EE24A47FB7CEB8 +:1055D0004CFEF229E437BD6F393EF5C21F8AEF84D5 +:1055E00026353BDF2DFA053C4FEDFC5DC1CB58FE67 +:1055F000D56F73DF65BDDB97EEFD33ED1F9FDDEBF0 +:105600002038CEEE7D35F74E2CBFE4F0239C679713 +:105610003B68FF2CBCD7131986F58380DEB86EEE8D +:10562000F9AAA88BD69D66A2D33C8DEF779CDBFDB3 +:10563000EFEF2B987FB0DBE1C379D4EFE57921F56B +:105640002FB928EE7276CF57C521F7DF6F3E753A36 +:105650000B11FF79D8EC1DC8AFA97C1FA0FEE5494E +:105660009B9A703FBC639F8EFB2BA5AFFCB508F5E2 +:10567000CBD91DDC4E3863EF7A0CF7416BB5A1CB6B +:10568000ED28F768B3F507BBD3BE604AB830115EAA +:10569000381ECE021E705E80974AD48B7DE1A359DE +:1056A000E3FEE67F3F7C7C7E2B8E5FB37B02C94DA1 +:1056B0000C2F4A80BFF7449C0ACD9FBFDFFB5511DA +:1056C000DA3D9FB537D13A7EB1796FFA1F376F2532 +:1056D0007A29F3DEFFDF9CFFA76B7C5D8A9783DE70 +:1056E0007CFEAB3BA8FCACC74FF05EA2FC1FFF9F4B +:1056F00046F71D4077EFC5E9AED8FFBBCEFB62741D +:105700007F4DD0DD63605EC1D93D7FA578B99CFF38 +:10571000C5E6EDFB7F74DED2FE5965F3B7E543FBCA +:10572000352CDAE90338570EBFAE0DC34CE0260422 +:1057300013D923413BF78F5485C761D8201E1762C8 +:10574000C29FA014301FC65116925DA7B95BC8CE88 +:10575000649ABF3300F85835729E9F7235D89863AB +:10576000212C0F9CECA7F8669C5FA58DFCF611B46C +:10577000EF9B9B003E18A7D9A319602931FB705BF2 +:10578000D45144CF0FF079978867D90DDDE257B82F +:10579000E3FC0297CF5AEF10FD3BD97E03F3889CC0 +:1057A0007E8D45B01D6B0B9BF3071CCCF41DD417ED +:1057B0006200D6643F7E53FC35F5E06F4C6700F124 +:1057C00037C246712D4AEA237CF823AB781E85D375 +:1057D0008ACF964EC4A3C6C0FFE3F322BF91097FD0 +:1057E00051135D68C36D0197B59DF08B2E4A1F4E16 +:1057F0008FDC1A419F25167A48BC5F802E167A48A6 +:10580000FC7E53BAC4D3231EFFDFB7F3B89BA49327 +:1058100025BF2383FB2151F0435EDDB689E21DA73E +:105820009FFAE0BBC8A7D52FABCC09DF9FD9E661B3 +:1058300051945F2DA2A33F55D5A1268CF34ABBBC42 +:10584000FA390FF179D50E4764267C5FB5F3C32290 +:10585000B29B96771F1E807181A7144EBF7057119F +:10586000EEDB5569DC3F88EF6FBD9DC7054EBD98E7 +:105870003C1BE30FCA569EAF58D57EA3DD61DA7795 +:10588000FE5F769EF70AED489EC34F2AB4DEF4868B +:105890008FFB05A79E54387CBBEC11CC7BACDABAED +:1058A000410FA15FB9F5738A63973EF78CB78BFC04 +:1058B00045D5EA3F6F55899EF024BAC5FBB1751DE9 +:1058C000B5E427D4B50B3F31CE8FAA7E6ECFCE3054 +:1058D000A0A6FAF927BC187F39D9B9C54BFEE956FD +:1058E000EE7F6A6E2DB17F7A31BFB4FDEE847EE922 +:1058F00049FC07F813FBEC71FEFCD67E97B67FF9E6 +:10590000CC178F619CF4D48ECF1E43B86BFEE3DFBF +:105910001E43FB9EED75195B60BEF54FBD4DF12634 +:10592000F9DDBB424ECF0C62E11C6877E6770ECA08 +:105930001F39B3E7E35CF4E7CE6CFF7326FAF54B4F +:10594000F74CCDC2792F7DA1348B259077F944BED9 +:105950008C5C429C309E0E073A0E901F72FA988320 +:10596000FCBE9EF8427B2D8FD7F8445C615BE23829 +:10597000ACF487EB3A3E2CE7F131E1175F2C8EF067 +:1059800016D0F18A4BA0D73611278AA3D769FC0716 +:10599000D0E5AB387A7DC1428FE7E03E6447BF3E39 +:1059A000E308D14BC0938CEF1EB6076C3ACAC18E88 +:1059B000E41E3ACD443A3DF3452EC6C33FB177933A +:1059C000DDD3BDC761A07F5FB5E7B72417675E3839 +:1059D0004AF15326E2AC6758CF1F8F8B29627E9B1A +:1059E0003D3CFE20F08DF1099F97DE8B3804E75790 +:1059F000199FE82B2E314117794F22EE5CBBF95DE0 +:105A00009DC5C579948948A70F2CF17139EFF8FE2F +:105A10000CC4C304737C2D71DC47FACD313AF1B864 +:105A20009A8C9F9DD920E26EF07EE018F407791CD5 +:105A3000A33EA2FC96259043195F1BA3C7C961E44E +:105A4000D2E26A1783F76FC5C7309DAF0B122FA73D +:105A5000FE92580F7F47E7723DDD169AA99BF6B379 +:105A60007F28F65924BE24BCA7441EDEA9A7548A69 +:105A700007B5B41F207D1A2FCF757D9C83B855E7DD +:105A8000F1D6BA5DFB8A50EF9CDAFF22F15DDDB6FC +:105A90000FF430F47378EBF33AB727399FA39E8E57 +:105AA00098F4F4A967F715F1B81FCFBB8DEFBF5A73 +:105AB000F45FBFDBDA7FFDB6CF2DFD5787DB75BE08 +:105AC0005E5E789C935AE0469CEFC94E3B437D77DF +:105AD000B25D9D1E496407EA76CB3E68CB519DD6E8 +:105AE000AB716F26517EEED2A3D3DF4DC17D3A104C +:105AF00033B47F3B9A385F75FC2C3000E9D271F4E7 +:105B00006615D78D9D8847931D5CFC5643A907E415 +:105B1000B5F8BDE03864AB783D30E198CD02378C04 +:105B20009385FAB819FAC17C7ACC1FC2FD51D55BB6 +:105B30003E1DE1510D9BE14AB87EF2FEECEE2043A2 +:105B4000BBDC6E58F395B3AF1371B4A8356F3D5BF2 +:105B500067C3711F9CD992FCB81FB0644460F421E4 +:105B6000CCAB5F904D71E29CEFF1EF4E1BEEB0EDD0 +:105B70008AD8BE6DF279E81FF3606C91B573E0BB13 +:105B800064AD5DC17D007832A4CBEDB6D0463D0357 +:105B9000DBE9CC07AAF1315DD128FF429C7B91FD66 +:105BA000C9767DED07CB7348AA807F88D80F1EC4C5 +:105BB000BA14DC0F5EEFE1E79106BBD3E9BCD12656 +:105BC00061AFF970DF15DB3558D7ED8B9E476AB5AD +:105BD00096D34B4B6E1BEC073F58BFA354037D90ED +:105BE0007E63C9F60106EE4BDF5F8A79F7E94F94D1 +:105BF0008CCE81F26C475119D5FF4BC9E85C28FF68 +:105C0000A8755219D5572B9417B847EF2E0DBB63C3 +:105C1000F29901C62DE65B80DCEE47B93D1D3CD50F +:105C200082B5B5D77FA9F3F3302C88F31F3491CF19 +:105C30007FA0FBBDED38DFC1B6AE26E4BFC7F77C61 +:105C4000958AED7CCCA0791AACD9C07D797835F1F4 +:105C5000EB0BE4FFC4E7C1487E7F2E39F41B84E3DD +:105C6000EE79C31F2A479D5AE3273E8ADF276646FF +:105C70003AD1A542D005E1749AF2902BF12402E9C1 +:105C80009B3203C751C235EAD7977F73784E487E5F +:105C900011E7C04CE7A43E45381F4E0ED133FE9CA1 +:105CA000D47E3DF819F253CEC2F3B908BF3CFF547D +:105CB000BAC84D718173BB59C491407EE4736323AC +:105CC000CBD086F65DFFB623F4671C37FF15DF8E59 +:105CD00023D0DF1515BA1F53D7AE58362E431BCB32 +:105CE000F884D09E1074CB465AA27CDDC1F8B91C52 +:105CF000871240BFF1EC8F0CD2BF032B66925F710D +:105D00003639AF1DF327CEDEC9F300608557500E3C +:105D100006ED4E89A2FF037CFC651C1F7F695D6751 +:105D2000ACE39EFDDAB7AB8BFA33447F60E864A244 +:105D3000DCF0BFB32AB7B3CF36FA080E300BF7E169 +:105D40007A7AA9E3653BACE7F400EFFD1D26BCE7DA +:105D50003AFAA45F9E83D38F9EF1F45BE86CC8454A +:105D600039AE0AB697A36BFAF1C23B8A91A9DFD686 +:105D7000439761FB9AD99D8779CE504301EEB3F5E5 +:105D8000A62F3F8F95B97B6E931DE315481F5F6F5C +:105D90003A5EB1CC9FA1F5B3D0752CC27FC5EECFD2 +:105DA0006D08BFA4E74322CF3FFEFB6F3914316E6D +:105DB0004D931DE324BB74B267E3DB4DC74355E34A +:105DC00063E52267318D9B65E3F18EDEEDF9FA170D +:105DD000EBD749E7B2FAE2C72283F707F8FFB61913 +:105DE000FFDFED1BFFB3B01DE09F9EDF00FF3762BA +:105DF000FBBEF02FEDE86AA117AA711F05F8E88F26 +:105E000081EB3287C2F8E5AA9BE460F11695E40FB6 +:105E1000DACFCCC98CE991C5931AF6E17C173FAA79 +:105E200010BF568873A69F89BCFEF87CA885B3C3B3 +:105E3000B4BFD32B2F2A12E7D7C5E5BBD7C7F87657 +:105E400030CF53E3E7B6542117A58B0A53D01EDA9F +:105E50006BF7FD0BD9D9AFA96C6302FC6F402633F9 +:105E6000D1755083CD9227CB2A522DFD962D2AA491 +:105E70007DEF251EDF05FDAAC1CBACEB765ED87A9F +:105E8000CE6848ABF59CD1B0B6FE96F697ADCBB7D1 +:105E9000D48F888CB4D45FBE758CA53CAAFD4A4BC8 +:105EA000FB2B764DB1944747BF6D693FF6C8759699 +:105EB000F2F8CE9B2DED271C9B67A99FD45565A9B1 +:105EC000BFEA932596F23F74FFC46AA7D818E94742 +:105ED00096A490BE3CD8383117F3B1D938A50CF14F +:105EE000592AF2090FDEA6DB0C2F3E0B6C06E8AD3B +:105EF000FD0B66D2BA7FF0B6CC808F9EC501F46BE5 +:105F0000983A795CA27CCDA9C6A45C735E54A9D3EF +:105F10006ED16F530D6B79A743ECFB0DE67CF372EA +:105F20009C7CD91B2647C13264FD170FCDC2F140BE +:105F3000CEF60A3DB7F792F45C6643319641CE0E39 +:105F400026923326D6D912C14FF00CE8981F59E695 +:105F5000A1F538802F7DF43EAC81BC4C71FA071E50 +:105F6000C279D9FCE9C88465B38307797F625D662D +:105F7000C36DDF645D96729E6D13F96B693C7FEDB6 +:105F8000E1050529CC84DF3F386CC28E6EE34FE318 +:105F900088AB276F35DFFCFE9324CD942FA72C9A76 +:105FA00049F922D97DE8453D3B7FC666D0C77A8E48 +:105FB0008F9EF27DCB6C5BC23CB06EA147A5BD3518 +:105FC00022666F75233D4E67BFF920E629D5CDE9DE +:105FD000267B2BDBD676DB619CD7EBAA885FFAF8B1 +:105FE000F92A61272F9871DF6D87715FFA9F87917A +:105FF0007E92E3AC6F9C3E43339D231FD887DF74B2 +:10600000B993C3F358E3F0191594B76DF0F3A2A256 +:10601000FFDC706D39DACD8345BEE983B6C4F92E55 +:106020006ED14F16921CE135DC2427A717BEE7D5A9 +:10603000601E8FC0EAE5C47DDB2B3A8BB91D16F0DC +:10604000E339D4DCE82D0F62FBDC6C8DF25DE3C735 +:10605000CF9A136ACDC3F8679ACDEFA672B782EDD7 +:106060001D3F65AC1FB46FFE0F95E069DE3F89F2FE +:106070003F1CEE0686FBA9725E07D21E21FCA81DFE +:10608000C9B40E32B12F2EE3AD5F645774A2BDF1D7 +:10609000C5FD761AEF0B98A301FD7FD1A1D2BEEB0F +:1060A000E1B4A4A80DCA6AAB87D6EF5CB43DA1FDEC +:1060B000C20E4FC49717C38BB66E329D87710CE426 +:1060C000F36F4E7347DC7934EF749CB78453CE7B07 +:1060D000501F7E6689803BE7B29E731A0CF95835D3 +:1060E00034EA77412A3F8719699C28E8659D4F4B20 +:1060F000F675D7DE84E787DE5219A686F8BADA6825 +:10610000FE0B61FE115F6FFC9EF6E57D695309CEC3 +:106110001284535D574EF3A076F05DEDE30A7B24C5 +:106120000FF930349DE8DADF46E7027BD9074E2EBF +:106130005F339C3C2F57CF2E98B1B91F3E87925C9E +:106140007CC7D9E7BA1F74727D44CF6F70BF00ADB2 +:10615000FF521FA9019BB073B95EEAB19FF4D00F43 +:106160009C19B1B29AF2D322ECB76FFB6CFB3E1DC7 +:10617000ED333723FB59EACDBEEC33B4CB90DFA42B +:106180005DB6386E9E30BF1A31BF9A44F3EBA56FEF +:106190006F6E9076CD12E705ECCA0C3DB13E7A5297 +:1061A000D0A1DED019C59B688D02BDB3D846E78D5E +:1061B00099167199CF97AF774ABB6EF73E1DF10CD8 +:1061C000F3463C6783FF5C4E7AC79E302FFC62FE2D +:1061D00048FEEAC21D47B03FB07311FA736DBE941A +:1061E000B40BD817F665AFBBCC78BDCF29F2B96335 +:1061F000787C40E0F18184784C073CDA2CF6E1CEE3 +:10620000021FE1F117CE0BD887A7BFF77E31AE474B +:106210006704BEEA7AFC5CAE9FFBC32285F1AA5AF2 +:10622000CC5F76F232EE07E15E0CC6E18A6CC127E4 +:10623000B0FFFA5DD673873F73F2381973F373B307 +:10624000B2BF4CA1EFC1AFFED61F7DA4F7FF11E78F +:1062500013F3AFBB8AD1BF5AF1C26529689795ED98 +:10626000BCC9C0E7B9F4A1B49E9DDEE908209CA793 +:10627000D378BEDEE99D130E63FCE1B3C623F96655 +:106280007D7FFAD9A3C576E8E7F48EA3C51AE507A2 +:10629000472C7661EDD7BF29C6735832AFBA875FF6 +:1062A0009C7C9DB8DFC5E31A19997A0BE68B9F4F4A +:1062B0004A257C3D9069BB3751BC06D527EDDB7B79 +:1062C00074DAA75C32C2B7C28DF19A3C83F2705780 +:1062D00028819C05B8CF32CBE9C77D80F47C363C61 +:1062E0002F055118626EC0A7E3601B1D374DEA34BD +:1062F000F6A17924E3385A29D7B7DDD7EB9437963E +:10630000ACF91E9A03E5ECD91AAD7732AEE348E654 +:10631000E792655CA7079ED7ECB40E2DC90BB59527 +:10632000C0774B26A5D177DE59EF10BF9CF5D9C2B7 +:10633000769C8FD64DF19D9F370ECF180A78347218 +:106340006C33C8A6F90B60CB94FFEFD5583805EC39 +:106350009BD5C0FF4381FF3B1A9DD4BE05EC432370 +:106360008DEE4988DDF361929B1D8D06B5FB65635B +:10637000367D775FA38F9E3D7604E3DF5139817EC2 +:10638000FDCF7ADED3C8EF1391E57F1B07761AD0D5 +:106390003B7D025015F0922ECE9FCBFA471A5F1B21 +:1063A0005236542003F0D9BFC6D8B0EA02F0A63B5B +:1063B00022A978C4F872170B974DC43CBFEE7BCB73 +:1063C00053F17CC45D656523008FB8BF7D2590CAFD +:1063D000755F339E4FCDA9F13561DC2F6797D28E63 +:1063E000EB57CEAEB525B88F00EDE8DCA0EC37C397 +:1063F000C5F55CF2818795FC51B8B9C0F7E5D99E27 +:10640000E448A2F3A5E35C5CCFF95D7C7F70B5D86E +:1064100057EF9EE526BD987CC045FC92B3FB72DA2F +:10642000DF73F7B1AF1CDF4FF2813F531CD8ADB41F +:10643000EDC37D4AB680DB9F929FFAFA0EDBEB97A5 +:10644000D0FEAC5FA3B83098BD34BFD3B30612BE44 +:10645000B1BD598F9FD513DB650181A795F6C47136 +:106460007A8DF171C67576D37E26DEDB84F8CE791F +:10647000AB4D417FFDB4C2F331FA033E764039673C +:10648000721BDDEBF49C3354EE82EFFE641C2B5840 +:1064900009E0B80A7F9F8BDF497CA845BA13F5490C +:1064A000CEEE0FF8391F5B978EF96F8BEE7E9EE272 +:1064B0008FAA1ECCE3E5952B313E99E10D6E403E4F +:1064C00061E1E7CB0E029F3C20CE2DE31BD47BABDA +:1064D0005DA21C6E6F0E009FACB6F3F2A2BB9F23B1 +:1064E000BE596D0F2EC673CF586E86FE57A7B6677E +:1064F000DBA0EC6E7AA6F9C8202CCBF6CF34872728 +:10650000831DEA92FA39988378EF291B501E652A79 +:106510006BBCCC9CFC29E7577BE0CF870700BFD43E +:10652000EDE6F7DCF4E06DD75A05D7A35F361EF130 +:10653000356B424EA4FE8075FEB26C467E8A1E51BB +:1065400022F90ADEF7D19A69CE57F941B222E21652 +:10655000F0BD39FE1877AE8D8ECAE0FADCCCF3427E +:10656000E2E9FA7652495B52069E470DAD52510F51 +:106570003E633728AFBE4B23BD7D4AE6D537D8C929 +:106580001EAC11E75CEDCB43AB46A05CDCA2F9315D +:10659000BE509DD75682F650F58B79FE2616CBD38A +:1065A000AD4E6DCF1CE38EE5E9CAF20A1197CA4AD7 +:1065B0006D484D2DC4FD98B5B9B85F52C7DA6EFD70 +:1065C00009C2FB86CA90DF3FDD372905EF1DAA858A +:1065D00032C6C16A3B8EEA2168776512BFEFA6AE6C +:1065E00003F8C6CDEFA1091430B641339250CFFF66 +:1065F00032D030124DE24DAE5F97B9FE81B127F235 +:106600000306D2F995BB8F353BB1AC1B23D8682C60 +:10661000FF6B33F259F5681BE559B2F0BF1E0C0C45 +:1066200015FBBD506E750D9A6A8E7BE7887386F5F3 +:10663000EBDD741E0CD6E58DC8DF75EB6C61DC3FBD +:10664000B3393BE91CD02B2E26E8633D3F75BFC212 +:10665000F56178018FA72E9D91F66D3A3FB532DF37 +:10666000085F20AE5B793E89CE49C9F295493EEA82 +:10667000BF520BD33E52E5792F9DAFFAFB8DE7B4A5 +:106680009CD7EA3D9E9BE091E3D5C4C623BA1E1871 +:10669000F3FA8343816E4BB7DB6D0E13DF2DDD2ED6 +:1066A000F6E75D812CEC2743E77866E80F02AFD16F +:1066B0001D37BC1CD6B241FF4BF90E9F6B2E9B8C35 +:1066C000748BD533ABFC07D01FBF274996FFBDB9EC +:1066D0006C6082F64971EDF365FFEA4AEC3F1E9E5D +:1066E0008CA458D909EDB5BF3A7ACA08DF5A5B5C69 +:1066F0007F69B2EC5E89E34BBE6ABD3BFD5018F882 +:10670000EA9ED4B612D4FFDD0B980FEFD1427EF58E +:106710009BF46DAB8BCB75E5F97C0BBD63782FB02B +:10672000D0E5E3C66CCBBEE7A2394B697FB6D52571 +:10673000E8C5C2FC9CCDFA012C628A07FD7F38FEB9 +:106740005638AEEC038E6FFD17C3E1B38C1783632D +:10675000A805BEBF158E8D37147C3B0F9A3CA084D4 +:106760009DF9B82EFC8CE7C5A9A965BE26DC97F972 +:10677000994671FD618CE7BBE46BEC883606E5A7B2 +:106780002D807110B69CDB2BF0BED53E86D621F253 +:106790001786EC76CCC5BC8DFCCAC0627CB2818504 +:1067A000B4EF23F749998813CA7D9E61062BC17BFC +:1067B000FF8E27CDA5752A3F38A71AE3EAAA675CA2 +:1067C00012AE870FD822611C2F7C1F1F2FC31669A2 +:1067D00077A2BDE41D6AE07A97E1E5FA8FAD2AA4BD +:1067E000F56FA32D7FE46D00C74AA524E935C47376 +:1067F0006A3EC5C7F13DDEB3B351AC5B6AAADFC0E8 +:10680000756AA358B75608FD2EDF27A705E7A21D16 +:10681000F1F355D3A63A27A11E0AB4F683F5E6DEB6 +:1068200055D356664FC2F5C697EF84F5E5DEA469E9 +:106830002B9D30998D4DBEFE466AAC3CECAFB05AF4 +:10684000939E98B632007AA7D9BDA40AED1CA83F42 +:10685000847EE2136952EFF0FA7CA9A7502F811EC3 +:10686000539B7ACA61D44BF93D7A671AE99DCD8F63 +:10687000A9545E0AE3A11D03F308E3FD60DDC33400 +:10688000F28F5C004B12945D23F269FF0CE6CD920F +:10689000D0FF1FC1EBE57E873ECC46FB1DD81EF125 +:1068A000E8CAE1EDF559FCBCB4EE7193DF26F74F71 +:1068B00054B17F9724F254146316F9C1CE35639610 +:1068C000A01FE51C6ADD9FD6E3F259D4F8FC1677C9 +:1068D00094ECAEB62411BFEEC7B2E9DE04F11E2C73 +:1068E000E531F8CCBCA9B984EED3F33003F3A9B3F6 +:1068F000435166B697E4D301EBA8CF24370E370B8C +:1069000024CAA75898CCED61F7798DFB890AD8374E +:10691000B88E7A841D2EEC23BBBCE7286EDD95F67D +:10692000925DDCA7B774C6942C3C97A4BA034EB40E +:1069300073F61963689F4665FE6B4B4CF64E737495 +:1069400006C5273523C0D0CE795DD839AAE1676660 +:106950003BA7A5111C7058AB361517D0FD358FB865 +:10696000A2CE2148DF076C7ED41B07C65485158C48 +:106970004F2E6324A79B8A33A7E03EC3062D98724F +:106980000BCACB5B309E8FD38DEF73AF50309EFE22 +:1069900085339882FAE09E5466F1A3AE4DE6FEC8B8 +:1069A0009624AE7FA49FD002F044010EEDFC48BABD +:1069B000CF67B4B04BF53965142FC334208C7F3AC0 +:1069C0005803E587CAFBEA1CD9364BFEA376BE887E +:1069D000E2895B92F83872DCBBC47D83B2EC640D53 +:1069E0003C6E0C3C9EC87FAB15703AC01EF2917D88 +:1069F00012B7FFDFDB3E227B45D2A7C74E51F8B965 +:106A0000D0BEECA3FAF3368B9E8D9D67D7492F9F9E +:106A100011F705C83C10B7D0672DD9A1B6ABF2620B +:106A2000F70368221F648DB81780656BDDE673F885 +:106A3000C9188F81FA669117921C77AEDFE55E4A1E +:106A4000FE826BB8663907E66421FACEE1B3BED7A1 +:106A5000B2E3EF0B08F7E48151DEA2C61E56E872DE +:106A6000006EEF0E107958A793DFA77823D8BB07E5 +:106A70009CB42FC1CF89CA78D837B58F5F47BB8AFE +:106A8000FCC2E9A3B1DF45B81E613C9B0573F8A6C3 +:106A9000633BA3BCA1247F17E3778E91BDA54A3D3C +:106AA000177EBE19FDA80CB37D67B2D72E5FFD7CA3 +:106AB000737321F91D545E74771BE9C1952E595EDD +:106AC0004D6558AFA2E8F7B09D0E1FF2137C1F4032 +:106AD000B961371490BDACE6834B0B7097E1FD872D +:106AE000B83FB0D3B111ED59F06BE7B94C71B2D3E7 +:106AF0009E63B9AC30617F614B7FB9DFAC3F18BF9B +:106B000003F38C647D99775D54E5DFF9F03B36B093 +:106B1000F3FD30F4FFC00B0EBA9744DEB31CCFAFC9 +:106B20005392B9FF8E7AC39CCFA9CFA90820734A8C +:106B3000F974642759F2BFA5BC6AE787937CCAEF52 +:106B40005E4FE2FBC79A16A0B89A76BE90E47F8BA0 +:106B5000A06B4BA3719171D2FA18670CF5D3F7387B +:106B6000C5424F30B13FA619E67B64FA92D7F8FDD3 +:106B7000C078FD269F52BFED15FDCF4DB6C697AB31 +:106B8000D6B51F4616FA892D54913C1EF3BEDEF38E +:106B9000E2525C638B16A1BCDDDEFB7D1D4EEE4731 +:106BA000224E50B0F5B6FDC8AE0DC9A1F54950AEA4 +:106BB0004A16FB00D9B0AEA9B86EF1BCA587B11ECC +:106BC000F31B42BE87A6A29E9A554EF1EBE7928335 +:106BD000BFC1EFEEBEAE98620512EED58D3CDF4E22 +:106BE000EA4B37E20BDA3BB4061EF77407A2685F84 +:106BF000DC97FCF6540DF950E372B06CF5FE951875 +:106C000017716A7EE22BA7DBE6C3F5DD09FE1DAE38 +:106C10007B4D6E1BC59356E03DC0F0BE599969A0EF +:106C2000BC2EF1E467B10BE847ED7CA6D0BFD67B64 +:106C300075FEFEE3A4D3F7BDEEEF3930298AFD6976 +:106C40007E46F93388840F4D7A55AEEBF1DFC5F7F8 +:106C50002FF129F1EBD04284571DED8604703D9948 +:106C60006CDDB7CD92FA33F59D8228BCAD55BABC28 +:106C7000689F805E7C12F9A46E54F7AF151FE9D3AC +:106C80004C6ECF84E57D0596FB91645C5E7573BBAD +:106C900046C2BFE4B5079CE67DA77878E3D74B777B +:106CA000A1353FC3393029EEBEE0263E8E1624BE04 +:106CB000B14F0E38514E9A8C3106DA2BCD9AEFB780 +:106CC00001CA2BB193DD0C76B8657CF9BC47DC0FAB +:106CD0007C54D851F1F51E719F72FCFBCF85FD707D +:106CE000CFBE9B480FF7453F3C508DF4F5E433038E +:106CF000CFE7D805BCDE8BF4DB171FDDBB8FC77574 +:106D0000B589CE08BA58F1E3A9F66000CF93A9A3DC +:106D100019D9BBEA203E3ED0D2C0B8B0775C1A1B6E +:106D20006E5A67EF1E7A1DBFDF39C3A0F37DAAC775 +:106D3000164C64674A3C1D4C96F75470BEC9967C4D +:106D400033ECF7740FBA896FBA13F1CDC164AEAFEB +:106D5000100E333DEF1E9A9F95883E31BDC8F9EA6B +:106D6000627CD121EE4BAC45DC807F5323CEDB9F90 +:106D700012F704CD4B16F70519DC2E96F75F7468F1 +:106D80008164B4ABE6F5EC5307E85C4A8D2B903296 +:106D900009F9F228B77B3F2EE1F7967D6C0FA4200E +:106DA0009E3F3EAA2A4DB4CFCFF302659ED5C7764B +:106DB000DFEA91503FFF176AA089AAADF6DC2916D9 +:106DC00018FBCF68DFEE5269FF28EFBEB9EA2868EA +:106DD0005F01861EF2D1BC527718D7DF8EDF37BC39 +:106DE0008F7A68FE630EDF7218E7E0BAB15F62F96E +:106DF000C41A8FCF4171B27C05EF155FBA36CFA0B0 +:106E0000FDA3654CD81943CB4B8732F614FE53C60D +:106E10009D9D74CFB8A80FB694C1FC466674D8DCAB +:106E20000053C41D6CC1734E2B9B82D9E8FF5DBB20 +:106E3000A6A005E38F999981CEAB411FAF5833BC13 +:106E40001CFDC18E47447FE1112DE8EFBD6C0BE5C1 +:106E50002950FFD49A29E594973B44F67F03D5CF78 +:106E60007BFCB22F8F1988D3CA728C9915CF91F001 +:106E7000D49697826E5F30599697E8584E4F669633 +:106E800038983DE64F529CADA3C77FBCA31CE3607E +:106E9000F3A734946AD07F9EE7A72D85201A13DAD2 +:106EA0004A8C005E99EBB9AF3C39036FCD0B54E3CC +:106EB0007A32D2737F39CE27BD9FB5FF7455C45344 +:106EC000D9BA16ECAF07BEF0D6168CAFCAF66FDE95 +:106ED000F34E4B78608CEFBF1BBB5FE93BEE0CBA07 +:106EE000B7EE3086D8729775EB3C9F57E4DF0CEC19 +:106EF0002AE27945A23CBC8BE75DCB72362F772C1A +:106F00004FBCCEFFDCCBE5AD232971FDCFDC5C5F50 +:106F100000DCA4E7538EB1C0B6047254E17653BBD3 +:106F20004360E739D362F274AD83B18998DFE4E45A +:106F300070CA7EE2BFBF538CC3C2D7A6211FCF1435 +:106F40007C3EC4AFF03CA55DC911FC3D06F0B2B477 +:106F5000EFC17CB68A78C45617FBE12C183A338906 +:106F600085F0DE9C8C7E502EA4EF03DBDDB1FEDECF +:106F7000E022CCA60E096EC6FEA666E58C5E9117D1 +:106F8000EB07E06E768EB1C0AD4D4CC3FA707F8CCE +:106F900093F4E0B390CF03F884F005C33C8DBF1F9A +:106FA000D0D139321FF5EF484CBA31E9F9E2CEEBD6 +:106FB000E83CCD52AFD81FF1F1EF334A79DE4BF701 +:106FC0008BC9FCFE4C676781793FEB21B7C833B8AA +:106FD0006BE643740EBAD3CEE8FCC2F6920BE61D04 +:106FE000D6605CCE6437D66851F2C76A302E371649 +:106FF000FB7B83CE1F623F3E117FC6B85AC68AC450 +:10700000F497EB60CD798385FBF5D697B1FED35924 +:1070100078ECC5E715EBCFEA37F6EE4F17717C81B8 +:10702000774DE05D4F0CE75EC9A7806F9B89BF1667 +:10703000087E93FB8167768ED868DE7F95E7864071 +:107040003F3F8DBF8F10EE4C227FA5580B5C83ED28 +:107050008B3BD3687F40F287E40B49D78EB4068A16 +:10706000B7743FACD039AE78B80E49B8D6F17BFBD7 +:10707000B2E68454F33DE3521EA0FF0ED1FFB8895F +:10708000243F8F727900B9B905E517EF61C179F82E +:10709000BB8ACCBF4720E12F425E1C4F74E4F87FCF +:1070A000C125F25738DE7AE3BFFF45E8994BF42C4F +:1070B000EEDC4FF3ACE9436EABBC5E9EC7762CEAC8 +:1070C000F541BB3182FF3BDA3FA47BC53A76A94C40 +:1070D000F1F179A3DE2AEED1C7E35F9D02FA38AB66 +:1070E000A70CFAD28774E8D19F51A733D6FE07DEEA +:1070F000F1D39A515F8A7B7BD355586DC6C4E0F8B3 +:10710000939BDB57134389E3580D5E8F458F3DBC3E +:107110006C0AFB10E67FA59BE75F4DEC0AD3EFEA14 +:1071200048B98ED753FD3C9C8E86E7FF929E725DD8 +:10713000444FB9A49EE2EF0FA1CD3B06D7D7AE22B4 +:1071400005ECE60A5B2013FDAF8F8EFE84CEA72CE4 +:1071500012F939A3303F07D7CD63415A573EC54A8C +:107160009EA733D09381F9DAD63C1DB6999F6B8DDB +:10717000E7AB181F8585FD26E010EBC1B58EAE6725 +:10718000793CC32ACFB20C70D6D98698EADD7CDD73 +:107190009274007A37D33DC7428E8FEFCCDA80FAF3 +:1071A000F64D0FCFB3491F12188DF3977209EBAA52 +:1071B000E013DB0FAF7373BD715D02FE9DECE17AEE +:1071C00076C13ACE371DFFBBF41AC47BC79B69A9B1 +:1071D000CB4D7AA24CC8B1EC57EA21F99DAC9F2265 +:1071E000FA9BE6E17251E6E67C877024CA272833D1 +:1071F000ADAFC43FAD9C7F60BE61337FBF29FA8DC8 +:10720000E153ACAB02CFB53AE017F0B7D51EEE8F25 +:10721000F949C59D36EAAF629787F2322BDA391EFB +:107220002BDAF6D9AA4DF889EF6FA987CBD1067171 +:107230000FED211BF01BE2DDCDE13BB33387F4E71B +:10724000220FB71B2EBE6E5C9A9ED920F23180BEF3 +:1072500094BF58FBD2800D563DCDFB4BEF175A81A2 +:10726000E7F0D21F627ECC29033C451580FB4B8F93 +:10727000D03B7A40C7F3B6DD0F33DA8F1F362730A5 +:10728000DA07E5FAA07B8C02FD15B4713D5C7C3F0A +:10729000D83128774EB92EBCB6CD3CDE9D1E8FE589 +:1072A0001C61C53A8EBF6160FF3C8D4FE8E759B263 +:1072B000E3393CC71F6CBF0AE34EF2FB5641FF8B1C +:1072C000C1578CF08D8BC187FD53FE8A3BB81CFBE8 +:1072D000ADFBCD8E01E67E1FE8E977DE1417EAF9F3 +:1072E000B5B0EE9074860EE0B98B8ADDA906DE9308 +:1072F00000F26C437F478E5BA1C9DFCBE92AC67BD6 +:10730000C20B7AC69174FDDD33E6F96FF2B8FFAEB9 +:10731000F4EDD043349FEEED00AF2F86978EF6B993 +:10732000CB5DB84E1C637E5C2724BCC3E674793108 +:107330005FA45EAC1F305F1BFA2FE9BFF0B1158868 +:10734000B7CE29744F423C5F4B3A0D675C7EA49FD9 +:10735000361C03FC50DEED2912FA87919F7BFCA5B9 +:107360003D4FF37B2D385DEAE7703A7679425F7ADC +:1073700032627208FA9CEE2FAEB8BF471FB5F3F722 +:107380009DB973009FBFF64839B7D2253DD8EEA20C +:107390004B66055F9F7E71546415A7338DDFD1EE78 +:1073A00089280A9EA36D68427F5BEA0984C79CAF67 +:1073B00024E1E9A123033A8E8ABD1F3687F7570FD0 +:1073C000F28E7C54A33628390AE9018AAF66A11EE1 +:1073D0008072563B6FC776F3FB1B249E6A6E844E09 +:1073E000C1EFFC574F21CD43E22B6B4ED45653884F +:1073F000F9CAFB077F64A2F311B15F8078B98EFCF4 +:107400000DAEAF6BD4E040F45B599683CEA1C23A87 +:1074100044FAE5908B692EE8EF5578E2BA3455BD11 +:107420008DCE094D1DA2901C830690F11EFA3DAE33 +:107430006BAF4EE6795B7FF9D1509C674632E743EC +:10744000E8C729FA71D23A28D6837FC905BB4E898D +:10745000E9E5438A42FD1CFA87CB37AE50627C894E +:10746000FDA1FD7448993590D6CB8E0C911CD46546 +:10747000C927EBBD9E75E562BDD95F44FF2EE66F5F +:107480002A774D039E9A30BD3D8A574E3785D56980 +:10749000FF08E34E057FD385FAD3CBF9FA505E5847 +:1074A000F5225CC314BA5FF97052A890DFD3CBC742 +:1074B000C914719B4C91AF8CF6023E235EAEFF4720 +:1074C000A6F0E78FC533D39B38CEB356D4D78B7B8A +:1074D000AD579524CE671BE8552CF1966BC5BE05BC +:1074E000DEFFEBE57EA7C8B3E5FB1C60DF137E4B38 +:1074F000EF9A43FB765F745E9FC2EF6FE0FAE04362 +:1075000025F0EB1B157C06E9FEBCF0DB2AE5BF7F0E +:107510006404BC98DF549B94380FBB44CCAF56CC6A +:10752000FFE3467EDFC27CDC4F03FD31D6CBE7B103 +:10753000A86D6C39D27BD11A85F6D3E4BEBDA46F99 +:10754000E57AD5124F9F8FFB69FDFE163FCADF8794 +:107550001F35CEE247C971E3FDA9E38DD996B8FF87 +:10756000BCB621E29E0BDE7E3EF313DCF35B0758D4 +:10757000F6FF586BC6A5DD030AFE5338217C3AE9B5 +:107580005BF9FE78A39385CD707C3294F21E067A67 +:107590004337217D637024B3B0190E3699FFEE9501 +:1075A0008BC75DC10EE7FE0B3C37B8C94EA77B6A9F +:1075B0007BE260A03F8C14D4472573BDE3637E83D8 +:1075C00094AF9AC989FD8771C2CF1DE7E6FE71CAE3 +:1075D00031E94F27F9502F4A7B3CFEBB861EBEB5D2 +:1075E000DA93178B3F00FF86CDFE517CBF2DA2DFC3 +:1075F0006FCE2FF97DF04BC17F89DF5D3C3944F1BF +:107600003DD6A6502ECA8432AB1FF48897AFE78FC1 +:107610007893E97B695757CCB1B67B0CDB8DC76794 +:10762000F225C573CCF6BB3204F51FEF4FFEEE4ECC +:10763000DEC93729FFF377E827427F6FA404B6201D +:107640007FAC11F9F21BFE7A207B3EDA43FF6CA778 +:10765000FDFA924797AEC07C6677BB62D0F9A35D16 +:107660005679F8CEB2F6C115808F7641A71A3F9FA2 +:10767000478D3FAA0F75637E351F7F60FB3E453304 +:10768000F1DBC04ADEEE25AFDD129FD98B65E867DE +:10769000B7D7907ECBBE19E9D83EA0A11DD01F7FE1 +:1076A000EF06E0E9DFC0C88EEE3F4EA1FEBF336EAD +:1076B0008382BFBF25E7D96A9B5568C077AD99C95A +:1076C0007E5C6F328DD0419C67CD7BD1282E8F138D +:1076D000DEEBD4D0BF1A6E040EA1DCC979F954A335 +:1076E0003FDAEDC9EF71F8DA7AE24A7CBD616CB538 +:1076F000B04337727B4C654718B7C7695DCF5C3EB6 +:107700009CD63D399FCC34B16E64B210E61F43FB6A +:1077100056B2539C7CDDCF5CCE7F2F4FD233E667D1 +:107720008E18837EE69035516D1E7CF7D27A5BC24F +:10773000FB353E14788779BC6F9EC7C5F4956C679E +:10774000EF23CE28F93D797A62FF9DB17BA9BEE493 +:10775000D1F49B492E9B75BA0F51E27FB811FC1CE6 +:10776000E1E9DFBE4141DC1C177905C7573DADA0FB +:107770001DF9A3C5CC5013F0538FBC2EDB31B8C21A +:10778000A437A17FA2C786B83C71196F71A570FF9D +:10779000E71623C852C653DE2EF9CF8B37F3DFDD51 +:1077A000E8131F97882FA592DBE535B3F9EF8E9686 +:1077B0003CAA11BDAB9BF9EF0ED66CDB4EE7ECD8C3 +:1077C0004F991FE5BDA67DBB5201E3566FDBAE2C82 +:1077D00030E16F404D84F2AB2FF3C87D8728D9CDBF +:1077E000F17C8DF102B4530EBBB8BC9F2A71877136 +:1077F0001FE2943D5483ED4EE524FB719F52E2FB62 +:10780000D5EDD3E8BE03CF0E47149FADB68DD94E4C +:1078100068D73A52F7231F0D3742C3102F695AB069 +:1078200003BF4F4DF7F8711FC3E7606368BDBE44E7 +:107830003C4C88E387093FE57272638A57C805A309 +:10784000BCA7AB533CD27E22FD74D8CEE7B1837186 +:107850007823DEC0B814E4C323FC7713FAD74415A9 +:10786000CC17891F37C64F812B11FE4B87B35D475D +:10787000BD5E2DF44CC9A39B950F4D70CF40A30A5C +:10788000F973DB0605E364504F7A06DA33CC4BEA32 +:10789000BF8DFBA5D550BFC0A457E43C12E897208C +:1078A000C2E77EAFF320D72F51BE2F20E08DA7E790 +:1078B0009C141F8D5F0EE601BDD7C3C3D12F3E9C24 +:1078C0009F44FD49798F97CF3982CFFBAFDFACD88A +:1078D000DCB47F4276A4844FB67B23654A08E199E5 +:1078E00030BD93F050BB5EA3F94CD583436F33C9D1 +:1078F000435D0AB7E3F6DFF83EDDFF73FFAF8E129C +:107900003FD6823F4DFE44DB51FD7A5C57C24FAA01 +:10791000B8DF750D3749D883E25EAC6B3AB8FEAD7F +:10792000EDD8AEE13D92924FF34EEEA7FBB46ADB89 +:107930001D0CFD28E0BFA548EF783EBD547A821E9D +:10794000E27E525817F1BC501EFA39523F47843D2F +:10795000CADCFCFDBD024F31FE09B5A458F4AB8B67 +:10796000E422EFE498FD989759EB57E8BCA48427EC +:10797000BD34B17D2EF5A2D4D718370C9AF4FA5A3B +:10798000A4EB782A47B93FCAF2715D9670C6D3E975 +:10799000E514AEBF13F0D3232909D62BB97EE73DFA +:1079A000B643C37B91249F5C83F435F1C99329FCD2 +:1079B0007EDD275334EAFFC112BEBFF8A09DAF534E +:1079C0000F3639295FF2D59B78FE96E7663D8ACF60 +:1079D00043B67935587FA83F87A3D5B69CCED781CB +:1079E000FC3D95427CE2655C0F72BD77FFF35C6FF6 +:1079F000D584DDE4CFD684BE5F4179ADE92E3FDD8D +:107A0000F7193AA85FEF89E1359E8F7C3BF6D1EFFD +:107A10001D5FD3CEE50DF426F1510C7F1CCF524EE5 +:107A2000A43C44E4FE0DF001B77BB8BF5428CE3B24 +:107A3000563AFD745EB252C4550BC5B9C7E2630134 +:107A40005A0FE6093A14D982AFE2BC2AD6C4C5550A +:107A50002FD1EEAF5EF6FA08FC5DB0AAEC23F494E9 +:107A6000F2087EA9456EDF11FEDF1E41EF3F08F9E7 +:107A7000AF1ED74EF256FD5103C9A97B3AD757EE38 +:107A8000F7AC7A96B17BC47CD7D0775393DBCB71BC +:107A90005F78EAE30ADDABD9179C8BF01C18FA6F0C +:107AA000EB0F78E7A23C8BDF8792E765CE08393988 +:107AB000B55515BF97D9A05FC8AEBE587F2CFA96B2 +:107AC00042F795089FEFD4B6D2497F44BF736B0A43 +:107AD000FD7EC967DBBEF7E33FA6E3EF835CEDC73E +:107AE000F53F7D4590F8A53BC3E5DFC8E3ACD33156 +:107AF0000ED5D47EC08BE76B3E7DFA8A31A88FF11C +:107B0000DE2D9CFFC9E7D5658897E54F3CF72DAC86 +:107B1000AF8E28FDD02E3DB5F5F1FFC0DF81AADC88 +:107B20005C4FBFF3BCE2E957C8BEFF3F75A9C786EB +:107B300000800000000000001F8B08000000000013 +:107B4000000BD57D0B7854459A689D3EFD24DDA140 +:107B50003BE93CC9A393404025A1131208F2EA2453 +:107B600084872076408620AFE61D20241198591C7A +:107B7000DD9B8620221767E2EA28F8DA0E838A3333 +:107B8000CE18306A90A0CD43C4195D5B040767919D +:107B90006DD4419090F446671677B8C3ADFFAFAA95 +:107BA000749F930EA83BCE776FFCFC8A3A754E3DCE +:107BB000FE77FDFF5FD51A5FF3DF52ED8454EFE9E6 +:107BC0006F3510422EFEF2E1716428218D2D8DFA61 +:107BD000A099902F7FD98CF5C3CFBFF4C67FD3F780 +:107BE0006ADCB14E78EFCB970FE9E1798D47EB6A0C +:107BF000A125F11CD5CFB2D0D2FB824C1209994AF3 +:107C0000D8DF637B0FE91D79B4DE221142BF27550F +:107C10007ADFA02CFA5DCB5EED1233BCE123A49891 +:107C20008EFBFCC2511EA8B7251092127EBE554F86 +:107C3000BCC6385AF623C444CB4BA566AFD49F903C +:107C4000D565E6AD505EFA8DA9CA47BFABD50773BF +:107C50006D309FA1C405F578AB86900418E76E5D82 +:107C6000AD19BFC77E3ED21102651EF192F34308E3 +:107C7000A16FEDBE361CC6FB2DBE4FDF2B3115129A +:107C8000327BDE3909E61333B45EB71AE7F96BD6F7 +:107C90004E571DD93E623D1D8F8E7B0DFEC687CB94 +:107CA0003CAB19DFA700C132B5B532CD01EBB71B34 +:107CB0009CB07EB1BED46A4FA3853EBF6DBDC729BF +:107CC0003B0879FDC289890368FDF921D270195EEC +:107CD00097A5856EDA7FADD78CE3ACD950463EA32D +:107CE000F31D6F95F0FB442BB1DF4AD753A12576E6 +:107CF0003394849CD41542FFCF62BBC3405CA488FC +:107D0000966FCE7E7623FDE4319D27A518FAD91A09 +:107D1000D03BA0DCCDE64FBFB79A0BB13FEBADF047 +:107D2000BD91AC85EFBA364EB36F93B0DF802E2E87 +:107D30003C6F424219B3F2587F4500A7C9DE2A784A +:107D40009F38F4B8BE2FE115C4A3377F7E1E940F71 +:107D5000B1F96A8807E825514F4B84AB27AB92D223 +:107D6000CD7C6B6995B5385C26F663ED6AB83E0547 +:107D7000ED149E67AC2E2CC99E784246F57E4F943A +:107D800002FE876777EA8374DC470F9C43BAAD0530 +:107D9000BA85F13D9FEB611D826E9708BADD7F0EBB +:107DA000E976499B84F454DB56A0077ABDD4E022DF +:107DB0009F69699DD3DF63527039D0B577BFC9FA27 +:107DC0002C8553A7A0CFEDE7CECB141ED96D290E7D +:107DD000099EEF6774FA9646E30538BDB5EB96E663 +:107DE0004629729E1B113E5235413EA9AD273E03E6 +:107DF0006D2F7D7AFD8929B4BEA69A380D943E6A0E +:107E0000557494F5CCA75B805E6C35A4C8E480758E +:107E10009E9D3880F65F5B438A814F5327B8F643B7 +:107E20009DB4496410D4ABDD4B61FCDBEC2B9D327F +:107E3000EDDF36C1DD0AE3DD661FEB94697F8FA5B8 +:107E4000B76C31D2766F05B13EEB00FC36956969AF +:107E5000FDB10A87954292C26D7732B493217AE7D9 +:107E6000B340C79EA535D05F6DF25C27D0492FFE89 +:107E7000DFBF7108CCB7D6D1CF69A2EF4F6D939019 +:107E8000AE88D74C60FEB514BE509FEA1BED83F957 +:107E90005CE6F01370ECD40516C0FC3A5F31102F8D +:107EA0006D9F3A81D1AB6D420BCA8FB7F74F3A2E17 +:107EB000E587E9D2F2AAC10FF538AD5572825C228E +:107EC000330D91786DD291856EFA9D6D32EB2767F7 +:107ED0003BC3EF739C9F9E03B981A59EF36F13A3D1 +:107EE00077AB37DF4DE9E132C73FFC3968BFABF113 +:107EF0001F143F4BFDC84F352FB2FEEC0657C1BAD9 +:107F000008FAB59713E4E33D26B2B0923EDF63630F +:107F1000A59A5EDFE5F3C87A662DE27D09C53BE0F0 +:107F200035753B7D0E70A3740170A378443AB8CDCB +:107F3000BE02F1B664BB7417E2D13B82403D219E84 +:107F4000AD53DD7F80CBC53D26779144FB0B255893 +:107F50009CBB24988F4B63827A81CDB98BC0F7EE9E +:107F6000DD305E4292C9D91821AF08711769E8382F +:107F700017122D0CDFBEF7B533F2801F1DD86F82AC +:107F80004CFC04E50FC976E785BFABC861FD55F031 +:107F9000FEA63579F349368307C285C3C3B7B15FFF +:107FA00055A43CFD08E041FBF5DD44AA406EBCA5AC +:107FB000276623F46FA5E3D0FE12778DFEE5369C8D +:107FC0005F23BEF7A6D58A6545BCBBA81E44708E4C +:107FD0007B3DC045AC530D8FF91C1E87672F28D001 +:107FE000001DDF697602DF3D7A405A8C74ED355210 +:107FF000A604BA677C48283E802F88478BF8A8AD36 +:1080000077FBA2D37D25F259ADDDE4344948F72E44 +:10801000D47F5EB38FD13DD37F319399BE0239595E +:1080200099D75B1E083903FA0DE859F045EDB860A1 +:108030002EE0F7DBCA954E1DE3F34E0A07E023C19D +:108040003796D719BF6CDBE82885F66D94EF23F1DE +:108050007D4CEF45FE3D96DDCF09FDC23CDD96B07F +:108060007C4FB4BAFBD9609E1AFF166D56581ED7C6 +:10807000BEFE60AE270AFD09796CD4323967F4C5BB +:10808000F858BF6C3C2305B7A5104B2FE8A3980DFB +:108090000C3EEA7ED26D664E8F46EBE7548F4FA7BB +:1080A00048EA9F43C8648D27DD46FB5F630C1EA32F +:1080B0009825191B427A984722E82EE09F5D313EB1 +:1080C000905B8989C4B32F4ABFFD6D8CDE045E9A34 +:1080D000E2181F25C6B2F747D918BD0CB5313E2DA1 +:1080E000E3EF8BF90BFA77683CE788DCB71E13DF08 +:1080F000D17961BB980FFD7E2B61FA17E79BB829F8 +:1081000077D7B6087C84F9E8A642C053CE76BF760E +:10811000B1393C8ED0A76AFCC3FC817F603D95439A +:10812000FB7EAFE910E347353D4EE17C62B0112C98 +:108130009B74FE3F235FDD6D21BB607E3B882B9EE1 +:10814000CEABEE8DC18C1F5CA15CE8FF609C6737F5 +:10815000E063E4044EE7F4F90CFA7CB596780D146C +:1081600027ABF7E87C4123E3996BF4FF62C0139DD2 +:108170004797C5E895299DBF1FE7A982EFBD65C454 +:10818000E907BDF4532A3F80FF88BF18E44B1D095F +:10819000C6029C6BE5402EA1F8BF1AE3990FF4F8D4 +:1081A000A9269001CF090922BD9E31C5E613DA5FE9 +:1081B000ABDE9FFE4F30EF7764B28BF6D34D5C534E +:1081C000611DDD014D9C97AEE393B60F7F73807EFA +:1081D00035FFC0E5F9F70294B6C52C789296F38C7A +:1081E0001AA37678181E672CD1E5EB8F395D2434FD +:1081F00032BB2BB4D1E003F8A8DF1B1FC7F05F77B9 +:10820000259578E3239F33395AA70DE9C184ACBB88 +:108210009241BC74DC4F34A4BA258A9DF9A18DE942 +:10822000AB564AFAD1DA4F733ADBA323B93B603E2F +:10823000CD540E02FCB40E9417D58F6439B7D16AB1 +:108240006B76E818D811A15F4828FFCFE898DCA129 +:108250007F771A4784F5279827601F565BBD7E0DF0 +:10826000951BD5EB2D7E391F9F6BC700EEBC562D9D +:10827000C8C1C55C2F2EA97FFB1B2996B66B8971DF +:108280000CFDEE0BF3D258500BCB7FBC2E118CEFB4 +:10829000A4794DC89F844CB0823D2EB9A6C9D7623F +:1082A000AE67CF69D16E477AA1F82D8F733F09F879 +:1082B0009ED79FC17BDEBA189F3742FEDDC1E1A386 +:1082C000A6B33D40A374BE6725A657D4E3BC1057A0 +:1082D0003609FAFDABC5FD1CF6BFEE32CAB379070D +:1082E0004C19A0B7565FD1205EBA0A02B91BB28002 +:1082F0009E43197FA0F05BDD6EB07A1DD0AE57E0D3 +:10830000F5D3062AD072C3F5C517064E246680AB96 +:10831000730BE079C9D618E21D129E1F18D240B720 +:10832000B55708F6B3B8FDEDD320A76BB541A48BC4 +:10833000C54633C2BDF68A16E741B6EA3A82E27B09 +:108340003ABFF858573BCCDBFBC018DBF95BE8C3FE +:1083500024FA1CD7E5390CFCF4784C2C71313EF032 +:108360000DA6F3EF363AFAC75138D4E929DE876112 +:10837000376E6384DD44D22C4ABCB6BFF30DCC67A4 +:10838000A9D1A307782CABAAD703BFCDEBEF2FB6AB +:108390000E8DC4E718F9DA2DDF1E9FCF73F9F2892D +:1083A0009ED27B14FE3ACDE5EF782E273E49657CC0 +:1083B000F14906A9DE07E5CDB4A4DF7D92CDEB85BA +:1083C000ACAEEEE72AE78B4FF2991EF2AE657A412A +:1083D000FD5E271FAF3CCE751EE0269E0F8F63CF3C +:1083E0005F88735D043853397799D3A1DF46FB9BCF +:1083F000F7A601E9906C0EE5021E7BD695CBE79BB4 +:10840000187D5EB670BF5F437FF43D17DAE36F9867 +:108410007CB0BF20D3A8DC0539BB369D809CA5E38A +:108420005EC5F772E9B8F89E01D741B652F94B190B +:10843000ADABD88178D9564AE913F8FFA0C10AFC40 +:108440002FE849D0919A7E4C7142AF31FD7A07E80E +:108450005719F5AB298EE9573DF02FED51CFECBC04 +:1084600081886FA433F9DBE3FBA09170F8BAE3E3F2 +:10847000509FFBF3DC79BDE12CE4DF27FD9474E130 +:10848000E3781CC0DFEB81731C7BCF9EC3F499B0F3 +:10849000FB6FE1EBDACDE5B428857E1A3959696FB7 +:1084A000ECE6F263B72D164B8A97C1B07EA1D77A5E +:1084B000E1FB29866FFADE5058CF3C4368413CD53A +:1084C0004B3FA2F68EBE10BF7B1EBEEBE57F98C071 +:1084D000F469DD5A0B017D3F228ED9B1A4289401A5 +:1084E000FD9121B4CC03FEA3F246BA31FE60AF9FEA +:1084F0004279E4F65807DB57CA7440E09921C40179 +:10850000FD517897C62584E1AD1EEF0C3451FB6E0A +:108510006A9CA43D0F382A200580AF051F7C659911 +:108520004FBBBC6C357A35543FFC58E3B903FAE9CC +:10853000B8E71DB4E7CFE8FDB94DE628ED7AFF3383 +:108540008F4BE1F6852FC85E3D9533AD818E5FCCB4 +:10855000A674B938203B61C8C5F7FDF9BD91602705 +:1085600007744ED8AF523B61BB96CEFB8C86E1932D +:10857000D42BF7FBAB38DEA9BDA42523C2F249E812 +:10858000FB95C43F08EC8225C4A587F2D3BB574CAA +:1085900023145ECBCCEB516E5D5C3B05EDE0E5C496 +:1085A0008BED4BB6EA3E8DD413CB9A94F5153B94E4 +:1085B000F5953E65FDD24F18BDF5A67B665F259407 +:1085C00047B71B1EE17479491FBDBD318ED169F9D2 +:1085D00003D31E47FE0FE88881D2C9FA83A5492438 +:1085E000CAFBA2ACBB924D7C117A286C57E412DF17 +:1085F00070E8EF2AFAF9A01FD8BFAE37B992609F92 +:1086000071A92CFA3CFE778FDDD2AF8F7E63B1DF8C +:108610004BD9D75F67DD1523BED7FB7B33F64BED18 +:10862000A7A8DFEFE670B81417BDDDD7D37F32EA15 +:10863000C5F0778C0FC2E3A4A15EADBB6255E8E93B +:1086400070BB9DE955BEFFA778F5A2BDCBED39AA59 +:1086500010ADE763C2724CD78FCD47F0CD671231B2 +:10866000A6A0BFEC612E479DF960F77E067615F057 +:10867000ED24C71B413AD525F78ECAD56687F94A3E +:10868000BD1E4A8F5F0623EC82B6388B1DF5B99369 +:1086900038615CC10F0BEEA9E8EFA178FB8FFBCA34 +:1086A000933C4323E9CE8BE3D7EA853D6756E871D7 +:1086B000A2D2F34BDADE417B6DA9D19D0BC2E94F0B +:1086C00007EF413E594EDC89C01F5D07076778FE02 +:1086D00007FA5DCC67A677918ED9E714A8946F67E7 +:1086E000F0F9CC6C67F6A2C6E8D2E1382EE2B026EB +:1086F000E2169CCD970A592DAD8FED993F3813099D +:1087000019C3E72FC1F714BE637949167B9261DE66 +:108710000618978E6722BE64281B47391D508E9716 +:10872000DC5A360F1FE27922A94F83F735C6A0CC59 +:10873000D649679008DFF7C00BEB165EDF7C67F762 +:108740008265F0DC6C41F9A3E7F3F846C84D2331AC +:10875000C2BA0D66FF4558978597DE32667F7BB3B8 +:1087600089B391BED68FB41018D76CBEEC85C55AAC +:10877000895582BAC9DAED877DC865ABD9AB198650 +:10878000F2F4FFA03C95DE5D0E78A1F29BF9A5FA0C +:108790006AD7FA71FF23E4631C9F5F23978F2984B4 +:1087A000C1C14EDC875C94AEFFC5B27C1A89053529 +:1087B000EEC1F177C64E3E0EF305C0A39E9FACFD01 +:1087C0003452CF24B8B50AF99754A5ACA77894755C +:1087D00023396305FA95FCEEE46BF1B8AF1B027E1A +:1087E0001A1D973777F663F312F49316AF51D82119 +:1087F0006EBECFAF8DD313F40F261A8D6418DA2511 +:1088000069F1CC2E394B314DF7832194E705E35DB7 +:10881000837E41E1BCE503D9B989E2698BC5B151D9 +:108820000BF6DE1CC9F92C92678B1FFC3ECD0B6C3E +:10883000CE6DD06E72FDFCFF40FB0732017BAB0EAC +:10884000FCEDF1F0A2B514BE6BCEB0E27BF6F210F7 +:10885000FA49430F12B4A77AD1E9553A7F0AEF5F7C +:10886000429DC2B76EA975F58BF4FD14778C538ABF +:1088700068DF0DED749E12A70B783E7E04EC6BD979 +:108880005F4E7B41C0057E0B978CFAB0AEBDE08891 +:1088900099CE23C753E004B21DD8CEE32A76838F46 +:1088A000C51528D7D279CC32B279D4B597DE514CE0 +:1088B000DB07068613882FC41C77CCAD81260DDD1F +:1088C0004FC3776531E8CF3AC9FD4A84CB83912AFB +:1088D0007E1B1DA67F6C2F10756A36B84630770553 +:1088E000D6ED8C0F9C44FC31FEBC9584FFE0FBF27E +:1088F000707F288F26849BC3FC469756687436D6B3 +:10890000D0F7DEAA9C84745807FB2E8A8F915AFFF9 +:1089100021E0EFD1BC2CE02559DC84F0DCB6D17F1E +:108920005897052E14B70CF511D6071BA1BFB192AD +:108930001FCB8CAA871B81AC5E03E30CED4E4F0569 +:10894000F0E3960A6205FBABB1C4E9B4D2A6D955EF +:10895000CCEF3AABCAE8033FFE2C2D61F12EAD27D8 +:10896000EB4794AF7E348FF97BA13E2FC29F22E26A +:108970001B27E93E666F147BE0B578A6C7C4F77580 +:108980009BF58A38D2CBF1CCBFB5337EE24FE2D92A +:10899000FCB280FFEE8BE77265081902722582EF48 +:1089A000BDF05E47E9EFFB920BCA762E1766B91E43 +:1089B000D1A11DCFE58390C36EE043FA5D4072E91B +:1089C000007E1F9731F89F285D89F26136F1E073D0 +:1089D0004A203A77A41F6972843D44C799E556DA64 +:1089E00047B3AB947541AF62DC391E65FB0C61DFA8 +:1089F0004E56DAB7F3FEE9AA0DF56FD2736BAE658A +:108A000062DC04F7FF75144F2C6EA2657194CD7A69 +:108A10001FD849756D77BF95007C741FE17CB457F2 +:108A20005A3A14FDB0D2B2083B62408D4F02B93FB2 +:108A300098AE2980780D61BCE8A4CE7708E228279B +:108A400057D215D3791ED1B378E45113F1823F5A2E +:108A5000D0A76506F3A75232C6B8489A35C609F4BE +:108A6000B4555388FED7ADB11667A4BF73DB464A31 +:108A700077117E578781145A39DD44DBFFBEC9E583 +:108A8000E16312F37F7BE71871BF9790E356C41B35 +:108A90001264721AFC883F897788F7D1CF01F1BA46 +:108AA000E1B4F449CC9EE9F95E269BD1EFA8923F50 +:108AB00009F14EF4F727F4CF43BF7D557BC16E9487 +:108AC000376693739014EEBFCAD3AC5D06FE83F68F +:108AD00066ED527398EE4E00BD02DE62480CD06B1C +:108AE0008F1F6F9F01FD783FD6B83F02BAACD1FB14 +:108AF000F389929EF1795F7A6C05A7175D997BCE19 +:108B0000323A9FAEF7F4CCAF751F417E7D79BF0D31 +:108B1000FD90DA1904F5C9E65282F4D0D52CA1FDF6 +:108B2000F685AD1AF7019BA526D4139D7113117F0D +:108B3000ABCC47715F5BFD94EED348BB6BD56E65E4 +:108B40007D3509E0BEBAE6C55EF48CF24BC8C7DAE3 +:108B500056E57764A0523E1670B95FE876CEAC80D9 +:108B6000A9573973D8BE9AF80D741DC5EFEAB9FF3D +:108B7000771ED39BE43909ECAD2ECB0599F13993DF +:108B8000C7C5BC3FB51E2AE6F6D4382AB760FF2910 +:108B9000EC23FA3ED68F6ADAE5644D785E45FC3BFD +:108BA000619709B92DF0525A424809A5FB643B97D9 +:108BB00043D9241BF04AFB477EA0E37AF571D8BF66 +:108BC00017F66DA3F97814EF5ED0B35E8DD10774FC +:108BD000B445AA47396D245C5E4B1E94CBAF79BD7A +:108BE00032C07514A99F398DBE37C61888017850D8 +:108BF0007A48B32784E9A491F833F64A0A7AC1F691 +:108C00000EDBEFA3D28BD02FFE8F997D3195AE185E +:108C1000FAA980400E2D8F4A6C5F38C9FCA816BE99 +:108C2000FFBD660AD2C364E2D3C2FC2AAC4A3C4F01 +:108C30004A56D6A7387AD1810CE3BA383CA70E51F0 +:108C4000B6BB845C234AB99645AE229EC983C77ED3 +:108C50000C7E81980D6408D81DD442447E53CB838A +:108C60007176B3C23E8A88838CB317F78E83747192 +:108C7000BFEEAD24B8FC45A937BD74BEB5414E8EDC +:108C8000A02B41C7AFF3BC09E94D1E6F2D62FEC09A +:108C9000B09E67F43282D76E057AA3EF2F147492D8 +:108CA0004932814EC6B699FC32856B01EFE756A07A +:108CB0009BC2B03EF76BCC0E7D36D08773AB2CF7E2 +:108CC000B6DB13E31C4827C3352EA49362E28C075E +:108CD000FC94185B1AB530FFFD230778CC0ABA580C +:108CE00062473942E902F9AA975E54B6ABE846E01A +:108CF000EF38B7972711EF40188F8AB1A3602FFB89 +:108D0000B318DD541017D2C9DBD953783CDAA3C5A8 +:108D10007E88521F961B9574A0A62B3AA226725CE1 +:108D2000359DF54537994037421FC6DF986EEEEF07 +:108D30009B6EEEBF1EDDA8E945C893BD266B39D8F2 +:108D4000A575D512CAE1E1EF0D6C84FAE0355998AA +:108D5000D7B2D7E644BBB5AE9EB517055C32E4BDCD +:108D6000E4ACE7ED59EE72A8D76D60F187E2932C81 +:108D70002F66E07DACBD6053FD110BE8772FFBFE45 +:108D8000F58B5BE458DAEEDBC2BF2F6D2A877ADD04 +:108D900056F6FD17103FA2F81D71DAD708CF6FDA2B +:108DA0009EE564DB4F66CF8EE774BA57DA7704BF6F +:108DB0006B62DFAD3866EC47D00E6676EB38BECE20 +:108DC000F14FB175DA3FBB6DB283D2EFB29017EDC0 +:108DD000A6F39A9A11286FFAD867964A4D695052AD +:108DE000BA4139E33252BACE66F1C55D7488437632 +:108DF00066078AB81CE40944E6051CB233FFA37871 +:108E00002F318EB038F21316F4078BB8A1FF712200 +:108E1000019FC11AB9FE8F1A479C94538FF1C34921 +:108E200099227E18D42EA6E3165CFB6A62347FCAB0 +:108E3000713EEE059EF7209E57FBB23440177B81B2 +:108E400048520148AB7F0776D35EF0BF32A5E125DB +:108E500025805756FFC8BE62DBD6340A5F4DBDD6AB +:108E60000B4A2683EEBF68D7D303C4DF3FB6F7FCB7 +:108E70002769891FF413D1B2F92F6FA47A500ACB56 +:108E8000A55942EC8C19847C7A27C7D367766E6F1C +:108E90000C27C341DECCE278FB91B15EC7F4659349 +:108EA0004EC5FF5F20FFEFECD36E56B6ABE4433503 +:108EB0001F7739B797579210DA05E7251F9617766F +:108EC000327B79B5F924DA155D4F303BB18604D198 +:108ED000EE50FB0F57EF51D6D7B428EB756DCA7A19 +:108EE000579E17C7E9DAB96604F8EFAA77BC877E00 +:108EF000E16A21277C4A39410D2426271EBF19FD2E +:108F0000361A2395134500AE7E9847329CB8E2414D +:108F10001E8092BD46EB0FC22729B4AE711B1350C1 +:108F20005E4C8EFF5C8C2F639CF63D97238C979E46 +:108F30007DA14A4E14087FCCC038F45709B951C0FE +:108F4000ED123259BD6F7C14F96F38AFE52428F764 +:108F50003DC2CEA0DFA39D11D0987D1A4DA45DE146 +:108F6000437E2C34523D812CE434B2FD4A1351E14E +:108F70007730ACEB3AFB2665BB0AFF62DF3282E357 +:108F80007F0EF10C007CDC49DC6F817E38F171B51D +:108F900062BFF4F11F270A7F0AEE9BBEFB7EC9FF6A +:108FA000BDF64B3D783751FB9196E533A60CFA059B +:108FB000C4BD5B4D98CF5927313C27CE399911E973 +:108FC0003F3CD14012B4117CDF38C56084F860A307 +:108FD0008EED27664CFD64C4E208B9F192B1746A63 +:108FE0004231E021F0937F87FDC53B32C17C99F689 +:108FF00004C47B77137D4EE9ADFBA95B9C5EFAF858 +:10900000928EC51BBF90EA97438A9398C7F20DBF13 +:109010003369A91E5B21FBDE08427C55F2BD5A4331 +:10902000DB4EE93D73A0FFD51ABF9EF9ED0218276C +:1090300015FDF7ED87F4A2BED31F667A3124F573D0 +:10904000323FAE373732DE5495C8F657EFC7B9977F +:1090500001DE85DE13F18433774FEA0FAAE16BE27C +:10906000EA0F714E490BB1A7DEE341BEC0E608BF6F +:10907000F21953F4B8C0DA04265FF7016FD1FFED9F +:1090800036D73A18F702DFFF5DE0F1AE0BB12CFEE8 +:10909000F5BF7ADE67E5A309CCDF7D81C7C72EC4A3 +:1090A00029F78DE2BDC778F97983D1B839029F8E4F +:1090B000C70DF53ECC93E27921EB09DB27EDB735FF +:1090C0006F8B8887362794EE837925E4B8F42900DE +:1090D000BFFD4C0F433C1AE2C64556CF76C04BADA0 +:1090E00083B820EE4A1C41FD4C883FC2BE13ED07F9 +:1090F000462F5D26568A79352754EE83EFBAEE0E59 +:10910000223E7BEA954C3E3627B871DCAE59A29DD3 +:10911000D71F0A72FC33FF81F067F7150F53C7BFE3 +:10912000A8E26076B689C93175DC7BBE90633CEEFF +:109130003D8FCBA1F9EDCC3FBEC048B60CA0ED0BE6 +:10914000DB93D87E31D69BAB887B7B63BE531E837B +:10915000A0CFAEF4404FBCF6898878ED1A1EEF5BC5 +:1091600023D6D7AA5CDF9B097DC66BDF4C8812AF84 +:1091700055E705BC0AFA7D60189E6BAD6CFD157253 +:109180004DB91EE4C45282F9E16BDF59D268A4F5EF +:10919000B50F82E70FFE98BDBA86C3ABAFF925B80D +:1091A00035C4A1F013F7238E887D718A274E51476D +:1091B0000B3822BF724075AAE2FBF4FA6CC5FB992A +:1091C0001B6E56B467790B15F59CADB72ADE1FD41C +:1091D00054A6A80FDE719BE2FD0292D31FE3B1C734 +:1091E00065F095909B7C3314EDB7ECB94BF1FD170E +:1091F000A4FEB131F4BD5613D303C4EB0A0CA57021 +:1092000059CAE79FD7B258F17DA3D432C24FDF5F6E +:109210001A60FEF6616DAB14FD5D8A9DC8F6113CC7 +:10922000FE584FFF6372DC21A33DD4269127A4DEB4 +:10923000F1C8EAF687B70C20BDED0AFA877A7E15E9 +:10924000D5F36047A9ED0C39D16247FD904A52AF82 +:1092500045F055980ECC6887753F25A33FAD800C2F +:109260007E7C0CC247477C8EDEF8EA26CCCFD3FD4D +:10927000A2C509FEB215EF2C41FA33242BE9C0E454 +:1092800050D241CC10251D589C4ABCF72F51E25DAD +:109290000D679B4B4907028E02CEF193957421E036 +:1092A0005B42FF03F81692D031CC9FF6494E3F89BE +:1092B00012EF6D6BC675DCC86ECB53C173F8515796 +:1092C000A319E1C4F2A9849D64E0FE69B5DF5CD80E +:1092D0001F6313B9DDC3FB117EEE2D9217ED9C9E2B +:1092E0007856893FC39F05F64E3D61FE127769624D +:1092F0004254BF1A3EEFCBAF26E028EC99D560CFA1 +:10930000D07196110FCAA5CFB93DB3C2FC28C605CE +:109310002FFD91C1B79AF8505E7FD77839D889244C +:10932000C2DFA886A3D42EF92DC0075C6EA7927663 +:1093300021B73D983741C9CE3842115F50DAA1C4F8 +:109340002545CA2761978AF1043C85DC12E3194858 +:10935000BD9C0C7CA092636488DA4E55FA3D849FD4 +:1093600004078B88638CEC894FB07D62D8EFC5FC15 +:109370001C7266562301FBDB2AFC1A81B9F05CF8EB +:1093800035D4FBFB1BC545677AA5E09359BDE3A126 +:1093900022BE4A97F9D9BFD38FC7488E74186FC6BB +:1093A000EB831388269A5FCE79FA00ED47D684E2E4 +:1093B00023FD65C27FFDB614C479FF88B8EE27117E +:1093C000F6422D699938370BFC9F546FC542C9FC92 +:1093D0003EA44D6D97B278A286AE04E87B358988AD +:1093E000176685DBB12EF7AE8B3C971BE97747926A +:1093F000559C5BC965ED4CBE89FD5B5FFB2511CFBC +:109400007F4B4F615218CE6B793191EF33F3493E68 +:10941000F44FF9AA2511F7E7940FA548BEEBC983CD +:10942000C1F65E7CA75ABF88E7CB9622F4BB2C8995 +:109430005CEFB78087B023BEA26B83725BA203CBC5 +:1094400035FDCE7CE482E6A24046A4BD5BA76779E9 +:10945000C1A445693F9F4CD47078B9E46F03A7BE9F +:10946000F1C0F3C2381EBEAD3D24F2C204FCFE289A +:10947000E46018DE671572AC67DFD603EFB3D1E4A2 +:109480009C80C7E5E2C0738027D9723211E0FC5797 +:109490008BFB33C04FFAE9E0794903FAAEE3B92711 +:1094A000417FB5C9B83FAA1DCBF2836AF763B09C70 +:1094B00074B61B301E58DD7604EDB28E062A4007C6 +:1094C000F60D9F9E75AAE0DCD73E45ACE3BF557410 +:1094D00026F244E8FAFEA6A0A7DEEBFF5B347A137F +:1094E000F94915F2D0FEC188FD483BDFF798B46E0C +:1094F0006D12FDAEE8C3B458804B85DC7E2C15E0C0 +:10950000B05EC2F347E30DC40B7EFE147E0EAD24A5 +:1095100058EFB4527824A799F13CD1E01FCB6E8864 +:10952000637EB27E5DDC125A7ED94087A6FB8DC178 +:1095300092C68D7446F69DFD6911C4D7E661DEF1D1 +:109540007C038BFB67FD24C69F43E5C39B7A6204C3 +:109550003ED365D7E3798B904DC67D865D2613801B +:10956000AE049CED316C1DE279E9D3BB25C86312D2 +:10957000CFC7378686AFA5E539C07771789DE3CB35 +:1095800043C3EBCD61388BFC40A20D65CC88E08BEA +:1095900037393C6A13F45B400F761AF9FE8FEF03FC +:1095A00089558BF2633D8FB39F194477A2D88FDF23 +:1095B00002F958B52657FF91E0E7823C025A7C6DCC +:1095C00075F5B7E1FA1D682FAFE7765527CFDB5E5B +:1095D0003FA52C09F6517DE53D952631FBBE86C79A +:1095E000BFC5F31AAD1FF3956A20DF3822DFE9BB50 +:1095F000E61B8BFCF13EE160D3122D8543AD44DCCC +:10960000D77BEFC0DFE4A8FBDCEA24CD75F3DF16DF +:10961000F2F589FCB65AC86FA38FD6EF2F4D2251B1 +:10962000FAEBD133576E55E49189FCE8DA2BE3303D +:109630008FACFC810E3CF707FD38CCE1FCB6BEE0F8 +:10964000FC66229B472DE4850D8F7CCEE446B87FD7 +:109650003BE2E1570040F073B4C9E88FFDD571CD0E +:10966000E45D51E6FB501283CFCD095AE48F5BFCD9 +:10967000C4D51C657CF19E38170270AECCEB3DBFA3 +:10968000D6B2E002983FE4AD461BAF2189EDAFC5ED +:10969000BC5BE382CB399DE3B98C9EBA5589C77F09 +:1096A000E572BFF5B660069E2F9A123D3F5EE07BE5 +:1096B00084B65E0278042D9E03686FCEA6956190F5 +:1096C000D7EFD7B0FC29C6677DE13D0C6F8D229F97 +:1096D000B037BCF58867D19FD88F5CDC2163BCFFB5 +:1096E000E209CE97C46596287F2DE2FAEA226171DD +:1096F000838B4D12EE43167B08D940E5CBA2DDAB40 +:10970000316EB3FCD9E15B404DC1F3FBA81C599409 +:109710004CC8385A2EDEAC8CDB2EDDDE2B4E4322BD +:10972000F522353B715FBDFC51E577D564FB7F8247 +:10973000DD53ADB26B06733FD7BE249ECF37828C0C +:1097400000F9BEF6D9AFF490B2DB17BD7F49F97AC4 +:10975000A016E4A015CBA349AEFD49141E1F26791F +:10976000DA416E777DC0E0D05DD3CDE4FE5376D490 +:10977000370610CEF49F86B92CFEFA001517107725 +:109780003318985D23EC39595E27C7D2F6517F5ABA +:109790001F07F8B3FF7AD264B0F7137E1DE3027897 +:1097A0006D2B7515C0FE7F5BA519F3188C0616F797 +:1097B000F5FD6AD46108030C6C79B80CF69FD6F6F7 +:1097C000437EF08F6CD5FC279E2BD93A8EE5B98964 +:1097D00071EADA2BF7C27C32EE647A635B96ABC037 +:1097E0001AD12FE1F6592D8759D7C1C13F1F4DF12D +:1097F000F8E471348FE9FAB2D10F773361F814F9D4 +:10980000543076A41DDA41F50F24E589FACD2D9266 +:109810005F47D7B3A6752FC62F6A36F913E7829E26 +:1098200079418BF11F313FFB9B296510E711FA65E8 +:10983000AE6445FD2FECEC3944FCB1385115A783DB +:1098400039DCBE9E1BC3E0BB983833E0BBBB8C2425 +:1098500016FCD373CB5B8A51FFACD6D940AF8B7863 +:1098600047DFF640743F51ED7316763E560AE542E7 +:10987000275FD27D0761FEA2A8E78D4CC99CCF72FD +:10988000B9BD3790B820BE56FBC6E066F00718FA9F +:10989000B1382C953BC69242B4778DB08F5979C0C0 +:1098A000E467FE6A1F3F07EB2A807C90BA1969853E +:1098B0009897709ACA0F0B9C2F0C66209F52B92262 +:1098C00051DD969D1C334D4BE9BB3695DA53B4EE12 +:1098D000DE91CCEAD9C1E51A5ADF905CC8EA3707B5 +:1098E000CF437D53F258562F0C2E9769FDE9E4A91A +:1098F000AC0E1B3B4A58BF4A9E31CD0BF6848DEB14 +:109900006B6710CF05D7BE3E5813E9A77C2C99C9C9 +:10991000A52FB9BFF5CB2CB27006C07B4810CF9DE8 +:1099200089F77E9A2CEC5B96DF2BD629BE23C9D112 +:10993000FB2FE0DFADE4E779C7C790AD2616A7F2AD +:10994000C652F81F6D1F8C71B6C4E438E68FB3D2CF +:109950007E8AC2FD08388AFEC4B8AB40AF82BCD54F +:10996000317FA9681F97CCE4381D67338E3394C1CB +:10997000BF76465A01E08DE24BCBF1A565FBCE6682 +:109980001C17FAB5E5A37C1F0EFEEEA357E9FB59A1 +:10999000E179ABE9632AA78F958D2CBE18B2E5203B +:1099A0001D8D8F61F61E2952AEE3690E87C7926D39 +:1099B0000C8E3DF84892709C460EC7340AF7BCEFF7 +:1099C000BEEEF93FD0BA23F0E592A1BDEDA65D91C0 +:1099D000EB11F9DAA29F2F37AABE2B617953B5712B +:1099E00039F8DD032662C4E76457CF7759F9CCCE46 +:1099F00004FB53DCD740BCE3D04950C3A546CFFDA0 +:109A00000B2D3C7F70A08B9D3F9E31AD88AFCFCAA0 +:109A1000D7673546DCBBD0C38F274319775A7AD333 +:109A20006F0FDC7BFA1B5AC8FB53F075B4FE803F06 +:109A3000FAC2C7CFFFDEF810F354C1B307CEAAF9BC +:109A40000978023FE3774395F428E6B92959E40BF6 +:109A5000ABF83AEB7B8E57CABE5B730FCF03762809 +:109A6000E9794D6B9606E2E7E2BBC9E0634F08FB7C +:109A7000DBF625F37D6B1A49EB23FFEDD5E4E87E99 +:109A80003A7CAEDEBF75D958DEB3DA6FD095E00C04 +:109A9000C0793EEF65763E7DB4CADE80F8CB3E737A +:109AA000F8BBB03E51D6E514C607BDFD40213C4F82 +:109AB0005B64287BD9E1A47B9DE4EA695A6A571468 +:109AC000F52F5B9745EBA79257A1BC2E1A50F65580 +:109AD0001695DF7F485ECDEAB7947D950DF51DABF9 +:109AE000D9FBE35D2F837C27DED5D326A484ED87C5 +:109AF000D3C90E849B5CAE21404706F96E27E84926 +:109B000001CFBECA2283A63E9A7D7AAE870E587CCC +:109B1000A284EBE712B13F0F6A15FBF3AE5876DE75 +:109B2000B80BF4295D6F47B2E77C32D829311D0BA1 +:109B3000B268579B62CEEAC11E925C5477819FC384 +:109B40006125F3209FAE639B1BEC23B2CA69D4222C +:109B50003CB9DF89AEED1AEDE7C01B2FDC3B800D71 +:109B6000E386798CE2FC5FF7C6377F81F868DD9782 +:109B70006627B8F546B5EF5C07F6D5A8F6DF7FC3D4 +:109B8000F42D3BA721E63D0AFC87F479499B01E7C8 +:109B90003FAAFDA665F0FEE80FDB73803EC69EF18E +:109BA000378238E83AF8DA00C5F90CF285F47DCE50 +:109BB00067F4C0E34FD478EA8FF030A624003CAEBF +:109BC000629E5467C2892D41B4D394E760A85D8E2C +:109BD000F1D56ED2CF097102718E5BEDAF3C5D495C +:109BE000D7479F8F0DD11944D8CBE3AFD0FD7D84EB +:109BF0009D5D4A6C8A7AB93145F17E85354BD13EFF +:109C000029F92645FB144781A23E75C828C5FBB734 +:109C10003B4B15F53B4AA628DEAF74552AEA05FEF4 +:109C200016C5FBC38FB729DB4F3A100FC3CFB8CB94 +:109C3000C18E77063C8D508EEC682AEFEF20BDFC7C +:109C4000B445415F233C1F7DB5BED84FA29C5F59F0 +:109C5000E541FF7EAFF32BA5EC7C7BA7869DDF1053 +:109C60007ED9AB319EB180A7B7250A760AEC71C6C2 +:109C7000503CE0AB62E143982FD51D22E8CF6AD576 +:109C8000077F361AF4FC7C19EDDE569E67D35A9591 +:109C9000E7035FDE6929F82AC4E9BDF3D9F980B189 +:109CA000D4C2C575434C53023C7914EB2E252B5579 +:109CB00078BA5B51AFB0DEA3787F52F24645FB1411 +:109CC000C7832A3C3DACA8DFEEDCA9C253B30A4FE0 +:109CD0002F28DAC77E1E6C04361ADFE1952D74FE3C +:109CE000B79E6E2A07BC8C3EE39D0FFC52E4F7340E +:109CF00082382C3E5A7F044A3FDD4F819FEA7043F1 +:109D00003296471B1CE8673AD63004CBE30D4E7CF5 +:109D1000FEBB86122CDF6D7061F96F0D93B10C34B0 +:109D2000B8B16C6968C1F7F735B4614921980EFA8A +:109D3000C21EDF73AF423AECE73B35C15A88A0AE92 +:109D4000DB7900E56467BF6027D43791D7A74D80E2 +:109D5000F35CB09902FB0A4A8ACFFB525D7F49A1AE +:109D6000F54D29AC2EF2125A34AE02B0AF1FD8799D +:109D700064BB369D90FB37BA93AD365637D23A2244 +:109D80001BFAF01ED9EE4A23E437A0326EC5FA342E +:109D9000A8779958FBA69D47A679513FB0F8F19D49 +:109DA000E1F8F10330AE3A7EFC9B0B0E0BF8534EFC +:109DB0005C1D6C81759DE0FE231729D02DA265A93D +:109DC000B640077AF1B4CA8E10659DA6B409FA6D43 +:109DD000D13867615EF06D3A0279E83324B61FED41 +:109DE000B10353991CEFBADD80FB9D931AD732CC97 +:109DF000779242CF00BCF6A49C44BDD265096500B1 +:109E00001C9E4BF990D51342CF48CE88BA8EADF345 +:109E10005F534EE03E22CA3A77A7448993BF90C26F +:109E2000E3067E573A9EEBE5F59395AE35A0274EB7 +:109E300096BA06C17C4EB80DC83F5EB7C507F99605 +:109E400044EB2A9E15E157C949D5E17777EA199F76 +:109E500091BBE4A8E7CD4B53999D857883FDDC9CAD +:109E600018B4C34F6AA29F179F93CAF4F5A57ED179 +:109E7000FD2B77F1F6B29916ECAF6BBD09E3B75D38 +:109E8000EEC1680775D5532851FEE8BA507FF91521 +:109E90006C3788D016C629E77239F59BF6757F3E78 +:109EA00045DF3FBB3EC68932DC7A33EAA7BBF8CB3D +:109EB000F3E38D68B7CC9F915E067A692E8F772D7C +:109EC000B0681331ECA5B5E9E18AA0A5E6822DA022 +:109ED000FE97DB2BF5365AAF4EBB7B0B94AB063EA1 +:109EE000AC87239A3543F76E01F3710D65AD62DCE3 +:109EF0002F05DF6BA0F35AB84176B0FD933877B8E1 +:109F0000FA3BE557083A3CC9F364287C715F38375F +:109F100095ED7BC4777339BD5D4CE1765B1EC9BBA3 +:109F2000A68CE35C063AE998FF5E6E1F7E77653B80 +:109F3000B7DB3ED2B371D5F7508871E771BC9FD4BF +:109F400013970476DC5D16A48FFCAAAF3615D3F503 +:109F5000E7B75B35188717723CC0EE032BFEDC8336 +:109F6000726E6447F0B95304E9BC0DF8E4467A6AAE +:109F7000A67723EA87515F53FD0372F1AAE7EC2924 +:109F80006CB5473D8FE96FA8E6F2B11EE5DAD186E0 +:109F90000D583FD6E0C5F278C3562E1F9BB0FDDDAD +:109FA000861D5C3EFAB87CDC83CFDB1BAAB07CA3A9 +:109FB000C183E55F2DEEB8D40420360FE667BEB549 +:109FC000D340E0DEB4EE7603D229E580679EB44349 +:109FD000FE8BC10AE7EED479306A79DB83FFD65E67 +:109FE000F76164A41647E4BD807D96D937FD9C20B7 +:109FF0000E0BC893114F24DD0EF2F984C36101BB2F +:10A0000075646A32ABBB1C161DAD973C41EB54BE68 +:10A010009CF0382C065A1F959AC2DABD0E8B89D651 +:10A020006F7D2285B5FB0806A9C73F91713BC89F8C +:10A0300052221D057E2837664D8094D90A6BE9515E +:10A04000E08349C98B26001FFC36C5817438C5B131 +:10A05000F128D4A70E69D6C2511B97B960337C573B +:10A0600066AFD4C27713D2EEDE0CDF4D1CF8B036EB +:10A07000F2BBC943F76E86FA3467B316ECC1DFA6AC +:10A08000B0F3FDA21F5117ED42BE8A3CAD61ED6EEB +:10A0900094E3F96D6E94E3022E657756DE0F7EBA77 +:10A0A000BA36C92AC13CEE947A82EF900B577B9561 +:10A0B000720B95B3D39FB8C9B291F2571DD46FC537 +:10A0C000FA431BA3CBDD99A951F4CB1F389F82DE45 +:10A0D000847CE83FE8D97D1E2FF3F5D5B52FB22C4F +:10A0E000427DE5B1807EDD9FC2F4E541AE1F2FF3D6 +:10A0F000B29B3FAFD3B8E6C3384B53FBE4EB6A687F +:10A10000A77CAB3A27D0473BE7EB55A95C3FF07BF8 +:10A1100013D610769EE846F95A2B23F76F5990977D +:10A12000D3720CF245D5F90F3570CE28A7771E30C3 +:10A13000958B2CEFB14D993FDAB3FFE8C7E41E1CB5 +:10A140005F844D4763DFEB7E2035E1BAEB56B6F313 +:10A1500075AF242CBF59BD0EE24940DE12F9CEBDC9 +:10A16000D7138CBE9E5EEBE0F7EEA9F2ACA91DF40E +:10A1700038CCA762A18580FF26524E9CBA8E9C5097 +:10A18000CB9DBF973CBB8EBC79319ABC11E79DD566 +:10A19000A5B0E7E09C14E4DBC17D2FE0A7FFA74456 +:10A1A000CF6BD04F5759E82F1AD89FD9834867767D +:10A1B0009BE775782EE959DC5DE4B15ED0787F0BC2 +:10A1C00076D1B12796A01CEA04E540F9F10D5A07B3 +:10A1D000B9536475FB017E6408A39FBEF233DFE6CA +:10A1E0007AB177C9F849E42976357F93817EAC1B33 +:10A1F000D07B5F70A890C704E13C4077490C9A3C43 +:10A200001D12F14B85906F9D88764447BA5E0BE531 +:10A21000DF7B9FD8919E8BFDABF78B1D29254636A2 +:10A22000EEC4C950B6E93D3B16C13E699401F749F9 +:10A23000EFF3FCBEE99F5EB583BE9A2EFB13F3A538 +:10A24000DEFBCC8E77E69539F27BEF37E9FA26C054 +:10A25000FA6EB4EF741B03710046F5FEB366C35F7C +:10A2600008E4458FDE7095C07D6437DE8F1219C417 +:10A2700044E169E711288B3F77611ACE880BF547D7 +:10A28000A01CF535DB9EDF289FE8D62B2D47D8F1A3 +:10A29000F0A1CAFB164A7ECFF6ABBCEC754FDB2AA9 +:10A2A000AF324FADD45F8C7914723016CACB5210D6 +:10A2B000FD5EB286DDC320EE5FA0FBD8C401C5B051 +:10A2C000EF65F952E321CF884EAEE2A71F2FB817F2 +:10A2D000F9DE84F64FCF3EF6150DE609B46A5DFD52 +:10A2E000C7C23E76C320E7465AFF8F40C22F0ED02A +:10A2F000B2CEFA1712797F5BCD866E45BD6363F8E7 +:10A300009E20C883AEF99B8C7AA78690AD80AF1A49 +:10A310007258BF36420F9296FFEC81FB302AE72A33 +:10A320000170B8AFD24C77D1F72AF97E83781B59E8 +:10A330009DEFB308F9EC7617EDB73281BF4F664F4A +:10A34000C77ABA68AF62F541A2BFD7D8FB29A2CEBF +:10A35000FBBB49D47FCEEA59E2FB16F67D9E18FF7F +:10A36000BDDBB1DDC2DE1F3F60FD74900342BE570E +:10A370000CE0F925FC7E1F2AEFA70C48B86E5E8919 +:10A38000B29DEB03719F4FC54FA7C4BC07FCDC22F5 +:10A3900061EE5BCD7D3AF46F5F8A6BC98F3C9F2C79 +:10A3A000F250DCE51617D87B6B5E1DBC4BE6F93826 +:10A3B000606F6CE3F1E50AD98CF188EEED4CCEF7D5 +:10A3C00065AF2DDFF0BA029FBDDAF93DCA18A8A328 +:10A3D000E35D7E2809F3DBC9C000C6C3570C90C4F7 +:10A3E000F92A3CDF2AF2BDEC39C405FB53FB6B268E +:10A3F000764FE5E70194BFCB5F63FEDE353B8FA070 +:10A400009E5B2C3B908E0F6779D600DD765AD87D07 +:10A4100084CB37BC81FCBA2193DB09D6D050053CF4 +:10A420007BC3FF9E1BC0FF9E7F24FCD57E66713ED2 +:10A430007AD577CC4BEBB4B038A893E3E9538D636E +:10A440000487D723B09ECBCB02B9361992860389F5 +:10A450002CEFE8DD62D80775D75BF09EA379EB3E61 +:10A46000C98F3C97224AB5FD7F0EF8A8380CAFE69D +:10A47000DEF07D16F0731DF82ADB7F60F826698315 +:10A480007A27C44D4FB37BC746043ED547E6BBBCD5 +:10A490003580E9DDFEFC1E6A75DED65B032C0C4FB1 +:10A4A0003C1EB366C6BB63201E23F8617C0C6901A9 +:10A4B000FF3AA56B27A76B27D0B5A0DF705C867E1F +:10A4C0001785BFC2F44B147969EF0E50DE0B46E1DD +:10A4D00016B801DD06FE9174DB4AED5F8C63BE6247 +:10A4E00042FF891ACE5F71B80A786BD3AE0F676DE1 +:10A4F000DA0F03676D9A43E17F10F0EE4B3FA9F14D +:10A5000023E61D854F8BBF0F9F36A67339A50D62BD +:10A510009EA81AEF3169BDF0DE3FEDFA7857B6FF1D +:10A52000C07857C34D5DD6F0F8A6FA795E9A88FFD9 +:10A53000FE3070FCFFCD7F3EBFFE90A27DE18677AE +:10A5400014ED8BBC1F28EA638281722073E10F1F18 +:10A55000772184F6E5F7F5ABF7E54F9FFEF20A0D9C +:10A56000C4DB4A02CC9FFF65BA67531A85F3FB1A16 +:10A570005FA385C275E49916766F57752EE60FAD09 +:10A58000E373FC6ACC7F9DBD97D2CD57C480FE4E4D +:10A59000FFA19BB48EBCDE74507A45435C11796890 +:10A5A000A5469BD685FE1AE28A46370F70BAC1FCD3 +:10A5B0001FCAEF5546A2B3533EAFAA9230DFA98A15 +:10A5C000B07C685AFA3DB47DBA96F8E1DEE34AB34E +:10A5D000D66FC0389FF23CB381DF8B4CECF18A73AD +:10A5E000CDB24BC6BCB459252C3E7897B905CF9354 +:10A5F000CE39BEE9F2BDB49D6CF616B37C6B71FE2C +:10A60000EC8F9AEF12F77B208DF17997C4E3C89213 +:10A610000EEFC7527F37378DF1D97479A30CF92E1D +:10A62000A10F08DADD82EFE8FA8E1B0AD9F90AF8E1 +:10A630005D8A4AA2F30FC6F3CE0F97C3FB35271DE1 +:10A640000897BA928DF980C7BA09D239437E785FEC +:10A6500053B7E16BECA7427EB111DEEF3ECD5CE17A +:10A66000233BE83EC511E9AF0C2E00BEBCD1FE472E +:10A67000CCFB4C831FE9E96CC3712CDF1FF7FB6235 +:10A68000B033820D81A87EC9EFEB1F107E01E12758 +:10A69000107240DCCBB7378DCB05A33400EF53D31A +:10A6A000B252C8CBD7D27AD92B076E205F0FFC23CA +:10A6B000E5EBB7A5F39A64A617D5F4ADA66B41CF29 +:10A6C000709F37FC1EC15DD4DE03BD3A9778F36AF4 +:10A6D000A89CAD5AD1A41B2D7D7FBA5E65FE3C833C +:10A6E000443967F2DDE5B983E54796CBB83F10F909 +:10A6F00009020F9DBDF1D69D767D3B53D9FE0FB764 +:10A70000E33F5FF0FDF41A51D80396F45EEBB6A573 +:10A710005F7FDDCAF61F78DD11E75F16C89AF07912 +:10A720000FC81F063BAECBC7CE33566735E13DF2AF +:10A73000A424140B76E3CA8332D221D1BAB42911EE +:10A74000F74D7510FF47408F2BC6ACC07370BDEE40 +:10A750008932B7E2B938F57D51225FB896F7A3BECA +:10A7600037AA96E709D7AAF27646A4F3FCE042524C +:10A77000C8F22B9476A9BAEC6C200ABF64E7D50620 +:10A78000F4038C4B6FF999372D8C8709E9BDECB830 +:10A79000C937C0DBE47F24DED4F42A5B76E379A8F2 +:10A7A000EF4AAF57335DF3D313C272781EE47015CE +:10A7B000C13DEE061FDCF72FEEC7EE92D87D345D6B +:10A7C000E708FA8D6E74BFF2A8931E3CCF39F25D94 +:10A7D00097CCF20858BE81B05384DD32BA2324B33B +:10A7E000FBEDF939289E17F46DE5973360453B473B +:10A7F000F8DFFE5E7E6BA1E70E1A995C13FEC1A224 +:10A80000A01BEDB84E9DBF18EEB3F7EE3745B5036C +:10A810007E96AEB9EE3DAE7FB5787E06F43293CB30 +:10A8200077719F6B85CCEE7BEE0EC8E8BF5BFFCFE8 +:10A830001FFEF649C78DF7F575D6EEA8FB2251D657 +:10A8400069D87989C27207E6EDC17E09FC77C29F9B +:10A85000A77EFFF5CC321FCCAF421E83F76B76EF9D +:10A8600060F3E90B2F751B42387E9FED7CFCBA83A9 +:10A87000C5D6C8FB30CEA5F7ECCFACE78D61BC7E6A +:10A880005BFC8F0D5529EC9BFFD7F70DD3656A3A1A +:10A8900052FD9827F9987D4A989D3A8F04B05C4004 +:10A8A00042587A08CBA75F4C9C582E256E2CA76582 +:10A8B0007A4EA5637E4B2811F3215FFDEB50A09BE0 +:10A8C000CBE3463741EEDC0F65A775153870FCAE5B +:10A8D00057FE9A01792D37E2FFF858D70598A73A25 +:10A8E000AEF16FA532C64F88712DCAFB4A7E4B026E +:10A8F00099C0E262DB12B390DFC2F22FA959C83FC0 +:10A9000088B7E69DD3B0FC909512DEE7DA16D42026 +:10A910006BE52DCBF2C1FD3C6DADAC3D6F8DCD2710 +:10A92000D17ADE28136BBFDBE683730FF34910F98E +:10A9300071219C7A90E11C0C936FE2FE736AB167FF +:10A94000839DB5ACDDC8F2F7497020C8F1FC3EF636 +:10A95000371332189F0FCB66727B5899D20FD18F65 +:10A96000B7AFCC2C5B960171D90C574C065DDFB0AC +:10A97000B8C0B6478AD02F8FBFB3F2C5A87B307E50 +:10A9800028BE6BCA2CB3C27B2F492CDFDC7B90FF27 +:10A990006E01092546DE273A2DB33C11DE4BCF2050 +:10A9A000DC6E8E0E57F83D3A7794FD9CC8671C0606 +:10A9B0007B2AF48FB37BA95E92583DFF19EB1D9B58 +:10A9C00087A20FDF0B766D53A66730AC63989E109D +:10A9D00033CCFF69836F17DA9FF519E08F5CF18C38 +:10A9E000410376C1C754ADC2B9927F6F3062F90995 +:10A9F000DDE742F91F749F0BE539BACF85F233BA10 +:10AA0000CF8572D91527251A42DEC970B9603D225B +:10AA1000DEA69EEF28016F31FE413D8EBF32D3830B +:10AA2000F0EDC1F77EE28378C84BB6506ADC75E87A +:10AA3000AD6F39E3E5FBBDE8F959C332D8BE36BF87 +:10AA4000558B7A3CBF2D18BB3CE2BDE9197A6CCF1F +:10AA50007BE5733C27DA69ED81AF4BA24B9EAE617B +:10AA6000F5E9CFE4227C5766BA96C1BA297FCF8038 +:10AA700075E4B77DF82F709E87F68F79045D52E8F4 +:10AA800031B4F355EB50C341ACEB255B601B7CFF4D +:10AA9000D22BD9B0122A6F08E31BA02329DA7A3708 +:10AAA000E27CEF30848AE09CCA1DD7E4A879C32BEE +:10AAB000334B11CE12D05B42049C38BEBE2F5FF7E1 +:10AAC000C4B3399D1271BF06C84E07E8A1ABB1608F +:10AAD000D755F2787D5BEBC0F7617DDEE33219E498 +:10AAE00040FA55F0DD0E8E1F51E61DD4BB014F2FED +:10AAF0001D3C3F10EE5FA5781908F7B16ECD18A484 +:10AB0000F02FE68DFAE68947ECF83EFCB21A95CFB5 +:10AB1000CD15904F32D778E82D58D27CEBB90AC8C2 +:10AB20002759982C1D837291236B22E491887CF71E +:10AB300025434A8F012B4D7356A23D560AC225422A +:10AB40001F941B63F865D042FFC42BEA9392072839 +:10AB5000DE9FE2C851B44F1D728BA25D8C3BCD3994 +:10AB60005CF1DEB0B85036ECBFE83AD8FDD7CFCABA +:10AB7000987797F7CAC9DB6EA1F5E9CFCDC2FBFE86 +:10AB80005EE2EDD3F795E3EF0B765178EAA92175F4 +:10AB9000A1E4C1C71E81CE54F67DCDC15F1E7339BD +:10ABA000AE63DFDFC0AE17F27575BBB118E4EBB76B +:10ABB000B5F3D578792583DF1FC2EDFEBEE8A58702 +:10ABC0001F2407A3177EDF969A5E20B394D11F2B14 +:10ABD000A79F60E7C0BEAB1CFB13C8B18873983D4C +:10ABE000A5CADF364CEF7C7F1DF8DFDF93099EABF3 +:10ABF000E3E7F396C3BFE5309D93A5CDF7C37D5240 +:10AC0000F4B917EC4F3807EAA2FD5FCEE07653CDDA +:10AC1000A1FB538AC2ED64FD39C5FBE43E698BA2FA +:10AC2000BE394B59DF5EBA25F2FBBEE4E1F21D8B63 +:10AC3000F41E3CBF2945FD3D57319F8AC326CCCF2A +:10AC4000BB1DF24EE8A3DAA20FB4106FBDBD0FFD1D +:10AC500029E4CE1C99D4476BBF92C1E28ED30E9BE0 +:10AC6000309FE5BBF6FB318525E60BBEC6F4E7C792 +:10AC7000FD03DA48BCCB99ACFFCBC50FFFF35F20D7 +:10AC8000EEB99F60FEE6651B93FBF9AD5F6834B4D7 +:10AC90001CD68FD14BBE35A8017DD2551DE385FC56 +:10ACA000FCBA9516CCEB1C961DFAC85840484CE6E9 +:10ACB000B69F1B29BDFD110E3346E8D32ED8E3D035 +:10ACC000BAFD5F1FBC6333FDF7D4C326BFE67BAC80 +:10ACD000C74E6D28D47F658CBF1700DD70BD02BEE6 +:10ACE000F3BAFB498F9E017900EB87FA6D990FBD8E +:10ACF000FF289D77DD3B8CBF21534EBD6F9F1BB15D +:10AD00006F274F31BE34D2FFC09E5B75B4490FFB35 +:10AD1000B91BF3770BE6CD7C5BBECECFBC211F9F6A +:10AD2000984AF152B79FDD33D1DD3E08CFB5F6A585 +:10AD3000BFEB766890FF44BDB35D9E0CF4AA3E273E +:10AD40002EE049ACB98A7B9CD68EFDAF19A027D7DF +:10AD50001ED4B2648FBEC6D9AA218E88715E7AC312 +:10AD600050CD7EA792CDBF4BE8E7837F8E2B1DCAC7 +:10AD7000CA8D51F41CD5CB3A3BE8E54AF67B0BA7CC +:10AD80000E269501FC4F49C4EFC073572CCF78268F +:10AD9000EB0E9E9BF1FE90E421DAC87B0EC53E725D +:10ADA000D6C15983C08EFCA875F1298A19B22833FF +:10ADB00007E96536F1A2DD7BCAE64E077FC3741E44 +:10ADC000EF3F650B75803C3E35364682F83DED7FA2 +:10ADD0003389B8AFEF94CE9DCEEE831079C5377F1F +:10ADE000AF7BDB2AE4FB4AA742BC7A1EB1C23EF22B +:10ADF0000E99D9B5E44DC69742DED549813898E71A +:10AE0000B4CC19EB3221FEBBE167B8AFEC819B9665 +:10AE1000FFDED3B7B46B7BF6AF7B24764F8993D933 +:10AE2000FBB5632EFD62369C73A3FB6C89CE677104 +:10AE3000DB21BC8747BDAFEED9DFFC0FFDA3BDF71B +:10AE400047EE87607DC2EFADDE27F5D8E5C2BE7B59 +:10AE500096E5B91F19FB78E76A5A5FFF6C0CC2F1DF +:10AE6000E233062FC8EF8BBB0CB8DFB918173AB323 +:10AE70000EEAFBF29C5E1C2D17CF7709FA5EA171DA +:10AE8000FC01F40EF99D0EEFDDF8E26903FEBEC78A +:10AE9000CA5FDEB40BF64F5FA43B7EFD22F8F77E5F +:10AEA0009D80F7019064F6FDED9C1F81BF1C141F6F +:10AEB000F2F316B41B56BE9C82F24BE0EFC2D326CF +:10AEC0003C077FF1F8CCFEE007EBD0EC65BF3329FF +:10AED0009BBD208757EF32A1DD47F49E9760FDE5CB +:10AEE000CFDF3E7B388CFF610281F574B5BF8CFEED +:10AEF000C7307EA3EBF5EEF61C26077AF42CCB9B2D +:10AF00005D18BEA7F915E87F0D11F720B2BCD94234 +:10AF10005962BF3BF950F473E0C73299BD5823FC26 +:10AF200025F1C4980C7CE821ECDEC78706E33DBB25 +:10AF30006733F9F96512E2E71D05BD9DA93D80FE65 +:10AF40001203CBD7EBE35ECB1399367C7FB9F16B61 +:10AF500085DFA476C315657D28FB1DE6C246C7F0D4 +:10AF6000BB69B98EC3F9BF92DCA7607DAB5A1E7E68 +:10AF7000F55D84CB533FF9238C7BDC8C7E1AF22E5B +:10AF8000839F7AFFB2DC18E271876685DD7B7EE7FE +:10AF90001F307FE4FC2BB7E0EF942D9603E7E17EB2 +:10AFA000AC4E4BE0ECBDB4DC77FC04E2453DDF5E2B +:10AFB000717889C9951A58C770C85F715FCA44BE55 +:10AFC00065FCFEE9B63C849FF0D3765D8CBEBF1273 +:10AFD000F314FD8BF989FEC57BDF707C5DD607F22B +:10AFE000412FFB200E11B1AECBB1817CF8295C5F03 +:10AFF0003ACBE7BE1C47EB117473A378CDFF055C19 +:10B00000F134E600800000001F8B08000000000003 +:10B01000000BAD580F6C13E7157F77679F1D623BE0 +:10B020008684FC217F383B10D2262447FE786902B3 +:10B03000E39A908822B69AC0B48CC138DA42293497 +:10B040008D97C086E8242EF5C43F819A69DD46A716 +:10B05000D2192618D2404D3340AC02E68256C8863B +:10B060005A77651ADD2274CB5A16AD2149195B85D2 +:10B07000D42D7BEFBB3B9C73025BABD98A5FBEFBDD +:10B08000BEEF7DEFFDDEDFEFDA00E26A15C0B3B997 +:10B090006F80A31AE8137667037C05CC4F56A6038E +:10B0A0004200ABE87F099FD7FDF62EE703580DBDA0 +:10B0B0004E2806B8CE776F130580E1DEEF3B550FC3 +:10B0C0002D5AE2BF590AC0697FE4C7CB00C6E9B375 +:10B0D0007832057000ADA3CFB840BF1AC04CFC6DEC +:10B0E00084D208F2B9E5F7687C25C02C8973DC743A +:10B0F000E3742114D23A9C97E33548FB5C7214E563 +:10B10000D9C6878B24DCF7AC18AF0021B96F1BAF11 +:10B11000B2E7C3DCD58D10A4E3E215612FC0E8745B +:10B1200011B80CA433E58492857CFE01F251E4331E +:10B13000EA84B63E3CB7A6898FF4313D1C833ACAF7 +:10B14000C703C7E4AB29C3E7E5008BE8B9DB943B51 +:10B1500080CF2BEDEB93FAD8C767249EE95793C9AC +:10B16000477ACB27E3F1B8391F85B840B8E2679535 +:10B170001B716F307107500440BB3C678E9F737B1F +:10B18000E24205CAED736B02EAD3700EED82E3066C +:10B1900047FC4DA29C02B07D06AE3DEB1CBE2707CE +:10B1A000E1905BE6203EF5A67939E4B506D7EDE2FD +:10B1B0002240E7BAA187D17D5C82C9F1451863546A +:10B1C00001BF8328C2CFE8120833DA021146974242 +:10B1D0000FA3CBA097D1E59060141E8E4721402786 +:10B1E0007DC77F331DC9634FF3E3486BBE0A915E91 +:10B1F000CF641CBE4938D43E08078D237FFCAC3891 +:10B20000B4809ACBF8A5E25150CAFC3B150F17F950 +:10B2100023DA2D0D62B94417812E105D4C8E8B7C84 +:10B220001E05C941E32650D8B8F97FC4A14E571D69 +:10B230006AF91478344DED173B4CBF1827DD6726AB +:10B24000ED745292D8D8B217A09CE1F993ED683D05 +:10B25000AF496FFCBBE407F841AC31ECC8C3717572 +:10B260006357318E8F49ADC6B8A1F117411C1F8FAE +:10B27000AD0C3B1E21BF6EAC76CA00DDDDABC24B10 +:10B28000705E4DF35500C615B495F0E43F5BFD06C6 +:10B29000FE6AF736D98F71A4167A64D2CFED42CC0C +:10B2A000103FA158803AA4454BE3179DB86E89A87A +:10B2B000F6503CB6BBE33E0971DFDADD9C03A8EF34 +:10B2C0006ED158EFC27DEEAAA45EF85C4BC3715FED +:10B2D0005F591717BCFFF9C8F790544B72CCD58053 +:10B2E000E438CDC986251B73DA304F0C279CB04F4C +:10B2F0004A9EF3A31CF508C901EE1220BBE7BB0D63 +:10B300003EC37D65656497930412CD6705AA09B7AE +:10B310000F73C22769FDA8D7F0AF936487DAFBD318 +:10B32000DF4BCACF697DEAF3D10F5100DC7F415278 +:10B330005F27793BD23F2DA1BC34B2E0BD5D7A20BE +:10B34000E9A71C9EBF06F58E2A1013591E59E8BFA7 +:10B35000897914D006E368CFD10DC80771A809AB6D +:10B3600051273EFEC29AB1102629E27B8ECEED1007 +:10B37000F5A205B8EFA5953744C3CF0A0C3F33F3C8 +:10B38000D0F90BFDCFE71BC3304C88AB8E0B77FF9A +:10B39000F927C4AFE3B647A6E5C9787AB90B7CB400 +:10B3A000C863CB1B569CD59F75C5051F8D1FDA4002 +:10B3B000EB16BD37504C7A2D1ED0A35EE273FE0F04 +:10B3C000F9861C665D503EE13E4F5D6816283903E4 +:10B3D000749E16622EC4AB938B5CF2D2F824276B5A +:10B3E00028FF5FDDE81F19B45EF1E4A15E9B4CBD50 +:10B3F000DAFB8FEEF222DDF4CA93CBA182C2C1C97F +:10B40000F2B7845F8AFF2DC79DC97CCE7ED110A87C +:10B410006707589FB8487ED0DE6B5FD701FB3FA619 +:10B42000BCD33131CFA35CC392378BD9CBAC57405F +:10B430002504F93D6DEE253D3C24F77931E6E29097 +:10B440001EEA92FD3436E3074EBCC0FCD25A0FAF61 +:10B450006432DB5BF1F4CC1E943D338957E53197C0 +:10B4600042B8571ECB5148BF4A11D68519DE31E686 +:10B470007795E81B1CFAD36BD3C7823C9EF3DAF9AD +:10B4800052193328BCB15381BFCC49CAD769C653BE +:10B49000B370A249443FB8FD14F83124A1B3FFA70B +:10B4A00051378E3BF702AD80DBF4837C6E0FF131B8 +:10B4B000E253DF5F9D4BF63E65C6A72B97076902F7 +:10B4C0004E69D234904A93630B5F97699FF4D21907 +:10B4D000B679AF3CCBB63FA32E68DFAF2989F21017 +:10B4E000E56363FF74E561DBFADDBE962BE4978BC1 +:10B4F000121B97132E994BAB6CF32170B3FEA1B6C0 +:10B50000C023C7703FDC31EA791D7E593D808840F9 +:10B51000FA35E8003F467BD40F3B6C764FD3D11F02 +:10B52000715DDAB50976C73F97641FCF0F987E50DB +:10B53000000513FD2089B3E71E8ECC0FFA7111E1CF +:10B54000EC1563D8724CC22904733268BEF68A00C7 +:10B5500031867B971CC7E733C376BC73DAEC78E798 +:10B56000A9767CF337D9F12D8CD8F19DBDDD8E679E +:10B5700040B3E357BCA7DEB67E6E4FA36D3CEFE051 +:10B5800032DBFA8762ADB671D9F1D5B6F5F37B9FA0 +:10B59000B0CD579EDD6C9BB7FC2AD5EE0BE29DB675 +:10B5A00075A976AFBEB2C3C6D7B2B386DFFFA79D7B +:10B5B00037A7D8F95B281BC5DDDBBEA1FD14865F6C +:10B5C0004E37F252B3B030A190BD173A65B2E93BA5 +:10B5D00052669397E2DDAC4361B30E417817B37BBB +:10B5E000D8F41339215FA23C5A753DDCE4C3718D58 +:10B5F0001EB944E93834D4D39421313791FCB89E34 +:10B60000337179BC8E03872D5E709C9DC46DA5D669 +:10B610002D64E0E2864F6351962EC9A9F0FC567363 +:10B620009EAB33F2FA0A250D1C13F058643E072A2C +:10B63000DAC86FA131052BCDFB00F6E520525FCEB5 +:10B64000BB63D1C054FDA47C50607D92CAFAA6CBE6 +:10B650009CEA24BACA9D28A2FA75285B7D298079C4 +:10B660007E849725D667717A94941A25C558D17926 +:10B6700027AC9453FF8EFFCEC2BCCB5F0D6B1E2652 +:10B68000BE5F47F955539EC301F55000F11FE4FC1E +:10B69000BBAA71EFDBF51F1551FD71098804E6C1E6 +:10B6A0004C9FF2133A47DBBD703AB35B0EEA8779E1 +:10B6B00054E725D63F683B38761FF888983D3221FD +:10B6C0004EF73859DD01F37EB4D6C4CBBA1FAD3185 +:10B6D000CF1F44169B304FAF3D7B99E1B2257718C1 +:10B6E0001C99CCDF589FF46481A76A1FE9A454CB4E +:10B6F000ADF3E9B9755FCA173E4B5D6C16CA33F4FA +:10B7000029FA458B6EC91D62F7B97BFB4F1875E4AA +:10B71000FEFC355667937A1BFC07F7A6B3FA32B8DE +:10B72000B7B0916892FF08E3BF36F2AECD4FD66D49 +:10B730007FDFE67FEBB53FDBE6F5AC31673EEAAF96 +:10B740009FC96BF93AE277EBB42B44F746B4DB358B +:10B75000B28BC55F3F306F099DF7DFF5FC1BC377E8 +:10B760006067021C73927ADED8799D8DF59D3AA3AD +:10B77000A97A5AF74C8B8A17A1D481F619E3A6C986 +:10B78000470293CFD91C34FAF08147B31BA9CE0EE0 +:10B79000148A0E839618E3BC3AB7316E594A74D4B2 +:10B7A000E9D943F7CC010E140EFD610DA7BCBA1EFA +:10B7B000F97E3B5BFD98FCB363F3588503E3A1A3DB +:10B7C00052FF0647A97FBA7A87F4E7B0BDCB9BC189 +:10B7D000E42CA1BE6388D72A38CC0515C19C15D4AA +:10B7E000970F4DD346A812971C99618C45233E4272 +:10B7F000C17FB178A8F1ABFF263E1F70429CFC567A +:10B80000FB25173BCAFC4D175BBD2C9EDAE8DE45D5 +:10B81000F75DBA6F8CA619D419E4987E620AA55E0A +:10B820009D682868E4B566617F0947FDC1411750EE +:10B830003CE0390AF515DA7957EC288EB35176EAEF +:10B84000537E2D1AFD7CD5AF5C71CA1B1BDD77982A +:10B850009DF28201C62FAB183317F2C97AD1158B2E +:10B86000927C7AA26805CAD7E3C4FE85E2FA1ACEB2 +:10B8700023DF5B07E61DD937C11E7941E37E084F00 +:10B880000118F3398769BEBD7FF006E5918B01B5DC +:10B890003088FC0779294479A4DDF7A648F9A73256 +:10B8A00028B17D282FD317F3C1773986B3DBFF0189 +:10B8B000FAEB3A4C3619747FE3D5B9C15ABAA7E806 +:10B8C00022F1438F60FDDFFDF4BFB521F1C372A407 +:10B8D000235EB988CEB1CE45392A898FA5B72547D1 +:10B8E00092CF83FD7AA37BCC16BF375FDE5D4271BA +:10B8F0005225700C9FD4F52D262E034EA3FF4B9D91 +:10B900005F4FF6AC9DC23EF3007291BAA661AD43A3 +:10B91000BA927042FC6E7D0DF5617D8BB280ECDBDE +:10B92000DEEA91296F59FC918FFAFA03CEF92427A8 +:10B93000FC25B2C3E6C8F7CE5C9592F3E87FCCAEA7 +:10B94000DA01C35FDA2FBC7FE3793CE5999FCDAF85 +:10B95000A63C6DED4FC579C42BB1F73B4F087186FE +:10B9600023E2BB9AF8F75DF95D36E162E1FC79719B +:10B970001D2D4C88C47FF4F0DD2209F7B79FBB7CF6 +:10B980009DFCB6DD7CBF00A7ECEF0D102F8DEE9374 +:10B99000F7EA08E5D6D96C9A9BD8B7B9ACFD050E85 +:10B9A000FB7E6CD0793CEF94796F394BF9628AFB5E +:10B9B000EDA904CF4AF4A95CEC0BA9FE60BDA77AFF +:10B9C00063D5FBADEFF22C0EB60680CD935C6457C9 +:10B9D0004E7F8BD51FEBFD4594C3BA8AB8758AEAB2 +:10B9E0000BE497A076B17A24CC46BBE2BEBEDF2C36 +:10B9F00033EF69467DAB35EB592DF121F9CB335847 +:10BA00009DAB31CF0DB9B17F0A52A9D0CCF734E646 +:10BA1000FB8CBD6FD9EE77FF01E91E35E2601400A3 +:10BA200000000000000000001F8B08000000000064 +:10BA3000000BFB51CFC0F0038AD5151818D6293159 +:10BA400030DC5266607055616038278F90A31556C0 +:10BA5000E5A04CFF0B4606865740FC0688DF319276 +:10BA6000AE5F4B18C15EC9CBC0A00DE4D7006955CD +:10BA70000106062E205B0788F701F9F780F81510FC +:10BA8000BB08313070F331309802B11810EB02E589 +:10BA90007D81F4373EECE6EB09E3B7FFB9002A5F9E +:10BAA000521095CF20805F7F97207E796921D2C385 +:10BAB000C44E9DFCF868A240EF40E09B0CA87C0BB4 +:10BAC0005906062F3906861E7908FF1A92FC3CA0FB +:10BAD00098A52C345CC5816907C8BFCC80DD5C1992 +:10BAE000A0BC36507E15D41C00DF43986568030067 +:10BAF00000000000000000001F8B08000000000094 +:10BB0000000BE57D097C54D5D5F87DF3DE9B2DB384 +:10BB1000852C842D4C58141070085B1094C9860134 +:10BB2000020C8B881675588410208980FD51B51F32 +:10BB3000139688967E0DA2965AB0030D82FDB00D25 +:10BB4000183560A0C366B1451B5C10BB7C1D16D9BF +:10BB50000C2404A5A3C5FADD73EE7D99F75E664853 +:10BB6000B4FEBF7F7FFF7F102FF7DDFDDCB3DD73F9 +:10BB7000CEBD910D76424613F235FCD07499400843 +:10BB80004989A6F4E79F5FA71232C94CFF2512929C +:10BB90002FDA081942C8441B099A689D89A3E8C78F +:10BBA0006442DEAD128222B4A1F502C3082926EC5C +:10BBB0006792446A85DB0969CE7AB562909B10C1B1 +:10BBC000EB25CB3369EA769199908E3AF085E020A7 +:10BBD000C4996520A40F6BF335FD9BE8B5625F4AFD +:10BBE0003EA9A083269FE2EBACA9DF71460F4D79F9 +:10BBF000277F3F4D7997A24C4DBE5BD91D9AFADD48 +:10BC000097E768F21981719AFA3DD74ED1E47B57D4 +:10BC1000DEAFA97FEBC6D99AF2BEC1624DF96D3B8A +:10BC20009668F203AA1FD3D4BFBD76A5A67C50E8C0 +:10BC3000694DF9E0A3CF68F243EB5FD0D41F7E7269 +:10BC4000ABA67C44F8579AF29117766BF27736EDF3 +:10BC5000D5D41F1D39A8C967933F68EAE79ADFD793 +:10BC6000E4F35D7FD6D4BF3BED8CA67CACFB534D9B +:10BC7000B98207E3FB5CD37C9FE0F987A69D447CF7 +:10BC800014D884184919A6665289A99554636A2361 +:10BC9000F5989E49F7DF8FF8F962A08250BC5B15DA +:10BCA00068FAEF249ABE9BD5D3E9EF0FBD7909A1BD +:10BCB000783B91754D269A6D2191E299C94C0216F7 +:10BCC0008A0A8E08C5B7248A771182A92B42F16DA2 +:10BCD00030C5BB8819D30E910EF83D29E2C2343924 +:10BCE000D219BFA744D2304D8DF4C0B463C48D695E +:10BCF0005AA41FA69D227D30ED1CC9C4765D221E6C +:10BD00004CBB46EEC0EFDD225998A64772F07BF798 +:10BD100088175377641CA61991024C7B44A660BD1A +:10BD20009E111FA6BD22F7E3F7DE911998DE129946 +:10BD30008DE9AD113FA67D22C598F68D1461DA2FED +:10BD4000B204DBDD1629C3B47FE431FC3E20B21C13 +:10BD5000D381919598DE1E0960EA893C8DF50645F0 +:10BD6000D6629A197906BF0F8E54623A24F2027E87 +:10BD70001F1AD988E9B0C8564C8747829866457E15 +:10BD800085E988C80E4CEF88ECC6762323D5988EBB +:10BD90008AECC5EF77466A31BD0BF02D09F02E8491 +:10BDA000A937F27BFC9E1D398A694EE43DFC9E1B3F +:10BDB000A9C7342FF227FC9E1F3989E998C8694C1E +:10BDC000EF8E84312D885CC2746CE402A6E322CD30 +:10BDD000D86E7CA409D3C2C897F87D422482A9C238 +:10BDE000EF4896DC1056F0AF07FC7FA6EBDC6D94B5 +:10BDF0002F11BFE16B9A121BC58311D1FAFA94720D +:10BE00003BE49332C5AB048ADF899417023F9C5808 +:10BE10002604EFCEA0F8911C3E0C7939CBE436D144 +:10BE2000FC03A44906FC25A4DEEE1B40C88111E7F3 +:10BE3000BB8629BEBE9B12EA46911B7E90DFCA30AC +:10BE4000A79EC06F1BA430FD3E31F9608ADF06ED6E +:10BE5000296D64027AD3F101BF293A025F7E402244 +:10BE600001079DEA71E86104D60B99687E6621F1AD +:10BE700066D2FA15234C3382749C8A4C5F918FA64C +:10BE80003FCEF0CD80F4F7403C74FE87787A9C1862 +:10BE900030FD32DD85E9CC477A337ACAA340ECD451 +:10BEA000361C1E4865ED88AD291DD6D7DE7612A159 +:10BEB000ED8646EBBF4C7C1FC2F7400EE953668B04 +:10BEC000D6A3DF4F42BD18DFFF1CEB7BAD813202F2 +:10BED0000AFF400763701BC827E2764E867999DD1A +:10BEE000CE29F6F8F37A7285ABBFD44B3DCF20CE86 +:10BEF000EF4981CCA866FC256DCA00EC1FE561C046 +:10BF00006AC1FE450E7FA5DD67004FDAEE3D8BAFBF +:10BF100091C9537757848BCDD52EB8D076D7112EB3 +:10BF2000126D676F7FBBF869258333F1BA711EFC10 +:10BF30007BA9890404BA8EA66DF6E0D60CC06137E1 +:10BF4000F2CF221767A0C9141854AE1725C21208E1 +:10BF500039BC3F2164A0F573B6D9B7821ED09813BF +:10BF600078DE0770DE2A936DB4CACAFD3F3AF173DA +:10BF70009ACFD9221313CD2F48786E18A170BB55D4 +:10BF800010D8F801EF815EB47F3F517EBC02F43FD0 +:10BF90009FB0FE1B054647816D4E84EB85BCAA8A87 +:10BFA00091340DEF5B5C48281F3F4FC1DA89E2F7FF +:10BFB000022B9120A51CDC88F009C867C38A7C414C +:10BFC0007A96A279B1757E3EE415FAA7EB5E1094DD +:10BFD000A379FA77E10E6D5E052FDCF7268B1CDC6A +:10BFE0008A78D585C1478197B70B831F87579E45B0 +:10BFF0000E1892115E41E0034EC18D7028B2C82127 +:10C0000091F65344E1082458B4EFA95480D3C21DDB +:10C0100016D759D5B88BAB1335F9D2DA4EAEB32A51 +:10C0200039DA7CF4970EA0D3256906D759CADF1AEE +:10C03000567893CED22DBBB2A20053053F16576758 +:10C04000B86C9A7EB4F9E64AA180E1B7DB396D405D +:10C050007C3C5B9266749DA5A47A690793B797565A +:10C06000985D304EC30A978B8D9B86A902AF45CB56 +:10C07000AD585F995FBC7EBFEBF9115243CE9881FA +:10C080009FD3B29EF1EBC7A527E93323D2499D7C0C +:10C090001DF0C64CFF7E6D403CC2BCD26F69B51826 +:10C0A00030DD0EDF776AC6A3EDDCE754F2253EDD16 +:10C0B0004AE49C0A2F97420748A766DC673FEDD108 +:10C0C00049FB6B946C6B418F9AC0F1A714EA517EC7 +:10C0D000B0D81C36FAE9A7CB356C3FE28D7369C541 +:10C0E0008E2EC0D78ACC9546605645D57DF3809E6E +:10C0F0002ED7AC4A05F9B2506CFEBE2F46FB1F2B63 +:10C10000741B949BB4F232C8E749FBD5D019B1B582 +:10C11000AC9BE61B0C74285BEB7E7F2A30B953B2D4 +:10C12000F3F8989174FE25B5578D308F0982FFA7DB +:10C13000424A74FD02AC9FF653BCE39411D677419A +:10C140000EDCF278C64DE0D96A9EB6B47309AAF93E +:10C1500005A82249E9757616A757E2BEF7CF943EA7 +:10C160002FFE41264FD379901BB4162D4FE7A573B0 +:10C1700089CF01F09A5DB310F9CF45E03F208749A0 +:10C18000E530C08FCBC45000EBBB4CDE730C56C106 +:10C19000EFA060E4F0A1AA2CE507261C0AE1D6096D +:10C1A000F895A9A8A25E1C08DFA500E74BC2D7C876 +:10C1B0004F8202F2B322F63D40CCE5B88EB58C1F1B +:10C1C00005E81FC83F5CA9E54FF3376AF3F3C8944D +:10C1D0005489F29779CFCAB447CADFD4FC8FC2EF33 +:10C1E0006581C9DDF9A4ACC245E7BFD948F789CE5E +:10C1F0007FB68B485DE8FA16BFB179D82C9A7F5B81 +:10C200006072ECD20A3AFD5B683F1DD8FA8B970743 +:10C210008DDEFEADD777A666F0F49104FB63F2B134 +:10C220005891BFC42D0D436E4995DCF8EBEF5223B6 +:10C230007A2D0EA847BFABF8F39CB5DAF5B5B57EFD +:10C24000FD7A097906F1AD78C7640278A6AC47D9C2 +:10C250002F653DF20EC11B8C4107618EAF0A5F6BEB +:10C26000E2F053F48ECF75F92F75F9AF757905BFEC +:10C27000654EDF14EF3F1786023D378D6178123629 +:10C28000B2F30CAB678CD6FBF266F54C9C5E68BDD6 +:10C29000AF6F56CF12ED4F32A4B4AEB7F88D575EE4 +:10C2A0000F50FC2EFECD730E42F1F1A25499EAA17B +:10C2B000DF176D5BE300385D90020EC09B8B41B1D0 +:10C2C0002016BC46180445DFB00974DF4B14FC1F70 +:10C2D000553E11E4FBF56DB2EB69BA2FA53B4C213D +:10C2E00013DDEF929A05856420E64FB1FC93570168 +:10C2F0003F4A6BE5D3EA7D2DDEFE5CAADB8EFBD0E8 +:10C30000C5003A30097521342DA9FA640CE8D1A58D +:10C31000A409F159DF0EC687A31DE5D7B38CCED68D +:10C32000E5CAB9B1947D22A5353FBA0AE7C65222C3 +:10C330009D56E35111E032D5F3FA19ECC9705E2035 +:10C34000C3C970E02B0A1C483005F9F2AA977F3A5E +:10C35000F0149D4743D51F1C820A3E544342B83413 +:10C3600057CFF95BD24DE4C2158A9FE41675BB2006 +:10C37000B673D7D20974A4D93A962E92438E9114EB +:10C380009E8BB6C81E8A9964D12BBF7CE9054A777B +:10C39000E46393A73785F7C2578E9CB883E617EE00 +:10C3A00092930BD9326C426A743F4AE95FB0CB2852 +:10C3B000F02F7EF588D13D807D7FA243741F16EE5D +:10C3C0003A6024035AC32DB7FA80316C8BB11FD564 +:10C3D000A7C6803EB3EAE5BF1B61BF2FEE1748C773 +:10C3E0008CD6ED8BB61C41FD05E084FBC7F7A76535 +:10C3F000BF5AED5368E2DE2158CF05FC3ADE3ED944 +:10C4000041560F453CFEF55E3A7ED19F4C1E587F4B +:10C41000D1AF973A601DE7A53286CF9BD7A47AE9C2 +:10C42000B8457220D58529FB5EF4E2A38867F38FB7 +:10C430003F8A7A19C58F4E069419814EB0BE873750 +:10C44000DD83EB9B47FC886F459B455F10F880447C +:10C450000A76C5A087DF707A38BF95724ABABEF3F4 +:10C46000C01F41CF7D4FE4FCF111D4231FE56BA524 +:10C470009A0CE63F37B37DAA301814BB9C5983A7AA +:10C48000554F221FBDD4CDDBD1D51FE1A0F04DE427 +:10C49000A7E2F1FC8E6C7F18FFC57614EF72E13BCA +:10C4A000D4AF97BD96819A769C5FB2F197F1F1E98E +:10C4B000BCADA07F9C4F657242BFBE3F1914FE48C1 +:10C4C000E5AB0ABF5474CDE8BCEA2946D70A9D07FC +:10C4D000271740F9671F30FA8176207FE8BC421D9C +:10C4E000B1FCC03401F980898462D17395CCE959DB +:10C4F0005B4E3934EA6F74DE92E054E309EDBF031A +:10C50000C21FF59279CFD2762A7DBA14C6C37AC6F5 +:10C51000E8F78C28DDCEE7F4FF2BA0FF8428FD93FD +:10C520004D29ED3A9F2D92832FBD00F44AE933E067 +:10C53000067A957DB0EE4F771E3A713FC5EB4FAB53 +:10C54000153AD5F24D3D9D16ED7E94007EEAE9F454 +:10C55000D3AE6524269DD2EF31E9B46BF87F856FA9 +:10C560002A703BAE831BE583BFD8EB8E0F3F3D1F88 +:10C570002C35B863F241FAF30119D61AEF147C5343 +:10C58000F0ACF8BF1677077ED3828F0ABEB5E0A362 +:10C59000826FFA756AE1A62FDF04FC46A51FC82B3F +:10C5A00049C04EF7B9699F88E7C4467793A3031D36 +:10C5B000778D853C047A76A38BE71359BE29C5583D +:10C5C000017C41F9DE642133003F1B7D4D8E449593 +:10C5D000FE7CAA4E74B8697938480A62E9D594E3BA +:10C5E000E2F86112AFBC1CE1972FDAD2970F81738A +:10C5F00095E801DD6D6EF9BD0E305934D6F59C34E9 +:10C60000837E7FF86D116D1A8D56C74098173DB720 +:10C610004B9D287CE7F07DBE4002CF8FA2EB9A5362 +:10C62000C7F4E2B9EBB4F098675B66043E43F5CF1C +:10C63000281EA8F045F113146DD296179375B85FB4 +:10C64000C53AFCF1F3F34E2791E3CF2032889F37B0 +:10C650000CD0DF12CEA7F2C5FE936650B8371E1578 +:10C660008989E69BEB445201EBDC290409D0712057 +:10C6700005F1B084F207A23A1736009E19E3D36F92 +:10C68000C36B7F1DF638ADB2E8F53F0FFC394D1B8B +:10C690005EFFF8963721FFC647E97F26ADEBE7EE50 +:10C6A000FFE241E0EF8DFB4D04ED24FB7F97FE3868 +:10C6B000E4F79A3C68E75869F2A27EBCDF1EEC0DF5 +:10C6C000E5DD987D69D5BEBF0F0CA3BC598DFB94E9 +:10C6D00027B2734473DD3FFE5B488694AE0AE4E8FC +:10C6E000FE04D4AF4BF75A8270E86CDCF7F7617E3A +:10C6F000DB77B79E1223F123FED9C98CDD80AF8989 +:10C70000CC9E56FAE6885F96D3F117D71C30CEA19F +:10C71000E5B9BFFD6A20F095C6DD4C3FB822875FC2 +:10C72000241E422689CF95CB74BFAE80AED699F237 +:10C7300025F14476C0160B2E0C0E8D140EB02E0A69 +:10C740009722E087F1E031EFDF161E571F84F117C3 +:10C75000D50D2762861A2E82977DB707CD02AE9F30 +:10C760007DDFFFF781C0773FAD2E47F9DDD6BAD721 +:10C77000C0BA53FE5F5AB7106ACFBAABFE6DD7CDC1 +:10C78000F0BF9FC8E4919E0E5AE3F91BDFC7FCAFD0 +:10C79000ED1E9C6F3BE9FFF0BFEDFABFE5BEEF1663 +:10C7A000D01FD7D6BE9FF9B75D775BFBFE36DF772C +:10C7B000BB0BECBD8DFBBE4A27AAF5B7B56E83F463 +:10C7C000EFCADF6EBE6E45EFA93794B986D0F97D0A +:10C7D0004C2AEFC9A0E91FBDD792E1384A69C017BA +:10C7E000EBDC9029B1738309EC4C50F11E41B11779 +:10C7F000D56BFCB85D8B50CF98E8FD31EA07442A31 +:10C80000ABCFA6F5EB73E6789EC61A9927FD909FED +:10C810007627CF6BCF531373C61F05BDEEDD723A7B +:10C820003F885BE826B9A8A644267945D403698ADF +:10C83000FADF87E963B0DEA42CED79E23EDD79E032 +:10C84000DE19DAF27B78FFD3C9332960779B3E97F4 +:10C85000D9DDEE25656B5CAA7DBA47D78F4322DC14 +:10C860004EF2EDE037B7057E4B101E245BF46C23CF +:10C87000ED801F61F0AE9F3628087618227918FCEB +:10C88000A62FF6A01D949F3365DE5EB6ADAD07BA48 +:10C890009589F67CA99C13DB8233E1E74FECAF4727 +:10C8A00014EEB257C4F3A7AA5F848BB21FDF741FC4 +:10C8B00094FDFBB6FB310CF62386FF6C81D97C0F0F +:10C8C000F82FCC7D043CB74F5A27621C8CB9BF802F +:10C8D00070F465C9E8DFF9C4E01B068A73E1E0E1A2 +:10C8E000258FB16E3D009F051C8EF34819EA9DE42B +:10C8F000C6D75F8F02BF114286967B099940CF2130 +:10C90000F34609212B5DF77C89049C9960D714C8F4 +:10C9100069B55D33A8CDC3CF5DA9D17EDAAA1F8FDB +:10C920003F7CD7E9DF283F3ADD8B9E572095707812 +:10C93000497D4E7CA88EC1B1749110EC817814921F +:10C940007D2ABFCEC71CAFFFF6C460E473D93F1980 +:10C95000E0C4F3ABB71FEAFBA55CDF6F0EB89D60C8 +:10C96000AF69AEEBE9047B4CF3D15C879A2F2AE9DF +:10C97000717E8E7C7F8519D3C63CA15284F31669E3 +:10C980009A887238CF4280EFE8DBED9114BB4B19E7 +:10C99000F333D21F7118EC23FB994F9B3A3BA8F657 +:10C9A0006DDD848BD2C0D6FB003FA7557E927F15EC +:10C9B000BE706E05B81EB784C7F862ACF70F1C7E58 +:10C9C0008507BF30829D604A5D860C709992276A08 +:10C9D000E26E0E49FC3C35980C8679151E1CEB184E +:10C9E00001FB7254F458287C4BEBAE1AFD31FC6D00 +:10C9F0007A7842FF60173E237BE6013CCFFCD842A9 +:10CA000002941EDEE1FE1F5AE405FE45BBF2827D64 +:10CA1000EC0389F915FACACC2E3EB5305B4EA1E382 +:10CA2000F6AF710D0211D399D7EF2BBBB1BC0B6FD1 +:10CA3000A7D4EBBC88D53B657495C45AFF04235B2F +:10CA4000FF7CE2F97E96F0EFB76FD93FB187724075 +:10CA5000BEE709C8475AE33541FA682E1082207FA5 +:10CA6000E11C8BF94201E5FF3B06561E98C2E4A586 +:10CA700082F77A380B3283B3327E86CCF0D92833F2 +:10CA8000F8287056E0AB9FAF529FF2ABD16AFBCA59 +:10CA9000A4DA41BF06FDA4A44E7081E9AF440A1B8D +:10CAA000810E4B6BD7CBE02FB8CFCDFA25926FA07C +:10CAB000DA5FDB5796703E873247A2FE786D1DD352 +:10CAC0008FBD73AF3A400F7AC7E0F9E348A0C7774C +:10CAD000458C278807C73FAFD8312D4F52F79B8130 +:10CAE000F39CBA285B0673D0F7161D903BAAF0A9F9 +:10CAF000AFDC01CB95EF9D17B933E13B1D0FE7117B +:10CB0000F84F13D946BBE85F5D9F9340CBBF579664 +:10CB1000C8F0B0A8FA8011F319585F194F19474FA0 +:10CB20004FD30A1334F939B9E1AE009742536899EB +:10CB300027069E1E96153FC93794135E8AB703FFDA +:10CB40007F901357C77863C06D83DC4A3E748C2591 +:10CB50001F9694BB3B02FC97ECEBD9118863C9DBB1 +:10CB6000F9A9B1E4C3872B983FF023CACF206D9C6D +:10CB700046E5C3ED2AF930CD82F8A16FF743B99DA0 +:10CB8000F241D9AFFF653EF321C88718745D296B68 +:10CB9000E5C3F4BA59281FA64F13895B658F7B52F2 +:10CBA000E67EAEB8F2213BF53ECCCB9E841878F3FE +:10CBB000213F97005C218571404EFC96F37DBDBC02 +:10CBC00088C7CFA71805EEAF6E839FFF5F82B3C201 +:10CBD000CF97D0F30BE881ADF19020BF5E721FE5D7 +:10CBE000E702E023E3E74B1EE076491D7FF5017F76 +:10CBF0001DA2E6AFAC7D899FC983D2DA8C9FCEA4FB +:10CC0000E5F757CA1E33AD7F7F94DF0E53F3DBDFAA +:10CC1000727E4BE19CEE8AB1BF33662610B7965FF9 +:10CC2000F5023E7566D0EFFABF0A78FF8E887EC4A3 +:10CC30004FB81C3F36E87743C07E9E6C94107F3E11 +:10CC4000E1FCEBCA8AE0B43C4AC7B973993EBC78B0 +:10CC5000A7887028A9617A5E492F6BD04DF36332A3 +:10CC6000BF407FE0C27DCC1F48015598ADDAC78533 +:10CC7000EF842BBA40F91601FD99F33C0BD18E4F8E +:10CC800036323BB199FE61711D5EB4232FE6F05A36 +:10CC900050B705EDCD0B825A3BF4E25EE32EC2396C +:10CCA00040E1BF0B77E8CA3D4FA1BF6231D89B5529 +:10CCB000E70F91EB0F0F8BA1FEAF426CE71FD9B9C5 +:10CCC0004ABFFF4ABD96F517FD8BEB3F4ED73FE4B9 +:10CCD000BB5F7F7BD72D1B39BD679221401F9F18FB +:10CCE000BC48EF81DFD3F5D371E6AEEFDD511D67B0 +:10CCF00094C4E9F21D83BFA213D42B11B0DEFC4D06 +:10CD0000BB8EA4D2FCCC6A3208CCF4F3376AE5625D +:10CD10008B1CAE71A39C9D59B64B98DD1FE04DCA8C +:10CD200000CFE6649AFCE04F3D6E6942FEA5E0DD6F +:10CD30009D4686CF23F9B8673A37E5E139A25670A8 +:10CD4000215D842CEC5C41E16FA1F94323FE3E861A +:10CD5000C31BED31A5B56C7F4AE97E005D8DA9E36B +:10CD6000F91D4C0FFB1E9537E80FAB3B2043BB2250 +:10CD70005A3F09F94D3F8D9F0BFC73D9A9AA7DDB62 +:10CD8000778AE1ED36C14362EC5B1FFA27E6BE7D90 +:10CD900047F8AAC0E34E23D7E7F9FE1DB7D4170E14 +:10CDA000463F94E0D90A95EB12D18F72B6B227EEC6 +:10CDB000E3788EBF7ABC06FDDEADB2274D8689438F +:10CDC000BC658105E3DC70DC1E4CFF51F313FDB93B +:10CDD000B994D4A31E3341F0FF5552C5B54DE7F1C8 +:10CDE000278A9F5655EFA7F24DEA91349701F8E450 +:10CDF0005225DE12E28753316E097F0E751BF6D184 +:10CE00004CBADE6B6B450FF87FEE35B84F8C02FAEB +:10CE10007D5A268097D78EC95EA6772620DF9DF59E +:10CE2000CE19194C21B3284C60BF67FD90F1D73360 +:10CE3000D019FDF6272AB7BCE0AB27D543217E7871 +:10CE40009AE740BE9BEECB3D438EAF013FDCD45C06 +:10CE5000D7891300DFA74402F03DBD3617CF274B1B +:10CE60001F1110AF4F523842FB7BA6659C3841C75B +:10CE70007D606D0AFAD5667A8FE4039ECD9964B71A +:10CE8000817F6D7C1F91F855707C80D4A39D626674 +:10CE9000D923F7C07C8BA81C003B6B51DDF1FC8EC5 +:10CEA00090DF2478DCB4FFD280DFD8916E61FDC6BC +:10CEB000AB46B0B7CCA3F5607B4A37B17AA55582B3 +:10CEC000C702F858B71EF9CEBC2A81B8A03ED5F7E4 +:10CED000CCACDFA099F65BBF89B6A7F9F9D01EFAF2 +:10CEE000AD4A9C0E7EB4D263226B9F55FE16F0A510 +:10CEF00079B41D2D26F5558F607F0B3609248DF6EC +:10CF0000579495F19F59D0DF31D903E51F1DF8994A +:10CF100011E6FD201DAF13ED7F8E18CE87FAE47168 +:10CF2000C1B50DED4D2C4EB691D301F9A013A32F31 +:10CF300081E7B91EA8C8C3F78D3D109FE62D2FAF1E +:10CF400080758503291970042AADBD6A04BDEE2CD5 +:10CF500085B39FEA6D67781CDBA1C0196358C5A72C +:10CF60009A8C3DB1FDDCDA6CA4EF87890FFDDDFE04 +:10CF70007226874FADB10405D03F6417CAC9436B11 +:10CF80006E7D1ED67FE51519FDA357BA85D11E7B90 +:10CF90007E934C02748EAB3689C837CEEF64762010 +:10CFA00071B38CF9F98F1A317F68D3D431C00FCFA8 +:10CFB00053F8031EE66ECE37427E3EE5EBA618FC24 +:10CFC000639EBB98F10B1D7F98BF514BFFADF8C519 +:10CFD000B2318CBFEBF8C1E2AE1568E7D3F38952EA +:10CFE0006253F84326E4EB439D107F4B8EC904F453 +:10CFF000B912C9F5E046C09B9916F01453BA081D42 +:10D0000001BE762D28B803B4FC7B0FED190AF03B66 +:10D0100007F006BA589784FED479C1590857259E5F +:10D0200070FE462D3E2BF14BF7F945E255CB81A220 +:10D0300004E255D5FBE887142FE9780FD50A418B18 +:10D0400000F9536F3D3A04F32EC0C392E55C9EAEE7 +:10D05000B323DE7EF483AB6B002F1F7C42C0F993B9 +:10D0600080BF02E44AC946C10D76CCF94FB0F6F351 +:10D07000697BC0978F7EC6F087E2B11BF0BC64D39A +:10D08000FAB7B07E95E086FE3FDA320BE56F51408D +:10D0900024585E750AF5632A07300EE850404C05A7 +:10D0A0003C2F596D72C13E2AF8A2E0DF2999F9EDB3 +:10D0B00089D933702A6DB7C5E8C675EBF14E9C91DE +:10D0C00081F855BA5346FC280D307C3AF58A8878A9 +:10D0D0007868CDBD883F57B60971F02FD7D809F0D1 +:10D0E0002FC8CA5BF0EF6581E31FC3EBF3CB183E9B +:10D0F000E64239E0DF6B5C3F25C4A6D63B14FC5307 +:10D10000F0A92DBC6B2597E2E01BD58DA7C3BC967B +:10D11000AEB1E0BC732BF64C5F8E7423A37F3EB799 +:10D12000E207A940A7F3241687A1C071B1C4E27435 +:10D130005ACDE3D97263A7F6CC47378F0351B9981C +:10D14000097211E24A42749CDFEDFC25C6AF5DFE18 +:10D15000D5298C4B5CF826DD775AFFCA4E3B09A1D6 +:10D160003E1D44FE525C23625C289142C3A6AAEE97 +:10D170008F28F1160B7F6347F816EF36050B69FB16 +:10D18000E2D7CF0C447FF8CAA6B7807E02BF1298C0 +:10D190005D3E101E3815E22A2516F7A197BB234CD9 +:10D1A000CC5ED3B0276106E83FC28E03E84F2AAEBB +:10D1B000BE5736A9EC931E938CE3D27AEC9E0BDD1E +:10D1C00077F023C2FC260F50CFAF9CF5F732A39B1C +:10D1D000E25A19F5A2E21D5BD0AE57BAE32AC6BDEA +:10D1E000E6FEE61507C0A1B456D4C643ED104326AB +:10D1F0008CD7124F99187FD2C42595D4B07B1925AE +:10D20000D53CEE471717B3F037FB5E0F50D02C7CA0 +:10D2100075BB03E8E852FD3607C093F687F14493E7 +:10D22000B2E2C41BB5156754FD54CC38A34BF00FC4 +:10D230008A200F9AB4F1996407E35374D787F9628F +:10D24000D833157D65E12B9FBF0871AF0DBB3F7DC6 +:10D2500011E6BDE89FD75E84B80DB2DFE202FDA102 +:10D26000F4571F62FCA0D26EB9899F7F5EDE8E717B +:10D2700097573E36A1FE7765DFF974D00FAEECFA12 +:10D280002215E22997EDCB47FBC3B2D7723B921828 +:10D29000E75B2505BC0CB623EE53BF0F876AC4902D +:10D2A0008DCEF3F24913D2774BBC58F562167FE767 +:10D2B000E671623B63C7D52AF14D25355327DD0959 +:10D2C000FCAD86C9F19678A7B6E2C33EA0FB797B98 +:10D2D0003BF66D278FFFD3EDDB65F807DD9FE74C4D +:10D2E000DAF8B0CF6B1EFEC50B505613FB3E9942C9 +:10D2F000C76DC14B89DB9D63F2064D4037BBFF0B09 +:10D30000E3F060BF0ADD20E73F4F07BBE505B90941 +:10D31000ED814DFB4C2E88DB2ADEF711D2C795D765 +:10D320008E635C2CE1F1B35748CB0F8B77E43689E1 +:10D33000D22A3B8B2BE37087B833B703BFF3F832A5 +:10D3400086B74ADC59BC78B30F4D3DF8BD0B1617B4 +:10D35000B7D85D6F04F8ABE3D0842CD8A7539AF804 +:10D360003D65DDFAFE5C0087E1EAB8C978F17C5CD6 +:10D370001F6FD927C687AF6CE171942DF19184742A +:10D38000CD84781F26EF4A83C24724063D2A719335 +:10D39000F57A7A0CB62F5EB2EDF97E3B781C32310D +:10D3A000FB930297861BB1F9F1A79CBEE9B9E49201 +:10D3B00049752FE5217E2E51E2C894F9565433B9B0 +:10D3C000DBB083E9857A7A2EE1F676FD385FF0717D +:10D3D0004A6A0F0C04BED370700FC73786CF253B47 +:10D3E0004F19039C3F07D5FC19FA8BC14F4433EB0F +:10D3F0008F9E6363F657BAF36ACCFE2E49DE7B61DB +:10D40000FE97EA999E71A95A2C08C6E8FF32973F09 +:10D410002DEBB61BF15C253AACC87F96D9B34E3ADA +:10D4200093213562FCC2AA721EEFF0434F1AC079F5 +:10D43000957D1C81F9AC01F8A8CE99B2CB4F40CFB5 +:10D4400091D37C43E0FCA4CC572937261B4850BD20 +:10D45000FF5200EF474EECF17709E44BFD0AEDBDBA +:10D460008E7AC9752489F6579F2778409F6D8D67FE +:10D47000DAFE277B458D3D0C6CCFB0AE668F01F791 +:10D48000D36E08B9681562B7D4A7E141CE4DDC521E +:10D490002A8674A35FFBE9153BBAC13D2B07F1084F +:10D4A000506EF7B4DC6FC1FE9C4417671D201FC08F +:10D4B0007D481B67264EE23A0076096B1FD207FCB7 +:10D4C000D62E62F5C0FB0A1BF8BDC775763FCADBD6 +:10D4D000B874E361F75E143B91334BD2DC8B49F4B3 +:10D4E0006AF349BA7B900ABFC62B7414FE63F8BB7B +:10D4F0000F89F96CFD60AFEAAD9A6F620AF184A002 +:10D500007C820DE3996D36363F65BE743EC80F28A8 +:10D5100098D87CFA8703A087D379E9E898E0BD27FB +:10D520003ABFD3BAF969F4B8FBCC5C3E4844023E3A +:10D530006233D7130EE7666D9C698040BC81B305EA +:10D54000AEB49CF693214C3241DC820B4EC13D714E +:10D550003C5DBBAE2EF57DB15AF8C708F4171D36F9 +:10D56000829FDF2CC0F19974045C032048F54600CB +:10D57000C64F6D4A3E84FAA2AFE6389E3F17571F4A +:10D58000C77203E4699A94E0CEEB328890A7D6E69E +:10D59000E5A5F5857AB3D20C1ECC1F96808E26FBAE +:10D5A000D30C8360FA79AB0F8F22643B29EB07160B +:10D5B00025F36AEFE1A3DD00AF083AED48C07B1820 +:10D5C0007073BB92A70C10DE57D86E6DC97BCD94DB +:10D5D0002F6EEFD1920F40BE0A807F078CE73DBCD3 +:10D5E0001AE27CCCBED5663AEEE4CD06A4BBD111DE +:10D5F0001B9E3F48B803F26742CAACBE18F7A55B52 +:10D60000EC3CBC5E5B7C7C3B8F479EECF77BE0AAEE +:10D61000F7702E8F892B3C18EE63379A673F6F5651 +:10D62000D3E1E666B1079DDFF3B0F7B4BDB3C03513 +:10D63000AE0F9D9F739381C5CF9AFD3F87FABD9F23 +:10D64000F01BA0CA68125E2A001FFE4B32CE47199B +:10D65000A7621F3B5755AC31045722FEBA05906FA5 +:10D66000D1FD0BEBF6AF89ED5FED29DCBF92BA532C +:10D670006CFF6AB71C30727B3C9C5BB613CF2E30BC +:10D680003DED5A3B234FA2FB92646AAA807D95C967 +:10D69000F4BCC2BE08D7DFC4842B9F5F5B70DD7E05 +:10D6A00061EB8F06825EDF60F0F426517829F54E3B +:10D6B00098599CD864ABBF0EC6297D365C01E7DF64 +:10D6C000BD17DE433F70EF86E6D0403ADFDEA3B8F9 +:10D6D00039858FBBBD612BFA33B7031EBBC175EF14 +:10D6E0005F0972323E3C187EB7C0A3E614C2C70081 +:10D6F00079FA7D37BF4791532B78414E2499A81C66 +:10D70000A5E91FCDEC1C73C62CF294D9199D0D3DD3 +:10D7100024D08B73A619F03CE5E46974FD3CFECF80 +:10D720002C69E48BB29F0A1E11529900E79C02A754 +:10D73000FF2F5ABC7926A1072D1F7DF6F452B0EBBE +:10D7400029EDB6AD209EB9AAFBD0147FF668DAE5C4 +:10D750003F6A057BA8521FF032D63981B6BB04ED73 +:10D76000601C58C79EB3CD22C0BBBDFBAAFF5EBFE5 +:10D77000828ED72B3EFDF8B2D9BD22FDF77F9A15D8 +:10D78000BF23D347BCD17B7FFF047C586C0E3BA6E4 +:10D79000D1FD2DC9BE660438AC4CB8323296DF33A9 +:10D7A000DE3CEA6FDC6A03397D30628A798FA0AF94 +:10D7B00085E917EFAE98E1013FFC532DF704983C43 +:10D7C000CBE37C37AF577121635AAAB83130587018 +:10D7D000B9990F5FE8FC0AB27649203FF3894A5EA7 +:10D7E000323BC504D0479ECA1109C6A9B9648D7CD5 +:10D7F0001B0FF67207BC0B52761886BF3B4D7B0F92 +:10D8000074D2A85312BC5730368B8A6301DEA7D17D +:10D81000968FD7DD139DEC9DE5C9E3E5D7F0FF4179 +:10D820005CE7A4ACFB3C796A392155F6817D3EFE6C +:10D830009518536F7CB4053E3E84EB1B160A9FDBA4 +:10D84000619DB3563399747378E8E1A8874BDE5F26 +:10D85000E6317BA10E1E77DFA83C9C14030EADD7EA +:10D860005DD907E4A6023F3D1CEAA12EEA4DA620A1 +:10D87000E881F55218E1584FE118E07EAB7CF53EA7 +:10D880002BF3E1FAC378FE5D0F4F3D1CA97E81FAB0 +:10D89000C3D80176B4831D0378611C40E50726FADE +:10D8A000FDED5E32791A785F6834C619DE45105690 +:10D8B000E40DA12C0FFD322EE65FA1F29CE1C35FC7 +:10D8C00098FDAA30C2E63FC6CDE265283C4EEBE0AB +:10D8D000715A87079A738B7E9E6FC03F46C4C00FF4 +:10D8E0008E078B2CFC7C934EDC70FF7FD8C7439C4B +:10D8F0008C2FC4968FA323BE967E98DEC1DEE710E0 +:10D9000088BFE5BB8BF613F2CA18FF996B76217DB1 +:10D91000E4126F12BC07014186304F655E8305DF5C +:10D920000F2D29F07ED3D824F5FB10CAF8CABEE427 +:10D9300072F8E592C0013887E612E933F5BA95FE30 +:10D940002A2C5CCFEA4EBAA39F1C8CA143A3FD29CD +:10D95000EB4B4A22217C3F4430E33D27FA5FC0D89D +:10D96000213A9E123F9A689F526941BF4E196171D8 +:10D970001221DCCF1C5E9EC3DF6922E6B8EFF29075 +:10D98000AF13A2F37BD12248F86E029FDFE5A3E636 +:10D9900000C46B3C26F8B7021C1A846303015E5472 +:10D9A0001FBB05EFE9EBCAAF9D3C5C02E5B4DE3C72 +:10D9B000ACC7D7B5506476327AFEC7F7505AF371C8 +:10D9C000664FA3E426C1FC15FCCFB132FA1E4FDC32 +:10D9D0005DF1BD34E297203D6C61F7D0EE3EF90C6D +:10D9E000EEDF1FAC771F057A2B204109DFF9716943 +:10D9F000F1B04D3CEDA33FFFF2775DA4A67480EB40 +:10DA000041CBADBD408E29FAC27B16DF6F61BD07E9 +:10DA10002D8C3F9FF60E7D17E4C2ECECC12786D01B +:10DA2000D460F6E1BB0B0F035E517866015ED1B6A0 +:10DA300007A1EB4E88574761DFE6ACD5E19599D950 +:10DA4000D36653B605EBC8592B7FA99E570BBCB8BC +:10DA50005C6C4B3F2487A9429F0AEF2D30FC3C6849 +:10DA60003105406FCB798AC547CC21FE172B057C49 +:10DA70000740A3AFCFB530BBF7DC9F5990CE69E329 +:10DA80004D65E0E7B2F0F71CFAB077775AC6AB54B1 +:10DA9000B5877D37A7221ECEE5FEC3B3023BB7CCC8 +:10DAA000B5E4B37BBF1BE566353EEAC78FDBAFAE9F +:10DAB000DD4181D9490ECA6E8C0753DA5DB1303928 +:10DAC000DE6CEEBDC97093FBE0F3CC1DFA4B49D17F +:10DAD000FC398B65462CBD40E9AFE55CDE729E30BB +:10DAE000AE39DC357A9E3094CB47B4E709F9C8BF2C +:10DAF000729EB03F2D1F594DDBBF6DF3A55A617C5F +:10DB0000C9D717E0FE1CD70FA926D3576D974EB57E +:10DB100032FD3075790E393338FA3E9B20D199E0C9 +:10DB2000FB1AFE729037D20C82FC9FF2998762C575 +:10DB30000525DA733A5B8746E9EF2983BBAA92C5CC +:10DB40002BA0BFD7B77C36EA7353971761DA78FA00 +:10DB5000C62D4087391C9EB75A995E5A9AC0E84331 +:10DB600010FCB7427FF55ED10EFED485B522F7D703 +:10DB7000B177ADA64E1053E0FB19B38CE7C08376A6 +:10DB8000B6AF67087B9F26E7B8C95743D31B247BF2 +:10DB90009C55A5EFDD2079982769A9E8BF56EE2BA3 +:10DBA0009E21196CBE6B997FA0796D06C6311F94BA +:10DBB000B5F6A85156A60F8FB2B2FD9DCDDFB103C9 +:10DBC0007C82F724664B6EB40FCE8E18D93B6A74F4 +:10DBD0001E886F166D3FF956163F91CFE13F1BE44B +:10DBE000E460A8A7EF4762FD73BCD5C3FD4D4BEEC3 +:10DBF0005880D30DE21D6745BEEE96003E39430EB8 +:10DC00009F04FED6363F0F08C0CF4B6F08A1EE60D1 +:10DC10002FAB91F17CD6C0F5FBCB35875267D3741F +:10DC2000F1AEF71D700EFC9E95E95397A57A7C77AF +:10DC300062D16B22DE9BA6689AFA3D6C3F6718BBE7 +:10DC4000F7C1EE2D2872EE8EAF7A76F5613D76FF44 +:10DC500040D1AF72CD8120CCEF60B98876292A07F8 +:10DC600035EF90E4D7B07B097ABDEB11ABCCE3354F +:10DC7000D93E2E73B171E2D16D4EC44A822ABACD1B +:10DC800091DC12CC3F27E220410AF7CB17B66E9801 +:10DC900048F13C9026E3398F1E7F0EA3DEA7F8C122 +:10DCA00003344FC739CCD773A466EA34785FE52DC7 +:10DCB00052B67A00AD9317F6273322A6A7B4615166 +:10DCC000BD2BDFA5D5F7F4FA6041DDFAD5F0164B90 +:10DCD000037C80F1CD268C236EA5279AEF8EA91F99 +:10DCE00012B21EF1F08ED77E391EDE9FB8E3A2C1BC +:10DCF00005F39B6C7533FB62CD357C1FA18484A634 +:10DD00004379498DE80AD1564748CD6D201715391A +:10DD1000AEC02574E390D903FCDE22BA56C23ACDD8 +:10DD2000F7D820CE626463FF64906707CD32DA21B2 +:10DD3000732CBD6D7354F87C3099BD1B7024B9A74A +:10DD4000F6BB79C36D20D7F6F0B8B5C3E7EEB7855B +:10DD5000B1DED464D4CB1439AED357157BD7D8DE1B +:10DD6000628BBD4BADE71271D3B3165A3EFE561906 +:10DD7000EFBDE58599DFB4951CBFE15FCDCF239A58 +:10DD8000EF055C3F6825D7A370D6E8A16F58B95E50 +:10DD9000E9260340AF0CDDD8B010EFCBD625B8563E +:10DDA000A23D81E92D8D678B374C80EFC744661FFC +:10DDB000B921221D1DDCBFB07B5845BF5422E0BEF7 +:10DDC0005D1F74F5CA9B745FAE7F62F504E0B354C7 +:10DDD0007D5B6CBF5890C329D499D9D9039DD93B99 +:10DDE00018ECDC7957F4DCF90EF001784706C443EF +:10DDF000DAA65346381F5FA6AA38E2175D34E0D78B +:10DE00005DDEB0A8BE7F738AF3DFC956EFFBC01F8B +:10DE10000324A70B55424891D59B0D71E04D938982 +:10DE20006B2B5DCFBE0B39824CF3A3B66578049A99 +:10DE3000DF0D8A25F0CDD7C420C493EC867B6BB46C +:10DE4000DF05F595C60C3A6EA04644BBFE026E1F78 +:10DE5000BF2007D21355F85199C0F8C905D9FF0B57 +:10DE6000E8E7C2C726B4775FF8C41A53AECE48605D +:10DE70007CF74D2ECF3213DC980F35EC7DAB339D04 +:10DE80005728E21A04702FDE7155847793EEE4FA76 +:10DE900057E1B3F5ABC12E33715393047CC71774AC +:10DEA000E583489DB2C323831C9AB6D327839A3D4A +:10DEB000BDA60CE39066D4561E81FCFDA16ACCF78A +:10DEC0004FF047002E77AD6D3A04E8D2AB9248F898 +:10DED0008ECF674CAF4AE5F3E811F11C7422366728 +:10DEE0001B00BF5BC67FA25E02D57DE26A363EEDB7 +:10DEF000CF9040D77D5759532EC8B5F4E5ACBF74C9 +:10DF000072A0DCE98EF63BFA46BDA0B617BCF898C5 +:10DF1000AD88F15B06F7F4C73B6FC173197159F116 +:10DF20005D454E4F398FDBD00F70FD07CC0F707DF4 +:10DF300010D3A7AFFFC0160CC4D0A7A378163231F8 +:10DF4000FC52F08D9859DE6B067CFBFEF36556A003 +:10DF50009B649FDBA88E3FCCD950D8EF6DE8DF6281 +:10DF600042BB5CCB78EBD97810880B78ADC8B1D9BF +:10DF70003AFF4B940F30BAA05D04615C2525C24A7C +:10DF80001751E749280DE6939EC0F85C95D13D13E3 +:10DF9000C6ABB29A5C30DE6C736F23F0AD16FB2615 +:10DFA0008F4F1BC9F5CB7D170E26C1BE5F1F549E38 +:10DFB0000E7A73C8F073E4536DE1DD4FACDEE10916 +:10DFC00038CF00EAF94AFD3DE7ACFD414EBE69603D +:10DFD000714FC433AB3BAC5769378DA7BBB99F4E6C +:10DFE000A193E47AE2DDD21F41E5DDAD82C7A4044E +:10DFF000468F4ABA5B7607189DB1B8CEDDF690B968 +:10E0000027D0F39E9E984FF6119B07E2586A7B7BC0 +:10E01000C05F43F9C0A404955DEA4ECE1F92EB9B0E +:10E02000902EDB7B1E18C6E11B92AA397D11E453AA +:10E03000405F8C7F87BAF0F778D0FF077C83EF4F83 +:10E0400027210DE3C1719F95752773BEB08CD33D19 +:10E05000C001CA4B795E295FCCE1952FF677AAE320 +:10E06000C75AC9F5E56904F4C7FCE59D312DE5F310 +:10E070005D605E8FF6D205C9EBD14E9AECADC474EB +:10E08000415E257E4FDB340BF163C1C6D8EF8C1D9A +:10E09000E57AD9E50B06F69E94C1DA19F04F297F8F +:10E0A000C72A737EE97F1CF0E162CD86E707BAA339 +:10E0B00076DFEB96CA89F703FE6F135DE5B03F5537 +:10E0C000F9823B065EA9E107F02AADFA1CFDA62500 +:10E0D00024CCFCA6DC2FAAF84F83558C9F5EE4FA73 +:10E0E000599155AB57562618383FAD1F7F3B1D3F02 +:10E0F000D4DC2B13FC4121292C4A6CFFD06E047C0C +:10E10000D885F8FE74FA638047821DF51EE0ABBB2C +:10E1100054F8B170E7968ACEF49F77DD60F77742C6 +:10E1200012B1A9F9B782270A3FD6AF6F2BC75F0597 +:10E130000F4746E5D4D6046E1FED49FB2D59DF8C01 +:10E14000F6D137147A067C037A5EABE0DB20037BE2 +:10E15000374D4BC7C3BF23FEBEE79917D2D1FE9000 +:10E1600045E916DE5903BA8E8117BF6DE103FEBD86 +:10E170000931E4C145C1FF8BA49ED1F67BCE8DEB66 +:10E18000375BD5CFCF389E5F97FDDD5D31E01585DC +:10E190002BE90CF850447706E04036092E75DC7BFD +:10E1A000F22666E7AFE7F055BED7EBE03D3AFABEA0 +:10E1B0005C3D8377931144765A90E905C430AE33C1 +:10E1C000C8F90556EF38B4B7AC37107C4F55C84185 +:10E1D0007C4FAE7AEEDC574320B5F440BF09711B8B +:10E1E000008F163CE5C6F3E0CA972C8897E71258D3 +:10E1F0009CC4CA2A99E1A75C89F875F193E2EEE024 +:10E20000770950B9DE3B86DCF9AD4E9EBFCAE5A862 +:10E2100082773DD631BCAB92BCD644155E6E27DE0C +:10E220004CE6EF6772251E3E46F1C83548C1A3593A +:10E23000F47B8FB56111F68BEEE335A0DF9EEB9A90 +:10E24000909FC5DB47C5BFA6ECA7C2E787DBB4F745 +:10E25000FA641B5B4F729C7880A89CD3F26578FFB0 +:10E26000CF36544B0F70E552594F23874B3CBA9829 +:10E270006363EF3E57FC75C38340CF15EBAD9E95AE +:10E2800024EAA751FCA7CA3C3ADA048D3F47EF675E +:10E290006934FB536D2ABC023FA01BF93DF3AB2848 +:10E2A000BF8760C93616E7B4078A808F9CB506D54C +:10E2B000F7776F958857CAA470B565E0BA6F0516F1 +:10E2C00042F3C9CB8DA4173D775D1F71E0B083D6B3 +:10E2D0009FD0142EBC9D2E718F313C6D12D87D893C +:10E2E000B718F40CB4D103FE37B07E89AB5A33CFE4 +:10E2F000811CDECAFE54FC754E5A2C3F8002C77842 +:10E30000FB3287C3C3C9CBF5F46FE1E59FB69B7EB3 +:10E31000034EA0DFBB48A01CE22FE8011DE3D65A44 +:10E32000E8971ED8A1FF029B967E957C0CFA2DB033 +:10E33000A9E9371266F4CBE9D459257B63E92DD3DB +:10E340006DEC9CECACCACF0679E4F461D839D00D01 +:10E35000D2FB024AEF40C701A0DB8E004F86673D2B +:10E36000BC9518EFD8A38AE9E3D713D97A17DCE96B +:10E370003D00EF252FA0E7018156ADE4F41E1FEE0E +:10E3800021A7C0E49B13F8CC5DA3C2B92087DD6050 +:10E39000EFE888BFFA023765F428120CD17D77DFE9 +:10E3A000208C7F7CF2C2838F01DF586FC37B4F8A42 +:10E3B0005C4A4DF017DB86C6A76B8A975EB0572D77 +:10E3C000F9C2C6CE8D71FCE2A3971B48AF24C4F3FB +:10E3D000A56A3C1FED6B1201AE4909FE34399190DC +:10E3E000D5B69C31E66E747D1954EFA5F9729A5F2B +:10E3F00007F6B70E61C2F315B64EDFDE5EB77A9D43 +:10E40000F72DB0D7BD94E05D09EB82380048EFEA04 +:10E41000D224227F6BA75FBF14EC77743DA7EFE98E +:10E42000F7D22CFA75F67DBE0A2855ECC9C3B93D62 +:10E43000B9B46E10DA995576E50DB0FE7876E5B68A +:10E44000C67570BAA7F88DE73F47569308FC51E1AF +:10E450002B5B6C1D383E8709BCD7AED017F025D09A +:10E460007795F802B03BDAD15F11447C85BC333339 +:10E47000CA6FD6551A62C63F55DB6C1A7A51F82915 +:10E48000A9FBC7EB8F29EF2C32FE5AADE6AF5595AD +:10E49000A75399FECADE2D5BCA6D001B567AFED8C3 +:10E4A0002B397AEF7984C91880F716E981CEED52BD +:10E4B000C54F0A7542C80E71795FD222C0A32F0DD5 +:10E4C000986EF80F5F4106D8594E1A90FF96F07B70 +:10E4D0004D59DD09BEC353CBEDA3D9676C5EF0FF88 +:10E4E000370A66E49F8DA7AC0190AB8D7603DACF37 +:10E4F0000FEF33215D5CEB65E5F68FA0C64EA2F809 +:10E5000073AE1D9B9304FCFF79EED77CFEBE5BD0FF +:10E510006EA9D8732589C2BC0384E9B07B9939CB35 +:10E520003BA3BD55B1EFA69A67092C8888F52F99B2 +:10E53000D9BA5225BF00F6F12D6DC43F9CB1191513 +:10E540003DF82F00DFD227C24638E72A7AB022AF43 +:10E55000BB37F438007110DD0B98396D4B83C10067 +:10E56000EBDB42D12831A3355EB5E04FEB38838B2E +:10E570001AB9B486C519B4E479BB5FF03883D167A2 +:10E580004FBF8AEFE999FD1F6BDAE5A75863BDD34A +:10E590003D7DF963D83E1EDE4F37B0F779F4DF13C7 +:10E5A000EC9C6F4B655DF07ED4DFBE9FE08E61C753 +:10E5B00099FED7D9F87B24F476B7E8F8FFE1C9A330 +:10E5C000FB26DBB9DF2F9DA4835FAD2D3FA67EDE4A +:10E5D00027647FB758F2491F67A78CD7BA3D3B978E +:10E5E000B5D43312FF2E1BEB3753D5EF283BD37F27 +:10E5F000A60B04E3DFC95704E5B4822714EEDDED72 +:10E60000B47CD83B67065BD1CFD324021FB876B267 +:10E610005757F4AFC739872AF321C4DF3B561CC7CD +:10E6200074788727C6FA46D8997C9E2E333F85702A +:10E630005F6FB40B4CB7980475DC7E6F65BF74FEDA +:10E64000D88396E178BF11ECF9B1E0A7F7D3F606CD +:10E650001FEA5006174F0C7C52FC820A9C2BB2BD5D +:10E66000D912B3A7E13DB5642FE39FC90504FD6B43 +:10E67000C3052FC263BC3D03E7B785C7C75D3BC673 +:10E68000E2598765BBF1F73C51393116E03A9A847B +:10E690005F35A8E2AD143CA97885CA638DBD31A071 +:10E6A000394F27723EEC82F72654F5DC4F000F8875 +:10E6B000CA81AEABCD9A7CFA321791547222D19BAB +:10E6C000A6C977F5B9AC708EEA5AE0D6B453F04ECD +:10E6D00089F7C39F6458B70BDF3DEAC0E7335CF0AE +:10E6E00023DE005F033BF202BE9F74BDF371BD05E4 +:10E6F000E16B6ABC51D6DBD6BA4EAF70232F3CBB60 +:10E7000082CE97F28539EB32CAD310EE2E02E78B18 +:10E71000732BCCF8FD61DE3EF1D959788F3671B597 +:10E720001BEDB889DEB2B7E09E4F62991BEF15CCA6 +:10E73000AD1404B0F7503E83ED36AF7061AAECB76C +:10E740008B960BB6E83BE3F1E4D75A7BBBE5D75A8F +:10E750007B0CF965307BDE06BFFFE23AD10D78B164 +:10E76000AAB003DAFD3654B3FB6E87EA58DCDD86C7 +:10E77000E94C8E28E35E79CD89F2E28AF2FB54BC43 +:10E780005FA64EC178802F5381CF6EB3F99FB7AB90 +:10E79000F8E586BAA116FEFEB246FED01F17DC7F52 +:10E7A00040DF9C007AD2A0B5524FA4FB1761BE6433 +:10E7B0005E78B0A527E0A9FF7D78A7F4DAC9CFD2AB +:10E7C00061FF143F9FE20754C651FC8482E0DF6E74 +:10E7D00057F1A9D67E40ADFF4A7498314E374B644D +:10E7E00071BA2A394B601F57813E48F16CD5292BED +:10E7F000C263D5578CDEE83C5F85710EDB8721FE56 +:10E8000028F294CE73E0BB243ACF524353BAFA9D18 +:10E8100052D53CEB6E3E4F5D1C2B9F97689770BEA8 +:10E820008DC4EA8179D51A3D27FD2067AF58D19E66 +:10E83000D7E8BDC302EFCD36923B2CF00E6DB5CDBF +:10E840007F14F643ECD6E4003DFB50DDE0BE30DF44 +:10E8500078FED8265BCE31A84FD7F7474847BBC2D2 +:10E86000D77EED8EAEEF267EDCF7A1FE3758FF5F38 +:10E87000BEC9FA4BE1F767300339EA5302E7BB7AC6 +:10E88000BC12EA0E7C01F143947E306E33904E82CE +:10E89000AB289C2A0630FC227309FFFD395A3CD86C +:10E8A00066F335C07C14BABB097C9A609D1B6DBEB3 +:10E8B0006648611E700F84F299CFB8BC7AD568881B +:10E8C000EA5149498C5F3525128CAFD1FBC913ED54 +:10E8D00053FE01ED52FBF80557FF6F84E792E3A664 +:10E8E000F00B615C84720F7531F87321BEAB466E1C +:10E8F000D0FE9E1D2D1CAA6D3E8703FC3839EC3DD1 +:10E9000039C02B78FFED26F0E8E04078F85320B5C9 +:10E91000CB145F002859B3D200CE8D666F2AF895CC +:10E920007697333834BEC3E0B0E7AC01F1F839D2A2 +:10E930000FE92ED3D0FC20F44FF9477758D7A8A67B +:10E940006A01CEBF1D8BDC06E0B35D9A3CA2E1E616 +:10E9500078DBD381FCDE7F8B83EDC352D887C1C7C0 +:10E96000987DE62678DBCF91F28DE03ED891D27E7D +:10E97000FE42F16AB8438557ED8D9B12F8FD497D43 +:10E980007FF43C84FE83037B4CC88F4A76B3FBA2A2 +:10E9900025FBCFE3B9BB64AF0991326FAF85DD7B57 +:10E9A000A861E557B263C70178E1978F817CA87EA3 +:10E9B000C4A395BB0166AFF436BB7A8951BF6AD256 +:10E9C00004768F60158F4752FCAB0E8E6749DD7C55 +:10E9D0005E902B49F904EF13386C2CAEB0F57D0135 +:10E9E00046B729BC9DCBE51600DEFAFB0329F09E55 +:10E9F00034F38F23BE8806AB07E47E5281AE9EAD12 +:10EA000000FDAF29BAFB06F31DDCFF6A2469C0478D +:10EA1000AA2DB1EF097DE650F43A2B9EEB243EAFD0 +:10EA2000C376237BE7C56EC6752F49244985989721 +:10EA3000509EEBFB69C12BAF41730F25A9C0AA798A +:10EA40006721C5D74193EF38A3B3A67E277F0F4D2B +:10EA50007997A27E9AF26E65999A7CF7E57768EAD3 +:10EA600067508453E77BAE1DA7A9DFBB728A267F60 +:10EA7000EBC6FB35F5FB06676BCA6FDB51AC291F94 +:10EA800050BD4493BFBDF6314D7D318E9EBD87C3D1 +:10EA90005954F46CFB103FDE3BB29B0593EA3CF704 +:10EAA0002CAF97ED284803FFF76AFB9834386F1EA8 +:10EAB0004E1CE60CC7E85749BFED396CB743D0D8B8 +:10EAC0005773B8FDECCA41CA45E0F7591CA27880DB +:10EAD000BFBFC9BFDBC1F5A9596EA8CFDFB5903C58 +:10EAE000B88EE90E33DAC5F4FD3FEB706BEC758A36 +:10EAF0005E2F1A3CAE42213EBC3E6B27BCF67E47E1 +:10EB0000F03AA18B1752CE6FFA76571DCC7E4AF998 +:10EB1000ED07C00F5BCE69A449F4E139EDB32B01D9 +:10EB200002FC94A0DE124F0F50C61704DF5FA11F36 +:10EB30003D3FF52D9FC7CE99062FDED78A777EBB46 +:10EB4000CAD71F3DBFE5CFC0FD48346AE0F4B71611 +:10EB50003AF76ACE6FAB1387E1F96DB5EC4D6BCF29 +:10EB6000F9ED6FC0938602DCD9BEB6ECA7D1E3669F +:10EB7000F73CB5FA4B6B7D9BCA3FBACE0DA0C709D7 +:10EB8000A0972531FD7B377B0F4019B71DFAB6E4FE +:10EB90006C87BE6D229EB59288FB657532FD7AA9A1 +:10EBA00045FC56FA7592F31BC8BFF7640FC6FFBF4A +:10EBB000374124F02ECBB582E1788F3A1E3E7EC0DD +:10EBC000ED2FEF39197CDBB25FBCB7A2E8A6F72FB7 +:10EBD000DE1BCBE22CA7E8DEDF1DE164783095A7D1 +:10EBE00014406887B8FCBA1DE3E52F8FFB107F6FD8 +:10EBF000D2E59AC14302F87BC23CCB20DE2660B34B +:10EC0000A37D6FCAD8A143CAED2A3CE2BF8F2CF77F +:10EC10008D771C60BF99B2AB674AC0161F7FA6F202 +:10EC2000F511297C0BC653BF79117F5FCD943DBD93 +:10EC300053987D511B9FA6B7FB4C595E82F8A6E402 +:10EC4000174708C6A3B5E42576DF787144C2F8B546 +:10EC50006ECE96F8F6F49BBD9BD65E78EABF2BF09D +:10EC60007C6FEC45766FDE125BDF58E1143476245E +:10EC7000FDBD9578F731E6F1FEAF158CC0FBF7537B +:10EC80008CEEDEEDB1532970AABF713E01F8C27E51 +:10EC9000B80F13A3FF879C8C9FEDF77E920466E963 +:10ECA0006C73532EE07F36B783C788D75F0A7434FE +:10ECB0003A52F09DC4EB3FE1D4C6EB1738195FD14F +:10ECC000C7EBB775DF68B231B67C9BC1E14EE1F7A7 +:10ECD00021D0EBD2CD32C6FBCDA7730880FD6D8B62 +:10ECE0008CF6B7F76F9808F841CE6F927F09F169FB +:10ECF000459B7B6E7E96E68BC69AD06F337F0B7BEF +:10ED000087848CB504C12F5BB4E5D1547857FC538C +:10ED10004AB78BA8D2347FF373180FF3FED9A7310B +:10ED2000FEFA22D033FD5EF4D593D301FE7B8C95A1 +:10ED3000B70DA2E9A29D82E6FE447195459357E284 +:10ED4000FE94FD2342F45E859BCA91979CDAFB53A7 +:10ED500083A3FEAE979CE8EF0A639C7CC904767F90 +:10ED6000EAD039767E3FD28BC50586C6DE5B388811 +:10ED7000AE636C0A7BBF451F4748C03906EFABF056 +:10ED800038DFB11F4B2DF75C58B9D796AFBA3FF0BB +:10ED9000D68A32DC97B13F637693B1192CEE3D6E83 +:10EDA0007C615AAB7B007D406EB68A2B8CDEEF39DE +:10EDB0001D0B6F0EE9E8FAD039164738EF187B3F84 +:10EDC000AB2DBEF9019FF7FB67FB3DF06B0A8FF798 +:10EDD0000B18177FFFC6DD6BF07D1A9F40209EF356 +:10EDE000FC8DD8F7C8529C8ADEE46FB96F03FB3301 +:10EDF000B560414B1EC8F21EDF239AFB38EDE737A2 +:10EE000037E7274F3AD93D4A3D7FD7E3FDFF29FE3B +:10EE10003E65EC9174B89F4FD397F09EFE2EC61FAF +:10EE2000F574AEE7E733747C30CAC70D9A78E319FE +:10EE3000C00786AAF9B911F9FCFF00D1E7EDCB00B4 +:10EE4000800000001F8B080000000000000BDD7D2B +:10EE5000797C54D5F5F87DF3DE2C496692C96412AD +:10EE6000B2336189A088C3BE457D098B51080EB8B5 +:10EE7000A1824E02216C21816A456BBF1948C08076 +:10EE800060635D8A8A76A041D1A20D8835D6A01331 +:10EE9000A5086A357EC5AFD62A0D82088812412D95 +:10EEA0006DA5FCCE39F7DECCBCC984A5B5FFFCE26C +:10EEB000A7BDDC77F7B39F73970914319DB9190B80 +:10EEC0000CD782B50A631BED7EB33395B1A1F66012 +:10EED0004A2163ACCEB921C13F80B1941476ABCF47 +:10EEE000CED869FCBB3C9C76D88BE2B0FEAFE2FC8E +:10EEF00076E730A8F75666114B646CC8DB4D8A1F65 +:10EF0000EA1F53D8B4A618ED4EC5991883FA5BCD05 +:10EF1000BC7C2BD61B102ECF74169E8A837EB7D94D +:10EF200020857A8CD99C07FAC1BC988925A98C9533 +:10EF300028FE4C1CB7D2D67E5F29942EDCFDBD0581 +:10EF40008AD843167FBA3614D69369F16ECCEB3A61 +:10EF50006E1F271F376D4911DB3F8431AB8D05E2F2 +:10EF60000633A6682C601E8CE3F8979AA0BD368DF8 +:10EF7000B155008F3D3037ACCFFAA59B581A633F8F +:10EF8000B131FA0B14319C0C0B7C161FAC85714E01 +:10EF900031FD425CFFBF987E11CEEB13A60FC0BCC3 +:10EFA0001CB74EAC533331FF9618F028772A7C1CDF +:10EFB000E6CBF739205FC4FC91F090A9CFA951BDF1 +:10EFC000C2876FCC6D87F2CFF7DD94CB20DDF1D017 +:10EFD00088A4F618F565FA8B9A6AEF38687A6F8D0F +:10EFE0009FD224C6749CCF9A9A39DE717D187342E1 +:10EFF0001EE7556EF1E52747F433C499CC18AC27CA +:10F0000071D4D6B65E40270756AB4EC503293315DB +:10F0100063FBFDC1A4E26D03783BB7A11D9FA70A66 +:10F02000E4C57AC3BAEDDA3FDA05EC4E335C2FA3C0 +:10F030007EBB5B67B9C09385796DD8DEF2D9553652 +:10F04000D60BFA537427E6253D8C8211901EEEC133 +:10F050004FA3605CC57FAB93DAE929B2FC741E8EC6 +:10F060005F4C79393ECB763196D13DBC98A2CFC268 +:10F070007E0E31BD1CD3664BE02227ACB7399ECD46 +:10F080008945CFF3117FB09EFE4E412FCCEE3C78E8 +:10F0900091180FE6F76482BE10FB3966F355637A68 +:10F0A000595647AD8A7413E714F5DB19E21DCA6F90 +:10F0B000C77296DECEAE06785F06935D05D9970FD0 +:10F0C0007DC63C00A7C48E03CC03E32722FE62C0AA +:10F0D0002D2199C3ED0F8C15C7E63B4E670131CF4B +:10F0E00046E017933BCC2F4F41BB2D0390EFFC82A2 +:10F0F000EFF4AB503E34FED2A5AC82F25EBAC784C8 +:10F10000F4E16E637A10E121E02EFBFFC469A17E79 +:10F11000910F9533F0E143E7C9878DBF9C648AC3A3 +:10F1200079DEC5BC7D3D58EE596683FC138B9DDEB0 +:10F130005590EFBD1A080DEAE72C89DFA042FDA02B +:10F14000E0A79E0FB26571503B6F5D8786F261D27A +:10F15000DD6D9A0DEAE7D5B56B289F5EBAEBD15C01 +:10F16000A4ABC39F5FA53AB0FF6F64FF0020E0F738 +:10F17000314E8E4336B2B427E2A709E79D1AC15734 +:10F18000F1FEDF22BF5F56DD31D60AD57297300D12 +:10F19000E5E561C5FFEB94DED86FFCB4E000442FD9 +:10F1A000A7B7970E1EE95F06F9ED92DF95A24C9680 +:10F1B000CE5841A399E059D0F8D02D08EF82C62B44 +:10F1C0003405AA3CA185140DD759AD6B01C8BFEB1E +:10F1D00034D3F8873F9FD753C1F9FED9CAFAC68006 +:10F1E000EF9BA2FF2681E7972DB1E97667A7DCE1C7 +:10F1F000FC34862952BEEE443A04F99AD81BE0B199 +:10F20000F0CEE3245F9F727A68FC27B4A69D993400 +:10F210002FE60DC0A7799BDE23792FC791F5E66F06 +:10F220005EBF02EB65DFE61CA47AB05D7B1CD2CF2B +:10F23000F7711C5FDFDF191F5CAA10FD0FF25D1C68 +:10F24000830F59C86A4A270CD878AADB4C2301AF30 +:10F250001D1D8528F7A0CB65C89757257B681DB273 +:10F26000DDFA0E673CF2CBD9F4C14181CF73A5C35F +:10F270003792B9DC0A74D59B47115EE7A1373B840E +:10F28000DE3CF16FE94DA12FA5FE94E54A32C7E7B8 +:10F290003DCE6EF5A6923CACABDE74B3E0BD03612F +:10F2A0003DECA8C9BB91751D3720E4DBD178DD9A10 +:10F2B0000C6981C27C386EE2D1CF98122187160B7F +:10F2C000BEDE2AE9C0C56E9D12631D95A23FD3F430 +:10F2D0000E4B3BF6D3A210FD775DAF85EA815CEC67 +:10F2E00081F3BEAC27C84DA5ABDC8C818F5CAC9F95 +:10F2F000F5B6FE3A12C9E8E4C60440FF99F0D10B16 +:10F30000EBFF2A4EEF8DEB93F01F7C5ABDD537A053 +:10F310002BFC2F1470BECCA1F7C7767F137CD61DB3 +:10F320005E4625737BE6AA648E97AD0E512FCE58AC +:10F330006F6632874B45B2912F23F0372A3986DD2D +:10F3400023E5F0D1785F0196FFE1D0D604A42389AC +:10F3500027297FA2F115E6B3A5341EC0793CB68FEC +:10F36000D63FB27DB41E0AB70FD0BCD7231D21BF34 +:10F37000211D79B89E583F203C3F49E77EB1CE1F02 +:10F38000E2F52908BFE8793A8F9A9433CD33B9C3AF +:10F39000AD20FF27EB4E4A5F3E6452705ECE0E4DAD +:10F3A000C17939857E8CD683202E045C793F6F0825 +:10F3B000B9B1E2AB99E988E71585FEF46AA83FD9AF +:10F3C000A1CF4238DCE3D4CB717EA50E7D36E64F6B +:10F3D000C571FE1F95ACCFC1EFC9C28E8A9E67B5BD +:10F3E000C01FC0B30AEB258E6301D487979FB40773 +:10F3F00041C4020860DEA01F12756711EAB1C4752E +:10F40000CC8B749A92D0D16A857CC743CCBB01F275 +:10F41000F9018FC98AFAED367D19A62BBE52C9EEC5 +:10F420005C51C882CBA81F6E87B2BA5E41D2DFC0E2 +:10F430006F91F4BA4CC079593297736087D42473B2 +:10F440007E5A9A1C6187483EEACEAE88E0C3FAF342 +:10F45000E4C35FE078E7C1870F083E7CF05CF8F01A +:10F46000B1301F3E8AF5CFC687CF083E7CE32C7CA7 +:10F47000B85BC0ED5D513F061F3E138B0FDD821E52 +:10F4800024BD231FA2BE0F2577CACFDFC5A2F77305 +:10F49000E0CBE6E473B00B3BFB3B47FAEFCEFE1B41 +:10F4A000E33AB3FDB7C7EEA4F5487E067E793399FB +:10F4B000F48EFE16C205F8E56DCE2FB1F9AB53DF21 +:10F4C000747039C1584302D28F9CE7E702AF00AF96 +:10F4D0000FB01FC967D24F91F0EBA40761F71E155B +:10F4E0006962C7670CE502C06D6F24BD3E25F82533 +:10F4F000309211BF8047558476E54B47C18E44ABAF +:10F50000CFC5E75BB0B6ED756475A635244C757450 +:10F510000FA72217B773BA83138C7F2C963C6D41CB +:10F52000BCD9BBDAF3D1F8FA44ACC7E952CE88AF04 +:10F53000B3CD43C20FE77109CDC3635A15A1E7CD1F +:10F540002E45F2B7E682F4F2711D2AA3798512C026 +:10F5500085EA94A72C1BDA0FEDDADE1E6E6F77C1F9 +:10F560003C2FD7A1FD80707B189FE45DEFDB409EB0 +:10F57000919DAC9B503FADC8E3F4104DF78D683FB3 +:10F580000C88C0574326E1EB3E9B3F13FB6FD43CF6 +:10F5900026B4EB1AEB9D4A80F0581D8FF463B7EB4D +:10F5A00044B731E490C7757E72A88F8BCBA1BEAEF5 +:10F5B000739043035C9D72E822ACEF3C8B1C1A23D2 +:10F5C000EA17B8B87CE94E0E5D26EA1509F8C69030 +:10F5D00043635C31ECB96D369DFA8DC1A79763FD2D +:10F5E0004CA7AEBBB85E2B7445E835683716F3F709 +:10F5F00089F6AB1B4CFDC87E66F1DE587E86CF6572 +:10F6000037D829970AFF81B5FCF3F7770D67AC0A65 +:10F610008BF83C7DAED4B03FD1D8F0591AE21FFE32 +:10F620000C7195079679DFED83787B476568873E97 +:10F63000F03FED168477737CE240764978DCAA7F50 +:10F640000041A6005EFE61A254E27161CBD2210CA2 +:10F65000FC88C2FD3FE4A25D796CDF3F283ED261A9 +:10F660002FF3E3F83BB6F338C989B767A6A07D2E20 +:10F67000C75F8CF882798D5707348560BDC777598D +:10F68000BCA86F55E6F95501CCA76A979905494E74 +:10F69000311BD637F3E932F3AE156D6A22E6B58039 +:10F6A000886F28A7C99FF12421DD9A77A90CF990CA +:10F6B000B9797980D9969E067F3369A4897922E247 +:10F6C00021C97A3CF344C427528A5D867CAA2FD391 +:10F6D00050BFC7B45E86F20CFF8586F2AC39830D4D +:10F6E000F99CEAD186FA3DC1DF89CCE705AE32D478 +:10F6F000EF5D3FD590EFDB7093A1FE056BCB0CE582 +:10F70000FD83F30CE515BB9FB7A05F7DD1A6C58631 +:10F71000EF1737DD6568070069EB0374328B71F80A +:10F720005FD2BCCC507F56FBBC4948B78342AB8C00 +:10F73000ED1ACC07383C030CE1F905F35B90CE34AD +:10F74000D6B1330BE0BE30A87843506D6E735E6F58 +:10F75000E4872FDF2CDEA50C8479ADE5ED643F73E3 +:10F7600083C6FC7C7533F14F349EAB58AF24CF5029 +:10F77000A40395059530DEE76F32B66718EF827601 +:10F78000F3C57AA2E9E20B56FD7001D247406FEB58 +:10F7900093165EB799350D0FE17741274E412772D9 +:10F7A000FD72FE72DD4EF80FCB41E15B90CE663705 +:10F7B0002BEC51A5EBFAE6B4DCBF222BC63A190BB1 +:10F7C0005AD0DF8E9EFF0E97C37D3001FE91CB7223 +:10F7D000316EC5BAF0879DE4F1F1756AD00A74AD57 +:10F7E00006FA45F18771FDD1703C5F7EF10838580B +:10F7F000D38DFC12E7898FA6B7E121D615AE09FD9E +:10F800008C7C24E128E1EAF066C6A42B0FFCC7E15A +:10F81000ABB31F13BE1D08DF8BC2F03D66F39F40E4 +:10F82000397CE2A36F55A23B7FFB10D463DDE9A5D1 +:10F830006447D1DF44FD5CAC5F9500723109FAF991 +:10F84000EC877CE4B74EB9BCA4CC3B0EE4A2A2F892 +:10F85000594A6AF87B9BAE3A8602BEE637AB5ED465 +:10F86000C3C7347BBD72092DD3E34C43252DF1C6AC +:10F87000F128F1A6B4BCFE7705E0056DFC168CBF3F +:10F88000167B6D384FC6A6539C5301F7E67402E908 +:10F89000D9C414D2BF3AA3F8DF71E6AD85FE6A1D64 +:10F8A000BFBFE82CF110570AD90FFEB478B43F3A25 +:10F8B000DA4F3C87DD6B6D4E1C678ADF4FEB198199 +:10F8C0001304BB9A39014E11F12268978DE34E79EA +:10F8D000FC9709680FBF74E0B84AFAE51337D9C33B +:10F8E0004F315F7F940F5DEDEB00E93D69AF837FA2 +:10F8F000D43B85DBDB7D5322FDA34EBBFACCFD80E0 +:10F90000DDD10FED99EE52E53595F4698712EFDD03 +:10F9100010439F8E4C31EAF94BC3F1B8912911FA8B +:10F9200073E1ED2776E23C00DE63709E0E07D8356A +:10F93000CA39D93597633FBF4A4824BAEED8AD06D5 +:10F940002F8006C76D9E2417DA9142CF2A1AE8103D +:10F9500057843F6B730DD0866079FF2416C34F9197 +:10F960006911D64B09E75F8B33FAA32B06F3794D68 +:10F9700011EB5C29ECA7F2146EE754611C2E251CD8 +:10F9800087AB9AC6E3CC0F45C52FCB531C547FA53C +:10F99000BDA81CD7BF224F21BB6985A218F6915282 +:10F9A000530ACB71BDB78AFECBA16F1CF7A95E7C51 +:10F9B0005EEE28FF3D0FEB0FC394F70B9CD41FE9BD +:10F9C000CFA2AA31E1392F45C4B1E399B4BF896F01 +:10F9D000260ABE9920E4E5957D415E1273E993C63F +:10F9E00043F93851CED4757BAC503EF10233433AE3 +:10F9F0001B877209E5BCD3FC597BBFB09C9FD0AF7D +:10FA00007A078A872BD2E17B843C2966BE2CA483AB +:10FA10002B3DC6EF13F74C388CFC3A9169D40F7D1F +:10FA2000CFE3704D7085E97D594AA7BCF79C06BEAF +:10FA30000EC5FB1F28C1F8C39F54EF066AD53624B4 +:10FA4000D22FFB85C0DB6AE1A7E03E12FA1F2E91A0 +:10FA500046C3E717293CEEB0DBEEFB05C2F3214BB2 +:10FA6000DB4F70BE214B7B6D128EF301A37132E729 +:10FA7000E8AD981FE6F3308C13AFC863762FD2E75A +:10FA80002013C541DC7EE7380BE4DDEB14B4849928 +:10FA9000596301C7E0B05C684EC913F3AA6D4D828B +:10FAA000FA49EBBE61BDC87F708E73A21C9AC56215 +:10FAB000C6359F167431E5F15E1AFA614936450F75 +:10FAC000C658C7D302CF201736E13A2EB7ED1BA296 +:10FAD000907EE07E07BAB2F47F074CC18D4AD7F61C +:10FAE00076FBD8E7900E251D5FAAB2EA2D764E5F11 +:10FAF0005322E458B3A4A7738C470F9BC362C64D2F +:10FB0000DF17782AB7F95EC1F90EDBE3A1FD8E0A93 +:10FB100029EF679998067478A320C31BD7B5FE9D7B +:10FB2000EC8B1F4E9F56A5DDCEA87F86FB0F150BD5 +:10FB30001C41DC8FA868C90B50BC698E42FB245560 +:10FB40002DEFF9305F3174A893E46482A21CEC4776 +:10FB5000263FE37251630725FDA90248D0FF34A177 +:10FB600067409FAC4E807555AC5BDF9A01457F01C5 +:10FB7000C301F1FF9089FB7FD1EB4A8BE7F059314C +:10FB800005FCE04128764FACDC918D78AEBE50F19B +:10FB900082B1B2F4F8EE5D978AB85826961FDFADB1 +:10FBA0004B3F3293A61162309FA7E23BF3BA2D9DE3 +:10FBB000E481CC0730DF88CC361AECB5078EEFAE87 +:10FBC0001B40F44B7A8969200F2E0EF3FB47AAFFE6 +:10FBD000A39FC1BAAF0365BC6430A61A9B4E784A96 +:10FBE000A7755E2BD619F807530EDAC270B9AE6549 +:10FBF00037C1FB23338C07CC632EE2A031DF954461 +:10FC0000FBC9603FD03AAFB7358C47BD7ECCD2310F +:10FC1000D08BF184ED1FE60460FC4F7F7EC2C18073 +:10FC2000EEFEAA7538F0FBA1BBDF77E880DF4FEF6F +:10FC3000568B917E6F117A52C22DCECDE9E166B717 +:10FC40008FB9511ED69C1AEE8F8C0B2D4925FD368F +:10FC50003708338CB097E66F4A400BAE335FD994C8 +:10FC600062C84BBD576965D5B1E2A097BA39BEE607 +:10FC70006E5E6FC9F2E0F87E178E7F08F40BD2CD6E +:10FC8000A16D8E20FAEF723E659B0759D09EFA6BEC +:10FC90008B9585D03FD3DACCCCCEE5A602F4EA171B +:10FCA00074193DCF9DAF24507FE50F71395B0A6316 +:10FCB0002D01B8FA5BE6923C8D5E47F9A79E093D9F +:10FCC00000DEE52BC172F1F0FA7703DEFC4BEEF9B2 +:10FCD00006EDD3E87596068CF27566BD312FE57E8C +:10FCE00085C037889B7AB4F3CB1B8CF52A5AEEA5D6 +:10FCF000FE2B502ECBEFB0FE216E61170E67235006 +:10FD00000ED7DA7B25F9CFA0678FD680419ECFD85A +:10FD1000911A1BA5876A18A5CCED217C2C6879EF78 +:10FD2000A748370B9BB758B09FBAE078279033B3FA +:10FD3000B600C7A33D8DFBE3D07406EE8FC33C6BCA +:10FD4000712219B87FEE1BEF067C999D51FBE5628D +:10FD50007DD305FC99DD45F4351DD73310BF6BDF2E +:10FD600046AEE7F8AE21361C77B25CD70858977AD2 +:10FD7000EEEB92EB91EB93E595203763C90549DFF4 +:10FD8000CCCDF5CDACC6292B320114B5DBBFA038E4 +:10FD900000137E8826F0A3D957911FA231F033F8C3 +:10FDA0003AB91F12607B58049D45D35105C2019991 +:10FDB000D8C9DBD9847FD2493F2D6B081E12CFD022 +:10FDC000613ADFB70CA5E3BE25D0D181283A32E4F1 +:10FDD000CB1B8CF9AFCDEDB9C8DF402F0722E1FB7B +:10FDE00075D4791999CE70F7E2EBF7E8139C505E61 +:10FDF000CE7C2B9CB4FE06E2C3435AC3CE9F21DFC8 +:10FE00003572BAFFABC0FBC76E5F2DE29D69FA4049 +:10FE1000946F45CB325437D42B5DAD38919F66D665 +:10FE20000D9A807C3898E9D4DF8C6EECCB8D02FE85 +:10FE300065D5666601E3A0CCC348AE956D53833C9F +:10FE40004EA7DB4B00BE73041E2A576EB164403AC6 +:10FE5000A7BA82DB3D41CE2F0057B27BE6AD6EA53F +:10FE60003802F85131F94DEAA9CA266379155B4D7C +:10FE700078A88AB27F82921EBDCC8BF4E8FFA9C31A +:10FE8000A6249D7DBDAC6B9C88E248C777F5257B99 +:10FE9000F8B8C7D303EBF901E76D68E76BFE11F81B +:10FEA0001DE044FAB263694210EDFD7D27C18F4524 +:10FEB0001BD4E91F6101B8B47F9C437A5CD2A75C74 +:10FEC0004F956D35D1671533FAC9A5E09061FCB740 +:10FED00074634A10CF0340FF039BD18EDA68263B40 +:10FEE00029C016A733A033DF7233C9C3B2E664F268 +:10FEF000D3CBEAF8BE51D9E6E4A0CAE30F7B30EEDB +:10FF000022F1B0AF6EAC2583F094E745FDCB9ACDDE +:10FF100006FA96F889F673E7D5B7EE4CF7741F0723 +:10FF200089C0CF816EF07320123F7BA2F0C3EE4EEA +:10FF3000E17266D11FFBE23ED9F1EA38AF1AC36F16 +:10FF4000927A886503010E0FC7138B33393E98E60A +:10FF50004D437C9E583D8CF0158DA7E27FCD247CCF +:10FF6000B08F1D0CE3CC337AB35BA7C2F75B15CE21 +:10FF70001F336AAF2C467DFD959033EF827CD22DE6 +:10FF80008CBD07F24907F9F43EC82DCC7F50934E43 +:10FF9000F90F6B3C94FEB9A61FA50784DD27F9066F +:10FFA00008C08276E309C12F27A4FC62B7A5A3E9A4 +:10FFB00050FCAFF7879930741BB8EBAAF160CF5CA7 +:10FFC000AD1BF5DDB46B8DFAACDDEC9C908E76EE5E +:10FFD0004A85F653CA7C630CF599E6B14C417FBD66 +:10FFE000DF90F077B25F3D96A9C0EF374E4A31D42B +:10FFF000BFBE3ECB904F48F5D0FCA614F7367CBF71 +:020000021000EC +:1000000069FA45867CE94900C210A46617E1E13629 +:100010001B13F104178FF38AF334DF568FE871074F +:10002000CCF7DBB7CD541E8D0F89D7596B4DCC0F54 +:10003000539BB916D606FD1E68003C41BB2F3F728C +:1000400030A4E3159B87BC3312F2FB369B295EBBC1 +:10005000AF2EE53EB48FF66D4E4DC438B07F852A85 +:10006000EC08A78545C8ABB1754BE99C4D69D0EA52 +:10007000257B6147E00999F728C8F78CF3CB1E353B +:10008000887139C01F8F673C63A57D884360B7398D +:10009000412F1C52581DA6A85892A0FCBBB6D420D4 +:1000A000F273F1BF543D1DE9E99938B1CFA4507FF7 +:1000B00047DEEBBB6115D197A729447C6B25FF6711 +:1000C000663B5F1F53066721FE0F25333D192651FE +:1000D000B9F8C3BD1AE0696E7EDBC010B49B9E17F1 +:1000E0004ABD01DA1D6D34D3B91BECD709F9CADF5B +:1000F0005AD77339A2F7407F220CCFE0405CF70C4F +:1001000093EFF254C0DF91D9C18124CFEE4E25BECA +:100110008A86FB018B9FE01B403E50C2F231CC67C8 +:100120007CFF10845A06CA9999666F1AEAA703AB36 +:10013000CD647782FE48C4F119DB4A747C40F34CED +:10014000C0751FA8CF6328AFE4B865AB55F2B39074 +:10015000FEA8FEFDAA1F6C0426F554A05EF1B31E96 +:100160005DE9E6278B46F4C0F544DBB732FD1A782B +:10017000D51F612FCCDBAEFAD03F6243DBB56B2FCE +:100180008E5C471DDFB748E7FDDF26E4FA825E6F2D +:10019000ECB59B50AEF74E42BFE7F01E95E8EC7011 +:1001A000AF86E1E9BDF178CC6BC3EF80FC97258188 +:1001B000831AE49FB0FA17205CE79B563FA140BB2F +:1001C000632DFBEF1B03ED8E3C6BF6E2B0F39E99C3 +:1001D000DB93F619847DDD556EE9D23E4853D2D1CA +:1001E0008E7092DEF6D4C120B4FE20CDF366D6B474 +:1001F0001CF1E65CC0BFEF1FE65885719A99C01EDE +:100200009176F77E33B70BFE2795FBB552BFB7A4A7 +:1002100072F932D3C4E99ABDA2909F8AF64E9F0824 +:100220007D2CE5F29A546E4774EA65D644F26A363C +:100230009EDB81F52DD8640D06F3A88D13F97C2E75 +:10024000470FDB8D7202C69D6779F661E4A10AD67D +:1002500046FAF3883938BB2D0FDBAFAF73517BB350 +:1002600097E2C5429FD88081501E5508BEAB6C50A6 +:100270008221E21BAE17CB45FF0CF54C84FCEAAAA9 +:10028000578CFAA45CE8D17216156F6E30EA375FAE +:100290000277E2E7C1B8A82FC3F302FB186036DB90 +:1002A0001FDC3999E6AD788331E651C13A422ACE56 +:1002B0007B33DF77889E57F43ACE759EB3BD53C625 +:1002C000250F8D18376ADE12DE14B08EC08384FBD2 +:1002D000EC0087E7EC1685F0F5B9B0CBE4BE8BC433 +:1002E0007B05F34DC6F384150F82BCCC0BD341A71D +:1002F000DEDF12A4FD952F5943A21DE87EC1DA2D41 +:10030000D78FC276EBDE23FF62BA2BD4D794CC58BA +:100310004AE0F355C53931F655A2EC831F0B3E3840 +:100320007B6DB86807F0286F54F5B881867AD45E83 +:10033000DA077302010BC661E788F8E6D9E659854A +:10034000F5069FCB7C63DB33FFE9BCBF4F15F1B9EA +:100350002EF650DF987E54A71D7416FDFB89399444 +:1003600083FAB7234723FDF3ADE6FDB0D08DFAB88D +:100370002FF905DDC9D7D9420F97A35E86F4E0DADD +:10038000E713D16FFFFCC1E7693FD7F26C7922DA3E +:10039000C507D7CEBC2F002C7570F34CD2C3158F78 +:1003A0004A3DECB744EAF7B16B4B7FFD73A4CF4DE8 +:1003B00071B41F317B875FD8DDE0B7A01C5CAB3028 +:1003C000D20B0F72B95781FA6A00E9AB0BB0DE4F5E +:1003D00067FB2F403A8FF84E7AECA733FD23A83DF8 +:1003E0007386D0EF02C919427D25F5A9D4B39AC905 +:1003F000DF270DE1A5BEFDC19DB0FEAFB6AAE4DECC +:1004000055AAEB739DB8CFD18DDCFEF7E16DEA8480 +:1004100077DE39C0BB0CE14DF60F87F767F51CCED0 +:10042000FB5773B8AFD8DC3B11FDDBCFEA7B93DD24 +:10043000F3D9E6BE04EF59AB00DE64F77A8C764F51 +:100440003DC01BED7C84378C5BB6C323E0EDE5F04B +:10045000AE177A67354F6775816BE01694273FFDBD +:100460008DD58BFAFC505C2815FD91435B5486E7D3 +:100470002C3AED2261BF48387FC71A9E403BAA8BB9 +:100480003D73BF95617C76EE0B8E2083FC11A5B089 +:100490000722E068C31B89385E78FC4E3B665ADA57 +:1004A000B0083BE61CF1B390F9E81EC2C296373E95 +:1004B000423B5ED1B95FBFD0660F21DF82BF73348C +:1004C000529E2B1E94691827F1DA6C4807D9CCE3A9 +:1004D00023BB46EE77F919EE777DDFF79B5B1613AA +:1004E0003F77E447C6C9ABE243668C2F756C510871 +:1004F000DF95B715261632DC4FABA679DC9EC6F524 +:10050000B1A2EB1437B402DDC4C3784BD23C24CF84 +:10051000158F93C711D7C1B88EF07CA3BF4F46D2B9 +:10052000437D6E8F1D77DE98C6ED804AD5447EC729 +:10053000020BF73FE47996E5621ECBD3B81F726FCA +:100540001A3FCF770CCF8340BFC72EB58AF3D9E3CC +:10055000289ED9193F9170736A5F77CA2BE42BAD3F +:10056000231BE1B477F47B66946B7BB12D19D380A8 +:1005700080E168C7F0F6EF98EDF56857DE3CF20DC4 +:100580008A83EE8DF379D0DEDA9B6AF3221D05B6FD +:100590005B89FEEE89E7F16FE64ED2909F6E12F214 +:1005A00076468155C720EFCD05F7F830857102B842 +:1005B00009B1A2F0F5E54847B7A6EFBFDD064B5AF3 +:1005C0006AE2F6CA5217A373409780B98E71583CFD +:1005D00022733AE54C74638C5B2FC0F8EC68C60953 +:1005E0006A24C1D39007B852FEE587AF9BF8603606 +:1005F00063FFCB3C17239E17204C900E4A93C8FFF5 +:10060000BF1AE3C42E4C35A2AFA91A0B98785A8FA3 +:10061000213519379E2CD679DD48164A82F5857624 +:1006200033435CFD8690297401C0ED6A2DD48AF0B5 +:1006300033D93C66F4037CC5CA60F48F172C3BB7F2 +:10064000F9BEF3B07FE283059037F1C38B1D772AA3 +:10065000C10D00A79B81B9912E6FD1D80E7530C7FF +:100660001BD25D95CB13A07A8B14B13FC4E3F91272 +:100670002F83A0FB48F8DE2CE607FDD427627B4BD6 +:10068000ECB8D1C769D2FFE576E67CC1A7F3259D1A +:100690006D36F2E73F249FA03D0B70BB59A4DDD11E +:1006A000F9DF44FF7F1374FEF9798E576965215A8B +:1006B000F7762BE1518E7BB548BF4BE3F6B29C87B2 +:1006C000A45F26E24F2690184847071A6AC95E9A27 +:1006D0001315FF6591712A3556BE53EE984E636A25 +:1006E000E99885F3512E8B237EB9D9D2D4B7DADEBF +:1006F000B51ED8D184A24ABB8DECBF85AC9DC7B3D3 +:1007000084DD2FEDC5B968E761BCB291DBB59AB065 +:10071000C74BC13F43A22BAD8FB077E17F939BB70F +:100720008CC7783E18267EDAB7B0DBE8DCC6E40575 +:10073000463BC92CEC2273945DC4A2CF85083B29AB +:10074000FA5C882AF817EA727F459C0BD184FDDB9E +:100750004947696681CF80611F7E3A6B33F3FB6244 +:10076000227E27F4F378D5DE0FE5CD7425DE8BF6F7 +:10077000FEB14247C09484F125338D371DF800E562 +:10078000C82771FC7CC58CA49F4E463B787AA24555 +:10079000C3F45367AFA41B18CA1B55EC1B0527E213 +:1007A0003E532DCA4D9EBF57CFA62898C86F7C0BCD +:1007B000F767AEFD01E64BF92727EAE0BF1DFBA373 +:1007C000280F401EE975B9E4DBDFF2FC43B2FC7789 +:1007D0003CBF52966FA3F18EAD91FD8BFCFD51E5B0 +:1007E0004BA3CA1FE1F9F13DB64D0C207CC4BED32A +:1007F000F4D10AED3BCD41BE02F84D5F16227A9A44 +:100800006E7A8DA7452C84FB8E67ABB7A8876F0ED9 +:10081000EA67D571C081F6C99D19FA1CB4AFAE4D17 +:10082000F5FB7AA05F3845095870FF714F305FE8DB +:10083000AF98E7E7E7083E5D98EEA3F6D2DE857E47 +:100840006EFC77FA39D5A34B3F653D52CFBF9FDD94 +:10085000E97C7D11FDCCFF77FA1998619C8FB4FF7C +:10086000DEC8D457E0FAD801B7E15CE4FCFFF1261A +:10087000A1FDC8F05C24807EFEB2A6DC21D0FFFC86 +:10088000E75ECA9D1D115F5878D2C474B013AB4E99 +:10089000324ABF6CFDB3C503F359B8ADD53201EA96 +:1008A00055413A36625E0BE4B960D6AE4D8DB05F0D +:1008B000EEED6112FC743FBFC7F5DC61DA3F9E6F5D +:1008C0006A3AF828F2E3681E678C5EDF4F7AF0FD23 +:1008D000BEBD783E20867F727F0F6E8F6CCFD61B99 +:1008E000709D8B5146423AB636F6F98A8F457FD3D2 +:1008F000E3B93C9F39DC61F35C82FBD9FE5ABCAFA3 +:10090000377B5DDE608C57DF915AF4688F33C67F8A +:100910003B78FCB785C77FA7BBDA6E0365C53EF899 +:10092000D5FBF7DAC05F9DF82BD6B91F8C71D56265 +:10093000ABE4BB2313C715503C8FF2CD3D0EDC1B3F +:1009400080F6BBE2F9F99119232E8E4779D09E9754 +:100950006072829C08B84B3FC079CC1871E904FCE6 +:100960005E6875E497F2FD03A28B80DBD784EBC64B +:10097000FA18BFF15B783CCFFFA64AF13CFFC004F8 +:100980007FACF307CF09387CD083DB67BB00CD6831 +:1009900057C979C8F1C120BBAD0DFA3BB02C63102B +:1009A000DE8BFCD85DB887E022C6FFD8ED6F8D1CCA +:1009B0001F963B10BF9FEB3C5E1174B147E0CD57D3 +:1009C000A0323D42DE4F1D9760C85F3B2985E9910B +:1009D00071E56BB30CF969D37B1BEADF34EB22437F +:1009E0007989B56D68F579D8F9550E473C9E6FF851 +:1009F000B4E5BBFFBB19EDD746D5ABC07AE66EDFD9 +:100A0000F87F63A0D6713C364CF6A887E27B47F0AE +:100A1000BC21F29EA66B91FB525FB1363AA719B189 +:100A2000EF61D85F9AEFDC41E7447FAC7DA9133DCD +:100A3000C4BEC7603C628E7AE8835C3C5FB2D0CEB5 +:100A4000D7F3D54BFB2C74BF03F507D0F715D8505F +:100A5000453E0F50BC7D6CF33EBA47F7500F2E97C2 +:100A600017662FD2C002655590A2DC9F00F22909BB +:100A7000E8A3AD955DBC0DCF57E739E83C4CE5C91F +:100A8000A98CA5201D05062C827AF3EB8B29BFF0DB +:100A9000643CF5FBAEDA3681CED1BFA8D0BE484962 +:100AA000D68C65682760FD9FC07825BFBBA218E182 +:100AB000B3701B3F3753A2FEEF50EC67414331B593 +:100AC0002F51D92E05ECA18963B97E2D415B06F229 +:100AD000EA70C72AD4ABAA2594FF18CA138B83E403 +:100AE00049D2C99B68FCAA93366A9F95CEED3473B0 +:100AF0003B9FD7F8933EFA2EF19E97DECB70EFD353 +:100B00009CDAA895D9B13EA3FA579DBC9052B9CEB4 +:100B100037FBFDC68D72CC9CFAED043C27FCA65B2E +:100B200071927915256F4F548F486231E4914CAD25 +:100B300042CEDE7C929F43EF95A98F4887794EBEC7 +:100B4000BB5DC37D2A66B739115E93470EF2CC8E2A +:100B5000E023F5B51BD1336056778719F5F9CD90B1 +:100B600046CAE35BBB91C797A69B0CF776A47E6150 +:100B7000C11BC9FEBE45DE53167C72A1A82FDBB790 +:100B800091ED04787CC14A76D4984CBF2F1DCADB06 +:100B90000AD9B4AD241FDB72717FE8C79A3FE0D950 +:100BA000A6903FD34EF730268FF498D03EBC2EDD72 +:100BB00064B0D3CEB68E2251FF5D952D417DF2EE0D +:100BC000E597B7E9D05FEBCF860C41B92FC79D9D64 +:100BD000CEEF9D3367C70FE8B756BD92E041BE2EFA +:100BE000C1BDD6A161BB1DBE338C7356BD62DD8015 +:100BF000E799AA12C16F87F1C7BE1A17423A6E7DF4 +:100C0000354E43FDF075B67F36E273ECAB178CC3FF +:100C100073747A8B556364DFE81508B7EEE67B36AC +:100C2000F9144D67922FFDF59C5F4A059D9609FECC +:100C3000F30B3E3A51DD83F8F0C4DD30695847D9F3 +:100C4000DDCAC5DBD01EF038E81C96E4CB12F4F305 +:100C5000E07BC945C9E4EF46F01DF1E182934EEA1D +:100C6000AFF2A447F0B98BF292DFCA04BF48FAF69C +:100C7000093BE26799FE87111E25B5C0EF787F73A7 +:100C800059C650E4A330BD589C4857402FE9B323C0 +:100C9000E8A1B615E8C541F44272C8076924BD5CF5 +:100CA0002DEF1531E7843498F7E4BA3CC3BDA2C7F1 +:100CB000CE93EEEB05BD94D9437DD15E3557C77910 +:100CC000F19EE47137DF875ABC92C36FB1D93716F2 +:100CD000ED87C58F285EC00CD915288F867F546D8F +:100CE000898CABDE787220F3C0FAAF39D987D23B5A +:100CF00052FD4F231C4A4F5E2FE035F0DFDAEF1C28 +:100D0000A6F3389A3968F5AEC7FDC438BF8AF83DF6 +:100D100094C39C0F44C4D130EE87F13FB90F2AE34E +:100D20006A56DC378ED093DF690DB9E8E77489AF76 +:100D3000151AF70B17B4FEEF7013941FC9D329CE01 +:100D400036C3E47F1DE979DED4E07366C8CF5FF374 +:100D50007C22C6F5253C9BB4505FD4934D00478C54 +:100D6000F735AD568B83DC9E49E0FB7C9CAE251DA0 +:100D700047D3F7BC93BD889E4E545B49EF9C007AE5 +:100D800065117A275ADF483AAED498F05B93E8DCD5 +:100D90008894FF617DB3FEBED148774735A2FFB08E +:100DA000BE99EA2BE4F44FE7CEA3E9FFC59A743A63 +:100DB0004F24F548B4BE8996EB525F7D92E1FF1E49 +:100DC000E154F4DB7F3EFF317CBA4AE37AEB2ACD73 +:100DD00041F4F3DF92FBFF3C4FFA3F2CEA83FD4ADC +:100DE0007621CAF5C8FEC66416256640794A06D73C +:100DF000ABFF6D799F92717EF29E65F0F99F4DDE9B +:100E0000E76770791F2DDFF1A222CAF763DBFBD3FE +:100E10003EFC5E06FA00F55E4B8267A390FFA41FBE +:100E2000E293826792FFDBB367E667C496FF1764BD +:100E3000FC07F2FF7CF944D26F77FC32F15E6E9FC3 +:100E400031B4CF9448FB8CC365D7855C0F44D86917 +:100E50003C9E027CD55789E49B0DF78D46BE39E652 +:100E6000F6E25940C927926F24BFDC2CF8E356A163 +:100E700017247FBC9AE1BF11E125F963C1D668FD53 +:100E80007066FABAD95DCD503FDC0A69247D593BC2 +:100E9000F583912F6EE9A4AB73E38B4919E766479D +:100EA0002CCAE0F7DCFF8B74B508E927065D2DFE40 +:100EB0004FE8AAABFDFAE150BCAF766228D0515E94 +:100EC000988E26BEC5B8DDD09BDBFF9D7462C9A19C +:100ED000B8CEC4D3FC1CAFA45389DF68B9F85CA6B4 +:100EE000EF61C4B7F41BFE5BF2EFB1F3C4F3CA7356 +:100EF000C4F36681E71FD15E7C31165E99D36588A5 +:100F000047007F5F43765C48A32341DDE1D5BC9673 +:100F1000F397CC2F0F6952EFA6A0DE057A69FE4F3A +:100F2000E8A5642C13F18D4393304E39F11722CF8D +:100F30008E4E423EBC7EA42C3FBC5AEF837286C9C3 +:100F4000FD038A8FBCAB8A7CE0C8DBE3605E131FC5 +:100F500060E1FD05281F5F90D4194F41D743D6FFAC +:100F6000F0912FDE5E4DFCCCCFF9307FBBC6F7D5BC +:100F7000447E28E41D11F99151F975BC7EA2D6CEAC +:100F8000F8B9CC20D7032A6E3572FAF145D82580FE +:100F9000C909787E62F236C589F1909B0A8ED1FE2E +:100FA0007378FDC727E905B82FA888FCF76FE37AA7 +:100FB0006FDAC6F3A71EF9C7EA8026FA4BA37819A1 +:100FC000FD599B145DC5F320239560AFBCAE703E08 +:100FD00015A5F7F04F33B66778CEEA7CDA239EA9E1 +:100FE0007D2F6A1FB29EC7F83714C4BE27E2C8140B +:100FF000F5445C81FA07585ED314FB1E4CAAA8DFA7 +:1010000086FB4504AFA43508BF368B8467E21AA47B +:10101000A7F18CE77B3E9A581218C0A7AF47ADFFE7 +:101020004CF35732BBAEDF636C1F3A13FCAC5DDA96 +:101030000BFA9963A4A724CDB7E304CC23C9AD3838 +:10104000D13E5EE88B5B8D7E40983E324A703D6DAE +:101050009D71FD68FACF2C41FA5FC864FDEC35E460 +:10106000E7983AEB737E90F405EDFBF1F7F7A8FDF6 +:10107000A847B3D6207C003F544E79ED0CFCD01429 +:10108000952F88E21F41FFC4BF28E7013E7D63C85A +:101090009969023E5F8973E46D45DC5E6C13F7E28B +:1010A0009664F238AD3F93DB637324DE23EECDB05C +:1010B000083C3371AF2662DD04A71BDD72DD052518 +:1010C00093605D6D2E5EBE3873E49A4076381FDD06 +:1010D000DF6D990525B83F11EE7FF49F506FDC2836 +:1010E000E0B62473CC9F025C1E2AC89795442080EA +:1010F000F76D4A80CE61215DC458B7DE95AE0251CE +:10110000ED75F319DA4FE8DA5E8F6ACFCCEEF3694A +:101110002FF036290AAFC551781D17959F2EF34140 +:1011200083FC9372B1ACF9FEE5696E8C4F2A74A70B +:10113000374CCF57113DCF774AFA9DF827A4D730C7 +:101140003D4F22384F6D92F2B0640DCAC329280F6B +:101150004787F3D7A0BCA0FCE4123D29525F5CBDD9 +:1011600046073CDF502FEBFBA8FE4D75B2BF29545C +:101170002EF1C802534B70FC1B870A7D11B8E64F55 +:10118000583EAF85B7FFEDA3D7FE29D0E70CFCD0C2 +:101190001005977551F94054FD07CFA25FEAA2DA16 +:1011A000DF1D55BE3A2ABF362A5F6F6C5F3A4B216E +:1011B0003E2C057A40449C8D2F5FCEECF47F3AF5AF +:1011C000A96227BBCDC057136B79FE8F8F9696D43B +:1011D0000F88C867CE2C89E40BB9BF0AB23680FAF3 +:1011E000CADC8DBC7CBE3BBAEC17AD6F79F95FF100 +:1011F0009F19B4CF63B00B5E578DF95655CE7BD196 +:101200009F6E1B10B91F5A5D8271966EF75DD8C232 +:101210009271917649A092E844AE53D69F70EAB499 +:101220008AE3FD25B3B2A411F7758AC47EA48BA707 +:10123000A0D754D49B55222E3301CF0363BDF85061 +:10124000DFC59176086BCAC775B6FE8CDF9308D4EC +:10125000027E30CEC6BC168CABB426252D7912EAA0 +:10126000BFFE337509EAD1BD4B52E81CD66559DC87 +:101270008E7C3DA9675A39E45B136EB5E0FDF3D669 +:101280007BC653FA9AAAAFE8005EFBFBA37797D818 +:10129000FB637912C1E7BBCC25254B81CE4FE225FC +:1012A0002568EF7739D3F01E075B6566FC3D24EFB8 +:1012B0001344376BAC83D08F2E5D7A11ED5F953D73 +:1012C000346502DDD3586EA67D0DF8A3FB3AFE55BA +:1012D000E3E99CD7AC3A9106AEA0F4D57FFDA636E3 +:1012E00011CF2D3CAED0FD904BBF6D7A0BDF5DAAC8 +:1012F000A8EFED45D4BC02763D9EBFFA6CED0574B7 +:101300002F647F5C359D7385FA0CEB57FCE07967A1 +:10131000F250ACAF3AF148C941F88EF6F0C195EA07 +:101320000605E795E888C7733C074F79DE41BB1691 +:10133000CA9DCBE0FBC1E573D3D0CE3AA878121595 +:10134000BCC7F0D8AA92F40C7C3FC12AF0B9CA51AC +:101350000A7C5D6AEAA417D21FB393793E356B55B8 +:10136000C94698FFC1472EA0736EBFCCD2D3B2003E +:101370004EB766EB3DB286E13CB99E7AF55F7CDF05 +:10138000F0E5A36569484F79599C8E5F39599656A7 +:101390001661EFCCFE4A23BCBF6AF1DC86F37C35D4 +:1013A0003E47A1F3E8AC2905E3DEB3849F09F4BB13 +:1013B000E4F91876CF0F992AF57BC0BA84ED8779C6 +:1013C000B7DE7BDD5807C0A5F54585F0308BF96B9E +:1013D00031CF9A63EF8BFE90563410E71FA6FF754E +:1013E0002467C9DF80FCC8AC47D604D00610E73BB1 +:1013F00019BE3E85FCBA392E1807F09CE5D6276049 +:101400007D96DE943FD511C1A7A2FEA7017E7EF98D +:1014100053A88FFEDEA781BF3822F72F64FD8A44D0 +:1014200047008D8F2F1C0E0DF1B657AB3988E71E84 +:10143000673F6E263D31FBF1D4BB3B701D405F7DA5 +:1014400059D775D46599895FBADF2F7DDAC8B7ECB3 +:10145000E933F2EDD4C7369534DABBE7DB0AE1D7DE +:101460004C78DC4CE7F82B863934DCB72C7AFC8FCF +:101470001BE9DEF1A2B8C1787FA3E2712BE1B7DDF1 +:10148000E10838715F35D1A125632AE8616916E763 +:10149000B3B12AD36C8329A57B1B723FF0F092076E +:1014A0001EC663A64758F0FA1100BFE3882880CB18 +:1014B00071796F2D6A7FB072F7F396427686FDC11F +:1014C000B3EC0BE20D78E4DB73DD1FBC232B7A7FDA +:1014D000D09C8FFB8F15627F70EC3A1ED7A958C243 +:1014E000DF65199BC2E3C4076A02F81832AE37E021 +:1014F000C47BD60F727D54C194A00DFE79C5BA4548 +:10150000F45EED1121874AF15DB501C85FDE5CF440 +:10151000EB673F1E4770AD7862EEFF3D02EDDA9754 +:1015200096B823FDE835821EA07F86F798653F5F59 +:101530002CFD792ECABFB1BF067F18EF4326B3E753 +:101540006ECC433C65E4E23EA6AC57B1EC67F9BC17 +:101550001EF8D3E03797AE54797CEA052BE9479023 +:1015600009E92CE23EFAACBADD16CB80F0FDB8CF2B +:10157000208F4F2C44DC93B320BCE4BD2DFC4B1FCB +:101580002EEC730FC91B7A6F7ABA49A1FB5D20E973 +:10159000E85ED4CB593C1EDA94C5EDDED25C2FDD7B +:1015A0000FAABCCFEA5DC6CF2BB1CE7BF1781ECCA3 +:1015B000D4369BF62D7F6FA5384A555D9C1E97C883 +:1015C000CF536C1D40E7C6350BEEB778B85C795940 +:1015D000D05F9567CA15482F50FE9186E7D51C5CF1 +:1015E0007E56268BF700A1BD09C63986FFEACDFBE2 +:1015F000CD181831BE22BE433F9EC470BFBB4CAC59 +:101600001EE33458BFFF408463CAF5D3707ECFAA6F +:10161000C4C7B0F8FB46A23DF8AC3A04FDE0D29551 +:10162000AF4F588BF92D83F046072B7DEE7DD22FDF +:10163000F305FEDBC5B9B932C8E33B057B041FF9EE +:10164000551E1FDA23E025E9409657AEE4E7A72AA6 +:10165000975BC9DEA95CFA21F55BE9684B43395D0C +:10166000F98299EE797F28E65DB634A7E023A0AB36 +:10167000327312BD2BBE205062C1FC820685F2E19E +:1016800076A9B948A75FD6BD9888F4B33F2ED41782 +:10169000F556C7A2382F9E5794F1B92FEBFA6EC0BA +:1016A00038CE2C679B03EF6BCDBAADB70BE5FC5E74 +:1016B00067C882E57B9BF24C98D79DCE02CCEBDAD3 +:1016C0002594FF529C57A13FA41785E379C1E6D723 +:1016D0002DBD60BC1FC47ABF7AF6FD7CD46B95B972 +:1016E0006DF9A87F800EF2B310CECF28A4B7176E85 +:1016F000E6E7F8251D2C443A00BE9B27E860E1B6DA +:1017000017EF407E5888F81FDC958E804E77D0F713 +:10171000ADEB2730DE7E07D289D47790AF33BB3074 +:101720005E27F2300EE64F213C8751F9385E1E18D5 +:10173000C0CF03B6D3F9C62A719FB3533E7583E772 +:10174000CC6CB17FB6D44AF236339BAFBB7DE50B90 +:101750008988C7AF9E7D7D27C6892BB78256F7C47F +:10176000E00B01972A844322AD83EC902A5C7762D8 +:10177000180E9DF42FF8B18AF175CA755769020EDB +:10178000B25CB4CFCAE6EB5CC004DCB65DC0F94F16 +:10179000F01BF233BDBB24D6E77719DF97D7C5FA24 +:1017A000FA8B7401D005DE5F63787D53CA0928FA8D +:1017B0006ACB7A8A13497CC9794FCDF6483DA22776 +:1017C000BBC2786C37C57E5F7B54369727FB96F794 +:1017D000C86D06B87D09FE189D37007AD522C693DC +:1017E0007423C71BFBDB2957E17AA1FF10F62FC733 +:1017F000DD1B48D0B09FBD8CF307D227CA4FC997D5 +:10180000636B675C3508CF4307BE72F4467B5BE0D1 +:101810006F6A367F0750473B01DAEBCD0AC5A9F75F +:1018200009FF7FDFF21713CB22E0E413F3967486EF +:101830007F18BF92F3DDE5E271DFE8794B3924E7E9 +:101840003DF69E1BAEC2EF72FE925E257D4A384A7F +:101850003A95F703A3E995684DEA4FD520EF493F44 +:101860005E91FD8DC56FEFFA3D3ADF6937D5A5EF83 +:1018700088BCF7B65F9C77EF48653CDECF806A2373 +:10188000F48ED4F3117A65B516A157AADC3ABDB728 +:101890003367E8A27CD4632F64F37329475893A578 +:1018A00010FA5B70A86D42A2276CAF5EFA6D48C556 +:1018B000F76E166CE3E7D724DC171CDD41F45F29D3 +:1018C000EE6F95AE7CBF6404D2F9D366DAE72C5D87 +:1018D0003E9EEE69CFDD387338D211DEFB40B97E13 +:1018E000B871D810FE5C9B33ED7ABCFFD1F8C0F51F +:1018F00037C1F759CDAA97E43BF4837C5B7AFB10A0 +:10190000A6D07ADB4B70FFB4E34ED58976FE988D76 +:10191000C3EEC6FA631C3D93713D7A630AE5752DEB +:1019200089F483B48FE5B9BE5A33A78B5F67737FA1 +:10193000F5E1CE5411E7F96AF371FFBD637D1CBD7B +:101940007335DD22EEBB6EEF417E489505AF5ED26A +:10195000FD59B2C7E658982D839F0FB765C0F7DDD4 +:10196000E6B6DB518FECBEDD3188EE1FA83F0C2FB1 +:10197000E3FE23CDA324C5F8AE949CC71382DEA357 +:10198000FB93ED7789F3D9FBC5FC0FD73D7D3DEA8D +:10199000C1C39BFABA70DD5F6C8FA3F771BE887A02 +:1019A000AFF37CEFB301FD46DD175B46F36BCAB6C0 +:1019B000F3FB5CC28E93F47ED6FB5C9FB8A3F6115A +:1019C000CE7C3EE9680DA37BE7B7812D8EEDC72560 +:1019D0009C7A1ECF05CE6EB03AF1DECF01A477DC43 +:1019E000BF7A41E5F7936D9CFE0F6C1914447F7329 +:1019F000F627FC1ED68EFBEFA17309E5605FE2D1EE +:101A0000CD4E7BF9C1FBAF473638EEF5AFC88076D7 +:101A1000C737F173145DDE77D8FDFCCEC8F71DCE55 +:101A2000D74E3E57FB58C6233EC936BE1F20E12A7B +:101A3000FDA45701FF230787E1F475CD1CB28F8FFA +:101A4000D6F8293DA6ECBB6F0CD2AD2389EE37BC8E +:101A5000DCFC808AEFD1546E1BF403FAC5A3ED4978 +:101A60004EE4D7AF6B96D0FEE8D19A6AFEEE4AE715 +:101A7000BBCA414A2FDDD64AEDBE6E1ED282F78127 +:101A80005FB12709B91FBD1FC4F1D8DD3D67B9AEED +:101A90002377727CCA791FD9343311D7D5FA584AC3 +:101AA000CB28C463429213EDBC0A714EE4E05A6E37 +:101AB000471FB2253D3909E07368DD3569F85E508E +:101AC00079EBB5D7E3F7D9DB1527DAFFDEED531253 +:101AD000D13FFB5C6B4FC4FB5F9FAF95F7C682F4B1 +:101AE0007EEFE86246FB55A3431AF3E4D1D633D127 +:101AF000C9A8A31ADDCFFD12F7B1305EF2433CC591 +:101B00004B98D89F2A7F89C7593AFD59E1CF8D114B +:101B1000EB1E91E392FB0EF47DEC48FEFD8B75CF3E +:101B20004FC6FE0E379A9D38EFAF1BF93B16F3C038 +:101B30000FC3AB008736713F675E93427EF1E14D84 +:101B4000A0A7615D958BCC3ADD6B8DA2BFB1508EA5 +:101B5000E72225FDCDD38344D7D1EF8C24B326BA19 +:101B6000FFF663D1E3C539467FAD930EBBC3BF809B +:101B700013F22DD2A1C4F3BCB5FC7D5B57D3A042B8 +:101B8000A42789F7E87B0EB51646F71902A6787ADE +:101B9000177A8ADD635660FDD7B8DBC7A1F87C24CD +:101BA00087CB4575AC49C7FB7AAC96BF63D0253E61 +:101BB0009DC3E5E89B398CD2B21C7EDE58DE5B9378 +:101BC000292C2487DE654C707DE7812AD7E46C9A46 +:101BD000ACC1FCA78C71DDDEDBCBD8CD39CF4DD6C7 +:101BE000806EA70C71BDD00BF2331EDFCCF397B81B +:101BF000869921BF54F9DDE47190BF2B479F9293E2 +:101C00001A1E47F60BDFAFC5EF8752FC37E40C43D3 +:101C100039CEDF2D3BA6740C5C9217AEFF9EC2F648 +:101C2000BEAC84F3ED6646EFE594E1FC53BB4F3761 +:101C3000E4E8FE9C6131CA19A3FB6365017E1F08BD +:101C4000FE7CB6343AA746F45426EF07D51BEF07BF +:101C5000312FBF9F26EF6DC97B59FDC3F7CDD69DB0 +:101C6000CF7DB363E27E5CF4BD3FA585DF97AB0D0E +:101C7000B0F638C243D47D9F04FE7EE3E217BEDA9D +:101C800081643557DA2BA86C8787DF3960E9FCBCA3 +:101C9000C0ED820EBFA8617DFA002B5FDDD696E80D +:101CA00081C91E9D1CCA47FEF658FDF508A72FD610 +:101CB000D5662F76E3FD58AB7712D43F14E4F74F87 +:101CC0001708BB9335A60A3E57439743BD5D79FD80 +:101CD000E99D8B5F0A7A3A9A17CAC577870279DC41 +:101CE000CF817A74FEAD78D915A958EFE8967BFAC2 +:101CF0009403DEACF8AE9F8B5286F7C5AE84BE4728 +:101D0000BAE8BD3FA6D2FE6E90FAC37A89A8D73D45 +:101D100033D379FC9DDF2F947892F0EF82179802ED +:101D2000DAA5261B33E3FCFBB3754ED4C7123FF292 +:101D30007DDBC52FF038CA62A5BD2E05F3CF2A740E +:101D40007EEE0B1BBF0FD455CF6DB420A8E7AC9B24 +:101D50006978C748BE23FB63C7835ECA11F7C20711 +:101D6000B14191EFF45688B6E3D5E91E7C677471F2 +:101D7000AA8DDE3759FC786FD2272C703BD181AC0D +:101D8000C7D6A5107DACC85309CE739B19BD4F545F +:101D9000D29C49E71D2735BB284D3C994EDF0F3FAC +:101DA000F9D6502E7F381E4A9EEA41EF8A973C753D +:101DB00041117F74AFCB3B49FC3D6DBB8DEE1B2FBA +:101DC000DECDF5D2E2EB548A5332710FCC27A6E375 +:101DD000B3D7535CC7C762BF0FEC93EF03EBE63397 +:101DE000BE0F2CE16B15F8897E2FF8BADD43D2D1F6 +:101DF0005F95EF05CBF708DBC47DAFE87783EF494C +:101E00009C40EF064FD3B91E897E37580BC479D159 +:101E1000BE3567DBF9BB16FEE87784DB355CF7F58A +:101E200005FC1DE1EBA619EFD3990BBE21396D2EF0 +:101E3000E8F28E9219E9DBEA33D6FFBBD42FFD59C5 +:101E4000FF33BED39C6DA1F7F0347CC71CF2D78B57 +:101E5000779AD18E43FBFCB8CEDFDFB3C6F375B7FC +:101E6000B1A1E9C8F7FFBFBF4F7EB677C9A3DF2195 +:101E70008F7E7F7CC8AE5F1AF2C3DA1E35D41FF1A5 +:101E8000D10643F9A8F6670CE5630E6D35E42FED36 +:101E9000F883A1FEE5275F33E40BD95B86FA636D17 +:101EA000EF1BF2E39D7F31D4BF227DBFA1FC4ACF5F +:101EB0009786F289FD4E18D7A3F927E4223F7BFFCE +:101EC00069683799797E81EF7BDFE036D1BB26C523 +:101ED000B946BA1B97C3E30AAC0FCB45F9355E9DF3 +:101EE00044EF241D6F52F8FBD2DDE8B124B0F7B403 +:101EF000887192751B3882E17C4AB1D3904FF5A569 +:101F00001BEAF798E6319467F8FB19CAB3E6780D37 +:101F1000F99CEA9186FA3D97E8867C5EA0D850BF8E +:101F200077BDCF90EFDB30CD50FF82B57E4379FF98 +:101F3000E01C43F9459BAA0DF98B9B9618EA5FD2EA +:101F40001C30940F0AD51BCA87EC6A30E487B5AD04 +:101F500035D41FF151D0503EAA7D93A17CCCA1264F +:101F600043FED28E6643FDCB4F860CF942B6DB5062 +:101F70007FACED3D437EBCF3CF86FA57A4EF33949C +:101F80005FE9396C285FF0A597EE4BB397F97ED8DF +:101F9000C47EDF18CACD6E46EF6057B2782FEE3B95 +:101FA0004ABBA6C4FB7743BF4FE6F2380AD0527B48 +:101FB0001CBE1F19F051FCC7850702514EE13D754B +:101FC000173F4F339DE2486ED26FA48A3C78BE071C +:101FD000EC8044F4AEF2F2D04E4E08DB63D9A72376 +:101FE000CED79DCD1EDB96CB681EFB73FD4FE7A6BB +:101FF000A2FFB16502BDFBCE022B701EF23DC07781 +:10200000A2DEBB96E995B6432CF25DECDD710DD9ED +:1020100083CFE0BF5F693BCAF0BDEDCE7E45BC42D9 +:1020200081F52D8EE8FF3EF017B43E8C35D400FFCD +:10203000808DF4CB1A27E51FAC49A7FCC3351E4A97 +:10204000D7D6F4A3F4D11A2F95AFAB1949F9276A63 +:1020500074CA076B8A29DD50E3A3EF8D35D328FFBF +:1020600024F8C5986E023F19D367C0DFC5F2CDE0F2 +:10207000FF62FEB99A00A54D35F5F47D6B4D03E581 +:10208000B7D5ACA5FCEF6B829436D76CA2F40F35B4 +:102090004D54DE52D34CF9576A42940FD5ECA2FC52 +:1020A0006B356D94DF51F311E577D6B453BAABE6D7 +:1020B00010A56FD67450F9DB3527297F54C45DF71E +:1020C000E51AF723645EBE5B21EDBFC968BF2371CB +:1020D0008C347F6DB0DFA3ECE8687C1C11E3E03B3F +:1020E000BD43816ECD99F91B6A23FCA7AFC478F27A +:1020F000BD8AE8772798B04FE5FBB0F23D8BD962F7 +:102100005E1582FE87217DF623FA7CFB7CFC05E9C7 +:102110000F5E9BEA3F45F499630A903F6CE7F791A5 +:10212000EF48F5B39EC370DFB07C278DE7F4D2FE95 +:10213000618935947AC3507A079EE272DD8D572506 +:10214000CE89775BFECAE16CB4A78BFFA5D27B6416 +:10215000EF981DF4BB97293D395C527A9A0CE93F00 +:1021600053FDAE9E907EEFA8BEC504F3FFFEB245C0 +:102170004FFE242FEC275F8DAE26F8375398C74CBF +:10218000E71199FEC73CB49BC0B0C2FC0D2C40695E +:10219000C0EDCFC275DD080637E6FDA3ADB9B1D6F7 +:1021A000153DAF7C31AF7C311F99F64FF3F7C5FE7B +:1021B000BE77E834AF77465D918FEB92F39A27DED6 +:1021C0009D98CC3A9EC0F97DBFFD9B834AEF30FCC1 +:1021D000A53F4EEF02A0BFB34811EFFF75797F8096 +:1021E000CAA7DFAE907D3603FC19DC2792EF0D1CE9 +:1021F000AF36937CC4F709701FED78F5E776246756 +:10220000A8C7709FA3160FF64079EDCF15A2AFE9CE +:10221000F88E08B49F9196C7EF4B339B8E7A787AED +:102220008B753DD2E974B0F7D07F02FA2844B8CF5D +:102230001BA5D27DF5774CC17C85F693CB2D0ACCBE +:10224000ABC2ED35FC8E4434FE178AFB07F23BD05F +:10225000D54484D7D72F8DE847F1F7574679104EEC +:10226000B5267EEF28F0A62A7EDF8B8B6675CCC55F +:10227000145F649AD78B71A212714FA555654B629A +:10228000BD1F5F29F0F44E3A7F5FB0366A9FA5BC50 +:1022900027F72FCB7BF2B873C96BBBE99DA585BB34 +:1022A000F87B906C68FB80C877793AD7B3E4CDFEB1 +:1022B0007D22D651D5BC8F9FAF60ED0322CF9FAF5B +:1022C00010E34BFA512D0EFF7A7BE4FC3AE97901D9 +:1022D000D17332D0736FA2E783B8AF38D9EA49BA65 +:1022E00041C15FC7635FE3FB47FE5F3BE93C913C55 +:1022F00057348BF928AD00F423FDFA02F7D37BB7EE +:10230000F358137D5F387226FD3E6D15EB18970E5E +:1023100070BBAE7EE91FF1B9C06B1AEE1F8F71D58D +:10232000A9C1D23F623AA5513988FE29F0C3CF1125 +:102330001FED4AF5723CC279D3E6C2E5B83538598B +:10234000E5F8606F717C00BDE8AAABEB3A81FE97BF +:1023500013FD27EBB40E35B1D840FFD397315D7133 +:1023600087CFC777F2C3C8F97FC52D60A675D0BEE9 +:1023700079D52B5617E2791EE3FA3A6CFF493DCD29 +:10238000F5FF7CD0FF58EF88A0E723398CEE211CA5 +:102390005118DD6F97F623CBF5A70FEE1DD6B74783 +:1023A0004CC1E189BD491FAFC3F9EE4CBF86DE0FBA +:1023B0009AEFB6D1FBB0479283B951EFA1D07B4DD4 +:1023C000327E759F99C793A2E7A58CDCC97FE7C4CD +:1023D000C202B82F81BFF33D1CF938D3427C568B23 +:1023E000A0C5385891CF13ABFF3AD1EFAE53DCCF35 +:1023F0000DE4F0774BBA8CE314E3C4F371A4DEE888 +:10240000FC5DF13466186F7BCF3CCE070E9DE6BFB6 +:10241000D4944C7226C3E66FC1F5CB788EF4FF7668 +:10242000E57DD187FCF41F6AE93D267ABF00CFF530 +:102430005CC6E5D13B660FBD4BFC4E611EC5EDA5EC +:102440009CBD7A248F7B5D2DE35C055171AEA8386D +:102450000B2B881DF762CC6BC671FBB34F247C2815 +:10246000BEF25A8166F83DB1D784DF79BCD83D947D +:102470007E2FCAC3CF5925A6F0F7463A1C2AD1D9D8 +:10248000EB01AF1D7F9F6495888FAE8E7A177CD548 +:10249000D0C54E3C176075F0F73ED714C5CF893CC8 +:1024A000BFEECEE7EFC33C995F98E18174803D5861 +:1024B000446A59D73C387F45ACE72227C0DB84F615 +:1024C000A64FC439E5EFDC8C23BD2CF17CAE7AF944 +:1024D000192DB82C1ED7EB66C4778EB536929F6A3D +:1024E000931EC2A3D4B3F2A71E47B9C1345F3F1CE9 +:1024F000A775783CB343FDEF5B2D147F7AC554F686 +:102500006B7C97B8E3CF5686E71C9A1C591A1AB70A +:102510004DA72E1C47A963CC04FE3E274BC0774431 +:102520000739D96F7E874812F7C92CE9CFF80E809A +:10253000DC6E52D82EFE0E979E80EFE13599D88939 +:10254000CB617EFF0FA64C086300800000000000F6 +:102550001F8B080000000000000BED7D0B7854D5A8 +:10256000B5F03E33674E66269370327930E40167EA +:1025700092C98B4CE290F054AA93106840D0E15578 +:1025800083243A58F446854C8AB445AF5F339000B3 +:1025900001F42FA2B548BD7640A568B50D4A6D6C13 +:1025A00023770242B197EA606D8BBDB57FF0F6F7F5 +:1025B0006AAD12C47AB1A5E5AEB5F63E9939930974 +:1025C000A2BD7FFFEFBFDF8D1FEEECB3F7D98FB554 +:1025D000D77BAD7DF28CA3F6FECB18639359C0CCAC +:1025E0004A18D34A838A96CBD854D641F57B954076 +:1025F000DBEE1C289D565F18FAD58E33F919D4D915 +:10260000C78E48A9C458E0986C313B18EBF3041D01 +:10261000F8DE05FCB90A9EBB4C16C5CBD84685B57D +:10262000F54299E1B3336665F47301FE05CE953149 +:1026300056C7D858CDC4D814C6BA5DFE985F8ABFB5 +:102640009F5C32551E1AD4DF2FC6FF17AA6FA58BC9 +:10265000BA9931AF23D22061C52F6BEA54C6E8770F +:102660008DB12A95052D30451A0B30DC0F9BEEB34A +:1026700006AAB1B1517DAB02FBF9A50BE9179997F9 +:10268000C90CFBE9F3FC6102A3F51EB267D6B031B9 +:102690008C851BB4FB1A2743F953B3AF8B7AA993EC +:1026A00071FCCC6C1635C1F3A10C73648F9BB1C364 +:1026B00061EDA95EA81F96AB088EF774C266000490 +:1026C0005B3BA1A2C4E7DB3A798DAA013CD332CCB3 +:1026D0005F3A8C702E32A9A5B08FCDF3ED4D1180ED +:1026E000E3BD0DF6362C73CA2C8C01BC97165B68C3 +:1026F0003D7BCBEABF5D0CF5564760B6A47138B0A0 +:10270000BC381CE001E3FB0D32DC6F8BCA06A5442C +:10271000B830804B06DF00BE770DDF32BB4666E186 +:10272000314EC65E9EF1F663BD304EC64E587736CA +:10273000BCDF71460EC23AD8F90B57D901DE01BD94 +:10274000FF4C89BD9978CEF0EFCD0AB13F37C15328 +:102750007D4B6F375F3ADC2D4BD6573058EFA64E86 +:1027600017C1AB47F2F9C7C27872C7A93BF0F94667 +:10277000193A02BCC25E25F238CE23072A703FFA0E +:10278000782BCB1A6ED0004E19D3FE907E0BF4FB43 +:1027900028CFA42170366A377DDF8EE777329DE13E +:1027A0007B99D9B1B647A17DE8F572B60786F9E8FD +:1027B000D6E00415CE630B9CD39B1E5C4D64AC69C4 +:1027C0003A9683634D2E02AE8B9741177FCE447BA2 +:1027D00084EA6FB98BE99C00FEA2FF20F5DFA26CB2 +:1027E000B7DA711EB755DD9380F7579959472FCC4B +:1027F000F775A40B7CEF7C97B63003EB12D5EFEFA7 +:10280000DC19F89D07D713A1327B7E840501DFEC2C +:1028100015612D0CFDAC1B5810DF4F86E7DB6E9960 +:10282000DEB71E7A8869D02FDBE39382D02F673E14 +:102830008CA7C399D1B987C7D442BF3D80309311CB +:102840003EF64838055D5E93DB704CCE1CFDFC9275 +:10285000F180093CD0CFD3FA577310F902632E13DD +:10286000E2DB5A2BC7D3C6622BA379D729BBD3602F +:10287000DE27B42C5AF787390D639877F4F91E8157 +:10288000F309033D4580AEB0DCD3A9B230E0C963A3 +:10289000802F58DFDBA951B9AFB382CA273B7DD463 +:1028A000FE54E774AA7FAFD34FF5DECE26AA3FD3FE +:1028B00019A0FA81CE66AA3FD719A4B2AFB38DCAC8 +:1028C0001F7576507B7FE73AAA5F9506E786FBA9DE +:1028D00008BB16C179F4DCA9F83580CFA038C7C38E +:1028E000FEE26C1F9CB7ADC2043407E5F11D0CF786 +:1028F000637399FC1138874DAE1DEC8B505AA66658 +:10290000F448C057363EEDE8918031DBE4FB19F224 +:102910008347A4701BF331F693483020CF60CCE39B +:10292000FA528313EA3F8BDCB2DD0A785BA62D6C8A +:102930005E9F50D7326A6FDBAFC6EB13BCBB653B03 +:10294000B4BFAADDBA3D47E2EB60F98CFD26727B8D +:10295000603DE051B4988511EE436E2582F8B812BF +:10296000CF4BC6F5ABB4FEAB5997CB04EB9FA02978 +:10297000B54837D03FCA722EBDFFA0A6D1F3E4F709 +:102980002ED6CF34F992FA31F345C6C376E922E365 +:1029900058A5C5D618AC7D9B45F08F5C07F18F1EFE +:1029A0000BBB310070EFB1F1F2CA6289F8ACB3B879 +:1029B00061B71BE6DDEDE672ABC716561B70FE6A0B +:1029C000930FF9055BE7FE7931CCF7959FCA6CABA5 +:1029D00016C7CFFF1078503A2183CBCF7FB4464A39 +:1029E000619ECF4F78BADB09F5D2477D3E33F4DFE5 +:1029F000C67C76C493F03D26F638D4BF3BB9C4B943 +:102A000010BA574DF98113F9ED5237E70311C69A01 +:102A100010DFD66FBC65C220941F9DE07C4A71F325 +:102A200079765B621D749E531C6C0F0981EDE9C8B9 +:102A300077D6BBE090A631661AC74BC5A25E8FFD64 +:102A40001410D461588FF29769D6008CD7752EADCB +:102A500009F90863B174E4638A2DA866C1F3ED61D6 +:102A600013F1852ECD119160DC6D8EDA631AF24F71 +:102A7000D5E42B45387A4D04C76EC7172266E4CFDC +:102A8000D2FA36942F11F519AB1B9E47BC2615E9D7 +:102A90003CE25FD484F57050F6956A8241607BD049 +:102AA00019D98AE3B2A17FB90CDB5B980FE1B03191 +:102AB000EF4F87D2A1DEB554F599796F4D06B93342 +:102AC0000E7F8329BB2C831BD2711DCB787FF8CD61 +:102AD000B710E5701A3FBFAF0FCC558B49EECB61F5 +:102AE000A14748178010658BCFEA83F61A476D938C +:102AF0001F4A39A3D6AAC13EBBD55AEB0ADA3F73A7 +:102B0000803284228FF853976A22398CED5F447AA1 +:102B1000EF662F7AF28894A8BDDBB16300E121DF74 +:102B2000CC985BC3F5C17C3ADF0378584B661ED363 +:102B3000601F3DB738691FB2E4A33ABB59A675E7D9 +:102B40006BF628AB013EAF2C38C6807FE45B6F9FED +:102B50008FF5716DF2EF0613F8F4D8A0B19EDB6C1F +:102B6000AC6733A85BE3F32E7273FC4D865B323C9B +:102B7000C6A9DD2770FDE382323D4C5EFF43EA03C8 +:102B800059F50CD7E9A075E6396EAA070801CA0500 +:102B9000D623FEFDADEBAC511759DD307F4D8E894C +:102BA000D496CBD8D0061C779BC0F71E373FCF38C2 +:102BB0005D9975BADC8A7439619D898513E48E3B11 +:102BC0006C67E184F94A7A9C867AE9F67C43FFF2E5 +:102BD0009DC586F6CAC844437BD5BE5A43BDBAF7E5 +:102BE0007243FFCBFA1A0CF549D17986FE75C716E8 +:102BF00019EA5362D71BFA4F3B7993A17DC6E06D6A +:102C000086F62BDE5E63A87F6EE82E437F5DDF4E87 +:102C1000968FDD822F7C5A3D3BCD05989D305FB26B +:102C20001E9FAC875BFFDAA56D407CCE54089F6584 +:102C300094E7505F73A7124943FCBFD2A7217FB925 +:102C40004BE0A3B7DC7F1F9E5B7DA695E482ECE0A2 +:102C5000FD64C71CD253C6EF04BE54875A231B6EB3 +:102C60004F47FEDC190E783CF175DBD4ED0CE9B76B +:102C70003EB3890D3AE2EFCBAA9F0533703E8DE655 +:102C8000B3AA61EA67D3E0FD847D1D34999803F906 +:102C9000F88042FA7A6F46818CF4D7FB97898D547D +:102CA000665C3107F17D92CA1EFD3EF4EF95D83186 +:102CB000067A52AF899D059D8D3D936447E9F6D311 +:102CC0007813B363B95B1ABC83A19DD271A2612C46 +:102CD000233BEB59DCF7BDA043E0BEEEADE17AD675 +:102CE000C6BC791AEA653DEEDE63C5B89E5C902BE2 +:102CF000480872C0877A85BEDF37C479CAC53D836C +:102D000028FFD6645935D49764EBF6C0EF005E8F88 +:102D100058069FE8827AB7A4AE42BB237CA7C3F7CC +:102D20003843FD91C34DCB30D56D80717BD7FBE52A +:102D30002C68EFDDC27CDD481F39F51BB2E07969F4 +:102D4000E10A9313E9C1B37E0396AFA01E0BF0AB6B +:102D5000F4EE3665437BD5E4FA6686B25785F9B260 +:102D600047C72773E64E86FB611EF92DC42BD4BAE4 +:102D70002FC0D2EB9D70DE30AF0DCF5BA292E06032 +:102D80003BE788D8B0EEE170B1F9A5483AD4733C7E +:102D90007EC9EFC5F776D2F9DAA2463D16ECCF37F9 +:102DA000DC53509F359EAB6C7D80D6B7CDC4E9A275 +:102DB000274B3B8EF2B9C7ED717669F175EA7CE578 +:102DC0006D618FEACF75BE723DDA1453E2FA0DE001 +:102DD000F94E5309EA67DB19F227DBDDDB19E2B5AF +:102DE0004D0D6B0CF5F0AF8509CF75FDF60E413337 +:102DF0008DC5CD5694D767736A499FB5ADDB4BE758 +:102E0000950C37DBA089F92F02D7CCB25D24DF8186 +:102E1000016B68871FCA73B4ED4EA1F76FD0389D60 +:102E20006D01328E79098FACC8AF2DC2CE004C3007 +:102E3000A17C3BAB326E27F6BAA97E4716AFEBE317 +:102E4000DC915B3BF662FAB70DECC260C23EB6C0E5 +:102E50003C08978DE71736215C994CC4C1B6FDC577 +:102E6000BB7B2BC252D8351B04BCBFAE71F88E574A +:102E700018D905BE9CF94D24FF5C4FD2F905CE153B +:102E800093109E56EC24F883116DEEA0F55B74F957 +:102E900064BA7019AD595360FD05F8A4184B2EDFC4 +:102EA000A0CBC00509F97F823CE305C9F702FE3BD0 +:102EB000C803637BF94E63BD3292F47E98BD86F2FF +:102EC0007F25E3F0AADA676CFF16CA71E01B2B8539 +:102ED0001C67DB2D24EFACB0A20B5CFEC6E521F035 +:102EE000876B7A63F5E9304ED1748B414E1624F628 +:102EF00003F8D5DE6A0AA0DDA0FB5F74B807DA4CE0 +:102F00001685E84123380D3F17FE9664FE3D3E8D41 +:102F10009FCB212523B2C1CDFD12C1326E6707813F +:102F200024EF957DBF6A417BEC98D907983D7C9E44 +:102F3000C9E7BF6F583F0ECC2F267B77B00EED6FE1 +:102F40009C2F98309FEE37292C0F2E2A86FE1F3497 +:102F5000E54CC6734A2B6416A463DD2FA2DBF9BBD4 +:102F6000115760BC6DBE573B0EC33A369F4C239F32 +:102F7000C66CF3F1639D505F532413DF53A7ADFA82 +:102F800036DAD30DFF0AEDF0CE664D1B4BFAFC315D +:102F90000BD9F50D02DF1B849DA6FB4F6E2BE6FAC5 +:102FA000F42DA28437ECDC4E8FDA51EFADDA073C1A +:102FB000DB882FE9BCDD4F7A71756F72BB9F21BD35 +:102FC0004F14F80075473DD427897A2F93B25538AE +:102FD000E7CB9A070FA1C9E17DE9881DF5B0FD3661 +:102FE0008E1F4F0ABD2F8F49BE28AC3F6F9FC3175E +:102FF000817E1966B63F06FBF0BD28BF399800CF29 +:103000009A7E63DDCB12EA6E5C87B17E8FD621217A +:103010005CEE690154842D6F28CEC879AB8A21CC2F +:10302000CB10FF669B1D93D0EE5A53EF6008D7B4C8 +:1030300053E5DF8C219F396166283FD474EDBE468D +:10304000785FFD976CDF7A2D7EFE4F76228B67ECE2 +:10305000C10B3ED6ED89FBA99E82F34479F33DB0C6 +:10306000C7B1BD17CE15EBCF803D8EE501B0C7F1DE +:10307000F973608F63BD0FEC712C7F04F6383EEF5F +:10308000077B1CEB7BCBEA1F4CF66F25FAF9E2FEBF +:10309000AD4149F76FA5015C1BD04E9C92E0E70A59 +:1030A000723FD7278FE3D7C721FFE1887186FD885C +:1030B0005615FD27C5F0C61878FEDE9DBFDE8B7263 +:1030C000658114DC87F8BD7ACA9B0AD7B38714ECF4 +:1030D000FFB00DF01FF854E128FEC32B679DBA2303 +:1030E00017ECF41F15B72E443BFFCADB4FD58D8775 +:1030F0003A2B39C6EBDF39F56C01F0EA5B4AB6F0E2 +:10310000FAFDA7CE1642FB18F6ECC2C619E47724E6 +:1031100039F6B0C49A13F5C09F08FA0CADDB41FC38 +:1031200014E400433874E505488E9ECE19CA5C014C +:10313000FD43B94379375D84CF87D63D48F2AA2B4A +:10314000F3F7A4A7740DCB151FC9157D5E5DAE7C8A +:1031500020704F972B6B6CBC3ADC2F5842CFEF1787 +:10316000FE1F1629A57AB68DD7FF5783F60ADA47D0 +:10317000001FB2870F674EFCFA4CB43F9B645F1A86 +:10318000D4EF77D4DA502E9D15F40BE386D1DE0F01 +:10319000CFB6461EC743CDD1881E9DFAF8391E54BE +:1031A000CE9853ACE3C5CBED51F40774355AF7A074 +:1031B000DEB9C3514CE3754D57C2E887D1EB1B2EE6 +:1031C000BFDC8A7A4756A6D38D759D3FE9FE5BF832 +:1031D00031E3B80D62BB0D5647D49C89E861F943D1 +:1031E000A23EED6031C21F9F090C17A0B7AF9570CA +:1031F000BCAA63BE667CAE481D6144C68771EDB84B +:103200008F0CE1CF44093535611FFE02BE2F7D1FB3 +:10321000194A58EC83F4A91D0E5314F5C21DB02FA2 +:103220001CEFDF8B35824FF2BE18BA6861DC59D3D0 +:10323000C5BAD59907701DB34DFE6E7CEFC8C72D7A +:1032400039887E7358878CCF4BC0F245FF2DA07410 +:10325000F7858BE827C9FEDB2BFF4DA2FDB0DB1500 +:103260003A17A58CEF7B97127133328423E31665EE +:103270008C8EBF2525FC7CE3F8EB67484F5D4E3F05 +:10328000C75F7528733DE26FD650DE06DA5734E526 +:103290007924E371F2F9D4206D73396046F87ED257 +:1032A00079EAE7A8E341B2FCFA5A89AA9FAF8BF604 +:1032B000E9AFE074A0EB5B0CECA18C91F0DB04E3D4 +:1032C0006965F1BAE20A901E6DC9F155A09FB7EB8E +:1032D000AFE6B6547EDE1B049CD667DA49BFEECA61 +:1032E000E4FAF540E63C835DD408769204F861CEBA +:1032F00066BD4847E631D7939FCC3C1635285C57CE +:1033000092DE3A663ED75B55D05B53CCAB9732EA40 +:10331000AD29F4D961BDD5398FEBAD990AE9AD0F6F +:103320006728CDBB53F09BA9255C2F1CC07DA4B0A2 +:103330000BC11E247FA56E0F2A6A90EC3A7D9F5325 +:10334000055DE9FDD3D40E86FE33B3E2D3502F35AD +:10335000DBB99E9906DBAC4890DFFAFC934A785CB7 +:1033600025AB9CEBFB262BD74FAE7C45EA4805F7F7 +:103370005089EE5F498D777F03DE105FA875287E48 +:10338000D40F6A1DAE06D40F467B0F4CD2F0DBCEB5 +:10339000385FF1FD75AA99E48FEC73219EF55A060A +:1033A0009F7D05EDBD230E9237BD1985349EAE5F1E +:1033B000835D1BAE8041F6FF1928D134D29E053BB8 +:1033C0006B4B09C6BFD6E44DE6E3829E573D52AF34 +:1033D0004CF61B0CD37BE65E377F2F320EDF93D685 +:1033E0004C1F8B78954CEF7A59E4FA69D14A5857BB +:1033F000D1B86354EACFFF8999C90F97DC3F327C7B +:103400000E5C2E57C26463CC248F23B8EEF7D6BE71 +:103410009AE783A5B4CB67482E7FD0317DCC668DEB +:10342000F3DB7D2867BE2413BF2DBC7520CB9970BC +:10343000CEBB3AFB8A640FC61762458D1EF2F7F9C0 +:1034400053ADF7B83E7F7402F1678BC0032D27366A +:10345000B71CE0AE394C3E542540F81AF840BD9CEC +:10346000D5A8C2FC459DCCE780BA9BA9E4F72ABA4F +:1034700060267C2B3ABC8CF07842CE9014F626CC99 +:1034800083AC38217EF2614723D167D1D8617B8F2D +:10349000E20C1FE64417227D7FF8005F51D1A3C6DE +:1034A0007690B1E497BE65AD3D8226E384BB5513AB +:1034B000D68BBE2DB14237AEE3B07B33FA757E9822 +:1034C0004E7E1DF34E0FF965BE2D050F105C23DAFD +:1034D000574C2562B3D06FF557ED7BB6921C8BCD60 +:1034E0002539F665137B3C85DFE9E725DC8FF19A0A +:1034F000C0F722D7CB452BEBB03C4EE77DA9F4C4F7 +:1035000004DFDE3C663BC5C5C20DAC02EDC31E0B3D +:10351000E0550A7AF57B387F19E6C7027E36B45645 +:10352000602CB324F4BC7D4F3EF9641ECA6D46F690 +:103530006472BC36BDA2971AD37D7E86FE0949F51A +:10354000733EAB865D618C03FDC59C12AFC77804EA +:103550009F766F7261FF468FCF857430E09EEABA26 +:1035600009E0E770282C2D810FEB78F262C654D267 +:1035700043F471D664145FD42E57801F6B1791D318 +:103580000AFAC7519F3934C3AAC17A37396A63A886 +:103590006F6D72E4D4929FDD017C23C1EFE4701C57 +:1035A000253C74F8B83FCE81FC17FD4E62FF03EE58 +:1035B000A3B47FBDDFBB820F397C511EA7046B060D +:1035C000FBD9E44018ED0C5B0E23BBD266E5F49406 +:1035D0000EC7614DE023FABCBF2BE1F6DAA6C2DAD2 +:1035E000583DAD4F46CF01DBE4AA75913C4438A36A +:1035F0003E3A6E581F25FF4AB180B33E4ED700DFDA +:1036000067609DCBDF988D7668C0E5C1711D375925 +:10361000C3281732265F743CAF4732F887E2E3AD28 +:103620009B25C62BC6F1CC19B52A8E67413E910267 +:10363000FF6688757D56FF19405425BB8D71FD0AC4 +:1036400030DE954A8FD04BABF0838D7C8FF349B73A +:10365000B05F804FCEF6A0DD52F8E6D17AEAC5ED34 +:1036600016E75CB94286F3FA004ED02CC5EDF8643B +:103670007DA6DE3C44724D9747BA7CDA85FA8C12FF +:10368000A7A77CCEB958415B80E4B6941320BC0157 +:10369000FD4643BA31637C3805DCB608F84B99D354 +:1036A00035A497C6F38305F8DEC18CB70B5882BFEB +:1036B0004DE7872F7EBCD786ED1FB6355C546FD1A2 +:1036C000E3C7A3C58D33EFFAFD9712F596D1E2C893 +:1036D0009F143F3E94A9909FEE11C9C897BA043F2A +:1036E000FA9AC00B6771F02B88478F48011FE98D4C +:1036F000C29FE22D0FDE89E733BE47616138CF8379 +:103700001F4F75217E5C2A7C753F7BBED0A7F21DC2 +:103710007B25A4D3FCB688847EF282B65EC97F91F5 +:103720007E8B3C9C9EF5FE1631FE55F29019E5D538 +:1037300055828E0BCEC9AC22410F5CE0E1FA944574 +:10374000E8EF99879EB0E178874C819E32940F997B +:1037500026EDF1047AB7DC5A6B6D48840FC67F52B0 +:103760009CDF773DC37A17D947BABCB5E8722247C8 +:1037700036C889503AC75B5DDF095DCEED21490A45 +:103780003E86F03E7DF9EFAF4196755AEA55304ED0 +:10379000FE49F18F61BDC61459A1DB31482F3E5956 +:1037A000FDF120BC3FE93BF5440F535890CA698CAA +:1037B000EB7DA0473DE321FD0E969C70BE0C5D0F96 +:1037C000799FBC8F473C5CDEDD2BC7C8CF7AEF7991 +:1037D00089F878327CFEE8D1FD5AC371BE8BFA4974 +:1037E00035F493BA316E65F463D61D33D6A7C48C15 +:1037F000F5692793FDA2FE5F24FA451F06BA427EB3 +:10380000A0FB410BC3917A15D65BC47A296E58D0C0 +:10381000E634C0F54AB3C8A7607E29D13F5B202FAC +:103820007807DFFFFDF0B98749CFBA45B4FF43E31E +:10383000CAAF74A3ED3CEC67D5085EFF3077D16C5E +:103840003CD7647F6B514742FC918DF4B3DEF2B0FC +:10385000C5D01EF04F223B60F112A37F96D691CBCC +:10386000F75B503B72FE4F9E17FE3947CEAF8FBBC2 +:103870000BF80DF251761ECE752AC28DA1C78115A7 +:10388000C95109E3D7F91DCC8FFA70C15AE64F151B +:1038900007282CE578900C6716BE8AE0374B3CCBA6 +:1038A0007798C94ECF5F6B223D301FF801F2816BD4 +:1038B0005601B940BD6095467AE4B56D26867280A2 +:1038C0009DEF34BC0FCB257FA77EEEBB703CD4238D +:1038D00057B38809F7D33191E889D6556CF08BBF7F +:1038E000C9E16525785D3BDD62F06B16A11F3301F0 +:1038F0002E3A1E14243D7FC1A31AE802E45961291F +:10390000E13F9773A528E76049EFCD38B917F3D9A0 +:10391000AEDCC068BF4359F608CF93188E27982FA6 +:1039200094037FB2CEAA40BFCA36D56EC27C8683CE +:103930005983DF62598CD594B270E34CC6FED93EF0 +:10394000542541FDF2D24777F4C0A11CB40D7D1778 +:103950009DBD0EC7938B9A3E17AF67661EA43A9B18 +:10396000CE3419E063C719609F7675DE3E33CC6FA5 +:10397000F73AC8096967C3744AFBE9BE5CBB07F341 +:1039800041BA4B4DA427B1C476D8C7774A553DBF3D +:103990008CF2DD58138FEF278E2FE75C64FC7930B3 +:1039A000FEE44F31BE95AF3F0F1F817CC9C3F5A325 +:1039B0009F1AC7C7F3456751E2FC623C998577635C +:1039C000FC05E673487C3E15F34DF29831BF6078F4 +:1039D0003E15E6ABFE3BECA779E479582E761ED770 +:1039E0007FBAF3E836F969BDE11A07D93F0C9A4D61 +:1039F00053D1CEE0F3D964F6A25CCBE1DA3D350ECB +:103A000057D0F7685CE8BEFE8280B305E1AC2A04BB +:103A1000E7D1E07648E5F94E5B547B64BDFBFFC11E +:103A200079B9F87925CE877AE325CF773DCC97739E +:103A3000E9F3217C917E86E10B67B221EFD2E10BA5 +:103A4000AB0A5F0A7C0FC1B8A604B8C6F38A1E523F +:103A500051FFB75902561FF0DF03A53C5FD19BB35E +:103A6000C84A7906B98BAC98BFB7D1EB68C278DD8C +:103A700046CF12AB25414E6FF4B6503BF4A77C28DD +:103A80006FD48EEE0956CD6264FF6F99D9E85A81E2 +:103A9000F8D3C1F3ABF47C235D1E3211BFA47DC10A +:103AA0008B633E7760E810F4DFD23199F2C9C664C7 +:103AB000FD89F2A8B6B5F97CD8FE2D8C33813EF194 +:103AC000A0883321A2921FADE6F247312E5B5BBA8C +:103AD00046C2748EC25546F9949F94A7537B26D64E +:103AE00080F9586C05CFB772B5C849F2D048B7DB3A +:103AF00010AE3C2F2A2271F81AC6FB3D32E95CD485 +:103B0000EFF730B4EF9E85B1CC46FA32617E523287 +:103B10003DCA8A5FAD47BD7C8D89D65180217F101B +:103B200071B5D5F35D2BE079E1CDB24F82E763BD8E +:103B300077539E1268F5A46F78BDC71BB03E629F95 +:103B40002B8DFB48DE57F2BA4170911EA29F57EDB4 +:103B5000195F3ADA51B5A58B288F8C7E747A372796 +:103B6000ED271BED5F93DF0672CCEE49D81733F4D7 +:103B70001376DA7F6DFD242213D25172FCEB6B01B8 +:103B80005A671AF359157AAF85EC453DAE968FB456 +:103B900083E73E9EF1B844F2FB53F9FBCCC5E36CDE +:103BA0006976303D81FEA4DBECE4BF4C4B833A9C4C +:103BB0008FA430EB3878BE4BF8FDD64B4CC67A7CE0 +:103BC000BE28E5A9774981ED3E3796DC5EB26405F3 +:103BD000280F11C3B48976E721CCEF80F635B7BA48 +:103BE000C7A2DF6E0C10440CED661197D2FD24992C +:103BF0002583CB517E1797952CB6A27C46C7D2E57C +:103C00008C5DB6B7E8FEF0CC385DA69DCB675A82D6 +:103C1000FD922677509E47DAB9F1067F4A54D85D67 +:103C20007ADD9F2337E27C73D02EC0BC26A676E3D4 +:103C30007BF500142DD13F7ACE6518273E7EA16119 +:103C4000DE28D8CF897180D1C74F675A45E2F8C5C1 +:103C5000A38C5F9634BE9A72FCF8B8D9867137CAC5 +:103C60009C5F8473EC9154FEBC95650D5797E58E6F +:103C70009E87F6C532E177B302CBC7B893C09BCD20 +:103C8000AE0ECA4B33DB797CD422E2258733DA8847 +:103C90005FB142635E5A0353656CDF9839E798045D +:103CA000ED0D0EA39E7ED5F937CDC877AE928D7AF5 +:103CB000BA9F75107E5EC98CCF2D85463E40BA36C0 +:103CC000FAFD3326C7287F2DD7417906A3F90F7E49 +:103CD000D3C928AFCA921EE840197777D9B4EC8DC2 +:103CE000D3A13E86E3D7D6B2F98BD11FF41B81C78F +:103CF0001B81EE118E2D6BC6EE36278CDBA2444B5A +:103D0000518EB498781E3FFDC0FCBFC9CD277F6A95 +:103D1000F2BC94099CE08F6AED90029E847DFC4683 +:103D2000D0C5F07C7714EC463D7678BEB4E8149AA2 +:103D30006F381F48CC97F7D9E67B43D0B33E5FEB93 +:103D4000578CFB6B5562B4BF561313F9FF7CBE371B +:103D5000707FEECF309FC8EB1A9EEFABC6FDB5A6C5 +:103D6000C5687FADC3F6A4982FEFB3CD97A6745066 +:103D70003CE63E899FEBA1BD4BEE477FFCD9F96B3A +:103D800034C437DD3EA3FB3366BA3F4372EFDA42F9 +:103D900085F4067DDC7D9DD3995FE17E1B2C2B662F +:103DA0004A740FA072BAE4C778D8C340F7FE32F461 +:103DB0004BA9D41EE97451B9A753A3F231B007FD42 +:103DC000E49FF251FD6C19B787EF1BA72E5B89FAB0 +:103DD00042BD9DE741CFBC0234D1B8BD0506D82114 +:103DE0001BE61B7E814DDA8A68BE93C323A7312F61 +:103DF00082E7649FF462AC13EA6933CC1AE677A7D2 +:103E0000B9592095DFE57D913FB359CF9BFF9CC405 +:103E1000E3EDA08FD4C3FE6F14A066E6F912EA5555 +:103E2000D77E358BF491962583192AACE30669D2A7 +:103E30002F3C008FFF2DF4911BC7733A4EB62773AA +:103E400050B24CC6BC3E732402BF2ECE584CF6E88E +:103E5000E2A58C39E1FD6BF13D902BAF087DE6E5E5 +:103E6000C13486F65AB891C7996FB8DB6847DE67E8 +:103E70008BAAA8C7DD372987E179B4AC35B66F16B0 +:103E8000F182C54976E5B5497934A065F27C10DC4C +:103E9000F30CC6DE2DCBC8A13C589147F384F00B40 +:103EA000B1C21C4AB676CEF58CC1F8639A92FA7EFE +:103EB0008E3E5E8EE03B2CC74F70D0F3CA99F9A9B5 +:103EC00049F4BE984F7F6F97F4D4B88BF935416FA2 +:103ED0007B6BB082CB67D4AF59B931DFE7ECFCE242 +:103EE000AF37B254783B24A35F415FFFFF2D7CFDC9 +:103EF00011EE17CA57667D3899DF432B6489F7CFD7 +:103F0000F47CAAC5C37599A15EB954AFBA86BC78D2 +:103F1000DEAF7D2EDDB795F04FE80FD1D74D17D22C +:103F20003FFD78C3EB70F98BB83F4EDC1314E38D83 +:103F300006E7E47C07DD6F433F53E3FED8AEDD3C8C +:103F40002F323FA7E11DBC3F85CFDF34E095F19EC6 +:103F500054D7C01312DA17DFC27B5F727C3EF4D3F2 +:103F600086497F35DEDF1A218F19BF97A3AFA74B94 +:103F70006115648F9A803FC07C0B1C83B2A4A1DFC3 +:103F80007D88EEF3DD59CECF057387F97D18AEE756 +:103F9000990B4C3C7F6382C6F53ECFD0F8C4B8D0B5 +:103FA0000DE55CAE2F487F75AD06F26F49F9938B36 +:103FB000313F69C19857D7BAA17E5DF97717CB8099 +:103FC000470B0A5EFDD00D3ADBB2F2A778BDEAD509 +:103FD0000F8BA1BEBCFC695EBF8211505ACBBFB72C +:103FE00018F9EA0DE5AAF0F3C50A71BE0512A78F0C +:103FF000CF5A9AD34C29E3F7FF50AEFB139905E74C +:1040000009F4FFE424F2A380EE7FF527C51BB12954 +:104010000FEF13899F9C4CD267E6E1EF00CFABE531 +:10402000E800BE6FB24609AEE59837534128F0C0AC +:10403000858BE44724E39104E8BA0EF5654D652DC0 +:10404000A01F77AD63415B49029E33BFC0739EC71B +:10405000A3AF479F7FC4BAE0486567E2BA1EA67166 +:10406000F4759D9E9416C67B677AFC545FD7696988 +:10407000E811744644AB0697E2B99ECE181A2F4158 +:104080005DAB5097503D77E811C99750B7F073BCBE +:10409000B7FC27A4F7AC95FCF79623BF541C74BF5C +:1040A000AD47E879DB728361C6F57BCA770C17F1FF +:1040B0007B038D93257F627CFF9B02BFF22A7839B8 +:1040C0003B6D7BC709C0C7D00189AD87FEA1F367EF +:1040D00015B4C717F49F52D0EE6E3F704A41BBBA79 +:1040E0001DEB304EFBC30AF1AB64781754980D7189 +:1040F00074DD9E385254B63107D6D3BE52F2618A6F +:10410000EC9AE7B366637DCD0ADC2563D7CFDC3F4D +:104110001BC9BB3530B011CB1BD9E0118C172C0B50 +:104120001AF5FCE56D46BDBCB5C3A84FDFB81D4E02 +:1041300007E4D78DEB0A0CEF31D490613DCBC47905 +:104140002E73DD1333D7603DE1BE8E44644DFE9D7A +:10415000E57C07501AFD160BFA25A2E3F6662BF94B +:104160005F8F14F13CFBD02A33E50585101DB0DECE +:1041700021097F969FF8A32EBF67F79D395A80EFDC +:10418000AFB2101C58D81F43FF43B3C0A71B9B9B63 +:10419000DE413C6BD66EE3727CC25E0BF957825CEB +:1041A0001FD784FFBBA5EFBE4627EA9F6B25F26FA2 +:1041B0002C6F33EAEBADF80BEA6FEBA448D48D70AB +:1041C00032B6DFB8CE587FBD5CC8DB2A568574F2A4 +:1041D000DB7249A67BC5A2FE87A25FBE1C8589EE65 +:1041E0009202A710EF5629D11A946B774941AAEB96 +:1041F000EDF0BC9DCB1D2EEF4D4051C4772DDCAFB3 +:10420000105E2D113E2E1F21FF13F403F3C87A4ECA +:1042100005F7B777D9026BC95E7A4152511F69948D +:10422000FDB2D31BB76793F13157E0F7CB6CD08B5E +:10423000EB2A43A003FCCB168F89A03FACEC9F5721 +:10424000507E63599DE433113D9BD8BA5A2C65E2E8 +:104250000FA86FDAA02C33F73613BFBE4C5179FE8E +:10426000A08B25F201FF134C4278E1D271DEAB0B3B +:104270008F7D8CE778CDCE7BCE20BFF394F86BEFAB +:1042800083F56DB3F1F9B73D2F91FEDAEE3D4A7C2F +:10429000712CA009CEDBEE12FCB10FF8A3BEFF62B9 +:1042A000BCD70FFC0A2F8ECCF7D2BCE3F4F8809E6B +:1042B0005F1B6D305D00BE3356CC5B50A311BCF26A +:1042C0006EEB9570DF452CBC1EFD44328E991B2F82 +:1042D000753FFED278BCFA9B789EAB5D830AE9DF1E +:1042E000225E9DA2DFEE94FDFCCCE047986D3E9FE0 +:1042F0008971E5352F945C34AFC26C3519E8D5A2CD +:10430000DA0D747D758591CE17F88CF47DEDF4127D +:1043100043FB427F95A17D71539DA1BE347085A161 +:10432000FF75CDB38CF6BE6B9EA1BF4D5B64A8A795 +:10433000575C6FE89FE1BBC9C86F727A297F40B1B3 +:104340008607831ADEAF676CBA33CEAFAB32AD9857 +:1043500064CCEC753607963D93D2A2786E3DF93C5D +:104360009E9AF6D2975D5184FA98A7ACF5507E5785 +:104370008A3460BCC82AECBC897733033FFFA72A84 +:104380008EE77AB9A42278632594DE7D5A01CF970F +:104390008E4DC4F3B1A20311F1F8392BE91D972515 +:1043A000E9BF4535F5CB2AF0BDBBFD73C92FD5C795 +:1043B00054BC57BB47E1F94CE1E778FEACB76FD08E +:1043C000E44FA0B7FF53C1E5FD37020D949FD4DE43 +:1043D0000FD20CF17BE79B0AFAEDDAFB0732516E44 +:1043E000D404DE5450BF8E3F17F2441EB263FCF279 +:1043F000FBBDA9F3D0BE51A1D0F84705BF6DFD327A +:10440000E7B78070F3D13ED2F967EB7EBEBFD6A589 +:104410000AD1B7CE47817F1AE261C97C79F9CCC84D +:1044200046A45DE0A306FBE5C62573DE417B0824B8 +:1044300035E931C0478DED859B88BE6F4CB26FBAB0 +:104440002A86F9A9F702D0CBC98029E5BEF654C95E +:10445000B4AF93C15904EF6F00DCD06EFCC60838CE +:1044600071F87D127C9E16FE44FD9C92FB7DA78A0E +:104470009FD3D3A3F0CB77059FDD23C56A919985A0 +:104480000276C2D3E556EB52CC33385AF4D1268C9F +:1044900027B4FE40425B96FDEBC04B799877A0ECC9 +:1044A0003F9287F910A1DE23790CE0B4CAA2AD4790 +:1044B000BD18F0C0B71ECEA5BD2F4AEB5FDD5B3740 +:1044C00080CF57F7493E6485A10367E6D03ED9E027 +:1044D00026D4E3F78CB2AEFD153CAFADBF42E37915 +:1044E000F7419813E5EC8134B2635BF7031FC275A3 +:1044F0003D2FD13D8C3D5BACCDA9F493A7AAF877B5 +:104500001B5EDCA2308CA3AC82F7711F478B8E2A16 +:1045100056C49BFD12D984A1DE134BD11F1F5A6BC9 +:104520006118B7D5D7F75E51ECB7B8FFD7575A180F +:10453000DE2FEC5AC9E3B1AFAF35D338E69B2D542B +:104540005F762BCF133EBCF2DF3615C0B8AFAF920B +:1045500028BF7ED6CD7F3C8AF565B7723D28197F8E +:1045600087F135093F97058D7837024FDB3E1B9E5B +:104570009EAC10F66B15AB41390BE73E7B2CE2CFBE +:104580009D8CEE37369F3F6C190BEB2DDEA4FA3075 +:10459000B45B6D8E6CCC43BE7098B74F5AB55BE27E +:1045A000FC45A37BEF053D0A43BBF15D715EEFE285 +:1045B00079E5E2D68624CC6B6372AC18D7E716791E +:1045C0005CCF5858F37EF423C99CBF54FFD0B53B51 +:1045D000D18FB44BE0A3CEF7AAC0DEDF4F7EE8DE7A +:1045E0007CBC8FFEB485FBC7C68BF14A4B86E62C9C +:1045F0008432BD92CFFF47B10EBDFE9CC07FF687CF +:104600004709BE0BAC1CEEF3D6455B701FB7C8C1A3 +:104610003F23FF9B3FFE97AB50AEF514FFD44BDF1B +:1046200065611349AE85C4791C9EF1EF0FDF81F9F6 +:104630007695763AC785871E8AE1B9B67B64CA3318 +:10464000B4954E1E1BBC881F21744E33DCEF6BEFFC +:104650003F33C79F82AEF757F1FD578B7B7CAC9FF2 +:10466000FB0F801FCBD36BE3FDF4FDEB7E0F5BE90B +:1046700063744E777C894DE2F7FBEFA37196AF3AF6 +:1046800021E1BD94EB2C7E8B03E0FCCB316C29DA6D +:10469000C13FED64744FED38DE570356F272A74AFE +:1046A000F598B8B7F66AA746E5754A603CCA95A57D +:1046B0002F769422BC0E173D18C0EF359C3E2EF489 +:1046C00059A6F2FB8E02F7CEF69B9915DACF1E9013 +:1046D00022E43411EBBFE15C3E0B023FF9B5B81F99 +:1046E000B77ADDCF89CFF9DACECC413B63D2AA537A +:1046F0009BB01E5AF7C739A837FC16E404E257A846 +:104700004F622E18A7E59C93DE5FDD7742417BFE6A +:1047100069D3D01C847FF8A044F7AA421D67887F24 +:104720003E2CFC2B37546671BED13FC944E7E99F4C +:10473000C8ED1371FE0313FF9489FCCBBA4E7BE5E1 +:104740000A3CC763663AC7AD0D43996A8A73390953 +:10475000E3A24FFBD7221F2FB9BD5909935FB6596A +:10476000E06D72FBF59526DD0EB7883C2526C17AF3 +:104770005A047EB532FE9DA0963E296A07BA6DEDB9 +:104780009F45FE8DD68E8B7F0766347CBBD4B29D51 +:1047900071FF865E47FB2B315F0BED2FE37DF5301C +:1047A000E1555A91676CF022FA5D68309FE227ED7F +:1047B0003D8CE225ABCF4DA4F2FDE737D3BD27AB4F +:1047C0007DE841940BACCC447AFDEAB051BF992D01 +:1047D000E876B6D06FD654827D52C186ED13B043D1 +:1047E000BE5CC9ED90CC43CC609F243F27FBC42A1C +:1047F000FC86305CF09914EB9E57D57057652ED22D +:10480000D576C26F06F88D7895BCCF8D959C3E7598 +:104810007A5E76E81D05F5DD505F6A7A5E5A55BF0F +:1048200011D7B36594FCBBAB05BDAFDEC9085EA173 +:104830009D4E82D37B6C67A001F0F23D5807DE5F8E +:104840003F1D08A467C1FBA78381748CCFE9F4DF07 +:10485000BED34EEF6DF12CCAC6EF6DECAAE4F1F3B6 +:10486000F7FB665911CE37ECE474A7CFF7DBE8B25B +:104870006CA49F29962105FD9385FDA73251AF9B1E +:10488000F2FCE26CA4BFD1D6B975A258E7BAFCA578 +:1048900074EF077ECC40F7B70B3916DA105510FECF +:1048A000B7AF6384BF03CFFD6B3BD2EFFBFDE92ABB +:1048B000CAC9F75E480F23BF3F7D302D6282A156E3 +:1048C00089EF24BD6719BC86F4C7E7CD94AF103AD1 +:1048D000F8EE83488FA1E7D2E81ECDEDFD9BCFA077 +:1048E0009C5BD53FF71D19CBA7FEBEF4B07ADDF86F +:1048F000A589F9C5EF76EECB47FEF9BECCF9C4ED3C +:104900007DCF923E7BFBF9B335983FF8DE0B7F9E5F +:104910008AFC2CF4CF67A7221F0BFDF8EC546C0F18 +:10492000FD30BD23957EF2E32AEE3FD1E5A3FB35B2 +:10493000D9E067B959E087BB7B7B137ECF60CA891A +:10494000251407D0DBA794F27BCC537ED1987D73DE +:10495000C27BDD3199F225269F684C5F998097D7FD +:104960005759747FCDA5F947441E82EE1FD9129383 +:10497000F9BDBA36337DBF6E798CC7DF93FD268CC7 +:1049800005AEAEC6F3BE35D787DFF1C1FBEB181716 +:10499000397D676984EEAF87AD473C097AD0B2981C +:1049A000299A867E90FEB428EA43CB62F2A9B40429 +:1049B000BFC86FD56736A21ABF2C68F46324FB41C9 +:1049C000E027434E889FB4AE8D5A7439B500E6FF98 +:1049D000E546A662DC66847FA4F9F3E48749F69392 +:1049E00068B107ACF89EE6E1DFDDD1F54C3CAF03E2 +:1049F00029E87DC344CEB7743AEA8E99E81CBA63BD +:104A00000D560F94FF28DA0F80D80C635E50FFE23A +:104A1000C7D14EEF3E7F5D3AC2ABFBB5450CBF2B15 +:104A2000715A6DB096E27BE73F6F5DEA8DE3C70890 +:104A3000FE3191F3C7617D6014393753CCFBF79297 +:104A400077D3279A84BFE1FF6F790776F55513B9BD +:104A50005DBD9CFB3DB85D9D2C2774FEAB8F1B128A +:104A6000F01EC97FDF21FD05EC5FE2BFA1891AF5C9 +:104A70002BEC5F984D76F16B4BB235C7C8F14B64A8 +:104A80009FC9E91D39BEAEAF85C2FE2356B463FC93 +:104A90003CFF34B444A2EF4B850212E9D9A1164B76 +:104AA00004DBF5F5C496F0B8E0529F44DF0BD1F576 +:104AB0003F5D3F1C6E9F0CEDEEB8BEA8EB85B100CC +:104AC000F78B2EF15BA8FD3A25780BC2E9B7511B95 +:104AD0003D9F32838F0B7CE008FA3FAFFB8244DFBF +:104AE000F3D2F5451D3F93F5C90FFA4B2EFA9DBA47 +:104AF00087055EEAF4353E892E7439B5AB92C3A7BB +:104B00001DE57436CAE98F9541C7E87A37C8E9BB15 +:104B100070FDBB2A19BD3FF917722095DD9D21C696 +:104B2000DF8AE7066561ECC57A5C6F118B515ED454 +:104B300068F2F3B62A4E0FA3B5EFAABC343AFE8151 +:104B400098FFEF45C7FB27FEF7D05B87F53F25F5BC +:104B50003EE755D5FF6822C0D56EEEA0FB51EC5F55 +:104B60002CE4B74EEE1712F218E499018F8F142936 +:104B700026B47B426DDCEEEFC9D25E21FBE4257EDC +:104B8000EFFE7691AF74DB3995CA1EFC8018B67FB4 +:104B9000D94D7E9BDBF69DB0F8E1FDE56BA549E8BC +:104BA0000F5ADE66DC4F4FAE7F6EA21FBC675C2FD4 +:104BB000C515C28F9768387E2B6E16FD213DF91101 +:104BC0008C3DB6A31FE7327C9E70DF02E6592D9E16 +:104BD0005F21FC3B2C490FF8F1C0EBE4EFC1B810AA +:104BE000D2AFD22F515E48E818F777B4F773BEF012 +:104BF000769B44FCE46D919F115A6723FFB6AE4744 +:104C0000BC23FADD7AA744FADE08BDC26F8CBBACC8 +:104C10007EEC17C41793F508E7013E0EC65BD02F54 +:104C200073A468AA84F5D56017E2F74B439A766DB2 +:104C3000015F1F8B107FF11BFC281F1CFB37B22369 +:104C4000973F2FB16CD23B92E22F3DF392E22F4778 +:104C50008F14E03842CF50E13FF41F26EB19ED7D71 +:104C6000272C68177C529C45A91AF6B7905F708272 +:104C7000CCFDAC13FA2515FD4913049CA66DB113A8 +:104C80009CE6BCB1321BE95C3F9FF717F2F37AFF59 +:104C9000F50FEBF1BDA96FC82AF2DB1FBFBEF6E727 +:104CA00005BCAE59357C6F6D3ADA21EFBFB1261DD8 +:104CB000E1F86328F13B4A3F3C29A7F41FAE15FCFD +:104CC00008E45B4115E6DBDE2DFCC632C8B78CB8C4 +:104CD000FF25F9BD1DC21EEBC1EF1B21FE3DCFE339 +:104CE000DB3DE382F3A8FE5031CF239639BE3EDB95 +:104CF0009FA5A2BE57059BC538ECF7ECAC1BE32B78 +:104D00003DB9C19F127D3C6422FC85F7F97727F6F7 +:104D10006B24EF106418FFA8015963A5BCC61C8A58 +:104D200083E8DF85190776A8F88EC2128CBB5689F6 +:104D300038488D9DC938FE364B706B25C65D0664BC +:104D4000DF7A7C47F665E3F79292E3317A7C588FFD +:104D5000CBE871E2D1E23212CE53C3F12CF13B2702 +:104D60007AFC857D81E76F764DEFA0FBAF63B12FB5 +:104D7000F1CF11F194D5686F26C753EEAAD4FB1B6F +:104D8000E3695B2B9E217CFBB471B41F4C1C6D7ED0 +:104D90008D9E27CF3F39EB833CB25FFEF21F9924F3 +:104DA000CFFACF92DC393D9426EE710E723F75BF7B +:104DB00085ECF5D36007E526C8B35F55F2710FF5B2 +:104DC000CF227C3C106B4CC7FE7FADE4F0D9F2DA09 +:104DD00092C5A84F876332CFC766DCAE391093A760 +:104DE00070FD60049C364D4C0127AB3D751ED054C0 +:104DF00081D753ABF8BE67BDCEED95D05A1E3F505C +:104E000005BD859A14E227478BF224DD8F3C365589 +:104E10007CE1F921E2B3ADB7F2F8EE25C717FA0647 +:104E20002CAC3885DFB6690EF19B4BF5D732B482D6 +:104E3000A7C6F9F3769D9F5473FFADAB8AE7F33BAA +:104E40003B26D5E377F1F47DA78023F35E5A9C2FB0 +:104E5000B3FAD2FA2DACB8B47E9B2B529C5F8A7EFB +:104E6000DFB8C47E3FB8C479D353D1578A7E7FBCA4 +:104E7000C4795FAAFC9FF8E7703D39BE991C0F4DBD +:104E80008E73A6BD747318DB364BF70C4511BA99B7 +:104E9000CF35E3F7D3E5ACC7ACC8D7E6CFE0F180B8 +:104EA0002D8DD6C86E291E17D5E1F55135D7BB54C7 +:104EB000EF99307E3F71BC3FD6980D747C7A062303 +:104EC000BBE1B44D7C0F4956C72DA4F353E97B38A1 +:104ED0003DB6D4F1A527C578A3F191A29AFAF3556E +:104EE00053E8FE50CAEF54DC2FF440B58F91BF86D3 +:104EF000C9DAB84534AF360EE5CC9817F9F3CC28AB +:104F0000A3FC3E68772F22FD5973E3FA7688B897A1 +:104F1000735E991BFD744E90B71817B90FE323E425 +:104F2000D757A99F3E5F9797CFB7C3C2248C63859D +:104F30002B795E056BE935C4358E5BA2BF5B2151D1 +:104F40005C632CD2FBCF4C51EF1E373F1784AFF779 +:104F5000804AF19697677CA782EEC58B38C71D2AD9 +:104F6000EF7218ED0C58C71D2FD411FE2E3F34E3FD +:104F7000572DA80F7A6482F3083D5CD85727857DAA +:104F8000A8DB5783682726D81B555ED3687CA92ADF +:104F9000155FDA2171FB37FC336EFFD629BE92C450 +:104FA0007CAA69021E2BA2DC0FABDBB535FE88297B +:104FB0000FE05077A7399A06B2B76E53B582FCBAA4 +:104FC0006E53919DFC4A2BF79B7478A73AF77AB100 +:104FD000CE2DC786282EF16CF23D732F8FBB0E09A4 +:104FE000FCE9C2B385FA1DA572178ADF3133557308 +:104FF0002ABF782BE8FDB8BE153D7CBD7A1CA435D0 +:10500000AACDC2794E1D19DA84656D9B7B16F90D08 +:10501000579DD984723374FEECD1ABC80FA068A938 +:10502000EE0B586BCCB48E6751114178CD95296F3A +:10503000B76EAE4CE7ED6CB5911DEEB430337E9F8C +:10504000D5B990CBB1DAA69C5958674BB2480ED768 +:105050001ED3B26EF6C6ED7CE7DCB5B908A74F8A61 +:105060000FE9FE82EB14FF4D788E9F363EB4FAF8BE +:105070006B946776C3A0313EA4C77B468B0FE9F1E2 +:10508000D950D387867872481E9A837E95BA174E78 +:10509000517C38D427A92E773C6E143A704621F8FB +:1050A0008A7811F457F0BD3A38F6714EFCDE008F65 +:1050B0001F3D87F9B80A7E4F4FA5BCDB1F613E6ECE +:1050C000197E4F8FE7E31EC47C5C05EF7FF07CDC2C +:1050D0004322BF37D47F86E24D3D5E63BC428F479B +:1050E000DC2505B679730DF10AAA27C72BCC766E9D +:1050F00087868E59E8BBE8A1E356E2B3F5FD2B267F +:10510000A03EA67FAFBC1DE30509FEA5F7FD3E1B33 +:10511000DEEF793FE0B3619CA06EE01D4523BE1336 +:105120002DC014A67639A6A0BD8F70A03CBFFE7A14 +:105130001BC2F513FDFA7DFFE3D7FF347EFD8C38EB +:105140005D12FFA80D98E85E79ED31BFEDE604FE33 +:10515000B025C0FDC35B3CC5447F0F048AB356260F +:10516000FAF19BB8FDE69CEBB1253E5F54C3EF0F0F +:1051700038A5D4F70B5EF7EAFED711FCF6756F4A37 +:105180007D27753C604B13E723BABF7F647CC0F773 +:105190009227C1CFFFFECFACF47717069E4F23793D +:1051A000FED10B697B50EFAE6D5A392103EAB5276A +:1051B000D3989BCB23435C617993C96FCB4C154744 +:1051C000F017D0F74293E3054D26E2EFC3F18226B4 +:1051D000F914D5857E7EC3997FCFC04F643F2B45A0 +:1051E0007AD0BE7876B5E41B6023E3073070019B6C +:1051F0000EBB68E27682AFD94A76C127C5155A0E32 +:105200009CD8887E82496C7B0F7E7F7292C7A48275 +:10521000284A1157E0F99DB5428F48F60F207EA02D +:10522000DC4FF60B665673399459CDFD983B51AF60 +:10523000CF8D8FA3BF977CEE5F147269343FE3621A +:10524000D1DEDD54BB05CF2D3CDFC490FF77373571 +:10525000583D09E3B9AB79DECC0E8C53E424C62962 +:10526000783C22393EA1F3A7BA818FE7E0B93FD05D +:10527000CFFD472117F767D61DACA77B26F17572C6 +:10528000FC7CC0357CCF308BF17D312BF773915F87 +:10529000A176FE8787F0EF12B04016FD9D83D07196 +:1052A0004F9703F9C87C798AA4917F7BD8DF8DFE64 +:1052B000A8C5AFB4CDC37CE0BAA5934EE0B92C6DC0 +:1052C000B150DED1E2579AE9FBE3BABCAA5BBA7BE4 +:1052D00003FEDD9AA51592CFA6617B5303B65FFD51 +:1052E00054143D7B6C01AE0EE825761C7A17937F33 +:1052F000BBBE1AD65BB750F8BD5BB85C5DDABFD0F9 +:10530000C23F6E659473878B3E22BBF96C7F1DF99B +:10531000B3B331DEEA8DCB99BA1740FE64C4E5CF52 +:10532000DF2A77BE58CDEDC0CB40FEE07A9C0B79EA +:105330005C30F9FCDDE2FC479327A3F14F941FFC9E +:10534000EFF2840B24575CEE6A684F4F8BCB5FB54E +:105350000FEA6347C7BF87847E95358AFEF580C014 +:10536000F751F335FAFE3E7EEFEDD5FF3DE257BA39 +:105370007DA3FBBF757BE8F702CE7AF9AEC08BBF89 +:10538000395F198562CA7C6567EA7CE51B7A25FA74 +:105390000E8BC8573EA2B0FAFD3998A727EE2544D8 +:1053A00002A4DF1CD9F5EB4D4FE4E0BD044945B143 +:1053B000B3BAF704C9E7D5A0CF901ED4FF2EF74BA0 +:1053C000F5F2FCD2D57DC6FB0F7AE9ACE1F1F646E9 +:1053D000D80FF991451EDF9C039CAE437E25A2B9F0 +:1053E000D12FF41539D12F14D262B97A7E6084CBD3 +:1053F000A594797CED6C88F2FDDADB241FCA83CF9B +:10540000EC27F2F3FCBE4BF513FDBCDA987F7AAEC5 +:105410008ADFFB690E4A12EAA356536015E5F71EB0 +:1054200094D45479A2EF087973B5F0D3EE55381EB1 +:10543000ECBD5CA2BC5ABC1783E7BBF720CF9FDF53 +:105440005BCBF3E775BFAC9E175F19F7CBD27D1826 +:105450003D9F5ECF8FD7EF872EDC698FA27EB1CDC7 +:10546000D2EB423A1CFE4E0FEA22D06E17DF194FE4 +:105470005EE72FAAEB775553BF51F59B3F56A7D058 +:105480006FFCC24EFB73F5A87AF95FAB8D7A39D504 +:1054900093F5F2FF2ABFEC37C43E53F9D552EB67C0 +:1054A00023FABD7889FD7E980A1E5DB6D4DF0B6DA8 +:1054B000AD11FC37E9EF92B011F77BB87CEB91B4FA +:1054C0005F5D41712E0BC5B974FED293C1C7F78AD7 +:1054D000F1F4F2F3359CCF8CF65DC945A2DF5AC9D1 +:1054E0005F553305BF1F6FF49355F71AFD6497F5A9 +:1054F000390DF549D17C43FFBA63C586F629B189D8 +:1055000086F669276B0DF51983971BFA5FF1768391 +:10551000A1FEB921A39FECAA738B92EE1D71FCAE84 +:10552000078C487C6F96F58B867E056DC67D15755C +:1055300018F735619D715FFAB8EEB0717F253DC6F1 +:10554000FD39D17FEFFDECFEFB9857E3DFC1E92F7A +:10555000A1EFFEED68F2D077AEF5FB7FFF09FEEF1D +:10556000D922F072000000000000000000000000DE +:105570001F8B080000000000000B53E16760F8512A +:105580000FC15BF918182EF021F8F4C01CCC0C0CDC +:105590009C40ACC8C8C02001C4FC40CC06C49E0CD2 +:1055A0000C0CFF81F81B10BF05E22740EC0CC40770 +:1055B00058B09BE3C6CAC0E001C4DC40B378988908 +:1055C000B7DF8917C17ECCC3C0700E889FF1D0377A +:1055D0000C061B5E27403FBB7E43ED3A2932F0FEAE +:1055E00006612131609A1447F0A78AA3CA0B8B2168 +:1055F000D8C9D294D9950FD40F00F19321F080032C +:1056000000000000000000001F8B080000000000E8 +:10561000000BED7D0B7C94C5B5F87CBBDFBE92DD45 +:10562000CD26E44900370960501E4B80C84BDDF0A1 +:105630003252C40411828A2CAF10027914A9A5FF3A +:10564000DABB0B2804AADE5851A37F6A17041B2D6E +:10565000DA80D11B6DE02EA208D56A684551AB0DEA +:10566000888808498C8F6AB57ACF3933DF66E7CBF3 +:105670002E89B6FE6FFFBF7BC3AF1DE79B993367D3 +:10568000CE3973E6CC9999B3268383192E60EC1B2F +:10569000FCBB9C319B893136A62B6D573A86AB39C2 +:1056A0005DE5B7F9BDCC6B66ACCE6FA5748B3F9D45 +:1056B0007907C3779FA1306867EC5EBF8BF2BFF0BC +:1056C00017525AEB2FA27A77FA4B287FBBDF47E9B4 +:1056D000667F197DAFF157537E837F0DA59BD4451F +:1056E000692C05FA66458559C98C553D9393B719C0 +:1056F000725B668D4F504743FE15233366017C9FD6 +:105700004AFD31D5BD69E0E8AE7A1A9E9BD449FDC9 +:10571000104EED128E17B3325B8C7A5938CE3B9710 +:105720000878F6D69A9CE4A8F50623BCDB4B00DE8D +:1057300050287085AC39D1E15D8CF03697A8BC5EFD +:1057400072B0263B3A3C0FD6ABB941C04B0F586301 +:10575000D41B83F536DC20F0EBE7ABC98ADEEF78AB +:10576000ACC75CEADF5AAD8CFEBEC9C6FFB7BB4E04 +:105770005D2CF246CC263136AEAB9D3E652CC0701A +:105780009C2AF315121FDC995F7F93CFD84D081325 +:10579000DA0726B19011FA0F24B1E0FA2CA9FE4CD9 +:1057A000AADFDAF7EB6F52A5FA014394FA26D6A0E6 +:1057B00060F9CF518E80EFF7F97329DD28E4E7BE59 +:1057C000A106C6B05DBA393808DADDE3F790BCDC73 +:1057D000ED1F4BE5770939FC7721674121670FA25F +:1057E0009C41BA15E5CC8CFDF95A4B014EFBDE7895 +:1057F000B6D94DF2B598F05419C1DFB077C8F6CDDF +:1058000000FFBE1B569DDE06F46F6B1EE63142BDE7 +:105810007B866AF2C5BC2CB9ABDE3DB34F38170DA1 +:10582000257A97219CBB3D827F2A0C2CA2DEDD339A +:10583000C2F52AB0DE5D9E30BC5064BF774D09D7FB +:105840005B457C56584983BD3B5F763085E623082F +:105850000AD1D784F48579F9EC80EB9456689F924D +:105860009C97C6A0DDFD381FCD38EFDC4417AD3D59 +:10587000D2D907DF332CAC1AE10365F71B015FD3E4 +:105880006C7722D2E5F66B8B98328CB1BEA23C3598 +:1058900050A464015CFB9C2205BF9B6643397C7766 +:1058A00089F2E435BCFC762C7774952762397C4FFD +:1058B000AA8672C8DBE7F2F23BFCC089C15DF5360F +:1058C000019F7DC4EF74FE1DD88AF4318DE6A98650 +:1058D000F713282440BF83988EE9C27FD3A07B337F +:1058E00016DABBF0B50DAEA7BC86DFA6C17194D7A2 +:1058F000F0B15DD82F6321A47D97F465DE5C311F84 +:1059000058773A277AB3A5F24CD593A0029D325F1F +:1059100032B200B02013C413E1E9DB153103E1D941 +:10592000E3FC4BEEDDFC330D95E9A0A547053D34C6 +:105930003A6CEC2FD3C13240A6C3C601321D2C17DE +:105940009C9F0E3B989BE81C8B1E5ABF9B87C8FDF3 +:10595000C65D24F7BBF922B9DFB88BFF39FDD664E9 +:10596000C9FD5AB3E57E6BB2E57EAD39FF58BF4C39 +:10597000F5C064407DA5FD5D28E9B7AB99EF2CB675 +:10598000473D87F349D373A6641FF3D9BBF809EBEE +:105990001463F99170064B7A15E07C8AF5008EF756 +:1059A000FC705C3A3883F470BE16F8B0483DDD0DEB +:1059B0000E1BA81F8749E1ED428688FE99EA6345E0 +:1059C0008EC8761E5DFF39FAFE9D8A1887E1BCFD00 +:1059D000BB7574CDD6E39326F06186F3D183B97499 +:1059E00070B2F470DC029F90725E386EFD382E1437 +:1059F000FD071469FD027A0CEB6AD70EF8D13A95CF +:105A00006709EE04FD10DAF7E5295C07CE355EEB99 +:105A1000B640FDFD232DA1CBA1FC5CB0206881F236 +:105A2000C94F1E75A21D53F1A451C572C33E1BADD3 +:105A30002F6D3B142AAFB2B4DC3901CA3B9E34B29D +:105A4000EDD45DA601C7774AE81416E2F9521BCFE0 +:105A5000566CDB7F23B62F6BB2301BC0AB787AD984 +:105A6000CC09905F76C8C4B04AC5CEB5E6BE905F9B +:105A70001E541A300FF8D23A15C8B3057742FD7597 +:105A8000FBBE6C43FCCF359A06213E67609D70C318 +:105A90003AF192A3257536D0A73CB87B1AB62FDF12 +:105AA000A57840C301FE3B0F6620FE8F281E0BB079 +:105AB00070457D3C7347CC97538D461AEFAA6D4ACB +:105AC0009001BC65AC761AD2B302898378782C41F8 +:105AD0009BD235DFCEF8EBA83F2D5FF108F407ED40 +:105AE0002B1F573C38E44A03F3E13C6E7BDA56F255 +:105AF000901DC7BBD63CD881E3DC68C67ACB820B4D +:105B00009FB2B911CF6DE66988EFD66DE6D2A14894 +:105B100047B6A06828E2F77F65FCEA8C5E1CEFAA16 +:105B20009196ED46C083D943036739BAEBD933B0B8 +:105B30005EB923D6CF72067A9FD6EFA0B97858D730 +:105B4000F72F0D89A43F56D41B99DBDAD58F261F7A +:105B50008123423EF63A88DE1A3F57B9F814D0F84E +:105B6000B92A51F057EDC89F35AC3B3E77225FC84C +:105B70009E7651FA0B583731DD02EB3CD2EF5EB026 +:105B80009FDC64977BE8FB03602761BA15EC244C2B +:105B90001F043BC92DEC24ACB71DEC244C77809D31 +:105BA00084DF1F067B1CD37AB0C7F1FBA3608F6331 +:105BB000BACB1FA0EF8FFB6B286DF0D752BA07F955 +:105BC0000669A33F48F59EF2D753DAE46FA0EFCF02 +:105BD000F89B28BD5DD0D1399115E03AEAF432172F +:105BE000923D6986B7C004F9A4229E4FBD21506042 +:105BF000867CAA0FF24097BE2B430516C8F7ADE688 +:105C0000E5036E6193AC901F10E0E5D9B77B27D90F +:105C1000209F5DCBCB076F0D4C8A83FCE0202FBF0C +:105C2000685768523CE42F6AE0E5C39BD9643BE4C3 +:105C30008787783EEF25EF6407E4F35A783EFFCF7D +:105C400081C94EC8E7B7F2F6E3CF068DEE28EBEF39 +:105C50001E937B31AA9C03CADB5E3503F266F74DC7 +:105C6000A8128F2AA728DF68F252F9FB4ABB578592 +:105C700075BED1ECA5F22F94CF29FF94C947E5F169 +:105C800006A580F2661F95F737C451BEC914A0F26D +:105C900011863E3C6F0E507981A15F01C27FC61410 +:105CA000A4F26B0C8378DE1CA4F25FA8C30BA640A1 +:105CB000FDC70DBEBDA8EFD62BBE32B40F99DA904A +:105CC0008EFA4AB32B77E2E0D0CECC30D33CD8F377 +:105CD00087FC87681EE05F32E64B1F46BB14E01C62 +:105CE0002438268063EC194EDECB632538792F9754 +:105CF00069705E2138B6DEC1D9F3F278199F97CB6F +:105D00003538C7088EA377E3CA7B65A28CCF2B2BCF +:105D10003538C7094E62EFF0693C2AD3A7F168987D +:105D20003E67707D589FD23B7C46BF26D367F46B9D +:105D300061FA7C4CF864F40E4EE36B327D1A5F0B13 +:105D4000D3E72B82D3BF77E31AFDBA4C9FD1AF873D +:105D5000E96332209CACDEC179EA6D993E4FBD1DEE +:105D6000A68FD380F419D4BB71E5BF23D327FF9D41 +:105D7000307DD2089F21BD83F3D43B327D9E7A27AC +:105D80004C1F37E133AC77E3CAFF8B4C9FFCBF84D9 +:105D9000E93384E08CEC1D3E4DEFC9F4697A2F4C59 +:105DA0009F3C8233A677F88C3D25D367ECA9307DE4 +:105DB00026109C71BD83D3744AA64FD3A9307DA60B +:105DC000109D2FEDDDB8C6BE2FD367ECFB61FA5CEA +:105DD00045700A7CF5840F03388ED8709E3927D31E +:105DE000E7997361FACC213853014E4ECF70C6B794 +:105DF000C9F419DF16A6CF02827365EFE03CD32603 +:105E0000D3E799B6307DCA88CE57F56E5CE3DB6583 +:105E1000FA8C6FE7F4A9B278263BD0BE4B649EEDB6 +:105E2000D0E492930D079C9037D99907C1BEA48402 +:105E300076207C582BC92E543D9A9DE2616887CE0E +:105E400070BA3DE8F7316AF6086BA1FD827D57A272 +:105E5000E40FFAD230E916C4D701565BA45D923044 +:105E6000364EB28712BD4952BE4F615FA97E4A517C +:105E7000B6549E567291549EE1CB93F29965E3A578 +:105E8000FAFDAB2749F90BD64C97EA67056649F945 +:105E90009C9AEBA4FA836A1749E517D6954BE5431C +:105EA00082ABA4FCC5F5FF47AA3FAC619D543EA25E +:105EB00069B3543E32F40B293FEAD00352FD312D31 +:105EC000DBA5F24B8E3D2A958F6BDD23E5279C7E6B +:105ED000466707CAFBFFF5058CDB831966B20743EB +:105EE0000E33E5CDFB6C64FFEFC73CF0D3DC7706E7 +:105EF000E5CDCF2E7627E37E1A01C07A5FD0B7ECCE +:105F000042F4F7DC3CDE77A10BBEDF6CF68D70450A +:105F1000F1477854DF3E03F98B5A14968EA9DB8043 +:105F2000699C51ECD72D5CBE3666E53F148890D352 +:105F30009AFE30FF207FD86026FB5593EF8DFD4BF6 +:105F4000D31746F4B3A1BFB964FB50FE7DB11DFB6E +:105F50002B7A11E75995B96330E2A5EFC7923D5608 +:105F6000EAC73AA08CFA790DFB89F07B590694E9CF +:105F7000FAB1966C17DF453FC7705CB1FAD9983D0E +:105F80005E1ECF8072EAE75D5D3F1B0794EBFA89E6 +:105F9000E3E381EFA29FF7CE3B9E9C89F2782E58D7 +:105FA00049FD74E8E866B960A5AE1F3BF583DF17CD +:105FB000933F17760169C0674B4729C9C17FDA58FB +:105FC00000E4C29C59FE6BCCB3B76C6C10F6E38650 +:105FD0007EA11ECBE5FEA3A70D49349ECFE280FF34 +:105FE00011766AD77E3640FBE2A5024516048C6026 +:105FF0007F5B296473C9AEE20137B9216D3A30F095 +:106000006EEC678BC33308F26D4D93CD8BA3C8D371 +:10601000D25AD3A9D648BF88B6BF99C472ABA1FFE4 +:106020005D369794D7D2958A8B097F04E54FC0BE21 +:1060300085C17EE0CFB02F6040AA774D7C9FF60EE1 +:10604000EC6F30DF0AFB1B2C676C2DB53B21FCB4D9 +:10605000276E578248EFCF7EF24313E9F1007B357C +:106060003D15FD6EFC6FC19A78F4F187F15B18E87D +:1060700023E5415D661AD2695F48FBDF8EA72DC11B +:10608000ED48D79A4CA0A9A897CDD8EBB0C9CD4878 +:10609000A26CA6612C63B3AB8BA7A6D12C52FAAF2E +:1060A000023C67358E34410BD6666ABDD163EF8200 +:1060B000CBBCA613481F2BFC4338D714423EA2FF8B +:1060C0006B8BE4FC5CA676E581DF838DD9826FA2C1 +:1060D0005FB7D7847C2D4AE5F8CCC5340F8BB9BFA8 +:1060E000A3C4C5DB6AF8542D36B110ED4F03290C5B +:1060F000FDD18164AA779DB6CFD4E15762B27A8B85 +:1061000080AE250B8D44573DBE6FEE8BF71A86434C +:106110005A73B7095D9B3DE13FCF2797B332DE9FAE +:1061200046574D5E4E09FE9E40FE43FA3EF21FF07A +:106130003E29F8DF25C79CFF5516DF4CE47FC7FDDD +:106140004646FC127C9F23F8BEB456E6FB1CF49333 +:1061500043FD39ABB382EBB17E5D1F89BF307099CF +:106160000EB5774D05B5DA0DFFB7851C5C57B3FB4F +:106170007964EFF565BAF1093EDC28F8305F478FA6 +:1061800039826FF305DF96B1C06D19E43F0A9AD0EA +:106190002F36AF4C61A82FAA7EAAF1AD55E29B4FD6 +:1061A000E39B0EDF1B05DF6EFC09E79B1EEF56C16C +:1061B000B7D6BA8F4D2CBB3BDE7A3C17ACD18D2BBA +:1061C000A0E75BAD38777099D1DE29F616F439195E +:1061D00051FF9AC22BFB9C8CD00BD716154BF9B9EB +:1061E00025F3A4FAF37C0BA5F2EBCB964BE5F3ABCE +:1061F0007F28E517ACF989547F6160AD54BEB8665D +:106200009354BEB4F62E29BFACEE7EA9FEF2E03662 +:10621000A97C45FD23527945C36E295FD5F4B4545A +:10622000DFB06FC8D5285F2F1D3532F4977DEA792E +:106230009FFC759F7A4C1EAC538932370EE5D94DC1 +:10624000F27CCA9F4BE969BF87E4FD8C7F2CA56D6A +:106250004D07ECE87FAC8A03BD9F0876B8F1CDB559 +:1062600035FD70BD81F6E3196B36B6AE0D40FE000C +:106270001E46C1BC99516766A1510CA4BB6F589EC4 +:106280003B8C11E5AD3D94D7A92CD4A77BF98CD6D6 +:10629000E8DFDB958EC119E8277CC3C27646F8EBB0 +:1062A000BA9F57B04CB42B62959F35B0B2C8F3ACCF +:1062B00093467E4EE2344E3A698474A599CFFF9599 +:1062C0007B32263127E64383ABA3F85DC2FD350060 +:1062D0003269C8E71C69DE2FABBBB86B9E33EC2775 +:1062E0009BE476797094F47D45FD04A95DAEE27B74 +:1062F000D708F5CEEE37D27ACD4207065C330CF1E3 +:10630000F39EC4EFAC2985ECAE16BFB7CFC9818C24 +:10631000FDD15F48E9ABFE224A5FF397507ACCEF9C +:10632000A3F44D7F19A57FF65753FA8E7F0DA5ADC7 +:10633000FE00A527FC35949EF4D7527ACA5F47E940 +:10634000697F90D233FE7A4ACFFA1B286DF337511A +:10635000AAE9CF9EE4EFB4585FCFA0FC459133F398 +:10636000AD6C5DCDC42E398B532DEB50CE34FACEAF +:10637000A8B308794895E42111D76192B31ECAEBFE +:106380004C420E63B58F5E8EF2D6F77B9037C6D641 +:10639000911CCC1472F75DE58DA1373E05E52953BC +:1063A000274FB21C6A72A4E9815CA568B83AA64B73 +:1063B000AE661AB99DA4C9D5CFD14E8C626FDDA04F +:1063C0002A62FDE3F611F36518D07E5B25FCFECC56 +:1063D0009D4EF94ED1F77A00D782F5D4602EAE23C8 +:1063E0009DB97F1B8CFEF1CE6316867EF858E3D3F1 +:1063F000CB4B6CBA7B69FF501A84456D54F7725BC6 +:106400001CA7ABCDC00A591E9ECFE61FF3013FE388 +:10641000FEF3E23CDCD7C27795915D15F41447F1A9 +:10642000B73394F1B49EE9ABD53FF5C097F9786ED8 +:106430003E53CCF3B803467EAE1D7AC8734DC4F903 +:106440000CECB7D3D1EFDC31C8EC22FB21D457A63A +:1064500063B0AF44C703833E1B8CE71B9B400E71A8 +:106460007E750E1C9CC0CE231F3DE9F99EE8B9281D +:10647000D8B797F434333C37027A6EC7FB2FBDA5EB +:10648000674F7AB227FD786233A7B353D8A7B1E834 +:10649000DC3E09E65D1439BE475565396603F97976 +:1064A00087467FDC9746D0FF52BB9BEA3FB7EFADF4 +:1064B00001ADD04F67E385098C9FE7905DD7F1A4CC +:1064C000B0DBDD99321F5BFB125C0DCE734FBE3E1D +:1064D00000F7C9B76106E6D993F145BF5253BAE058 +:1064E000F5F61C3ED6B8767FCBF9D99EAACDCF96CD +:1064F00001284F9F093D10737C3DC9298E0FE05C38 +:10650000A5F0F16D3016FD0EF54C787CA3537A356D +:10651000BEAA04335346007E0EB3992530B643F528 +:106520001D54691FE7690DA09F625FBC673DB0A461 +:10653000CA79E6E5901BDBC9FE8C15F536976C3FF2 +:1065400025BA64FB29C315693F751E7AC8E903FCA7 +:1065500056A51B5C2747E13AE715EB1C5F5735FC56 +:106560002A1AB25C76098E9CEFAC550A1B489EDC59 +:1065700009B3A39C9769E9AA74B3EB24AC5767EA03 +:106580007312B0DF337EAB8BAFAF2E17EF37DD1555 +:10659000B9BEAE5C1347F535FC62C1FD67E3C75871 +:1065A000237BD78AEB2294E5C4AE1F939FEA27662C +:1065B0003A976E367D86F6BB2D57B3DF55CA6B70A2 +:1065C000AB1A8C01CB08FCBE4BEA0FDAB9B53366C7 +:1065D0006C175B6E54764AE327F0DF8A07EFB46FDF +:1065E000B5129F7D003101E0B5ABF61A94AB132ACA +:1065F0009FCF55424E2BACAD669F9BC8DD82F2BC4F +:10660000682CD326CCDCB7404F7FF0A289EE69B16D +:10661000AF007A7ED7558125ACC8894ECF458D2BEA +:1066200066E0BAFD8141DB0FD7E6E3B8CF31432105 +:10663000EAA573EC8FCE5111F3758889FB63580D71 +:10664000DFE704E01F8E6F69ADBCEF595627E74BBB +:10665000D9AC54D4B7A55B4C2C08B82FC77D933662 +:106660006ED0BF1926EED758C6AA37E03EFD5E139E +:10667000F7F72C72313513F0AAF88F5FE6A3DFC766 +:1066800063E27687769EBC3C89E35D3E3B68F642DA +:10669000FD771B47CD018D0BED831BC8FE29669E40 +:1066A0009DAC3BDD17D7C8F8F584BF1E5FCD0EEA61 +:1066B00076AE2DF048AE57BCC1287AEE329322F662 +:1066C0007F7C7ECC36C9FE9C7926D9EFA3C981494F +:1066D000C8C109D577B5690CE73BF251513BCCBE37 +:1066E000887AE6AE7AB3CF57CF82F58C546F9E2965 +:1066F00005EB754CA3FD3103791ADA55CFD605EFBA +:10670000460E4FAE57F11F8F3D15007929FFED3D25 +:106710004E06EBE6076A6DAA07BEAFDC799BD30B8A +:10672000E96935E0447E7E10341646A3C796303DB5 +:10673000BC7605FD69423E594D80FC149FED34B98D +:10674000C8CF5F6F0959404E2B1B97CF60C3297F7D +:106750009CE7377E64C47C93CCAFF25FDF93EAE6BC +:10676000F76CB83F8985C8CEADDCF1DE345C2FAA6A +:106770005807C999BE1DF6FF7912CDEB85E684EE68 +:10678000E58027F913AAC42CAB6AFCF9474627E633 +:1067900065F92813F62AD209F7F9B7991CC9A7E2B7 +:1067A000217B09BB04E7B9460F16E476EBFA47EE06 +:1067B0001B7E1CF039BBE345A73234523F7039EBE6 +:1067C0006C58FC2BAB21B61E6903398CB48F00309A +:1067D000B57337097BBB99A72B4D2127DE6759B9C4 +:1067E000CDE40109642B1F3332BC07C0DEB004D1F5 +:1067F0002FBAE2B1E75F1B0F745FB1DB943C830FEC +:10680000C7AEA476F1A50AFEB726AF8B0FE54F3CC5 +:106810006F760FE3DF6F49EAE2C78ADDFBCD6C5884 +:1068200077FA4D6ED86F6EB547E14BC3F169B8CEBC +:10683000AE7FE4AF66F4277EB04F616959DDDB9728 +:106840006D7B9ED63BA413F151F029CCB76EFC0AA8 +:10685000CD7C6634D573A11E8CC5AF6542EF823CFA +:106860003FFE0CDEFF79D3E2C1F1973D7E9313C763 +:10687000F1BE5ACDE5FA97B7A5E2FC2E3305525D7D +:1068800094F2EF650FFE88E46DD9911FA592BDC00B +:10689000BC1906D2C5810C1CDFD2ADD7D2F84A99FB +:1068A0008FE4AEEC97C622BC8FF8A9CA0A77479945 +:1068B00017716685F0797F3B183230BEF7717F899A +:1068C000FAEC8F46BA17C5D80FE9DED88FC45861E5 +:1068D000E5A3FCA756CEA7E3424FE24496E475C772 +:1068E000C616E4CF99FEDE343CE7003A0404BD94BA +:1068F0006F00AEF1C8D434CE1FE656F3453BD0EF5F +:1069000093F13BD66F31796DC3A576421FF2FE57E6 +:106910008BFE01EF385CAFDE4F8D6EEF8D11E383A0 +:10692000BF1616215F11F39BCFF71D9BF8FCD6E62F +:106930007BB0B810CB3F7995CF1F6C87EB03E01588 +:106940004AA3F2FDB315D207B0AF8E36AF7798C425 +:10695000BC96CBC152A4F51EF0569584483901F877 +:1069600049447FDA07976E817611F65715F647F599 +:10697000CC5DDF23D68765420F98CC30FF2FEE9A8F +:10698000FF6C2B9FF73DD9932B4DC1871FC0F9FAA0 +:1069900086C51370E37C3515E1B83FDC75E0B5EBD7 +:1069A00040AE3F6CD0E6A9AC3FF5F3B46CCF1816FF +:1069B0006D9E7E6887FD55B4790ADFA3CE537B2B8D +:1069C000C9F1F7AD3F35BA0D35CB7A13F5E033EEAB +:1069D000D8F4D3EBC1DF9BDC4447BD1E84BF5759BD +:1069E0007E77B9D3E44D93B3F2DF545C80FA262C62 +:1069F0008F9ABC85E5519337FD3865BAE9CBFF2AFC +:106A0000F4CDF5D6C26BD02EB67630DAAF14CC36D4 +:106A100006719F6CFD84D17C9F74433CE5E71A5B53 +:106A20009F409BEFAD8AB9C3701DBF9E054CFCDC37 +:106A3000BCD64476EA57DF7C3311C6739DA0EBF5D4 +:106A400040E6AB800F25AA128A033CE7A92C909060 +:106A500084FE62859D88C0E3FA32398F7F97A576E0 +:106A6000C1E9A9FEB7B5ABBF6B7AC4CFCFAEFE8488 +:106A700029ED2FC0708E90A3E2667E4E51355A09E3 +:106A800066D3FC6B558B22F6098F99B99D7164CA48 +:106A90003563907E05738725907CD70EA17D609528 +:106AA000D05B9D017702EAF3CEE61CDAF7751E5A39 +:106AB000ECF045D15F07849C3D2FCE59DAED4AAD0D +:106AC00011E4BD9D7590DD12B0DBA2FADDEACC06C3 +:106AD00061EF08BEC19F11FA2F1172380F9A26E498 +:106AE00045F06DF6551FA8CEEE7CC0BF1311FB8696 +:106AF0007F94BE28D748DF03B6D6694551FC338F53 +:106B00000A7D7DD9B35F98719D9BD25CA0221DA7A1 +:106B1000D88D92BF63BB365F87B2A188D765CF2E71 +:106B2000BF630CC871D521A3C706E3AB6AFEC8ECEE +:106B30008BB27FD3D313E1A3FDD86AE6F6F15153AC +:106B4000D152A4EBD16BF979EE9FCC9E8A6878CEB6 +:106B5000B6723CE7B1A24F472BFF7AF42D98EB08B1 +:106B60004D027A74DAF9FDE4EEF2C7E77DA74B092E +:106B7000AE55500E8D3C9FCCEFFF4E63BE3B262A98 +:106B800034DF2F8FD45F054DC58FE17D96CA66C572 +:106B90006580F24AB5D58C725CD5B45B45BBFC0709 +:106BA0006EFECE82A9D5C36647F8B75ACDDC9F7476 +:106BB000E06FD7CD47FA7E3CDBC2102FEFD08F9C21 +:106BC000B8DE7FDC3C8AE641AC71FDC1EFB9660AF4 +:106BD000FAE3CD5C9FE9E5615A72BC94BF7632EB73 +:106BE00087E7BC97595A6FF244E1DF3A0B9FA7BD84 +:106BF000D66FD6FF61FA6D22E8372ED7A648FD364C +:106C0000DDC2E53E42BFA545D36FABD6BAD3502E09 +:106C100056EDCD4943BEAE3ABC34259A7E7B41EC5D +:106C20006B0F8B7BD2EDFD40BF8D88D06FFD40BFD9 +:106C300045F1838FB66876670FFACDFADF33FF5ED2 +:106C400040FD1665BC5708B9D3F45B61F35AD26FA7 +:106C500085FD8CD27DA4CB2CC28E8BA9DF16DE7372 +:106C60002DE54D9EF828F2837445FD7658E839EC01 +:106C700007F5DCCF2CDF4ECFCDB3727C7BD473FF16 +:106C80004D74D6F4DCAAFE0AD92FDDE590EBB95598 +:106C9000595CCFADDACBF5DCAA415CCFE9F5DBA4DA +:106CA0006EFA8DB7AFCC85F6B44FCCBAEF06BCCF39 +:106CB0005762F258A1FE0CB7F6BEA07A4CA4BEFBF8 +:106CC000992586BEF380BEB3F7ACEF5E417DA792F7 +:106CD0001E1B88F3482F1FD307C64BF7D58E7E7136 +:106CE000EA37BFC5F9F20723DD077ADDC0F743FBBA +:106CF000BE38350AE7DDCB880FCC979D42FEDAFC23 +:106D000063499F4E1ECAE77BC5A1385A272A1B1527 +:106D10003EDE5B94A01BD781BF7D4EFBE4F97BF97F +:106D20003E79AE85D383FDD8C8DF4500091646C835 +:106D300043C9E7E5E4E72B519915EDD70587A67F11 +:106D40008076EB82CF6BC8DE5D80DFF17EC5EED64C +:106D50000D99D0EFFCE50AED3798B80FA1DD97B893 +:106D6000BE793FDD5FD1DF83D0F4F9FC6AF9FB0225 +:106D70009D5D7F408C13EC59A20B7BC518D53F77E6 +:106D8000404F0F0F1F7FC56A6E1F87E901F4712BFB +:106D9000DDE9011C9DB130B56BFCF39F8471257753 +:106DA0008D4BA3877E7CDAFE6481981BB1C6ABD184 +:106DB000AFDB78357AEAC6FDBC45D84517B36138F4 +:106DC000CF5E37F8EE188372F17B183FE03367DE51 +:106DD000A0B4483DFCA2D0E757F98E4F497523BDBA +:106DE000F8FBBBEBCA763F9F0AE3B8DA9B9587575F +:106DF00011AEFD9BD9877E8403B60ED26B9A5C5D83 +:106E000068E572FE7701E7685FD7145A3F9A141756 +:106E1000CD97904E6F897B6155404F9C8F554D6249 +:106E2000BD0179C3F9364D5B7F90FEF09F573573F6 +:106E3000FA57552B44FF99ACE320D2B73259F1846D +:106E400000D4B4A6DDB7E13DAA176CF01DE76D993B +:106E5000E2D9CEC961CF488D2A976A34B964D54347 +:106E6000C8AFA0AD830BB05E12BE17793D05ED1320 +:106E7000BDBD7199A5E528E271D98F4D6C1BEB6EF4 +:106E80007F68FCCE857FDF44BBCFD383FC0E12F638 +:106E9000E50B486F3BD2B5C38C725F15E2EB8656AB +:106EA0005EA5BAA7107D347A37C1BA309AD31BDFFA +:106EB0007DE9E979B5964779C6FACD8A09DB5F099C +:106EC0007CE80345930D5F1CD4E417DF89E9E98270 +:106ED000FBFF8C88F98E7A29F2DCB1B2E908D16522 +:106EE000FA6A30AB22E88EFAEA7CF4E9361F9AF6A9 +:106EF00047BD07F56DE7C38556793EECB375BC38E1 +:106F000002FD5B7B15D207AC3951DADF5F61E5FB2F +:106F1000A603361FC96DC76113DDF7D6EB8DB182AD +:106F2000FEB89F887C0737190782E7BB2E1B7B576B +:106F3000C3239BCB4FA4BE7EC1E6233EC5823F4DFB +:106F4000C08F652F85F1C5FEF03CC52DF7A75F2FDB +:106F5000343F4F4FE3BA46ACF7DF755CE1F349D6F7 +:106F60006266DC9FBFDB1C71CE3447F8F9353F58B1 +:106F700044BD999631B1EBA1BF2504E37E61D743AF +:106F8000E4D73DF7E8F19928B72B7E676456E073A4 +:106F9000DB2E070BF17B14665C57CB1B8D51CF4565 +:106FA000185B4FF8ADF8AD83F44AF91E4B7006B488 +:106FB0002F7FEADDE1E89F6A5BC7F54BE051211FB7 +:106FC00081D6E1785E5EAEF2F3623DBC1F0B79398B +:106FD000FB747C09EA47A59EBFEB2C6F986BB2440B +:106FE000ECCB2BF1C08DD7A37BC8814714F28377FC +:106FF000C76F2DAFF708D77BE54DA620BE0F2DAF8D +:10700000DF46FBD9AAFA8FCC68C74DFEED63644713 +:10701000543519653F61BD3164213FA6F138A67A28 +:107020007F5D656305CDC7CA06E10FD3F98B56FCBA +:1070300076EF530120CD8A277EED443D73A665A7E8 +:1070400093FC70F5DCCFA6DAD5E87EB89EFC6F0D18 +:107050009BA2FADFCEE07FC0FCDB6A95FD6FACBE81 +:107060004FAFCEC1573CF6E983782E7476CF870FA9 +:1070700022DE2BBFFEF8C19FA27DB2CFE6C2F5AEE5 +:10708000EAD1A3E457D7DA3D25E655DB23BF7EF8E6 +:1070900001987F6D6F58E8FE55DBDEF707B8619CFD +:1070A0006DBBBF4845FFE5EABD5369DFB2FAC9C908 +:1070B00069E7BB47827219ECC579889E0F071A8D64 +:1070C0000CDF419E3B66213B23EC476DA8E07E69C7 +:1070D000B7F09FEE8A7EEEA4F9FD2A1BAFB9FA52F3 +:1070E0005CF71A4D1E377D177EC09EFCA6AF023F8F +:1070F00047F4826FBB845F5CC7B773F81FC09F3FC4 +:1071000059657FF3A78D4B7FF5009635F689E937F2 +:107110000DF5825EDAB9D636ABF71D2BCE873DBFB3 +:1071200021FF34F20B6C6ED6F6D8A703D0DF70DAED +:10713000D47123DDBFD86BA17B42E57B5FA7F9D17A +:10714000F6E4113A2F62E25CA98D85FFF83980D808 +:10715000CB54ED70707FABA03BFA63DD4EFA2EFC92 +:10716000AE5C6E357F6C2C3F6C1F9BB8072ECED962 +:107170002A76BC65663ABFB63216F9745C3A17D403 +:10718000C6AD87E7423A5C12799E10CBCF2DF468EA +:10719000984FFC1CA16D9B385F089F1B30D62F0FAA +:1071A000EFBFF3F3EEAAA0F23A8B321FB5F304A7B8 +:1071B0004D371F83BD3B47E819DFEF460FC5C6F7C4 +:1071C000AD1A5DCE7E155D1F0FB129E2FD812FD76F +:1071D00016B1EE2C10EB4925D08BBF27E3F89E1596 +:1071E000FBBBB38F1A83B80FDED07080F4AA7E5E2B +:1071F00057B2E8F143C6DBB83EA96CDA3F1CF5CFC5 +:10720000D9679F26B9ABDC75DC1C003807EB9F30D3 +:10721000B70EED9273D4D7C1087D7DF6F1FDC3F9A9 +:107220003907DF47EAE15F21E05735CBF0AB767DE8 +:1072300024C15F116830BBEC3DF77346F5CEC5F154 +:107240009E6931515C94330DC6C268F14A86622052 +:10725000A9942E3A6D70F0F771C62433D991AB1D05 +:10726000638F2524636A76E33E7AFD5A7E1F72FDA2 +:10727000CF3CE9C897F58973E81CA856474757B231 +:10728000AB00F7D7AE2945A351ACF47A20D16B906F +:10729000F05EED284CC3F7DCB70A7B84A91E7ABFE9 +:1072A00067744E2BC471185D06972DEA3ACAE199AE +:1072B000EC45142FC2E492DFD37DEFF11FDCFDE437 +:1072C000F80F817EFF68FC07467130FEDFC77F083C +:1072D000603FFF02F11F42E4B7D1E23F247FCFF1CC +:1072E0001FD63239FE83E06738FE83E0E7FFC67FB2 +:1072F000F8FF2BFE8331EEEF53303E8316FF21253E +:10730000CE3C3532FEC38571095323E33F8C8B4B52 +:107310009F1A19FFE10771595323E33FCC8FBB68D4 +:107320006A64FC87AAB8515323E33FAC8D9B48792C +:107330002DFEC3DD7153A7CAF11F664E9D02F9B63B +:1073400038DFDF71BD8A15FFE13D9C2C637A8EFF2B +:107350000070CC716362C77FD0C38915FF01E02440 +:10736000109C18F11FBAE11323FE03C049273831DE +:10737000E23F74C32746FC078093457062C47FD008 +:10738000C38915FF01E05C1497123BFE831E4EACCF +:10739000F80F006714E11323FE43377C62C47F00BB +:1073A0003813094E8CF80FDDF08911FF01E04CA570 +:1073B00071C588FFA087132BFE03C09949F8C488C4 +:1073C000FFA087132BFE03C0994BF8C488FFD00D94 +:1073D0009F18F11F008E8FF08911FFA11B3E31E233 +:1073E0003F009CE5042746FC073D9C58F11F00CE5A +:1073F0002A821323FE831E4EACF80F00E7A7042752 +:1074000046FC876EF8C488FF00706E253831E23F75 +:1074100074C32746FC07807307C18911FF410F27FA +:1074200056FC0780732FC18911FF410F2756FC07B7 +:1074300080F32B821323FE43377C62C47F0038F530 +:10744000248731E23F74C3E7BBC67FB085062A3983 +:1074500014FF81E24486E33F247FEBF80FCD88EFF1 +:10746000FFC67FF89F19FFE166BBEFEB38F2837E22 +:10747000B7F80FB6F86F17FFE1667B517C3CEE2F33 +:10748000BF65FC87D4F86F17FF01FA498F1F13BB44 +:107490009F58F11F7274FDF414FF01FA1974DEF1A4 +:1074A000C488FFE0D1D1EDFB8AFFF045DCF9E33F72 +:1074B000FCCBC559806D0A9EFF149328B27F99B802 +:1074C0000BD7C6FF93E32E90B1F0AF1477417BBF8B +:1074D000DF60C2F5EA4DC1F7D7845CBC25E22F1C02 +:1074E0008B197F217815F94597CBF117A60B3ECE66 +:1074F000F3C9F2309DF1F386E953B278BCCC325D2A +:10750000FC855CF9FC7A86EFC81400C7AEF2C8E3CC +:107510003822E46166C947CF217BAE1E1B3DFEC207 +:107520002CC18F621D5DA60BBE158BF47A7C920276 +:10753000F23CA3EC888A749DE96E55C9AFFD038DBA +:107540007F6E897FB3055C3DBEB304FF665DC9F9FC +:10755000A7C7FB55E49F13D2B251C43F3DDE7A3C2E +:10756000F5FC6791FC8E889B51C0E4B80B93AD721B +:10757000DC85A92E39EEC215E972DC852BDD72DCC3 +:10758000851FE4CA7117AEF2C87117AE1E2BC75D16 +:1075900028F6AED5C57DD8A48BFB70972EEEC3FD23 +:1075A000BAB80FDB74711F1ED1C57DD8AD8BFBF04F +:1075B000B42EEEC37E29BFB8E6B0547F69ED112921 +:1075C000BFACEE0DA9FEF2E071A97C45FD07527932 +:1075D00045C34752BEAAE90BA97E6FE33EBC2ADE33 +:1075E00003BF26DE031F13EF81DF8C11F7E1AF3FEE +:1075F000FFE2B6C8F7F85FFEFC9BDBF03DBE41BC86 +:10760000838D15F7215C1E23EE4357FB6F1FF72177 +:1076100025F99FFF0E3FC7CECF3727C44FCAB1A76A +:107620007CF777F8D716C9EF99E796C8EF9973EC0E +:107630005C9FCFF3C9EF9AAF2F93DF3597D97CD9F1 +:1076400088873EEEC384786F8E1DF5A5789F1FC294 +:10765000F7A9B0363E8BEF53217D0EE33E407A1002 +:10766000E33E407A08E33E40FA7B8CFB00E94B188E +:10767000F701D29731EE838A712302226E448D88FE +:107680001B512BE246D489B811411137A25EC48D3B +:10769000681071239A44DC8810C139E13F44E949FC +:1076A0007F0BA5A7FCC7283DED6FA5F48CFF34A583 +:1076B00067FD1D94B6F93FA7B4B7712334B9FC3305 +:1076C000DA0D66EC9FCBB126A733EC033744CA69C9 +:1076D00091FDA20D28A7B1E245CC459AA6C48E170C +:1076E000112E8F112FA2AB7DEC781169A3BFBF784B +:1076F00011FF16CFE5F51F8D1731BF5A8E67B060A9 +:10770000CDF9E34594D98A56A35C6AF2F86FF1FC8F +:10771000BCAAA77811DBEC8A58AF812E6877015D8F +:1077200068BDEEE1BDFD738E8773713FD1997BD14A +:1077300079E31CE8E52236BD795C83EBBEE73811BE +:107740003DD155ABFF66398F5FF06FF1E78F5FD0AA +:107750002D4E444FF105067D467AB2B771227A5A12 +:10776000177AA2E7ACEF394E444F7AB5277DFAC7B6 +:10777000E99CCE13E2CF1F8F231C17CEDA72901A2A +:10778000BBBC34B555F10EBC60B68BFC27EDBBC459 +:10779000BD312F73BB52F93B75B437DBF7240C674F +:1077A000F47EDDC5BCC09F78F15DD9B57F3F9EA753 +:1077B000DFEA64DEC4248A07EF36E6E03E6CA415F7 +:1077C000FD29158D1FBDFC3B806B6B36D27DB276DB +:1077D000C0A185EC3E6F22F22D9EDD4EFB743CE392 +:1077E000FAA64FE47B66DDEF37609588F39BA946E8 +:1077F0003BED9B3AB7F27B9E4676F17D1347D37DF6 +:107800006A167413FFC84E5D21F0ECC414EBFBAC98 +:10781000643F2E3BFC447E88F1F3CA48BF419F423F +:10782000D94F5367730EC777952CE06D41FB7B8969 +:1078300080975224FB6F3E5C547808CFE997F84A52 +:10784000E91E425A89ECCF61E2DD386EC7C2F7E526 +:10785000009FD226853DA0747F475ED67CD706DC8C +:10786000E72C0FEAED6F968B7256CEE23CB8EF5DD7 +:10787000512F973B1CE23E879DD97B45B7D60BEF36 +:107880009B987C5EBA7942587F9783EEC32E3BBCAF +:10789000D88CCCB2A4CB74B3B965BAC5E7CAF4D15D +:1078A000D3CFE191E9A3A75FC258D9FFA5D14FBBC0 +:1078B0006FA832715F34C8EF91767B87DFB48DF0AB +:1078C000D4D34F4FAF510E714FA28B5E45D6545259 +:1078D000F98467861A22F9D6CF874C7B48C1FFEE20 +:1078E0009F1C5C4BAD3C0E15F5563A07CD9425BC5C +:1078F0005D3CCE078C2BCB3C341F70478FFEDD7870 +:10790000F66721F7EFB26F20BDA9F8B9E38BA07439 +:107910002BCADB08FEFB0BE4AFD27E3781795CB863 +:107920008F6AF05BDD4B543C1764EE2503F13CD0CD +:1079300045E99DE2DD6FFB5046FBFE86D027A97826 +:107940008E76675EC74CF43F542D6545B87EFDC802 +:10795000C9DF5D6C12E90827F7CF6C2E3230EF6873 +:10796000FC1D1E635041BFABCB7BF872B4479B4DEF +:107970006E7A47ECEA78F97A2A1F45EFA3330CB503 +:1079800023111FA84FEF6BDB9BDF752E8ED0C36DCD +:107990004D770FC1FBC5F71BA2BFEB2D7568EFDB61 +:1079A000F8FD8E115D71064A1D63281EC19DD9D058 +:1079B0004F657127F15193CB0982FECF954E27FC7D +:1079C0009E6C56DCE8AF9B66BCE107C300BF714705 +:1079D00055AEBFC4BDEED1A2FED3CC938EF88EBB04 +:1079E0009429387FC6BDC13C0124717529DDA7FBF0 +:1079F0009D73DA21E4D7946690279C0F67ED1EBC37 +:107A00002A3FA645BE2F9738C57700EF175E728CC8 +:107A1000913EBBE498AABF1F63C4FDFEB856F9FBB4 +:107A200004DDFE739D26774E968A72B7E52B23E11F +:107A3000D5DEC13CEB006EFB92BE746EDBFE09230B +:107A40003BB1FD2B6361B4FB25773BB8DFEB7E33A5 +:107A500023FD7D7FA99DDE393C5B5A7E01DA179FAD +:107A6000FDC47741343F65849D96C0DF9F7B13D86A +:107A70005894C35B154EEFDA8CA228EB9626779AC2 +:107A80001C6AF297511AE78B765F33D9C9EDA34987 +:107A9000A5B98A19E5679FC290AE6DEB00AFF3AC54 +:107AA000DB01B62E13F1A96AFA98EE61599B95A8ED +:107AB000BFCBF384C3C9EF03AE0BACC5FB1737C311 +:107AC00024423D9561AECD8A063FC0B6905DFA80F6 +:107AD000C3CDDF0D58451C21B53603EF23B4354D1A +:107AE000BE7203E0F900CC07E4EFFD260FE11DA80C +:107AF000608CEE930A7F5DBF996CDBE608FB77AF85 +:107B0000A3E030CAED6107B71BFBF83C0AE2EDF9D0 +:107B1000FB5F9D08BFFD730BF1AFAFB037B57627A4 +:107B20001D9C3E254EEF016CCFCA9249F9787C4EE0 +:107B3000F7923EE837077A47B1AFB4753DC9C7E859 +:107B40007C22C96E089272F27ADD2EE9BE7780E659 +:107B50008D360F584861F85E5FD36F4AB31272805A +:107B6000DC8FB6DA4378FF2CA90CC69D8CF13CACB7 +:107B70001C5E8B7A56F66B813CE6A371CFE8BD3F65 +:107B80003A5211BEA6F7347D796B22D747B7DEA5EE +:107B9000523CD0AD6AAB0DFDA9595EF7240C4D9354 +:107BA000A4BAE95E4AFF323E0FE3737E9918B6032A +:107BB00060928FFCDAB820DA7BA60C94A714A49705 +:107BC000EF4307A4C30F753C8BE682C7C6FAF0FBF0 +:107BD00053424F08BB669A58EFC6BD67E0EF284393 +:107BE00097B3C8F7457A3D0172FF27FCFD9EFBDF86 +:107BF00053294E68583F944EA3F58919871E403982 +:107C00009BF022E3C751423FB8E01FD2E792977C36 +:107C1000EB118DEFAA17F4FC66216B388F3FCD3640 +:107C2000EA10CCB7C875D629D67BA1476E2A1EB8F4 +:107C30001EE797264717DCE231FA22E8A86F1FF605 +:107C4000532AD6F077770EEA91978C783FACBD0037 +:107C5000F80D747912E70BD03BF193E095C8F72D3E +:107C6000CD57D850BE6F0D4D72CD803689D6226269 +:107C70005E22F3923F270FA8837122D69350C07ED5 +:107C80005D2DCA72A6E03DAE42C9DFA3FD2E1E0CDB +:107C900094F812E603C871E43D564D3EF5F2A8C9CA +:107CA000EF7ADC60E1F91D7ACC21352A0DC4200B76 +:107CB000DBEA423DABD997EBC3F65C22ED33560BC2 +:107CC000BB68BD7D9A95D4C0FE645ACF57E3FA04D1 +:107CD000E35F9DC2681E68E3D0CB63D5E706168CD0 +:107CE000D81F54A91D748FAFEA73330BF6C171FB13 +:107CF00026E1B835BA8C1474D1D321DB29F69B82E6 +:107D00001EB1F1CC77E1FDD944AB976D243C27D16E +:107D10003DE786509E15D7DBDB7478F602BF39D17C +:107D2000F053ED31F013F1DB2630DFEF5A415EF313 +:107D30006FAACBE0EB057B353D827FFA7933B6A99C +:107D4000FA803962BE687E5DFD3C19D1CCAE41BA85 +:107D50008F0BA90CCF5F7B9A2F9F88F156C5737A42 +:107D6000B5CFE9188CF2B943F5553BC9BE6835600B +:107D7000DCDFF6A719CD67CFFE934E8A6FD4D2BB56 +:107D8000FBE99A1DA5D94FFA7A9AFDA4E95DED7E2B +:107D9000F876A7CF8FFD2B4D209F30FEF52EBE2FFE +:107DA000DAEBF0ADC3EFF130063C4A62B9A12CFE2C +:107DB000FE5596FF58F21EAF93E706A013FD4E1630 +:107DC000E8FF414A773CB4FEA73813F9790BCC663B +:107DD000D443FDF219EFAC92D1FDC97EC3990FD700 +:107DE000A77E79FCDE5F50ACDBDB84BED5D2BD8ED6 +:107DF000A2FB117F93CA0296BCEF8E37A28AF7B11D +:107E0000B73BBDF7A1FC590BBD348E4C17F3A0FD59 +:107E100099A93628F86E3269A55BE1F7B059D73BCE +:107E200026809739C35D80729289FB68ACDF1C3D68 +:107E30008ED6134E9364677A58384ED513D82FD800 +:107E40009907CD80779F195ADC2BEDDCC6A3209DC6 +:107E5000DA1C7308E9B64F156E8F27727AE9F703BB +:107E60004878C44F15F9DBCC4CB525B1AEDFE13411 +:107E700058C98E8F679E06D44B2F3BB3C5B9A8A7B0 +:107E800006F3FFAE7658138776C9F19D13677954D0 +:107E9000A8E2BCB47338EE99409E0F23BE6D133B2D +:107EA00007DF4AC4E818C0E5C66B94E2E268F46FE5 +:107EB0003249F4B7E13E3B520F3ACCB48F6C53E2F7 +:107EC0003C38CFDA962B1C4FC52AE206A9F2FE5F9A +:107ED000E8234DBF763AB308FF7816A07D00B37A49 +:107EE000AC748F5DE08F7115C9AFB3373EB81DCF4D +:107EF000A3747114F57116272FB6D3BD8B2D7B6D2E +:107F0000B42FED2CE2E7F39DCD16D2BFB1E6691A8E +:107F10002A83F3C40B04BA7520DDD24CD589A8F7A7 +:107F2000D2E6F3F9AFA7473B0E14F73B7F3005A32A +:107F3000BD57D7D2F4F4BEC56897A567A453AA7DF0 +:107F4000AFB3AB51EF611B1314294EDF10E851ECB6 +:107F5000738C09F0FD9CEF8FAF7959D7BDF6BA3815 +:107F60004EBF4EDFF8848751AE40E0E8F704B473AB +:107F70004DB19FD7E22769FD6CF15B8B31E467DD82 +:107F8000A2E9365C075298F7CA793829B798D84ED3 +:107F90006A972BDD77BDD73FB218DF276726F07BC6 +:107FA000B49F6C994AEF9953D93ADB60A043699129 +:107FB000C183FE80738BDE741A407E1665B6E4A31F +:107FC0009C26987C990963C87545FB8D6525E660FC +:107FD00008E8955C070A81E818B892E8B8D010D58F +:107FE0003F9C9DC0F79D6F89F5243D7D40F19251E6 +:107FF00091F97E44574D8E60FE642C19DD150F13E8 +:10800000F87951429479D06E624DF85E42D347C9F7 +:1080100042CC347DA8C97132CE0FB4E38A403F49C7 +:10802000E77D5035B5EBF70C95E617BE403BD679AA +:10803000E924D237306F6B48CE73B9FEB4A13E8BC2 +:10804000F05BB5EF7DBD3FBE637AFB671F3BF05D24 +:10805000CB5FD40E07EAAFD3B7FCC98171C0DEBED7 +:1080600085EF936FD4D9FF5709F90826144D41BA0B +:108070002EF0FF3D3FD25E636BB8FF7979507EBF33 +:108080008AF7BF23FD80150DFAFB00011EA74CFCEB +:108090003EA79E0FEB041F96EFDA66CE7463FFBE19 +:1080A00039D8FF69B1BF39DDE8A0F7141A3E8B76E5 +:1080B0008D34A3CDFF97668B78A7D762E27AD93B40 +:1080C00003DFE7F804DDF4781EDC174FF096DEC31B +:1080D000DFAF2E84BED6805EF435F3384AFA712CB9 +:1080E0007DDB3D0DFDE84B3729B48FC3FAB7C03AAD +:1080F000E15BB391DEF1E8C7B93020FB73F4F11A0C +:10810000B5FDC032C1FF25F86BBC3951E23836F3FA +:10811000F774CB74F645E7A19C781CFF9A0461675D +:10812000E7B34B306EE79E43D909D1E26168E95964 +:1081300071DE8FF7FA313DED67944E4970F3785D4B +:10814000CD476E46B9AA6CDA4DF111F705DFEB3376 +:108150001EAA14347F6144A12A10F6D87C618FEDE9 +:10816000615C6EC08EDE8CF27FF9E73A3B5A8CF38D +:10817000064DEE0F2591DCDC80E31A8EDFD54FA291 +:108180008DEBEE04F9FD576FC7A58D471B9F565E1B +:1081900021DE9FEBDB69723E45C8DD921DC51BFAEF +:1081A0000229D6EF7D7F8088234771B63439D2CB40 +:1081B000C932C1B7B03C34DF41E3D2F806F29E2E9B +:1081C000DE25A5A33FA327B9D0F3BFCDD43A00E75E +:1081D000AB9EFF6D31CE7DB627F0738D256EEF34EB +:1081E000F4AF8079B8C115613F9C566B0FFE14E760 +:1081F000D10E2EC791EB22194B2F9A689D5DE57029 +:10820000A725DA05DFC6E1FB454B00EB69FD9CF2D3 +:10821000D7CC1A48E78DB5B3060EA4771B946AE550 +:10822000A5F77FEC44FBB43D97917FA1CD21E37B83 +:1082300004179B319872FAAF545BBE7E0B75D08EDB +:10824000168ADF7AEA2BE19FF8CA52186D9C6713F1 +:10825000B81DA8DD3FB951CCA31B9BF97BBB455B87 +:108260008BCDE4075823DFD77849714DCB84A6BE68 +:10827000869166E4B39E1F4B3D57D03BF06E7C6108 +:10828000B7135F97EADFB5897B4C0B847CCC74B95C +:10829000859DE6A377C44BEA8C64DF2F7357D3FE2A +:1082A00066851AFD3DD61897E1BCE3D18F6361A3C3 +:1082B000427A4F8FFFB21D6B37F465387E3EBEEEBB +:1082C000E308F5233D23C6C95A2FE7EF32C5BAFDAF +:1082D0005F995EED8C008000000000001F8B08009D +:1082E00000000000000BB57C0D7854D5B5E83E7356 +:1082F000CEFC24334926FF21413C21111212E29089 +:1083000084000171F24BC4080301826075405184FE +:1083100090207A5BEFABB79990682DFA7AA358CB8F +:108320006DEDFD062BAD0A4880A08126E9041403FB +:10833000040D820A96D68014B1053280B5587D8F1F +:10834000B7D6DAFB64664E92426F5F87D69D7DCECC +:108350003EFBACBDFED7DA6B9F65ECD94B720E636A +:108360000FB7CB8CE53356FBACEC65A98C2D63CAFB +:10837000E9BE0C46BF6BA9F85F67E59204C6EEC57F +:108380003F5568DB57553278AE5CAE9985CFF56FB7 +:1083900090995982EB1EEF53C971D036498E461819 +:1083A000C71E379EEEB33066817FD746D33C8C25FF +:1083B000E0FCFCD723B1A75260FEB38AFFBD08786A +:1083C000EE2CC0E181799678F873F47EF8FF32C71D +:1083D0008C2F2478DFFDEDF229730E5E5D6D32C0C7 +:1083E000F8A52F496C1D8CBFFF69DD78B12EFD3AD1 +:1083F0001EDAF0A3B9E91981710F7B9F0BE9C3DA8B +:108400005456C0D87D023EF6EA7F05EE73F84DAEB5 +:1084100008C632ED117167B3A05BC0265D4B63AC3B +:10842000CE1A99C3A2A03533C2233B64F46E02B8BE +:10843000D644C08201CE355BA3BD1EC4E3EA68C644 +:1084400046C0B8F68D26B70DE6C4DFED8C9DAB6F48 +:108450009E9B9E0EEBAF7F7A6EBAC2D82CBB9DB1AD +:1084600089408FB6E7685CB7E29A6487FE2A4BDFE3 +:108470008FEF5683F03899D363995C696286C07C2C +:10848000FA7659B3F1CBBEA0751621FC56F86312EB +:10849000C02FFF3DF8D5C4685B006EFDBC7FAADF2E +:1084A0001002F74A85395B6C81F568E326DA0DB472 +:1084B0001EFDF37A7A30E6A5717ABAAC443A04D15B +:1084C00017E15400AF3D1D56EF5A89F888E0F67465 +:1084D0008411DC1793D6CD3D93C7D8617C00E0AE04 +:1084E0001DF132F55F515C6E7B3C5EF48F728DC77F +:1084F0006762199B323CDE6046C6607C2ECE0FE37D +:10850000768539F3988CD75DB1C807D31BFAAA2CAE +:1085100040AA3AFBA40A05DE33FDB9BEAA30E83F03 +:10852000629FCCFB9BFA8E5A1C8C35B02915A5F0A6 +:10853000FC63700FE7BB5E9B6F762D66C05735807E +:10854000534B0CB4C7C6BC8DF256D35B5921454280 +:10855000CB984FCA057E7046FAAC39D4678530AEE9 +:1085600033CAFD1FB8BE55579B2EC938EE98C2E5D9 +:10857000A53B8EF0A000EC61F05C53B853B503BE90 +:108580009A622C8EC654BAEE098BC1BE535583AE87 +:108590006BF4C0E7108E2603734643DB75604C54C2 +:1085A0005FF6F078EBAA57AB14A0FFBEFA0C6AF5A1 +:1085B000F78B4CF674073C5F6460EE16DBE0FBAFB4 +:1085C00022BF109DD414A4736DB789E41C7F12F0F0 +:1085D000FD2AA1876A81405100CFAA63CC171E896A +:1085E000E3CABF50B06D95D8E910BE6281BE3C3C75 +:1085F000DC37DAD6E27C4A309F703C152BA9554A0D +:10860000D07B4B6D99217D39D19081EB6172B8633C +:1086100013E0574E31ACDE01EB976F8616F0A1D810 +:108620001DF212689B4BA6CB4BA16D34B2852DD8A1 +:108630001AD8F2603C750879D2DA4B76D76F90EE93 +:1086400017DEEF2DB0929E1A6927F916EB6D941C78 +:108650003ED4439E2EE6D804D79A6417E37CDCC24E +:10866000908F7F2FE671980D3B55E0D7F7EC0F12F6 +:10867000FF3AA20C8FA642FFA3E615150AF0AF231E +:10868000C570251578F478F34ADECF325C190DFDFC +:108690004F9A6B787F2A4C99CCD8C9E655159E6CB9 +:1086A0009C97EB31B6C59985EF510C12C9A9B2D789 +:1086B000E46D843F9B22393F3519812F6370BC4A9A +:1086C000E39F6A28DE6C05FE578A9DEA6A1BC73560 +:1086D000F2C3FFB4D5F0285B0DAB118FD822BECF0B +:1086E00088756B7460ADCEAC39A8175A9C5973234A +:1086F00010AFEECF11AF793DBDD3510FB77EF0492A +:10870000813B9BD30BE7C9EB612C12D673E1AD9B88 +:1087100036CA52803E97EC45E7515F4BA0A61F87B3 +:108720007549AA9DDD0372D7E864AA09D695C85E8B +:10873000B2A3FD30207D4005B532AE5F3AA35C5F49 +:10874000E2736CA48FEC4CB5DDF515BE5FD3CFACF6 +:108750003766483DACD757A69CC765067C1093D2B8 +:10876000767C29EAF3DF9A1DB7A8088F933D0E7037 +:108770006C333085C5107B642870DFCAC21DEB5096 +:10878000DE1D2CC903F2856823E0E01707F6D02828 +:1087900064485B073C5FCAA09D8470DD4AEB929100 +:1087A0009F2630978C7AAB8079ADD8F677BC9584CC +:1087B000F87A3E8CDDE782D6F22A737A83F4467E1D +:1087C000B444F89F1563A436DCD83217F934FC1290 +:1087D000B3A31FD0FF0B9382F38360DC89D71DFB0B +:1087E0000D0CE1FCB5D16B8F82BE3F53515F6681AA +:1087F000F9FA059DB5799F37A999D1D0AF8A91082B +:108800002FBF2EE2F6D8FF85C9FB722AE2C7B2DA83 +:108810001B2457E3A3F9B8BAB8E2B1D1F07C4B47B7 +:1088200038C3F74FEA0C3720FE376FC90D433ED8E7 +:1088300086B881F5C798ED8FE07C315700DE54BAD9 +:10884000EE24BC2AEA8428C06BE14C9BBA0EF0FEF1 +:10885000EBB09699C8F7FEAD06F632BC629BC93103 +:1088600007FBDB2EAB76D4B3BF4E6D09A7F56C3595 +:10887000D07AB685FBC7AD01B8D7652815089F62C9 +:10888000650AEA5FC550AC3E02D7A74573FDA8E96B +:10889000E39A6895FACF4BF0FE5C1C57447253265E +:1088A000DB48DEFAFDCC6B86F7C4CFEB95911EE179 +:1088B00073809590DF159FCC703E17121A5A9BD18A +:1088C000AB929E75DA9600DDA70B3D3BFD644D250E +:1088D0008BC48EE3D854986F9FCDC8705DB7B13EFE +:1088E000D902FDDBAE32870FF9E7AA427E981DFE62 +:1088F00005FB7B65629E5F494C898271455FAA0AD0 +:10890000F257110BF5DBCA36947F81F6ADC4A2BBDA +:108910008EFE5C24B64AE03ACCB3285AF861A3D85C +:10892000A86BA4CF60D6046147555C7FF67FE1BA9F +:10893000FA2B4C0E5CFF769BF3E3A9A8077B8D6CAA +:10894000131B5E8E7E550F1A7D0C08C7D570E68D01 +:10895000253EB421FDC76D68F684C17AC7A5F3F939 +:1089600091DF506F8CFD455C2CEAED8868AE4FB40A +:1089700056E32FE4237B14E723FBAD01F9FB5E7480 +:108980002A8DD3E409F90BE7D963F42E760D61172C +:10899000812FBF877CB9DDC62A90CF9F1961598886 +:1089A000F2A4BD67B7E07B7DFB54C39A2E23AEFBD8 +:1089B0002FA0FF01EED2E4ABA660FBDD15C7E12DD1 +:1089C00093BF25BFFA62BB44FE7C423BD7D7C17C34 +:1089D000316268BE7801F17A3DBED0C7011A5FEC02 +:1089E000B81E5F74FF637CF18B68E1DF0ECB17DF8D +:1089F00046E2FA1FEB2849647FC78F69137C30DC9D +:108A0000FD2956AED7F4D7DB053E779B9AEFCC41D4 +:108A1000B9BFCBE040B906AAA7CC05FBB23B9C3F4F +:108A2000C794D569D8DFAE703DB2BDDD4C7A64BB6A +:108A3000CDED267B9D6461E82730C5DDF77DD47FD1 +:108A4000C916755D10DF3E2EF4408BD137E573F407 +:108A50007F0F70FA4EBE2B5736C1B8110F70B9CECA +:108A60003F67DA28C33CD53145BE6818DF17CDED26 +:108A700062DD1918057C597BC644FAEDADCE23E5BD +:108A80004E1BF9374EE4AF497B8E941767E378CEDF +:108A900047DDA2D5FA53704D3164768E25017E5D97 +:108AA000C24E4C615C0FB9903F72027DE634523C7D +:108AB000A6F1413563596827E6F639CA908DAA2A8E +:108AC00042E95BED9B4971DFFCE3CEB20858D77CED +:108AD00097EEBEA07FB58EFEE007FF01E564D5E608 +:108AE000DE4E1BF2ADCAED698B697516F77B56A792 +:108AF000A1FFAFC911FD004F2DBFCF78795D901D4B +:108B00005763F83A9F752874DFD367F2DE0297FE49 +:108B100037E3CFB5087BF3AD90E3DCC7DE588CFCC0 +:108B20009BB7DCB90FF1BF284EA6EBFFC97C96348A +:108B3000A48F4321FFABC5A8967C2E05C631C595F1 +:108B40006183FB7BE2C3F3F0FDD531EE6B4827A6D2 +:108B5000F8BBF1B94985B9792857B6094DB1687F95 +:108B600034B801AE8A4DB6001C1A5CE785FEA98EAA +:108B700059720DF180CFA15E693B75D682CF6B74BF +:108B80006FE9B8C4E91D447FA47780FED27DD8D7B1 +:108B9000F06011ADD6FFE7E9EF1B89F41896FE18D7 +:108BA000F747FE8FE83F2A6608FA833F958ED73550 +:108BB0007FAAC5047E7576A0AFD1BDDA5E44E31C02 +:108BC000265819FA4F9D1057A21CBAA3D1B9613B80 +:108BD000EDFC5DFDBF3F3B0A5C4036292686CB930A +:108BE000C93F06FD8D093E89FCBE0920F0F7909F24 +:108BF0003592F49D43E0879D95A4B319DC05BF969B +:108C000082FE9F2F16E56082B9D287FCBEC33A3D33 +:108C100005FDB75CEBB434E4A737331E3B8426E78D +:108C2000CDE4E53B5F51037E8EA6D7F68969B5F7A3 +:108C300097C770FADF0E6A16FD3D740D83E1D0F41C +:108C4000379205E1907CD5866B56D2C7ED7D80AF1B +:108C5000DB110EC06B97C45A517F17199C7125E820 +:108C60008FC5FB14EED77D3D4A05BEA96C7FF73852 +:108C7000C25B69B1F930DFC21CC6F37D41F912BD98 +:108C80009FABF9259ADFAFF92D5A7C89FE0DDECF17 +:108C9000C7EB00BFDD0C00A2FDF159BC0DF0FEE7F3 +:108CA0002FAB994E21AF0AACA352AC6336EB25B87B +:108CB000D8B7D7AE4D03FACC12F8A8EC86B8300777 +:108CC000EF337617E0E12E85C78B7739203E0CE233 +:108CD000A3D99343FBF89B9E1098E77AE3F5FA7FBC +:108CE000AAC817FCB371A6D676831D3A0D0C70B0D6 +:108CF0009EC73485A3658F82F1803BD380FC5827C3 +:108D0000EC1A84C943DB2321AF8586BE1C07E0B77C +:108D10006BCF3764FFF6EEF9E623F4E7A67CA130CB +:108D2000333C5FF8457E14EA07E60A9DB7EE8FAD47 +:108D300056C6AF13FFD48AB5EFAFC78C18C267A170 +:108D4000F637E79F5F8FF37D7946E1BC2DDE5F6EDE +:108D500072A7DB6DD8F2787FBFC4FD1DEDFE7E23C8 +:108D6000C00DD737C568717FAF42F919F89983E80C +:108D70007C17C6FBB901BADE75AEE20B2567307D04 +:108D8000F0F7FF23DED7E2FCB744FCC0F69D30A924 +:108D900000D78CD64714F4A36724C9CC19F4DE3B62 +:108DA000542B7306C5FB6FC4E8FC907DAFAD9F05E7 +:108DB00076A4AE477684A1BCB66F3F9483FD5ED99E +:108DC000611D828FF4F89DD1FE8882FC9F10CBE557 +:108DD000E67AEF2F1C077C722BD29D911F77B14052 +:108DE0002239D2D377EF9E9FC7F6650F8FEFE1E868 +:108DF000AFA7C36FCE1747215EAE470F3DDF76C2E8 +:108E00003A3DB03E1FACD303FED6DE7A3BF5DFAE73 +:108E10004FA2BEC6AF751DBF8C457F4DE3D3B25880 +:108E2000CE375376AF8F65B600BD347C5D1474AB1E +:108E3000668EF9B3E0CF5D922382F48487F5261520 +:108E400004EC55F5B172F233347B552D671B51FF9D +:108E50006AF60AD3C2A8CFF4F6697E7A9111D5AA30 +:108E6000DE2EC1028DC8BFD50B43AF57F4342B1192 +:108E7000D433109D2449E043F8D51A3C1F3217C162 +:108E8000ABA7A7069F1E2ECD9FAE1674837596E1E5 +:108E9000D2E7AA45B48E417655ACF746EDA93936EE +:108EA00034CEBA72AEF4FD9C21F87538BED5DFD74A +:108EB000F44039BE20975A0FFA1109B10944AFF2B4 +:108EC000AB26E6047BC14686B1CF82F3EFAF649256 +:108ED000BD7B54D8DFE1F8A6F6AA81B96303FC6331 +:108EE0006C7BCE8AFCB35B69B662DEF136DB9CC676 +:108EF00028C053E91F8BE7A15F57D76760989A2A6C +:108F00006BBFB40FE3F6BAE3CC81FAB0B8BDAB04E3 +:108F1000F9ED6DA557A638FA4BC69E0BF20FDBDABA +:108F20001BADE83FB5C5C914A7EF8FE6FCA8DD6F00 +:108F300089E5FCD776E6F22CE710F73F13F74B4FA5 +:108F4000E51AD148F6C74750BEA1FC6903ADBF542E +:108F5000B25755A2FF718791FC7A885BFEF07DCCF9 +:108F600037B599B763AABEACED878FD881102DFFB6 +:108F7000E7B30633E60FE6488E97615CB9EAEFC2C5 +:108F80007EF9BC54DA8799F47F65F25FFD774B94E4 +:108F9000F7280776C17EF93DA95ECC3FEC9178DFDA +:108FA000D3C1F3FECCEE899D05EFF9A03276C23A2B +:108FB000E229AD7F4BEE3A261838289E7A6C17DFEF +:108FC0003F7AAC4CA2FDA3327B0AF304F155F9D3EE +:108FD00040CF3CE0C7F6C462E4DFAA0A997983F87F +:108FE0007ABECBCABC41E3F7877178FC92D98BF982 +:108FF000124D5E670AFEAE5E181B327E0EE37EE205 +:1090000042D66C44F9AE13F0D415013CF0FC4C117F +:10901000A7DEED4E09796F256641606856DC68B2BF +:109020008FB3BFEC23B33A473E796C31BC87657090 +:10903000F9D0E4AC4CAE69223E48921C181FCF9781 +:10904000C0AB9451DF85CAD1ECC9A1FD394EBD7EBC +:10905000089577BD1ED7E47C7E876CC4387A7E91F4 +:10906000E46043E803BD3FADD703930C8E7730AE89 +:109070009E7BD549FC35480F9CACF887F4C05B203B +:109080005B93415E7FA4E9839BD84DA80FCAE42D72 +:10909000EB913FFAC1AE9987E00FCD2E68F176399A +:1090A000C827F2033BCFF725CAAE829CC606E2ED85 +:1090B00001FD007E8363087FE657B16921FB490308 +:1090C000FA22C86F3016FCF37E4319F88BA65C8435 +:1090D0006F24F3E4919EA2FC1EB43ECAB3255DA2A8 +:1090E0003C4A1DC4F114CFB35F125CA8D7A498000A +:1090F000DFEBFD092D4F3B42E409F4FC3090B79BB8 +:1091000067F4229F69FC506EE772513E4FA6FCB98E +:109110009E3FB4F75D8F2F7C12F085F477F842C83C +:10912000D38DF2C5218D1FD259FA8DF083C6071A4F +:109130005FE8EDC5415DDE65387B71F23AF6E29D90 +:109140000C23E965BD9DD0ECC28138AE7FC7C7F264 +:109150007D8A9999F36DE8578C407D80FE9EB037EB +:109160000379A30D9C0FDEE95BAA486837500FA472 +:1091700006E15DE44D35BEAB7D9A51FEB052E89FED +:109180008B1D3C9F56572A7B2DF06749FB73EB796B +:10919000DF48F9B622A54BB1C0BCB31D9203F3352D +:1091A0004E917F9B75D5E455293F3FF47E7A95E03B +:1091B0001B8C7370FC6CA7E4851074901EAABACA4D +:1091C000EDBE5E1F5589FDF22ADD7EB9294ED0F530 +:1091D0006676F3BFD2EEC7C72570B919868EDAF36B +:1091E0001A1D35FA4DC0B1283FFBBE36A911DC3F30 +:1091F00046FACDB8AAD03CA3E242FD962FCFE7FEB7 +:1092000027C574627C5DFB25937BFCF0F05FCF2F5C +:10921000BD59F3C3855FAEBD7726C8780A3A863A52 +:10922000FBA1BDE7BAF6423CAFA7D3E4B8D0784281 +:10923000A387A64707E15BE8D9E1E8753D3DABE9C7 +:10924000B37FB59ED5E6D7EC80F65EBDFE1D2E3E03 +:10925000D3F4E9531B0D9417B94DC4C1B7893CEB46 +:109260008342CE970B7DDBFF178B01FDAC6D9DDC40 +:109270001F7198ED87D06F08E4F3385D9F8C601EF6 +:10928000DC2F674AAF85F62F8B81A4B87F99CCF786 +:109290002FB7283E17E96987C21A405EFE2AF216E8 +:1092A0004FEEF52C463DFDE4E93106DA47577CBD2B +:1092B00018174FCA55683F28DAAC52BEF76287D9F3 +:1092C0008ECFF5EFFE5E9711E7F90B7360A8F67687 +:1092D0008779603F06F54299DC23635EBEDF0FBEEF +:1092E000388C9FB6D05782F1CE6DACB711E3EA420D +:1092F000A4E310F47B55675FF479FB920EEE27959B +:1093000044F0BA9FE980467CEFF43613F985D7CB59 +:10931000DB177DC9C85F1A94AF6FE37A0606119F09 +:10932000DC68DEBE107D3DE0E39FE8F40E1B267F87 +:10933000BFCDC4F773FC478C0CFD5E762E6EC8BCA7 +:10934000CBF5F2F8BB3BC39D6A24EEBB71FF7C7783 +:1093500067B253CD197E7C4E9FBF18F395DBB6CC18 +:1093600055284E14F9CF41FB223AFCED9058931545 +:10937000F369ED8E528C3F86DBE728F63B69DE1BF6 +:10938000C51B63CD9CCEA27EE9762163DBCE863BF6 +:1093900091BFB79D4D76223CBB057F6AFCBEFBCCDE +:1093A000E570DACF343955DC07F6475B1C2F13BF65 +:1093B000723E6F1931C68BFBADDB853C6C0BF71F22 +:1093C000CC8A0BDECFE0FB179DF59EAA33E9B4DF14 +:1093D0002D61BE51DB27F680BC505D4E0C237E32E2 +:1093E000B21686EF6D74B29F633B7D9A1A85F8BE04 +:1093F0001CA7ED47AA519467F8F64A816BFC60BC44 +:10940000EFA877513D496BFDC22A05607CB3DE4D64 +:109410006D5BFD726AF7D4AFA6FB6B0F453E8E768F +:10942000BFCEB9A04A09D21B9FC5F3FC526ED6E944 +:1094300012E473F60D6318EF4C7FA24F463D71FBAB +:1094400055584748DD887219F14CF9CBB4403F5567 +:109450005A12867C79FB55E8078D97E2A3391D9A4D +:1094600094A65B0A485A881FC2E29D17E3E0FA0FF0 +:10947000ED2E7F5C3CF241F5BE0B8CFA97F1FA0EB3 +:10948000E96EF9028CCBF31551DE380FF3C6B9340F +:10949000ED62C4DFC42E13ED7B6BF9DB5C31AFF3FF +:1094A000ABD03C729EC8DBBEC9FA289F9C6F81C0BE +:1094B000CA807071FA39A5F94912E6FBE24D0EAC8B +:1094C000579898E6CAC37C6B573CA3FC695757C2B0 +:1094D0004815F0E054785ED7A9E575D9DFCFEB7673 +:1094E0007F1AE9217D057E0AEAA7EEA3910E1FED02 +:1094F000FF59C8FFDB810F627D4338AF1760F3E689 +:10950000511EFD760B5F07D89FF878CAFBF9F61D50 +:1095100086E77E7B99F17DC4DE93B43F5D62C84CE3 +:10952000EC0338F74963A3B07DF1D3C86C6A8F466A +:109530009E47FC741AAC2ABEF7C37A56857567CE6F +:10954000F76DB49F31FD7D9B82EDE1FA3EAA477B2A +:10955000BFFE1CB547EAFDD41EADBF4AED3B701DF2 +:10956000F9E7103C8F6DEEE2087A6EC7A20813C2CD +:10957000DB19C9B668EFC17A335FB8AF1593F9EF5D +:10958000C57FBECE7213D83BB37BBC3481B113F11F +:109590009FCF54A07F68C6A87FFF0BDCFFDD4F2E56 +:1095A000ACB3005CF38EDA5A7BA0FFE94F2EAEB36A +:1095B000A19E3D140ECA0EF546FF41907496873663 +:1095C0003D9971053B19FAB1A2EFE99F590A245F51 +:1095D00050D297C580B5A6FCC43FD302785C6075B5 +:1095E000FF1BF64D9E976696DE847DE6C17A2EBF00 +:1095F00064A4F89E8D94E2B07E6599DD7D2C3EC812 +:109600007E3BA53FD2FE51815362D1714457DACFE0 +:1096100062F653B1C1F2B6CC5E760CE971473CDF1D +:10962000BF9A384D7206D749E8C74D3CA396229D94 +:109630000ACE9537613BBB229AFAAE85939A509E2B +:109640004B6DC33D5F42CF2F8837127F162B524898 +:109650007D887E5C1E3013FAC7FE03E1941798786C +:10966000CCDD8875A36549A9B9B2D0798CFAD11B34 +:10967000711F6D62E587A5B1283F36C981E6A180DB +:10968000F535C5C661FD231644E1BA9E2BC1FA9D8E +:1096900089AAE440B41539BB5AF1F9224784A308DA +:1096A000FDF1636A299A9CA3CA84C3F9306E46BA55 +:1096B000ECB0C044477D774CBD00FDA28C28CAE3C6 +:1096C0001629ABAF1CA67E84A341C5756CFC792D11 +:1096D000CD63267BBE6356C97F20FF14BBA228E75B +:1096E000576A3B3537B82E0CD64D7017D9656F9831 +:1096F00084FCFD83523BF4778C9218CACF515FE60D +:109700009FE97E77B81A0680EE30D94B71BE1D26D0 +:10971000C9BE96FAAE121CEF196354314F541EF7AE +:1097200045C8FC334AA5296710FEECA80978AD624C +:10973000E4A590FB3D8BAC64272ADFCF267FA8678A +:10974000510AD98BCAF7A71563DB63E07E7AE5FB84 +:10975000951574DFC0E3DFCAC5DF718A3EC5BB95CE +:109760008B5751BF4B4AFC777CDF95ECA85CCCA3B0 +:10977000CD4CFF7AAE12ECFFADCE24F9CF1579BCFB +:109780002243E6FA6900FFA307F83E4465B6145287 +:1097900037372BFF54483DA86BDA1721FDB9A59741 +:1097A00042EA43E7557E1DD25F304FAA0A1E5F7A18 +:1097B000209FEC6BBEA85FD2F24B458285DEA9CF1D +:1097C000A82A05B93C00ED03A01F8A7A45DE55E1C1 +:1097D000717506FC433D586AD3E577994AFBD91564 +:1097E000DD7CDFBA3CCE783AD83E54C84F707F411A +:1097F000B7FEDC0346B293B9D132E5AB34F82A4662 +:10980000863EAFF95F1502CE1D0677530CE5C79C67 +:10981000BDE87F68F06BEFD7E0AE90EF29A5EDBF14 +:10982000EBC0AF87170025FF4D0FC78178118780E8 +:10983000BF41FE5937AF4B835FDC50765BF3CF2BD4 +:10984000414F4507EB299B1487F576C3E9296DDE67 +:10985000E1FC306DDE6576173DEFDCFAD9D1423997 +:10986000A89F7A2A3626B8FFDA67EB43EEC79FAA8D +:109870008A0EEE6FFAAC0AEF4F57D4461BF0E34165 +:1098800026393CC89F3DAA82FBCF25C79C4DD89660 +:109890009D746399299B71C6D384EDD4F3DE1E3386 +:1098A000ACEB8E0C59C5B85DF33FF4F09A13781CFD +:1098B00072F0AA6AC5FDD31D1ED58AFEFB8E275401 +:1098C0002BFA1F3B9CAC02E331679A6135FAF3CE69 +:1098D0002C5E677855E8E16FE2F9F35A7B5A717FA5 +:1098E000837A11EBC2D127A8FDDA4F75E007D1AF1B +:1098F000CA1EEC571D54BC367CDFC127BCB6E07DC8 +:10990000C21BF5ABFE8C363A1EF96C4E887C96581D +:10991000EEAE0A96EF32FB9290FB9FC6A904FF8C35 +:10992000A48743C6DDA13E12D2077F3103FD9146D5 +:1099300013A33A598F81D7C9EAF1F8A8C0A3C36627 +:1099400047378619E354AA6BD38F739470FCE9AF41 +:10995000A727F0B86823C80CB6F72470F8F475B1DF +:10996000FA3EC47C0B713E983909F9DC61355C0123 +:109970005797391392EEA47AD93CC3A369D0AF4E5E +:10998000C8E2FDA9869D581F7B774236EFDF6AC883 +:1099900033821FF02B36FE4EAC07AF0D13759D0FB3 +:1099A00024D27E9816DF2886532F2EC638738F91C7 +:1099B00061FEFE1913D8BDDCC0BEB9D5CCE352ABF5 +:1099C00089D76D3F957AF429D41B6A987B7A02F97E +:1099D00051C52AE2EFBCDD42759D8FED2E4B44FA56 +:1099E000DF93C0F35C593BA726A17EF917BC7F56D5 +:1099F000C2C4E1DF8F75BE38CFF91D59E47F67DD42 +:109A00000CE89502F887F098AE87419840E72598D2 +:109A10003309F36C8DD1269AE79E04CE7F37DA0E98 +:109A2000AAFB8D32ACDE0EEDFD82FE0FE07B095FFE +:109A3000FE51737063CEEE1F35773CEF237D6539A1 +:109A4000D78F7EACFF3B11B4AFC246FA69FFE5E3A6 +:109A50007BB21CE89F7E12CEF1B7D03BBAB14FC5A6 +:109A6000FA0DEF4D582F9191E8AE453C2C327B6FAB +:109A700021FEB1AD8EC0F96FB41E78F07B21800459 +:109A8000FA544FE1F4D1DE0B38B5A03DF8589C03F1 +:109A9000D1E080F7FF00F9408367000E5D5DB89666 +:109AA00067AEFBA381F20C7512E83DE8EF3CC91CE0 +:109AB0001E98E7A2E6AF8BBC266E45E17BA61C5E36 +:109AC0005A628336BF6D258F737B95903CD7A4E394 +:109AD0008A7EBF83ECD654ED795D9E71AA886BA710 +:109AE000EAE2DA1713849D4966C9C1798035226E8E +:109AF000B8DC333A0AFD4CD45132E0D5A4CA6C72BA +:109B00004C40CE5B21EE674171BFC667E38FD9EF52 +:109B100047B8C71F63F7915DD7E61DC82F70BC5CBF +:109B20003ECEF132A12FE3A7D3A06FEC3632AF1AAD +:109B3000584F2107955DC6FFE078BBC98B75CB05F3 +:109B4000077E99E7834BE624035383F010A6863300 +:109B500035482F5A336242FAB2866F61CFF3C4FCA4 +:109B6000118EE49079F6C49477A37DCFB32D27FBB3 +:109B70001E357974C83CAC4709B1F3B028DABF9CF4 +:109B80000840FD0CF05A704C09B1E793E23CB86212 +:109B900036F9A4A2B3FFCD32CA41E199D0EB0786D2 +:109BA000A3CB70F863393F45FFEE1FC55FB4331494 +:109BB0007FB115A1F88B7785E22F7161289E46B899 +:109BC00043F192B27C5CC8FD9B56E786F46F7EBC85 +:109BD00030647C2A18A4E07EDAD33343C6DFD23C5B +:109BE00037A43F76C3A290F199DEA521F7B35E5D5D +:109BF0007143F41EDFB226649C9EDEB7B6FDAF90C3 +:109C000079357A7BE0DFBF82DEE6C4507AA70AFDB1 +:109C10001AEDE4F565FD46DBD312E8234C13A15E93 +:109C20008B6E7FF76BCC43788A55AA9FF3CC64B4D4 +:109C30000FFD82EC92500FA5C0148634AA5FA7FADC +:109C4000BB1F1B0C21FBE28989DCBE2726F27CCDE1 +:109C5000CF4DFCDC520AF88F64870C2C102F031EAA +:109C600022315EA678FAC7CF60BCDC14DD97A14232 +:109C70007C6CC6FE4D017DB9C8AC36F6013E26C8E7 +:109C80005C1F829E4C4B84F93F919E30723FC263B1 +:109C9000443F22C5C23C91B9643F287F1CCDE224D9 +:109CA000ACC78F0AE869F51A106BDF8A2C3A07F502 +:109CB0001E4282FEAF2586ECE8DD9A7E5A9E49FA66 +:109CC000E9B22DD40FBBFC401A5D3F71AF99F6FB92 +:109CD0004F883A446DFDE784DEFA53BD85DAF3F52B +:109CE000F6103DB67CE3FA08F41F4F64707F51BB59 +:109CF0005E82789B88AD2CEC9AC58EF9AC7BC0381F +:109D00004701BE5775F7452E62E43716E3BA6B3745 +:109D10005EB9F74DE8D719FC09DC3E7878BDCCC7B1 +:109D20008CFCCFEA6F5888FF343791C7E973C5FCC4 +:109D30000BA0B1039E1600FEA3B17D775A39F2271E +:109D40005CA7F369B3BB19D59FCC71A7D23EE35191 +:109D5000E6F8701780F89D4495E09CC75CB45FFFFF +:109D6000D1BDAB2270DCC07CDA3CC028E86F7C1C23 +:109D7000ED312660DC7F1BAF6F80F759F0BAEB9EA8 +:109D80009427D10E69EFFB88B92F7C88FBDDCC418D +:109D9000F36AF3331613A29F762C5FF9692CBC6F1C +:109DA000CD0103E513D6749829EEEA5FF1D7AD2F04 +:109DB000C2FDFB52FA6E42BBFCC98A6FC6203FDC73 +:109DC000BD01F410ACB130CAFD7062509C72E281EA +:109DD0002B11781FECEBA617D1386E36537DEF2789 +:109DE0002B368F09F6471F4D2CAAC5E7D8E41B3B3D +:109DF0006F58F27A6622D563097E7A58F0D39AD7E3 +:109E0000C6921FB52662809F787F13AFEFD0D6F140 +:109E1000A1E0C715AF7F5D107CCE7407F0913A8644 +:109E2000EF6BA920533B7B2EE7E0FD57147713C25D +:109E3000D779F57424F677BEF737829FCDBB31789A +:109E400051063D0581FD65EDDCE5C2F6D83CA43B3D +:109E5000C85933CEBFE837AF5DF81DE2A763F3A65C +:109E6000EFE3981B3C7FC9847D71083C807DA1F89D +:109E7000A09F85F3731D428F2AB8839E86E7991CA5 +:109E80002AF1B3931DC27D97C62E03C3BA9548DC51 +:109E9000B409CAB345CA06CD08392D49A09F855ECD +:109EA0007925F1E49D4DE4E787FA3DF96FAF08F1BC +:109EB000775CF08FFC9D97DC8D9807BAAEDFE333BB +:109EC0002C3145DDB8FF0381B0532A105B38F06BAD +:109ED0004B14FB22420F77A21C61FD3FCE85F97A1D +:109EE0005F383F670CA602F5F80F604DF8B02945C2 +:109EF000B4D2C50C0BE8C5BD897F78E669D09396CE +:109F000074BE5EEC37E2DFDD9CDF06FCABB7C791C9 +:109F10009E62DFC2DB100F225FA1A7533EC8078BF2 +:109F20000D9233F1BC6FFFDF22314FBB35467D1FF1 +:109F3000E9E03F20D33E4D98D2678A1E222E7B1344 +:109F4000F59E89FB4D546FDEC6F38116D5C9300EE0 +:109F500008B3DB27049FB36B17FA6ED5FE4F469903 +:109F6000800E170C3D91D9307FCDAE1D91E8C6DF34 +:109F70006B747F8A7CB7F2C40705763ACFB671144A +:109F80009D03F08DA6BA83F10AF328B983E1A8DB1B +:109F9000904BC6B8760325E3D9F8F6BC87501FD599 +:109FA000F9F83A716E2CFCCB6C63D4BFD8D6188309 +:109FB000F3D5FDB62319E567733C8F135FBF3A8E67 +:109FC0003FAF3005C77F99182DF8D96BC03863B300 +:109FD000884F2E5E35D038EDFDE3DB8A643BF043DD +:109FE000B6AF792FC543ED6615E91AF60AE378682E +:109FF0000F2339AFEB9CC1309FDF1FCD1C12DCDF7C +:10A000001AEEFF039D33EB30AB981F0DB337B31837 +:10A01000987FABD80FCD048EC2F34ADA75ED7D611F +:10A02000ED3FC55802F981F2B4614A33BBCD168CBD +:10A03000E708C2733CF2533CBEC767C0FC88FF16FA +:10A04000C65E26B80270327AAF066726F9735B4D9A +:10A05000FEB3787E05E0B223FD33198793B58F55A3 +:10A0600031BE0FB33B691D6176D5E19106C35597AB +:10A07000C3BC68BF7FBC960DC82BCA6F5D78A06F4C +:10A080000119D83A9A09F9B63F5B3A2DB80F8A649C +:10A0900072E0F9711B629E6D1A49718347C63816CA +:10A0A000DA88185CA7CACF3B636A2897E301F7C533 +:10A0B000AD167E7F603CF0B70DFB363ECE1165B726 +:10A0C000CE94484E28AF572BE4FD31C977F67690F1 +:10A0D000D3BFF8F6E6A8004BCDBB7B884F571ADA02 +:10A0E0005F1C0FF7375ADCF94980CFB74E1AE81CCE +:10A0F000E99F5E0BF35662FCB87B63827308F9D06C +:10A10000CFFFC3E36B9F4F41FAEF9654CC9BF61BF6 +:10A11000FDA310DEDAF6CF4D548FD0768AEA938E07 +:10A1200024B99DF89EC96D0DB46F3C8535D3BE71C1 +:10A1300096387FDD92C4F5C7E563635E6E08C2FFA3 +:10A140008349DC0F637EF7CD2837ED423E3BD12FAC +:10A15000817697F08F7675DD9DA606E5FD1AD8DE2F +:10A1600014C4F75AF636B5DAF57E2F3FCF98F5913D +:10A17000E53E6710FFB993B89FE716EFF327B917CD +:10A1800024A1DC769D3645AA785EA56514DA911681 +:10A19000F09FEC43E065406E757254A7F84D38BEF1 +:10A1A000EE1C3F770A746EC2FAFFCD1FB58D5B02BD +:10A1B000D77701AEB1DED373C24C758FBB8CAE14B2 +:10A1C0001CDFF0E15739A8B72A1069F0BFAF3A5643 +:10A1D000DE8C7803BE2F0E47F9DACE488F69F299EC +:10A1E0008DF209CF6723DFE7633F93F4F056532FD7 +:10A1F0003FF7B98B9FFB04BE273900BEB7A39F90E2 +:10A200006D0739A0E7C7927C6FED35D0F9540FE8A0 +:10A21000F15BA85F5C85FDADBDA576926FCCC3E711 +:10A22000A29CFAF6D23C2D108320E924E60AF61F00 +:10A23000DB1323898F35FD783091EBFF960C350ABF +:10A24000EBFFADB21C2217417690F7859DECDD50F7 +:10A25000FCEC0BD3D0DE09BB20FC27769CEBF94746 +:10A2600085AD5AF34EE1EC2DB0CE3587E5817A6E9F +:10A27000F4577D824FF60AFF15ED849AC7EB67F01D +:10A28000FAC40DBCCEB5C0B9BA04CB38265734EFEA +:10A29000C3B6D0D55282678EA72DECDDC7CF1EF393 +:10A2A000F3E3AD7BEFC8C27DEAFE136686FB24AD07 +:10A2B0007FF3FFE175C0C3773B01FF43D825580EFC +:10A2C000F11F58EA149634F87EBFA4E98FF9952857 +:10A2D0006F175BE5401FEC612D3038F67F9D54F51C +:10A2E000AC07004B1BE17C1D59A230D94D6DFF918D +:10A2F000BF25A02DD8758CFB4DAD266716F24FEB10 +:10A30000E8D0F3FA5AFB62123FE79C6F6643E625FA +:10A310000F09BB37C6C39E413EAA6D95ED5EA0FBFB +:10A320008556D96902FFE6ACD39D806765CE31CFF3 +:10A3300082A968E745DCA87D4F6519FA2760A71E4A +:10A340007C61501EDF807CF450BBC47E066B5EFED9 +:10A35000D2D0FB0A35629E87DB36EE4F013AAE78EB +:10A3600025745C8DA813ABD1F92F8792447C98C6D5 +:10A37000D2D02F01FE21BD605458B719F8F5C16441 +:10A380007707C61B9BC5770C407F921C7608BEDC06 +:10A390002AEA04FC5B25DAD7CB7CD52B1BE0F942FB +:10A3A000C52BA39D62D0E23EC164A7BB1CF10BEBA1 +:10A3B0003E86FB35CB851E5CAEF9655EBE9F01E631 +:10A3C00096FCB229CCDB1889EB7E5572F854FC8ED2 +:10A3D000C8A03A5C5A779D5877CD8623FB318C5BB9 +:10A3E000D5123AAE4EACBB4EB76E6D5FFBCF49BADD +:10A3F00073C837B86FF16723F7133E10F368F7CDD2 +:10A4000023B83EAC05F0906E355ED9EBE57E9D0D30 +:10A41000BFC373BF80F77E41EF3AE633A5C0B8559E +:10A420002FF075B26743EB3F1F6C7DC484F1959E9E +:10A430002F966F31923F0A8833A1BFA8E78B156230 +:10A44000DD2B74EBAE754B3AB8B89F3C18AE960551 +:10A4500048D7555B8C0CEB11F5702D6B59528E7CE7 +:10A4600036985F395D5688F90270AEA6737C370A5C +:10A47000E7A811822FC7B17144978AD81BA28BDE3F +:10A480008FDDBE7F9C15E5FB72F7688ADF35BAEB7E +:10A490009F2F177EF08C0D8CDA0B6D25D6F118A747 +:10A4A000F4181C924AF156E478C0475E87CC2AA182 +:10A4B000DFDF9EB6DE0378CF3D9C5F85F17CDE61F9 +:10A4C000039D77DBD99D4FFBC07907D263D3281F4B +:10A4D000EDA0EFCDC03C643FFB7B72D7E3B980FEBB +:10A4E0009ED27C9C57827168E773851D68E8C9B568 +:10A4F000069FEF2E18C1E3F5A7923EFB31FAE13338 +:10A50000B61BE97CC30CA3FF3DAC9FDAD9ADD0BE2E +:10A5100075CDE1A56BC390AEAF49B46FBDBF774DAC +:10A52000DC62E4AB76A31DF7A1FBDBFF6D2FDEF74A +:10A530006C91E87B12751D65595BA19FBB31CF11F2 +:10A540007CDE2B375A25F8D8082BC5C3336E3292E0 +:10A550005D3C9F6CFD25FA372B9C1B498ECFEFD9B4 +:10A5600069A2FAB9AD1243D3BF3F69DF1B888FF3ED +:10A570006F1E31A1935DD27AC4D4F777ECFD052F1D +:10A5800004FE1407379B304E59B551EBF799904EA6 +:10A590002EE1FFD4BE728AFA2BDA24D2332B5E92DC +:10A5A000E93CFBBE8EB74CC8C7B55B2496981A74BD +:10A5B0007F8314F21D84A58CF3C152A1675632EF3C +:10A5C00053C9306E6533AF23604F87D6E5AEDC32BA +:10A5D00087BEDBB4AC79687DF3B0E0EB87301EBC9E +:10A5E00015BF83143AEE61EDBB5C3A7E7E5CE3E717 +:10A5F0004C9689FCFC55911A950DD7BF3AB2E2E60C +:10A60000A1CEB1F7083BACD9C1CB3E03D911FDB8FF +:10A610008B6D5708DEBA9ECB26B483E5ED9708EF25 +:10A6200095ED5D54C7711773D7209EEE6AB7DA5166 +:10A630008E2BFBB85E9AD96EF67A25BCDFD284F4F5 +:10A64000ECEFE4758B9E3D12F92F9ABE7A48E0EF4D +:10A650002181BF874041A7E4A21FCBE3DE873336C9 +:10A66000EE8F81FBB5E27ACD817D91E8EFCD6497E5 +:10A67000EE457AC07B18BE87BD148AE73B1987E395 +:10A68000CE2DBCDE596FAFFA4764CDA6FC23C49D26 +:10A69000084FCD96503CD7EAE2ED7523B87DDEA495 +:10A6A000C373A59F59B3110E5576786974AF82EFC5 +:10A6B000EDCE9128BFDAADA6450DB5FFA8B5EF09DF +:10A6C000BF59EBCF16E7AB5BECCDB6E038D894CCF6 +:10A6D000EDFF8A29B207E934103FA4EFCB510D8179 +:10A6E000F801E286DF8C88E771041674BC3B526681 +:10A6F000717181F8E18749EB2B73A15FB785CBF9C5 +:10A70000C5C9301F7EDF4B61E45FD66D31D339C0E0 +:10A710003AA03BC509EDFC1C83AB5D2A437A83FF5D +:10A72000FDEE888978AE8619E360DD73DA389FCF55 +:10A7300029BD447C72209DAFF7B2A2260EE58F6B37 +:10A740007E389EC35283CF3F805CE2F8DA765E0F9C +:10A75000D4BAF7EB51A9A8D73AFE3A6A09B45746DA +:10A76000F0F56B7E9E1FFCBCD1DCCF3986FEE78303 +:10A770009ADCD8F93EDA83C2CE30A989F8BBD6D8A4 +:10A78000F2760CFA4D5BF9BE3DDB6DC46F9CB18671 +:10A790000F5E6F8A81755F7C5DA27A347CFE09E072 +:10A7A000B38B4B5B4EA31FFDD5560BF98F0F828FDA +:10A7B000383D77B03C6A72AB7D77AA81AD257F7258 +:10A7C0002D6BA27695E0E38B6D8D26CA9B79839ED7 +:10A7D0001F3DD8EF58A5E33B537228BF357C104E80 +:10A7E000FE5FFF01D98EFB2780A7FF4E0EC687F0C4 +:10A7F0002F5AF786113DFB8FD8C85EFC49F0D979F6 +:10A8000091376E982CD3FA0D53789BD5F9D668A45E +:10A810001FE21BEBDE3777BE358E9FA7F612DE57A1 +:10A82000BE8A49F120385BAC94DBD3FA0D1F2CA211 +:10A83000EFF0D4ED19806B8C292E00D770FC2F49D6 +:10A840003C1E3448A1F160DD6ED9155CEF05EBB913 +:10A850000FF54F929003A6F813D02F1999AC92FDE3 +:10A860006A68E7F43474F016DEBF80E73B8CF4FED0 +:10A8700041F78B3D3578FFAB542BDF4FBEEAA9C4BF +:10A88000FE7747CB544FF9DD0F568C0DD69B0CE16C +:10A89000047AD619FD0914371E31107C75472E270E +:10A8A000A4DB501F6D2CB567A3DEE1FA6EFF68EBE9 +:10A8B00072E4630FBE373130CF6BC2DE325C6F1291 +:10A8C0007A152FF079C57AD7B2B9223EE67C942D5D +:10A8D000FC3D882B26264F1C1C57DCA83F09F6E0C0 +:10A8E000E86209EB89140FC6B53B8F737DD0D0F1B8 +:10A8F000D0A7C8E7759F98A9BEEABB9D0F8DA53A62 +:10A900005BB7FB56F42BBEEA7CF856CAF3496B09D9 +:10A910002E0FC29784FECB8709580FBAAAE3C3044F +:10A92000B2AFBB26AEF744A09F927B275E07BF81E4 +:10A93000F80FFC17E2BF9D3DF99ABF62C579571D1C +:10A94000505C889F5507F20F55A21F71B8381FD56C +:10A95000B874389FFC953CF4576C01FF455B4F651C +:10A9600032AF77E9EF0AA33C81C44673FE61E92167 +:10A97000FC53D3FA0ED9F59A3639A46E507BCE9D8E +:10A98000ACF07D7E8D7F5A2427F1C776DED6B4EDFC +:10A99000A4F5AD34B610BD1BB618F9FDADBCD5EAB3 +:10A9A000AA3D2CC683F8388497800E334D5EFA6E2C +:10A9B000C5C154EEBFEBE9F15932CF631C3CE1BE97 +:10A9C00019F9E560917BAC7D08FBE061C53C3E95E3 +:10A9D00004BE5BF97925FDB853C93C8E8F8C0D3DC3 +:10A9E0003F3A605F9239FFCC340DFD3DBD9F69F267 +:10A9F000C4D83306E08BA39546FB3AE1B78F08FA3B +:10AA00005E42D55D46F20F8E32FB3B5867384BD322 +:10AA1000AF93B95DD5F2DDAE0D2ADFD7197CAE91CB +:10AA2000F4E47C6D3EFD7969E1D7CCD7F935EB359F +:10AA3000FD37868D41FDD722CEB9ADC90CF306E7AF +:10AA4000A3F4ED7EB18F81E775B06DC8FC98F23646 +:10AA500007BB4EBC41756627C2D8689E97A3FCF51C +:10AA6000AA61F2D70D03F2382F84BF347A5C10DF6D +:10AA700055D1D3E30D81776D9F2D5CECB39D56DCF2 +:10AA80006F24535DD67913FF8E9A9FE2AB864CEE0E +:10AA90001F5D2893685F1CE01C650ED2EB1746F023 +:10AAA000B8EABB0B24CA9B76E1788C9F5A24AAABE8 +:10AAB0005EE5EB35211F8D695DF224C9AB871D630F +:10AAC00041DFA9986DE17671806EDABA07EC568C99 +:10AAD00087EBE1386A713CDAC159C2EEE9CF218DCA +:10AAE00065BDE51857563B2507EEDBEBE93D77E101 +:10AAF0008477E2FF013A9F4B761F21FDD67B7901D7 +:10AB0000E63F0F667E3E0AED65ED307CFB3BC1B74C +:10AB1000DAF7591C63D546FC3EC98F12DD9F207EB3 +:10AB2000FB0DDF468E63F87CDF7FAF91902E8CE8C3 +:10AB3000319C9C9C12F39D4A16DF258CE3FB24CBB1 +:10AB4000B18FF26AF48EA4FC42F68DED4B35EC7EAB +:10AB50003707F5D6C5AE0339A6203A9E5F03F28EBD +:10AB6000F6A3635F826A0BE63303F1972469FCA6C0 +:10AB700008BB18CA77E791EFB2B1FD30321DF5EE90 +:10AB8000F6A391B7E07CBB783BC09FED328D837814 +:10AB900067CCFC8860F89E24F82EB4F07918EB1B83 +:10ABA00053353EF87EE3707C6B4CE1F584217CAB41 +:10ABB000ADB705BF8783FE7DA799BE8783F9E6E819 +:10ABC00020B9484DE1F230497CFF660AF3D0F70026 +:10ABD0002789EFE04C51984F89C17D2E9FCCF765B6 +:10ABE000F9798602C1BF93145F17D6394C11FB3235 +:10ABF00085AC97C64D677E6A9DCC4EE7148A9983D3 +:10AC0000DAC916DF9D9876C96E69A1FA3F5F821294 +:10AC10007DD622CE430C41B7C0FA15FAEE0DF1A550 +:10AC20008CE76186FE6E4A650A9773FA3807D2F799 +:10AC300002A3FC147EDF0C5F325561155877749BBC +:10AC4000C22CE100EFF6B70D24BF9D7DAA17EB40A3 +:10AC50001DB1E2B92F18D5BB4E7272F944D382757B +:10AC600012DA7AF5782884F9303F364981C892F0B3 +:10AC7000E8A3F7DDCEF8398D22A6D207566EC78F2E +:10AC800027935EF7539C54027112EA7583C543F80B +:10AC900028C3E4CA44BEBF1109F314364BEC38EEA6 +:10ACA00057A4F1F56AF3170223E0B9BD32B15E4C47 +:10ACB000811E8FE1FB1E9154385C6AE7DF094AA0D0 +:10ACC000EF04DD285EFB13F8772123EFF75FFC7EAE +:10ACD0007E60FFC781DF0D8A0C7C8FD281E74C300C +:10ACE0007FE753CE07FBCD77A72CAD4E9918A897D9 +:10ACF000636EA6A25FA1AF9743F49D0B3ADFACD57C +:10AD00007BBCEA9DABE2B9B98571163A4F9B6B19D2 +:10AD10009587762B23D15D9D42751F5B6EA14914EB +:10AD2000EF44574480CFADCC3919F11CA8D7E3DFED +:10AD30004F1A38CF94C0E8FC9FD5CCEB199F01B9CE +:10AD4000C0EF178154A958D7C29E28A1FAC7A7A25D +:10AD50002D0E3C87604678AD01781B2DA2EE47573B +:10AD600077D96833D0F7381B59389DE79E15E6FE32 +:10AD70001EAEFFB188623A2F9DB56D5A12F983B0AD +:10AD8000DE69DA7A0D83EB10B1FE0F9FD3D7FF692E +:10AD9000EBC2E3EBF85EBBC097B64EBB76DEC7A94D +:10ADA000849CF7D1D6FF4C385FA71177E2D3E859DE +:10ADB00015F5837E7D1A3FFC3FDDFB356D605C0041 +:10ADC00000000000000000001F8B080000000000D1 +:10ADD000000B7B2ACBC0F0A31E818565181826F1D5 +:10ADE000A18AD112CFE066607804C42C3C0C0C859B +:10ADF000407B23807424101F01E2A340ACC2CBC06F +:10AE0000100BC471403C07C89F0BC4A5409C05753E +:10AE1000632B0B03433B107702713710EB30333059 +:10AE2000E832136F7FBE0803C31309045F51126831 +:10AE3000A734FDFC3FD8F00A7DFADA276DC0C0B018 +:10AE4000D502C15703B2B759A0AAD96E81DF8C1DB4 +:10AE500068F23BD1F8BBF0E83FAB87CAB7D540E515 +:10AE60004B693130782285899D067EB7A0E30AA020 +:10AE7000DE4A200600FB72DB43680300000000008E +:10AE800000000000000000001F8B08000000000010 +:10AE9000000BE57D0B7854D5B5F03E731EF3C8CC9E +:10AEA0006412420818C2092FA30D382121058AED2A +:10AEB000400091A206B50A1575C22309794DC0C795 +:10AEC0008FB56D0682111034582C51A39D2028781F +:10AED000830E3448908003581A7A5183D7FA687BDE +:10AEE000BD4129200412F185DEB6FE7BADBD4FE6E3 +:10AEF0009C9319E0DEDBFFBFFDEF1FBFF6B0CFD99B +:10AF00008FB5D76BAFB5F6DA7B648B8B484308F906 +:10AF100016FE7E40C8748910D23FFA74BE4E549219 +:10AF200048485D0E2DA710923E9C848840C8E46A74 +:10AF30005ACE23E4D13B49C89A49C8FE2316FCBE29 +:10AF4000CACFCAB45DD8720DFD3E82BD7F328BB6CA +:10AF5000A3EF9FBC2062BBE04C12DA4CCB4984F6D5 +:10AF6000368CD021FCF89CECADB78FA2F51BEFB46A +:10AF700010AB4AC8137418329E1017F1D9096DBA74 +:10AF80006A38EBEFF19996E745013E46D2E6D3F2F7 +:10AF9000EA29C5F9AB69698DCCE06A9853FC7C90CD +:10AFA000F6EFB10CC379D07A4F3A69BDC7DE2F21D5 +:10AFB000AB69BB0D732D427136ADD7A4CC0E65477E +:10AFC000E7AF3DE71289B70B5A2DE3E0E9E3CF88FD +:10AFD00002CF5F4CB4E0386BAB193E683DC592467A +:10AFE000484BC7019B9FF6B7B6A2E5E834FAFD913E +:10AFF000E1162FC52079A4E380FD4A3A7E30CFE2E6 +:10B000001D416BA74B11C1E38C8E379E50C0C7D238 +:10B010007ADE1D36D5D9B73EED7712CC7B0DC5BB98 +:10B0200098196D3706E0A4EDD6529285E9B8BF9421 +:10B03000BD8761DC5FDE902C0449B4DEF50024D4CA +:10B040009B6B21115A8F483D3642C7593DF16DDB4C +:10B05000085A7F75A1052641D67AB5EF5E3B81FE81 +:10B06000A68E3C3C1CE87A3DFD0EF3C87E7C36CCB7 +:10B07000FBB1290A01FCFF52A0F5288A1B8A941F04 +:10B08000027CAE6AE281F7F4E98B85D756C18670FF +:10B0900090351B08C9270002FEADF685560E05FE49 +:10B0A000CA235E28A77B697B67DFF69D8215E9D2FC +:10B0B00020070702FEE2D16F38C7E7EAAC2576A089 +:10B0C0000721F56985A308590F78824125BF3ACB3E +:10B0D00015ADBF5260F85927139F40E79790A7849A +:10B0E00096513C5BB23D7360BE4EBF42AEA3E55588 +:10B0F0004270A0087419A590CD2AF2857D042DAF69 +:10B10000BD2AD90BFC572784D324F87E03FD4EBB00 +:10B110003C5038660EF067A357417EA6FC7318F0CA +:10B12000BDD69F4C56ABF8BD03DB3B877BAC880993 +:10B130000A0FC54B3FCA4B80D79C9BEAAE1F06F453 +:10B14000196BF10085560B93D4F9203F49360F8CCB +:10B150002F8FBD19E927F74F16888EDE3F077A53E8 +:10B160003C3DAA16FE1C9E4FE77D943482D65F9329 +:10B17000F34A03D0E999FB6D48BF67C6762C06B940 +:10B180007AF242EEFB7E944BC5BB99F6F36CCE8906 +:10B190004C42077C7CFA474980BFC1C3EBEF216E6C +:10B1A000FA9CD953434653F8487DE1824CE413E1BD +:10B1B000168AD7C14B15A2DA182DBF25F09DF8C20B +:10B1C000D9ACECA4F319CCE9DCD2F1B6AD08FA9B0A +:10B1D0004B2223DDF8DE969A1CD53383F348249561 +:10B1E000F6FFE4C24328E7CF5C9DEA65729E86FCC9 +:10B1F00092C1FB4987FA54BFA4D94830813E07B7B2 +:10B20000F7DC0C700DCE3A3117E0DCFFC62101E807 +:10B21000F6ECE85415F45192BF837452BA0FCE7E07 +:10B22000F741A8E77286D20AB3B1FE5FB19D09FE6D +:10B2300066D5B709F0B64DA83E0CF409E658BC8CAB +:10B24000DE4C0FAEB93735047A64B0E34FB3C4A116 +:10B25000C80784A452F83C04E5A44E88D88641BBB4 +:10B260000758BB212424009E076705178B6EA8EFA3 +:10B27000170A5D7DC76D018D08F241391DF875BB58 +:10B2800042CA0A63C8C16B5C9EEB04321BF9994841 +:10B290007F03BE1992C4F8462B3F0BF0D071B7BFA5 +:10B2A0009EFCC36C0ACFAF960ECD11293C8F42BBDA +:10B2B0001872B396CB81A39D04058AD7FDBFFB9D71 +:10B2C0001DF0B6DD424AA1FEA4ACB0AD93D315E8A3 +:10B2D000B190B0FE1BB337DA505F0859C8770BC77F +:10B2E000293EFB6890BFE5829FB64FF330BDECF27C +:10B2F0002A21D0CBAEB4A060A1F0A8D9C4B33193B9 +:10B300007517A4F89B07FF00469758FD356B9342CD +:10B31000ABE9F779D954D0006F1457163AEE02C250 +:10B32000E639CF5BB718E84748A105F0B9DAC3E8BA +:10B33000D308E3D0A934A6B37ED6DE4742CB818FB3 +:10B340003CACFD706842E9363CEF95FF25D07ED3DA +:10B35000793B907B68979016B259683BB5DA4210FA +:10B360003E29725800BA8F4A55019EC634EFBFCCB1 +:10B3700004F8674BDE8DF4F3708083F6D3586DF1DB +:10B38000A1BEC8539A404FAFF6313DAFE12B938F2A +:10B390009BEE8D0874EE2493EA49C4932F62F74024 +:10B3A000399BC19399C7E6D50BFF2825B49C364E2F +:10B3B000B74508D4D3F050CCFB2BE6F370A68556E6 +:10B3C0004A00771E839BAECB084F7AB6D2047290A8 +:10B3D0009EC6FA53297E34BC035C0E0DAE3C5A1F48 +:10B3E000F4B0576902567070F88AB3193CFB8FBCF1 +:10B3F000DD2EB0FE50AE1C1C5E079F3F017853B996 +:10B400005EA7FD35CB1141A4F5436389BA918DA6A2 +:10B410004AF9D1EF8F57533CD082938F43D65B517B +:10B420001EE8ABE0B7940FE6D7D37256543E46AC55 +:10B43000B41AE4C5C9E74DEA991C51B68940BB4C22 +:10B44000C2CA1628D379146719E58C7875650A87FE +:10B450000BF89DEA9F65E315C63F57313B86105DAB +:10B460003DE0F3B1EA736BF0BB82EB7AC64F150394 +:10B470007C83AB53278BA04FDA9FBAD9027C752F00 +:10B48000B18889C8CF42AFFEA2E3ED5812B1C32400 +:10B490001DED85C980B78CEAE4C90AE0B1DD8F658E +:10B4A000477BB50F9FB0348D216410D18D9309FA7D +:10B4B000D553DE4CF14AAA9530E8EBB17A38E9F77A +:10B4C0008CD7EB6701BD1E5E7C6820C86FAAA9FD02 +:10B4D00068CB5094D3C1AFD35A38FE899F41FD55F4 +:10B4E0005C9F3800E231F87C1D9E839D54CF523D15 +:10B4F0009D4111AC8C89EA8BD557BD9BE37772FED9 +:10B5000049C667049E66BDA2AB7F15AF1F142E5AB5 +:10B51000EF04D6D3E0317F3F2758504FB9C0CEA4B7 +:10B52000F87D8C78E6E0BAECB5E0BA98C0DF87BD6C +:10B530000726233DC3C42B6482BEFD9B55CF073F26 +:10B540008197A06FA530CA8992E140FB90CA710231 +:10B55000AC7B8D527529BC0FA73B08E88503530FC0 +:10B560000980CFF456FF109043CDCE9DEC0DA7C1BE +:10B57000FB470EFBAF44F98C63376A76A2793E57DE +:10B580005CBB1CF5C1107F4F3BACF7CE0AC97B1DDD +:10B59000F0979FC2E5443DA992EF52F8BDC165A066 +:10B5A00067553F2D0FA0CF0AFE2C65DF57D594E6D7 +:10B5B0001E97A2FDAE1A4EED51AA17D777ACB7DD94 +:10B5C000007646B54505BE5DEB7DDBE673427972DC +:10B5D0003FC0734BA166F74504182FFD1D1FDA7994 +:10B5E000633D8A0794D6286B64A047B75E344E7DCE +:10B5F000770CC0416EA5441C189F8E74BEC867F1BD +:10B60000D61380C5A25B47F667EDC0F5E50D721550 +:10B61000D2455B57B475047BA4FA653E97A347D423 +:10B62000B04D407D456597D2673ED7234EAE37A9D2 +:10B630001E667A8EAF276B17A7E27AA2E94FB0ADEC +:10B640004149CCE7FA766DCEF3493750989CA06714 +:10B65000412FA591C9B0FE8E003D03FA490A0A3078 +:10B660005EE3580F598DEB98519F8EA8667AF09142 +:10B670003482FC44D7A12658EF1AD3C369D04F6354 +:10B68000F501C1AF5B3FB5F5CE55DD41400FCECBE7 +:10B6900063EBDCBC6C36DE1F00416319BCA057CDE8 +:10B6A000EBDE2F26EE406599C0ED2D33FE050BB382 +:10B6B000031F9BF936E271ED82C7F149EA37607FDB +:10B6C00069364683555907F0FD1ABF653AD8DDEB58 +:10B6D000A58E95C329FCEBA7CF5382F4FB1A2FF359 +:10B6E000BB564F9CF73CAC6B568BC2E0AA2E457BF9 +:10B6F0003581C3B501FA463F5141BFE8BE3B37AE85 +:10B700001C4AFB49A37E8CA042A590CD4ABF3B8139 +:10B71000A6A0BFFD1106BF974C2631E0FF57C1C15F +:10B72000FC507F47FB08A4A7C503F026787B6CE09C +:10B7300027AAD40F53558057B58F42782D9E656A3E +:10B74000B4FDEFB9BF70172CFC60DFCF79773AC832 +:10B75000D7BA3B995F6686FFBE49A1760B8E43D070 +:10B76000AD73C5C1EB5CD060A07FBC2184CB95C517 +:10B77000E03A2E307A3DD631F97AF4930AE97BDA51 +:10B78000D1E31D43ED20DF667BEF99840F73D0DE9C +:10B7900031AD33972A0F36E9FB51D6F00CE4B76D83 +:10B7A00016D45384303D27108BFAED305844185C82 +:10B7B000C87A547FAF90237316D0FA2B763A09E0FB +:10B7C0004BE38774DEE7EA6ACA0731E6DD2E88F1CB +:10B7D000E8CEEC0C4EF70E18AFFFA5E94FA5D90E39 +:10B7E000765B385437A80CFC8F6AE6EF8623075047 +:10B7F000FFA44FB90DFD942D4DA97316005F65F997 +:10B80000BC800E0D1EB04F62F989332CB68BFAEF57 +:10B81000F1F47043C50AF47B1B3A62CF7FA285F92D +:10B82000DB61AA27BDD9F1C7CFB7303B3AC9C2F90E +:10B830006EEAA134FD7AA6ADABDA3A3B582241510B +:10B84000B71EDECAF1675E3789546F1BC9F81CFD4D +:10B85000C786052C0EB161A205E32B1A9FD37A6926 +:10B8600080573A0FB4E7281F86C09E7B8CD4A3DC98 +:10B870000469FBCDA42FDC7712CB65CD6F029F5FEF +:10B88000EF78DCBFBE8BEBAB7539F7DBA12B3A5EF3 +:10B890001AF047C0CDF464A58BD9B1053BE5C80FBC +:10B8A000281C954D02DA59967D7684F3DC265AA63B +:10B8B0005D475C0AD63FEBB1613960ED78F47BB44B +:10B8C000DCB35324684766392CC0AF2738BF923C9D +:10B8D0005A067BD8CE8A954DFBEF82FE4A5BADC4FB +:10B8E0004EFBAFDC5D72E3F768B9A45D2650A5722C +:10B8F000F33265102D2F0A096128774FA60B15E04A +:10B9000025590981DFDEEDEE48FD119DF7E91A1B8F +:10B91000512928B5AE8ED45B293ECA42DBA741BB74 +:10B92000B2660134229DC7E64303615E5B052FF8D2 +:10B93000F7E55B120CF6E0093A951FD0EF4BE83CB7 +:10B94000412E4B48FD3458E72A37AF53545DFCE194 +:10B95000748D07C7D1CA955BE938B45DD54B8217A2 +:10B96000A65865217ED043E776DB673FE784F92D53 +:10B970005346BA605E0F2B50AF2454F48A5D05F82D +:10B980009A9469F47B59639302F1AD8095DC0D7E46 +:10B990006EF9967E46B81A4494D72549B68DA0CF45 +:10B9A00089D39776F3A8BE743E5D4375ECC868B939 +:10B9B0000CF421F2614899A5AB3F444C427E2DDF47 +:10B9C000221AED6CBEFE078F32FA07F7BA30EEA7E7 +:10B9D000D16F09F79735FA2D49E2F4947AF263C1F1 +:10B9E000F328D083C2530FF8A2CF351C3EF7443260 +:10B9F00009E22E6E1FF10831F8DAFCAC974911B05C +:10BA0000EE3F2D9F35491A88EEC362883C7956CCAB +:10BA1000993485967F6F29DC6C41FDE155418E3468 +:10BA20003FFB590B93CBBA810AE2AF7E6AFE732CBF +:10BA30003E4170DDAB9F5AFC3CD805B4FD360BCAC5 +:10BA4000216D3F2A7E7BCFB47186F69E69A55AFB95 +:10BA50009DD8DE76F1F6F5D32618C79F56A6B5DF3A +:10BA60008BF03B2F0EBFE7BA89C6F1AFABC0F60132 +:10BA70002BA3574F920DED9A1576AF4F6276540473 +:10BA8000DE4BC92337423D51E307D2E103FBDBD94B +:10BA90009C346635D1F3C5E437000E1795163D5F2B +:10BAA000248E7318F831C9976C28D39E3C27BEC3E7 +:10BAB000CB3088DB86F0288314D4179306D910DEA8 +:10BAC000FBF7D9B17CFF0406EFFD839C2867B8B66D +:10BAD000503ADEAFF8AFD1DBADB0324128E94DD1FD +:10BAE000FF11E037FA5EB5C07B8748AA513F5B097A +:10BAF000EAA38733F39F0BEAF0B37230A52F2D9F93 +:10BB000005FBA77F14AF0F0F2E4E2BD28D53375846 +:10BB100099BD319BBD9FEF84F10ABB010F01A56761 +:10BB200024D895E671AC43C719C6B16594E238DFF5 +:10BB300098C6B166949AC6B1CDDEC8DFF371FE0235 +:10BB4000F38A37CEC3432718E7935186E35845D38A +:10BB50007C32CA4CE338D87CE87B3E8E5DBCD87C16 +:10BB6000864D34CE6748058E93222A86B89575484F +:10BB700085691C278E03EF611C92CEFC1BC5DA532E +:10BB80008CF47FCD4EC09E56ACFE17A05FF2473BB3 +:10BB9000417DA2D27107805E49C6FD827FB524E354 +:10BBA0007CBE7450FA3BF5740E6A7601DA3B0B39B1 +:10BBB00088245487FE7915E7D105CDB33296C1B3F9 +:10BBC000B520AD08FCECF52E2FC44FCFB51628F3E9 +:10BBD00063D8050BEBE5139D06FEE57A6F32C9AA23 +:10BBE000063F8BDB015AF904D55F84EAAD8FA8FECE +:10BBF00082E74999EA69FAFE38D56F44D1C3BB0C94 +:10BC0000DB9D90181E4F34B275E4CB7547658CF3FD +:10BC100005C93B59741EB7F1692CAC4F60BE028751 +:10BC200023C0E9D1B3DB1ADA88F4F05D01760F693D +:10BC3000E84771C5EB0D057C517149C6E215601FDF +:10BC4000FD78E5F6DF40B57785A2C14BE87C67B7A4 +:10BC5000AC93AFA0E57372E75D5EA7AE9FD9F247E4 +:10BC6000306F1BFD0FFA99E3A765DDF877941ACBC7 +:10BC70007712295AA6749B2A0EE5F4E0E3AA21194B +:10BC8000E8755B2A83E74E788E81CF1EA4D75D1EB0 +:10BC9000D6568327F0A04C22B81E75F667C66D7F76 +:10BCA000ACE7D7D615137C77C9365F21A5E75D0FC2 +:10BCB00088884733BC9DFB127C16EA5775367C2674 +:10BCC000837F7929F8EF5E6AFC4E826C3C0DAF1AD7 +:10BCD0001FDC3E7B52BFE3BA7A73FCD7F73BAEE37F +:10BCE000973B4A6719CA7756CF31D4BF7B6991E138 +:10BCF0007B517091E1FBFC958B0DE585F50F18EA02 +:10BD000097342C337C5F145A65F85EBE659DA15C48 +:10BD1000197ED2503FD0DA64F86ED977D54D208F96 +:10BD2000B5BF1709D8675F384F3C0AF6D5174E09DB +:10BD3000FDAA2AE0352A87A76AD290BF4FD7A8F874 +:10BD40003CD79A8BFB6301079567BAD66FA83DBCB9 +:10BD50006CE544D023B43ED5E14FD7BEB52C487D29 +:10BD6000F78D10A4A67C2F362824D20FFC98E45E11 +:10BD7000BEEE1175DF3B2FF1BD812E58B97DBF8B13 +:10BD80009DB1DF770B3D23C1BE0B7E60C5FD9B7867 +:10BD9000F603FDBB82C4F01FB46717C437747AE79B +:10BDA0003591D9D5D788935F13E9B34261F25EB17B +:10BDB00063E064881754289191D531ECECDEF1C230 +:10BDC000149801D00F939745A12BA2F28BF41B6618 +:10BDD00090FB1B2CFE7DA09FBBF68B6C7F207230EE +:10BDE00003F669AE117DAFC17BD2DA1FD7C7776B7F +:10BDF0007CFD8E0F27E4FD9AE9F8FC434D613F88F6 +:10BE00001FFDA96636963FACF1E3B3B3A6149F1F9E +:10BE1000D554E3F7E3354BB17CA22688CF53352BBD +:10BE2000F179BAA61EBF77D53460F95C4D089F9AA8 +:10BE30001C68F62849E1F61FB7D7E9CA81E5F37C0B +:10BE40000E22FD7707CAB5370DE4FABCF3CB91603B +:10BE5000E79E7FDF8A41F4787832F35B7CFAF970F1 +:10BE6000BD2F0E51FAE7F6FD6E7730FAD82D643A01 +:10BE7000F867AB462804E2EA8ED7BE83F6327D2F00 +:10BE800011D49721AF7E1FB1B77F98F3804BD34970 +:10BE9000AB7FE2A97FCF9F970DF461F4751C14ABC3 +:10BEA00019DD9EF302DD74F86376D94EAECF4D787E +:10BEB00094B8DC99F179B6BF86CF8E0C88B7548AD6 +:10BEC000851689BE3BDF62C5799D6F4B60FBD89EAE +:10BED00094CB8AE7956FB17BF4FAA1329CE431EA06 +:10BEE0008B811EBDBE38DFFE9C1BE47E499AC57364 +:10BEF0003C17F8C3C7F983F19DD67F6538D3E33487 +:10BF0000F4632C9FAF17A6B37D4535F1D618FE819B +:10BF1000F65C92A6788E53BD707ACBB0441897FA2F +:10BF2000711E18A7ABC6E361E3A679F47C59B1D4BE +:10BF300081F535F8E2F5FBF7860F76FC3EB6B15891 +:10BF400013C469E2D58F4B0FE97305FC03D2267F3A +:10BF500009EB8E234B5B77242C6BFD06C262D07AF3 +:10BF60000DBC6F368C47DBA99A0F0DEDE2D35D2235 +:10BF700027347A523D791DCF0FA1CC8C74F6D31E95 +:10BF800013697FDD927325C479332515F55D0006AD +:10BF9000A2FC5469EB54FC2AA2BB03E39EE334B930 +:10BFA000576FFF2365B94FFE59C67806F90BED9D13 +:10BFB0007E97F9D705A4D00D4EC6BC96F299A0275E +:10BFC0003FB168F6407D3ECCFB2CB1E07EFE59F2DD +:10BFD000B63B576797954A3C3EB992ADCF41FA1FA1 +:10BFE000CC8FDA6986F5BAA4C1582E2637A7823CD1 +:10BFF00014AF9761C7962C82F55EB76F325BF2E0A3 +:10C00000BC4B48751DD829AB65B68F3ACF43A42BDE +:10C01000285C95BB9EC9077B3620317DAFF9CF8B5D +:10C020009219DC652921C547BF7FDC927BDBF708CD +:10C03000B40FD5815E0BBA8837563C66FE4A237C26 +:10C040009782DF0C2F21CB0D7068FD6A70885B84AE +:10C0500098791A3F93041ED761F2B15632DAAF8F46 +:10C06000733C68E50DA672A3A9BEC62732E7934CC0 +:10C07000C9FF38E89F4A5BCF34B4D308E58FEC683A +:10C080003D255A6FC3C5EA59A19E88F51AA5B1F19D +:10C09000EBD9A3FD35C5EAAF72D7B65782949FCAD4 +:10C0A0005E7EC20D41DF4FA4FA54887F556C7EC876 +:10C0B0000D783A2505DD40EF4F4262CCB8E07BBDFC +:10C0C000F8F23905F02390B529DE5F7CE446D0D73D +:10C0D0005F6E96312F26B0C51AB1523EAE6A593402 +:10C0E00013E2F7B47C8C951FFE14F60D03AD467A6F +:10C0F00096BDF0442AC489282699BD4D22687754FC +:10C100006DFAF334D0E301D2837C686E07E35F48B5 +:10C1100046B92F5212FB7ED7F215025CCE022D8F4C +:10C120007C0A79090113FF94F6AE279D0AC411DA3F +:10C1300025570AFAE5DF25DF053DA0E18384983D18 +:10C1400051BB75C3E863149EAE4DFFEC160C7E37F1 +:10C15000E3C3F3E1F9BF7A558DAF67CE717F28DA7B +:10C160002E84EDD45666FF9036F6AC90236EB03731 +:10C170002B9A642FE55052B1EDB9E79F023FED03D2 +:10C180002BFA69E5DB7EF3EE045A2EDF2EA7CC6492 +:10C19000D3710AA951BA04E8FF968E89D2A1ECD7CF +:10C1A000BF51D451ECFD4F93A3F428DFBE5F21A310 +:10C1B000FAE2AF20BC5FE974C6A04BF8D834B057A0 +:10C1C0006AB77EA580DFF5C93E810CC8ECDBBEB442 +:10C1D000E937B81E029E908E9C4EBD74EB43AFC8EB +:10C1E0008DAFE6613D0FE8C978F47A91EBE5CA5D61 +:10C1F0002E9204F1CF3F584333818E2FDDE38679B1 +:10C200009C94AA195F3FF3502AECFF95CAC1540FC2 +:10C210003ED9FBD267EF437E2B11AA53D93EA66FBE +:10C22000208F970F84F92D6CFC11CEAF98F891EF09 +:10C230004A9F110B213EFC8544A66F8F211737C8FA +:10C240006CFFE9E4462B24F9919360E7837DFDB60A +:10C250008871564216E33ED87D5A1C972CC1F217BE +:10C260007C5F6AB86CD1FC439B815F373DDC01F495 +:10C27000393DD83700E0A47808727C09B0DF2F1E62 +:10C280009D3A80D187E51B603BAAFF0BE03DD4EFD0 +:10C2900090719F50D78EEB4B36FEBD7C7C0AB70366 +:10C2A000D6B393A96CBFD23CBFA57C7EF4AF83E824 +:10C2B000F84B27DF4CDE37AD62F2ADC97B68D67430 +:10C2C000F8FEF93B4C7EA01DAC1F14AEC800FCBEAE +:10C2D000FF5601F581954462C9F52699CBB5F17BEE +:10C2E00080CA29C40528DC12E43344F984F69F8C03 +:10C2F000F847BFA4783D6DA7B3CF02301ED653A236 +:10C30000EF75EB4709D703D365A3FC93C6FE97658A +:10C310002F56C82408A665C50756F4BB2BB6C98599 +:10C3200030EF33CD07DFFD31E5EB33614D4E8DFA54 +:10C33000D32CA7A53B360BC09F66393D534A57EB1C +:10C3400058724ADFC794D3D2CEFF2BFA53C35BC0D7 +:10C350008437AA07872459E2E3CFAC075DB21A53AA +:10C360000FD2BF77487E5FBED3F84DE3336AA10D8D +:10C3700001FDDDCB8F1ABFF5F2A3C66FE6791AF186 +:10C3800066FE3E010C350A57E16E19FD928A36B6FB +:10C390007F43DB1DBA220FF1E3C3E58BD41FBA2222 +:10C3A000455F0E99CA61537D9FA95C68AAEF3795D6 +:10C3B000AB0DF52B5A0F2A2CC92862A8675DFA1419 +:10C3C000F938867DAFAD3381964F9520F0437A8F53 +:10C3D000027A4E5E4E4D33889FED15D1DFEA567BD3 +:10C3E000DCC9F4FD4376E6C7767B783989957BFA1C +:10C3F0002B75A0E7B4F73D7616E7EC2EEC7127E934 +:10C40000FCFB636DA21BF6833B432C1FB52F3CB591 +:10C4100028379D24DE7716179C2A3A339682FF56DA +:10C420002F7AC1355CB0EC7637ECBB75B70DBB69C4 +:10C43000367DBFF0B008E633E976B847035C24E800 +:10C440009306E6F3FC09FA778A047F3911F226DABB +:10C45000987DBD608DC91E76DEAB607ED97A5D5C4D +:10C460004BC7FF65BC9FD246E3F732B206F9AFCCAB +:10C47000240F7EEE0F1CD5E42187E4B0FD6DC2FCD5 +:10C4800058AE77A78AD937CDA678EF6E17316FF6F9 +:10C490007C9B48EA609ECD02EE7392607F94AB2A4B +:10C4A000D283FA4EC34B17C88D125F1F75EDFCD7B0 +:10C4B000FC07813F5EF9E3E8A7E9B3EB950F46EE91 +:10C4C00081F2AEF732FE48FAD62FD8F735EE237652 +:10C4D000EFB3629CAB7BDF6F331E84F2AB568C7381 +:10C4E000752FB7E23E4A709F2B3402BE0F66FE40A6 +:10C4F000EDDEAF46B33CC91548A7BFC8CC1F39DF36 +:10C50000F6EF1F42FEC8F9363A2BB00BF625A0DC39 +:10C51000045EB5A3FFDDBDF7AB7CBFF3EF379F2A09 +:10C5200085F891FF5C64F60EE0D724160F0EEC1927 +:10C53000FF1CE43757B6EC5720CE5EF0DA5F478336 +:10C540009EECDEC1EC9D7372E7B3B01F66553E5D95 +:10C550002E533C9F03E11944C873CA988260762C1D +:10C56000BC303C74533CC0BC285E4A41BFC7C34783 +:10C5700086F28F8A8F4FEF627AECBB98671FC58B6C +:10C58000E063EF5D219B80F367EFF77D351AF4CC14 +:10C5900099F032B4472E35EF6B15B6CFF23F67DE18 +:10C5A00042E472E63DF71F96DE8CFF3F82F5B57FD1 +:10C5B0005F39E8CBE7BBEEC7F24B2E2FC27B99F277 +:10C5C000FFD3FF6974DF41E9EEBE34DD9FFE879D36 +:10C5D000F7A5E87E98D3DDE581FDE5EEBD7FC5B822 +:10C5E000A936FF4BCDFBD5FF47E7ADD9EB332CD5B3 +:10C5F0004766D1FA4748647D2185F3F5F4A9EFCC6D +:10C60000A25F7F1BC71E39ADB0F8C76F09CB130CF3 +:10C61000A6092CCF83FB450584ADEB05592568673A +:10C6200014643D82F60191AA8FE4507CCCC858E88E +:10C6300065F96063F01CCA7503AFF5623CD0E41F76 +:10C64000165C7D7D3BF829079751F8E83807078B82 +:10C650001E6A299129E972C43A1A9FC7E079C83D38 +:10C660001DEB4D711AFDA399E0DFE8FCBDEB55E32E +:10C67000F769BCFFE9E4400AE4934CF7CA2404F5E7 +:10C6800048FD0AFD3EF234533F87C0AFD5C5CBFE0F +:10C69000A3F84BB7323FF2B764C9911CC05FBA8CA4 +:10C6A000F1C04BE28FB0FCAFEB06E6E079142279E3 +:10C6B000117F330655727C32BF59E2ED25675D0765 +:10C6C000C8AD44A8DFCBEC32F49735BFF7527826DB +:10C6D000DC9F96F8D01ADEA57419F35675FD225E1C +:10C6E000347AFC47E9A0D1EF3F4B8F73267AA47FC1 +:10C6F000EE91403E0BB8FD3FE5F30E11CBE95E092C +:10C70000F7A3B8FD3FC9992481FD7FAD745404B9E6 +:10C710002CB1B5CE8038BDCD2B205F5FD96541FFF0 +:10C72000C6962720DEB31A242C1FB578C682A17DB9 +:10C73000E3F7769D7980407CD8A7A0E14D0A597C2B +:10C74000FE2FDF7E3B513BAF81DF09B981FA5F0BE2 +:10C750001A49C441E7B75022C1C46488EF0AE423F0 +:10C76000437CD75886BFEFA746FBB954FD787AE4DF +:10C77000EFFDDC45F5D647942976C313F755282BF2 +:10C78000E8FCE3EFB6317C058E90D050D40B3EB17F +:10C7900050B76FF68895E98F5D7FDA910B71B149DB +:10C7A000DDD9894C9F0E47BF20C0FD82F3444D84E4 +:10C7B000FC83F36DC312715FB05D74F963C465B639 +:10C7C00072FFF99F209F823EBB37917A3887D14D07 +:10C7D0007A301E1BDC648BB9BF7BBF558B3771BAB7 +:10C7E000D13F513B6FA462BE4830514FB7AE999FC5 +:10C7F00048A3FBD201FE3ED2ED97FC57F10BFE3A67 +:10C80000E077ABBD735AACF3602B39FE6E3CF0356C +:10C81000C631AF6E6BB200FF5EBDC962D86F0C5AF5 +:10C82000B9DF35868C01B86E3C6077E5015DDA458D +:10C830002FE40F06DA3E55FC31F6ADCCF884FE212C +:10C840002EBECFCAE2FC7BE4F07CC0EB9EB336CCBC +:10C85000CFD9ADD497C782F34A3BD3730B49F89E27 +:10C86000D199FF78F89DD4ED8C4C063F7313E1719C +:10C870000C33FF11E4E3F35B089E0F05BF14F4C211 +:10C88000F966760E98A2642DF8D354DE7FA08FCB84 +:10C890005CD9BAFD9FC00EA86A133C903A5B25751F +:10C8A0002A106F0DB42689B0EEE6A85A5EA567D4AB +:10C8B000AD3AB9D86765F9C60727ECB903C6FDAC30 +:10C8C0004B21608FF85EEF71C3BAFD595B6E62ACAD +:10C8D000BC79EDF9EB1A32638A04FD10C4BB991FD1 +:10C8E000B29B1D86F2F744FF2090AF1BAD9DF77AF7 +:10C8F00063D0CF6F637C76D9FA2DF4FF997E7B47A6 +:10C90000D36F7EB150274759B63EFA6D402CFDB625 +:10C9100044500700DE97EC1D3600E8BAE4B0DC3F77 +:10C92000967EDB56C3F6F35EE6F9B0DD2D54BF5DAF +:10C93000A3D36F2D36CC8B33B74BB659F8BA7809E1 +:10C94000FD16FAEF91BF6DA0DF62CC77848DE90D03 +:10C950004DBF8D6E3B86FA6D748BC590379A6EBB5A +:10C96000947E13FADF0AF670BBEC4D88C13FDBB84A +:10C97000FDFD32CFC3837140CFDD6163FB9B97AB7D +:10C98000E7B2ED8CDE97D473FF4D78D6F4DC929D40 +:10C99000DA3947331F323DB76437D57302F023D3FA +:10C9A000734BF6B27B1CCCFA2DAB8F7E2358BF2A7B +:10C9B000C2DA075A3337CCA5FD8DF1C95E1BAD3FF6 +:10C9C00026AAEFC6EAF5DD1D3676EF421F7DD77E3B +:10C9D00079FA6E27D777548F0D05FD6AE60F6F9BA6 +:10C9E00031EF78CFF893CDBF06797943C47DC3A3E7 +:10C9F000FC5CDA9BE34FE6017F35DB98FEADE5FC9E +:10CA000077AE2688FD17BCCEE657E964F9C8552DE8 +:10CA1000CC3EAC6A16422AFDE7B4095F2B00FFA2A8 +:10CA2000BD021940CBB3ACAC3E7941DBF722337386 +:10CA300074FCB0605C39C6ED1748C40671F972E742 +:10CA4000B44F201E5F3E8EC5F1CBF9FB45873BEB13 +:10CA5000209EBDE84901F73D09CF07D0F21B4BDA14 +:10CA60009661BCD69C17A0E9F34521E3FB72533EC7 +:10CA700063139FE72CB113F142DE1263E62534996C +:10CA8000F1D1CEF1B149C475B3171F143F6A665F87 +:10CA90007C508ACECC498DCE7FD11B745E79D17902 +:10CAA00069F830CF4F8B3B97F376F1E6ABE1AFCF30 +:10CAB0007C357C9AE6FD1CE80D5008392417F2629B +:10CAC000281FA0DE08FE4EC4F3FB8593460CD0EB76 +:10CAD000E1AD5C9FE7D64F2A1848005FA41AF8A67C +:10CAE000B861F1A18174DE63DF57C7C0F2F8BD09F8 +:10CAF000563FEC8F6EB5F7A05ED3F8EA1BCE57EF2A +:10CB0000723CEE19548DE75403AD8207EC8A40C4A1 +:10CB10008EF80B50FCC1F995003FBF18A0FC05F240 +:10CB200074F0C92F19BEF60A2AC4C7A769EB0FE033 +:10CB30009FD6CF6D63F80F8404C47F1EE9C1FD91B9 +:10CB4000AA06C11BA1F5AB5A1763DE83A66FE99F46 +:10CB5000534F0F1D3F4AB1F8112BE9D6BF725EEF5C +:10CB6000466BFDBBC09F37BE2093261D7F66D1FF5D +:10CB7000BE8D41270D9F97E2CB0B1C4FDB008F4EE4 +:10CB8000C0570FB39F225FE3391AED7B400A1AF0BA +:10CB900058F0D4858BE269AC8627E053D0536D45BD +:10CBA00022948B5B05D22FB3EF3C617F522FB78B62 +:10CBB000F61E63FD3F23E0BD2566BED5E6DD876F2B +:10CBC000E3F02B9C4B03BFE872F9F61B13DFBE6941 +:10CBD000EF39920B7CBB5760F183B624C3FEE22091 +:10CBE0003B5BFFB7DA297FC3BED661D9BB51ED2BC2 +:10CBF000DF097CFD02BB5F7F2EE92A9808E43D6EC9 +:10CC0000B1611E19C23194D9957ABDBACD4EFADF01 +:10CC10009A17BFFF81BCFF78768D561E05E341BE93 +:10CC2000572B1D2F2B3A9E59AF6B7EFEA5E635F292 +:10CC3000BF38AFDE3C4CD281FB4E9992FF31AB2E18 +:10CC40000FEE369E67442140FB4A572FDB76917AE0 +:10CC500024CD83E79FEEF1687CC6F2DD0B791EFBE5 +:10CC60005471E27BB07E7EE663FB7C7916F2FB8931 +:10CC7000A09F27CB788EEFB32332C66B3F9BC2F2C7 +:10CC8000386F7AE3A004F1999B4039517CDC34562B +:10CC9000407F058E61C1BED92E6ADFF846E27C7204 +:10CCA000E11C57CEA6FA02387F3C664BA8169EDEE2 +:10CCB000829E9437018F93440278ECF0F52B80FB31 +:10CCC00093EEF933C1FB43E83A8BEDC7B493FE50C2 +:10CCD0006F82AF3FBA03E35BD617407C74D641A79F +:10CCE00013EE67C96AB4509F218ABF0924540B719F +:10CCF0009BF1C77DB700BCA5D45E80B873695B5358 +:10CD0000AD1BCA8D8257A5FD0782FE696E3A8F6DF5 +:10CD10000D9F4EFB0EC823AD07DD041A59BDC0267A +:10CD2000B87808DEAFC33C9BE24D021EFCDA161257 +:10CD3000888DF51BB2D17EB735D2F679B04ED0F6DC +:10CD4000D0EFA64FDFB905E4FD88C8DA37B37DEA36 +:10CD500062DA4E05BEDDB418FB5BD4289034DA5F8E +:10CD600069335B074A8FC85EF8DEB2FF495CC7666D +:10CD7000D2F1066682DE8F4C8132C9153C18EFACC9 +:10CD8000188974EBE6724E268E60FA43E065EE3742 +:10CD90006876D3BB7696EF5BEC5DA6F4A3FDBC3959 +:10CDA000AE7F26A405045A3FC5FDE7E314CF7EDA23 +:10CDB000E5519EB77170DCC74AA76E1DFACCCEEE66 +:10CDC000B75AD03A09F319169242CC67B8713CB3FE +:10CDD000D7DEBAD61E822B0EDE927BD2E1FDC16B6E +:10CDE000AD68FF9EDB26231F9D1BDC89F1E9938D37 +:10CDF000329E1BAE6D64F7739D6C66EBB8F80CDB6E +:10CE0000D72F7129583ED878CB3458DF4E6E62E761 +:10CE10001D0B9E99AA40B9A449F0B2FB8B987ED411 +:10CE2000FCB7620FCB47D0F45F259F779FBC45933B +:10CE3000BEABD4D61B93BEAB847D65373C8DEF0370 +:10CE4000C4C9F420D8FD40F7C8D7C8BF554764020D +:10CE500076BFF071D734CCC7DA2B603C7F7C9BE087 +:10CE6000837DFDD2F7AD21B457434577FF04F4F835 +:10CE7000075622A890D74EF14EF5C3386BCF9F7E50 +:10CE800041DF7F72D4069930944F8A10CF5AFE67E3 +:10CE9000DE6696C79277747D2A9CB72453FAA1BEAA +:10CEA0002D6910895FA7373E117CB7FC98E965BCF6 +:10CEB0009F42A35F9E525F0CEBD83007D34BEA66CC +:10CEC000197244C8611E27A1F6349EBF5DB47B5D14 +:10CED000AA42EBD5F1FC8F457BD7A58AF47D2DAC1A +:10CEE0005FB4FE2285F5BF689FE069D2F5AFB5D784 +:10CEF000FAD3FA51761BFB19B697972FB31F0D0E75 +:10CF00006DFC78F6F8B87FB9B01EEE8B19F79688ED +:10CF100049C7E33E9E394CBFDFA13DB5F86BFE3BF0 +:10CF200016E2D3E16DDC9F1CC4A7E38B96B154BE1F +:10CF300029DD6E681542004ACBD8634A651E963DCE +:10CF400020CF553C4E5B3585ED5BB5E41C5D01F2B1 +:10CF50003D334F403E2041BFD22F05ED2015F6173F +:10CF60004AF258FB12DA1EE4AEE5492687541FA8A0 +:10CF7000A02FAA1AD74DC3FA9B0415FA6F692AC2CB +:10CF8000F5BE749C48F0FBA663687F94B61E4B0107 +:10CF900079A5F2B91ED6DFAA8956BCCF4B933B4D7B +:10CFA0008EDF92F97D4D36CF28C8EB7F10808A2125 +:10CFB000BFE211C2FCD46619E52C308EC9E55BDBFB +:10CFC0004494E783D7DE8E72786EB310478E0B14CD +:10CFD00038977C32C4BEF7CAF15681CB31D30F27C4 +:10CFE0009D4CAE0BE03BC8F14E81FB83CC1E34CB95 +:10CFF000B126979792DFF22D26798E23B71D52E73F +:10D00000AD30EE3DD7DA11EE82EFEF7EF71ED43F62 +:10D0100032E67D147CFF8154D077C512CB57D2F015 +:10D020005829B17CB63E70AC5FA60CBC2C788C70D5 +:10D030003C6D7745F587087CCEEEE10A6E9291CF84 +:10D04000CD72F85F959FBF973C1FE6FCA3C123EE0E +:10D0500065ED217F2C42F1F4DBE6E7304FF5EC8BF8 +:10D06000C76E043C97EFA17C4BE77BAED9C5EF7B45 +:10D0700009E13A53D622621E389122F9B7B8F47208 +:10D08000C9F290CA5F76217F94ED60F9A465AF7C08 +:10D090003C1AF34496F7607E55F0456E6F063B47A9 +:10D0A000035F97492C1FCA2CE7B73A98FDD9B53BC7 +:10D0B0006136CC43D8C2CEE997856F97810FB57A98 +:10D0C0003F74C85A3DDCBF0C52BE85FD75804F7F52 +:10D0D000EE5CCB83EADACAE4BEAC55467FA96C4B62 +:10D0E00013C6B1035B3EC53CF78297B761FC20D005 +:10D0F0002A1AF31EB788B87F459FB84F65CE3FAC5C +:10D100006AA9C4FDB6AA30CFEF33E5BF95BFBCF71F +:10D110009520454DF9AF5F70831E38DDB1D90DF80C +:10D12000A4FD61DEE0F73F970C7951F1F37B7DC6FA +:10D130007CC2F0AA98F984A7E11F94C11F70707E89 +:10D14000D5F230B7F4E379DA91FCC218F1FBDE7363 +:10D150003BDBBE7816F2DCBB769C7916E0AEF8DBE2 +:10D1600067CF423E13D967C77529F0E2EF314F58B8 +:10D170006BF70B07F7F3B7BE80F9D5E73EB0A29F78 +:10D18000736EEFC90CC85F3BB7FDEB5488C7DDBBBE +:10D19000772AC62BEFDD593080C4D0EFDA13F8328E +:10D1A0007419F9DD663A1C6C3988795767DFB7A2C4 +:10D1B0003EEBCD0B0D57B23C5B95E78336C7CEA354 +:10D1C000D7F218AB5A6EB9E95AD0CF2DCC9EEBCD21 +:10D1D0006BBC541EE83B949ED75C06DD9A799EAFEB +:10D1E000896E67E11F943E6113DDBE6859F8ABA7F5 +:10D1F000E05B4BBFB879A091CBC09796A7FF738730 +:10D200006F8F03CEFDED4808A6317A85660A60EF80 +:10D210007D9101E71A4EC93D98EFD1B3D7EA817CE1 +:10D22000C6B2BDEFA17C9CDB7914E3AA84E7C99F59 +:10D2300023BD7F2CAF59E0F3DBE462F9A31CEF9030 +:10D240005FAABAF13DCF23657CABE597C6CB2BED4A +:10D25000710C6571687E6EA092FA49FCDEACDE7CD2 +:10D2600053611CD0E998214F579BB7B93F0FD79B0B +:10D27000D1FCE8D879BB5ABE60944E6C1DD1F29FA8 +:10D28000CF35F1BC69FA3E7D0CE4C1B1F53A10121C +:10D29000DE2331E451CB8F3EE330E545872E2F2F3F +:10D2A000FA52F0FE67F1F1A183C5AB35BC74FD25E0 +:10D2B000B63E561298DD49FD533901F705987F7A3D +:10D2C00037F74F357C69F0D68599DDD0B585F907FC +:10D2D0006679AE8A735F520A1FA7AA75FF68D03BB2 +:10D2E0005D0776737E63FC5CD57C8CE5DD52FD1CAE +:10D2F000D2EB677EBF84B9BF0CDE5FA02D767F8145 +:10D30000E64F63F6775AF2DD0EF09FEE6076D2E9D3 +:10D31000B0383DD6FD36B604D9903F50E762F76588 +:10D32000886E07DA47F7BAC6BD9F98024F05F37AB1 +:10D330006A97F13CA09F79F15ED15AD70C02F03C7C +:10D3400004F8D1C519648F9F809D26A715E6896AC8 +:10D3500014DE5E7AA45848484F7F29920EFAFCC327 +:10D360009C9332F4F76FA6F8C8BF49A46E0085EB12 +:10D37000DF828277991ADFAED6CAFE9F8A86784608 +:10D3800095B5E743B0CFC96B76DC0F17F7D9831893 +:10D390001F7B96DDAB7170E757CFE3BD3CBFB21288 +:10D3A0006E170AA00F4A789CE2E4CEAF9EFD77B0DC +:10D3B00023A1311DBFE4595A1FECE7E604B4F7BBC3 +:10D3C00077248E863840C96B0FDE08FAA204741FDA +:10D3D000D8992F0F08D5D2FE4EF467E513DB06E38C +:10D3E000B980F21D2ECC273CB8735715E8FB732F7C +:10D3F0002710D0F767E5CEBF4139B0279134A9682F +:10D40000F7A9FA7575119154BD3D570E65437E0B12 +:10D41000C1FC168CBF517E2E6F4DC4F31FBA7A5CCF +:10D420009E8383F83D518340EEA8DDA81AF39ED970 +:10D43000F705094C7F05AC3DF7B3FB1058FD80D2D2 +:10D4400053CCCAF58398DC7660FDC51ABFF2EF7D38 +:10D45000FB65F503092C1E10ED87B5AFB2B2FB35A5 +:10D46000CCF4FD6982C0CFE3FEF5CA58F74FC48003 +:10D470009FDDCB259020DCBF4AB6DB314FAB428924 +:10D480008C847CF55714B6FF51E18E8C847CF53D7D +:10D490005CFF55386899BE1FC4E180FA5026B6CEAD +:10D4A00097F05EA75D76BC0FAFF235970FFD8457FE +:10D4B000BE3AF1741EE4AB25609E74E56BFF0BE988 +:10D4C0005F698DDC05FCDFB3DD8AF793766D3F9CE9 +:10D4D000017643971CC948BEC8BE4E65D86AD8A716 +:10D4E000D6E671BA66E90438C7AB9D332C8BA32FFF +:10D4F000DE4860791D4D09BE5F313D67BC5FE67453 +:10D50000CD6CC3BD8965B6D87AAC19F4822E8E274E +:10D5100046CF153643BF674967DD204A924AA107C7 +:10D52000F7C7CBB664A683BF7BC07E25EE5B1D909C +:10D5300055F407E1A9D7C7A76ABCB9129EA7CFCAFD +:10D5400095281CDD4D9F160F22901F689F1D4B3F95 +:10D55000ED4D48407E2AB359639EDFFC1DE7B76D51 +:10D56000206F63D978DEECE8B807E49002704C7461 +:10D57000AA389F32EA07B07BA2E6E4EACF6D2F9289 +:10D58000EAB11E952FC4C722B25EC973F6D52B8BA4 +:10D5900096E6E54AB9A8B0BEE9E537314A27124C0C +:10D5A000413B49E23424EB071AF2FD25B9D006F8D5 +:10D5B0005248A1471281D4F528A70E12C6A7939A04 +:10D5C000216C1DAA26101F3FC5F767AD92FA18DE21 +:10D5D00037D32EA23EBF14DEDE4B7023DC56A99A51 +:10D5E00078D1DE98E9017B4C08FAC9B7941F6A6BC1 +:10D5F000A6E7B273E1C407796E6EC2E0737B0E7D5D +:10D600000DF601E533768FD5F749A8968E07C78CBE +:10D6100031FE3799DD676F1EEF2F9C0E24B8DF7047 +:10D62000DF39FCF568F7E781BF9EF8B771B01FE3FB +:10D63000F49008D84B094E1249180DF7E449A7F5A4 +:10D64000F2EB26AC3C94B233E835CF44E377335F5A +:10D6500013AFF479AF5E14B1FDE7A6F69F5FACBDE2 +:10D66000868F806DA3F7786E142F0E3E87E064EFEF +:10D67000854EC0C768B7B716E8A8F47CF820E06309 +:10D68000B493F983290D44EFAFE53A99BE5AC1EF3F +:10D690009FA67F854E5D7FC463C3F8E82A8EF7DEC0 +:10D6A000FA5ADCA44F7DBB0478ED53DF1EAFBE23D6 +:10D6B000767D573C781262C39314A7FF60ECFA554D +:10D6C000AFBDF7664485974C6F40709E9F5BCE75EB +:10D6D000827F95F8616A11E30AB61F60A29B03F886 +:10D6E0008FF28363B8EE3DFC5FB68E7E4363D09FBE +:10D6F0004490EF8A383CB4EC1C48E1FB310777CA10 +:10D7000026B65F39F75E1627FAB18DE5971EE3F767 +:10D7100001CD6D607EF5DCA56C1F9194B2733E1E49 +:10D72000FA1F8C77277442E97D67BD108A64C2BDF9 +:10D730003526FBB5F77E9C450AD42F32C55D347E75 +:10D74000D2CE23CDE7F67526E7CF85A4C705726F45 +:10D750003EF7FE3AD76B9ADE0FAE2359706E5FB478 +:10D7600038BCB03F2AF273A6C4CDEEF323BEC1ECA1 +:10D770007E392D8F2B4B4D84F58D84F97BBECFB236 +:10D78000E47A7580FE9C9674C181F783D4CADE3436 +:10D79000D083F2056AD751574DB93094A8BA736453 +:10D7A000D49E43E1963DECBE44C953484AC00EE4C2 +:10D7B000F703909419BD76D75B140F4BD6A9786EFA +:10D7C00075A193D999BF7015DEE31C0BF6E5382FD0 +:10D7D000BBE7D648C7E04E36BF5A985F665FB86B66 +:10D7E00015AF17EDCE19D462C0388E177FDF41B464 +:10D7F000AAEFA9208FFF2CB3DF2BE8830746BFF3E6 +:10D8000029C9782FFB02F7EA0F814FD7F0FB0857A1 +:10D81000D664E173754D1ADA9D75355E7C6A78B110 +:10D8200079EBF1DE37DB70D69FCDE3677605B56522 +:10D83000209F42F25447A06C4BAF2660EFDA7BF199 +:10D84000538FF8517ACB7E2C5B3DEC7723E486999D +:10D850008867DA9E94D0EF4B5CFEA7404EECEAD589 +:10D86000867BE4AC69634CF70D9AF0A6F1C7368667 +:10D87000BFB502E30F33FED6CA1D2AEC2BAFBDBEE7 +:10D88000F7DE19C41F35EF19FE7EC7F6D9E2E2CFE5 +:10D89000938CF6EB82FCBABB204FFA11BEBFF87036 +:10D8A000CD38C4D72A7E8FE443353E7C8A803F3A08 +:10D8B0003F6B7690C0FDE8ECB721E8D359E883FBD5 +:10D8C000678177017FA293E1D39A568DFB6B362750 +:10D8D000C397E80C225E6427C397E864FCA6F0B205 +:10D8E00004F8CBC5F6F89EE2EF00F0972D7D82019B +:10D8F0005F4ACAE4CBC3DF93147F148E142E5F6695 +:10D900003CA428EC7E4A4DAEE2D9714FD0F9C3BA9F +:10D91000BDA186E0B37F1C7F71A88BAD9B2996EAE1 +:10D92000FD32E02399F0F52448D2F3094B3D84BF42 +:10D93000B42051A12C303848FD60C3BD92A24732BB +:10D94000DDCBA66E003E587F58B640BEBCB874868C +:10D95000E13CA838DB97A4223EFD784FF323352A1B +:10D96000D26F1DD011EE01E5FED7439C9E0FF37BD5 +:10D97000285771F958CBE5E5312E27B5FCDEE435A3 +:10D98000D3599E554A8E85DF571621FA3CA6246F3F +:10D990009828142EB4A9557CE23D8BE47D6B680475 +:10D9A0006D97904D7CC02749EF3F1062F735160EFA +:10D9B000043B2849BB7F71A29A34070FC24624E674 +:10D9C000775055887E4C8725D63D55B5DE03368881 +:10D9D00087C68327C1EBCB7C888E97D0E042FBBD06 +:10D9E0009FBF70CE425A76362460FC2F81FF3E8B5B +:10D9F00093C25DA2A377BC7BA837BAAE4F74517AAD +:10DA00007A0046FA7CBC6118FE2ECB137221FE8E82 +:10DA1000CB137C3DD5EE39D7DA7DC3F5A33BEF6A56 +:10DA200083DFBA5EF6613BCF44A3FCAFE7FA3679F9 +:10DA30008A91CF357D7BBC57DFFA87023CA917A6B8 +:10DA4000A01E4BB939B6DEAD9515BCB7BC761493A4 +:10DA5000F36091C2CEB5F4D50318A73EEF1FB911FC +:10DA6000F4A8C657CB09D33B41E2F0E23AC4EFB782 +:10DA7000D1ECE095700F20D7AFF01487B3DF1F48CB +:10DA80009DCBEEF35DC3EFB17A94F215C17B4FBD30 +:10DA9000F89CE162FB13CB6D63F03EB55AA705F528 +:10DAA00084F48135042687B47FBC07E20592ECED4F +:10DAB000F041BCCF2585E1DEDC5A671EDEFB2E245B +:10DAC000E57980FE5FBA160CB9583E1D9D28DE9799 +:10DAD000E94929241F65E36E009E5F913D37138855 +:10DAE0001B6E48A9B603DEC6BB585CBFA1281FF158 +:10DAF00048F17B93AB7FB49F01B367F4DE8305DD10 +:10DB00006E88730EE60E17B397487A900CD7C979D2 +:10DB100083F63B276A9064E9E47DF9886904F68717 +:10DB2000FACA791C3DB699E9B115426C3DA6D9995E +:10DB30009A1E934DFA417BD60D996E38A7A5A4780D +:10DB40008177E119B478C1BE7BA5EE8E24C443353C +:10DB5000E081A4CDE8F55F7F3014ECC7FC98FC664B +:10DB6000D65F0B7AD7735F2AD0E994AC0E9803FC8A +:10DB70007438F67A3EE9F1AB1E033E58F03B51D0C3 +:10DB8000EFA7945C5889EB69F18571F82C6D988E3C +:10DB90007C4F200AAEF3C34E36DEE706B84E36F0B1 +:10DBA0003C80463904F919271BEEC3FB4A20CF5BA2 +:10DBB000D4EDEF933C15ED4BED9EB193A17BDCFAD8 +:10DBC000FDDDE25FD87D60B7C6E3AFE2C6D87E3D3B +:10DBD0009E35828D3CE2CD027B98DA373D11B07FD5 +:10DBE000365ABD41122D071FB7C7CC4F5CE29AFAD7 +:10DBF00004E07D89CBF70CC83971B27B41E3F3397E +:10DC00001BF7046C02C37ED3533C4F53F2BBF5F7B2 +:10DC1000BBF5DEC7C9E324C416E7BB43FB7D8338ED +:10DC2000DFDD2C9F8378627FD7FC8484A89FD00A95 +:10DC3000F3A86C3853F701E289FB091CEE533283D9 +:10DC4000FBD4F356F63B3726BE38C5F34716090C0E +:10DC5000AF1A7F9FEAB577FC780F8D99FF848D57B7 +:10DC60006D184FFBFDAC5DC6385C05E51FE01B6120 +:10DC7000E378CC5F171E1FFF18E4257D7E44C4EFB8 +:10DC800065176CF8BDEB67DE0D7321CEF3868CF75C +:10DC9000757FDE3E3591C5798C71E8856EB6CE9F75 +:10DCA000E6725F7C6135F2672F7FD42F5440AE8AD5 +:10DCB0002F3C8AF64CF11601EF8924C19E43932430 +:10DCC000CE8713A0FDD969CB01DF13EB717FA3646D +:10DCD000B3D5BB5AE84BE7D32ED570AF7A49E71AD4 +:10DCE000EC97507B2A45B7DF7D8AE701975C60F7A8 +:10DCF00003124F90A401DF73BD13E55FE3BDAF5D79 +:10DD0000F6D871F66FB83D537C6182C16F88CEEF53 +:10DD1000FB4C3EF97A5ED2398EC1D53B9F0DE36351 +:10DD2000CD273A8F89D8BE2B29F6F8991CCF276AC0 +:10DD30004AE1E406295558BDE2FAFB14D027C58D07 +:10DD400049C9826E5E250DE5863C8C92C622659E91 +:10DD5000AEDF281D1CBF9D343C4A87CC47E5EB96BF +:10DD60003B61BD2F74B961BC8D8BF27FA2427F4CA9 +:10DD7000FF7C22D76754A37EB9C71DEB5C43A65B2B +:10DD800035C4954A1A387DA89D9CA7A38F46177362 +:10DD9000FB134D25F93F8178F293EC5690F87AC742 +:10DDA00044B7CCD8789BD08BB72CCC07BA34DEBE26 +:10DDB00063C8FBE983374E5F0D2FDA7B6A1FE502EC +:10DDC000BE2640C0A93FF4C3E87F297C45C7E5F4DF +:10DDD0009F147B1EFEDE792C25416A3F2CB8E43C63 +:10DDE0001E2441DB45E6A1D19F5C6DA0BFFFD11190 +:10DDF000D7811C6AF45E70E049E4DF05541E615F60 +:10DE0000FE64FD7D86F5210A5F1CBA0F0F92ECFCC3 +:10DE1000FF7374FF440E6640DE57701D5B474E6D06 +:10DE20007C24438FE725AE490B812E6453FFCB5AE8 +:10DE30003F8293BDED2AAE4B32C6C376BBFC0137A1 +:10DE40007D5FCAFDEA1549D346C65AF7A95F381166 +:10DE5000E2CFB535D32742BC4DE67623FCB216D8C7 +:10DE60009B70057AACFBB5EA395D1FAAA9C6F835E7 +:10DE7000B10589477FDE9730BBE81BC2E22D5A3BD4 +:10DE800045F67B20FEA908A410ED39C9BF32330F37 +:10DE9000E2182939411DFE1E7533BB6E4DDA010FA4 +:10DEA000E4935A69FF108FB1A54BE78DFB94AC9CAE +:10DEB000238C97613E724A98603C339BBED7E15BEE +:10DEC00049A1705EC4DF946C6EDC2F9208B3D3B4AA +:10DED000F9D337B89E3DCCD7A5E510C74D013BCC53 +:10DEE00082FED07A1EA7FC654D21C78384EB98354E +:10DEF00089D5571219DC76885B8BB0AE46B0EC82C0 +:10DF00001B7644BC9A0C7F7F3489A8F83B7DFD4882 +:10DF1000A40EEF3199D4793FBCF725F8B7001F7CE8 +:10DF200039B0E34301E2D085FE2B61FD6D108339EA +:10DF30002AADFF2BB12707EAC1EF7BBD9FCC9E43E3 +:10DF4000206FD9AFDB9762F772AAFAB89EB93C642A +:10DF5000A964DAAFF9CB95FAEF4D09BE5D0047CA67 +:10DF6000C702EEC3D4DAD9BD3EB5AEDB1261FD3EC9 +:10DF7000CAE985F407FE696776CC79494D4CC6F845 +:10DF80006656EEEB86F1BD86B2C4FDB74D941F25F3 +:10DF9000DDBDACC3259F05F865443D7DAFA75F8C13 +:10DFA000B85AB213AFBF8DB90FA3C147C725803F81 +:10DFB000F1C234B6BE9AF8608FC0E00FBAB8BF4560 +:10DFC0008222D0738E765FB0B48295B5DF8B002A43 +:10DFD00052383ED0F617C80A56E6FB9481796C1F7A +:10DFE000D20CCF9CB6873B20AE3FA76DE07CD89F7C +:10DFF0009AE31CF96778EE917B0E24801D789F8050 +:10E00000E73F7EFCFBD7E504FADCF9CE463C6F7CAB +:10E0100096CBDD5DA407EF61F7130FDF270FE1FB60 +:10E0200079F00373580ECBE0A7CF8D847E74032D57 +:10E03000DDF97AE80630DBEE6AEFF90DA8017FD84A +:10E04000330DF700B476ADDE43ACCCDA45F160E3D6 +:10E05000F6A80DE7159DB70DF1F0416FDE7810E9D8 +:10E06000D18B277EAF928697DE7927DE3603E2BC1E +:10E07000F1F4D91C67D69FD9E60783CB8CA7CFE1F3 +:10E0800013B5233F77FBEC8954BF7DECF639E0599B +:10E0900061EBC99086A2BCB8A15C25FA87A4523C6A +:10E0A0009C1DECBFB23FE0A3A3DF65E9D10FED4CAF +:10E0B0000F90BC0C9C8F76EFFBC1074EBAC0EEAC44 +:10E0C000DBF95E063C2BC5CEB5B7637C53447FE8D5 +:10E0D0007CCB95173D1FF621C49DE8FA372251E30A +:10E0E0004336BFBBF9F99ABB5B12F07CCDDD4B45E3 +:10E0F000C3BDCD772F65797744EA187DABC15E5FEC +:10E1000011B71F880398FB99BF7432F9B81FECB39D +:10E110007A26615CE059C65FF3A7F844C8479EB011 +:10E1200052C078CBF8E36A6B272DCF0F25E1EF1DA6 +:10E13000CD7F60492EDC4350D5C1E27B03C4C53995 +:10E140003F83F8C901B68E437931C8B7D3A73A7572 +:10E15000F1FE2EB93A07EEDD0BDEE9F401FF14DD26 +:10E16000EAFB007F2F91C721B47575574311E6B1C3 +:10E1700016CD55C701DD8BC276FCFDC1221B911C5B +:10E18000548F1549C406CF010A91ECF074101B3C62 +:10E19000F397B37BB28B1B66A17DE01E57A8C0FD31 +:10E1A000B7456D2F7C01ED4BA4C87E76AE85E1A707 +:10E1B000A8EDF0D7C03F0B7D859877F89D2D8AC1DB +:10E1C000FF1B153696AF6935967322C6726EBBB1CA +:10E1D000BC15EE38D3D91107F65A719D283FC3CE2E +:10E1E000E9BD2AC0DA04F1602BCA5341795B3EECE9 +:10E1F000479F79C96581EF7BFECAFCDE9EAD76BC88 +:10E20000EF6DFF1F1CC40179852FDB37C2F7338EFA +:10E21000703EC4E1687DF63B5B85E191E0BFBD7275 +:10E22000B5E6A78746C3BC5EF91BCB93E9D96AC59F +:10E23000DF4F39B3FB8597605FECCCD62BD0CE7A1D +:10E2400055085AA0DFE02A467F339F966F31FAC502 +:10E25000F727327DD32D307C5FD9609CF755216341 +:10E26000F9E789CC9F9A4774EF3361FF5EAD4B832A +:10E2700075F5B9D8F70D3FC4E5E2C517158D6F45A3 +:10E280007E3F1B5175E797F644F7EFEEBD02F22A89 +:10E29000001743A3EFCB4DE36AFD1726B27DF814B8 +:10E2A000BE3FD3F38688F8396DFADDC25EBBAEA6F9 +:10E2B0007AE014DD3A54DCB03FB508FCA3C6FDA9F2 +:10E2C000F374EB4BC5D683A977605E9284BFCB54C1 +:10E2D00031E7F94727A4C07B310CF0C277887B7502 +:10E2E000857FE3867AD4DE1D23EAF05ED270DFC03C +:10E2F000293A39FD8FF2A5264F15DC3ED935AE639C +:10E300001AE4899737B0DF6F2A0FFFE816F8FD454A +:10E31000D2C8CE99E64BA450A4F253B1FD473F8436 +:10E32000DFE30A3C33D60BF0D02E6E85F7E5CD9FA8 +:10E33000E27982D5A6DF11D09EFB387D69FD888504 +:10E34000D65F7D9BB314F413EDF775281FC8DA88E8 +:10E35000F79BB84FB1382D7DFF3EFC24CAA9C9C137 +:10E3600037EFA04DCF90F0BB3764C2BC8D7C46F92F +:10E370005600BBAB67B380BF6B4B2DADFC9BC1A4FC +:10E38000F62DC3BC5BFAFDEE58E79D17858CFD9812 +:10E39000E9FF07CEBFF42F4BCF47E67AFD6606F1C3 +:10E3A0005C62C552AAEF74767EC5F17ABCCFD13CCF +:10E3B0000E06E174F906B05EAA28DF76EDFE21C1F3 +:10E3C00096CFF36687B132DE5B08FC4A19A5FC6A7A +:10E3D0003245057CDF4CA6C3F35521F2A828323D17 +:10E3E0008171A06D09A827BA3C9DCF3F0DFCD53C9B +:10E3F0000AE34F83F879CF2E3582F73C76F3F86441 +:10E40000978795CBDAEC980773E6AC827A7459F863 +:10E41000A01BE8D1F592DD02BF4B7A667BBFC990A5 +:10E4200027D91566F7FF9E0EF7C3DF7F8DB76E996C +:10E43000F581B64E1E837FC27A9AE8FB06D65BB2A0 +:10E4400082E5910EE8579D13EBF724B476294A75BF +:10E450000EF829FF1B63EBB5D4008000000000001C +:10E460001F8B080000000000000BDD7D0B7854D5E9 +:10E47000B5F03E73CEBC92996466324926218F096D +:10E48000841020E024860814EB24040C187542D173 +:10E49000A2B638804080BC44DB46A55F26244242B9 +:10E4A00051428D08087140B1F48A6DB0A8C106EFE1 +:10E4B00080F86AB537DADE5EB5FDB92370295A1ED9 +:10E4C00023F452DBDBD67FADB5F799993349AABD6A +:10E4D000F7B6FFF7FDE9478FFBECC7597BADB5D722 +:10E4E0005A7BADB5F744BE6EF1EC2D60F0172850A5 +:10E4F0009C8C5DF2BB3C9BA0BC4482573318333AE2 +:10E500007C465B3A63D672C6BCF0CFF186BC5786B8 +:10E51000FA53B2E79BB6718CDDC57C0686CF72BF1D +:10E52000818D853E9DD0388BB1650A0B290E782EE2 +:10E53000F4BE2F4DA53263D07FD92E29D801FDEF2F +:10E54000DA6C64CCC4E8EF33F8B7A217CAC5B1F2ED +:10E550002A16343019FE63575C3B187F95123A2A0D +:10E56000A530B6DAC442C930EEEAA7B4FDD6B01081 +:10E57000C1D370E03363FCF8303FC600B4FF64EAF7 +:10E58000BCBC6EDB34C69C0628C3BC236FEB8388FF +:10E5900087FF907D34AF35CC4FE3DCDE5AC54EA506 +:10E5A00031D67C5F6BD65DF0BCD87A7FD65D5743A1 +:10E5B0003DC201DFB730DE9FC1BCF601CED654B3F9 +:10E5C000502EC0B71CE69B5406E541293405CB26E6 +:10E5D000164829E3EF53CBF87CBD71F0D5B31EFA92 +:10E5E0005EFD2EED7BF68B34C267031BA27AF654D8 +:10E5F0005C3DE0A341E0A1E100BC8FC3C3CC03526A +:10E60000C07A1596821D19005FD359C63641A9E913 +:10E61000D06746CDF8AC8731C04366126366A0D799 +:10E62000A3125BD45F42FD26D64D8136F8771D9646 +:10E63000DBA9DD0981BF476F5991E587765BEC5017 +:10E64000CE16089E0EDFD0E1C7A91C32C17792AE6C +:10E650008E96A9BE623D2FD7D98A6BB6E730B64DEC +:10E66000EFCFB2011297C9BED77480BF271DFE5BE2 +:10E6700090DF96E9BC790ACE97798B7C00076BE531 +:10E680007878ACAC65624B490CAE187C9CBEDBA4C0 +:10E69000FE900EF82C7058F2EC7323DF46F47E4B9C +:10E6A000AC5DB34DA279A41E0BBF3606E9FEBCC417 +:10E6B000F642BB1DD287AF8D817E3BE6B9590794E8 +:10E6C0005D4027B90CDFB34E09F0527EA8EEEE573D +:10E6D00091CEE5499EF1F0683C5429375A68FE779F +:10E6E000FA009ECCE4963D3AA8CFBCB3B80CF91B17 +:10E6F000E67DE702787FAFCD4DDFCBB270BABBD6F7 +:10E70000070AD696E0F77D77BF0ADF8B4C49F2E027 +:10E71000F733015756073DBBCCD88EB54BD8EED159 +:10E72000143E7EBA4EBEB30ECB65BCEC582779F7CB +:10E7300012F36DA579671A590DC289EF8325B46468 +:10E74000BC07A93EC8E93BBBA514C7CB1CC79F4E5D +:10E75000432807C7794BA5F760968E6520BCF0DF8C +:10E7600000CFBD072B331DD0FFAD732645970A4F51 +:10E77000176343D84E0959183E0B8B797B93685F1A +:10E780003A3B131783334FDBEEA2DE9B7A35E0254D +:10E79000F08ECC901EBFB37853EDD0EE4B063E8F7B +:10E7A000443AF6217D603ECD9F02E46971745B744A +:10E7B000C580E3357FAAB0E0D5B1F7E7DA4C2C5835 +:10E7C000142B37D41F9B8BED1AD9D006E4ABC6FEB1 +:10E7D00064168CE3F72F258DFC5D95BF9B3FD5B16B +:10E7E000401AB16F8ECF8AF8896C588EF01F91D87D +:10E7F0003E86F5061688FB7EF3A70E6D390A67067E +:10E800008D136BC7B4ED067E4FEDD8F4700A7EE72A +:10E81000822D9CE210F3C37ED9326B41BA5C0CEAC4 +:10E82000027A58C717DCBCFE226335FD96587B750B +:10E83000BC0B8B0C2C44788FD0B8889700C8B69D41 +:10E84000839F18DC506E183C4A7851F9211E3F8195 +:10E8500038B991D13114D2C19AFE856D55578919B5 +:10E8600048714C5DBF6BBABCB3A05ED669D67372FB +:10E8700079747D93587954270B79D0D0553D2BBEB0 +:10E88000CCDBC7FA37D654C3FA2F2FE1FD4FD89A05 +:10E89000DE58AFC4E411CC230FF1122D9B12CA161F +:10E8A000284F892BDB12EA9D09F5AE84720E6F7F2B +:10E8B000CE1ACA933D8C7D645B5BA3807C3997152F +:10E8C0005A2C417973C7BD35D520E71ACB87BC32A6 +:10E8D000CACF41C923B118FE9A3CCC1B04FC593C59 +:10E8E00061C3B212C4C3D06BB8FE1B06249B047C68 +:10E8F0006EE93F18A232F673C7F5EB97A85F43FFA6 +:10E9000087D46FD4F18B75B48E37159FA4768000B1 +:10E91000DB69A0D35799C45201A5058AFF8FA8BF10 +:10E920001AFB7FC3F52E8B18F8FCB81CBC90E57D54 +:10E9300085E4E011C986EB2ECA7738AE25C6EF6AAA +:10E94000FB5F4D19FC571C26F9DE4FDA1568FF7F77 +:10E950001A7F338D01A97E854D66A05C0D4E447DE6 +:10E96000BC93F927A21EFA7AE3F8A33A6877421F0C +:10E97000DECD005FC5F64D350AB43B610DE74A2098 +:10E9800043266DEDE5E5F4F06EC46760EBA384DF2C +:10E9900013B9E15C1D94A7DA43BC3C3EBC1BCBB76A +:10E9A0006E7D8697A7847365E83F3670A0A61ACA65 +:10E9B000FB6C23AFD77C3B97E32A7C97C779B3EDF9 +:10E9C000E9C8765C4FECD603C6401E2E5EFDF1B35F +:10E9D000FB000F8BEF4F2639B5EFDC57E6FB68FEE7 +:10E9E000019F5201F290B33ED763248F15B203B258 +:10E9F00050773962F4B0E60DB949CE4F6A3988FADA +:10EA00003E737109C9F94F53BDEDF669B1E7271996 +:10EA1000F00438DAED362E97659D97DA3F6025BB16 +:10EA2000678B99CF07D60DD1D722E8512EE6536ECA +:10EA3000D7D133CF3687C6FB40F2EE30C9F8640138 +:10EA400033D2735512D91977EC01B90072B957C096 +:10EA5000DDBB75623000E3DF21311FCA8D5EBB373D +:10EA60000BE5C30B7F91EFC4F9F69642199E3F1652 +:10EA7000F2BEB7CE9B658FD38BBD7B78BD2A777AEC +:10EA80000B787F55DF6476F0EF646E99B817E791E5 +:10EA9000AC302F96972F2ADADB4E7A7B01CD9B790B +:10EAA000BD5912CCF7F4AAB13AB42355FAA4157A99 +:10EAB0006FC2F9DC8EE35B627452BFDF8EF346BD3A +:10EAC0002F83DE87F93EE0F0D3FCC10E984A76A092 +:10EAD000B003DA71BED362F8654A781ABEFFFF0848 +:10EAE0004FF760FDFF144F23C88B00B66B6C0579A0 +:10EAF000A18B9317027FDBA4903E93CB0B0FEA39D7 +:10EB00007CBF00E4E3ED36FF468447FDFEE2071AD2 +:10EB1000C9EE53E14AFED68B355F65C3D759A25D76 +:10EB200076E203D366067AEC84A19FE4E289F9CC0D +:10EB3000D38EF243C7EA118FAA5D5971FF9AB718B5 +:10EB4000D8B397ED32D1B95BF266E1BCBA81AE269B +:10EB5000D4C37586E0BE82985EECB50777AC40BA48 +:10EB6000DE52E209B8493FD27A0BB42653BB5E7B32 +:10EB70009829583FC36D034890CE448FC86D86E0F6 +:10EB80005E09E9CDF9A577D5A4604022BA07A8FFB0 +:10EB90006D9C7F7AEB18D9F7BDB7B9886FCC2C681C +:10EBA000467846E3838C0E467CC414EFD43A6B0C53 +:10EBB0000F3F13EB3AB93CFCFCBFA11DB9D94C7611 +:10EBC00024EA4CDC77B19E4C8217E8F902F187BA4F +:10EBD0005F7A242BB889F6679E0AA4C746AB7709EB +:10EBE000C1FFED6437C2BFCBCCBA4C65B8FD609DA8 +:10EBF00024EF043CACE73186F6D99DC23EFBF7FA20 +:10EC00004B56B4035EB573FB0A19C504F26F29E3D2 +:10EC1000F54BD7257F88FB99A5EBE49011F62BAC3B +:10EC20006B8E371CB7CF208E82F1FC425EB2ED11A5 +:10EC30002BF28D1FFBA5E0F87FB4BA2D5886FE534A +:10EC400091ECD0BF38D6FF3DB16E17CB1C7ED69667 +:10EC5000EC46FC26CAF5F754F87A1EF3C67F4FFD42 +:10EC60004EE2B8B08F7B1FF105780FA5A23DFF6D76 +:10EC700099E89A08AFD31079C80CF58BDB64FB7A5E +:10EC8000C0A7BFD54AF355E1BD3333722DEDAF12A6 +:10EC9000C63F93DC54A1E0FCC5FE83ADD3EEBF18A4 +:10ECA00033C4CAC017CB5984F631C3DE8B7D6BE207 +:10ECB000BE8FB1BF18E3DBA9EB85B9A504F8055FEA +:10ECC000B92505E9E69738DDA2F44E805BC5A7ECCF +:10ECD00018199F4E433817E595BFD5487848ECAFD3 +:10ECE000EABDC7CCB03E80AFB64B12F1E3F6FB9263 +:10ECF000498F3113A763F3EA2437F2E74E43E469FF +:10ED00005A372F1919D2F5A239F202C9A342EE37A8 +:10ED1000B8F833790FB6BB90CEF9FAC2613DAD2792 +:10ED20000E0CD83B3F93F752BDC4C7BDD09EECC676 +:10ED3000F5D88C9884EF3707FEAB8D01FE4EE9F8CD +:10ED40003EB87940BBDFBD00FFEACB6272E122E34F +:10ED5000DF090C703900335D45DFB923896D82719D +:10ED60009B749217EDA3A6D593821D9C5F4CB85E51 +:10ED70001A04484D3AD8F795C5D67793EE6411EE4C +:10ED80009B1A4C9B87E414AA3F8EFB2D86FB25E83B +:10ED9000B71A3B150CE7E7A6CDBFFD33C2DD7448BB +:10EDA0004BF786187F489F49D83F8E5F0A627C40A8 +:10EDB000F635CA876A161C2F713F0C96936B8682B4 +:10EDC000E8876916FE89F463E1B9C81FD6F27EB6FA +:10EDD000149ECD67B97D317370CF2BB8CFB5D70CEA +:10EDE000E5E2349B5BD75E7DFAEA187D5538670C07 +:10EDF0006E9571FFA6DA2571FBC7890BA6C43FD7B4 +:10EE0000533FDC8FE2F7C2F80AD785C2F5D936A1A5 +:10EE1000CF40EF91DC5DDE3381F41EEA25945FEA9A +:10EE20007E16E519CA8F271D558B1C30CF92B4AAC8 +:10EE3000AF38A6F1EF901D8F9BA019C3F199A85789 +:10EE4000D476B8AF6DB18CDE2EEAE7D991CAE583EE +:10EE5000225179C54FF57B36117C0AF1CBDADD05FD +:10EE6000246F557F4C83F043AD10FE9B15C27FB3DA +:10EE700072BB91B9E3FD55416DB941ACF74616E659 +:10EE80007EACFD501FEFB7A966212BD6A3FF069FCE +:10EE9000FDDAFECD2C385B41FA0E7C668C7FCF7A92 +:10EEA000F97CEF1474DF61E67E9B99EBF6C8DC1900 +:10EEB000C5E79B5AE62D7810F5C49B7AF22FFC87A4 +:10EEC000A0938A17A3A3EAEB88EF24DC8F61BB072A +:10EED0008D8497D3A08F0F0ABFC602DC67B6F9B343 +:10EEE0000A0B113DB6BC05D6E1F8DDF492B91EF966 +:10EEF00065B343A7E1A72A879ECAE4EF41BCB727C1 +:10EF0000935D0D689E8A7C543156D5936C2AFA998C +:10EF10003ED483BD05E5A65B2D7E1C2F8C76019427 +:10EF20007708F9B5C361A0F1D472741F27F805BE44 +:10EF300043E3A1DFC517C707C168FBADC25EE4723A +:10EF400061DBAA24924731BED531E2DB129F01FD7D +:10EF5000452F0939F2122094F651FD662E47142EE2 +:10EF60009F5E3A3B89E4DE1B1FAF26B972695112DE +:10EF7000334AD4DE2B61FDF3C6E07A28DF25FCA8F6 +:10EF80002F49DC0E0C1CB1D2380D06FF0EF42B34C9 +:10EF90003C37DE0314632F1882DF7F1AEB5F369352 +:10EFA000DFAA2185C3D9F0D21892933FD6079FF9E3 +:10EFB00001F9218C649F3524B953A9FE27690CEB14 +:10EFC000BB92FD8348CF6C23B71B1B0CA1223BE0F7 +:10EFD000F16490DBBF2751D0E0F88356B26B00CCD0 +:10EFE0002CFCFEA9EE4CCF26770C2FA71E9A4CFCCA +:10EFF000BF4DCFE91638CCFD9A27F5BEB959503E22 +:10F00000F97CA907768EECA2CF1032008CCD5BB8CC +:10F01000BDB64CE7EE6B45D9F472B247B3DF7C78EE +:10F02000652DD637AF5E7713CAC1D1D633CAF37810 +:10F030007FED0516C9A3FD66FDD8FE107CF7C2E082 +:10F04000440FA947E60262039FD878DBD37AC03722 +:10F05000F2D7113DF1EF171D1FE78BFB3FD42FF8BF +:10F060009D6690BF513F32C9DFB8B23C5299D3B3CD +:10F07000F9A54C619F69EBEF48F55F40B9D6F4DD27 +:10F08000DF9F6825FC4648FEB11EEE1F3FADF72E00 +:10F09000463EB557870C4BE3F6B78634BE8E9619BD +:10F0A000855E672143FCBA53EB2BAAB47CAE3EF5D8 +:10F0B000697C1F691DE2727C78BD4EAC9BAF185114 +:10F0C0006F71D70DECA7CF727F8621CD4DF533CF71 +:10F0D000860CCBA09CBF2E6458219EB82E00DF2149 +:10F0E00013CCFBF40E2B5FCF80061C67C57446F66D +:10F0F000C80A19ECD0327CEF1E08035DCE3C6FE7E6 +:10F10000FCF527C00AE07B0913ED8C60B782DC7A3E +:10F11000B1530AA15DBF64BB71AFB900D7B157B697 +:10F12000223D774B24B796745616ED80F2EA43538E +:10F1300088FE29D3395FAE0EDA49FFCD147270997B +:10F140003168203BFA19EEA783F1C91E6E804E5933 +:10F1500065C3F180F25BC30F416D9C6166BF90A7F0 +:10F16000FBE3E20B63E3E47A7F427FB0E3B4FC119C +:10F1700050F50E9773CC9D89724E95C34687AF3478 +:10F180008DE4526126D217E8C9E5E44189F0DAC876 +:10F190005AB8DE10F23EFA5DA12FCEC801AE978CB0 +:10F1A0005BE93937AD80E8B61AF50DF9CDF9FE6E99 +:10F1B000343E989BA6137271643EB85EF041C35909 +:10F1C00016BA16BED7B08E851AA7F2A7752AE941DE +:10F1D000AE0F4D229E61E2F18ECFD38B897A70986B +:10F1E000DE4BD0779906A1DF049DE3FDD9A8EF6738 +:10F1F000AE0BCAE8D7CCB379AFCD4C8FD92FCDEFBA +:10F20000994CEEABB0EC63632DE89FA97CC685FEFC +:10F210005DD88FE3BA4A06BCEC81F7BB55FBD6C577 +:10F22000E7EB3270FED52B3E566A41BA0CD17E35E3 +:10F2300092CE6CC88F2A3E775BA15F19F6E3EB2D67 +:10F24000DADFC43A93E2FA57BD6426B97AE5B035FD +:10F250006824BBC39F6F87F1327E65243BF4C24BA9 +:10F2600056D29F1784FE73AAFB7EB681E8D38A74B8 +:10F270004D476EAA1A83FE5326CD1F832250B5C375 +:10F280001AEDA3F9B3457DC1D0AD9CAF8CB45FBC82 +:10F29000620F7F13CB000F43FBBA05E98CFEF643E8 +:10F2A000B34B1F80F7CD3E8B8763DF5F8AFC6A9488 +:10F2B000EFBD15FD2A73E57591FB601E8DB9169B98 +:10F2C00011BA54E7FFFA97B741F9A3437A66443A73 +:10F2D000EF9BBD888D1D5DFEAE0AEA4F86E3D6CB5F +:10F2E0009AFDDA7263BFB6DCCC9493E13879FC58AE +:10F2F0009AD5796632C90ECF67C0DF4663CBD93D58 +:10F3000000AFF1C746D2470D69FE5D69E837D545C4 +:10F310005E433C1BF3CF4D453F4555FE9F28AE73E2 +:10F32000E5DBCC83705F315792FEBEB2C3EC0EC4F6 +:10F33000C9AF66C1FFBD79B554DFBBD3E896787D10 +:10F34000EDB40AB407E9DBF867D201FE9BB7CFFB47 +:10F3500088F64D68B543B917ED4BECF79C146C4734 +:10F36000FB713BD77BE7C17E34A1FE14EBA9591E8C +:10F370009C6B82FFEC75D44C44F9A2FC59F121FD41 +:10F3800037E25071F6EEE1E8FAE47E9C1BD08F3351 +:10F390008EFC3887516E349AC2864A18E7BA3FFF0E +:10F3A0008EE4F2CAD6A564D7C7EC5C23C99195F761 +:10F3B000F9E9FD2B3BAEA7799D8179237ECEECE662 +:10F3C000FBB995399620C2779D9DDBBF2BA19F2469 +:10F3D0000DC74B221E7EB3EB7A17D2FB378C7F2FE3 +:10F3E000D0CFED84DFD8865248FEB85B52D0CE6BCA +:10F3F000DE7EFD4728B756EE963DA8C7D9112BF9FA +:10F400003D56EE9E3371B905C7B99C568978EB9B82 +:10F410006393E9BDEC0B72FFC9D075F05EE9BBC622 +:10F420008DEBE4F86E2387CF6E7A1AE1BFEECF3210 +:10F43000F1BDA2637EB4577B0DDE89B8DEDCBBF67E +:10F44000CD45BCFEA62E5B47ED9F95980DF1606FF4 +:10F45000CDC0F72B25C587EBAB7EFBAADA787BA462 +:10F46000334D267C57E6AFCB085B88DF6F453DD731 +:10F47000B85B4F76DDF1051FFCF236678CDF57CAAB +:10F480003DB7CE8CB3379A77DD28F8013436E06982 +:10F49000A5C093317F5D117EF7F3F87FE5FA9622E0 +:10F4A0001E8FF9EBEB20BABE77F1F5F007D0F7B479 +:10F4B0005FCF7168ECFBD1F641AABFD9E461DE7D74 +:10F4C000168A1B7A719F9BE754A83ECFC9ED6CE565 +:10F4D0000F6BF7BF0DF0F7A7F98D4E789FCFBCA546 +:10F4E000485777C45605E6244E89EC1FB6CBC8EDC5 +:10F4F0004985FBDDB6A5B3A737C5C1998DE3A5D373 +:10F50000FAB43961DC0BEFFFE935C45F53DEB9A90A +:10F510003C9EF63B8A4F590679DCD2E2F131E48B0E +:10F52000E6C13A7657494C1E367BB8BC4E9CD77222 +:10F5300027DF67343B23344E753A5F67AABF77678E +:10F540006B12F9F5763A8366BEBF0D3094E73795B6 +:10F55000CB3CDE22EC129FF09399BCAF308CC730CD +:10F560008FEC190FE521EFA9CE3428BF5D3EC723EC +:10F5700043D9E27DB26B2CCEDBA317F5E3C85FF86D +:10F58000D6AC4AB24F6EF2CAF45D569F42FBF521EB +:10F59000EFCF9D77C1776F66DEB4D3F08D1A50D66A +:10F5A00048C721FC36DA018ABFDC19E75FBDD133D9 +:10F5B0002FED74BCBEF472FD8FFBF17E113718097C +:10F5C0000F2569953311BFD77D99D3E1E367F9FE24 +:10F5D000E36333F763ABED3EB6723D53EB94841DAA +:10F5E000D89F87723E5AFE5AB1260EEC34F4E7E1FA +:10F5F0003AFBADA41D6775978EE2B3ABBA18C5632D +:10F600003FFEFE8B79286F3FDAF762DED238F812C0 +:10F61000FBA9CF5B9D5ABF94EA87748AB8F4528FD6 +:10F6200091FBFB46F143AAEDD976BE1FBB08D21D64 +:10F63000F94EED77B13EC98B76E545662279B67411 +:10F6400050F835BDDE4227EE1FD4FE09E36F41FEC0 +:10F6500001B8A40189F6E7C9251192AFAB4CBED71A +:10F66000C6B8312FC54BF499877494905FBD069C42 +:10F67000B722F67946C5D788F45CDEA3A56396D396 +:10F6800026E2944EA2BBA1C9A2A07EC8E810F2FA5D +:10F690001B3ADABF18B25D16944BD715257562DC9C +:10F6A000DD99943215FDE6B9D9C5D43E50C5F93A75 +:10F6B00090C1C86F95C55A2492B736EEE7CE99CE61 +:10F6C0006C98E7F1A293DB832EE6D92E933DD82FD9 +:10F6D00091BF5FCC5F95EBC82F28E73E964CC42FB7 +:10F6E000D2A044F69DACEB5F8CE38EC63FBD09FC17 +:10F6F000D3FB0FE69F3EF57BC3F8C74F71BAA52E2B +:10F70000D3C8FC23FCAA5FB8FD6871C26F98543F50 +:10F71000B384F3AD15E3D59A2C21792AC98773F107 +:10F72000FED45D6067E27E448D2B8EE958E2E6767A +:10F73000FA5018F7E5C9D79848CF7D47375480F677 +:10F740007C629C11286B47798F3286FC8AAD55BE4E +:10F75000D36971FAFE08DF3734DDE7A5F7B307B9DF +:10F760007E6F2E3490DDD93C200590CE4D3E43D0A7 +:10F770005440719525A4B71F32BB799CC4DD4E71EE +:10F78000926FBB791C25EA470DF73D80FC566F212F +:10F79000BF4362BCE585BFC8FCFBE3197DBFB794DE +:10F7A000C7777AE7B9C9AF911847635DDAF5ABC699 +:10F7B000512E5A0131F0BDA59BCD44876C99E39938 +:10F7C000A59AB87E192E07C85F9B315D1046C43BD1 +:10F7D000A2EB1A240396B345BD1A9FB196F80AD03E +:10F7E000C2BD3DEDB93793D2FF967C86D6EFFCD5EE +:10F7F0007C8680B116F3194C683D8B7A041BF4ADFE +:10F800005AF69ADD18BF89D52B60379A0624F1BDC8 +:10F81000E76F9853087890D4EFAFDFE4B550BC5849 +:10F82000F3BD78F89484F1F530BEC52DDA070ECC1F +:10F830009BA3505C52D47FD68DF91B5BF4DAF108A0 +:10F84000A5A23F16D4EF1DCF9CFB9DCD3931BD0F36 +:10F850007680297D5A4CFF6FFCA0B6E72AF856B295 +:10F86000EDB201F5AAAAC79B9D3CBF2171BD3AD25A +:10F87000F97A05FBD5914E7283DBB5B5223E09F6C8 +:10F88000EC5C5C5ACDEB7C0CE393602F64A4631EAC +:10F89000C3FBE7CE1C45FA2DF898ECF9E64F15EEC0 +:10F8A0007701BB03ED7393E07336A0277DABF2C104 +:10F8B0006A217F7AEDA0EF915F8F48D302C4172DA4 +:10F8C00079B7000DEE4FF7BA697CB1EF4A847746FD +:10F8D0003AF793341757ED28C2F19F9218EAFB4D7F +:10F8E000C52733D02E691EFC3063795CBF55038F6A +:10F8F000121E56EDD78F38FF19E9DCBE6C3AFC3C7E +:10F90000F9073F0E4AB496EB9560F74C28D7D7EB32 +:10F91000D04263E5C125B791BF7F91818D87F9E51D +:10F920000B7DD4BCFF2B8199B83F837F12BCDAE9F1 +:10F930005B417A6FE7229305E30ECDC54BEF263C82 +:10F94000D892BC88874DC55559F89DA6BAB9368A54 +:10F9500013807D85F54DF7DD4E7E1315AE4D03FA10 +:10F960001AB4BB2AC0CEFA11C09DEB985FE381F5B3 +:10F9700037463E587A8F05E3C223CBDF7FC9E0F4D8 +:10F98000EC947C819BCBC94FC8E2FD7EF903DC9EE1 +:10F99000AB4B3768FCC275E9DCCE9C15189A8DBC60 +:10F9A000F7B2124E46BBB799793FC1FD25F359DC3A +:10F9B000FB884E5C8E38DBDCE43F3239C3DFB90AAA +:10F9C000EB6729B47F604AF811FCEE856EA76713D8 +:10F9D00013FC8BE5FB4A822847FF39DDBF18F9ACE1 +:10F9E00042D88F170E5F5F8A7E36D53EEADE630E01 +:10F9F000621CB0DBEAFE6E0DCAC13F283CEE6D8A88 +:10FA00000CCD467AFCD141E3769B83DD48FFC0569E +:10FA10003DD51FB6FA5721DF9CADAB29A2BC1B4BCD +:10FA2000A008E3BC7A670F433B01B60BE44F3039C3 +:10FA30007D0CE3A1B3034B1409E57C82DD315BE46B +:10FA40008F92F084F755428C8D072E3863A225D013 +:10FA5000F9595ACC0E79E34F0B157CA9DA273A13E2 +:10FA60008F67552F4A6232F2FD86C86B3AF45F3BCE +:10FA700087C87E6DEC97E83B8DC5CF513ED81A9173 +:10FA80007714CDFF51C2940FB53E3D59E8F14ECEEB +:10FA9000EF6C88F6CBEC00A7276361CA938AED234D +:10FAA000DAA99D3A9E41F8DD1B85DF053418D53F64 +:10FAB00094AEDA07EBC553CDEBE2DFDD260D7965B9 +:10FAC000C46BA9A4F117ABCFA7D2B97D987A2C3219 +:10FAD00017D76FE4B09AA7C9F330774C9BE441D3B2 +:10FAE00069589EE6C02773916FC0D0A6F5DA34F04E +:10FAF000C5F234BF2FF60DFFEB799A1EC9BB179ED6 +:10FB00003F4AB773BF959AA7E9E1F853E36C89F9C7 +:10FB10009917B2420ACFB70AF7ED43FE1C30521EC6 +:10FB200057EDC0EBEFA17EAC35B17E8C4326DA19E0 +:10FB30006DB6AF0C22DF5F3C7FA6EF418679BA2F0E +:10FB400078285F23C17E48DC27ECC52659A3DB7BE0 +:10FB5000EF46E9C9EDBD68F97FDDDEE3F67C601FA5 +:10FB6000CF0F50E579B3D89F5DACBF94827AE6445D +:10FB7000149E843C86A7441EC3E0C8790C8AC8073B +:10FB8000027B3D407C7290C775DE783A99E4C725C8 +:10FB90009BB217EDA5F3D6C83711598AB0933A8FA7 +:10FBA00018DD282F40DE91FC0E1CD4F3380DC66DF5 +:10FBB000308EF3F24411C711F1A29792C96E6948D1 +:10FBC00071A7627F354EF363A16F1A92787CA62BE2 +:10FBD000D97F397D84B8CD1E617FED81A16C38DE7F +:10FBE0007B4611C7060181FB9D877279DC41C46D9C +:10FBF0002E8AB8CDA9625DC8C0FD10E4A77277292E +:10FC00002C0BEADDEF99836EEECF32E940EF2F53F4 +:10FC1000E3362F733FD532119F39B5602EE5072D9E +:10FC2000C7FC7719FD18DCCF1CCDC767361DCE6722 +:10FC30000D888B9D28620280F56BE0B5A493D09E61 +:10FC4000707742998C656F4F0D7C7769A78EF6238C +:10FC5000CBBAB4FEF22B9BEEAE41FDBDB193C71FF4 +:10FC6000035D12E9EF65CCEB427B43E587828C3480 +:10FC7000A273A053E7C5EFCCC8E0FE04407D90E638 +:10FC8000279E9D7AE1671770B4335D089F3A893FDC +:10FC900037DA949A11F5B218AF53DF62AA443B36B3 +:10FCA00057477EDE2B06EF22F2933A8A886E9DD666 +:10FCB00096AE1A5E4F6BE58A39E2A3FA6B156EE8D1 +:10FCC00031B703E564668688DF24CC77798FB69CEC +:10FCD000187F5815D4969731FF842C3C87B05FFB72 +:10FCE0003E3383CBA92B9B0A849FDF437EFE4EBD10 +:10FCF000FBDD029453DD0AC9C9F61C8E2F5D2E7FF1 +:10FD00008EB5572F22FBC00E7605C1CBE11F7BAD10 +:10FD100053427DD969E77CF93F853B11DECA8C22CD +:10FD20006E27A07187EBA85B0A727C71B8BFA8BF71 +:10FD3000626986F01708F9132DFFEFEF37393F7628 +:10FD4000CB62BDD948FE2C15F1C65392E7E910BE2F +:10FD5000B7805D00702FEB96CBD03E99FD150BCD93 +:10FD6000A3E96573D008F58DEBC279B88E9AAAC263 +:10FD7000452D23E015A15554B905ED963A617F80D4 +:10FD8000EBB64B1B871A1E57F47E2B231DF721A7BA +:10FD90000EBE8EF43E6826BD04FF75D488FE8EC369 +:10FDA00005642F4D4DF5B765A03E4F0AF57DAF00B8 +:10FDB000ED136E1F350E1AF7A0FDB7B4537B6E8698 +:10FDC0006DD6C6B9589783FC19AC57FB1ECFA768F0 +:10FDD000FA0D8B7B713DBFCDE09F8876DD755FE6C8 +:10FDE000F1F5F3AB740CE9BB4CF6AC403972DEAC08 +:10FDF000B5BBCF5B39BDFAA274F614219DFB46A5B5 +:10FE0000B3A708E9BC4CC7FCF1E334229DAFC6ECB4 +:10FE1000734EE7F3CF5F5384743E77F09A22A4F3D6 +:10FE2000367D8F17D7CD930EFF5EC4CFE9393EB232 +:10FE30009BD4BCC92FCA8F8732B4FA305AFE3BF923 +:10FE40003F46D383A1281C5A3DE834B873501E2E78 +:10FE50003519FFAA3EC4BF11FD692623F9235EFEB2 +:10FE6000D3E58751BF050665B23FD4F15E56FCE38A +:10FE7000D05FF0F27B2E4F401A7DFC066157B94CE3 +:10FE80002C807E0FD5DE57EDC64479FC0B319FD315 +:10FE900019DE1AB4B355FF6CBD18D314BCCCEDD326 +:10FEA000A724F2BF9ADCFD3C7FFEC8121BFA67CF85 +:10FEB00006B93FB6E9F952F2D7AE0ABE12C2FC2724 +:10FEC0003628D970DFB0EAA90F53309E0DFBD0530E +:10FED0001971F19539621F7A36782A05E3DEF0FD53 +:10FEE0006AFC7EB2336240FE6D82FD1934614D4A78 +:10FEF00084CE0D353919E9FBF201ED7E4D8D4FEEC3 +:10FF0000F41948DEED1C9482B83FCB30F80B7250E8 +:10FF10003FB11CDB99E4D87AF924C36BCB9C161F44 +:10FF200017F65ECE88CB570AEF48253E0CEB999723 +:10FF3000EC801D56219778BCE63F77D9833C7F89BA +:10FF4000B7FFCF600195557DBD429CC35B21CEE1DB +:10FF5000A1FC0E25C8EFF87234DEAC9E3703791E83 +:10FF60001A29FE1D97B714DFBF8945447EDE674618 +:10FF7000CDB8D17C9D965237C0BDE66B163A67D896 +:10FF80000C7CDD5A16E3C3063115950F9B845FB7D1 +:10FF9000B9FE24ED039AF17C05DA551ECE870DB02B +:10FFA0003FC2FCCDC475CBFAB5F98CA3ADE329995A +:10FFB0005ABD122DFF83FC98D333B5EB579DBFEA92 +:10FFC000078FCE7350E2EB2B615E89FBCA44FFB50D +:10FFD000BA2FFCA272EDE64CAD5C8B96FFC172EDC0 +:10FFE0008ECCD1E49A363EF037CBB5C4384121F7F8 +:10FFF0007F639C00E3B6FFD338C147EE9E0C1DCF54 +:020000022000DC +:10000000C3D7C44FBBA4969B4CE330AEC8E3CB8DA3 +:100010005623C56113E3AACDEEB9228E38F4CB196D +:10002000A8370FE919EAF37ACB4A8A5736CB070C7F +:1000300078A470583C51394A76FBDF1A575F9F19F4 +:100040008DAB17605CFD15CBE5347F1C3DAB4AC022 +:10005000C02F193DDF68B3A053B2C88B30290166A9 +:100060008FEB3F5ABFDE4C6E27BF22F2635C069EC9 +:10007000C7BEC50AFB3098BF4BC7F377EE4FF76D8D +:1000800043F9687273FC3E71F8AB0CCF1D3DA1EFD4 +:1000900027391268B478501EAA7E17757C45F80F70 +:1000A000BE28DFFF2081EF7FF077E6FB447C0CA8C1 +:1000B00072E76F8D876D07DC68D607A3B8D75B182A +:1000C000CF2918CEC7A38D331A3FFF34D3F75A2652 +:1000D000C947EF54CACBFD82F226B93C720AFD3BF8 +:1000E000EC90D18DFB0D933897C13667893C4A4F10 +:1000F000451DE513F3730DEAF98FD1ECC20FA3721E +:100100009ADB851F8E2AA7FF7B76E1030EDF299CF1 +:10011000E7E94A6F11EACD8D56801FF77BDF378EF6 +:1001200078CE423D0F00FCC4CF9B3CCBE3E0897C02 +:10013000F58704FDF287BFB37E194D9EEA5D2A1C48 +:100140007F67795AFFC714F47B8E3E4E80E0A8A8E3 +:100150001AF28AB815C3B8913A8FE6219E7F96218C +:10016000F2AAD4F7116117DEE9F266BAA0FFB9F777 +:100170004D26960A2610F218DA633E0BC5039AFA4A +:10018000799E48D33A46715FF51C65D3401D43BB49 +:10019000AF3FCD5F8079601B3FB004E454F4932FF0 +:1001A0006068EF5D789F971BD2FCE3294F6C5D5828 +:1001B0001377A8F8ECF206F46700BCE41F708AFC21 +:1001C0004C15BE3A179767EAF32681EFE8BC9C1CF2 +:1001D0004ED62F07D14E4C760F911FA9E91037DE6E +:1001E0002A642FF9EBD91A079D9F683A54594AE7B8 +:1001F000CDFBCDA568E756FCAAD686FE8973D73A13 +:1002000029CF204F0EAF423BEB9FD3FDB3105E6B67 +:1002100079701EDAA9F960A7A2DD7BEEE0BC527FFF +:100220009CBF7B1BFABB61DC6D56AD3F9B99789EF2 +:1002300078FD5E9E077CD8EA9F8BF8DD66E6F006C7 +:10024000B68ABC67E1E74E5CFFEABA8F9E73BCC317 +:10025000447169552E6CD3333FEA3D559E94883CDA +:1002600039C007CFD31BACE3F91EA26C716AF3153A +:100270004F67CC2941784AD0D13B0DEF518848E8EF +:10028000775F2EE2F0D78B7C0A357FCAA8F8BE8E46 +:10029000EDD9BA9A58FC7D2CF617F177912793FC8B +:1002A00029B79FC7DA0CC43756585FE41F01BE4117 +:1002B000FACC8A0CCDC6F34485BDA15988CF973FAF +:1002C000D5113E94BAB7287E928A648371C66D0EAA +:1002D000774F403F8AED17D7225DDC3DB62A445D5B +:1002E0007F9AAF91E0505A8A715F59F5AF7A9E07B5 +:1002F000782499FC03BD790D940778E103E388E73E +:1003000046D46780ADA7BCBFB1033F273FBEF59081 +:1003100034623E6797CBC2CF0D078628BF8CCD7263 +:10032000123E9423BFA2B8AFD2AD9007A353EFD52E +:10033000E139A8403B23FFE5F85E9B0EE9922FF2DE +:100340004B2EBEFC5F53FDB44F51FDF6419E0FA4F2 +:100350000F6FC07D97D21EFE32AC60D678C8AE6BF0 +:100360002AC1F1224D3CAF3D99219FE40F8C5BFFE8 +:100370002528E777D99884F2E7A535F9E42F857920 +:100380008E1F619E77BB78FE8E722459877A4BD977 +:10039000CA28FF50B1675411DC8F4219C65923F89F +:1003A000468D4702B82ED44777BAFCBB11CFD17324 +:1003B00032AD49FC9C8C3877696DFDE0593C7FD2A9 +:1003C00067E0E70C8FBD3C7901F9EDBA1509E970DA +:1003D000C5BE24DF06EFF78B756B558698CD128F5F +:1003E000FF63946F39F608CF4B53F49C4F946EE73C +:1003F0001EF40B7E9AEAA7BCD26B3B4332C5B36CAA +:10040000A71FA971C7ED6BB6733DD2B49FEFA713B9 +:10041000F7319FA73F8EBAB47649B4FC0FB24BDEDA +:100420004AD01B7FF3FE8469F77589F649E23E6E78 +:1004300098DD9D30DE68768A9AD75115FB0EF1C3A0 +:100440002B56D50E0A68F25EAA2CE2DC9B493BFED5 +:1004500053224F47CD83C9E870B7635E79E4DB8CE4 +:10046000FC6C6A3E4EA08AEF1B023A139D8773B163 +:100470001ECAC319C3429244F67F98CE7566623E87 +:100480000EF47BDF3596E0DECD3C5D32C943B784A8 +:10049000709B318F83F236833B56E0776EB1D07715 +:1004A000CC98C7713586E2BD3B507ECEAEE77188F1 +:1004B0006CD0B7C8B7D9859C0FCD8B783E879AAFE3 +:1004C000A1E657A878A812F8CD9EB0A200F707DDE4 +:1004D00092FFFBEA79DAF873D2D1F3D1ABC6D279C5 +:1004E00093E8F9B94226EABFD839E9447CAAF91D54 +:1004F0005536BF2D2B7DF87959953FE2E84670EDD2 +:100500003CC2EDF5AA7A03C17F71D57CF2235E5C13 +:10051000A563B86EAA068D9CDF12BEB7337A0F466C +:10052000D04CF75D08BA7F9EBD0AF42C463FEDB172 +:10053000B69AAB4F036E8FB7F9E879D12CF5CB574C +:10054000D179C6C528992E67EDACC57B0A2E5A23F2 +:100550007978CFC1E5EC076FA4727AE404965376FC +:100560001EBA11EF3DB8383ED287F71E14EEACE448 +:10057000F5C883D98C5D9555716380E6CDFD4EB38A +:1005800063E7B3CB113F8D2CBC6188FC3B3C7F1FE4 +:10059000F3FD900E2E8B81EC1997C8B364D522EF32 +:1005A00012233050EEC82AA578B585B90F0D617DAC +:1005B0000E3F2704F5C4BF1DE3B95FD824E8CA7213 +:1005C000543F523880F2A9A3C04EFDA372F490317B +:1005D000C8FD59FCFBEF3C3F85E24B6AFE2863B641 +:1005E000DC855328DF445356EF37608A2D17ED859D +:1005F0000EBDB04B45392DD55F97156717BD33E755 +:100600005B25B80ECEBFF04021CAA5EB0D60B78FB9 +:1006100020877E9DCDE5D045BDA54B023BEDE7296A +:10062000FEDB719CF79217CFB5C3BC16A5551AEC2B +:10063000086FE0FB32CAC574416FFB420E9FBDDA02 +:10064000272D87713BCCB07EA17FBA5FF1529EBD52 +:100650007FA1740BC0DD2171790B9D52695F52EC53 +:100660004EC5FCE506715E5216EB7E46FF5619ED4F +:10067000E977DB06662A8531F87E2EE2CB3F2F60D4 +:1006800077D68DB0DF6DCDE2727B81EC9E827CB43B +:10069000411A78AB360BDFBBE9FD9C94D672CC3B9C +:1006A000BE3EB9A51CF5CFB0F7A9F0BE24AE6CE4F0 +:1006B000ED1A4C913C3C9FEC4DF6AFCBC2B8D092BA +:1006C0000F296EF9CDEC774E60DEC13BFA9ED92939 +:1006D000A85F0AC4B97EE1377C6D82EA3734F1F253 +:1006E00064EE378CE6734DE1F964B50BF939C55A00 +:1006F00091AF30D7C6CFF5CC2D2FF074008837B12D +:100700008882726FEE7BBE14DCB7B385FE72DF9415 +:10071000D1ED19E6D2BBE3D7EB3C775C19FEDD5097 +:10072000AC2DDFE8D1966F9EFEE709F1E53DC9DE0D +:100730001D38EF1F4B3CFF313083D9689E4E298016 +:1007400076C7E417B3C5F94E9EA7F74F625FF4E290 +:100750007446F519FB4D7B31FF5DF533CBA27EB2BC +:100760008B99F21DFCBE00D4571149E4FB39299640 +:10077000C25EB8DBC6F1076D0D30CE0B4BDCB43E6C +:10078000322C3AF6655C43E526B2432AC69892902D +:100790006F8E09BE53CFEBAA7C58A1301FE62FC045 +:1007A000A717E2F31DBDED28FA97031F31C6E955DF +:1007B000A950FEA1F81663ED547E4CF0F7310153B9 +:1007C000E0DB0AADE757AD06A2A7FC13790FEA09F3 +:1007D0008CCDA0DFF8D2E649049FBA7E6055173A67 +:1007E00033C8A52DC655740844B1B02754FE460B36 +:1007F00008DB8DC1FF2C203E27791399C6EF4FF8F7 +:100800007901972791AD0E711E8CC7CB724DD171B6 +:10081000BD386E56F43BFCBC51862843554807F35F +:10082000FE4D560197CB83AFFF81F4B2C5E3C7EF0E +:1008300018524C744E465D37B6CEDFBE553B03E7CB +:1008400059F40D9AE77CAB0DE7590C6CBDC8414FCC +:100850006F1A8DC7D78F9CE471E33AF94ACDE199BD +:100860004A1CDF40FF46DE3F59DBDF05FD1D71FD01 +:1008700053A07FC9F0FE4F594D21DD541CA7C21D66 +:1008800026791EA2C9CC17F3923378BFF9221FB480 +:100890003005DAA3BE29D6E66BB0E91E13BFAF431D +:1008A0009B9F71BDB42E0BD7D53C53E36018C67B1C +:1008B0005DD0ED7A9DFF77783FDDEB8B8B8EE37A11 +:1008C000AB310515DC0FDDC0421B9098172BFD4F97 +:1008D000D8C7913CF80BAE8B26D93FC101E5F3FA9E +:1008E0009EC2BB0B68BD7C96356D38BC2A5FA8F0F4 +:1008F000227F209F45F92301EE289D6EEAA744B68A +:10090000DD60F7E053B583186BE1F9C6EEDCD8BCC7 +:100910008089E69A5A0AD10E79BD3D4072E37AFB8E +:100920002394D7F4E7317E6736C0B5E8AA4FE85E76 +:1009300013E65A3201ED7B80373D3BFDFF1DBCAA1B +:10094000BD372CDFF6238326DF76B475A57EB799F5 +:10095000F1FB69660FEEA1FCD9E685160F9E836850 +:10096000C6FCCF728A2F911D87E784E99E13C924A4 +:10097000ECAE2F9A97CBD7616FA39BECB7A81C174F +:1009800079E5BDA51CEEDEBBDDEA3D27DCBE5BC222 +:10099000F83D29EA3D27CB6D54AFE69FF7EEE17EA7 +:1009A000BCDEE727D07929B0DFC85E60A93A0E5FC8 +:1009B00081F67E15FC933262F9D2DBF4DCDEDCA931 +:1009C000F354209E77621CE8AFC47FBF9AADF59BBD +:1009D000A8E544BFDE930EFFEDC817CB4BBC7912E0 +:1009E000F0CF3203F7DB017FEDC2B31535ACE5295B +:1009F000BC3F701E6BF9856E1CF1979FF86BF22758 +:100A0000FC5EC1187F2DE1FC1520A1A4F25794AF24 +:100A10008A13F3ABFCABB17DAFBDFF574D68A70E9A +:100A20001A892E6A9E5CE23A8E83E7B49EC3E394F1 +:100A3000658267ED48F07C113E8FE7AF4CC6F979CF +:100A4000347ECF5458C05A16E3F73DC9FE76843F32 +:100A5000CAF71BF87E6418DCB285F8E3D6DB649E27 +:100A60003F9ECCF515C62BB2E0FB75E2FBB7767363 +:100A70003EBAD56A20BEAB1B6CA47C2256CDE30ED9 +:100A80001EF81FDF077A09BF8B44BF85CE523DB2E7 +:100A9000ECC25A6D7C6291458D7FF8F4B81E6F5D93 +:100AA000A83F19AFEF17B1CD9F60DEDB228C63A8A2 +:100AB000FDE0BB8F6747E31813308E715CECD32FDA +:100AC000027F23FFBF9ABE72D7DDC0B7131E2F2946 +:100AD000437FCE9C8C554F6D85F2F7764EA2F2ABDC +:100AE0001977DCFB0ED6F71551B91A2F71C1FD46E7 +:100AF00023EF5F5C71DBFC02F8EE71B31817D715BA +:100B0000EEFB92FCBD75D0CE35756C19E623560B05 +:100B1000F970F16E9E0F7FC355569EE2B9D24D7E9D +:100B2000A3EA2451FF753EEE5BA5FF568679A9D551 +:100B300063238BE93EC6B21F4FC2F271E993C5230E +:100B4000C54D26174BA189809F6A076F5F5BF6FD35 +:100B50006CDCC75757F1F2644F65F738ACD75D5A74 +:100B60003CD2B9D09F8AF5143DF724D6E98BDE0F2D +:100B7000E99C93CF2479708ABEE91FF27B892C927D +:100B80000DFD8F3E6F81827ED2D95E9EB758656A19 +:100B9000CFC2FDEF4D7E4339E69FDA4CA5C7D1CEDB +:100BA000489D5E390DE93BDBC4F4A89780CFFF85F3 +:100BB000F8FC9A4FF25290B92C5A3E57F9A84EE5DC +:100BC000EF6A2D1FC3FAFCD7ECF4CF97AFA3F13136 +:100BD0007CFFDFB1FFA22F69F54A74BC84F596381B +:100BE000FE687200FFE2E55C0C8E7E5A573998155C +:100BF000360ED75D8FBAEE220887413744E73EF2C2 +:100C000025CF243AF0388AFE57E1CB05D9C6CA86EB +:100C1000C3857F8A6A9771086CB60CFC2EAF877EFD +:100C20005EE688C105DF676350EF6FE0F0EC965A2F +:100C3000B8DC1076B1BA3F6E52E73BA09D6F45120B +:100C40003FEFEC42FF05F673964EFA6B70370BBD23 +:100C5000B9D0E47BC80873B8C5BE8CF8E1AB2CF002 +:100C60003CDA27C654BF634C3AEEBB0247C205E4E8 +:100C7000CFA5BC01A077DA9838FB44852B111F4D16 +:100C8000A3C8C344B813F110A3CF10D957EAF9A9E8 +:100C9000E8BC12E6D361E5EB3532CDA8DE5F528CBD +:100CA000EBE26D699227DE9E7E3B416F27C2A5DA9B +:100CB00011AA5E55E1417F11FF7EA41DCF90DD3862 +:100CC000662CD99D2ADF640AB80C3A69C438EA8DCB +:100CD0006374AA7F4E43C7C4734E2ABED4BCA044DB +:100CE0003CA9793DC3E23509F1C8D1DA49603F8FAB +:100CF000710CC79F1AEF7144FD5C029FA512C93F9A +:100D000087F073CDF6F0F309B5ADFC9C7C6D0D4C0E +:100D10000070FFB6F01FA8787EC8EEBF8DF347784D +:100D20001AEED3BF3BEF698A73A8F7C825E267F9CB +:100D300028F8198DCF47833F2DD5B712BF7B5E1A98 +:100D4000AAC0CA2DE9E2FE41E62FC07560B715546E +:100D5000A21F02E4EA679FE1660EAB80AEE50E7F5C +:100D600033F2F957996F0ED2D751E3D773FF3A2375 +:100D7000FFED5AB1DF9A23F4EDA55D32C507AABD98 +:100D8000131F9B8576E21B7A16A4F5EE25FDB94666 +:100D9000C07F099FD8DEC2F5EECA377F54012B868B +:100DA0004DD8AE8BDDAF00FF26069334F72B4CDE1B +:100DB000EFD094A7F4676BDA5F353056535F1A9A19 +:100DC000A4A9BFFA8D324D79DAD04C4DFB6BDEAB66 +:100DD000D2946784E76BDA7FE9EC024DF9DAC8ED6B +:100DE0009AF6A7C4BE9805BC43C51978BF389FEFD3 +:100DF000759F2ED5F4FB6DCADC37900FEFDACCF37C +:100E0000972B01339A7B267AB85DD102FFE374F504 +:100E10002988AF15606F63DEF2CAED5ABBA37E70FE +:100E2000EB0694A5897915AB594B155E49979857F0 +:100E3000516D5BA243BEFBA731C2EEB8865D23EEC7 +:100E400085F9AB742D62E3FF5B7435BAB47435BBBE +:100E5000B5744D2ED6D2D5EAD1D23575BA96AE76C6 +:100E6000AF96AE69355ABAA6FBB474CD5CA4A56B37 +:100E7000965F4BD731F55ABAE6B668E99ADFAAA56C +:100E80005F4160B5965E09F456E5E5B8AEB59A7671 +:100E900051BAFBEA291F667CCFFD9A7155BA07E06B +:100EA0007F9CEE2D94AFFEB7D29DB120F95F13E980 +:100EB0007E3681DEA0AF3E42B90076C6397C2E9ADE +:100EC00020EC79DFC876862A7FE2F57AFCBE75349D +:100ED000B9344C8F897DECA87A2C611FFB3E66F1FA +:100EE000907DB499FC3CB709FEBC8CAF66A01FF5A1 +:100EF00007A49FDF0740A6035CEF23DCF09DF79378 +:100F000026939FE10E16D2D3BDBF98890883DE8950 +:100F100089C932DEE7E3A6E732A1BF970B3F8437EA +:100F2000D99F92C3FD0FF919F8DD9C217EFFF25B7A +:100F3000695FE89E8293E887079D721AFDF0F0BC16 +:100F400060E6FC7046950F5EE676C6E16DE96C8959 +:100F5000F4323A7C703FBBF4AB12C51996FE9E3F4B +:100F6000C7E770BB37F1D9D1AAE28DEF876EC871A0 +:100F700093FECD61FDC27E637ECB381A87FBCD9F89 +:100F8000E4F78F3E2B3165BA838E49111D334D1C1A +:100F9000AE67F5CC84F87B86F9DD8897EF28209A38 +:100FA000789EFE24E487A5BF7F672CFAB164D975CB +:100FB00013DE2F3D1DBF0770CCF95A8B847EDD4CAC +:100FC000578B847EA361EF0FDD2FE1F9C26899F1A1 +:100FD00076F8877850FD73C53A1EA78EDCCDF717DB +:100FE0004F7D9D91DFA9A3355019C0F8940C0607D9 +:100FF000E6B1E8F979E41B72B8DF2D8B0DD1BDA6FF +:10100000EC3561178AFBE04B44DEFB0511E759B173 +:10101000C7C4304FA2E4E05107C67556002D875073 +:101020009F297EBA5FA364C7AB0E7ECFB8DE8EE782 +:10103000D8543D3A3ABD1576262E7F1CE8D8329218 +:101040001E5F93CBE3B31D6D35B3302EA3C2F360A7 +:101050009B7716F287AC7818C693F0DE9DF8FC33C8 +:101060008313EAE3D6AF62A9D194F5161F5D66B18A +:10107000A1AD85F84C2FEE07DA98B3D616FFBB0169 +:10108000AB7374E21EF200433B9B8B7A7C2A675061 +:101090003EFC91F17DA8D105E3C4CBB57BF358BCF0 +:1010A0005FB9ABCD47F06E90FC7E1CC458C842E6D9 +:1010B00014CC5BC0B397F07EC7F56F601E8DC1BACC +:1010C000D613728F8E37A34BB9122F971EC801B952 +:1010D000941C934BDF6D3B4B78EA685B44DF037CE9 +:1010E000318C9F05B2B87DDAD1B684DEEBC0CE423A +:1010F0007E7A65C784A36EA83F01FFF09E1CA39370 +:10110000C3C5CAF3483F2D167C803EAB5CE09F13FD +:10111000AD7AE2B37B722D415C84F7BC3DFE28DEE4 +:10112000F369005E92FF06B8A3DF11783208B904B4 +:10113000FCE4C3F566C856C8FFEBB02D203AFD7736 +:10114000C753F16B3033BA87C6906B21BFCD17857B +:10115000F37B39097ABE3C8FE4E83D022FAFECE027 +:10116000794727EE6564BFDE731FF7BFDDD3C8285C +:10117000FF9BB5C25F458C6F54799D8E3781C0CB84 +:101180009E361034458C3DDC66C293572C19FD64A5 +:10119000E36274ECF12A7674C76FAD76D6E1F3E1C1 +:1011A000E9A77B50AC6C99F5BB217CA28F1BBF6F6C +:1011B0006B6141B43329160BDFB7D74319BE9F22A9 +:1011C000EA53FCBC9C2AEA5317F172AEF739A91A0C +:1011D000014B8883E45A1CF30A51EEDDC5F8B95B74 +:1011E00071EE7EB790BB632C8EBA6AACFF1AA37CFB +:1011F0007CB5FE71519F6539D9350EE5F2426DFF20 +:101200001D020F9996933DB3295EA2AD57E31BE9EA +:10121000964B6F50FF126DFDA3A2BFD57269683661 +:10122000D6176ABFFF90A84FB67079C87CFCFE54F1 +:10123000B5FE3BA2DE8CF5F87D8FB6BE5B7CBF436E +:101240000A127DE88E585C3FE9DC5FDAD7C6AEC58E +:10125000F5D3D316A175F470DBA7442709992C3D6B +:10126000B6AE6CAD6CC4F3E092906729EEB0D73B9C +:1012700082BC53EB1D367EDE5D7619888F8C16217D +:101280002FC43A8CCA0BA9C5C3998BFBB13F8F9F62 +:1012900061815D41FB220FFE909F73EED5317F9CF3 +:1012A000DCCA6E4862FEB8F6AEBB1C9A72C6D7B2F4 +:1012B00035ED9D0BC76AEA2DE59334F5CC9B4BEBDE +:1012C00065ADE0ABA492324DBD7A0E9FF5E46AECB9 +:1012D000677DE14C4DBB4BC56EFAFD9033F3D4DF17 +:1012E00019F198502EACB58ECD44BDF34CDB74345F +:1012F000B2D9B3B09EF0E8D4013BCF2F3E807159F4 +:10130000B4D7DBBCF47E1FD483E5C29E84F5E686A9 +:10131000F67BDA6C547EA2CD45CFDD6D6E7A3EDE73 +:10132000564CF53BDA3C547E0CC6C7E7A3300EBEE4 +:101330007FA4AD86CA5BDB7C54DED2B688CA0FB50B +:10134000F9E9F99DB67A7ADFDDD642E58D6DADF427 +:101350007CB02D40CF8EB62EAABF46D0FB8038C7BA +:1013600078A0929F4B4EA4E3AC5C49732F983596BE +:101370003F302B17F307FAC39AFBDD71DE349E99D9 +:10138000CF3F71BC3A1C0FBE3B890DB527F3754C9E +:1013900071C7F1039EF5C9C0EF635A381D0A0622D2 +:1013A000549F55CF695127E065CE00CBA9E0C750C7 +:1013B000B1DD0569A82A99C76129BF8CB9609E155E +:1013C000E27E1C62BBA00EE152A673BDA9D2353AE3 +:1013D0006F3B8713E73F12BC5F13F397CBFBF9FD1D +:1013E00017353D2164FB246F0BDD7F615AE40BE16F +:1013F000EF57387D7E3A8F3FE9D3B9B0B90139F361 +:10140000E997991B9E390DDA7D4FF65D659AFD854A +:10141000FCE9C3CC7D358C5BA2DD9F2415AED5F4F1 +:1014200033E5DCAFA93738D76BEA97AE29D8E0426D +:101430007C8E61149F316E6E6718525CDEBB95E046 +:10144000DA24F07E4172D379DEC041353ECFEDF330 +:10145000EF09BDC24C9B693D4CB0F362516A4087B5 +:101460007AE1DC8F52491E3DFD842E88FED7892CFF +:10147000A8C3F53F19CC3DAC9F8237E8CA74A58A52 +:101480008CE552E696B17C358BD0FE04ECF3F5B9D1 +:10149000DC3E7FC28CF1C15CFFF778DE5288F466D7 +:1014A00091A06791BA1FD9AE24FA65BB72890FB5B6 +:1014B000E7993A859DDE6EAFC8C4B8E88551F2CA97 +:1014C000ACAE9933F177B4AC59D3E9A9BE7FC8ADBE +:1014D0001BF19CEEE3025F2ADF4F0426177CFF38E6 +:1014E000CEE37CF9BB19B8DD6B2A8C10FF5F90BC92 +:1014F000AE2588D73765CE878359342F45E05539D7 +:1015000058E95A02F853DE1EE709B0D8779E6EF309 +:10151000CE549458B948E445EE6FAB9B591DF7FE85 +:1015200075014F311BAA41FD545CA2F30469649715 +:10153000467E990B7BBC78CE5C29631E146F1359D1 +:10154000CF7AD4D5CA5F64CA73518ECD606ED81776 +:10155000582C21867941AF47E7C934BFAFF43B5BD4 +:10156000752ADD17981D957BA813F1F79486907F57 +:101570007ED7ABE7F33AA6AD2FB6F0FC9D15C58636 +:10158000A05BC2B07A0FDD8BA7F4490C4D7FE52F2D +:10159000B3090FEC8564E2BFE4ED53E94AED9B1417 +:1015A000FF0F91BEE743EE1774E3042F42BBC6C999 +:1015B00086BD688F4D40BCE0840A8B09AFCBC57CEB +:1015C000F7B72D213CFD5ACCA33337011EE6F1E2DB +:1015D000BD912B7A55FF87769E0F9557DD8CF7ECE2 +:1015E000750CC9C256D2E273937E682AFE36DDF9C5 +:1015F00030C025139CBF46FACBDB2BE8F795408122 +:10160000D0FC1A9F80FD7E01C9A31AD2DBD374944B +:101610009F9AC857A7841C6BC9E5797F56D79767EF +:10162000E2EFBCC5CAB3883F9FD1B162CA2FD1F1E6 +:10163000FDA59ABF0186831BF775A579BAE83D1A07 +:10164000F3515FDB7594F727EF49A2F389B25DA1EF +:101650003CE34E4BB56D358E635328AE32579E3505 +:101660008476B3D1AEBB1AEDEEE37BEF1FC2FC1262 +:10167000395761E82FEAB429DCEEC8D1513E9662B1 +:10168000AF36611CA6C872BA12F17974CF37C9BFE0 +:10169000217F43E488087F925E90AC93B5D0F881B7 +:1016A0001C45DCE7E1AD2DCD10210437EE7F6A3E0D +:1016B000423FCA71DB2533DA2B6ECB0AF2A715E65F +:1016C00015D07CF4186F83F213EB2ED9516EBDB98F +:1016D0006783A300EDE7A0423648F19F3BB2E9DC07 +:1016E000F91E039D8B57F19A1F503471BBDC566D68 +:1016F000D99810BFD3279C4BCACA2B107A6E110BF6 +:10170000C5CD47EFE2FB35E6B4D07EA7304F629FF0 +:10171000E962E531A2BC5F1FC8F6007E8EED5991EB +:101720008FF3BA72D84F79BEA3D9FB1FE7BAD5DFC2 +:101730004332EBE87ED59019F37E9F6A63E968DF58 +:1017400099820AE55DEF13F2ACD0C2F9DF90CFF9D0 +:101750003CF159D8C3D79D722029988C74B3F59762 +:1017600005804F26BF328FB941FF15DABCE43F2C0C +:101770006C35A463FEC0DC1F5A884F2E5992C84FA7 +:10178000A8B42679F07DC7DE8A62771CDCC1365B9F +:101790003AE6E5EC6D33A5A39C0A8E225FC7D975A6 +:1017A00094AFECD6F17CBAF9791CAEF979FCBE970E +:1017B00079A2FCA4125880703E09F4C43CE9A39BB2 +:1017C000B93DBCB6DD4470AC7D731CD955A3E1EDC9 +:1017D000E936573ADE0FBF77B32E1BFD4795DD85FF +:1017E0009BF09E84B5567E4FAC9C3AE9314C4567E0 +:1017F0003FD533B4DF3B52667A96C5C97739755603 +:1018000031F2952C07B2D12F7267DEFC9B315F124B +:10181000E8B713CB2BFB4A79D91AC8C6FCCAE6BE77 +:1018200069BC9C1ED889F995DFEA9BC1CBB9816C54 +:10183000FC1DA9B6BE6B79797C60279637F655F208 +:1018400032FA9E40766EE99B7333CAD90E83A71E87 +:1018500005F20F00FE1280BF5F3CB70ABCA8F5CFAF +:10186000E17BC0F321F14CAC7F41F41B18A5FE25B0 +:10187000513F38CAF82F8B7EA151FA1F13FD8E8F6E +:10188000D2FF35D1EF8D51EA7F22EADF1A65FC9F46 +:10189000897E43A3F47F57F4FBC528FD7F29FABD59 +:1018A000374AFD07A2FED709E39F10EDC3E2FD58BA +:1018B000EBE60F42C07763418EA05C2AB66E76E0FD +:1018C0003ADFDB554EFCDF51C1E33B2ABF8FC5DF5A +:1018D0006F827A5D3EBF4F4A97CFE33CCF88F1815C +:1018E0000FB720DFAD7D5BA63C9B0E9DE76C10E53E +:1018F000E8261DD9036BDFE4FBF3B5DD4A30FEFCBF +:10190000C53309F06F10F0750A789FCCE3F139A365 +:10191000CB955E1BEF47B269CB9896857217E4377B +:10192000E5ED167757751597638C4C471688D26886 +:101930000AE17D0D8A55E8055B794F31C26751E8B0 +:101940009CBA625742FBB1BFAB9CEC3B15BE4E8BC1 +:1019500042F775C956AE07E6FE70960DEDAC4EE641 +:101960001FF2627F9742F6FBD1AE321BCA3D83F570 +:101970002E1BAEDF76379F5775537112CA6BF92154 +:101980001DC9EFE336BEDEFB5C3AF25B805EA1F37D +:101990002C20AF3DA82326B0503B9D8F78F885259D +:1019A000DCAFC7ACA515745E448D434B4A9CFD7FEC +:1019B00059E0275FE81105F50B3C9F2C17E71C0247 +:1019C000DCFF0464738D893BAF79394FE6E740D47F +:1019D00038A25C4BF716E5AD5334FEF79C7BB5653A +:1019E0004382DE5012F4CAB82E9093717AA7206019 +:1019F000D3944FE609BF8E8779D07E9DFBC3CD245B +:101A00000F2FA17E9346977B51F92BE4F193E21EB1 +:101A10009E2703FC1CF1D1CD653F417AAFEDD6D1B5 +:101A2000BDD35F548E3E93C7B87FDA0F7A07ED19A6 +:101A30008565E37EE9F3F0305EEF73D0BD0A9F83E6 +:101A40008FF18F963B50DE8EF72BA47786E98DCFF2 +:101A5000C1D7B392E73D3FD2D19EC4ED6A1B9F77B9 +:101A6000678693DF4724CE1FCAC25E7B50F8C195BC +:101A7000D4B96EFC89904E7B0B9537489ECC1BA049 +:101A8000FD46C96FC3F21B8E24AE777293880FF7A1 +:101A9000A32D43F71C16F8D03FD21F34A8F71486A5 +:101AA000F0FF0E627E8E7A0FA28BEC33710F63EF24 +:101AB000CDD5D85EB14D469373DA138F6DD1830DBA +:101AC0007AD0C0A2EDF13CD533C775E29EC4DD5B90 +:101AD000D05E3D98C434F7401E443F3A8D17DC82F7 +:101AE000F73EC2F76E90610F767DFEF7B658B26290 +:101AF000F054B90F6C69A73C59BE2FB1337E4FF734 +:101B000079773805970BEC4FAECAC77DF99ED3198C +:101B10009ADF5D13ED5345FBA6C148D30137B59F4E +:101B2000960FEBA07120925242EB2B5211DF3E45F3 +:101B3000ECF7E3DA7F89C61FA57DB10ACF81776F05 +:101B40002DE1ED2B71FC0BEE7006E5BC24C0933645 +:101B50007CFCEBFF1A3C9344FBF3A177A9FD05162F +:101B6000CE985240FD6EC27E17DF7AB742CC3B035F +:101B7000ED64908A37E37B34B7F8EFB1B490FDDCC5 +:101B80006FEAB1A1BD66D6F7F850EE16E2BD4ED3AE +:101B900063CF05F985DCAE4A78DF6F6269B5C88F1F +:101BA000AD3ADABFF49B86CA4AD09E7ED102320F8C +:101BB000F5C23A0FCAC181F05A4F09B4EBCB99452F +:101BC000FB8A8386967E3ADFBBC442E74FFB6C3DBF +:101BD000365C3F667B8F0DE308F27DDC7E52965AC1 +:101BE000FC4F213F85D6162F8F5BBF556E3DC1DF61 +:101BF000FDAA6533EE03BAF59E9E0968675B15CAB8 +:101C00003F57960ECEA7F3823FD03192EF30AF2AE6 +:101C1000287736EAE8BEFA87DD4BEF413C30C5E76E +:101C2000AB827E79E98A84E72F1E547C268C5F186C +:101C300085DDD6E7E1BFF7AA7E7787B02F77E4F39B +:101C40007BABBA971C287E0DFAF5B5AEEDC7EF99C0 +:101C5000279A18E699F5E59CE9C6F3A28FBB60C701 +:101C60000B78B034E8E8F75A1EAF8536A9E8CF30D4 +:101C700068FC15CF4AFDD43ED0A8A37D82A5C4A0A0 +:101C8000F16FA435E8BCE8773CE0F66F427EBBFA22 +:101C90006DE506FC9E6BBC6243FDF490EB17261DC0 +:101CA000C09952AE1DD7364B3B8EA35A5BEFACD5D5 +:101CB000D6672CD4D6BBBE6648F0D768CB29C847B8 +:101CC0008847900116D04349BC8A2559AED0EF858C +:101CD00075FB77F54C8036C6E440E96B006FD2A403 +:101CE00024DAEF6F7C3509171FC81F467267E314AB +:101CF0004679AFC772BFE9427D9A889FBE1C03CD6B +:101D0000D75208F82CC0FDFA59FA5D2F0B8B6B5790 +:101D100080F8F13E93CFF7EFCC5581FE394672F053 +:101D200059D57F7C0B3F4FD5D7CAFDD20F2DE27915 +:101D30008134830A5CDFBC7D0AFECED854F4DB77A5 +:101D4000DD8DF98E8978CDC4FC3239C61F1BD4F3E2 +:101D50002B787AB2828B655C7797DCFCFECD970599 +:101D6000DF1C14F72D44DB23FE3218DFCAC2786F64 +:101D7000E6ABFE077E1E609B1A8F1165BCC610CBBA +:101D8000078F3B6EC0F5B46DA1A30CD7D346619706 +:101D9000A5E618BC1301DE47DE3004A4ABA0ACB04E +:101DA000E37AD0E7071DFCBB86379302789EEA11E1 +:101DB00057399DCFFA389FFBF39EABF4FCBC96D607 +:101DC000A342E7DF1E717ACC65DCDEC0BBAE19A58D +:101DD00016816971B4B68CF6A98F783D665CAF8FB9 +:101DE000E478CC989F6CCE526CB88E1D2E85EED1C7 +:101DF0007AC4E4B7A1DDE2000588BF1F67C8ED998A +:101E000047E7920087BA0A1E1260228F0FF3E8D2CA +:101E100004BEFA5C77D9F0FCBAB3F0D0B7D0AF9E6D +:101E200086E3A5F07E8827BBC0D3A57C37CF4B16B1 +:101E3000E3A7DDF51CB5C7BFCE8AB8F13C9CBF0C4B +:101E4000F358907E074D7C5F1D273A3EF392DF7E6C +:101E5000C34F38DEDA73F9FD4186358CF661CF5514 +:101E6000FAF71F45FC6425D13E3BDB955D85FC916F +:101E7000FDC6CE05780E61C34FB8FE342CE7F1A63F +:101E80006C8599BE8CF34EF7DB108F89EB30EB78C5 +:101E90004F1D32DBFF054658D4C60080000000000D +:101EA0001F8B080000000000000BD57D0B7CD4C503 +:101EB000B5FFFCF6954DB249360F424248D8CD8B5E +:101EC000401E6CC24344D4E5114445BA913722FE0A +:101ED000420204482080F6A6D69AC50445C51A2AAF +:101EE0002A5AD48D02C58ABA5440ACE85D1E5AAA5B +:101EF00056D3AAB7542B4D842AC82B86F65EDA7ABD +:101F0000ED7FBE676692FD2D89D2DEDBCFE7FEE373 +:101F1000A71DE637AF33E79C3973E69C33B33B9399 +:101F2000D82D3E076349136DCC6567F4F777FEBF84 +:101F3000740B5B674E622C650AFF5E10F63D2D65E3 +:101F40007C7E0963A9D38DF5D35858DECDEB1DEE09 +:101F5000BC8DC53336A0DA58EF89D8A3A5CC845CF4 +:101F6000D877F3B7E79BB5F67B078F60CC9F6EF110 +:101F70006C75319619311E635F4721AF3193EBEFDA +:101F8000398C8D772532D60FDFEB5DBE62C676DAEF +:101F90009C131C298C75AE649EA779FBF12FAF9F13 +:101FA000FB36CFFF67A6C319C56B651C6E692BE2B4 +:101FB000DFD95E7D30EA6FB6E84FC5F2F2CD47FA61 +:101FC00033BFC658542CAB0F723CD94C4C47FA77F0 +:101FD000FC5D8D71AC34CE78179FD448C67817015C +:101FE00053DA3F9F06070E2C747AD09FBBCDCEFBF1 +:101FF0000D5A9C85169E1FF9D4A30F5A33310F0E2C +:10200000E3189AB6978D66ECB9437CDC013CE77F18 +:10201000E2C189165E1ED35DEE47F94E9349E4FD99 +:102020008107278E656CE0A1E01A8793B18AA7B675 +:102030003F68E7788BFE9528F7F1BCDF02BCD40E31 +:102040006AE7F33B90B594E6DFF4BB2816C5EB15C1 +:102050009B3D9B90671F47B3AD3CBF7DF7D8D92E02 +:102060005EAF296E944B2F626C9A4BA3F95720ED0B +:1020700077F1BCCC368FEE715CFCFD7A8937C63CBB +:10208000475A397D8B9FB1B1FB786101E006BD5A9B +:10209000A3034F83BE2D8F72A663ACDA29685EBDA1 +:1020A000E7BEACFD3C7D25AEA2CAC5DB57C74D4C93 +:1020B000053C191718D39339DD1AED4CE7B8CA4817 +:1020C000F999C6387C03530E8D630EF04DDB1A2749 +:1020D000D2FA18A687F165C6050BD387A33F2FF563 +:1020E000873F7B2AB850FC3527E96C0D87C7CF7135 +:1020F000BD15DCE98CE9D04AC0F813BDED6A7D64FA +:10210000834FD9EC6011B84EE0C1C6716A2DE3A9C6 +:10211000C3128AEAA5FE6DB29ED9EE089987F1D462 +:10212000F9E611EAD76139DD6EEFA9670F58081F8C +:10213000AC9605F234C2933F0AF98424CA33AFD770 +:1021400095920AFE6784DC0C0B3B14C5C725EEE5AF +:10215000EB279D85287D82A3C791834A99899FC5D6 +:10216000327C62E0E3A7199B1CCED72A350D3211D1 +:102170007CB90DA67EC7397E0A0F46131C96752CB6 +:1021800010CD07CB053D38DD72D7B380C58D7AB64B +:102190007EC793D1CE25F9C06962345E7028D6D54A +:1021A000A6371DEB5902D197E4CEA61856037CA999 +:1021B000F1185B43FC10907CB1B9D1497454E5032C +:1021C0006B0F44D031C94047552FE3C200A2674F7F +:1021D000BF01EA2FA36117F143C6852CC927AE6F53 +:1021E000E93FBB8FFED3A87DDFFD0FA4F19F087DE3 +:1021F000903895A3E2C79DBB127D3C8DB6B6F83CE6 +:10220000BDE039E356A39C1CB6D72877155EA2AD76 +:10221000DE940A8EFFE8DB4C9E56DEDF65478CF5C8 +:1022200026BB3F4CC47AECA91F4A9986FA75A2FED8 +:1022300015278CF57DE37647D417F05D7DC1582FC7 +:10224000923E91F072B8FACD08836B823DCAD07E7F +:1022500076E54570F59B1506D73569C6FAFA9ADE1C +:10226000E1BABE20EA1BE152F5BE33FAD2EA45CE0E +:1022700063DAE4A83EF02EEACF9A7D69FDDE54F3DE +:10228000CDF56E69881CC72FF72BBEB6F83A4EC63F +:102290003FF812486E3079A3F93EEA649D0CEBA832 +:1022A0004BAEAB24E6A4F5CC17BE8675F53EFE9981 +:1022B000CED810B7EF2BC8AF0976EFBC8779D58998 +:1022C00072BF6253788F97A3735FF18DC517F31FA9 +:1022D0006377115CAF6ABACE689FB57BB6F2F55DE5 +:1022E00098C1ECE95C0F606981EC1BE3188B752BDE +:1022F00079CD450D8773A8C4DDF30382AB12699DC8 +:10230000079200CF3F3A6E7FB737C9DDAFA77E6433 +:10231000BD9EFA024F365B7025E0ECAC7378B03F9F +:102320007C8022DEEE9999512133C7D739AB639D6A +:10233000C6E5CC91D8F96FF6E378783F5E77A1FFD8 +:10234000D9B3AEBD1B79ED40B26B1587EF5C65FB71 +:1023500028E0D51BABE7BA391CB5767D502A9FE241 +:10236000994C7D7002F0EB4B26BCF27F14FB7A8512 +:102370005FC0335113F84F4ED08B31CE4453DB93B3 +:102380003E7CB3B48D423BE6EC47F09DB17179D70A +:10239000CBFA5778182FFBD96FF57CD5C9E7B77FF3 +:1023A0004382A789C35B9D3C6BFE0A5EB4D0E44BBD +:1023B0000D990D705F81F16A1D9583D201B755C2E9 +:1023C0006DEF27F1EECDFD26B89B301EF6B51F68E8 +:1023D00081AD6E414BE45FF62706EEE3F928D3F9B1 +:1023E0000F203F3A8B4D1EBE47B0CD5CBFB0F37D92 +:1023F000E53D89EF27B8FA634FA2EFEBF03D2D469C +:10240000B44F7BC41468E2ED7DE35F213A3DB3DC59 +:10241000E131F3B12A99CB06BEAD625E1BE0FFE36A +:10242000B8BFBDD6CEE737C7AD4FC73C6E4936659E +:102430007D4070E885159CDFD85881FF6FE307C6A3 +:10244000D69BD828C66E94FAC14289C769CC6BC5A1 +:102450003833986EC5B8BF396BF3422FFD0D7450F9 +:102460000EEF2CE6A7EF735880D29B5888EADFCC9A +:10247000DA29FFEBD892CC060E5FC5A383F3B01E1A +:10248000C3F0BE54F2CB2D29825F3EEF0FBC6FEC40 +:102490007749FC5BA109FC0D71EBABDDB45E5D29F6 +:1024A0001EC0E49C30D01717B67E26F613FC677169 +:1024B000E67DD3FA69EB8A2F61C3481E38D2391EF4 +:1024C000AE91A4BCC6BB6C0AE60B0982F5FA1DB935 +:1024D0005ECBCD0E96C2E9D2E63207A2382C93C766 +:1024E000AD4CC37C7FB186FD6A38A7DF2FC69959F2 +:1024F00013D5F452BBA9B2BFA903279D847EF20E67 +:102500000BA58CE0EDCA2FE88712387EA69A7734A7 +:10251000738D9B4D1E68FDB43D4CAE5D9BB2D3C226 +:10252000B8FE725DAEF1FB94229E0F93BB5399A54A +:10253000A79CD37F3FF003B9C35ACCE0DF47DD71DE +:1025400029D057D85036549C0F3835C2E6D365FF92 +:10255000DA768EB77BCBAD3F093E5A9578763EE969 +:102560001D16319FE5EF9A49AFFCB49181F3D87104 +:10257000AE1F7AF319FB8CEB17C89F684CA3F40BC2 +:10258000AE0F203DDD5840E5671B3D94FFD2EDFBCB +:1025900009E8B460DD9716EC4BF7442B7C0B3856FA +:1025A0004BBEBB2773D4A37FE578BDE71DBE303893 +:1025B0003C35C19649007B75E6A777417F5EFDAC4F +:1025C000E641BD65FBBC36078767E121FD6E90796A +:1025D000F13BED532126EAA0BF72BDE15EAB6F3740 +:1025E000C61BF9E1F1549D57F0EEEB783399D7FF14 +:1025F000BC7134C175B2D14B709D6A9C4C694CB6AC +:10260000EF55D4F7B22F6DA87FC38E0E4B06AF5F88 +:10261000EED5BC588F57795920C0E1D96415F27DA9 +:102620001397EF589FE38A6F7CE25606F9ABBF81A0 +:10263000F63392AACA93F9F7A9A32B2DA837EB2B4F +:102640002ED3DC3D7CF8EDEB50E0A34ED2E5CCEB95 +:102650001AE1E9CC9EC2EF5CC1FB7BFDB0999939D0 +:102660005C5D174C0457D79198009456556FD56E02 +:1026700033E993AB326D01E06FD5EEC2FED0A74EC9 +:1026800071BAB1FC9EF14E3DFF6F2E3D4C8E9E4ABD +:102690000AFEE74790539F0839C5F5CDCF1E871C2A +:1026A0001B38C003BA9FB572BD1C8866F5B1D8C788 +:1026B00096DBE4FAE27206F95331E21C3CEA858CBF +:1026C000F1582F18CF65EB9143F92F3C9AFD7D57B8 +:1026D000CF78DB830B3F7A9CE7CF044C7E2BDF6700 +:1026E000CEB0E0D99F438E6E7178703EB847E3F06C +:1026F000601FDD3A80F2059A25A681F83940EBB5D6 +:102700004073591AB8FCA9FDD96303C04FAF721CBE +:102710008CE6E5AF6E8825F9F4AAD573B401FD3DCA +:1027200021FAFBC90FBFF7E95EA40FD4957D0F48CE +:10273000CE4E227C57FF68C950B4E7FB344BE7FD0F +:102740003DF7B2168AE6EBB378E3FEBBD2397CC321 +:1027500036779806F0B4748BD684B430F3BAC36677 +:102760005E6ECF76111CC377B8CD19585603021F81 +:102770005D4DFBB7715F2FDAF8E5781C2FD5FE3E73 +:10278000540B7ED18AF370D691329DF0D742FDEC86 +:10279000DE37EDFD9B18E6C13507C05D69F3D07EDD +:1027A00012F0B782CE67F402CF7D58D33EFF63A00C +:1027B000EF193DD583FD658FC91F3F06F58F5A6818 +:1027C0009E2F6FF975BC95E713765959342FAF2BAF +:1027D000ED9C84FA75992E3A87673E79CD64E0675F +:1027E000F9AEDDADD44FADDDA3619DED3EFF6606D4 +:1027F000CE43D7324F1EF86E97C8DF3FD1EB01BFF3 +:10280000D5B4FE59E4DB7C94F799FD6E0BEA5709C9 +:102810003DE751B98FB1F6129277C4CAAE1E7ADD88 +:10282000CF8B51BEC9ED4FAF77F4EC7F7CDF2ACC64 +:10283000E6E5E936D9DE392DCBF70FEC5B36B90F7B +:10284000A9FE1EB5317F34EF27937FD7B0AFDAC42E +:102850007EBB95CB17F08BDA6FF9B857648BF65EB9 +:10286000C8C90CBEB996F2F9643C1A15A03DFD1218 +:10287000C7577AD28A1821CF94FE313BB9E9B57691 +:102880008ED73FC5EBD7607E0BE57ECD2C9E34CC3A +:10289000EF58BC7732C6AFB57766610E7C3F9C823D +:1028A000FC7233D79F72C2F427FBA5ED875109DE76 +:1028B0001BD1FE52EB8F8DE95DFE8EED1A4DF2F7C6 +:1028C00035297F57FFD9C44A797EF5C351244F6813 +:1028D0004FEB052FAFF1F5AE73F9F2EFB01BF0F44B +:1028E000CA3FB59BE9FC71C854FB26DF4F69E86C11 +:1028F000FC5F6753C208CA7B41E6ABFE64EAF57C25 +:10290000A8524EA77ACCCBFB95D1DE70F5574E1B63 +:10291000F5EF48BAA4F99AFB98AF395ECC771FE679 +:10292000CB69B7FACB329297FB2E719E9951DE3567 +:10293000A06FE43C38DCF7E07B24DCDDFCDD79696A +:1029400070DFA631BF09EBEC4B5B00EB6C1F07138C +:10295000EB76DF92A200D6F31E9BC8FBE36DA47F4B +:10296000EE8B637EC88F7D15A901BF1B729009FD98 +:10297000B41F13E5D1B2FD9C546A3F208AF33FCFC8 +:10298000B39B6264FFF56F17A37C4D868743C0F548 +:10299000DBC0BA6CD26FCD64373C22E5F5C6C4D03B +:1029A0004D66FE7DE397F90CE31C61A18C15A857D9 +:1029B0001343726863A2373D89E371CFD766DA1794 +:1029C0003696F2BC83E434D977365678D313797EC1 +:1029D000AEA4CBC6D6C0D647D05F4581C7CFC719F6 +:1029E0006066F554CF2DFAF9C82ADAFD4ED285AFCC +:1029F000635AE7EF672F0801CFFAD4580BEC221C7B +:102A0000E3E91A87FFF1EA3C46F252DABD664B1A57 +:102A1000CCEDE103AF7D14F45AF13767E1D668C815 +:102A2000E31935D164973A5273579C8B8F374337EC +:102A300087A2A0FF4D2F37D89DDECFF6D2B8FC601D +:102A400021CF09A12AE0F1F54E3B835CEE8B9E7508 +:102A5000C171C9C7C3F8A1C626E4C709A90FBD1231 +:102A6000A7BF0B7E5FB1F7DAE4E361FA5EF5C2F26D +:102A70007CB2FB565FDAF9AE09741A46EBD56F02E9 +:102A80007F04A389FE936FB413BDBB1CA6A76197F7 +:102A9000BC45CAAB261C84F9F7A6DD5181BBF8B74B +:102AA0001551A19990579CFECF6E035D5F8B26FA5E +:102AB000D7DA043FD5FEBC90F86B8FCDEB5E8BFE72 +:102AC0005F8F22BAD7C6BB12A8FCAD6426F98FF47B +:102AD00086DA98507E22C7E7BA58FD24F0C6F98EF0 +:102AE000ECC1B536F1FDA8E4ABA3BC0FC0E1AF8FDC +:102AF000237E6432AF7F3F99CE535C1F25FED51FE6 +:102B00002CA4BC6EF3A62FC4FA58154BF01D95F6F5 +:102B1000B4A3B589C4DFF31E5CF60EE3F43CEADB34 +:102B2000766F3EAF77749FD5837DE9F70DE6908D84 +:102B3000D3F5EC1DC7466DE2F9F6BB3ECED2C3EC31 +:102B400068F3EEAA9B8276F396DE3115FB655FF89B +:102B50009E571BC5656E0F9D5272BCE61C8E7F4F43 +:102B60008E6ECBE1F35C51D4BE0872EFACADED4993 +:102B70009C0F3E4AD0A3F1FDDC2B9F6F237968E9BF +:102B8000CC877EBEDCC2F9007C29F7CF15922F5F7F +:102B9000CCD113509FE38FF4F1D8A23621F7EEB8D1 +:102BA0003439FFC5BEAD7B343ECEB2987DCB2935DE +:102BB000074AD0CF292D14AFE5007F5C8FE3FD9D40 +:102BC0007686E241075D9E9B966D37CE0B7FB0AB5C +:102BD0002CC33F78BB654133D955F8FE6E03FCCB5F +:102BE00060E935F813845CE1FD3C4DEBD0F1FBF975 +:102BF000DFE7F85FFAEC9032E893CB12F7FEF00AC9 +:102C0000AAC7DB293E375F9C57F3B9181E31BFD3E3 +:102C100092CF4F33290767DBBACFE1D083CE3EDFB7 +:102C2000DFC037679F1D42F92FB44E2D86C37556FE +:102C3000CA23E6098EAAC001C21B1C057DF611F944 +:102C40007D59727014E48F9247CC1E2CA17375418C +:102C5000B004E74925CF982F984FDF03C17CB4DF3C +:102C60006312760AFAC3BC9FCB68253CD8C57A5C50 +:102C7000FA5C21E1458D1349BFC8F94ECD11FE0123 +:102C80000EEF2D3E5E7FF0269BA17C48C0989F29C9 +:102C9000EB0F8AA0CB0073E7FE28C8FB6718ADD7FF +:102CA000C8716FCE11F6F49FFEB49B0E66795E6418 +:102CB0002E457F97D0B7ADC0F7EFBAF17D6B069781 +:102CC000A7CB30C7EC9EF9EF29D53320F7CF9A84F4 +:102CD0009D7A4F22CF1741CF11F8547985C7483ECE +:102CE000BAEB778B32E04F5997D3EDE7E80F7E6B65 +:102CF00082BCE4F2A2C92AF0F14563CDF0E3169C50 +:102D000047EBD3AB2D3DF359B4A9D48EF5B278730C +:102D1000A97D41D879A769FBF0C32E4E97D3DB2D4F +:102D2000643668B2047E083DBA69BB39E867546E00 +:102D3000F7F2FAA71D07DE45BD459B13CBA0F7AA06 +:102D4000F68B37DD965E1D86EFC2ED46FC17078DCC +:102D500079D8A3C3F33F822E38F21F6F571A32E699 +:102D6000871F36E63FFFE0D69960E397470B7E3F2B +:102D700011880BC04F55F3F1A4C3D8D74EEC793965 +:102D80001EF459F649F59B38B72CDE64E4334E3710 +:102D90000D7ABD7F9B46FCB12410B9EEE47ABF6882 +:102DA0003DAE5176CD82703E89A4E729169CE9E5B7 +:102DB000FC54DBB06A38FC21355338E372782E0FAF +:102DC0006EB0C16F10395E5FEB9E39BC2ED8AB2A56 +:102DD000478BB2310DE3D931187DD7FF7A12D65B1C +:102DE000E5FD1AEDFF952F0D3E04F9DDB173CE75AB +:102DF00094CE9C4C7850F6B3C5FBB4501CCF3B47E7 +:102E0000BBF6B6F3760B031AED0F0B9AA37AE41018 +:102E1000FF5FF5FA083836869573F817EFDDFF1770 +:102E20008DF75FB3D9D86E09C717E4FED22D7F8F17 +:102E30000AFFAECE7D63F6B59A31EF850A7EFF5567 +:102E40000CF3122E482E3AA4BE721C192EEFA39238 +:102E50007C6DD85FC66C14EDB8C0AAC47CEB1C3680 +:102E600017E65B6767A1580EC7E1389BD7C9BF9FBC +:102E7000DF1447F6A945515C2F2CA3944597A19DDB +:102E800087F6E9CFDE3393BE5287B1D1CF531A9D77 +:102E90007FEA606C44FE19915FC242340FF08B37B9 +:102EA0007C7E01639EB5887353AD25B41FF858CA64 +:102EB000DAC5B987D3D11BE68FABE5F33C92047D2D +:102EC000C8D87E050B52FD157BFF1E15FE3DCC4E6E +:102ED0004AE73975AE34DB9817FAB1F9CE18DAEF54 +:102EE000B9208E017FAED5BC8FD9CD48C5BCFC1BA7 +:102EF00084FE33B755EC175C3FCD077E366E18E283 +:102F0000819E3297EBD9D1D02396C450BD8D898C48 +:102F1000EC2B1BE7E40B3DFBEB974218A7F3618D0D +:102F2000EC231B4B45BF1B1F1842E590871A8D13DE +:102F3000457ACBC60A559E497AD247002D1D7AAEF6 +:102F4000FCDECF45DF0798BDF9D0D7D943D174DE79 +:102F5000577AED33497A7C6EBF9EF92A3D98D55C4D +:102F60009AFEB755EE779D1B84FFF7B8E67BD31426 +:102F7000A6970ECA15FBC3A8F1DE6DB21EF901AA11 +:102F80004D15F75DCDE1A97EC4E46A72F7E09D7945 +:102F9000BDF998FFF10DD165E0B351E385BDE76858 +:102FA000A990DBB1239837C0D3825CB17F14E49A37 +:102FB0000C695A0CE73FDECFF172611F8E1BE123D3 +:102FC0003B1BD7D9487E47CE638484AFDAE67BEBE0 +:102FD000CA5EE0E9E6838942CF38BE527B5AC0C55B +:102FE000E9CAF3A37E144DF6B9E3725F51F8E77CAA +:102FF0003392F66929AF36483ED900FA633F5B2227 +:10300000CE413D7C62E483B99AC02B7B40E8A71B8C +:1030100013455EF1013FEFB0BF824FCA19E1BDAF6A +:10302000738F9AE7C65651CEE93D05F48E3CF728DA +:103030007A334B6024CE8D7DD17BC1E8C4519A890F +:10304000FCD67EF8ADB1D7115EEEB504EEE2700CA1 +:10305000B408FC675A047F71A9EC8F29A3FA5E1BA0 +:10306000CF573EB4987979FDCA0C46F6205E9F256D +:10307000A03EEF06712CD82BD0AE3241F45BD99F25 +:10308000D13981FEB8BCCA459A4DFD7A4D49A27D21 +:103090007C19B5F79B447BAF85A78372843EDFB96B +:1030A000362AF034E4F33D99F9E08329E38D7CF08E +:1030B000EFB962BF57E9D03C97342A79D2B0BE1736 +:1030C000340FA1FDA229DA57B71B747B5EE8FF9588 +:1030D00077DF7CC348C0F742B207E07D317527F93E +:1030E0001B1634CFB9ED439C1BB647D3F76BF2F4F4 +:1030F000DB7347420F74CDDFCD3F2C9871D096C65D +:10310000DBEBC18A333FE7E954FFCE77A10F4C9D3B +:103110006EA6FA5399B08FB26631CE0DFE2F2D698F +:10312000BCBF1BC66A1433D011EDCC5AC9E1AF94B1 +:10313000F4BB5BF26F53349BFD3307E0CACCCFE6A0 +:10314000DF6F8086D98BFFEA90AA3F4EDB0CBD660D +:10315000D004B1BE547DF4837EDF92EB6983C48BCF +:10316000CA73BC52FDEA75511D39F148ADA1C13C8D +:10317000EDCC1FFF30F86A4A369BB40978FF9E19E0 +:10318000B10A1CDECE4A5AF771F92EF0A9CE588842 +:10319000E223024388AF3BC67576DCC3F31DAD83E3 +:1031A0003D64F391E7E885385FB9502EE498922F9B +:1031B000479DED71C4AFF25C5D2559E38F0D131E81 +:1031C000B98CD7AF72D83AB01F2C7C785A3CE24CFD +:1031D000AA369A453CC77AE3B99A9F7F5F045D227D +:1031E000CFC991E761F00CF8A87ABD467C38A8C930 +:1031F000634B2739A63931BF6A472817F2BDDA1366 +:10320000ED41F9E9466FF2F15CF8232653CABEE2BC +:10321000781F057B2CA3208E0379FA3EE0A9B2A586 +:1032200092CE8BB1453AC9A7BFE5BA08CF53604FDC +:1032300084BCB1B4A7631DD6A9EF49CE7C07F17356 +:1032400034031E3AACCE7CC0D5B136DA847D73CA65 +:103250005D82AFF93AB35B78FB7B2D2C06EBFD3E2C +:10326000D97EDE1A8BAF95E707DA99252E097C55B2 +:103270004A7C5D3658DF003C9CF8011B8DFDBF6A1F +:10328000FD068247F105B3B44D4C867EB7D55D7619 +:103290001FEBE1A3B2C1E3DF47BB6E7E98AE111F07 +:1032A000F0747F0EF1C38D47503E657C2877551131 +:1032B000FC58B5CC0B3F421AF3C01ED0C53A499F0B +:1032C000E8E2FA04E49992274A6E703EF022AE4793 +:1032D000D157C98F6D8D1C248ED7ED8D764A7FDA3C +:1032E000E864162E037634A651FE854617A5C1C69E +:1032F00002FAFEB3460FE577358EA6FC9E462FE513 +:10330000F7364EA6F4E78D3EFACEF1427248C91563 +:10331000258F143F29B914C947F3397AAF2AA3F688 +:1033200024F794BCC33C4C653DF248D1375BF3F9BC +:10333000D3DC9063ED73202FCACDA79F7F197692BF +:103340001A8727CA05BC08B9D7E5B0939CCFB2B19C +:10335000BD38AF37ADF476DC13B6AFDE54A3314BD6 +:10336000189FDE5C1FCD2C617C7C4B43A2213FAFBC +:10337000E1FD37FAF3FEB544DD91C7E1387AE7673E +:103380004FFC967F7FEACE2FF2406F0EC7D64731B3 +:10339000EE1D31DD702421DF6C25FD61508C380776 +:1033A000E10F7459C0C4FA7CEACEBFD2FAEE688845 +:1033B000729979BD050D5184AF8F40278ED7DF4BB1 +:1033C0003A55AE3DF6FCCB58E777D848CE2D6896F7 +:1033D000EB721DC76798BEF6693A23BD4CF33206FF +:1033E0003FCCA73FB085F89ECF3ED5EC010DBA0F7C +:1033F0003F24CDE3DFF575BFA0F82BADE130E9C385 +:103400003AE2B26027F05B0DF1585A838CD36A1F01 +:103410006888A38A1DE1B5413E80A741B70505072D +:1034200018D6356BD19CD802AAE5F7EA751AE91BC4 +:10343000DDFA429E99E8589F6BA1F45DAC71DA2FDA +:103440005A687F52FCCAE585378075D1526A5B1491 +:10345000268717C8EF5505264AD5F7FA5C1BF5F302 +:103460002E8403EFF7BE826CDB4292732E1BE48046 +:10347000AABFA0A0ECEEEC11E8675C0A0B5B8FDE44 +:103480003C0BB5AF47A017CE477661FFAFED631F8A +:10349000507AC909FCF372829FCE5B4B5F78EE05D0 +:1034A000F8C7967E1C45745A3A4CDA238A02A3A6C2 +:1034B000913EE375687C9ECB25FD273EF7497C3B1A +:1034C0002F5FB14BD82F79DA8174F91D3564D75A43 +:1034D000EEE1EB230972D5E8473EF4C2C7F1ED7483 +:1034E000AEF06720BE906F0B192C0DFEA2639360A7 +:1034F000175FC13AEF465C5764BB15DA57F1C2BE9D +:103500002FFCE4CA7F59FEDA9F53098EDDE7532171 +:10351000D756BCB63655EF65DE2B22FCD7CA6FAE48 +:10352000EC602BD8FA2FE1778BACB72A4FFAB52F86 +:103530006397919DC2C2288E61955DE0A12B909703 +:10354000C07A19AF7BDC4D5CB0F3736897C595E02A +:10355000E1709EEB238EEFE53CB13F9F917ED473EB +:103560003BCCA4179EDB1147FCBF7CC7436F5EC1F9 +:10357000F3CBB7681896D5B136C2D3F25D66660F45 +:103580003FDFC06E93DC379CCB9E8BAB073F2D0992 +:103590006ADEAD45F0CBBB12FA85EB8B929F964568 +:1035A0000547111D24FCF749FD48D55BB2EF211BEF +:1035B000E8C5EB9D25BDE5C558E8DAFCAFF35DC075 +:1035C000796AF370F2EB2E09EE5C4EFBFE8E582703 +:1035D000A6F885D5688F0AE489F514C813FAC629B8 +:1035E00069FF3DF58299E40FE0C43AFC4213765E30 +:1035F000D56E9B6CB74DE2ED863CB11E55FD25C1E5 +:103600008EF85C5EFFF3BDEF531A94F35AE2682B19 +:10361000C17EF9F9AED8C9014A7F3CE9553EDE9931 +:10362000E0B8142D6C5DBD9627E286CF6C364F0650 +:10363000BE5840C51905693EA776646874AE05BEDC +:10364000397E4EED7A29DE44EBD62FDA493A9AECF0 +:10365000C29EEAB6B8A4FDC2EE849E31976B75098E +:103660005CDED5ED12F10091DF557D5A6FE9E0F790 +:103670004E9BE07FE9BF97FE25C489903F3ECE1662 +:10368000C0FE3A7F986BD64D90676F5B053D06BADA +:103690001EC5B96AFE7BC964AF586575F547FE4F14 +:1036A000EF58C97E3E7FB85CE769ED23619FEC70FF +:1036B0008B7DBD761D5F217CCA0338FDFD7C7EB508 +:1036C0000113C5531ECBCB26B81EAF31796DE4E78D +:1036D00008E5C34E79D4C6FC66E8C93F8B26FDAE2B +:1036E000365BD8DD1F07BFF3B43629949F0C7B9758 +:1036F000A463ED8DBC3C8C9EB54F87F2A1B79CB600 +:10370000093B1ECA9D48CB44BD26C937E807FD7654 +:10371000B89D6749BFDC1DC7A0E79B5E8E13F6848A +:103720009F4493DF41F57B5EF25593F473F9B70A3A +:10373000F80017F4E625B6967CE8956ADC25F12DAD +:1037400034DE6939DE929816E13F907161A84FE34B +:103750005B9917E7F1CE67A3483FFD22BD6D0FC609 +:10376000FFE2D921E407EF700716EDA572AEB7713D +:103770003A2CFD695408F09E7C368EFC9C27AD42A5 +:103780000F3A19974A7AD0E1B847E6A3BFAE2D5158 +:103790001AEC292735664B43F9D67EE4AF5ADAD8BE +:1037A000407E82A57CB9C31FCDD3C9F02B9FDC3AE4 +:1037B00084EC2C277F6926FF22FFBE0EDF75D632F0 +:1037C000FF76ACBBEDB16467FBE2A77F1B12EE7F17 +:1037D00050E9D22D467B92A2BF2A4FC917EB2B2569 +:1037E0005FE0312D5FEC3375B1C147B2699E62BDB8 +:1037F000723AD0798BAF8F54D8A78F065F49D51C0A +:10380000C07328FFC7C0FB7671AEF9628795FC22B2 +:103810004B5F8EF392FDE69ECB4CD82F969A85FE99 +:10382000BB94B39B48857D68697C3ED98738BEE9E7 +:10383000FCD8B9D52CC711E39EDC9629ECEF219971 +:10384000DF531C009F4F4962B7DC48FACDE612E017 +:10385000F5FC965813F8828FE385DF7EE9EDDF17DC +:10386000F84C5844FA38431CF428F8CB85BCACBB60 +:10387000E78A04C4C3B0F7CC0CA2EFBCC5D31FF2D7 +:1038800030125F8BF3A5BCDCF3840DFEB35ABE5E31 +:10389000101FB44CFA4D97FD54237D6ED9DD573C73 +:1038A0004A72F05D2BCBE3709C0E3E141F4E8F0AC4 +:1038B000D94F4F7B0FD55FC6EB8BF66FC7133CDB41 +:1038C000AC1EC01349C74B6EFF53F325B5EFE68F0F +:1038D00020DFD74B2E9EF779D6F6DD8F2147764431 +:1038E0007BFCF435487EE753D6E022CCFBD4F3D101 +:1038F000245F4E258AF5FE3997877E1BE0B8FE418E +:10390000B26FFC661A83E85E1C30F6ABC69D992F39 +:10391000E46F5DB22701FE8C3A4E07F4C7E9F21D51 +:103920006AFF9E95DA47CE63A46CD7BD3E9F8F2574 +:103930007E393540D0E3D40B83695FE948147CCEEF +:10394000E1CDC239E554A2487153067CB0549E4380 +:103950004F8D0BD2B9FB94B693D20EAB68B7B4417E +:10396000FA6D39DFA5816FC093F05BD9D7B7418F6E +:10397000807D7A5419A5A1A8A48BEDCCE04FEC432F +:103980002FE40B7B16D41AC875F26F907E12B441E7 +:103990001EEB528FABDD71B1BF8CFCA03B34F2FB50 +:1039A0003C20D729A04E51F671CE8FCBFC9A17F14F +:1039B00046CB9A572E01BF2FABDF7013F85DCD6356 +:1039C00099854DC6F9AA4333133C1DD17CDD000F08 +:1039D000E1E365F7E07793821720A7929E49CAF545 +:1039E000E67CB15F21DFC2FBAB6DD6D6D3386E75F6 +:1039F0009E14F35378E268B1C14EC6CFF9A2BC8FD2 +:103A0000F92B3823E7AFE009E60BFB4487DBF5E051 +:103A100058D0FB5766B29F9EFF6A7842D237E8655E +:103A200038B175DB8B39FCAFF1BD1AFDF821DFB081 +:103A30009E618FE670E66F36FA3F0AB618F3437759 +:103A400018F345BB8CF9927DC6BCE79031BF558E0B +:103A5000ABF084732EE2DA70CE458A73AE2B5F9C96 +:103A60007391C7391729CEB9F88E732EF238E72231 +:103A70008F732EF238E722C53917DFCF4AF95D2B55 +:103A8000ED8EA003C557BD12ADFCE0B45ECECD49AE +:103A900025F9A9FC99E7961451BEDB9E5361277B5B +:103AA0008E8AD3B929413F924F7EC3B6BBD34137EB +:103AB0004B3BD97157FC5CD8716BCBA21DB02FB4B6 +:103AC000AFFDFC6EA84F2509FA27F914D7D4B94DDC +:103AD000C42B85486EB4AF71BD77B5A01FD93954DA +:103AE000DC4D25F6BBA4BEE918E94761EB8D7E935A +:103AF000483F4AA4FF24920F94DFE4296B673AE41D +:103B0000FDB167EDEB01FF31691F63B39DA47F2910 +:103B1000BDBA5BFF7A407B1AFBF6D7F949D4BEEBFE +:103B200030D7B77BD96F555A75A18CF4C6EEFC7AA5 +:103B3000CD44712369F1B40FAD963065699D1DF7D1 +:103B400040DEC599681F3FEF30D1B9E0FC0766D26F +:103B50002306433F0F9BCF90408C81BF0AB7274578 +:103B6000F8FF0618EA0FDB9B1DE1FF1B6AF44B4DC3 +:103B70005FB31FE7EB69EB871BEA55FBAE88C0A379 +:103B8000845BEAA54D776CCA82FC591DD745F0AF1E +:103B9000DE1D4D71B5D51C5E2FFC72C87014D4D8D3 +:103BA000BD5381BF9AA03511FB7C95DC7F58837192 +:103BB0003FAEB130BF33A987EF6A9CCC9BC8DB9F77 +:103BC000296DD966E2743B63DAFCC85817FC4AAD2C +:103BD000594ECE57B76AC1D4CB797F7FB3E84583BE +:103BE00039BF6559433F9C0779B93387ADE1F58EFD +:103BF000AD7F299EF46EC9675956670CE8DDDA621D +:103C0000A67301EC52E6A41E7E686D498EC975F458 +:103C1000CCB387FE5FD1FC385D3CB8A7D8E538301F +:103C20007035F4B8A0986FCD38CD4F7AB29CCF2ABA +:103C3000B9AFB05CD1CFAD327F5C9E17D4FC4E0FD4 +:103C4000D95FE2821FB3716F961972DCB4631BEE09 +:103C50000FDC19A35F337824E225F37E3B968FBBFC +:103C6000F44311AFFBC78D13E22F87FEF9BCD533A8 +:103C700085E7EF6979C68673F1524BC0867367CDCD +:103C8000B3AD362F4FAFD9DE4ADF176DAFA4F3F6D1 +:103C900062564FE7C8132AFE56E2A366BCB6D9C9DE +:103CA000E17E61B0901B3531226EA3DC3CF60DC481 +:103CB000A59FDFAE9562BED37D3B6D95B03FCB7ABD +:103CC00091EBA3EB9D69E5FD604F0A0ABF675FEBCF +:103CD0006146A880D6C3B40B2E4AA75F184AE7D81E +:103CE0000F99AF98E44451C479F61D1187DCB54FA4 +:103CF000AC831A5B28651AD6C9EB565A27755C7EC9 +:103D00008D2EC33999B1313CF58D351BF875C5C47D +:103D100058033FCF6649063FF24C5CDA0CCB4F9F0D +:103D20009263A83F6B7A6104FF97F594931C196323 +:103D30008833A9BBC3EFD2289E65BCF13B4FEF206F +:103D40003EBBCED0BE8EDDD8530FE7E02DBF263C64 +:103D500033D666C379ABC624E26A66EB1DF27B3BC1 +:103D60007DE71331ACC341399EDF8A7DD14A767934 +:103D700065979E8D7FE7F4B62F7242CB71111F0AB3 +:103D8000FB8221BE900340E74F26E85027ED3D75AA +:103D900005C2DE53E76FB321FE96E3DF92C151B255 +:103DA000BC45237B1EAF6FCF4812F93BF07D97F1E6 +:103DB000BE01FABB80F2C3E64AAC97C8F2E57CDEEE +:103DC000D03396C34E033B93EA5FF6ABF873F1260C +:103DD000A3DD6839EC396174FC72B08BF874E9F6D4 +:103DE0009D6F0EE07899E64B2CC5FAA90D56582B1D +:103DF0008B2EE63325DFCFD798C8CFDDF5CE41E255 +:103E0000B3AE1A0BF1F3B7E163B957D83323F96FA7 +:103E1000119F0FFCB28B76699E8026EA012F03C0AA +:103E2000971178C9E8055F0A4FDD788B285F8C7F92 +:103E30008C40DC801608B97BC38BC4A3EA3F024FD9 +:103E40006CB4110F8B74D77B90378B0E9B59E0129B +:103E5000E6BD18F3C3F87C7E18FFC60BC24EA2FC69 +:103E600006332F5828DFCD273E113F3D7D8A715DF7 +:103E700076F38D4FAC93191752A9DDFF36FF7C1BEB +:103E8000DF28B823E393D5FD9EFF1A2CED8423D9B8 +:103E9000485AFF971837ACF67B85E741778EA678AE +:103EA000A22E4736E90FDDFB8DD358BE2A2E9BE2AA +:103EB0008875699F53725797F5D43895BCDC351CCB +:103EC0007C3C301576D7BB9B73B2DAC3F4127DAD60 +:103ED00095ECA6596B9229AD8C76A662BFA85C635F +:103EE000F6611FFCF4DEFEA9A361875F6B4D99C2EA +:103EF000BBFEF47B23B25831F2E5941EDB10353B58 +:103F0000DC9EAD525781D80FEAEE3C42FBD719D365 +:103F10003BF1B3B1CED6EE8E4748CDB2B5EF8F723E +:103F200072D5A3D5A20F2A401CA1D6BACD09BC399F +:103F30005B4B608F1E06DAF5EBD11396AE2DEF0FBB +:103F4000FB57EDD7079FC4FEAEAFB1A642CF3CF9F9 +:103F500001DFFF34DABF483F3881F8E314F8AD627F +:103F6000E97EDB098D79E1BF5962DE5FE234ECA7BF +:103F7000FB66028E5762F46105E4A70D6C4BC3F833 +:103F80001E3FC54BEA6BF2127AB397A874C526A1FF +:103F9000BF6D53F65A69D785DE8E3CF4763885A01E +:103FA000B7230FBD1D29F4767CAF90F6FA414D9DE5 +:103FB000A53877FAC7B3827ADA5F1D05D0CB576B85 +:103FC000311EC89BD59AA73FEC606C4BBAD85723DB +:103FD000E8ABD22B3BB96E15C6EF575FB0B3F0F824 +:103FE000B1712CD1909F604F37D42F77BA0DE5D7A0 +:103FF000A40D31945FEB2A35E4AF2FB8DC50FF06F7 +:10400000CF3843FE3BA3AF35D4AFF05618F2D326DA +:10401000CF31D49FE1AB3494CF9ABDC4503E475FBB +:1040200069C8DF54F33D43FD9BEBD718CABDCC698B +:10403000C1FEB60FE7298EF7D7719EE2E9EA5FE588 +:1040400039C2E93A7682A9BE377BFC7725FF6E1A22 +:10405000E25D09FECC94F74032E57D8EE60217F171 +:104060006706EEEDD379B62D1D7C13592FB27C6C0B +:10407000EC81F32E4EC33F6C9F39DDC2E5C3D8CB34 +:104080000E0CCFE1F9A421F74FB770B932F68A03CD +:104090002F65F3FC80216F88F26107CEA3FCFE211F +:1040A0000F8AFC3446AA45F690F1D3FD7C1E63AF1F +:1040B000CE5EEF11F6905EE32D550A3C206E11782E +:1040C000401AE2FC89F400E74FA487387F56E732B4 +:1040D000F626E74FA487F9B912DFDFE2E74AA4EF3B +:1040E000F07325D277F9B912691B3F5722FD4DE3D2 +:1040F0006C4A3F68D4A9DD7F34D6507AA4B19EBE05 +:104100007FD4D840E9EF1BFDF43D50A0EC0721B26D +:10411000B3287FD272F8F16087DB6B3D1DEE6755E7 +:10412000FE40E5FF6BAA67EDB158A7ED96C4CFEC52 +:104130003D7EBDBEE5AC857D16A66FB5C67A9F2BCC +:10414000203BC94027C96BF97DBC362DB38CA77FB6 +:1041500071E93B41EF1965556B13DCB807526F05E8 +:10416000BF7C68EAFD5E707381B03FAC1AE2DD434C +:104170007C22FDD8CA8FDC1D9F12E6E73685C5C5B7 +:10418000D05F587C8BF237AB789AABEC223E4FF97C +:104190009355DC8CEAAFFC02237977E53A0BE927EB +:1041A00071161642FF2A3EE64A7BB014F10257D63A +:1041B0003A280EAD3FFF6E2BA37A5E334FB7FC99C2 +:1041C000D72FE9F15FF797F0F37282BFFC824E764A +:1041D000D72BA5FF1EEDEDA2DC8FF6889D829EC138 +:1041E00053B2AB3D8138A7B21E7F3AEAC78AFA21A3 +:1041F000F497FB9F7CBCF89EF59399142C453C5595 +:10420000E67207C5536D1E17A2FB5B2BDCFAA7A055 +:10421000932FCAF9492CAD9F9C4CD8092AA4DEFBE8 +:104220000D74F81CED147E149E155D147EC3E28E91 +:1042300008AF7DD129923E917451F428BFD0836795 +:10424000E0E9623AF4D009F6D8FF2B74186109D27C +:10425000FDBFA85ABB07707D1B5D6EE96493709F1C +:104260007870B6DE0C3C575E70BD897C151B370933 +:104270005B932AF77C4BF92C94F7EBBBFCB63ECA58 +:10428000DF8E56F1085E4729A7CB04293F56970BCE +:10429000FC4E769B09BF138A16933ECA1C42AF732D +:1042A000F1FF204F267DE56B467F93528CFAA1F2F9 +:1042B000075F27FB9B1CE107BE4EEA8DD745E885CB +:1042C000A38648BDCFCDDCE2DC27EEB94F94FB746A +:1042D00086A4730E3FCC8F051D996E81D03A847BE6 +:1042E000EE25B807EEA7FCB52C40E9F52C44FBD62B +:1042F0000D5CC021FF1DC6289EF160ECD4792B789F +:104300007F13864FC8C5F7B07B7DD70CE947F7FA16 +:10431000FEE00CBBD77760A28BF48603F61CD26359 +:10432000B00EAC6176B45F72B98F5086837C5F400B +:10433000FA06DF17723993FF82EF0BC85F57B0861A +:10434000A1DD249731DE44B5BFDE399E5986F72DB5 +:1043500077AF2F796520EC2B6F270E9E08BBF3DB20 +:1043600089974DC47CDF4EEC6F1269948DD2E29731 +:10437000737BD3B3141FF68C378959922FC6AFC203 +:1043800067241E157EFF097CAEEC0D9FCDC001ECAD +:104390007AF6F7E3D3B2E1FF12EBBFEEE5E2FE807F +:1043A000FF2440435CB25DE025D2BEF379231B08B5 +:1043B000FCB22D09F4FD36C94357368CA1FA5735A6 +:1043C0008CA6F95D11A3DF35848F73BA2C94CF3599 +:1043D00007F6F9E626BA7F7BE605B307FA77ADD98B +:1043E000B5DE83B5FEB6B82FC7BE3A98057F1BDB96 +:1043F000D27BDC6EAD5DE1CD4FF8F4667B9BC5FEF4 +:1044000027EE11ABFD776094887755F759FBDA8F6B +:1044100047C508B932304AC8414527DE8EF219BC7B +:104420009F515C6E643C1843FAF78824EF63C0A781 +:104430003A4723BE09FBD455A1C204E427E33CC993 +:10444000F36FC9FB696F0DAD4FC9E6F83E68D39FA6 +:10445000413B66FECA8C75DD94A7D13DF7AEC339EA +:1044600029C0F756B5EE4A5849F87B034A3FEE1E7D +:104470002FC54C7EF155F08FA6E0DC64277BD1552B +:104480002C9FFCA613E5F8E5BFACA27710D4BD8F36 +:10449000A83493F1FD1C578CE13D98D88224433E0B +:1044A000CE33C0503F6174B6A13CD13BD4509E3C4A +:1044B000B9CC90EFE71B63A8DF7FF678E3BB6EFA19 +:1044C0007586FA1935371AF24A7E65884F2CB37E05 +:1044D000AEA1FDA0860586FA6EFF52E3FB367E6F25 +:1044E0005B412AE49EF8CB59B7CA50FEE37871AF1E +:1044F00061B26311BD5791D772BB717C49A78C041F +:104500004127E612F2D5CFFF03DF94A719E5ED04AA +:10451000A7F1BCCDF5410DFB7B46BDC5F0FDD3FF3A +:10452000219D23F1D2C5B7A610EA431FE2F9ABF4EF +:10453000A10FC2AE3131C5EA0930614F0F9F17ECB0 +:10454000E9E178803D3D3C0F7BBAF15D2823DD61D8 +:104550004F0F2F1F7ED848F7916D46BA5F76C4483B +:1045600077C58F91F4B9BCDDC80F91F4B9E244046A +:104570007F487ACCE6FFFD5DDC93267A4D7268ECCD +:1045800071F73F4F9FD4A19C3E853DF4F9EF0C3D60 +:104590007D683FDC4F3F9F6503BD3AC57B7D2BA502 +:1045A000FC54F184FCBC2BEED3DD6E26FFFE515390 +:1045B0000BBD9774C0A9BBD1FE96A27A0DFE8334C1 +:1045C000E6DBB988C337FFDFA3C89F307F90B8D739 +:1045D000C98ADA29CE5EC9B9F919228E65C850791F +:1045E000BEF0887896A2A1422F8CF33829EEB5B29E +:1045F00048DC23E0C782ACF9C5E09F77A2F16E6189 +:10460000D74661BF6FB78AFBA57ECE47F08B414F7F +:10461000841E9729F5A8A6DFD9ED807FF02666D8FD +:10462000178704EC86B8CBC2ED4E43BE389866A817 +:104630003F6CAFCB505E1A2A30940F3FEC31E44709 +:10464000B68D36D4BFEC88D790BFBC7DB2A1FE1525 +:10465000277C867C06EB7C0CF81DA489F368F5505A +:1046600011C7C3D710F993E6DF9328EE0FCA73AAD8 +:10467000D283553CAE2EF92E529F1E64D329BEB76D +:10468000299D79E81E805D9E4F9851CFD6653CAD3F +:10469000D24799DF184FABE268BBF571A97F2B7D3C +:1046A000382C8ED61B1E473B5FDEF38DDCF7EA25E8 +:1046B000DD23E11F6413F36DFA9E8DEE2D28B822E1 +:1046C000E1F99B8CEFDC6AEFFDFEC89D4385BFFDE1 +:1046D0009739BEEF825F9F84F8C8E96D3C4FBB9F5E +:1046E000F357D30F6C9EBB5CDF3EDEFC61623EF392 +:1046F0004CA65B2A8A286E69F6CFC2C6FFA11C773A +:104700007591D6EBFCE62788B822966073817FFB13 +:104710001E4FE033CDC69AE99E8B8C3BBF797DF06E +:104720000198C8E7D95AACE2FDB28015FC30653C6F +:10473000D79F4A61B7FAFA2107D7339E6CB0901D14 +:10474000E2E1A137CCF0E7F6DC2318C4CF17E00F85 +:10475000E82A3897D88B44DCEC9EA162FD979BBF7A +:10476000EA8EFF267B3A63527E8B734B2FFC467C8E +:10477000A8E6F1AF8E038FC4933A1732B9EFE44A3B +:10478000B814FEBACFF1127F2A1EDFB5D2EA7BDA67 +:104790004171FD9311CFA4E837B048F0E589A182BB +:1047A000DEA80779D457BD72735102ECB55DCC9584 +:1047B000E0FC067BE4BF0A2F0AFF7DDDEFE94B3EFC +:1047C0005C2417FAB8EFD3177FD2DF3F70EF274C86 +:1047D0003E88F812498F40AE89FCB9F7C419D771E9 +:1047E000FF4281DF7D6ABFF0F3F3A4514E30D897CA +:1047F0009BD69AA59C10FB2AF40D7C5FB8D64AFA8A +:10480000066B10F1C835521633E64B1D3302FE58C5 +:104810002BBD67759597913EB2C0610BB4F2FA95C6 +:10482000FEC87DD54BEDC95FE3C2BB259EBB617F52 +:10483000AF5A67ACB7D821DEF55A18712E5D2CCF70 +:10484000A58B23CEA5D185725FF6300FE94DD2FF3F +:10485000ACE0ECE6AB400EC505E39C6A16F6128AA6 +:1048600057EAB6E3C3BF10F68E26C7674C01F6EDD4 +:10487000664BAF7164DDF8ECC34F7E1A7E7217D6BB +:104880007F17DDFFE9DA152DFC68CA7F21EB9FF663 +:104890009FA772D4476F674ADB4AE047EAF677443E +:1048A000F84DBA1CA6F8D1E86F87787F41C5012C76 +:1048B000FD6BA0C419E6E7D4DB4D86B88BC8545F06 +:1048C000B39BE2025A2D7A59219FC7298BC78EF7D5 +:1048D00022EF751C48C57DED29D25E13096FB71E06 +:1048E0003A56137E42BFD043BB266BA48772B9C829 +:1048F000B08E943FBB828552902AFF81BE6E34E118 +:1049000059F90F2A43A309CE194D8BAD78B2AFFDEB +:10491000B13BCA635C3D7E85F64C118FD2977F61B7 +:10492000DA050FF537FDC218EAA7A2D02DEE7135D2 +:104930003FB0127C34743BB3629EED11F1D82ADD96 +:104940005F28ECDF470B95DC96712E6B34A1676B0B +:104950004CC5BD90DC56F9F32D325F2EF2ABD78AF1 +:104960007CBB7CC7689BB437609E48311F9C8B77AB +:10497000487B04E68114F3C077C829E421A7908717 +:104980009C421E720A29E414BE2F60BEAC52B3F0E2 +:10499000834C0C5B37F0834C0CD383E00709CFC307 +:1049A0000F125E1F7E90F072F841C2CBE10709CF73 +:1049B000C30F125E1F7E90F03C1B7D6D4F1E72CDAB +:1049C0005B61C84FE3FAF8C4B0750B3F4878FFF05D +:1049D0008318FAD3571ADADFC41A0CEDE10709AFCE +:1049E0007F4B8366F093DC22EFA5576D4A22FE9839 +:1049F000E3F6FDB090D3F70FB15FDF66C539CDBCEC +:104A00006F099D9FEA623C82CE2D9305DD4D4CD00F +:104A1000B9730ED1F90E9BC8978BB8D8DEFC0D1375 +:104A20007385BF0129FC0D48E16F400A7F03DEC397 +:104A300086BF0129FC0DF80E7F0352F81B90C2DFE0 +:104A40008014FE06A4F0372085BF01EDE06F400A18 +:104A50007F03BEC3DF8014FE067C3F0ABF476E0F94 +:104A60005CD0DB730DE73BCE8786F39DD39087DE6A +:104A70001E5E1F7A7B7839F4F6F072E8EDE179E892 +:104A8000EDE1F5A1B787E7DB86BA685D427F0F6F7E +:104A900007FD3D3C5FDCE27F0336A61B369F3D846D +:104AA000B43D4E7B52E3A2E0BDE78ECD80DFA83D52 +:104AB0005ACB4AE44BDEAA9D9C3191EB67BA8C2F0E +:104AC0002B619DF4BEB32EDFADD1438CE2618BFF31 +:104AD0009226E482BA37843F4EF7D25D8CCE011520 +:104AE000723F55ED3DCC6926B925EBF7E47BAF1756 +:104AF00039BEAA47F2320C0E7E402C451C44E91DFB +:104B00008E32C4716F3369220EF22E11871AC95783 +:104B1000E6222197B699761E88415C4BA546EFC5E3 +:104B2000E75BD861BCE35DDC525F067DE15461A2C6 +:104B30009C57FD18C4C528B8951D90CB09BA5735A8 +:104B4000B693D9AA8BF09E18B32D847CB7093D018A +:104B5000ED707E2CF46BDEA7C3F8FBCF85627FD3AC +:104B6000FD2BC754F3EF853BEAC7E0BED69418D1BE +:104B7000EE274FC5131EA7366B4FE35EDCD81DCC66 +:104B80008BFB975F4B795AB8C369ABA6719D74CF05 +:104B90004BF55BB9398BEEA555B2F6896964CBD775 +:104BA000E81D7385373EBF43981F17F187ADA48F6B +:104BB0008AFB2231F2BE88BA27E2B6F8424347F6B2 +:104BC000DC17B972446239E2B5D83EF1EEDE0D234E +:104BD0002AD7F6E3FDEB01F1EEDE957FAA7F83F2A3 +:104BE0005BC4BB7BC406A3681CDAD706FB357AEF2F +:104BF00061AABFD594E2C2FDD135D654D4DFC13C01 +:104C0000507F0633710F52C157C4DA4C78779C6FCE +:104C1000310793C3F8884B80E9A07BA9C74AEF41CD +:104C200054589C56C88DC87DFCE278BA083D2122B4 +:104C30001EA2E98E2359E66CD87B4C9E10E4D6EE7A +:104C400058D21794BE5329E3A0CE37BF41EF59572E +:104C5000EE14FA81CEE500E49F8A8FA8CB0964990F +:104C6000A02F0C682D49328BFDBF08F791FC2FCD8A +:104C70001CEDC23DC637285EBF72EDC804715F47A8 +:104C8000F81FAA259EAA65FC0B2B72A642EF54EFD3 +:104C900098969BC726D07DB716A1CF29FB4BE5AFD1 +:104CA00086BF093A573E21DF03595749F78022E36F +:104CB00050947EA8DE3B59D26CA5F89625117AE077 +:104CC00032A9072E8BD003AF2B8AD003D5FB74B249 +:104CD0004EE5AF0ECE203DA55EBCC7376F8DD05BD5 +:104CE000D84EF18EFDBC35134C78B762DE6EAF47FF +:104CF000EB853FDE93FACB140C9A8C389F0194CE4F +:104D0000BC9046E9AC0B052407701703F46F7F8550 +:104D1000913EFDBED4576620CE0FF7E3FC51329E84 +:104D20008F91BE54CA9CE5901B43BDDA4198AFA752 +:104D300058F5B588239CD2CAE83ECC0DD06B78C11B +:104D40006CE839C3C1E7EE72BA173059A3FB1537C7 +:104D50008C5829F99AF339039FFB25DFFA28DFBD28 +:104D60001F48FED6FD1D167A97D5AFD9F02E9B2E83 +:104D7000CFB38A7F23F97CBEFCBD09E61076A66E10 +:104D80003B1480A5C755AE9A097D713E6C7703240C +:104D900021398AE28A447973D155339B71B8F91F5E +:104DA000DA27E6A9DF61E07A16E4E9CDB796DA16EC +:104DB00084C9958A92F1CF14F7EBA1FB82EE7B6355 +:104DC00045FDA1FFAFBA37AFFF37DD5FACE278C674 +:104DD000FA989FD07E1B5EC6DD52C4BC1347E33DEC +:104DE00066354F1642BCDA5C99FF75D1E2FF585721 +:104DF00044F8A17C60C794997E5A2F425EDD047905 +:104E000065869CD29F2CC2FD0E7BFB24D023B6A8C6 +:104E100053DE8797FB51843DE2D745820E91768918 +:104E2000AA2221C799C5957513DD5375915D4FC1B0 +:104E3000FFA9D5786F50A5BF54FB48E3BF26DEFE1F +:104E4000CB54FDE7901F8F98C4FDED01E61626EDCB +:104E500043E27732E4FA61F23D831EFA73A901FA64 +:104E6000DFAB39C3E9AFAFD3C4BDE93EEC38ACA08A +:104E7000F3B1ADB0E3358ADFE7782A5FF0D153B7FD +:104E8000DB48FF9E676B7B03EF34293C7EDCF0231D +:104E9000ABF89D97501EDE9F9A5B1F4DEFBD569459 +:104EA000F8DA4097D8220FD1E319C494F2FAED4E04 +:104EB000DFFB984FDDFAFD4FE2FEF88A7D6EBAD730 +:104EC00058B9B7F46EBC6B5151A21F4179A5C369A3 +:104ED000C3FEBDBC3991F6B3F9FDE5FD42D6497E6E +:104EE0002A85FFCE2261C7DA5622FA3F27CF21104A +:104EF0009415867A32AE38629D28FB60A49D21F21B +:104F00003D81BED68FB227C07E600BB32F2AFB84B3 +:104F1000B5E0D339D83FE7D98CF7E154EA2E96E7CC +:104F20005C790E5CD8BD7F154DEA0F7D798346BF55 +:104F30005B53ED70CDBA9CE7AB0F5B1129C8A6247B +:104F4000B9C43B12F78A772416F0F50A79334FC6B5 +:104F50000D556F1A4DEBAD3AC0D3E4BED7E54D1BEE +:104F60000E66BE02FE0979E99E78B5D36B4B0A5BEB +:104F7000F7552D9AE19EB9CA27160B7BDC3C3C61A4 +:104F80005E0679E1B6E12D97795CAD401C9ABBD8FD +:104F900065F0BBF27A14C730259BBD29DEF1E170C4 +:104FA000BBC5786561FD2F6831DE97E7F5C5BB1499 +:104FB000C571D45FA593CF1BF60FA793E0E47820CB +:104FC0003C753EC0FB73D138448FAA50C08AF3F6BB +:104FD0003CC44FF0FC5C67C08A7116348B772BF4AD +:104FE000F5621C7D5DA2AD18FA92C569CB04FEE4A2 +:104FF000BBF61C3E9283D51C2FB8FFA3EE0146E200 +:10500000A752C25BDD9268D4C35A3658418F397DAE +:10501000DC9FBF41D27D41F338BAFF5C6DF1527C19 +:10502000BD2EF1FBC795D1F7C13F3067E3A35637DB +:10503000CF5F592CF8F70689D729D9A13C7A9F660A +:1050400065B40770CE71B6D0FCBAF1FB30C7878665 +:1050500077507C845FCE177EC491556F34D2B307EE +:105060001E81DFEA8D95B4DE1659749B331C8E4D7C +:10507000FBF370AF670E5FDF7877873975BA6FF330 +:10508000D9C3B3B2689E1C4EE035CEE39A84F7666E +:10509000389F101F2B7E51F783D5780B8BC53DC1F0 +:1050A00085C5BDDBD77BD6A597F49B264E5FD8BDC3 +:1050B000FB5A97365C34E2E3DAAAC53B6091EB54C5 +:1050C000AD4FB52ED53A55EBF749AB2F94A6F5C8A1 +:1050D00019BEDFD6FFAC173C3D23E19D2BE9CAF199 +:1050E0007A28FC5ED1FA62218FE6651BD73BFA4332 +:1050F000BFB7ABF2F1A13CDC0354F5D5B8F3E4EF54 +:105100007481EFC16FB74BBAA3FE2AAA6FBC1F51BF +:10511000D52D2F76AC4D85BCD8A991BEBBEA818335 +:1051200099FF063DF679A1C79EAADDBA3C1D76031C +:105130004B202BFC7DA6EA90900F0BB9FE0379B1B2 +:1051400048EED3D7E4E9F7168F0CABF7D0F3F9BAF2 +:10515000902F21C897DF3FFFEA87635C3DFBA78262 +:105160007FC1BA5F5B2B1DE1F8127C7E5F4117DDCA +:10517000FBAA72D85C88B3AD6AAE2479CBD2F87939 +:10518000420B8B938AE083CA668DDECDAA6A18151E +:1051900030FF2FCAE5AAF515F4368FA2937A7F4324 +:1051A000EDA70AFE1D12FEB9928F5F94EB6F6E8D14 +:1051B000DBB688D6BDDB5605FE97E573AA8DDFBB4F +:1051C000E9D4ED672EBA3B4DDE63A173C97AABB06B +:1051D000EFED88237DF5D4AA97DF9DC9EB7DF148DB +:1051E0006B16F41305C76269C75B28ED718BA4DEEB +:1051F000CAE9F47A71989C5DFC94A053D50BBFFA70 +:1052000004EF43CDCB96F2EC0171BF7C417027D106 +:105210006DCEBA0D5637AFF76EB1DB20A7ABEA4BB8 +:105220009DB04FCF5DD76A851C78B758E02D92DFCF +:10523000E7C9B8548557EC3B5A98FF42D587FCDB49 +:10524000C9C7B97565743CE232D438FF25F9B8AAEC +:105250003E3109E355D557FE10E71E25EF23D7DD74 +:10526000B168B11E16F0FEB02E8F8DF3D03DDB7904 +:10527000F2F7A522EB9F9574FBB155BC2398111B47 +:105280007C96E20A56C478201F7273DB031817FC61 +:105290000CB86D26F1EE606E6DFB978083ABC51484 +:1052A0009F8214EF1D414D4EE5F9A74DE23E10627D +:1052B0004B90A694087E80690AE52CA59DDE3F0BE5 +:1052C0008BCF34F0AB8D6D5987F7576C298C7EEFFF +:1052D00045F1A7EA47F1A7E2DFBEE6E728B9B4F94E +:1052E0001D734B3B4481270BF728E63F3898DEE7D8 +:1052F000FFB679DAE43B78DDF38D12BF5B70D17CC9 +:1053000073C5B9A5EFF96E2C4FED65BE91F354EB63 +:1053100044C55E77FB155A845FE198C6F72FDEEE31 +:10532000D8CA688AFB52F35276EF4B8D97F79424D4 +:10533000493B427B1CF4C879F2F7205848E4F1BDA0 +:1053400022ECBBDAF7D5BB614A3E1FAF97FB226B5D +:105350007F00EB9935E4D03B19475B8EC5E1FD8EAC +:1053600063E3047CAADDAD5671EF95C5D95C783F47 +:10537000919FAFE8771F1636F7A773E4CD0D392458 +:10538000176EF6270ABB83D4EF174939187B6BE5F4 +:10539000DD97A1FE26B753E3E32C74783EDB44EDA2 +:1053A0000B3DD007633756D8B249EF15E700E50744 +:1053B000BA55633EBACF043989F565DA9F8B7D67AC +:1053C000F126710E986262EBE02F1CD4E49B940EE0 +:1053D00039F1987837926D36BEAB7420CF777D095E +:1053E000F016F11ED9ADD6A0B73FE438D7376067C5 +:1053F0005AE8F091DEFE969493473776D0FBE40AA4 +:10540000AF17DD53B1897BA99D7126B2BF5DEA7DDF +:10541000956AE94F527CA3FC518FE3FF2E079E4C07 +:10542000B4AF959BE7D1BB3E776F9C4069F586F2A0 +:1054300047FCC5B80FEB4B1D43705BC93E565D374B +:1054400041DC1F7D3A2A11E79B2CAB3F2B5C2FAD33 +:105450006EBD87EEA99C688DA67B2A139D1513133C +:1054600053E8BD5DBAF7A5EA7D5FAECBA575130C19 +:10547000F74C16F23E1107FBE7602CC595AAFB23FB +:1054800077C6E8DF2DE927EE915CEE12F747D2A947 +:10549000BEAB577BB84A3F6B14F711C2EEC54C9DAB +:1054A000C3DBD7D6BD148F7E963DFCFE288E19D85F +:1054B0009FEE02DDBAEFC56C12F7629A705E821E33 +:1054C00099E49B3907F8FFA599F0DFD77835F851B3 +:1054D00092B073C4CD8104D25BF510B3C19FAC3BD5 +:1054E00019E9C527CCAC017A80D25FD4F747245E96 +:1054F0004E24B464813F966C7B340BFBCBC938914E +:105500009FB76DD65B9057FA9628A19F5B18E9C3A9 +:10551000557EA15FB39A24F52E66F47CF8634B6246 +:10552000C53B3CF2FE8C824BBDB77AD222DE8BC1EA +:10553000BD18F0FBC796D042D0F763AEBFE21CFBAC +:105540007D29C73E6E31D3EF8EF8F942811EF2718C +:10555000CB4B71B89FABF4B572F3EFBD788F66D5C6 +:105560006E714F15EF9AD39B95D20EB25CDA41560D +:10557000BD629D84DF1DE1FA177DA9B5846CBDD1A4 +:105580006FA9D4AFBAF3BB76D2B9AD7687D01F6A14 +:10559000831DA43F287D44DD8B5BB6A383F409D52E +:1055A0006EF92E8197BA5DE27B25E2D6E5EF856A3A +:1055B000B9384F6B94FFA468C1AC3596F07C25E5F3 +:1055C0003F2952F6914ED207EF2BF80D9DC3EB9A6F +:1055D00065BF3C6F0D1BEF0D30693FF13DC781F694 +:1055E00062DF57E575BB12A97DA82E661DF679EF1F +:1055F00072870569539D83F6FDCDF5A602CB0800A1 +:1056000017E3811EB74FC66FF55BF61FD1B01FA41D +:10561000B3CE8378F7F580533F027E55BF67A9EE7E +:10562000BD9C7BEDF3E1E8FFAA41EDE7F1C6837590 +:105630004DDD2CF827DA4BE43C8ADA8783AFFB1D7B +:1056400010F2F9092B5B47EF075B7C0C76FB90F4BB +:105650002BFAFF6212BF2FA1859E09D7AF52860990 +:105660003DDC1725FC8B5EB77E12707C47B3169726 +:10567000E24CED32E7A17FF53B2A4A4F1D2FE5733F +:10568000A63C5FD906A439C0C79AD74BF710EF2ABA +:105690003A50857DF9FE4E3BFDBEAA8AC31BDF1939 +:1056A000437A6BE680C9B49FA97B29078A4C7EBCEC +:1056B0007B7E3FB38BB8007B845E6B8AA678646D7B +:1056C000DF2FFE02799E61FEF2207EA724E3DF3405 +:1056D0007AFF727ED7674FE03766E6B14029BD8317 +:1056E00097A89B86410E774DEED039C9EE7706ED2F +:1056F0001EB14FB070F8F77DEF2FF149A61EB8CE5E +:10570000757E46EF0A9EEBB493BD76FC3EF9DE5EF5 +:10571000043CE7D25C1417CDEB85F0BECA3987890B +:10572000DE191BBFEF20BD9B375EBDAB6737BEAB3D +:10573000C7DA3213614F261B2A570A529B04DDAE8B +:105740004A309E13F38689F356DE30213F14FEBAA9 +:10575000EC67DFD6B59E75B842F9EFD5EF4DD5446D +:10576000D1EF4D75EDCBF9C6F713DE87FEC0F5829C +:10577000F5D9DEE261FD7AF6CF19122F6A1F36CB1A +:10578000FE6748FCCC7098043E227E6F43F187A2EE +:10579000BF8257D157D18DDDDEF606EE05717A1541 +:1057A0003FC8884E97119DFEF2CE5A5CF31F60F6FB +:1057B00076E8EEFF8B740A450F869EF0B0F8FDADDB +:1057C000C8B84656C0689DCF37C7901D5097EF8226 +:1057D000F3F5FD06D6B75AD78326B717637F3CCAC1 +:1057E0008FDE80ABDD14A4EFDF1D26E20907B2B621 +:1057F00074197F33127A59937CFFB8FB770C973872 +:10580000E8BD917301F5FE71E0B1457CDC8D338A12 +:10581000C8AE7F8EC9F55ED3FD4EB678FFB8FB9D4E +:105820006CB39FEC247362C8CED3FD4E769E78EFA6 +:10583000FA558DE5E31D5A7F859DE2E323DFC9E636 +:10584000FBCCB3F0673C5E13437E28F53EF278A7AD +:105850005E0F3A46BE8FFC88E69BB310FD153BA851 +:10586000BFF639312F6C13680EC18E73B4218EDEF2 +:1058700085567CA9ECD783FC1D8F014FEA5EE71F9C +:10588000247F29BCAB7B6D0AFF8ACFFC5646F73FCD +:105890004107BC2BABDE67D7EE907243DD277CDD82 +:1058A000E342FA40A2BE0E7037ADE47283ECE2ED43 +:1058B000B761BE4F7C2FCE0BB88E9A8CBFDFABD2B8 +:1058C0008786990CBF133A5FEE57F355DC7F83311F +:1058D000EE3FF21DCDE404DFC3C378FB33DAFBA354 +:1058E000F0F19DFF36F71A47F2A45CFF2362F5271B +:1058F000505FDD7F50FAE13BA59F67D2EF8D7C754D +:10590000907E5771AED31740BDE85CE10FF8437A43 +:105910003BDDD7F8C39CBF66923DF90EF1FEE7A5CB +:10592000C279F17D5AC10FAB178A78C30C564FFC70 +:105930009BD6734F331A70FCFF769FB6E7BEEBE43D +:10594000E1C729EEC247BF5711498FB151075E72B7 +:10595000F193CA6F877D318BEE93261C58EDE6F9E3 +:10596000A32F9E15F98C03E7DD9C36ED2F9E13F9CE +:10597000C203E7711FF5D3173B45FE0A46FEACE3B1 +:105980002F7E390BF74FFBBBF53F825E332FD4BF21 +:1059900081EDF5C335372E74D37DCA8ACC02719F51 +:1059A000F26394CF485DB03641EBB94F69F2F8FE2F +:1059B00008BE3DF7A5E06F3787157CF2CFA6EA3E1B +:1059C000A992B77DC945B5EEFE55F761D53A66DBBC +:1059D0003CEBAC6042FF3F7D4F9579F8BCFE1F9BCE +:1059E0004A017000800000001F8B080000000000CA +:1059F000000BB57C0B7854D5B5F03E73E6994C920C +:105A000049C80B02E104420C18D299BCC05BEA1DE4 +:105A10002089015A1B6CB52018068D90D76442A8C6 +:105A20002DB5D80C0611A8DE0B5754B068274000DE +:105A300035E8A0012718EA00922252BF98FB37F2FE +:105A4000FD5FE10B3E90979310B557EF55B96BADE5 +:105A5000BD4FE64122DAFE7FF8DAEDDAEFBDD77B03 +:105A6000AD7D86B1B196F3D18CFEAEC98C1D3FFCE5 +:105A70009EA249646C4681D16A90A034772BC602FD +:105A80000EBB01DE7595F935B1BC9F36B45FA2D768 +:105A900066C17E7566EA973908FD72B1DF9F476B74 +:105AA000B1BE416F356430F6B48EB94D098CC5680E +:105AB0008EC8B84ECC2063CDD07FAC8131631E63DD +:105AC000297AC6B01DFA312394BB06F97AE3121A7B +:105AD000563098675C85D9DA9C81BBF53056C8583A +:105AE000DA28FF68DC5FDA4A3DD5C7687A94063366 +:105AF000638126FFDC0F33192B8E8ACD653F8052E0 +:105B0000CFB2711F4C13656D85F54AE4AFBAD20070 +:105B10006EEC906CB0342B36946F671319ABD702D0 +:105B20009088FF33795A711D6D77F51EE8D7939CE5 +:105B300066DD08E0D8D4832C331FC6BBCA72D804F4 +:105B4000C68E5A1C39D62468679B241C1F9DC3C768 +:105B5000FFAC2C7A870CE3FB0FDF54E880BA3B0CD8 +:105B6000CA0166652CDF3B7A81F61680E39442C950 +:105B700002B075EC02ED688053940312B41BDDA3F0 +:105B80001714DF82E7335A3ECC66EC174C62718003 +:105B9000970CAD63BA15CEEB2CFB44CF34D83EA0A6 +:105BA0002F9F0AF76A854960FDA4A3704FB0CF818B +:105BB00039319E1D703E96A314627BBA6E20D602C8 +:105BC000F7D1FF95B6CC63A671B13F87FA6BF8F7B2 +:105BD000AF8C3DD72953BD0AABE5375689EED79533 +:105BE000697E0CEFAF3ED568A4B2F36A29C379B4DD +:105BF000E59977C03C763D5B529E73FDF801AB861C +:105C0000F695B10E103A86C8CBCE14F8BF28A6C2BE +:105C10006E369DB1965F41C5BFF0763809D34FD23D +:105C200008F896ADC5DAB0FE76EC1F6C6776230BEC +:105C30008E775AA76E5D9B29D6433C2F639E497091 +:105C40008434D62031B8BF54E627FCBC644BA07323 +:105C5000D11FE0E9D94453CB46A45719E8328F4A03 +:105C60006681322D1AD683F6B4374C1EA4AB5D265E +:105C70004EB7991A5EEED2F0FEFA28E6463A1D07B4 +:105C80003083F26D9BE377B6249AC74FF3C8FB6D60 +:105C9000488FA39997D64F616EDA8FDA6F2CEB3667 +:105CA00021CCB40359844F5933EC7D26D9666E4616 +:105CB0003A0B34D9D947DA607D203A765528FEEA86 +:105CC00071BC3974DC2C1AA78E77AED2B08F46E146 +:105CD000E1FD443FCE4C8DDD9383E3D89B521ED62D +:105CE00077EBCB6382E37A9B8CEC23B8D7FFD3C4EA +:105CF000A83CDD64A1F5FF6F532A957F6B52A8FE87 +:105D00006C5336957D4D56AA7FBF693A95772D8A9B +:105D10002940FA77F966B28F8C42CEC0FF9C5E9D17 +:105D2000A32F04EE9D393C1DBD26E8A83763F8F685 +:105D30006E6C077CF6DECAF1D97F3FF3ECC820BA5F +:105D40005C6B49B81EFF30C284E7EB8F610BBC70FF +:105D50004F6F1748347FFF680EEFB7EA683EBB8687 +:105D60006DC5F16F17E8F9FC133455D86E4FE0F3A9 +:105D7000F666010CFB59307DE6CBC897F664A8CFD8 +:105D80000BC2BD5378BB7D0CAF57F7ABB6FFCE66E9 +:105D9000E17428F0DEAF83F57388DE697EB5FFD746 +:105DA000459C0F23FB7B3235659E61EE23C1C6FB0C +:105DB000135FC07DB8910F3242F8A25E21BE50E958 +:105DC00050A5BF976CFC9E330D82CE4127D0FDA11C +:105DD0006E40F99A027C20D1BDD8199C679724F8AF +:105DE00025921FA04439AEF283CA072ABDA7019F9E +:105DF0004909C173FC28825ED5F2B495E3A53B390D +:105E0000E601C26BA7CE02A210FA03221310BEB3A2 +:105E1000C00EE34A1E35370C27BFE2FED97B50E5A2 +:105E2000C108F770DDF9F5BCFCBEE727F986721BE7 +:105E3000E9761879F5B53581F6A3D26D92CDFE5F7E +:105E4000483FFD92492BC54169E2741379FEB70BB7 +:105E5000F83954FA79C9C6B8BEC4734EBC5EDEA91F +:105E6000E7193AE77246722F338AD747E2573D5710 +:105E700088DC8BB11506EF93316E0F8C057B606368 +:105E800046907E03495F2E43FDB5CDAAD0FEFEA00D +:105E90009109FFAA3E19AA97E425F373C2F40CB343 +:105EA000001E070E1B88BFFD1A56F50A8C6B255580 +:105EB000113CF76D362E0F06174CD2AC827D05FED5 +:105EC0006E76A3DE0A8C19382BC1F8C0563040C854 +:105ED0007EB0FF584A66EC7ED029A897AE809C63BE +:105EE000598CC9DB3E3F2BC1BE976D9319DA350142 +:105EF00010DB328C733D19E331F2718CC1B83A3149 +:105F0000AE79EBA777217D9D07FA44FBE62353FD8D +:105F1000040676CFEC6D3ABAC765317A0FD61FDB2F +:105F2000FAC48945009F6F9714B4374A6533B5D7D3 +:105F30003C2F7B709D3A73E94509EC9C407BCB5329 +:105F40005150EFDCAB63261857DA2E59FD30FF7243 +:105F50006F0CDE0C5BB645F77E5F76506EDE26F486 +:105F600058D52EC90314C3AAB687B7D7EC0A87EB56 +:105F7000983608C3FCB36C318964FF4D6636B4FFB4 +:105F8000D89604545643723B92AE506D237EEC8DEE +:105F90005C1E33F659F21D4097F2E1CFD3DF377321 +:105FA00078BE80CF01FCC9E7FCFED57BAB1732FF82 +:105FB00093D1ACC00BE7AC3F6CB2B8E160F51D32D9 +:105FC0009D23E08DA37B7645F5DD4E7C7A48B6A017 +:105FD0001DB6C127BBB1DDD969DAA98173D61F907F +:105FE00018DA9F4E9FC1C3EFE9EA326C5FEE335976 +:105FF000146C3F6460328C0F00DE4C88C7717D8466 +:106000007FC42BDAA7F0F763A928887F19F19518C8 +:10601000C457F356BE9FF37B397E4AE5D55AC25723 +:106020008BC45242F0FC67CD8B43F8C27EB3B7FD00 +:10603000B50BF1BC0CF6675010EF32E1F93CE0070C +:10604000E7D51FFE28BDCF1CC4B70CF8FEAD3A1E25 +:10605000FA2FBF01BEAB987B1DDA73DF17CF69C87B +:10606000FF4964F79EFF03DABD31608F23E908FB27 +:1060700038A9B6F778222C589170D9B902EA27A529 +:10608000BEC232C14E90E21D8F225F9F9DF39747A3 +:10609000101D3D735FB4215D34EBFA5A9F860A7779 +:1060A0007CB41579B03F63FEF6D7609DE2842FD3B0 +:1060B000F723BFFCC96041727A42F023FE1901FF49 +:1060C0004EC6EF1BF0780ECFEFEC34F80D708FACAE +:1060D000BDC43E640F4C407DECD5A39C2AD10F5427 +:1060E000AC407B1CE6C375242023E4EBDACE3F9F53 +:1060F00096609CA424B2C5081BCD7E19E769D35DC8 +:10610000193A37CC2359FE42FDDA6C13E8FC1353DD +:106110007EA4A0FC695EC81C5113BF4DCE3392F320 +:10612000CF0A7F6544FB6F0479AFDA7DCC3D361E24 +:10613000F90BEF82F30F973BCBA733F127F842C05F +:10614000556BDCB146E8BCFC666B2A9EFF63A4B3CA +:1061500058A4BF53DA51B0AFBA5689F0568FF483C2 +:10616000FE15EA37A8EFF70A39F27C77F1A8442C3C +:10617000252B702AABEE94AD7E68AFF6717ABA8E9D +:106180006E84FCA869E3F2E33A3A6A0338C44EAB82 +:1061900047BA5261C0F7C9A0FC987A0DF6FBF234F9 +:1061A00026F4955BD05B4E5C1FD0CB2053E22C399C +:1061B000217A4BE2F6962A576EDA0AA23E64DDC9CE +:1061C0001E23D386AC7BF35E4B183CD59B1AD6FFBF +:1061D000073E25ACDDE6CF0E6BCF3F610D830BBBD9 +:1061E000A787F59F76DA1E06DFD25716D6FF8717E8 +:1061F000CAC3E0C11C38CF3076C7901E4A95C2FA98 +:10620000CF514C61F3CFCB8E0F8307CDE27E841D3F +:10621000A8DAA75FD8B81D1459AAF7FB136BF83A90 +:10622000AA5FFCD3E9E1EBCDB787AFF75DF1B21B15 +:10623000EC7E2DD8F57B413F62F902D8FF5AB0EBD6 +:10624000DBC0FE47F825B0FFB1F482FD8FF5AF80CB +:10625000FD8F703BD8FF081F047F05615F531995C0 +:10626000879ACAA9FE46F7D725D63D21D63D29D61D +:10627000FD47EF492D9D6593345F009FCE4CB8A834 +:1062800047396C6FEC2BC538C0C05B32DB810CE248 +:10629000F09C684A447D348AA1DDC2CA07DEC63854 +:1062A00045FD8189968D0AEAA1FF7C07DB03EDB2EB +:1062B00082F2FCA8EF83589CE7CA17C087F938EE32 +:1062C0008358F48FEBBE64046F847605E039FB419C +:1062D00030903D03720DFB67AAB047CFA02C6FDB57 +:1062E000AF477CD4EEDD4FED6F7975E1ED7B5BC29E +:1062F000DA2DD81FCA5AAD87FCFB4B3E753E3FF5E1 +:10630000AFCB94EC68175FDAFB9FC9CBB05FDBBB08 +:10631000C9F77DCB7D7F72F0C51C94EB4ED0C37E58 +:1063200073701E67874EC07CDF7599FB4B1350114D +:10633000B4496C121457D826B60AE45DADAFB50E59 +:10634000E5506DF6221DCB207924E20D206DD15E43 +:1063500042E71EEEEF8AF7D3D8FB60DE37BCC76F8B +:10636000B723FE3A8FC5E2BAFDED72983F73771EF0 +:10637000B75BEFCED313DEAEB41F8B55A07D83F792 +:1063800018BF6FAD9FCE7D54C0FD50D23DFB643A27 +:1063900077F5171ABA7F75BEFBF3649A678E6F5252 +:1063A0000C9EABC7CBD773E529B4CE9CCCA595B8D2 +:1063B000FF93A90B0B65B2F34030A35C9D32AF1580 +:1063C000E303B55ED93E9CBFB546CCDBA5E374F8CC +:1063D00056E6AB5D63803E4E968DB291CC17FD7E46 +:1063E00093C7EDF152BD2313F5428F5989413A7E8F +:1063F000B86C620CE2F52896585FB653EF80B2A6EF +:106400009DAFD763E98E457AEB69CF97D16E51E79F +:106410005B89EB1686D0F510DEDC84A72A4F8B193A +:10642000E709E28FD7BBF2B81D7ED2F3EE5D68A715 +:10643000F464475B112F5D7A46FE6D2DE015F54142 +:106440004F675A0BDE83BA9E4BE0A33F5B43780D48 +:10645000F874A2DFA25616D64FC7F1B52B7C3F16B3 +:10646000CFB97F5B847AE959B0ABA1BA4ED7908C93 +:10647000E7FF787BF8FEAAC43DD7E9FCC9C921F43F +:106480005AD731C42F66A2EF0E953F14C2A78AC710 +:106490009E6C6EB7F5A41A3CE82FD6ED6F25BABEF8 +:1064A0003EBED39D81767EDAAF8D1437BC913FAB73 +:1064B000DA01217E0F433F4E5736B1503321A8EF0A +:1064C000AFD9EC2FE615A23F544EFE5E0F1B588647 +:1064D000CADF8976701CCADDBF3D85EB0EB683BD71 +:1064E00007EB3A8DBEB91F829D35680546817D0F49 +:1064F0006ED779847F6246FB7499B04F3F561C4536 +:1065000032E857E71A0D9DAF2E278ADBB5424E7E43 +:10651000B23FE3A748AF7527648B11ED50F05B08DD +:106520006EE37641BD37E3DF67A0BDDDA6233B40C8 +:10653000B53B9CC2EE382FECD9F36B06F464AF1E6A +:1065400096D813B08F2ADFE6AE346877E6CC257B89 +:10655000D529B751FC71F9D670BBA0DA130ED7EE6E +:106560000D879D117683EAB7F5E40DD90F93D1FF1E +:10657000289167A4201F7C2CF0A9FA232BA75A533B +:1065800090DF376895B96A3C00EFC975F8D56ADCC9 +:10659000AFA72ECA4A7EC1AA43749FFD9F71BFA3B5 +:1065A0003F9571FB88F17BEDF771FA76E924EE6790 +:1065B00000B9D27C46C9B3069AFADD83B124971894 +:1065C0002B437E685CC8FD483BC65CA1DC9727E294 +:1065D0004511FAF2566D9F1C1F221F3ECB9B40FBBC +:1065E0002FD63307EAA9953156D25BE38DDCDE2E38 +:1065F00059EDB5211D8C07FFD81012CF1E6F1E90CC +:10660000B0DFAE8778FC5CF5EFE76B2DBAF810BD14 +:106610000792276C7E90247CFC8DE6B7C0FCE6E0F8 +:10662000FC70DF7178DF9F1658491FA7CF67AC9BBE +:10663000F8B181F8513DCF15A0B362A0338C9920F9 +:10664000DEEAB61FA138B09375933F521ACBF751CB +:106650008AFB41388A97967C2E37CAF3F9BD350BF1 +:1066600058955B6FE5DBE3F3A1DC9BEF48CAA77AA3 +:106670000BD1E54A412B60A7A4F40D23771BFFC281 +:10668000FDAA4F810F90CFEF699094CC303B88D317 +:10669000B78B57B1CBCCDB3B03EFC16DEFCE4E4692 +:1066A0003F8AF3D59255262533844E5D48E7702FF7 +:1066B0005596EA1FA3DDED5895AC60BCDF85743FAD +:1066C00001AF91D37522FC43FFE23A3AF786C3F05B +:1066D000B71DE9AB9E19ACA8475CBEC876AB16E304 +:1066E0003AF9F9C0073707F9205DD0658B43F2A06E +:1066F000DC6FF94ACBE3588B258A5BDD0995489717 +:10670000F487FDAA667A70FE3B01447F886D4924B8 +:10671000BEA14690233F17E7BD53EB3F827C7C5CD4 +:10672000E7CDC078CA7127CFEB2C646070807C59AC +:10673000CCBAA9EC8DAE3FE0A7C9DDE3D06F7ECF28 +:1067400061A0384ECBDA1D31284F73D95ACBF96C82 +:1067500054EE6CEFB5FC91ED0A2024765EC50BC5B6 +:10676000853611FE55BCEECDB7CF47FC8F34BEF653 +:10677000AF076E4797A2F681567D0A279BEEECA2E3 +:1067800020FE5CCC9B8DFB55F135843FD8F358B887 +:1067900087056CA008FD1A156F46F8371CDED4FB80 +:1067A0004CD70DFC0CAF0CF412C997487CAAF75BD0 +:1067B000CF1A743CCED5F0CE42E87FF75A8D82F6E0 +:1067C000E175F8BD011EFC26DEE48F91C8DF1C09CF +:1067D0002F2A3E54FC9C8EE7E34EDF23539CEEFFB2 +:1067E000355EDECA773CFA6DFC18C97F23F1DB9277 +:1067F00055117C19C17F2ABE1CAB6289CF543CD68F +:10680000298CFCD6BACE18AB8705F167867F883F06 +:10681000CC53503CA65D62CF48DF850FFB28AF11FB +:10682000891FA00D3BCAF59D11FCA7E26D24F9A3B9 +:10683000CAAF33CC7FDC22517E80F3E7AF0C1ECC95 +:106840002FAAF901350F704CC8BFC8F20CD81D989B +:1068500077D998DD9384F65AAF5E9D87E71FCFAC5A +:10686000E91EB702C69F99C9CB5EB4D342607B14C0 +:106870008FC39D196D70E3BD9D9126CF423D7E462D +:10688000FAF5ED1C4ED12B082F4C996501B857A78E +:10689000C6ED1E1672D843E59985D38AA99FC4DE3A +:1068A000C4FB5024564EEB48524219ECE7CC0393FC +:1068B000F29A59F0FCAFE4737BD62BE4F9501CFB41 +:1068C0003712C5B197800AB060BC7DD6D36513A0DE +:1068D000FEEC83136D94FF6B0C5F1FF56806C50714 +:1068E00037D37CB77E31A05B9A13DCD790FE2BBEEA +:1068F000CAEB2B27913F512570684F98CCFD58CF9C +:10690000C438D447AA7E1A3CF1AA39347E7911F4EE +:1069100017D387C0931F4F0FD56F4776FF3E0BE706 +:10692000A9D2BB73AD507FA1E50FE9680754ED7E96 +:10693000348BECD2DD1BB2D0BFA8DAF1FB2C3BC10B +:10694000D10EF26FB4FCDC97F7DDB27363881DFCE7 +:106950006021F70B161B8F94A07D3AF7E64F1EC1FE +:1069600078F8A407258A8BDDC3BA1F41BD5991CDA4 +:10697000F9886D31925C87F928EFD83AF927BB5036 +:106980009E9FCCFE405709FD4C055ABA8F0AE67906 +:106990002C05E361EB258A8705FB8FA33CE6D2B586 +:1069A000923E3511F561BC4D56705C3CEDE3DEF571 +:1069B000B62EACAF58CDEBE71A3CED3D38CFD37ACD +:1069C0006BAB8213954F280FC90B9B0AB8DFB5E458 +:1069D0003189EC71759D494F25B7849ED35420F4BD +:1069E000F98C6EE2FF9F0ABCFC78F5BB6FA62A9873 +:1069F0004F72C41540FB3B4F9ECF44F9559C7031FC +:106A000007E97C92DEF14C359E7B8781E28705B9F0 +:106A100069720AF4CFFBE5CC27B05CB27AE933D5D2 +:106A20001807DD6A243F4ADD5FA3A468D0DF3CD6A7 +:106A3000F28B7BF1DE2E3C69243BBAB1E5A614361D +:106A40000C9FAAE51EC0BF92C5D8F34D462A5F6CC5 +:106A5000B230058EB8AF2995E0979B142AD9024E23 +:106A60005F8DC25F1D69BE7CF0F715905705EB6125 +:106A70003EB0376D26FB143CE7A429CE1D1BC4B9DC +:106A800026C1789B3B6336DE43C186155D688A2646 +:106A900017F0FCE2DB3DEBD3C98E5E7DEEB96A6890 +:106AA0005F5A509E5F00F76DDC7E95FCFC631D8F86 +:106AB00056505C7F87819F4F9CFBC2935929CF60C2 +:106AC000DCF52D1DF9DFAEEDE79EDB00E57D8FAD3A +:106AD000D087D2FB773DAF4DECE7467C35D23D7C8D +:106AE0007FBEFA7D3AF1CF0EE0AB9C7F9CAF5CABF2 +:106AF000D7D0FD3D5A507E37DEFB059D3B1DF9E9A1 +:106B0000C2E41F119DBB0F4B74FFAA1C57C72F1067 +:106B1000E7ADD5781F237B50C8F1CFC1F3C3FB3D50 +:106B2000D2F17116DAC39FFB167EEBB90F36610600 +:106B30001DE35A462A23DB8BF48E8956385F9186F3 +:106B4000DBC191ED0F17A871719E6FC73F8C0BD7FA +:106B500009FDE9848DC525A0FE93FC51B998E7B8DD +:106B6000EDA216FD2FF0EBDE0FB72FD9FB217A7CBB +:106B7000A4FDDEA8ACC779B441B93BEDB486F943B6 +:106B8000F4F62D7D51CC1FB2EE90DF01757ACCB3B7 +:106B9000748C26B98078C3BC4CA063F20E842FEAB3 +:106BA000391E0307C1BFE27115261705CF79B1E37E +:106BB000722ECAD9C8F3D61FBA4CF451E77BF4AA97 +:106BC00044E79F73519B7BE3F31FD97D3917F1771E +:106BD00051D757847E5440DF978B78A87F9DCBF3A5 +:106BE000EF7B0F6A7DF57A3D8FEF4916F2074BE494 +:106BF0002BE4C7074E703FBEBE6327C9D3C14E1EEC +:106C00004F7169BA4B5330FED070AE0BE5D9602A94 +:106C1000F7AF607E3BDEDB8C89420F6A07D2E783E9 +:106C20005C3B2AF2B5AA5F7701F9578FF378EBE85E +:106C30003D526E3443BBE212F233D457ACCA58878C +:106C4000747EC193849120F676EEFFD453FCED8DD3 +:106C5000688B4C762BD486E06FE81C1E993F9C61B4 +:106C6000AA9F1ECDEC21FD5C7AE5A7E41F9FE47985 +:106C700032D714CE4FEC10E727E7DA23FAD490F995 +:106C80005E52E587B01FE7BEF13FC497A76CF6538D +:106C900028CFA25116E27CA9711E4912FD8A827981 +:106CA0004073A7F0C7CB646A77F964361AC7A4C6E5 +:106CB00050BEBE8C6DD2A2BD3B977967F077327D16 +:106CC000FFF643689FF7869C8FEFB1C07EA6FC71EC +:106CD000699423B311ED238D24EED55B303F549F8F +:106CE00015727B6B862C911E1B181D4D76CA9C0558 +:106CF000CEC5B85FB55F9996EB339887EC2CE61953 +:106D0000C8C57C26F30FE4629E53ED77D71BD10DE7 +:106D1000A41799B7E0AE9075C61472BDF929E69F25 +:106D2000419EB844FEB344FEEA29F4A31A0FF33C93 +:106D300061AF26E33D7CAFE5867B46BC5E06BCDAF0 +:106D400051FF3898DD8EFC3335C983FCE3DA2731F7 +:106D50007CB756DF61D881719D7A5D5F32D2F306D0 +:106D6000DF5FF548CFAE03EFEA95A9389EC781C033 +:106D70005ED7E0FDBA84FE72FA6E7A0FE36ECE1330 +:106D80005C8B3AB5EF925F5FDBBE9FFCF73AE6277C +:106D9000FFBDAE2D9C5E0653799C3D923FC6142AE2 +:106DA000617C31672BE78BBB64D680728E89B8E932 +:106DB0009CD414B24782E3849D285F7E04ED97FE45 +:106DC00009925582A9FAA3DC6BD12E7267717BA65A +:106DD000FF4F2F162C23B9E229F819BE8B11F6EEBE +:106DE0009CF59BB572C87EE674F238617F14AB3AAD +:106DF00048F8768C453CA4E7958F2DE4EF6472E962 +:106E00009D8F86C73523CFF1AC88E39CC4384F4EA5 +:106E100070DFF3D2D2B81C631EA29F2E0D5F5F7D80 +:106E2000F7A28E5F21E869C81F92787C6A24B98234 +:106E300079944A9147A91479944A9147A91479946D +:106E40004A9147A91479944A9147A91479944A918F +:106E500047A9147914AC3F895BA5F7703B9F417A31 +:106E6000E8421E1B13847B1322E031E1FD7B13A457 +:106E700070788C44FD8B0B773EE3CEC138A645C8B5 +:106E8000252506EDAF0B261E5FEA8871CC2D84FA0E +:106E9000CA39CDBBF97B443BBD67294E58B818F9B8 +:106EA0006B30D1C0500EB90B1DF3111F274ECCCE45 +:106EB000DC4CF2D164C53C77EFDD37C7515CEE2D79 +:106EC00099C9B0E4CCECFCB50500CF344B44B720F5 +:106ED000277E50AEFA9330CFEC4E9ECF2891EB2A0E +:106EE00071FEC6D1A67C8A6BE53B161586C40F4A97 +:106EF000C72CCF443BA84BA7BC87F154F75F740C59 +:106F0000FD2835FEA6F6EBCD9B598DFB9A933D717E +:106F10006D1ECA1B602E946F763D6BC37DD935D133 +:106F20005233C92B458BFC5F2DF03D4BE1F6B05F32 +:106F3000AF6813D06F8F9A99E85678BEAA52E4AB27 +:106F40002A45BE0AF1730AE36650BE03F55876433C +:106F50003D9691EFB9761794AF24BA6503E9A1EF96 +:106F6000C1E6225F7139938EF4FC8288C367178A69 +:106F70007769F9E50FF2715E9AA756C4DF2EEBC26E +:106F8000F378EAB8E07846E51D3FE0F299C5E9F903 +:106F90007BD7B1CC8DEF69EF786D34C593021E8D30 +:106FA0005B170730F038CA2FF61AF76F592AE797A0 +:106FB0003B5E4DA17ECD220EEA4CE8CE4A40BD2B71 +:106FC000F84A850F7EC3DFF938F30086F275899F92 +:106FD000CF794777563CC001C9A4C1F8B873076F91 +:106FE000EF117CE79C20E613E761466F3AE2A3FFCE +:106FF000F06BE9F702BCD1EC5FC6E5BD3F8BE43432 +:10700000F367E17BA1CB92F72CBEB7FDF5C17F59A9 +:1070100084EF6B2FEBBCCF21FCDB8333382CED3FAF +:107020006B096D4FF2A6E37BDC5F1FFCE1227C9FC6 +:107030007B3969FF73F1D61058F7CA596CD73F3CBA +:10704000635131F49F67F09C6842BA7999D397698C +:10705000DF81F3783FB51DDC5E9FB5EFC0955750DB +:107060001F1F88A17CBDAF3083EEBBB963CF6348DF +:107070006F81FD3AE2838D6D7F7DEEB7D4CF4061A5 +:107080009479066F01865CDC457FBB1BF7352FDAF0 +:10709000FB19C29B8B6EA37DCE1BC5F9F9A9A2B9C2 +:1070A0008B903F0307F6FD0AF96F5E1C18B2B89F7C +:1070B000174D849F9A572717631C2010D35D81F3C7 +:1070C000D7BF60B0229DD6BC9A320BE302C70B79C2 +:1070D0007CBA7ACAA674D4AF9A43CFEFFE2DC629E4 +:1070E0005F30517EC695C0EDBB1AB9A56805E16F4A +:1070F000E76E7C371278DE4479D26A9803D7ABDE2C +:107100003D89E2EAAF7FFD4105E2A144DEBE1BEB13 +:107110003FDB65D2E03DF4E8ED713F423EECD191BA +:107120009F592DE0EADE517C3FD17DA584BFC44D3F +:10713000E9A85F6B46FDE676DCF73C79D373E8E7B8 +:10714000B03D06CA155C7C1EEE0DC65D6CD5D12B1C +:10715000D5C0F3315AA497CBD2A68A6770FE56DE0B +:10716000EFB26913DDA7BBF52686EB413F86F2EA55 +:10717000B2B439ACFE62EB9E5CF4432FBD308FFCA1 +:107180005195CE557EA9D96508D387240992C57B30 +:107190000952B36E66063D5B2DC04B07B7059E6175 +:1071A000C1F197DA747E3DDC51B581ADC5F7C12AD6 +:1071B0003FD4A4DD5686E7ABD1B464A1BD529DDFB8 +:1071C00057817C71D1C48CA9F88E4EE8AB9AF63504 +:1071D000F3D1EE1D693FB1E25DDFE7820F3FF79922 +:1071E0003CA1F9C1C8F26F4D4C3915F26EF89E06FC +:1071F00003D9EEEA7C6FEBBD75E89FD52770F97176 +:1072000016FAB7811C331771B9B76455787FA9880E +:10721000BF4BACD7F765A1DE53E7FFA650956B7D5A +:107220005928AF22C7CD9385BC7951227953D32EEB +:107230009D93E19E6A8C6E0FBEDFA94167929F53BA +:107240007B4DE2E3528BC4BDC3D8A78B3268DD9A75 +:107250003693DD04E36AA3FA62D11EAA8BE98B455B +:107260003B277048663B04BA1293057E2608948536 +:10727000C41DABBD3ABB2977183CA3DD84EF73F086 +:10728000BF61FDB622CE2755BE685A8F59FA8A9043 +:107290004EABB6878FC3735942F82FE0DB991CEAD7 +:1072A0008FDBC4BEFBA573C427FD5FBF9F8E78AF85 +:1072B000D1B0B59847BC24F1EF1E00A6EF1E2E8971 +:1072C0007C64CDDFCD51482F973EAF23BE0D487D66 +:1072D00024D7CE1C5C407229A0EB23B9D65354416D +:1072E000F22110DF578172EACCC17ADE3EBAAF429A +:1072F00081F64E84B17D1C237D7FB9E801921FF396 +:1073000064FEBE81EDD459781C687D6F13F9153A7F +:1073100025D4EFBE52A4E66DF4C173CB41BE093053 +:10732000655F3BF2619599E239603FB5BD8276DEDB +:10733000C2642BC6C5AB701CA7037D68FE2F31E16C +:10734000CB65889F45718E3B8B308F9DD347FE0365 +:107350005035D9E9F57F32901FD9AF1BD88D722AED +:1073600037CEB1B008F651A7EF5E87A1A72BBABE02 +:107370002ECCFBCD95B93C627B385D057276F2EF81 +:107380002444FEB0BA88CB5FD05BAC05E942E2F89A +:107390003DE67BF514CA9540F74492C7917C73D1C2 +:1073A000F7442CCA87D3A0C7DD217EFEE9A57B2840 +:1073B0004FBF00DF654079EFDA707A18FCEA67E4C6 +:1073C000EFB1C742EA910EB784C3917484F4E80F19 +:1073D000933B6EA29B3D82AF6A6775D7E33D0CC1BC +:1073E00077002C87C04723E088FEAC9CDB097BF04C +:1073F000BF61DEBA71FE5EF2CFF7F177B1CDA0BF0B +:10740000083E104D7963CD3ED04F895C3FA15EA808 +:107410008DEDA6B854E08081F2230F777C4CEF19F4 +:10742000810E29FE52DBF15A32FAED3EF4139248F6 +:107430000F26D33B95031DC9E86FA8F5751A6F9603 +:10744000788F4F76BA5AEF94FD59B8FF5AA93B1777 +:10745000DB7D8516D11F60196146E7A89338BFB35D +:107460000E99E47924DEF60A7A05B9904BEF2C0EDA +:10747000F1B8802A07AA853C398AF5399CEF2D6A34 +:107480005E49C2F772D1C3CA879B8A547BB881E236 +:1074900036BB8A147EAF623CCDCBE34AD45EFFFAA2 +:1074A000E5DC0939384E11E342E4D0C4A05C41FE6A +:1074B0004F25FE7F58970CE7AA794EB236A39C5A07 +:1074C000BCA614BAB3E5DA15A5142F13EF3F23F7C2 +:1074D000154947F6228EDF1A4D7C4962C87C97C059 +:1074E0005D4FCD233943EFE8EF4F7CBC14E313BF6E +:1074F00058BC99E87948DF84F2399E673B97E3C826 +:1075000036D734D7D3F1F286967529C3EC23729F10 +:10751000D58E96D264E5FA7A75BF974CEAFE66E995 +:107520009242EF61C19AD22428971BFFD17BE0E7FA +:10753000BDD461F0A35EAD5EBC625DDC3074739D52 +:107540003ED81EA2BF26207E3D94D71869FF9165C4 +:107550009DE4EFC5381103BE6A25FE027E09D10BFA +:107560006542BF0EC51BAA968E47BF9339968E47BC +:107570003D037C55611DC6AFC42F4B34F476C34D1B +:1075800065E47E3E2BE271D2B222CE2FA76CF66F5D +:1075900050BE8EF4BD85619AF4ADDF5BA46906DF51 +:1075A000417E4B4B8E51300F54323B9AF73B6CB2BD +:1075B00060DCA6FFF09714D7ED7FC4BC80E70BCC4E +:1075C0006C34B477A54EDD11AA473CD3385F46171B +:1075D00070BBC595ADFBF6B8504ECC505C88EC86C0 +:1075E0009C68CA93047C9F92DEEAEF2CB4603E2331 +:1075F000D00DDE21F093EBEBFF4A46FD1AE8FC8844 +:10760000DE8305BEFA98DE896D10EFF48EFAC43B76 +:10761000AB6E2586BE8B2BFBA014FB6D1465303E34 +:10762000C0E35A6AA9FAFF21FEEF946985C3FABF45 +:10763000090E73685C4049192E8E121A17C8D4F2CD +:10764000B800961817C8CCE4710184312E8025C685 +:1076500005B01EE30208635C00618C0B208C710195 +:107660002C312E80F59F89EF1FFA4130F178A599D2 +:10767000E4FA4A7CDF0EF7B7F230CF3BAD6C9529C8 +:107680007F8BDF3FA07EBBEEDD4CBB7837E3DD4C6C +:10769000793CD701D98A2872E9068E631CC7B55F89 +:1076A000B2AE41B9D2B480D6DFD059F8DE62AC6F49 +:1076B000D559350AD111C7638B44EFF46B3A5B2976 +:1076C000EE549C72584FF56D12C338E95D06EEE733 +:1076D0003A65A8CDA33C28D9C14E4337F91FB57BE5 +:1076E00025A532F49DC6F4AB2407D47CF232DEC467 +:1076F0009C5E935239CC3B90A177E7E2DDF432CC2B +:1077000033E37B71F92B7AD7EF04877414D2E156F7 +:10771000FEFED902FF88DF23DE35D574EE5F87EFEA +:10772000A122F3CD43DFD345E49DEBA789BCB28D05 +:107730007F5F51F664E5BE03B0DEE02603D91BEEA1 +:1077400042C703D39230EF6FA7F8C8F1C326F28B7C +:107750003EDC7C53587C84E53B1E9C46F9F9B11411 +:10776000AF68D449A48F67974D4CC17B9C7D42473D +:107770007AA737AF7C35F66B9CAA503CAAC4C01ED2 +:10778000A079C47B29151F25CD924703F05266A529 +:1077900077F64BE09A305ED9AF33AFC7774D4B18D1 +:1077A0007FE7A0D24DE36689E8060304789F15E2DF +:1077B0003E9774FEF94B7CC7709F81DBAD691A9EC2 +:1077C000BF4EDBC8DF33DCCF1C7AD4B3CB91BA64B5 +:1077D000D28F7FEA837A47F4D8746E972B2938FFCB +:1077E000D2933A7A6F5B92F2932C07E9E9627AC7F7 +:1077F00020F917C9D76E1E997F22DF311CD771B9C6 +:1078000002F748FE5017D225C5651C549E6CAAA2EB +:10781000F277E27B88EBDFFF0F9C453F312D25C6D9 +:107820008A726EC4EFDDA2BEFD7BAF17C4FBB53418 +:107830004D4FBE82F7F177B315EF437D2778CA56D7 +:10784000BE1FF1648F656E0B7D0F061210EEB5142E +:107850000F22615CDB6BC7EF8E060E4B167A977CAE +:107860009D7CDCFC08BE1371654A1649C1F8F7A679 +:107870009264D877E9840CDAB7CBC7E3A37443C921 +:10788000183FE7F84ACF731C9B5618AC9F27F82681 +:1078900000FD399DFCD083F4F61DE2A6BBB0BF9B72 +:1078A00099E87B6AFA83FDCCBB791CC54F55BA19A0 +:1078B0006C4BD98174F39E90FB8B17BFAB43FDDFFC +:1078C0009BEFE8C17D54545E7D2499CE377CFC4A01 +:1078D0007DA71E19BF0A959FFF3FDEA79F6A6AA07A +:1078E000F29DA655547637B9A93D44FE5F1A41FE74 +:1078F00047C63FAF227F47C63F99518923FD09FC08 +:10790000CDE3CD11F1CEB251F7AE87FB9BBD456FF4 +:10791000C52A35FE89EF87579A491EFCF7B461E303 +:107920009EEABD99294E3AC84C7978FFB3B2276ACE +:1079300035D0AE9DCEF1A7C61D913FF07CC81F5833 +:10794000227F68B541FE78560F2C5CC0F5BC9BF4D5 +:10795000BC89F0BA6E0DC80F80EF639630F97125BF +:10796000427E80C371377D57D56960182754DF5137 +:10797000CE82E28BBC61E48997CB937151DEE7E95B +:107980007BFFFA287A9F7B5CBC873BBE81BF87ABBD +:1079900064E5B4EE30722516F171DFA881B37F8003 +:1079A000FEF7FDDE4CF6CABAD1CB8AFE19B9724D8C +:1079B0007CD7F234FEAE80F6DB7E57E03109F3A1CE +:1079C0008DF7301BE259FD5D811491CFFE1EBF2B58 +:1079D000306D7AE177FF5D815BA78F5F1CFABB0298 +:1079E000B7FA3238ACFEAE001BBF7884DF15983D85 +:1079F0003DE9FADF15B86D3AF71747FA5D01B02790 +:107A0000CB705C92CD3E07CB34B1CFC8EF694F8AC3 +:107A1000FC5D97C6B118CBD258B796EA359E02FAEC +:107A20000E5EE3FD25F981F98E9FE3794B9FB04D02 +:107A3000C90638CDE02539D99B67BF13EBAFD9EC28 +:107A400077E13A917173C42DFAF7B09FBBB13DF263 +:107A5000DD958ACF15D3B9DC6814E58CE6E1BF2744 +:107A60006F9CCEF3F237DA37ECB706D71BDAFFA6F6 +:107A7000A505B81FD86F2DD6C37EEBB064E684B0E1 +:107A8000EF53AFA73337D155E3744E5F20CFE67D78 +:107A9000C8ED412AB3B49E78B41FC73CE489C7FD42 +:107AA0008E691930E177107F740F9850BFFF71F520 +:107AB0008009EBFF68E7EF9523E77F793AF703B298 +:107AC000660CD0F8F168E3937D3E108FF65356D5DF +:107AD00087EB28DFB27732E997F142BF8C7F68826B +:107AE000AF0FE86DFCB638CA67B3E2446AAF3172D3 +:107AF0003EAD79A8F2E00185BEDB9AF76188BD331F +:107B0000D903FB0EB3BFB483FCDD25C0784F7B7572 +:107B10000423CDA27DE564FCDDE5182137D04E5B62 +:107B20000C72C159F5E69794F7C7F1381FE66891D2 +:107B3000FE7CBA41F17D9A05FDD0E50BD674915FCC +:107B4000B875A85EF899FBD7A1DF0CF65B587D4DA0 +:107B5000E5912ED437B57BC3EB9D0D57C97F05FB4F +:107B60002DACFE9E5F9ED3F3DF2F08AF07FCEE45E2 +:107B7000BA54F17B5CE79D8C7EDE71679495BFDF24 +:107B8000F7D2EF95EC10DF3FEFFC8F599C6E04BEEF +:107B900061BC3774FCC8F4D14CFDDDB35836F2C378 +:107BA0008D4A552E0DFDFE899EB929BE373786E4D4 +:107BB0008E4BF855F59516D2F369F546925F25720E +:107BC0009415E1A1DF3F2993859CF212FFF7DC1E9B +:107BD0004F713C3A00C2095329EF93DCCCE1812478 +:107BE00003C987124D79DD1E28DFD4847FC7FE2CA0 +:107BF000CA0719F9977F87E9D27BF977E25AA5106E +:107C0000FDDC66C9BE0DBF7B6C96441CB1DA4CF935 +:107C1000827E8C2FC279B6C47BB62D8375B6DC9973 +:107C200043F6713FE3F2D4BD80E7ADB6C4972F5E53 +:107C300081ED0BA750FBC16F263E5E80F653759415 +:107C400015EDA72D366E5F6F999F4DEDAF4BCA1A9C +:107C50003CB7FB2146EB6C99CFCFBDE5F171E2FB60 +:107C60000B8F09F9794B8B7D34E6A366591C1710ED +:107C70005F63443E6E4B06D443F99454BEF07E9C41 +:107C8000672ADFEFEF6C0AC98FE30BA73CBE5B21CD +:107C900035E2C7BC906B6E0CF9C1FF0BB81F749432 +:107CA000704700000000000000000000000000001D +:087CB00005020D0000000000B8 +:00000001FF diff --git a/firmware/bnx2x-e1h-5.2.13.0.fw.ihex b/firmware/bnx2x-e1h-5.2.13.0.fw.ihex new file mode 100644 index 000000000000..ea3e254335b1 --- /dev/null +++ b/firmware/bnx2x-e1h-5.2.13.0.fw.ihex @@ -0,0 +1,12849 @@ +:1000000000003BE8000000600000068800003C5053 +:1000100000001968000042E0000000AC00005C50E5 +:1000200000008DF800005D00000000E80000EB001B +:100030000000E3140000EBF0000000940001CF0882 +:10004000000058E80001CFA0000000C40002289082 +:100050000000F9640002295800000004000322C0D7 +:10006000020400480000000F020400540000004594 +:1000700002040058000000840204005C0000000636 +:100080000204007000000004020400780000000078 +:100090000204007C121700000204008022170000F6 +:1000A00002040084321700000604008800000005E6 +:1000B0000204009C12150000020400A0221500009A +:1000C000020400A432150000060400A80000000489 +:1000D000020400B802100000020400BC001000007E +:1000E000020400C010100000020400C42010000030 +:1000F000020400C830100000020400CC40100000D0 +:10010000060400D000000003020400DC0010000020 +:10011000020400E012140000020400E422140000B3 +:10012000020400E832140000020400EC4214000053 +:10013000060400F000000003010401240000000098 +:1001400001040128000000000104012C000000004F +:100150000104013000000000020401D00000890603 +:1001600002040004000000FF02040008000000FF79 +:100170000204000C000000FF02040010000000FF59 +:1001800002040014000000FF02040018000000FF39 +:100190000204001C000000FF02040020000000FF19 +:1001A000020400240000003E0204002800000000B9 +:1001B0000204002C0000003F020400300000003F59 +:1001C000020400340000003F020400380000003F39 +:1001D0000204003C0000003F020400400000003F19 +:1001E000020400440000003F020404CC00000001AF +:1001F00002042008000002110204200C000002008A +:10020000020420100000020402042014000002195D +:100210000204201C0000FFFF020420200000FFFF5A +:10022000020420240000FFFF020420280000FFFF3A +:1002300002042038000000200204203C00000000DE +:100240000204204000000034020420440000003575 +:10025000060420480000001C020420B80000000131 +:10026000060420BC0000005F0204223807FFFFFFE5 +:100270000204223C0000003F0204224007FFFFFF6F +:10028000020422440000000F010422480000000084 +:100290000104224C00000000010422500000000074 +:1002A0000104225400000000010422580000000054 +:1002B0000104225C00000000010422600000000034 +:1002C0000104226400000000010422680000000014 +:1002D0000104226C000000000104227000000000F4 +:1002E00001042274000000000104227800000000D4 +:1002F0000104227C000000000C042000000003E840 +:100300000A042000000000010B0420000000000A85 +:1003100002050044000000200205004800000032F1 +:10032000020500900215002002050094021500202D +:1003300002050098000000300205009C0810000033 +:10034000020500A000000033020500A400000030F8 +:10035000020500A800000031020500AC0000000208 +:10036000020500B000000005020500B40000000610 +:10037000020500B800000002020500BC00000002F7 +:10038000020500C000000000020500C400000005D6 +:10039000020500C800000002020500CC00000002B7 +:1003A000020500D000000002020500D40000000198 +:1003B00002050114000000010205011C00000001FB +:1003C00002050120000000020205020400000001F5 +:1003D0000205020C0000004002050210000000406F +:1003E0000205021C0000002002050220000000138C +:1003F0000205022400000020060502400000000A59 +:1004000004050280002000000205005000000007E3 +:100410000205005400000007020500580000000813 +:100420000205005C000000080205006000000001F9 +:100430000605006400000003020500D80000000665 +:100440000205000400000001020500080000000190 +:100450000205000C00000001020500100000000170 +:100460000205001400000001020500180000000150 +:100470000205001C00000001020500200000000130 +:100480000205002400000001020500280000000110 +:100490000205002C000000010205003000000001F0 +:1004A00002050034000000010205003800000001D0 +:1004B0000205003C000000010205004000000001B0 +:1004C000020500E00000000D020500E80000000742 +:1004D000020500F000000007020500F80000000718 +:1004E000020500E40000002D020500EC00000027DA +:1004F000020500F400000027020500FC00000027B0 +:10050000020500E00000001D020500E800000017E1 +:10051000020500F000000017020500F800000017B7 +:10052000020500E40000003D020500EC0000003779 +:10053000020500F400000037020500FC000000374F +:10054000020500E00000004D020500E80000004741 +:10055000020500F000000047020500F80000004717 +:10056000020500E40000006D020500EC00000067D9 +:10057000020500F400000067020500FC00000067AF +:10058000020500E00000005D020500E800000057E1 +:10059000020500F000000057020500F800000057B7 +:1005A000020500E40000007D020500EC0000007779 +:1005B000020500F400000077020500FC000000774F +:1005C0000406100002000020020600DC000000010A +:1005D000010600D80000000004060200000302200B +:1005E000020600DC00000000010600B80000000068 +:1005F000010600C800000000010600BC0000000069 +:10060000010600CC000000000718040000A900004B +:10061000081807C800070223071C00002C2C000044 +:10062000071C800038930B0C071D0000293119317D +:10063000081D686052F40225011800000000000047 +:10064000011800040000000001180008000000006C +:100650000118000C0000000001180010000000004C +:100660000118001400000000021800200000000122 +:1006700002180024000000020218002800000003F5 +:100680000218002C000000000218003000000004D6 +:1006900002180034000000010218003800000000B9 +:1006A0000218003C00000001021800400000000495 +:1006B0000218004400000000021800480000000179 +:1006C0000218004C00000003021800500000000057 +:1006D0000218005400000001021800580000000435 +:1006E0000218005C00000000021800600000000119 +:1006F00002180064000000030218006800000000F7 +:100700000218006C000000010218007000000004D4 +:1007100002180074000000000218007800000004B5 +:100720000218007C00000003061800800000000290 +:10073000021800A400003FFF021800A8000003FFF9 +:100740000218022400000000021802340000000019 +:100750000218024C00000000021802E4000000FF32 +:100760000618100000000400021B8BC000000001EE +:10077000021B800000000034021B804000000018B3 +:10078000021B80800000000C021B80C000000020C3 +:100790000C1B83000007A1200A1B83000000013806 +:1007A0000B1B830000001388021B83C0000001F4B0 +:1007B000021B1480000000010A1B148000000000CE +:1007C000061A1000000003B3041A1ECC0001022711 +:1007D000061AA020000000C8061AA00000000002AF +:1007E000021A1ED000000000061A1ED800000006E3 +:1007F000061A36E800000004061A36E0000000027F +:10080000061A500000000002061A500800000004FA +:10081000061A501800000004061A502800000004B0 +:10082000061A503800000004061A50480000000460 +:10083000061A505800000004061A50680000000410 +:10084000061A507800000002041A404000020228F4 +:10085000061A400000000002061A400800000002CC +:10086000041A62C00020022A061AD1000000000209 +:10087000061A200000000124061AB000000000281B +:10088000061AB1400000000C061A330000000014E4 +:10089000061A33A000000068061A81080000000252 +:1008A000061AD1C800000002061AD1D800000020A4 +:1008B000061A249000000124061AB0A000000028A7 +:1008C000061AB1700000000C061A33500000001424 +:1008D000061A354000000068061A81100000000268 +:1008E000061AD1D000000002061AD25800000020DB +:1008F000021A292000000000061A30000000000241 +:10090000041A30080005024A061A301C00000009CB +:10091000061A320000000008061A5000000000020B +:10092000061A508000000012061A40000000000263 +:10093000061AD0C000000002021A2924000000009C +:10094000061A304000000002041A30480005024F29 +:10095000061A305C00000009061A32200000000868 +:10096000061A501000000002061A50C800000012BB +:10097000061A400800000002061AD0C80000000253 +:10098000021A292800000000061A30800000000228 +:10099000041A308800050254061A309C0000000931 +:1009A000061A324000000008061A5020000000021B +:1009B000061A511000000012041A401000020259D9 +:1009C000061AD0D000000002021A292C00000000F4 +:1009D000061A30C000000002041A30C80005025B8D +:1009E000061A30DC00000009061A32600000000818 +:1009F000061A503000000002061A5158000000127A +:100A0000041A401800020260061AD0D80000000242 +:100A1000021A293000000000061A3100000000020E +:100A2000041A310800050262061A311C0000000990 +:100A3000061A328000000008061A5040000000022A +:100A4000061A51A000000012041A4020000202679A +:100A5000061AD0E000000002021A2934000000004B +:100A6000061A314000000002041A314800050269EC +:100A7000061A315C00000009061A32A000000008C6 +:100A8000061A505000000002061A51E80000001239 +:100A9000041A40280002026E061AD0E80000000284 +:100AA000021A293800000000061A318000000002F6 +:100AB000041A318800050270061A319C00000009F2 +:100AC000061A32C000000008061A5060000000023A +:100AD000061A523000000012041A4030000202755B +:100AE000061AD0F000000002021A293C00000000A3 +:100AF000061A31C000000002041A31C8000502774E +:100B0000061A31DC00000009061A32E00000000875 +:100B1000061A507000000002061A527800000012F7 +:100B2000041A40380002027C061AD0F800000002C5 +:100B30000200A294071D29110200A29800000000E3 +:100B40000200A29C009C04240200A2A0000000005D +:100B50000200A2A4000002090200A270000000002E +:100B60000200A274000000000200A2700000000059 +:100B70000200A274000000000200A2700000000049 +:100B80000200A274000000000200A2700000000039 +:100B90000200A27400000000020100B40000000185 +:100BA000020100B800000001020100DC00000001A9 +:100BB0000201010000000001020101040000000127 +:100BC0000201007C003000000201008400000028C7 +:100BD0000201008C0000000002010130000000044E +:100BE0000201025C00000001020103280000000075 +:100BF0000201607000000007020160800000000137 +:100C00000201055400000030020100C40000000190 +:100C1000020100CC00000001020100F80000000108 +:100C2000020100F00000000102010080003000001D +:100C3000020100880000002802010090000000006E +:100C40000201013400000004020102DC0000000186 +:100C50000201032C00000000020160740000000784 +:100C60000201608400000001020105640000003000 +:100C7000020100C800000001020100D000000001D4 +:100C8000020100FC00000001020100F4000000016C +:100C9000020C100000000020020C200800000211CD +:100CA000020C200C00000200020C201000000204C4 +:100CB000020C201C0000FFFF020C20200000FFFFA0 +:100CC000020C20240000FFFF020C20280000FFFF80 +:100CD000060C203800000002020C20400000003406 +:100CE000020C204400000035020C204800000020C7 +:100CF000020C204C00000021020C205000000022B9 +:100D0000020C205400000023020C20580000002494 +:100D1000020C205C00000025020C20600000002670 +:100D2000020C206400000027020C2068000000284C +:100D3000020C206C00000029020C20700000002A28 +:100D4000020C20740000002B060C207800000056D6 +:100D5000020C21D000000001020C21D4000000018F +:100D6000020C21D800000001020C21DC000000016F +:100D7000020C21E000000001020C21E4000000014F +:100D8000020C21E800000001020C21EC000000012F +:100D9000020C21F000000001020C21F4000000010F +:100DA000060C21F800000010020C223807FFFFFF9C +:100DB000020C223C0000003F020C224007FFFFFF14 +:100DC000020C22440000000F010C22480000000029 +:100DD000010C224C00000000010C22500000000019 +:100DE000010C225400000000010C225800000000F9 +:100DF000010C225C00000000010C226000000000D9 +:100E0000010C226400000000010C226800000000B8 +:100E1000010C226C00000000010C22700000000098 +:100E2000010C227400000000010C22780000000078 +:100E3000010C227C000000000C0C2000000003E8E4 +:100E40000A0C2000000000010B0C20000000000A2A +:100E5000020C400800000411020C400C00000400C9 +:100E6000020C401000000404020C40140000042195 +:100E7000020C401C0000FFFF020C40200000FFFF9E +:100E8000020C40240000FFFF020C40280000FFFF7E +:100E9000020C403800000046020C403C00000005F7 +:100EA000060C404000000002020C40480000000A0E +:100EB000020C404C000000F0060C40500000001FE7 +:100EC000020C40CC00000001060C40D00000003AAB +:100ED000020C41B800000001060C41BC00000003F8 +:100EE000020C41C800000001020C41CC00000001CE +:100EF000060C41D00000001A020C423807FFFFFF29 +:100F0000020C423C0000003F020C424007FFFFFF82 +:100F1000020C42440000000F010C42480000000097 +:100F2000010C424C00000000010C42500000000087 +:100F3000010C425400000000010C42580000000067 +:100F4000010C425C00000000010C42600000000047 +:100F5000010C426400000000010C42680000000027 +:100F6000010C426C00000000010C42700000000007 +:100F7000010C427400000000010C427800000000E7 +:100F8000010C427C00000000010C428000000000C7 +:100F90000C0C4000000003E80A0C400000000001B7 +:100FA0000B0C40000000000A020D0044000000325B +:100FB000020D008C02150020020D00900215002089 +:100FC000020D009408100000020D0098000000338C +:100FD000020D009C00000002020D00A000000000B5 +:100FE000020D00A400000005020D00A8000000058D +:100FF000060D00AC00000002020D00B4000000026B +:10100000020D00B800000003020D00BC0000000249 +:10101000020D00C000000001020D00C80000000227 +:10102000020D00CC00000002020D010800000001CA +:10103000020D015C00000001020D016400000001CE +:10104000020D016800000002020D02040000000110 +:10105000020D020C00000020020D021000000040F2 +:10106000020D021400000040020D022000000003E7 +:10107000020D022400000018060D0280000000127C +:10108000040D03000024027E020D004C000000014C +:10109000020D005000000002020D00540000000884 +:1010A000020D005800000008060D005C000000045E +:1010B000020D00C400000004020D00040000000145 +:1010C000020D000800000001020D000C00000001EC +:1010D000020D001000000001020D001400000001CC +:1010E000020D001800000001020D001C00000001AC +:1010F000020D002000000001020D0024000000018C +:10110000020D002800000001020D002C000000016B +:10111000020D003000000001020D0034000000014B +:10112000020D003800000001020D003C000000012B +:10113000020D011400000009020D011C0000000A4C +:10114000020D012400000007020D012C0000000721 +:10115000020D01340000000C020D013C0000000BE8 +:10116000020D014400000007020D011800000029D3 +:10117000020D01200000002A020D012800000027B6 +:10118000020D013000000027020D01380000002C84 +:10119000020D01400000002B020D01480000002755 +:1011A000020D011400000019020D011C0000001ABC +:1011B000020D012400000017020D012C0000001791 +:1011C000020D01340000001C020D013C0000001B58 +:1011D000020D014400000017020D01180000003943 +:1011E000020D01200000003A020D01280000003726 +:1011F000020D013000000037020D01380000003CF4 +:10120000020D01400000003B020D014800000037C4 +:10121000020D011400000049020D011C0000004AEB +:10122000020D012400000047020D012C00000047C0 +:10123000020D01340000004C020D013C0000004B87 +:10124000020D014400000047020D01180000006972 +:10125000020D01200000006A020D01280000006755 +:10126000020D013000000067020D01380000006C23 +:10127000020D01400000006B020D014800000067F4 +:10128000020D011400000059020D011C0000005A5B +:10129000020D012400000057020D012C0000005730 +:1012A000020D01340000005C020D013C0000005BF7 +:1012B000020D014400000057020D011800000079E2 +:1012C000020D01200000007A020D012800000077C5 +:1012D000020D013000000077020D01380000007C93 +:1012E000020D01400000007B020D01480000007764 +:1012F000020E004C00000032020E00940215002085 +:10130000020E009802150020020E009C0000003022 +:10131000020E00A008100000020E00A4000000331E +:10132000020E00A800000030020E00AC00000031E8 +:10133000020E00B000000002020E00B40000000423 +:10134000020E00B800000000020E00BC0000000207 +:10135000020E00C000000002020E00C400000000E7 +:10136000020E00C800000002020E00CC00000007C0 +:10137000020E00D000000002020E00D400000002A5 +:10138000020E00D800000001020E00E4000000017F +:10139000020E014400000001020E014C0000000199 +:1013A000020E015000000002020E020400000001C3 +:1013B000020E020C00000040020E0210000000406D +:1013C000020E021C00000004020E02200000002099 +:1013D000020E02240000000E020E02280000001B74 +:1013E000060E030000000012040E0280001B02A281 +:1013F000020E00540000000C020E0058000000090C +:10140000020E005C0000000F020E006000000010E1 +:10141000020E00640000000B060E006800000003CE +:10142000020E00DC00000003020E000400000001B8 +:10143000020E000800000001020E000C0000000176 +:10144000020E001000000001020E00140000000156 +:10145000020E001800000001020E001C0000000136 +:10146000020E002000000001020E00240000000116 +:10147000020E002800000001020E002C00000001F6 +:10148000020E003000000001020E003400000001D6 +:10149000020E003800000001020E003C00000001B6 +:1014A000020E004000000001020E00440000000196 +:1014B000020E01100000000F020E01180000000EC5 +:1014C000020E012000000000020E012800000000B2 +:1014D000020E01140000002F020E011C0000002E5D +:1014E000020E012400000000020E012C000000008A +:1014F000020E01100000001F020E01180000001E65 +:10150000020E012000000000020E01280000000071 +:10151000020E01140000003F020E011C0000003EFC +:10152000020E012400000000020E012C0000000049 +:10153000020E01100000004F020E01180000004EC4 +:10154000020E012000000000020E01280000000031 +:10155000020E01140000006F020E011C0000006E5C +:10156000020E012400000000020E012C0000000009 +:10157000020E01100000005F020E01180000005E64 +:10158000020E012000000000020E012800000000F1 +:10159000020E01140000007F020E011C0000007EFC +:1015A000020E012400000000020E012C00000000C9 +:1015B0000730040000E50000083007D8000502BD30 +:1015C000073400002EF7000007348000311A0BBEEC +:1015D00007350000356F18050735800038C42561D0 +:1015E0000736000014C5339308363400398002BF33 +:1015F0000130000000000000013000040000000085 +:1016000001300008000000000130000C0000000064 +:101610000130001000000000013000140000000044 +:10162000023000200000000102300024000000020F +:1016300002300028000000030230002C00000000EF +:1016400002300030000000040230003400000001CD +:1016500002300038000000000230003C00000001B1 +:10166000023000400000000402300044000000008E +:1016700002300048000000010230004C000000036E +:101680000230005000000000023000540000000151 +:1016900002300058000000040230005C000000002E +:1016A000023000600000000102300064000000030E +:1016B00002300068000000000230006C00000001F1 +:1016C00002300070000000040230007400000000CE +:1016D00002300078000000040230007C00000003AB +:1016E0000630008000000002023000A400003FFF2E +:1016F000023000A8000003FF0230022400000000B6 +:1017000002300234000000000230024C00000000F1 +:10171000023002E40000FFFF063020000000080055 +:1017200002338BC000000001023380000000001A69 +:10173000023380400000004E023380800000001021 +:10174000023380C0000000200C3383000007A1207A +:101750000A338300000001380B3383000000138834 +:10176000023383C0000001F40C3383801DCD65007B +:101770000A3383800004C4B40B338380004C4B4095 +:101780000A331480000000000233148000000001BE +:10179000063220000000010206328020000000C84E +:1017A000063280000000000206323DA8000000045E +:1017B00006323D800000000904323DA4000102C150 +:1017C00006323D00000000200632500000000400F8 +:1017D0000632400000000004063240D00000000243 +:1017E00006326B680000000204326B70000202C215 +:1017F00006326B1000000002043274C0000202C402 +:101800000632DA40000000020632E0000000080064 +:10181000023308000100000004330C00001002C66F +:10182000023308000000000004330C40001002D610 +:1018300006322450000000B406322AD00000000214 +:1018400006321000000001A002323DB80000000086 +:101850000632500000000020063251000000002037 +:101860000632520000000020063253000000002023 +:10187000063254000000002006325500000000200F +:1018800006325600000000200632570000000020FB +:1018900006325800000000200632590000000020E7 +:1018A00006325A000000002006325B0000000020D3 +:1018B00006325C000000002006325D0000000020BF +:1018C00006325E000000002006325F0000000020AB +:1018D00006326B780000005206326E080000000CE1 +:1018E0000632DA880000000206322720000000B429 +:1018F00006322AD80000000206321680000001A03D +:1019000002323DBC00000000063250800000002082 +:101910000632518000000020063252800000002074 +:101920000632538000000020063254800000002060 +:10193000063255800000002006325680000000204C +:101940000632578000000020063258800000002038 +:10195000063259800000002006325A800000002024 +:1019600006325B800000002006325C800000002010 +:1019700006325D800000002006325E8000000020FC +:1019800006325F800000002006326CC0000000526A +:1019900006326E380000000C0632DA9000000002B9 +:1019A00002322A300000000006324010000000021F +:1019B0000632D0000000000602322A340000000087 +:1019C00006324020000000020632D0180000000657 +:1019D00002322A38000000000632403000000002C7 +:1019E0000632D0300000000602322A3C000000001F +:1019F00006324040000000020632D04800000006D7 +:101A000002322A400000000006324050000000026E +:101A10000632D0600000000602322A4400000000B6 +:101A200006324060000000020632D0780000000656 +:101A300002322A4800000000063240700000000216 +:101A40000632D0900000000602322A4C000000004E +:101A500006324080000000020632D0A800000006D6 +:101A6000072004000093000008200780001002E611 +:101A7000072400002ADE0000072480002E050AB893 +:101A80000824E4A061D202E8012000000000000068 +:101A900001200004000000000120000800000000F8 +:101AA0000120000C000000000120001000000000D8 +:101AB00001200014000000000220002000000001AE +:101AC0000220002400000002022000280000000381 +:101AD0000220002C00000000022000300000000462 +:101AE0000220003400000001022000380000000045 +:101AF0000220003C00000001022000400000000421 +:101B00000220004400000000022000480000000104 +:101B10000220004C000000030220005000000000E2 +:101B200002200054000000010220005800000004C0 +:101B30000220005C000000000220006000000001A4 +:101B40000220006400000003022000680000000082 +:101B50000220006C00000001022000700000000460 +:101B60000220007400000000022000780000000441 +:101B70000220007C0000000306200080000000021C +:101B8000022000A400003FFF022000A8000003FF85 +:101B900002200224000000000220023400000000A5 +:101BA0000220024C00000000022002E40000FFFFBF +:101BB000062020000000080002238BC00000000166 +:101BC0000223800000000010022380400000001269 +:101BD0000223808000000030022380C00000000E3D +:101BE000022383C0000001F40223148000000001DE +:101BF0000A231480000000000622100000000042AA +:101C000006227020000000C80622700000000002BA +:101C1000022211E80000000006223000000000C08F +:101C2000062240700000008006225280000000045E +:101C30000622670000000100062290000000040058 +:101C400004226B08002002EA02230800013FFFFF84 +:101C500004230C000010030A022308000000000007 +:101C600004230C400010031A06228100000000A08B +:101C7000062286000000004006228C000000003C86 +:101C80000622B0000000020006228800000000804A +:101C900006228DE00000003C0622404000000006C5 +:101CA00006228380000000A006228700000000407A +:101CB00006228CF00000003C0622B8000000020062 +:101CC00006228A000000008006228ED00000003C20 +:101CD000062240580000000606228000000000088E +:101CE000022211480000000006223300000000021A +:101CF000062260400000003006228020000000081C +:101D00000222114C000000000622330800000002ED +:101D1000062261000000003006228040000000081A +:101D200002221150000000000622331000000002C1 +:101D3000062261C00000003006228060000000081A +:101D40000222115400000000062233180000000295 +:101D50000622628000000030062280800000000819 +:101D60000222115800000000062233200000000269 +:101D70000622634000000030062280A00000000818 +:101D80000222115C0000000006223328000000023D +:101D90000622640000000030062280C00000000817 +:101DA0000222116000000000062233300000000211 +:101DB000062264C000000030062280E00000000817 +:101DC00002221164000000000622333800000002E5 +:101DD0000622658000000030021610000000002876 +:101DE00002170008000000020217002C0000000388 +:101DF0000217003C00000004021700440000000825 +:101E000002170048000000020217004C000000907A +:101E1000021700500000009002170054008000904C +:101E20000217005808140000021700600000008A22 +:101E300002170064000000800217006800000081A3 +:101E40000217006C000000800217007000000006FE +:101E500002170078000007D00217007C0000076C12 +:101E600002170038007C1004021700040000000F65 +:101E70000616402400000002021640700000001CFC +:101E80000216420800000001021642100000000184 +:101E90000216422000000001021642280000000144 +:101EA0000216423000000001021642380000000114 +:101EB00002164260000000020C16401C0003D09085 +:101EC0000A16401C0000009C0B16401C000009C4B0 +:101ED0000216403000000008021640340000000CDA +:101EE0000216403800000010021640440000002096 +:101EF0000216400000000001021640D80000000158 +:101F000002164008000000010216400C000000010B +:101F100002164010000000010216424000000000BE +:101F2000021642480000000006164270000000023F +:101F30000216425000000000021642580000000045 +:101F40000616428000000002021660080000042409 +:101F50000216600C00000410021660100000041449 +:101F60000216601C0000FFFF021660200000FFFF49 +:101F7000021660240000FFFF021660280000FFFF29 +:101F800002166038000000200216603C00000020AD +:101F90000216604000000034021660440000003564 +:101FA00002166048000000230216604C0000002466 +:101FB0000216605000000025021660540000002642 +:101FC00002166058000000270216605C000000291D +:101FD000021660600000002A021660640000002BF8 +:101FE000021660680000002C0216606C0000002DD4 +:101FF0000616607000000052021661B80000000171 +:10200000061661BC0000001F0216623807FFFFFFC2 +:102010000216623C0000003F0216624007FFFFFF0D +:10202000021662440000000F011662480000000022 +:102030000116624C00000000011662500000000012 +:1020400001166254000000000116625800000000F2 +:102050000116625C000000000116626000000000D2 +:1020600001166264000000000116626800000000B2 +:102070000116626C00000000011662700000000092 +:102080000116627400000000011662780000000072 +:102090000116627C000000000C166000000003E8DE +:1020A0000A166000000000010B1660000000000A24 +:1020B0000216804000000006021680440000000561 +:1020C000021680480000000A0216804C000000053D +:1020D0000216805400000002021680CC00000004AA +:1020E000021680D000000004021680D40000000414 +:1020F000021680D800000004021680DC00000004F4 +:10210000021680E000000004021680E400000004D3 +:10211000021680E800000004021688040000000493 +:10212000021680300000007C021680340000003D62 +:10213000021680380000003F0216803C0000009C20 +:10214000021680F000000007061680F4000000056B +:102150000216880C0101010102168108000000002E +:102160000216810C00000004021681100000000419 +:1021700002168114000000020216881008012004D3 +:1021800002168118000000050216811C00000005DF +:1021900002168120000000050216812400000005BF +:1021A0000216882C20081001021681280000000861 +:1021B0000216812C00000006021681300000000784 +:1021C000021681340000000002168830010101204F +:1021D000061681380000000402168834010101014E +:1021E00002168148000000000216814C0000000425 +:1021F0000216815000000004021681540000000203 +:1022000002168838080120040216815800000005D3 +:102210000216815C000000050216816000000005C6 +:1022200002168164000000050216883C2008100197 +:1022300002168168000000080216816C000000068A +:102240000216817000000007021681740000000170 +:102250000216884001010120021681780000000169 +:102260000216817C0000000102168180000000013E +:102270000216818400000001021688440101010158 +:1022800002168188000000010216818C0000000403 +:1022900002168190000000040216819400000002E2 +:1022A00002168848080120040216819800000005E3 +:1022B0000216819C00000005021681A000000005A6 +:1022C000021681A4000000050216881420081001DF +:1022D000021681A800000008021681AC000000066A +:1022E000021681B000000007021681B40000000150 +:1022F0000216881801010120021681B800000001B1 +:10230000021681BC00000001021681C0000000011D +:10231000021681C4000000010216881C010101019F +:10232000021681C800000001021681CC00000004E2 +:10233000021681D000000004021681D400000002C1 +:102340000216882008012004021681D8000000052A +:10235000021681DC00000005021681E00000000585 +:10236000021681E4000000050216882420081001EE +:10237000021681E800000008021681EC0000000649 +:10238000021681F0000000070216E40C00000000B5 +:1023900002168828010101200616E410000000043E +:1023A0000216E000010101010216E4200000000015 +:1023B0000216E424000000040216E42800000004D1 +:1023C0000216E42C000000020216E00408012004BA +:1023D0000216E430000000050216E4340000000597 +:1023E0000216E438000000050216E43C0000000577 +:1023F0000216E008200810010216E4400000000860 +:102400000216E444000000060216E448000000073B +:102410000216E44C000000000216E00C010101204D +:102420000616E450000000040216E010010101014C +:102430000216E460000000000216E46400000004DC +:102440000216E468000000040216E46C00000002BA +:102450000216E014080120040216E47000000005D2 +:102460000216E474000000050216E478000000057E +:102470000216E47C000000050216E0182008100196 +:102480000216E480000000080216E4840000000642 +:102490000216E488000000070216E48C0000000128 +:1024A0000216E01C010101200216E4900000000168 +:1024B0000216E494000000010216E49800000001F6 +:1024C0000216E49C000000010216E0200101010157 +:1024D0000216E4A0000000010216E4A400000004BB +:1024E0000216E4A8000000040216E4AC000000029A +:1024F0000216E024080120040216E4B000000005E2 +:102500000216E4B4000000050216E4B8000000055D +:102510000216E4BC000000050216E02820081001A5 +:102520000216E4C0000000080216E4C40000000621 +:102530000216E4C8000000070216E4CC0000000107 +:102540000216E02C010101200216E4D00000000177 +:102550000216E4D4000000010216E4D800000001D5 +:102560000216E4DC000000010216E0300101010166 +:102570000216E4E0000000010216E4E4000000049A +:102580000216E4E8000000040216E4EC0000000279 +:102590000216E034080120040216E4F000000005F1 +:1025A0000216E4F4000000050216E4F8000000053D +:1025B0000216E4FC000000050216E03820081001B5 +:1025C0000216E500000000080216E50400000006FF +:1025D0000216E508000000070216E03C0101012098 +:1025E00002168240003F003F0216824400000000B5 +:1025F0000216E524003F003F0216E5280000000017 +:1026000002168248000000000216824C003F003F84 +:102610000216E52C000000000216E530003F003FE6 +:1026200002168250010001000216825401000100CE +:102630000216E534010001000216E5380100010030 +:1026400006168258000000020216E53C0000000059 +:102650000216E540000000000216826000C000C0C3 +:102660000216826400C000C00216E54400C000C02B +:102670000216E54800C000C0021682681E001E0057 +:102680000216826C1E001E000216E54C1E001E0083 +:102690000216E5501E001E00021682704000400027 +:1026A00002168274400040000216E55440004000CB +:1026B0000216E55840004000021682788000800033 +:1026C0000216827C800080000216E55C800080009B +:1026D0000216E56080008000021682802000200043 +:1026E00002168284200020000216E56420002000EB +:1026F0000216E5682000200006168288000000020D +:102700000216E56C000000000216E57000000000F3 +:102710000216829000000000021682940000000061 +:102720000216E574000000000216E57800000000C3 +:1027300002168298000000000216829C0000000031 +:102740000216E57C000000000216E5800000000093 +:10275000021682A000000000021682A40000000100 +:10276000061682A80000000A021681F400000C0878 +:10277000021681F800000040021681FC00000100F2 +:1027800002168200000000200216820400000017DA +:1027900002168208000000800216820C000002006F +:1027A00002168210000000000216821801FF01FFCD +:1027B0000216821401FF01FF0216E51001FF01FF5E +:1027C0000216E50C01FF01FF0216823C0000001317 +:1027D000021680900000013F021680600000014058 +:1027E00002168064000001400616806800000002A6 +:1027F00002168070000000C00616807400000007FA +:102800000216809C00000048021680A000000048CC +:10281000061680A400000002021680AC00000048EA +:10282000061680B000000007021682380000800003 +:1028300002168234000025E40216809400007FFF17 +:1028400002168220000F000F0216821C000F000FDC +:102850000216E518000F000F0216E514000F000F16 +:10286000021682280000000002168224FFFFFFFFEC +:102870000216E520000000000216E51CFFFFFFFF26 +:102880000216E6BC000000000216E6C000000002CE +:102890000216E6C4000000010216E6C800000003AC +:1028A0000216E6CC000000040216E6D00000000686 +:1028B0000216E6D4000000050216E6D80000000764 +:1028C000021680EC000000FF02140000000000016E +:1028D0000214000C0000000102140040000000017E +:1028E0000214004400007FFF0214000C00000000EE +:1028F00002140000000000000214006C0000000040 +:102900000214000400000001021400300000000165 +:1029100002140004000000000214005C000000002B +:10292000021400080000000102140034000000013D +:102930000214000800000000021400600000000003 +:102940000202005800000032020200A0031500201D +:10295000020200A403150020020200A801000030BA +:10296000020200AC08100000020200B000000033B8 +:10297000020200B400000030020200B80000003182 +:10298000020200BC00000003020200C000000006BA +:10299000020200C400000003020200C8000000039D +:1029A000020200CC00000002020200D00000000081 +:1029B000020200D400000002020200DC000000005D +:1029C000020200E000000006020200E40000000431 +:1029D000020200E800000002020200EC0000000217 +:1029E000020200F000000001020200FC00000006EC +:1029F0000202012000000000020201340000000277 +:102A0000020201B0000000010202020C00000001FD +:102A1000020202140000000102020218000000027B +:102A200002020404000000010202040C0000004045 +:102A300002020410000000400202041C0000000416 +:102A40000202042000000020020204240000000210 +:102A50000202042800000020060205000000001207 +:102A600004020480001F032A020200600000000F1D +:102A70000202006400000007020200680000000B70 +:102A80000202006C0000000E020200700000000E46 +:102A90000602007400000003020200F400000004BB +:102AA0000202000400000001020200080000000110 +:102AB0000202000C000000010202001000000001F0 +:102AC00002020014000000010202001800000001D0 +:102AD0000202001C000000010202002000000001B0 +:102AE0000202002400000001020200280000000190 +:102AF0000202002C00000001020200300000000170 +:102B0000020200340000000102020038000000014F +:102B10000202003C0000000102020040000000012F +:102B2000020200440000000102020048000000010F +:102B30000202004C000000010202005000000001EF +:102B400002020108000000C8020201180000000291 +:102B5000020201C400000000020201CC00000000DB +:102B6000020201D400000002020201DC00000002A7 +:102B7000020201E4000000FF020201EC000000FF7D +:102B800002020100000000000202010C000000C867 +:102B90000202011C00000002020201C80000000045 +:102BA000020201D000000000020201D80000000271 +:102BB000020201E000000002020201E8000000FF42 +:102BC000020201F0000000FF020201040000000008 +:102BD00002020108000000C8020201180000000201 +:102BE000020201C400000000020201CC000000004B +:102BF000020201D400000002020201DC0000000217 +:102C0000020201E4000000FF020201EC000000FFEC +:102C100002020100000000000202010C000000C8D6 +:102C20000202011C00000002020201C800000000B4 +:102C3000020201D000000000020201D800000002E0 +:102C4000020201E000000002020201E8000000FFB1 +:102C5000020201F0000000FF020201040000000077 +:102C600002020108000000C8020201180000000270 +:102C7000020201C400000000020201CC00000000BA +:102C8000020201D400000002020201DC0000000286 +:102C9000020201E4000000FF020201EC000000FF5C +:102CA00002020100000000000202010C000000C846 +:102CB0000202011C00000002020201C80000000024 +:102CC000020201D000000000020201D80000000250 +:102CD000020201E000000002020201E8000000FF21 +:102CE000020201F0000000FF0202010400000000E7 +:102CF00002020108000000C80202011800000002E0 +:102D0000020201C400000000020201CC0000000029 +:102D1000020201D400000002020201DC00000002F5 +:102D2000020201E4000000FF020201EC000000FFCB +:102D300002020100000000000202010C000000C8B5 +:102D40000202011C00000002020201C80000000093 +:102D5000020201D000000000020201D800000002BF +:102D6000020201E000000002020201E8000000FF90 +:102D7000020201F0000000FF020201040000000056 +:102D80000728040000C00000082807A8000B03491A +:102D9000072C000032FC0000072C800035780CC0A6 +:102DA000072D00003AC11A1F072D800039E228D0F4 +:102DB000072E00001C3E3749082E3710391E034BE2 +:102DC00001280000000000000128000400000000AD +:102DD00001280008000000000128000C000000008D +:102DE000012800100000000001280014000000006D +:102DF0000228002000000001022800240000000238 +:102E000002280028000000030228002C0000000017 +:102E100002280030000000040228003400000001F5 +:102E200002280038000000000228003C00000001D9 +:102E300002280040000000040228004400000000B6 +:102E400002280048000000010228004C0000000396 +:102E50000228005000000000022800540000000179 +:102E600002280058000000040228005C0000000056 +:102E70000228006000000001022800640000000336 +:102E800002280068000000000228006C0000000119 +:102E900002280070000000040228007400000000F6 +:102EA00002280078000000040228007C00000003D3 +:102EB0000628008000000002022800A400003FFF56 +:102EC000022800A8000003FF0228022400000000DE +:102ED00002280234000000000228024C000000001A +:102EE000022802E40000FFFF06282000000008007E +:102EF000022B8BC000000001022B800000000000AC +:102F0000022B804000000018022B80800000000C83 +:102F1000022B80C0000000660C2B83000007A1205C +:102F20000A2B8300000001380B2B8300000013885C +:102F3000022B83C0000001F40C2B8340000001F43D +:102F40000A2B8340000000000B2B8340000000058B +:102F50000A2B83800004C4B40C2B83801DCD650034 +:102F60000A2B1480000000000B2B8380004C4B4088 +:102F7000022B148000000001062A29C8000000046A +:102F8000042A29D80002034D062A208000000048A8 +:102F9000062A9020000000C8062A900000000002C7 +:102FA000062A21A800000086062A20000000002032 +:102FB000022A23C800000000042A23D00002034F85 +:102FC000042A249800040351022A2C500000000017 +:102FD000022A2C1000000000042A2C0800020355CD +:102FE000042A300000020357062A300800000100BE +:102FF000062A404000000010042A40000010035937 +:10300000062A6AC000000002062A6B0000000004C5 +:10301000042A840800020369022B08000000000053 +:10302000042B0C000010036B022B080001000000B1 +:10303000042B0C400008037B022B08000200000058 +:10304000042B0C6000080383062AC000000000D88F +:10305000062A24A800000014062A254800000022A1 +:10306000042A25D00002038B062A266800000022CD +:10307000042A26F00002038D062A27880000002279 +:10308000042A28100002038F062A28A80000002224 +:10309000042A293000020391062AA000000000281B +:1030A000062AA1400000000C042A29E00002039334 +:1030B000062A502000000002062A503000000002BC +:1030C000062A500000000002062A501000000002EC +:1030D000022A520800000001042A6AC8000203956F +:1030E000062A6B1000000042062A6D200000000432 +:1030F000062ABCD000000002062AC360000000D8E7 +:10310000062A24F800000014062A25D80000002210 +:10311000042A266000020397062A26F800000022EF +:10312000042A278000020399062A2818000000229A +:10313000042A28A00002039B062A29380000002246 +:10314000042A29C00002039D062AA0A0000000282E +:10315000062AA1700000000C042A29E80002039F3F +:10316000062A502800000002062A503800000002FB +:10317000062A500800000002062A5018000000022B +:10318000022A520C00000001042A6AD0000203A1A6 +:10319000062A6C1800000042062A6D300000000468 +:1031A000062ABCD800000002022AC6C000000000A7 +:1031B000042A29F0001003A3062A50480000000E3C +:1031C000062AB00000000006022AC6C40000000063 +:1031D000042A2A30001003B3062A50800000000E93 +:1031E000062AB01800000006022AC6C80000000027 +:1031F000042A2A70001003C3062A50B80000000EEB +:10320000062AB03000000006022AC6CC00000000EA +:10321000042A2AB0001003D3062A50F00000000E42 +:10322000062AB04800000006022AC6D000000000AE +:10323000042A2AF0001003E3062A51280000000E99 +:10324000062AB06000000006022AC6D40000000072 +:10325000042A2B30001003F3062A51600000000EF0 +:10326000062AB07800000006022AC6D80000000036 +:10327000042A2B7000100403062A51980000000E47 +:10328000062AB09000000006022AC6DC00000000FA +:10329000042A2BB000100413062A51D00000000E9F +:1032A000062AB0A800000006021010080000000165 +:1032B0000210105000000001021010000003D000A6 +:1032C000021010040000003D091018000200042341 +:1032D0000910110000280623061011A00000001894 +:1032E00006102400000000E00210201C0000000076 +:1032F0000210202000000001021020C00000000287 +:10330000021020040000000102102008000000014B +:1033100009103C000005064B091038000005065056 +:10332000091038200005065506104C000000010069 +:1033300002104028000000100210404400003FFF2F +:103340000210405800280000021040840084924A75 +:1033500002104058000000000210800000001080A1 +:10336000021080AC00000000021080380000001045 +:103370000210810000000000061081200000000201 +:1033800002108008000002B502108010000000004A +:10339000061082000000004A021081080001FFFFB1 +:1033A00006108140000000020210800000001A8018 +:1033B0000610900000000024061091200000004A32 +:1033C000061093700000004A061095C00000004AE5 +:1033D0000210800400001080021080B00000000184 +:1033E0000210803C00000010021081040000000068 +:1033F00006108128000000020210800C000002B5B7 +:103400000210801400000000061084000000004A32 +:103410000210810C0001FFFF06108148000000022D +:103420000210800400001A80061090900000002412 +:10343000061092480000004A061094980000004AC6 +:10344000061096E80000004A02108000000010807C +:10345000021080AC00000002021080380000001052 +:103460000210810000000000061081200000000210 +:1034700002108008000002B5021080100000000059 +:10348000061082000000004A021081080001FFFFC0 +:1034900006108140000000020210800000001A8027 +:1034A0000610900000000024061091200000004A41 +:1034B000061093700000004A061095C00000004AF4 +:1034C0000210800400001080021080B00000000391 +:1034D0000210803C00000010021081040000000077 +:1034E00006108128000000020210800C000002B5C6 +:1034F0000210801400000000061084000000004A42 +:103500000210810C0001FFFF06108148000000023C +:103510000210800400001A80061090900000002421 +:10352000061092480000004A061094980000004AD5 +:10353000061096E80000004A02108000000010808B +:10354000021080AC0000000402108038000000105F +:10355000021081000000000006108120000000021F +:1035600002108008000002B5021080100000000068 +:10357000061082000000004A021081080001FFFFCF +:1035800006108140000000020210800000001A8036 +:103590000610900000000024061091200000004A50 +:1035A000061093700000004A061095C00000004A03 +:1035B0000210800400001080021080B0000000059E +:1035C0000210803C00000010021081040000000086 +:1035D00006108128000000020210800C000002B5D5 +:1035E0000210801400000000061084000000004A51 +:1035F0000210810C0001FFFF06108148000000024C +:103600000210800400001A80061090900000002430 +:10361000061092480000004A061094980000004AE4 +:10362000061096E80000004A02108000000010809A +:10363000021080AC0000000602108038000000106C +:10364000021081000000000006108120000000022E +:1036500002108008000002B5021080100000000077 +:10366000061082000000004A021081080001FFFFDE +:1036700006108140000000020210800000001A8045 +:103680000610900000000024061091200000004A5F +:10369000061093700000004A061095C00000004A12 +:1036A0000210800400001080021080B000000007AB +:1036B0000210803C00000010021081040000000095 +:1036C00006108128000000020210800C000002B5E4 +:1036D0000210801400000000061084000000004A60 +:1036E0000210810C0001FFFF06108148000000025B +:1036F0000210800400001A80061090900000002440 +:10370000061092480000004A061094980000004AF3 +:10371000061096E80000004A021205B00000000101 +:103720000212049000E383400212051400003C10D2 +:103730000212066C00000001021206700000000078 +:1037400002120494FFFFFFFF02120498FFFFFFFF25 +:103750000212049CFFFFFFFF021204A0FFFFFFFF05 +:10376000021204A4FFFFFFFF021204A8FFFFFFFFE5 +:10377000021204ACFFFFFFFF021204B0FFFFFFFFC5 +:10378000021204BCFFFFFFFF021204C0FFFFFFFF95 +:10379000021204C4FFFFFFFF021204C8FFFFFFFF75 +:1037A000021204CCFFFFFFFF021204D0FFFFFFFF55 +:1037B000021204D8FFFFFFFF021204DCFFFFFFFF2D +:1037C000021204E0FFFFFFFF021204E4FFFFFFFF0D +:1037D000021204E8FFFFFFFF021204ECFFFFFFFFED +:1037E000021204F0FFFFFFFF021204F4FFFFFFFFCD +:1037F000021204F8FFFFFFFF021204FCFFFFFFFFAD +:1038000002120500FFFFFFFF02120504FFFFFFFF8A +:1038100002120508FFFFFFFF0212050CFFFFFFFF6A +:1038200002120510FFFFFFFF021204D4FF802000E8 +:10383000021204B4F0005000021204B8F0001000AC +:1038400002120390000000080212039C000000080E +:10385000021203A000000008021203A400000002EC +:10386000021203BC00000004021203C000000005A5 +:10387000021203C400000004021203D00000000082 +:103880000212036C00000001021203680000003FF6 +:10389000021201BC00000040021201C00000180822 +:1038A000021201C400000803021201C8000008034C +:1038B000021201CC00000040021201D000000003FF +:1038C000021201D400000803021201D8000008030C +:1038D000021201DC00000803021201E000010003F3 +:1038E000021201E400000803021201E800000803CC +:1038F000021201EC00000003021201F000000003BC +:10390000021201F400000003021201F8000000039B +:10391000021201FC0000000302120200000000037A +:103920000212020400000003021202080000000359 +:103930000212020C00000003021202100000000339 +:103940000212021400000003021202180000000319 +:103950000212021C000000030212022000000003F9 +:1039600002120224000000030212022800002403B5 +:103970000212022C0000002F021202300000000987 +:103980000212023400000019021202380000018401 +:103990000212023C000001830212024000000306F2 +:1039A0000212024400000019021202480000000640 +:1039B0000212024C0000030602120250000003062D +:1039C00002120254000003060212025800000C8684 +:1039D0000212025C000003060212026000000306ED +:1039E00002120264000000060212026800000006D3 +:1039F0000212026C000000060212027000000006B3 +:103A00000212027400000006021202780000000692 +:103A10000212027C00000006021202800000000672 +:103A20000212028400000006021202880000000652 +:103A30000212028C00000006021202900000000632 +:103A40000212029400000006021202980000000612 +:103A50000212029C00000006021202A000000306EF +:103A6000021202A400000013021202A800000006C5 +:103A7000021202B000001004021202B4000010048E +:103A80000212032400106440021203280010644054 +:103A9000021205B400000001021201B00000000192 +:103AA0000600A000000000160200A0EC5554000023 +:103AB0000200A0F0555555550200A0F400005555E0 +:103AC0000200A0F8F00000000200A0FC5554000025 +:103AD0000200A100555555550200A104000055559E +:103AE0000200A108F00000000200A18C5554000063 +:103AF0000200A190555555550200A194000055555E +:103B00000200A198F00000000200A19C000000004B +:103B10000200A1A0000100000200A1A400005014B6 +:103B20000200A1A8000000000200A45C00000C003C +:103B30000200A61C000000030200A06CFF5C000055 +:103B40000200A070FFF55FFF0200A0740000FFFFFD +:103B50000200A078F00003E00200A07C000000005A +:103B60000200A0800000A0000600A0840000000564 +:103B70000200A0980FE000000600A09C00000007D3 +:103B80000200A0B8000004000600A0BC0000000372 +:103B90000200A0C8000010000600A0CC0000000336 +:103BA0000200A0D8000040000600A0DC00000003D6 +:103BB0000200A0E8000100000600A22C00000004A2 +:103BC0000200A10CFF5C00000200A110FFF55FFFE6 +:103BD0000200A1140000FFFF0200A118F00003E0A2 +:103BE0000200A11C000000000200A1200000A000B3 +:103BF0000600A124000000050200A1380FE000002B +:103C00000600A13C000000070200A15800000800C7 +:103C10000600A15C000000030200A1680000200073 +:103C20000600A16C000000030200A17800008000E3 +:103C30000600A17C000000030200A1880002000031 +:103C40000600A23C0000000400000000000000008C +:103C50000000003100000000000000000000000033 +:103C60000000000000000000000000000000000054 +:103C700000000000000000000000000000310032E1 +:103C80000000000000000000000000000000000034 +:103C90000000000000000000000000000000000024 +:103CA000000000000000000000320056000000008C +:103CB0000000000000000000000000000000000004 +:103CC00000000000000000000000000000000000F4 +:103CD000000000000056008C000000000000000002 +:103CE000008C009000900094009400980098009C34 +:103CF000009C00A000A000A400A400A800A800ACA4 +:103D000000AC00B100B100B300B300B5000000008A +:103D100000000000000000000000000000000000A3 +:103D200000000000000000000000000000B50102DB +:103D30000102010A010A01120112011B011B0124E7 +:103D40000124012D012D01360136013F013F0148BB +:103D5000014801510151015A00000000000000001B +:103D60000000000000000000000000000000000053 +:103D70000000000000000000000000000000000043 +:103D80000000000000000000000000000000000033 +:103D90000000000000000000000000000000000023 +:103DA0000000000000000000000000000000000013 +:103DB0000000000000000000000000000000000003 +:103DC00000000000000000000000000000000000F3 +:103DD00000000000000000000000000000000000E3 +:103DE00000000000000000000000000000000000D3 +:103DF00000000000000000000000000000000000C3 +:103E00000000000000000000015A015F00000000F7 +:103E100000000000015F0160016001610161016259 +:103E2000016201630163016401640165016501666A +:103E300001660167000000000000000000000000B3 +:103E40000000000000000000000000000000000072 +:103E50000000000000000000000000000000000062 +:103E60000167016C016C0179017901860000000095 +:103E70000000000000000000000000000000000042 +:103E80000000000000000000000000000000000032 +:103E90000000000000000000000000000000000022 +:103EA0000000000000000000000000000000000012 +:103EB00000000000000000000186018700000000F3 +:103EC00000000000000000000000000000000000F2 +:103ED00000000000000000000000000000000000E2 +:103EE00000000000018701BE00000000000000008B +:103EF00000000000000000000000000000000000C2 +:103F000000000000000000000000000000000000B1 +:103F100001BE01E9000000000000000000000000F8 +:103F20000000000000000000000000000000000091 +:103F300000000000000000000000000001E9021A7B +:103F40000000000000000000021A022102210228E5 +:103F50000228022F022F02360236023D023D0244A1 +:103F60000244024B024B02520252028A000000003D +:103F700000000000028A028E028E029202920296D5 +:103F80000296029A029A029E029E02A202A202A631 +:103F900002A602AA02AA02FA02FA031103110328D6 +:103FA0000328032B032B032E032E03310331033489 +:103FB000033403370337033A033A033D033D034019 +:103FC00003400381038103880388038F038F0393D6 +:103FD000039303970397039B039B039F039F03A3F1 +:103FE00003A303A703A703AB03AB03AF03AF03B064 +:103FF00000000000000000000000000000000000C1 +:1040000000000000000000000000000000000000B0 +:10401000000000000000000003B003C20000000028 +:104020000000000000000000000000000000000090 +:104030000000000000000000000000000000000080 +:104040000000000003C203D703D703DA03DA03DD5D +:104050000000000000000000000000000000000060 +:104060000000000000000000000000000000000050 +:1040700003DD040A00000000000000000000000052 +:104080000000000000000000000000000000000030 +:10409000000000000000000000000000040A050D00 +:1040A0000000000000000000000000000000000010 +:1040B0000000000000000000000000000000000000 +:1040C0000000000000000000050D0514051405188F +:1040D0000518051C000000000000000000000000A2 +:1040E00000000000000000000000000000000000D0 +:1040F00000000000051C055C00000000000000003E +:10410000055C05650565056E056E05770577058017 +:1041100005800589058905920592059B059B05A4E7 +:1041200005A405FD05FD0613061306290629062D1F +:10413000062D063106310635063506390639063DA7 +:10414000063D064106410645064506490649065014 +:10415000000000000000000000000000000000005F +:10416000000000000000000000000000000000004F +:10417000000000000000000006500656000000008D +:10418000000000000000000000000000000000002F +:10419000000000000000000000000000000000001F +:1041A0000000000006560659000000000000000054 +:1041B00000000000000000000000000000000000FF +:1041C00000000000000000000000000000000000EF +:1041D0000659065F0000000000000000000000001B +:1041E00000000000000000000000000000000000CF +:1041F00000000000000000000000000000000000BF +:104200000000000000000000065F066E066E067DDE +:10421000067D068C068C069B069B06AA06AA06B996 +:1042200006B906C806C806D706D70748000000002A +:10423000000000000000000000000000000000007E +:10424000000000000000000000000000000000006E +:10425000000000000748075B075B076C076C077DE1 +:10426000000000000000000000000000000000004E +:10427000000000000000000000000000000000003E +:10428000000000000000000000000000000000002E +:10429000000000000000000000000000000000001E +:1042A000000000000000000000000000000000000E +:1042B00000000000000000000000000000000000FE +:1042C00000000000000000000000000000000000EE +:1042D00000000000000000000000000000000000DE +:1042E00000010000000204C00003098000040E4029 +:1042F00000051300000617C000071C8000082140BD +:1043000000092600000A2AC0000B2F80000C344050 +:10431000000D3900000E3DC0000F428000104740E4 +:1043200000114C00001250C00013558000145A4078 +:1043300000155F00001663C00017688000186D400C +:1043400000197200001A76C0001B7B80001C8040A0 +:10435000001D8500001E89C0001F8E800020934034 +:10436000000020000000400000006000000080000D +:104370000000A0000000C0000000E00000010000FC +:1043800000012000000140000001600000018000E9 +:104390000001A0000001C0000001E00000020000D8 +:1043A00000022000000240000002600000028000C5 +:1043B0000002A0000002C0000002E00000030000B4 +:1043C00000032000000340000003600000038000A1 +:1043D0000003A0000003C0000003E0000004000090 +:1043E000000420000004400000046000000480007D +:1043F0000004A0000004C0000004E000000500006C +:104400000005200000054000000560000005800058 +:104410000005A0000005C0000005E0000006000047 +:104420000006200000064000000660000006800034 +:104430000006A0000006C0000006E0000007000023 +:104440000007200000074000000760000007800010 +:104450000007A0000007C0000007E00000080000FF +:1044600000082000000840000008600000088000EC +:104470000008A0000008C0000008E00000090000DB +:1044800000092000000940000009600000098000C8 +:104490000009A0000009C0000009E000000A0000B7 +:1044A000000A2000000A4000000A6000000A8000A4 +:1044B000000AA000000AC000000AE000000B000093 +:1044C000000B2000000B4000000B6000000B800080 +:1044D000000BA000000BC000000BE000000C00006F +:1044E000000C2000000C4000000C6000000C80005C +:1044F000000CA000000CC000000CE000000D00004B +:10450000000D2000000D4000000D6000000D800037 +:10451000000DA000000DC000000DE000000E000026 +:10452000000E2000000E4000000E6000000E800013 +:10453000000EA000000EC000000EE000000F000002 +:10454000000F2000000F4000000F6000000F8000EF +:10455000000FA000000FC000000FE00000100000DE +:1045600000102000001040000010600000108000CB +:104570000010A0000010C0000010E00000110000BA +:1045800000112000001140000011600000118000A7 +:104590000011A0000011C0000011E0000012000096 +:1045A0000012200000124000001260000012800083 +:1045B0000012A0000012C0000012E0000013000072 +:1045C000001320000013400000136000001380005F +:1045D0000013A0000013C0000013E000001400004E +:1045E000001420000014400000146000001480003B +:1045F0000014A0000014C0000014E000001500002A +:104600000015200000154000001560000015800016 +:104610000015A0000015C0000015E0000016000005 +:1046200000162000001640000016600000168000F2 +:104630000016A0000016C0000016E00000170000E1 +:1046400000172000001740000017600000178000CE +:104650000017A0000017C0000017E00000180000BD +:1046600000182000001840000018600000188000AA +:104670000018A0000018C0000018E0000019000099 +:104680000019200000194000001960000019800086 +:104690000019A0000019C0000019E000001A000075 +:1046A000001A2000001A4000001A6000001A800062 +:1046B000001AA000001AC000001AE000001B000051 +:1046C000001B2000001B4000001B6000001B80003E +:1046D000001BA000001BC000001BE000001C00002D +:1046E000001C2000001C4000001C6000001C80001A +:1046F000001CA000001CC000001CE000001D000009 +:10470000001D2000001D4000001D6000001D8000F5 +:10471000001DA000001DC000001DE000001E0000E4 +:10472000001E2000001E4000001E6000001E8000D1 +:10473000001EA000001EC000001EE000001F0000C0 +:10474000001F2000001F4000001F6000001F8000AD +:10475000001FA000001FC000001FE000002000009C +:104760000020200000204000002060000020800089 +:104770000020A0000020C0000020E0000021000078 +:104780000021200000214000002160000021800065 +:104790000021A0000021C0000021E0000022000054 +:1047A0000022200000224000002260000022800041 +:1047B0000022A0000022C0000022E0000023000030 +:1047C000002320000023400000236000002380001D +:1047D0000023A0000023C0000023E000002400000C +:1047E00000242000002440000024600000248000F9 +:1047F0000024A0000024C0000024E00000250000E8 +:1048000000252000002540000025600000258000D4 +:104810000025A0000025C0000025E00000260000C3 +:1048200000262000002640000026600000268000B0 +:104830000026A0000026C0000026E000002700009F +:10484000002720000027400000276000002780008C +:104850000027A0000027C0000027E000002800007B +:104860000028200000284000002860000028800068 +:104870000028A0000028C0000028E0000029000057 +:104880000029200000294000002960000029800044 +:104890000029A0000029C0000029E000002A000033 +:1048A000002A2000002A4000002A6000002A800020 +:1048B000002AA000002AC000002AE000002B00000F +:1048C000002B2000002B4000002B6000002B8000FC +:1048D000002BA000002BC000002BE000002C0000EB +:1048E000002C2000002C4000002C6000002C8000D8 +:1048F000002CA000002CC000002CE000002D0000C7 +:10490000002D2000002D4000002D6000002D8000B3 +:10491000002DA000002DC000002DE000002E0000A2 +:10492000002E2000002E4000002E6000002E80008F +:10493000002EA000002EC000002EE000002F00007E +:10494000002F2000002F4000002F6000002F80006B +:10495000002FA000002FC000002FE000003000005A +:104960000030200000304000003060000030800047 +:104970000030A0000030C0000030E0000031000036 +:104980000031200000314000003160000031800023 +:104990000031A0000031C0000031E0000032000012 +:1049A00000322000003240000032600000328000FF +:1049B0000032A0000032C0000032E00000330000EE +:1049C00000332000003340000033600000338000DB +:1049D0000033A0000033C0000033E00000340000CA +:1049E00000342000003440000034600000348000B7 +:1049F0000034A0000034C0000034E00000350000A6 +:104A00000035200000354000003560000035800092 +:104A10000035A0000035C0000035E0000036000081 +:104A2000003620000036400000366000003680006E +:104A30000036A0000036C0000036E000003700005D +:104A4000003720000037400000376000003780004A +:104A50000037A0000037C0000037E0000038000039 +:104A60000038200000384000003860000038800026 +:104A70000038A0000038C0000038E0000039000015 +:104A80000039200000394000003960000039800002 +:104A90000039A0000039C0000039E000003A0000F1 +:104AA000003A2000003A4000003A6000003A8000DE +:104AB000003AA000003AC000003AE000003B0000CD +:104AC000003B2000003B4000003B6000003B8000BA +:104AD000003BA000003BC000003BE000003C0000A9 +:104AE000003C2000003C4000003C6000003C800096 +:104AF000003CA000003CC000003CE000003D000085 +:104B0000003D2000003D4000003D6000003D800071 +:104B1000003DA000003DC000003DE000003E000060 +:104B2000003E2000003E4000003E6000003E80004D +:104B3000003EA000003EC000003EE000003F00003C +:104B4000003F2000003F4000003F6000003F800029 +:104B5000003FA000003FC000003FE000003FE00138 +:104B600000000000000001FF0000020000007FF8CC +:104B700000007FF800000CDF0000150000000001BD +:104B80000000000100000001FFFFFFFFFFFFFFFF2B +:104B9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25 +:104BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 +:104BB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05 +:104BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 +:104BD000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5 +:104BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 +:104BF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5 +:104C0000FFFFFFFFFFFFFFFFFFFFFFFF00000000B0 +:104C1000FFFFFFFF00000000FFFFFFFFFFFFFFFFA0 +:104C200000000000FFFFFFFF00000000FFFFFFFF8C +:104C3000FFFFFFFF00000000FFFFFFFF000000007C +:104C4000FFFFFFFF0000000300BEBC20FFFFFFFFCF +:104C500000000000FFFFFFFF00000000FFFFFFFF5C +:104C60000000000300BEBC20FFFFFFFF00000000AB +:104C7000FFFFFFFF00000000FFFFFFFF0000000339 +:104C800000BEBC20FFFFFFFF00000000FFFFFFFF92 +:104C900000000000FFFFFFFF0000000300BEBC207B +:104CA000FFFFFFFF00000000FFFFFFFF000000000C +:104CB000FFFFFFFF0000000300BEBC20FFFFFFFF5F +:104CC00000000000FFFFFFFF00000000FFFFFFFFEC +:104CD0000000000300BEBC2000002000000040C017 +:104CE00000006180000082400000A3000000C3C0FB +:104CF0000000E4800001054000012600000146C0DC +:104D000000016780000188400001A9000001C9C0BE +:104D10000001EA8000020B4000022C0000024CC09F +:104D200000026D8000028E400002AF000002CFC082 +:104D30000002F0800003114000033200000352C063 +:104D400000037380000394400003B5000003D5C046 +:104D50000003F6800004174000043800000458C027 +:104D60000004798000049A40000080000001038064 +:104D70000001870000020A8000028E0000031180FB +:104D8000000395000004188000049C0000051F80AB +:104D90000005A300000626800006AA0000072D805B +:104DA0000007B100000834800008B80000093B800B +:104DB0000009BF00000A4280000AC600000B4980BB +:104DC000000BCD00000C5080000CD400000D57806B +:104DD000000DDB0000007FF800007FF80000192ABA +:104DE0000000350000001900001000000000000065 +:104DF00000000000FFFFFFFF400000004000000037 +:104E000040000000400000004000000040000000A2 +:104E10004000000040000000400000004000000092 +:104E20004000000040000000400000004000000082 +:104E30004000000040000000400000004000000072 +:104E40004000000040000000400000004000000062 +:104E50004000000040000000400000004000000052 +:104E60004000000040000000400000004000000042 +:104E7000400000004000000000007FF800007FF8C4 +:104E8000000005C700001500FFFFFFFFFFFFFFFF49 +:104E9000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:104EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:104EB000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02 +:104EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:104ED000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2 +:104EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:104EF000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2 +:104F0000FFFFFFFFFFFFFFFF400000004000000029 +:104F10004000000040000000400000004000000091 +:104F20004000000040000000400000004000000081 +:104F30004000000040000000400000004000000071 +:104F40004000000040000000400000004000000061 +:104F50004000000040000000400000004000000051 +:104F60004000000040000000400000004000000041 +:104F70004000000040000000400000004000000031 +:104F800040000000400000000000100000002080F1 +:104F900000003100000041800000520000006280EB +:104FA0000000730000008380000094000000A480D3 +:104FB0000000B5000000C5800000D6000000E680BB +:104FC0000000F700000107800001180000012880A0 +:104FD000000139000001498000015A0000016A8087 +:104FE00000017B0000018B8000019C000001AC806F +:104FF0000001BD000001CD800001DE000001EE8057 +:105000000001FF0000007FF800007FF80000112E73 +:105010000000350010000000000028AD0000000076 +:1050200000010001000D0205CCCCCCC5FFFFFFFF45 +:10503000FFFFFFFF7058103C000000000000000060 +:1050400000000001CCCC0201CCCCCCCCCCCC0201F9 +:10505000CCCCCCCCCCCC0201CCCCCCCCCCCC0201BA +:10506000CCCCCCCCCCCC0201CCCCCCCCCCCC0201AA +:10507000CCCCCCCCCCCC0201CCCCCCCCCCCC02019A +:10508000CCCCCCCC00000000FFFFFFFF40000000B4 +:105090004000000040000000400000004000000010 +:1050A0004000000040000000400000004000000000 +:1050B00040000000400000004000000040000000F0 +:1050C00040000000400000004000000040000000E0 +:1050D00040000000400000004000000040000000D0 +:1050E00040000000400000004000000040000000C0 +:1050F00040000000400000004000000040000000B0 +:10510000400000004000000040000000002625A0F4 +:1051100000000000002625A000000000002625A0B9 +:1051200000000000002625A000000000000E023252 +:10513000011600D60010000000000000002625A087 +:1051400000000000002625A000000000002625A089 +:1051500000000000002625A00000000000720236BA +:10516000012300F300100000000000000000FFFF1A +:10517000000000000000FFFF000000000000FFFF33 +:10518000000000000000FFFF000000000000FFFF23 +:10519000000000000000FFFF000000000000FFFF13 +:1051A000000000000000FFFF000000000000FFFF03 +:1051B000000000000000FFFF000000000000FFFFF3 +:1051C000000000000000FFFF000000000000FFFFE3 +:1051D000000000000000FFFF000000000000FFFFD3 +:1051E000000000000000FFFF000000000000FFFFC3 +:1051F000000000000000FFFF000000000000FFFFB3 +:10520000000000000000FFFF000000000000FFFFA2 +:10521000000000000000FFFF000000000000FFFF92 +:10522000000000000000FFFF000000000000FFFF82 +:10523000000000000000FFFF000000000000FFFF72 +:10524000000000000000FFFF000000000000FFFF62 +:10525000000000000000FFFF000000000000FFFF52 +:10526000000000000000FFFF000000000000FFFF42 +:10527000000000000000FFFF000000000000FFFF32 +:10528000000000000000FFFF000000000000FFFF22 +:10529000000000000000FFFF000000000000FFFF12 +:1052A000000000000000FFFF000000000000FFFF02 +:1052B000000000000000FFFF000000000000FFFFF2 +:1052C000000000000000FFFF000000000000FFFFE2 +:1052D000000000000000FFFF000000000000FFFFD2 +:1052E000000000000000FFFF000000000000FFFFC2 +:1052F000000000000000FFFF000000000000FFFFB2 +:10530000000000000000FFFF000000000000FFFFA1 +:10531000000000000000FFFF000000000000FFFF91 +:10532000000000000000FFFF000000000000FFFF81 +:10533000000000000000FFFF000000000000FFFF71 +:10534000000000000000FFFF000000000000FFFF61 +:10535000000000000000FFFF000000000000FFFF51 +:10536000000000000000FFFF00000000FFFFFFF34F +:10537000318FFFFF0C30C30CC30C30C3CF3CF300A4 +:10538000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FF +:1053900030EFFFFF0C30C30CC30C30C3CF3CF30025 +:1053A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D9 +:1053B000305FFFFF0C30C30CC30C30C3CF3CF30095 +:1053C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B3 +:1053D0001CBFFFFF0C30C305C30C30C3CF3000141B +:1053E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF29A +:1053F000304FFFFF0C30C30CC30C30C3CF3CF30065 +:10540000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6D +:10541000302FFFFF0C30C30CC30C30C3CF3CF30064 +:10542000F3CF3CF30010CF3CCDCDCDCDFFFFFFF748 +:1054300031EFFFFF0C30C30CC30C30C3CF3CF30083 +:10544000F3CF3CF30020CF3CCDCDCDCDFFFFFFF51A +:10545000302FFFFF0C30C30CC30C30C3CF3CF30024 +:10546000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DC +:10547000318FFFFF0C30C30CC30C30C3CF3CF300A3 +:10548000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FE +:10549000310FFFFF0C30C30CC30C30C3CF3CF30003 +:1054A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D8 +:1054B000305FFFFF0C30C30CC30C30C3CF3CF30094 +:1054C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B2 +:1054D0001CBFFFFF0C30C305C30C30C3CF3000141A +:1054E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF299 +:1054F000304FFFFF0C30C30CC30C30C3CF3CF30064 +:10550000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6C +:10551000302FFFFF0C30C30CC30C30C3CF3CF30063 +:10552000F3CF3CF30010CF3CCDCDCDCDFFFFFFF747 +:1055300030EFFFFF0C30C30CC30C30C3CF3CF30083 +:10554000F3CF3CF30020CF3CCDCDCDCDFFFFFFF519 +:10555000304FFFFF0C30C30CC30C30C3CF3CF30003 +:10556000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DB +:1055700031EFFFFF0C30C30CC30C30C3CF3CF30042 +:10558000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FD +:10559000310FFFFF0C30C30CC30C30C3CF3CF30002 +:1055A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D7 +:1055B000305FFFFF0C30C30CC30C30C3CF3CF30093 +:1055C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B1 +:1055D0001CBFFFFF0C30C305C30C30C3CF30001419 +:1055E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF298 +:1055F000304FFFFF0C30C30CC30C30C3CF3CF30063 +:10560000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA6B +:10561000302FFFFF0C30C30CC30C30C3CF3CF30062 +:10562000F3CF3CF30010CF3CCDCDCDCDFFFFFF97A6 +:10563000056FFFFF0C30C30CC30C30C3CF3CC00060 +:10564000F3CF3CF30020CF3CCDCDCDCDFFFFFFF518 +:10565000310FFFFF0C30C30CC30C30C3CF3CF30041 +:10566000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3DA +:10567000320FFFFF0C30C30CC30C30C3CF3CF30020 +:10568000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FC +:10569000310FFFFF0C30C30CC30C30C3CF3CF30001 +:1056A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D6 +:1056B000305FFFFF0C30C30CC30C30C3CF3CF30092 +:1056C000F3CF3CF30002CF3CCDCDCDCDFFFFF406B0 +:1056D0001CBFFFFF0C30C305C30C30C3CF30001418 +:1056E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF297 +:1056F000304FFFFF0C30C30CC30C30C3CF3CF30062 +:10570000F3CF3CF30008CF3CCDCDCDCDFFFFFF8ADA +:10571000042FFFFF0C30C30CC30C30C3CF3CC000C0 +:10572000F3CF3CF30010CF3CCDCDCDCDFFFFFF97A5 +:1057300005CFFFFF0C30C30CC30C30C3CF3CC000FF +:10574000F3CF3CF30020CF3CCDCDCDCDFFFFFFF517 +:10575000310FFFFF0C30C30CC30C30C3CF3CF30040 +:10576000F3CF3CF30040CF3CCDCDCDCDFFFFFFF3D9 +:10577000316FFFFF0C30C30CC30C30C3CF3CF300C0 +:10578000F3CF3CF30000CF3CCDCDCDCDFFFFFFF1FB +:10579000302FFFFF0C30C30CC30C30C3CF3CF300E1 +:1057A000F3CF3CF30001CF3CCDCDCDCDFFFFFFF6D5 +:1057B000305FFFFF0C30C30CC30C30C3CF3CF30091 +:1057C000F3CF3CF30002CF3CCDCDCDCDFFFFFFF6B4 +:1057D00030BFFFFF0C30C30CC30C30C3CF3CF314FD +:1057E000F3CF3CF30004CF3CCDCDCDCDFFFFFFF296 +:1057F000304FFFFF0C30C30CC30C30C3CF3CF30061 +:10580000F3CF3CF30008CF3CCDCDCDCDFFFFFFFA69 +:10581000302FFFFF0C30C30CC30C30C3CF3CF30060 +:10582000F3CF3CF30010CF3CCDCDCDCDFFFFFFF744 +:1058300031CFFFFF0C30C30CC30C30C3CF3CF3009F +:10584000F3CF3CF30020CF3CCDCDCDCDFFFFFFF01B +:10585000307FFFFF0C30C30CC30C30C3CF3CF300D0 +:10586000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCC +:1058700030CFFFFF0C30C30CC30C30C3CF3CF3CC94 +:10588000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEC +:1058900030CFFFFF0C30C30CC30C30C3CF3CF3CC74 +:1058A000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFCB +:1058B00030CFFFFF0C30C30CC30C30C3CF3CF3CC54 +:1058C000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFAA +:1058D00030CFFFFF0C30C30CC30C30C3CF3CF3CC34 +:1058E000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF88 +:1058F00030CFFFFF0C30C30CC30C30C3CF3CF3CC14 +:10590000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF63 +:1059100030CFFFFF0C30C30CC30C30C3CF3CF3CCF3 +:10592000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF3B +:1059300030CFFFFF0C30C30CC30C30C3CF3CF3CCD3 +:10594000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF0B +:1059500030CFFFFF0C30C30CC30C30C3CF3CF3CCB3 +:10596000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCB +:1059700030CFFFFF0C30C30CC30C30C3CF3CF3CC93 +:10598000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEB +:1059900030CFFFFF0C30C30CC30C30C3CF3CF3CC73 +:1059A000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFCA +:1059B00030CFFFFF0C30C30CC30C30C3CF3CF3CC53 +:1059C000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFA9 +:1059D00030CFFFFF0C30C30CC30C30C3CF3CF3CC33 +:1059E000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF87 +:1059F00030CFFFFF0C30C30CC30C30C3CF3CF3CC13 +:105A0000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF62 +:105A100030CFFFFF0C30C30CC30C30C3CF3CF3CCF2 +:105A2000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF3A +:105A300030CFFFFF0C30C30CC30C30C3CF3CF3CCD2 +:105A4000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF0A +:105A500030CFFFFF0C30C30CC30C30C3CF3CF3CCB2 +:105A6000F3CF3CF30040CF3CCDCDCDCDFFFFFFFFCA +:105A700030CFFFFF0C30C30CC30C30C3CF3CF3CC92 +:105A8000F3CF3CF30000CF3CCDCDCDCDFFFFFFFFEA +:105A900030CFFFFF0C30C30CC30C30C3CF3CF3CC72 +:105AA000F3CF3CF30001CF3CCDCDCDCDFFFFFFFFC9 +:105AB00030CFFFFF0C30C30CC30C30C3CF3CF3CC52 +:105AC000F3CF3CF30002CF3CCDCDCDCDFFFFFFFFA8 +:105AD00030CFFFFF0C30C30CC30C30C3CF3CF3CC32 +:105AE000F3CF3CF30004CF3CCDCDCDCDFFFFFFFF86 +:105AF00030CFFFFF0C30C30CC30C30C3CF3CF3CC12 +:105B0000F3CF3CF30008CF3CCDCDCDCDFFFFFFFF61 +:105B100030CFFFFF0C30C30CC30C30C3CF3CF3CCF1 +:105B2000F3CF3CF30010CF3CCDCDCDCDFFFFFFFF39 +:105B300030CFFFFF0C30C30CC30C30C3CF3CF3CCD1 +:105B4000F3CF3CF30020CF3CCDCDCDCDFFFFFFFF09 +:105B500030CFFFFF0C30C30CC30C30C3CF3CF3CCB1 +:105B6000F3CF3CF30040CF3CCDCDCDCD000C0000B9 +:105B7000000700C000028130000B815800020210B3 +:105B800000010230000F024000010330000C000051 +:105B9000000800C000028140000B81680002022062 +:105BA0000001024000070250000202C0000F000086 +:105BB000000800F000028170000B81980002025082 +:105BC00000010270000B8280000803380010000002 +:105BD0000008010000028180000B81A80002026021 +:105BE00000018280000E829800080380000B0000F4 +:105BF000000100B0000280C0000580E80002014002 +:105C000000010160000E017000038250CCCCCCCCAE +:105C1000CCCCCCCCCCCCCCCCCCCCCCCC00002000D4 +:105C2000CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCB4 +:105C300000002000CCCCCCCCCCCCCCCCCCCCCCCCB4 +:105C4000CCCCCCCC04002000000000000000000000 +:105C50001F8B080000000000000BFB51CFC0F003B9 +:105C60008A59051918AC84117C7A607E4ECAF43BBF +:105C7000F232303803B12B103700F1616E06862303 +:105C8000DCC4EB3F298F607BCB32309403F1766923 +:105C90000606133984B8AE0203C33C203F012AF63E +:105CA000144867CB53E6EEC182155431C564951193 +:105CB0006C452CF2C858094DBE461995AF4C40FFB3 +:105CC00040E3781D547E8F16847EAD0DA113D0E481 +:105CD0007BA1F28E507F25EA6037D789487FA7B233 +:105CE000A0B9078DDFCA88CA37E340E52741D5034D +:105CF000000749300AC8030000000000000000004F +:105D00001F8B080000000000000BED7D0D7854D5BE +:105D1000B5E83E73CE9C9949CE4C26BF4C20C04975 +:105D2000082168A4C70069B0584F2060A8D40E1499 +:105D300069AC8A032244082452EBC3ABFD328100D4 +:105D4000010204B13414A44300A5B7B43752B4D44B +:105D5000523AE0A7C5D6F7BDE0B356AFB66FB4145C +:105D60007F8A12F3AED6BE6BEBDB6BEDBD93734E49 +:105D7000664810BDED7DEFC6CFEFB0CFD93F6BAF1A +:105D8000BFBDD6DA6BEF71BBFC246F34211FC3DFBC +:105D90007584FC2F8D1092DBFF747B4934FD738476 +:105DA00064E698D1441921C372CC389944DF075571 +:105DB000DD23F5B713CF9399334350AF25D70C119B +:105DC000DA474BE67C1281BE227584E411A2780981 +:105DD000FE89FAEEE05C2F29C3577FFB587C9709B8 +:105DE00059172CCA8076CEFE09891132D95A7611FC +:105DF00022FAA4EDBC006F068557A72F289C699353 +:105E00005CB1EB0B29DC7A0CE14E2FA070D3F2C908 +:105E100091CF78C7D0F2A66B5D86075BDF4D480552 +:105E200021ABA02FDA76D35571FE5D31A03C433E05 +:105E3000DCAC427B9D181E5AF65FD51857B19DA960 +:105E4000E5D37641C2DA054B97CC261308C930D585 +:105E50007EB8583D9C7F3AAFE7D1E9F7D2FEEFE933 +:105E6000A4ED3D3900A50409FB69FF958EEFA5332C +:105E7000DF807ED389A55F3A8FEDF08F7C42BE40F4 +:105E8000FC39E7A0F3CF93CF031E487516215306C4 +:105E9000E2AF1F6F51A42F217536B8041D3418636B +:105EA0000C21D7B7265E72E550784C17013CCD9493 +:105EB00035DF185ADE765A463C6CABEDF106359C60 +:105EC000DFEC7CDA6E34EF677425C5039DCF9E2628 +:105ED0005AF60CC46FC1A46E13F8C33FA95B22B479 +:105EE000BF0283906C3A9F60232D17D176247E6683 +:105EF0000CE52FF2009B6F94FEF771513F1E331992 +:105F00000A88E6C07326E091E2A9E01EC7FB4A8634 +:105F1000BF4C62C16B217213E2E90EC0DF95C8F37A +:105F200063117FD12CC4EB50F127E011F80B723EC6 +:105F3000BEBE2651AB00DF4CA5F8037C513CA6D376 +:105F4000F9F6BEE489C985D08DD91D027C8BF95440 +:105F500032FED9C2E1DA08F81B879F5CAE1021BE81 +:105F6000B22E93C94B5C82727A199D01EDCF6732D4 +:105F7000FCCD903509C6DB5CCAF8940E20B92A071F +:105F8000C245FFB0FD660A8F668167B3B7CB2BD1E0 +:105F9000F2760A6F14F04F8E04811FC5BC3DBACB58 +:105FA00086572594E6E07306A7806FBBC9E4D80244 +:105FB00007BE27DD5DAD1285F383192EB2491ABCE9 +:105FC000DF6D7DFDD8FB77F63B287C89A0AF98CEAE +:105FD000EF8367656313C5CF66BDABD545E1D85682 +:105FE000CDE63B90CE97395E4F8FB77892653C8374 +:105FF000C9CBA73E0EC9B4CFAB32E80B965DFE38D5 +:1060000024B87034D03F153D3E35F8750ABF054FB2 +:10601000BEE2A004FDFBAE7AD04B50EE8F78010EAD +:10602000E73803E0758CEB1C47298D9A0A96ECFA49 +:10603000C8138C1162D12F58478727D3CBE9865DCF +:106040009FF84AEDFAD9A9CF15D03701686FD7D795 +:106050003D42CF083D3D69887AC6AC43788B48DF26 +:106060001FCAF3182ECFD30F253ABC147FC57B84EB +:106070009E7EE057A5941F0E829EA6E5831D04D741 +:10608000C38347498CC935D3D713786713B8DEF972 +:10609000419FBEB1E3E7CA76731AE89D3262BA7CCB +:1060A000B49F31878911A7EF0F93F8DCF1A0C78E59 +:1060B000B1F97BE97F563D7D05C7E395871B5D40C0 +:1060C000CF317BEC78BC82E3B7ECA8E33DC7DF15AA +:1060D0000EFC6D837F507CE54B1C8F634909E27198 +:1060E000EA10D73B8E47A7BEEEC3E31EAAAF29DE58 +:1060F000B2830C8F2D6D2E02FAA137E642FD585A5D +:10610000D8E842FDC9F5F6783EBFF17CBD3BC0F151 +:1061100027E02C9E6D5401DEC612E324E8E5CC7620 +:106120008A37027ABAA00ACA3B1E22489FB10FE9F9 +:106130002EAEDF109E4CBEFEEEA82E7F16E4A2F718 +:1061400021C590E9380789B1C62BF5E3379B8F9FAE +:10615000CDF1F86543B6F1A1938ED91CAF4EFC94F6 +:106160001EB0E37FAC834E63DAEDE56C075D6E90A5 +:106170001CF6C710E9E15148D49305E518DA755EBD +:106180008AFB5C5A967FFC940978D63AD8BBCC3609 +:1061900057AC908EE36F6165A54D8955513CDC0687 +:1061A00086172D8F6B2531B047E56A9324281EC7CB +:1061B00005E344A678CBAE268837E2B02F05FD8AEA +:1061C00039131473FECFF872B90FE8B52348F10EF6 +:1061D000EBE26C85B7377CE1ABFAF1EED40F5FAB45 +:1061E000B5E3FDA670BA0D5FB3F46C5B79E2E9E14B +:1061F00017A593D01F828F04DE06D0A1D55EF65777 +:10620000DBCB4EFD13951CFA678874524F91529068 +:106210008B71AE34A3B37060BDED928BDB43DED8DF +:10622000593ADE4222910CDAFF0A921805F83EA68E +:10623000E9F87DA52B9107E50BA467E7C831FDFDC3 +:106240008F52C83189DAED1245EF6A0AD2702F8970 +:10625000A7A33D4CC2DE3C4401E245A2FFDF8AFC1D +:10626000A2B8005F2382EC3D896628500E11F1A789 +:10627000239D3CFC9FF9AB9FF98B44E92BF1A70CC4 +:1062800074A4E3BB4904F9C14BDAB19C46BAF0A946 +:10629000916E7C06A8C68667900425786611039FD8 +:1062A000E48AD8637194C30782C8F7BE3F908FD346 +:1062B000FBE7B38ED36D3809FF48CA053AC4895746 +:1062C000EEE7433FE7436AAFA15ED64A19FF6A9300 +:1062D000E8BA5A86F28F7E17F988E2B702C665F5EA +:1062E00005BEB772BB7A4B9317F5CDE6A6203ED517 +:1062F000A98D61002FB33AD17107A55786AE1AD781 +:10630000D3F90FABEE89839CF85B99DF966630FC7E +:106310009EDCF8C44B8BE8FBB6428DF9412DCC9E38 +:10632000CDE0586C9B9C88ADA5F06D2DF41A56FFFE +:1063300040E8A7ADD7260EEDA7DF3B75DA23FDEBCE +:10634000AC3E9258037253A08226229B27FC930EE8 +:106350007A2DADB8A7C9AA77B40F65A6BC0AA25119 +:10636000E02B3ABF282CEF4EBE6A2BBF02F562DB52 +:10637000A967894E2B14D5C44DC0977F2A3565E98E +:106380003CFC35BA2BAA8154465E053C67B4062511 +:1063900093E22FAB5A9F0632AA119DE96BA53B04ED +:1063A000F23BA0FF91F1D01DB4BFE8B5AA7110D99E +:1063B0004A77CDF7A796872D1BEFFDBA99C4AE0A91 +:1063C000BA24A4FBA96BF3F2C1FFF591607EFA2415 +:1063D000902F951C8475EBDA25A32349DAF5CB5968 +:1063E0005CD835499FA9DAA5CBA4B1CBD26F898BF4 +:1063F000C9A1CBE5C5676619E3A3A252EE17B71290 +:106400003396040E93C3AF2971C2FC39DDF559E20E +:10641000EB6DAE2FB648A4B62BC9F74E0ECF0C7954 +:106420008F09EB6FC646B64EFA28A85D14BE2285CA +:106430003E2DED66F1FA87F8F312F450DE4320307A +:106440003943D3833EC7B8E259FE09C6DD46C79536 +:106450005D415CF704DE9DF4144F97CB87F53EB8A1 +:10646000F6C5101881A9E0D4414687D167017F861F +:1064700050D713BD943D9DE35D6A7F5F74B1793859 +:10648000FB2507985D95C1D7AF93534A9AD1EF9DED +:106490002DFC50BBDE007F18F451E701BAF01782E3 +:1064A000DE60E5CD318276566F1965E42288277467 +:1064B000A3BE2D20119463FA09CBAD5CFFAD07FD9F +:1064C000479FEF93F02DAEC9A04762A7145A69F613 +:1064D000A4BBA7258B1FDD09F231F9D2D6A92FD293 +:1064E000E7426F7829F4AF19674C505B99F3249415 +:1064F00027A75C51F60CCDB5C80D91055F30796AC0 +:10650000E1FC0E723387966B8A93C3D9B9B1223FEF +:1065100082FDE9C3D1EE50F4E1D67E3BBFCCE46A04 +:1065200087437E3AB8FCAF017EBCB479E6D5D0672C +:10653000D08899A02EE7471B9F06BACD93221B5CFB +:10654000B4DEBC7BC26E903FED40375D23F1FD268B +:10655000C0478DDE0E94239AD91D85E7E6B245A883 +:106560009F7B436CEAA9F82ACD74D9FD27A73F3851 +:1065700044791C6F44A701BC7AED7B277375A05347 +:10658000E461806B64F86415A05DD3CF9859167AE6 +:106590006597327DB882F371E66C4A37D0778A19F5 +:1065A0009AE387688EB91FE63BD4F153F13DD89D3D +:1065B00080AF6CCEE72D06E3732107195C0E5AE01D +:1065C0003BE06B12E3FB96607930D93AB187AFF3C9 +:1065D000DFE37C5F4092EBA193AE4BB7C3C6D367BA +:1065E000095DC1009EF749E469987F1697B3CCEA2C +:1065F000980BE011F234DB38539D9D03768A5E0ED2 +:1066000076B118F71DCE6F0BBDE6AFA17D4D71B30E +:106610009245E735AE8C18A05E6715674A563EFF77 +:106620006D5FFDF0F3505F2BEB46BF7CB076DD7CF9 +:106630007EF3A4F0CBC87F0FB42B5EA47BF815ECDF +:10664000E7816EE2B5E89B228E6779E3A92AA04331 +:106650006F2309025FCED71B9F9680BF43E1752E43 +:10666000CB3C66E9763B9EF2F99BD0EFC8463B7F78 +:10667000D69076855CC2BA314A8AF400BCB31FE872 +:10668000467833AB993F4CE1EE45BDF2E9C3FDF1ED +:10669000C5E07E13843517E47D1FEA330A9F225339 +:1066A00038C6CD8E2B5988F7330AC047F1ACCA16CD +:1066B000391FAA7CEF00E0260F2EE72DF08F29600E +:1066C00027477264E03B61F7264E12E66FD9E396E6 +:1066D000C25E0E84A8BD4CE525B32641C03FCE3E28 +:1066E0002D1BD7D32AC36A8804FE9FB063B3B85C5E +:1066F0000AB8B6723B794B5308E5285BEB390D714C +:10670000FEADF92E630D01F9AD40FB6D4755220436 +:106710007E60B0B262E31DB47D5B938EF5373619AF +:10672000D87E4353253EDB6B5E47FB776B88D9BF32 +:106730009B9B4AB9D3C1E0CE1276728D885FDAE1B5 +:10674000A2ED6DFB1FA23E0959E25A4596F63AD3D7 +:106750003783B54F9F648F8BF5B53787D6DE67D803 +:10676000DB57998956F087833CEE2FF45E80D7097A +:1067700056BAD06F1678F694DAE9DE5E937C3F471E +:106780003C9DE3113DCD367F12AD43F85671F85272 +:10679000F5B38EC75F44D9CDED4567BD15325F1F98 +:1067A000F9BE54908FB5C3A4F8B0C461B239DF6D9F +:1067B0009DCDFC321264F13AE197B909B1F9656EE9 +:1067C000BE1F8565D4F751A68F1DF08BF62A6F9FEB +:1067D0000A0ED5D9DF59DA4F85A51F079CA9E073AA +:1067E000EE939137EDFDA4D65F8E76E7874687015D +:1067F000EDC06A28B596B31CE5E18EFA458EEF57D9 +:1068000038BE973BCAD738EA4F7394BFE4A83FD746 +:1068100051FEBAA3FE22C7F7658EEFAB1CE57FB22F +:10682000D72FBBEB93E1F7FF333C09B91A88979850 +:106830006D9FD7295745243E2A0E7E43E6734BE0D1 +:106840005342969473CC1761712D129F60F55FFFD0 +:10685000A845FE00EB58E747665A98CAD581F6E787 +:1068600003A08FC4FBF3D2AB81F13A21F56A7C25FA +:106870008B03B5A3DCA411E5F544295049C2F8996E +:10688000575B8C28F716D3F7567DD5CEE4AD18FCB0 +:1068900022DA2EBA5D45BB2F3A92C4C6D2766A81FF +:1068A000BDBE9BF74F7258FFF89EF65BAE307F215E +:1068B000146EAF02D91D5EDB75129E4EFC84A64796 +:1068C000AF7E06E20B3B981F7E6006F5032C7AEE46 +:1068D0006685E9B7DB944BF64B5F9C28F7F77FE0C2 +:1068E0005B9AD14CAB1C0020C0EFFF963706F18CB1 +:1068F00051109F639B07189F1B49F81F8FC381BBD3 +:1069000008EBCB48ED34C6DBF4BAE029D0757395BB +:10691000121CEF7B52CF7818CF957EFE6AB62EFE02 +:10692000ED63B47B38FE429B2B12518A3FB24D354A +:10693000C61258520D94238F425A3CE5C01E0CDFFC +:106940006B61D565EF157F16C4D9C2585641EFC2A9 +:106950003A067C24C3FE761CCB7E92C07206B76FCB +:10696000C781B3087E00D125A6270D09F6994237C5 +:10697000503F3CC9BA1196AAC62993FBE39492CE24 +:10698000E29152DB337F91205E594A74B64FC5E3E2 +:10699000821B65E96388B70687B6CF13BAC54E5721 +:1069A000A2B49339163EBEA58F9E0C5F63426CFE67 +:1069B000A16D6A23F8310766D9F940D497954BF653 +:1069C00007774E18F3D9F141A63206E119C807B787 +:1069D00006213E2D4529DED2878EB7A06C7E5DC193 +:1069E00079122CFF40326F053A89B242CC05D6F2BB +:1069F0006FE5F0422847A791D246ADBF1FFA7E71DE +:106A00008AF74B93BD1F27ECD5B36CFD2EE1323EC8 +:106A10006C4FD005766461C7AA34AB7D55C2D7E907 +:106A2000473B8EF860BEBBEB93EB3FF1DCC2FDBD94 +:106A300054F502527718E841262BE460127BFC499A +:106A4000E06F8B1E0D38ECC2EA966815B4CFAA75BC +:106A500011880BD3F51DEDBA426E1FEE9C1A9554AA +:106A60002A873B7611B48FB35A16F9ACF3C9E7F312 +:106A7000D9393B2F0DEC957D8B177D09FD156AF7F4 +:106A8000CB181F8F6C82FEF36BD83EBF13BECD7C3C +:106A90007EED8B199E9CDFD355124926874F2ADC49 +:106AA000CF55A212C9EBDF37D97CF2BE5F8DA7E3C9 +:106AB0009554BA0C9FDE0FE7B83E7B2981F84ABF98 +:106AC00046096E027BAA43B5D999FBF63CB86B31F7 +:106AD000F837F43DA88347AE6D1C1EA6703DFAE55D +:106AE00025CFDE057CBFCE45401F0938B432BB9DA3 +:106AF0007BB24F3EEDE3D27E991F47970F39C9FE17 +:106B0000C9E5E2A3838F9B8A4F9CEBA9930F2E6567 +:106B10007DB851BEFCF9FD18E490C293C7F3B58669 +:106B2000D5EACC6FE37294ED158A848D93C7F92C66 +:106B30006BF6833EE0B35DB5E5283FBDB31749A0D2 +:106B40004F441E54AAF152C193EE6EF7411C74D704 +:106B5000E207A56478CB8FB0F890F3BDE966FAB48C +:106B60004D6997A07DAA7AA3DC9C1FB85CE5F379F8 +:106B700085A6C6C380AF3C43216B28BE76CC5E544D +:106B800055027C47E510E22AD53504ED877C93ED6C +:106B90000B0529BE9EA4EBDECEC5C488D37A3B4D3F +:106BA000D5B61F23E4D0C98F3B175F5CBF10AB7F06 +:106BB0004EF95F716B6C7FB09814831DB523857D92 +:106BC00076A9F80D2D76B1F86875F920FABCF9525E +:106BD000D7A9F9D7023F0E35DFCDA12FC853BB6629 +:106BE00095805F6B507D4192E1C7AE1F06C387134E +:106BF000FF13009FE99F1D3E9DDFB3DD3CBE3D447A +:106C00007CB4D516FD0FDC034F51DF391FD14EE4A4 +:106C1000A77D91F4C820FF2670E818F0260C7C565A +:106C200093303EBB95C857DCB4FE4CD28865117FCB +:106C3000AA53828C1E3CFF45EC732BD319DF8F9B2C +:106C400048629DB07E4C9DCB377F15F39C178C36E8 +:106C50000A47127F8A903538EF118EF558C427867F +:106C6000D5B7CF2EA7FD8E98EDC2F8C588CA23B63A +:106C7000752CC0E547F4B7BB7268EBF3238EF5F9CA +:106C8000112581F95D8F54AE6986E546C97A339442 +:106C9000ACFDB80E3B5EB77ED4E50B278167F7E20B +:106CA0006398C7B5BBF2E2F1934706E19B7172723C +:106CB0007BF68B1EB6AFB43BD37B334B2E5A6DCBDA +:106CC0004320B256681D77F74724337C517D629785 +:106CD00097AD6E9E6FE0277EE0FF54F810CFCF1A7D +:106CE0000F8F4E6B5C164ED2BEC4C3EC89759924CF +:106CF0002A533E79F4652506790E84EBE18A9BF5EB +:106D000018D80BEB404950FDFB6815C1EF1599FCF5 +:106D1000FBC33AE6558DE8205195AE67235E5ABC19 +:106D20002393D66B5B4C3DC7C2FEF76DC6A956D800 +:106D3000177EE20517C6732B7C71AF41E755C9D7A3 +:106D4000C1DD8B4F61DE71748F628C45FD2E11A900 +:106D500002BD785B1CF3845B61EBBDF1A04FA7ED36 +:106D600077E909ECE79B534E7975D82F2FE8F6C2E7 +:106D70003CB754B2F5F2C8E2A2AF96205AED79269C +:106D800033E5A9DD261D6FCB62B65F9199E8F67AEF +:106D9000E87C02B50AB99EC217D0D87CDBD6911820 +:106DA000AC53E53C9F442273D01FCE77E409E5390C +:106DB000F24D82C6CCB760DF3F08FBFB3009B97EDD +:106DC000C755A06F1B5C3C0DD54439F5F3F9F90D9F +:106DD00013EBCF948FFB60DF77578B12C4F5CFD1C5 +:106DE000AF731E411239694AD80F8EB3EB21B64EEC +:106DF00006276B06D558B429873B48E1CEA643B693 +:106E0000D8E11678758EE37794DF14FC3C828C050C +:106E10003D24E2CC027E27DFE654C48E3E4FE7BB22 +:106E2000FB050DD7EBDD95CFDFD200EB7CA907F397 +:106E300023BEF4C1A1FA7FA1CF5FBF77AC189E3704 +:106E4000E41F98D4007880FC8889A42F8E97073D92 +:106E5000A3FDCAF59A18AF6C5F8B3B075F45FDB485 +:106E6000BCE5D4CB75108FCEAF2768FFE62B8C3FE7 +:106E7000FD2DAE5833853FE79A76E48711B571044E +:106E80005AABED92A29678A7C8FBF6D747308FE2AF +:106E9000FADA76CCF7F6F3B8AF7F523BDA4933E44F +:106EA00057BD68AF71FA89FC77217F4EFA942CEEBA +:106EB000AE817E46B42806803DA2BED105709554B1 +:106EC000D2358BD2ADA4A34B62FE1FCBA76729CFCF +:106ED000F419AEC3BC2CB287E5178A3CF040BD9DC7 +:106EE0007EC1BEFCF9880BFCEFC20EC7F770CD1B4C +:106EF0008C0FEDF42C52393D4B781E21C7C3088E00 +:106F0000872DF57C7F4EF3C62E66D7BEC0F7E75EB1 +:106F100084F98F1BF8FDA614FAF746D0BFE0B7BA84 +:106F2000BA5B011FE41A17FA714E38B6D633BD7733 +:106F30004075D9ECF8CB1DFF36AEFF6557E2EF3256 +:106F40007E7DDFFCFF3EE3DFFF771E7FD3DF19FF8F +:106F5000BBFECEF33FF41F3CFFF9A592CD4FEB549F +:106F6000BDD8DF4F3C223E66D7DFB22BB9BFFDBA9A +:106F7000EAB2E5138BFCC4E9B5E6428897F80D76D2 +:106F8000DEC3D9DF0CF9B956D083BB785E36D5A302 +:106F900026E4A9664C1179324CFFD570FD57C3F534 +:106FA000DF91147AB5BC92E9776A5FC4F442583233 +:106FB000DAD19F099C56303FFB08A1CB0CE835DDA8 +:106FC00093343F3B8FC3EDD4A7795C9F963FE7781E +:106FD000CFF5A8739D2FEC8B9F128C9FFE7795E7C2 +:106FE000033BF4AAC0C3AE4A662FE7CC4D6E0FB682 +:106FF00039E8A84D6AC4FC03273D5E57997F2DE808 +:10700000B1D06BBEA2E6A6A67782D3FB3A4EEFDFE5 +:10701000A83C1F8AE789A4A277A5878DF379FFD9B9 +:107020005033CC265C857490399D64D2D68DF15F47 +:10703000F24D62F52FB77E44ED1058FF35CD584321 +:10704000CB9FCF212E9174FF91D89FA37FEE6E1618 +:107050004795735487BFE5B483BD513837B3DB74AC +:10706000C5A285604F74EE5E09EBD30B6998A7BC8F +:107070003BB3E339F4E7DA272A0087B01B098FCF47 +:107080008249C1F2509CFB4E76BB7FF7475D71B0E1 +:10709000BF828512C6FD5AF50773929EC773D8FB4F +:1070A0009AC76FF377C9F543B3DBD7727A537F3151 +:1070B000D76391EFB5FE9913591E547510F67724D6 +:1070C00073A60BE2E9A9FA8148EF39CB7E539D62A2 +:1070D0008E84FE24F01F4BFBFD47420A587C5ECC99 +:1070E0007FA8E707EAEF62FBDE1CAF39D7747D2A81 +:1070F0007EA4F0FB453D919FE7ACE7F4C7AF779BDB +:1071000053607E43857F2F301CC4B3CBE49A64F177 +:107110008304D7AF5AF8B1676FA25527CD93587C37 +:107120009F9A6DD6FDB4B61CA52659BCEB975C4E54 +:107130007EA3EA5CAFC7499684F92404E625E4D12E +:1071400039FED57CDCAB2F73FC17B85C5FCDE59ABC +:107150001003F763528D5BC5F586787ED271137C80 +:10716000DE552A8F6B0C32EE1C3ECF399739DFF398 +:107170007CDC39439CEF423EDEC2CB1CF7433EEE43 +:10718000C2218E7B37C7EFDD978967C52BF17E86DD +:1071900086E7663E5EF3658E1BE4E3360F71DCED39 +:1071A0001CBFDB2F13CF057CDCED0E3CA792DFCE9E +:1071B000CB1CAFD4CBE4E700975FA75E13E36BF97A +:1071C000AE30B4DF1DB2F77383878D2F9E24FE315E +:1071D000FAAF23F8BEEE9495F72E32938C2BEA3B50 +:1071E000D7E354E3DCC2E335E229C609F0FDD02938 +:1071F000D7D07192E047D4BF5A657A3055FFCB386B +:107200003CCB2E711EA27E15F43F3975FFF7713805 +:10721000EE73C03F58FFA2FE9C41E06FE570B45E84 +:1072200022FCA2FEC241FAFF0E87E33B9708BFA8EB +:107230007FF720F87984C3F1C825C22FEA370FD22F +:10724000FFE31C8EC72F117E517FFB20F8798AC384 +:10725000F1D425C22FEA1FE89377BBFC69E23E0612 +:107260008394429EF1289266E0FD0646E224F801EE +:10727000DA6A76BF01E9729E87B29CA3A2227EF2EF +:10728000BE9228D4DF7B178BFBEDBD9AA01FB137D0 +:1072900097E729F3B896C6EDC1BD57B338C8DE10DD +:1072A000FD6EF1CF44BC68AFC1F29C7B0B581EB39E +:1072B00056D68E26260E97C74D441DF269D8B92A98 +:1072C00061EF89F3556B799C6AAF49304EB5B78C45 +:1072D0009577579398ABD072EEAA348EF9A760D801 +:1072E000423CB6FFDC984956975BF23156C731DF16 +:1072F00040E179231421C49697E138AF25F60F6F4A +:1073000032CC19A0E60A27B1FDBCC2B0DD7FA88748 +:10731000435CB4FEEFB99E0C4E4A7E9EE6B05761C8 +:10732000F4E3F99AF3F8FC05DECA393DB7CE79AF3C +:107330007B3A9DE7B353DD983FFAEC698EC7A9729B +:107340008CED9F1377B27338A9E26C5A47E3293862 +:107350009F7BD373C40032FAF798EB748CAB7D84B7 +:10736000FC8771353AEE4D7BDA15E0BF591DFA7492 +:107370008807CE7B4E5FAB41DE7507314C40EF474F +:10738000DFC07EB25A881163A46A0EA29DEB88CF3B +:10739000F17393223E07E16AAB7F398BCFBBBC25EB +:1073A000B80EB6EECAAB3D36FB7516F733BF627A40 +:1073B000ECE725F9F9C7590E3FB3C36B8FD7691DA9 +:1073C000E11910FF96E79D31E1FCF3B8B0141C46BB +:1073D0003FDF16DEAE407C72D69E46CC5F4FB5BF17 +:1073E00095F1F05CBFD57E17FBD9BFD973717B5D7A +:1073F000C41944DCE134E4157BC04F0F71BA30BED0 +:1074000012FC91354FB2F1498797E9910E2F8BE32A +:10741000FF179F7CBA7CF23BAF3DFED001DFA83C5A +:107420009618C9F7E9EBBCEA7FC9EB674087802F64 +:10743000391D487D862D8F58E45539F1B681E34DCD +:1074400094BD29CEBD14F8F83AEBF4EB5F8D54C12E +:10745000BC449C8690FB1DFB9B538D8BC5256471A2 +:107460005F8CEB5519E653EAE3FA47210AF6EF98E9 +:1074700007CA7D1E9E53643038FA5BC7CFAB89794B +:10748000B98BC326DCB742C7C0FD3EC8573F520682 +:10749000EB63D0366FD3C7D69B4DA58CDF36952ACC +:1074A000B174965F65BFB7A8B8D39BCCAE104F62DE +:1074B000BDB7A26820BC6A71246A8547E5F038FB35 +:1074C000999B129E3A5BFCEB52E1F18C27A41BF8CE +:1074D000568911A697BF61EBCF551AC3F3FDA9FAE0 +:1074E00051743E2F075D528DEF2DB0E741A93969E8 +:1074F000367E57B42C479E9483BFFAE242431BCF9B +:10750000796EB1859F4771B6F729EDC44882779FA0 +:10751000EECCC788211D9CE76ADC4107DC8EFEDBD0 +:10752000E05D923C1C71DFD006BEAE6D5462686FA8 +:1075300045299890EFB98EF3A5128CE1BD5EDFF678 +:107540004949E74F8CE4EBAD529C1C7E6F811DEFE7 +:107550006A4E969D0E4AF2731C1B85DC070F98F647 +:107560007BAC9C727EDCB8D87ADE77AF96F43BF9C0 +:10757000633AA5833EC73D0943A4AFF261369E6BD3 +:10758000EF2B53BD0AF15A2A2398CFEBAC7F46E08C +:10759000EFD54E845FE8E9F43D22AFF693CD4392F8 +:1075A00008DF27B7B74F29875CCFC99CAF9F1E6400 +:1075B000FEA9E89B56ECCC2B1C1A7D7D20F7B0EE83 +:1075C0002926BF0CCB2EF7A9C6234136DF4B95FBEE +:1075D0004F0A67764D84803E53431112A1EB7C7EA7 +:1075E000A81DF7C935A9270AFE1895291DE8BC3B37 +:1075F0005B67F76658EA4DA3EDDC85AEA81BF24049 +:10760000F87D30D110E982FA108FE92CEBAFA74951 +:10761000240CFCAEE52A61782FFACB986AEF8F9A9A +:1076200009B2F51C96C817405787CEDF3D85FAA7EB +:10763000B4BD4AEDD07DC9F4491AB343D39FF29942 +:10764000982710D662C092F9936298CF995F470C41 +:10765000F0E74A3ABA498476FA6D8063327CA7F340 +:10766000D620FFA31DF7ED733CECDC7A7E7DBBB426 +:10767000D0324E691AE3EF6973BDB84E7CA38A9D80 +:10768000DBEB0E2D6AAF82F12AF97D7A390A194EA9 +:10769000F1E17FC9C3FCCF490902F809F2BC863782 +:1076A0009B48F9E2B184BCDDE4C5E7F9A6203E833E +:1076B0001FFDCF10E4B9AC9B5CA143BEF507FEBA39 +:1076C000D1B06EBCDB14C2EF5BBE65E8904F249F67 +:1076D0007A19EF8FE8E7F7A84C2A210F366102FDEF +:1076E0002CF3EFF459F6F9FBE645E7BB908EB3595E +:1076F00072DD0EE3417911F2A957562DF91F2AF7D1 +:107700001BDDEB48F8B132B8C72426DD5D6679EFA2 +:10771000A3761BACAF938348F77E7CC69A39BEAF85 +:10772000067F37FF398ED7B99517DD37696B8A77B2 +:10773000578FED2F6B29CEBBCD714FBB2E0DE2467F +:1077400070D8938E377D6EE930C0D743EEE4F72FC3 +:10775000C8C1894631D48DE6BB500EF93D2BABC66E +:10776000EBC3322DFDCFE17C299FFA29E237BD8C96 +:10777000E587D0BFD9F996FCFF82481DDE8F441AF9 +:10778000D93918B10F39FAD644336C498C5E6D3F44 +:107790001F33939FF32C5CE7C2FCD7C229A843494F +:1077A0006133BBBF6ABF6C94037F3F4C5EC88403E8 +:1077B000EB0514BE9154540BA3F67EF62F99FD0CE5 +:1077C000C401C4B9D1B52DACBF51BA715A87F849BB +:1077D000990BEDE5D1C4F042FFA3351781734563E2 +:1077E00088A59F4238476BEFD7096FA1DFE5827804 +:1077F0008780671439EA3573B07F12A3ED0BA89B1D +:107800003722097CCE71C6887A579597C7499271FD +:10781000494F33EC0B0D187F907E9BD2B81DEE279D +:1078200001D0E77B2436FFE8B3B27110E87AF72184 +:107830008CD714ACEAC075BD238DD977EBA93DA0D8 +:10784000B9C14EA1CFB1A9F9500E52C465E0FA9169 +:1078500094FF1E4DABDA9606F1B0B469DB800FD30E +:1078600014FD6B783FE76937817DCC34B31DE50F9C +:107870002E64023B6373595106C85B5AA39AD45FC6 +:107880006B4973237C7BD22405F242296FE1BC94BF +:107890007AFD3B3369B13BD7FC1E8CF397DC083E85 +:1078A000C5FBD0A25A1DF873FAD2328C7FF5764808 +:1078B00018FF7A438AA990AABD7C5EE304B82F67BB +:1078C0004E66E41168B7548EAF77537856DCDA58B9 +:1078D00002F8990DF97EB9305C94F98305AF1B0A63 +:1078E0009C072B50E26ECADFDEE0A997D8335A0519 +:1078F000FCEE859330949E8162F32DF09BFCFC1C82 +:10790000924C7AA2901718984AC8EB16BA814F6722 +:107910002DC39EAEB59C0AFF833D17D3B6AF8F85AE +:1079200055DE3025B40B62883F35684C0038E5D011 +:10793000E9BC62CB3AE7E1F3F34C5FC4EF4932B9FB +:107940007F6310AB7FEBE1F3021DFEBAA5BD3B6484 +:107950002FCBC14F771EC2EE967EF1D77340C7B5CD +:107960008FBB31EE39FD7177FC3A5A5EB14FC2756B +:10797000C67582E9F5770F4828F771BF8A7AE09DCE +:10798000A017CB0D9EEEAD5FA0E59EC765D28968BE +:10799000A9C57BA5CE89F5F4182B2FE10ED28A7DDF +:1079A0002717407F75C73C04D689153F5D7AE317DA +:1079B000687929E563A8B2E260B33A9C96EF8A49F8 +:1079C0005D50BE308D209F45B3D418E4B55C08747B +:1079D000E7DDA4E13A46F471B0BFDD9D378FF2E3F5 +:1079E000B2D86333A1DDB2C3124452E93C0E3E93D8 +:1079F0004FE15AF17D09D7C7E587D2D95D2B1C7FAE +:107A0000E7E854AEA3DF57D179823E5C4ADA6702D9 +:107A1000BD561CDCAE5AD7B9B79B4A31F5439457D3 +:107A20007C9F8E43DBADFC9164C0145742BE03AC17 +:107A3000973FF5D5EED7607ECD6A891FE6B54185C3 +:107A40007A4B630B9FF0E900DF3E7526FDBE6CCFDD +:107A50003E754919E08DDC0EEBEAF2435712DD4228 +:107A6000D7731D32FA0BAB32BD9D78BFA966BF0F2D +:107A7000A51F2E62836B19D71BD4EF53ADE7DD9E94 +:107A800048CF443E5D7E48B68D23E81F3D43D879FC +:107A9000B49FFBF13C9AA09F58AF04FD56890BFFA1 +:107AA000949E8A64F06C057AC0B91BEADFC0F3C10A +:107AB000A6103E1F6AD2914E3B018FE3585E0ABC6E +:107AC000A7725B05F756054CB8180CCEA5985590D3 +:107AD00087991566E5BC5B23927E113B5D3C77BAC6 +:107AE000230BC1C8999AFEDD190AF5C776AA91BB86 +:107AF00021641D543A6754D335AF3E3D5C916ED935 +:107B0000F75B2FB1F37D9F4BD771FEEBF355C4F7B5 +:107B1000CEDB2AF6F3F813AE933B6F5BF208C4C7D3 +:107B200069FB2FA6837FC1F7FF52B5CF5B50696B0E +:107B30009FB7A04EB49F89EDBD176FBF73C135F6D7 +:107B4000F1172C13ED6F44F8B58BC39F77FB54FBF3 +:107B5000F8B7D763FB060FA36F4FA617F3AD5B7C97 +:107B6000461CF4315EA83609F2C94B3AA19E5877FB +:107B7000A8E637217F5B3B9C59BE8958F968DA0239 +:107B80008003F2B2AC7C9451996693AB4C33CB56E4 +:107B9000CEAE196EAB9F1B2EB27D1F567B85832FF9 +:107BA000353CBF8865000A0C730AA73A5C457D54D2 +:107BB000359CD9C1F79EF061F9DE6BD8FCEE1DAEA5 +:107BC000A11C03CCE097DFAB463E67BDBF95C03D2F +:107BD0004854A7DEA945EE8379F4BFD75DF03E8D0A +:107BE000E73BA57908EABB0D8515FBA3167CB68E8D +:107BF000A4FC40CB2DE92AC33BA7C386914B425638 +:107C00007B7DFD48B516FC0D787F8706E385D7C3DD +:107C1000780D6A4F09D81DCE713C4595B671BCA34D +:107C2000EA709CEDE92C9E2AC6F18CAA738CE3AD18 +:107C3000EDE4EFF9383B80CF528DB3A1E81AFB7C1D +:107C4000462DC371F63AC6D9306A99639C34361F03 +:107C5000FA9E8F13BBD8389E3153EDF3195D8FE335 +:107C6000FCC0399FD1F58E71341C07DEC338D4F0C7 +:107C7000D5E1BE2CD5D3B304E9FF0B1FDA39AA270F +:107C8000F228DA39AFF8D0CEA1B54CA8474A997F8F +:107C90007B4F7A16D2E783344A7FCD4AE728CF3B21 +:107CA00088A25F7C270791C4284454BFADE43CB848 +:107CB000F8F09C51CDF03C363DB410FCD187FC1857 +:107CC000C77BF7D874F58E24FAE8CE76F7B98485A9 +:107CD0009FFBF42A8FC786D2D93EA4289FE3F19F49 +:107CE000D7214E449F6FB809FA436779BCA81FDEBD +:107CF000666C778EEFEB9DDBC3D6A90FB69F71A3A1 +:107D00001D11252F9451B8E7F369DCD96EBF2FB34D +:107D100081D3A3E7A71E760E889823F03EBC8E6C15 +:107D20005BBCF07727BEFC0CCBBB2323E0DEDFAFD0 +:107D3000B73EF634547B515A3872159D6FEDD1ED34 +:107D4000EE11B4FCAE3BB1C0D02CFDD4BAF1DCBD19 +:107D5000F0436E8EB86DF6F32D75F6F26D0E7BFA6C +:107D6000D5F422B13FCBC6D5636EA0D77CD863A52E +:107D700024BC0D9E987C17447A2D08B2B6029E86CC +:107D8000FBDD248EEB5D2217E39CD15C8CD344C4D5 +:107D9000BAE5806F81DB6B86293D17DC27231E9DAA +:107DA000F0264EA49B2EEAE7243AFEB71BCEF10C38 +:107DB00006FFEDABEDDF49D46DBB8740F0C1D76A5C +:107DC000ABF69FB5F0C7CD9159FBCFDAF034C7566B +:107DD000BEADF1665BFDDB572FB47D5F18BDCBF602 +:107DE000FD8ED6BB6DE53BDBEFB3D55FDAD16CFB27 +:107DF0007E576CA3EDFBF243DB6DE5155DBB6CF5C7 +:107E00001B8EEDB37D779D18FF15F4037F23E37977 +:107E1000E7F7B5735BC17E7B3FA8E07ECE9B7CFF1E +:107E2000EE6D7EDFCF4AE0BD29203F13BDE0373441 +:107E3000A45179A6B6C4042D777DEB54D02304AFAA +:107E4000D428D746AC8F5267770A3F9F2877A8245B +:107E50009E0DDB2BFD71D81EB9FFBB92A0DF27A6BC +:107E6000FE2E772849BF2B092569BF17A49E12B0A3 +:107E70001FA32F7B929E03EF974B32825CE43EC997 +:107E8000F32E5267F5DFE66B2C3EF44CFAB4F95A48 +:107E90002EDC8FC1E4BDFE48FE34F01BEAD57849E4 +:107EA000B27D9BBEF1BA24BC3770BEC6E4E5AED845 +:107EB000085B3C6DF9A13136B97F292D729346EBF1 +:107EC0009D3F29A39E25F1A7467DF52A18DF9C0F2B +:107ED000EFC9B15C5C1F5F6C32F79FA57EC04B4D54 +:107EE00035F8FCD7A6F0FEB3D4257CB5A916CBBFD8 +:107EF0006F8AE033D15487CFD79B1AF1FBD9A6D52F +:107F0000583ED714C5E79B4DADF87CBBA91DBF9F5C +:107F10006FEAC0F2BB4D317C0A3910F62E09737B33 +:107F2000526C981056EEE57390F3441CD3C0FBA33B +:107F30007AB50F4AC08EEE7DC98379B7A9F0E4E423 +:107F4000BBD4F43371BD5F12B3C799C5D397C6E8EC +:107F5000E373911AC891D83856C5385ADA2FAE440F +:107F60007B9CBE57D865B231634E927B3BF142E4B5 +:107F70006183D349D43FF7DD7FAF585406F42942DB +:107F80003CA53D253732BAED37BE7AD5E0F8439BA4 +:107F90002F7F201EA55FFC6E14C4A7DEC915F8EC68 +:107FA0001E05C12D450BEF023EEC3DEAC179F51EE1 +:107FB0004F67F92810541B42FEEBF243BE98553F21 +:107FC000ACE8CA8CD9F5457ECCAA2F7A4FEF0F804A +:107FD000DCAF0AC9B1B313813F4CCE1F8CEF44FF15 +:107FE0002BBA0A639AAD1F7BB9B75DAAC17B1F8903 +:107FF0009E312F89FF219EAB422A8EF3F6A1319844 +:108000007F40FDC4D85916EF8CB17143312B5FD638 +:10801000AF4E8F9DCDEE872F55BF9F367C841C259C +:108020007FF0A63E8F3BD89328FFA6E2FD6EC7DD0A +:108030001FC0BAE3A1FF7F8CF9420A9645BF0D5DD0 +:1080400072D403E779C961DB78B49D2E7C7458AF94 +:1080500052D3DD9E0FFE7BE0255CB7D9F9F2089C78 +:108060002FA7FD5D50B456E973FDE7CB1B385FAE1B +:10807000F026D4087DF5CED13117CD0779BBE97450 +:1080800050190B7904ED7871445DD7F86AD08FEF01 +:108090001C5D9B07F1B4E572EFBDC9CECD7EA8B1E2 +:1080A000381B89B97B1296F988F80C21B45F6F3FB1 +:1080B000FCC0E9E72C65A7BE164F979FC5DD571E8C +:1080C0003E33F30B14FE95C7DE53018E635AC4E5AD +:1080D000B7CC5FE2E7EB971D7A4D85F9BDE98E9647 +:1080E000DC7F113D35104E2D64DB0F8D926E90E3D9 +:1080F00045EC3718809FBEF60A15CDB77EED26F009 +:10810000BB0E62BF429C7B584CC201C0D7A2A3CB1E +:10811000313EFCD61337707BAEBD02F8E31DE2AAF8 +:1081200081F9BD439E0F4CB4E0AFD8CFFC18D2CA42 +:10813000EC18712E90DAB336BB666987BDBC84CC6F +:10814000CD03BDB1E42137895114DD452CF72FD182 +:1081500079E7F899BDBB9434AE077B4EF130FF60F0 +:1081600051902823A83E5DF193872BC0EEBFD2CF5C +:10817000F61D451CE3AE2C66EF2DCB89A9B09FF010 +:1081800087A313E77F01B8CF135B0FEB32C948BE5B +:10819000FF7747AB1DBEC1E077C22BCEBD0F88A7CE +:1081A0007038E44352D2FCB4297ECE775C8FACF1B8 +:1081B000DBEDFC0D8EF26C3F8FB3CA44063ABF1361 +:1081C000F4465D19F81DCFD9468F788CB53ADCA7F7 +:1081D000150E037F51BB6002B1D4FBA316C1F7E7B4 +:1081E000A5E796E03973253E01F3F1BC04F314557D +:1081F000CE0F725A6002F91CC4491BD1A95FEB0B68 +:10820000744279BD9F9D836A0039A5FD6D09CC3C00 +:108210000D717D2F698F9B85B0FF6D8F7FFB747B08 +:10822000391DE409F409BC007A1804E345E9A5F610 +:108230007A7EC35E5ED687A7B86C3DF711F06A718F +:10824000F89D2152A99CB7DACD2BBD0C7EB8111C2C +:10825000EADFC3EDF995448F62DE6288F1C13DB378 +:1082600058DEC43D7EDD88D2EF9262E2F9880DD0FF +:10827000D4B28E357C28919845AF37283D2AF065D9 +:10828000C3870ABEDFAB45BE057855898976AE97B0 +:10829000220DF6AF15ADC666F792027E2FA0237FA2 +:1082A000A1CD1FB4F97B422FB8B95EA4FA62833F17 +:1082B00017F460CF4CB6AF9E50D9FE0EABA7F6D7E1 +:1082C0006B033852D5F3F5D7DB9EACDE8A9FFCF00A +:1082D000892895F765FFF2ED006CA6BDA5B4E741CE +:1082E000FE43FDC17501E0E337956800E6FD562CBD +:1082F00079DEFB2FB9BE837C27382FBF92D3E9EDFF +:108300007FDE7C23E0FD83836E3C6FDF70C813F754 +:108310005022AE3C7A17E3A7439ED7587903FE6EEE +:1083200054C331BBBC2D7BF4DB793A6EEE4547F08C +:10833000FBD8D17E5E79E08F33C11E69203DA8272E +:108340009CED60FC0FB370FD5A08E7FE9DDF45BE53 +:108350005503E7FB86A39B31AFAAE1E82CCCA36AC7 +:1083600070C8791DF7438EF9EDBFB321F04162CC9F +:108370002E5EFBFDEF4C788DC273FEC0AF03922DD5 +:108380007EC4F4446FD71DDF7B524FADDFDFE57E47 +:108390007D7FBB18B6D38F313B9E1C67CF7A773C6D +:1083A000007E53FD3EB7413508A9FFE1FE47BE0BF5 +:1083B000FCFDB207E30DCB7FF8F48BD7D0F2F2C708 +:1083C000DC39B3D93434C80316748133EE90AF2B43 +:1083D000E8B0ECC74FABFA55ECFD0359FDF458FE7D +:1083E000D849955C35107FD3BB4EAAECFCB9832EDF +:1083F0005DAFCD04BB7BEDF7FFAC827CBD75422247 +:10840000C30A07B6AFDBF734DA758027A423A75376 +:108410001FDD06D02B7EE39393B05E10D6B1C1E88A +:10842000F55DE0995CE4EB1F3D09FB05FFEA3100D7 +:108430000F753FFA4600E6F386D2C8F8FBE175797E +:10844000B08F5EE78EE605F1C9DED7EDFD26F2DDE1 +:10845000D233DFCC637950663EFB5DA3683EC60134 +:10846000F7DC84F35C4222C87F750FCB9887FEBE91 +:10847000426A1E4B221FD705981E7BA3D38397DF2A +:10848000BD010A17FCC5E7E5183B6FCBF212BF2907 +:10849000F63DE0DE465A7EDFCBE8951B70897BAD6A +:1084A000BC36BE3DB0A11BE8F4F6487318C42B29B6 +:1084B0001EA21C6F12E821F9CC8C618C4E44572A05 +:1084C000783BAA27A7C37BA8DFED367D136CEDF8B8 +:1084D000BAC6C6BF878F4FE14E03FBEC8D3C6AEFF7 +:1084E0002499DFF280907F6A7F58F8CC22E74CEE27 +:1084F0000F6C64722EE43E36A706BEFFDB0B4C8E7B +:10850000A01DACF314AEF830FC7E729E847AC14399 +:10851000E2C9E4FB809BCBB7FD3BF5CAD1BE157C1D +:1085200042E15760DDEAE717B6CF4BE980F6DB9210 +:1085300087687BAB7D0EE3623DB5FFBD65BD5FCA5D +:10854000F5C13501C7EFEEECC91DD27D79F5EED846 +:1085500023DF05F9A5F20AEB4FFD0FDD9827F2A7FF +:10856000C34FBDF875CAE77FEA12726BD7A74EB941 +:10857000AD3B32992493DB3F6906492AB7F47D521B +:10858000B9D512C8CFFF51FA54E06F51C09EE7240D +:10859000F4632A3C3AF5E3DFFC3AE2D3A91FE9DFB2 +:1085A0000BA462201F0AFE137CB7EC072BF0774167 +:1085B000FAF853F05F1F7F0AFE73CED78E3FE7F7BE +:1085C0002BC15011F162FA74AF21513FC4537F2E79 +:1085D000633CF50285693DA5F385C385788E789D5A +:1085E0008FF9E717823D81AC32BC0707CB3DB9EA72 +:1085F0007AD017E27D8F8FC5BF2F847B02D63C9047 +:10860000D78ECB01D8EF4AC4484D327F846A648448 +:108610002341527D67F1E20B60FFC17869A362409C +:10862000B719B2366A35F8F9EDECBCFCE2E6AF05F5 +:10863000601FFEC2F131DB407FDDF9AC4CF8EF2862 +:108640002A906F7207A7FF9B24BA732A9DE71DC764 +:10865000995FB1B82D39BF2CE3F59768F7A8A097BB +:10866000A85FF0BA351EBE8CFF9E64DD1EC7FBE31B +:1086700037205F2D73F05584FB8D3F147C7535B921 +:108680009AFB6D2E6B3EDB0CB96C1BD825174EB3D5 +:108690003864EF7119E9D17B5862F94F100F9E02CF +:1086A000FCD0A35AF3D8CE03FF25B9DFA0EFFBE33C +:1086B000BFABB89F56A97FE29509BBE9F3FC132F26 +:1086C00097FC0CCA3FF9EDA857C8C0FAD34FFC0578 +:1086D000F7B32F9CF0201C174EFC72D4FD507ED2B5 +:1086E00083F7D55C58E361F99F27FCB1B1F07D2495 +:1086F000CB175AFBF33F4F48E0BAD482747B29C0B2 +:10870000FCB1DEE3FFFE7BC81FEE3DEED1611E0D26 +:1087100027D2717FABE1491FC6692EFCFCCF15D66D +:108720007CA6CB9DCF4A7E1FE2053FA9853CE50B89 +:10873000996CDFA0E16753F6C339A215474FAAB081 +:108740001F33FD177F9D007AE7C211664FBCEB4EC9 +:10875000EC857DD63F046EDFE086F82EACD7C309EA +:1087600069CA885D0FF7E10CC40BC3C3058A07987B +:1087700017C54B1DE8CB54F8F83FFFB0F8786F01F0 +:108780008C5F7FFCF32837FD78914CF6DE1F83A3C6 +:108790004D74FEECFD893F4F00FBE84F5DCDB8CE38 +:1087A0000F36EFFC8CFFD7E62DC58732EFCA7FD896 +:1087B0007933FE3F11D059DE9F430E06F2F94FEE9A +:1087C000C5F28FFC06C23B44F9AFFD879DFF27A48D +:1087D000FB114AF7C0E074FF6F196C5FF81F6FDE82 +:1087E00083D1FD594E777F10F2102EFCFCAF185F3D +:1087F00017F31F6CDE3BFF93CE5BD8439B5C467B3D +:108800005121E461C7BB750AE7BAD2B9ED1096925F +:1088100079DEB513AE6732987F214B2C6E4346B29A +:10882000F811E1FE46DFEF416AEC7C95A2AD67F7F7 +:10883000912906DEAFB7E98A4506E67690F29722DF +:10884000502E988ABF73EBF4BB942BBE741AECFEC7 +:1088500096660A1F1DA7C5AF04A9E544DCA5AEB8FE +:1088600067023E5F83E7061EFF7207559BDFA13953 +:10887000FC059F6EFFEEE1FD7BC9A920E42F790D79 +:1088800005F3537DA43D6ACD37F0104B3BFABD1381 +:108890007E10D0624F5E2AFEFE9CC1FC4F592AEF2B +:1088A00086BC5832DEC5EE3727EC5CF1A60223B653 +:1088B00089E55D78EDF85CDF0D785408F50FD9BCDB +:1088C000D0AF24DC9F5478174AA9CBF4D9EB717F41 +:1088D0006950FA307A8CAAE7F45965A387C0FB4542 +:1088E000E862A387C0EFA5D2C5490F27FE7F95C1D7 +:1088F000E274824EB67C905CE697C4A981FCCBC33F +:10890000FB312EF2CE3FBF7623F0E9F29FC9C44B74 +:10891000DBBF7BD84FE220BF4A4C053F6BD95119D2 +:10892000E3C2FF174BEE49A70080000000000000E3 +:108930001F8B080000000000000BED7D7B7C54D5F0 +:10894000B5F03E33672633999964F29ACCE4C52496 +:10895000811834E0248480823A218020F43AA008EF +:108960007AA38E10209827485BDAEA8F09411A1EF5 +:10897000B641E5A1453A2028ADD8061AB9A0A8838A +:108980003CC4566FA3E5DEA2450D8A82C823A51715 +:108990003FDACF5BBEB5D6DE3B73CE6402DAAFBF43 +:1089A000FBFDF3E59F937D1E7BAFBDDE6BEDB5F761 +:1089B0005CBE0C7FB73076595C196B652C83B1BAFD +:1089C0005F3B184B67ECC19D09E1C9F970DDF5E922 +:1089D000503684B1734B7A0E65C3FDD02F15DF5628 +:1089E0007C3DD43DF40EB8FFA0CAEE0F9444FB9139 +:1089F000D754A781B1E18C9DD9639B11B633A66C86 +:108A0000DB771FF5DB31DD94A044DFB33A4D342E24 +:108A1000BCE7C7E7A15F28E1414ADFFE186BE1FD33 +:108A2000FD42E1F0ED3685AD08DFB64DE620C0D160 +:108A3000B4EDCF663FC051F5EB1793BA61BCA6DD2C +:108A400046162966F47799E173632461285D8FE304 +:108A50009531BF5DA960AC11FFF5C2B5B361324B72 +:108A6000826BC7CA3F1B93F07BD327DD96E8F7756F +:108A7000BF7E7557085053F79BE793BC703DDDB53B +:108A8000358995507F0F98931953EDAAEE7DECF739 +:108A9000526ADF7E605CC65C709FDF624D1DCBF961 +:108AA000789DDF39C9103E06FD48B8617EA7F11FE9 +:108AB0000F63239D8EF4CFAF83FF47B011978D7066 +:108AC000DD96C6D80D7DF114C55788D3F3C58B1B31 +:108AD00043809F333BBFDC88F0D7FFFD2F1B7F0413 +:108AE000F863AF599D5B61DE4DBFFC8F24A4AFFCE2 +:108AF0006EAA53A1EFCEE5B29007DE3BF77E423877 +:108B000004B7CEBD7A32CF0BF33DB7E3AF2E2FBC07 +:108B1000BFF0D5719938FF852F5565327BFF709C6A +:108B20005BCC5838410B5798E8E8DD0D9D664273E1 +:108B3000AFB8C6D0637FE7FE3C84F3ECD1045F029C +:108B4000E209EE2D2A43FA009D86F2F6C380DFC6C5 +:108B5000ED3FFEB371683C3C87B20D6EA4EBA7E31A +:108B6000114EC622D9CC8DF8ED59E6B4F77DBF97EA +:108B70005E47809ED77F03BA6D5FCEC7ED00BA25F2 +:108B8000F5A5DB59FC07E8D38474B345E976910574 +:108B90007FEE298476671AD1351EBE22DF005FB5CD +:108BA0000AEFFF26A7FF874E949F9DB65E7A4D463B +:108BB0007ABD78318F01BD4F997AEE63E58CF5BCB3 +:108BC0009AE0DC0CF71F7CF58F2427E75E7AD78CC0 +:108BD00074843FBB02F33AC77AFFBA709E8D8A98BD +:108BE000E716472421298AF7C6F09409DE24BA7FC4 +:108BF0009CEE8739FF22FEB2913EE17D772A71E833 +:108C0000D1E12CA079B07006CDBB61CB9FCCC83729 +:108C1000924E481F6524D2EBF878BC2FE924E71D5B +:108C2000DB9F13F1304243B72D5C0EFBD2B5C7CCAE +:108C30000AE3D10BE0C5EF105E689FDB94A02AC960 +:108C4000FC7E0ECCE39C89CDE84038C2CA1FE3D13C +:108C500097B125349F1762E552CCEF6A727935B827 +:108C6000FF51BC3CE37452FF123F67BE8EAF9F0FB3 +:108C7000A19C03FCBBEDC183C83F8C59C227A09FB8 +:108C8000FB99C2920BA37893F09E5119E9DD33BF93 +:108C900034864330FF651DFB49CFC6CA37CCCBDFD6 +:108CA0001167BC3F8AF11A77EF1B8A7AE8CC1B7BED +:108CB00088FF1AB71F3787A09F43DB7E63EE2E899C +:108CC000F23BEAEFB0467F9FF9D5BEA1A46FB1FF9A +:108CD00038FAE684E8BF69AFBEFFA6ED7FD6F55F40 +:108CE00017EA303BED571FE7B4EA9F8EF33DDD6591 +:108CF00062A8FF4E77182784E38CFB96B05F124F73 +:108D0000CBDE35931D2B7F2F319C00785AF8EE84F3 +:108D10003F25A7E3D5EC05D4B2CE16CE579D8FF8EC +:108D2000B3912E9DEFDE63447BB20BF1784DB4DF3F +:108D30008A23CD550E90DB8A63817264AB587D30F7 +:108D4000E2A84107378C9389FA7929F4E3857E9864 +:108D5000EA7307A05F63D2F809088FD169705AE3FC +:108D6000DA55DE9FC91E604180CB0476DBABE1277C +:108D7000F7D4A4A12C19A7E731A05E5800EC85FA1E +:108D8000D96D66C52AC0C70C89BEADD0EF82C1FEC1 +:108D9000D283D05E30DBED0BC173CF1DFCBBB34E75 +:108DA0007BC8703DB6F3C22847B64B46E605D5777B +:108DB00046797B0E039560137C95DD61233B6353FD +:108DC000BDEBAAA16DAB557D8051F6993D989B9264 +:108DD00081DF99E93B4F8AA27E8EF34E6249286F6C +:108DE000B27FF99EEC97A991A1387F66612A03BBF7 +:108DF00092C338DC46319F42D6A5207FB74E49DA70 +:108E00008CED0D8E5AB2FF79AC679F1FE8F66CD2DD +:108E1000F8C3A8C7E05F03BE97DBACB7EF0316E962 +:108E2000DBF92135467EBD8600F05F619BFE7E7AD0 +:108E300055E5FC013EC6EE4BE99CA082FE4E9F5ECE +:108E4000B9231B703A69C57BBCFD7C65A907DAFFB5 +:108E5000B1BA61A20A7A24FDF795A579D0BE90FA3D +:108E60008389F4BC0E907423A8FED54327864AA2BA +:108E7000729B0160261B499E6F463C9C0D9C598647 +:108E80004F1BA67D658647F817403CE48EE478C802 +:108E9000B11FDBC1E0FD0186EE16E4CB9FBFFABF38 +:108EA00052F03D2F73D27C9D6CA9F3730B4E9E8DB7 +:108EB000BC3CEC4AFA4C659F4B3E3446E520D91544 +:108EC000BC3D05F86AD9CCE275E351D7D6FB88BF23 +:108ED000606427D943F9BE339DE85323E883705A71 +:108EE00080CF66F357582D6B177A68AC13C7514281 +:108EF000F5C6CBD77D7B78664ABE713007DE57EB6F +:108F0000BD045757867F36E2EBAF1941BACAFBEE74 +:108F10009933BC41C0EFCD2981B9380FCF9C4B7933 +:108F200008FFE41446FD55CDB5FBD1AE5ED80BEA83 +:108F30002F8E5CC9EBE6C5CCA70EEAFFF9D4D4E0CE +:108F400077B1FF82D7BD3B0F437FD7D7987D5618A7 +:108F5000E2FA45E53E358DF109A1DF21E8E6465A02 +:108F6000A2DC7D8F8551EECE27287E3FB4CF3FE433 +:108F700024BD9C5333F930DAB3F3B6FC8E08DEFF20 +:108F80009197E4113C0005E521776F72C49A44FC87 +:108F9000FC550C3F7FA5E75FFDB8E72F7B77775344 +:108FA0007F4ED11F3844F03C57D0E9BC91FBE5E738 +:108FB000177B090E701FF7A1BDFDA6E33D9922FCAA +:108FC00024419F47ACFE35480FC0FF3A2DFE7FD6A7 +:108FD0003F1D37E27B4047BAC6D2718EA5390FF5E7 +:108FE000C283818EF1A0B1D9C939DFAB40E69E9230 +:108FF00012DC82EFD7CFE83A6422689A8B506EFB7E +:10900000D259217DEEDAFB408B09DA4D48276F5F9C +:109010007A5EBFA894E8A6A16F07F67FFDDE3F1B2E +:10902000107E49D7750AB703B1DFBF92A28871EBF2 +:109030005B4C80CF0BBBCDE4FFC6BE7730C54BEF9A +:10904000C9F6504B854F0539CD34B060BC7E0FF664 +:10905000E9D7E24B88037F6F7F4EDE1FE0FF4D2D87 +:10906000FE7FD73FFEFF5DE0FFDFBF25FE8F209D27 +:10907000FBC3BFF4BBEB847EA863ABC8DFFCCC3F73 +:10908000D53510C61F6FB4933CCCDB6A243984F706 +:10909000277B5C517D32EF86E67D38DF79CF28C4AF +:1090A000B73541AEE7BF9C33F910EAF7D9ED7AFF47 +:1090B00069CE8C9019E19CBB5E7F7F5E38261E6472 +:1090C0001ABD0E7C7126CABF03B8DE7193BD340A87 +:1090D000F9A89A5B928CFED26B26EFEFC91F7FCB6B +:1090E000C836C7C17F5E6A3ED963D9CE6D06246992 +:1090F000EC3CABB11A505FCA7EC7CE2DC944BF66E7 +:1091000081C37BC5386CC022BD5DCF0F2532AFA6B1 +:10911000DFC2B6545D7B507B96EEFD6BD617E89EA2 +:109120000F0E5FAB7B7EDDB6325D7B48C78DBAF735 +:10913000AFDF3D46D72E8DDCA67B7FD8E1A9BAF6FE +:10914000F0AE7B74EF8F383A53F7FC86EE0775CF9D +:10915000479D5AA06BDFD4F343BD1F6360A427591A +:10916000A2427AF3C0E253152790E1CA95B188CFA5 +:10917000AA91FCDD03F3CD0667125E8B0C4EE08FE7 +:1091800037664F263FE0C07C97DF4BD70A3FC63F8C +:10919000CC38BA3C18C7CF1DE7FCA2E28466DC2AB3 +:1091A0008B49A7E7C639F5ED61A9227E18C0F9669B +:1091B00064AA5EBE8CCD9323666866CD1B9889E356 +:1091C000819C8D4AE57246D7ABCA59527305B641A8 +:1091D000CE2A53E3C81913F6B652F0135CFDE632FB +:1091E000642C07D9653FDEF4D2FD900AF1CA188BD2 +:1091F0002FE720CECBE04B47261C3B237080F72780 +:10920000EC332B367C1BFB2CE5DC6DF086C8AEA561 +:1092100032CA2F3D35BB289969F07B4FAA41E883BC +:10922000761E473AB70D53251E0BB4F7270C578B04 +:10923000A3F795B9933351EEDCFDE845B3BB70F06D +:1092400016D0C7664F3E5DE5FD65330C13C271E86D +:10925000DB90CAE30CE9770D8EFA5D0D88DFB3EE83 +:10926000F7D60E027C3556F790DFE536B4CF3F8453 +:10927000F3FAAD91E7CDC0B342BD305BF8D1B3276F +:109280003E3EFF10E8A7D9EF0C22FD24C7D9B03825 +:109290003258EB37E4F413576D13F06C5CEC1F5C41 +:1092A0003388E022FD20FDF4BC50C3788C7706B0F3 +:1092B000668A1BD71A586DBC7E968B7E3291E40865 +:1092C000AFD34E727276CEB12415E691E8082E47E0 +:1092D0007E9B797D5705F7C7FCBEA9C03F79917B7E +:1092E000D7E2FB796E958595BEE3675607DBF261A1 +:1092F0007E4B530D3E3BB57B147C3FE161C6D2E013 +:10930000FDA57F37123C4BDFB88161BC96606F666C +:10931000E8D7CA79ED4F7D9AF063ECB4911D64E80B +:109320009202FEBE2B687FD15DD3857EC7C5274DD7 +:1093300034DE4598A313FABFD8690CA3F37E283511 +:10934000316280B6B1CD41F63B0F7D50787F4EA79C +:1093500023ECCD8FE2455D3F9A45C0DE25E4F0F970 +:109360002F4DB587EDF934EFD5386F09A79C776E8F +:109370003F71682495DB59E62FD6D1D903315917AF +:109380008EAD82F30FFD189F34519C383BC54E7053 +:1093900086178706D798FACE6F997BEAED77033C5C +:1093A000AD478CCC08FD78BBDB091F73001F616FD4 +:1093B0005F7C9FF5E67F653012DC11E447E3FAF14C +:1093C000342F867E3D7CD7F073853D9D8F7C199C24 +:1093D0004074CE32B0ADF97DE7F1662ACFDF1E4E84 +:1093E00075D2D5EC2EE272E21E38780BF4F736EA2D +:1093F000290B8BE707FC3E95FBD3748DD54F600797 +:109400004308C785F50AD1F3A412369B006575772A +:1094100036933F20F593D16F24FF43EA290917E8DB +:10942000B10F5235F6D198FCF050ECB77F7F6DC785 +:109430003E33FA6B4E46FE9AD4A3FDF96BE8A721A2 +:10944000FF493FED54CC3C617E5F8AF97D196F7E08 +:109450007DF4EF3DCDD2CFF973EA15FCCC0C737CD3 +:10946000FD744D1AA74393D3CC283F85F132FA0FF0 +:10947000F30CE1CD988752C3D6291AFC64A5493F65 +:109480008FFB1BFDE9BDABC525052B4B48FF5EE8F7 +:10949000F226A7C235FD53A5395E3FC6452F0C43C2 +:1094A0003ACDB356DAD2004E679A1E5F4F2DEF6366 +:1094B000BFD2D238FEE8DA077F76C09F41E727EEB9 +:1094C0002AF212FE3C6957F013CFDEF15105DAA5FE +:1094D00073024F8DBD712FD7D35960AC30AFD5C05B +:1094E000FCCF9E28E6EDCB0AAD7A50BE6EA33D3090 +:1094F00008FB6FDA3DF159ADFDFE3A95E7D3983D93 +:1095000095F2ADB23F97D0FB1067DFFC9997F4FF5F +:109510005748DF68BCDD5D81F156EB4BD724A37F54 +:109520003676D7DD4EBC5E481F48783DBB2BC18FD9 +:10953000709E4D057D6CC7F688439887F872F1E1FF +:10954000542D5DCEFEEADD0A13F47376E7BB152ACF +:10955000E63344BEA6D71E5DFE434500BE0F8D61B7 +:10956000C5CD760D9F58B8BD78D2CAF31D192EF31C +:1095700032763DC4231929F4FD1A97E12778DF6874 +:10958000F943DE0994B398FCCE93266FAB1DF80C1B +:1095900062391FAE132C18ECF7CCC6FCCE1437E59D +:1095A000655A15AE4743B3791C9A5EC08AF3A13F52 +:1095B00093C168C4EF7A3CCCB7195E4938D01E41DC +:1095C000B597D8D5E147F0CB1353099FA3CE3815F3 +:1095D0008C27643E48ADE2FDF54C3387376BF24093 +:1095E000EE192AD9459BDAC1504F3F90914AF0CBF2 +:1095F0007C50D5D419814A84EB5103C533A078152A +:10960000D487D9621EF99E9DCBA56FA3BA902D1960 +:10961000267FD84AE0FF8180E724AFC18FF9D7A425 +:109620009CC85113F877D94B19FB44E347DACC4275 +:10963000DEDE3192BC39BEBEC53203FC235B22CFD5 +:10964000AB260596CDC7BC38DEFFD732A40BFF9EF4 +:10965000E863C434150B2503C88E91FA7E25FD3AC4 +:10966000175B7C0381A1772E76D2F5B9C56E82EBAC +:10967000F1C55EBAFE747131DDEF4F4EAF767D6C91 +:10968000318CABE1A7F4118015986FBA91913C3FF2 +:1096900036BC2279661C7F405E9F5E7CD835769012 +:1096A0004020D023ABDEB969453ED119850866F765 +:1096B000CE72FF68C61E35F9E73360ADD5695F8F9E +:1096C000C5BCD54AC54079AAC7D3DE5C1ECAC1ABAA +:1096D00097E86EDBFF3EC37CA7A7BC5D4179F7D45A +:1096E000B7131F947775B1A0B8EF87B6E708BFFF2F +:1096F000A895E379156313105EBBC202783D67E558 +:10970000FEE0E756AE1FBF10D72169C18D28C7FF05 +:10971000E53C5AF42880672DF9200FD73B6CFBFFFE +:109720004AF960E350B305E5C3B3F738AD83180DCC +:10973000DD660626F9F5273EA6FC9AD11CC8E7EDA2 +:109740009756603B2329B0095D3616FA78E2013757 +:10975000C80DF2C38D848D10CAF14AAB68878E1193 +:109760001E569A78FBF527FE44F35E690ACC43BC8B +:10977000607B29F4B732A5C36D80B6BDE5FDE587F2 +:109780006FC2B67CFFFDE521F8FEE534A96F021E2D +:10979000D41FBD6D27B48768DA2A6F330BBFCAF9AF +:1097A00035ECFFEBA16CE0D7C6BD4A0782E6D9BB1A +:1097B0005AC1797A76AF267CD31FC8074E83F2A4AC +:1097C000969019BF7F6EF161E752A0B39ADAE64234 +:1097D000BC5FE30EFAFDF1F21319D2FF85F7B579FC +:1097E000B6B0A9A75BE38F7B18971BB614F4431C94 +:1097F000FF626846E517E9D0CF934A708511F5CC32 +:109800008B2627EA11D6C5F5D019D1170B67917FA2 +:10981000536FE54DD392E08AC1A827EE557D183FDE +:10982000D7E5B757A27DAFDB93EF6B61517EA94BB4 +:10983000E9709521FFA4E8DBAD22EF9299D29C92CA +:109840005282EB11ABF370BDA091B5DFF74384F703 +:109850006D23433FFD8B7D37248F827603B4D16F18 +:1098600068E87CD78CFCF9443AD79F8D9DC03FD0E7 +:10987000CF2A902F3F38329B546722EAA7E7FCCDCE +:10988000D7A28BF7F5137F9B6805FA3E5FE077223E +:10989000BDDDE9A61516701A9F373B07B3526CDB86 +:1098A00089BFEA4A0D5C8E98FDB77E55AC7F42FBBE +:1098B000F813136FD3E6773DB82E03786EDA600F96 +:1098C0001992C9DEFC6FB4B78DEB0D21D45F064B46 +:1098D0009719E9EBC6B55DA28F93F0B650EAF3187D +:1098E0007DBD7062EA6DD85EF86881337485FC6571 +:1098F000ED251B0B6BFCA327D2B91CD7AA215A4715 +:10990000A9BD9444CFFF79E3595978D895C6B3D30C +:1099100073395E7D743CA2EBFEB2DFAE1D08745B52 +:10992000B8C36448D0F0DDC21D62BDDAEACFC47EA0 +:1099300032CC4CE01DFC7DC0AF9ADFDB0EA920E7E6 +:109940008FF5CAF98015634723DDA2CFD9489D1E44 +:10995000F063BCF958A2D403D7C47F3F31E6FD02BF +:10996000D9F6AD189BD3179E8CC468DB02EFABFF12 +:109970009DD0DB46F8561B62FA4B95E38FA4FE247C +:109980005F1D4FABFC6D68203C4F69AFC4FA8D9EE4 +:10999000D9CC8B7619F9D5A7D1FBC7D3B85CD75EE4 +:1099A0002AD4D13B8AF722DDFD938BDDBA75BFB98E +:1099B000D50B697DF238EA79EC878528AEAADD906F +:1099C000CDC21A7FEAFFC3F18FC231AA1F386EFEE3 +:1099D0001F86235F279F513806EAEEFFA3706CBEF7 +:1099E000ABE8B67C78658D12B214A05D78C440797E +:1099F0001363CA586F0BAE3F3CA2929F872E09D6C5 +:109A00007F14A8ECB05A86F2D3EEC7389F2DE1F947 +:109A100023B8DF662A233B447E70E1DE8407D04F03 +:109A20002BA8F5CFC32BCB29A1F50DB92EC8441E09 +:109A30004CAE670C72B24A159CB751190F909D2A13 +:109A40000854D7A13367749427A27D5C630887709C +:109A5000BCD0E37CBC0C43B8C382BA3769A013ED19 +:109A60005D4612D77F6C4509D9BFCD86826BE7036F +:109A70001C8F2A95896F219E530A28FF8BF717C0E8 +:109A8000FDCDC26E19537C4EB4539B85DD6A15FA29 +:109A90005DDEB7A5061E407FE254FAC2DB2C37A07C +:109AA0001EF2B7A581BD3999BE7085DB83F6C65B12 +:109AB0006001FB72F2C987C8DE6C6EF1663953A291 +:109AC000ED41FF0DD69AF4C4432BD05F596A5FF085 +:109AD00020FA3BF0FCB716D0B3CFA70ABD239E17E0 +:109AE000F4EA29D04BA0C78C2DBDED10EAA5825E0B +:109AF000BDF310E99D2D1B8DD47E07C643FF07E6FD +:109B00001132E27C07A9E4D75B019644685B071732 +:109B1000D03A11CC9B25A27F3D983F97F97CF3204A +:109B200003E5F3F17DC4A3D5C3DF374F613E5CD7B6 +:109B3000323BEC1487C8F501A358A74A14751A8A5A +:109B4000730AC5779655650B301EB30CD4AFC39A14 +:109B500063EA398CB1F51DF608F95F5FA48BBC7E12 +:109B60001A735F2E8CDE07BD5D8657D7DD4B2B1138 +:109B7000DE050EE634625E2518A175CE58BB66017F +:109B80003BEAD5C887C5CEFCF1EA090E65703FD621 +:109B90007E49A5F8E64905FC1BB4A30ECE67D23F6B +:109BA000323925DFEAEDAEF4974C297C2E0B278E57 +:109BB000C9C4F8DD68F75BD0CFD9E72CA3BC80918E +:109BC000F96EAFD4F83B4B231329FFA63AFDE48787 +:109BD000178A38D1E8F431AD9FB36C310496D73091 +:109BE000F66C45D1189487A7AD114B21D2778D81A2 +:109BF000E2BDFD650F8614CCBF2D6224A7CF56B8F9 +:109C0000C6601E7D931A48BE17E5E5088CE7E5742B +:109C1000E3EBB9AD0AE68B2F5A02C9A80F1E43BE6B +:109C2000D7E0E5D7021F7F4FE7FAE75113978B651F +:109C3000004F04E0502F5D47F9ADD5193CEF61AE00 +:109C40001E4BF91F33E003F37B09AC39E4A4F9F2AE +:109C50007C5D82DBA0AB0B542F0DA5EFFF9E6ED079 +:109C6000C5D56D304FAF467F595988F27588E3AD41 +:109C700071FC977732783C62017FC84BFE49CC3A41 +:109C8000775FFF88FC15499F5E3F4501FFE40AF1BD +:109C90005813C4CB5A7DDFA4F690FE6D827818EF7E +:109CA0009F735AC83F94750F76A1CF96B983EDA3E1 +:109CB00090CF139386621E40651D84945558F7809B +:109CC000FAD0ADF6F4F23FC87CAB356933BEB75479 +:109CD000D441D87C7AF94964ED113FCA67B1466E28 +:109CE00018E23B44FD2678F5F7190B328C33547794 +:109CF0006C9D44A8B71E8AEAF954F614AE5F4BBFB8 +:109D0000375BD4239DB57D447934F07B2BD3681D1C +:109D1000A087E21699EFF9B67E7221F68179844523 +:109D20007FA938817236657C3EDEB7A99C4FC0158D +:109D30005713CA30BC1A3F2F05E67FB7B07FE9C67C +:109D400076AA1B795DC4B3FFE59CE1A1380AF0490E +:109D5000F53689BE6E8A17859F66ECD58F1F2FF763 +:109D6000EBFDCE90D6CF5BB9E6E3E54B79BC42ED97 +:109D7000D79F8890FE7CD42ADBAF501BEC5C04E3B9 +:109D800025B62BC18B7C08DFFB51DED85D45E4672F +:109D90001B0B5816E2636C9285F4A67157C266F4E9 +:109DA00083212E7E394DB35E7CD671340FFDE138B0 +:109DB000FD8574FDE57DBBFE60FC4EACC791CFC751 +:109DC00026AD8F18F9775EFC8EE5747D1482FED780 +:109DD000BC94C056000A9F36E9E55D5E370B7946B4 +:109DE0007DA3AD873457D7F891A9A55C27B813593F +:109DF00044C34F52CED54B835944232785197C5DEC +:109E00005555FD9447522F95D0F3BFA34CD338CE70 +:109E1000AB8C93DACF38C3487FF43F4E85D02F4CBC +:109E2000AC5FA9545723F5427F721EBB4E16AB1789 +:109E3000E555EAC5CC0CDEFFBE0C7DFEF5C1F51D77 +:109E40008790854EDB830732A83EEA58129AF07A53 +:109E5000436428F2F1677DEF37E2E4DE4EE379FFF9 +:109E6000A26DF3DF4076EDCA085E443FE8B71962A1 +:109E70007DD20DF6D088F60EEC4509E5732FA6636A +:109E80003E37E85D378EA13CDD45F9DC6457A00420 +:109E9000FB5F36B582720E12EE958B799D9AD4B324 +:109EA000763548F8B2A8217E7506C186337621C37F +:109EB000344955109F5C8E8EAEB940726055FDC41A +:109EC0005756A7C18B7E8115E242D4BB2D4E035F4E +:109ED000BF715B28FFBF4C810811F4C68294822BAE +:109EE000AE8F9B2FB9C8DE02246EADDEFEE78F93E6 +:109EF0002EEC837E1CD5C9FD06B69FDB6144C2A74C +:109F00001A7D2CFD81D8EF62FB97F894F8B5205E9E +:109F10004BC81EC6F537AC2EFD7A66A6D4B71947D6 +:109F20008B2270B741E94E42BF06F4A8D5857A7AF4 +:109F3000484F92C14BFAD7C5FDA090E06B66D7F2AF +:109F4000B5CC53CB7949F817BC35DBA25D7F898549 +:109F500037D6CEDA4BF4750B56AFBE6E41EE0B30F2 +:109F6000AA01E21BD368BF05E5A4C559E6443F67D3 +:109F7000A9EAFDA39FEA2D4CE46F83FFAE1B5F5E51 +:109F80001F03F947384A5D065D5D8DBC3A701D259B +:109F9000CE77535C5C4F3DB6EF6ED2C3AA8FAF3322 +:109FA000C5D28FB176E21747117352FE54C09B742D +:109FB000957EFBE3A39FECB3929FAC8EB484B1AECD +:109FC00033763CA329E05750EF9632F2938DB97C5B +:109FD0007CE3204675E049E5A9AC5883C765EEA946 +:109FE000F47C41869321BD8D0E43201EBF483C0D5D +:109FF0007419747CE3967CE3F9A008E540C33781CB +:10A00000787C33D0C5F515C2A1A5EF327741663C07 +:10A01000FA44F522E7ABABF1C54C1BF7733ACD5CC4 +:10A020006F36208E205EAACF302FC3FCF7190B7F2E +:10A03000CEFCC5DC2FB3709E9B69CB0BA33FD4A98C +:10A04000FA6DE897CDEC5DB7F5D37E8F7AAB3FF92B +:10A0500006B48FEF72BFF964A5BD4D817E4E9AFCA8 +:10A06000C988EF93EF1A95165A07E7F573B20EE910 +:10A07000A4C9BBF25A783EEB67467F0B3DD6FB8303 +:10A0800067987FD83BE81FEF36D27A4BFEE30F1874 +:10A0900087C0FB35E028223FCDACB287D00E777E5B +:10A0A000D0FC11EAA3591B13BC4BB08E65FDB0AFB9 +:10A0B000B0FDF92A873781F26C058A07F35FABF3AD +:10A0C0009DB46EB2888978EECE4955A0437F89430E +:10A0D000CBFC35CCF973269F87568E85795E9BD154 +:10A0E00069B0034CCABAD04A0BD0EFD196801BE3BB +:10A0F000C70ED7F495183FBA5CFEAE5B205E3CE11C +:10A10000BA7B12B63B9F96FDDDB3D20F7AF91543A9 +:10A11000305F81E7B6CC872651FD6AA1EC7F193DFF +:10A120009FF9F36BBE3A0AFD97AE5B3F09736E155C +:10A13000D5E2FBD03304DFECD1B2BDD9563510BE29 +:10A14000B7315D1ECD148D47294FD7D9EB5F3D3711 +:10A1500009E3CF59639AAB54E87FC9BAED2B4B4062 +:10A160004446B4573AFDD0FEF1BA3726D980DF3ADB +:10A1700099BF0EE3DD95EB0E4CB2DC04FDA7E9FBC5 +:10A180004F378A7C6CE8F04ACCE3F5C2C7DE5FE962 +:10A190001F187D7F983B61552827CAFFFF22F81FB3 +:10A1A000F8FD572E5C07B4741FC2145DDEA21E3387 +:10A1B000AF7B15F52939DD4379DD8D681777F33AE3 +:10A1C00065D976F376E792F8F6FECF6E2E779D8905 +:10A1D000F19F7F24F439C0EDC7FA95E4A3CCBF3DCD +:10A1E0008E3C1D74D949FE0E82BF67498DCAD5EDDC +:10A1F00020DB23B1FEC7C2E194FDC47E7F4CE8277B +:10A2000016BA3D15F978B2E0F3429FC2EB7876DBDF +:10A21000C283D0DF6311F50E98CF3691CFD8666533 +:10A22000F74F81A15D892CB803FDCF346897D0F733 +:10A23000FE1DF6687F6F735166E30A035BB0BF7162 +:10A24000999ED2D6FC683F00F7524B990E6E75640A +:10A250002A3E0F65CD2FD1E0B384CF03F884F005FB +:10A26000C3BC700BC84B67D7B5052B600A2B5D5E6E +:10A270005DDC57D13595F6A5FCA79BFB3FCCCBBF4A +:10A28000CFA8E275213D7B6C94A76096AE22A49383 +:10A29000FCEE92C047D58F27AFC3F7EABB4C8CEAE0 +:10A2A000FF77545ED11FA8C7BC9EC67FAC5723144E +:10A2B000CFD5635E6F18F6F7B619ED18F6E315F90A +:10A2C0006BCCCB65B4C6A7BFB487F5975258685816 +:10A2D0005FBD19ED3F9D9E5F6D5ED1FEF47167DF3E +:10A2E000FECC621D40E05D157837C7877340A6E05D +:10A2F00053C0B741C35FB305BF81F6243FE0DCAE76 +:10A30000C19B57E46BC7E5FB6E403FBF700BEACBC8 +:10A31000AE448A5B2A54FF247CBFA22B95D6172417 +:10A320007F48BE9074ED4C6DA67C4DCF530AD9C1C9 +:10A3300058B88A245CEB158223B33A687C40039FAB +:10A340009407E8BF53F45F3E92E4E7192E0F2037DD +:10A35000F7A2FCE27A25CEC3D73D74EA90BEF0FFA7 +:10A3600014EDDF70A223C7FF4B5651CFC1F1D617B2 +:10A37000FFD957A1671E3DAFE87A83E659DF8FDC2E +:10A38000BEED4E2238338F4692BCF0DE1382FF3B87 +:10A390003B3E4D1A8572B1DBC8142F9F37EAAD0AD8 +:10A3A000A98FD99CB7C780FECBEC6D83BEF4221D6C +:10A3B0007AF567C46289BEFFAA7BCEE4A5F02C3D86 +:10A3C00081CB6BBA11AC4D59148E6999DCCF1A1937 +:10A3D0008CEF97BEE776D07389EFA71655B14F6122 +:10A3E0007E3F73F1F5CF91DD2105E922E53A564F25 +:10A3F0002DCCE4F2383FF3FF919EB25E454F59A554 +:10A400009EE2F70F427084EFB95CDD4315F09F6B5D +:10A410000C7E17C66127DEFD21EDE3982BEA5686F8 +:10A4200060DD0ADACDA301B22B5FE0435EBFF20824 +:10A43000C680B3DBF5F52B6C0BDF271ACB57513EEB +:10A440000A09FF5DC021ECC1ED09DDBFE245C67A16 +:10A4500079966D80B3D150A8796EE7764BD201E83A +:10A46000BD94A546E5F8935D999B50DF0E73F3BC50 +:10A47000627AA1BF14E72FE512ECAAE013C3FD53E3 +:10A48000ED5C6F4C8DC3BFCF08F99CBD9EF34DE7CB +:10A49000DFAA2621DE3BDF4B4D59A2D1135B851D80 +:10A4A00094FD4A3D24BF93CF9F15FCB12D3389DA2B +:10A4B0005B5D0E91E731C4DD37B755635F897FDAA5 +:10A4C00038FFC07C435AFE1EE65674F6B5D7AE0A76 +:10A4D0003C379801BF80BF6DA65016D6ED54741955 +:10A4E000A8BF9ADD0EAA07ACE9E078AC69DF67A8DF +:10A4F000D3E027B6BFFFC8E4FEC02603AF233A6807 +:10A50000007E43BCDB397CE77679487F1E16EF5D21 +:10A51000DD6E7C333DB3C9CCEB4881BE54CFD7F060 +:10A5200072F626BD9E6E11F80FB6E23EB6F475CCFB +:10A5300087B55680A78802704F770BBD63F69B7175 +:10A54000DF6ACF538CD6F30755FB4BBDD06E0AD8CC +:10A55000CB14E8AFA89DEBE18A27C18F41B9B3487E +:10A56000BBF0D676ED78C7321D221EE1FC5CB39EAF +:10A57000E36F10F83F2FE015FAF915F9F11C9E4F23 +:10A58000D6768CC2FC93FCFE0B41FFABC15781F029 +:10A590009547E1C3FE919F983DB004FB6DFCC3CE8F +:10A5A0006C6DBF5F65727D9B6E9C39C68A7A7E3505 +:10A5B000D81D92CEE07EDC9750B337C5B982913C6E +:10A5C0001B30EE91E3D6883C24C85DC514985A51DF +:10A5D000EF3892AEEFBFA89DBFEAE6FEDC3F8BBE30 +:10A5E0009DE620CDA76707C0EB8DE2A5B3E38125EB +:10A5F00056B41347990FED84847750757712D69D22 +:10A600003409FB01F33560FC92FE332F6B45BC75BA +:10A610008D3163FC14CBD7924EC58CCB8F8CD38AF3 +:10A62000718100DAB9EEA142FF308A773F79F9D51E +:10A630001756507CC5E9D254CDE958E90E4E7767DC +:10A6400044E510F47905EAAB9A277BF55107BFDFA3 +:10A6500095570DF8BCDE2DE55C4F97F4408715D774 +:10A6600035245F9FDD3324BC82D399C6EFEC708420 +:10A670001505F7A136B760DC2DF504C2A3ADC39470 +:10A68000F0F4D291011D8744EF0FAAE6FD3581BC9D +:10A69000231FD51B9B158F427A80F2AC99A807A087 +:10A6A0009DD9C1DF637BF9B908124FF5D3A1538857 +:10A6B0003BFDEE129A87C4576675C4500FB72658F3 +:10A6C000AAFC2734FEDA61B1DE8078994AF106D718 +:10A6D000D7F5C6400EC6AD2C3381F671821D22FD22 +:10A6E00072D0CA542BF4F7265CD12E8D33CEA77DC1 +:10A6F00034E30A159263D00032EF13417FFAF65B20 +:10A700006C24FFECEB8706E23C336C9C0FA11F8BA3 +:10A71000E8C7427650D883DFE7815FA744F5F2416E +:10A7200045A17E0EDE74DD66AA2D147C89FDA1FF95 +:10A730007450999243F6B23343141771F8FBB7671C +:10A74000DD79F85C1B2F627C178D374B57DD0A3C97 +:10A7500035624247C4E044E9289FFC7D807F1CC4E9 +:10A760009B5698FF0382AF0FE6878C4908D7209845 +:10A7700037DC3A94182C69B647C77189FC8D4BD4E5 +:10A78000EFA2BF80578387EBFF9F78B8BDF8505C7E +:10A790005D49F1F33D17C5F38FED5C4FAFA88CBF5A +:10A7A0006FFB11615764DC79BB58EF80B8F3113748 +:10A7B0008F3B45FD295F1F01FF9EF05BF5E36A5A61 +:10A7C000F7BBD8352D999F87C0F5C12C51FF79FF74 +:10A7D00023D37E8A7C7602EBCC010F9F0A7E39E17F +:10A7E000F427619D544362FC3AE267053C0D020F79 +:10A7F0002717F3F30B66E1BA1CF0DF1A37F7F3E61D +:10A80000B60F1B8F749FBB4AA17539B9FE2FE95C47 +:10A81000BBC1A8CBAFCFC275B9B47F249E2AED27A8 +:10A820009E2AD7C55372DCD8B8EA93C56EDD3AC00C +:10A83000CCF642717E047F7F16F311DCB3DAB27579 +:10A84000EB88AC2DE31BEDFBC7382A14173EB3EEA3 +:10A85000FE278B2D2CA485E3D440AA9F78C41D7CB1 +:10A86000C5AD83C3C642BA7CE86827ED27B2F23C87 +:10A870002CF8E33C8E81EB263BF9EB13D09FEDCD1A +:10A8800087811E7126A35EAADCEF1E1E8D1FA49C6D +:10A89000D58F8E1F47AC117ED01A178F93938FCA16 +:10A8A000B83AD18BFA51FAE5B1DFBDD7CBBF7ABF49 +:10A8B000F26A7908E0E390364E8AEDF794FB1F8D3B +:10A8C000BF0BFBE197A2FF91F8BB627490F27CACE6 +:10A8D0005DA19A961163F5F1D0D768D787E3D5A625 +:10A8E0008B876AAAF5EF310FB7FFCC63D3F9F1FD7F +:10A8F000E153EBC72B85A807797F8D822FF24FBFDD +:10A9000047F5A4A33DDC2FF265F9133C705D25EA01 +:10A91000C95759F97EFE4DFFBDDF3D0BFDA3774CB6 +:10A92000B4FECF7673BEA97C66612B9E0F60EF509C +:10A930009CDAFDABDF59A4F86B40AED3847EACF754 +:10A94000F1F9D4FB22E68176AC2FE670E474EC5387 +:10A95000540DDFE5D4F2F7723D265D5E3C5FB4072F +:10A96000789C328ED937311DDFF7ABE81764752834 +:10A97000643FB39A19F9D559E50AF5FF9DF24DCA1E +:10A98000AC92E87CDB0C534A9CF05D9BCBE643FB2E +:10A99000F3C3ACE0351E84EF582482E672C4B12EB6 +:10A9A00015E3AD5559FE62C4839CA7D7E8CC423F5E +:10A9B000DE768CC3D7DE9B67E2F687B195C22FDDCA +:10A9C000CCFD33233BCCB87F4E76DEB5A498ECA00B +:10A9D0009C8F2B55D811170BEEB4D3FB6DE4B758F1 +:10A9E000B81FE05A5244FEBCA46B34EE1C5C867166 +:10A9F00067E1AA883A13BE7B798321EE7915E305D6 +:10AA0000DE611E95DA795C4D6FC9F74CFDE41D25BA +:10AA1000DFDB26C48FE7C112D2F3CA67D2EF21F978 +:10AA20005C6A6698AF96F85F9515B813E1C9EAD8E5 +:10AA3000A4206E3E11750A9F24F27CFC272B5E50E9 +:10AA4000D0BF7C681E731A59FF70D72F32FA6BB4CF +:10AA5000F2BCD44C7491F14A141E9E8769F070FBCD +:10AA6000B42F2B5083E337EE5E4D71F5BC2DC7CD6F +:10AA7000575C87F88678536AB9BF5E3FC342F54C8E +:10AA800095CFA844F7BAA5665A37ACDFBE83F6A7C0 +:10AA9000B187990FE5BFBE63875203E3D66DDFA18F +:10AAA000CCD6E031BB3E4CF5DBD738E47A4484FCAD +:10AAB000E958FEC63C02FA2F87AC5CFECF54DA435D +:10AAC000B83E71C614ACC7F7CE786C3E5CC79478BC +:10AAD0007F73C7AD745E8063674204AF6D86CD6ED1 +:10AAE0000BBCD776ADD987FCB42A2BB81CF192AA3F +:10AAF000063AF1FB9474870FD737BC09AC8CECF79E +:10AB000037C4C38818BE18F130979757847E813FA9 +:10AB1000AAA77AD6C3FD725C5E427D75C8C4E7B150 +:10AB20009371780D1EFF7A944B763895C6CDAA8F17 +:10AB300028587F113B6E94AFFC1B3D19DF06CE0EEB +:10AB400033EAF93AA16F2A9FD9A27CAA81FB458FEB +:10AB500091E0CBDABE49C1FC193C277D03EF33AC51 +:10AB600077CADACEE3D53A783E5BA35FE43CE2E80D +:10AB7000994E84CF7EACEB00D73311BE5E20E08DC2 +:10AB8000A567C4E3A5F1C783BB40F7CDA1628C974D +:10AB90000F1524527F52EE63E534E2E17E65D686DE +:10ABA0002D8AC14EEB2AE45F4AF8E47BBEAC310744 +:10ABB0003C84872EC243C30695E633CE1C18385F0B +:10ABC000230FEF89FEDE98FE119DABF3E4BFBD4B72 +:10ABD000FCD8007136C519EDEF9AA7A19D09FDC2F9 +:10ABE00088EB6093B88BC2D68A73A72675723DDC5A +:10ABF000D0B9439D658FF269FEE937E8BCAA868E1D +:10AC00000486F115F0DF518427964FBF293D411F7F +:10AC1000F1F829641679BE603EC63F524F1B84FC92 +:10AC2000333BBF7F41B4A3FC133CEDD1E9592BC9A1 +:10AC300045FEE9B237B0DEB3C1A7D0791D129EF44C +:10AC4000AAF87EBBD48F526F633E31A0D1EF1705B7 +:10AC50005DA11DE1712A2B403B2DE18CA5D3802CF9 +:10AC6000AEC7E3F0D3DF11DE58BB25ED79FEC69DFC +:10AC70002AEEBF917C3209E9ABE113479699E07067 +:10AC800064A9D4FFDA4ABEEEB8D6C4EDD5DA160B05 +:10AC9000D561BE7937AF0B73DC638EE0F5A06166DA +:10ACA0003D3E3F98C5E168332CA1FD68207F49599E +:10ACB00019C827498CEB41AEF79EFC0DD75BF521F7 +:10ACC0003BC5B9F5C13B6B68DD3FDDEAC37A591678 +:10ACD0003C609EE688E235968FBC3BF799711E93E7 +:10ACE0003AB8BC81DE243E8AE22FAC9313290F864A +:10ACF0005E3F2198CFFD201E479588FD81B5161F28 +:10AD0000ED2FAC15F9D612B14FB0E2A89FECC14CB3 +:10AD100041878DF6C0755998A75915936FFD8671B7 +:10AD200040DDA2DF51DCF5A0FB2DBA4A79847855CD +:10AD300027B73766713F3B5F5C2BB3389FD495775D +:10AD400090BCD59D682639B54FE0FACA7E2CC62F37 +:10AD5000648F09BE5B45E38EB3758CC7F5E2713F26 +:10AD6000579CADAC7F38E7E23E2B8CE736EC4F7A50 +:10AD700000E5F96B882634FB70A666713939B30D8E +:10AD8000104EF6A8D97C253FFB6AFDB1C81185CECF +:10AD9000F910B83CB3BDEA86CF707D675BB20FF7A0 +:10ADA000D37FB9FD8E1F7C06709FD9728B0FED7F0C +:10ADB0007A6B80F8A527C3EADBCCF3AF13303FD51D +:10ADC000D2B13F09F7ED7CF1C2F565A88FE7657157 +:10ADD0003D75FA37C645889725CFFFFA667C5E1722 +:10ADE00056D2D02F3DB3EDE77FCF827E6AB734E1F4 +:10ADF0000962ACF585D7C9DF378437F1FBDB92C92F +:10AE00007FFDE2D9D53723BE5B3B5AE9F9E96737C5 +:10AE100051FB8DE77FFDDADFE0BDFA4012ED673EC2 +:10AE2000FD9B7D4497FAA04A75E7BD7C1CAB077774 +:10AE3000ECE37A10ED37F2FD0CAE9F241F4BFEFDC4 +:10AE4000E2F9FB6FD0DA0379BF4DE469DA12B97D1C +:10AE5000F852C869DD187B1B5EBF7CD14AE76E36AD +:10AE60009ABB8B307EAF2FE17CF17D818FFA8EF91A +:10AE7000A6463B7D4FFDFC27303D5E87007F627D0F +:10AE800017BCB5E532D529FD8AEB99443612F33863 +:10AE9000D3AB8FF37D9B25CDA63A82F305FE1C66CE +:10AEA000AD7D5EB1307EDCB83ACBAECBD366754EAD +:10AEB000C9F192DC27F80669FCDAACDA60AB03EE84 +:10AEC000DFB630E8C37DEF2F9F7A6F3CEE4F78BE40 +:10AED000581946F4372ADC7E85EC344E03AE0F4118 +:10AEE0005CF1AC9013084BD36F84F98C53593A6ED4 +:10AEF000DD1DC7D81113E985ADF41CFC17F2CBBCDE +:10AF0000AF4FDF8AFECC5A53D0331CFB6913766FE8 +:10AF10000B871FBE77DACBA83FE78DDC0F5F80DFA2 +:10AF20009D6F999C8E7E3BF4DB65D2C459C09179AC +:10AF300068F7B0BF72C4D384D00CB23F5E33CD4F3C +:10AF40009EE709F31F7AEF90A87CC6E691503F6117 +:10AF5000DE775F56E55ED433F2EAEA270FC3B2F933 +:10AF6000737FB69FAEDFF47CD037A69FE3F6FB95E8 +:10AF7000E3C4B78DC8B7387EF084CE7ECF927CBB59 +:10AF8000E738F1EDACDDDC7E37EE2E3523BF7EB940 +:10AF9000D8CF3E0507B651F0DF5AA57B0EEDFFDA9C +:10AFA00063A57D7DE7247FAE3AFE39D69B16ECF68D +:10AFB000509EE0DC1ECEA7070D068AEF0F6EBE6E18 +:10AFC00053ABD2D76E821F4D72D2D8CC841FBDF046 +:10AFD0003DF4BB1A6A799D79630C1FE56FFC641917 +:10AFE000F24B0A78BD583F037ECA78DA1759CF86EC +:10AFF000A39C668DF5EFC9A6F53F1E7767D5823E07 +:10B0000081F66DE9F37C789455CA58F07791FFD2B8 +:10B010006FF2613E6C6D6EC732F48B43E3189D9BFB +:10B02000BAD6D43E06E3DBB5E3BC4EC024E06D0BDC +:10B03000F9CDACD82CEC570DF9DB8DEE7FF551BE78 +:10B040003A56FEF7B490DFD6E84DF4E139B6937680 +:10B050002B0BB89F6267087F23E017DB93C2A3C264 +:10B0600008CF59813F89C773A62E3A4FF7DC4B09A9 +:10B07000743EE1A4B19C5F53C67690FE7873CFAD69 +:10B08000649F255F3A7625909D4E559D0AE62F18C0 +:10B09000BB23414BD77651879B22EC48E12A4EDFF8 +:10B0A000C46CEE6724661BC4D52CF85C9EB712A254 +:10B0B0007CC259417FFCF36ACE6B6AA889903CD56B +:10B0C0006FE7FDA527F84B1FD2F0AFF497E47A2B7A +:10B0D000AEBF4E89C3DF3E0147FEC60544F759B5F2 +:10B0E000E23C8755DC8F60C0178837A023F1C16D23 +:10B0F000E973896EB35629F7101D431594D7947ED2 +:10B10000576CFFE5D95C2F6EB306CAB18EAF27C36B +:10B11000E1C3FA806D297E03AD0F94A6507E2323F0 +:10B120008DFB8119C20F8CCA7DA0DC00E39C7239B3 +:10B1300038BDC3BF57316FEDCFF6C6F5EBFAC6EF9A +:10B14000BCBFC9EDA1A118CFC8F563898F704BE2D0 +:10B150000CAD3EBD51E0233C98CD40BD0171829DB8 +:10B16000F2EB4E1807F3049B473DCBF304FC5CE77E +:10B17000C26C9EA71B97162847BF2CA330B090DB4C +:10B180004F3ECF587CEC13F6FD8DE9F795627CDAE3 +:10B1900078A7DD8772F7E42BCA4CE2EB90050FFB32 +:10B1A00001BEE772080E13D5ADB1A04AF4686C0E6B +:10B1B00084E3F3FD1492B346F0F3D0BF9F847C9EEA +:10B1C0004E7C1FE67CCFED9FCC23A09ED4AEAB4837 +:10B1D0007D20F50CDA37E46729178D377717217D45 +:10B1E000BFA95E3967E2727E0EF0807224E5C6F177 +:10B1F000329797152DDE4A7CBE02E45E4BEFD8B83D +:10B200000BE1C4F855EAF71F66051AB3318E3044D6 +:10B2100096D1DE52A18F1B5F5E5E146F7F90D4C704 +:10B2200016711EA6256C0B6BD741B0B6C25146D71E +:10B2300010DA23DBA2F87996966C695FFBD4A5B58A +:10B24000640FEF5B97E642DB85F2B3D946FBD4642B +:10B25000DE29B6DF87B2155D7E47C625B89E81EF31 +:10B260003F23E4A75DF0E573D932CF1BD6F1BFD7FA +:10B27000103C8E7505FDD931F9DD3F2B0F26C791A6 +:10B28000F63496FE723D06E733A5A4FFF7DAF731F0 +:10B29000B1CEA7E7C717859CD46533BAB69B2217F2 +:10B2A00049AEE63B18D5F3AC67FE345CE77BED1A9C +:10B2B0002E0FFE9E22EC7F606ED09A9311CDF7E2A6 +:10B2C0007D8C3FEB54164A009AD46D3385B5FB64F0 +:10B2D0007E86B58600C779872564043EAFC80DEE2B +:10B2E00045FE0A8DE1FBE1423FB4D2FA1438D2C3E5 +:10B2F00051BF34B1EE24C473A3B1AB08F393D5AE00 +:10B30000E03EA4FF2786AE3C5ED7C1D7CF8E897CB6 +:10B31000EE3191CFED344772BF9F1E3D9FEE02E3A9 +:10B32000755517BA0CA918F77DB8FB0F2FBE025F31 +:10B33000DFFBCAD97B7F84D85A61BBEF6770ADB69B +:10B340001803AA26EF76CC115FCF7E20F8A8B7EEBF +:10B35000A925216E3E7F6B0E7FAF2966BD7A6B0EED +:10B36000D7A7D17D4F7CBDFAC37ECEB5BA2147D4D5 +:10B370004B8A7AACD8E737E7707EDB666245EB1123 +:10B380009E4D0E5AE7672A3F8FACF6897C1FAECFE1 +:10B390007716F0F3EF7BD62864078E99B8FE81BF4D +:10B3A0003B2D15513B8A6E0AFA89B5CE50C400FA7E +:10B3B000A376A12382E760C27D7534CA5AC8497555 +:10B3C000C133857D9CD5FCE65F319F51AB32CB68A4 +:10B3D000F8EEA4BD2609CDC39CEF3E8447CCB0CC8B +:10B3E000EA76513F2ACE57F34F365EB65DC9AFD3EA +:10B3F000EF1BF9454E80E5C0FCAB9339BEAB1FE2B5 +:10B40000E7ECCAF77F23E43696DFB621AF02BC1F14 +:10B4100029DCBEC48EE3CC1DF302F253B53B60A31E +:10B42000FE1F3A4B7AADFA152B9D7F5487EB5CA03B +:10B43000F2CE9776152DCA47BEEEC9FB23E6C9F6B4 +:10B4400026505D721DAE7769D6A7FB5BEFEA7F9D44 +:10B45000CB6B46FE6DBCA410FD67EE7DF328EAEBD6 +:10B4600046B59BF862A6C54E786FBCA4D273D6666B +:10B470003AA3DDDFB6D0EDCF47B8433F1E9D42EB88 +:10B480006599709FF0574CE7632C10F5E0CEDC60B7 +:10B4900031BEB7CE96743FC67D172CFC3CA4263334 +:10B4A000AFFB6662DFB0A43FCB71E8E9BBF7ADBF8D +:10B4B000225C3596209D2B397B06C4C946A447647F +:10B4C000B8B3444BD7D1DFEA5C5B7B0ED7371F9A0A +:10B4D00079DD4F5FBEE67A69AB7C2F8BCBC787796E +:10B4E000AC76275EAF852B7CF761816897F1766C2F +:10B4F0003F33857C7C3894DBA5D0025BDCF33CEEEB +:10B5000014E3FD22C73F19F125EF3F25E4CF99EB66 +:10B51000BF1DEF83DEBB03F51EF0632405FAAB7E8F +:10B520009DFFBE005BDA4375A7BDF32A12F0BAE2B5 +:10B53000C3F5FD68BFF7607FF09E9FFCF3D7ACB406 +:10B540006F8D4D063D8C7A77412E43BD0BE3CEC403 +:10B55000F1A1DF480ABD9740F3606DA08F41E0CEB6 +:10B560000FF7125D5654029F968BF3F2BD51BE92B7 +:10B57000FC14CB474D424FC5598F6F42B862D7E399 +:10B580000112A237F1DBB7D8FF352A8DEB7F90E7A8 +:10B590001FE4905D8D0CD1D6F3493C4B3DF861A280 +:10B5A0009E2F4C02CE16F15E2F9EC5F953E985DC25 +:10B5B000BEC93860B5A0BB557C27AFD25EC5E6F3E7 +:10B5C000ADA25F6B4E92A4CB6308A7B4737DE8BDB8 +:10B5D00081D31BDE7B9CF44742CF7D6960A7EE02DE +:10B5E000FF07CF9F84EFECF85D9F7CC4586E5F9B94 +:10B5F000163818DAFF0D39A24EBBBC87AFB715C39A +:10B600007508CA1FE81DE5EAF4C3D8DF037AEED750 +:10B6100058EF01E329583F944A6AC08BFD01BE9F51 +:10B62000D7E23B76BC63F808FCBD1D39625F5C293C +:10B630002B457ADDF7EE5F1CF77AF17C72BE1FF7BF +:10B64000337BF025ECE7CC0FDE22FFFE983952D495 +:10B650006E8FF3DC1CD9B84E893EBFFF17C610FEB3 +:10B660001E4567D79935D3812F6776197D38E4CC8D +:10B67000872FBE3302FDE62E13AD1B81DFB00ACF4C +:10B68000E73C26EA0059B33EFE7F57D047EE0B96C3 +:10B69000FA49DAFF79CCC7F552223F0FFD93F973CF +:10B6A000695F700D0B1CC2F3D0BF583091FCE2B93A +:10B6B0002C48E771CF6AD39F871B7B8E6EECF9B95C +:10B6C0009880477CC59EA3FBE5F7AE9C2F97F52B92 +:10B6D000B1CFFF26F8F1CB7EEACB4F0BFE95F500FC +:10B6E0004DB21EE0D52BD70334C5D40344FD0C590D +:10B6F0000FF035AF0778555F0FF0E598F8705C10E4 +:10B700007034E1393A71FB4DA2FB5F165C799E4DB6 +:10B71000782E4EDC7DDF76BADF5F3D822D57E0A9C3 +:10B720009F7A8C845CD9BF47678F6DB9DE183F2B39 +:10B73000879E37C5D435449FF37A06991700BA52CD +:10B74000FD9CF4EF62F7C3CB7CBC949F4F1566F170 +:10B75000501E6DB5881B7C43D11FFE14FD2C94DF59 +:10B760005BBDAF7503A8B37E7443915A1095AFD8F3 +:10B77000F9005F9ED6EE3B1F902BCE6FF0311FED90 +:10B780004B147271DF0FC625633EFFE387AB74FB7A +:10B79000CD7AF7A39BA57F67D7D9731663EF67EDC3 +:10B7A0007E8BFCB71A4B80F6BD7DF6EA0FC8CECF74 +:10B7B000610117CAC9F957AFC90BFE5FD87909CF24 +:10B7C0001DA1074CDC6F4F27FF64AA80E78EBDDC0C +:10B7D0007F3458FC261AC7CFBC4E1785E61C5E5036 +:10B7E000B678EEDD4DBDF097D07919A305FC0A7E41 +:10B7F0000FF8BD495CD9CCA01BE196FBF881EBDCCE +:10B80000786DBDC1E7C5EB2D4A40659AFD9DE359B2 +:10B81000730EBE6FB0741BC5F962742E7C42145F48 +:10B82000D47688F6D23B2FDC371BEFDBF9F9C26602 +:10B8300001473057EC5BB6300BCE3BC11EF982D6C8 +:10B84000FBC4353486FBE3A1025E479C88E717C042 +:10B85000B876FBD9104ED6C99CB42FDFEABC10C114 +:10B86000B844F3BB1035B9C335BF0BC1223C5FD51B +:10B87000DFF398DF8D4815F0B50A3DE9C1F3050BFC +:10B88000E91C05D2938F3BE6D079E219F685B40E18 +:10B89000FD54D2045AA77421E2B13E7E82E61C0414 +:10B8A000789E11D09F7F903943DFF604F56D0B3BF6 +:10B8B00046F55C4A24E0BE9C163DE7D124F4CD9DBC +:10B8C000891CAE3B1379FCD69AABDF971990BFE782 +:10B8D00092CACF4938E7B258B0AE02FC93D65CEEBC +:10B8E0009F7C0494863891FFDE4BE92DFE416BCAA4 +:10B8F000F1774C8CBE2540A7650E6F8B8A7EDFDD0D +:10B90000E277BFD40EAA57D8745F8A0FEB6B9659B3 +:10B910009D9598070DE5F2FC4F93D8A70114A9DB7C +:10B920000EDF6D9A9A4DEFA557F550FEB467392397 +:10B93000BFAA0F9F7E0DFC0FF87E16DB787E438D2D +:10B94000AF0BF7ED7AFC46AA3396CFB7E07380537E +:10B95000117C81F76FA988FE2E53E1DED2FD78FEBF +:10B96000240B2A3E9E8EF412BF4F13FE7CD3DECAF8 +:10B97000DB87035C855DC3888D07EE15EB2FE90936 +:10B98000627D989FBF1BFBFE407C1FDAB6C3DE7F43 +:10B99000ADC7470688BBF1BB31369AF711917F627C +:10B9A000423F8C8891BF515179A0E7A5A2DD24EADE +:10B9B00001F1CC087F054F6FD07BE95C3E7C4CFEEB +:10B9C00071B9BD9145FFB09FAA68BFA4A7C6461F25 +:10B9D00047E510A65866F1B5D6C37B07A7F075F406 +:10B9E000116A641FCAFB28712D155736B39DF0BB31 +:10B9F000A225F286291F532D0123B62B9CCB5BB1C8 +:10BA00009F9B94085DF366AC6E4535EDCD2B14FC21 +:10BA1000161C87F2B96C1CDFDFDC3AD2E773C2A3D5 +:10BA2000E933787E76DA0C0BD54D4F53F9794C4CCF +:10BA30000DE6DF0572765735CF0B63BB5A937791CE +:10BA4000EB204720BED911C73FF0E671BB25BF6F81 +:10BA500012753EF2790E1EF40C001AF2C67F9C4B52 +:10BA6000F684AFF77E962BFCB462561CF3FB315F75 +:10BA7000901EA8FC5D7F7A42FF5CE88969FE274C36 +:10BA8000E4DF0B7D21F57240D42F75897354DE1FDE +:10BA9000C3F1FE5EE53CD21777B266D2E777B1908C +:10BAA00009F1DBABFF2768FC2318675A40EF2F4DE5 +:10BAB0009F11EB57717E95E3DE1DD43F9F2AFDDE7B +:10BAC000097ABFB7FAFB5FA7905DCC7CAEE1F2804C +:10BAD000689D52534C9D52A3A8536ADA3DFF60867D +:10BAE000A64EA9692FAF536ADC7DB53AA51E5A57F9 +:10BAF0003A620AEFC3F59623F3402400CEFDA2AECE +:10BB0000E500D6B59445F9D23195E75D817D69FDB3 +:10BB100024C769F3213FB519CA284FDB96E4F069C1 +:10BB2000F3A22B5A80EF34F959599774A49FB8B8EF +:10BB3000388FC7A96B159E270FDD6DA13830A33054 +:10BB4000A05B97C830B2A3986FFC58F8416B451EB4 +:10BB500004D7F586C135AC70FFA6F77BDCEF84F91E +:10BB6000C9187D9491E6A375818CE42194DF9FB17F +:10BB7000B7740BE91BBBD587F5FCB2FF19C14D2A81 +:10BB8000D60B35EDDDA4D6D8A37C372A4FF0AB8D8C +:10BB9000D9905F7BF37D3B1328DFF7993D704B1EF7 +:10BBA000CCA7DE1C19CAF4FC4CF7FBB36B7305BFC2 +:10BBB00098C604EE9E0DF09C7FC7CCF35E0F3392C7 +:10BBC000D7DFEC49A17CA53A95917D595AC9F8EF88 +:10BBD000BB6C52C89F3B99C2CF0D5A3A85911D3C10 +:10BBE000973A9EE8378F850FE1B940B51B4CBAF301 +:10BBF0007F1EDCA26FD7B30EB237F5DBFBF033E963 +:10BC00002DA91F1B98D7887AA8B153FF3D1BA8D731 +:10BC10008FA5C21E0C9B36B6D504DF0D3370BDC593 +:10BC20001EF6654FA5B8BB9ADB51F61C9D3775DE35 +:10BC300071CAC8E59CEBE3E151ADA9B34BC3857F65 +:10BC400075B3CA7F1741FA4BC3C5EF241C30EC35DE +:10BC5000D26FF20878CAC577D24F93FA5AD2A5723A +:10BC600024FEC603443779C2DF2960054857E89FA0 +:10BC7000E441C140891F714CBFB7304A8C0774E75B +:10BC8000E7CD192C61E4A3654A33E9690B13FA5A2D +:10BC900009925EFEB750C8887C70036BBE037FBFFD +:10BCA00073B4A5CB467EA93DF868DEF0289FB4B2F8 +:10BCB00048DE0E45C72FF4FC4CCAEFE2F28BB42BE2 +:10BCC00091F7B9BF3189811F08E3FA3FE07ED001C7 +:10BCD00085C78BE00F1EC078F1778689C40F13618A +:10BCE0001AF8DE38A79ECEB7BAF5ED89DE3E7C6045 +:10BCF000D4FEFE04489C8AF04C2AD6BFE797FA8D02 +:10BD0000E9F55B3EFB9AD7C12F3FF45DCC1BD816FB +:10BD1000B162F463C073F4C5FB7DD16DC25EC459DA +:10BD200037D99697D177DDE4BCC8FFDEC8BAE76C97 +:10BD300057FAF2CDB9838B8C6E0D7F497E7E59D434 +:10BD40005928AF8BF5D9729E2F8CDA79CE3715A290 +:10BD50007523F21DBCFF96E417F13B2137EDB64683 +:10BD6000F077704A453F3722FF9445ED7AC460F77B +:10BD70009A0B904F7C6D46635F7FDE95EA257E19B6 +:10BD800066F013BF0C67BE34A4D3484B47AB8AF0B0 +:10BD9000EF19911DB4EBF8E31DE20F05F883F2599A +:10BDA0007DECA3FE790CFF483A1E167EF4ADCC4B19 +:10BDB00071C404E14747F239FF54D9EF54F1FB371E +:10BDC0000B78BE612C2E28D23E53BD5DACB2E8F993 +:10BDD0002096BF60448376DC587EEB8F6F0620DFB1 +:10BDE00048BB987675BE39DF3FDF9CBF12DFC4F2D7 +:10BDF0008BD42B3BACCE2A3BE6B76A15D2C7C3DE49 +:10BE000019D88AED6B1AF2A90E66478A6F3F3D6F0B +:10BE1000E6CFCBBBFC46AC93295C289EE707AAB0D3 +:10BE2000DDB488AF530C3FC2EB68063ECC9F972E23 +:10BE300069DE8FFBFA9A42FCFB97BF5846FB9BC218 +:10BE4000CBC4F795ED55D86E6AE3DF9FC4F5A6EB3A +:10BE5000B1FE2DDC8AF707AFCAF7F1B094FBB5B796 +:10BE6000083EDDA1ECDC4FDFB5F3EFE61EB224D2D5 +:10BE7000EF060ABFF56631CF5B36F079A67F7A1BF5 +:10BE8000FD8EE8EC9E10F94F9F1BEAE9776AFA8B6A +:10BE90003F2B95F61CBCDE8AFA040FDFB2005F1759 +:10BEA000F0F5C8CD30C47503B83F28D7F1B0AE4027 +:10BEB0005B4770DD001E17C9F75CA97C1F1A7BDA8F +:10BEC00041F962B9CE1859C71494339CA3F003E228 +:10BED000AE3BDE5AD84CEB8DB70E90EB8DDD2A9E33 +:10BEE000A35E7AF92FE3E3E559CA06F03CD0295165 +:10BEF0002721EFD786F3E977C1762093D03EFAF079 +:10BF0000EFA92DCE056762DFDA8E7CDEF60FD8F062 +:10BF1000D3B61CC0AFA159C573D4589E42FBF6FEE0 +:10BF2000A58B459293FAC27FABCA2266BEEF8EE024 +:10BF30009FD36ADECCF74F72BD344DAA9DD18348A2 +:10BF40004EEF1474FACE00E1770C63C350DF4C134C +:10BF500074BBCB027E2BE9B576538CFC4F1980FE67 +:10BF6000C653FDFACFFAE731FAA1568C3B47F8CD1C +:10BF7000F3F0F7478D78BE3BF79F4F3DC5FDE607D1 +:10BF80005907E523CF3FCDFDC506981EF24B9FDF35 +:10BF9000E7DAA66F3774C4FE2E6C88FAEFF3BBABFA +:10BFA000253CAF7BFEA9860ACCEFD5AE7F87F2C7D2 +:10BFB000B5525F84F5FA021C0CAE2FD65D4B791D8D +:10BFC0008385FF2EE630D017586F320CEB48A1FF67 +:10BFD000A162DFFE72FC84EFD77F6800E98D09540F +:10BFE000674AFD19697DF71DBF374A1F693762F53A +:10BFF00045A9CCD70C4CA57C96D41FA5C24F611384 +:10C0000062E3C727490E8789D64F06E8E320E97720 +:10C01000C0F7E4777419EC618341EB6784492ECB58 +:10C020002C602F48947C1626F6FFC7D0F971A273B6 +:10C03000FF7194FE790C1FC838A642F0C1DDCC4FC9 +:10C04000F1D12EC107EFBDCF7FBF6D9A7D21F1E108 +:10C05000FB1F70BF53C651DF3E7E8AFC43F1532F56 +:10C06000DDADE04FDAF07728260E5A83EBE49D56DB +:10C07000FE7BD50AA7B3EBEE2379DAFCE27BF8BBB3 +:10C080002B9ADF73689D9860C175C456138F2FA6D5 +:10C090004EFAB062A6467F0C49ABDC85F85AA6740E +:10C0A0007DEF4F186FBC25CE4FDD9B4174BFD0C5CF +:10C0B000EF5FD8709D2F04B7BF3489F3A894E63999 +:10C0C000581A25E198237EA765AE31FC5A37AEC7D2 +:10C0D0002AE15DF50AFDAECA01ECBFCE1031F3BC1A +:10C0E0005E17E5E965FFFDE72943A4CFCC6F70FB40 +:10C0F000D8A324FA789E37A4FBBD9E035E1E6F551D +:10C10000E406BA060C8FDABFD8BA8363F36FA57D55 +:10C11000A9FFC5FCC9B82EAAA8FCF79963C7C53A00 +:10C1200083A59A3CF5316BFCF5838F849ECF435CED +:10C13000C1F88BB2FD1FE33C4F89B8F094581F3B08 +:10C1400095C4D7CB4E0BFD9CE715EB79E27A4AAC50 +:10C15000A79D4AD5C793F23D83977F7762B125B0FB +:10C16000544357EFBA8466CC4B64148ABA92858CD8 +:10C17000C74F7B5274E72438BC9579DE0C7C4F9C0A +:10C1800033B087DB655CC7C675E6F559C14B88B728 +:10C19000462FF3E33A2DF3769BEFC0F54AB13FF714 +:10C1A000BCE09BF3567E957039BC53F2BC88EFF926 +:10C1B000DD44D7DEF6946ED297FF072EE42C97006D +:10C1C000800000001F8B080000000000000BD57DE0 +:10C1D000097C54D5F9E8B973670B9909939040101D +:10C1E00088938D246461B261D86492808A22262C5F +:10C1F00015651B50C2964DA0FDA5D5BE0C06117944 +:10C20000DA426B5BFCBBBC01C16AB52562B0B126EA +:10C2100076544AA1D53A22286A6A4754D69044A057 +:10C22000567FF2FBFBBEEF3BE764E6DE4CD89EFA9E +:10C23000DE4BFC7972EEB9F72CDFF9F6F37D07BB24 +:10C24000B322C999C058F7ECA099A98CD965FD21F2 +:10C250005E871F031BCCD862FCCB09A5D5E657F33C +:10C26000E0EF0DA6CE6026B5B36F52185354E665C5 +:10C270007150C964CE0A3B3E9DE0389A0D4514B416 +:10C28000433F7566DB066534BD5E6185FEE68BFE69 +:10C29000D870BB11FB9FC7BB62F3DBF67FA5C43030 +:10C2A000B6C0CAD60F83F6856D43CC3003B62CC614 +:10C2B0003BD291836F4C761C8571156FB4FA4D3467 +:10C2C000F48D3F93FA968C19D951393F5A8797319B +:10C2D0005CD78800AD6B63694FD27F1531D6D36EC2 +:10C2E000716C83716ADAFE7A588175D5C8F5B568C4 +:10C2F000D797ED54182BC69AD5F7A995B15B98C27C +:10C3000006423FAD364F36C2ABC61AA479428FE61D +:10C310008A5C18EDFE09B1B4FE21F03DCCE7C546BC +:10C3200037FBC41482E72A075FFF14B5BADC1CCFC1 +:10C33000D8993B99C3028F56EDBFA3C90AF5550F93 +:10C3400030071FDD6D6063A07F01AFFEE69750618F +:10C35000604EABA8E3B07306306766A83ED413A75F +:10C36000A943BF0CE7B152F43B6CD9559AEF47D4BF +:10C37000A768DEBFBA6194A63DD95BA0A9A76E18D5 +:10C38000A7793F7D5399A69EB1E546CDFBF92C7563 +:10C39000208375D6ED53990F409BE59BA169CF7E15 +:10C3A000FA76CDF7C758FDAF27C07B2D5131790CF8 +:10C3B000F0A8292A661B96CCEB0EE4007CEE14EB69 +:10C3C000C86D5EACE9E754CC75FB705FEF0C544D63 +:10C3D000638057A35B5768FA5DA956F37DDB643A27 +:10C3E0001284EFEAE117E159C07AF60E03FCA8F5D2 +:10C3F000292E3F342FDDC2DBE577CB5BB7D277CB7D +:10C400007DDAE72B9FD6D6BD652CB3DE06EB74DA5A +:10C41000E38F02BEB2ABD855DF84D155080FE025BB +:10C4200018EFCC63AACF928CF0C9F8CD04828F8923 +:10C43000F99C7DF7EB0C632E3FBEFF9CDDE585FA92 +:10C44000D2FD77D07C2C895A3C88726AF1203A530D +:10C450008B07769776DF079668F75D0FDF58F7A8AA +:10C460000BC277D00D5ABC90702D81DF6F13AE8F49 +:10C47000E8E059B8C7DD642338B159D631083F3EEA +:10C480005F0BAB50592AFC1D0F7C069EBB7817EC46 +:10C49000B4C3E63500FE3CE3548CC427443FF94660 +:10C4A000FFABB89EF58A97E17751CC9788FCA2A99B +:10C4B000C49FE4877D29B0D6E3CEB1CF6C15BF47CA +:10C4C000BAAF36FBF3B05DF6F799CD43CF3B953766 +:10C4D000AA18AC9719FD79C40FAD8CC697701C33A0 +:10C4E00080E3F14A5661C6715E14F8FCE9FBCB08A3 +:10C4F0008E55AC7EAF1BC63BF50187EF72E6A5F704 +:10C50000966CD2C2A10FFC747003B471E2B875626C +:10C51000DD2B18F31952FBC2536953FCF63C04435C +:10C520009BE4DB9E6F0A39DA213CC7B1DE1FE2DFF4 +:10C5300012BEF08212CE9F703CC7E0D078129E925D +:10C540006FC9712CAC5E4D443AD0F13196A9DD270C +:10C55000864C620CFD473F7F021E6A8D13830DC619 +:10C560007E70F28C5D23C6618B3D8908272BDB44EE +:10C57000FBB751716D50611CF5EAE42606F02C748E +:10C58000B855DCAF6216988BCF4BACCD4D46E8EA80 +:10C590006A76DE41F834E4A99A6F0685D6A1C8759B +:10C5A00079156684FA44519FE955828F26E37AFE15 +:10C5B000FA158E3B519433B184FD83657EF2217C64 +:10C5C0003C41718EC0F166FC292301F166BD52CF5A +:10C5D00074F33BFC32F4A31A7A06E17B5398C7C884 +:10C5E000E5AE8FE4CD5F9520CDFB07CC7D1F965245 +:10C5F000BED5B2E6EBE642BDB605E4560C96517EDA +:10C60000154AD6AA8327331EC1BA015682F8BD1235 +:10C61000EB72DF9343ED5457FBD6D7C21A86C65D43 +:10C620005CBE3F98EC10F2B167246FE7FC6D998017 +:10C63000D73229B77CDAF975E01F4319FB8B1960F3 +:10C6400052807464F51A063296980C7489F3CC63A0 +:10C6500079D83FD0D5F064E87F701CD0A1124E7716 +:10C66000FC7DD9DE87EE74EB67F5B0B96301DEF6C9 +:10C6700022B30758EE1DE1EBBD0478483D6221BEB0 +:10C680000BE37DE174525933A0E35D373617059211 +:10C6900050FECB7DAA33334F33EA2DCD0934AE7C27 +:10C6A000EE4E360878013E5E029CFADF8734D28770 +:10C6B000E43E5CAA3E347E109FBF84DF75C9820FC2 +:10C6C00086E07DA3069E0CE099AB81F78D91E02D6D +:10C6D000E171BA38F014EE936A3F3818E13C2FB19B +:10C6E000E2966400C188C3C1A38A01E55DE7538F68 +:10C6F000A2FC6A555D48C3B513397FAB7D492592CD +:10C70000EF6AB3F814F87E59EBEBA4977536020381 +:10C7100035F50F9FDE75EAE0DC170E7CFFE43AAAE0 +:10C720007478B6E0EDB3F6F94E5ADF8AE4840BAEC6 +:10C730005FDB2ED67FEA476C61450EAE2F67603017 +:10C7400027346E26EE37BCFFD3988A7A845BD13BC0 +:10C75000C363102E53D4B6BD57211CD6282E0B8C84 +:10C760003BC9C2BC51B0BF431BCAD927B04725C182 +:10C770007A9703E09138DCE652011E193F542B7C76 +:10C78000D0EF3FD7AC8EBB03CA938D30743A3C5781 +:10C790000C1584676CD7473F81FE32ECF35C1BA11C +:10C7A00036DF02F38171927F14ED4F05FEF067339F +:10C7B000B3229D9952EA0F4C857E7B625517EABFE2 +:10C7C000F12A9B8C7825E11C1FCDD7219F973EBE77 +:10C7D0005D09DA42CF2735F514AE82F2E66427AD63 +:10C7E0004BAE7352794F21EA3B12CEF1A9FC7D6624 +:10C7F000EC499A114617D9021E1DA8CF013C6B13B4 +:10C80000CCEB51FE7559799DB93349EF5D63E57401 +:10C81000D11195E443B9D8016B0D507F7E3BB385B0 +:10C82000F1C328F7C06B60DDEC6D95ED80E29CC331 +:10C830003D3096E0E1E0FD083DAB8BB11B104E6B47 +:10C84000A6960D898332A189C3478F273B93159AFA +:10C850005FF597407085A1E7D546BFD961C3E7660C +:10C86000CDF3230037AF25545F7C3CED3A46FCC541 +:10C87000B51EDFBF634334F386E9552D621EFDC14B +:10C88000A536D6C88C008F5A85555CE8BD97FF5BEE +:10C8900025F8EAE7FFAEE02F09E591D7F76632B752 +:10C8A00067CAEF9FF61BD43B6B03266681476B5E1E +:10C8B0002A1DC222F4D70BE72FC733DFA0B0BA314D +:10C8C00048F0A8FDF25A7A5E7E7FA719F11EFB712F +:10C8D000C2F33551EE21AE0BC0395BC0B9F6CB586F +:10C8E000E61D14FE9CE355A8FF786AFF1D0210F0B8 +:10C8F000D6DBAAFA76C0A7BFDB67B8615B84F97E96 +:10C900002DD63F2AC148F492ED67EEAD11C697EFE0 +:10C910000D8E033E6DE370AECCED3BBF96B2E002F0 +:10C920009CFF3593993BD278A7C57B72DE2D71C1F0 +:10C930002A81F7232BED617587761FA3C5F82D3764 +:10C940000693B0FFAEA96C4E7384FEE57E8F31D6A0 +:10C950002B088FD2444F06F291EA5BA10278326431 +:10C960009EDFE0C909D15D7FFB1E8237D85D851748 +:10C9700082B799DA657F270E08BA646E9B02F4B419 +:10C9800048C8AB45DB574E03DED96BBF9CD802F6D7 +:10C990000B0C7182D5BF6EC7FA2685EC93C51EC6F7 +:10C9A0001A80EF54ED285C8F626B512263D7C6F179 +:10C9B000E7F760B9CE1492B3F47F370B978B72FC14 +:10C9C0003B1FD4EAADCBD8839FA3DE73E200E70F11 +:10C9D000A09E92FD5DF5B0B6BF65DB6F3A86F35C55 +:10C9E000A6D37F3250C103FD233545D81363D81831 +:10C9F0009403AB769C35C738FBA7839340EF69E976 +:10CA0000C82F1D548E49718F4A81FDE87E9BCF73DC +:10CA10004A8A272F05FD0D6FF3799DA93EC3E5C412 +:10CA200063F1249F2CC8CCE14FCB5CABAF09E6711E +:10CA30003FB09328808FC5C2F520A9FFA9EA6A35C7 +:10CA400006DAC77EB6260EF737FED9EB6FC0FE12A8 +:10CA50009E8D76E37A3696BAF3D15FB0B1D2E66AAC +:10CA6000822EADF03DCA0FDFEFC6BE76156A07CD48 +:10CA70009BCB8621DAB5BDEA477FCA06C3E77B8731 +:10CA8000C1FB1BAE65AE26161AA7AEADF2799C4F60 +:10CA9000D22C2E673626BBF31D61FD32A1CFD50AFD +:10CAA000D875B767FC7C3CECEFA3FB489D86F5A5E9 +:10CAB0000C44BE318AF17D66E7014E80273876B896 +:10CAC000DEDA09F28A6584EAA39A15BF09D653D340 +:10CAD000F2BC01E561F5BDFEC173512E3D63746D7D +:10CAE0000B9B5FFC9F8796396342F268AEE2207D24 +:10CAF00041EAE5B731F99343783347E0CD6D421F02 +:10CB00009F1BCDE1BB98B992F0BBDBAD2CC60024D6 +:10CB100035B7BCB998E4D54A532CEA3FB89648FBE0 +:10CB20002DCBFEFC4AB54FD9BD0AEC7B97D2331210 +:10CB30003B3989BE1EEE5FF26D4BEEDBCFDD298205 +:10CB40000E470AFD308DB9EDB0EEDA5732B66E847D +:10CB500026CB00D8C702E24BD69202D28FAD68F73F +:10CB60002C7F39CAAFC484E0C21CEE7C03FA09668C +:10CB70000C2FD8883AE961E02F40605DA66012D1A1 +:10CB800031F01D0564DFC329932B8D80E7B55781F4 +:10CB9000FE05F5D7B655F27A4AB0CA00F593292BAF +:10CBA0002B8D8097B5A38247B17E2EE547BC5E10E2 +:10CBB000AC52A13E30751D7F1F0D4140ACE1A9FF75 +:10CBC000B3D20BFD9F8C15F2DD155C80F853FBA7EB +:10CBD0000CC3C6B0F55A5339DF3A19C5DF3B99CCBF +:10CBE00016CE4078670647E23C7BF12245EAC39BBC +:10CBF000A894EB94DFB1C4C8FD3F99C2FB5F5E2EE1 +:10CC0000F49268B601E106DBE48D01F8EF69CBD858 +:10CC100086EF6F488913F0827E8A42FD4838CAFE4B +:10CC2000E4B82B50EE223F36013F0EE3A3CD295C42 +:10CC30006EC238EB689C1C0EFFDA19C3F371DF601B +:10CC4000BF8C62BF8CDC4EDDCAE707FDC6E611FF74 +:10CC50002F34C2FB7BCEC3FBC9A179EBF1A35DE00E +:10CC6000C7F2266084A4A7A5121E4D8AE6FA212BDE +:10CC7000D2AE63602A879F353596AFB3773F86285B +:10CC8000344E9380E370807BEEE5AFFB2D319F6FD8 +:10CC90007BDD61FBE556B1BD356B5BF87A18DBAC2B +:10CCA000E9E7E45ADD77254080388FB854FAEEFE84 +:10CCB0002866A5E76C5BEF77C9795C2F457DB546A3 +:10CCC000E8D5CC7B2D3915AA05D7A8D910303BB1B2 +:10CCD000BD5971FB103FD3607D08DF19D38AC4FAB8 +:10CCE0001C627D0EBE3E9F064FD9C19EA459F6BE62 +:10CCF000F8DB0BF7DEFE720A447F1ABA8ED41FD21D +:10CD0000477FFBA1A47ECBFB21E7A983672F9C75FE +:10CD1000F393F0447AA6EF72B4F828E779AE3FBAFD +:10CD20004EBEC2F14AF977353F867D44FDC4A9C5A0 +:10CD3000E79A9664C3E29CD077ADB897C521FF5CB3 +:10CD40005AAAB07387B3E1C8BFBD65DC8FEADD6561 +:10CD5000713539C9AF97995A1CD1AF47CFF5F65EF7 +:10CD600077AC9929A41769FD0CDD09AE801BF5D4B9 +:10CD7000D3CCB503FA1DAFD33BBA613F77D942DFBD +:10CD800085E489B6FE43C13FFBFA8D7A92707E45F9 +:10CD900096B2179C2EC6CA52B712BF2E1A58B63A70 +:10CDA00019EAD7A73E49FCBA6858D95974CD4C4DF9 +:10CDB000DDCEEBD9656753B0FEE476FEFE24F70BBB +:10CDC000C8DF99777BE5E4A121FDE1C654278DAB4F +:10CDD000961B18E29145BDCB857252C2B3BFB2C853 +:10CDE00062A88FA4BFCEECA5677E9E5122E4738912 +:10CDF000B4E783468D3DDF1D63F5AA00D76E94A787 +:10CE0000B0DE05A99E3908FFBAE8CE05A80ADF1BE7 +:10CE1000FD9119F521C50DFA06FA459C0E360FE66F +:10CE2000A9746EAC203D7085CB6A24780A3F15AC9E +:10CE3000ED1BE8E7E5579EB97B181FA602E73156C0 +:10CE4000D07FDD2B5F7DF121CAD1933617AA816394 +:10CE5000DB1E598DFAD5D8B6BF7FC5E5AD8DCEA9FD +:10CE6000E4BCC7A2BF119E97B45A68FE63DBB296BA +:10CE7000E0FBE3DF694B45FC98D8E16F4276D0DDFB +:10CE8000FEC7619EF0732B764CF926FBF2F58B5EA4 +:10CE9000787C6666A85F023C7EC2E171BE0AFD8AAC +:10CEA0005D0907D607494F1BCEFD98E27BD0CB33F7 +:10CEB00091CECFB0012E3C57E8B6F37EF4FECDC341 +:10CEC00095B03E783EB1076610A6374FFAD20A0CED +:10CED00024542F65B19A7AB975A8E6FD298E644D60 +:10CEE000FBF589599AF6A9CE7C4DFDA6CCB19AF7EF +:10CEF0006F76956AEAB7944CD5BC5FE9AED4D4F3AB +:10CF0000FDCD9AF70BF7B56ADB0F3A691F0A3B2A8A +:10CF1000CA519F77053C4D585ED3B9A97CA093F5C3 +:10CF2000F1EB16057D4DF87CFCF9FA623FEBEBDF87 +:10CF3000652B3C741E60C17D51C3CE074A03448FEC +:10CF40005D069733DC8F3B6FB067672AF97101ECA0 +:10CF500000EC6BAD3D8370BFA62C7C488DC17DE994 +:10CF600061E4FF6A31077F361EE5FC7C95F4DE162E +:10CF70002323FDB1654EAE0F7D7F8795E08B1F2289 +:10CF80009F9A1F4DFC642268B8B46E3C0355709F95 +:10CF90003C9A7597B2E5BA7DBA4B539FE2F8B1E679 +:10CFA000FDEB13D76ADAA73A1FD0EDD3664DFD66C5 +:10CFB000D723BA7DDAAADBA76734ED133F0D3621FC +:10CFC000194DEAF4AA7698FFB8C39BCA715FC67779 +:10CFD00078E723BD14F93D4DC442F6D4BF8EA51F9A +:10CFE000EC2AF46BBDD69848E59E4627F9A5F6369F +:10CFF0006652B9AFD145CFFFD65842E51B8D6E2A98 +:10D00000FFD178039581C60A2A9B1B9BE9FD5D8DA4 +:10D01000AD54020447A0BC881F24E40FD4D1DEEF36 +:10D0200032046BF1C4F5B327CF115FEC1A10ECC2D8 +:10D03000FABDEC2CF1C5401A233AB4A633E2635D85 +:10D0400069EE6569509E4BE5F56E936D03CA816686 +:10D05000833B1FF5EBAF9E3CBFD93882B1FBD65660 +:10D06000243A6279DD0A75DA6C34CCBCE737BB87C9 +:10D0700033F67B1419E3A85E89F5EE28DE7EEEC94F +:10D08000F3955E9A1F3F6F9E153A6FFE2A35C2795F +:10D09000F3EF8F3BEDE86F39703EC38EEB3A20FC27 +:10D0A0004B6E966F5A0465A931DF8472F1B04E8FD2 +:10D0B00090E5BF6CA5065C4FB3C1351BF514EF8D31 +:10D0C00026B603F8C50C85DBA3BD7A601A9747DD49 +:10D0D000375BC8DE3968702F413C073EFD04C2EB68 +:10D0E000AA34FB0C845FB7BD2709E1909866E3F58D +:10D0F000849E27145758DDC4D7199B163DA39F75EE +:10D100000E4E8BB0CE61690E1A9FF9DD2350FECA18 +:10D11000FAC14A770DCA8983A5EE749CCF810A0BA8 +:10D12000D18FB7C2EE4B4726677417CF0EF3BBFC07 +:10D130002ACD44FB36CBCCE98CDDAEFA7644B0D3B5 +:10D140005E48E3FA3EED1BDA73B745931E7ED0C00E +:10D1500096ED8A00C7BFA77139776A4064FFCB1B81 +:10D16000027E6533EDD45FF79A283AEFEDAEC82022 +:10D170003DA8BB1EA004F4D17DBCFEF46E6AB7C806 +:10D18000A3303AD79C2BF8D4EFDB56FFFB10BCFF43 +:10D19000D19A6817F170C728924FB78B97E70FB2F3 +:10D1A00092DE327FC68832944B73C5F9D802BB71C8 +:10D1B000301D931963CD0EE8E74E5BFE7A14FF55E0 +:10D1C000F195E658A82F1B7ED77A2C57A46D36C749 +:10D1D00041599DF3FC7A541F6B80B48AC95E0ABE24 +:10D1E000D908F35AD8A03AB9FD24E49A7BE565C57D +:10D1F00063483C4438229E027CC92E7C53C05B7E2F +:10D20000F7A680E7DC34A1B7E5B2DC6FB4E73E0BEC +:10D21000114F3AE7BF39B21F3FBDB65DE86DEF9AD7 +:10D22000F9B82B9F36F9C2FD4972DC7F88791C342E +:10D2300033B7827ADCED76C28FBC3967EF2D86F585 +:10D24000E7B5390C746E2FF9788091FFBEF8530F53 +:10D25000F1B96B3A834F1D6284E7AD4827179353AA +:10D2600033BD6B493E8C3D07F207F9E279CF478722 +:10D27000880F2E137CB09EF8D79EC606AAEF6DF4D9 +:10D2800052B9AF7183E0839BA8FD8DC62D820FFA42 +:10D29000041F7C9A9EB735CEA1F295468FE083FCA1 +:10D2A0005C7586C0A779899E7548FFF2FC7296D599 +:10D2B000634278FDE5110B53F17CA2CD42780A144C +:10D2C000F0C4A3F1182F63716C74F68D9BD1F3DB5E +:10D2D000DEFDD79DF3AE49746FC27DE98D9341FDAC +:10D2E000ECEAFEF1E70073DA919F3CBDBD82F8C71E +:10D2F00001A7D38E7AEB3369953350AF3DE076DAF0 +:10D300004D50FFDDF64ADEEE71DA2D507F366D06A8 +:10D31000AF7B9DF628A83FB75DD47D8C0EB59FDF0F +:10D320007EEB0CF4639432650FD243B9357932B099 +:10D330006B908FA57B900EAE4F5C3419E9C099E6D7 +:10D34000247C98EA5CBB07EB37656E350E72A2371A +:10D35000347F1D7E57165F69C4EF260FBF6B1D7E9D +:10D36000775DDA6663F87737E43CBF0EEBD35C5B3E +:10D370008DA80F3AD3F879A9EC47D665BBE4AF681E +:10D3800027209E8E6EAB203E9ED75A417C5CC2A564 +:10D390006C56E57DE8A7AB6B551C0ACE6396D27B35 +:10D3A00058AF800E517B1EA805F8AC7FFBE2B8B5E4 +:10D3B000188782F57154FFC5DAC87CF72F88077A81 +:10D3C000BEFB9EA053949B95D0CF7B403FBBA09EBD +:10D3D0002ED657D7B6C8BE88EC198F1DE56B761AC6 +:10D3E000978BA385DC5C28EA778AFABF6CEEB7706E +:10D3F0009C77FBA7EB0FB01DE8B68ACFA30F5D6B40 +:10D40000DB055D770838B2A29E24ACD7B04DE42787 +:10D41000BC587CD7F270FB2D19E3249A29FE421FD9 +:10D420002751CD02BCBF665D9C050B9AE93CB63521 +:10D43000EC39F123617F0CE07C6F0E326BC0BF7F53 +:10D44000A78973C7BEEBFE4AF0ABFED6AD6D17EBF6 +:10D450005ECE7C14D7A65F07F324106DADB41DA477 +:10D46000FDECBB9E60E4F5F45907B7DF651C8BF457 +:10D47000CB831E14955E8C7CD0CED07F13CE270E2E +:10D480005D804FE8F9D1B7C5E72EC06F92709E7AE4 +:10D490007E23E3B3F4A5D4E7A0EEC5F83CEF2B510F +:10D4A000E4A7FFC4E9C9C27EBACB7ABE30A07D161C +:10D4B0001F243C6B002B0F9F2B667E4E0F5F8CC48E +:10D4C0007D3B6EF0FE01F5A2921D8F119FEA42E1B5 +:10D4D00000F4E8823AF29D2D575514E0772C93E33F +:10D4E0004FB7C2E5A2A47BD007A91C9BCEE551DFB4 +:10D4F0009269E21ABBB77E95447EAC8BE07B7F706D +:10D5000098A24E087A91DF974493CAD3A930BF02FC +:10D51000FA5F67E960D2233A47988D587EDB7662DE +:10D52000E78891D4BFDE5EEC1C5A62E5E35E7703C8 +:10D5300096AD66CF964568278DB5909DF496880781 +:10D540009C1ECDE3A7DEC27362786FFA91F3F128D7 +:10D55000BFF4F666E7FE7965CEBCBE7627AC7332C3 +:10D56000AEB3FA63C37DF8EC72EDD0EA862F987102 +:10D5700010C8ED86F3CC587829762953915D141C98 +:10D5800076BD8E65F1A781B83C27DA9F527F10F6F1 +:10D59000E945E2904A7AB8BE30E93CCB3416A19F07 +:10D5A00069009DDF28257FE776AB28E5B9C8043EF2 +:10D5B00005B6C060F39953347148894628E7A9C17C +:10D5C0003158EF62013A27D1DBB37F157E28B06B6B +:10D5D00037A6935F8AC727C18E0C42FC9DF293F752 +:10D5E00017DC4D7C208AF4A15EBB76B781E20C5A31 +:10D5F0008CEE8113D1AE6D4877AD85FABF0209BFBD +:10D600007A19CA3AC717043749BFD50D67099EBDB5 +:10D61000E703C2EFBBC904F207CAEAFF56490E5539 +:10D6200033B681F68DBD665E15261759F3E7BDF05A +:10D630001F0D7CAF12014876D684996EF8AE52D891 +:10D640001FCCDBCEEBC2EE626CC44C37F453992096 +:10D65000DE679B79FB08D9FE0B5E4F97FD7D3E830D +:10D66000EA43655DF49725EBFB793D598E7792F798 +:10D670009F2BEB165EB7F3F75F48FFC34CE40B92AA +:10D68000DFBF942EE4443ECB177139EDE9C5178C0A +:10D690004BD1B60BF9B0F019D56B1E8DFB3335FAB3 +:10D6A0004DA4EF668562E7AAEF3191BFFB545C732E +:10D6B000DEEA307B45C6B15494DBDDA8FFD5BC98CB +:10D6C000B14D15F13CA87F7CE1E47AF914D546E729 +:10D6D00013671EE47CBF3FFDADAAE165CD7EF66910 +:10D6E00057156E8FE3C11D8C77FAA1215BC9BE4827 +:10D6F0000BD0F9F98782DF0D06DE5A12178A178BD5 +:10D700004F656EB457E3FF08FC19F7F8D300F1E357 +:10D71000AA3F72FF6FCD23AF93DC5BAC3AC99F5B2E +:10D7200096E3F918E1D3650F905FB1AAE1159AD796 +:10D73000992C61573A7A72C2E179A22FFC4F5F04AB +:10D74000FEA7BF4FF8EBFDCE2B6C7B68BD2B2E33B5 +:10D75000AEADCBCECF455D629F8E189C6304BC2CD2 +:10D7600023012EA7970446C6AA18741C18CCE3966A +:10D77000DE2846BBE84CBD9DE1BECF5BFDCF3C4FF4 +:10D7800004BFAFDE1EB80DC72C0EC12B61641FF89D +:10D790000EC5F12E005F6DFB770CDF21C6A0D98589 +:10D7A000E7A88719F5332670C41C1E1F337624C7DB +:10D7B000CB81ADFCDC481FF73576A49DEF93389FF5 +:10D7C000A999F1C6043C9F91F430299A35A3BF1D55 +:10D7D000F0DA25F0DA85782DF137744E03DF45A0B5 +:10D7E000AF10FE6AE1EAEE0BD7C9232F8CB7DAF649 +:10D7F000EF18AE2DA00FD3B9E6EE28F2A7E8E1BCF2 +:10D8000074243FDF92F06EB8089C1BBE2338378C1F +:10D81000746AFC1112DEFDC927FDFEC87947A0D34A +:10D82000E22BA1D3AF33847D630C529CA97EDF1B16 +:10D83000FBEE7BD345E8A9E9FBA4273DDCF465B505 +:10D8400038EFD43FDF3A92FBCDBE2B38FEFFE64FD8 +:10D850009F5FFFAAA67D61C37E4DFB22EFDB9AFA94 +:10D860008460A01CD15CFAC7AF3DDEF33AD6AFD4DA +:10D87000CFDE9F7F7DFA0B4B0D78FE5612E0FEFD4A +:10D88000C5999E2F90AFBC65F035D901AED77434E1 +:10D89000AB741EE6CBA773C0D5628E6727FCE7A3E7 +:10D8A000BB016FCE320BF93FFDAF66199DB97DF11B +:10D8B000A0F44B95B9C3F4C4526BAC11F5A75260F8 +:10D8C0007991F0E66B8137140F04F43EC7CA4CF12E +:10D8D00040E773E62814FF3487F1786A28FD1E6854 +:10D8E0009F6E647E0BD42B6D46BF85CEFD78BEC384 +:10D8F0006C3E4D663182C686F65DFC20B28367E1E0 +:10D900004398AFEA56299E6D76093F2FBCDDD66C51 +:10D9100042797ADBBE7B4FDF0DED6C9DB798C76B0C +:10D92000CBFCB50F0C97730EF8F5484EE7DD8A383F +:10D9300057564C2E8C73D57FF7D6484E67D3D5B546 +:10D940002AC6BFF4BCCD48EF967407EBDB6729E02D +:10D95000F919E3709DCCE4CF8841FD797339BE5F3E +:10D960007DD04970A92B599B87FB583759F9D8921C +:10D9700017B26FEA1ACE919E3E457DAE09DF3F7326 +:10D9800098BBC6AFE9F4AA68AF84FC97C105489775 +:10D9900017B383E4BC3B1AFD844F1F35EEA3F2ADF1 +:10D9A0006BFF5E8C7A46B03110D17F79A5FE02E91B +:10D9B00027907E03C907FE754FF910C4CB74C917B1 +:10D9C000ACCA30E40BCCC84BC92FB333FAF0D7D173 +:10D9D000191796ABDAF6EF98BF5E2A9E572772B9F1 +:10D9E000A8C76F3D5E4B7C86CF8A1518F776D0F7B7 +:10D9F00050AECE65DEDC6AE0B373966E328D57AE04 +:10DA00001CAF57D83E4D6211F2542E9F9F3B79BCFC +:10DA100064B94AF6818C5790FBB03843F81943FB40 +:10DA200056957161B9A86DFFDEF5F84F175C995CEA +:10DA3000639AFC86B57DF1F5BE8BE0EB7DDF27BEFA +:10DA400086E5CF2C500DA17C118C27463DAEDBC75F +:10DA5000F32197256F8AA1E0CC929E18D41B97B72B +:10DA6000AB8487CCE8360E057C5D2AF0B593F9DFF0 +:10DA7000457C5C3A6129E5D12D7B2C725C71AD78D7 +:10DA80007F85ADC58CEB5CB15DFB5EAD882BAE7E5A +:10DA90004EEB17AD9D70FD31ECB75617CFF36C868A +:10DAA000881F2E60053CEE42AB9FEACBAE46A6F146 +:10DAB00057769D6F247FC00BBF3DF94BEF8430FB41 +:10DAC000BF2FDEB65F046FDBFF6FE2AD6ADF4E791A +:10DAD00055978BB73F1AE53E80F396FC781EF226E9 +:10DAE0001877DECB169F17CF478B9DDCBFA9F89A1E +:10DAF000F0BCADFB2B46FEA3C5C2CFD95F5EBA8C8E +:10DB000037187BD0D7C4E30DDC2AE6898ED957516C +:10DB10008EC715856FD4933ED2EFB995CCAF12F175 +:10DB20004397CAD7A45F6FCCF17AD2B35C0107E9FF +:10DB300043E3BE6C7E1DE5E3B7E5EF96F270FC2093 +:10DB4000EEBF280A56909ED765F217BF877AC24B60 +:10DB50005111F5047326D78B667A179978BE619FA9 +:10DB6000F34073269E070AFE6FB0BA4D08A7296AD4 +:10DB7000E7AF6E45FC09A8E4DF5BF3D377FEF0A8BE +:10DB8000F3E2767F9DE32CE90DFDE9FF75069E7FAC +:10DB90005150EEA4383FB4A7D0BF27FD7DFAF78BD4 +:10DBA0004695256692FF6942C08DF3D9C2E7D3DF5F +:10DBB000FED4357CAEF12FF6377E5D7BB1637118F4 +:10DBC0001DDC96A948BBC371D41ADADF4BC5838923 +:10DBD0003D7334FACFFFEB76C57415544B909FB963 +:10DBE0008A8FEBAF8CEBB1F35880CA05AC874A0F34 +:10DBF000E3F1F78B998BCA3B451EF3DE2CCFCD9911 +:10DC0000781E61EA194CF1932F7E9D837873FADABE +:10DC1000F19B30D6EEBBD2E3BAF39D347EF7EEAF84 +:10DC200093300EE6627C614DA2DB9319E1FCF91F93 +:10DC3000A52A9DB7B0C38F929CA814B730B0C9FC79 +:10DC40001CED0B6732E143882F0ED92AF9229ECFB3 +:10DC5000E67E6CE0F124CB155F3ABCDA1A34106929 +:10DC6000E52E49F6A9586FE1EDB935B13E05EAB99F +:10DC700063A378FB5DB13EF4A3CF6741A2C78540A3 +:10DC8000A2582E629CEFDDC1DC3CDF81F5A4A01E12 +:10DC9000B6A4CDCAE3FD59300DF97B5E3FF64F5B6C +:10DCA00026E7D3A353383F1F5DA6F553DC2BF8C0FE +:10DCB000275965FF447A3A96E96EC272745C60E354 +:10DCC0002F8BC86FCFD07E3836F6C774DE28BF1BC7 +:10DCD00030AA6C03C26FA7C2E3D3BDED168A8F8052 +:10DCE0002F065784C5F5EFCD2AFF19F6F72BE1F77C +:10DCF000EB0FAEF09D266F36444F5E9ADF68B4B9E5 +:10DD0000C8FF0E0F4A685CAA3FF5F4B459EB72C81D +:10DD1000C7EF45BD77C028CFFFC2798D363366C3C4 +:10DD2000F93F6EF16D23FDB43E09FD954B9FB01890 +:10DD3000506F781FC42DE6A17CD868A5F29F6007BC +:10DD400063F92FB083B1FC18EC602C3F013B18CB7A +:10DD5000255FE683B060AC2CCBDD9A591C3A9FD38B +:10DD6000CFF77901CFDEF1DBCD34FE27591E826F6C +:10DD7000EF7EBFC47C78A8B333B6E7AAB80BE05BEC +:10DD8000FF7C86C3459E17EADB7F2BF63DAFC54877 +:10DD9000F23DAF35185315F6DEDE4C33B5E7EEFE37 +:10DDA00094F250BB1CBDF0752BB0E4E9065EDFFBBE +:10DDB000F46282EF2759EE7F225C81BEFF86655EAA +:10DDC000EB3BBFC0FC1FE89FE20EBA959E5F931D20 +:10DDD000A05B871E0E725D3B63031BF1FB9DBB5373 +:10DDE0007025C06F18A71BC42325D27AD7D27C6FA9 +:10DDF000B1F414615ECB2DDFA811E38C3FC92A2555 +:10DE000038FF18F12D210C4E62BFAE94AE7BCFBF10 +:10DE1000059E32797F07F24E27CAA1F331A8EF554C +:10DE20008AF3FDD696B4B7707DDE7D2A4B7712FE5D +:10DE30006AE8CE91C5F14496B9EDE60ADCA79DEDFE +:10DE400047D3EEB4D1BEA42DC171B3D235FEC7DC29 +:10DE5000B15FFDD72FE3E97D070E751BDB3A05E3C4 +:10DE60004FE65A5FFD0B2E69BEE3E329187FB230FF +:10DE700051D98BE52267F275187722E3E3EFC82CBE +:10DE8000DD8BA434CD55497A5A2932973079506EBA +:10DE90008DC643C1DEFA14C7204DFDFAC4619AF75E +:10DEA000A73A5335ED3765666BDAE5B8D35C859AEA +:10DEB000F746C7F5A4A07D06EB207A603B548AD3D1 +:10DEC000CBDD7DF0C66CA84F7F6AB60BD5929DA2C4 +:10DED0007DFAAE721FEE4737C0D30C0AD4F1920719 +:10DEE0007EFD4BEC4CA7FF57B73FB9D7EDBC0CFDFF +:10DEF000BF1FBD5FF2D9956DD662E4B3976A07E89C +:10DF0000F7272F4B6B17F48737BD74A13839DEEC38 +:10DF100057D98E08788311A91C0F7939FD00CF1FBE +:10DF2000BB5C7EF619F2B34121FAE82D757EB9D1BA +:10DF300066D75BABD14FFFA6CA281F4FE4F555E16A +:10DF4000DF6A08DFD99D5BEF1B1A4FCFBDA8E762E0 +:10DF50007EA91BFAAFCA12FEEFEA57EF1B5A146AEA +:10DF6000676B3ED6BCCFEE51D66BEAEB92B5F507A8 +:10DF70004BD7877FDF1F5FACDAB2C8ECA1FC4FC57F +:10DF8000ED8BC01FE47CA6BC1645717D3763BC0ACF +:10DF90003CAA2D7ADB88E7B437F7234725FFB94D34 +:10DFA00065F591DAEF12FD4E7B2D8AE2602EB7DF28 +:10DFB000F701961467F8472E47DF1F183086EFFBEE +:10DFC0003D595C0F3D5DBCF9A75FE0F9E84B8CE281 +:10DFD0003E4FC772FE9FD772CC608072F4008E2FC6 +:10DFE000798EA001E54AF7B2682FC6F5D72DB75351 +:10DFF0003CE8E8949E77ADB0F5EB9ED9FBB015F602 +:10E00000ED034C820C93ABDD681441FDA1ACBDB3B4 +:10E01000D6C1DF37BD16E5375CC17A1EC2730994DD +:10E0200083659CCE1720DE08F9823EF6BAFB58AF16 +:10E03000BC41BE80EBC7FA9E67F61F7C18F5F0FD69 +:10E040009CCE31C24E6FDFCF0DB3EFD9639C2EADA6 +:10E05000F0CBE39474F4BD6793D976413A6FA6B8D8 +:10E060009B4BA5EFA7919EB32F48CF076E82FDA9CA +:10E070007B89DF6B71A62D9DF262FB93E7755B5484 +:10E08000A24359EF6A536F40BCD5E7A14BB832B7F2 +:10E090008BE853DE1BB56AE27F66A0DC5CD56EE4DC +:10E0A0004122FD8DB34165CEB07176BE625946798D +:10E0B0006E62FEDD525EB7FF3BAE3487976B23C8BE +:10E0C0003D90D3A67894D3950AD99587DA87942181 +:10E0D0009C0E29CCEFA4BC2D1EA73C937787CF6D57 +:10E0E000745F496226C5274BFB52DA95B3DB67A7FD +:10E0F000A35EF96ECBE243B073ECC3AC541AEF5697 +:10E10000E6253DF8506CC508F44B4C17F1018762C9 +:10E110007B3A912F1F9A18ADE0793FF4BF0EFB9721 +:10E12000EB3A64AA18C1EF9F9071C9A3AEE89EB8FC +:10E1300029EA3DA537E1F9F63CE640BBF21695EB3E +:10E14000B9ECCF9C3E25DFAB53027138CFBD5933BC +:10E150004E67C177431A7E26FCAA026E461E877858 +:10E16000A97A6EAF3DFBB4C2EF457171FDBF76C2B7 +:10E17000A95FDD8A797260772B309FC5ADAFD2BDC4 +:10E180003F7A3BBBD7DEF93FF4A7F6B5972A2CA31D +:10E19000C2FCE47ABBA9574F97FADE0E1E27FFFA9E +:10E1A000C4DF74AD84FA9A1DD104C7134F58BCC89C +:10E1B000C74F6CB390FD7322AEA76335D677E5BA2F +:10E1C000BC349A4B732FDA5283F33D943FEC6F26A5 +:10E1D000BAD7E3D8E3163FC67B2C7F326B1BDA53EA +:10E1E000C746389F7D0EFD81CF26D03D03CCC3BFEF +:10E1F000BF59D023D29713540FF5B776D22396BFC9 +:10E200003094F898DCBFE38F47511EFD897D3307BA +:10E21000A2BFACD3F03CE5F130D5E6457EBC725BE5 +:10E2200014E9810D0E4FD628585FF96F6FBEB510F7 +:10E23000C77F2781E17ABADB5E207F65687F23CBC9 +:10E24000F7336DA99C0FF4CA5B1E77BB10E36E53C6 +:10E2500029EE7634C2B786C97B1779DC6D81AAB8FE +:10E2600029EFE0A1C879E4EE515C7FAC96FE9341C2 +:10E27000CC9A8874E861B4DEEE8732B6A1BD33670C +:10E28000545CEFFD4C3C5F52E25B47EDCBE43FB1A9 +:10E29000F078BFA8C8E7D8D346F1BCE22AEB398DA5 +:10E2A000FFA6B6E12B8D5FA5368791DC2D6872162F +:10E2B000DE05E56A01E7E52915B7E0FA56346F7E19 +:10E2C000F10D82CB633FFA00C7DD6723BF0D7B836F +:10E2D000C34F6FCF54593F17F4B45573CFCCD147C8 +:10E2E000DEA37893A3BBB3F370DF16AB81A3781FD3 +:10E2F00057973DF0D1DD50EEDA7780F6453FDF3EAF +:10E30000E7F60AE72BD5B88E4118EF52B16414D165 +:10E310002DA7F7231B73097ED29FDB7D22B2BD257B +:10E32000E729FB97F393FDCBF7568BFD3A6D0EE48F +:10E33000A17C4ECC746AD6753A2690176BC3E7DC85 +:10E340009F773A0EEA6178F35D9DEFDC2EFC3C8707 +:10E350000D6B7F6806FCEB6CFEA5C913CE472FF34F +:10E360005C47CE57C695CA3CDA874789F388116C5B +:10E37000443FF9B75B90CEAAFBE6DFD2F3FEF26F23 +:10E380007BF36DFFCDF36D657E6D51B9A13E3CCF42 +:10E3900056F2C3A26C789E83E7FE5AF95E345AFBAC +:10E3A0007E7FFCB1209BDBD7458322E7BBEE1FC5F8 +:10E3B000DB9B989FDF3F28E4E278017779EF97D4E1 +:10E3C000536A05DF96799EE3DB78DCE67891B70344 +:10E3D0005C80F25CFBDCEF96984D7255DECFA74077 +:10E3E0005FF3E222E50B07681ED7B21E2ADDCC617F +:10E3F000C412C04FE5645641E575AC9ECA1BD826D1 +:10E400002A6F64CD544E63012AD928BF88F7BC8790 +:10E41000E7994E5D6A40F95A746B64BDF8D445E1E2 +:10E42000E0A5FB032F170ED7317ECF5F1F780CCFEF +:10E4300024FCD6C3439FAF399105E9E2924988B8DD +:10E44000A968073B29BEB59CB9A93EE512E1501267 +:10E45000F418797EAF0E1EE591F1E29CA0FF9FA219 +:10E46000EC2C0EED5356B693DFDF20F60B0CB144C7 +:10E47000E4FFFA7D94CF8BA2CBCE3A8145389E6DD6 +:10E480009C4D79DC8565AB53A19E92BD6936E579DB +:10E490008F2F7B01F3BCD39EDDCCEBA3CB0A4D2E9B +:10E4A000D022D7FE6236E6337A44DCB447C44B331D +:10E4B0004FBEE69E2CCFDA1FD2BD639E113617AE3B +:10E4C00053E685ABA9FC7C35E906FF6B2678AFDD0A +:10E4D000E189CE46B965F5C738514F583B85EE8F77 +:10E4E000BADFCCDF97F7D9C8F5C97B6E76EDCA5E87 +:10E4F000ADA45C7C1ED0FF50ECDFB3369DF2E33C54 +:10E50000BB15910F5736640EF08DCE8089617E81E8 +:10E510001CCF94E249C2F71926C5035D0C1372B8EB +:10E5200073577636EE5356B638DF8F4F2E4438DEAB +:10E530009A529185EFCBBCE82CDC9784FECBCA6C59 +:10E540007706BEAF7F2EF3B2C7657B72B1BD2EFAE0 +:10E550003CE59B75E5BFB33E98DC374FBDC9CD7C2C +:10E5600066E22BDAFCF4EE2566BACFA9A8C2D38402 +:10E5700021CAD7CCEB1983FA31F45B929D80F7095D +:10E580000693F2E1BB8767F2FC777DBE77FB2BFB3E +:10E5900035F9ED92CE7AF3DBCFF0FCF6107D3DB28B +:10E5A0009A85E5B74BBA9174370EF3DB63B09EB52D +:10E5B00004DF9BF84E07E5B74FEA088AFCF6F7B48C +:10E5C000F9EDEEFF5C517EFB3171EFDB312BBF2F9C +:10E5D00049DE27B56A373FFF5DA5F0FBA456FD9ED7 +:10E5E000DF2725EDC265627D35FB77ACC773BE655D +:10E5F0008FDD41F75131710FAA137EC3ED42792FA0 +:10E60000A93E0FA60EED41D29BFDA477E9F361EA86 +:10E610001E2B277BB04EA747AFC816F6A090674CBD +:10E62000E87F4BC5B7B80E1BD96766D23B573DBED6 +:10E63000DAE5C0BAA02BF6D87374EE26DF678F0D2B +:10E64000225C9074B67C8342FAAB84DFE8A72C6E20 +:10E65000BAC7F8A921A4B782BE2DF2987DDCCF0FEE +:10E66000B882F1F03B637B52504FDED99EE9020E37 +:10E67000CBFED4EFFDD3CFE9EE9F7E5273FFF419AA +:10E68000FC1FEA69C70D3EEC670CCBFCF904A81728 +:10E690001F37BA7CCED07DCC17BB7758C2DF22F6AD +:10E6A000EB72EF21D6DFF72CF31FF4F711DF2FEE1B +:10E6B000239ED8CF7DC416B54D25FDE19C51732F07 +:10E6C000F135629D254EE6C37B7EC7751A35FB5F2B +:10E6D00012DCC4501F8A3A68D4F8112C4E6DFD39F3 +:10E6E000890FE27E91BEF0B6F5C2D342F04CFB0D2D +:10E6F000C15377CFB38453EF3DCFC36D84F7E3F6B7 +:10E70000BFA0223FB8DCFBBEBFEFFBBD2F769FB79B +:10E71000FE9E6EFDBDDCFDDDF32DF73DDFBF4AF350 +:10E72000BE7EDF0BF7FD447B0FB5D86F2FFC7E9BC1 +:10E73000FB7D325BF877C57EF7E00568C0CFFE1140 +:10E7400073FC4124CBE9D1E23E3869D74F30919D2B +:10E75000F5967350B91DE95FC8A90A21A75845333A +:10E76000AF0B7C7105781C41C1617E7F455190C71C +:10E77000138C391E393FE896124573BEDBF7DE6213 +:10E780009E673CFE3C8FD3D39FFBCBBCA14A7794C2 +:10E79000F6FE867EF288A41F07F47866463DDEC04A +:10E7A000EFB38B70CFF11635353C8FC843FE9D59C2 +:10E7B000D64012E27354B2273E2721946F3409F3F6 +:10E7C0008A14B20785501AF8038CF3ECC624DBAB2D +:10E7D000307FD4F603CC9381E93B8263B8B98B3F99 +:10E7E000C9399E1139C0078F288EF585F0ED3FC6D7 +:10E7F0009D4A42F964C173ED023AF7BD3A27FCDC49 +:10E8000057DCCF1F343849BFF0FE4421FBE11476BA +:10E8100036368C5E3798445EA3EEDF2F10F694FCFC +:10E82000F70B8E4017CB806FCF6FE579D42B133B5E +:10E83000851DC6EF71BD63B88DEE7F62EE4217B7DE +:10E84000C3A57D354CBD1CB979B1F8A29589273493 +:10E85000762E7B6ED0259D2786D6CDFB3FF24034A9 +:10E86000C99B230F8C203F5FA8FF2EB2FBE7D76B1D +:10E87000E38C1736BCAFC1BF45DE8F35EDC1F81E46 +:10E88000D330587FF0C5A1D7CD05F89DDE6D198333 +:10E890007406FB362B27CC0E0E3E943199EB0117F4 +:10E8A0005BE7299A4787881395EBFCA8F130D5835D +:10E8B0008D415D3C8F576397CAD2FC1AA37B727A55 +:10E8C0009401AE487E9693395C6FEF1079901D22CB +:10E8D0000FB243E42D76883CC50E91A728F3473B41 +:10E8E00014E6C6788A798AFB8945C9943F7A17AEBF +:10E8F000B36E454F1EE6DBD58D0E2E5054CA1F5DFC +:10E9000083CF23E48FE661DEFB1F726EFD01EAF91F +:10E91000C70778E95E92A79E9BC1EB664E1F2FE664 +:10E920004CFC01CF27F5FC0FECE75345F5D3FD1761 +:10E930002F29749ECADC41F38C0BE497DE97C3CF7A +:10E9400017D6EB4AF2452760FF4CE47B3D3892F244 +:10E950007EB65828EF07C6A1FC2B79FEAFCFCF2A91 +:10E96000F8B3C58F7C43FA611EC94996F702937FBD +:10E9700025FEE7169EB7150C24619E17C6FBE0BD69 +:10E9800019EC2073F33C307E7F9FDC87477244DCB8 +:10E99000195EA45F14CA13ABD97FE423E42365395D +:10E9A0009EC771FD327FA926E6558A9BD899E3A4BC +:10E9B000EF60BEB45EE007EB1482731F3FDC0EFC19 +:10E9C0005E9FFFDEDFFA4F2F09FC3A2739943F158F +:10E9D0009637B53327CC5F26E711EAE7C2782DFDDD +:10E9E00049217FD7FD23914E0AD00F1EC1CEDE2BC9 +:10E9F000E0D2618AECBFFB384789983F5790C11835 +:10EA0000FA0BE57D93EF209CD0EF749B8BFB4119B3 +:10EA1000BFB7AE6686CD857C4BF68FF7E53E7F812E +:10EA20007196A754BC89EB5F51CFFD7DB2BD5BE110 +:10EA3000FBEA7D88E34BCD2BEF7F74378CB2FCB7BC +:10EA4000B985C8A7E5F77A3877D979FEDE62D54F60 +:10EA50007004F87E80FBA4F7F35D295C2F377F1AE2 +:10EA6000E045F730F6F583032285E96F16F9FD706E +:10EA7000EDFD6616FC771860BC1661F7B408BBA7FD +:10EA8000D524FE9D1C9D1DDC12E071442D89668AF3 +:10EA90001362E2DF7590727FCDDB3CAE684D32A32E +:10EAA000769C1FEEAF12DC4B72A8F79E2A05E42B72 +:10EAB000C0EF94C3A3E6A21FDAB39AE4927A35ECCE +:10EAC0002FFA4DFF76A3B0E7B89C2B1672AD18FB5A +:10EAD000C175E40C24795724C61D63AD277D7A2CBB +:10EAE000F30AFF8EF0833CB097ECC0FF0D9F4D61A1 +:10EAF00077606800000000000000000000000000D7 +:10EB00001F8B080000000000000BFB51CFC0F0037A +:10EB10008AF92C181856593130DCB0666070B4612F +:10EB200060D86C8E90BB218E6053133F97A74CFF2B +:10EB30003C4906860540BC0888974892AEFFB71648 +:10EB4000825DACCAC0F007C87701D25FD519186ED4 +:10EB500003D97F81B803C85F03C43B805804C8BF92 +:10EB600009A499D518189E00E97F40BE34907D44D1 +:10EB70000DBBF9FFB5F0DBBF5D0395FF128D7F4143 +:10EB80001DBFFE284DFCF2AF09C863C35EF6E4C7A3 +:10EB9000471F057A0702AF474BD7E2A60C0C7A66EF +:10EBA0000C0C85D0B4BF0649BE192826610A617FC6 +:10EBB000D103E617207F258E7CF11528CF0F94EF27 +:10EBC00037C76FBF38335A7AE1C154F39609C1AEE3 +:10EBD000174295DB248CA9FEA708030300E92850FF +:10EBE00078D80300000000000000000000000000D2 +:10EBF0001F8B080000000000000BE57D0F7454D54A +:10EC0000B5F7B973EFDC9924772693106042024E72 +:10EC100012D458038C18302613B821098424E0003C +:10EC20007E34565A07E421B640A3B5ADEDF395E125 +:10EC30008F315AACD0F2FAD4767DDF40D5D5F6B913 +:10EC4000DE0A8A4A43422790502488112DD66AFB57 +:10EC5000A276D9F81AED80C1C6EFA38FEFEC7DCE76 +:10EC6000C9CC3D994942F5AD7E7F64B537F7DE7377 +:10EC7000CFD9679FBDF7F9ED7DF63963B7B988E75E +:10EC80000A422EC17F0B09F95C2E21645EFC2A9E8C +:10EC90002F729270C61C42B29C077A67E710B2D8F6 +:10ECA00050FD4B7C844C75AEED26A5840488C3E7EB +:10ECB0005008E9525EE89D4DEF8FBBEC7E0781FF67 +:10ECC000EE22643E21773BE99FB4FCF173F40AEF36 +:10ECD0003FB145082D5FAB361205BE772A7E870F00 +:10ECE000CA9BC6B22984D410F6DF8273A446A1CF92 +:10ECF0006BBC773492D984547B68AD4EF6EE12FE2D +:10ED0000BF49082D5F4158FDA6D3FABE82EC3AA751 +:10ED1000BAE12EA60667D1FA2EEAD6F7DE257F24C1 +:10ED20006E2897F0BC80F603FEA03CB88AB872DE6D +:10ED3000CBA07FDF406EB8A4D2AB3689901BE37CBA +:10ED400091AF848409994C483BFF5E23C1D9704F31 +:10ED5000C833D87EB6E0635D3FF1D27EE79411FF01 +:10ED600012CA87A9756617A17CADA8D1191F6BE7D8 +:10ED7000E7F61B84FCE083B63C52423F8F6C423E78 +:10ED8000E6703E767DF0FC9B5B806F7504F976D86B +:10ED9000EECF0D968CA62750979D46683D7B824707 +:10EDA00033B01E42FEF3D2145E4F11211DC1C2CCFE +:10EDB0005092EFC4F591AD1E421CF1FBDD26A96B0C +:10EDC0003346977B1E06731E54BF06E9ACE0BCFCBD +:10EDD00081429ADAB0DD261CA7C39CFE6EF368461A +:10EDE0007F09BC8F66D8683FC2E76CE4495A45C7C3 +:10EDF000E0A274A077BB698BC2F38E413D02FC2078 +:10EE0000DEB6BC15B346D37FF8DCBAB9D8AFD0268E +:10EE10004BBBDF1FA4FD35A07FCF642CA6F59C1F44 +:10EE2000B479543AAE7BF8F3C3A1B60C0F7C37909B +:10EE30008DE3F9C856FAF7D5A9F9F1C8822F1786DC +:10EE40000C28E7B4F263F0FC89223A6E1D7B353F53 +:10EE5000F46B3C7E7E9FB723EEB3FDD16A0FAD37D6 +:10EE600010F32BA017D983844C2A00BDE838E6861E +:10EE7000F16D24A84781E0A2B42B593FFCAA0FDE14 +:10EE80009F52413E029E28F663841EA0EF6AA0D3E3 +:10EE90008BD747797B3F8471C4FE6D4FBB8AD27B91 +:10EEA000BE4CC37AF69BDBAB34ACEF62540579DC25 +:10EEB000C4E429C717DA6607FEAF27FEB00FEA25BC +:10EEC000D8EFFFCEFBFF635E9F68A76330BB4A03AA +:10EED000FA9A881FD4A456BDAF0BBE0F6C64F4CF52 +:10EEE000B8B75901FE5D715F3F5E239CCEDDF03DFA +:10EEF0002D90DF1C53806FD3EF89E275EFB6B7BA60 +:10EF000080BECC9D240D6CC19E1A5B167CB767F148 +:10EF1000B43478EF0E52C5A7F620E0F7DCD54DFBF0 +:10EF2000B3B746433AF70E52FED372EEB0C70F7A2C +:10EF3000ED0EFBF8D5EF87F2BFE4FC38CCDBEDE457 +:10EF400074B8C3262FD75C02E5DCE1305E23BC9F9A +:10EF5000C4B719E5EE6E2E77BFB4873E077CCF1994 +:10EF6000245E42F5F9F087F5B9D0AEA85F2EFFD444 +:10EF7000E3FFF37A783F7990BC6D9F0DD7E85A682C +:10EF8000EF6AE8871BEEFBD62A68A722A847E6456A +:10EF90001B21C5713B95331C5C7A13DAC75AD42305 +:10EFA00061072A06759B9299A86735A8077BB91E49 +:10EFB000D40C46514EA89E1DB3513E853FA07A46C3 +:10EFC000E5EB70D086E3FD444C473B4C8AA3792B9C +:10EFD0005CA3F5A8E3DC86B9C06FA14FA3EDC7FF22 +:10EFE0001BFAB597F62394C4AE89F684BEC9EFC761 +:10EFF000D5374F18F5AD83EA5B18F819B4A5CD04E1 +:10F00000FD6BB5A19E786BDABA98BE6C427DCB5988 +:10F01000CFE899BA26827A309EDEEDF579AA34A837 +:10F02000BF89E969C7E03BDB1C301E6B08B71317CB +:10F03000BBE03E702FD36B59CF643DCC0CF4A17E66 +:10F0400016EC8C11B8FA7634A25CD356D250FF522B +:10F05000E86107E861E9FF3F7A5823E671CA982C16 +:10F06000CAFFFA186178C8B30FF150AD8FE3A182DF +:10F07000D76FFD2A7DFFA23D03C7F5C5C9F421DE88 +:10F08000AB110238E3CA7F5973372D5F9F23F0CF4E +:10F0900046D4EF3AAEDFC7E011D59FAA7E85CCCF2C +:10F0A0008672EFEEAEA6E54F0E103FBC3AE9531163 +:10F0B0004F750F12AC4FE8671DEF6F37BC07791B18 +:10F0C0002611D04F81236AB97E9FCC61EFBB2F12EE +:10F0D000B403A2FC49A244547A7F9CCBDFF9E2DB63 +:10F0E000FF87BB90903F6F8BCD8ED2E7FF6E8B7DFD +:10F0F000DD468BFE7E99EF69B81FE0E5FE83CBE924 +:10F1000020C70D27AE0DDDA450FC5349621BEE86CF +:10F11000EFBC458FCC2550DF47330865ED57AFFE78 +:10F12000CB7BA4102869D383AEB85E89FA443D2F07 +:10F1300078434D0A1D8F81C8BB6E18BF0F0E7E34F9 +:10F140001BAEC49884386B3C3C1610E315EBDB0116 +:10F15000B883D450B9981F978BA9B1BE63886387D1 +:10F1600018FE22759B711C2A3D8C4F5D17CEE6C19F +:10F170007747385D9DE7FAF2D01ED659EBE9B4F730 +:10F18000AF09B2FAF1FB80878DA3A0A75DD8074530 +:10F19000E025365E01FE7DB9D637690EE57FF909B7 +:10F1A000D5BF8D7E573EDC5F4392D89D889285FD0A +:10F1B000AA18B0CA67E785E32AF085D2AB02BD95ED +:10F1C000B13E95D96D2657012E5795B133167B2E3A +:10F1D000DAEF8C9D699803F66380D9A7547CEDE63D +:10F1E000FD38CAC7FB88D04F12C900FA7B28FD0F33 +:10F1F0008DF17DAD47B5D02DF4ADDA9961C1E70B46 +:10F2000087B325BC6FA5778116457E2D007E91D4EE +:10F21000FCFAB6928DF52F1CFEDBF825DB11516F41 +:10F2200027F0B164345D04845BD0ADFE9FCFD74E30 +:10F230006E67A8BFD20DFA4AFA0FA8A08FB5AA81AF +:10F24000F6A5E26625E248B02FA29F0BB95E4DBD40 +:10F2500048D06E980304CB1D8E31FB9F8ACEA35BF2 +:10F260004DEC5FD645DF4E98571719C17CD09BAE49 +:10F27000C97F647AA69C43FD322FBED7FB55CAFFD7 +:10F28000535CEF0E6FADC3EBCB5B9B912F014371D2 +:10F290005D0F54CD64FA562DEC1A9F4F4E70FB71E2 +:10F2A0009CCF33AF6E0DE1F357B66EE47C65FD592C +:10F2B000C4FB1335AA0D18CF6E6711CEFB0B355367 +:10F2C0004BE65755C4AC7274CC47F18E0178EBA86D +:10F2D000713DCCC7D43F46BCC2EB19F92E5F6953D0 +:10F2E000E6C4EFCF0A5CC4CBFDCAFF2CF3EB6ECEB5 +:10F2F000C0F9A02216AA05BED63629C4097C9D3EB7 +:10F30000AB318B3EFF7C93759C457D3D39EF4E02C2 +:10F31000BE5704825A905E6BA3B7683E57EA71E805 +:10F32000D1828DD7E1F832FDA988F5D798948E2542 +:10F330009E8246F44787351BD8C3463ACFF5A35E75 +:10F340007890CF62FE3895A3D64500EF0DEECF0042 +:10F35000FABB3DEA64B86E87C981CA51ED458A4F50 +:10F36000E78CD1FEB046794E2BD2A2CC5FA3F5C07C +:10F37000B5C750F9F3208E470FAD179E77FDF5877F +:10F380008D737300F7ABC89F00F9DAA9EB60FEF24A +:10F39000DB91DF426F851C741B6C7EEC8959E7475B +:10F3A000C4B7F455CFE0F76F5E09F323B1235E12C3 +:10F3B000F8577C7FC4B87DEF0AD03BA2FA0919FD4B +:10F3C0007DF066D5A247E57EAB9ED5974EB2DCF7C1 +:10F3D0000CAEFBF15DD05E2C9DB517DE64A1F78805 +:10F3E000C1E6DF9E08C30762BE16EF0344D66FB9BD +:10F3F0003F8B4EF9C1CE50F9043B53FD49A951430F +:10F40000EBABC9513DA097C73CDBCE82BE7C10F868 +:10F41000F53760DEAD2BB1D2DF3138977DEF5591F6 +:10F42000BEF69CEBF1FEB0D72EFA6F2C037AE02FDC +:10F43000FAFE08E97F7536AD7755C44AD78A6086EB +:10F44000E57E73DD24896E6B5CA8FAE2068CEF2CF6 +:10F450002AEDDA914DEFCBC11415419CC961F92E0B +:10F46000E0B4DE97437C877EB78048CF2F2EC6B8A6 +:10F470004E39C475C473E0A764C7E93DD221E6796B +:10F48000593EC57C9D4A7EDB6D6423C443C8D0CA07 +:10F4900071E242DB93CEF744DBABC0F897739CD0AC +:10F4A0006E6FCB80E795E798FD2443D949F18D3CF9 +:10F4B000EF13F2359423C14FE209939CF9C8C7A416 +:10F4C000FD127C69A5C37209F00EC749F87112FDDF +:10F4D00096BF9F02FA4DFBB3B8E9408687CA5775BD +:10F4E000CC86F2D561EC41FD6CF7AB5C1FFB2F25A0 +:10F4F000CA674353D529880FD2F204F4B7C3B80BB7 +:10F50000F537781DD35FAADFA88F01AA8F897858B5 +:10F51000C8BF2CEF03247CF67A68977CF4DA2AC003 +:10F52000C10759BBB2DE53BD433D3E4FD4547A8E22 +:10F530007AD943F532593B97AFE73613DA3F7FD09C +:10F54000C570F7283D7FB56612B4E754587B9FB16C +:10F550009E1FE1FA23CBF7687D5F6480FD3F6FC893 +:10F56000FACEECDD62D7BBAFCE66C52D7AFF59E986 +:10F570007BA0789F0A5049E8F178FAFEB7EA794A09 +:10F58000FD9DA07ECBCFB7D814A62F29F433AEF7BC +:10F59000612CB7C3458A213ED6AEA4FBB717809E27 +:10F5A000B3788D5C3E5DE5F51267F80FB43F6BA94B +:10F5B00053964959BD99F4CF808156737DA8775BE6 +:10F5C0006CFD53E0FECF2436E55A15FC067208E2C6 +:10F5D000408A49C8BD9424C5E7216BA8A3D5A2865B +:10F5E0002ED968796520FA890203790FF101AEBB43 +:10F5F0005A09D954FADC41F963D0F2443B83788F3D +:10F6000022201CA7E55C09963B8D28C6CFCBEC8356 +:10F61000FD426ED05F5BE379EF5A5A2F892A97AE8D +:10F620008DF7F3297B24CF6F403F233FDA02F1A609 +:10F63000C774FF93BED1FDFCC426FC9FCBEBE7272C +:10F640005456909F36C6CFB02DDD0FF12CB97E53A6 +:10F65000BDECFACFA6D36B05F071CE683E2A839439 +:10F660007FC007ED3F2F81BF57E16572A5FE593777 +:10F6700021BE425467E4CA2474ACE774B4A8E66CB3 +:10F68000E0B75ADD86FC390CE36F00FF72C8371211 +:10F69000E4AB52D5B17F6A0369C67985446D6037A2 +:10F6A000C61B0FBB463415C6B1EF12DADB164E9FF0 +:10F6B000833E37E6A61E2FB5C11F8BD271227F660F +:10F6C000E37478A9552EBFC6E9FF32D0358F992152 +:10F6D000A8BFDCCBEC90FA27BD3992448E7708FEA8 +:10F6E000737EC9E50FDFC2FA2FCA7F87CBFD372FA4 +:10F6F0005FFE574F2D4A3D6E42DE95C1E3A9C6AF6E +:10F7000039D9FC364BB5713AC2CA44F4A15265727C +:10F71000A956D37183FED55AF9F86DCE8F55BCDE4C +:10F720002F2A6633C8C3D54AF06E15DAA9E943FD1E +:10F730002B847AE8F36B89790F3CA7EFBF01E5488A +:10F740009DF53D7DFE2D7CDED487EB4AE279976204 +:10F75000FE23FFEE9FB05ED3FA9ECAE156784EE5D7 +:10F7600085A873E1B90FE9A172429C602FF6DDFE16 +:10F7700005E02BFDFE7EAC9F9CB17C6F070391CD15 +:10F78000AECA5C767D1CE48EFB993B9A4CE4AB4E92 +:10F790009AB91FCCE6AD057CDE728202C33CECD187 +:10F7A000715ED4D2CC48945EB33D5113E278934855 +:10F7B0005F18FCA8D5D27CDBB4C63ABF7C61BD75AE +:10F7C0007E59B329CF72FFA57B8A2CF7A1FBAEB57A +:10F7D000D4B76EE7F596FBF5BB2A2CF71BF6565B04 +:10F7E000BEDFF8E306CBFB2F3FB1CA72BFE9E95B8E +:10F7F00093AE4B8AF9EE41DBDB9BC01FDB01AF12FE +:10F80000E60B2DBEEE686338CCFA1D153F9F361F00 +:10F81000CA110C29C872AA49EB96AF8FE8CFDD96C2 +:10F82000F9F668B820C74B596A166806C6DBC26687 +:10F83000DFCC29F1F9BCDA47E76337F8E1C9D757DC +:10F84000355EAE8AF457C3B8999AB59CC6D7590DA0 +:10F850007F0CE329F23AABE663F3B44CEF19D5958C +:10F86000037689D6EDC3F555237B42EBABE3F68FE8 +:10F870005AC209F58FB75705FD2C4ADDAF05A531F2 +:10F8800015C89B68BFE2745A718F58DF5EC68A92B2 +:10F89000F282273280DE653E86874829C3374EFADA +:10F8A0008FCDB38CFF0DBC7CF01E8F1DE2C8C11A3A +:10F8B0002B9D0D1C3F513DD4C04E94174BEF81CE74 +:10F8C000D950CE8A93BAB93CAA1A5FE79E4FE6E3B5 +:10F8D0003870BD5D21F4B696C5278827F9FA77FD03 +:10F8E000302D84819888256FE06471513A7CB7ACE3 +:10F8F00095F81C149F3C386F9B6711D5FF46D3EEDB +:10F90000AFA3A5ABFD2C1E5E6FAAB8CE7B4531BB65 +:10F910006FAC51224B287DF5A13E8CE735AE8F6C44 +:10F9200083EBB48D510DE990F8FAB82F926553E34B +:10F93000FCCDE3FCCA137CE57C14767CDA26EB383C +:10F9400036965AF9B59CF353E6F372CEC7E5121F0B +:10F9500045FCAC44E3F22CF17119C7A1CE794563A3 +:10F96000FA758FF33897901F4D9AD784FD1899DF59 +:10F97000B8FCB6801D079CE7E13885CF7B55331571 +:10F98000F4836ABD0AF2B776E63E4B7C73C9885CA5 +:10F99000323A6BF97897E7BF8A71CDCE1C3EEE9470 +:10F9A000AFB5F3E372D83093E563ECE4FDEEE038F5 +:10F9B000BA9DC72D5BBC67D4C4B857C78CBE7C3F0B +:10F9C000BD7FE942DF9AAF517A1AF3157F1DB41B50 +:10F9D000E271565EEFE1EBB6E5037D27CEF561DC23 +:10F9E000E7A59CA231E38802BFCBF250EE0FD6C050 +:10F9F0007CB224FA0B15FA5F1EA36C53002747351F +:10FA0000C05F8DDEBB358C73E5DFA541BCB1367FB1 +:10FA10005F35B41B20A1DD5510F7CAB1FBA33E88AA +:10FA2000FB8477BA419F4B985E6EA4FF12F552D0CB +:10FA30005D31D8AC019D4B7C92FFC2E5A8D62B3D31 +:10FA40009FB904E52820C9D13D420FAF245726CAEB +:10FA50008F8817E8E70AB91E26971F310EFFCEC719 +:10FA6000E1773C7EFC268F7FBEB1D587D75F6D2DB9 +:10FA7000C6E73D5BFD78FFFAD632BCFF358FCBBEC3 +:10FA80000A71568C930679BCB509EF7B79FC54C892 +:10FA9000E7037CBDA356EDC0F860833FE4F424ACDB +:10FAA0002B3470BA51A4015F9414255DBF75CC3816 +:10FAB00084FC3B3322FF04EDC0CAC682FD0F51BE59 +:10FAC00038BE434280171D477FA15D45E5BAA1AE10 +:10FAD000C0BE01DA0BB769D7D3FA1AA2BFD08AE049 +:10FAE00079E375F6DB93B42FDA49D5BE6CB756D5FA +:10FAF000A9921F2AD68F4261E8E7D458280AF40554 +:10FB0000BCBACF9104F777E56EF0825CB59C0B79B7 +:10FB100041AE5A72D93A032059901B9DCBA9281F98 +:10FB2000F05AD7D7754E77077D0EF476C4C65EF7C8 +:10FB3000167A20CA55686DAAC748DD3F397EB4538E +:10FB400049EE8F5ED46CF89D1BFA4FED37B5851AE0 +:10FB5000E8198828D03F958A0DE8976110B42F19CD +:10FB6000FE10B7B7D6F939AB2C18AC827239C4BFC6 +:10FB700004CC96D1EF05B951CB16BF0FF327294915 +:10FB8000B0C7E0CFC8FE7CE2BD8A262AECCA86ABAD +:10FB90005C8EF1D7E022D47A1DA3EF7B03D6F8AFB9 +:10FBA000C1F95BEE3BF11BB097DFF3DB58B91CB634 +:10FBB0004E7ABE6C1DE2AD728EF71D6437964F27EC +:10FBC0006D78DDC1F97DBEEC0C81F95BD5281ECEC8 +:10FBD000017A9C9130FDDE2DD96DCDB0F25BA13C58 +:10FBE0005903B87940B3F8114A19B3DF4EF0C3C1D5 +:10FBF0003FE1B824EEBF85C82560FE0471D24EBB3C +:10FC0000D5CF12D7DF6ACC0FB1D9A5FCB6FFEBF97F +:10FC100077FC33E59FF0FF46F0DBB13B09ACA788EA +:10FC2000FC3E51FE57521C49CF7FBBC64CC2F72A3F +:10FC30003BE3FB7576096F05E476D2C2C04F9DFAAF +:10FC40004969CAE87A52B54706E68E138FDAC6FCD0 +:10FC500044CDC3FAC7F373A8BBAD58FC0EA7E905A2 +:10FC6000BF6FD4F75E9B454F47D3CDF8F359D3BB55 +:10FC7000903A9A705D2EEC7019C3892B7C1427D2B0 +:10FC80003F57184C4E4F572991ED28A7A6C58FAA6C +:10FC90002B5BF23EDA25EA67E8F339FEA6F4B742B9 +:10FCA000BDB49E5772C57723F6C47669CEE87A82D2 +:10FCB000350CF790F0CF9726C60582545C8AE74250 +:10FCC000BDEC7B5AB4EB52323AB8DD0A96DDB5DCB6 +:10FCD00070C3BDA93C0A38AE24011F005F673AAC6F +:10FCE0007C96EC5FCD28BB67B5B78BA9FC1EA2ED57 +:10FCF000D4A9CD8D35B4FC923DEB0EBE88E408FF4F +:10FD0000C297B4DE53F0C78D80F6AC7885F8599E63 +:10FD10004575D887EB822B7214122900FAAD742C2A +:10FD2000CE97FCAB1CB91FBB711C8F6A741EA1E37C +:10FD300075948EE36EF47B93FB49C27F5B583084ED +:10FD40007E92F0E308F7E33CF45F221EABE4E5AB00 +:10FD5000EEF169B07E5025C58F2B47F28109FA4933 +:10FD60000B8995DE4AEECF554AFE9CD0F79F0ABD1F +:10FD700015FE2AB78737093FA93239BE10D70E2999 +:10FD8000BF8DE247B3ED32F4800055B4BD4632C2B8 +:10FD9000278B7C75155CD516A57CBDC99FC6F2AFB7 +:10FDA000299D9AB0E7C82786B797F3F237F974947C +:10FDB000FF804741FBDE384E3C2250C6D6555E36AA +:10FDC0001496371826AFE17A11A7A786FEEFDEB9A1 +:10FDD000D09E552EF27D7DD59939306F28FE0819B9 +:10FDE0002DAFB57C5CE1FBFBB2C14FA1BE7636AC5A +:10FDF00067C8F1883E0899527F9CFA4A05A3FDF92D +:10FE0000057C7CABFC04C47E943FBF808FEF8251A5 +:10FE1000FEBA1567BF1C7B07F3ACCE9728B82ED26D +:10FE200055F031FA09629D26CEBFE3E84F05CA3E80 +:10FE300062790323FE08AB6FB9A8AFEC18E617DEB2 +:10FE4000EF3986791CA74FB0F5EBD35ACC007F640D +:10FE5000A9C05794A35191FF5E007912ACBE28CF80 +:10FE60006778D9F96A06D84D9117D21948BE3EB7BE +:10FE70005065F16371CDD7198E2BD6D9FC23EEC511 +:10FE8000F88EC8937AAA94F97BDFB68CBB5C3F945A +:10FE90006FC2B85FB42438467E41A3C4678F6EC575 +:10FEA0001BE3E15AD14F990F723F47E98BCEE260D5 +:10FEB000ABEDE6747D72BC1D31DFC9E5573893E7C1 +:10FEC000CD549559E38E72DECC6A7BA804EAAFD696 +:10FED000949D993EB46BA84F472F1A8863CEC78E66 +:10FEE000EE8461ED196271CF4AA2F23C1AB311D6C9 +:10FEF000D3C43E871A1EA790E918AFFDCAA17EF4AD +:10FF0000B3AB866335207F3705BAD0AE2EA37675A6 +:10FF10005212BBBA581DDC3909F4D7AFA07D78F96D +:10FF2000ADBE9A494C9F313FD5AC2CD226811C786E +:10FF300092C7A116703949A577F4430D70C344F5F3 +:10FF40006EA53E82836EB85434FE38A59287F3B115 +:10FF5000F35F4B161F15D7EA14E3BB8548FCEDB0E1 +:10FF6000C695E57A449C87A81DF9A0CFC2FF95CB22 +:10FF70007D5B67F1FE9E597790FE04BF4ED803BDAE +:10FF8000ACCD80F8446FD9D8F3859CAF5645ACEB27 +:10FF9000CED54EEBBA73AB66FEA36EC1496B99BF6B +:10FFA0005AB616FDD5E5250EF457BB66DD81FEA9D0 +:10FFB000F0AB5B6E3C807117914725FC5399EEDEE8 +:10FFC000DC670C28371EDDC28FEF74B03C20F0DBFD +:10FFD0007DE8B7BF8DF94572F9430EC6AF2735F3FB +:10FFE0000740FF4EBBE95D0BEB87B31CFE27938CEC +:10FFF000C31B0EA6DFBD29D6514FC382C664EC07D2 +:020000021000EC +:10000000F2419E6F841F2BF60D4DF532BD6DE07EE3 +:100010006C45C95AD4C72C2FF55B816F7EE6B79229 +:1000200041AB9FBADCE8CB83F197E73B7588FBB522 +:1000300013F45B1F48637214F210A797BE4FD328C6 +:1000400034A5F3E82E75D173C08F07B208FA03A761 +:10005000B3F4C8FE24F18617B9BDAB553759E4ADEA +:1000600092E312BDA6DF8078C0E9A1B1F3F21E923F +:10007000707A6131A972B8E11AAB027ED07BD3816C +:10008000D718E64B7F77D686C264F5ED6FD592CE52 +:100090004B6FF1715BC9E7BBAC3A169FDC52A263B0 +:1000A000BC776ADDDBC7514E1BB99C2E7360BF7BEA +:1000B0006769382EBD3716B4C17A65EF2C27E6275D +:1000C00074CD7AE1ADBBC1AE96297CBFD9468BFC1D +:1000D00056525C9D0EF57B55C42B5BA8FF920EDF3C +:1000E0007BED0CBFF03C90CD7C4C4F1F64F8E64399 +:1000F000816F381F5709F96F14F1502B8EA2E6C497 +:10010000B24E43F8FAC312562DB5534C1F3E6C64E1 +:10011000F1CC2DA2FF870EEC043D6CE072D475612A +:100120008317F5F5D0018CA7B5CC5A8BF1A3AEDCC3 +:10013000B33ADC6FF6BEA7C3BD8C33C4386F297BDE +:100140001671482F1FE7CD1077A7F2BFC4CBF0552B +:1001500074CAB5769F11CF6396F1DDCA681AF67F2F +:10016000D5451BFA9D2BF9F747A6FC4987EFB64406 +:10017000A91E53FBDEA0F5CF00DC9221E1C50F9F45 +:100180003B900FFADD33FB8F58EE8AB2B75B80EEFF +:10019000696507308E9F77E8407736AD7F7931F11A +:1001A0009BBED1EDD7F2F9694B0EDB07B1C51F0934 +:1001B000C33EB00F8608CE4F0B9F3B56ADF892ADB5 +:1001C000B79804708858AFD1BC7CBD83AF3B908B8F +:1001D0009794C4F16AD0424EB0BF2D65AFBA81DEAC +:1001E000C283EA5A90EB9AE7AEFF22C81FB9D1E169 +:1001F000B992F6E703CFAFDD5719ECFD1DACBE0594 +:1002000021CA8F869203F91B668DB62B237A53F28F +:1002100097AD214AC7E9A52FE4035E7B95DA5B1F02 +:10022000B4C7ED95EC272D94E6D3C090B4CE24F559 +:10023000D7A5ADB8D1310FC6F347DE820479A2FA53 +:10024000BF0EE8DFFCA8D303FA9275E8155D05BB85 +:100250004671FB920479DECCE5A5C16076AF6516E8 +:10026000896C5740CEDE6BAC007D7B5165FB500E38 +:10027000BDCDF23EA579A197CF1742AE7B73DF715A +:1002800083DC7D7890EB47D8A624C6918CB2D8CD7C +:10029000301E823F1D929D0990E4F3C22907C3A935 +:1002A000951A7B6F50BB0DEBD4F27B13FC28C04139 +:1002B000DC9F12EFD73B18DE15D7CBC82BF8E177C0 +:1002C000A8BE77ED3AEABD1DED9381787DF3A103D9 +:1002D000C5B00633E5E0811A9EF78DFE98CAFB395A +:1002E00095F8D03E2D379CB87E20CBB7BD6C5F14FF +:1002F00060B3989FC111D7A6C4ED869A187F48E2D3 +:100300007F91B0F9DACC843C2C3AAF13B01FD55EA4 +:10031000167795E524ABECC04E361F50294C58C7D4 +:1003200095E5B6C10879617D9AEACDFB6C3D93CE27 +:10033000531097501BFD389E5C3E6DF41FCC7B190B +:100340007EAB7CDA8B750B4E91E978C4C1D7C5388A +:10035000EE17F37296B71FE95B6EB4E543FB53BD2E +:10036000FDE86751BB9E0F572167C24E8FC8DFACB7 +:100370001BEAC14E815CC392F7E9B2EBD3C1DE3513 +:1003800078193E21521CBDD73BB69FD12DC9E369D8 +:100390000FF3AB1ACA48BA2713F49DC59B7A1FCE38 +:1003A000DE9791108FDB630FFDAB6372FCDE5DF2B5 +:1003B000F97A8F1BEC0BCBC72AA766CB5E148F6331 +:1003C0008A78A958BF13F1D15171CC922ECCD7B2F3 +:1003D0008B3C0ABE9E372A8F6782F9678EED6D9A35 +:1003E0009FAF93200E6BE4F1B7A1B9E3C441B70905 +:1003F0005C76DC31797C5CF628F72BDF00E341AFDB +:10040000B7383C783520BF8492DA9B961CAF1DE04C +:10041000F8E572F4F3840ADFB176DE7458FD4AF130 +:100420003C8E83991E4C2D3BD09D88832B5B296F7E +:10043000E838E9AD6406C94C2D77CB47ECDEB3163E +:10044000F91AC1C5E3E061215F83AAF967C7BCD48B +:10045000E51A381DA9DEB7CC723441FE142D47A62B +:1004600066B2EBD5F4DA3DFB40BE8D3E3F09B82BBA +:10047000818EDEC70E613F5ED6D9FE97DE0B1B0A6A +:10048000611EEFD24CE29C3771F991F5C939CFF476 +:100490006DA3FAD799EFC4FD7E9D5E86375E81928B +:1004A00009F2B45E0F799C93718A304936377242F3 +:1004B000CEC168D64C6CFFD66D19FDF70413ECFA6B +:1004C0002E78958BE70660BF1ED4FB31BFE6365A07 +:1004D000BB83B673CC50A7ACA3F7454E66F78F85A8 +:1004E000ED16BE886B9193C9DD7A3D58047492B6BF +:1004F00066D4B3B58A1A04FD27FE89C5E576B4270C +:10050000CF132D8DD73F07EB3F48EB07DCE0E771BA +:1005100077E2999234CECEFB1D25A40EF4E57B59EB +:10052000563F739693E9D99C78FD1589F5CF7132C2 +:10053000F9A7CF17E0F3A7D9F35CFEBCAA88E5A919 +:10054000093E8A7A6BE3F5D5E27787D877939D7C6D +:10055000BD80D32DF0BD9CCF74431A1B8F2AA17789 +:100560009A8278BB9CE26FC4F7DABE6318BF73F25D +:10057000FD91690E7CDF916B477CDFF10941FCD96D +:10058000E962F1C8AE0B676FFD2ABDD78689251FCA +:10059000DCC165481B7A0AE36FE5F97C3F1BD7573E +:1005A000B16FEB486CBF655D55ECF3E974F23C0C40 +:1005B0005EDF025E1F9170BBE897C039ED7C9F4EF5 +:1005C000B9E8DF407407DA958128F6ABD2C3D68349 +:1005D000BBB2BE81FEF503179ABD8971C1AEE9C7F2 +:1005E000D9BEFD7C4A77499C2E8DE3B1F261DBA632 +:1005F00003C00F4DC18CEDAAE88B1905B4FF8B4EDB +:10060000A8FE34E8BFE4672CC9E779D41CE7A6C28A +:10061000F5BF54623F80FA6D19178B80FE2353FE9D +:1006200055053C5A1E7D43059C5EA9B1BCDD851273 +:10063000FE6887F33A809EBFDA2236DAAF9EF3EF88 +:10064000A9307F5C311CC17E4F1BEEC3BC89BC014D +:1006500016DF5D30534985EB7764421E868FED735C +:100660002DF7EFAEC9867A87F8BEE5D8F94940D7AD +:10067000685C6FC529015F15F67B04E7E7B3B8D264 +:10068000E5E2E94AEED708BF408C3FE503EEE36AB6 +:100690001FBEDB09F36315E76B61BE8DF907D30B52 +:1006A000D7A07FF089EE817CDF073C5F77A27F4097 +:1006B000DF837F5009FE4126C4E5FAF236B846F7DB +:1006C00047C853E1D0C75B43B4FC11FBEB79806BA7 +:1006D0008F5E782A0FECB2C80B17B85E9477695515 +:1006E000CF83BD16790802E73B04CE8F3513D8CFF0 +:1006F0005F396CB3E07C0797AB4A83E955FB5F0930 +:10070000AE7375BDFF5E6F01FDBEF34516879E1A81 +:10071000EB5713717E39E777E7277D78FE8890FFE6 +:10072000CEF7D939221DF97C7F0AC7F98B092BBF77 +:100730001870BEFBF271FEEC3466774C8EE317F353 +:100740007C54F1BE9FDB7119DFCBEF2F17DF138EC7 +:10075000DFE3B8D82AB75DBB0A713DA5DCE364FBD3 +:10076000CD0662CFDE45AF5362A127F600BF2FA6AC +:10077000FBE13307F7BFC6CDE794F0FE5412D79BD9 +:10078000287D9495DF8F7A5249F504F6938FD2072E +:1007900019FFE7C78E41F90584E955F57088AD8FDB +:1007A0008D83F72B8DFE3CC4FBC38BDF677EC3D8E4 +:1007B00078DF94F297EA663AC6F64FD3AC786C814C +:1007C00088770C37B378E47033C623170C717B79C4 +:1007D00081D94B319E0F70B913F65CE867E785B39A +:1007E0006A28C16E8EC8F730DB872BBEEFCC6778E6 +:1007F000FF275A1FEA73E7D0DCF4C438958CF73B27 +:1008000001EF97401C89E2FD39A0BF04ED5E27E0AF +:10081000FD04BDA578FF9AB404FCE61E5A5DEF8185 +:10082000F5E009E613083F7631F8B1D909F152A78E +:10083000D58F4D25DF67F9FC1DE7671F9B7F86FB82 +:100840008E25F253E3B8D60178724E7CFF7A672A80 +:10085000BE7E62DDC72CF2B53B8727E637515C5B75 +:100860009F363975B94A4E47AAF70F5CD011D702A7 +:100870001E9F3A875DAFA6D7EE8FFBF212712D3126 +:10088000181EEB7CEC37B83FB8338BE2D992443E6C +:100890006F1B077FB0FB055E3B5F87B1E20922CD8E +:1008A000FFED2E260747291EC1F848DAAF908F1DAD +:1008B0009F9CC5F6657C22F0888C4388843F04BDEC +:1008C000EDF98CEF476267BEEB877D7327C43E531B +:1008D0002B2E91F9353E1EE9437B2ECB7987CBC475 +:1008E000BCAB383ED1116F3C60677843E0138A3B64 +:1008F0008EAD05DC3140481A89D32F708AC01D6245 +:100900007E6C1FE6E72D79F8BC20E19411FBFF29EE +:10091000718AA847C629723D9D3CAFA39DE2966DA2 +:1009200088638EE33C3B51FC22E395F17049E54C32 +:10093000864BDAFDEC3C268167645C52E7EBC23CF7 +:1009400040815F268A5304CE91F18A4C5727E09765 +:1009500092387E91F18A2C4785F9642DC4F7058E73 +:1009600049A59F50EE0E771CDFA42A47ED33E29E87 +:1009700094F50CC52E17F7FC1AEC4A6ADCC3C6B90D +:10098000F222C13CA05478E4017F3F3B8F489A3764 +:100990008EE49F7913F7690EE83E157111B5934601 +:1009A0006A3C24F46EA4BF60074AE2F3524ABE0CCC +:1009B00070FDC81F7BFD65A27849CC17B3D3D87CE6 +:1009C000906A1D323D9DE1AA070B997F2CBF8FE7EE +:1009D00095587113C99985F2FD55BE2F39158E2290 +:1009E00024E66671A930B683F9E480C34037E7F3A3 +:1009F000BC024A6A70269909718D20BC8775AC7952 +:100A00004A244C495B01CFE9B856D5B075A033B341 +:100A1000D83913A7AB1C38AEA73E6479875D2E1674 +:100A2000573D7D5D9A7F3F25E143A897CEB767D2BA +:100A3000FA4A615CA78B7E66B37E2ECB886EC27548 +:100A4000F0EBAFB5850B46DB8707D3391DD906AE72 +:100A5000A735F0F814AC07E6CD1DBD1FA035BD00CD +:100A6000FB0DF9EF79B4DC4E5BDF770BE9A3341BA8 +:100A70005B3F95F9FADB7445E4EB841D097C689CC7 +:100A8000E934D3A83CA67D8EE50374D638709D2941 +:100A90000D96CC69BD0F1517BA92C987E897FCFC73 +:100AA00061DEEF33D363787EC6CB3C8F77B3A68409 +:100AB00081DF6880617E9A346DDF43B4E8D274765A +:100AC0006ECCCBCFBD8271A197B2381F4C05F31508 +:100AD0004EFB983E853D4604F655D2EFEDABC7D0B0 +:100AE000E7BEAA25C51C8F1105D6C9E08FC2D1FC6F +:100AF0005E55A762BF577976DD05F3C699BA5733BD +:100B0000E0DCC7E54336027AB7CA537E073CEF7292 +:100B10003139063E03FE5F55F3F9AFC0F3C646EB2D +:100B2000781C4C2F44FE56686C3C60FCF2E68E6EDE +:100B3000977848489F92C0FFC00BDF5412D62144DB +:100B40007E8A3345BE5EAA7E2B8976578DC719A74C +:100B500096EDDB0DFB5B82A5ECFCCB061F09C37A8F +:100B60006E839F440BB87C61DE4CF74CB6AF87EBCD +:100B70005756D9BED642884B0E696C9D599A5F2A4A +:100B8000E858E567439C9C8DCFE9792AE2910AC831 +:100B90006BC4F32B197E6F30D722FE6F7CB87B5766 +:100BA00021BC57F36BAB7C6C1DD492477588C5DDB7 +:100BB000564872EE92E2FA157E290F90E7EF75160D +:100BC0003FE101F979309BCBCF5C05F5E815C5F71E +:100BD0007061C23C7363BAF0CB88CF9E201F23F2B2 +:100BE000C0C757E67B2A7ECA7C92E542E6F7699742 +:100BF000C4AF14FC4FC5EF8AB2AABF2B7F3FB03BF6 +:100C0000EC20B75DF63FE6B37815B5C109F644E6CA +:100C1000DB0786CF0576E2CC108B87BD34DDF74548 +:100C20003C8F8AEA319E9FC9F5213E0E541FDC8914 +:100C3000FAFCFA0CD0672A6776A8A7D154CC34D036 +:100C4000BF830FDC85FD063D75C7F548E6FF28FD2F +:100C5000A3FFD304BD45A3F548CE0FFB5BF5EF4ED4 +:100C6000B0E7946F73D37D7815F6B49178BE98B8D9 +:100C70000F55AC937715B40461FF78C3808DC07CA9 +:100C8000D33EF48CB60EF6A5D62938AD19A40FE9DB +:100C9000355A59FEC3558FDF4B203FFDE1E9C40FA4 +:100CA000F6CA6865F910F43DE64308BC2ECE4DA4A3 +:100CB000EF4DE687B376EB79BB2EBF359F67E5E056 +:100CC000225C4FE82EE6F148EE37883C5622ED6371 +:100CD000698127B9F1FD1EAD1722E83FB4A7D8D727 +:100CE00022AEB21F205F7B8EFEEC2BE00754CED4E9 +:100CF0003D00292A87A24EA8EFBB2547EB105FD500 +:100D0000291E5867EBF9B86D07A172B4B2E49DA42F +:100D1000B8E4F0073FF4433F0EDB77FBB3C13E6C12 +:100D200067F356DAD525D3D78D817B427555750586 +:100D3000B353E78DDC9AC1E7F7AE3BF73F08EBD939 +:100D4000833AC643EB393E6ED07637ADA3E3D9BDC7 +:100D500054F16FA3CFBBAFD9D37C14E2C8EFEBC083 +:100D600071D27BE1A97CF0234E3EE66C82FA7B3E99 +:100D70007EEAC7983732A8CF87FE8ED07FA5C1DE26 +:100D80007FF8FC09B0332B8B5796423B691AD90D7B +:100D9000F274C550DB9B70AE41C3803E0FECCFCAEE +:100DA000BA7DCE7F003ED53DEBBC925EA70DF96AC1 +:100DB000613C33D243733228BD792505F7E7403BC8 +:100DC0007EE23791AF7D04F8BA528A3F5672B96914 +:100DD0005F5AE04A8C639C192A74617E421DCF4F92 +:100DE00058AA06C10F3EE3B9D28571C73A9697203B +:100DF000F36B25C7E92BEB0AA627C3E385757F4173 +:100E00001CDE7E8DA32919BF6FE2FC4EFBD386FD4D +:100E1000D0DFB41F393D00AFD352E45B6667F07C8E +:100E200052EFC4E22002CF50BE3AED0971108AF7AA +:100E30006FCE4888AF5C6EFBF519CC0E0CAAA12FC3 +:100E400001FF2B781C64BCF843F938EB6E548E908C +:100E50004F2B797C62A5884FD4174CB7C42788E9FB +:100E6000053B7B06D6DDC0CFD6566C013A7A3F6093 +:100E7000EB6EA9E477E5CCA76E3D9A60EF7AED269C +:100E8000EE97ECBE86F949FF55F23B226775CFB667 +:100E900096D2E70F95AC9C0CF62F418E5B613C2EF1 +:100EA000578E65FEB52F2D7211232ECF428E47CB64 +:100EB000A582FEA890EF54E301E5C01F5D398E3F87 +:100EC0007A66E9D549E53F5ECFB931F5A086CBD545 +:100ED0004D5CAE2A89E9C173A9F2DE44BFF557DC47 +:100EE0001E8FC889AB0FE341E1279DB83EDE7941F3 +:100EF000C7F3CD3B9FD8F8139837BA871679DEC36E +:100F000079BCCAB38AD2750DF80F25383EDD5A4236 +:100F1000BCFB8D0CB11E6ECDDFFD37CF1FB2ABD841 +:100F20003C6B54517ECFE1F3C4E70A9E4887F97CBD +:100F30000ECFA39FDDA1279D973984202539AFD8F7 +:100F400000FA971CB4963346F691B7D960DDEF737B +:100F50004F4BEFF9FE6739DFB13723F9BE6731DF59 +:100F60003A2F8C1D47FC39F7AB9FE6F9BCFFC6CF83 +:100F7000ED6BE3E7DC3E03FB56E9F520EC5BA5CF28 +:100F80009F877DABF4FE10DFB74AF227762EBB3881 +:100F90008749E77C68CD8D58D607C53EEDF652955A +:100FA0009D53E1D5F11C548A9B6C987FC2F1A22D10 +:100FB00023E0D4E9B8EAFF4130FFE4EBEFF7A13CCE +:100FC000ECE2F3AC8C633A243911573DCE470DE285 +:100FD000589DD3434DC1123E602037F3A6EE7B28C7 +:100FE000014FFF2F2E172DDC6F0B5F209127957877 +:100FF000F9972E90A71E421C45C22AE00EF88B8A54 +:1010000070FD00411C575FFA00FA5F80030197E111 +:10101000F96085101F7D1EF15CFDD0FC3BF8FAC124 +:10102000281C37C23715F9C4F079E92B1827A91FF6 +:10103000482E6FF1BCA5A6EE9909FB0C1A87C43A9D +:1010400005A5644A7C5FB92EC9955C4F56A982E319 +:10105000B2AC98EDFB12EB1C623C7734F7617E4733 +:101060006FA9C307F1051927CA385F2F65FBC2B402 +:101070001BD9FED4FA0B2CCF1005664AFCFC349D1C +:10108000E7EDB67B427E38AFA4C12FE1DE189BF7B7 +:101090002A8BAD785EC6FBFA802EE1FD309B0FB740 +:1010A000B3F13CFD21413FEAC9BD2C3E70D8EB6352 +:1010B000F24722E8F72CF4DAAE7BC807EB526CBF9C +:1010C00065F9103B6FB37CC087FBA7170E92E855FC +:1010D000B3213E4A5AF13C20897F0B095B7758E8DF +:1010E000F5754F86F8A34676C23930539C6B4DD0C8 +:1010F00003DDDB8CFB6BAA9D0A9E934DF8FA98E00A +:10110000AF9E7E6A07A8C0429ECF277E1762AAF3D1 +:1011100000CA813E4E5C56AC7FE95CEEC47A56153F +:10112000AFBF6A90E5B1C97290E53CF7269CA3BCBD +:1011300068C8C0753179DCE5715D64C4DE7D04E2A8 +:10114000F617D2FDDB619C9D6C9CC538EA6A870A64 +:10115000FB3588C6C64BAC7355CABF0F21ED8393D0 +:10116000E912E71F7CC590F685711CBF8853D79A9A +:1011700076C0B2BE22AF031CE6F9083FD1D839A22F +:101180008707C75EAF3ACCD7AB886782E70EF2F32A +:10119000022ACA483AE09C8A41C2E4EB615B2471AE +:1011A0007D4BDE27EE1E5C5D8FE7AB793C789E427F +:1011B00005A1D7523CE715F31B4D72C0B21E6772F2 +:1011C0007BAFF3B898AEB07E093EC9F4DD3664F566 +:1011D00087BE18B6EE6FB8F55EEB7E8C5B9AF32C8B +:1011E000EF976C2CB2BCAFF55D6BB9FFBCD77ACE74 +:1011F000CF7F0B59CFF959D5542D9D63673DE7E754 +:10120000A63AEB393F0DE6AD92FE9AD67507A58F4B +:10121000AF5FBC5534569C37617FE198E7FEA01F55 +:1012200098645F8BBC3FF1AC21E28D563DE80E57D0 +:10123000B17371067C7BABE8FD51E2D7D0C1E5E725 +:10124000FF887D7BB55EB69E337ABF1DA34BD84128 +:1012500079DF8F38B7AF62B00FE5A0523E9FCF9BCA +:10126000FC7CBE570C8E17C4391729CEB318357FB6 +:101270004FB47F7C1D6FDCFEF176CB49DF3138E760 +:101280002355FF26DAAF91BC2D383790F2A30F1EFD +:10129000E5B2F706D5B79D59C5789E85DDB92866B4 +:1012A0004C8EC73B8979FDC4F66DF3383E31578DBE +:1012B000539EE9BDDDE9637261327CB45331237022 +:1012C000CE5DFC3C0B827640E7F3A97CAE45DA4E5E +:1012D0006296501685179128E28D42676407AC83A9 +:1012E000E6B27DA32DD7D870FE693967EE86FC93F0 +:1012F000D66B34DCB758AB1A585ECF67F35300D6C1 +:10130000A0203FE2A4D964398FC3BBDD037AA2FFDA +:1013100098BD4FD59F8E5CB63E2C3F2F72313CD48A +:10132000A505F35C281FA697AD4744F0DC32916F0A +:101330009B2ACF9602470FDA6D22F0011BBFFB619B +:101340003D2589FEFA5D4CCF02254AC40E79A337AC +:1013500093887D0CBFB2C36B4B1ACFC875F1B8E848 +:10136000C54B781E9D2ECEC7CB63E7E37549E74E8C +:10137000E6F27E1E7039991C143CC5F6A34AE79428 +:10138000D7FB3690443C5BCEE7193DF60EC6994E2E +:101390000F8C8DC3C5FAD32EBE4FB9FA822D988C0F +:1013A000FEDFBB3496176CD893F66F3DA7B7638604 +:1013B000FFB5209583967FB6E1F9D2016FCB34DC7F +:1013C000C7EDFA07C2E25D8CFE7AAEA7016F640733 +:1013D000A1E31788BEF128FC3E875EE6C0F5E7D39F +:1013E000D7507C426568578CE2C58278FF5C7CBE32 +:1013F00009EC3D5A5754CACECD8778CF9201964713 +:10140000BEBC6C1F3F77A51FF725CABF0F525E17E2 +:1014100032615E5EDE18DD81F8C7EFABC2DF0B2103 +:10142000FE6D6CBD50DE3F6920EEEA186272DFF19E +:10143000537F17FEFE8657E046B3B1764AFC7CAF79 +:10144000CA734777C2128C7CBE977C8E90F0CB74A7 +:1014500009570A7FAC81448E69CAE838732A7FEC49 +:101460009F5C1C8F5C43FD313AFEB73958FE6CE03F +:101470003EA50C9CC6B4FB945CB05F2D7C9C5EAB1F +:101480000C615E404B8AFD747FE472FF5A6514F76D +:1014900029751484BCFE31CAE7BA542CAF5F64E7E7 +:1014A00078E84E96D73272E5795C42AE0BDD0E7667 +:1014B000AEA19BF9DB0B2F3D9D37D6FC591E0811C1 +:1014C000E80FB52F49F365F689F6A3EC3C0ABDF5A4 +:1014D0009D9A64FA2CF470BD1EFC890BF61D2ACD72 +:1014E0009134B403133F7F728EFAE9EDCD9F0CF374 +:1014F0001968FFA4FD5F7CA01F3B42D6DF7512D7A1 +:101500009346C889FCF71ECD007FF377E9A1C3603D +:10151000F720DE0DFB053B62CF38D19E4A7C97EB6E +:10152000B9CDCDC653F7B1F7E437A66F65429CE459 +:1015300006371B17BBD3EC81FA67DACDE340DF83B4 +:101540008B92AF43BAB44527A1DC7546F01494EBF7 +:1015500088EDC7F8F12769E64BF0BC54334FC375EB +:101560008FDD7C99D9E91ACF7BC5F17D0CA9C6190D +:10157000162EDE2B4EE4D7A7E3B3DD19EC87F6E990 +:101580003C18322E739CDDF45A07730BFDBEBF323C +:10159000F97A7B0B9727AA67989F25F6B904BCC4F4 +:1015A0004C367F89F274FCCF035D0FEAE120ECD763 +:1015B0003A3DCD46F627D839712E414B8CF985E757 +:1015C000EF51F633BF90E0FD4FEF2CD80FEBBB3758 +:1015D000CFE07ACCF759DC7E8F75DFB368F7CA4C61 +:1015E0006542FAF9CD4C260777673AF0BA2D93D1C8 +:1015F0003B61FDCC61F5083DD535765DEE61ED9F33 +:10160000E1F57FCCEFA91EE6B8991EF6BB2E6F7CE4 +:101610007EB8AAE8D3CB87D007DD6FCD33FD16D7D0 +:101620000761AF289DD7B8518E9A43E99747E79451 +:10163000F2CF408EC57E033543B1C4C303DC7EDEEA +:10164000E416B8C8AC7433FD5D00D731F477919BD4 +:10165000E96F8DDBAABFB56EA6BF8BDD4C7F97B857 +:101660003F85FE9E05FD81FC3C1EC727A7AC768703 +:10167000E2E255D07EBDA6F07DDBE40F4A82FF5149 +:101680003F1022269B2C9F48C40D14BF9AB85FE3DD +:10169000356B7D3D7CDEA276EC4B506F0FD7DF1DA6 +:1016A000BF65FC033E3E93442F051F55C75A2FE4E8 +:1016B000C5A79AE7026EB6BFBDCAC1F6539013B470 +:1016C000FD5996FE6C067E8DF4274C3DBBE4FD096A +:1016D00027ED4F9FB5BE84FEDC0BF58AFE2CBC7453 +:1016E0006A4C7D0C087DF4445598B7035AF279A1F1 +:1016F000DDCDE6CDDF67983BA17E59BEC475179757 +:10170000AF54FB5EBAB445BB80DFE51AB383C4882F +:10171000F6AB09FD2B2F5E2BFA1DB225C6D906921A +:10172000DBC947DD237AF728CADF5EB64F87CAF5E3 +:1017300063D0CE6D933CAB715FD747CC6E9EFDEB13 +:101740007D76F89D94A69C3DF7C3F5A49BE5BDACC2 +:101750003D57E88661E8AF64FB1D5B72D9F9682DDF +:101760008AF59CB4937C7ECCCD147EF5C4CF11C792 +:10177000B392FF4EF31BE54F07B74BFD69459767E3 +:1017800097E67D06EDDF3C83203E6ED9A7E33E035E +:10179000A137B7C1D8B2730D4CC8A3F812BDB7D1E9 +:1017A000FB7E70BA291DA17C42BC73B15C58C77323 +:1017B0000FCCD7983D327F0DE34BEDD0596E875E4D +:1017C000877B6A877EF369ECD0336EA637AD54868B +:1017D000FA400EB508DF8FC3FD11DED7F2E2639643 +:1017E000B89DF0A73A06F61B61C81B2C66FB4F5349 +:1017F000B52BF205C7FB3D82AA7F5EE70427600791 +:10180000C575104715BF5FD701ED1BD09EAD11F810 +:101810007A92A8B80E2FD7D7329DCFFB2E2ECFB9F4 +:101820001BD0BF927FBFAEDA1BD93597D613387164 +:101830003B3B2FE1E2ED64F52CC0272102E76AEA89 +:10184000F40AFBDA05DDAECCAB2CF1409D28DAE2E0 +:1018500092B81DA98E91E8C252C437B87F0BEAF145 +:10186000F17A42B360BECFC273564F1627CF4FD81E +:10187000A58672322727F041FADD0B3AFE93E13D4F +:101880001DFF2999F370FCA766B279C80BF7BFE179 +:10189000E3B84B0DE6C1F3500E5B82A6E5F379F990 +:1018A000E9999F819CEC20EC776F417E13D7ABF7D1 +:1018B00070FBF0B3C9A11268AFE6A72BBAA7D14F4E +:1018C00036B5ADC5738A175E11FBE865CA1F92A7CE +:1018D000E37A60CBC3D679E4071CFFFC3C53ACF73A +:1018E0005D1E8EA0F6EFC64CA48FD9BFB097FDBE8B +:1018F000E7DADCC2EF31F8481DCC29F1736A6B3CA2 +:101900002B6AE0F70ABFFC74C15C38D74AE7F67966 +:10191000B1B74B5F07E30ABFFF94C49E378ED8412F +:101920006ABD2DF354F2FCD42F65B2F993EAF1B2FB +:101930004CA6BFCB81CE7D93CD9B32E7FDFDECA3C2 +:10194000B043218DD91BEA3785C16F5A3DDCDC03DA +:10195000D35413D9530BEB1B542E3700BD5F701EAD +:10196000E8613F9D129E06ED5279BC83CBE3462E83 +:101970005F777279FCF2A7E9D76A687C5E6AFC2916 +:1019800070B8C0DFD4CE7F2B93E1649FFBB399374F +:1019900076F0FA42EECB9C376EF90CDAA778E3FBCF +:1019A000C0C7924C3226BE7D94CBD5639923F8F6FE +:1019B00031F86EA1D37C3C33116F949CF803E4C9D9 +:1019C000C5F14697CAF1869618CF0E50FCC5F3EACA +:1019D000D6DBE6C7F5448F25C7216599237ECACF9C +:1019E000D0AEEC6238A46C846EFF4004F4701AD759 +:1019F000F737983D5EABF7AF07FB7C3E8B7D1FCB87 +:101A000062E3F81CAFEF6DC59534BEF942E608EE0F +:101A10007901DBBB8FB5A7665CC77EB743D815BB22 +:101A200082ED88F87059B6B59D79D9360B4E95DBA5 +:101A3000E98EF7AB1BE5F81EB1EFD7EC81760371A9 +:101A4000BE4613F90AF6C5363F819F1CD7A5C27161 +:101A500009FC7B05FBD3CADA19E15F28B99DC5DF14 +:101A60003564B8F475A02F957CBCC5E5E37771F9B2 +:101A7000F81D978FDFC37737CF60E370DB24EB7EF1 +:101A8000F277F977F7723E89F192E9FF7A362B37D0 +:101A9000C20FDF892712716DA0386B7513C42D5BDF +:101AA00055BFCD375ADEE87F336D09F6581F88E001 +:101AB0003C510FF296C4EEFE25CEAFBFE0B8D43055 +:101AC0007E75A5F0E3EECC66FDBE257F5FCD646834 +:101AD0003F7CC9F27B2D5FD8D8A526FA09FF1BBE33 +:101AE0005F0B5400800000001F8B08000000000006 +:101AF000000BE57D0B6014D5D5F09D9DD9D94DB275 +:101B00009B4CDE1B48C224040D1A708110A304995B +:101B1000BC780688BC4445591E86F04A22624BAB0D +:101B2000FE2C2684A76DB43EB045BB2054AC682380 +:101B3000A64A31D00D08E2B3A1ADA2B58F2008A806 +:101B400008216A5DAB7EFCF79C7B273BB3D905D4AB +:101B5000B65FFBFFF1EB77B977EEDCC7799F73CF08 +:101B60009DBDFEC3E373350721E7E06F44B0AC4A87 +:101B7000B010924C48FD0CF741359F10AFCBE2DE20 +:101B80004A7AF65B1E2F63BF51D93E298EF67BE35E +:101B90002C5136D37E374C11345F1E21233B89E60E +:101BA000A3E37F192F103294104591B0FF1509ACB3 +:101BB0003E4AEE985B1966FEBEFCF9689568CD74E6 +:101BC0009CD10AD17684E977295FE7A8E8F0E38C15 +:101BD0008271E8F331848D13FA7C1C7F3EAA24FCC9 +:101BE000FB97C1F8741DD35DCF94271058CF26AB57 +:101BF00087F6CBB16AB90A6D5F53D2B128DC7B4E50 +:101C0000A9240F9E4751D059071372337DD742073D +:101C100098494B9996EB45CF6085CEEBA1E070D10A +:101C2000E7B45BAFCA01840C726843A0FD8B282D1A +:101C30001FCA7C491B0AE3DC6BD50AA04E889F9023 +:101C400002422610F637C1EEF08BB1F41F85D65351 +:101C50001D76D6762E1BFEFF0CE5F8E58408C42F12 +:101C60009CBB1CEA3E11C6BF5A3DF8B640FB5FADB7 +:101C7000BF77520A792F5D391EC3EB22AE0BE1B359 +:101C8000CBFA90EAB0F4DCA75EEE7278EC0087BF86 +:101C9000447BC6C33AEB5D9B1D2A85F72B9E66BB32 +:101CA0009BB61F8E2308C7BFC66813613FF5BB48AC +:101CB00075336D176384BA6603FCA6280C9F531511 +:101CC00086FF36499B0AFD47D8B56930EE944C8AA9 +:101CD000273AEECCC48EA546B8CFE474309DE3EB32 +:101CE0006699F50B5DE754DEAF4812BC31B026C7EC +:101CF000C163620A8507E9FECBB1D0FA58F8974A6A +:101D0000FB9D54A64D4FA2385B2DBA2DB42EE70A89 +:101D100048CFA1E32EE2EB9D2B572E82F512B54E54 +:101D2000AD7452FA90C3D3C731DEBF3C025D66F199 +:101D30007596C1F330EFA771FE284B6A13097DBF7A +:101D400088F35B68BF490922E36337191D6E9C7AEB +:101D500085D13F5D773DD297C2D69D63AD5C09FBCF +:101D600098A11C2A8FA7CDC5F7244D2349000F0B3E +:101D7000B165219CEC84C249E270A2CB24505F6221 +:101D80006775297A1189A365A6CBB76E20C0AFC14C +:101D9000EA5669FDBD93EF8984D2D9D6FBBB0442D4 +:101DA000E5C5AE4E4212B3601C1946843FCB39A143 +:101DB000E778F4992AE9F351D05C739268364ABF08 +:101DC000D714764E22B1A6F7C9393A9EA3B3DD2BBC +:101DD00000FEECC41B730592F11F735270541C2F4C +:101DE00095CE0BFB913F253ED88FE6F2549081842F +:101DF000C47776FCAC16DB1DEE51B82FE2007E0BEB +:101E0000EE7309F29FBE2ED9D1F1D88F69FFD6CFDC +:101E1000A2DD77C3BE3B477EC0D643BC4EE06BB16C +:101E2000C2EDC983F76CB83E0BFD0FF86C7880AE3D +:101E30003797AF1726C937AC9FF4DCCF7AB1F27968 +:101E4000C0C74C3BD16207A37CD809F5BE56DA81E6 +:101E5000C2B151117C5EDAAFF1FEB9ABB3405EAFF7 +:101E600097DCFD08D039D929503A1F46E75D46E591 +:101E70008E5C481C0AADCB2EB6FFC67B9236C508D9 +:101E8000F05C2233E8F3619DFE2F040A8758575512 +:101E90008542F721F3F7050A38785F501532633031 +:101EA000D06DBB48503EB8101E3AFF689712E1381B +:101EB0005D373C02FA2A9388D74EFB0B2E36EE355F +:101EC000A453247D010F5411D0B284B8B16C143DD9 +:101ED0006F02FDD9658A57BA7EBBC5EE5B2100FE55 +:101EE0002A5F1B8D702F538EE706E5592439049025 +:101EF0003BAEC355FCEE72AF7C6978BEFA30C83792 +:101F00001F32B94CF986CE33259BC99DFDCE8E1963 +:101F100046BE5FAA30B9B494F33D91189FCD95B5F4 +:101F2000B380C7487CBE8CBF9706CA07F89884E781 +:101F3000E39FC7B3F54CB9DBD7D88BC26F4282E0C1 +:101F4000063D5CBE7D96D45B0DF693B9BE3B97AC67 +:101F5000917894C3EE93BE24D03E32EAF7C677C898 +:101F600074187F16979F27F8B8EFC7B375C4703DF4 +:101F70007E44704E0F0717677CB71C74C2F8C4C349 +:101F8000E022C60CEAF4D379486F3E8F55C079DA67 +:101F9000B2997C8C4F30CF13CBE53895FBC9F12833 +:101FA000F77DE9D0EF152B5B5FE8BCE9C179D37110 +:101FB000DE456CDEB120E781FFD5832F829C2FE2C6 +:101FC000743AB6D343C0EE011EB61404E5BDACFAB4 +:101FD000C53ADA5E1441CEF70FCED31FE7A9637876 +:101FE000DC9EA25D06EBA476C1E550B6652B282FDA +:101FF000DFE865219B295FCE4ACBFE11884D7D9C91 +:102000004D7C9F6D598DAED9145F722771DB90CED8 +:10201000AB51EE1571F952BFCB43E0B9B7179599A3 +:1020200086F7E5CED976E2C0ADFCCF39BD3FF051A1 +:1020300067769C270C5EF472DD72268A88BA18DFF8 +:102040005BC2DF0BEDE778606F0C8CBF16FA5F4A5E +:10205000F996EB1BBA615CDF58CE3BF59D9B633A6A +:1020600068BF5DB9734CEBC1E7948F1A731F8B0186 +:102070007BA93583EA0190532F8B28271B9D0C8F5A +:102080008D6955C4638073A9CB2F1E8771BE9A4397 +:10209000A651FC15B93CE4126770DD45B9555E21C7 +:1020A00009DB9F8BA2E3CC89BF04E946CEF3909174 +:1020B0000E804B33A9A2FB9715BFE8A6656927F1EF +:1020C0008FC887FE54CE0B6C3CD5691C8734C3384F +:1020D000B29BD203BCD7E9C7F5EC3A797E383AF225 +:1020E0002C26F9ADF325B5EB6A802ECA946BCBE2B2 +:1020F000E9F80BB6670D16E9F8235D6DF2EC3C9438 +:10210000DBB5401F9B92B53AA49FFF257B6E3AF149 +:102110005901EFA332991E985023F83653F83486AC +:10212000D8098D9C4E2F0DDA37AB61FDA450B71343 +:10213000B435F1E7B783EF893FBF1DFC93F8F07624 +:10214000F0FDF1CC0E7E209ED9C10F4249EDE08713 +:10215000E2BF831D3C5C21BA1DEA43F8C7B37AFD98 +:102160009F983D1ABAFEF9F1CC0E5B4DF7DA0E746A +:1021700029F92446E78C4FAFE67C3AF624E597BC74 +:102180009EF4DF4AE9DF4BE9AF8BDA4D6256647AA1 +:10219000F25F245F163FC0F8BEDEB517F9EEB79CBC +:1021A0003F5BF9FCADB96205E0F315222AA2D073BA +:1021B000BCC60C8F0BE47A28FF695F99E9B9D4E5B6 +:1021C0005B3F18F8E6E01C372C2B941F655A560D20 +:1021D00008AEFBF79C0FBBE51311A49117C1873024 +:1021E0008E6700D819F112F05F3D61F37A0F8AA86B +:1021F0002722F111A59B77E30DF31503B00DEBA793 +:1022000074F367C02FE5B3BF7C177AF93EA70FEAD6 +:10221000871C87F192787D5604FFE2E3F86EBBE0FD +:10222000639C7706D343CE7895BD479264D02F9AAE +:10223000989109F2858E7B16C6DD1377FE710341F6 +:10224000BD1340BA5DC6C67D1E8CECE49EE38E4A8B +:10225000A0F6479871EC5C8EDF10C15F50B85D430B +:10226000F2BAED136B02FAED6C7D4F246BB684E489 +:1022700020DF1471BBE525C1AC9753B93E57B83F79 +:102280002726B0FE646EF7B80A8CA3C353B7036663 +:1022900071F9A08F93C4F92F2E4161EBAA66EF1359 +:1022A0005E1FC9FD270A97DEB82E3B7B7E21BFE863 +:1022B0002E85C52D2671BBAA1336C8F41BC27574B2 +:1022C00024BF2B68F7F507B81037EB9FC6E143DB57 +:1022D000F3B0BD82ADE352450D1B3F88841F1DFE48 +:1022E00052025F4F2E1B9F78BBE17625EC53A797D8 +:1022F0004870DB13C7E056A0C3AD818F13220FD601 +:1023000049CD7625CC3E47727AD5EB31B966F910C6 +:10231000299E9215D413E3111FF96CDD91E22BFD78 +:10232000F87E2FE378A0EF4D41F839D87AEF52BA12 +:10233000DBAFC3F67436DECC60FB0D388F8BF58FC8 +:10234000E4F7CFE4EB9A9AD08DA759385E127B2F31 +:10235000349EA09737F2F54D0FAEAF1ADFCB61EF89 +:102360004941BC2FC4F6D1ACFDFAF44D65C92AE051 +:102370008D8E037AC2C5F4C10DD56DA2D1DEB93EF2 +:1023800042FC4DE2F35605D7FB7DDCA7C6F67F2263 +:10239000AEBBFD87386F119B3792FC3811C7C6BBA7 +:1023A0009DEFE31AF08BE918F101922B2581D714E8 +:1023B000ED1E45BBA406343FE88F924F6515E474CB +:1023C000B9E8F00A541E4BAA1DFDE4288968E0D73D +:1023D000B67DF63D57471ED6FDA0D7574515DBC144 +:1023E000EF5C9D25B9411F16DF2B31FFFA9405E5FF +:1023F000FD4871118EB357D1EDDC5B4D7EB4AAA8B8 +:102400001551B00EBB4854E6FF578CA7CF477079E3 +:10241000BDD79E6881F18665B078C108B50AFD75A3 +:10242000F215F3A335FA1F93DF1AEA6599BF27A5C2 +:10243000D711014BB3BF2D93F567C581A817D08E77 +:102440001AD669F6BF6575E409185F2686F7E8BCF9 +:10245000DB129C49684FE5907EE728FFD872056241 +:10246000BB02FC6CCF76C0CF18B54A29A1FBB1A541 +:102470007BEC208773ACFEDE104F684897DD5E6012 +:10248000C3FBCBEC59E06F3551FF1CE1A0255C3B51 +:102490002088275B9146800E294E90BFBA4B072BB0 +:1024A000854486C7B7136C580EE275FD7928DEB3F4 +:1024B00013A319FF13BBF7582EC80981C4513A5C06 +:1024C0004C3A32811EC534C6E735968E14A89F213A +:1024D0009D2949B4AC6F924687F37FD6F1B8D41AE0 +:1024E0004B787BE95EEB9857010E12C40DAEC0B875 +:1024F00080C7D637183FD0ED553D8E10C96E6D148C +:102500002BDF04BA1614FF17D0BFA7FDEB65FB4EF7 +:1025100067725A2FF5758C4F64FC6E4BB463BF3DE8 +:10252000779692D92AE2E908C7D3C12B012A5973B9 +:1025300015C0D3CB590FE6405CCA9E757F12F0E7F9 +:1025400068C2ECD372FA8E8B962B1D9E9309067B84 +:10255000634CCE2CB49B8A32EBD09E5A15C12FBD52 +:1025600085AF43E27432C8E1390BFBDA7AFF123BE4 +:10257000BC2F2995D150EE094CC292DABD9FC0F311 +:1025800055E9AC7E213CBCC4F939D2FA47815E8062 +:10259000784D7AF73E84C4647CEE950707F761585E +:1025A0009F3531CCFA3EE5FA485F9794C3E932D7BC +:1025B0004C77457CBFA989BABF78D174F7D6C5D00E +:1025C0005DE87EC7642D1DDD9F04D7AFEF57DF3F69 +:1025D000DD6F1FD86FB9C4F6BF55F168300485B3FD +:1025E0000AFBECB12F7B78BDEF48B47CD3FD3C985F +:1025F000D0F7E2F7F30DC69D96F80DE0B47FB8E68C +:102600000279D2904CE993E2A94160A5DEFF0B6EFE +:10261000A7FDFC9BE32BA5DF37D85FB14B7811F406 +:10262000E108CF9152D86E59D120503BC08F930111 +:102630000F2579F74AB369BDF1CE39283FF70FAFBF +:10264000C375AF729AD7AB9742228FE3676AC87F90 +:102650000D9CFFCA09F323F57E4F72F918CA1FA11A +:10266000E385F2F54A873617D62524323D1BF4FF61 +:10267000DA45A3FF57C2F5D770FB6DA6F8C770EE19 +:10268000FFADFA34DBE1A51BEDA27AED9FE2FF7D01 +:10269000419F809F945E6237FA7F0DF6526C5F9582 +:1026A000A18DBE2209F4B1E8BE9B20FCD01FF40A24 +:1026B000A2B2358C3FB82A43F68FA0CF6D0AF90538 +:1026C000ACAF94EA4B88BFD8148D5C32A0A75FB83A +:1026D000D75E4A206ED2A590E7C01FBBD07E1E48B1 +:1026E000BCC464474AE017F2F1D12F54EA4807C648 +:1026F0007B4A09D835D0AEA25DA5118F13F408F539 +:102700000B0DF2A9CB7E1BF27BE87C546E3D027C64 +:10271000DEA0303E0EF507BB389FEB7236941ECA22 +:102720005D8C6EA2E8D2AD4C6EFC2271684FBAF897 +:10273000E6F2696E19B800D79115FBC1559B1AE8EE +:1027400094C0E59993C8F8A9D2F14C033CD7C70FC0 +:10275000C50FDDB906F174B06758FC86DA6BD48E0C +:10276000B2527B6DAD109C7F0DA78348F888A4AF53 +:10277000F775CBB5D038D16DE6F317C54B920A5833 +:102780005C9F8481BFC8EDA4D5945FE0FC668DD5C5 +:10279000ED02BFA2BE5FD1DB1EA0BF7E32B377A425 +:1027A00026D7B561FC90B511E2DAEF2526203CA3CF +:1027B000732C26FB8C7A0626FB31D2BE095F9795D7 +:1027C000EF4B0078E61AE119B2EF3205F70D663DDE +:1027D0008C1B6B71133FE58BD84CE24681156BC1A6 +:1027E00038ACCEE70AE7735D1E3814F6DEB0A4BE3F +:1027F000EC7C4F74748A145FEB92A83D4DC7A9D747 +:10280000F6A25ED5DF8FE3FB770C67F14687D3AF87 +:102810002861E4DD8F2F80DF264D8A2FA3EBFBB1EB +:10282000C2EC6F69B8A5D287F12816AF5538ECC451 +:10283000E27C3BD8ED05E0780F85F5EC508C712BF0 +:1028400091AF27C649D7731E39B98AF3B75EB7A9C6 +:102850001D65B07E294B53E20DEB1F94A4EB9576DA +:10286000E4EF48E3DDC3E5BC2DDD4DAAE8BC768787 +:10287000DB0FE75A36ADAA00FC05BBEA26730CED68 +:1028800076AD6088CD80F7A67EF2F4707CB92089A1 +:10289000C97FA7A455C27B4E4522704EE6E4F6726E +:1028A000A47123ADE342F38D8A349F1ADEAE884DC6 +:1028B00062FC270DDF5109729A0C9048BF307A42B2 +:1028C000E0FD62E50E15F88AD2A327DC7867126571 +:1028D0000EEF7F117FE8767771CBC16CBADE7A8715 +:1028E000E416407E159E6C570D7281EAF509490683 +:1028F0007B59747850BE892A3B771F6D63FEF6FEC4 +:10290000E1E673B2299C5E5EE56524B97079928533 +:10291000DB4DFF9A7D7E53FC0D4A2226B834015CC4 +:1029200008F0D77D0DF561E42585CF926F039F6593 +:102930009CBE1EB9007C32FECDF0B9105F07F9CC09 +:102940004B8E86916FF54E396D8E89FFA91D12A1B0 +:102950005F95A13D121FEAF4310AF002FCD0A49960 +:10296000E2027292B79DF995B79BF59CB8C8CDE588 +:1029700033F9AA808539E12FDE41FC31B1C1F1E59F +:1029800032733CE1C9241E17882251009F2EF72480 +:1029900001F214A22C3306410834853409A02752D1 +:1029A000609C81D44FE6F23C540F266BCC4FEE4D29 +:1029B000EA04A657D2717D497C1DA17A308DFA3583 +:1029C000108F0154833FDD5B82182F3CD5F01C5CD7 +:1029D000F05AD05F76119F00E3A7930E2CFB402A9C +:1029E000021D3F8BB40B39147FF796570D02F9FD8A +:1029F00062C83E2E648FEAA56E7F2CFB37C1FB9D1B +:102A0000FF5E78AF2835C0BBEB3BC27B0A973BA18A +:102A1000F1BC31DDF1BCA617310EF715B33FDABEBC +:102A20009631BED790C5E279E562C506B0E7C7A882 +:102A30003201FD26E576AC833C27DDEE049704E207 +:102A40005C7ADCCFDE6F4EE560782E9D4438E1D9AC +:102A5000908AF2CC998CF286D91123F8FAC7A8553E +:102A6000F62CD5E83F3599CECF644E07635C25E858 +:102A70003F357C757EBBE362FDA43DD2030EB06B97 +:102A800074FFA83E670EDA3DA1EFF9A5A63F435CAF +:102A9000D29F6353575078BCCCE5D5CBFD1E928CAA +:102AA000E7BFA17E906E578DE0EB2FCD997510FC9E +:102AB000AE31CA6C06130E0799CFD3E0EAC273F0A9 +:102AC000DF7E65417FAB8BFB5B63B89F05FE4E9558 +:102AD000B3E73E87279BCFD574FF694CB7FFD4245B +:102AE00019FDA73111FCA7D1B6CE57AF80BC9057C6 +:102AF00045CC0B8904DF50BF2954FF8C4E667A67A2 +:102B000076323F270A81A71EEF0B3D976ED4F94F0F +:102B1000F20A46FE0F9D5FDE3B06CF05896288C73D +:102B20006607E38982E625CB0607E38761E2863301 +:102B3000920D71435D8FE9746CA37DED78CE1C3EE0 +:102B40009ED89A75A02FF30B5F4C04FC972B2C6E2C +:102B5000A4AF8FFA85F3930D7E615127D3DBB6FFC7 +:102B600053D7B182C297241037F30FEA547B3EBA91 +:102B700013896B591C1DF3B4C638048C874BFE288F +:102B8000AC979D72FBA268DDB6F76109FC84524ADE +:102B90003F5142907EC670FFA221E7E83AA0AFAE57 +:102BA0005392FB7C7E7799430CA1D3E8601DE55BD3 +:102BB00082A9BE5AF2AC647CDB2B086F11F2C1B261 +:102BC0004DF9675B25AD11F63DCAAEAD4AFECFC4E7 +:102BD000FBCF605D8272E05BE13D380FD30760B3ED +:102BE0009134C37C0EDA7815CCA322FD77C7A59764 +:102BF000123C8FD90638033FF763E28338CB0BD6FC +:102C00009744D0478D7C9CAB49932AF765EB857E32 +:102C10004F6C756D5A0BF238390BC77BC1E1590FF8 +:102C200036E4C12DD22088DBD4ABCFDA217F76EF1A +:102C3000D6C6F40E03FF1D7CC2D3279C7FA897F451 +:102C40002FCE5288FB8A65A5265A5CD82E42BD87B6 +:102C50007DB6A54581799ED86A0F6B4775713EBFD9 +:102C60007A0BB36B47E75ADC1402A48878A50438C2 +:102C70008F7113B79F36C40CD8D15E02BA284B446B +:102C80003F9FD6F7C5D27ACC500DFD83FE0376E088 +:102C9000FBFD3F2E71B33C4AAF6330ADAFCB2D1976 +:102CA000BA16FA477BDE04FC513DD324A13E6D8E5B +:102CB000813C8098019392A98D4B620452192E0E8B +:102CC000F84132B3F39EB0EA7095300F72EF5619A7 +:102CD000F9EB609A88FC46E1B608EA7F4F8B2194B5 +:102CE000124999E62D03389693E67AF0A7CAD46B79 +:102CF0005F8C25DF027EF93B14E0FF756087875902 +:102D00005F1B5F1F0A114A3F07B634DC40C2E45123 +:102D1000EB74F88B18ED1380C31A7EAE4B5C939066 +:102D20007E22E3FB6EA41F67B3BF3E9AC2F1EAEDB9 +:102D30004DBD8CE3EF4F564DF1371DDF90FF4CAE8C +:102D400080FC5B0FE6D3D69FB420FC5EC9137C02E7 +:102D500085CF815C91DA6C745539765F3F5A5FCFCD +:102D6000E9B862FBA1865E00A494245CEF2BB98FC6 +:102D7000D9597EEBC5C7AF87503E5800E7C9141F2D +:102D8000A394689F4AF1B51086C887FC1CBBCF4F3F +:102D9000E76B73B697C6D1295E4816DC9B815E72DD +:102DA0008902F2035D100B439442EB2032909E9215 +:102DB00008E673AD2BC8DB0CF2766DBADA0CF98637 +:102DC000BB07D831DF2C349F78B750F7623CE499C9 +:102DD000C40B28AF0FE4FE1ECFE90EA4DB08D02BF6 +:102DE00026FCD2E70D098C4F63F2CDF6677E4A16BA +:102DF000F7B389D756105C574C8E5D8BA284F45282 +:102E00003C7BFF608EE0037A3BA872F940F7BB156C +:102E10001201A91D346D4064BCBEDC6F94AADBC5F1 +:102E200082BE4F4BCF7DBC20F85667C33EFAD37DA0 +:102E3000D0BA3357C0F99DCADA5B099685F3E01C16 +:102E40003374FD35298C2E654A76B920DF9A578F69 +:102E500031E6C7C885B74E70C4621E13DA95A9B9AA +:102E600002D35F27D9796E8FFC6C857864137EA8B6 +:102E7000D591121C2FE6D3E7BE0FF9BFE30A057FF9 +:102E800014AC87E737D3FF6B03FD22E7CC62F9D799 +:102E9000B99B703F630BAD6E38CB19EBF03595D015 +:102EA000FACB1F4818CF1E97330AF3AB43E75FAB4B +:102EB00010FF680ADF97F3248477D4258FE1386FF9 +:102EC000E45950DE8C837C6CC85F36E655A33E34F3 +:102ED000E7738F13FFAC1543B39BF12B91BCBD403F +:102EE000BE4F7099E1E73C693E2FAEC8B799EAE35F +:102EF000F2E49078A597C58733185DBCD45FF06D78 +:102F0000CE0AD2D9D893093EA033F8130B4C7034B3 +:102F1000ED33A653D6007E07FB3FFE1338278951B9 +:102F200057DD8AE7E01CFE3A9DC470BC3BD39FFF8F +:102F30003EE8291DFEA17470F1F8BFB6B218F09FEB +:102F4000AF9FDF87E03F04DF1883D4F7D1B727DED8 +:102F500071FEAC9EF8D6E9A0C7BEEF69599D4DF150 +:102F6000FA8A933E003C6F927D770B413C5D10AF37 +:102F700039C548376B952607C8FDA84B8E3AC0DF88 +:102F8000D0E98288ADF946BFE39F85EF92F50273E1 +:102F900026DD820FE27ABF83475705E77936A53BE6 +:102FA0009FE8D914D013952C8FA35E1BCCEE5DE562 +:102FB000337DDA433EA4B07B1D6DD697D2CF97A761 +:102FC0005AE1F010381FAB877C3BBA3F79FD2CB833 +:102FD000D140E429B3505E92F5028BCB17FD01E599 +:102FE000FB5C976FA510663EB464709D2A937B4589 +:102FF00089D89F4CD7F3922A5FC5F54F61F58B5D59 +:10300000D7EBFFA4751DA0B4420CFEE7446E37EB6E +:1030100076F70407CB3B9C5024223EDED822F830C2 +:103020003F92F6F3523A59C0C97622B703BB0A9FC2 +:103030006D1CA4823DA899EC4EA1A80DEDBEB8422E +:10304000B33F18AF459BF09F383AC1544FAEEC6583 +:10305000EA9F3A3DDB1C57F05C667ADEBB7AB0A98A +:103060009E5177B5A97F9F6525A67A9677ACA97FF3 +:10307000DFD5934CF57E4D3798FA5FBA61B6E979A2 +:103080007FDF02D3F3CBB72D31D50734FFD0D4FF88 +:103090008A9D779B9E0FF2AF353D1F72F03E537DA8 +:1030A00068FB4F4DFDAF7C7BB3E9F9551DBF343D47 +:1030B0001F767287A93EBC7397A9FF88C05E53BD77 +:1030C00098BC6AEA5F6AFF83A95EAEBC6BEA3FCA3E +:1030D00075D4F47C8CFA91E9B94E07E3723F31B5AF +:1030E0008F777F19724FA712E59B0CF180BEF0A875 +:1030F00009CB68D2CCCE75483B962F1578DCA94019 +:103100009F8F7A1B2121A9DEDBF957389A7EA3B065 +:103110006F1CB39F3462949F7A7E2AF55BBC5194F6 +:10312000146203946E8750BA0B08582A012A591367 +:1031300021DE138565422011DB1303F15826057A41 +:10314000637B72200DCB94405F2C53035958BA0215 +:1031500097639916E88F65AFC0107CAF77601096C3 +:10316000E98161D89E11B80ACBCC4029B6F7091481 +:1031700063A906C6619915188365766032F6EB1B64 +:10318000B816CB9CC08DD8DE2F703D969704E660B4 +:103190007969601696B9818558F60FCCC7F2B2C02E +:1031A0006DF8DEE5815BB1CC0BDC81ED03023FC045 +:1031B0007260A01ECB2B022BB07407D661BF418179 +:1031C00035580E0EFC04DB8704EEC5323FF0336C3D +:1031D0001F1A7818CB82C063585E19D8846561E0E5 +:1031E000492CAF0A3C81E5D58167F1BD618167B0AB +:1031F0002C0ABC80EDC303BFC1F29AC03E6C1F1104 +:1032000068C3520BBC8AEDC58197B12C09FC01DB68 +:103210004B0387B02C0BBC8BEDE58177B01C1938C4 +:103220008AE5A8C0112C47073EC2724CE0032CC7A8 +:10323000063EC1F7C605CE625911F812DBC707BEBC +:10324000C0B25BDE45CC57F658D09FE57E6A647FFE +:10325000C18B72D2CAEFC5416E35E6FFD709BE51A8 +:10326000943452933A305E682DB461BCF026D26932 +:1032700065E7D0ED4ED04B6D579D488738DA1BC9B6 +:10328000FE0C63BE8395C701CAC553188F9A90B4CC +:103290003719F4E94DB419F28C88760EF32027F033 +:1032A0003CC89B24EA60D1A51E8211AEC27E7E1B63 +:1032B000ADCFA820DA60DABFF12A1BDE2F6A1C4CE2 +:1032C000FD205ADE93C5F2657DA94C5F3ECCCBC78D +:1032D00053D9F9CB5F0B589EEB8C5BFB317E2A4BAD +:1032E000BC80DFC4E0307420CF8F757466627EECE2 +:1032F00045BEF7A714FE1EEFBF3CB5F2C954BA0E87 +:103300006F09C9AD7304FBD1F6A723B43F03F220C4 +:10331000B47DAF85E1C3FB96C8FD84CAB849E7F127 +:1033200013DE58DE7ED98BFD82F5DF45F043095967 +:10333000C1CE0FF77E50711DD587130B4537951CF5 +:10334000E4CFCB770E3FD68FCD0B71506F8988F1CC +:103350008B194587F627D2FA8CA5F19877DFBDAE99 +:10336000122B3E9FE07AEBB217E9D66FAAFBCDF0A5 +:1033700063A6789307EDAEDB388D12CDFA8F0EFD84 +:1033800039D22B8BFBDE0693AB20FFAC386EBB66CD +:10339000F59D2F3F866836A299E89EC16B1DAC1F34 +:1033A0007C7F62B7C0BCB1BC0F852BEA7D6FACECF3 +:1033B000AB17C07957E380EE62F23AC9F9E2CB006D +:1033C0004F092E4E920E07D83191E029B8581C347F +:1033D000AE487379297E1ABE16316EBC2FBE4001ED +:1033E000FAFF91232715F843E2FD1ADADEC1F856F9 +:1033F0005C7E27F13A58FC5EB5C139BA1DCB95CB3E +:10340000DD58362C2FC4726DFA7D76889788C9985E +:10341000094CA232E6623C489FDF1A3FDB5EEC2695 +:10342000E4CB87BE1E07212411E20CD444F89AD6BF +:1034300057509FE2642AA3CF375CC71CC00F2753A5 +:103440005596876F61E7C631F97E0DE28D316EA525 +:10345000445283EDF89784ED9BC11F798374AC9F30 +:103460000C70D4D87D8C7A7EDFB4BEB81F87ABFEDB +:103470005E08DE43F02CCA6E3CB716A369FFBCC8D9 +:103480007875B9585E02D09744E9EB6FB06EB037EB +:10349000B5180B8CA7E3B74BEAC47CAA7A217CDE73 +:1034A00065B68BC987064553CE778E4214E91F4611 +:1034B00079EAC8DB1942CF0E94AF58877C2E2EAF25 +:1034C00076A46AB92E3A7EF3355C0EA427A01CA020 +:1034D000EDF75D4DD7BBD3C2FC146F828CFC4281EB +:1034E0001087792F76356ED279F220562D5734C950 +:1034F0000AE7036A1CC06B15CFD7831BCA4639F095 +:10350000AFEA1794173E961719D27FA785F3557423 +:1035100014EE4BE4F0D0DF9BEE62F2F8C1ACCAF1DE +:103520002E8C8FA8E92057697D22C08BEE3F1DF8B5 +:103530008AD6AFC5BAD25D9F8CFD5DAC3F26D25C0A +:10354000841CA6EFDD80EF49DDE3CCC0BAA37BDEAF +:103550009B719EA4EEBA079FA7B3FE173B8F5E76C2 +:10356000EFFFF74C4E7E2A697109143E95CBE65465 +:103570009651BD3D79D97C2CDF5BDEAE815C3D4E42 +:10358000E54903856B6571DF24F073268FEFEB50FF +:103590000DF43A8FC735F7AEB68E067D57B246ACFE +:1035A000DC82FCB4C214B7FBBECBCAE34D6C1D5524 +:1035B00094C7EFA424376FC3A1CB1A0CF6E86CE2D2 +:1035C0009681DEE7ACB606E99A18F853616D3B2D9B +:1035D0009E1F5D0FFB582BF2F30ACEAFF184FBF375 +:1035E0006A4AE579F40E596D239E30F2B8277C08BB +:1035F000F907E5834F1D391897A5969A3DDCB83A2F +:103600009C22CD372F42FC5787930E6FBDFDE8FA01 +:10361000210AB3AB7D2638CEB96728C62BE7F178EF +:103620003D89B773FE64FDAAE83C3BE03D49538108 +:10363000DEA11E4EBEE8F356D17FDD39381C7C3941 +:103640001CD65A991E0F81EFF10DFD62410F85E2E4 +:10365000EF62E15C6B23789FA273AB93C59192A656 +:10366000E3F8D57C7E923403D753CDE77B714F8C42 +:10367000DF42FB976C756E063FF84C89F7C14A90A4 +:103680004F9BAD98CF76F79E756FFD0CEE7D6CB2BB +:10369000E299C9FC98070AE0FCF42F5C8E5205D031 +:1036A00006DF4FF010FD4F1360FC79848D7F463F9D +:1036B000FFD81A87F03C59B6A571182D3B762FAE6E +:1036C00080B8CB893DE30F80DF3C3F9A4878979DD7 +:1036D0002832F29FD77ACC6C1F48C1BAD8B33E0FBC +:1036E000EA86F8D17C9FF59891CE176E33D78DF08E +:1036F000B218E1A59699E1A5969BE025FCD6E917BD +:103700000DF02A8BEA97047A7DBF4BC5F1AAA35628 +:10371000A6007CAA77AFC172E1B628EF31C3BC8B9B +:103720009BE34DF5DA9D695EA35EE93AF8582CD02B +:10373000E11297E83D46F5DCA9E55A3DD831A79757 +:103740008FC652C7FFE2E62CAFC3348EB9DED52454 +:103750008C66F2598D9B721E7E5DE292719E0FB750 +:10376000317FF3C3E5762FCC736AB9E265F3BABC57 +:10377000CC8E62F05AB42CC67B6C48707D91C6FD2D +:1037800067AF8F901672D44EF0CECEB9F3E8ED88C5 +:103790007249FA5446FDD16AFD3BD08D9DFEEF1C67 +:1037A000C65125ACEBE3D6368B5EC8272664BB69D1 +:1037B0003EFA9E7ADCC06F91F582F93B13FD21162B +:1037C00086F2999D8378E01C848E774672AC8638A9 +:1037D000827E0E520B13D1BE8BED1DB287367DDC7F +:1037E000D2F7BCF7CC299EB2402F57DB9B6450B672 +:1037F000D5CDFDCB809F3E6EA94F01F9B150ECFABB +:103800005EB8FB5EA5699C6F7DD64EB3BFE8D3D78B +:10381000992599F88C38BAF74DEBA722E40B8F4F16 +:1038200063F66CCDF6432387D1F5D7EC3C2B63DEF2 +:103830005A9A677C9A61FF023F075AB0ED888CF66E +:10384000A7D57BC91DE7B3EF7BACD3E132E51D7A89 +:10385000493BF0E7EC42A233EC75EF5279F3C1AB90 +:103860005602E787E42BDA8B3ECFE44FE792CA5843 +:1038700080D7EC9685287F3E786EDC01967FD45405 +:1038800000F4F131B160DEDCC7E4F7B1430CF05B6A +:103890009626EB7144BB31BF852E300DF3D3AB1BA5 +:1038A000DBE1DE988D485E2E9704F6BD1A9F80F20C +:1038B000AC9AB57B897D05EE633593475EFA1FD4DC +:1038C0006F6932CBA7791BCCF52A322905F2BBAB45 +:1038D000EEB7420611996F947F147E33D3581EFBC6 +:1038E0003C52D708F6DC2332C5135DFF6C8548BD1A +:1038F000A91E5AFCFC2305B3687D791A3BDFF990B9 +:10390000FB19F3C13CA5CF172CF3C95A5ECFFD1D9F +:103910006D19326D18C1F198DE5AA0DBAD448538BF +:103920007E6FF85776E4FDF76E11F1DCA937B41B12 +:10393000E4F39CD5E6FD5D68FFA1FB25E43EDCC712 +:10394000826DD7A2DFA6EF47C797BE1FEBB6F0F791 +:103950007C1FE4F4DA7DBECAE1A7FBDD4FA631FB94 +:103960005DAF3787D47F1D52D7E9DBCAF99BD2FD03 +:103970009369C9C0CF9D23199D74C8C6F35039D827 +:10398000AFF97CFD6C9C5F68BF5F9FAF5F5470BCFC +:103990005DE1FA2D7EFEA9E7C01F5DF0AB0762E195 +:1039A00030E803A92905F284166D5D190B703A29D8 +:1039B0007963816E3EF089A3C3C1ABB31B5E9A43AA +:1039C000A078AFD1E9BF68C504D0EF7FDF6A55C0EA +:1039D0002FACDD66F3C3F7976A5AE6E3790DAD1FA6 +:1039E00061F55578AFB276A7F53D235E173CFE40F2 +:1039F0000AE677106F6F769EEEEF0D9F0EAAD9F252 +:103A0000FE48F0936B4927D273E87B307F2001E5B5 +:103A1000F52C39AEE7733D6E5ACB9A486DCBBAB3ED +:103A20001037AD6D197302F8BE9648EF19E9A91A5F +:103A3000689AFA2B47D278DEDD95E44A902F3A3C1B +:103A4000882F19E573FD130F0D3C42D7736ACBAB7A +:103A5000B182D15FE5E7ED5DCD73FE96781EFD7016 +:103A60009AD2A9313F5E97BBEA4EBA80545A6D652F +:103A7000E522AB3F761885EBA24D56BC1FBAE8A9EC +:103A8000C77EF153C8237AC786E71F0B9FDAFFD69C +:103A9000D5B4BEF0196B5205DB8603CE8375BCD45A +:103AA000D2FFC1F9848E8705CFEE9721FF0BDAC1D3 +:103AB0003FD0F1B1F09936990CE809BFD2E636B99A +:103AC000C311062FCD4746E23DA3273E9701EF1FC6 +:103AD000EC11486A56CFF7AB37ED473B06E08478E8 +:103AE000E478EAC65B0F7CF927ECCAC77E0AC8ED0A +:103AF0000BE16B1FE8D564A4EBA777D17554FFC920 +:103B0000E60638543F7D5B2CECE78454C7E8FB9114 +:103B1000952990E7566DF5A62858B2F6EA476F4703 +:103B2000BA9B77E8F61476CF414BE3F91D69B0CF25 +:103B30005B364EC57D56110FD25FF5236225E4C179 +:103B40007C2691D1CF84E18FEA5E4CAF9ED84C9118 +:103B50004BF77902E46552D0DFD1EF35DFDE1D0788 +:103B600061E7909FF173C86B7A594CFAA59B6EB7C9 +:103B7000AC42B9FA6186960AE793140EBA1C45F96D +:103B80002A1E2A4F657862F218DFA3F4570AEDD097 +:103B9000BFDD8AE7C286F7B8FC64F32FE5F3D3757F +:103BA00047833D722285E98DD0FDDDCFF747E0C226 +:103BB0008681CE0C7CCEF87ECB1AC6E73ADFFBAE10 +:103BC0001D0DCF3FFD23E323780FF4115D973F15C3 +:103BD0009FB74D11502ED8883F1C7F6FB172FE36B3 +:103BE0003FA71209ED399D4EE8FA25F81E59905E5F +:103BF000E83C098807B457AAEEA7EF1BECEC5A98EB +:103C000017FBC9C1F6AC201FCFE3F2604E2FB33CC7 +:103C1000201B932F2A2EB0C8EAFBC54F817F29BFF6 +:103C20007A55E05F2BDEBBF968FBBEB76EA074FE71 +:103C300051B3CEB766791ACAB7D53B6EC7F86028BC +:103C4000DF7E945E47C2F26D3ABF3717CAB7E91DEF +:103C5000FF5679AAC36F5D08FCA87CFCF92E3532AB +:103C60001C43E5E3A5BDD4B0F291FEFD9114F4A48C +:103C7000439DFE74BA5BF0E4E23E2087BAE953A7A5 +:103C8000BF6EFAD4E92F74BF66F8853E9F02C94E15 +:103C900006FBC17A37F13A29BE3B778BF8BDA433D6 +:103CA0006A672CC47F5646919960879F51783D9EE4 +:103CB000D53B93E54690137A7B67148B579EA9EC0E +:103CC0008C8D37D8D7475AC55888EF76F8C2DFE7CA +:103CD000C08C443A7F4784FB1E7A3CE24C74EC4033 +:103CE0009C2F3AD307F82A171D99CBF2C10F13F175 +:103CF0003B3E73575C170BF921675AFB4E9C4EDB1A +:103D00006F79997FC6CFAB496914CE7338DE4F12F5 +:103D1000EF8345747F735A99FD3C777D783AD1CF14 +:103D2000CDAB1C4B659047D46E0DD20781E7EC3BC1 +:103D30000BD51B43DA5BC7213D2D08A1270FF78F59 +:103D4000DE047A82B8EB203288FB2716633E48B93E +:103D5000983711BECB79E6A08879EB5DAD226984F6 +:103D60007D6E177C04F8DB9B8C745943E58731FE2C +:103D70007B0AE8EE3CF7E84EFDFA2F0577D02E8B54 +:103D80009E7B77E0CF6879EAB9772E7901EACF1F79 +:103D9000CE7C9784F1B3F67C7133C8FF337B6C041F +:103DA000E32A7B5ECABC03EABB6C987774E66E9B21 +:103DB00086F6F41E27E6D19DC960F1D4FADD9F0F87 +:103DC000C47C74D2C0E8AB37BBB7D5D5FAE55FF198 +:103DD0007E6D2BDD15E8DB3D31688FD7EE8AF281F1 +:103DE000937A66F7E705C6F38BEFBA9F1A99C5EF8A +:103DF000CF38C974887B9D896771EBDA17AE7A0C6E +:103E0000F2E117B7B4C9706FA7F4B75F0F04797305 +:103E10006607B3234E5B3B1E256E42627ADF768FC8 +:103E200095C2F934D87694571EEFDD321ECE377A1C +:103E3000C285C1E10C8503EC8BC2A51AE464247829 +:103E400064FFC7C2E3ECCD30FFA2D62BF1FC210802 +:103E5000174163ED4E9F5DC0FDB3F63D9F0F0479A2 +:103E6000FC51F30AD4EF17DA77F1FF73FB16FC1756 +:103E7000B36FCF7FECBE19FD1F07FD94DC930F7A63 +:103E8000D2F9F3DFC3FAD34E37AEF722F9DFDB9B6B +:103E9000C51DFEF3F6FF2DF1BE43C0FC950BE1FD01 +:103EA000E7FFB5787F99E3DDA9409EC499DD5F67A0 +:103EB00012C3FE2FB4EF3DFFA5FBD6EDA0764B9DC0 +:103EC000924FD7F70E699A9A45CBDF699F2481DB21 +:103ED0006A8B704E73BA37F32B6C02CBFB265305FB +:103EE0003DBED46ECA7B4AAF467B6382760FFB3EF3 +:103EF0009354D70E79A7ED2573DC6BB1C7E0B73DBE +:103F0000509F329CD7CDFED684927107C1CE7B6381 +:103F1000055D1FE4F965480ADCE598A8896817D2B1 +:103F200012EDC137334762BF8985667FE3FA103FE0 +:103F3000E1BAE9E6E753F9F8D3C87DC910A79B3683 +:103F400097C5E9AE23752B8DDF519B1A32CE2B100E +:103F50004033D891DF147E6ABA0EBF25080F52ACE9 +:103F60009FDB5D007E84C1BB7DCA20965F2CB919A2 +:103F7000FCA62D7663DC94FBA156FEBED5B1BA1D1E +:103F8000F8D64ACCFEA7EE475E08CE84FBA7385E83 +:103F90007610EE564D44FFD4302EC245C7C737C504 +:103FA000838EBF6F8B8F2EC087E15C572FE7DB6757 +:103FB0002D8473083BE4BBD37D4D5CCFEE8FD8F3EB +:103FC00004846365A115EF4DBE6FA92C00C3B962CF +:103FD000C895353F64C3BA013EF3391CAB481DDABE +:103FE0009DE4AB73E78A0AF0F40FEDD6F91A21E3EA +:103FF000A95F525524F8A3E9BEE749C41B3718E26C +:10400000A00279CF1807F599EBF0774D4A709C0B19 +:10401000F58F241FFED9E5DFA83C7A8F22FB089498 +:1040200098374324A3FF38B395C1B17691E0CB46CE +:104030003AF25B8DE7BF0FA4B378E3DFEE1C827228 +:10404000AEF8C703E2985F9B8FF93CB5DCDEEFF278 +:10405000AA7110CFE96AED1B07F19AAE83A5B1E111 +:10406000F2780E71BFF20FCBED589E29139AC43827 +:10407000BC773201F570591401B913FADEEDE97A13 +:104080005CA68E9D4B1296875FC5F7318FBE1A973F +:1040900060C0DBFAF11F48037BE201FEDE339CAB1C +:1040A0007C57F8821F0B703D14D53132DCF709576D +:1040B00071F855ECFD4286F8C1A4D62CFCBEE4A4F0 +:1040C00032D194A7BA3C9DFB5343C8105857C5DE64 +:1040D00031B157015E0E8AEE280ADFDAD6B3B22775 +:1040E000CCF95C283C617C88231FB5BAAB009E47A5 +:1040F000EF89C2FBFFAFF3F3A23CFE5D48F87410FA +:10410000C4CF9AD2593EC8FBE92C8E3EB9A2D89AA8 +:104110004CE7CD6B5106415E592FDEFFFD74159FB4 +:10412000F7E6EFE9FD7A2D62FD8EC84A4DB8FDC76E +:10413000640AFC3CC4FDBD42E13F0F6FC53F76FA07 +:10414000E15E5C5799C0EFCD84D23541FEE81A2D6F +:10415000F840FF821F8BF50A01F5FFEB7ADEDD24C4 +:10416000A62F75BA0F85F36E0E677DFEBFF0FA5E5F +:10417000AE377438EBF00D5DAFDE9FCAAB11C67879 +:10418000CBC49D839E06FBA4A655502C74A81AA9E7 +:1041900043063EACDD79AF15CE17AEE7BFCF42A4E4 +:1041A000CA81C6F3DDF7D3D9EFBCEC1B3C0CEDC7DD +:1041B0004FD633FB589B7B3616ECA0D72DEEDF0D88 +:1041C000037E7C43347DD73CB47C77B9B2A0CC6A03 +:1041D0001C370BD7397951B115C243372E6AB3A6B4 +:1041E0001AE8E97DC8C31A1A6CEFB548C5FC453A10 +:1041F0001FAEC3FB231B817C8CBCE6F69218FAFC35 +:10420000C6BA784687D5CD6D32D6D97786F5F9F41A +:104210007942F9694A458CA93EA7B4231DE0526151 +:10422000F32F7587A1536F867EAEF20DF58446E9B4 +:1042300076E0FF0F7AE2ECC870DF419D98D1433FF2 +:10424000A486D30F4B56A8A900FF25BBFBA602737B +:104250002C79B93C259C7E7873393B3F3CCCF32EBE +:10426000CF4CA1FAE10A837E981285F411FADE554B +:104270001917A91F747CFD9BE5CC9BA01FC2F0758C +:104280004586593F4C6B9D85FA61DA1491A8867872 +:104290005C69068FDF46D40FC529D763DDEA8E0936 +:1042A00043376F72BF04E00A25CC037AE28E0C26F6 +:1042B000F743F5452479AE5CAC3CFF5F82B32ECF6B +:1042C0009750FF85FD0E4E281D1294D74BAE17F068 +:1042D000F74B96EC66F27CC94D3C2E19225F2B41C0 +:1042E000BEE61BE52B7BBFC6C3F441EDCEAC8766B3 +:1042F000D0E7373459DD76DAFF86A0BC2D30CADB33 +:104300003B32241DCE994A18FC4E9F114354B3BC36 +:10431000CA01397574D04B79CF02DDBFCEEE99BD9D +:10432000CFF5F86B835ECA8778FAEFF9B89B391D31 +:104330009D5E4E1694513894CE65F6F0E2ED22C2A1 +:10434000A1A685D97935DB04BCCF3B72F017786E16 +:10435000B870373B3784EFF9161BF0B8F0F58EC60E +:10436000DEF07C9380E79E55EE85ECDEDF061627B7 +:10437000B6D3FF205F624D74EC6682793A1AC69B11 +:104380001773B855D83A0FC0FB158F0BEE4D28D7D1 +:10439000CCF1E9C539633F00BF60E1B69076F71A0A +:1043A0003CCF580C7167831FD2C6F7778BE8CF7B61 +:1043B00016F2027F2786FDBDB3B65038547F4738CA +:1043C0001CA270C8FFF670A86DBD17F36FBEEBFEA0 +:1043D000F76570FB7030C9077E79DFA221FF7B5F34 +:1043E00011F15EF1DC7BFBA51AF3940E6530BBE2A4 +:1043F000758BA7310DFAD5B0FBC7F3363EB31FAEB0 +:1044000086CF682683206C3F6F83594F76EBE51685 +:1044100015F5EE8CBA6704F89EFF2D22C1DF019BD3 +:1044200033D8E681F3D743519D28CF743AFC12E884 +:1044300090C2FD0B3EEFD15E9D65E857EC1414E48D +:1044400013F89E06D4291EA2603F577D3E92C31DDD +:10445000E333B53B199E6A295E80CF46527B17F441 +:10446000C88D54EFE079596B9B15FA57D37E892894 +:1044700077DCE8EFEAFA09CEEF8A530C78DB7D842B +:10448000D1EF56C14DC2E02D97FE773EBC45C29795 +:104490006E3F5C2CDE74787CA9CB6F8EBF4351EDF0 +:1044A0001543F09C8AFD0E10698DC77395634D7D91 +:1044B000118F519982E9BB32DD7805FD68882F5D47 +:1044C0000B0BC70FD747619E1CCE9BCDEC21A37C65 +:1044D00009F5A36B493BDA35629AE7E174435ED88C +:1044E000349EBFD27DAE1BEC37392339723FE22AAE +:1044F000C1F31F3DBF167E390AF3C1787D5F46C107 +:10450000E11974BF9FAC16F17EF27516F5AD22E08D +:10451000E3B5560274F9C96B568DD9A13128876766 +:10452000BD7ED40AA19159905F40FBCDBA8BC9DB07 +:10453000A330186DFB13D5631A7CB784340F85BC88 +:10454000FD29EEB672C8DB9E9A7F68259CD34D2E5E +:1045500055DE7A0BE0BB462400DFF75697A2BF7208 +:10456000DBAD02D2F5DBCBF1B7B0C8D429596FBDB2 +:1045700045E7BD6975329EB3CDD0F69703BDCD99A1 +:10458000E874C039DDB85C91780C70BC89B463DC28 +:104590006246DDAD5361BDD5542F40DCB5BAF55050 +:1045A000792AD4370AF83B6AB55E8F0C57A0DA3700 +:1045B0009C9521FE5245FB017A6A37B27EB55B04B9 +:1045C000BCDF5345E503ECAF6A8B40E022493BB5C5 +:1045D000FFEC6C5C9F9D8EDBBE91BE4FEBF3E07DEC +:1045E00018774B3CFEDE5DED6BEC7E5055E18A03A7 +:1045F000209FAAE87BF43169DF722B8E377FA340BE +:104600002035B8BA30EB478530DE6B56FC2EC8E15A +:10461000B6876558F7CD74BE343AFE1CB1A31CF3BF +:10462000ACEF1014CC83FEEA07C80767381F90D799 +:1046300096313E13789DDB85BA7EBC37339BE5BB54 +:104640002F5BD108FBEAF02667814B54BBF3AC0C1F +:1046500076DEB1E5F0E1198A379E07B7CF7B54EEDD +:1046600030C8A9A733FBB2EFE4EF2C463EBF855418 +:10467000E2B9B86705D3CB475646F904B047AC0A50 +:10468000EACD7D2B2F7D10F67FFA292B9E979ECEAB +:10469000E8C0F8EC898D56FC6E48FD4611E5C889E6 +:1046A000ED2C2E243E3275641AC08FCA01A0BB7D4A +:1046B0001B4B659087277C02BE5FFAC8ED292CEE64 +:1046C0006B961F55EA0294178F4431F9306F43F807 +:1046D000F3D588F262E94826DF43E4C1E2F4468C70 +:1046E000FB85CA895AE2D0E5C360A8B7FBD3907EA8 +:1046F0006B5EB312B0EF6A24E5E60D403733A2E0FB +:104700002499F2857F3FC8B74F7C82EAA5CF6F9C82 +:10471000F99BA100BFE3006FE08BF58978BE5AE5F5 +:104720009B8570D5F311E76D30D3B39EF774BD4709 +:104730000CDEF3A1FFBBB13A8668867E87EFA274D8 +:1047400049E79BB953C0EF211DBEEBC881DBF3B134 +:10475000AE001DD62CE37A75BD13E9F6F00FCEAE90 +:1047600004BABCF94E01D74FBC9E46D02B351B0472 +:1047700015E29AF3EE64EFCFA3EF03BD1C7E98D150 +:104780000FA56315E8BC66E3BD07B0FF164185F1D0 +:104790000F6F9A857AB8DA2B127CBEE508DACB5413 +:1047A0001F60DED03EAF9802745ED3605300AF3A14 +:1047B000BDE8F477847F7F9AD8DD0327C3EF536485 +:1047C000AAECBE7C08DD89D3B390BE6AB75B915E6C +:1047D0006ABD8C9E8E3C25221DEE5B79DD48A09F34 +:1047E000D35B8508F447E92B3F485FE223567C7F83 +:1047F000DE132CBEB06F23A3EB132DCC3E2D7DA476 +:104800001FFA35F35EB712167F200EA3FD71213A11 +:104810000CA5BB1E7A89D36124BAF3589BA741FE2D +:10482000C1ACA7E9FAD520BC4A1B7F807180D2C6F3 +:10483000EB71BF3AFFC0BD16C8DB98DBB482E5332D +:104840004A2CBFE71BAF2B641DCB339D41FA175990 +:10485000FE899FAEE3A5ED8FA11DF0F12F8F607E45 +:10486000E3C21728FE69FFD3DB9DC48F76B60FE540 +:10487000CC821611F34B89E42F986CB8BFA5E7657D +:104880002CFC9513E1BE6087CD5741DF5FF0DCD192 +:1048900081784E7E37B353BDBF64DF9921DE8E81B0 +:1048A00093213F5362F921A1FA3790C9E230A77EE4 +:1048B0001383DF6312B6B5E139D382E6EBAC36433E +:1048C000DCF24CA615E7A5FDD83D338A7F385F841E +:1048D000F5197F4F42CF0B39F504E39F053BAD68D7 +:1048E0001F2DD8B609E37DB5DBCE62FE6CE9AF9E25 +:1048F0008A0538D4EE14CDF953DB44BF0DF3BCC4A4 +:104900002336F65D0E531E534D0BBBDF51D3CCF354 +:104910008442F26716FE6AF7735E0A9A85CF3E1EDE +:104920000BFCF461FBD65880271D0FF38F2616462B +:10493000C84FBA505E52F31A9E97341E7FA7233495 +:104940002FE943F807D5E3997D42F2BAB631B9456C +:10495000B15F10EE1E926EBF2C7CEAB347218FF63A +:10496000D48E8F1E85F52FFA9F4F1E85BC0EB22761 +:104970004A017BA2F6976F62FEA1FE5E611F664F41 +:104980009D7EE271CCDF3CFD8E0DEDC2D3BB4F644A +:1049900082BD70FA992F52202F73E9EE728C4F2C42 +:1049A000FD7529DE0F8DE46F027DFA2E227F34140F +:1049B0001FFB5A44BF83AEF3E3B76DC8FFDD7966D2 +:1049C000CD8B59FE9ECAF3CBB687CFD3D5F3A16A60 +:1049D0005A264F1C0EF2AE85E9F5EEFCA80BE595C4 +:1049E000FD91E2F58A8BC0DF769E3FD83C3E6C5E3F +:1049F000D9C7F00F8AA76921F8FBACE5969FFF1491 +:104A00009EB584BFA7ADF3F585E0A6E701F7EDA35A +:104A1000CDEA037CB4E349CCE303BC55A8A0FF3F37 +:104A2000CB84F8E6496B27C60D3B77DB14C8F75AF1 +:104A3000B0FB30F2CBE95F1FC23C5BC2F3714F9316 +:104A4000EE3F9637C96317B55B9C2C1F8DC31FF2D1 +:104A5000D5D4586CE779698C8EF57CB548796A0FA6 +:104A6000F5C966F1439E9FBC586D971547105F804E +:104A70001FA110F075C494FFA7EF3B743C05E070D4 +:104A8000A531FF32523E20B7D37BE08BC9E5D39BE3 +:104A9000783E66779E2521E983213F88E9C35A9FA6 +:104AA00070381C7EF5FCCBFBFA70BF53E74FDFC5B7 +:104AB000E55D5E78DDDF0E2E0D7DD8FD001D3EA785 +:104AC000BE0A2FA79FE2FC4EFD96ED7D0CFECD4C5D +:104AD000EEB7E87967FA7A1B9B995E3EB58DD98D62 +:104AE000A1FC5D13E1F7B45EE8C3E20D353BDB06E4 +:104AF000821C3AB5F7379CEE7CFC1ECE11D9CBE573 +:104B0000B6CF28B723FC7ED97E3E1EF577C38E57DD +:104B1000BBFD6CD8F13E94B4EB60FD1FB6333BE4B3 +:104B2000C36631ECEF20FCAA8FD5E407363A65F472 +:104B3000BBC4D86894474B9D856FC377DD963A65B3 +:104B4000CC77A85FC1F323EE72E3EF78D43BC7E2E2 +:104B5000F74B57027C0C7EA855F1E0EF4E585D955F +:104B6000F9E05F85DEEB94932CC467C4BFE4C5FB1A +:104B7000BD13B23F9740EFB42F37DF1B699794FD09 +:104B80008974BCF632C10DF66E4F3A338F7FAD2675 +:104B90009AE26710AB867D75B9D9F7D09C16BF42F3 +:104BA000BB106754BB0B1D3D95FD5E35FC4C179C3F +:104BB00083AF5D6ECF817B5CB1C48DDF1976BABBEC +:104BC000EFCFE0787124246F9BFF5EB5830B95389F +:104BD000A2B441DC223A97FDFE8342A2DDF0FDA2A1 +:104BE0009FC46A78AF69BDD3837A3822DFB8D9BD54 +:104BF0001A3D9E1457C8EE51FE5FBBEBC4160080F1 +:104C0000000000001F8B080000000000000BB57DB5 +:104C10000B7854C5F5F8DCBD77379B6437D9900421 +:104C2000C2FB6EDE0921591E09A82837E16110D0A8 +:104C30000511505137E1FD4AE2A396AA9505621A83 +:104C4000296D8380528BBAD050FD5AB480B4828DC6 +:104C50007603D162AB36A0566DD52E101194C70ADB +:104C6000948FFAC3F29F7366267BEFCDE681ED3F0A +:104C7000FDEA30F7CE9DC779CF3967660921E40A8E +:104C8000FD7F92A6B485EC04FFA09E4C747537FCA2 +:104C90005723A4373CA77F2A211365072123E977EF +:104CA000132C811809DF4FC9A2EF1DEC1392944A0F +:104CB0003C41783FD5E1F1D3F60E876F0A49206475 +:104CC0004382F6A6444BE2518E8672A12B955C4935 +:104CD0002724B120E4B7D0C789A3E973DD3CE89F5E +:104CE000E475E2FC8E9AE677543FBFFEAA33E5787E +:104CF0003CAD2844B922D3F1ECAD84D0D2E951CEF9 +:104D0000C13891FEFC4429A1E3F0792612FA9EF6FF +:104D1000E396362A57E83A5CC425910C1CCFF4DDA3 +:104D20000017F60F75DAEF5EF8C73584F45BA6B6A8 +:104D3000D8E83ABD76C90560E843E7DA0A40505A38 +:104D40006D008CA71CA21EB49102DA6ECF215B8885 +:104D500096CB771EC2F716A8D332395E1DDF7F18B7 +:104D600021930359DEB43C68579166F160BD554903 +:104D700025A46E9A2FCD320CA69FD5D0328090E715 +:104D8000494DBE44DFDB6BDDAD07AF27005A3A1952 +:104D900078EF6ED50AE03DAF131224741DCFC7B56E +:104DA000D7357B1AADA7B7D7FD506F04E05F0BE393 +:104DB000B95B6BE9F7BB54EF44958E3BED190B9152 +:104DC0005208197BC91190800E42BD08E90B9FD58E +:104DD000C4015EAEC0DFD84809F025A99176E6F798 +:104DE000E676749EE53BE9FAA7F92ABCE347103260 +:104DF0004A627025AED088E94E9847E56CB538F226 +:104E0000DDB467CEC9E9747EB3294D11FA3CB1DC3B +:104E100075532E9D5FE2160A2D15DAFBEE82796737 +:104E20003DE2B300798C25A1FB258A4FF2490ACED9 +:104E3000478C53F79A8CF45BF79825B01AE957958D +:104E4000BC43F5F80B99F01766F8DB7B04F157D5F6 +:104E50007484E16FEFD666C07F5593E48A51613D5B +:104E60009E5D9488C8FD816BBCCA408AD798701D2E +:104E7000E0D54A4679A7C4225CEF85F574802B9F64 +:104E80005F77707DFEC4B61F17D2A6FE53164F166D +:104E900089C04BB4DBACDA102E7DD27D8F021CAA08 +:104EA0003786EA62E9BC5E3D7138C147E79B75EA27 +:104EB0005CB090CE376B0CB271FBB8CF9FDAD66C7A +:104EC000A3FF7C1EE898BEC826BED52E4757F060CB +:104ED000F4DD0E8F3D47103E16A8D3E7BB6D64117D +:104EE000E0B56CAFA40580BE63C83D5E5AAE572DD9 +:104EF000B88EEDAACC4B89E1F154BAA2D2EFCB66C1 +:104F000058B4002D137919597F2DB6DBAE2A580AF3 +:104F100078087C0A3A22A4217E1AC5635A8EEF597A +:104F200023DD3C119F4EDF8F6D3B7A3FB144BEDBEA +:104F3000BE9278E75923ED28FD3C6CF86EC2F7E28B +:104F40007C0591F64097402766FCD0EF7630BC3E5A +:104F5000110FEBD8D7764E0678F714AFE6E7AD2BF6 +:104F60007DDEF1D6CEF9C75B2A7B01AEE6E7418054 +:104F70002FC2C7EE6FCB05A92D91440A6AB9AF2F96 +:104F800008F35B6E0F25CCA0F8AD2A3D6F0338AC5B +:104F90008E3F739D2F4A3F9DCDA3F5728EC34BD795 +:104FA000B7FF520CC2DBDCFE2B8ECF7757CEF68ECE +:104FB000A704FA785C42210A5B3F793F93EA87F1C4 +:104FC0005CEE8ECF5C3285092DC5CFE5B8742586A1 +:104FD000A0425068BB09F084CEAF7CF42E85A44378 +:104FE0009DB613F2D88DFD6E2345800F6B1B3CB729 +:104FF000D3FF811E999C79D349D02FAD4A684D22A9 +:10500000057D6B9A84FAE7C6CB0D2DA0BB6E4CB321 +:105010001AF4DC24D5589F0C7A4F37CE348DE29D9C +:10502000BF3F8FFF0DE0FA6E56296869FF3767C6EC +:1050300005FC74C9B78CBEDD3B5EA72F0E7D2BDF50 +:10504000E32DE8089FD16E011F2FC2F595580A9FE6 +:10505000225867452DD3495DC3C30C47335CC67FD7 +:10506000B2600A29EC08979EAEBF1DAE84FC04D640 +:10507000375993C95A7704AE66F8D0BFA9D0EE501D +:10508000296D27815D704AB1D0FAA46B2422EC828D +:10509000097ABCF3F999E16A869FB03726F3EFDE0F +:1050A0000678517A9A2C6F71003D4CFA61EBF864E6 +:1050B0002AC7260D64F825410A5CAAD76F20083359 +:1050C00080EB36A43B9715ED0CAAD7197D7C32F105 +:1050D000A444C79F7289BEA3F39CA84A01CA2200B8 +:1050E00097A326B81C35D1C551FDBACDF37D05FE79 +:1050F000714D147A511A7281EF8BDCDC3E1944D465 +:105100002B541F957C3C3291C987E87A72EC256F4D +:105110007B3F0C1E0D483712F1B53F77D17E829A46 +:10512000358582818CB3BB904FC6116D4D9B1D4060 +:1051300021E33CC5BC4EA6793537FDBE944C5AD30D +:10514000A687F327429F33788FE3F01B47FCCD728D +:105150000294CA05FDBA457F93C47A0693C1600FD5 +:1051600035AB2AD3FBBC3FB1BEE4641294E804C360 +:10517000923DB04D82F913BFAD57643C2BC7EFC7CA +:1051800099D36F75A3DCAA21002F305B009F65FCCB +:105190007D99DD1184F910BBF5543B5EC086217307 +:1051A0005CC787205CC895F8C8FC2ADC92723C3743 +:1051B00032BFD307ED7E99D2B5A7AF6FBE9BCEF3BA +:1051C00094F47621C08BDA65D920CFCDEFCF7FD490 +:1051D0005205EF69BB05D88EAF6BA92C21DD845F2A +:1051E0008B096C734793E7AB98FCB5534BB42442DF +:1051F000F765718CCF2713AF02F6E5FE58C6672D11 +:10520000B18B911F26929ADAA1B4BFBFC4DD78108A +:10521000F86C12F163BB092E231D7647A73791F076 +:10522000DD60F74ECEB59AEC683FE2677F6C4E26A4 +:10523000E8B3FDB14C2E0BFBE149B7778D1BDF0FB7 +:105240000A805C3EAA15BF0B7AA2B274C4DF46D2B4 +:10525000D262F7DA009FF381BE285C47037DD16FED +:10526000F743D77D91BED601FEE6D69BE8CB9E8C58 +:10527000FD7BA91883799569D66FF476753BDCB808 +:105280009EECCE5E242D0AC9A5709DC7E9747F6C83 +:105290008C1FECB8B2C7291F53F8CD25BE671B245D +:1052A0009887D560BFCF8BB5A2BD37EFE7B1C8EF08 +:1052B000F4E32D3574C805F4F95ADA0FC95507E837 +:1052C000F53A69D07D0FF8B7AB488FF35CEC591B0A +:1052D000EDA36F2FE8974A370A4FB2D97A4E4F970E +:1052E000E6F13BEDD7F4DD7E89CC06BDBADFAA0E30 +:1052F000F0E8F4C76E37B39BCED9B3B658D23B872C +:10530000D3027BB2A68C88D48FC7C6CE8E66278880 +:10531000FE045C23FB8B130D2D6322FB0BCBAA2F0A +:105320004CFB8B2FFEABFDC5A1AD5FB4D6D2F934DB +:10533000647AFF0EF446146F1EC07D13B71729A5BB +:10534000E44DD3E1E1EF6E66CFF45E318E1CA3A491 +:10535000146327FED8E194DF15E2B70E87F6BE5539 +:10536000168A57653641FD43E50DDA99E6F57E9CD0 +:1053700059F6198C27F8B02C8ED239E5BBC72D6AA7 +:105380006303D8D37F96A96D49475F3117EDBC5BA6 +:10539000572CC6F2ECD1CBD9C0FF651CAEA7417F1C +:1053A000835D1DCFF8A73A9EF1CB2B69BED340FF9A +:1053B000AD9AEC1C49FB5BBA57F6C4E0F2C38360BC +:1053C0007DB74E9553E1F931BB15F789FB9D0CCFA5 +:1053D000C78854BE13ECDE4331DE3DB45C9056EA20 +:1053E0004AD7D9830BD2C6639D9453C38ED2DF7D37 +:1053F0007646F7C7889BCDBB5EF26CA78FCED5BB38 +:1054000013810EF75B89C1EEB0A4337BD992CEE055 +:1054100058798932E108465F3574FC4A45B5819D6B +:105420005F79C986CF611E487FB1C67EE2793FF1C0 +:10543000EDFD48E80CD81F6BEE4761CF391D9BF19D +:10544000F0A87B5C22AC67419AE64A4779AF2A0014 +:105450009FB2912D1F81DCEB5ECEFB2590F3D5979B +:10546000A5E060BAFE537BACB87F3BC5EDFFD37BB4 +:105470000EF4AEA4E5F25DEF25C03ED19DCEF075F1 +:105480005A694D80F92DFB1DB59B0B906C7BDF8914 +:10549000DFCF2D59CB86B1EBF5DFB5DF660CF062BF +:1054A0003B3AC19288FD35CEEE0FC0FCF6AF926755 +:1054B00003DEA87E14F69704F270C21E598B2DEC01 +:1054C00068978D4AB7727E63787CC0C5C6E98C8FB9 +:1054D000CB2EC593808E8FCB145581F9975D4AC032 +:1054E000E7A74F6CDB7033A57B7F9A15F781747B40 +:1054F000D48276A1C4FAA56CDD9249C769E1EB7943 +:1055000063CFAD33AEA3FF7C13F40C6D333EE44B9D +:10551000614C4D777125113B6B82CB680F9AED453D +:10552000A1B7CA9BD6D7F62700F7C0ADD7011D9EFD +:105530005008D061077BDA7E632776E37A84C7ABB5 +:105540007B7E89FBA53EE92AE3AB3DE727021D5799 +:1055500091E04CE8B76A8FEC0AD2D66F903D434099 +:105560007F08FDDEBEDFB97CC0EE01F91F2BBB5604 +:10557000C33AEDB739540AA7EBCE16A4A09EB35B8D +:10558000CB41FE95C56639E6EAE8797F8A5C0E7400 +:10559000F0464A86F1B97DC310D073FB2C4C1EB582 +:1055A0001CBFC311C276B7A6A0BD26F4BBC93E1569 +:1055B000FEB0495972209ADD4BE42D1B63E9FBC90B +:1055C000395622839D1E5A827ABF837EBFECC37DEB +:1055D0008059CF0BB8534823BF74B04F237036D8CF +:1055E000A98FA6533B6D08D2C050B03B8397372C90 +:1055F00085799E6D8A77AD46BF03B36BCEB62DD944 +:1056000030159EBF2DA31FE5EC6519F969FFEB4B23 +:105610000787747C4C3505E2E9E2B0AFCFFC81E24C +:10562000E7E2E7711E3F3C56760E89B62F16FB2542 +:105630003A723F4B1ACEBF9F6534B21BEE4F6F8854 +:10564000EC4F37A6E3FE343C11D446DA962336A05D +:105650008BD3D45487F9FA29F2B753B8DEA0856406 +:10566000976E3E2FA44BDCDFA13D0D72C54FCAFAE9 +:1056700053E3842C8AD34AAF03BB731A716DA3EB37 +:1056800079ED449964A5F531DBDD1E89D67783E198 +:105690000974FB3B39B09DC2613795C7BB69BF8BAD +:1056A0005B1B6C6E3AAE7F0F9DD4285AA7880438D6 +:1056B0009CB0FA0725E9E8645606932B27ACBEE7B1 +:1056C000A09F131FC710D8079EF83C2EAABE1D9C92 +:1056D000C1F4ED1FB89EFB37A7F7E0A957DFEC47F1 +:1056E000E715BCE41A06705FF2C2D772051DE77AAF +:1056F0006E974DD9D85A0BFE9B9BB78415903FDE11 +:10570000806B02A8DAE92F78ACA09766ECF05AC15A +:105710000C9FB9A7C60AEF67EF6D7803EA770477A5 +:1057200062FD7CBAEF8F00971BEAC307805C321BD7 +:1057300088027C412E307BEB533E8FF44B9EFD89DB +:1057400048D5A516A0F3F6F11F6955C0F4B9B9966E +:105750008D4FFB7B0BF074434D781CE8B7412B5801 +:105760007F8348F3AA4435D2EFD8CBAD92DEAFF0B9 +:10577000EC438E454CEE32B80F7AB8DFD6B5C82769 +:10578000AE38D0F782AFCA1E766880EF8B3F880BA9 +:10579000C4B881CE98BD7DF1078E803F8ABD1DA122 +:1057A000B3600CA32F416FC4CEEA9A1DE8EDC12768 +:1057B0006BE2407EA478559B4F87C7B20D53F2DF52 +:1057C00082FE6363D07FD73EDE7A361EFD3E1FE841 +:1057D0005AE8B34AA007835F4AC803C617B48B00D0 +:1057E0008C2B4A22AD76117D9D04D3603E9F03DC55 +:1057F000E9778D36750E8CD71817E382F12AED59AB +:1058000036905FED7E5070265239721DB73B5F3B7C +:10581000B13F19F07E71D8AA41B03F085A7E81F29B +:10582000AA3BBABB2D5DFB0FD3B7FE41B0BF12ED53 +:10583000F71D8F2B007DF9079077801F4FC56058AB +:10584000AFF8AE7F06D3F7945F70FD824F525A894E +:10585000B6B50041A5EDD6C1A337E70B51EEB6AA08 +:105860007EC667D44E01BE7306ED19C0CFFB32B0C1 +:105870009EE2250E0F7D5FBD37CB23AB28077A67ED +:10588000A446E4C3F55C3EA4B486912F7BBA4FF8DE +:1058900096C337A8ECE4FC45504E017F31391EEC2D +:1058A000CFE490BF3FE005E406C74F5F89960B3910 +:1058B0009EC5BA53B85CB84EAC0BEC375A2FC960D2 +:1058C000F247BC1FC9E136412E480C45F1FFB4D365 +:1058D000DD8ABE04ECC9092BFA635992C1E6BBD834 +:1058E000BE1EFDAA8B53D6A33F35456BC072F1F89F +:1058F000067C9EB6A502E963F166C9E01F15E5CFF7 +:10590000B87D76FA8405F51BB1C4F503FA13EF37B9 +:10591000723BA44FBAAF0CE07C72CF86270BD588C0 +:105920007FF8626CC3CD7700FD6F975DAB003F8D54 +:105930001324350A5DE9E107F0AA6EFCD744985FAD +:105940001509D5817C569B24949FEA5E5AF6A1C422 +:10595000DFC8E4E9496EA72D8A33DA97B338DC4E05 +:10596000585B2717D1F183E73287835F27A88464C8 +:1059700085E18F007F801C7621BDAF1DF410D09192 +:10598000E444FB07E4EA2E1D7D2CDDB1B5AE1FFD1E +:10599000E70D975DC364EC8738F4F25BD08990C75C +:1059A000E6F52DE6781574785D444F2DCEE07E54F3 +:1059B0004059D5FA73E8477D94E3AF11E80DF8B983 +:1059C0005ED0DB300BCA5B131F8FFA1FC9F77D4F08 +:1059D0003C3D08FD13A329DF52BE3E097C1D852EE8 +:1059E000EADAE5806F5546147D7052F23D979C11BE +:1059F000F97EDFF19BF22B75FDF8383C2E5A7D8342 +:105A00005D51E015812BE907F4B0886206E040B6ED +:105A1000482EB00BC5FB942D2C1EF014E723F15C2F +:105A2000D405BCC702BC3310DE4FC17CA95D600346 +:105A3000959D16607601B1DCD40FF4FCE238ED26BA +:105A4000F4C7ACB710F02F11A90CE93DA571D3F143 +:105A50006F4742199B8EF1156A77031D2D7E5CC539 +:105A60007DE2EA5FC5225DBE98918EEB5ADD6865E6 +:105A7000F4696D40FA3AF9F992C1109FF153BD9E55 +:105A80001545EFD499F4F943194C8F0ABA4B5FC707 +:105A9000E8AE51D1E2927474F93CD18683DC167A77 +:105AA000A5337A8CD0916B98A0A30AFA3CBD3E2412 +:105AB00003BE281E5F053ACC58174679D6191E45F5 +:105AC0001C4EE053C8F9FFF0F98BF1DFE6723E851A +:105AD000DB3B1DF1BACAC00FD747F8E12F0C3F11CD +:105AE0007EB0AA91F5FC9EC3A533BEC8CF7461BF3A +:105AF000759F6EB81BF8B96E7D9C673589C4734479 +:105B00009C55CCE3334E879DC56376A9BE4F334C7D +:105B1000F14215E53D8BBF4CE076FA7DDB63D0BEEC +:105B2000D807AF408EB4C505C0BE14DFE528445386 +:105B30008613F255861BE79F032284D65356D84816 +:105B4000261DF7E235CD2D09B4FDD470684A115DEC +:105B5000E23E5B68C62DE01726DA12B033D0970F0D +:105B6000F47F8AF54B5C3B0DF3FC1787B7C04FDD24 +:105B7000A773D3A2C50B041C3BC34B7E268F9FF19A +:105B8000F766FE6F15FAAAC7FCEB4F04FEBD81F85D +:105B90005741FC845C262ED0D3EDFC7B99B0F85C99 +:105BA000A6917F453D0AFF2666EAF9F75288F12F54 +:105BB000E7D3C446AB16CD6E19986965EB6A9C5065 +:105BC0000AFA28D14BD06F429789FCBE98F23BF07D +:105BD000B11FF8B60FC093C9DF74ADE16E789FDED8 +:105BE000C8ECF18B496CBD8BAFD79A65E07FBA1FCB +:105BF0009068D306CEEF9DC33D982831FD9608727C +:105C0000E68631A171A08755881BF481F531FC8EA1 +:105C10001D4302418A77F53261F2E3F3A7EF7E0874 +:105C2000E4C67A87274B8DE8A54FD37DC332533B1B +:105C3000E76B4A971AF8B1EEFBB783ED1F3B899FDC +:105C40008F5D2123FD513ABF365307FFB1DEB00C03 +:105C5000704D8EF7A55993E83EB0316BBA7D205D4B +:105C60009F9BDABDB45E4EEBEBC02FD72B4478FD83 +:105C70000947DFFF224F2033F330F8F1966768932E +:105C8000328B31AE3D19E67343FFB08CF2AD87F134 +:105C9000FF6AF0EBD1F51CBD2DFF5715F469E5ED5A +:105CA000DE3A782BFCCCA3B89FB9BA6918FA9F7575 +:105CB000FEE63B60BCCEFCCDDD8D9BC0F99ED237AD +:105CC000EEFF12468765908F42AE2CCAECC5E939CB +:105CD00044A60F8DF017C825B077451E02F8239D06 +:105CE00018CF0820FD413D717844DEAC6BB094477D +:105CF000A3EFEF673AA2CA53D2F47FBF7FA884AE66 +:105D0000175E31F9FAFD4C9D7C6D6C38DA9BD9AF8A +:105D100054FB537BE27EEE03D8B0DAF3D74CA0BB42 +:105D20007765F4C35C1363F34BE02FD088EAEACDC8 +:105D3000FB03B66B9282CE425AFF46221AF837BF57 +:105D400091B1DCF0A8B7DC0DFE968F2C287FABC09C +:105D50007EA3F0193D9804ECF49F7BB9DFB4F4986E +:105D600043833C81B3921DE5E7D923717ED0AB67B5 +:105D70009D16F4ABB7BC16837C713E338EFB41029B +:105D8000067F8988F79C7F7B6E32C8FF2779FCF3FA +:105D9000C958E68F7DF2F66CF4630A7FAFA250D843 +:105DA000F782B41E0AD75E6037F7473FACF0FFF6C4 +:105DB000B657482CE9888DA3D8D9FA7A2B3E09FC2E +:105DC000E75BBBC997F84DA64DD8C38D00E7EA47FE +:105DD0004236D8EF0A7B58E8EDC1A7D29B216F620B +:105DE000703973AF6D3D65B1C03AB752724A727780 +:105DF000A42F41475B3BE625ECCAD4EBA7C7585E0E +:105E0000427B9D7FF71CCF4B18DB76F465B0F328FF +:105E1000BF6F357C372135CE17456ECD5CF1307EB6 +:105E2000DF19FDCFB4105F343DF21ED72344A9E93A +:105E30000F7A8AFCF3C178358A3F67E6A795A900F7 +:105E400017B31F2E32FEA338FE3B99EDF1CE411061 +:105E50007FEB2EDE699EF7DFACBE81D1F494C0B338 +:105E600079BC8EDFB3FD597B3B1BF1ED72B07E87B1 +:105E7000EBFA55B2981D345362F17CF22D417D2D21 +:105E8000E884C2FD0BA08B92778E8D88C338505862 +:105E9000067970FEA3CC01188FEF643F2AE6432DEC +:105EA000E7AC68791F743C6F343C48594C8FCEB4D2 +:105EB000B23886747B16FA0766C6C648313AFBE4E8 +:105EC00074BBBED50C71DBFDB1A346A2DFD3AA0E15 +:105ED00088063F733CF774264178025C3C51E849E0 +:105EE000C49D059CEB4AB55285F9D5C83650811A38 +:105EF00093A329E504E36FA3240DE1910C467331CC +:105F0000D03FCBA73BFFB68C72A1A4540D4008959F +:105F1000EA8BA4AC62CCCF7AD9A2CBCF127452F761 +:105F200022D5CB06BFA3DFB0AF4EE2F2985A8FDA8C +:105F30002E5D3BF5119001117D30A0D66EA80F7A31 +:105F4000C045149DBE48D2D20CF5015E571CECA78B +:105F50000694AB86EF04DD89FC40FC4B8175BB02E7 +:105F6000901FD18BCF6794E443BA01F9067EE561B7 +:105F70001C9F74BD4559B41C5B1E3AAFA71BB1DE14 +:105F8000EED67574259D0F15606D2BE97CA95C9884 +:105F9000BBCEBD2A0DE1EE22B0CF38BED28ECFE708 +:105FA000F3EF933656D4F5A54324D5AAE8CF4DD2C6 +:105FB0006ADEEC0BF99835B44EFFE6354812F87DF1 +:105FC000A89CC1EF9E59E9C252E0DB45DF4BF4BD0E +:105FD000BF8CE4427CA7333DE6CD7218ECBE2EF4B4 +:105FE0009837ABB8A31EB3D83D6F417EC0F2265997 +:105FF00005BA5833A517FAFF36EC943CE08F3BD036 +:10600000C4F2F436CC64FA448C7BE67789A837CEA8 +:10601000488CCF494B12F2417512C74D6D12C66BB9 +:10602000CFF2FDF6B24C9F2F4B672F6D682A8EC5BD +:10603000B8AD492FD13F9744BFC3D89D04F6D3B024 +:106040007A2503E5C022F89E2C088D88CD00BAF58C +:10605000BD37460239706110E0D31C0F1471431133 +:106060004F7C25CD77AF7EFC8E7142637C4B4EB06A +:10607000E7029F8D96E33CB251FF12C0EB1AB013BA +:1060800029DDAD391287F059F32DE33F3ACF1F02D6 +:106090009C5B9C25484F42CFD27916BE4B3ACEB37B +:1060A000DA12463FA26E9E7559C55DCDD39407CBDB +:1060B000E7D50E7F1ED7929D0ACEFF2C89F3C03CF8 +:1060C000F7DA3C1FF9400F9F8943BF9FC04F15E788 +:1060D000B1B3141F129DE7D9BD23622D0EB08F7C82 +:1060E0004F02BCE481E104B0CF0F348DC883F57456 +:1060F00016DFDD9B59F67416F299EF19E43357E871 +:10610000FC4B6A64FD5DC485B742FBAB80CFAFBB7F +:10611000C6A3113ED58AA35E628E75B4C3242EA792 +:10612000CD74273535FF1BF29228BF615EA87F1022 +:1061300009ACA170AB1BCAE88FCC232AEA65139D7A +:106140002CCBF4BE0AF8127CDA057C5E8779DF93EB +:10615000E90D4209F3E83F1CE5D2FE2CA6DF5EB64E +:1061600059F07B96DF9244305FC71C77FF38B3F25B +:106170002DFC5ED85FB93EC95570557C70B86BF880 +:1061800005912E9673382D877830E4B3EDB19E32A9 +:10619000E44D98E0F0FD4CEF270C0E94CE46323AD9 +:1061A0005B43BA844708DADF93E93B06A5D34AE9A3 +:1061B000058032BA220DE0BC4BD5303F61F72A068C +:1061C0008FB3EF3078EC6BB3205D6F22F9C897C3C3 +:1061D0002DE7EE86FEA97C390DEB1A13DE29C1BE30 +:1061E000B9CF22D50272B97FD8235BBAA6DBAFB391 +:1061F00070FFE4BBC0F1703FE061C4DBCCAFD305FE +:10620000DD5EE274DB53B84BD95DF27507BAB26656 +:10621000A746E8AAA7F958942E48FF5E1DFBA3FBEA +:10622000288C3B34EF8B417955B55B42795EF5FAAA +:1062300017B85FAF7A35068972FCABB1F8FEDC1E89 +:10624000F6FE4C69F43C8284EC5EA8A796EFBCD7BE +:106250006BD4D37ED4473FD3CEB932E5485C367990 +:106260002A3BA7B086E73D89F86C02A7B3E4815EBC +:106270000DF450F20482F984090E96A7D8F13C027D +:10628000E3DB54FE9DCBA54A0067F3F904398EE5A4 +:106290001FA692755F039C92CB8DEF531DE518AF3F +:1062A0004D359D6310F02ECEE6F6B38DA4811CD93A +:1062B00069CAC710E5FE6C6E07D626E17E50E1F391 +:1062C0006A71DA906EEF73DA71DDF72591E429587F +:1062D0005750FF9BFB1165926621AAFE9C45791CD5 +:1062E0005175F651AAB797A1DE67763F43FBBEBE54 +:1062F00074C3FBFE8BF20DEF07D60C37D407AFB893 +:10630000D6D0DE4D01A0AF67D4DF64689FD530DD05 +:1063100050CFD97C87A17D5EA0D2F07EC80B4B0CFC +:10632000EF87EEBCCF502FDAFB90A1BDDC895DFE7C +:10633000A36CB63F92855DEE1CE903BA929D762967 +:1063400046B7FFABE4F8284D284F83B879AD7362A8 +:106350001AEC4F5B92A83EEEC2EFF65DF76D7E81C0 +:106360007F6E7F9571BFDB99FD548A50FAAB3A403E +:10637000E9A008ED2F7F36F72354A8D03E6C437D6B +:10638000A278701D3313ECE84F33F75F99AD1AFC18 +:106390007C621F205B3CAE2952E7F01274D91DBC11 +:1063A000EA395CFF5B78FDCD946F24F67BE6EFFE67 +:1063B000986DE1F6B86F5BB67E5F47C2B217F775AE +:1063C00017CEF809C85182764D75BC0BFD12663B9D +:1063D000408CFF4A9AF7372057CDF2D4BB62016B4D +:1063E00067A11B0CB9F3FDDE1FB3CDFBBD09B311D3 +:1063F0001F4936039C5E6CC7B366D8EFD52695E07F +:106400007EAFD6AAA5F564BFF762364178D7035EA2 +:1064100075FB3AD9E6515D28E78DF64B47FB9CEAC0 +:106420003FBACE0D60D749609725337B7DB784EBAB +:1064300016E37E07FBFCFDEC1ED8E731C453AFC862 +:1064400088BFBF67337BFCFE58F93BD9E3C7AE4634 +:106450001F1EB67A30CFFDF05499ACA2703C5F3E5F +:10646000AA0F89228F45F93EF7DF6CCB2188B7EE62 +:10647000FC1F87572EEAF2BCC7E1492C8F733AD034 +:10648000916EDCD81C46171939DC7F13C3FC18A7A2 +:106490007FEFC47309A76FFA208138212F6EC4489B +:1064A0003FE43913CF0390B7E37738D14F387D52AB +:1064B000F1C8554E1D5D8D66701EF7CA3B09E0FFA1 +:1064C00099BE2B23D5EFE89C9E32F8FA8812CAC6F3 +:1064D000BCED3F9CECADD272FABEAC54E6A734E6FC +:1064E000BB99FD46D3575419F878F925890492755C +:1064F00075A515F30A975F52F0F9E96CA35FA953EC +:1065000078F5109EE6E7029E87279D1C04FEF43373 +:10651000B1D1ED8F5B38BCDBE9C7744EA6B3F31F76 +:1065200025BCFFF3E5D7F4013937DDA666F5C4CF06 +:1065300025E0D47AF98B789013AFC3F99B28FD1727 +:10654000E5B0B8D2EBDAE7703C8294DAC3E380EED0 +:106550004BB93F3DCAB9807139E087B954FE3F3924 +:10656000173025C7782E202D478D7A2EA0BBF34DEE +:10657000D36CD1F55D6E047E1F00BFDEFF8CD505A8 +:10658000F35A08B613F8EFB65AD17FF7DEE51802D2 +:10659000F1942FB6587F09796E8B9EC9786623AD2A +:1065A0002F9A1483F19F855BAD2C3E37293600AEC0 +:1065B000AA455BBFD77B2E1DEF2BCAB7CBB2E8FB3A +:1065C0006736615ECD7B6D6B31BFFB24F0337DBEE2 +:1065D000E8DB1FCD04F8EFB3350C190676FF0EC9C2 +:1065E000704E634963ACA12EF20805FE881439BFD2 +:1065F000A1527DF2608EF1BCD68848DCECC11CE66D +:106600002FC13CFCAAA9ECBCD681E36CBFFF462697 +:10661000CB330C4E9A3565185DC7A4542BFA4BCC7E +:1066200079898420D2C9029E373CE96305CFE54EC3 +:106630001AEA443BF0CD95358807FA9D6382EEBC9B +:10664000C2A49F33BFCB2437CBABEF345FD194A729 +:1066500028CE0F75C84F8C9C1F3A1A8D6E36E4F009 +:106660003C45CED7078EB37CC4056FCB6C5DDDC8CF +:10667000CDF7F93ADE6BCBBFEB250A8FF7CA991439 +:106680007FEFF28D8F81DFEB0BAF44203FF48BCB9C +:10669000D1CFAD7DDEAE5F7DEDE77A003FB7962FBF +:1066A0006EAF035BDEE6BDD770EEA7E7F2A66B79AF +:1066B000322B87C521CCF2DD4CF7FFBFE4FBF44958 +:1066C0006F0CF23BB1FC1594A77631F968E673B311 +:1066D0003C17F332CF77F925D990BF9CCBE54044E6 +:1066E0009EDBF03D35F7713DFE1225B046423BE0A2 +:1066F000831CDA6EA423905C4A87A8756D8BEFCA61 +:106700007F43F7CF1F43FB3BDCBE4FA04CFE4BBF8C +:1067100032D0F723DEDE89F987673BC9436F769B6A +:10672000F2DA2463BCE0CB9CD266C8E77F50A5A513 +:10673000CEBE1E499990E73D7CC9F9F3A710B7ACCE +:106740007AEB22F2E7269B2F0DFC03FE7E36CFF676 +:106750002879231772AEEE3CC316EE9F27B9B9868F +:10676000781FF889306FE1681CFA89D6A669DFC006 +:106770007C9E4BD3FE0FCA2169DAE51C1D5E6AF9C7 +:106780003A154B74BBB83857D0BF17F5F8FC322A0E +:106790007FA3D0A19ACBCE01943E79FB20F0C77D98 +:1067A0007EE48E41201F5B368DEA32DFED67C09FAD +:1067B000547EFE18E47E56249EFA13CE37C2DF3D87 +:1067C000DFE6CDD6E769C9B949385EC235BB5BD3D0 +:1067D000299DB4AD93517EB739587EDB318752DEA7 +:1067E00058C0BE4B317CA7B0FD07D03DE563C5A1C5 +:1067F0007CA39747C5B90CAE9DADB33897ED136C2C +:10680000C46387EF6D476FB2831E9525CDC5FCFF2E +:106810008C1EAEA123003DFC88CBB19369BEA2DCE7 +:1068200062F88EE9DB6BB8BE551C26FD3AA0EBF88A +:1068300078639A3632978E3F314D2B86FEF6DAFC1E +:1068400043806FF6C645CF57BB2E97D923FFCEE1C5 +:10685000F4421C68BFE27832C6E96FC865717A0DF0 +:10686000CA1BFA87D7401E7AB3DBC5DB87F0DC1D75 +:106870007D3F01DE93B410B905F2E7E864E17CC422 +:106880001F4E1C2520BF12C26D04F269124C79B054 +:10689000A2FC0787DBAB3CEED991EFD83CBD1CFED8 +:1068A0008D945FE0BCA8E01788AF43BEC483AA8F75 +:1068B000F31DCBF7687CA297047196744DB5007DEB +:1068C00040FE29C827737ED08E5C76FE1DF850EA04 +:1068D000820FE7F379F6940F1B9F98628985793EC2 +:1068E0004430AF8372C26A3BAD3F7B9FCB03E7C7A7 +:1068F00032D611DC070D5C11B70DF649351C1F832C +:106900003792D5B1B4B59BE7F7897C6A776D48C1FA +:1069100073060FB1FCBD939FDF243BA1FFAF45FF82 +:10692000C67C4191DFE7CFB518ECC2DBD27D0F23E7 +:106930003E4DF9D89DE7817D9907790E3F11FCCE38 +:10694000F370C6F03C9C318D9BD01F37A6F14645B5 +:10695000A24D9E558212ECF79EADD114D037CFE5F3 +:10696000B2BC9CEEF2E39EE6FDFB01CFA99DE75988 +:106970003ED92E773AE4593E999BAACB2BFB01CB0B +:10698000B3FC7E2ED323CFF23C9A676B98BF6EC9BF +:106990000B8750DE8B71443B918F37E001968FF768 +:1069A000AC128A05FAB9184BDAF3CC57A1533E342E +:1069B0002CFAF90591576ECC271F1C0E97623E10DA +:1069C00021784F42BF3CD5A007B7865D71C02FDD4F +:1069D000E983DFE75E9D3E782A8FF14D14BDD9949F +:1069E0007B757A33087443F5E60128AF5A6F727DE0 +:1069F00029F4A7787F88E373562ED39F51F4E621BC +:106A00008E5783DE4C2101CCD320A72C1E7DBEA83F +:106A100028BDBCDF97D3B50F61BE63B83F25E1D475 +:106A20005122E9E45019E76B71FFC4F3BDC83DD3AF +:106A3000A2ACE37ACE9F963961BCAF22A1498A9A73 +:106A400087D6ECB689F8ED1730EF1B0653B92975D8 +:106A5000949B51F07106E6D9FF6DED0010C9B54960 +:106A60008DF1603E75818F73B968C768E7A114F036 +:106A70001F7EC5B88F14F0FF86C3C396A5FD1BC645 +:106A8000F913E7B3CEF0129BC7F0D12F8FD9332281 +:106A90007F7DB7C91E1D91C7E0322ACFC8973AFC47 +:106AA000C5E645B17B841C7E39DDEB80F7AF9ED80F +:106AB0001D0F7424F024E48F195F113E5B85E352AF +:106AC00038A7E6A576D43FE27BB31E8A7CEFC7F9F0 +:106AD0006E053A1AC9F27DF07C013FA720E627E84F +:106AE000DCC3D779205D73E715779CA7EB9445EA63 +:106AF0006A9E49E11409F83F497361F98713160941 +:106B0000E6E50A2B982FEFE2FAD1AC07A9B8E074BA +:106B1000C3FA798ACB8DBAD32C0FB1AED49706FEC7 +:106B2000FFDE59DAC83CE423AD18CABC2CAD04E63C +:106B3000D9EC66788ECDD346435DE40B98E7A9E5A2 +:106B4000B5E71D8C857609E3891FF421DC370371D5 +:106B500096049EC790A0B9CA408F256C21982790B3 +:106B60001C1F6E8E81F8DF26E2817353D97ED50219 +:106B7000FBAF8C07B4D550D69DE6F7E694123C7770 +:106B8000D99E47579B8E7974C06F7A7A9DCEE73134 +:106B90003D8FF125B5436EC963F39A06A5B0430452 +:106BA0001F756657E8F87076DED5F1E13DD0FE2A14 +:106BB000F8706E1EE3C379793DE0C3A579ED7CB82A +:106BC00004DA77C7870F71FE7BAA1B3EFC39A7CF7B +:106BD000E7F23A95A30FE54595A38C1E04BD031F6C +:106BE00082BE6FE0FD51F9B9321ABDF7802FEBF389 +:106BF0007A6017B6F7D743FAEFCCFE8BCFEFDAFE09 +:106C0000DB0279E3BAFD1EE597A7617E945F7E0102 +:106C100025E5972D8C5F54965F6EE2AF767D136607 +:106C20007202F2F3F4795ABFCB6BD737DB01CEE6B1 +:106C3000BC9C31267FFE3B9CBE9B7899103E4A400F +:106C40002E50B8BDA4A7D7E739BFF847B3BC53AAA5 +:106C5000D9CAC0AEDC778ADA91003E2E0FC66C6EC0 +:106C60003D007623511AE2E11EACCEE0D42B5F1535 +:106C7000F99551E144C7FF633479DA04787374B449 +:106C8000E7CDF8DA91C7E83CC4E1F15DE721E00720 +:106C9000F328C279A896B53A3DFF41445EBD0F780E +:106CA0001B3B3E2C139C57301EE227429E9201F460 +:106CB000FB911DBFFF24F2FD27B0DEB11AFDBE20FF +:106CC000F27D12B8F233408E51798676B286E71C97 +:106CD000EBDC8C1ECC74DF6863E724DAF1D5D00FCF +:106CE000F1E5557D5F42FF8D0A3B4FD258EF92D8B8 +:106CF000394196EFFB5E8686FC1A450E85AF520E33 +:106D00005DC843FB4CFB1794DDC9A1CB9CBFA91CFC +:106D1000FA3F681FCAE95A0EC5E7337839F2997C01 +:106D2000E94C0E25F076BDF225839F522787E2F3CA +:106D3000A3C8A107550687287C9A985F0CFE15CD3D +:106D400095CFF834295FA7D7E877C9D09F17BE4FF2 +:106D5000C5BC33CCB7F093384FB47D869AEFE86961 +:106D60001EB59A9FDA31FF8C749347BDE1D1900D27 +:106D7000E02DF29CC4B8E6FC6981C7AAA65523C8D9 +:106D800050C8D3BA3C08ECCAB347BE41FFC8DECCFA +:106D90004A0FACB3E5B55186BC2C31FE7DDC9F3685 +:106DA000412ED809FED973076DE8F79489FAD418F3 +:106DB0003A9FEA8356124039C5EE2910F130EBC1F3 +:106DC000BA56F0C75B89EEDE28DCCFA88940B7D67B +:106DD00083ECFE2692C2DEFB897D15DEB738DA1819 +:106DE000E74FD28C71FEE4F25EA6B8BF31CEDF670A +:106DF000B631CEDFD7678CF3F75F34DC14F737C6D4 +:106E0000F907AF2833C5FD8D71FE8CFAE9A6B8BF2E +:106E100031CE9FB3D918E7CF0B18E3FC0BDF7AD93B +:106E200006FBEA212FDC678AFF1BE3FD1420AD99E6 +:106E3000BAFB648AF6AE36B49F1762F7940D0BAEB8 +:106E4000357ED7C0EE39F0D3FF013CBF203E1BD0CA +:106E50009942C26FF687FC9680E409D2668BF7EE02 +:106E60002A817238F78B2FDC6CBC1F6171C058FF10 +:106E7000EACFE507210FAC1A9888F653FD82140873 +:106E8000B83BC7FBD2178CDF0B3FEF52BE9E73DCC3 +:106E90002838B745C6F3CC663A59F8D6ADFC5E3112 +:106EA000AD15EE8F107010F4E2E2F422E625E0B1A9 +:106EB000545E867C2EE020EED7AA32ADBFC37AF7AF +:106EC0006EC5EFCCEB36AF6353BE31CE473AF08997 +:106ED00083E509D175419C5CF6E79AF8C40887CE32 +:106EE000E0D753BE51391C62D28C7C13ABC699E9F2 +:106EF0000EF16D86677CAE919FCCF0747AFA45A551 +:106F00002F713F2AAE07E2217B25F2B4D411AE8B5C +:106F10009AD6D7F58F424F840430CFC30CDFE67C7E +:106F200063BC6597EA6B01F978FEA30B32E2D517D3 +:106F30001A01FAAC8BFCB383BC7D4FE3ED87F2758D +:106F4000FE1173BCFD2CE449EACEAB48ED78D34C7E +:106F5000799207FE0D7124FA8DCF067ED8728F9D2F +:106F6000DD1766CE5FF3FD331FF5B046D00F788E88 +:106F700078D6D0FED6387F3FA41BBFC8B1FC62963E +:106F80005F00FA6B6C3874FE25E85E6975C138D114 +:106F9000EE29359D3F3C0DDF77760FE4F3C49B4728 +:106FA000A2C4ADC5FE55D8ED749F74219FD9331787 +:106FB000A1BFF67D52BB7DDD753F228FACB352DAA7 +:106FC0002FA35E0D4B719E68F798C50E31EEFF75CD +:106FD000E73D6387E8F468D5F7CEBF09F3A0F07604 +:106FE0000CA1F3743AA97D23F5C8BE71413F4FC58A +:106FF00027205D87DF9203396EB8DF4A4DEC55D00C +:10700000F19E2691575803F73025C3F3BCC4AEF266 +:107010002FCA4CF76099EF33AA1BCEE695CED7392D +:1070200085DB5125BC2ECEA5097F5CF56CE66FDEB5 +:1070300064F263960C71627B6F665909ACBFCE2D0A +:10704000A1FD5427498678D2F1FC527CEFE1FD97EF +:1070500000EF15E3F93A9C578A691F7F8EB73F9777 +:10706000CFFA857BB180FE6CB21C159ED70D61F303 +:10707000FF3BB7A3BEC3FD34EFC78CEC783F8DF95F +:10708000FEC489B9352D201ECC71DFDF75773FCD69 +:10709000FB13A3C67F01BEF1BD22743F6388F19E3E +:1070A000C4609C6FC354F047BC237BB6E157AD234B +:1070B000F4FBB48A21CC2E5DC7F72D1057C2FD0812 +:1070C0002FCD70AAE0706AC8F45600FD6DB2B5DE2F +:1070D0000FF41BB4B1FB42C31F101CA7DF22AD1974 +:1070E000EAC55E15CF57D4B98903EE190A0FB3A0CC +:1070F0005F24C5E71A0FF7FEA66C917A0138855C0C +:10710000B02AC4EFA4F4B276881BF1B08EAC6986C5 +:107110007B5112B77C4DD2713FE11AEF0279348F67 +:1071200044F5733ECCE963DA33E90AECCB12EDD1D6 +:10713000EF79787888C863F33E04F431D67E6484AE +:10714000847A82ED43606B8BFF69B318CE358BF286 +:10715000BD8C717EF84ED0F3F532A9D9E56074A6E6 +:10716000BF7F6DED90ABF34F172F2251FDA8DBF9D8 +:10717000BA72546F03C0BDF87D15E31F0B85DC9F09 +:10718000672170CFE9ED9C1C6FDFC2F2E1C9E52BEE +:10719000576461C713EC9F403C62E1326700E21321 +:1071A0000B9BDC78FF1F592461DCA4BAE99017EA35 +:1071B0000B478E74A1BC8C9724B807124C08261F6D +:1071C00015725CD09FCC8144FB9FCDF50DD52BEB88 +:1071D000E2E9BA166ED9DA0CE72CFE410D08C0FFC1 +:1071E000267E6EDEBC2E713F5DE4FEBC4F36E9EFBD +:1071F000E7B6ACFAC707C6FBF3FEF1C17F737FDECB +:10720000BEDFFCE303B89FDB7C7F9EE0FB8F64DF87 +:10721000470FD37FDF4695F28AE1502A640EE229B8 +:107220000DD73983AFD3FF0D918EDB2370B9ADE954 +:107230002D84F747563A1E651E6B19038DF5A14440 +:107240008C2F8B7CA499F68609A0D7CFDAC28570E3 +:107250005EECEC6B1F0E84BC834F7F78DE097908EF +:10726000FF54C24E787EE291F79C1AC5EFA78FB00B +:107270007BB6EEE6FA52C0ED1F9C1E0A0BBC87815E +:107280001EEE59F96D89FEBE20B22215F5DCE280B2 +:107290008C292C428E2C7D211E2CB9F6FAF29DC928 +:1072A00086BAD07FCB63484D34BFA8AB80F1CDE226 +:1072B0001D5B6DFD5518DFD706E39F80C4694A3713 +:1072C00027F638D14E16F3A9DC31CC0676D53F9B94 +:1072D000624810F66B4AAB959D37D5A648945E7D03 +:1072E0009C2ECDF37CF3F578EC6FFE26266F2BE811 +:1072F000582B285C7D4DECBE4FF33AE67FAA4EEC4E +:1073000043E13DFF716AC1A8ACFD23146FBE153F78 +:10731000C2FC71F33A2BFCE6FB3D3594F70B397E4A +:10732000E7D61BDF2F6CFA31F6338FA8EB204F72B4 +:107330007E83F9FDA42F8048179AF2D16D055C1E5B +:10734000979051208FF7DB3312A39D3B15E5A9954C +:107350002E64A22F57DAB13CB192607978888A7096 +:107360005FD674E841A09FAABDBBF01EA696C0845C +:10737000144AD6E4C6A6DBF1FEDA1B79DCFCAE8E3D +:10738000F78BA6151443FE91E9BC375FF71C8E07F7 +:1073900071FE7B0EACB7109E2B17F4EB397730C320 +:1073A00001E3BAC5BA46D175C93D5F97588F589F5A +:1073B00078BF9CCACFA8F1704EE787B9BC9ED7387A +:1073C000ADAE1F05C59AD7BE40FF00E1FB92F6FBAC +:1073D00091ED3F6E85798F27A67D899FBC4F74F410 +:1073E000B69068783FAC99AE049EA9DEC6EFED7CFE +:1073F000DFD24E4F4D3F41B8087CC30D82FA7BA9C6 +:10740000285D19F609948E0CF5F90DC6FA196B680A +:1074100010F0FB42D3EF459C31E5D388D25390CE98 +:10742000E0A06A13E1DCD07CE2AD6379C7ECDCE17B +:1074300009A5E1CD87810F1B191FFC93E37F6781AD +:107440007716E09F285A21DE17B9BAAF0C171F57DD +:10745000AC935CC05F736B87E1FD43C38986FDDD40 +:10746000D589DDF910E7FFCA1A2BB15163A1928EBD +:107470000172AE728F2CEEFB724CED0DF7D7303EE1 +:107480005AFEF82E5B5F5A2EAA59C8ECA100E31BE6 +:1074900071AFB6A03FA19F96AC6B46BF03DD6F19DD +:1074A000F8AB1ACE8114021F9B9ED7DC8878A836D1 +:1074B000D945DF2BE0FB330FF1007DFA1E74DAE1D2 +:1074C0001C5977EB261DFD49E86F3A77300BEDE547 +:1074D00073AADA07DAF912D83DFE92E21B05CF292A +:1074E000BC508F8657C5E3BDC6472EC944C5FB5562 +:1074F0007CA3E0BC7FE8EF0309BBAF8DD1AB586F35 +:10750000B57D1DEEA3AB4DF45A41376CE027AED8E4 +:107510009E8C796AB4FFC2BD605F6DB7A2FDE4279F +:10752000F7A5C1BD1ADEC7D8BDBC957B93701F5FA0 +:1075300059CBE24B953B92F09C30DD47BF0FFE19D3 +:10754000818F23B5E36C7D115F6EBC2F8CECB5FA97 +:10755000F93DE748E7024F1DF7C1263CD537BF99F3 +:10756000A676DC17EBF0D4D6099E0CF758FE5AC865 +:10757000118E27F208973FF7BE910571B57335B1AB +:107580001E39CAFEAAFD3EE379D7623E9DF03F96C2 +:10759000F713BFAFE0E90D783DBFAE18F166C657EF +:1075A000F97FE6225EC8DF9D04FCD27765907BA65A +:1075B000D3E7F7488C5FEE5A33A91CF4F9810266D1 +:1075C0001FFF95CA2D2D879043546E69546EBD4799 +:1075D000E519D43F589986F50F57AA587EBC321743 +:1075E000CB366E170A3EA2846003BBF2AD0266EF93 +:1075F000BC5520FCC10FA4816951FE9FF78A2DE084 +:10760000EAF5CF9F3981DA3BB768467D387B8651F2 +:10761000DF85ACAE89707ED9FF38BB17AED27B9DBB +:10762000A13D5154DB34D8D7E78E883C477E536D5B +:1076300070FEFEF629C986F633EBFB1BEA470A54B7 +:10764000764F507986E1F91D738618EA15FCDE5BEA +:10765000A28E46BE7980E7C912329AE185E7DF5CE7 +:10766000A819D5E7FB74BE17DEB6E27B333E045E95 +:10767000E76D96898FF6377733955F748A6D0D14B1 +:107680004FF4BBAF3E72C2591952B763C4BBA36972 +:10769000FDC80E96AF7BA436F9A7603F1DD9919A1D +:1076A000007E635F9DCCED0C17DEF726FA1D57BBFD +:1076B0000AF3722A023178EEA2A2C5FFACA8C34F2A +:1076C0002EA089077CF3BE1C084A883FE6F7F875B0 +:1076D0000CC62D4E50BBCE45F5C40989D4420907CE +:1076E000C512E9FB7FB5A60680AFCBFF236B6940CF +:1076F0004FBF8EE5712909FBFBF250D6B6B5485F46 +:10770000EACE20F26F0CEE8FE686D8FA8834BC3FC2 +:10771000E0FF4412D192E82496DFF7E1670AC5D36F +:10772000E2ECD642B817678E3B983A8B7E77AAD1A7 +:10773000CAEEE9A7FDBA687DF96F62F8FD8F5A1F9E +:10774000D86F44E019288475A7F6F3A60EA5FCF1BE +:10775000E5824021CAB5475291AFCC706FB3F910A2 +:10776000BE7EE003292227237CC6E28D54B8F505AE +:107770007933D7EAE90DFAAA6D9D95DD8FA76809DF +:10778000ECFEC9DD48C76D8A3A11D6DD56EFC6FB5F +:1077900083C4B895EB648DDD5F49E912DAAF977D5C +:1077A00070DF8FD05BFE7AC907F70299E9E6FE7BAE +:1077B00047619EBFD9FE15E519CAAB3E9D1DB1E4D8 +:1077C00035197FD7838C0C29330CF783B1DF3F2128 +:1077D000BED186FCDB65E97FFACC6141BB2611F6A0 +:1077E0004527DF9791CE4EA63794A465403ACDFE4B +:1077F00092EFD3FA5753FDC7E11CF13D837D65003D +:10780000D7A59675CF4A1638777DECA770CFEE973F +:107810002F5A3D30EC925F2F1E8C71096E7F77944A +:107820005B9AB0177AC33D5115AA0BF5B85A2B11C4 +:10783000B6FE00CEF34EB2F331C09B6B197B7EAC2B +:10784000D8B916FC03734DE7D88EF17B3A660C6508 +:10785000F244E8FB0D4399DD34D7C2E89ABC2EB15F +:107860007BB4F8EF5F087D20E4B590FBF38632FB34 +:1078700042C86B6A39A0DC5A00B747D1752E7B210C +:1078800086F9D355E202382E6668225B873279B1D9 +:10789000C4F6E293C04B0B492BEAD32FAD8105AD63 +:1078A0006EF87E6B6D2FFCDEEA41FF32D72F70CD74 +:1078B0003FC8A5859CFF963748781F14E17A723E31 +:1078C000EF9FBC608DE88DF428FAC5A457E673BD20 +:1078D0003A9F98ECC006A3BEF3C6B3CDFE123A2E73 +:1078E000E8CFC8BCA8FD4C61B7C01778F3669CB759 +:1078F000E4094499C742120EC2BD58CB77307FBD10 +:10790000795EE675F4749E0B3CD3C6278DD48D6BDF +:107910009AB780373AB8757810705FE067F05CD03E +:10792000C4E21F9F737B4DC46BCCF85F48BC3743E8 +:107930003EE2C28D547EBA23F420E860F1AE00C668 +:1079400067BE220D090ECA07CB36EF9A798D0AFB66 +:10795000FC43B80F99D32B9865492224D97FE8C9F5 +:10796000F281DDC727FE577022FC7E71FC8EC26556 +:107970007E23BB3F5CD78EE7DDFB91AE17F9FD366A +:10798000F0DF2EE2FED0EEE659ADB073FEDDCF970C +:10799000C1F17F3DEF778776661F6545DD6FB5DB0B +:1079A00045DDE8E34FACC181A08FC30315D4471771 +:1079B00014CF87A529A09FB370DFD099BC5DC0F517 +:1079C000F27CD0D3B43CBEF965BCE7E9F38D2F63FC +:1079D0003CD8F6E2FC04B0978F6F9EFB53380771DA +:1079E0007CC75CD4CB0B9F167AD967D3EBFB719B1A +:1079F0002B9EFB21D0E90BB118C758D0E2E3F63833 +:107A0000DDD7805CA4E3A19ED8C8E4E042D05F0546 +:107A1000A8BF72A0DD830B7C3940EFBAE7A8D71E60 +:107A20009CEB1B85DF135790DDB3EA0A82FE12FA46 +:107A300055E8DD57FBFA2E0F053E92DFFEE0077496 +:107A4000FDA777CBE8D3592E6F1D04BF0FD3991C28 +:107A5000FFEEF0B6B4C3DBDD03785702BCD11E6283 +:107A6000F03E5ACFE07C6C1D837BDD8E8C04D80702 +:107A70001FADCF403BE8E88E2C84F7BCB514DE6820 +:107A800007AB463BA89EC21BEC7F80371DB7B245B3 +:107A9000E5F0F63078D7733DB48E95F33AC0D57FD4 +:107AA00037C895077F19E3C1FBBA6383A9B04F3983 +:107AB000B14B2690A7D16E27717B46C0F95FA4E138 +:107AC00059B0AB3AD837EB6308F87317FFCE89E7A4 +:107AD000A4BE944AFB00024E35FC2901C68B8CDF04 +:107AE0006ED7780A8B75764D0FF15345BC788EA111 +:107AF000AAE94F1F815D0FD72CC1BEBF4ADC8FB1F1 +:107B0000D7783F86A4824CC3F3B2763BD0C100F352 +:107B1000FD213EFCBD9C8B595FDF7D1FF273385BFE +:107B2000EF57AF8E0B5AC11F15DE2521BE973F5070 +:107B30009A504A200E5783F3985AC8F4B3A469E8C0 +:107B4000678CA1741347C7F3C265C2F05C7531BF7F +:107B5000E3163AAE33325FF3F39B4110817E7744F4 +:107B6000F753FF908FB35CB6E03E64998DED4744C8 +:107B70003ECC5D85CC6EB8AB90ED4BE616B27C93F7 +:107B8000B3903C45FB3D7B7D0CCFEF1E8FFE4F71CC +:107B90003F8222E0E652CE187E674209E3EFC07CC6 +:107BA00076ED21BC7FF733F8168D6B8A8012B06BAF +:107BB000D8F7EF5AD9BD2E778EFE13FA4D3F8BF5CD +:107BC000AA607F7D966AF7001DF9E11E3C4A7F3F5F +:107BD0008A63FE729292A8007FDDC1E5ED5D63626B +:107BE00034D04B778EF991174A3A8E1F821675A5BD +:107BF000071E033ABA27EDD8F7EC7449AB2CCC6ECC +:107C000059D58B601E511135DFC16F4B5FEDB992B5 +:107C1000DC15DD18FDDCCBC09F7B2D6104351AE13E +:107C200069A853B8627DC34BA5B3360E20E430512A +:107C300087029E97014C800E2A12D12F700BF89567 +:107C40007B41A9207D4D5788DFC2CA7A07DEFBC180 +:107C5000FCCC37F375DE369A0413E9FA826F118390 +:107C60001F7E56D012CCA170BB45093603FC2C7682 +:107C7000D50AFB026FB9341CF6CBCB56F76CBEBFEE +:107C80007A69CAAC8D6368DDC2F21CC23F90F09E77 +:107C9000963B2973035DDEAD90167938C31BD05D2A +:107CA000752F761F79F85E89C79398FF5FE0651896 +:107CB000ED5E0FDF3BF9FC683FF509F0BD2DBA5FC3 +:107CC0006937A753616F2EE57CBA54D0D90E237F54 +:107CD0001E167C02F62D85DB9DBCEC8CCEFFCAFB0C +:107CE000FF6B21F35FBD7695E32D8F2141FDEF56AC +:107CF00089716FE1E53B85CC6E16F310F44BB85FEC +:107D0000CA422506D0515BC31AB4971699FCC444E5 +:107D1000EFBF92A3D5DBE58EE50A94B6F03C988FD1 +:107D200074432CF2CB9DB69D59EC9E1963BBE50DB7 +:107D30008CFE973BEC68078AFBC5C53E40D88D8B0F +:107D4000C1DE037BBF91D9B70AB7CB2BE87E0D8884 +:107D5000CE4A42B5FD61DF5CAFB37F519E717FCFEC +:107D60009E613E18E74E871DE39F372F33DA4B564F +:107D70006E475A3BFEFE9D31AF84DB4BE6BC129949 +:107D8000F3316DCBF6313CAF44E1F6B0A0A30F0B5D +:107D9000ADDCAFE237C4F1E790562BBF778EF9F731 +:107DA000B89E9E203BF03E863912BB67EB6CA9D390 +:107DB0006FA172E9137ECFCDB91A76CE79CE0FD8E6 +:107DC00039DEBB121FBC19ECE239093605CA4FF87F +:107DD000EF7D7DEA4A4F9C4540FEC83CEEF4935946 +:107DE00010BF59037294D59FD2C6A0178DD79FF8A4 +:107DF00010DECFB84CE78DF50DB3343ADED937F845 +:107E00007B3FAD437CE831C1C79B597D9378BF85EB +:107E1000D51F17EFB7B2FA4F44FFBCBEDEF47E9514 +:107E2000E9FDCF597D70D1D6597EB0E379DC6ACEB9 +:107E3000B512C6AD34E0330ACF39AB83485F732C3B +:107E4000FB5959468210B7ECAEDDE422AF06FA5A70 +:107E500076B639C15E99314CC37AFE505F7E11C54A +:107E6000CF926992DF06F1CBF703D95C9F45CFC76C +:107E7000E7FA699287F527EC5FDACF88A2E2ABEFE9 +:107E8000E7A3A20EFD8CF92EFD34769CCF84EFB2D1 +:107E9000AED861C67E843DB86DB8E6837991F1D7DE +:107EA00019FC9C4B1FF524823D49DE65BFBBB574B0 +:107EB000F5CE412368FF4B5FDA376881CEFF5075FE +:107EC00049261A95C3D597242CBF6AFED806F74BCE +:107ED00054ED69B64D2C80DF0B6AB68DD3CD6B990E +:107EE000C833262165BACE9E995F64E17CC57E7752 +:107EF00068E94B2731FEBCD4B2F3F8D3C097D73230 +:107F00003FA4797D53F9779F417E4194FDCAD222E7 +:107F100026879F1EA92D01B84D0198D1F6E3D644BE +:107F2000CFD3D8C3FB9B13C7E4FBDC12A75D2D8224 +:107F300078B86F0D9CFF5BB0C53D1CFCDA5387968B +:107F40003D50D4A57F38CCFCC34DCC3F3CA757EB6C +:107F500003547991DFFE36F814DCFB3CF929D21E7C +:107F60004F06BF2B1E8747BEFB70D6F831E8EFC324 +:107F7000FA1345879E82F3DF07F9EF31DC356A6833 +:107F80001CC885903BDEE2A2FC3CA3A0E2B780BF08 +:107F9000BB465D3F119E97C638B32B589C01E962E2 +:107FA0004681772DBC87F6E0DFF1D998BFCFF76720 +:107FB00019FD7DBEC2785FB4FC857A0E87DF16B1ED +:107FC000F31B072D749EC323F310E35303ED815677 +:107FD000DA5FDBEABEC3E09CE5CE82D297909EF8E2 +:107FE000F83B0B7CBFD08F0F1409CF7B3A8FCD4568 +:107FF0004C9FBEC4F1E61D43E94D27F7A78F8F378D +:10800000D4674C49269ADEEF3CA3BFA13E7B4E8647 +:10801000A1FD1DF38618DE4F8D691D597315767FFE +:10802000B5D31907F9119F36FDEB6F77823DDB2839 +:10803000E3EF172D7E6DFBDFE0F7BCCED10527A364 +:108040007DAAA2FFEFCB83EC775889A229FA38D614 +:1080500069D2FA24C47D75F191A8F163111F59EA20 +:108060006AC13CCDFF368EF56E118F630D87D475D6 +:10807000D0471F0C823C952A075BD7E97D47F0F774 +:108080004C20CFE34A09C47F091A89D59756E1EFFE +:10809000C88DE3BF275D5DC4E473D5807B15B8B799 +:1080A000A09A9620FF2752399548E9A4B5990CDD8E +:1080B0000379DB6E27E6D52CBF742BFAF50FC6F9D2 +:1080C0000BEEA5ED96D64FC27AD5A578ECF7AF7238 +:1080D000EB44CCCF7F45C2F8C9D4FE77AD86F943D7 +:1080E000FBFBE978537F7B6339C0A96A0FCBBF994B +:1080F0002A1F1E09FD2C6B9884DF4F95C94189DA30 +:10810000498997EEC47EA7828D43EB7289732DE86F +:108110005DD916CCFE05C8159B13E54AF5A558FC9C +:108120006EF238A69F2F16B17D8B35C4E635E1D2AD +:10813000347C2FF07FB928DD709ED49ADAA8C07DF8 +:10814000ADD69084ED6FBA34044BB1CE3FE7FE124A +:108150007F9FCC9A7A6122E4DFFE394572A1D9650E +:1081600092BBE76B4625EAF7D3FF0F762BD097003B +:10817000800000001F8B080000000000000BCD7D78 +:108180000B7854D5B5F03E73CEBC9299C9E4C9843E +:108190002470024908106032791042209310109127 +:1081A000C000550906199047401E21BEE295FB67A5 +:1081B0004212088216B5BF45453A205AB4B6372256 +:1081C00056DA224E006DACFE366A1F786B6D502F6A +:1081D00082458DE0B5F416E5AEB5F6D999394382FE +:1081E000D0DEFEFF1F3EBE9D75F63EFBB1D6DAEB3C +:1081F000B5D73EB978117ECA19BBA895E6F332F31C +:10820000263276D37989790B18FB3ADF9BE04E66EC +:108210006CD6861EC592C418B3599C4F66025C92F8 +:10822000AF2ECF0BBF271FA961EA18783FA9D7E867 +:10823000B5C1FB504EB185EB1731E6ED0098B11E8C +:1082400065AE3DFCDCE53630968CCF9B192B827EEB +:10825000FBDAFD8CB114C66E7632FED3088D52194E +:10826000336AEDC5FBDD12D4C1BC022F98834FC227 +:10827000EF291EFF6837F4D35DC1E6EFC77E94EEA9 +:108280002173ECFF73F3AF9699454AA0757871DCC2 +:108290005925AAE15EE8CFDDB78E0095DFB68E0CDA +:1082A000ADFDAF65D6D801F3F8757979B717FAEB5C +:1082B000BCA7A04056C3E356B84D8417E6ECBDC03A +:1082C0000A195B773856BD17D6590D3442B8F725D1 +:1082D00073704F263D67521296E63D12D4AF73F489 +:1082E000E6F860FC292F5B436C2CF4FBB25561303F +:1082F000CE1B85FE0AA4E794974754490E98E421C3 +:10830000B3C2A0DD75E3BC9588B781E67B318A4FA7 +:108310004429D6CBAA261A583163B759F86BD3E64D +:108320004881B838C6FCEDD73206735D7C7E1E638B +:10833000C04F4BCEC712ECDFCE9F9FAB1F340DF169 +:10834000786E034C1AD6B1648334E600AC8BA97600 +:108350007736E0A13A6DE146E640BC1B68BDD5A387 +:10836000E3832DD0F4BA29F680218EE8D185F45824 +:108370007D3E9EFA5B733E93C6597B3E91E075E766 +:10838000AD542E393F9A9E0BFEF6217F437983C769 +:10839000BF1EF151DD72CD741CC7BF31B5D06F8BDC +:1083A000E4179313F90AF8C5B53C821F5A3A815F66 +:1083B000ECC42F8A17F0EA8332925F6623FDF31034 +:1083C00013CE692930EF59AD99867B59B8FE4EA47A +:1083D0007FD195F3FD2D1ABF2CB185B20DD09FB181 +:1083E000DEEADE08F33A9BA44E43BC346CE1F86B42 +:1083F00030FAA6D861DE0D8F486EA00CBBA5D86EF2 +:108400006180A7E2E3F5267F04BFD79C1FCB54C051 +:10841000C7BCF35954568FF1B722FD179FBF41A334 +:10842000D3582A995A62C0F9DC8E74557142259C42 +:10843000CEDAFCBEAC1F3FE82E18FFCB378C545F62 +:10844000E40DDC8CF33106CDEEDD309F5356BF8C4E +:10845000F43D95C19C0FC1144F1959C009F4BA6578 +:1084600087CC02D0FF5228FD509E8A67DE780FE24B +:1084700013D699CBFBBE08FFFF53D93E840D07BA34 +:1084800036FCFE7D6518632B73BAC786A0DFDA8AD7 +:1084900050F28DD0EF99BD467700C65DDDF976B11B +:1084A00001EA3FC9F40E6232A06AB07F17D275D5D7 +:1084B000DCE04F8C00DF7ADFF38E096A189F1D4ADB +:1084C000285B81F73B008F019857C736797A90F087 +:1084D000CF62E78C09F3B5E0E368FE5E757E38E1B4 +:1084E000E75CBD79CC01E45FE0577CBE46E3F35B1B +:1084F00091EF890F39BF0B3E5EA37079B5C6161791 +:108500000CC03A8C3DBC5DF5BF01FF01CAD71ED837 +:108510007D7F29F2DD1985F87FB5B64FAAE5B9BE92 +:108520000ACEFFEE1678FE62930B9015E6FFA9E7E0 +:10853000E750BBB8F337517F82EFA3E579C4BE6142 +:108540000CDE7B31DFFF16E2A9F2477F7BFEDFE125 +:10855000D10C2594F358129676E29F7F96DCFFDDCE +:1085600055F2FF31ADFD74335BE4CBE3723DB2BF36 +:10857000144FE5695CC7676E89CBDF7FB2BCFFEC47 +:108580002AE5FD1FAE50DE4BF95CDE47CB7706FDDA +:10859000A17CFFFCA5914194FFEF33D007A8F70E13 +:1085A000C5AA4F6AF29FF4434C5CF072F2FFD1C24D +:1085B0005BA4FCFEE5BF21FF1F90FF7FEF3E11FC97 +:1085C00018BD5FAEDBDA4D7A81BD283194BF62FF02 +:1085D00074C570BC748DE27A20BC6F24DA570CF637 +:1085E00055B614B96FF6DC5F8AFBE6F324770B1BF4 +:1085F00078DFDCA4ED93459A5E10FBE3D17C7F61CC +:108600007EC4FE58BD3F5A3F5C9EBF6E4AAA67A813 +:108610001F164119C95FE63EFDA0DF1713F2AF6ECA +:108620005F8CD0DA7F1B5FCDFCE7F3D5CC01F8AAD5 +:108630003A3FF9EFE7AB687E3A57FFFB4215E67326 +:10864000AE10F82833CC3FD7BDCEB8DD30DCEE7E9F +:108650009245F0892923D882ED2EB27AC463B43CC6 +:10866000147CBB05EC009CA7A07B574C206F7DDEE3 +:108670003F4FFEDD997F7576EFD2FC2B931F9B91C8 +:10868000CED8EFFF9CBDF8607F74655E6E1784E9FD +:10869000629E47765C08149C34305D8D3BF8FE1278 +:1086A000705B48117A3711F52EF0CB43FF08BF54A9 +:1086B0004F815F0723FCBBF9DE74E8EFBB1A1C781F +:1086C000773ED2E7861251FFFB1DDE2C9433F06B10 +:1086D000298DE06516C2AF061F3F5E85FCFB505F2B +:1086E0007D00EBA796C569EF332FBA1EA2FDFEFCF5 +:1086F000DF1EDF46FB793BDFBFFE1EC53726022E9D +:1087000004D81E019744C13B797B87D2C39C848FD8 +:1087100020DFAFD0BFE4E1FCE38BB04B8092D3E22B +:10872000D1AE3C2039EF05FA2F28FBDC84F40AAFE8 +:10873000BF87D6BFF690A4C11F1DF70269161CE0C3 +:10874000F0F1FC533B028AD61FE079B58666738749 +:10875000E495818EAB4BA4E0B0CC4BF17CBC4F3E9A +:108760008979802AD6BFCF4C8557F73EEE6F7A7F46 +:1087700018BD1F325FC5F83796316FD07669BB538D +:10878000A2DD058045FF80CB79B0BE60DEA5ED7B24 +:10879000B5F6DD068386AFAF7720FEBA4D029F1790 +:1087A0007678CB80FE8CC3FF957F617E208F4FDF74 +:1087B0001BB5FECBCDFFBD7CBDDD803FAAFEFDD04D +:1087C000E5F0F7C125F8D3F8A74ECF4F718AEFD85F +:1087D0003998475C92E444FB78ADCFBA0DFD803008 +:1087E0007F986B703DDD56D6C7CF7AFEB7D454C1A3 +:1087F000FAD632511FF308F93986BEF67C3FF4F100 +:1088000017F3E6023FA10980EF2779AC8F046C448F +:108810001FAA2738EB32FBA1230A2E8BDA3F1AFF5F +:10882000D3FE45390FF8C9EE47CE1478387E3E9511 +:10883000D87C9493DD95DC5EEC1EC6CB791E89EA6C +:10884000277A381DA66865774C041ED2C374869FAC +:1088500010FA2311EB263CD52469EB0E8CAC990958 +:10886000EBEE4EE0F5D5FBB31F099485E1E8FE661B +:10887000EF1F59837CD3D77F60C4BB88D71A0D6F95 +:10888000F3F6E7BE1BE0F250C27DB9861804A87566 +:10889000400AC8B0EE35C817FDAC3BCD73C9BE0A5F +:1088A00044BDEF355EE6FDCC4BDFF746BDCF8C49CE +:1088B00057F3BE46B79951749D1E45D7AA28B8569E +:1088C000C0419DFC137271C9C107DA52601EB7EE38 +:1088D0009350CD44F07309F1F3AD4EC1BF13DE45A3 +:1088E000791FE6E75282E776087E9DF808CAFF39CD +:1088F000280F4BC3F03C94170497D578C745EA8BF3 +:1089000049547F63BB683F99E005ADA2BFF2475071 +:10891000BE0A3A02FA6A70BC9A42A12F2ADEC5F654 +:10892000AB0EF1F737792ADFBDEC7ED81E85979D17 +:10893000517020AAFDF7BE45BFB446BDBF21AA7E37 +:108940005B14BC230A6ED7BFBF78A944FB7031F01B +:108950000312E2DBF6E5C39E3E3BB54F9F4A36B2BB +:10896000DB74FBEABA160E073DB36BDA6D11F07ECD +:108970005F8D266F695F1819FF01591B407D651CCB +:10898000405EDE3F105FE646EB5B5EFF27FC351581 +:10899000ED60A6B30B8ECA7AB853D6E61DB8F9DDE2 +:1089A000DBF3F0A18017D6A07F70DDF7F5EB02BFF7 +:1089B00055ABBFA9A6AA2CC22E6137119F88758A14 +:1089C000F6D3BEBE28E3783FDDBFA0662FD4D756CE +:1089D00086B2EBB14CE025E83519F5E63A2D2E3399 +:1089E000ED25D9877AAD362694DD106987B08E1CC7 +:1089F0005C67E73D32D127D002F4C1381B739B304E +:108A0000AED21917D7F814B43F7A8FDC887AF4FD08 +:108A1000C6C4149C7F6A01B7238FC60D4D590670DA +:108A200067EC22930AED3A374FA5F288ECDDD40BC0 +:108A30007BED379E5535B691581F47F8E9DEBFAC40 +:108A4000A619F6C13B1E95DEF72738530EA2FD7C12 +:108A5000AF913DA9E27CDCBB886FEE33E7A31FBD7D +:108A6000B879740ADA934BFEF79C69A9D06E499BDA +:108A7000D12D513B3616E7EDBF77AA09EB97B66AC1 +:108A800065E01A2A5FFEE6891607B4EF7D5C72EF97 +:108A900081F693BEEC787D2CC02BDA87BB913487AE +:108AA000CF1B9813C6F960C788A00CFCF8A1B5FECF +:108AB000D559BC3DC3F62B2EA86FCE2AC4F6B2738F +:108AC00023B43F09CFD11E3EB945DE23E1BC1CF6DD +:108AD00018099674F26BF54DB46BA1DEB9119E9F27 +:108AE0006C5B998276D649497548B0FE5E4F638DBE +:108AF0000BF865C50EB346BFC6D4C5B0AF171BFA99 +:108B0000F885F4C7F2780EF7EEBFABE64998FFC9D7 +:108B100047463810CF6B0BBC5F78501F157ACF7A61 +:108B200092719E5C4FBDFC8DBC08EDF15F9C59922B +:108B30008271BB0B1A1F1F3EBF24654984BDB3FC65 +:108B40005385E8FEB249BD1DE7F9724C8684F12CCD +:108B5000A07B22C6BD976A7E26F06FE3F3FDD83D69 +:108B6000BFF7C844A78FCC8DEC43D8549D5BAF9F13 +:108B70006207BC74BE28111D96327F0BC2ECA0E4C4 +:108B800046FA45BFFF9BB195D682A248FEDF4272EE +:108B900096FC0D80139FDF44FA906D800713A03C74 +:108BA0006A253FDDF8AC3568057C2E4DF24EC3F6E4 +:108BB000CCD59133D71EB14FB5F67F0CD8A9FD1F88 +:108BC000A13DFA7B7F0CFCC1CE6C97DAFD2B1CF625 +:108BD000001A1F1FDBED0AD2ED7DA5E9E4DDF0DE12 +:108BE000F2C78DA427963F9EBCA117D701FC95CD57 +:108BF0002E5D87BFC048F81D70DFB2EFD754E9FC87 +:108C000089872FBB6FC7143C5CB3376FE07DBB42D5 +:108C1000F36BA63D6EF4E1BE5B51645718E89BCA46 +:108C2000C75F7912F7C78AF5568F1926BEE27133EE +:108C3000D1B7C76E0F38A1DEEFB02BF1504E2CE04C +:108C4000FCB0B040A5728ACC148B87CA568CAF9EFC +:108C500085F924027CBAF1A187C7C3389FB0E00D23 +:108C6000E3017F6791508097B307648A3F32C5ABB9 +:108C700054833CAD635C8EAC79ED795305FC5A5757 +:108C8000BF6226FA812B83C60F7A341FEFA2B64C3F +:108C900094BFEBF823D0C3FAFA756CDB17F2586275 +:108CA0007B13EEDF351D51F5F5D77C8C719C754C2F +:108CB000F9A047C479611EF30AEC49274703E06134 +:108CC0001EC0103B5B6FCC61B0C41536D887B0DED8 +:108CD000293B797C6745A31C3443FB29893C5EFC16 +:108CE0005113D07F04AD3BE00478C5F7B85E5AC19C +:108CF000A4A0057EBD66E77A05F7CF2B1E8EA7C51B +:108D000012F3E17EF8D0EA1E82FEFDF2C7AD84DFE9 +:108D100015BB56FEEE1178AFA7B93A29D29F5EA9CE +:108D2000F105F4CF2C09E17E3E6EFED7212807A77E +:108D3000FC00FC6258EF8A78F6939A4CA457EA102C +:108D4000D5166EB762E33D39BC1DF8D5B0EEC55BF4 +:108D5000641EA77AC14C7A1264838BE4B886CFA5CF +:108D6000ADAF994C7928D7B775CBD0FE0380651B82 +:108D7000E12BA0E1D184F85A84EFA6F2775CC59A82 +:108D80009DAE92DCF1E3FA6A0DD2A2B9A4077A4D46 +:108D90002807BE5FC0EDDE6D5AB97888FB668A434E +:108DA000DF6F76A35CC31F59CC03FCB03586EEE5BC +:108DB0001807663F35533C655DABD56B75909FE2F8 +:108DC000DD8FF3539862C2731795CB97EF6B7CB826 +:108DD0004E9D730DF20DD41F57A07E8D9DCBD135C6 +:108DE000F180776ED77A0D30CEE7F8DB70DE6FEA70 +:108DF000D888F125ED39F4A33AC2FD7619583BC65F +:108E000065B0FDC8B188C7C41BE6E3FC7E2CD37EE9 +:108E100086C5DF5F8276E18FE502F487176F393A06 +:108E20006D07C2CFE53BB1CBC53F7987F4CCAD1A16 +:108E3000FD7BD03F40BD03F073507668FBC92FF334 +:108E40003851878627C107A27ECD16238FDFB799B9 +:108E5000C9EE59D3FC7BEA778DBD3B05E5F59A1742 +:108E60008CC528D79FD7E6BDA439A3EC38F0D5121E +:108E7000639C538247AB03D52684576F97080EBF78 +:108E8000973C04F9F4CFAD2F3A907F3EB486B251AF +:108E90007FF5AEB7BAF7E002B438DD9F5BB3F76099 +:108EA0003C67A9B3DB2E41FDD2DB8727A0BC7FDF67 +:108EB000193261FDFB1D990684BD4E6719C25E65BE +:108EC0001CC17F0651D6A1F9ABC86F6B254EE7D503 +:108ED000CF1E350D83F18E17F0B8F9A73F7E270717 +:108EE000F5DB9A21DD39A887800F72D210CFCF48E9 +:108EF000A4BFD73E2B7BAD63C37CB016F900F6DD73 +:108F00002A8D0FD61E78F12EDC0F6B91FE9E4BF949 +:108F100008F8F4183DDFBF7B1AE3EF1F433E117AD8 +:108F20000FE05623C6DF4C1A0CE320FCAE864FA898 +:108F3000AFE2F581BC7A1E5733A19DBAEEA031D0C5 +:108F400013716E34109DBF2AD0CED19ACD2477BF35 +:108F5000D2D6DDB3E50507D2F1D31F1F7D15E3C5DA +:108F60006BF6837657FBD9171A5ED6211E1CB40EFA +:108F7000B247D6E1BA1D613CF4F1BFB61FD731BE8E +:108F80004EB1EE758A860751AFBDFF176D9DAB9947 +:108F900086B70323F8FED3F61BEE6794AB627DFE23 +:108FA00004FEBEE0D3F442BE3E6321E7D7D5C0172E +:108FB000EE3CE21FAF49C809A8FAF4B9DD142F123C +:108FC000F412F31E5BA80A79E78D4F08D3B1C7C02E +:108FD000EA3AFA89B3241772FC9D681B34E420E056 +:108FE000EDCFE097A1FD85FCAA448C27F8468C378D +:108FF000E5477366E07AA1FF10F62FC67D3F10AB00 +:10900000603FEF33BE3F903F517E8A7D39A565E1D9 +:109010008C7C07B6FBD43E3C0FD7CBC71F5BE8A4C4 +:10902000F7BD682FC0FBDE8312C5AB4F687180139C +:109030006D2F3A9644E0294F7B4FF019FE601C4B90 +:10904000CCB72B81C77FA3E72DE49098F794CD3759 +:10905000CEC0E762FE825F057F0A3C0A3E651B9236 +:10906000C9AE89E657E235A157659DBC27FD784D0D +:10907000FA1726BFEDD2E7D1709FFDD4EA3A9615D4 +:10908000A1D73FC4380FCA93A7E520C913065C1BBC +:10909000A17784BE6F5E7F8D13CF198DCF4A6E345A +:1090A0007D22F4CC362542CFD415AECF417DF6607B +:1090B000E1302EF793BCA7919EAB4F754F73A8611B +:1090C000FB75D29721390EE36107323D917A75F530 +:1090D0009963B40FD6B0EE4DE87F2DDEF24EF578F1 +:1090E000E4F7A78D74EEB9B86DAA09FD81954FDE3E +:1090F000528CFCF441FB7092EFA7F71615107F31EC +:1091000067CA0DB00F96EE7DE88605F07CE941D97F +:109110004D721EFAC1FDBBF88E0226D1BA7BAAF1B0 +:109120003CB5F76ED98976FFC4278B3660FB89F68C +:10913000A1F1B80EEFDE4482BD4A1CE909612FBFE0 +:10914000AFC9CB1623E78F0DDABEBAADAFE4FC335F +:10915000A5A52507CFE37B77839CC6736993DA11B6 +:10916000C2F15E1A447EC93A70A35C40FF5312B745 +:10917000CFEA4CCC92EAA1E7965478FE9AB1FB0E66 +:10918000D427AFDD61CF6FC609C8178A97707F9269 +:10919000E60176348D2FF026E6714F21D74FD1FDB1 +:1091A00089F7BBD0FF40B9AACDFF74EBD337A03EFF +:1091B0003CBD2F3B01D7FDF14BD676B4AB3E3672AA +:1091C000F9D867EF048D1F45DA6B60DFE960B0E71F +:1091D0007430F0F1477AFB7023CDEBBE429BCE9EFC +:1091E000137C5FBB3E3B2E320F21DA8E6759D1E7ED +:1091F0003DE3E3583F724794679A0051C0A873D08B +:10920000B68771AB62BF7EBE1BEDFEED66A719D6B9 +:10921000F911F23D9E67BD2007F1FC066D74DC0775 +:109220001F3D971F44FF73F97BFE69D8FFB10736D6 +:10923000539EC232B033074911F6F3F71EB801D975 +:10924000FFACDBBF2915DE3BBB8FE75540B52DCA10 +:109250006E7E3555FDC7EDE62BB597459CE2E7855B +:109260009ADDEC666EC4B3C0AFF09F5E063E28F197 +:1092700084F1F559531DD9CB679AFC547E2E9DB8C5 +:109280007F22F2AF3DCEBD075EFBC5C187E434A4AB +:10929000F381FC0BE82F97DAE29CB86F3F6B6AA46E +:1092A00043CB334DF5540A3A8B38DDA4039DF4DEED +:1092B00067070B0E4D84F70EDBE2B81EB8E49C88FE +:1092C000D3333A8FE4B6F5E307E173B1AE4FEEE680 +:1092D0007415F3FE64DF2D0E5C57E7638987262043 +:1092E0003D63E39C68F7ADD0F2474EEEE076F5299A +:1092F0004BDC533331EF64E7BC1406F27659E77761 +:109300006EC0E7CB5F929CE80FB85F9AE3C078EB42 +:109310007F283D0E2796F05E08E7A304659447A5D5 +:10932000D3199D63958614A666D2D130F1CB8433D0 +:109330004A10F34EFE8CE75B1847B910437114A630 +:109340009D5B2DFB198FBFF4F9B99A9F37515B775D +:109350004A5102E76FEDF99412FEFCE39DCFCFC2B4 +:10936000FE4EEF353A71DE9FED3552FFABC03F3315 +:10937000C07C4FEDE37ECFAA0E89FCE5D3FB406FA6 +:10938000C3BAD6AC377A4D7197F2E114A8EFB18524 +:10939000F970953748FCCD347EB4C0BF8BC32EE541 +:1093A000C778D6B109F1F18FF2A5AD48EFC7F5F155 +:1093B000E3407CA0E10BF731F2A3A0F72AA00B9EBB +:1093C000CF2674E457205F09FA0B3911A864B9A8B5 +:1093D0005F5B4C2C17F37802861837EEEF3936D5E1 +:1093E00028011EE625F554A138BDBB88CB49798AF2 +:1093F000C16B40FDD2622639102D47B28BB8BDF447 +:109400002CF234FCAF2872723B8AD5933F224AD0AB +:109410003B19A8C7E7C426FCA70A4D3C2F7C7F81D7 +:1094200002F39F3331E18EE16EE09B171E5FA000D7 +:10943000FFCE2948786118C065453B393C2EA1C84C +:10944000087073F3AE055500D71479DD45C9E17195 +:1094500044BFF0BC009FFF7CB4BF18CB75261BC96E +:10946000E9CFA5DEB18D99E1F66F49ECFD5F48616A +:10947000B8C7C886A09D57D137FFFECB8D45DE7299 +:109480003EAEFEF912C6DA28FF2EF0CBE312F7C784 +:109490007C9614CA6323BE5A62B185C8AF6F379EEB +:1094A000E9A337F2913B4E41BACED2F868B612EA40 +:1094B000C4F747B256E7490B99523B2F260E2CBFF3 +:1094C00061E3B193A23FE097CF8DB05EE06B09D826 +:1094D000B311B68C0448AE05F9251DFAE55FB1DF7E +:1094E0009600EBB1121D6A9DC86712F31B2E42B99C +:1094F00026D63116E3276B62870491EF1B5EF8F4E2 +:1095000018B2D74A61BFF84B88DF6F77F2F5307F2A +:1095100029F1E31D1A3F7EDCC4EAB360EBCDEEEE29 +:1095200076A830E933B34239B8DFFF34C45F5784DB +:10953000FEFECE96F406E09F4FF79BDD33A1FDA91A +:10954000E0F314BF5BADD9A56C6FB2B6EFE550394F +:10955000B4EBCA1CB907F54B4311D7D76732434365 +:10956000EE41B991C9FD2068477972D3375E938C7B +:10957000EDCE3CB7396B19D0CFACB0803D814AE617 +:1095800080755F0B7D97006C0458A673E020D10BAB +:10959000DB3950DFABB7B8789C9EF950AE087A093A +:1095A0003A5C421F9802DAAD060B33E2FC47B29DEB +:1095B000CE93B1613A7D6C013C621CCD027884FD92 +:1095C0003D15830F85884F1E7769907A5A1311FED7 +:1095D000B144797797EAC1274D88F2BA9DB790FCDC +:1095E000117247857FFDC99DAB8E1FED9CD2AFDC0C +:1095F000790CE50EAC83E5B3FC8BDC4024FAAED0ED +:10960000DE9D2AD7AA0ACE3BD9E2C6B85AC3E3C325 +:1096100049DFB00BBF217F58B4633B13895F3665C8 +:10962000CA84F79507259E1F79308DA95035F360C0 +:1096300022958EF3A9F4FCF453AF1772B9C4E95222 +:10964000FDC3419594AFFAC311548A7934687C37CD +:1096500055CEEB08A11D61837900DCF01AD75B0DB4 +:10966000D7CB14DF6428A2539098FCC7676BA73848 +:10967000908FF5D9F9D245B2DFD538A48BAF4B66C0 +:10968000C83FE07504389E2DCD8867B3CBC0D47E2B +:10969000EC0FB34627AB1AC3D408FF43098CFC6E0A +:1096A00019C665BF637407A1BEC5EAD883FB8905E7 +:1096B000BCDDE847CCD7DEEBB672FE88CD4DD0BD21 +:1096C000BFD931AD0BF96DBE97EB1DBB7BB06E7C86 +:1096D000B3BCDA884CC6FCDC5E14FC407C09E3CEEB +:1096E000F649A45FAF9F0FF511FD1ACBBE20396E6E +:1096F0002CD3DB99669FBEDD1F84DE19C94646D296 +:109700003F8C779B17EDF4B35E3BF13168F7EF9731 +:10971000017C439791E17ACD317C5D671153181F2D +:10972000F5CA418C9B6C463CC0F3B8123D3EE3BD8C +:109730007AFC254ED7E323D9A75FFFA0F9C374F5C0 +:10974000A9FE51BAFAB43A8F0ECEA82FD5B51FDABA +:1097500058A98333033374ED87B7CFD5C1D9DB174D +:10976000E8DA8FD8B144573F32B84A573F7A5F831F +:109770000E1ED3F12FBAF6E30E6ED4D5E787EED5E1 +:10978000D517743DA8838BBA1FD5B51F7F7C8FAECC +:109790007E42CF33BAFA89A7F6EBE049BD3FD7B591 +:1097A0002F3F7F440757B0D775EDA758DED1C1537F +:1097B0009D7FD0B5BFC6F5A1AEFE5AF5CFBAFAEB84 +:1097C00072CFE9F93586CBBF6AF7DF74EF7D9EE68D +:1097D0001F558C3A533EA320DFB62C945822C6D591 +:1097E000BBE659500EE4156B7248E3C3E1453C2ECD +:1097F000C1B2D810946753E5990CE376673BB87F04 +:109800003D90BE8B0375A5448C1BEFB58003198674 +:1098100013A73B7570B2CFA56B3F68BEAAAB4FF5DF +:10982000E7EAEAD3EADC3A38A3BE44D77E68A35716 +:10983000076706A6EBDA0F6FF7E9E0ECEDF375EDDD +:1098400047ECF0EBEA4706EB74F5A3F7D5EBE03114 +:109850001D8DBAF6E30E0674F5F9A1765D7D41D74C +:10986000761D5CD4BD43D77EFCF1A0AE7E42CF3ED8 +:109870005DFDC4531D3A7852EF415DFBF2F3211DAB +:109880005CC15ED3B59F62794B074F75BEAB6B7FF2 +:109890008DEB84AEFE5AF5B4AE7EF59FDD213A071E +:1098A000F8053F57BB2EF70B5DBD3109EC5A8C43D1 +:1098B000B218379E5F0AFBA7DAFD575DBFF7160F98 +:1098C00023FB0278A9C72AA37DE4A3F85102261638 +:1098D000025FC6811043BE4257A196E25049A4EFF1 +:1098E0004835A99827047602000986CC4CB4A763B2 +:1098F000C3765BFAC5822BB7DB76409F388F5F1645 +:10990000FBEF2B4E467FE5B96968B7AF64814D38F0 +:109910000FD07B713DB03FDEB4EAE319A2BCD602A2 +:10992000F88918EF35EBF674CF65FCFE6B2D67A850 +:109930007D5FBF5A9C4382F53544F47F3FF8150A9A +:10994000D875DB9B60FF80C3F8609393E0EF35B977 +:10995000087EB849A57247532E958F36B9A97E6700 +:109960005309C1BB9ABC04079BA653B9A7C947CFEB +:10997000F736CD27F829F0A3B1DC077E3596CF80E6 +:109980007F8CF5CF82BF8CF04F9A02547634B5D3DA +:10999000F3FD4DDB093ED0B483E09F3605A93CD8EA +:1099A000B48FCA9F377550FDA1A683041F6E0A119C +:1099B0001C6AEA22F8485337C1C79A8E13FC6A53CF +:1099C0000F955D4DA7A8FC55532FD5BFD1749EE0D0 +:1099D000335ADCF6956249776F4AC08C55113F08BF +:1099E000FB7016DAF9C81C25C6CF74767E94BD1DAF +:1099F0004D8F4FB4718C95602E62FC7070CE9E9628 +:109A0000083FEB2D6DBCCD312C6005F9D66CE07EA6 +:109A10006D7302A33C6EA6D9AF2B34BE6449DC6ED5 +:109A20005DAECD6B85C6FF45C89FB9C49F6F5C8D89 +:109A30005F21FCC65163FC27883F330C01F29F6D08 +:109A4000C11CB49FABC7F83F42B97EB67ED9AB34D8 +:109A50009ED34DE78FD5E650F28D181F794DA6782D +:109A6000DE40E3ADD3F2CD07AC3F7C3A1DEDEDE92E +:109A7000DFC87EC4D39B46FB7C8C17FCA598FBA754 +:109A80007F2936E8CA77C6F8BFC2797E65AFBFD9ED +:109A900000F3FF6AF2FAA76ECB0CFBD3B3D1250516 +:109AA0003F680E538D94D7C8BCAF644257D78381AB +:109AB00085F08D2C40E577F2FC17715D35608823C9 +:109AC000EC2F350FE96F5DD1F38A19CFE71533DE3F +:109AD000A02BA5B17EEBF8229C9797E6F5E6846B68 +:109AE00072705D625E956355ED3E44EF2E9CDF57CC +:109AF0002F7D71521A1EC6BFF0DB375568F928EB6F +:109B0000251E9713F69A96CF22FC8EDA3BA420DA14 +:109B1000EB0BC1DFC173A6F734FBF33D2BD7CF6747 +:109B2000EB8D24276BA518379EC79DADFF0F1BB289 +:109B300035B467785ED282894250DFF2AF12F159B4 +:109B40002DF463807E8AC666D27A6A99C58BFAB88C +:109B5000F6907937F26B2D987FE867019FE48C4788 +:109B60003E9920074C6007BF6908E648742EBDCCBB +:109B700024C1FC5624017F0C1B980FD66AF719C428 +:109B800073E02F37F6F7D9CFC6E7521CFFF0041564 +:109B9000F1D562E0F79802BF92DD3C3F868B687991 +:109BA000E2188A4F32C5EDC6F852B576EFA5536676 +:109BB0008DCFF5233FE78EE7FBEB4D97717A90FA57 +:109BC000D59FD7CC18CFFDD0195ABBEA23AF65E09B +:109BD000BDADB55D46F24358614F9ECFDECF7A1AD8 +:109BE000B7DE9915C1D7EB0E9EE0F91AAC272F32DC +:109BF0009FFD56AD5FC147B2C9EEDF6D8B9C1F1F45 +:109C00001FF87A0EE2E1AB78E0EBE1C4D727D1CEC2 +:109C10009E6556E36E84B207501482D2FF0327E597 +:109C200027893CA5A5CC47E50A6003E4635FE00112 +:109C300013E27F15EBA0E76B4B6E1982F03AD65B0F +:109C4000E5423FA2BDF91517CC72DEF607A6625CAD +:109C5000766E70F12B58CED92B9D44BF15F6C512E8 +:109C6000E4E31EA9BE6D308CB7E0D98AB634783EE5 +:109C70004BE6F460AF737A00BF78E5844BD709FBFD +:109C80006015ED83782FAD43764CD7ED83DA8DCC1C +:109C90002B2585F3EDFBF645C9AD7F4A433F48E9E7 +:109CA000A5F3F77587CD0948E7558CEBEDB01D2876 +:109CB000F435B7036E053B00DB7DA2F1F327198C69 +:109CC000EE357C228163E709DB916C88DFE5191EA4 +:109CD000D6BB9F1882C58EE1A4979B71BEAFBAE632 +:109CE000A9182FBB35C9E296B13E3E38849FA3F632 +:109CF000C9777631361CEFBADFC8E34FD1F3924A09 +:109D00005EFD2BDA0D66130BE0B906EC6B568CFB8F +:109D100079B089F6590BA216E366953EB5BFFE5B96 +:109D2000B57EBBBEE6FE6F00D683F77C2E19C7A9B1 +:109D30008D13C3C711FA03C723F991C274E3ED1958 +:109D4000CFF7F59B762FCDBFD9104FF2E60F43FD2D +:109D5000BB91EF44DC47F8855D991F6791FF7EA1B9 +:109D6000251DED73E05F9EC73899CBA5378D6A003E +:109D7000E1372B3229EE2FE4EDEC121E279B2DE26A +:109D800062655171B1A8780C2BEB3F4EC698DB8809 +:109D9000E38E64EF09FC501CE6489942740F00DD25 +:109DA00031CE7C44F34F2B62B95F9E509248EB4C0E +:109DB000B8368BF8CD91C842740E659789DF8EB2A4 +:109DC0007C5B42849CB8578BAF6E033B8845C4D5FF +:109DD000EF2D6CB060BEC1661BBFFF785F654C5D48 +:109DE000647E7CE2649EFFF2C3C915AC04F0976701 +:109DF0000B5692BAF62A2AAE47D2D637DA09F83786 +:109E000060D73E2D4EEAB6F0B85415E96B41F72BFA +:109E1000D5D7CF28C18D31B8FE2446FBD0BEC34A6A +:109E2000F254EEF08630557BD9E4B9EF223F33C5CA +:109E3000978BE37416C7301BB4FFAAD344FEFD61B1 +:109E4000C3921F9870FFBD6B6678DED9614F535087 +:109E50005F747C3DAA8A4AFBC4698CC739630D20B4 +:109E600028F29DEC897F43A269F7D54CAEA3933EBF +:109E700002147748AC8B51DCCD1B6B009FACC3C088 +:109E8000CE95C3FCF6DB3C0F8D2316F4C9B8DEA1DA +:109E900093FC9F227F15B37A82EF33F9EA76C3F8F9 +:109EA000F72558886F3CA906BA3FC8FE6AA3BC1FB5 +:109EB0005F97624415F76299FFDCF808BBCCE73284 +:109EC0001831FFA7CD04F23B0FE32831FCCC8A7197 +:109ED0007BDF773E87E6F78D264F5B5DDE6EBC88C5 +:109EE00032205E9D4A6F5FDC84F8329DE27D02CFB6 +:109EF00091F47416EBE8E93746D2B304E8392692B8 +:109F00009E5EE96AE8F90E26A1155DCAC7814AF589 +:109F100081AA42AEFF30952E9A8F2BCC936C980776 +:109F2000D3E9900D48D7CE98B43C8CDB093E167C23 +:109F3000DD0F3FAF3F8A72255D71E279B2B93A8693 +:109F4000CE67047F0BBE9E5EDAC7DF8F95023E1799 +:109F5000DA7C5351F644F337C6CF22F9B876407E07 +:109F600067CEC87D3E0BEC8DB804B4934EEDED8802 +:109F7000E0E3DAFA2F142E772E96C71487E37DB329 +:109F8000CA24F64124BDE1FF07B9DAFAC84E52C827 +:109F90003F1378BD52FC1BBFD39C8B76DF26BCFFE2 +:109FA00008F86A97DCDE411807AB3F711B3E6FD3A0 +:109FB000EE2507F24CDC1ED3F695E86FD9E4CA69AA +:109FC000B8FFEDE3CFC42E87765FA51854444E9BAF +:109FD000BAE4DF689F1E8F65F89E23B1BBEE09DAF5 +:109FE0007723189E277EB5D23F14CFF7B7009D3E4A +:109FF000A0A4EDE020039D7DF50CC27D07C875F19E +:10A00000D2EFE2CF99561F24F80F138669E78C5ED2 +:10A01000AD7D0FB5DF62DA6E89C171322DCE3D1193 +:10A02000FC5FAEC5E35B4BC4FD9F1615F3DF5A4BD7 +:10A03000B83DFB50D3BE491F65E37C3A267D04F34F +:10A04000499C19647EE0EB98DC808AA923966FA670 +:10A050004878CF818D621D18A7C7E7CD63C2FDAFD9 +:10A06000D4FAB5A09D03F4B36C0CA89172D662909B +:10A07000FCFDE5C9FC718242FBD5B29151BDE5C83A +:10A0800023F4FD80C42CB784F9D5968DDB199EDFAF +:10A090005843FC795296575A1AD16FD24C9877048C +:10A0A0005F007F05E2402E59F6006316221D6228EC +:10A0B0005E193DEEACE4CA2EC531309F44F31BD38C +:10A0C000F84DF08D5827DD8089F80E40D5300BE92A +:10A0D000C9B646D36EB4CF7795C4135EBE4CAA8C76 +:10A0E00063FDD8A7A2DC057C1030A33F6DA1720FE1 +:10A0F000F8E38111E84FBB087E0AFC712CF7813F21 +:10A100008EE533E08F63FDB3E08F23FC13F0C711BE +:10A11000EE007F1CE1FDE08F237C00FC71847F0A50 +:10A12000FE389607C11FC7F2E7E08F63FD21F0C735 +:10A13000112E37037FE07A7203AEB940D7F6BB4DDC +:10A140005ECC33FC6D0997A747BDC312DD407F6B22 +:10A15000AE8162E5D6371E64B81EABCB40F7CC3675 +:10A16000B91E64B7A09F5B6C277BABEDC7DC8EB1DB +:10A170002A0F31943BBBA4401D73C3782537D5E229 +:10A18000B960966B7D6502C0474A16EFB4C0FEC841 +:10A1900051E7CC6F8E8055BB67D573CE303C346FA2 +:10A1A000B7029E0CFBE5C15B76E215239C07E61720 +:10A1B000BF55B2BC16F3EA43C318D923BD9926CACA +:10A1C000E3598AF4CAC6F9F373C0EB588B0BCF3945 +:10A1D00087AAE02D49D49EE24C57DAFEB7252A3DE6 +:10A1E0008F7EEF72ED0C8557D48EC997E90FEBA5E2 +:10A1F000CBF46391E659BA61EE5B8D9A9C4AB691B5 +:10A200009C6AC7B80FE0BDDDCACBFC52BECF8DA59E +:10A21000950F4F80F2E1099CAEEDD680B312C71FB7 +:10A2200063A03C07D698F9CE3018EFCE5F290CF327 +:10A2300045057F9ED1F8207BA89DEBEB7B2C74CE4F +:10A240007FCDD01FB726009CFD84DB8DF9105B9974 +:10A250003B06F924B0CD4079913F2A1C9E30079AE5 +:10A260008F2E7A2101E5FA8C097C1E412D8FA8B929 +:10A270006DF9508C537DF51697877FD3C6D96DEC59 +:10A28000AE277A16D918CFCBDA4EF648B30B880D25 +:10A290003AD390CA4B93D1B900DB99C030C0BC6DA2 +:10A2A000D3D7E32DE80FB69C374FE779B5DD649F30 +:10A2B00098AC7E673C3CDF1E30905C68516D940723 +:10A2C000B7D5E6E9C27BD301A781F265B7E61908E5 +:10A2D0008FADB61B82E8072852731DEAB1A073BF89 +:10A2E00025139E07F30C94FF18F4CE9D8E70C0CFFB +:10A2F000BF47413F58EF4FA0FBE25B59EFEBE3B0A4 +:10A30000BE96DB696D29FF752416E3E2D73BDDFCC1 +:10A310001886A9983746296406F4C77B36C6E23CFE +:10A320006A98E6EF06C8BF759839FDBEDB79AD7354 +:10A3300018D91911E75D668CE1B92D6EA81F6BF372 +:10A340004C47FF53B17B2C9817D8EAF45816D3FA30 +:10A35000793E1BE56B40BF2D4E03F9C1587F0BEED4 +:10A36000F75646F97083B5FA56DB839D880F651959 +:10A3700063992ACE4F09449E275A869775A9B08EB5 +:10A38000F6E509B40E457213CC962934EFC16A0C78 +:10A39000DD937EC854DD85F6E460CBAD74EE955A4E +:10A3A000A7E8CEA506F9F570F27C3D9CC894F0B9FB +:10A3B00016F2D9041197D3E32D1A1FA9CED6B77080 +:10A3C000FEA97EBAC47BC9FC1F717E2FBE82E13C10 +:10A3D0006D34CF14DB920AB49B9299AF19F9EF1F39 +:10A3E0009DE758E75C4B268C3F36C940E6D138D60E +:10A3F000BB11FBDDAAF17B7B26A767785FC9625F93 +:10A40000364D48C6F305033874E1FE3303E0D8E95E +:10A41000CE17127470F6F6C1BAF623760CD3D58F28 +:10A420000C8ED2D58FDEE7D1C1633A4A75EDC71DD8 +:10A43000ACD4C1F9A119BAF6055D73757051F70274 +:10A440005DFBF1C797E8EA27F4ACD2D54F3CD5A025 +:10A450008327F5FE8BAEBDB0EFA3F5E3DD13B87D2A +:10A4600071B576BDD93558F7DD9C68BF21DAEEB7F6 +:10A470007CD3A26E447E7698889F15D4E7780E7DB3 +:10A4800037F79F2C93DD2AE5396BFC5854EEDD84B9 +:10A49000F2B4C26121BDA0D8783BC5368DEC9521C0 +:10A4A0003B4CF43D1FC5C9FAEA63513E37052665AA +:10A4B0006587E76D756E67B87F2B1CD319E6298910 +:10A4C000F715A797F9318F1B3FD28376923340ED72 +:10A4D000AC2ABC1FB18EC30603B3A11C073F0FFDFE +:10A4E0008381FC3AE1CF09FF6D20BF4DF86B430C2F +:10A4F0002C06CBDD52CF6DE8DFE7D5BF553988910B +:10A500005FB70FF9F53EBC078EFEDC586E67B5A548 +:10A51000CC5031DED39ED9D1350CE7936CA0382ACC +:10A52000D8CDEEB911F6E2DB9AFE5186B5F7A0FE62 +:10A530006B88B7A8682F2996DD933E027CED32F632 +:10A540003C8DF18B56C9B9BA03E5E2DD36CA0F7905 +:10A5500048C39B6A37146C847E3B9ABD0ADEF7EFD2 +:10A56000D8C2DCADB83F922A36C6C3F3ECF4C506B8 +:10A570000C138DC86ADE88E5B109FC3C6864DE6EA8 +:10A580004322D48F2EAC988F7131D9B99BFCD981DD +:10A59000F84976EC60B81E96A59C44BE42EBFE22BC +:10A5A0004CBD2201E80DE35A91DE12958407EB7948 +:10A5B0005BD08A7016C78BD52B0563256EB7627E7C +:10A5C0005D45C20EA2AFB067D1CEF5737FF76DE4E3 +:10A5D000A3A4997ABA2A96BD848FAD06BE2FDAE37A +:10A5E000D537503FB7676625B4A8E1790AB9F24775 +:10A5F000CD0E17CF855C998D3938C961FB06F87C83 +:10A6000007C6E7ACCA76BAE769DDB09D215F5BF1AA +:10A61000563CD9FB01D547FAC3A7CB4FAB1A36DF5F +:10A6200082FAFA5C9287EC596BE34F697ED178B37A +:10A63000F6F03CB581F0EAC87994F43B086015FD6A +:10A64000FE2329B6BAC8B8A828EFD2FC13A3C8279E +:10A65000024F02F5D93991AFE48DE5F38BE7F0D1E4 +:10A660009C0534BFDB923D832E676F5BC1DFF447EF +:10A67000D07D8BE2B3201EDA2ECC994EEB56683398 +:10A68000B0AD5FE7EDA678B3E62FDDA5E1B7B58401 +:10A69000E3738889DF337027CDA4EFA40DC6F84893 +:10A6A00041385E32AA94E737BA034CE6F1BEBEFCED +:10A6B00076C3C571346715EF1FE09920F2631AE382 +:10A6C000FA0C9A74623ECBF076459F0FAFE9F334F3 +:10A6D000FE3BC87F7DFD881D7A786430EAFD00FB73 +:10A6E0000DEA7BB477299EB14F5FFF18EA6D901396 +:10A6F0004B35BDCDB6F3FC120BCCE822D7B761FDCC +:10A7000007F260564777452CF49351A2CF3B498B13 +:10A710006C07F8F3AC34D0BD1211DF1178F7D519FE +:10A720008C26E27F55770E27E239D1F25ABAE7CC70 +:10A730007ADC5715B1B12ACA598C77F8CDDC7FF78E +:10A74000833F739FE2FE7D2DFA5F5D32E561097AFA +:10A7500046D37F6F9F3DEC2B2F253FBAA700FD7A94 +:10A760001CCF1F319E88CB6497FBA7623B119F399A +:10A770003B5D794552C3F116113F7818F719B4DBE8 +:10A78000EA7EBBFE28CCE3E87133C54AA6CA6F74E3 +:10A7900035619E55864272CE397EF50FD04FAFFCA3 +:10A7A00003D4635C52550791FDDE65A47841A5C6CC +:10A7B000EF959A5F26E2320BB579D7940A7B281081 +:10A7C000C3FDFF500CDAB9A3F7818CD6F34B2CAF45 +:10A7D000E771BA311DD1F55ECA7F1AA5F103E6AD66 +:10A7E00055A460BA18873B9894E8043A8F9BDF73AE +:10A7F000045D8CBCD75E8941BBEB392BE78F673496 +:10A800003B2F85496ECCEF4FD9677307A19D5D66DD +:10A81000CF75C33ADCC7145D9EDAD8437A388F45CA +:10A82000C099380F3DBC4DADC7A36BB6AD165811DE +:10A83000967C47A9964792C37290FFA6CAB67CF44D +:10A84000B31A2A6C0CF16A3E31E2FBDD2857DE9226 +:10A8500019EA0B67ACFA4015BCEF7C3DD1DDAC8644 +:10A86000E9FF0CF8DBA8471EBEE866ADC670FCEB3E +:10A8700059A067169D4F3BA9BE03E88AF07EF0BF42 +:10A88000B3E87C3A979EFF14FC6F840F82FF8DE53E +:10A89000CFC1FFC6E787C0FF46F887932B1EC4B819 +:10A8A000D97BD00EF92226FF806538C6CB6D32DD0C +:10A8B000DF89E6C7CDF51FDA6E049936CA953C33B9 +:10A8C00019F9E17699EE45432733D1BF8D8CBF4509 +:10A8D000C623C3F1B71E49C4DFCC409F519A7FD92C +:10A8E0001787F3F338DCB7F7E315FD509CF3927E3E +:10A8F000FAE29D96C047B928B2241607CF3FBDFBA8 +:10A90000DF9F427D24A7FAF7E23E5953F48189DBA9 +:10A91000E7FC5E56BAB68F765A793E6ABA96471405 +:10A920001DE79C3CE5C46DC980B2177F7ED3428C85 +:10A93000134CBEF544C11080BF29FD25877F78E206 +:10A94000F934C0D3D289ED1C7EE8C4B97437E671FE +:10A95000EC5F88F9C38E44AE07776AF79B047E8F5D +:10A9600069FB665DE313A4EFC11E61888F96141F17 +:10A97000E9E1CF937A1D8BD1AE4BEE4D597219BDE3 +:10A98000B1AEF1297A7FA7E43E15C4794FB0F0BC8F +:10A99000554D2F9DD57857E8A5062B07C57C187314 +:10A9A000D1F387B47811F3A6D17B89560E1F759425 +:10A9B00092FEBABF52FDB5CACF3FC98F3EEA18F525 +:10A9C0005DCCCB6B99AED0B9E443368F15F5DBE7A0 +:10A9D000DABAA0FF00C60902532D745EC492E6D312 +:10A9E000BE4E10E324D5523E4382369F63A53121EB +:10A9F0008C23B45459F6A01C7DD0368CFA6B2931C7 +:10AA000005307E23E08DA5301FC067BC2321136174 +:10AA100021E7447C99E1E91CF45BA92DBB52E44990 +:10AA2000588C6722ED701BEB26FE711B5419EDC884 +:10AA30000D13395F1530F77C7C6E92EA03C88CB831 +:10AA40000E43E43AD42AFD3AD4A9BA75480D9610BB +:10AA5000DA8F2D53611DD0FE98BD98E61B4D37B19E +:10AA60009E0F4B55C257F43A99762E25EE1F543A55 +:10AA7000CB0EE0BCA61ABCAD38AF57FE5A9B841F64 +:10AA8000E89BC6EA157C3E3C9C0FD47A35F91693B8 +:10AA90003F94F839DAAD265A9F71329FCFA3A66052 +:10AAA000265D0C5182A9787E3C101F674E8CE663B0 +:10AAB0002FC3FDD592E0E57CECEC7534231FC7F77E +:10AAC000A66CA47585FAA54F343F47D32B6F22138C +:10AAD000DF079111FFDF465F41D7E8F334C12F1B39 +:10AAE000263A05BD5DB4CED010DD7923F4A0F6770B +:10AAF000CEBE09FA5323CEE54C2E1FD9E3C62477E8 +:10AB00002EC6A55BBE91FBBD7F59ABE1A9D9114310 +:10AB1000767A8B83DBE99D8E193AFFAA0AFC2D3CDD +:10AB20008F96135907EE2B396E01C5DBE441689906 +:10AB3000115BE8EDDFB899DCFE757A2E7BFF4AE900 +:10AB40009175DF73BBC4FE4D98C1ED5F8789ECDF63 +:10AB50009D76D3FCDDFDC89DC289DC4FEAC475F447 +:10AB6000E35F825F49714FE1579A9C7EF20FC53ACD +:10AB70000BB57D26DA9B9DF50CE370B2C9ADA2BD85 +:10AB80002B6BF764312F3A37C22E10E38F9BC8ED41 +:10AB90008EC1E53C5F53E4C74FFEB554DF1FDED7DF +:10ABA0004C147649FF7CF70FF00DC9098FCDE445B1 +:10ABB000BBC36373511EF940EFE151F8A984B09C07 +:10ABC000717F532C933E52DC742FA0C3D8F3FCAF9B +:10ABD000D16F7CC5467AA7C39E4EFD09BBBD2296A8 +:10ABE000517E33F8C9815CE8ECB9BFC18E3484FD75 +:10ABF00063F0D7364F8C38D73CD27092CE8BA2ED13 +:10AC0000D5E8F843DF7E773C95C9E7134CC5FD2BAB +:10AC100035940C42BE8ADEEFA2CC70158C5A0AF332 +:10AC2000CA48CDA7523C7F9CC9D3FBFB6EDBAE3E2E +:10AC30003A703D3D12068B93493FEFC2797F7AFB14 +:10AC4000DB296E15EFEB7E417AFA6C7D49DC66E418 +:10AC5000F7DC0492AFE9DAFD33319FF4959DF109F9 +:10AC600036CC03EC1D89F973C126DFA82A23C50D54 +:10AC7000BDFDCDF757DAFE63A1A12CF2BB446A52A9 +:10AC8000F7B52300EFAACDE056697F3949FF0939AE +:10AC900050A1C4573981CF339A98DBA6E2A79B9D78 +:10ACA000143FCBB82813BF651CE5DF971E9AD42B41 +:10ACB000E1778FFAC6D1F2A4C439CC97F555B43FE9 +:10ACC000330631D68D7210F43DCAF92F934273705A +:10ACD0007F7FF93D3EA38C27F4F5A07329BEBDFC10 +:10ACE000F698A00A5D0FDD00F3C3F9FC4062E99914 +:10ACF000388FA3999B313EF4622CC587E41D59140B +:10AD0000DFB93ED5BF7F22CCE3D3A07AA761B8B626 +:10AD10005868B7E6AE18FA2EC14EA9FB5ACACBB88E +:10AD2000C340DF6D8DC6D75B13B95FF9F644BECF64 +:10AD3000325CC59CDEAEC2514B13AF7C3F7D83DFDE +:10AD4000D601FA6E8D0BD2799EC82BDB66EC9FAFD5 +:10AD5000CACAB87CE993C71AFE2CE80521BF489AF5 +:10AD6000DDB7EF99679E4961FC8AE2307E6E197902 +:10AD7000BE1C9315A4CA18B797E48FE4F47239EB9C +:10AD8000AC770580BF377F2DF73BBEBD4C93D31901 +:10AD900077BAB07D95EAA6B233A3F8F862C09FCD2A +:10ADA0006662E608392CF8245ACF37D8875DD6DF9B +:10ADB00037813C562F138F306979649B8E4CB0E0FD +:10ADC000774B37D93CDD687F6DB22579285E6F03FC +:10ADD000B91111BFB2D95E253EB4B9795CCF86F204 +:10ADE00017E357B8FE3C9CFFABB47ED1EEB4268788 +:10ADF0006CEE109DAB5ADDDBA99D45F1D1FD3B4BBF +:10AE000012A37C088B937FEF3426CBC02CFDC8E3C4 +:10AE10000F501E433F9BF23CDD95343F05AF65B1BB +:10AE20004D2E8F8BF421E219DE3F6A2F8E8BC4CF1B +:10AE3000500DCF2D9D7C7DBEC654675501FAB5BE21 +:10AE400094B222EC678905BFAF27DB0B2FDB4F6E77 +:10AE500019972BE17E1E49A94AA47E86623FB2DD86 +:10AE6000E3C47E8CDA775BA3F15CA4BDFFF7C6DD9B +:10AE70000083940F447821C2847474892E6D183F26 +:10AE80004BECEF3D2E173335FF05E4624519CC6BD3 +:10AE90004DDE07AFF23DC6FD96846B79BED1592DCC +:10AEA000DF3C3A4F23DA8E11FA47E823E847C67EA3 +:10AEB0001E453B6644781F0DE6128BA5D5F9F87E3A +:10AEC00049F211BF805DA3E27E91B57CC1E8F56CCB +:10AED000D6F027394A54D41755177AD2F0BDC3F6A5 +:10AEE0005369DC8ED59F471FFBEB5356ACFFB2AEC8 +:10AEF000F2B2F68A387F1EE8DCD9F12F9FAC8FB40E +:10AF000057063A87FEB6F3E7230E13C5F97649FADA +:10AF1000FBF5CD9A1CDA5026E232FEDB901EBB24F4 +:10AF20009F9B5F98E6F199A272FF9DF87C48BB89D0 +:10AF30000580AE87FF5AECF247F473A57816F1FA54 +:10AF4000C19A3D35D8F69484FB74705D50C2787B0D +:10AF50005A5D87E4BD4CBBD9655C8F8BF646ADFF6F +:10AF600072A557467D55EEE47A31EDBCC27223E4FA +:10AF7000CE8C32BE7F8D9AFDEE38F2B415FB3B626B +:10AF8000F0B5E7A07E7018D42723F6BB71A5C75291 +:10AF900019B1BE163C47EA878ECF94F5D95DA4BFA0 +:10AFA00085BE350A3D91A4E8F4C4BA58CEC7C2DEC6 +:10AFB0005957CAFDA175B1DC2F7FD1E57F02F7F3A8 +:10AFC000E7A59FCC1AAEE23DDB0E139EBB7FDB797B +:10AFD0004A9F7D63082E16FE0CF2BF5B71FEA2072E +:10AFE000DECFFF6105D97B45F8E512198F70B9FDF9 +:10AFF00007F6D473385E014E3D82DE2CEABB860331 +:10B00000AD67277E4BAD08E37FDD14C7BDEF82D46B +:10B01000EF7D8A2FCB84BDD0776E78D938AC8A711A +:10B02000D84C3C07D3C7490BBAF47051B71E1E7FEA +:10B030003C3AEEEAFD6D64DC7527EC33941322CEC6 +:10B040009A1E0856E03DF30CD641E7906975093A1F +:10B05000BC4E96B5FC0CFCBC7244FC374DA93E8D31 +:10B06000EF9FEE5B5780E9EE07542DBD133FC519E6 +:10B070008EE3AA84AF15D7CE9D8A748D8EE766D4F1 +:10B080002BBAFB84D171DCE53BF5F70D7DDE7CF25C +:10B0900007E67D471FFF1579EDB8DE34CFA5E37FC6 +:10B0A000FBB8F03FE1D2F145BF8F82FC21F9AA7DC8 +:10B0B000C73803ABB01F2524E179F8E07A46DF33C7 +:10B0C0004EBB9D79FB3B57489BC4F1158D671628F5 +:10B0D00027FC4DD19E0DB6F1BCD7C1B71BC81E1CB5 +:10B0E0000C7281FEDEC16AC612014E5BAD923D3923 +:10B0F000BBCEC0503FB00B4DBAF761BA144F1574B8 +:10B100007FD4C6F37A33D6B0A001D7533F8AF61363 +:10B11000CD6B982EEEAEFB2EC1EC12FD7DDF8CA820 +:10B120007BBE820FD2A29E1F2A73EAF605E8B9B44D +:10B1300049C4275CFF65A3FE83297D3AE1F8539853 +:10B1400087377923E3DFC3898FD1BE87D3775E2129 +:10B150005F047E3D6299928BF6CA56678C01F32399 +:10B160000EC7F73CC6E2191B338905F0FB9D2FC7BC +:10B17000F48E96009EF0D29E5DED4094C3D6DE1F05 +:10B180006130D9B6EDE99BA747C08EFB5F22989549 +:10B190003015BF2F84B9ABB8EF629C33F6E1F77C72 +:10B1A00063F26C149C8C61FAEFF8B496AADB30BFA2 +:10B1B000A435DBA0DDB38EA887753C35C929F2E242 +:10B1C000284F8F4DE7F90291FD639EF780FDCF80F8 +:10B1D000FE0BAFA27F0B9F7F0A3E023D9382F3C717 +:10B1E0003838F68FF4C5A051E4F85A7F0A0BECC644 +:10B1F000F31D18CF26F1F19C98BF92C2F4F90A7D95 +:10B20000E33961BC31FF17D633FF527A182F478FCD +:10B210000557478F568397E61B186B233F08BF8758 +:10B2200085DFBDB36AE359B5EF7F215E5B8BC378E1 +:10B23000053B90FA85E6CD17353C633E628AD344E0 +:10B24000781E086F479C3C7F6A8B3326D89CF9FF99 +:10B25000805E2E4EAFC8F1D09EBCE2F116C0784998 +:10B26000573E1EE217F74F1F7E81261B53AE1CBFB1 +:10B2700030ABC095E0F708F46B88C06B384FE9112C +:10B2800027FA0556A3CF82799BCF4FE2F98F7949F0 +:10B29000732D94B7903C97F290DBF26C9457DF9645 +:10B2A000F51D8B31424FB7E5D5523DB4A7FCAABC82 +:10B2B000500C8629D818D64D71802D65552EF40B6B +:10B2C00003F53C5F4BE42F097DC8B4F3515A17BC1A +:10B2D0001837E940EF1168BFA5BE90F2D3E2E2FF54 +:10B2E0008BF2B2B6D6B9DD58FF189E63813DF1B03E +:10B2F000768E858C4AF1B4B1A54FE0B9AF27BB413A +:10B30000C2E3A6F4D57AFD34382AEFC7F345772592 +:10B31000E677B1C53C7FCB55AB44E943FDBEDD8A42 +:10B3200078E579564189E357D7DFE949C9A4E7B6FB +:10B3300064ED6115D0EFF3D097ACDF5F06CC778A70 +:10B34000DE8F8AC94BDF29630D069A471AA6108043 +:10B350008AF38C99E95A0CCFD39729F4FDDA417915 +:10B360001B28EF09AC7CB237F2F2DEA844F89275E4 +:10B370002ED5AF237A5DD1F316DF5716F4F27CE1B8 +:10B380008E45FFCA933D97F2D2E847EC77396A3D84 +:10B39000600F5B930CF45DB998AC8875315D3BCD63 +:10B3A0007FFB9F857F3F8971FB39FA5CEC7FF1FB66 +:10B3B0004766E6B698E83D715F879FB70DC6BD83C7 +:10B3C000741FC2787E78F4FBC5FC7DE6E2E76FE689 +:10B3D0001866C1FB3AD2AA188A639ACD00E37D1E93 +:10B3E000ED7B658F6AF1B6668929A99EC8F1429402 +:10B3F0005F2F5BAECB42BFE188659E93EEC9697E4D +:10B400009431DE47F98D2C3741E78F1ED1EEBB35E5 +:10B41000ACCC1C84F1BB38A8EB46BF5A715B90DE04 +:10B42000226EE218DE7313EAF16193872FB2002EC9 +:10B430000EA3135CCAD8B8C3193FC0EF148BFD69C3 +:10B440003ECFBFF7D1072BF5943F623E3F44F73C18 +:10B45000A4F96102F626295538DE34F40F92F1DEA4 +:10B46000B8B315DFAB00E4E8BE2FA07D3FE4D2FE09 +:10B47000D375CF43E05F479E0B0CDC7FACEE3B0502 +:10B4800066F077FAEF3F27AA7F67BFFD87FB4DD4B1 +:10B49000F5DBA670B911488A09F617DF5B36B9F2F9 +:10B4A000BAC94503E7B72D9DACC5E12C20FAF11CC4 +:10B4B0004AE39FCDAE7ACA779363F8B9A911C4085D +:10B4C000F2D3517B1DC92D96AECF7713DF2769C309 +:10B4D000EF8E407DA54D6FAF57B0DEA3E324F4534C +:10B4E000F5F6FA645439783EC5A2EDF87A3A273574 +:10B4F000A6EBE5C2456DBF18EC85DD941F976CA3E4 +:10B50000BC8681E20BEF3531CADB32C6FAEA51E77D +:10B51000FDEBE1F143DB4A008EE37CB6F5F0CC4570 +:10B5200018377A4FE3E736900374CFB561D06E39A0 +:10B53000A2DF5A53281BF54AAD81DF17A01F18FF61 +:10B54000BDE4C114678D1E577C7F46C00BEBA54937 +:10B550005911EB7B4FDB1F7DE3DD96B61BEDDABEA9 +:10B56000F1CCA1221AAF2FFF481B2FE5EF1BEF8F65 +:10B57000DAFE16E32DBC53BFBE85A66E5ADF42ED40 +:10B58000FBA762BC3FE2FA32FF8EF1B4BCB1BEF160 +:10B59000EED2AF6FA1B99BD6B7B0CFBFD4C64BF92F +:10B5A000FBC613F90E66737D1DF2D340790F22DFBF +:10B5B00021C795A8CB77C09B2715598C3D2071BE1C +:10B5C000787D72CD0F30CE7F6E66839BEC14CDDF1D +:10B5D000A37B4432DD23223D3A3B9DDB21A2FF7D4C +:10B5E0004D25CC3B82C783B0CC2D93E89EC2C812B8 +:10B5F000C98BE76C3B417EE077F476C13EC7FA60C9 +:10B60000938BCA3D4D2A957BC1BFF452FCCB4DF0C4 +:10B6100085C9DC5F7C20D559B314ED8F8A189EA7AD +:10B620005D36112CDBB0FF06FBE58815F3216F605A +:10B63000F9F8772D7376707C2655A5D0F7F663F26E +:10B640008F753701BCB9445631FF7CB3DA7F3CE7D4 +:10B650002F5ABECF662DBF3280F72E49A9803F59A1 +:10B660004C7F3F8BFFC833E95ECEECBBE2C9BEA97D +:10B67000FD4E8FDD09F3B859CAFF6D16E0E34F9A0E +:10B680007DB368C80C9207D1FE69126AAA42CC3B0E +:10B69000948341F8759E7D1EF9B7F3AE672C01DEE9 +:10B6A0009F8DEF819EFAB5661FBDD96366E8FF05E1 +:10B6B000AAF8F9F5CD1BF47EE903D69013EDC20785 +:10B6C000F29318D2A3F6767DFD6613DF6FF3A2FC2A +:10B6D000D4D951793FE23B8A9BF1D7098C7D395906 +:10B6E000FB8E9196F7B35F8B33B1F4044A0617F7DC +:10B6F0003DCD66D6EFB9A4E82F11041DBD97E42512 +:10B700003C88BC77263F9B8FEF8BF1C47B8F4ACF61 +:10B71000A65E2E6E0A76E0C99E5CAEEFD15EB7964D +:10B72000EBE7796EE6B0EF56B1FEF8B657C1388553 +:10B7300098FF3F8B5F8FE27A414EFF7ACA9785FC74 +:10B740003E5E3A8BBC8727F2BFE6F5C10A7D9FF8C3 +:10B750007A01BA7AF390DEBF9914EBBE97F84FB333 +:10B760004742EF1A2EC65E7D7F7DF370793374F702 +:10B7700060B5FE06C2F340DFADA09FE2709CB7A5A6 +:10B78000D9EDA27B77C9FC9C6D7052E569BCE78559 +:10B79000F51FE8F84B7F9FABA5F36909FD96C7F04D +:10B7A0001E9C31224E54D721B5D9B0DF208F2B8576 +:10B7B0009EA6F86F7A5D486ACD0BDF1B8A968BE9EF +:10B7C000ABF5F7D2A2BFC7586DEB512415E3FDBD11 +:10B7D00074DFB1AD5C3B9F411C63BB646E4FCA69B3 +:10B7E000069E2F3254E5F66556EF90C8F38E55E568 +:10B7F000DC6EA88E7DFB761544AFBFBC6311E645B9 +:10B8000055C7BD7D7B26C0B7943FB708BFB3589DD1 +:10B81000F6F69799206F9795EFE7F0E8B7BF1C060B +:10B82000F08AF2E7398CF91E80A495E50716A1BCD1 +:10B830005D552EBEBFD84DF7BFE554CE477F776923 +:10B8400036F4BB2F6F2B17714B46F7BD7D877E7982 +:10B850001CE5944FC479BDFAF34DA67D7FF13AC142 +:10B860005E490EB29766E0EF80CFEBB4EFF6182C8E +:10B8700021C2EB88F07751BE7735DFED09DFB7E7FE +:10B88000DF9D6A69647EFDF715BD1AFFF3BC2131A7 +:10B890001F31FE25F3C2EF0B2644CE6B27F523E6BE +:10B8A000F579BE39208D0B9FD78A797D2EF5EEC2B2 +:10B8B000A047CF94DEC548D7CFEDBD43F0EFAB94A2 +:10B8C0008786FA094EEEDD25B9236023A7E323E539 +:10B8D000FF87ECA951A9DE47CA317FCFC4BF83D00F +:10B8E000AED9915B93FD01F4EB81DF286F3390C1FA +:10B8F000EF3B5415EAFF0EDC131A7F1579F9F9F4C2 +:10B9000054F3F6FAB70AF1BBEC126B86F6EB2E9CF9 +:10B9100033A1DF5F7DE88409FDFBB5074E98D07F3A +:10B920005F8B30F4B376A7A9DFBF4357EA95C5FE16 +:10B93000D5F92BAF64E4B425C17CD62EE5DF016BCD +:10B94000F859FC54841B16E32AF1EFF93D37155FD3 +:10B950005BE8EB6CC37211EB7905CF256AFC7A3F8B +:10B96000E2A63ABDDDBFB05E6FAF2FDA0ED401BDE7 +:10B97000B6A8312DEA7B80FC3B83351A3D6B5CDB3E +:10B98000BAF13B06352CEA3B83011E47BA89AF006A +:10B990004A7D7CA41AFF9E15AE63B54C71DE57320A +:10B9A0003629784F6E5DBD44F97B530F7E61A27AD4 +:10B9B0006887E74A2983F9F7F484FC14FAFDA6970F +:10B9C000761B315E10FDBDC145F3A7D377C5E7AB4C +:10B9D000ABB87E1FFABBA909F03CFA3B82B507B9A8 +:10B9E0007EAF6D9482F8DDDE9BEAF4FEC042D6DDC8 +:10B9F00086FECCC27AFDF3458D7AF823A1D746B3F3 +:10BA0000D1B83F4E974B0AED170D3E93F1BB37432C +:10BA100030BE3BD5C7BCC027AB4DA1B1A8E7DCA960 +:10BA20007E82453D3C5F8BF27FA07DF8FF4BF9DFC6 +:10BA30005818855400800000000000001F8B08008B +:10BA400000000000000BED5A7D70545596BFB7FB07 +:10BA500075A7BBF341E73B31045EBE58244D68D265 +:10BA60000441778AD7DD494FF8723A40866008343E +:10BA7000B350152549478953B1CADD341063072DEA +:10BA80004B59B4C0F28F06C5D51ADD0D92C1CED286 +:10BA9000301D302C3A387676D08171B582CB3A524F +:10BAA0008E9088A3B8CB167BCEBDEFD1FD3A2F8AFE +:10BAB000B353FEE16E527073DFFD3EF77CFCCE396E +:10BAC0009710E1A3B1D984E8082537F484EC344811 +:10BAD00056E7024202EDD47E5024A419DB4D84FDCA +:10BAE000DC28C1FF797F56D74FAE3B244A480DCCA6 +:10BAF00063F676119CE718B51E844FB5822464D98D +:10BB0000E03B254D0369D0177F96C4CB05928E90FC +:10BB10005C427E43C66CA48C90592930610E94AB74 +:10BB2000A78502B0EEAC5F6D0A50986F9683DA7508 +:10BB3000B0AFE5B0E3EE6A2C05B21ECABB0542CC3D +:10BB400050CED20F34E1BA649ED17A90EDB7809096 +:10BB500085842CC33F619CF432A11FC37970EBB87C +:10BB6000EEF2E9A7BFA619307EEFE3137A28CBCB1C +:10BB7000A4EAA7607F8F99F9FA8F0DD1D07698A7A4 +:10BB8000C376EA1CF6CB97085BB7A3202D8AFD4944 +:10BB9000D8F0C79BE72F8576D14AD6674165858D5A +:10BBA000AD5B28D30E56261F433F1A75E96E5442EB +:10BBB0003F79DD1F794476EEBCFB06289EBB9804D6 +:10BBC000B65358AF0CD6413A2A2521A6C04518DFF6 +:10BBD00008F7340DFAE90B7DCF2F8171ED0563462F +:10BBE000528AEDE346EF5CCD7EAF2EA9D1E8270166 +:10BBF00001617F0F58395DEAF4D73380F2E4816345 +:10BC000065F9C436F97E94526FD21151E107F86795 +:10BC1000B05A88383B5E5F3E3B5B555F692F52F5FB +:10BC2000FFC9A232557B8354A96A5F5DEF50D51BD3 +:10BC3000BD77A9FAAF6D72ABEA2905CB54FDCDE211 +:10BC40002A553D75F63DAAFEE9F69FA9DA49CE4090 +:10BC500081379D10A32930E6033A04815717C1FDAF +:10BC6000A518D382741A219519D0194A8BC39C86C2 +:10BC700065707E4A14EF2D785B4615D653DE7CB096 +:10BC8000208A549FF68AC909E52F68C8950D73006C +:10BC9000997C0340C7390F13299440CF636E1DBBB5 +:10BCA0004FA5DC26F9FECE09A5ED25B1086E047E70 +:10BCB0006273F07E4C16F813F9F88829847C3C0FE7 +:10BCC000E6248BE3F32CF138BB251CF7B0B414F950 +:10BCD000948489B502FA1D30C2CD423D70C4C8C6F5 +:10BCE000D9C2633A2941DE042797CFA7BDAEA53854 +:10BCF0007F47845A09F2F7DE8F8CA20DEBC319122D +:10BD00009455DE8F8C242DF1FB05237EEF10C62D7C +:10BD10005628FF69405F1FD2E09341C9C8F8F95423 +:10BD2000B191C94FCB83FA500A65FCBFC209FCD65A +:10BD300024CB61CBA1F1A81ED66F013D13804F4DDE +:10BD4000E27D2B08CA93CFC0F48D097E519E9E2EB2 +:10BD5000CC3840E671F92179846C94A5E99E45516F +:10BD600003D2ABB9D510D74FF06FE31ACF255A05E0 +:10BD7000F376267D9FDEC7E47B63A2BE427A49E963 +:10BD8000391F833C924A62BB01F272CEABD33CD7DF +:10BD900009B7C0CE75CEE766F47E1AE8A6A748C7F5 +:10BDA000643A71FA7D1B7D5EC5BB4EB8A7E47EFF89 +:10BDB000E2A6BCDF14FAD2E2E4ED0768AC1A95996A +:10BDC000DF6B617CDA6CDAB4F5A203E9FF651F452D +:10BDD000FAFF92921498FFFDE137F344E4F3432312 +:10BDE0007963309F7F60248F009FB519C4ED420EA8 +:10BDF000E303FB76B8978E7094EDBF7DC0318CDF86 +:10BE0000DBC3D48EAAD03F38E161E724637DD6340A +:10BE10005C577B5F31598FBF2F898CCFFC3E5833E5 +:10BE200007C7A7844214EF1DF410EE6B889227A178 +:10BE30007EA0DFD414D298E70CD21BC6BFD16F24EA +:10BE400002F0491B8CC7739C2A3E653421DF1C829B +:10BE500073513CC768632ACEDF6520228DEFEFB3B4 +:10BE6000E2D88778FEF39B0D2400DF776ED6337A15 +:10BE70009FEFD2B379F45BFEA3AF08EAEB80FF52E9 +:10BE800060AB27375F3D5504F39E6F853A9CD7BD65 +:10BE9000C5C0E46FDDFD94F54FE65F855F9F95F9C2 +:10BEA000739D4FCD6FC9FC3A894F5BBF1B9F7E15B9 +:10BEB000E7D32AB4B370EF75F9C83F0F11FB419473 +:10BEC0009FEB270DF9B0DFD23EAB7D07D4E7EA4305 +:10BED0008FE4A15E38C9DBE7B7EDA75CBF88F7E068 +:10BEE000B98A8246B28B221FF1FBB23845568A646A +:10BEF0009CA6A2BC0AB152D443B0B484F7FC9A8188 +:10BF0000341DB2E177AE5FE6BE5EB07F5702DF0E52 +:10BF1000499C1F15BD576924BE4369D87FE0B6060A +:10BF200098E755188FDF67C8F355948D7B1AA09C4E +:10BF3000E3E47A3047DE87527F4FE67FD22A50A46F +:10BF4000E34A13A7FBB2EEE87A3C47E974DF6DA839 +:10BF50003757CC78AF0DED5AB0F42D9B0FF747EC67 +:10BF60003AECEF97E97E72F11F9EDB06E735DF6E54 +:10BF700061F7DA70625F0CEFB9A35C2078EFE68AB4 +:10BF800005F93E0DFE534AFFB512E2CB8ED73B2298 +:10BF9000131E4943AE47DD5CAFCE35F2F393081074 +:10BFA000A990E963615175BC9F727E4276B0FEE64E +:10BFB0008A17D83D6DBB9FCC67708A3CC5CEDDDC4F +:10BFC000364A37C13C6B0D92210DE8FCDEB4A6ADBC +:10BFD000172B0879AB0754241CE44C8F89F8FE0A10 +:10BFE000F0528F95D5633D05ACFEAF3D222B7367B4 +:10BFF000787F84F4697CA3B302E975B2F819AF0BBA +:10C00000D6B972C6C0E840888BD1699BCC7B5723D8 +:10C010007A6282F6AB833444687CFF1BAE15111F35 +:10C02000E893DFE37A30B0BDFBB74CCFD95B273C58 +:10C03000621AF2D5853EACFBBBFFE441DCF021D8AF +:10C0400009E42F7F9892029867FDB56C36BE3D3C9F +:10C050006A14910F74E31EA47FE03825C897FECEC2 +:10C0600009A63F9F837349B0EFBF756672BD1199F2 +:10C07000AFE3F7B980E314F9FE87E7FC6706EA2F20 +:10C0800053B7F8CE5D788FA7F5EC1E77B9C633AC01 +:10C090001AF7720EE625297CFF5826B737190315C3 +:10C0A0007618D724F36D72FB43323F02850D881357 +:10C0B000F08702DDD6CBFCD50247990678617D98E2 +:10C0C000462D20B72D11F72501CB4E4A3E52E903EC +:10C0D000423E4AC0C953F1DBAD961D385F45BCBE38 +:10C0E000CE079326E09CE6D65434A209EB07185FEE +:10C0F000A51497E7FBBE01DFF9C700AFC17D75004E +:10C10000101281EFDBAF55B2F2F2D0A322CA89C977 +:10C1100032FE0CDA05324BC7707D7B408D6F36CB1B +:10C1200072BBD9CDE5F929271510F782DEAAC473B1 +:10C13000DB0B7D7B902FFF58FC5EC609F8DC668C1C +:10C140005611EDEF1D88874D284FB06E25DCCF6B63 +:10C150001AFBBED7EDDAE7CC45B97A92F13701FE8A +:10C1600046BE4A3EE70B32EE51E479DD894B46C4C8 +:10C17000BBFEB0B63C77B99D2FE07EFA09A9D7B2D5 +:10C1800073F7C9F2DEBE97327AF9F766333A7D4625 +:10C19000F67A5DC0979FC13E0E005F5EF17A533321 +:10C1A00061FC159F37352B2D2EFF1D7B53D9B8FE13 +:10C1B000F255D99BA03E847C0FE7B81C769B90CEAD +:10C1C0001BF672B953D6FB30BA2E1BE5A7C6306EEC +:10C1D000B443FBF4C8850CC4753543ABB351FEA61C +:10C1E000DAE7CB2E7E1FEDDDDBB65ECCE6FCA007EA +:10C1F00079DA2ADB31FF8EA811E9BFB59B30FE1D2D +:10C200003EF27E07CAEFE548AA15EDDE67C7520386 +:10C21000A8EFAF1C4F09E960AA36E477D0679F19F1 +:10C22000C6EE66F871486F45FFCC7FFCD367501EA1 +:10C23000FD47401A61DEAD914727D0BEB545965EF9 +:10C2400012B07CE5FB9587F6EE9FB3F32AF54F7BA2 +:10C250004C22EACFCB02D7135BC387199EDD7AFD50 +:10C260006A95D786E7FCAF85A8CFFCBFBABA10F5B0 +:10C2700098FFE8D585D8EE7F3DB5530B9FBCEFD630 +:10C2800033BA2AF6B1E4AC2025F6EB95F9A3A4F76E +:10C29000C9FA52A05FCDE81ABB5E8CB7D754E8BC90 +:10C2A000D8BFE6DDDAEC2D89E362423D7E5F305A8D +:10C2B0009BBA39812F1F721B643D04520DFA679D92 +:10C2C0004CC375058FC7F455581702328EA0371826 +:10C2D000DE26A2B010FD7782CE3DE98F090CCF0497 +:10C2E0005AF5A10A686F8EE9247315F3EF038938B4 +:10C2F0008310EFF2B978DFF7E6DA7789CCDE931EA8 +:10C30000AC3F5411427B4F02A691F2041CB42EA6FE +:10C310008BA600DF344552A28887D6C5840BAC2E8D +:10C32000E3A30FADAF3D826E27E0A38B893807F002 +:10C33000D045355E22E9B85F052FBD87B80AF06C9D +:10C340004B57D480F60A7092AAFFC6A61F5F423FE1 +:10C350006C63B7FA7B494CD0AD84739680BA433294 +:10C36000F4C7F698503E149C89F735A821EFFB5D81 +:10C37000FCBE1439EA8DE9D83DF4C65CA672289F4C +:10C3800095E568D0AA230198BF37B2FA20FAE9BD33 +:10C39000D7D7A622BD7ACFAE223B50DEAD2E5305B5 +:10C3A0008EBBFE6353A32DCE1F93F4878BEBC73850 +:10C3B0001ED0B673CDF2BEBE2F7BB7D6F5C3B07715 +:10C3C000E0576F70E532BFBA99C73DB85F9D6C27E3 +:10C3D00014FDABCCFB847CCF93F5EF25865FC0FFCB +:10C3E00065FAF70997C8FA4D8F346433BFF8EC9AB1 +:10C3F0006C316DF2FC65825D97659B3CBF82D7FC1A +:10C400000169C4847E8CA467F2E95F434314EB5E48 +:10C41000CA70B67FBD2184EDCA7E626B28EBD768F7 +:10C42000A721338DE33F051FDE6C5F00ED2571BC56 +:10C43000A8E0C29897323F688D6460EDB9337C8F75 +:10C44000B86AF07C66F6BD66319F17F4C008FA47FB +:10C450006B7F4A09D303325E54F833194F7E1E298D +:10C460009BF64D71A3E764BE54E46B46925C28765C +:10C470006A48B6D31D68A71D68A7BF36A21C4C85A5 +:10C48000BBC14EEF73B171848D5FF0AEE0D5F2BBEE +:10C490006DB21CBDACDC5BEC0D27EEB798C4B6A347 +:10C4A000BF3895FDEC9771CC54ED43323EFC3639E4 +:10C4B0003E2B9FEFFB92E3D80F448E6FE23FA3F633 +:10C4C00039EF753BCF23FF5AF49D3127CADDAF0DFD +:10C4D0002C6E9DDCEF09D91E833D53DDCF48B15151 +:10C4E000877E8FBF95C7018299E23BCC3F79534F3E +:10C4F000709EADD70A194EBBEF5A262B838584DB7D +:10C50000D1074B58DCE6BE97460D128C6FEEA2F3B6 +:10C51000311ED4DCAA3E4F30575A9A18070F160E18 +:10C520009C42B90A1C2C1371FE163C2CC6435A338C +:10C53000433B317E81719C79F8DD12A703ACD32E89 +:10C540007FBF4B8EEF90241C7074F83C8BF7F8077C +:10C550002941F93546407FA03E39CDE31D1D11AE7E +:10C56000173EE936337DF289C0CFE1EFA6A1ED3465 +:10C570008E232E459ECA43399B842724C01379718C +:10C580003CD1FEC2BB4C1F26E387AC41BE8EBF4DE3 +:10C590001FC278CC48F1428AF576F007F311278A5A +:10C5A000E24F8AF8BE4888E91549152739701BB74C +:10C5B000FB9F9FFE77E647360F5192CD7087142B75 +:10C5C000CF8BE38E8DC165CCFE2B3863E3CC532338 +:10C5D00045389F8C33ACF08BF1C3649CD1111E3570 +:10C5E000A05F30094F24E1880AB73A2E3853E07132 +:10C5F000D699116AC578D24C999E77F45B182EF6BD +:10C600007CB0391BE55CB99FCB0DFCBE2E9FFFC2F1 +:10C6100089E3167E205851DF1E3DDFF5DB225E17D1 +:10C620004D228EEB4A453FE4F2070FA4223D8F4294 +:10C6300049405E5F3F2768C60FFF3E1E37BED38D61 +:10C64000F6ED61396E2C807D4B8FC75F92C7BD269A +:10C650008F0B829BC1E28E4384F16FB0D0B78CD533 +:10C66000F79592832CEEC3F9F57024D38A78AF1234 +:10C670000EDB0D7AE21F2DA417F32BC15CDF5B4CA0 +:10C680003EF6E918FFC2789697091C1299BD4392AD +:10C6900061FEA3CA087BA9267C3190B739F2BD158B +:10C6A000821F8AF917D8CD9A1B40A74A390F5265C5 +:10C6B0002102CEFF98C1B7EB76CCBB0C0BF6ED3860 +:10C6C00046B06737A44FCEC70077B37D2979198A62 +:10C6D00079976FC8CB505CA78AF31BCBC31089DE58 +:10C6E000488DE75FC84FBD2C29B473512741BF73F4 +:10C6F000B187F0EF93F3298F3B35F229FBD0FE3061 +:10C700007DABCEA7ED9AFD1AE3B7EF9A473BEB520C +:10C71000E64B5E5FE47E67D2FA0B323FCF63FECB1F +:10C720007F7F95C1EC59E42AB33B57C653488CC56B +:10C73000EDC6789C3A6260FEFA15F0837213ECD96C +:10C74000974E4E87131137E3C7C1586D2AF62F96BF +:10C75000ED65FFD935AB57229FC4047B05DB25F778 +:10C760006B0663420DC70793E874D0A5919F3259B9 +:10C77000B83E4FE6CF46993F1BDD9CEEEEF3DC5F03 +:10C78000F177F1FC815596377F27657AE554711E64 +:10C7900055E2C8F95AF985A171A6675BEEA5F68046 +:10C7A00038757E61B7EC6724EBA18EF0217E6FC9EE +:10C7B00071DB7A0FD33BB71AB725E80D2F8CEBE965 +:10C7C0000145AFCCE571DC3BDC5676DEACCEF9CE74 +:10C7D0007C123FBF063DC55AAD3CDEE47EF3EA6EF7 +:10C7E0002D2FD829DD5ABF17A55B5B77F016FB9D6F +:10C7F000BDC57E73B4E44CA35F8EF3D6CEF18966DB +:10C80000BFFFA379D0E43C67725E3439DF99F2E66A +:10C810009600B63D4A1F1F8F2275338E3451105932 +:10C8200021F30513CAC98AC53C2FD05F6B0AEDA757 +:10C83000F1FCA842AF020FC75F56DB44201BE83C67 +:10C84000438AD566833C5F594C98FF70C5CCF3038F +:10C8500044B01636B0FBB316AE02BD1F346BE79979 +:10C860007E5D27E3E929F4C9128F733ACA8B1571EB +:10C87000B9C63D1E96E394D63061711B228885AB04 +:10C88000D8BA6221DA9B696FF0EF195122ED67FB8C +:10C89000124B56311C2D96E0FE76CBF9AFAC65B34A +:10C8A0004A305E97057617F3234F619E84F901564F +:10C8B000D64F59EFF95ABEDE6E03A198CF0ADCCEEF +:10C8C000DF57907FB3AAF21B670CD18B9B28CB6FED +:10C8D000DC81FB7F5B17B51D28E1F782F4B50D5AAB +:10C8E00059DEE5378BFF61B68FADC3F31DDBACBC02 +:10C8F000CB49F437601FDB8E3918FF369F58FCBBDD +:10C90000F5880BCB0546E749785CF6B3CEC97EA225 +:10C91000E2678DA1BF98E0772CAFD54DA59796D74C +:10C920006AC8D56ECAFDE0C0DBDC0F7618ED659DE8 +:10C9300009F7B4B696F3C3A6288FC72AFE6D9514DF +:10C94000D2E5011D1C0FE9A32960AF1D7D738DA8E1 +:10C95000B71D7DC516165FDA7C48A7D05BEBDE37C6 +:10C96000D5723BD27F7A9CE5270E27E5299FAF350C +:10C97000B2F62C991F9FAF251C4F55083BD10C4F89 +:10C98000FB6BAB5E2B3EDE02F81FF7B729C8F7AB97 +:10C99000E4435AA2A21BD7B93032DE8765756B8992 +:10C9A0009BC50FDB26FAD07EFAAF5F3DB584C50389 +:10C9B0008C22E2ABE479E778F46CFDC30848905E22 +:10C9C0004B8510F6732C15D87D67B598993F9E65F9 +:10C9D00020FA34AC37707B565D9FE3C63A5993C951 +:10C9E000EC71F56931738B2DEEEF672DEDCA453A89 +:10C9F0007D5B9E48891BE4CE907620BF7DD73C515D +:10CA0000FB99B3463CF78631759E48C9FB4C952788 +:10CA100052F2B4FEFA2F547965BF30EEC1F88AE3C2 +:10CA2000D8059627F687A9B5A0249E3FF20F4E1889 +:10CA3000197DE5BC11F437E2B8C11E9E3F3A02EB06 +:10CA4000631986F34AB08F7F86F3621981F3E2F7A8 +:10CA5000E33DB35919EDB1B3F244CF22563A806D9C +:10CA60000AB330EF34C1F24E2FD5AAF3164A5EC294 +:10CA70005EE8FD05D229216FC1EAC9790BBD85FBAE +:10CA8000A3FED306FB01F8EE3F63627AD619D934D0 +:10CA90001371D997A3BE99569607C8667EA5C20F93 +:10CAA0009725BB3913FD01AFDD8CF902C7F025A333 +:10CAB000C8F44EB4089F3275083123FAFD4807893F +:10CAC000E139A719E9FAADF1FDF0FFC7F7BF4B7CDB +:10CAD0007F5E5C2E99FEA8F6EAA4FD589E96CC5B7C +:10CAE00012F443BF97C789FBCB4B99FCEDF19666D7 +:10CAF0006E4E8CE7D7733F2E6B69B939F17B97C7C0 +:10CB0000C0711F255E2D3DF6F5D4FAF66B2D7D4BD9 +:10CB1000A6C80BF4D7733DA2C4FD27E709EC6F96B6 +:10CB200027C4FB2FBF0D7C0A7EEBF0500AB3E75FF2 +:10CB30001E4B3980F8BBBA7EF3CC74A8579F4B21AB +:10CB400025DC1EA9F20BCDF53AC99CA1954F908A20 +:10CB500074C0B793F206F53AA6DF6FE60DEA850BCF +:10CB6000AC2EE3F40D137F482FA148FF5010FD8C2D +:10CB7000C3EDD43E4C26E71160E222B2084E517F4D +:10CB800096E595ED9DD42E8ADF9E5FC893E30C1D3C +:10CB9000E14C3DF279CB1B84E0BBADC979867A8646 +:10CBA000F7ABC993C15A7C8F55AEB3A23D4B8E17DC +:10CBB000209FA0FD4F8E13CEABE3F7384FC62B61FD +:10CBC00019DF57CBB84419977CFFBD75EA7C4472D6 +:10CBD0007B97DCDE5B5FDD8FF71758A12368077A50 +:10CBE000EB5DA6F284F95C75FC1DCD6ECC5BE42494 +:10CBF000E62D787E22395FA1E829C7F0D71EBCFF59 +:10CC00003D111E4FF217F0F8A6E3B8F334CA7D7C4D +:10CC10009FDCDEEE813B8E311C65CF24FC5CC4C4FE +:10CC2000E35E2CCE50BDE28B13A9483F2FD82BD406 +:10CC30004B67CA77A6A13E5921D45091C5BB6FC698 +:10CC4000BF313EB5FA9DD66504ED7FE3FC51A47B70 +:10CC5000E37A037B87A4D8ABD5EF347978FBFE1D4C +:10CC6000166C9F4DED6611BFD7BBF0FBF257A218B3 +:10CC7000E9232B91DA2037B13317059497DC19BEDD +:10CC80009FA17FE46890E3E0EBB97D6D8C34184898 +:10CC9000DA647B77B2F84BE6475F8D38587C3B1BF4 +:10CCA000F3AFB6B8BD701C033B94FE97B343BD759C +:10CCB0005646CF796087703F590D3C4F987CFF2EC8 +:10CCC000F9FEA7B22B53E951B423BA455C6E684113 +:10CCD000DCFE8AE85FDF11B7C3D630D4F3BF21EEA4 +:10CCE0002DE3ACCC2970D82F657E9FF2FD46F8FB72 +:10CCF00089831FAAFB81C4C1653F4789872B7E5169 +:10CD00009A8C639532DDC3E9FEBF7EBF8CC651F3BA +:10CD1000FD7296F6FBE50D03147186F27E79C44828 +:10CD20009C8772F0DD1E25DB51BE430D0CE78C3C69 +:10CD3000FBFBBE97E17BC720B5A2F9691F1865769A +:10CD4000BA1D700DC343914F799C6A80BF376D0F38 +:10CD500053492B0EBA40B6CFB512617AA35D7ED788 +:10CD6000E719E4721D8F13FD5C488C13F9C558AEAA +:10CD7000F25E30C4ED93E6BBBE0E32CEDE0376B477 +:10CD8000527B14BE27C78D92E3454FCAEF00A78C94 +:10CD90001B49DFEDBDDF9FEAD2733E061650E2CF9E +:10CDA00005B53C4ED4E4A314E737E9BC6DECDDEFE8 +:10CDB000716AD57A3F9AEAE17667B91CBF7DD1C81E +:10CDC000F9E1C53B297B4FBF9CF038ED8BC7F9BB20 +:10CDD000FA17ABF9BB7A255EABBC97BF3D1EAFDD42 +:10CDE00083F15AE59DBDF26E9E9010BB8786BD967D +:10CDF00028E28DC70C0305288FCA7BA3A375DCDE50 +:10CE0000595248A7967C7E55E73C5AC7FAE9A6884E +:10CE100077FAF23D1A71209FECB7157BA6C4E9A200 +:10CE2000275785D3593D19A7FFA5E2B547EAC8544E +:10CE3000FBBF5F1BAF4DEA77F116FB9DABD3A0C7DD +:10CE40004E397E924CDF1E8FA287A75B193FDDDC37 +:10CE50003FE1F95C39EE3522DBB920157F7717CB3E +:10CE60007F1958FE4BD133C1743EFFDDB29E51CACB +:10CE70007BE53268D08ED374C9ED730AA595788F9F +:10CE8000952FA9E3667307D471B379E12C557D7EA4 +:10CE9000F436557FC7E952557B4D6C8EAAFD8E73D3 +:10CEA000D5AAFAE2B13B55FDEFFAC4A5AAFF685C2A +:10CEB0001D375B724D1D3753F8DB091C9138CE6D61 +:10CEC000FA1B55BFA256F5B98A3BD5E79AD9AD3EB4 +:10CED00097326F49407DBEB2A0FA7C5918D7B7FD92 +:10CEE000F971FDF15A518EEB979971DCEEFA7233BC +:10CEF000E2183DE631E1FBFF001DADB367003400F1 +:10CF000000000000000000001F8B0800000000006F +:10CF1000000BE3146060F8510FC1D3F9191836F310 +:10CF200023F8F4C0C79819188E83302303C33E201A +:10CF3000DE0AC46B80F83D0303C352203D078827F7 +:10CF400003711710BF048AD5B1623787858D81813F +:10CF50000D884F02CD3AC54CBCFD8A7C08F6215E97 +:10CF60000686B5407C9497BE6130D8F00C41FAD962 +:10CF7000F50C6AD76ED181F73708B38A3330304A5F +:10CF800020F8FD12A8F26CE20876960C6576950101 +:10CF9000F50300295128158003000000000000005F +:10CFA0001F8B080000000000000BED7D0978544540 +:10CFB000B670DDEE7B7B49BA3B9D90952574802051 +:10CFC0002A4BCB1201113B2189010306440928D2C7 +:10CFD0006C2184249D01661E3EFDFF6E0842C4D173 +:10CFE000898A1AFC195F83E004079DE0A0139DC0A5 +:10CFF000348B8833E804C70597795F401E204212BE +:10D00000A338E8F3C9AB73AA6EBAEB763769B7FFFA +:10D01000F97FFF840F8ABA55F7D4A9B3D5A9537500 +:10D020004F149D9524DD40C825F8A1E5AB0A2124C5 +:10D03000255876489DC3E581C1F6B55E177119097B +:10D0400079C06BC272BD379DB8AEA0CF47EB8AFCEA +:10D050001642EEF7DAF1F9E3DE122C1FF59662F9CB +:10D0600088D78DFD1EF29663F92B6F0D96F77A8B9C +:10D07000B0BDCEBB0AEB372A0BD2605C425CA6ACDB +:10D0800064423C2F0F1CB981D6D6678E4F9047D390 +:10D09000FA5FF5449F45DF1B2D17F987D206B9A427 +:10D0A000286B74B09F8AE78D4A5E5F80F3F8581D45 +:10D0B000EB67AA792D3B72BF2C3286E2395646FCCB +:10D0C00089A564727672C47E8301DE2343D93C89CC +:10D0D000DDF9DAA0C8F0AE06780F0DE5F825DB27FC +:10D0E0000F8A0CCF09FD7EE5E4F0D23B0F0F8CDCFC +:10D0F0006F0CF4AB7372787D7DA60191C71D0FFD97 +:10D1000062E013C589105F8BD19F9DF5FDF9455CE9 +:10D11000F42FC5A763AF79EB0609F9370DE8B4D64C +:10D12000BEFCCC163A4E7BCB30A7DE41C8672E67DB +:10D1300082DD1213DF6E8179C4C0B752182706BE94 +:10D14000CD8D916F0BA05F0C7C5B02FD62E05B6597 +:10D150008C7CFBD94F846FF7021EDF836F1B62D478 +:10D16000B75FC5C8B78D31F26D538CFAF6648C7C0D +:10D170007B2A946FEA73B5DC4124B48B372A253BB4 +:10D18000A09F27B3CD3620EB27C1BF3DDF53EFF67D +:10D19000C7C8BF5763E4DF11A04F0CFC3B1A23FF45 +:10D1A000DE89917F1FC4A8776DB8CE58E4AFDA86C8 +:10D1B00010FCB93400FEB5D84F5DCDEB7AC03B8989 +:10D1C000908C7039504BCA51940799B8DBD9BA5535 +:10D1D000F0CDA51C425698E87FE9FBBE3C12D0D3A7 +:10D1E000F17D36E2AF9584FE9F039E84E47F732930 +:10D1F00055E8EFD345EC4F74D0FE30C815E5FF6617 +:10D20000EF102CEBB91C6D2ED2A13CF8920D285FCB +:10D210004F789DD8DEE01D8BE5635C2E3772397A3E +:10D2200000E4EE0A90C3522E574CEE082971945335 +:10D23000BA76EC89271B1C28576609F09499BCDD47 +:10D24000BBE7CAAD1B28FCCD35BA2BB785C8D913AF +:10D2500045AA7C51C94C0EF67BA2FC846DC150A43A +:10D26000B70DE03414EBD47EBED07E0DEEEE7EBD65 +:10D27000A0DF63C55CBE6412081DF7B1D2EE7EE983 +:10D2800012A5CBBD12296DB284F3658AC4F4942A29 +:10D290000AF243E6F4DD9F7796B4D1F76DF6916913 +:10D2A00084964F827EA2FE39B054DFAFA7747653C6 +:10D2B0007A641A494D13E04B5A2585E22B8F752469 +:10D2C000821C3D34CE45242B21FDA19D8EDF677449 +:10D2D0001BC9A265E2F836220D837EB49DD6537831 +:10D2E0007BC650DA4EE13C04EDD6607B2A6F4F736B +:10D2F000F0F7AF63ED0F7B098EAFF6BB8FF2D94D20 +:10D30000F15B47F1C5E7C5C4057494293BFD21F3E2 +:10D310009F2DE971DE95BC54F1BF2FFB54C6FCA1D3 +:10D32000417CCD832F66CC0FC1EFBEC173B0AEE29E +:10D3300063BEA212EBFD57F5A69E18D707124EE763 +:10D34000D49903847687EC443FCD71444F7C945F3D +:10D350000E2A9E91F8F30515E71F54FF5C8C1EDA28 +:10D36000F6BB3574589721D2C1D05BA4C3BADE2274 +:10D370001D0C7D2E4F87299203E147A3873AEE8645 +:10D380002BC571E3AE12C7DD7095386EDCD53FCC8E +:10D39000B8EBFB89E31A33C571D7678AE31AFB7FC1 +:10D3A000BF7189ECA40F99B9200EF8679E60DF2E3B +:10D3B00010F7C3A0DF60E7F4C9413B27DB4B88DBF4 +:10D3C00012E42791E9CB39A170EE14EC2A85F37FA2 +:10D3D000381CD7E5E1D83570E66AE16CE37048A8FF +:10D3E0009D0E8343EED0CEE3B7FCBD802E647CBAA5 +:10D3F000BE92126BE87B4ECDF8B76BC7DF0D760C93 +:10D40000E6A1BBECF80E0D5DE768F1D9C3E110DDD4 +:10D41000E5E841EC1A38B3B5700E713801E9B27025 +:10D420004AB5F3785DE5AB24AC5F941EC382EF751B +:10D43000E4759E423FE845C5B19DB64B7FB2066E8E +:10D44000A0FD8F6C91FC465A0FEC8DC7F5E3FCB63E +:10D45000E958DF778D11D789F3CEC97E23B527939D +:10D460005E78DB06F6A5EA05BD0C75DDDE8F6D6D19 +:10D47000142F8FB1F5C1EBE8F3CE17F4642B4A6398 +:10D48000A10EE87E8ACB2659C5EA656656ADDAB2AA +:10D49000EF4E805BDE6C24660AA7EAA525D3AEA317 +:10D4A000F5258715025DAAB6AF36F4A6F5A57EA9C7 +:10D4B00009EA1D79A41CF469CDDEFF6C87F5E8FC50 +:10D4C0006E251BC63F4BD70907B5C747ACADA9337F +:10D4D000291E15FE5D85F05EC54EC9492D1CC57718 +:10D4E000FBA10CC07787E434527A2F6B8C270ED5C2 +:10D4F000DED1BFA776EB71FECBE9FC0985B784D4FA +:10D5000017023DAB803830BED3E8374B417D3BEB53 +:10D510003D8CE3A9F5AA1D743CFA7EF5739213A61F +:10D520005AAD236EC0B3FD2573E9531698E76AC35D +:10D53000602BCC6FBD01FA2DF1CF7FD1EC003CB751 +:10D54000180A01DFCD5B0C6543817E645EC950C063 +:10D55000EF2F227E0D7A17CC77F935C6AD7AE0A78A +:10D560002530688635DCCE9EA5EB952364FDAC2086 +:10D57000CCEE13D96F983E2CF8FC257D22CAC1B29F +:10D58000463D7184DA0D2E1FBEA384F9317BACFEBB +:10D59000ED59413E2EB77379E57C5C9EC8F92A7738 +:10D5A000E6CC18168ECF83C01723F38FA07C98AEDD +:10D5B0009B0EF47F1C48BFC7A8FFE440FFC889CF7B +:10D5C0009FA07E12949BA99F04E593D44F82D24FD3 +:10D5D000FD24E8B795FA49506EA37E123C7F9AFA73 +:10D5E000E7503652FF1C9E3F43FD7228777A7DF844 +:10D5F000FC396F1D964DDE7A2C9FF73660B9DBEB58 +:10D60000C77E2F7A1BB16CF636E1F397BDCD58B6C5 +:10D61000780358EE053ED332E06DC572BFF7189619 +:10D6200007BD6DF8DE21EF192C7FC9E96E9B4072B2 +:10D63000652A2F3617B1039B928A5DB9E0AF249516 +:10D64000B07AEA1DBE5C03ADA7BA699DD2B1776519 +:10D6500020D748EBBD6B587BE63D24CF44EB993E89 +:10D66000D63EE097AE3C33AD0FA867ED8337FBF2B3 +:10D67000E2687DB09FB55FB53390174FEB5735B17A +:10D68000F6E12D649285D68707587DE411D7242BC7 +:10D69000AD8F6C65F59C0F7D936CB49ED3C6DE1F79 +:10D6A0007F2E302981D6C777B2F6895F937C3BAD58 +:10D6B0004F2412D6F32CB9F989B49E6767F5C2BE20 +:10D6C000F3654784F57DAFD2B6104CDACF7539B922 +:10D6D00032F513F61ADA5680C95DAFBB21571E47E3 +:10D6E000E9A79045D0BE4957C4EA06B212DA7FAB2B +:10D6F0009B8EF5FD8A03DBF7E8E6B0BAC181ED7FCA +:10D70000D52DC4FA41C585EDC77595AC6E7061FB2A +:10D7100067BA9FE378871437B62BFAFFCDEA06374E +:10D72000B63F2CAFCFCDA7FD2BF56E8F8ECA75AD52 +:10D73000E42E2703415E9BD2C11EAEE37EEB2C9DFF +:10D7400003E57E5D8601F56CEF7FE53C857A063F5B +:10D75000C9502F7B1AFC5E0A6715C251281C7DCF69 +:10D7600070267E33568033F19B7215CE6A84638EA9 +:10D770000DCEDE6FC68BF87C53A1C2D9A0A3F6BE36 +:10D78000D61ADBBC265E9A20E273A95285F308E222 +:10D7900093181B3E01E55A014E4059A2C2D98C7024 +:10D7A0005262C3C7651827C0711996AA70B6239C28 +:10D7B0008CD8E0040CD789F81896A9709E43FAF427 +:10D7C0008B6D5E2EE3F5223EC62A15CE1F109FAC50 +:10D7D000D8E0ECB78AF4D96FEDA64F00E164C73604 +:10D7E000AF3C9B489F3C5B377D5E433857C606671E +:10D7F000BF4DA4CF7E5B377DDE4438C3629B575E4E +:10D8000082489FBC846EFA7C8070AE890D9F83290C +:10D81000227D0EA674D3E724C219131B3EF9A92258 +:10D820007DF253BBE9731EE18C8B0DCEC154913E4A +:10D830000753BBE9F305C2B93EB679E5A789F4C938 +:10D840004FEBA6CF258493EB6E447C0885638D0E49 +:10D85000E7503F913E87FA75D3C7A407380514CE29 +:10D86000C09EE114668AF429CCECA64FA21EF46295 +:10D87000726C700E658AF43994D94D9FDE88CFD4CE +:10D88000D8E655D85FA44F617F461F8FB173921DB4 +:10D89000FCC644E2DC4A5F9994FCB383B0EE2816E0 +:10D8A000E204B047A4C036804FD756F44B65A7EAD0 +:10D8B000073909F8B9C5368713E2017AD5DF21ADFA +:10D8C000B81FB1EC4C14E24D2FE9F38603BE56EAC3 +:10D8D0001586FA3D0963E3047F2BD19524D47B158B +:10D8E000F516FAA7940C10DAD34AAF12DA33DC2318 +:10D8F000857A9FF2F142FF7E357942BDFFAA294227 +:10D90000FF2CDF0CA13EB06E8ED03FBB7E81D07E5F +:10D91000454385D07EA57FB950BFBAF15F85FEC370 +:10D920009AD608ED239A3708EDD7041E16EAA30EFF +:10D930003F21F41FD3BA5568BFF6D83342FBB8B6BF +:10D94000E785FA75675E16FA5FDFB95FA8DF70F1E9 +:10D95000CF42FF5CF237A13EC9F481D0BFC0FE9137 +:10D96000D07E63FA271A3F568C5FD4E612E6CF6664 +:10D9700018D09F0D580D5837EC35B3FD0DD49321B9 +:10D980000E518C75C3FE858E6488070000EA4FE453 +:10D99000F62EBF02E255BF18EFBE02E2B8BF30B8A4 +:10D9A00047D823F841EDB2FB1E3DC6135B25920E0E +:10D9B000A54307659C9EC7138C4C7ED767E53CE565 +:10D9C0000BD183BA7ED4BFA0F5F57A8AC798A0FEA2 +:10D9D000ACEF57963E3F649C75FD0CA55B87B2E7A4 +:10D9E0000B2D305EC97D309EC7D03918F0D28E63C2 +:10D9F0001C305618C794598EE36C84715282E31818 +:10DA000033CB35E3984AB7F2E77C9CC7406FA28DD1 +:10DA1000B37EC078713E991538CE16CD38EB332BD6 +:10DA200034E3C4B1F9D0E77C9CA72E378E71E004B3 +:10DA3000713EFD2B719CE7B4F3E95FA919C782E33E +:10DA4000C0731887F4A5BB9834CA67636719CAC145 +:10DA50009FCC182733F4A9F80DD4C90766920DE3BB +:10DA600038E8B8B41F199244859A907FD127217F56 +:10DA7000BE88A3FC0F89A705F7E33EDCD72FE62875 +:10DA8000123FC588EE93AAB96C2EDA393D738583AF +:10DA900096CD07063D02E36CB43AB369BDBD7992F9 +:10DAA000616104795A5CAF9C6A0B91F3EEFD591EDB +:10DAB000195243C75F1167477CD4BA5A26E9C4E7B5 +:10DAC00027E8BE8BD0FDC987749F42E87EE5238599 +:10DAD000ED33FF9DEECFA0DE46F767D04EC86A7CDF +:10DAE000EF048F339FF8A5E4077A7F71D7CF145CDA +:10DAF000277CE4ADF4548826B09F79ABE2291382E9 +:10DB0000F8CDF7F512EAD41CF7D1A5E3BE16E3076A +:10DB10009D2F19FD5B81AE757D284D79BF0184BCB9 +:10DB2000BB77EA21C986D53EBAB184CCAC995E9068 +:10DB3000865A24F55B4EF19CB1FB1A85BE41DA95FD +:10DB4000B63B9D96205CE2524E007D4CF40FC0B96E +:10DB5000A588D643C6BFB544ACCF2272B04EF97D7E +:10DB6000523F80B0F83F1FD7E15280AF25748E1925 +:10DB700094D5B3A01C09CD2C5E536A67EFAAF87840 +:10DB8000162A2480FB6B5F0AC4B1892F19FBCD5183 +:10DB9000F7C91AFC4A1593AB84D2B574BE1EE9AA24 +:10DBA000C5F7FDBDF12EDD705AD63DA24068B627FF +:10DBB000FC67BBC57652CEC653E9AACACB29CEDFD5 +:10DBC00013C07F5A9E06FE53BC4F72FE07E598F1C4 +:10DBD000DF63744F03FE776ED213E417E7FB6D9C8F +:10DBE000EF8BEB45BEDF06E771B4FF6D2BB358BC7E +:10DBF000A9A197C05F3A71910EF50F1550B31A861F +:10DC0000FFDFB91CCCA9DBF50AB0F7F672CDFC3802 +:10DC10001FEEE47C98ABA1C76D9C6F7339DF961043 +:10DC2000DFBD1918BFF02B10D79B5D2E11B0179ECA +:10DC3000BB55BEB5097C73AB7CD3E07B27E7DB9D8E +:10DC40007731BE69F16EE37C6B6BF84C2103C2F156 +:10DC5000D6E2396F95665E3E2DDFEAB95CDA0DE0FB +:10DC60004F4D77E5AE3819D2FF96A2C92B4E86D814 +:10DC7000855B4BA60BF559A5B385FEB3DDF385F6A1 +:10DC8000DBCB970AED736B7E26D4E7ADBA4BE83F4A +:10DC9000DFB75A685F58779FD0BEB8FE21A1BEA4F7 +:10DCA0006193D07FA97F8BD0BEAC7187D05ED5B495 +:10DCB0004BA87B9A5F12FAEBF65E7933C8D791B71F +:10DCC000F504E27D179CA731CE78C1A938A1CF49D0 +:10DCD000AF03E5F89477089667BC4E94F3B3DEB1D2 +:10DCE0005856834C8E033B7BC002F1534F1CB5FB4F +:10DCF00089741D97C7ADA99B00EB0D6D1F4FC8BF61 +:10DD0000CA37ACF1F5A55A00716F4AFFE206030964 +:10DD10008C2254BA7B77CB73A73EA4BDAD87F606A1 +:10DD200099047A85B717B7457EDE21750ECE80B887 +:10DD3000EC7B46B23D24DE187EDE42FA805F11ADF8 +:10DD4000FD9C8E94879EF76C95D939CF117DDE5658 +:10DD500099E2556960FA5FF97C461EB1413D30B8E1 +:10DD6000C67299F19A283269C0E78182DE2F69B8BC +:10DD70003AA8E704C661F674A97F94F07C59E3756C +:10DD8000C27B6F48EE2D80C7B97D7A5CAF49E04019 +:10DD9000E62DC3003FD75619D6D1E614F4BB5ABDC1 +:10DDA000AE15271542DEF41661F996B704CB77BCA1 +:10DDB000A5581EF3BAB17CDF5B8EE587DE1A2CFF17 +:10DDC000DDBB0ACB36AF0FCB13DE3A2C4F7AEBB16B +:10DDD0003CE56DC0F28CD78FE5596F2396E7BC4DBB +:10DDE00058B67B9BB154ED674FF27786AFAF674172 +:10DDF0000E8DE1727670EDBC35757D837276582E8E +:10DE0000433953E95BDC60E4F2902AC8C35F611DCB +:10DE10004E0179E9A1BD41E17218EDFDC8ED206F19 +:10DE2000BD7F047923640DCA8105E4EE7BC81B81A4 +:10DE300053841490A73E1A7912E550952355CFDFED +:10DE4000904ACE817CA9726591993FA4CAD5FDE024 +:10DE50002746F0B77A2B125FFF987F4402B93A2029 +:10DE6000D9727E5E417C2EAC77F1B16B29B856E851 +:10DE700027FB87C03AD235E4ABC110DFEF3A4685C5 +:10DE8000202BFAFCB4F2129DEE2EDC3F94F929F31C +:10DE90007B85B79BE3185DCD3A524446C2F972CEFA +:10DEA0003137E567DC9FAE1E09FB66FA5C26490048 +:10DEB000C7EF9C1EE1BC800C2248E79EE8ABF63F12 +:10DEC000F5C47FE6C0B9BF05F49CCE3DEE80BE86AA +:10DED000E9EF53CE5B42CE973C46673AC4C13BB3B1 +:10DEE0000D76E63F4C12E94826E1F9814AC703D98D +:10DEF0005F0C86F399FBA81C827E750D1A9C402E40 +:10DF0000231F3DD9FB9EE8B900E61B133D0D04CE4F +:10DF1000B9283DB7C27DC758E9D9939DECC93E9E4B +:10DF2000D8C0E87C84FBA7D1E8AC9E8769F1B845EE +:10DF300091391FB81C933B34F42F15E8DFD7EAC0A2 +:10DF4000FE07F77E9009E7785DBBAF48204343DFCB +:10DF50002F60E73DDDEFE70B7A20FDE9EF99B03F59 +:10DF60003EF8C2BB58AE254C0F375A4AE62A6382A8 +:10DF7000F062BD47106D5E1E4512E7D5837E76A424 +:10DF8000AAFAD99A09F2B49BDB81B0F9F5209FEA8D +:10DF9000FC0EC0FC289CA920D3741EF972C95DC276 +:10DFA000FC46A7E0BC7B9A9F27C140A411143FAB5D +:10DFB000C14012A83C2AEEB50AEEEB9C6D3E885398 +:10DFC000EC8D77D65296786C67DF0838E03D319E4D +:10DFD000B1ACD15C23FA4F8935A2FF945113EA3FCB +:10DFE000751D7ECAE6A6F82D4FD7D79CEC05EB9C95 +:10DFF0008BAF736C5D55F1AB6ACAAAB10870C47A75 +:10E0000057BD54C4EEE13812664638EF53CBE5E90C +:10E01000061CE76CE3C00418F7ACD754C3D6577B93 +:10E020000D1B37BD26747DAD5C155F73725410BF38 +:10E0300068707F68FCA844908F4CB02ED2B681D116 +:10E04000FB47E5A7FCB901CFD55B942FC07F370F05 +:10E0500051FD7719EB2A5C4F93DE671C01CF770ADD +:10E06000E3D1F71CEAD938BC175D6E64724AE5A7A4 +:10E070001ECEBB08DF1F9890CF6E0A3181C2EB9095 +:10E080002D7520577E85E9B387CB6995A9CDE076BC +:10E0900020B95B41AE178C55E5DC31EB036AA73F35 +:10E0A000FE8B82F7CCC8D7147A4EF0AAC3225262F4 +:10E0B00083A0EA82DDCB8A61DDFEF8C59BF83EBD18 +:10E0C0003E07E67D9EE88AC02E9D276FDA4685E8EA +:10E0D000EB6985C5B1481DDBE7F8E81F98DFE27AF8 +:10E0E00071DFB3A441AC979119A9606FCB362AC4F4 +:10E0F0004F715F0AFB2675DED4FEBEABD811B92581 +:10E10000A4661DECD31F5358BC67819DC87DA8BD74 +:10E11000AEFAC3AF7320EED3AE307F573D0F5F9A98 +:10E12000C4F6831533FD0617EDFFD1EE51B7518BC1 +:10E130004BDFF7AF43FF673A716E27E1745F5827F3 +:10E14000E2D713FE5A7C553F28EC5C9EE391DC2815 +:10E1500045BC2FF535B773AA7E2419EC42DC274D58 +:10E160005357E540E172E057DC56430AE33BF05178 +:10E17000923B0DEE907E8660BF24C398E8FD8CD064 +:10E180004F8FFDD258BFCE42DC1F132A4F4383FD71 +:10E19000CC41787DD9B862BFAA3F3CFBA28FCA4B65 +:10E1A000C5EF1EB511BA6E7E2CD7A73AE9F3CAEDBA +:10E1B000F7DA5CB43C23FB6CC0CF8FFDFA88F77DA7 +:10E1C0006F31A8F470592488A771F924753E8C53D7 +:10E1D0007CB15DB1E33942A33160A4F259BD7B69E2 +:10E1E00031198EF5E3ACBEFE533DD49B457E55FC04 +:10E1F000E6D15407BB27C4E24924807E6EF5B6FF02 +:10E200002884F5C2433A51CEB4EFC1F8179350AF0A +:10E21000E71B12C2DBF162702ABCCF7E3CBBEFFF72 +:10E22000546F8372F269D0238F464ECAB9DF0AF465 +:10E2300082FD7EBEC19A8CF6FE5A722DE8BB4A174B +:10E24000E267FE6BED8EC7871FA7789DDBF6179BF5 +:10E250003434D44E3079EB6A5AF86F265D747BD231 +:10E260004EE531D44FA280F13D4733F7BB5B58599F +:10E27000A9046C701FA7728BE2A492482A9FD51341 +:10E28000B89F40DE33FA213EBAECD957DE194FE988 +:10E29000BF6C97925CCCA663915283FCF1D0BFAB6C +:10E2A0004606F951F1FB570C8E61ECF93D4941BE30 +:10E2B0002CDBB5CF408685D37152D33E439B2502DC +:10E2C0007F9A8E17C27A5BBBE31F06882B7EBC57F2 +:10E2D000226959E1EF976F7905D73DA013F293F3C7 +:10E2E000AB9B7F617C0B4C7B7934F6B3833DEC892F +:10E2F0006FD9B09F4B41F97EEE65B8C7F4BED10926 +:10E3000074287F6E850DE6735AAE6172FEEB7B5307 +:10E3100041DFCB155FAA1D4BF6BCFCC99FA3FC2DAA +:10E3200039FAF354F41F882B4387B6D99701F35C6D +:10E33000BCF9569C671971A31C96FF5A5F02F74CF3 +:10E340002FC8A46857043DF98B81ED5F4E6FA5CCB3 +:10E35000A5F33C0DF8817D7B53EFDF8E71F39FE1D8 +:10E360003DB89FF339D39510EB174C8C5F5B0C3A9B +:10E37000351E6A12E477DBFA56E0D3D97EAE343824 +:10E38000F7A074F071BA4997285CFDD18234C62792 +:10E39000E29073F87BD4DE4F82E7D0BF5571998746 +:10E3A0000BEF71FBC8C65FC9C7A778C7C1FA753A3A +:10E3B00035B2FFF70F3E3FFAD34A42E42C44DF99CF +:10E3C000FE6FBB8FE9BBAAFFFEE945D0FEF95B4CAF +:10E3D0008FE03D582F285E81346CDF375342FB407D +:10E3E000F7D991F47C9BC2F55C6CA73B1C5CFF5594 +:10E3F00039A1F8CB5242A8BCD07192900FB83F2EF1 +:10E40000DB48DF0FF1CB3C302EF633049F87AC1B8B +:10E410004BB85D38A4B10764734A4C7E74A5E27FA3 +:10E42000FA09D0DFF78C4E9F03F4572981F97FB2A8 +:10E43000F3C03B73A89C7FD2A4EAAD6857B57A5B62 +:10E44000FEFC1812496F3FB1D07D5724BDA5CF23E4 +:10E45000EAADA50DE5F9FF965D55E9D7AEA11FD848 +:10E46000C7971DD1E9A8B58F1B0C8E88F691FEBC0D +:10E470004572C2E550953F55EE2A7E5BD51FEC50A4 +:10E48000B77CAAF2D72D9FAAFC69E72BD24FDBFEFF +:10E4900007D06F8AD7EDA64DD3C07F3675128CC3D7 +:10E4A000E7CED4E33D4DD3E784DDD3B8231EEBB3F1 +:10E4B000F46DBF079FF083AA59C3609DBF9DF814F8 +:10E4C000766E5FAFA01FFBF5A54B13E87CE670FAF4 +:10E4D000DE4EC93D95F2A35496027114CFD932F1A4 +:10E4E0002524413C59222742F0B8BD5CACC3CFC4BF +:10E4F000D4209C9EFA7F5BBFFBBB9647295F4F648D +:10E5000013F2372871FF411DEB10799ADEC2CE312C +:10E510003CA325FF00D4C336B924641FE13132FB8C +:10E520007334FF963140BFDC59C312989C0FC6FD6F +:10E53000A287DBB12E9F2301EC7B57CB40DC177603 +:10E540001D5E687547B06707B89CBDC2CF613A2CA5 +:10E5500052BD9ECA7D07E944BFC66731478CCBCD0B +:10E5600031AA769AF38DFEE8E9F8A55C0E67D357D9 +:10E57000134686F06DE6D48F655B381FE0E744C82C +:10E58000BEE2FBD217E41AE87BC0DC565812217EAB +:10E5900053C9E93771FF970658F7F25B7265A063BC +:10E5A000BE452FC4431619B9BE0E254301AF89FBE2 +:10E5B000973E3086CAB1E7B0DE69A6F3F3B47C6A51 +:10E5C0007047D8DF69E909F0C1BFDC6A64FEF2DB9D +:10E5D0004AC962A0EBDBB7B2F3DEBF199C5591F0DC +:10E5E0004C37337F733629B9305AFAE9D1377796E9 +:10E5F000359047E9D16561F7B5C3E58FE97D975D52 +:10E60000F2AF96400EF5AC9ECCEE371712F703131F +:10E6100024D4F71B42ED576EF3F467E13E4D758B42 +:10E6200064D7D1F66AB9CD0072EC69DE2583DF7E4E +:10E630009383B8707F2DD70C9B1912FFA2CB1ED2EB +:10E64000EBC05773E6027D3F9B692480976BE8A778 +:10E650003658FF3F6B19857A106D5EAF7BC9B47C6D +:10E6600005E0307BA69587C2E478A17EEB24D21723 +:10E67000CE81271ADB563823F02FDFC4E42C66FB4B +:10E6800066FAFFCCBE4DA0F68DC9B5126ADF2CA686 +:10E6900030FB9616C9BE2D5FED4803B958BE672002 +:10E6A0007EBFB5FCB5C52991ECDBAB7CDFFB1ABFA7 +:10E6B00007DED197DAB71121F6AD2FB56F11E2E47D +:10E6C0005FC46ADF4CFF33FAF72AD8B708F3359BEB +:10E6D00044FB56D4B21AED5B515FBD705F8998A8B8 +:10E6E0007D8BBF9C7D9BFFE8AD58579CF111E407E3 +:10E6F000E80AF6ED356EE7601CB0733798587C3346 +:10E70000563BD72F563BF73F4467D5CE2DEF27A179 +:10E71000FF122E87CCCE2DCF62766EF91E66E7965D +:10E7200067333BA7B56F7961F68DBD5F3D84BE8FC2 +:10E73000FBC7ACC7EF80FB84A58AD344FB173BD44F +:10E74000EF276AC684DABB1B4C32D239CCDE393FA4 +:10E75000C5EF607AB2777F057B978D766C10E89174 +:10E76000563EA60C8A17EEB3BDFDE5A9DFFE0EF4FA +:10E77000E5753DDE177A57C7F6477BBF3C350AF48F +:10E78000EE2113B3BF4B4C8C9FED5E1FDAD3494390 +:10E7900099BE57DDC3E857BD5B62F35DA9F73B60E7 +:10E7A0001DF8EA22EE9FE7EE61FBE759C6D69478A2 +:10E7B000B897F42F0A61DF7D90E2F921F2507AB127 +:10E7C00002E380CFC7D9B6C2FEB2542626F063E773 +:10E7D0001D9EF231F8AFF32ED6A1DF3B0F9EC33959 +:10E7E00009BF27A1DEA398D3BCEB953E24FC7EC4D1 +:10E7F0004423E3C3C415927F4B16DC4710DBE76963 +:10E80000FCFA757C9ED49F45BA90BFEA23C6EFD62A +:10E8100069E9E164F3AF5AA917E9512345A407E573 +:10E8200068F1FCD4E0FCE7BED0B6AE0FB42F957013 +:10E830003FA5D2433B4F953EEA7E651ED7114FCB95 +:10E840002E05F8A59DBF4ABFB079ABF4D4CCBF4E1E +:10E85000B51F579361A06FEFEADC0F8C01F9F83315 +:10E86000A503C5EBB6D9D969A1F6F8416E97A6BA4A +:10E870008FE7A73A806EECBBC439E5BB5E49A5F3D0 +:10E88000B9D9953512BE1FBEF52B831BE20B07CC01 +:10E890009D68DF54F9FA84CB7B80C379BBB73D1FF9 +:10E8A000D79166C98E7A13D0D82F7E7FCC730FD3C1 +:10E8B000AB03D23FD6F5198D7485658014AAEB1091 +:10E8C000F081FE776A0BE38307F840FF3B8D741EEF +:10E8D000023A57274BCE00F46FDE752FC8CDAB66DA +:10E8E000FA1CF4B75C72B2EFCB882523F5B2F2299B +:10E8F00047924F0C4EE404D7C579D02F29DCEF980E +:10E90000686C7D1BF09848F5610B09F74354BE0F06 +:10E91000A17F2E45BAF7D3831C7FCCE5F355A0B772 +:10E9200005E8DA69007FC61360EB87DAEE911DF91E +:10E93000481F95DECD747D18CDE8AD8B40CF9BD5BB +:10E940003AA7A7A74552E0FDC974FFDA4B82D3ADC1 +:10E950002F0FA9720CDFC369E901F1808C10BD078C +:10E96000FB147A3E59DD7C14E932652575AF42E827 +:10E970000E76EB72F489A617D5CD3F8C5E7CA2D1C2 +:10E980008BBDE6CEBF8C80F8D71E09ED0369491414 +:10E99000F6FBF166E6671C30BB517E3B5F53F0FE31 +:10E9A000B9D68E7CCDE51EF617A1DFFD4D8289809C +:10E9B0009DB39BC9472A1E03981C85DAEF57CD6E7D +:10E9C000E45734F8717C1D8EE63FA9F51B613CB815 +:10E9D0008FE810C70BF32F78FCA7A779A5F171BFBB +:10E9E000EBBCBACF3349AB81B0F8FF0A63C8B9D4E6 +:10E9F0006DFC5CA03B4E16EC67375DA61FC45F0242 +:10EA000074DEAFEE7C0AE3BFE79F393E0DE477D9B1 +:10EA10001FF5C444F9DCBED34A02ECDE8501D6D929 +:10EA20008ADDFA88E72884D4B2EF1C7F6745FB5261 +:10EA3000F1BCD15F4CDFAF78F1A3E110B76A5FC3DF +:10EA4000EC8CEF192E1FBEB6E170BE5E21B3736170 +:10EA50002DBCEBB8BC9C7B29BE14ECA4D4C8BE5F13 +:10EA6000AD689AA51843F6E923CD0A8E4BFBE1BDAC +:10EA700065DF0E09E3E5E1F8AD66F07630FB57D1CE +:10EA8000ACF8E13BD88AC62DB8BFF5347E6A00BF2A +:10EA90006ED2EF9E65DFD736EBC5F861A33E60C44A +:10EAA00038A7FEB87138D35B49884755A15E563701 +:10EAB000F13899267EB4EC777B5EF451D22CFBFDC5 +:10EAC0006F6C606FCEB66EB7617CAE91C5DF648B44 +:10EAD0001C393ED7535CAEE93E1E979B7A9A0C0FC9 +:10EAE0008FCB9D85FF503D9C6FE6FAAAC6351B7BF8 +:10EAF000C5747EBEECD90B4FC279D2B9E73F79120B +:10EB0000F0AFFCE6B327EF867389BD663BAC7F9E12 +:10EB100067DEC6F8BBFADEDD5CCEDB77FCE6E92714 +:10EB2000A81EB6BF67C47B5BED7B4E67C2F78CED5A +:10EB3000BBBE4C85F8E6CA3D05B89F59F9C2A4B4DE +:10EB4000CBDD3F01F9F4C7707EA2E5C781DD7A0213 +:10EB5000DF739E3F6644FFA33BCEDA54C5E2D70E77 +:10EB60001E5FDD19F9BC4A8D0756EFBEE5E6EB6185 +:10EB70001DDCAD381DF89CC7077B8AABBE45F93A52 +:10EB80002206FEEDE4F1F3A6A911E3AAE7E13F9422 +:10EB90004F9BCC625CF5C2EEC5FFF604B4EDEE15FA +:10EBA00035AE1A88816EEA795899D9B5CD0CFAF14B +:10EBB000FC6F318E0D7CA33E39697FF64226C4235B +:10EBC000CE289D77E23DE53D46BC6754B1E75DD474 +:10EBD00097F6178EE23913E1E751EDA4FB879D1BF1 +:10EBE000F0BD8E679B95C56339FD215EEBB0E17387 +:10EBF0001E976572ACC66BA3C569DF37B3FB50EADD +:10EC0000F95CD5B60F0C4413FF96C602BF8E0BE716 +:10EC10008AEABCB5F0EC40876B43CF1FA2C5C3B9ED +:10EC20005D0DE3173B7768DFC2CF23BACF1908E940 +:10EC30003B12CEC7D9B9B9C72FBD1B89BFEAF9C3EB +:10EC4000DB5AFDF4C776EED033DEDF8D2EAF9AD9D6 +:10EC5000FE56A5CFB9AF23DBE94EAEEF749DE93088 +:10EC6000E3B9315B67E6F175A69AD28D7DF7C6F000 +:10EC70003DC7F781E79ED1FB61BFBCAEE900DA5B1F +:10EC8000AD9E571316FFD28E27C531FFA0BA79DF8C +:10EC900070B047E7F6BF84F257BDF3B8C147E11C37 +:10ECA0006AFCBDA16D6850DEC18EFB43ECF8B9E78C +:10ECB000F60D67E72291F3B4D8387C4F8B08DFB3A9 +:10ECC000F35301FE325F93C16EE9799CB3B26B16C8 +:10ECD000CCF76CAB42E03EFBD9267D913FC2B89F9A +:10ECE000C13A362648A77556F61D9F3EC9807EE676 +:10ECF0004AEBD863F0FDF84AABC101FBEDDAD5EC85 +:10ED00005E65EDFF72A6035F6A136FC373A37A0D8E +:10ED10001DEDC9F65CD887DBF34B46835869ED419E +:10ED2000A24B27E0BDD25A94E6B0405E2FE6A71072 +:10ED3000D989DF19EA6D8545300FBD5D6737475CBE +:10ED40005F193CC5C2F2662876F1BBBFEF9007831E +:10ED5000403E8E6F9D07A3539307A3FCC6FFD7F2D7 +:10ED600060F8609C9F401E8C00C677D43C18C93F59 +:10ED7000721E0C882F8D0EC983D1A9C983C1F9F8E1 +:10ED8000CF3C18FFCC8301A59A07E39D0D65059044 +:10ED9000A742CD83716683A700F252A87930BEDA0C +:10EDA000B08AD5791E0CCBFDAB0B42F36064DEBF9D +:10EDB00001DBD53C18CEFB1F2908CD839177FFE6F8 +:10EDC00082D03C1833EFDF5E109A07A3ECFEE70A0F +:10EDD000843C186BFF500079305E8F77B7C6A5442E +:10EDE000CF83D11CE788290F0685F31EC2899207BD +:10EDF000430B275A1E0C0AE744DC98E87930C2F02E +:10EE000089920783C2F904E144C98311864F943C77 +:10EE10001814CEE738AF287930B470A2E5C1A070DD +:10EE2000FE0BE144C983A185132D0F068563884F2E +:10EE3000899E07230C9F287930289C048413250F72 +:10EE400046183E51F2605038E908274A1E0C2D9CA6 +:10EE5000687930289C2C8413250F86164EB43C18F4 +:10EE600014CE55F163A2E7C108C3274A1E0C0A67F6 +:10EE700014E213250F46183E51F260503813104E1D +:10EE8000943C185A38D1F26050380538AF287930A0 +:10EE9000B470A2E5C1A070A6213E51F26084E113D6 +:10EEA000250F0685330BF1899207230C9F287930B3 +:10EEB000281C37E213250F86164EB43C1814CE5288 +:10EEC0008413250F86164EB43C1814CE7284132575 +:10EED0000F46183E51F260503877239C287930C293 +:10EEE000F0F9AE7930CC8141D240CC8381F938BB86 +:10EEF000F360247FEB3C18BF027CFF9907E39F7906 +:10EF0000307E8C3C18B75ADD7F8FC77DE377CB838B +:10EF100071265E9337A2873C18B75A4BCE823C7F4E +:10EF2000DB3C1817E2BF5D1E0C3ACE3F2E374EB4C5 +:10EF30003C183ACBB7CB8341C7912D632E339F2822 +:10EF40007930122C62FE901F2B0FC6B1F8249C4F13 +:10EF5000B43C183FB97C13749B05FBB4E9288AE4E0 +:10EF600027937F62B485C70D7FA8FC1330E99C9F6F +:10EF700052FE09358F419302EBE1FB9CEFEF70B934 +:10EF8000F880E7A13816350F857F2AC677978A79EA +:10EF900028A6703ECE768BF23085B0739429F9594D +:10EFA000FE5AD8AF976BF2500C11CFE98BDD47F3C7 +:10EFB000293832D529CEE328978769A59F1E04F604 +:10EFC000DC3C36721E8A199C1FD3357499C2F936FF +:10EFD0009D97B7C3A739549E8BCB8FCA40D7698EF4 +:10EFE0003619E3F437A9FC7308FC9BC9E16AF19D6B +:10EFF000C1F9376332E39F16EFB7807F14EFB7CACA +:10F000004721FFB4786BF1D4F29F84F23B247F4810 +:10F010002E11F34F4C3289F9270AEC62FE891BD37B +:10F02000C5FC13931D62FE899B8688F927A63AC505 +:10F03000FC13378F15F34F4C77ADD6E4BFB84F9321 +:10F04000FFE2214DFE8B4D9AFC175B34F92F766859 +:10F05000F25FECD2E4BF784993FF629F505F58F7AC +:10F060009AD07F71FD51A1BEA4E13DA1FF52FF7175 +:10F07000A17D59E3C7427B55D3A742DDD3FCA5D080 +:10F08000BFA7FC036FF1EFA1DFE1DF431FE3DF4325 +:10F09000BFDF43FE8B772C4BD785E6BF78DFE25985 +:10F0A0000779098E5B1C3CAF40E4FC16DDED51F2A4 +:10F0B0005F04DFFFF6F92F52927FF87C043A2BFBB6 +:10F0C0001EB0B7254F674DF9EEF9086E2D11BFEB55 +:10F0D0009E552A7ED7ADB3B2EFB567BBC5EFBB6F08 +:10F0E0002F17BFEF1E11E796000F6DFE8BDE1697F0 +:10F0F000CE0AF692E72908C077BAD9106F2BC2F270 +:10F1000020E4BFC886785B29968721FF052DFF0C78 +:10F11000F92F687904F25FD0F20DC87F910DF933B1 +:10F120007C3C7F461DCF9F51CFF36734F0FC197EA6 +:10F130009E3FA391E7CF68E2F9339A79FE8C00C233 +:10F1400039E13D8CE5496F2B96A7BCC7B03CE36D18 +:10F15000C3F2ACF70C96E7BC9D58B67B2F62196BD7 +:10F16000FE0C552E3F04BFE10A189FC9B32AA757CA +:10F170003FF0C8BAD0FC19231ED884721A2D6F46EE +:10F180000E7CD397123D6F46777B94BC19C1F7A3D1 +:10F19000E7CD481BFDE3E5CD986BF961F266CCAD98 +:10F1A00011F33ACC5B75F9BC1923E24A6E41F9E3DD +:10F1B000F238D7125BDE0C9F55E2DFE553BA80DFF1 +:10F1C00045E982EB750F79070E5A9F1E02FB89AE47 +:10F1D00021575D36DF83562EA2D39BE57798F32324 +:10F1E000E7CBE889AE6AFFF72B581E87B9966F996F +:10F1F0002FA3877C0B07B3BF403B196BBE8C9ED6F9 +:10F20000879EE839E347CE97D1935DEDC99EBE391D +:10F2100085D1B9770F7456BF97AE34B51EC297ED3E +:10F220002E546D997F0F9F3BD38EF1998E9DFC5E7E +:10F230009C8B38ECA9EC7B7DF0373B9E4F184EF051 +:10F240003B7E3B7151FEC4F3E7D2CE7DFBE05EC056 +:10F250005A1B71252681B3471CFA81B00FBBC60427 +:10F26000F19AAADD9FBEF1470AD7DCA2C7FB721D47 +:10F27000148756F4FB5C89C0B778F24BDCA7C3193E +:10F28000DDA55EA1DF756B7E0F0774490D9E3F15EE +:10F29000E82DB86FEADACCEEB3EAC9D58F4F188DF6 +:10F2A000F7C689DF81FC433F7519C7B38B10670030 +:10F2B000FAEFB4E2FDD525AF2D34C0A070DE1A1AE6 +:10F2C00037E85524C6811ACCB6E1706F2F5DBDBFFB +:10F2D000E773B5821FBE88C34D2911E3449F2C28D4 +:10F2E0003A0CFEF3227719DEAB482B15E346847FF8 +:10F2F000470FDB32F03365C2EF75FAD97DCFB0EF3F +:10F30000EA9BB7209E4BFD9AFB4B8D625DA5DB39D6 +:10F310002BBF9762219698E8D676C5E31392BF3D3E +:10F32000DD8CE922DDCC0E916EF14344BA68E966CA +:10F33000758A74D1D22D61AC185F53E9A6DEA7FCA3 +:10F34000A1E89664E3F73C82F42A31A5A2C9473CC0 +:10F3500033E400CAB7561FFA5802F01B7E48BF6458 +:10F36000FF6A7CCB6995C16EA533D0445AC4DE8B4D +:10F37000077D80FCBDC489FAA0FE3E8A78F2219701 +:10F38000FB8FC8255AAE987EF0F802DABA19E46D00 +:10F3900004FB3D1A18AF4A22B89F5388D30EFBA82E +:10F3A00026AFC9B94881734DE25C940DE799762C7C +:10F3B0001FE4DF3B770C25B8EF6F0A7C9E0AF70647 +:10F3C0001E1CD9390DE20F9EC5A404D6AF59096C95 +:10F3D0007D5DC64B5B028BCF6C28D111D768F87D61 +:10F3E0004A7ABF44C76BB7BB5EBB01FCD116763F00 +:10F3F00080D83BDFB81DDB47E1F7E119BAFA6B00B3 +:10F400001FDA1FBF2BEE68F9C8B630C40EB7373FFE +:10F410007225DC6BDDA48BFC3D73818DFFFE1D7EB0 +:10F420003F654430DF42816D0CE6657870001DA7B2 +:10F430007A7A17F25195CBEB38FD0F964D41FC5E71 +:10F4400068911C10AF2BD4DF71D3308ADFB8B76559 +:10F450007EAF97DD5F1FCDFBD79AA9FEA2FDAAFF65 +:10F460001BFC9E95974ECA980F71744D19DE13FCC4 +:10F47000A3ADF030F02BC7D5340AE429BF2511CF56 +:10F48000713D1F12277E9AD52ADE07CCE1F7B673AD +:10F49000DA881F84E2DA6362FBB836B17E9D66FFCC +:10F4A00039DFC6F5D4465241EE367EAD9760FDE8B1 +:10F4B000E824CE3514DF8E45BD71FC8ECF09FA8964 +:10F4C0001D5FEB8B22DD8F596E63FCDB642068BF10 +:10F4D000379559F0DEF9FEB28AFEE05F7C7197BB8A +:10F4E0007FA43865889F96C0BEBB772590B12087E2 +:10F4F0006B2546EFFA8C9208EB962A77AA1CAAF2A3 +:10F50000975116E78E740FF5339B847296573644E5 +:10F510003280FCEC9530FCD5BE86E2759975DB47F0 +:10F52000D6F4017C3CCD9FE17D32538BE48A744F4D +:10F53000E7619B8DDD6F5CE35B0DF7467E419508CF +:10F54000EC5486A13E2B127C1FD9887EE95D3607DC +:10F550007BCFC4F320C9F519709FA2BD79D2E475A1 +:10F5600014CF27A83EC07AB5497122DEBE2A42F0E8 +:10F570009E2C8FD7F59D46B66C08F17F37DB721B4A +:10F580006D145EA38D7D6FD9CBED94006FE77FFD89 +:10F59000C306F03B2E1A917FBDB9BFA9BE7780D3B9 +:10F5A000675C826B2BBC4FE0979F51E3E374DB9C5D +:10F5B0008B46415C9ED23BC40E06F9E663F951DCF2 +:10F5C00004CF3F922C3A9443E27239ECC27D761F0D +:10F5D000EA8DAA07242011C853A0DA37A9450A5892 +:10F5E000A9DC8F365902708F2EA99CCE3B19F29A56 +:10F5F0009818BC56F99C18D7A2F29803CE3DC1AB1F +:10F60000F3104805F8AADD53EDE5DA44668FD63EDF +:10F6100024635ED4CD729B19E2A9592E471EA4889B +:10F620004C921D78AFA65F3971520C49FCC05F2720 +:10F6300076FB0154C9AFF9463F2FD2775B176DCCEB +:10F64000DF1E97E0FE33D06BF8E1CEFDE02E38CD23 +:10F65000A417BBFFC5ED04F76B0AF97A37EE3F74C8 +:10F66000EC7BD1C00D24F43B2AAD9DD86466EBFC45 +:10F67000B8EBD9BA37EEBC05D7BD6E3B515688EB17 +:10F68000D4C8965107E09EC5C80F997E126E1FEC34 +:10F69000F40FD029E7B04F0FF4F9B67641CB6F12D3 +:10F6A0003075D787EAE01C86EA5BC8FB673576646D +:10F6B000C5F441B5185EE672D4FF1EA7DE1D4247B1 +:10F6C000EDFBDD714AC9D4FDDC3110ECC8113DDC25 +:10F6D0000BE9C8A5F3A3F3DFC8F525F173FF649820 +:10F6E000D7C6961BCD20DF6B0379F662FA4EA2A92E +:10F6F000049997485C18CF19493D32C88F518B4205 +:10F7000041FD41A58424A4C03DB42221DE432C49FF +:10F710003CFF4B00F9D22DA7548E43EFE5AAF2A986 +:10F720009547557E6BE1A005CE0721624E4BBDD4B7 +:10F7300084878146B2D90EEBBBEA5FD6727FAED624 +:10F740009CE9C7EF977C19E81FADE4FE51ADA5D049 +:10F7500084E6605F32AEEB2B217E42E9B03285D980 +:10F7600079753E5AB9F45CD4137FC83EC12377E261 +:10F770007D44CF45033E5FA7B807C0FC55FA5CC384 +:10F78000E9A3A58794C0F79D9C2E3DE39B63877BEF +:10F79000C1892617598FF8E6E13DEEA6C04813ACA3 +:10F7A000BFF76AF08D01CF6B13C684E3295BA2E03B +:10F7B00099CCF0BC8EB8FFD846E53767455D6D3C07 +:10F7C000EA15792B3D275CAFB47AA4EA8D1AE7BD20 +:10F7D000B6B2FE005EBBED416F3CF18C2E4EA5042F +:10F7E000EF5739F7C4A31DD1EAD3E77CFE9E7846D4 +:10F7F000BF058A7B06CCCFA3EBCC043919EE20BD24 +:10F800008A2992C39BF5A8E7A435B67BF8AA7FA501 +:10F81000FA55DA7EAA5FA5DA63F51EFCDA04F77CF6 +:10F820009003A999CA2DC5A7D6CEF64B9B6DEE4580 +:10F8300080573CC53D0EF68D430259ECFB5F512FBE +:10F84000A2E941BC46CE9B0232AE0B3EBA2E644BBF +:10F85000E178A8E30F4A48647CA45A0EEB7DDF1CD4 +:10F86000C206AB269837A7EF70E28675ABEF4876F5 +:10F870009F714D02B3BFB5096CDD52CBCDB692BBC3 +:10F8800051BF65E2338EFCEE7803AA70DF7C6D8297 +:10F89000EB2EA087A9C885F3E863274EF04BFBC881 +:10F8A0004D127C379A54E990D83D7312FC7E8BC27E +:10F8B000EB53ECC8057DED03FB6BE8DF1239CFD8C5 +:10F8C000A309EAFD5EE67F3A49771EAF471398FF2A +:10F8D0007908529FF42A56F382A9E7394E09E8D4F1 +:10F8E0006EBD0D916EBF20313F3D91D14BBB4F009E +:10F8F000C287FEFEBD7B0D44362791E0EF59D599B6 +:10F90000D0BF8F27CE26B057BB1206F0734C671DB1 +:10F91000D47F25779A128706E55D95E30727CC709B +:10F92000422A52DBF55DC3614F45E57A27D0BF7DA2 +:10F9300042D760CC41493A3399FCB8F442BE209595 +:10F940000FCD8AC00733ECC343EDA4D53004FCD1FE +:10F950007629CE09F72CDA974A0C5FC9C4F329C976 +:10F96000C23CD3E3997FDDC1EDD53B09592827AAD5 +:10F970003DA6F3AB83523B0F8F11EF7490CE3DF158 +:10F98000FEAD706EA5C93FA9CD4F3969A105EF7FC6 +:10F990006CDC63C6FD6B57093BC7EF6A31A27D8EF5 +:10F9A000A6B7696DE688711CB5A4F47B0BE897A631 +:10F9B000D424823D4C9B7BD2067CD7D2A543F25DFA +:10F9C0007308F645AF2B11BFBB55CBF4F49B121750 +:10F9D000D1FEE91993B1549F3758E488F7CD4F739E +:10F9E000BD52E5F14A3A22DF0F9D06793CEF7EF3E6 +:10F9F0001D1709DEDF6F8863746C886374EC728F87 +:10FA00004F781AE4CD9781FAB0583D07E5FB7F3572 +:10FA1000CF943ADE46AF2951A62AD0B0608A19D6D3 +:10FA20008914E29A3C1B9475A342E03BA2C7BC3BFD +:10FA300012F3318E6D12EFF9DAD9BDE1CF3716E04E +:10FA400077DEA9648D7930A5475989CE09F183F312 +:10FA50000BDEB7E9A83C2DE8D39A03F2FBBAE22605 +:10FA6000F63118EAC2FDC99252833F40F996DC4054 +:10FA70000D05A5CB7F03D85B39A8008000000000EE +:10FA80001F8B080000000000000BB57D0B7854D5DB +:10FA9000B5F03E73CE3C92992433794E1EC009E1F5 +:10FAA0009D108724BC1F4E9E448830BC0485EA808C +:10FAB00028CF2488D6DFB6DECBC444F4A2B745E90C +:10FAC000AFF4D6DB7FB0A2A8200182069AA413402F +:10FAD000E4113408A8A8AD5129620BC908EAC5D6BB +:10FAE0007BFDD75A7B9FCCCC4922D8DE4E3EBFED62 +:10FAF0003E8FBDD75EEFB5F6DA872EC977134B641C +:10FB0000CCB7D8C0B64A8C7D87BF1B43ADD96E60D9 +:10FB10002C89B196383BB54EE70CC7D284F07E8570 +:10FB200063693E63D5D6D85C16876D7F3F8B85F1C0 +:10FB30008A58EAD202685BACAE5A95B12546AFDD71 +:10FB40000ECF774EBA3CA48EE12FD8DF3392B12E80 +:10FB5000236B94E2B01F606C0C4350F8CFED56ED70 +:10FB6000D097F0FFE1FD448B2D20C3B8CCA35CEC13 +:10FB7000B0F047BE1B281E4D66CC285E939ADEF877 +:10FB800046CA652C7672116370DFCA5C8FB22CB8DE +:10FB9000318CA99E18C6A2D833F6F3D98C19F07D02 +:10FBA000584757F3BBFD7C00C71FFEE54A0C83FB9B +:10FBB0001F29C118570E63171E3C15E3B6C1F50780 +:10FBC000E5723FF46F4740C687F0926F870BA31929 +:10FBD0007BC4EE1981EBBA63DD7F8FF1DA42F7D98E +:10FBE00003703195B1157E19E7E6F0C27FABB659C7 +:10FBF00019B384FA95F509117DC018E1B5D2CCD6B8 +:10FC0000D4DB7AD26305D203E65DB17D8B295DC575 +:10FC1000F9BD93ECD0BFA0C0AB80EF0B0D317E5F80 +:10FC200066089E25DB4799D2E1D6474D661680755A +:10FC300030A5DDC86C84B50A09F0E61578D3C37920 +:10FC4000B8C54AE3DDF57F65BF1996BA18E67A2094 +:10FC50001E9E6F5A51C1727BAEE3AE3FA86529402C +:10FC6000BCBBFE4D623E953FFF601E3CFFC0235F64 +:10FC700020DDF4EB5CEC337ED211B16E376300CF44 +:10FC80003241EF3B1F8DBCBFACE9311A6729F39AB3 +:10FC9000909E776DD4DFBFE933E4BB654C095D0707 +:10FCA0003C5C3E9265453CDC618F493C0F20038FF4 +:10FCB0008DFD0EDEDF7D64609C37A7277EB5F6E202 +:10FCC0003AE06F33637F5E67A1F6C23A46ED08BB48 +:10FCD0004AF459DD74F27EE4AFAAC65D261CA7C5BE +:10FCE000FFA78409F04861D3373232572173DF7B95 +:10FCF0000EF0F92326B3EF007FBB19E79FF546CF3F +:10FD00003D48AF1BAF96D37DFDFA1769FC7F249E5B +:10FD1000F86711AE3B17AF2B5FF6B6AE9FE2BA8025 +:10FD20009FD95858977CFDEBD2D6A3AD4FBB5F2926 +:10FD300003DFF5F2BEC6EF23843E58FADCACF5696A +:10FD4000808ADAE6CFFA77103FB1D328BF1A3F2D69 +:10FD50001374D2F38D46C76EFE68FA775A9F463FFA +:10FD6000E07FA7C1896DC06918D7934FF47CA1E7E4 +:10FD7000834E63477F945F3D1F744A6C416FEBFA7B +:10FD800037FB405AD752D55D6687FB7731CF7A3B38 +:10FD9000AD67235DBFA06C3CFC3394ABE7385F7765 +:10FDA000EB3933973776DCE847BDB936464D71D825 +:10FDB00004FD80CE9DBBCC3E7C4E9BE7FC3AB77BDE +:10FDC0009011F15E4EED9FD779DC830687EEDFFD63 +:10FDD000AB2BB12ABCDF358C95A3DC77C644C2BB04 +:10FDE000CF2E133CFB900EC87F4AFBFF7C803AE984 +:10FDF000B9F631A847CF7FFB5FB11E78BEEB5B73CE +:10FE0000796FEB3C2DE807EAE5B413F8EC7621674F +:10FE1000B73755125D963C33CB84FCCC1EE0F8B46A +:10FE2000C01FEAD7B6A8D867711D8B1B24D2237ACE +:10FE30007ADCE59AFA39EADB3BFD85F47E0FFAB00D +:10FE4000C789BE77213D8685E831D6A1727854F8FE +:10FE500003BEB943F0CD79658DC9007AE4FC3380E7 +:10FE60006F007995C2DCBDE9C1FE0ECE877DAD473E +:10FE7000BF8EBEE05FF65CCDFA3486EB1F654AEBC1 +:10FE800045EF68EBBF8BB96249EF88F5B28E1B492D +:10FE90005EAB2D7C5E6D9D2B9AEE9C817C51B519DD +:10FEA000E895D973DDA87717F7026F997CD168813F +:10FEB000F7BA1E905CA86FFBA283A627EE12F85A31 +:10FEC000B96DF10C349A8B613E3913F5D1176FC6B9 +:10FED00024A25C415FFA1E7A35C91F9B711D8CE319 +:10FEE0007B09E07B8374FDF45BB6B9D03D28ECB9A7 +:10FEF00015FE9BDC83C2F5998EAE6CDBACD0F3644F +:10FF0000B7DD26B4C7F10EA1BF845EEE5BBE60E133 +:10FF100000E7DA1D0EB26F6C8D83F46375D3165350 +:10FF2000B8DDD5E44B93B7B10E3BF15955E313F46B +:10FF30001CE85FD501FD4A4BC7CF6F55C3F0394E62 +:10FF4000D051AE30A1FEEE4B7F82BEF9B2236C9D44 +:10FF5000231CC2AE08FD7B2DFDA0C1AD1F57D307EA +:10FF60001ADC1ADF6BEBD1F37D5FF0E9E9C2989FF1 +:10FF7000FB0B3AFAAC427A84F5115E05F0DBD66CE5 +:10FF8000F53F04F0B6491C7E5F7314C1DFE92C769F +:10FF90009F033FAF2A7521B527F0C554F4EB3CD33E +:10FFA000109F9A3FC70A1222FC247DABF93779C211 +:10FFB0009FDA1BE5CE0713093F4F02F2C3949A8ED6 +:10FFC000391620D9AD8EEDE50A8C3FE5898E395181 +:10FFD000D05FE8D8C1FB5B3B4E595C8CD5B057CAAB +:10FFE0004BA07F3BA013C7BB565B60F62C44F95D6A +:10FFF0000D7E9205ECD1EAD3430EA1DCAD6EAF28A5 +:020000022000DC +:1000000097C0EEAC068323813DAA74C706ACB9D471 +:100010006713E0B9E7EDDE65C42F57EBC86EAD3E60 +:10002000AD70B9399248EB5700F62878AF2E1AFC1C +:1000300055C0575DBCC5559B49D77D51F1D877ABAD +:100040006AD8758D1EF81EC25167606E07B4AD4741 +:1000500087C4757C8FDD6E5DC72A14E08383EB2C2B +:10006000D4EAEF179AEC83D0EE151A98B7377DF9DA +:10007000A483FB8DC0E4E948E7AA23269277FCA17C +:100080001F5829F4511510280EE0A93CCD02D1B11A +:10009000F85CD9E70AB60D12FB24C25F61A1BEDC91 +:1000A00037DCD7DB56E17883C3F984E3A948912A8A +:1000B00094B0794B6C51117D39C5300CD7C3E468CD +:1000C000D756C0AF9C6E58B31BD62F0F8016F0A129 +:1000D000D85DF2626837164F9197405B6BE476B556 +:1000E000D6C09687E3E905811FADFDC0E1D98A74CA +:1000F000BFF456FB182BE9AB0C3BC9B9586FADE404 +:100100000A50DCD4CA5C5BE15A9DEC619C8FEB1910 +:10011000F2F11B621C97D9B047057E6D747C40FCE0 +:10012000EB8A33DC9B09FDC0131FF17EBAE14A263E +:10013000F0F781273ACA15900757B6E1CA40E81F81 +:100140007AE2637E7F220C0906EAF0139F94FB6C2F +:10015000382ED7676CBB3B1BE7510C12C9A972C084 +:10016000E4AF85FFAD8BE5FC54073C82FCF786B01D +:10017000B3EB6B8A5EB602FF2B456E750D8CE3C741 +:100180008069F4DFDF6A7894AD068A53B0457CBF9E +:1001900029D6ADD18135B8B367A15EA87767CF8E78 +:1001A00041BC7A4F225EF3DBDAA7A03E6E78FBFDFE +:1001B00031E8AF22BD709CFC3688DD603D975EEB78 +:1001C000B7450E8B473F7014BEE3003996DCDC9FC9 +:1001D00094543B5B047257EB66AA09D695A28BEB4D +:1001E0001A18D72FCFDB3D7FC4F7584680EC4DA1BE +:1001F000C3FB31CEAF8F57597B7CAF7A59AFB74C29 +:10020000B90FC8E8E7C4A737BEB704F5FBEFCDAE1A +:10021000C12AC2E5660F003C3B0D4C61F1C426C308 +:1002200094028C3FA35D1B50EE5DCCE90339C330D3 +:100230008D80845FE298B0B855AC07DE2F61D08E18 +:1002400045F86EA0F5C9C857A3984746FD3586F90D +:10025000ADD87635BFE644BC3D19C5EE40BFCFB240 +:100260008DB9FD61FA63403CF7F726251809EE6861 +:1002700063FD6CE4D7E82F981DFDAAAEFF34293842 +:100280003E08C874BCEE3A6C6008E70B46BF3D0EF2 +:10029000FAC1E18AFA2C0B8DD725E8AD8DFBA44974 +:1002A0001DEE407D93C0FB2F1472FB1CFCDCE47F31 +:1002B0003613F16359E30F932F673CF75BBD494554 +:1002C000F1F1D0D63747339C7F6C4BB401E9F0F2A3 +:1002D000F6BC28E4879D881B587FBCD97E0F8E17FB +:1002E0007F05E0CDA4EB6EC2ABA28E8A03BC4E9814 +:1002F00066533700DE5F88AA9F86FC1FDC6160CFF3 +:10030000C2143B4DAE59D8DF7959B5A3BE7D21B398 +:100310003E9AD6B3C340EBD9191D1CB116E0DE30AE +:100320004C2947F8142B53500F2B8622F51EB83E4C +:10033000349EDB574D2F2F88E7F2F3A404F3E7E157 +:100340007385243FA5B28DE4AE2BC8FC669827695F +:100350006EBB8CF4889E05AC847CAF046406FD49BA +:100360001E46498D4936A35F257DEBB62D06BA4F53 +:1003700011FA76CA87AB2B78DCE33A3D11C63B68AD +:1003800033325CD764D621A33F38F92A7305907FB6 +:10039000AEF278C60E7FE83F3DAFF3074BC578EE6F +:1003A000A0BD042F17B2483FAE7473D9E712CDA396 +:1003B0002A68A78B2DBAFBE8E7C5621B193795C5DC +:1003C0000BFFA63FEBFF1DE937E05E98EF3E3B9F3A +:1003D000AF54CEF915AEAFABDCE4423CECB2B9DFC2 +:1003E0009D887AB1DDC8B6B2BEE5E979883FFDE007 +:1003F000730CBB6A65FE7CE2471BAE67C4E68DBE2C +:100400002858F788417C7CE43BD42343FF333101F7 +:10041000F5F855A15FB456E333E4277B1CE727FBCF +:100420000D2139BC333E939ED3E40AF90CC7D96F32 +:10043000F42FF4F46227813FEF44FEDC6563144738 +:100440003D966A598072A5CDF3BCE0637DBBBE6664 +:100450006DAB11D7FD15D80380BB24EDAA29DC9E16 +:10046000EF49E27C552A7F4BFE766793C4D0CF4F8D +:100470006EE2FA3B9C3F527BE78F5F225EAFC51F67 +:100480005ABCB0FB87F2C791BF8F3F365C933FBE2B +:100490008D453CDCD75C9CC2BEC7BF6914FCD0D77D +:1004A000FDF156AEE7F4D75F1178DD67DA383D1716 +:1004B000F5C0CD0617CA39503F7D36AC635F347F37 +:1004C0008F296BB2B0BF4BE17A65579399F4CA2E6E +:1004D0009BD74B76DC6961E83F30C5DBF133D487CD +:1004E0006916754318FF2E8DE7FC566F0C8CFF0CB8 +:1004F000FDE2A39CCEE36ECE934DF05CEA522EE774 +:1005000005174C5B300E2B4D28DC817C7402751670 +:10051000B4D5E7E029407CD53913E9BBD75A4E96CC +:10052000617E11FC1E37F2D9D8FD27CB8A72F07993 +:10053000AE4FF78A56EB8FC735C5B3EE78D723ECAD +:10054000C678C6F59207F92437D4676E23C56B1AAF +:100550003FD447033F805CCC67AA3116869C73CE9C +:10056000F330984336A73C92CEF303D3283E9C7BCE +:10057000BAFD55D0CC6C9E47775FF0C17C1D1F80C3 +:100580009D3D1E8FFED2F180C980F399D664737FA2 +:10059000684D16F293264FF4033CD5FF61D8B31B88 +:1005A000C2EC7B6C0297A3C75D0ADDF77598FC83EC +:1005B000E1D2BF33FE5EBDB03F9FA33C63FC70DF62 +:1005C0002B0BD18EE62F771F44FC4F4F92E9FA2F69 +:1005D00058C09285F47129E497D51BD5E2CFA4D0F9 +:1005E000734CF10CB3C1FDFD49D1F9387F6982F735 +:1005F00022D28929C123F8DED80979F9285FB651BA +:100600007509688F34B801AEF2ADB6101C1A5C677C +:10061000055F94262CBE88EBC7F750BF347E7CDE86 +:1006200082EF6B74AF6FFE82D33B8CFE48EF10FD00 +:10063000A53BB0AFE1E12BA157B4FE3F4A7F2D7F30 +:10064000704DFA637E20F6EFA2BF352129447FF07A +:10065000B3E2B1AFF7B3EA4DE077E7F4BC5EE82868 +:10066000A4E75D265821FA552D1077A23C7A1DB4D7 +:100670002FB0C7CEE7EAFAC3F9FEE022B2C109F112 +:1006800084F76A537008FA21A30212F985A340F097 +:100690001791FF95417ACF25F0C4CE4BD2F961DC9A +:1006A00045FF2E1DFDC34002FA51A3CC1501E4F70E +:1006B000DDD629E9E8D7E5592765215FBD3AECBECB +:1006C000E368825E4D5BBEE73935E4FF68FAEDA072 +:1006D00018569BBF2081EBA11B41DDA21F882E6312 +:1006E000381C9A3E47F2201C5260BEE13B2BE9E5E4 +:1006F000A60EA0C78D0807E0A155620DA8CF0B0D6F +:10070000EEC462F4D392020AF7F7BEE98FF9C18A08 +:10071000A637DE43782B703F04E35097F162773EB3 +:1007200062604F3F58F357B4B840F367B4F813FD15 +:100730001EBC3F405CB79B0140B447018BBF06E63F +:100740007FF2B23ADC2DE4568175548875CC64EDA5 +:100750000417FBF6BBEF26017D66087C541C81B8AC +:100760003117EF337633E0E16685C79337BB207EE0 +:100770000CE3A399E322FBF89B921C1AE75ACFEBF8 +:10078000EDC044DDFECC3FDA1E017BF409B8CEC7D4 +:10079000D6F1B874C240D9A7A0E11C9769407EACDD +:1007A00016F60DC2E85EEDD24BC22F9E60E8C8750A +:1007B000017E5BF7FF8DECE081FD7F7B07FDBCF1E7 +:1007C0009F2BCC0CEF4FF8BC200EF5041BA7125F3B +:1007D00069E356FFA9C1CAF875E2FF2AB1F6C30062 +:1007E0008F7B28C267A1F677179FDC84E37D794E63 +:1007F000E1BC2DE62F337907611EBBCCC4F3018722 +:1008000025EEFF68F70F1B016EB8BE2941CB0BB474 +:1008100093DDC79F398CCE37633E202F44D79B2F63 +:10082000947FAEE4F6A40FFEFE37F2015A1E60ABD1 +:10083000C01F3B78D6A4025C531BEE51D0BF9EEA8A +:1008400094993B6CDE9B542B7387E5039E49D0F94A +:1008500023075FDC3403EC49759BEC8A42796DDA3F +:10086000753C17FBEDB2CBDA0B1FE9F13BB5E91E86 +:1008700005F9DF98A8927C5F6BFE0923804F6E40DC +:10088000BA33F2EB3AC74824477AFA1ED8FFEB8412 +:100890008E9CBEF1DD17FDF574F8DDC522DAEFB9E7 +:1008A000163DF47CDB02EBF4C1FA02B04E1FF85D9A +:1008B00007D6D9A97F689D93FA1ABF5637FF36012C +:1008C000FD368D4F4B1338DF8CDFB72981D942F4C9 +:1008D000D2F0F5A1B0577BA3347FC3356F065C3AE5 +:1008E00005768718D4C7DA9D6342F66BFEE932F2CB +:1008F0003734FB355F5E544A6A53D82F4C23A35ECE +:10090000D3DBA9B9EA6223EBCD3E2D88EC97B76D16 +:100910005462A867203A4992C087F0B33538CE3088 +:100920000FC1A9A7A706971E1E6D7D9A7F3D5FD0B8 +:100930006FCEA04C23C2DFC3AE8A75E2409887B861 +:100940005EBBFAB58E9FAF5C28792BB717BEED8BD7 +:100950007FF5F7357D508613E451EB43BFC298987D +:100960004C742BBB6A626EB01B2C238A7D1A6657AF +:1009700058C550E29F7B851DEE8B7FAAAECACC9BEB +:100980001FE22363E31356E4A37DCA462BE6272721 +:10099000DB66D5C6019E4AFE543417FDBCEA0E0341 +:1009A000C3145669D3170731AEAF7E8FB9502F16D7 +:1009B00035B51623DF1D52DA658AB3BF64EC893082 +:1009C0007FB1B1A9D68AFE5463A24C71FC6107E7DE +:1009D0004BEDFE9644AE3F1ACF5D9EE1EEE5FE196B +:1009E00071BFE4E33CE2A3B24741AE310E4D8AA1B0 +:1009F000BC4489649F53817EC84D46F2F3218EF931 +:100A000023EE035E6A34EFC2D47E69E323F7D88114 +:100A100010F5FFFD698D19F30BB324D7B3F05C9982 +:100A20001A6CC57ED9DC4CAA7B18FB3F32F9B3C1E6 +:100A30005B25CA8B9401BB60BF6C51A61FF313FBEF +:100A400025DEF735F37D0266F725CC8079DEAE48EA +:100A500018B581784AEB0FCEDBC0042387C557F762 +:100A6000ED9549CFDC572AF971BFA9D49ECE7C61A0 +:100A70007C55F6A889D635BB29A508F9784EB9CC9E +:100A8000FC61FC1D107EE13C0FC4E161EF1D8EE2B4 +:100A900070051703DC52486EA7093E9FC5B89F3802 +:100AA0007F4142C47BF0C62D688F6E6D8238157A07 +:100AB000D344FC7AAB373D625E0FE37ECD09162C42 +:100AC0008983F1FB250D24FE9B11B48F0EA8A87716 +:100AD000CE24A25E63C3B89C6872572AAFAE237E51 +:100AE00070F27DB2791248938CFA2F529E668E8BEB +:100AF000ECCF72F7A83788907FBD5ED7E47E5EB3F7 +:100B00004CFB72F30A2517EB453FE8FDECB1D17DB4 +:100B1000E8856FD587E37AD30B1F96FF5D7AE135C1 +:100B2000082BC681FCFE3451E8877EAC1FEA875251 +:100B300079FB26E4972EB077E65EF845B3175A3C6A +:100B40005E06F24AF27E91EF67945E4D65BEFC5000 +:100B50003CDEAD2FC09F70F5E2E73C9D984572D416 +:100B6000AD5F34FD11E64F18C7FCE3FE4429F89150 +:100B7000A63C842F83E02B633C1F588685439897BF +:100B8000737E41F9966A88F329DE67BF25B850CF96 +:100B900049F12139D0FB195A5ED72AF2087ABEE80A +:100BA000CEF3CD35521D8CC61765762E1F65736545 +:100BB000CABBEBF9449B4FCF1F015D5EE69AFC2157 +:100BC000E4EC87F24773A2D8571DC4065D0F5F6837 +:100BD000FCA0F187DE8E1CD3E567FAB2236FA21D5D +:100BE00019DDB71D797D9891F4B5DE7E68F6E27760 +:100BF000495C2F6724F27D8E69C3E7D9D0EFB02618 +:100C0000F13A0DCD0E75E79736737E78BD63892274 +:100C1000A13D41BD9019867F916FD5F8AFEA51890A +:100C2000F28D15422F7536F3FC5B7589ECB7C0FF6A +:100C300016373DB189F78D949F2B545A150B8C3B79 +:100C4000D325B930AFE316F9BA196E89E7EB5C9199 +:100C5000FBF42D3AFACE117C349305EBD01FD7EB81 +:100C6000A53957B95FA0D74F73C4BEFB1CDDBEFBCF +:100C7000554DDE07B001FF4C7FC09CF4FDFE80F6B1 +:100C8000BE46478D7E2AEEC5A11C1DFCC6A4C670BB +:100C9000FF19E937F5AA42E3D893045F0A7FE6CB50 +:100CA0008B79BFA0984F3C5FDDF485C93BB26FF8EC +:100CB000AFE5B7C6A29F3E3AE4B76BF34E53184B6D +:100CC00047C74C674F6689EB3FD47E0CD7AD43A333 +:100CD00083A6477BE059E8D9BEE8742D3DABE9B364 +:100CE0007FB69ED5C6D7EC8036AF5EFFF615B769E6 +:100CF000FA74FD1603E54B268BF878B2C8C3CE4FC5 +:100D0000E2F1C1AD493CEEECFACA62407BB9B38571 +:100D1000FB272EB3FD38FA05A17C1FA7E7C331CC12 +:100D200087FBEC4C69B7D0BE67119012F73DD3F842 +:100D3000BEE77625E0213DED52580DC8C9397C0F3C +:100D4000E679F8806F21EAE9873F1962A0FD7725EF +:100D5000D08EFEC9D83C85F68F1C6695F2C19DCD1C +:100D6000663BBED7B5EFFFB41A719CAF980B43B882 +:100D700043CDE6EEFD1BD407A5729B8CF9FBAE209C +:100D8000C8083C3F6941A018E3A0C9ACBD16E57B8B +:100D900002D2B117FAFD2A498BB37BCFEF17377315 +:100DA0003FAE3846263F6E8AAFBD18F7ADA62892F3 +:100DB000AB169FD5E5F75FD1C51FA1FCBEAAF0FA1F +:100DC000435DFEBE91EB99EBCDEB4F40DD067CBC65 +:100DD0005EE373A16F581FF9FD9D26BEEF133C69BA +:100DE00064E807B30B89BDE663AE95E7DFD712ED84 +:100DF0005663719F8EFBEBFB5AD2DC6A6EDFCFE746 +:100E000076048BD03CEEDC3E5BA1FA35911FEDB150 +:100E10007FD2C7FE88BBD17E08D5695FFB21C55F45 +:100E2000AA94F6B95EBC69750B4CD43FDDC8B49F7B +:100E30009BE474E7F96837F2F9CEF3696E84EB79D5 +:100E4000C1A71ADFEF3B77399AF6414D6E15F78F40 +:100E5000830E8BEB59E25BCEEFF5A943FCB84FFB59 +:100E60001B21173BA383C7B213C3F73DF83E47CB03 +:100E7000BA47679F33D27EB984F9486D7FD907722C +:100E800043753DF18CE20F23AB67386FAD9BFD1AC4 +:100E9000DB2993D438C4FBE5446D1F538DA33CC4B8 +:100EA000B757A8CE508FFFDDEB9807EB511AD659F4 +:100EB0003C0AC8FFABEBECD46F5CE7A476FF3A9535 +:100EC000DA878EC73E8076BFDA6DF22861FAE39D3D +:100ED00064EE77E5657F524CC5DF7F6354873EE55E +:100EE000C10E19F5C58D57611D117527CA65C43727 +:100EF000E537B342FD4C69710CF66FBC0AFDB0E7F3 +:100F0000AF2439B83DAA53EA462793B4105FFC2DAD +:100F1000C9DD9104D7EF71783EC176B734FFE02583 +:100F200046FD73BC7FAB7C099ECB0F14525E391F0C +:100F3000F3CA7934EC42C4DFE85613ED976BF9DD60 +:100F40003C4DFEBE8ECC33E78BBCEEABAC83F2CD1A +:100F5000051608B40C0817A79F5B9AE794301F98F2 +:100F6000647261BDC3E82C4F3EE6635B9318C547CE +:100F7000ADADC9196A0E720FCFFBBAB5BC2FFBFE1F +:100F8000BCEF918F627DA4B7AE9A687FFAC8A9586A +:100F90005780F60B2DE4FF69F5C82DD1BCCE8065D6 +:100FA0002CA03CD38DA29ED162F69A93495F050E88 +:100FB0009E80F77E7F99F17DC7F60F695FBBD830C1 +:100FC0003C05EB7E0F4A43E3B07DEAA3D81C6A4F91 +:100FD000C55E44FCB418AC2ACE7B669D5A82756D02 +:100FE00027D6B112AC637B6B9D85DA93EBECD49E74 +:100FF0005AE7A4F675B88EFC731C9E477E71BF65D8 +:10100000A37D92296FD9146CF316C650BBFBB6189A +:1010100013C2DB12CBB66BF360BD5A203AD080C945 +:10102000FED6A7BC8F59FA81DD337B474AA3186BE4 +:101030007BCA3B5D990CE34EEDFF93AFE0FE9BC98D +:10104000CB1EB3005C734FD91ADAA0FF76F2F2C759 +:101050006CA86F8F4783D2C3F5AE38EE1E0474437D +:10106000A590C605978D837E82D65F31BD641263DD +:10107000B71477643360ADECE495D32D80C75BACD7 +:10108000DE1F63DFE44B9A5ED20FFBCC87F5604135 +:10109000C948713FCB9012B1FE65A6C3FB4672589A +:1010A000FD9E5BFA13ED338D714BCC41871F8CB4E1 +:1010B000EFC5EC1F2784CBDB4C47E91B488F89C960 +:1010C000BC0E78F424C91D5E5FA17F6EF439B504AF +:1010D000E934E642591DB633CB1DD4F72C185B8793 +:1010E000F25C62EBEBFD627ABF3C99D78D1429521A +:1010F000445D89FEB97C6026F48F8347A3294F3075 +:10110000FAB4B716EB4F4B9D9979B2A6FAA8EFD86F +:1011100082FB6DA32BCE9424A0FCD824179A89318E +:10112000ACA32E01EE17DAB1A00AD7F54431D6FFF1 +:101130008C562517A2ADD0DDDA80EF17BA625C8538 +:10114000E88F9F564BD0F49C52469D2880E7A60E10 +:10115000925D1618E854E0A68997A05F382C8EF2AD +:10116000BC85CA9A2B27A81FE3AA51711D5B7E5D1F +:1011700045E398C9AEEF9E51FC2FC83F459E38CA43 +:1011800009023E4AC2EBCA60DD0477A15DF6474919 +:10119000C8DFFF5A6287FEEEFE1296CBC37CC3FF08 +:1011A00042F78F44AB5100E86E93BD04C7DB6D92EC +:1011B000EC0F51DF538CCFFB861855CC1F9525467D +:1011C000458C3FB5441A7F0EE1CF891B85D7CA33C2 +:1011D0001C11F7DB6EB3929DA8782B87FCA2B6DBBF +:1011E000D2C95E54BC35A908DB3603F7D32BDEAA7F +:1011F00028A7FB061E07572CFC915BF429EEAD587F +:101200005849FD5629E52738DF959CB83CCCAF4DB1 +:101210001B945AA244F8810349FEF3447EAFD030B8 +:101220007CD32480FFDEA37C9FA2222733E2F9191E +:1012300005524978FDA8675254447F7689A324BC9F +:101240000E756E456A44FF96B99911FD92A3056427 +:10125000BF410F5494801E380AED5260C1025107FD +:10126000A5E59F0A054B15B68BBCACC2E3EB61F05C +:10127000877AB0C41669A77747733B5FCED6D0068E +:1012800049F911BEBF5D9668FC24DC4E94CB15363F +:101290005E97158987BCA346B2977931921FE3FA0E +:1012A00092A34BEBD0F4966744BEAFF961E5023EE2 +:1012B0006D5EE673B7A33FA2C1ADCDAFC15F2E2F68 +:1012C0002AA17CF735D6A18797C17A503FE8E1681B +:1012D0004A16FE1AF81FE4AF897324F04BECCD7E5A +:1012E0006BFE7A05E82B47B8BEB2498958B7D79745 +:1012F000BED2C6EDCB2FD3C69DE9F0D0FBEE1D9F2D +:101300009E9A2087F5333F4E880FEFBFF8E9A688F5 +:10131000FB491FCF7184F7B77E3A07EF4F51D45A7C +:101320001BF0E53126B97CC8076DAA1203F4283EEC +:10133000EDAEC3B6F4432F96ABB2A9E77C75D84E99 +:10134000BCE86F33C3BA6E1A26AB18BF6B7E881E1B +:10135000DEBF26F3BCC3B1ABAA15F75977FB542BFC +:10136000FAF3BB1F54ADE887EC76F37319EE2C0348 +:101370009D8F7167F37AC5BF24F3BA834EF1BED651 +:10138000FA8DDE4E841BEBCCD137A8FA264875E5E2 +:10139000C7D0BFCAE9E95F1D53FC369CEFD8837EF6 +:1013A0005BF87EE2F5FA577F041E43380A99E40998 +:1013B000D723C596284FB8DC96DA1D11FD93C20FCE +:1013C00099EA4C8D78EF263533E239F01B87A15F1F +:1013D000526B62546FEB33F07A5B3D1E57A4F0F80A +:1013E000CE65B3A33B83FB66726FE7915CC5865EF7 +:1013F000CFB7A5A4707FF03F5218C1352B85C3A786 +:10140000AFAFD5F76BF17C0FE293B99CC8E72EAB79 +:10141000E10AB8BCACE0E927A6535D6DBEE1DE2C65 +:10142000E8573CBD753AAFAB35ECC13ADB194F3FDD +:10143000CFEFDF60C837823FB0CDF7C274AC2BAFBF +:101440008AE2F5095551A23EB46E7444DCA3183EFD +:101450007E6A21C69FFB8D0CF3FC8F99C00EE6853A +:10146000F6D9AD661EAF5A4DBC0E7C7DE6A9F5A837 +:101470003F3E8BF2E6A5509EB148453C5EB45BA86A +:101480003EF4BE7DA529C807B35278DE2B7BCF443E +:10149000279D2FFBE7C151FC7D7060FD308E73717D +:1014A0007736F9E5D903189D27D1E801E1335D8F3F +:1014B00082F081CE6330B713F36FB50E138D332BEB +:1014C00085F3E3F5B63DEA89E30C6B7641BB2085F5 +:1014D000C7CDB7E2BC046FB0FF2CDCD0B307FBCFA5 +:1014E0001EC9FB486F59CE0BA27F1BFC510CEDC3EC +:1014F000BC1FCDF1C63282B46FF3EEA26CD706BA30 +:10150000CEF1B8C03FB0B643C5FA0F7F3FACB718B5 +:10151000E8F42E457CDC66F60F26BEB2AD89C179B3 +:10152000AEB7DEB8EFF921E0047B327F3CA79736F7 +:101530003FE0D882747C579C3BD1E001387E8C70B0 +:10154000687075C3A3AB3FEF147E7B278E971BCAD1 +:101550005357FFC940798A6A09F424F4F77CC85CC0 +:101560003E95E8437950DCD2C2F9C69F58526C834D +:10157000B6A071158F8FDB9588BC9866CF268AE759 +:10158000C7BEA744D8A38922FE1DAFCB4F4E6C9C8B +:101590004EE7F826EAE2E25FA488BC651A4B0BCF5F +:1015A00023AC15F1C6E5B68171E89F2A10E7CA8021 +:1015B0006F932AB371F121BDD0B08E459C53D4F8FE +:1015C00070E469FB9D38DFC8D3EC0EF207B471BB41 +:1015D000F3131C2F97DFE37819D531ECE949D037A5 +:1015E0001E3132BF1A5AE7040E2A833087E2A4CB99 +:1015F000176C645FC61C9D43F5DE66A781A961EB8D +:101600008F52A3991AA62FADC3E223FAB2A04F5D61 +:1016100054A41F902FE68971A5458CB73FBEEC08F6 +:10162000FA05F9B6E5E417C48D1B18311E6B532279 +:10163000FC833CE67163DCE802FAE27ED998D34A87 +:10164000841F302EB091CEA18EFB30F2FA847391BC +:10165000FD037DD1A52FFCB1DCA7D12FFCA1F87330 +:10166000B823F197501E89BF244F24FE521644E23E +:1016700027D51B898FF4E52322EEF75B9317D11F43 +:10168000F0C08488E733C18085F7B31E9D16F1FC56 +:10169000E08DB323FA4337DF16F1FC70FF9288FB2D +:1016A000D9DB56FE207A8FAC5F1BF1BC9EDE37344F +:1016B000FE34627C8DDE3EF8FBDFA437730AFF50F8 +:1016C000D03B51D859879BD7AD75196D8FE2797C86 +:1016D0003C3682FACE81E7E963D1FEAB5497E79BB3 +:1016E000C6685FFB97B24742BD940EA8356451BDF2 +:1016F0003CD5F5FDDC6088D867B73BB93F647772AD +:101700003DFE6B133F2F950EFE26D929030BC5D93D +:1017100016AC77648299AC8F639C5DE7E818A63AB3 +:10172000306F07FDC921BDAAE9D1DBCC6A6D07E89E +:10173000975132D793A03FFB39619EF7A5078DDC07 +:10174000FFF019D1FF48B7305F6C1ED919CA433B6F +:1017500058A284E700E2427A5CFD0E887570653617 +:101760009DC37A134140BF5975D17ED3AD9A9E5A1D +:101770003E9CF4D4655BA4FF767969165D3F7BBB24 +:1017800099EA07CE8A3A470D0FFAF3D6DA396CEDAB +:10179000FEF22D9B62D0EF3C2BCEFF6AD7270BFCCD +:1017A0004D76CAC2FE59D6603E6C1118F138C07B26 +:1017B000E5918ED8DB18F99B9370DD555BAEDCFEAE +:1017C0002AF4AB0DC1646E377CF4DEFC77F9B9EE18 +:1017D000F97F8BFCAE408593C7F91562FC5BA0B125 +:1017E000039E6E013A38B07D635219F2275CA7F36D +:1017F00071338F3023CAF32C6F26D54D9C62AE33E4 +:101800007B01C4F94E95E09CCB3C46CC5BBD737B21 +:10181000650C3ED73D9E360E300CFA25EF3A7CC65D +:1018200064CC1B4CE67513309F05AF7B16A53F8C2F +:1018300076499BEF1DE6BD7406E83B9BB9685C6D7D +:101840007C86E9F9303DB57BF9AA8F1260BEB547B9 +:101850000D948F58DB6CA678AD6BE57FED780AEEC2 +:10186000DF91DED10FEDF6FB2BFF3604F9E1D6CD8B +:10187000325381DEAADD7BA7336C5FE5ECD22B31DE +:10188000781FECEED6A7D058BE6CA63AE2F757BE4A +:101890003C24DC8FAD74162EC7F7D8B8EB3BEF585D +:1018A000FCD2F014AAF712FCB442F0D3DA178792F4 +:1018B000BFB536A69B9F787F2BAF1BD1D67146F064 +:1018C000E3CA97BE89F8CEC46EE023D5CCF7C5D461 +:1018D000A160EFDB2EE7D2771F8CDE7F75C2BC2DB7 +:1018E000573F89C5FE9E37FF4AF0B3B9D7072FCAC5 +:1018F000A26F4C687F5A3BEFB9A029211FE90E72F5 +:10190000B601C7BFED772F5EFA00F1D3FCF2D69F88 +:10191000E133D779FE7397967714F6C625F001F672 +:1019200086E28B2E16CDCF9308FF46C11DF92CFA07 +:101930009E874A7CED66C7711FA7B6D5407526B154 +:10194000B8091496AF8B950D9A51725B9CA0AF8528 +:101950009EF97FCEDB2AEAA83E20D21F2A38B43275 +:10196000C20FF2C05FAF7ED033DE5ACC2FE9FDA1AB +:10197000F101C36253DCF7F84587A6F5EA17414049 +:10198000ED96C688AD21F835E8F4F37E2157F53899 +:1019900016E6FF03D1FCFC33980EF47B7F9ACAF560 +:1019A000B72D83F1F36952E7300BE8CB16E7A2C7F6 +:1019B0001F856B96417CDDD8AFA53335F9C47FDD3B +:1019C0007ED7A111A4B7D8B7301BE243E43DF4742D +:1019D0002BC0F3ECF9617227DE0F1CFE6B2CE67D49 +:1019E00077C4AB6F213D824765DAFF89523A4C8E4E +:1019F0005EE2BB57510F029FCAA9DC1E581A797EBE +:101A0000D1A2BA19C60F5176FBA8F0737F8D4E1E76 +:101A10004F561E7EBFBF09E871C9D0169B03E3AFC6 +:101A2000DEBB3B16DDFF0C93F703E4C35567DF1EF7 +:101A300063A7FCCD96FE180FD607F87730462ACC60 +:101A4000A7E4F584A37A332C2601CFE927503BB2D3 +:101A5000297F19F2597580AF13C7C642BEE18D12B6 +:101A6000F53B1B6BE371BCEADF37A7A13CBD9CC40F +:101A7000E3CD97AE66F3F715A6E0F341A74310D385 +:101A80006FC0F8E46511D7745E95E9396DFE918DEC +:101A900085B21DF82127B0F100C5514D6615E91A30 +:101AA000F51CE378688A22B9AF6E99CAD0EE77390F +:101AB000984B82FB3BA2837FA4F36ECD6615F3ADFA +:101AC00051F68D2C1EC6DF21F659870347E179298F +:101AD000EDBA365F54D3D31873203F50DE374AD95E +:101AE000C826DBC2F11C437876A4723EDA111D30A1 +:101AF000609E253898B16709AE109C8CE6D5E01C35 +:101B0000EEC7F3843B4CC1F3786E06E0B223FD8749 +:101B1000330E276B1AAA629E20CAEEA67544D955C9 +:101B2000974FEA0957752EF3A35DFFF943AC5B6E3F +:101B3000518EABA3437D0BC8C08E814CC8F9CF1F1B +:101B40002FC908EF836219177A7FC8AF363E5E3718 +:101B500089E2099F8CF12FB431F1B84E95D6A76078 +:101B60008A298FE301F7DBAD167EBFFB79E06F1B9F +:101B7000F66DFC39579CDD3A4D2239E1F5B8421F2C +:101B8000DC2705CEDF08A4FD2A702057055856BF74 +:101B9000B19FF87495A1E9A99170FFEE28AF2B15BC +:101BA000E67BED43039D6BFDF38B51FE0AC0C7B08E +:101BB0007D5B92DDBDC8877EFC47DE7BE8C974A4EF +:101BC000FF3E49C53C6C973148DF37A96AFACC44DF +:101BD000F50D8D1F53DDD39BA9DE4938CFB8C61A4A +:101BE000DA8F1ECF36D27E74B6380F5EEFE4FAE39A +:101BF000F2E921CFD684E17F492A972F16F40E40CF +:101C0000B96912F2D9827E0AB47B85BFB4B7F5D622 +:101C10002C352C7F58C30EA423BE1F6287A8D5AED7 +:101C200077F9F9B9CAEC772C77B8C3F86F9190F7C8 +:101C300045A9224F96EA9D8DF0AE6AFDC414ABE231 +:101C40003999FAFE6857EAC19FB2F782976EB9D503 +:101C5000C951B51234E1F3D517F8F957A0731D9E99 +:101C60003778F99DC6118BE1FA5EC035D695FACE6C +:101C70009AA9BE72AFD1938ECFD79CF93A17F55679 +:101C8000090201F07CDDBC6A00E20DF8BE281AE50D +:101C90006B17233DA6C9670ECA27BC9F837C5F8054 +:101CA000FDE1A4877798DAF9F9D3BDFCFC29F03D72 +:101CB000C901F0BD1DFD861C3BC801BD3F94E47BFE +:101CC00047BB81CEC9FA408F0FA67ED11CECEF68CE +:101CD0002FB1937C635E3F0FE5347080C6A987D82F +:101CE000044927314FB83FD9E88C25BA69FAF1B0D9 +:101CF00093093BA1C6E17903AB2C47C845983DE465 +:101D00007D612F4FFC2AF0F82FD176B8855D10FE4B +:101D100014F3E6939EBF57D8AAB5AF4F98B91DD616 +:101D2000B9F684DC5D3F8EFE6B40F0C901E1CFA2C5 +:101D30009D5013783D0E5E1FBD99D7D58E71AF298A +:101D4000C6B3CFE3CA371EC47682A7BE18CF3E4FB4 +:101D50005AD07E909F81E6E7D91B0EDC948DFBDE86 +:101D60005D67CD0CF75D1AFE1AFCE34B8087FB5BC9 +:101D700000FFBDD825580EF11F58EC74E6EC79BF72 +:101D80004BD2F4C7A90AE4C7CE0639D40740AA80CB +:101D9000C1B1FFDBD4938FFBA09F95E67E3E15FD7E +:101DA000ED742FB55D27FF9A8CB660EF69EE47356D +:101DB00098DCD9C83F0D0323BF1FA0B54FA61A89D1 +:101DC0000E057D7CBFEB482ACF6F0EF1B1C7908F17 +:101DD000AA1A64BB1FE87EA941769BC01F3AEFF6A2 +:101DE00026E3D99C0BCC77CB44B4F3228ED4BEF738 +:101DF0007217FA2960A7EEFE65EFFB0FAB99F65B51 +:101E00006340BE5AD624B1FF001C2C7F26F2F9D5C0 +:101E1000DAF76A1AB71CC6EF88AD7C4E771FFD153E +:101E2000FA0E46A41F732455F827592C0BFD13E016 +:101E300023D20F46851D3103DFAE48F7EE437BFC0E +:101E4000B2F8BE02E85192C77D4E615744FD417021 +:101E500007AF2B1EBECD2F1BE0FD098A5F467BC559 +:101E6000A0C57D87716E6F197D87C9E73E8DFB3EEA +:101E7000CB853E5CAEF9697EBE3F026637C24FAB92 +:101E800016AB1FCFFCB5B1B8FE6D12C5CBABB645D6 +:101E9000EEA7548BF5AFDE7CF2309ABCCA7ADD7DBA +:101EA000B1FE6ADDFAB57DF3CF5323EBBFAE773FCA +:101EB000E42F46EE37BC2DC6D1EE9BD2B87EAC8265 +:101EC0006520DD56FB65BF9FFB7936FC5ED09D62C9 +:101ED0005D770AFAD33AE1B9CA6D923F803CFE7849 +:101EE000649DE95DF58BCB90AE7A3E5929D6BD7CD9 +:101EF000BB91FC55FCFE0FCA9D9E3F568AF5AFD4A0 +:101F0000ADBFCA2BE9E0E37E744FF8EA6F413A5760 +:101F10006E37B2DEE0D3E8B552E3EB3EE0D5E0D475 +:101F2000E0FEA1F0F64F13F9AD116C04D1A93CE12C +:101F3000BAE8A4F773771D1E41DF5BBB7C6420C544 +:101F4000FB1A1FE8DF2F137EF2D4CDDC6FBCD45810 +:101F50006C1D89F14C9BC125A9149FC58E04BCE45E +:101F600037CBAC02FA5D4D599BF0FB8379270AE62B +:101F700060FC9F7FC240E7EFF61C29A07DE7FCA331 +:101F80008312B228CFEDA2EFE3C038645FBBDAF270 +:101F900036E1F984AEB692021C5782E7D00FC8131F +:101FA00076A2A62DCF1A7EFE7C4C1A8FEFD73B3F30 +:101FB000FD39FAE9537719E99CC55463F04DACDB60 +:101FC000DA7344A17DF2D527963C1485F47D51A2A5 +:101FD0007DF2C3ED6B1317229F3519EDB8EFDDD5F8 +:101FE000F4E30378DFB75DA2EF5E54379766EF80C6 +:101FF0007EDE967C57F8F9B33C874AF0B1542BC586 +:10200000CF53FB19C96E5E4CB3FE16FD9F95EE2DA6 +:1020100024DF17F7EF3151DDDE0E89A1293BEC3CBF +:10202000F80AE2E3E2AB274DE88417379C34757C6D +:102030008F3F70C92FB300C5CD1B4D18C7546ED14B +:10204000FA1D26A49347F84755CF7D4CFD95E8CF60 +:10205000C37C2B9F91A97EF760F36B26E4E7AAED82 +:10206000124BC90CBBBF598AF85EC312C6F960890E +:10207000D03FAB987F7D1A3CB76A23AF5B608F4639 +:10208000D6016BFCBD42F0F7AAEDB3E8FB533DBEB1 +:102090005B8871E30DF81CE7EF659B23EFAF107CC5 +:1020A000BD42C7D73F4913FA67381B8E7CFD75A127 +:1020B0001A9703D7BF3EB972406FE7ECDB84BDD6F9 +:1020C000ECE5E58081EC8DFEB9CEC62B046775DBAF +:1020D0006513FAA7654D5F10FE2B9A5AA97EE46638 +:1020E000E65D8DF8BAB9C96A47B9AEE8E07A685AD0 +:1020F00093D9EF97F07E3DD53977B5F0BA49DF7EB9 +:1021000089FC1C4D8F69DF775C26F0B80C14787A57 +:102110001EFABB3C6EAE1271F28A615B0EE33E7B2F +:1021200095B8BFFAE8C158F40FA7B12F6E47FAC0AF +:102130007C0CE763CF44E27DBAD08BD3B773BDA8E4 +:10214000B76B5DA9D933298F09712AC2B57A7B246F +:10215000BEAB74F1F963693C3FF6820EDF15416650 +:10216000CD413854D9E5A7A7DB159CF7482ED85B9D +:10217000B4936AD6F77E87F14DE1676BFD99E21C57 +:1021800078BD7DA32D3C6E8E4AE7FEC2CAF1B20F28 +:10219000E9D51D6F0C3A98AB1A42F106C419CD6906 +:1021A000493CEEC082923732649698188A371E7185 +:1021B0006EAAC8837EF5762EF79DE3603C3C7FAD2A +:1021C00030F247ABB79BE99C6235D09FE28A267E0E +:1021D0009EC2D3249522DDC15F3F9A86FBB19852FF +:1021E0008575CF6AE47C3FABE40BE297A383F87A72 +:1021F0002F2B6A4A6FFEBBE6B7E3F93035CC7FAFD1 +:102200000239C5E7AB9A783D52C3816FFA67A29E47 +:102210006BFEAFFE8BA1FD5AD845CD2F0C825F38E7 +:1022200090FB45F4BDC9BB857C2DB3F37DBABB855E +:10223000FD61521DF17995B1FE503CFA593B78BDD4 +:1022400000DB871F8503FDF8F64B75F1B0EECE97E6 +:1022500024AA87C3F7F17B949D4BEA3F41BFFBEB78 +:102260001D16F237EF06BF654A5E4FB9D4E45BFB3B +:102270006E560D7B88FCCF87581DB595829F3B1B02 +:102280006BE9FBA09ABF42EF0FECE98F540ABEAF97 +:10229000D4F15F547A24DFD5BC1D4D7E63D751D96C +:1022A0008EFB3180AFDFA485E345F8210D07A288BE +:1022B000AE5D276D6447FE2CF8EDA2C83FD78C9326 +:1022C000090F86F1BCCD6E796D20D211F18EF5F734 +:1022D0002FB7BC36829FFBF613FE576D9323BE0FBC +:1022E0005B591FF9FDD79AB76FA3EF0855EFEF863B +:1022F0006B88293104575F7220493C8E34489171B4 +:1023000064F53ED9135E7706EBB903F551BA900731 +:10231000A6049331FF35009D0680AFA689D3D5D0A2 +:10232000CC5B98FF169E2731D2FC3DEE17F956E3A1 +:10233000FDAF33AD7CFFFAAAAF02FBF70F94A9AE55 +:10234000F3FEB7570E0DD7A30CE104BA561B83C991 +:10235000146F9E34107CD5272F270FB2A15EDA525E +:1023600082DF0F9D2EF4DFE181D6E5C8CF3E9C379A +:102370002534CECB69BC7E8FE17A9DE86DFC928FCF +:102380002BD6FB109B2DE26ACE4F39697CBD108F96 +:102390008C4BEF251EB95EBF13ECC3A98512D63353 +:1023A000293E8C87F7BCC7F5424DF3B28F90DFAB67 +:1023B000DF37539DD7FD2DCB8652BDAFD77B03FAB8 +:1023C0001B5FB7ACB881F283D24304970FE173A2CD +:1023D0005F732619EB522B9BCF2493DDDD3B7A9361 +:1023E0002F06FD97BCE9781DFC09E23FF06B88FFE2 +:1023F000F6B415687E8C15C7AD3CAA78103F95479A +:102400000B8E57A07F71A2A800D5B974A280FC984A +:102410007CF4636C21BFA65B4FA6733FA6AB358AE5 +:10242000F20B121BC8F9870D8AE09FD50DAF93BD43 +:102430005FDD2847D42F6AEFDD99AED038CB34FE6C +:10244000A997DCC41FBB78BBBA710FAD6F95B19E65 +:10245000E85DB3DDC8EFEFE0ADF67D581F8BF721E7 +:102460003E8EE325A0C334933F03F3D3C732B99F15 +:10247000AFA7C7E7E93CFF71ECAC7700F2CBB14204 +:10248000EF507B2F76C2C78A785C2B097C37F073BC +:1024900053FAE73E4B97C4774222CFB76AEDA9744F +:1024A000AE3FA7997AFF2EE06FD2B57309EC3143A6 +:1024B0000146C546FB06E1D7A7867DD761CECD464E +:1024C000F2174E31FBEB58EF3843D3B3E3B87DD569 +:1024D000E7CBE789F73C9B55BE5FA43B3F334F3BBF +:1024E000DFA43BEF364FF83BF374FECED3E9C28F47 +:1024F0001FC286A01EAC17E7EFD60E8FF287E7B398 +:10250000F4ED61B12F82E787B0AD19FE2EE57D8E27 +:10251000B59E7D85EADDCE46B1813CAF47F9EFCA75 +:102520003EF2DF35DD72393782CF34BA5C12DF8399 +:10253000D1D365B7A6AFC4BE5DB4D8B7F31BBDBBDE +:10254000519E2B2D174DBCEE3068427D56339CFBBF +:102550004D974A25DA6F0738FB9BC3F4FBA5541E41 +:102560007FDD7F8B4479D7567C1EE3AC7A89EABC49 +:102570002B03ED26E4A7210D8B1F26B9F5B1D32C33 +:10258000ECBB1A332DDC4E76D34F5B77B71D8BF740 +:10259000717D9C482D3E8F767186B083FA735143CE +:1025A000597B593AC033DF2DB9B01EA02F3ACF5E08 +:1025B00030EA7544C3F5D2BB33DDFB4E3ACA79FB32 +:1025C000E55B308F7A6CF867FDD18E56F5C1C71F79 +:1025D0000B3CEBBF2BE31AAAD6E2F7556A9DDE0E41 +:1025E000D29F866F6347301CA7E3376B25A4132364 +:1025F000FEEF4B7E3E13E37E96CEBF770FB8A77DEE +:102600009755E9BC4EEB98D19F41798A9CEBDBF75B +:10261000AAD9F7462EEAB3CED6A3B9A630BA5E5CE5 +:102620000B7A00ED4AF3C164D516CE7706E237493E +:10263000D2F84F11F632920F2F221FE6607B2676DA +:1026400010EAE35DA76207E3787B79DBCDAF4DFC51 +:102650007BF6101F0D9917130EDFC304DFA57A3E1A +:102660000E631D43E68C0CBF5FDB171F5B33888F47 +:102670003B22F8585B6F3D7ECF07E38016337DCF5A +:1026800007F3D78E3039199AC1F5CF58F1FD9EF175 +:10269000CC47DF391C2BBEE3335E6101251EF7CD2D +:1026A0000232DFF7E5E72DC6087E1EAB045AB18E75 +:1026B00062BCD8E799C0DAE9B9292C48AD9BD9E9C1 +:1026C0001C451173513BCE12988EEE544E7D3DD574 +:1026D00025069215C7798B38AFD10BDD42EB57E851 +:1026E000BB3DC49F329ED7E9FDBB2FB333B8DCD3CB +:1026F000C74590BE9718E5B9F07B6D38C9448595FC +:10270000637DD3648559A201DE5D870C24CF2D1D26 +:10271000AA1FEB535D09E2BDCF19D5E18E75737920 +:10272000459383F518DA7AF5789800E3619E6DACED +:10273000029128E13140F3DDC8F8399242A652FDFA +:10274000736946A6D0F7418AA38A218E427D6FB075 +:10275000F8081FD33354BA8FFB25B130CE848D12C5 +:102760007B0FF73FB2F87AB5F1270023E0F9C2E911 +:1027700019DC9E614AF5BD78BE8F124B05CD2576DA +:10278000FE9DA364FACED1F5E2B52B997FEF32F628 +:10279000CE60E7CF0A42FB492EFCEE516CE83B9B32 +:1027A0002EEDDF830844FE7B1077642CF911F2A331 +:1027B00056AFC7BCFCDF7DD0D7EB85D5E7B10B6149 +:1027C000E7B0B5BA926DFED92A9EF35B9068A1730B +:1027D000BF7996FEF968C7063ABD34FEFBD2F6C152 +:1027E0003498E21FED8909F1BB95B9C721BE437545 +:1027F00083FC3B50DDE7AE92199D57B49A797DE595 +:1028000063201FF81D26902E15EB68D883C5548FC2 +:10281000B9DE6171E1790933C26D0DC15D6B11DF04 +:1028200005B5F07D717D3D68ADCD40DF1DAD65D155 +:10283000740E3D29DABB2E03E0BA2FA688CE776747 +:10284000EF9CE444BF317CFD93B4F51B7AD647C2BC +:102850007A1FC9E8A51E515BA7F6EF76D805FEB42E +:1028600075DBB5734A6E25E29C92868FC7A2F9BAD2 +:102870008DB8F39F45EFAAA837F4EBFDFFDC29BC28 +:1028800016A064000000000000000000000000002E +:102890001F8B080000000000000BB3D36660F851E6 +:1028A0008FC0C19A0C0C5DD2A862B4C41D120C0C6E +:1028B0009780F80B106702EDF5926460F006E26D08 +:1028C00040BC1D88C5A518180280381088FB80FC04 +:1028D0007E204E07E224A81BB30519187281381F09 +:1028E000880B815848808141588078FB8B151918D6 +:1028F0005EAB22F85A6A0C0CC91AF4F3FF60C3816C +:10290000B6F4B5EF16D0BEE56E08BE0490BDC20D9C +:1029100055CD4A37FC66AC42935F8DC65F83477FD7 +:10292000810D2A7FAB292A7FAF3903C3072435DB0A +:102930004CF1BB051D2B00FDA788274C9730A2F258 +:102940002732A1F2F9A17C00BE1E313CA803000091 +:1029500000000000000000001F8B080000000000C5 +:10296000000BED7D0D7854D599F0B93F736726992A +:1029700099DC24433260126E7ED0A001879860B04B +:10298000586E20E147A30E082CB440262888166D07 +:10299000C49FC6DD500609BF0921E14F70D11D104B +:1029A0005DEA63FBC5565B75BB7682D646AB356880 +:1029B000D787767765A015BFBA761BD96D976EBBA2 +:1029C000F57BDFF79CCBCCBD9900FEECB7BBDFF30A +:1029D000C5C7E770EE3D3FEF79CFFB7FDE73C725BC +:1029E000FB59701A631FE31F9413731963B5A9B2DF +:1029F000C5C362D9398CE576488CD530B6B25D89CD +:102A0000CF827F1676B4BC82F5E56D6EC35DCA5881 +:102A1000FF036E7F0DD44F6F57C26EE8DAA8F8A897 +:102A2000BEACCB15761BF07CEB472FE7E3FB8D525A +:102A300098419DB1BB199BCCD81A0FFC13EACB2A45 +:102A4000921DF8FEDD2D523886AF99E99B04EF6F99 +:102A500065FC7DF3038AC664A8EFBBAD894D64ECC9 +:102A6000961E98C5430DD9C7BC3D63058C45F82318 +:102A7000D6B205DE57A6DE4758D7470AF46B8E3923 +:102A80009EEF9BF53E0BE07B2DF51CD6730CFF31C2 +:102A900085B14B993F783A1BFE1D66E18F15281BC7 +:102AA000F2191B9DC297B3640CA01FC5D85CC65C0D +:102AB000AC1CC6A9BDCCC5CA607D161EDB381E97EE +:102AC000354984C7653E46F577E74AF1074BA91FAC +:102AD0009B5E0D253C2FC88332C8CC4228231E960E +:102AE000C806F8E7B65DF61EAE7F034E359ADA27C4 +:102AF00002F07E018BBA18C0F7672C46E56216A774 +:102B0000F2CB2C41702C6543252AD4EF52129B182E +:102B1000CC130E45A7E3FEFEAEFED8BB12BCBFBF72 +:102B20005AAA9D0225F3E5D1BA2FB43E6B7E954596 +:102B3000AEC37118935D113F63E3AD751E66B18A34 +:102B400020637A8F8FD3CB61D6CFA03EBE41D04BCE +:102B5000E3FB7208D6DDF33C0B633D049B3905EAC9 +:102B6000A1AEACF806A8F73C1EAB47BC1C6B01CC71 +:102B700043FF638D6E295A05A54B7745A00CA98CA0 +:102B80002980A7FA86F59202EDE646F938E34D4D25 +:102B9000665742FD704C52C573ECAFEB314987FA72 +:102BA00078A83F28E17BDDC5609C86865C57B20A29 +:102BB000F1DD334687B2E2B0969001BFF5A64ECF65 +:102BC000195B4474355ED0DA5C93F79B7B38CFCFCA +:102BD000E83DFBD3C7D67BC0EF25457CDF8E1D2E9D +:102BE000CB417859D4DEBF4865314F5E0ACF3BD721 +:102BF000C10B770ABFBB0E976D45BC1DEB53C3825B +:102C0000946DE3C3B8BD0DF0FE4C951C560CE4B3B7 +:102C1000220E7F85EED77DA97176AE83F697A5E06B +:102C20006854A6F6133E4C46FC38B706DA57A5DAC8 +:102C30003F81ED018E3D080FF55B73D48BF3441893 +:102C4000CD33123DBCB04EA77E83621DD7FCEF3062 +:102C5000EDD3DC861689CF2BE06BB0C36795167C6D +:102C6000238D7F4CC0658D6FCDF7C4BA10958D4A0A +:102C7000D523F7E2BA8E687C5DF38DC77723FE8E8D +:102C800078C231A83F79DDDF8CB91786B862FAF3D4 +:102C9000973FC370BEE50FDF8EEB7A2E8BD6F5D44F +:102CA00087675EBB910D9FF72D81879F9E9B3F4459 +:102CB000756BFEB9A63446023AAB34A5840BE8E541 +:102CC00058FD571EBED7C07ABF89F2A4D23C664ACF +:102CD000504E846168BF99FAA78F419E554277E4B0 +:102CE000C7490D520BB67BE2C687BE741F3CFAA9DA +:102CF0008BC37DC55F72B82FBB7EED9308EF653740 +:102D0000AEFDF93350BF028520F0DDA537ED5FF34E +:102D100077F0CF6F2CFCCBE57B18C9855836C09176 +:102D20006B4A0CF777D9F7DD36B972EC793FC99564 +:102D300042B33486FCB7AC4F22F9DCDFE866417C55 +:102D4000FF3377DC8DFCF5806452FB67DD71940FF7 +:102D5000C75C8CA13C5E76DC1B477E61AB9691BC68 +:102D60008E58F2DACC5F7A2F8CF76E8325CF399D9F +:102D7000D27B58DFBBE62FB65F0DFDCF98AE308A11 +:102D80004D4B5E38F1FCAEC06FA4BE9CE860999AD2 +:102D9000748533D043739B6293DBF50D2789AE9620 +:102DA00041C9D2F874AEE0B3650DBF10FCA9935CC5 +:102DB00072C2F3466D617126BA3B25E0490A7A7BFF +:102DC00017F7FB32840F7A21DD742971254D4EC32C +:102DD0009F2B3281EA3164E95BB6D8E1B4E4764BEB +:102DE0002CDBA6AF40FEFE0BCACDE6B67CDBF3B90A +:102DF00039AC76EAA793C37F20399C94081ED0BFD4 +:102E0000B4FF91B81447B968EDCF1D627F22158CCD +:102E1000D6F3AB03523C06FBFBAB23627DFBA4B8AD +:102E20002211BD9AA73D382ECC599EDAFFDBC5FE94 +:102E3000A7F68FE3C7C2574ACFE56E4A02082DBEF8 +:102E40004809CA6B8B7F2CFCF6EFF95109EE5F61E4 +:102E50005B69771DC2794021FEFDB0FE6431EEDB77 +:102E6000BB2EC02BF48F1C7E2CC07C29F85B841CED +:102E7000FCA003E8059E4B0867651A9C026E17D6F6 +:102E8000A1DDED0D521FF2E92FC5BC56BF1F6D9994 +:102E90003113F173478FC4103FB71FE95DF6E7B0F8 +:102EA000FED5F1EC304EF1ABC6E2C02500CF8A1E54 +:102EB000FB7E9EDA727300E9E6C3BEFC021CE7F6F5 +:102EC000A9090DE15C9D78553380CE6699BD5A32D3 +:102ED000035D7DD8B72180ED3F547B6EBC06E7D9FA +:102EE000A784D7C3F8AB8F94CE34399D12FDAE16AC +:102EF000F83DA9F6CC1C03F0B57CA39CE4C17B7D16 +:102F0000CAEC7806F9F97549213A58DDE696719DC3 +:102F100023D1CB871D2E96C079D404E173A4761FEC +:102F2000F4B5D0FBFE070A6F40FBEDF67617C98BB0 +:102F3000DBDBDC444FAB1BA4389352FCB642C0BB76 +:102F40007AB742EF4F9A12C90F6BBF6E17F476F241 +:102F5000F055AFA0BE3F03F207E5EE8C8D3FD42EB7 +:102F6000013CACD8C2E5D1C9DDB94BEF413922F4FF +:102F7000E51D62DCDBE28A8D3F56B667DBF623DABD +:102F8000956FAB9F3E927F631DD2759742FAF39681 +:102F90008D8F6921924F767B13396C5241CABE3CAA +:102FA000C186165C23A5E8C9A29F5BDBC0DE0C0CC2 +:102FB000B7375B8E48648F5EB49DD90676E6C4E170 +:102FC00076A6254722689F95A7E4882537EE52A26A +:102FD000638300C7AF5DD1CBF2CB496E3C20D522D5 +:102FE0009DE8BF45BB92C5945A946F172B2F68B1CB +:102FF000161FC1DF7B1D405719E87506D215CC336B +:10300000B3A73F233DCF900C1A2F4537B704886FE5 +:10301000715080A3D96376219C97C0C4DE6A2A9937 +:1030200092C74B15EA9B1166A087536BA5F8A15276 +:10303000DECE87F214E0BA069E37775D1EDF26A14A +:103040005D087FA83FDBB8DD0DED4C7F1E3D3725C9 +:10305000288BDA4B5FC6FDB904048056CDDBE33C18 +:103060006067114AA07DC25D4D5D6301288BA19F01 +:10307000CCFBD37B6C1720391EA7F5E2F8384E85C0 +:10308000125F8372C6A2E36542EE805CAD5481BEDE +:103090009A595618F566735BF979ED971BC276F964 +:1030A00071539D5D0FCC35EDF2FFE6D997D8DA2F3D +:1030B0008894DBDEFFD9A22B6CEF1747AFB2D5BFE8 +:1030C000BCEA0BB6F64B5B67D8FDA49FE6D27AD676 +:1030D00008BE1C09EED785BCFC89C33EB5CAA6EB69 +:1030E00013356FC33EB175EEF0E3509C98C316F5EF +:1030F000A5C9159F2C113E7F036CC2FD833F7D4CFB +:10310000780CF1799BFEC2DD9A89EE34D10FCD2582 +:10311000B4979CED4F2C8679D2FAFD9B24111D9E0D +:10312000EBC73C3DBF04905B80937300F577B264BE +:1031300009EE9B3BD7A0F777C9C902ACFF860DED1E +:10314000CDC7FDF5258B917F9A55F69C9483FDC2E2 +:103150001E37CC07D6106B03FA6869FBD171B4E354 +:103160002423C89660DDE34B207FB30ED787490B3D +:10317000EFC087BDA1E88712C021B5F7FF5EC2F797 +:10318000DF6706EA61962CCA45FF11A74AE7C3A686 +:1031900019AC15F175A2D18E37AF58C7CF2599DA82 +:1031A0003DC7CCDF221F9D9474BE3E01EF36C93C63 +:1031B0008BF35970BF9BAB6BECD3C1ADC8B508F7AF +:1031C0008F08EE0DAD2C99AD8C0CF715CC74CBA3FC +:1031D00086C373969959999ECF0276CDF4FC7237C7 +:1031E000AB447BF58494155E5F8AE5D03F7E0DF895 +:1031F0002AF60D5FF87163385D4C957369FE666160 +:10320000EF16B64B896CB44F9987EC57D6F390E91B +:1032100041B926445C4B9B7412D7CF3A1ACDA427F0 +:10322000B55E66482CBDDDB97D6F73537B4BDE58B0 +:1032300072CBC2A725572CF965E1D539FE48720635 +:10324000C753F310FEE824399D4E74C0C70484C7E9 +:10325000ACC6FDB3F60DDCC898A77AE47DB3E414E0 +:10326000B463E8FF8FB45F8027B2EB5C6146787A85 +:103270003738B4F42958F7401BD7D7EF1631B20FBF +:10328000CFB45D359083F8F1782A103F857C2A56BB +:10329000181C5A87F2D5A726FA11AE42A1BFBC8CE2 +:1032A000EBAF4266ECB81AFDFBF6934BB09DB53F11 +:1032B000B9627F9A617FD01F69F60D15A39DE44620 +:1032C000BD06EDDC2077512E17B6BFFF1FA8170BE8 +:1032D0001D7A112161E9706455EDB8DA481FFFA32A +:1032E0008D685F5AE35287F4FD0F6A2711BF85EDA1 +:1032F0009BEF5602B6F1A58F110F426EA3D9756EE2 +:103300009E52B457E5843B90A20B275C56BF91E8D0 +:1033100084A5CF536EAB933DE1ACBBC39A4D3EBF8A +:10332000FBC7F29C56DF79E8CD399E93BE9D7C2089 +:10333000F0F029E87413A7532E172CBEFDCFA2D3AB +:10334000A8B5AFB1DC3B8EA07EEDD2C2B30CB413F6 +:10335000867EC8ED04B77108E92C266555C2FB6866 +:10336000874A76A36557F4AFFDEB2D65F0FC44ADBD +:103370004C7EC489F59CEEF73CC0ED514B6F478500 +:10338000DE46BB00F10A76C3809B971E1CC7BFFEBA +:10339000E65209E0F61843FD6E6CDF6690BD9A5365 +:1033A00017D71BA18C571CF28C3352722919CBCF23 +:1033B0005B0EFBF5AD5C635984ECEBE8E8B9FED439 +:1033C000FB1FCB5C3F4D2B6179B361BCE45639FCEC +:1033D00020F44FBAEC7ACC2AD7285C5F26BDAC0427 +:1033E000FDE091DA0D29965ED535DA97F903C771BC +:1033F0009F46DA07D8019DE298E7E890E31DE6A131 +:10340000F1937EBB1E3A29F49005FF27D0AB0B8BBE +:10341000813EF64A99E1FE488C177D0E0080FD8EB4 +:10342000AACCCCD4CEB9EE7F10FD12B24AF3EDA8EF +:10343000D8391BF73B1653C2E9FB61957FA170FD9C +:103440009933B721B711DAB1F599DBE589768FDDCC +:1034500097B508FD2B409D8AF19A504C9F371BE38E +:103460009153F326A18FFD63D43F30EFEEC819BD11 +:10347000C5F789F051105246C6C79BB2CCF7D1C1EF +:10348000B77BC05D43F999943C147F6989B933F2E5 +:10349000B125A79CF2C8A9E724D3646DD5C3E58AFA +:1034A00035EE27D567201FB2945129BBFD9C3EBB4A +:1034B000587A1C410E94C82CDA97C13FBD5AE17866 +:1034C000EA8FF138856ACAA4B7662A4D4C023C6D72 +:1034D0000832920779B8D7C8B70D2C0E2860F92C9E +:1034E0003CE0437912945982FC56A71F6836A11F0D +:1034F00018E4A0317D54597F213C0FCE5F49E70C81 +:103500002CC2E5AD0EFF713E32495FB8055EA3B136 +:103510004914E7CC6BB2CB7137FA81201FF506C78F +:10352000F3F933E9BCC1CDD29EC33AAE52FCC1D34C +:1035300060DAB36A5683FC59BDFFAA5D8B61FC9AC1 +:10354000476E7E1BCBC907EFC9FF1294758FEFBA88 +:1035500019CB92D7A26333C553AD123885C9750014 +:103560009F8F19EE9C91DB19EB9508DAD5B08F1D72 +:10357000480FC9587916D2F72A85F37FFF022D80AC +:10358000F119750B97ABEA7C401ED13FF7D39B53E3 +:10359000FE34F915AAF093947685E20849BD8CE2D1 +:1035A0002D87B6C81A96206763388F357FAF88534A +:1035B000778A78AB13BEDE92A162948327D67F44CC +:1035C000F6A1A2678567C37C5D7E5642708878410C +:1035D000B3D8BFE4DA7A4F7ABC48117E4EC7D139EE +:1035E0000306D2C18012F61AC4371A8E1BDD329D33 +:1035F00061FC65961E66684F740ABF47F1990CF727 +:10360000355B6733D1AF85575A08FB57B17002FB62 +:10361000B7F7236E61BDE6EDC8073FB896DB2127FB +:103620004AED721B48A80BF694CD2A5AAF226D368C +:1036300005275D8534FF7BA540C8554EAF6FD44E3E +:10364000796C1BD0C1736EF31E65D427E023875CB1 +:10365000FF01B009EEDBA3925D9E5BE541271FB53C +:10366000496417AA265FE74CE5C346D4931BC16E95 +:103670002C3486F3CBC6D719D98D1B81FF62A5994F +:10368000F8A75A421971B1FC93D79E2B611CE3B382 +:10369000F2CF5F2AE29C4EF00FD05902ED984725F9 +:1036A000A3730AACEF3BFB1A7F3C055E3F7B604592 +:1036B000F635507E2FBEF1FA6B60FEDB1FDF938D77 +:1036C000FBFCE8ABC04FE7F1E32D7E6A461BF63CFE +:1036D000713663AD9D9F8CF515C44F6F295C7FF5E6 +:1036E0002FF8DD1B57FF7F7E3A1F3FBDAD007D4E9B +:1036F000FBD3D9E2E879E45B7311D3D0DE823626BE +:10370000D27934682F7D6A16E17B9D8BCB31BFCB9C +:10371000CBED8E107FEF1CEF6FD44F1E3F5850FE45 +:10372000D9F9749DCFFCE8F3E077903B246F4E8C81 +:10373000B3F37DA78BD3DDAF5C9F787DEF7CE17326 +:10374000581FD8F564DF5DA73203FD80892F7848C4 +:1037500058BC3A6EE311648969F03C94C7DFBBF34F +:10376000485EC6D18E19522AA9BFC9B81DDF54B30D +:10377000F9083F9718AC5804FEF21CF817DA23D763 +:10378000F9B85F01E3B0108CBFDA1B2D5647D17832 +:10379000E45FBEFAFCBE20CA97D73D66093E674982 +:1037A0003517CF072CBB63647E57D9E9343FEB69EB +:1037B0008D111CA72ED5285E89622C00F5ADA5972A +:1037C000529C928563C725AC8FD219CA71251859AE +:1037D0004C76489BDB9805F5AD6040C58244B72424 +:1037E0003795F6DE5000E500D825F85E8DCDF568FA +:1037F000E8BF8C923108CDDC6D1F91DF7DA298CBA4 +:10380000DB8E298CCE69061EF8B7A532DA3BED6E49 +:103810003AB700BB91F8352AE44632383DD4827E6F +:1038200046911696A0BE29F68BE35FE3F2C4F44CF2 +:103830004E8F8FF078474B88FBBB4EBB6FF3D72F73 +:103840007BD3C0F17EF85AD7E550BEFEE4CF5FBF10 +:103850001CDEBDF1ADD76A30EEEDAED36C714737EB +:1038600033DE447B0B7CA68486F2397672096E6661 +:10387000CAAF9362889F688D3F8EEB45DE46FC247D +:10388000A728FC7C11FE42005F40C0D71D3C554577 +:10389000F3C4DEFF8F4CF29EFE260B3D02ED36E7B1 +:1038A000DD1F4739929A6F12C9A728C827F423A3AE +:1038B000BE9E256B683E7FF841ECF347D8D5C9A979 +:1038C000F3C2435BE6B5209EE72EF0E84867EED8EA +:1038D000E6BB91CE9DEB3CE37BF0520CCDD9E607E5 +:1038E0003E715768A697EC5F7698F64334B1E0D600 +:1038F000418160DC01FA2F5BC132F437A03FAE1387 +:10390000E419DADB563F206313D77BC637FD528AB2 +:10391000F78B7885D5EFA69844E7043795031B9479 +:103920000FC7D3069FFC93AFE1B94B4CD1154E079F +:10393000A18A34BCE19F3D6EC6E9E2B27D76BD0B43 +:10394000F32F2CC5F73185E8C5C92FE3E3F6F61B45 +:103950007CE73FD71FBE9F1CCF1305BF59FD2DF835 +:10396000085E29537CDD7E2E73539DBD3E77183E45 +:10397000CE0FD774D57E6ED3E0B38F3733687F3FD9 +:10398000BBC85EDF80F19B4FB26E07DF3D3DC6FCDA +:103990008EFA19FC7A4BEEBEEF89FC2D8DA38619A9 +:1039A0008ED3BF60EFFC794007853AB73B0AE72F1B +:1039B0006CC8AD4139C5449E4966FBA350E87BA560 +:1039C000FD252507FD5193B74F2E796B460E9E17A7 +:1039D000D7313A4F8FAAF7C4728C943DD2AF966715 +:1039E000219E3F7F7BE46E6F7ADE4DCA1E79E055E3 +:1039F000A326833DA2DE239930CEAC25608F54A54B +:103A0000DB23AD12CAA0EC25608F90DD117D0FF194 +:103A100035925DF263CBBEF767B6ABFFA0723D0B8C +:103A20007AE69F3E8B9E19E735FF45FD1CEC8169C8 +:103A300025C6CA48063AFC40E5F10E4B7F36061310 +:103A40000A9E9D83DE545DF0FCDABAE44B288E3B7F +:103A5000F49D415C37ACC7E5AAFDF4EB39A372785D +:103A600026AA3C0F66A47EDF1AC15FF16A5E61B7C9 +:103A7000D8F7BB7FC13BBA8CFE0BF831E8BF247D81 +:103A800065DB302E7826A652BC4E9DBF72F75CA433 +:103A900027B0B3393D9FDFBEBE7648B6F1F1B4B36F +:103AA0005936BEAF67F673BA191EFB395DA36E3F78 +:103AB000A79B15B29FD3CD31ECE774D757DACFE986 +:103AC0009CF6FDCCD1AEFF9EF67DA891113F5DC066 +:103AD000BE077EBA09E969247EBA2EDFB83F92613B +:103AE000BFAB356EA7AEF6461620DD4D33B85D1779 +:103AF0008DADA77CC0BC28C89B528A1B52DCCB8AE8 +:103B00006B59712F2B2FD08A6739E35756DCCB8A3C +:103B10006349311EB76AF6445720BCCDED27659442 +:103B200023FA73300F3282758E372C3EC7E5414B36 +:103B30007BE6B89C33FE3662BB4FC9579F837E58E5 +:103B40008FEBB5F403F0F9839F85CF416E6DC3F120 +:103B5000FE05F97D14C9936EDABF0AC035DAE9B003 +:103B60000F1AC6E9179CDE8FF138F5B89BF8F6629C +:103B7000FD5F4C749061D3A2E083633C2B1A2B252C +:103B8000FD62F18DC5274EFF78187FFC57F3CF45B6 +:103B9000FAC7C03FDF739D471F017F3C8FF89E56D9 +:103BA000C9F1EBE4078BFE8124125235EE773481A4 +:103BB000ED2D7A672F864D8473A2F06B4E8CD6C89C +:103BC000BF38F1FCBFF373D8E73DE171628DF87E39 +:103BD0006277417C5B698ACF2C7E6AF7447FEC4A2E +:103BE000CB03B1F21D0F7BCCD7F17948ED4BA0BFD1 +:103BF000129ACDC21B0CE2B363FC39E7535F9851B4 +:103C0000FCF433FB657B5D713C1F6A91869632F252 +:103C10005B99867CAB0A79F26256F424E2B3797A36 +:103C2000A484D3D3D0381FC0F58B0E85FCB5CFCA82 +:103C30004FCD23E1FF1C3EA243AEDAE1F901E97268 +:103C40000BE55B28A4C5374819E495C0579C85C788 +:103C5000E0FA603FFF1DF19857C5245A8EE0E366F5 +:103C60008FF907D767B33F14AD36C5C780378F8646 +:103C700072B11AF0563E1C6F275D7CFD4EFA0BA9FF +:103C80004919E93F0472748394764E2AF062AD6755 +:103C900024F96CD169DA7943484B5FEFFFA372D9FD +:103CA0009297977BA293711FDC6644C83F93F6D727 +:103CB000296786DB41329D339E01BB07BB5DAC7C2F +:103CC0009D76D68B87256CEA5985CA6BCFD2E109E0 +:103CD000FBE2D96C2ACDB3F954D69FCDA572FAD99F +:103CE0004BA89C717634950D67011830711ACF96E8 +:103CF0005239F3EC1554CE3A3B9ECAD967AFA2763F +:103D000073CE4EA2F2BAB35FA0F2FAB353A874DA3C +:103D10003FC67A95E4B725BF2CF9EE94DF96FCFBFD +:103D2000BF26BF630D1765FF80FEFBAA761EF93D17 +:103D300092BC00BEBE4F4B971329FD7CBFF619F80D +:103D4000FAB8E053E0DFF7300EE3012F8EE2546162 +:103D50001EA70A189A81791AFBB0096CA9BF3472A0 +:103D600012E306CD0B3C7A0CE01E28D5483E6D0BC5 +:103D70006A74EEB659D2477379904C20FDED0C6908 +:103D800034DEB63F2A5ECC5F7869544100E7E9F63D +:103D9000CB3AB6FF566E72DF2D788E3F85850FC108 +:103DA000782BF6ECF1A4FBE1FBD13800F802B1A7C7 +:103DB0001903BEDE38EA774B713EDF5446F118280E +:103DC000CD4CF962DF748BF36975288478DAEA9355 +:103DD000491F74EB1E91879A1C68413FB74E66DB02 +:103DE00060DE0DA3DFD98260ABE3CA7694417D67C4 +:103DF0005D991737E9E9573E08913D01EF10142806 +:103E000013A23473607F3ABD61E37CE76D8A31B4FD +:103E10000E8915FBBBAB476EB7C93F1042FAE89855 +:103E200034B9F21698BF7752C1689C7F7BCD511B85 +:103E30003E14DD1E4F5130E0887E785D92E26A1BB1 +:103E400064634719AC2F20F2AD01CCCA485ADE8119 +:103E5000058712867570B8120A5F0F2B80E7B97557 +:103E6000895892AFD7C4B8ABCF970CA1BFA8D49D47 +:103E7000A6785BA73FB988EA0E38ACF17FAB5979D9 +:103E8000019C6F7C826F9A277D7B11E5915769B405 +:103E90006FDDAEA105588FAD75B1C733C46F36085D +:103EA0007EDE5679FEB88CEAB3C3D1EDB5FB8B1636 +:103EB0003CEF8BD20947B36B6854A6FDFBB4F35FAC +:103EC00068DD9FF77C9D23E40F5CEEB6EF4340C8AE +:103ED000F3E629DF0EE1B9B8054FA704FB50F3F96B +:103EE000EF43F3142EAF3FEFF5FE4F1BF7F71A8F9A +:103EF000AB009FCE2EC738E398C9218CD7FAAC7897 +:103F000074384EF949018C47532F83F490AAF3314A +:103F1000149525900FE5EC0F13B84F4AB566282489 +:103F20006733EFBB12DE44796D4EFEB4E0A6BFC925 +:103F3000C274A0F343AF159F36D4C9FCBE04C67F3C +:103F400015669DCFF2F8B4D55FAD90291E4D81EC7A +:103F5000B47154D0C3788EA3609C3A6FF8FCDF4DE7 +:103F6000D1A37DFE221E1F5754EE07BE27717CC4CD +:103F70005E5528DFB3EB792EDFD87146F2BBABD6A6 +:103F8000A073951DF03FFA0FB15A5F1CE95671E41A +:103F9000E39DA99C1E42396AC5C5693E7E3E4071BB +:103FA0006ECC53A4B8B9C12AF07DB700CD1A47B57D +:103FB000E2F2956B26613BBFC13CCFC1FAFC752C88 +:103FC0007109C01B74B76EBDBC34433CBC72CD37A5 +:103FD0009E8479773F35FD574F427D971C7EB50E05 +:103FE000DAE57FB98EF0EA8C876FAB944D1DE583DF +:103FF000CF7708F7156C68A28B5B7BA4183ECFF6D1 +:10400000F90EF2FD6E0D298817D0938817AF332F64 +:10401000321DDF6508C7CE8179F06FEFD679CB709E +:104020005E841BF32B57F4D66BA867824BECE71723 +:10403000FE267BDD5B658773ABD8BF0BD1BF330F2B +:10404000B1C79CB708E9F64C5063286F36AEBDFA8D +:104050004692FBDB1536AE3403FD3AD6D5A9B948F6 +:10406000FF771BF57B2B506F346894D7D31DF7C6B1 +:1040700031C57B7B5DEADCC466BF1B1A3FC7AA91D2 +:1040800013EE4C76BC381F0B8867CC710ED63D5BA7 +:1040900026BBA6BB87CF638DD75DF79607E5C448DF +:1040A000E33E3DC63CE2467B2A9A7751F72EEEDB93 +:1040B000E8E2743D458B4BA5688FEA0B17417DF311 +:1040C0003899EC2126FCBFEE6BF979E2C39A61BB0B +:1040D0005FB169CA4AB21B6E72EB82BFC02E9C9060 +:1040E000BA6F71C06BBEE086E7EA733012D803EF97 +:1040F000E5866F44BA680C7E4476D4AD45B28EF442 +:10410000B5624F23AD6BB32EB304DABD6A2B19A988 +:104110004DACD5C4F3004CD444BA9B036F64BA17BA +:10412000913CD40970CE195738691BD4DC45AD9445 +:10413000C7D26848E4875D07984179D0521C51A5E1 +:104140002AEC37FF1DB4FBE6044B65F4F7AF535977 +:104150008396669F835D7CCC9DB6AE13E3F604E543 +:104160002A9C1FE6C1F91779E83E811BEDE32B532A +:10417000F6F14444649A9DFC6B342A319E5194F8C4 +:104180003DE5797F3F29E3BCEC0556BD4DFAE47E61 +:1041900035F897BFC4FD8C33A31F530D3F6B5CE212 +:1041A000EB9AD827716FE5B027F21B1CDF8A074C0A +:1041B000D4F8FDE6CD2D2C1C4B8BAB6C7EFECF8F47 +:1041C000A3BD6AC55FCEE5DD09382DB837492C8B14 +:1041D000F4BC27FA0777BA5FCC926573277C7E70B0 +:1041E00067C897F3D5023F8D15FC93575BE145B93E +:1041F0003916F37D701FDAB93C31E1BFF47C1F45FD +:10420000305F30DCDA2F1BC3E59222EE4D015D4BAF +:1042100068C73AF38114CCFB99385C6E1C10F47FAC +:104220008947E4FF4C6693B91F6E3FBFF22FE57AD2 +:104230009FB5E665BC87FA7DA1F75F147E6542DC19 +:104240006B3C2AEE2DBEBCCE203FEF957595540EEB +:10425000AC0BD3F3D7D6D55199BA5FC5E7CD177656 +:10426000988A41353CE7F7B1B801F0FA47AD192813 +:10427000453EAFE3F7BBBB9B4E6D2927BB919F5BD0 +:104280006C2EAA4E14A2FF02B0E643DDE5EBF3F07C +:104290007B5EE6606501577388F7FFEAF30A275DE6 +:1042A000E8D6FE3BF6DBC75A19CABB8069DFEFECE4 +:1042B000B0D3BFE1FBEF2ABAB87DEFC57FC03E7E29 +:1042C000C9DAF7ABD9D5FCFB0C17278F918F2A855C +:1042D0001C1803FC7400FC79B7C2F3D5F3799EABCC +:1042E00019E2FC66AABC1E1B2FDABB3809B1813C5F +:1042F0009ED75ECCCF13A81FE695E37B0C4BBEC0C8 +:10430000E35B2C47E4BF8F15E3AC16E34EACA67B12 +:10431000BBFCFC9FF5E958FA5892EAB9C007580669 +:1043200059AB84C81CC306C9DF2E9686A86E487A8E +:1043300016D6CBA47019F7C3E3A43FCB15F3DB1556 +:1043400084FC88CCE345C9C5644F825E46B91857E2 +:10435000238B50BE6C68D3C28089737972787F0ECC +:10436000CB0D7D350378FE118BC9247F94E75896D9 +:104370007E25D97BA4BF36ACCF3B984DF91A49CAEC +:1043800073DFEF29B5E9A989BE85D7E9B05F1B4581 +:104390003E9D0BFAB30CF9A7563E1D8C5B92E9BD0E +:1043A000556EF46B8B32F9FD0F7B2411CF488EA62E +:1043B00038A0D8D7F85439E37DC67D1E6ED73C5A55 +:1043C0009AD99E66EC411A6FBF47778C9B6CA1FB14 +:1043D000333A8F6F64B94CCAAFD9D8C6EFE95BF8EE +:1043E0001B0D762DDAC31BFBE6CF46FE8E55AA9435 +:1043F0006F0EEBF721FE5C222F79E3F8E0C16C1E13 +:1044000097284539DD8FF8AB4DC35F706513E2AF78 +:10441000E3559EDF0BFADCC732E41B5AF873F9D878 +:104420001733BDB7CA8E51DAA24CF7868F7A2C3B70 +:104430003D59CAE984E32FEB5A3592A97D42E0BB8E +:10444000A48C45CF87BF7E8F6E1BD73AF755468821 +:104450007749BE04C5B9266ADCCED8B098E375C3E7 +:10446000F3D71C8FA69D43FC12879C928A075B7131 +:10447000634B6FB67BA2FFE81995D297ECFB8CE4F7 +:104480002E7BC17310F72DC339C4294F6D867388F5 +:104490009E8BFBBECB58C1B787B61C9D87F3FC55DE +:1044A0001D23FB2AF00C9F37576771B914BF536067 +:1044B0004A1867B926A2D7A3FDE66A6726E6CF8C1D +:1044C00015719BC2F63E05E922087B5928E1BDA67D +:1044D000640CBF67327637233F512D9CB96ABD21EA +:1044E00044695A7E94C286FA697DED9AF1782981F1 +:1044F000F553D40F63C4FB40FBCC5FA1DC1C1389D4 +:10450000521E2EF48BF9D1BE10782CF072BE5DDEF7 +:10451000109624681F0C26293EE994EB63003F9710 +:10452000A4D96F015167ABB89C96E13FD4F3F91160 +:10453000BBDC1EE7B8171D70E4BDE47A45BEBB25A1 +:10454000B78BF8A64E5007E54C7E794ABF3AE04358 +:1045500019569DEA1FB0EA9F113E2004A2670B1E68 +:10456000BC4A8972778F4BFFCA53A89FEB359E4791 +:1045700026EECB650BBCFBD061867603535E3171B2 +:104580005F7784F97769CE4C9D477E68769D759FED +:104590008EDF5786328671BA6C31BF75AF2E9B198C +:1045A0006F96033D649B49BA57A75BDF55305902AC +:1045B000F370749F4C7974BA2F42F2A9678147C790 +:1045C000EF7C68E29E9E4BDC1FCF364FD3FDBAECEA +:1045D00061EBE3F7EB2CB8B3B3AADE2C376CF3AC8A +:1045E000C7F836AC7D74C6FB7575DC4FCA36791CCE +:1045F000226D7CBA5FB7636A99ED7E1DCD837E9C88 +:10460000A03FEB9E9D13AE73FD6A32DB6913C27649 +:104610003BE242F7EB5C217BFB1D17C8CFFAC4F7E6 +:10462000EB041E86B573D8832ECB0E1D2533DCBF5D +:10463000330D327D4724F7A3646486447109D2F7B1 +:10464000969D97C787FA6F67E7E55979FD0E3BCFCF +:10465000B2DF7267DBF1EDB4FBDC5511EA73B176C2 +:10466000DE2EFC07D0CB435E879DD794993E9CF20B +:10467000229F0DEEBE12C6395AFB2305F3D576E50F +:10468000F2EF1FB161FEC15B33685F7CFC7B47BB0F +:10469000A6F4ABF8FD9BDF2D656427597104B78044 +:1046A000795791BC9EC2EE5D0F117E82020F4DF8CC +:1046B00001B21AC2557C1CF199E9C5BC85FC26469D +:1046C0008D0A2BC2B4EFF85902992E6DC554D4E36C +:1046D000F58895343CCDF0D8BF13D0A8E73BF6D190 +:1046E000BECFE7CEC11FE4DF539863D8F7DDF29366 +:1046F000D09CC5F9AEAFB4D3C1092932A84097A761 +:10470000B34A85FD33A8A3BEEC5EEB22BBF1A12525 +:10471000655BAF447F3528EBFC3872681CDA47CD07 +:10472000474D2FDA79DB23D3BDE3E0FD431D4A1863 +:10473000CDC3A796AC7915EBB1DD2EB2839EEA9B73 +:1047400057B0228DEF36EF5EB07031BEEF70917EC4 +:104750005FB1E7BE81D220F677D5A67F6FAA65E369 +:104760007D3AFA6D6FD47A33DA31576771BB64A33F +:1047700096A4F8D3C6791A43976B6349FDE8156888 +:104780003F5CA365BC4F7E57969BDFE773B54A2815 +:10479000DF0BA399EF0558EDC6D6FC96CE3182B358 +:1047A00065867E9CEBFA7932D61F827DD5A5143DB5 +:1047B000E5097ADA5874EFD60A5CDF40E67B875663 +:1047C000B9366B1CA7D3889DCF5D854DA371DD2EB7 +:1047D0007764A01E89AB50D6312EE272B7466E4682 +:1047E0007BF46A175238DBDCF1C38645B82F614988 +:1047F00097609EA01A59457416CC62A80F1A964469 +:104800005A112F85A0FF30B45758F44B3AA728AC63 +:10481000D39817EA9E253D0917BCF75444AF42BC14 +:10482000BFB4967FE7A530E8A37B4185117E0E5784 +:10483000D8EE6668326C0417D845FE814471222791 +:104840001F59EB6A5ECAE5F8EEB5BF1D95E97B33EB +:104850001559658457AF615FB707F52E8C33D51CAA +:104860005C42F8AE71B338F1AF9BE87B57AD8BE09B +:10487000DA35E5E45710AEDFFD3E8BF6FB5A664AAB +:104880000857FE103F67B5E6C96F1A54783C9CF391 +:10489000A193EF2C7E70C2B773F63C3A8FDBCC0647 +:1048A000E723BE636765A2A3CD456BBCE971D15612 +:1048B000417FB00F245F623AA3FD56FE95ADC77CE1 +:1048C000D88D5F8C54227FBCEDE5F756EF5BAAD103 +:1048D0003A1E9AAB51BCF1217F2BD1FDA98DAEF0D0 +:1048E000210447D517E27EEE2EAE0863BCEDEFF053 +:1048F000F039CD3FD83DEA4B9588CF2FFE218B8FE5 +:104900003345B5C6F919D17BAD97E09CA1B4FF6CD6 +:1049100005DAA14BE4C9943BBD6A09C92F9790E31E +:104920002F2FC9AB473F2570C372C6E5218F5304B3 +:10493000D656F3FB0C0EB99FA85377CFA05DE2F1DA +:104940009F7A21EFC6DE30BD1ED7592FF482A966AB +:10495000FE2E63AE685F381441936C58FC2757E80D +:104960008FB1BB1DCF855EC81D16071FACB819E4FB +:10497000CF97B2841D3942DC67D79279C40F678024 +:104980001F282E5D7292E83F067202EDE637A4649E +:104990006845DA7998F59DB99F887850C42CA53C74 +:1049A000E1B7443CE8A7E2BB73EF8878D071110F00 +:1049B000FAB98807FD03C683F0FB61DECB69DFC669 +:1049C000D57DD48F719C9D350B3C068C33551F7C57 +:1049D0000981FCA239E813F9F7046FD0D24373CFF1 +:1049E0001FA74A205C6E8C4B71385F16DFA37B4596 +:1049F000C03520E07A4DC065E941941B48676CAC36 +:104A0000AA67928741B555C2F35E9417FD4192178C +:104A10003C4F3CB84632260C971330DEE8743BDD41 +:104A2000A2BF53A37C44C7CEF11FCDE2F70E5F5A5D +:104A30003B6B3F0BA6C9A3C8C2554877F9B03F28C6 +:104A40008FA24D5C8E47F1DE459A5CB5E269B023DA +:104A500061D23B37703C8D245F2E24570A1D72654E +:104A600037CA15A8EF46B9124C972BADFDB8EE200A +:104A7000CA1596D243C1C827932B3FF396D9E22497 +:104A8000967CB91AD898ECC430E853FFA7D7A76F23 +:104A90000B397121BD6AE57F044C467A7D0FE685AE +:104AA000A03F339ED13D1CC51CA47CA2DC7617C35D +:104AB0007C90ADD86534FA330B291F64C77C8F8E88 +:104AC00074F1B09408213EF7493D5EBE2F7A3FDA7B +:104AD0000BDB26F038C98E3FDEE3453BFBA5DB0B45 +:104AE00002788ED39B6BE581E88B6F85FAA94646E9 +:104AF00074B262CF0A5BDEC3CFB3F2081FB9319044 +:104B00003F808F876FE7FA4737781E089419F34084 +:104B1000DC3E110F526321A48F6D52D4437198462D +:104B200099F4546F98E7AFF4825F8EE783BD0D3B35 +:104B3000E7A07EDE70ABCC285FBCB2E71E94331DCD +:104B400013161AC897AED1656FA239BEC1277BD3A1 +:104B5000F348F13841ABE6E786A2347300E4CD5E5A +:104B6000D338DFFD5155F87DD8DF7D9E3CF8CEDC93 +:104B7000D0688C13F4362E0CE1BCBDA322A13CCA34 +:104B80004F1943F6C0C6519B1663FCA963B9C6D240 +:104B9000EDA461F305EDF6B51567541B78FE488763 +:104BA000CCFDCB5C713E0D7C5589784B5F27C2A94B +:104BB0009A3C7F04D7ABF0F5D2F74D731BC03FACE6 +:104BC000E2EB47FF55F7E9A3517EA80D3C7F64B3A4 +:104BD0005F5F8C7EA3130E6BFC6BB3259B7FA45B86 +:104BE000790BF56BF8396211CF5BE8759D3F6FA1CA +:104BF00043C843CB6F1C091F2EC73975AFD71E079B +:104C0000B4E0B952944E3846CA17F8B4F35F68DD81 +:104C10009FF77C23E511ACC9966CF72B72AD7C969F +:104C2000C635219413163C9B2F903FF269E16A6EC2 +:104C3000E4ED3FEFF5FE4F1BB73E9BEB47E0D301A2 +:104C4000BC47D931716608E5502A1E3334508EF6C0 +:104C50009CB8CF68E58FB874FE4F55E5DFB993B3C4 +:104C60008BE83BCBEA749E3F427F19F240363136E7 +:104C70001BFD1D55C46F9C7C7A21F89D792337FB61 +:104C800084DF1875CC27F2449823EF440DF1FC1211 +:104C90002B9FA44B82F50553F92023CEEBC0DB7884 +:104CA00021F7DF73F41FB6EE30BF5F69E59F0CCBD1 +:104CB00023992AEFC72D18964722F2517A728D3820 +:104CC000CF13E77925A836319E372C8F64EAF4108C +:104CD0007E53725A89E87703A3EFEFF67879BD77B0 +:104CE0000E8BE3F7CE7AB18EFC54CB28AF65587E9D +:104CF000C9D43584278D4596F1F31D7EDE6FE1C161 +:104D0000995F72417ABB401E49D0677D8F2242F382 +:104D1000F4F8C33FA923F8643A8F2FF8D2F170FA60 +:104D2000F897F8B89CEC1179783DB9F67CBCFBC4D7 +:104D3000BE548876CEFDD58B385D77D5EB1477776A +:104D400037F078E5B0EF40D4D8FD01673CEF8490B0 +:104D5000D7175ABF33AEB76D84FB660B7C3C8FEB25 +:104D6000A12587282FF6CC2AD0B380AF87319FA505 +:104D7000E6E2F3595ECFE2F92CBD46FDC24B518FFE +:104D8000453586F2B417F359E0FD868611F2594491 +:104D90003CD18A8F8E94CF927BEE3CDE9ECFD27B2D +:104DA0002BCF67E9EDE1F358E3F53654939D35D207 +:104DB000B84F8F31651FEE7FC5C59D9F4E2B89FC77 +:104DC00019E6AFF4946AFA8306D20BA7E7AE468DD4 +:104DD000E8BBCBC5FDD8D868EE3733351E5A086D11 +:104DE000B6F8138B289E2CF2327AC5FDF9BFCF326C +:104DF0006CF67167E3774368D7031DBEAC733EA1C1 +:104E000071F2D5D2F5600332B7DE62A24F3990CD90 +:104E1000E308AED0B181BA343ADD22F41DE2470690 +:104E2000FCE44AE7F015950B28BA4F7F6B047DBE72 +:104E300091CDE7B7E890A993C2FCFC8F55A01CB1B7 +:104E4000FCD761ED3CBCDD30F9E390233D98DF8673 +:104E5000154B9EDC60C9133B5D5AF28339E4CC39B3 +:104E6000793287DBE9E7E409C80FFCD499530EF5E2 +:104E70007AB9BEB0E071A3600639F29E2B6C8BD379 +:104E800038E5CE85F8E8F3963B2F65E70BFB83CB3F +:104E90009D20D206F24DB6758EC8EF3D9C99FA2042 +:104EA000C9438FCAD7ED8930FA9D00ACA33CF7E027 +:104EB000394A46B95E2D51BC419C8BE48BEF0F3EC5 +:104EC000EC0A537EDAC3C0CFE8E74D309CF6D9F93F +:104ED000CF159CE7490FAFFD1AF7CF00DFE8775DEC +:104EE000AC1CB2E4C487D97CDDE7E8CBE4705AF4AB +:104EF0009546CFF47D018B7EAD712D3A66C8A00535 +:104F0000E7A15741D7188EA638754C8A631CC4CACE +:104F100023B3C67BC3C7ED9191EE5759EDBE63F93C +:104F20005DE7E2C17A40A77CB21EBA6FCEBA38FD07 +:104F3000CD61BBD53555944FA032CA278894A03F88 +:104F400073D867F78BAD7CB06925E110CA890DC2B3 +:104F50004EB7F2C8ACBCB4C3BE5CEB9CD9969FB64E +:104F60006184FBD96F9EC3CFC57FFF04BFDBB6DA78 +:104F70006B3E8E7211F0658AEF39511E9A35EE77CD +:104F8000059E5EF7984FFA3EC3FDC917B3EC7957FB +:104F90009D3EC31117E0789DA8C7EAE93E5E94DF05 +:104FA000AB729EAB8F74FFD5796FEFDCFD5771FE4E +:104FB000DEEC89BE4CF0BFC8F3DFF470F46027FB71 +:104FC000FCD673C06BFE04C7EF14FC3D2DC8EFED9B +:104FD000BCEF89BE8DCFAF63DCAFB6EC9CC3D80EFF +:104FE000FAFB5F06A90DF4B2A996D36B5125A3EF86 +:104FF0008F4F6FE5F51D4BF9774DFB5FE7F73EB639 +:1050000045F9F74CA15F9F0C78D9319EEBC3FD5554 +:10501000BCDF7EBCDF847C5AC1EDAE3C8CDE2B282D +:10502000AEA3544EAFE9F14E80F70796CA1417DDD0 +:1050300023F822C04C8A736CABE4F3ECAA909F1067 +:10504000DFA359740BD43B67AF9C8CF74BB68B78BE +:10505000CABEC52B9FC0BCBE0F02E582EE1274EF24 +:10506000B5E7F86D141F7968499EB412D6B8EF60A1 +:10507000E6FC962ABF2AFAC5DC229E24CA8486E56D +:105080005653E4ADB632F13DF69886F1A76706793E +:10509000DE6AF7EA678ECD447D5C29539E59D7E0DE +:1050A00051EF65B8EE3A9ED753A426A474FFC5EB22 +:1050B00077713BADE6A8C7A81ADEFE99C1A3447775 +:1050C000DB01EF4A9AFF270B38BBD19F807E7B5DC7 +:1050D0003D0333A1DDDE717952CC48B51BEDE7FC11 +:1050E000D7BD4416DFA167F41D874EF39407E5662C +:1050F000279E7F40FBEE1A2B2FB587EE65ED9D3383 +:10510000790EE6896FBB81074BBBC287C84FEE990A +:10511000CDEDB2BD12B4837DD9D7A25D4FF7985AB9 +:10512000799C08CA8C71A25E4C0446BC8A733B4AC7 +:105130007D81793B1BFA06709EA23AFE7D8BA29A76 +:10514000CCFD5F08B8A9FF3E578CE29F23EDDFBF7F +:10515000FA383E3BABF8790163718A4BED167E1746 +:1051600053A346FA77425B021C3F3B5DCCC478995F +:10517000AF4E23BD2E870DB243FD603F623C6E9B58 +:10518000145B8CF921B1491A7B9C30627AC761FCAF +:105190006E425E18E96F939408E1779563E3787C3B +:1051A000FB686427DDBB3A00763485835982F4546A +:1051B00077348FEE431D8D540F527F5F85EEB634EA +:1051C0000AE6CDD38722199B74D9A6AD68D7744E51 +:1051D0009175CCDBEC94EAA3385E2CD7437164D78D +:1051E0009479B47FAE517952BA3EBAD1CFF5C2D0DC +:1051F00084C88D7E585768CAA95C8C5B6EAF7D658C +:105200001FEEDF23F77B888E1EA91DBC1BE7D97F0D +:10521000F6AAE351E24B7E5EF768EDE952B47B7685 +:10522000359DCA45FC15637C0EF46171058FA3A101 +:105230000624FB4CED6137031E8BDB3466A4E96367 +:105240002FE3E779F8E79B4C728FFE9E193CE569E6 +:10525000C1F196B0C4A5017AEEC1789625678AEBB4 +:1052600058A200E4E1FE15EFC4304FEE91890574B9 +:105270008FB248BC27C909E39588F1FADF78653D0C +:10528000B67BB4BAC04079513C30340F954471D5E7 +:10529000698AB385ACFB1F5163FFAD449F327DA784 +:1052A000B238FCCE5FE03A02BE3ED273D09EE266D8 +:1052B000CE7504269AF7F9018FDF945A5F1D174CBB +:1052C000F963F487FC782FBF975D9CF50F7395B455 +:1052D0007CDB121117D8240DCE26BBF4016E878F0C +:1052E00065719273C555B1BB79BE6D94F26D9DF336 +:1052F0006EF79FD3AF12DDA3CE6F12F74AF8EFD847 +:105300009488DFB171D27D28945FD57155AABE2FE4 +:105310007A8AE8FF69CDB82BD3F71EF609B9B049F0 +:10532000F863D6F86373F9F856FD519DD3E3D32F94 +:10533000E75D5F05EBF9ABB6B24918FFDC31821FC0 +:10534000B732C0E92F7B002C1CD003FDAFBDE6C5F2 +:105350007C96A765B60AE5547D55C293AC12788455 +:10536000F1C91783F10F84BFED41B9F4D54025C1D0 +:10537000B5622A8F1B74563D48E740219DEB1DE422 +:105380004F94EFBE504CC2B8F7F21AA61F12F19616 +:1053900018E09FEECECB2C95D7BF3D97FC1CE015B7 +:1053A0007EAF067393268BDF9F28C773A24D778B42 +:1053B000FC5919F1DD29E601BEA5790E148971EEBB +:1053C000E3F63FFA17D8BF5CCC535EF7DDAFA11E02 +:1053D0002FD2395DA4E0EBF3107CAD3223F8D4C4B6 +:1053E000ABE8876E9F546020DD1C0885DF6E82FA73 +:1053F000F2452AC5E3CB6B381C075A65FA3D207F7E +:105400009D7690EE8F99A02FD2F06588798B6A12E5 +:10541000129E6B19AD7C5DD0CE8B72D108033C50CF +:1054200037C4BACEC13F4923F88B3C83985B740ED6 +:105430000F2B713CA0DF9575BC9F3FD4B705E5D815 +:10544000F23A0E37E87782A728AC1D447D5F14E25C +:10545000E32D07FC1C925270655B70D5C9947F5593 +:1054600054A31D443F385BC0B732CCE1E97FFDD483 +:1054700080C4C73370BC6C016FB6583F25EC16086A +:10548000FD00E33DE54AD4E3BD9C5353987188CFBA +:1054900046F12CEBFDAE56C003E0C72FE661BBDD45 +:1054A000C44FB0C4D8C732FFFD10232D6E51B15B7D +:1054B000B3D5FD62FF58177F4E7E1CA9445E9785C9 +:1054C0005FB7B2CADE8FD5A4D5CBF07E19A7F7F5AA +:1054D000D7F2F38E0313B87D847EC739FE463A9F18 +:1054E000623CD615C4F71AE9BB9276FBB8C5AD0588 +:1054F000D3513E140F3C3C4F86F514DDCB64258719 +:10550000E8593A27FF60BE6FAF49D0FDD9EC81481A +:105510001ECABB92D6BCE9F8FDB7EC8128D5B3070B +:105520005A4D9E7F062E4C1EE6EBA5CD538A729AED +:10553000E7D3B156AD0FE55A6D3A9CF0BEE4E59E57 +:10554000B9D87FF3DDAF8C46FE2D70F4F7E470FF21 +:10555000A1F8656815C0F94FAFC5F6567C271B2129 +:10556000CEA3F2652C8B7D208FA12C11F97796BCF0 +:10557000E89CF0CEA4A84FD00FE5E3B144BA9DEF6C +:105580002CA1FD78D13E269DB7DD696A3752BC69F2 +:1055900020C0E34D0161AFF630633FE9F71A9EEF9B +:1055A000E1C3E7A03FFA6A8E4EA7FDEC6361A4E772 +:1055B000E2B63FB9D3E5F5CD8152710F3A4174AFF0 +:1055C0009564D1F91EF0317DDFF480DA4AE7AC7DD5 +:1055D00045FC5CF3E89C5724C467D1733C4FDBB2B5 +:1055E00097A7D72442F8BCEBD5E865C49F23D89F82 +:1055F00096BDE95CCF25F50F923C181B655E3C5FBC +:10560000F3AF56298FB5240A7055A15C00922E0481 +:10561000F86B62EB916E8C28AF1BAB45B90ACAAB35 +:10562000C1BE5D3750FE4B576ADCAD1560D7A2FD99 +:1056300034B8DB7303DA2BAD608D18682F9EF2E06F +:10564000F754BA5BA7E7239E9F8958F66542C2F1DB +:105650008B7E6A92BD58AB6B3AC66126B813A3D352 +:10566000CFE90ECC79A79ABE2736FFE2F2C946D21F +:1056700027088B9CA647FAAB8E927E79C23F9EF498 +:1056800090A5572C3D4223827CB945F0519791F06B +:105690004824AF807701CE5B508E001DFB8BB83C59 +:1056A0000739CCE59CA54FEEE67ADF929F15629C08 +:1056B0005B50DE42BFEEDA27726F40B922E4AC3FA6 +:1056C00064CCC4F3B90A215F991A9370BE0353F8EE +:1056D000F72A030E795AD1CAC7E90A31A227D04363 +:1056E00007916E0E1425E89EF881D6A352FA3D5319 +:1056F0004BDF055A930CF77F5C1D9783E3845CFDB9 +:105700008EDFE0F4E9E172F59CDE13F276AB79947A +:1057100089EFC266CCC3FA7BA1CF7B2A0E915FB022 +:10572000EDD653844F2B1E1A12F1D0EEAAB7E8FD26 +:10573000F628BF07B0CB9C3E87E08F2CD728FFB45C +:10574000E6E89C32F4379A966B68D79D0C1458E7BC +:105750005FDE85684FB6AE22FBD727F6F1A1301386 +:105760007EA7467ED67D4BBF3D80FD43E0174906B0 +:1057700036EAF3B891CEF17B0A88EFE82075F6D5CA +:1057800018F41D08E73ABE17E0DFA5F5479303E3D9 +:10579000685F65BAD2E3AB61E4772E07BF0E87DDA1 +:1057A000AD86BD13E0FDEE26595FCF52FDFF578059 +:1057B000E7A34DF4F37B0A3B179FDE8271BE9D4B3E +:1057C000C577CE1CF0DFD7D8E751681E8C09501E74 +:1057D00073C6EFED57F9B3F8F7176AFA06D09E0FC4 +:1057E0005471B85E0C181CEF831C8F3D1199F8683A +:1057F000D760B517F59DD36E7C24FBDD493CAFC562 +:10580000AE6F2E542F76C8FD09EEBEEB48DE7D53F9 +:105810002679C518977712930DFC5D8D9600A7A782 +:105820002A21AF3B5C89FD9857D0F1AC8FAD375240 +:10583000745124C6EC6C9533FE7EDAA180C2F77FEA +:10584000F8BE73FB41ECFB93020F17DA7F0CB3A099 +:105850003DDD17DF34E60E94E3ADDC7FEE4BBC4557 +:10586000794745B31792DF73E4E0A5E40F14559927 +:10587000B6DFD7CC1EC16FADC8F19C371E30923C4D +:10588000DEB7BA83FCEC7D8399EFC514E4F0BCB4B9 +:105890003E9097F87D9391E6D77338FFFD5340D043 +:1058A000DD9C77E87B19697AF665A16749DF16AB5D +:1058B0002CA6A4E5394C10F873EA4FA6C63D97D63E +:1058C000109D13FEF689F38B874C99F06ED1399EAB +:1058D0001F205E611DA6A0433ADFE861710FF24D03 +:1058E000AC89E77938E19EE0972F6A7DC11CEE878D +:1058F0009C9B4FF8EB13FD1CEE9DB5F7D33D4798ED +:105900002F84F421FDE03F4ED37DA8675DF47BB684 +:10591000339E752530A675E741FE7B8BF28B5E8248 +:10592000F39F0FF3EFAB27FCDC1EFBB5CE7FAFE898 +:10593000ABEEC1EE2F407DE85985913D1907C505B5 +:10594000F47A5AD02B7B8ED7577A79F5CE83FDCB5C +:1059500070BC55CFF13CCC3B9FBFEDC62F40FDB690 +:105960000117DD19B8F3F1F5DA18A8DF1E97FAB0C0 +:10597000FE9BE98C7EEF3396A7519CEB3781C18269 +:105980000580EF0FD679987119C649070BE6031EFB +:10599000EE883F3D13FBDDF1941446B69DF1ECE338 +:1059A000AF8C06B8EEFC8644F95F5F39926DB30B9D +:1059B0004FC352A6C1FB3507F9EF46DEC67A662211 +:1059C0003EEE7CBC977EFFD0C2E707EB2A9991F6AA +:1059D000BB61777EE369FA3DC3BBBE25D1EF2BDE09 +:1059E00025F37B44FFFCBC77D1633E5CDF7AED524C +:1059F0003FAE6BB386ED6E8BB77C17539AEE881F64 +:105A0000D466C2FB3B0E1CD456A25FE666CDA87FCF +:105A1000BE72E40A9BDC39BD4F21FF604DAE87EEBC +:105A2000D7339F199A3761F83E7FB08ED9E0BAC359 +:105A30008A13A8716D6E5A7B97CEFDDFAF1C516C37 +:105A4000F3587640EC18D70BB1BFF553FCDCDABF46 +:105A500035C2EFB6F66F8D15885787266782A71B6C +:105A6000F703E0E959A753B9735D88CADDEB0CDA97 +:105A7000A7BD884728BB04DC81A9AC1EBFCF1F305F +:105A800079DA715E93598F77CBF222BC5EB0244AEB +:105A90007EC848768C55EE75455BD087ECDCD13FEF +:105AA0004B05BB67AF16BD1B235F7AC7ABB31AA00C +:105AB000FE3739918D39246FC206F29DE59F7F3DF7 +:105AC00087CBDD4DA335C2F7DEA5931F532CFF0B0B +:105AD000E37E4B573E81F604F4DF9E437C1BA6EF2A +:105AE000748DD4BF60599DAD7FC1B25556FF3DD472 +:105AF000DF73FEFE7B975D639F7FD91D56FF4708CE +:105B00007EDFF9E12F689E6A9FBF7935F5FFAA9B7A +:105B1000EFEF50AE87F2E93BBCE1848BFC6746DFD8 +:105B2000E750F32E3D44DF4F3A17671A3451CFFA4E +:105B30009ECAAD463996A2A3E9DFC475F881BBD2EF +:105B4000E928A72ECBC657B9669EAD9E3F7B8CAD8C +:105B5000FDA84899ED7DE1A2CB1D74E9D3290F96EC +:105B6000717D6A629C13E0D4C6F0EF35D58FF1D019 +:105B7000FAEE7FD14BF5FBAFE1EBBB7F8C8FF89852 +:105B80007417ECFBFD5AF4CA74FB18D62561C8EBF8 +:105B9000193D3A90539BFEDC90F17996C27FC72E57 +:105BA000CBCDF5E5E6D2C98FC5D2F0B9A518E8018D +:105BB000EA6FE768B638CFE6E295A196B479361574 +:105BC0006B8B0E55F1E7B7A01DAF47FE0EE7FBAAA2 +:105BD000367429DAAFCE79DC6575B6793C25AB68C9 +:105BE0009EA4631E77C92AC73C9E4587C47331CFE4 +:105BF00029A49391E6D95C768D7D3D2577D03CBF75 +:105C0000C6796AD3D6537287639E2CBE1E782EE661 +:105C1000F9CD79D7533ED5BE9EB1AB699E7F77CC87 +:105C2000E31EBBDA318F8FE6C1E7380F2BE27E949B +:105C3000E61E5A49FBFF032FC33890E68EFE355D02 +:105C400052F97B2FC585A19589EDFE0FF9438DD2C1 +:105C500000800000000000001F8B08000000000012 +:105C6000000BE57D09785445B670DDBEF7F69274F9 +:105C7000773AFB420837801034C40E840CE0320DB2 +:105C8000411E3A80C1155CA0C3923DE988380F4798 +:105C90009D34041111B551D4A0C034080EF840034E +:105CA000132040C006D4C119D438CF7199059B4543 +:105CB0008210930651F1CDE25FE754DDF4BD9D0EF5 +:105CC00030CBFFBF79EF8FDF4C51B7F6B3D539A793 +:105CD0004E55939C0442461172308EA62308F92635 +:105CE000C67DB5C34AC8F7F0F74342FFBC8424F32E +:105CF0003485903984FFF9170BA490905A33CBCE9A +:105D0000DE3C256B01A42D45692505F41F2B6CCEC7 +:105D10002B14423A5B8A8CB372C3FDA9E91C9F7CA9 +:105D20003298C3DA7E4FC2E378C7929C3A3A7E59E2 +:105D30009C03E7A3E64FD6D3BC899063F504D376E2 +:105D400099CC28A6DF4FD4D3090CD6CE7701B63B29 +:105D500029D17F26D17495E0F70A745DCB3F90C9B5 +:105D6000001CE6C31CBA8E3BF832E6F862093187A4 +:105D7000E7E1311117B40BED32F9D709F0D5D5C7EA +:105D8000904693C64442D4F9F627E48FFB26BD2DF6 +:105D9000D831DBC7309290BB966C7D0BAA7D2494E2 +:105DA000F49D4BD73BB579B9DC87E63BE5E074A7BA +:105DB00055D3CF54F918ACDB4CFF837EA6B9695E8E +:105DC00033FEDDE5FAFCBD440AE7B309B9CAD19F49 +:105DD000E3838FABF865C0D71D744DE91485F74296 +:105DE0003A0C8A1D88AFE90ED6569D8FE72199049B +:105DF000603E523099E4424932D673433DA5E7FCF8 +:105E0000A6CB665731C5E7F407458463E47C83FB82 +:105E1000625D863C9A367E2593FE979EFF8CF9FA4A +:105E200072E265E3A97055E9E0CEA9639E3DA1A1A8 +:105E30008F69EE1B9F3DA183D3145DFEDEBA69BA64 +:105E4000FA33E697E8CA4BBC15BAF2594BEED3E5E4 +:105E5000E7F81ED4D52F6B5CA02BAFF03FAE2BAF75 +:105E6000DAB85C97AF695AA9ABEF6959AB2B37EC3D +:105E70001B7233A1706CF8AD484C148E5F5B4F3EC3 +:105E8000754D12A49213E07EAA3E0DE9FA74BD820C +:105E9000692DD0DE28E09FE16637C5932726544A56 +:105EA000E20979C477ED9225D7D2BC91968FA6D41A +:105EB000EE1BBBC49B49C8128782742F361A4980D7 +:105EC00092AA4012BAE93A246ACA8397286F944882 +:105ED0006078CF723118FD7B97101A9441D7E1FD9D +:105EE000D44436083DF93CCC97A40F49EBBDBCC364 +:105EF00040CA9B34726783C380F349768CDDE0A08F +:105F0000F4506D64FC5EBD2D7D2CB1433E30A8CEB7 +:105F10007A91F19AE86452A11FC62F15FE3E61FEE8 +:105F200045FC0DD0F1FDE038F77A071DAF63BF38AF +:105F300015E6410207B36E1D0AE3BB36C077D242B5 +:105F40003B49A7FC5DEF7AF6C415847C523F01D330 +:105F5000DFD5173F7B4226E40FF553317FA4DE8D5A +:105F600069B0BE1CD363F575587EA27E3EE64FD65F +:105F70007B313D55BF04D3D3F53E2CEFA86FC47CD5 +:105F800067BD1F53950FA83C9A510C7C5A5C6C005E +:105F90003E9D6B21FC8FE5CFF13588F4DF6DC8D7CE +:105FA000CE34E0EB73D66F0665507A3BF70925A631 +:105FB000ECDEE1144977BDE3CF6500FC95FA29F1E9 +:105FC00024F62CB7C430FC580C6402A1F2E7F12B84 +:105FD0008C44A2E3C7BC71D53A311BBF4B403A7425 +:105FE000E3704EB145E97F20417C5D0A4F6AFD9325 +:105FF0002FFEA970662EE0A73FD249CC41B18EE1B9 +:10600000ED6527E0ED52F093387F45C25178E38F7C +:1060100059415AFFCB64159E6D5984A6B73A8A4FF1 +:10602000011D9C6B36E1BACEB5C6FA09F4E14842CF +:10603000BAE81D6E6C1E551B2D3EAD7CA8698AF713 +:10604000E9E545BA4F2B2FCE1D7AD90E7C3F374D4F +:10605000F49D180EF4E1E2F4C1E84EEDBFA629DB91 +:1060600067D5F5A3CF9FF309139A50CE2B71B70DC7 +:10607000ED7D9E73D38C38CEE98D03E260DCD3F5E1 +:10608000661F8CD351EFF0B171D37C5ABAAC9E1F0E +:10609000EB3B91189E5F6FFDFEB3E7474833396EC7 +:1060A0002608FAEF07F45EBF577C48E78DC5401F0E +:1060B000ADF237B0EFC4E4A8FB8E8479B55F4F939F +:1060C000E8355D0DDF37EBC6A3ED94932A9EFA5FAA +:1060D0000CEF1239A9AE93CAC9A15476039D52623E +:1060E000463CBB698F71B4BF2EC9BA44A0E398E2A5 +:1060F000152CF7C040949E6ACC41A35B4170B781D8 +:106100009E3573A4CAF7CA9DBFA724F7C5AF65B271 +:1061100014CAFF4C7BA7E5322F9D4D8AED848E3744 +:10612000B3B96A22C8C92F76FC88EB29BE4258F75A +:1061300097C43001F8E44BF21BFB708D5E3639DEFC +:10614000C8E6B784EDCF5EFA1FAC8FEA69BAFDBA34 +:10615000AC519F2F25B7A4003F94AE90899FCEBD30 +:1061600002F67B75DD94EFAF8F677A5C19A95B0C43 +:106170007ACA52994C057CCF7410A90F9513353B00 +:10618000571796D0FCEDF106A4ABD354BF53A81C0F +:10619000AA48607A4C6592DFE8A2E5C79B87DF7169 +:1061A0000D81F6FEC520D7BC36E2DC407AC27DD632 +:1061B00012FDFC2E35FFC8F912B210E7ABCE43ED4D +:1061C000579D87B85170F9A3E8B3B3E285B09E4CF0 +:1061D000D3FBE3F5FAEB7CC86BF4DB4722F20B232D +:1061E000F22A9DC89C4E4CF1EEF9F1C94017A1F17D +:1061F000A8A7114A1FB9E17AC670BD472E56CF0431 +:10620000F544ACB7F062F52CE1FE1E8B56AF66E7A5 +:10621000961D5E4A4F95AF3F6727549E7F21F952E6 +:106220009CF47BF58647ED00A75392D70EF8FEC28B +:106230002F4E8806AF7DDDF0725905B02390B4294A +:10624000DC5F7D6232E849DF6C901D22ADE2D968E7 +:106250000A9828FDD636574C2479983FCAF28F9D6C +:106260001521DFA2C767E5CF9F4B516C8807A66F4A +:106270009300EA1DB5EB3F1F0F72DC434248879144 +:10628000ED60FC0B09C8F725C6B89EE5749EA827EB +:106290007B389F799A9F382BDA21BDB11DF8CC133A +:1062A0004147E5DDFB4BD0584CE7F37ABC2DE9E4E0 +:1062B0005534FB03F20390072A5C889FE9150D9B78 +:1062C0005EC83B4AE7D5B1FED77621572B47183D2C +:1062D0009E6B9AF5B3DD4AEFF2A693DB45E1767E3D +:1062E0006CA7B4303D88B4B2B45A0ED841EFAC5E5E +:1062F0002B3B29A592EA2D2FBFF222D86B9F9AD073 +:106300005EABDAF2D647A369BE6AAB9C34912DC767 +:106310002AA484F1E3A1FF9B3F2C8C8FCA5FBC654C +:106320005486B2EF0F2784F152B575BF910CED0979 +:10633000C7A2A6FDC6A0350A7E9A8E8E07BDA561AE +:10634000D3B746B0BFBED82790D4EC9EEDCBD7BE16 +:1063500085FB22C009F1C9F1D58DBF1E780B4CDE3B +:106360005D80F51C202F2F85371F97D3353B6D247B +:106370009ECEA3FC7726FF44C0E76BF7DB613DEDC3 +:10638000521DA3F3D58FA6B8E8F8E5B237C5812929 +:10639000FB5EBEE601A4BF32A12EC581FCE44A37F4 +:1063A000A0ECF6A6C33AE7ACBA1DD7594ADC488739 +:1063B000E5ABC5623F4DBF96C884AD51F8A43081AE +:1063C000F149FB3A8A5CBACE76D0FB41DFFE8DE81C +:1063D000DF80F6E97D04E4FF037CCD74A7C4FCD71D +:1063E00066862F6B8241B517CD3AFA5DFF581BE0E8 +:1063F000E9745F572ACC93C2C1CBE1267C4FFB15D1 +:106400003FB82195E1892852216F47F78322F80E82 +:10641000F5DB6497254FD78ECB4F36FE3C3E3E9D35 +:10642000770CEC6FED2954BF8FB2BE99B03EDC17EC +:10643000E93EA7A1330DBF33FE5FFF38E37795FF39 +:10644000FD532640F9F90F191F413BD84FE8BC0214 +:10645000A958BEFF3601E5838904A2F1F97A99F3C0 +:10646000B9BEDC43F915FC042A9DD0F94B429C9639 +:106470005EE838098807B4574A57D0F65AFD06C671 +:10648000C57AC6F077CDBE52C6E5427E029507B109 +:1064900061794056255F961E592D132FA89CD59FD4 +:1064A0009AD01EAFDE2217C3FACF6C3EF8D15D94AE +:1064B000CECF34A97CAB97AB917C5BBE6D8300746F +:1064C0001AC9B767CAE92E1E8D6FE9F7A87C5B1E53 +:1064D000FC7F2A5755F84D4BD0CB532A1FFB810A1E +:1064E000D11B1C23E5E3D7A06F25F7948FF4EF436E +:1064F00052D8930E55FA53E98E6A70FD40AE77D3A9 +:10650000A74A7FDDF4A9D25FE47AF5F08B2CEF0F78 +:106510003612A593E25D54A3A3F8AC6E15FC26E4F5 +:1065200073EFDB7D0A104E2EDCDE88EFED3E49DA9C +:10653000BC3F22DF1451DF15912F8EA8EF8EC8D7F4 +:10654000E9EA57B71C3412C47F4057CF34FF257295 +:106550003C8A3DA8EE3F9EE6B3462FD04566C8086C +:10656000724F5E485537F0AFED15D1BFD6A584EC1C +:1065700009F4FBA31666A77539783E9EE543C9C6A4 +:10658000C520F7D4EF210B41FBBCAB38648FD7D8C3 +:10659000FF475B45BB42CB837E3241EB4708CFA729 +:1065A00001F11D24BD9533BF61578C3D0FC78BC9C9 +:1065B000F203FDDD205AB3E683BDE7139D947CC84A +:1065C000EC0577DA09A5B3AED601374FA5DFE7BCF6 +:1065D0002382BA4DD1E392D229DDCCE2747C8A7851 +:1065E0009FBF96AE6F562BD3C3672F8B4EF795BCCC +:1065F0007EA9759E11E42BD5A38F69FDA295641920 +:10660000D25DF9AA88EFAD3F42FEA88CE00F37B704 +:106610001FF6AAFC914FF251BE10C2EC5F2E976F8D +:1066200010736F9E4AF1D07548242605EC59912CC1 +:1066300086756E16FCE02F20DE64E4B35A124279B0 +:10664000A8C2A903F86870EF72AA63FB1F0B1F02B0 +:106650007AD9F1FBBC9768DAB1E3D3417B20BFF371 +:10666000E3ACDF939EF58BF67D371DF6B3AE7D264A +:10667000F48B75EDFB65D64390DF6D42BF58D74272 +:10668000930BF8C0BBCFE6BF02CAFB32FBA161EFA0 +:10669000B77941DC5F1721DE4E2530FBE55CEB9FCF +:1066A0008E084990D25581FEB02F16F9C8B3DB820F +:1066B000F67AD7DE6F0BDDD67FDE7A6A8DC48DF475 +:1066C000682353B701FDC633FFB167CFA89717D032 +:1066D000F16B9AF71B67D1F2A237FE9207F2B36B08 +:1066E0001BD38B3AE5E01AE224E4AB84B2C765F031 +:1066F000F301336510F274E2C61BBDB9D1E0C2E00C +:10670000D045E100EBA2702907B9DF1B3C62128D76 +:1067100048EFFF7AF0383B9DC9B51F10F00B85E1BB +:1067200022B8D8779BDF2CE0FAD9F77DDFE681DC51 +:1067300039D3B400F5954BAD7B48E2BF2A1DFCBDB3 +:10674000EB160297B3EE09FFB2F866F4FF5E8282A1 +:10675000F38CE4839E74BEF3C7987FCDE6C4F95EE4 +:1067600026FF97FF6FC3FB368A77FBA5F1FED8FFA4 +:1067700058BCBFC3F16E7398409EEDFD0BFA59D51E +:10678000F55F6ADDAFFC0F5DB7AAC7DF64A83B3CCD +:1067900085D63F4C022B8AE93CDFCCBCE1C329B44F +:1067A000F497BDE8271F25323BF097A07C80FD972A +:1067B00026F837A05DC1ECA622C2F6F5A29C32D421 +:1067C000378A729E40BD81487587F3293C6ECA9A0C +:1067D000E35C8AD5877DE2A6F97F4BBFCE89FEC3F5 +:1067E00008FBB1E8CA1B0F81FD7270019D1F1DE7F8 +:1067F000605FD1413527322E530E98F2303D0AE9C1 +:10680000DBF609586F9C556F3F4D04BB47630FDEA5 +:10681000A8E8CBC7F3FE2790034912ED7F825326E9 +:106820007EA8477C8BB4E7CEE323FAD946754CADFE +:106830007FED6F859F3989D999BF24730FE703FCDA +:106840003265F41F5E127E006F8457BE7F29E856C2 +:106850009213E17753460D8727B3AB25DE5EB22E48 +:106860006E03BE9508B58B995E86F6B46A175F0A0B +:10687000CE84DBDB121F5A85BB9449ED6D7DBF08CA +:1068800017151F7F2B1E54FCFDBDF8F81DE0634457 +:10689000181F99E71D12F06711B707C69D6F1331D6 +:1068A0009FE994F0FC85DB0363ACF112D803D74970 +:1068B0001F88C09765E65D95708E60760A48D7831D +:1068C0003B0C68EF980B04847B4EA384F90F0C8E6D +:1068D00011A0684FBE66E7990709F8935D46A67850 +:1068E00017337FFE9FBFFFFEDA42F0ABB0BF32FA34 +:1068F000BF49D41E9BBD8A0462E8FAE648C40B2156 +:106900000E737C0239A6F307EBF3F0777D4AB89F4C +:106910004BD5EF4D8EFCB3D39D546E1DBB82905D65 +:10692000903267BFA4B59B7FD0CAE0E5394CFCFD2F +:10693000512EB8C462CD39DBBF2731F9B1F30FDB7B +:106940008683FF6C4C576E1C93A70506A04B0FB7B0 +:106950000BCE11250EE215CEB50E88C373C443A22B +:10696000CD1DC56FB389DBD3FF518F4E65D2B59E68 +:10697000F844B09B4808FDB7DEF5E6A8E7C13393BD +:106980000C9C6E38DEE89F5808E7166CFC39B46939 +:106990009C166F1D13BF90F27AE201FE8E69CE57EE +:1069A000FE51F882FD0EF0DD64098E2F8E223FE647 +:1069B00071F84D3EF01DFA3BAF6C5D6B00FABD7295 +:1069C000BD41773E599DC4EDAE616418CC6BF201B8 +:1069D0008BAD00F07248745AE8FA3CAD678DEE2832 +:1069E000E75C91F084FEC18FFE6A123B17D8233713 +:1069F000CD02B8EEF9D24CBC14BFBB8CBEAA68F372 +:106A00004C4A61726E0E69BA3F2FFB5F0FBE63BACC +:106A1000AC81B16067AE27DCAF11497F04E9F8DCD7 +:106A200046E287FD14EC52900BE73613DCCF294881 +:106A30009E04BB9AF2FB0FB57E9AC12D5BFF03F457 +:106A400080DA56C161A0E5B552D008FE584F4BBC64 +:106A500008FB6EBE425C783E2C3986DEA6E18B5781 +:106A6000932484EFC1D17BEE8671BFEA3012D04708 +:106A70005C6F86ECB06F7FD53A1CF9A0B775FDA2AC +:106A80009E548E93A11F260F23E92177738C2E7FAE +:106A90008DE8CE00FE9A6C0ACE7346C1DFC4644610 +:106AA00067972DDFFCFF9FC9B70F55F9E6168B35A9 +:106AB0007C9494CCE85E23DF52A3C9B7B982920AD2 +:106AC000709FBB77402AE075EE3B727234F9B6A531 +:106AD0009E9DFFBD4EF911D2AE662ADFAED6C8B775 +:106AE000662ADFB27BB6FBEBE5CA37FF7F0FFF6D8F +:106AF00001F91665BDF11C7EAA7CCB6B3D8AF22D97 +:106B0000AFD940148DDFC99C7C29F92624DF06FA11 +:106B1000F021D9191B857EB670FDFB751EB707E302 +:106B2000809CFBB764765E7AB9722E3D85F1C925EB +:106B3000E5DC7F139C553937773B9573D9D1E890C5 +:106B4000C9B9B9BBA89C13801E999C9BBB9730FF09 +:106B50005B847CCBE921DF08D6AF0DB0F69E96ECC6 +:106B600017EEA1FD0D73C94E33AD3F2C2CEF4668D7 +:106B7000E5DDBF254B08E71EF2EED0E5C9BBED5CB5 +:106B8000DE5139D61FE46B247D385B6374F93DA375 +:106B9000DA37FF02F8E55D11CF173F30B073A0F789 +:106BA00046B517007DADE4F3F170FAEBACF762FF88 +:106BB000456FB2F5D56C66FEEFDA66A61FD6AE1746 +:106BC000FD0AFDE7F8D1DF1961FE157B05924AF356 +:106BD000534CBEE7AD20837F2E13762E4626E66B00 +:106BE000E861F6C82AF4E33758ECEB08E5E3D9127C +:106BF0003183BFBECA3AFE0BF0D3578D64FEFD2A27 +:106C0000FE9DF0B801350EB2B4E5BEB7FB909EF123 +:106C100003934D0C8F935F16FC6BB3217E495F5E2F +:106C20001511FFF8145FE71431887021EF8B51E3E1 +:106C3000189E8A84C7210E0FBA7E1D3CFC425478F0 +:106C4000508C4ECC4F09AFBFE2DDE062F0E757ACAD +:106C500014F0DC578547E43A55F8A8FEE92ADEDE51 +:106C6000D37A1F9EFB47AE5F855F8F75ABF08C5864 +:106C7000BF2F999F7BE593E1104F43E901E587F72B +:106C800057140E749CE23157A46AE5F1F31C0EC34D +:106C90007D638AD209C08DD401FD9436DEF7763A41 +:106CA0005DFF884F9461B04D5E33DAE48673D44D56 +:106CB0009610CA3795BEDA557AE7FDECC9A81B8B4A +:106CC000F67A8BE000FDC213B0201C3D94CE2CB4AC +:106CD000CAC195DF8CE770749890AFF8BE43E16E3F +:106CE000A0F5C7ABFB10853BF0CDF0D6B3789E5B2B +:106CF0004042785E52DB283803741DB52D0C5EAA25 +:106D0000BCA57F562D3EA2D0A3148D1E0938890B39 +:106D1000C3FB6015AF37D9E4FB08CE6126537A5F19 +:106D20004BC278CCA1FF011E23F1A4C2F352F4F9A7 +:106D300039D73FB6001CAD00AF10D3A302745FB0CB +:106D400085CB3D925707C7A2172F30FADA2B287050 +:106D50009ED00D27A0575A3EA295D12BC04D01B809 +:106D6000B79688902FA5F04DCCEEB94E38BFD4F22F +:106D70006FC5DEA3ACFFD5829344A15F75DDBDD1A5 +:106D8000EF3F4AB7ED1174FB9E25747838D0ED5E65 +:106D900081F9115AE375E78EA61476EEBEC942E971 +:106DA0001BCEBBDE919DEB949E7C7E81C313F47F52 +:106DB00045E3971A020B80B3C08D668C3FC379F40C +:106DC00067FAA556BE6EB190E4DB0A7AEFDFC8ED34 +:106DD00081DEF41B353F14C603B9D742C7CB098FF8 +:106DE0001729DF557BFF52EB4A4CF9C7D6D51DBF9B +:106DF00049DAF0FCC914EF7E2809FD3F2C3EE90E6C +:106E00001E9F4467807A96A65E5AF288DEEB913424 +:106E100033EEC3F7F3B8F81B442BF1D2757CE5923F +:106E2000914EE92EFDDB6B412E8FA5FB084DBE3A3E +:106E30003CE2E37BB05CC4F3A89BDF4DAC8173BA4A +:106E40009B4118D1EF37E70BB8FF7E009D8D023DC7 +:106E5000D64C5C264EC2B47CE40FE2D16F94BFDE08 +:106E600057A4507E1AB6D1DF00A9B32894F41EC0EF +:106E70006F8C48007E6DAEC422D8BFEEFF9CE48BC1 +:106E80000AEEB3D8CFB0432419EA8D7625A3393062 +:106E9000AA794511F847A71CB45A81CE73561988B0 +:106EA0005B43BFA389BF01FC36A34EB86E05FE2B22 +:106EB000A7FA02F89DCB5BD736D821BF4A702AB417 +:106EC0007F8FD73DDE4EE7B5A5F1ECF8AB800F69BB +:106ED0003DE8C6B38AD5F3AC179C102A5BDABA1C1E +:106EE000E3714AD70BC401F5FD0231B37EFD66DACA +:106EF000EF9655B43DCD97417BE877FDD90F6F05EF +:106F00003E3F2CB2F69BD9B975296DA700BDAEBF27 +:106F10000FFBAB58259034DA5FF96626FFCB0FCB19 +:106F20004E286FDEBF12F7B18974BCF46C90F78104 +:106F3000719027C30507FA3B33EF42BEEEE27C4D6A +:106F40003AA632B921F03CB71B54BDE9400A8B0F79 +:106F50002E752E3026D27EDE1B999C0D61029E96E8 +:106F6000B3781E7D82C2D94DE1FC018FE73838F23B +:106F7000B831A8D97F3E4B19807438BB650CC6392F +:106F8000CC21C518E7307914D3D7DEBFCEE217E89D +:106F9000BCDE974399F0FDE07526D47F3BB7C878F7 +:106FA0005EDCD93788FEE9F6553281788D86552228 +:106FB000CAC5F6CD6C1F1757DF3E3E1DE0B74170C6 +:106FC00082DC3CB8AAC808FB5ABB5FC0F645AB1FC1 +:106FD0004861760C9387AADD56EAA8D0ED1F91F29E +:106FE0004D957F351C0E9172AE46DD6722E45C0D37 +:106FF0009C37DB21D57FF7102B937FA0F703DE03AF +:10700000DF21FDD61E9609E8FDC2F18EF118B70505 +:10701000FB262D1FD52AB8E09CBFFC13931FF55506 +:107020007FC98C9F80FCFED4440405E2E029DCA9E2 +:107030005C18690AFDE159FAFD8B0FCC102143E978 +:10704000A404E1ACC68B166C60F12D051FAC482979 +:1070500005388C4B44395BD62812B7465E7C21B884 +:107060006EBD8BC963C7068D3C2A30FA4A61FF7238 +:10707000A43239A86C902166846CE7F289EAD32E99 +:10708000D01B2A762D4F31D27A8B793C48C5DEE56C +:107090002954349006D8B768FD0A23EBBF629FE0FD +:1070A00058ABE95F6DAFF6A7F663DCA5EF67C05E8E +:1070B0009EBFCC7ED479A8E3F7A68F8FFCCF0B2B95 +:1070C00004DADFC8F7450C521E797CE200ED7987BF +:1070D0009AAAFED7C20F0DC4A581DBC83FC4109782 +:1070E000862E9A4750FEA6789BD4C2F4A1E611479B +:1070F0008D35059877003FD7723F6DED38766ED5A8 +:107100009CFFC122E0EF890502D201F1BA8D8949C5 +:10711000A8072970BE5056C0DA97D1F6C077CD2B9C +:10712000191F5279A080BCA85DB57C3CD65F2F2882 +:10713000D07FF3DA12DCE7CB478A04CBD71F45BDFB +:10714000A3BCE56812F02BE5CF15B0EFD65E6B72ED +:10715000007FA87CA7F2F1FB328B0F2166C750B8E5 +:10716000075096A244E55FF1306176EA6619F9CEE0 +:107170003392F1E5FB5B44E4E783D7DD391EF8B0D9 +:107180007383D00B1F533E2D08F3A9B89AC5EB9417 +:107190006D62F6CAC1554C3EB437333DB168B53C5B +:1071A00009F265EFCA84F9BD983E78B9FCDC434F1B +:1071B000D9189D9F7BE3DFC972D347F7D3F9DDFC74 +:1071C0001A9DBF128657D1F50FDAD14F7FFD345C7F +:1071D000AF2A874A2516CF34DBB780C5FB4A2CEE91 +:1071E000ED6F9E57C43C1E4BB185E58808F41ECF59 +:1071F000E2A4D7CB48EF91FCF88FF2D13F8BAFB729 +:10720000733A52E723EE65ED21AE2C40E1F8CBCD89 +:107210002F635CEB97AF1E9D0C78AEDA43E997AE17 +:10722000B773B38D04406E497EDC6F2A9B458C1F7B +:107230002752A0F0569B963F597C52D5EB36A49B23 +:10724000CA6D2CEEB472C7F13C8C175918C2B82B1A +:10725000EFAB5CDFF406F380BE2B25162715C9EFD4 +:10726000635299FED9B12B762AAC43D8B81FCF5BB5 +:107270002B9BEE9481FEBAE547AAACD6C3734C2F84 +:10728000A55F386787F94D19AA9DDF02C453C72649 +:10729000C6FF952DB2DF02F3DBB816FDD99E8D67D0 +:1072A000313EBEE8F52DE847F0B488FAB8C88D2223 +:1072B0009E63D114CFAB22E3136B9B6BF0DCADB6B6 +:1072C00089C7FF45C4C555BDBE77879782A6EA1713 +:1072D0003FB7833C38DDB6C10EF0A4FD615CE1F53B +:1072E000E7255D7C54EFF1C02E7DBC61D3E33CDE2D +:1072F00070523BC9EB196F781AFE01FB4D6A44BC12 +:10730000E6C6441EDF1D282C8EE2CFEFBEF7B3E5A4 +:10731000EB351027DFB1EDCC1A987FF55FBF5A032C +:10732000F14D649F05F729CFABBFC5B862B5DD82CB +:1073300054466F9D9B7E8E71D99D9F9AD0DEE9DC6D +:10734000DB9E05F16D9D5BBF4B01FFDCBCBD37A033 +:10735000FF72DEF6A2541245DEAB29D0A7FF32E25F +:10736000C223F171B0F920C6617DF98909E55B7727 +:10737000FC68530D8BCB5578DCE8E6E871F86A9C25 +:10738000636DF3AD375F07F2BA99E977DD718F97D7 +:107390008A17FD90E2F5EACBC0DF661E17DC3429C0 +:1073A0006ABCE897F00F8AA79FA5EAE345BF6E9EE7 +:1073B000F3B317A1AC39B1D778D1C065C04D8DF307 +:1073C000AF4E75BD9A0A7CB42DD69BC6F0E69F28B9 +:1073D000801EF87516DC8F382587300E24B4D7E46C +:1073E00080B8C7CABD1F23BF746EFF00FDAD84C740 +:1073F000D97792EE3F160F2DF075AEB7B138530E18 +:107400007F884355ECF89DC79B323A56E3507B8BFF +:107410003F0DA6F2FBC3FCDE410DB59B589C7A38AC +:107420002E551809F83AAA8BEB55D71DD99F83CB57 +:10743000D1705C75F4385F358EB027BED8BEA2C659 +:107440004D77AEE5F1D6F47BE630889363FBB9C7A0 +:107450002F7C1C0DBF6A5CF5EF23F0ABAEAF37BEDF +:1074600050F9F352F3FE7BE1F26E2AF367ABF0E9D9 +:10747000F8737439FD0DE7776AB77E9DAAB16F671F +:1074800070BB55859B3ADFC54D4CAFE8D8C8EC873B +:1074900048FEA6EB71458BB397D298FE5BDBB23FFB +:1074A0000FE450C7815D9CEE185DD76E3ECAE27452 +:1074B000A9DCF66BE536617EE4C8FEECBC3F4F6BA1 +:1074C000F4FE3C9BCF46EDEFB4E4BA13E67FBA8DF1 +:1074D000E951A79BC409FE28FD5FE0FB52F7BA6D96 +:1074E000468C9712ED31A84FCDB38DFC242E095256 +:1074F00023C6FD342CE071428F38D300CE0DB69BED +:1075000008CCE751808FC6FF203BDC04F43839AD4E +:10751000B84054C2F355CB8D4906E2D7E25F0A6406 +:10752000827C3F92DF2E437F9F45F84D3E93C8E219 +:10753000543AAFCFBC827381D2BBDEADE6DD0F8B98 +:107540003A3F47AD297404F477F28605FDD6E23E52 +:107550008B17FD666B2CB8CE83DBBF7D05E0D5F9BC +:10756000331361E7089430A85C28E3FE8BF6EDDF67 +:10757000AEF913E899D0988E5FB686D607FD7A7378 +:107580002CDA035DDBE2F2509F7CE3A1C92037CA0D +:10759000600F033DEFF5547F03EDEF6432CB9FDCCA +:1075A000D217EF13546DB361BCE1C1ED3B6B41FEEB +:1075B00077BE1E0BC7D1E44B39F857C87BF6C49190 +:1075C000B50AEA818A76BFAD2092A2D5F3AA20AF90 +:1075D0008B7F2168A7A33F8ED273554B1CDE1FD132 +:1075E000D4E3FCECCD60F7650219C077549FD48DCD +:1075F000A396DF96D69FDFEF0DFD98BDAFC0EA7B67 +:107600008CA15296F76530BE6DC3FA252ABDF2F201 +:107610009EFDB2FA33D2FAEBEAA9ED6B4DA42E1A15 +:107620001F54A709FC7EEF5F06477BCF22CAFCF1FF +:10763000FB0302F11A400FD86AC138AE6A636010CA +:10764000C4B7EF30B2F3916A7B6010C4B7EFE1F2D8 +:10765000AF3A86E6E9F70C3E0FA80F79620EBE0638 +:10766000F8AED969214BC17E7FC3E6023CD7ECF866 +:10767000F6E44B0510CF168B7EAB9A37FE1DF15FFB +:10768000630A4C07FA0F6D359175B47EC7D677B291 +:10769000408FE8900359091739F7A96932E9CEB14B +:1076A000D5759CAEF70F84FBEBEABDC5CA5EE4C599 +:1076B000DE34A68F2E4F733D9D867C6D75A0BC86F3 +:1076C000FE44E8A76580F65E73A5125D8EAD4A9311 +:1076D00075F768C5F03DC555D0EF9724B83883A23B +:1076E000A44608E1F979E5C6B343C11EFEECA757ED +:1076F000E1B9D667C6D05090DB9F6585866AE5F113 +:10770000A97AB322C9E897C0B46BEDD9D20C02F1C3 +:107710008396A9D1E4D396B4589C47E5C3B151EF01 +:1077200083EEE6F4B61A6830998D0B7E0875DCCFCF +:107730008C7E23CC23375DC1F2CA4CBF11BE576D7E +:10774000DC3540F7EE84E4C37A94BF101E156485DF +:10775000B1C0DA53AE54CCB72A12DE8F96FEAB9B83 +:10776000DEC4309ED0C909716A1C877467423FA885 +:107770007A1F40928BCD002F2329764822A0DA87EA +:107780007C1A439A30B5527584ED437504E28A4EF3 +:10779000F1F35B93A43C0DF2C3744844797E29B89D +:1077A000FD32CD8EF3364975C4897AC74407E8D5D2 +:1077B00082D74DBEA7F4D050BF71C00976FEEF82CC +:1077C00038383B61F3B33BDEFE0EF4034A6768676B +:1077D0007BAF27FE063A9E6464793296F8A39DC774 +:1077E00077703C10EF7E943F5612FE0BD17C2C4AF2 +:1077F000283A6EDC5F47829D6B759000E84DB1566C +:107800001288A5A935573AADE55F3B61F9FE949C16 +:1078100041AE39AED59747D235714AE7BBE5A2886C +:10782000EDCF47B43F7FB1F62A3C3CE601D9ECFEF0 +:107830003B834B0C5F8377ACF34210E09167773664 +:10784000001E8DA1230F013CF2ACCC4E4C6A245A91 +:107850003B6E403A93578B04B65FD2BF62ABA63FF4 +:10786000E230A3FFF4710EF7EEFAAA5FA5477D8B15 +:107870000470ED51DFD25BFD98E8F56DBDCD273684 +:10788000FA7CE27BE9DF1BBD7EED1B1FBF1750E0DA +:1078900023931B1231A8F7A007A483BD157724A555 +:1078A0008451053B2788C05B0CD01FA58798819A1F +:1078B000EFF07FB91AFCF58F827F1240BA2BE1F30B +:1078C000A1796B3A9DDF5D7CBAE3D6B373CC7BE6DE +:1078D000313FD25D0FB3FB42477FCAEEEDDFD3C825 +:1078E000ECED7BE6B3733352CEEE0139E87F30DE48 +:1078F000BDD009C5F7BD3EC11FC886777022F4D739 +:10790000EEF7761E90A07E49843F46A527F5DED28D +:107910002CAE5F6773FA9C434236E0FBC87BF4CD24 +:10792000692C2E8D9A632E58DFDD7C7DEA3EE05D6A +:107930004E72E05D00D110E384F31191DF5B257698 +:1079400023BBB77A5B824EFE9CCB51E260BF236FB4 +:10795000F2EFFC3DA2B9372AA9DA7B5ED285587CCA +:107960007FA44176A6815C942FFC8828942F8C17E5 +:10797000061045730F8DEA77C8ECB283A01F4772DB +:10798000149332D00BE3399D25DDD4AD87BD4FE193 +:107990003277B982F760EF4C67FBCBD28CE239408B +:1079A00017A27DA4D36DED8957EF76B6BE06585F5A +:1079B00076CF7937189D4ED4436FA21A04FA7B9C78 +:1079C00066988F68523E56803F7F2D13B0FF7BC272 +:1079D00081E1F35C52821FE25F66DB971E01BA5DB4 +:1079E00056EFC073B425F539982EAD4F433D7471F1 +:1079F000BD1353152E66A7CF2552389B07B2FECC78 +:107A00000E37D333E83E04F11792A32E0079736644 +:107A10001D01FDD7D20D1F1FC2C7D89D7763DE049D +:107A2000799ACA8D1311BEB43D29033F6A867B192A +:107A3000C0C7A25C49140D5D98D286E9F23DE0A66C +:107A4000D2C71606BF2705461F91F07B526E53E042 +:107A5000FCF9C91BBBDFB541F851759FC1EF57EC6D +:107A60007CAE57F83912509F9D5DB8783AC4553FA7 +:107A7000C1CF211FAB1F89F07A1CE2BA06837DE0DB +:107A8000C25404F8513A32E57A8948DB9B143667D0 +:107A900093B5D8652860B40BF013AD0C9EA6B43A2C +:107AA0003C8F335B19BC44AB17E1225B19BC442B00 +:107AB000A33723CF4B00BFE1D81EBF53F835A78FA4 +:107AC000003C8CD6C1CB9834F6F2E0B792C28FCE90 +:107AD0002389F357241C92E09E426E98AF7AD3EB31 +:107AE0009EA3EB877DFC050A1F48937BB11F933350 +:107AF000981C4D32D4ED97011E0984EF2F5E9259E8 +:107B00004858A822FCA57989027981CD83ACD7E3B6 +:107B100055744811EFBE292F001DAC784736C03987 +:107B2000A938FF47BAFBA4E25457BC82F0740BB0EB +:107B30003F3F51AF20FE96031E07C3FEC8ECB1477E +:107B4000393E1F033E41FC32FE7892F3CBD39C4F6B +:107B50001A9CECFEC4B2092C2E2B29DFC0DF430B8C +:107B6000106DDC53BCB38918E9BC50C756300DA06A +:107B70009EF189C97F056D179B4B5C4027F19F3CA7 +:107B8000E8C7B592E274D08BE2B9FE4BAE55E2A7DE +:107B9000E145DA80C4EC102A0AD1AE6933447B0790 +:107BA000ABC179C00C7ED3DEE6B37FCA0EA4CBD2C4 +:107BB000AB313C9824BA8BA7CDA1796B632CFA0723 +:107BC000639DEEC24781CF1B6D48A7563AFF320D29 +:107BD000DE637BC1EB8B19371A32281D8AA0B451A2 +:107BE000FC3ED338C002707E4E2E4E07F9FA1CDFE1 +:107BF00067290E14ED3954079793F6822B75F6EC2E +:107C00000AD985ED1CD7EAE5C00A2E7713C6E9E943 +:107C10005D95BB1F75CB5D7732CC27E5C238E4C7D5 +:107C2000A45BA2CBDF06D9E88577051A86327EF7FA +:107C30009618D97D989EF200FDDAE7DC83D6813C68 +:107C400055E96B2161F2C74B629CB81FF177745400 +:107C5000FD7809BC37C8E52CA4E24023D24DCA3DCB +:107C6000068CCF5BC6DFCB7A8AD217A43E4A5F90E0 +:107C70005E97C1CE33169A87E1BB6D0D5603CA0BD2 +:107C8000E95393DF0AFAEAFE510EF02348B2B3CD6E +:107C900005FE409BD4B48E40BD0233BC2721C417DF +:107CA00038800EBEB1CDEE77B1383C8A4E01E8C8BF +:107CB00091544C8EE5E2E901DE7B911DB710F02B6B +:107CC000BE90546701B8E56630BBABB1A410E14883 +:107CD000E13B362339DC4FEAD49BBADFDB826E5FAF +:107CE000E8E5FECCE40CAE47677AC9400DBF370A21 +:107CF0005C0F53BC2447C3F70BAF184FE05CA927B8 +:107D0000BFF722CF363079B648882ECF54FD539531 +:107D10006772849C50D3C5FD26E8EE7719939C408A +:107D2000BB907A0D144592F7EA27EF8E4738CC02C4 +:107D30003890B49BBAEDDA1FF607BDB2302ABD45C4 +:107D4000CAB1D9DDFBBA2B05F0744A5652A7013DE2 +:107D5000BDD3DBBEEE2A453AF4F551605FDAFFCCC5 +:107D60008FD0AF73E2199B0272A8ECC2E3B83F94C4 +:107D70005E18856979E38DB89F0BCF4E2A047A6827 +:107D80005F7543DEA7E0E7F1D970DF6E6F2C1A84D0 +:107D9000E791BE5805E23BDA1B697941B81CE2C5A0 +:107DA000454DBC0001EFBBE6FE372950502F55DF93 +:107DB0003DA3769D7D34F885568B782FACF4599B86 +:107DC0000BF4CFDEE8AF7455747F00DE614AC70163 +:107DD00073408FDE6F1F1D0AD07E67AF63E7080D0B +:107DE00046D7C900E84DCF58F01CB22121FABB207C +:107DF00073326E580672604E86EB39C49395BD534C +:107E0000DA3B3FB0F14FC221339C63BDC8DF4791DD +:107E1000DCF629BA7336768E7592FB5988B997F2DB +:107E2000185EAEF4526E67F122C411BD5CB53362C8 +:107E3000C3764613ACA3A6F1CCE24F115EDCCEE0D4 +:107E4000F33E25B3799F7AC5E45F1885FE4FF1F8BC +:107E5000940A81C157E58353DDFA911BDFC389A4DE +:107E60005361DD901746D17EBF3A24E3BE514DE900 +:107E70000BE96ADD288C8F179E19F534C40D9F3FDE +:107E80002C6279E5050B96773CE27C01E29E42EF9D +:107E9000CA04E4D3F94337C4313F91DE8F7D6F1FAD +:107EA00026178E71F9507AE109A4DF6E3AF1CD31CF +:107EB00002FF955E788AD1F74601DFAD24DEEA77CE +:107EC000C70CE4F4391ADA574C5A08F0BED687E7E3 +:107ED00024651B4C4ED00722F17C2C43D1F93DCABE +:107EE00082CBB05F42F5AF24CD79FA291E675C766C +:107EF00081BD57481C5E9206FCC0E553988EF5EF95 +:107F0000D07658A2FBE9CF71FDA7F4C2353A3B23E6 +:107F1000BCBEEBF17B29DFFFCB82A3301F5ECF0B12 +:107F2000A3A2AD27BC8E6BB17E477CF4F1D3399C04 +:107F30004FD6971317956FE54656AFD4F78011E4E7 +:107F40004EE9AAF80441B3AEB2C62A5D9C47D9AA4D +:107F500012E34C4DBF613C2C7E778C14C643FA4B28 +:107F60000B262DB4825E502CF7017E5A5751F81320 +:107F700005FA63F2E90BD99705F2BABDF17E7BB43D +:107F80007B13E97D22F0D3C8F143F5EA020D7E545C +:107F9000BC44B63FB9B6ACF027E08F5EC95E21E9BC +:107FA0005DFE44E02D3B3ADC8675C32D07E38D2E44 +:107FB0000DB7AB7471453DE0C6F1ABC245FD4EF562 +:107FC000A8ABFA8C80F108BBBFD3C8F07F297885B5 +:107FD000C7E5F81F137D1D53BBD7319F7829A3CE6A +:107FE000BEE43A1E225EF345D6A1E29FBCA2C3FFC7 +:107FF000D497D6221FAAF89E7D6025D2EF6CCA8F37 +:1080000070DEDFEE7BC01E2DBE686A6F781FE8252C +:10801000B985FFF7F0FE85ECCD82B832EF720BDA4E +:1080200023A7D63D91A585F39C8C31F7025EC8FA53 +:10803000E4CBDA3FBC639D87C0BEF43E23A33F6D13 +:108040006B86BB0CDA97733B7C51FCF841D1F4830F +:1080500047EB0F0D013F5D437D1BA632D72F09E88B +:1080600097D9A82FB9A2BDEFB5A40F932B8FD6B780 +:1080700031BFA7D94B1CDAFBC484E94FFF4598BF39 +:10808000466D6794DD0EF09F1A05528C7A9FE45E70 +:10809000925D007E8FA47CAF067E8BFBB0FB48CB4D +:1080A000D20E38E03EB189F60FFE1C73A6744E7FE7 +:1080B000CEC9F2F9C2A722C437CB494D04FDA1B9FC +:1080C000F4BB06DEC6A4369D7F3A120E92D98EE727 +:1080D0004D1261FA9CBA7EFA05F7A5C7F8BEB482C4 +:1080E000FB359FAF6F42BFFFC2583BEE7F8BFB1942 +:1080F000983D6596F0BD1A533CAB6F8C63F3B68028 +:10810000DF5B847D3580791BBCE823E2D36802E421 +:10811000E38922403E910416E33B2963823F86EFC8 +:10812000CE34B71FF0F84D7ADB1101FCD8C5EEC193 +:10813000B0FF368ADE7C85D6FF9918CA877A59B493 +:10814000E8930496F6837868B7E65C8BBD13AA685B +:10815000FD8291F97EF3A588F39E3F0FD6962F4FAF +:1081600073BD0EF368B0B07786928E0B789ED360A5 +:1081700061EF0D35D8EE88837DFC577D98DE8E74D7 +:1081800000747488E933E724252E81F94995377501 +:108190007E7EB3F2A6661C89DB7BEB295D4A9A736F +:1081A000958192CB007473858F7ED7CE338A3F2E14 +:1081B000C18ACFF2463DCF51E70771FB0047F1C2BC +:1081C00078B4D722E9614FB79FD92B023EA7A9EF18 +:1081D000174B8B583E9EA87F687F7DDAAD8F2E624D +:1081E000797ECEE999C9CE311B4AE2303E4E9DC719 +:1081F000B4D6C7DA404F9DD69A3E0BCEB7A65907E4 +:108200007D0EE91E39742016F4C00704BC5772D7DE +:108210006FDF946369BAFDC375789FF9732E4FA71A +:108220009310BE0BEF260E7ECEEEC7EF338993E799 +:108230009B64B0EBEF09F86F9F4473F7BEE99F04AE +:108240006ADBF443A1B7400CB89B1CE3F10C416D11 +:10825000D7E27C9BE559BBEEF54B665C4F78BD667B +:108260005CBFBA3E3A53847F377CF87B4D2A3CC4CE +:108270009974DD945EA6C5DD7113B9885E3ECD9A12 +:10828000F3393B3461F38984CF7928A2FA63471F1D +:1082900017C9A4F8FB7D1F970069B5399425F547E8 +:1082A0003E91215F2BBAFB41E8F3977DDD8393017B +:1082B0000E6D8997253F8F5818FF1F017A8638AFBA +:1082C0000B49B82EF51DFA830FB6DB40EF5CBCFD01 +:1082D000637C67B9460C3E7927FA4345B49BCE359B +:1082E0000FBEE8FDB323E0A7A2FB5FDF4CF59E25A0 +:1082F0005BE70C89F1C98CE6588CC79F315FD4BD10 +:10830000233D633E8BE723525BDE6D3A7D7D51AFAB +:10831000FD80BF20B29F59F38BC8F1E1704EEB187E +:1083200083FE83358CBE668D738910EF3C7A89801D +:10833000E7ADA34E282D419A9FE58F77027BCE7A39 +:10834000F03F07C03B07B56DCC1F982ADE97FF08AA +:10835000F8590EB07D1CF2F7019D585D8A55735E89 +:10836000D021D7E5C37B7FDE7BAD2EE0FF92DB5CC7 +:108370009FE27BBEDC5FA1EEAB3B1B4B304EB6E415 +:108380001E6524E0BFA4C9E2C2D44CA4182AC74A7F +:1083900024628634D548240BA431C40C69E142F62A +:1083A0006E7769E314D40FEC238B8DF01E6F49EBCD +:1083B000CFBF86F6655260BF9017864F49EB3BDF13 +:1083C000015EE7B88A319EF1AA8D469D1D38B449F9 +:1083D0009FBFBA459FCF0FE8F3C30FE9F31B3209E4 +:1083E000D2D14CF3ADB900AF037B4D742F82F83F6F +:1083F00013C6BB1C13187EBC9B2C280F8BAA5A0BD0 +:10840000C10E3EF39ACD0076F49EBFFC02CFC3436B +:108410005B6209C459EDFF5D0C898178C5D72DEBEE +:10842000A0BC8AE20EFC9755AF5BD6821DBEE34A24 +:10843000D58EF7E7C17A76FC95C5D7843699FC705E +:108440003E7E66D7CF5F83F3B4339BFAA07E754C34 +:10845000F01A6260FC2F98FF33C8DF8B0BF2F7E253 +:10846000AA36EAEDE2B9994CCE04175E13174D6FA8 +:1084700052D39CB4C4DC71746E5D8F9B66801F68A0 +:1084800070A31E2E6ABD217EFDF78778FFA3893178 +:108490004CA7D91027E06FB0C3FEFB72F477921798 +:1084A00072FE79F5D5EE76227F278E289A7B53616E +:1084B000F94DE6F581F80D807FFFF0F72AA2998F3C +:1084C000463F99C0FBFFCACCE29993F8FBFDA7EBAE +:1084D0000FE1BEDFADF7D5BB5CE334F9D2C6FD29B1 +:1084E00025603FADDA9F325303AFEA4D0753EEC626 +:1084F000B827093CB8A47ADA2B4F81BFA27A93D867 +:1085000004F38472805B47D35B76A847F5E161E0B2 +:108510000709EBA337B8C669F8F86FA55B95DFAA22 +:10852000B9FEB27364DB788853AF6A149C50ADAA6D +:10853000E9F65B2701BC57B17BAE85122916297F6E +:10854000556FBDFD4743216E66F50827CC877671D0 +:108550001B7CAFDA7C16EF332C8DF8DD0335DD9D07 +:10856000C9F4425A3F60A0F597DE612D07F945FB3B +:108570007D13F20772D6E1FB2AF653ECFC817EFFF5 +:10858000C440F5965363BDEFDD4D9B9E214D1F4DBD +:1085900002BF52A39E1E297D0BA097853608CE757B +:1085A000F87561E12DA072BB1660BC2F2D9F11EDF7 +:1085B000BE75855FDF4F24DE3FE2F3A57F395AFAAF +:1085C00089AC9738D18BF1E4D5F3A93CD4F809AA4A +:1085D0004FF8F07DC9C8718896AE993E41149087D6 +:1085E0005B2CEAFB4782B990C7E90E60797C571192 +:1085F000E894124AD595649C02F0BE854C80743490 +:10860000C815784F7F64531ED4DF2D045F7909FBB2 +:10861000B3A11CEF7004F09DC90C7ECFB44361F987 +:108620002EEEE754CB2B5B2D186773E64B23CAD98C +:10863000054D07318EBEE3358BC140E5C199AD894B +:1086400063211EB3A389BD537CBA2971ACF122FB0F +:1086500076A4DC50F7D3A3F04FBAEFFE29D3F54D43 +:1086600026EC538B58BC6A6A625D7EB4DFBF50DB78 +:108670002519EBF2C18E09DD6B75AE433879B32550 +:10868000F483A739214EA84460FD1AFB158B7D6940 +:108690007D1BAD0BFEE8844322FE5EC371D1F963FE +:1086A000C7007C4F1EF5A0D9056E7C9F922C62718D +:1086B00095B324129028BDCD82FD280FF32897672B +:1086C000AD1230AE6CF632FD7AE09D5CED3E5A4163 +:1086D000FCEC7D0BAD1FB13FC4BBD0FD06DEB53455 +:1086E000B3F88BCAF5FA76552480F3A9DEFCBD29D0 +:1086F0001ABCBE26EABA5C99B02EE11633CEEBFE68 +:10870000E7E2D8798F91B8603F0D3D6743F95E4548 +:10871000DCD8DF5D7C5FF73C58E29A0D7278FE2C66 +:10872000D7EC44B86FCBF63F34F990BF05DC77AA9D +:10873000C691405FF6EE06817DB5AA55080C85BC52 +:108740009978EDC3D877787F00D6ADBD5F534E7C66 +:10875000385EF92AFD77F221C36B35BFC748D66B67 +:10876000CAFB837EC6E051BDD9A4F3EB8CDE2C7826 +:108770006D78DFD5DF9042E7577B8ACA0A0271AA7B +:10878000DF9B74FD433CCF08DCF78985E2EDB96ED1 +:10879000B9EE1F122DCEFF0887E373B797A603BF6C +:1087A0003E0D7A6B0607F448945BDC7F4002663A24 +:1087B0004ECCF0EE3C96172E64F9C9AB5F99DC788D +:1087C0002DB5F364379E0BCD128BDF86FB602FF740 +:1087D00073DFD2978E33CBE0CA92906F5D83D01F48 +:1087E0003A9FC1E185617543EAA2E8812A9E9F17FD +:1087F0009A02702EEBDDC5F42F5B4148D6EEAFD563 +:108800007D993C8A3B10C47B13A1ED02DEB35C2949 +:108810001CC5FB882B6F5408D8F769144F208F575D +:108820000A649140E152D03CE5BEB700CF05314E1D +:10883000F8B98B9AE631628D15D7CFF4B4D8BAB5B2 +:10884000709E933A236718D0395DF78C5BE8F7FB8D +:10885000FA2A385EBA95E13D6DA1371B7E072AEEF4 +:1088600040F17D6F011F0E8DC17BB2A91456B60475 +:108870004C9780FE9546160850EF393BEB3FD920C8 +:10888000CE9802F9612C9FF0B0E05A87C4B71CFB68 +:108890004F359109304FF80E7AA419FC0A58EE674B +:1088A000F82DAACB87FE5207B034C918C8847E0EB3 +:1088B00077E3DB8D76C53CBE8FCDDB3A2615ECBC6D +:1088C000C31DD4E0A672EB709AAA0F05ACF8FB505A +:1088D0000373587D6E17CECB67F70D92B2F4F5BADD +:1088E0006457DC7090A31F303DFEBCD585FEE96B5C +:1088F0008CD1FD592FF5657A8BE78240FC9A7DC0BB +:1089000033F51BD42B3D1724DDF78E7AB32ECEB969 +:10891000BAFC00DEBBAF216D18875DD314AB8BDBD7 +:10892000BD2626FAB82A7D7B2E88C41B755CA3FE63 +:10893000FB8544E24D8C562F45FF9DAE43976FF962 +:10894000B67B1DF09D8C0CDAC11E9CC8F5DA2EBFDB +:10895000C12B5F1DC64BA723A8DB773A1596EFE224 +:10896000E7716AB9DA7FE75423BF57C4DE5506F8CA +:10897000780713F262EB59F44757B7EE1FCF7EDF4B +:108980008BD185164E5E8DFC4869680B18286FFFE9 +:10899000A6EFA9A7728750123BA0F2F1E9A75C9459 +:1089A0006F5344838EAF630BBAF91CC5CB7306912A +:1089B000CB85334F8DBB569B67F5C3ED3B268FA30D +:1089C000BA7D412E6BFF87BE5FBEB77060582ED157 +:1089D000756415DB34797344DE4AF34335794744D3 +:1089E000795244795A443E93D5EFB005B2442721D9 +:1089F000ED7DCF4E9646C13976603ABC28B0ACE1E9 +:108A0000ABC9E368BEA6A00DE3676A5B05271EEB52 +:108A1000ABF1F14EA667599D41FC3DBBD882B6B77C +:108A2000410E54B7080E81D2BBB5692BC6D554434D +:108A30003B45D3AE89D99DD54D47B15DAFFDE71814 +:108A4000909F97E61CC37AEAF9D19DA4FBF73A2ED2 +:108A500080BCAC696A67FB70C4F95167BAEB20CA85 +:108A6000C388FBAF1EE8D71AA67BB5FEEF87B6FE1C +:108A700016BA899D77768144EBFFB1A67D04E84B59 +:108A8000F0C625C8FDE705FF10D89F5F24EE21B092 +:108A90001FDD5B73C57E03AD77440EAE86A71A0655 +:108AA00065596E96A89C3E620BF615A82CC9599381 +:108AB0007833C0F34872105F68F8E99A2456DE37BD +:108AC000D817CE5D73B37EC8F257045743FEB63550 +:108AD00057B2FCD0605F91B6EFEFBDEA6680FF064B +:108AE0004774BEED9BC5E4B93ABFB27C575A16E84D +:108AF0009BD56CBF80EB97662A17A7579EDEB28185 +:108B0000C261FA4F62515E6DE8B8F5A6625CBFB70C +:108B100018E2DCD813EF7C3F43B92CA11E900E7BEA +:108B20005842181FB6AC3605E5FD95755B61DF4F01 +:108B30009D9E8BF2FE7CA6AB3E6B4438FD76004BCF +:108B4000EBB3D87D8F54D180F106A90FD9500F7A9D +:108B50009A9F2751BE41FC5A393E866531F9372C20 +:108B60008BD949197D6FA887F5DCC5F5D3158FFB27 +:108B7000375928FC7F07449284FE6DD477EF5E4B13 +:108B8000E5461CC453B8D2411EDC0DFEDFDC705E2E +:108B9000D5DF57E4D3BC356CA7AD98E24AD7C60100 +:108BA000AD58CBCA5579B3229BB557F79DD406066D +:108BB0009FD4A787AC8375C44A04EF5FCC993A6809 +:108BC000DD02DCBF6FC1F912972B1DECEF1315FD11 +:108BD0000DA057AAF8792CDF3511D723B278751577 +:108BE0004FEAF8F57CDDB344BAFFD3753ED4CF8DA0 +:108BF00070A4FA401E0B2E60FA403D386293C3F019 +:108C0000255270047CFF5F04A7FB60DDFF289CA257 +:108C1000C88B9FC2B835F3A9BC3068E40587DFF381 +:108C200042404E2DD0BC5F42BF831D78675FF7A3E3 +:108C3000599A739CE90FD5A0FEA7CE2BF6DF774E8D +:108C4000B893F4E4B348FDECC8EFCCCBD00F686C1C +:108C500042B978E426E25C00F2839FCBAAFA65E190 +:108C60004FAA0E831D752E4BC4761615AF42F1D652 +:108C7000520AA7C7E9B60AF7D1BD53587C8FBA6F1D +:108C8000AEE0EFEEAE78F02A8CF3EB2241FC5D36DD +:108C9000EF4882F2AFBB7CDA202CA7F8F65A80DFCF +:108CA0002B62F0770756E413BC67B362DA9558BEBF +:108CB00047F52B4D33E3382BA6307A5A51C1E230B9 +:108CC000611F01B8F5460F290DCCBF4124579E36D0 +:108CD0001EE05D8EBFD882E0F68F41AF5C6641BD7D +:108CE00012F64E3C1FF1A5E27814AFDBB390BED96B +:108CF0003C663D9BEE5F8AE33AD13E7FCCE62A415B +:108D000079F548AC02F35F65214BCCC3C01C218BC5 +:108D100050EEF1F910DF0B18E73183EB6B9F959F55 +:108D2000B3813EF02697374030602FCF24AC7CE6ED +:108D3000C3B147C1BE99F9B088F70BC9921B5CFA61 +:108D4000F30E3AD714F08FF3BFC6900DE0E08676AD +:108D500076E8FFBF6CF09E89FB6176BF9778697BF0 +:108D60004D3CF4C7C0BFE06717D9FC497DAC12ED9C +:108D70005DD08FB97CA7F37769C753C789EC97DAC1 +:108D8000779F00BC28DC03700F2CF488C87FAF5598 +:108D90003FDF2463E8490B2D9F5E2FC62FA4F0749C +:108DA000CFB7E17AD5F9CE480D5DC77E1756DFFF04 +:108DB000C9D8DA42F087ABF60879586F8F815FA285 +:108DC0003B2F629C34DA353DBE737B36D20E24E4F1 +:108DD000AF266DBDEE7B1A8A10317F4E578A200177 +:108DE000DEDC3C7EA11BDF11F356E169E8171D9E16 +:108DF00049C6605F905BEEF9268443647B75FF7B18 +:108E0000C142BC6027360A02D263E383B1B89F1126 +:108E100033C3A3A7324601FA7CD118C23826EF6EBD +:108E2000F6FB9F5D96D00E944B03993FA1EB3D71ED +:108E30002DD4EB4C6674DDB94BE6FC44D83B12EF05 +:108E400089EBB05C60FD762E88C5F828B8FF698490 +:108E50007B99DE3FD5837F45B5E38FEF60EF29C077 +:108E6000EFF668ED60B8375B3E2C2C1FF07D18E004 +:108E7000E79658EE277257E07877C71088C3A83571 +:108E80000818D75B5B7925DE2321FC1DE76A3EB518 +:108E90005A03B5078785F9BCD6706C10D853D5E650 +:108EA00065F8BE332D7F13EC30F899DDEEDFF1C8A5 +:108EB000EE49D7B5CBCEFC05EFB537EBF15F1DA67C +:108EC00013BC1F57A9A59BEC303DA0BE0D72621CC0 +:108ED000C17BF9369E8F9DD0E6073F8D87FB2D9293 +:108EE0000FB0776B6D054D04FCA69E534CDF18DD6B +:108EF000BAF620D8BFF113DAC0E2A2F599DF2DF25D +:108F0000FED0A8D6E522D875AA9EA2B12B87DC3266 +:108F1000549BB2FBB660A7C27841F804FC21B1FDB6 +:108F2000ED79BEBFD17D10E5F11CDF60DC07619FEC +:108F30000239A6DAB920D7408EBCDC6FECD47E743F +:108F40009D79CAD85BFBB1739821A8D77B2FEFBC62 +:108F500049AD07F6EEC5FD610C6EA195714C4EC092 +:108F60000F80829FF8D7F25A7CD71B042F9DEFDC2D +:108F7000D5D92877553F4D35F7539572BF4E29F710 +:108F8000EB805F551BF70A7E4B6DBE9AF37D0DFC9F +:108F90009E14BE17600AC7BD823F671C09D8A01C7B +:108FA000FC3A7676BF4EDBDE43FC4512D2F9F7265B +:108FB000DDBB582BD87A6770BCAFB4307FCEE88762 +:108FC000D78ACC49C5D61B37CC95FD6841F87DAE14 +:108FD000CF399E54B818FB8DBD17E01E23B2F7CDD4 +:108FE000438FB2DFBB3E41F7E7ADDCDF718B15EF9E +:108FF00017BB06425C82E4C8BA25CAEFB62EDD6D07 +:10900000C177FA97F563E7C1EAF7B1FDD8FD5DF4E2 +:109010000301DC17C4A29E4DC19C077454D85FDDC8 +:109020002F491EF89F8EF2F8CEDA3BAC6EE82FC8BF +:10903000FDE22BFBB17D6B653FF6DEBF9AEFB6EB31 +:1090400038BDA8E758E08FD1FAAFFDDDF599FF44B0 +:10905000DD5F9FAF8841B914A65B03DE9F8CCD2DE9 +:1090600036821F6937972325DC5EDF0D07B4204F5A +:109070009AB8DF59724C87DF05DA7D2A17E325930A +:109080008C4CBEECBE2B8640FCDEA1D3AF3EF11E65 +:109090002D3F77CA88EFE1CDE6FED6DD0271C178BB +:1090A000DEED26F423561B99BE58BD6F28D3538C92 +:1090B000EE9510D7EDDD26A35FABDAEEDFF40A966E +:1090C000A73B2966E13E28D37377C5B2F631FEFF90 +:1090D000780DECCE7DA94E2FAD3F3FCDBD0FF09A60 +:1090E0006152E2887AAE2A84EF8B1EF333BDF81802 +:1090F000081E18A7D5C67F47CE953E87F673FCF1AC +:10910000545C0F95B7A83F1D7FCA84E766CF778F61 +:10911000CBFC9FC7E4627C2FE6D8F67C27B52C49B0 +:1091200057B13100FE6DCFD34C9F9B6550D6007C6C +:10913000C8BE58A7CE1E7DAA8CBD1F51F9F0E48B86 +:109140009D63837CD7FA773B49280BEDD1F2FE4D26 +:10915000104FDAD93AC4C98EABD2F090A4969F2FA3 +:109160009F90197C437B65A4E7CBED1FE8A2FB77BA +:10917000EE4482BFDFA63D4F8B3C87E8996778F4C9 +:10918000EC4EE57A9BBEFCD64C7708E45BED33DF12 +:109190001E99AFC078219487C4C7FCE92764D774AF +:1091A000A0DBF871015D9C9659617C35CBC4F77BDF +:1091B00012306AF9502D2F1C4BA29EDB9814A60783 +:1091C000D8F8B97364F9FF014BC990C00080000062 +:1091D000000000001F8B080000000000000BC57D90 +:1091E0000B7854D5B5F03E73CEBC92996426992481 +:1091F00093F7C93BE4014308112DEA24040C98D2EB +:1092000009A062B538BC41C943B0BDB1C5662011E3 +:1092100002A2861A1128E0848762D5367801A34617 +:10922000EF8048B1D5FBC7475BB4F7F78B4A2952AB +:109230008188964BEFB5F55F6BED7D92394322D86F +:10924000DBDB3F7CB0D967BFD65E6BEDB5D65E7B0E +:10925000ED1DB36A602C81C1CF4C334B64EC1AC650 +:109260007F324F316FD0C6984555A9FC9A5321D310 +:109270007CC867AE0C991689D40FE909230B59CA2B +:1092800021DD620FEECCC2965E86FD2C9A00FF8532 +:10929000A68B64D66629C3EF6A4FBF8BB193079C38 +:1092A0009EF5F09D7DF995CC2A189BCB443D336B00 +:1092B000B7C431F67C9B14B240BDB99BCD3BADD059 +:1092C0005FC56AAF6C87FCC076C9B313EACD6DABDE +:1092D000CCDF02F93BF7977A64681A83E3603EE8D3 +:1092E0000CCA50FF9AE649ECE3718CCD37074D0A62 +:1092F0007C674F4B6C0FA3FEDBB0FF65D02819E0F5 +:10930000F90A7FAE1F4A176F36C364F9DCBFC27F0C +:109310008261F96CE8B7BB4B66305FB617BE170EBB +:109320007D5FA6840E49318CD57747B4677F330FB4 +:10933000D643405980F0E832B13B7C369A74525D96 +:1093400029637FC0FF263366CAF48D53C76326376F +:1093500069861DE65DC5E735B04F22BCD6B326133E +:10936000C37E3AE319BB3A6C5C0B0B45437A520E51 +:1093700050F922F3464A6BD42C1AEF4ED66F62395D +:10938000D8EF80C907E3D9FB80AE2597CEBF06F999 +:1093900060FCC87C3055F0C1B2532C742D8CB76C76 +:1093A000250BD58FE6A91DD2450A0BC4005E170117 +:1093B0000E62451A55C6F1AA160EE16569509F471F +:1093C0007CAA6178463C869737F67C650ECF279954 +:1093D00018B3C60DD119084570274D6A1ADB047001 +:1093E0005EB3322833985F4ABA77522EC01B5DCEE7 +:1093F000E7DB78DC6251C760DEC7B2A1DE17699592 +:10940000CFE54179A3C2BCDD501E0D78E982EFDBC8 +:10941000AD2C80FD3F9EA752BF6E13E75FA3E263B2 +:10942000636D4897BE9001E992C01CC88F1A3EB781 +:10943000DBA15D19B693A8DD607B0B6B8B0A6B5FBC +:10944000F5A29531582F175EB007CD509529FE4CE7 +:1094500027F497F87B335B0FF9B32FDA97607F67B8 +:109460008D6C7637D477C9ACA99BF8650DE1FF8781 +:1094700048D7F1C84D55A90C795F9A96CADC58BEF9 +:109480009ABED73B81BF86A1EF607956DFCD9CAFF6 +:10949000CCEA4E18EF82B3FF079807785800F2CB5A +:1094A000550E77E3FE49637F04DF1B7D360FC7BE91 +:1094B0007F2CF2AB59BEE7660BF0D71479E5C0BD3F +:1094C000308FFA749BC30C4DAA33FFE3B7B742FE4B +:1094D00093FD4666463AEF99349B655F0A87962E60 +:1094E0000D1A3FEA0F5B2F77EDD5E7EBBBF5F94699 +:1094F000A67CD4AFF101A0608B6A779D8C26D9E160 +:10950000F90AF8DB6C6E3AD505F09A5F327B56C1EA +:10951000E706D5BF03D7538361E028E2D99CF9E978 +:10952000683FE0A52AF3CBA3A988FFFB9807E1BE1B +:1095300060AD9C4BF4D862550361F2AB51F07F678C +:10954000462D95776E35AB122FAF1D0F726B092D1F +:1095500061AA623100FE1B374FFD441A4DE516A487 +:109560004727F029B57B4E0AAE82764B362FAE6583 +:10957000507E86054D1680E70F623D35CABD532CDF +:10958000F0DFCEB89A51285F94BF2A3EA4FF5AEC70 +:10959000EAEA217CBD34B83E2D1D27002F373289E1 +:1095A000C5E2BC9DFE97709EF5967E5325F473FD33 +:1095B0005FBF20B9BCB8F9D59C13E350DE78E71241 +:1095C000BD617E284716DF7B88BE4B332C04DFC984 +:1095D000745BD00CDF5FDD62E679A789F227B74BB9 +:1095E000945FDC2D052D5958FF627C25CAEFED46AE +:1095F00087995D8AA748BCFC71DBEF621880FC4745 +:10960000102DB8BE98A329C667C7B2A69819A58819 +:10961000AF1B3E41F9B578BBEC09A19C7ED9EEC9E0 +:1096200063989F3C6AA10DDB7F1E5F89F8DB31D90F +:1096300021D377D987728829DEBEEBE1BBB2E32A5A +:1096400015D7CB91ED1CEEC54ECB1348E7EBFF2AA7 +:1096500013FF2B06E6DF67433A7847E1BA53B7EDCD +:109660009982F8FD635D8A81EA3F2B3107E2C3D915 +:109670009C88DF174B8A0FD7D992CD4B6B59CC10F2 +:10968000DED7A832E1BD32736562BF8DF8FE66D4C5 +:1096900077F5DB81CF71FC19EFFFF656D710DF4B62 +:1096A00033364FBF06FB7FD248FCA5F5D3B8EDDBC0 +:1096B000823F180B019E160B3C993357E6E3F8974F +:1096C0005B0F8B5737E53B6C975F1783EB7D1BACCC +:1096D0008F62C6FEAA4AEC2BA0034B8B233D33D2EC +:1096E0007AD4F493ADD0C0F5BE8779F7409A64661A +:1096F0005E09E457769642E5D95926C287F297E586 +:109700007BDF04F89F53FDD15990CF64DEB1A86789 +:10971000D40147552CF4664306294738CCC13D2473 +:10972000E7200F78DA94C09E581F066786E80FD6A8 +:10973000AB0BFB39FBDE9747118F0D199F8E46BD92 +:10974000DD78F10B930AF4B4F54A24676D1E1F43CC +:10975000FE68ECAD630B4A86E463A387CBEF4BE472 +:109760004C9691CB33D700F533359BCBB74E275F63 +:109770009F5B9BA38228F7B6BA8256043ABA3CC0D4 +:1097800050BE4F2F973D08B666A7F82C9C5E16EF8B +:10979000AB4C467EF5C81E14F17DDE8FDBE221FF67 +:1097A00066F9648F0C799B77577B36CEDB6314E5C3 +:1097B00039019CF71B132BC95E99EE95695CB624A1 +:1097C0002688AAA2CFFB8E6B018CFB1DE67DE404EC +:1097D000D0B1069437D2B10FC7067A9D71F8272011 +:1097E0005EB4F97CDB33F59113E1768697DB03F009 +:1097F00089EBB1F2E1F1305AADBC0EFBB9FE3A4E45 +:1098000087D3CF9A83AB61FCD356D03361FAE2B4ED +:109810009DEB1D5F9624ECC2EE0C94FB837965945E +:1098200001D7FD3D0E8E0F97A93B03D7DB9F247D0B +:109830003F77B6CB2C08726669BBC48200E2E9A709 +:109840009ECF40F9FBC99EE733E685C117D94E4B41 +:10985000BFAB8DD7F198D702E3CD63DA78A1341C82 +:109860006F9EC7FC21CA0FD63ED9DB1F663F90848E +:109870000CABCF367B497E9F83D5887CA7B53BB7A1 +:1098800024CA8B76E63966094A30D4BC5E3964C690 +:10989000FEBCDE5C17D0BB416B1FD17FA7E01FA9C8 +:1098A000470AD9A17E74C900C9DBA516DFD15428A7 +:1098B0005A8A7484FA53918E12F2ABD784F35624E9 +:1098C0002ECFCF387C7767C1BC1676E8E9989EE545 +:1098D000E0F375B8B83DD86053505F24B6326E07D8 +:1098E0007EDF10447DED8A8A19CDC08E31A5B86D1A +:1098F00028A7AECF8F6A33C4E2F78C20D64F4F290A +:10990000A476812ACEDF8144166C95B0CB2689ECF3 +:1099100040473F53E07BDA04E6580FD9DE2C6E2730 +:10992000BA9967B34C7662B78476A286074DBE2398 +:10993000DFA0DC3B2D59886FA45E89EC3ED9D03D79 +:1099400007FB1D898FB644F0D1967F321FED1A9127 +:109950008FFC2AF191DB323C1F81DCFC46F559C0BB +:10996000A700BE9204BE1E16F265E0FB16A21BFC09 +:109970004838DF5AD15FADC5169247939CF87450B2 +:109980007E433FDBC0FEC47D4A32DACF90A6B6CE1E +:1099900055B9FDDED72F417FD1575948EF3D60E8DB +:1099A000CB423B3FA9A8691FF247D29C92B256B264 +:1099B0004FD29C28F751D6E0FC1B9A27F9B81D001E +:1099C000FD221FD599683FD1706FA58FDB0135B49B +:1099D0003E1A375855D467937AB356217F34AE0474 +:1099E000FB08E56F4FD79645906F9865F3A09D6291 +:1099F000B5CC2CC176AC5DBFCED649DD641707A6C9 +:109A0000320FCAED734143C03806E56CFF8E1FA1CB +:109A10001E5F5AE209A8B8DE045FE632D20B9D4E03 +:109A20006F721CE0F5E0DF64DA17758E853CA42FB9 +:109A3000097A76D679939D909FB7C14A78EFECE288 +:109A4000E5E7EC8020E83F45E6FDB1580BD73397BA +:109A5000CA030BE23D7102D37E36633E45CB773CB1 +:109A600046768CB6DE3BB3383CF6125F165ABEB76C +:109A7000ABE3FAA260BD27CA066D531440BB3B1A84 +:109A8000C7E4792F0EF7A8010049C1EC7F6FAC9EA7 +:109A9000189EE7F587DA3F30A33A8DF4EB60398200 +:109AA0000D7A57CB7BAD00C75AFB50B902F6A4A57F +:109AB0004712ED27CC980CAAF89C24C60F281BBD92 +:109AC000808F87AD4C375E387C4A44FF46E8DFA67E +:109AD0008AFA8152DFE45C80B74C6BBFAAC30BF0FB +:109AE0003D6CD4F7472815ED31A38DF7EBDCD73764 +:109AF0006E481BD2FF600FD8B3C70FD9016BDFAF21 +:109B0000ED180363453B3E37A17ED5F479A34B2284 +:109B10003B2372BD2665F3F50A766D5236C90D6E8C +:109B2000EFD6A2BD2B939D3B059756E34A1F43FBFF +:109B300012EC86D46CB21B3E3D7908BE77CE384D10 +:109B4000767EE34585EC8F46B03FD06EB7F4727BEE +:109B500096F51849EF6A74BF53C89F4E27E87DE415 +:109B6000D397A5F1C8A78C3565DC043468C9F6E63F +:109B7000211CDA7E2C12DEEBB2B95DDE5858B52519 +:109B80001FFBDF2D31D4FBEB0B3F4A44FBA4B1F7A5 +:109B9000C3C48561ED96F63C4A7858BAD738ECFCD8 +:109BA000AFCB9669FE0D2F1CF0E27A3F1D94682D15 +:109BB0002F5182EBD0AE5CB2C480961A2B0FCEBD73 +:109BC00015D73D9B6D627930BF5CD44BB89FD83BB5 +:109BD00033700DEEDBE0AF049FB6FA16D1FADE3A31 +:109BE000DB62635908E7BCBB090F8E282FE2617D59 +:109BF0006155328ED35037C581FE9346B0B3B0BCA9 +:109C0000E1DEEF923F45836B7D8FB106EDAF0AB089 +:109C1000B7FE15E04E8F9B56E381F5982AEF1BBBEC +:109C200002F29B4690BFBFC9E1F46C937C81EFE0E8 +:109C3000BA7F41627BD4A1F2CC1E6ED7DD9CCDED04 +:109C400040EDFBCDD9DCDE9C18E89B84BCF78AD2C2 +:109C50001F8DF66F23F37E86FB4EE6B3A97B884EFD +:109C60005CEEB85A54F22B595CFD0F8CC1F2890A94 +:109C7000ED2798D2FF088E7B769DCBB39E09FEC55B +:109C8000FCBD2541DA3F64FBE7237D2B841D79F67B +:109C9000851BC6CE2B19B293D6755983AB010FEB3A +:109CA000ECEA4F6A50BEFD4521F9C62C037D939026 +:109CB0001EFF1547FDAEB306D721FD031B8D54BE15 +:109CC0002FC5DF807C79AAAE261FF7C1CC16C8AF9E +:109CD000037E32BA3A18DA0BB07D203F83C5E563C4 +:109CE0002AE42705E62A12CAF908FB6312FA796802 +:109CF000DF0083C3F72A21B6F2800B4E5A6809B4FD +:109D00007D153F648F1CFB7296821F353BC560F149 +:109D10002FC5A6D5B3A3988C7CBF66E0A801E61337 +:109D2000EDEA233BB6BE5BA271EA0B9F33A1DFE4F1 +:109D3000AE6EBE2E1BC53E00F09781F6C0DAEC6811 +:109D4000A1C7DB38BFB33EDA47B367383D19837A22 +:109D5000F6F0FDC42AAAA7F5675ACDFD5EF5C21F2D +:109D6000037290CA7F922D897DED6A9176F0548CB2 +:109D7000BB49EAF3CA88D7B192279C6FB4F4292172 +:109D80002F620F0F4CC1F53B00FC857E992D52DDF3 +:109D9000DDAFC1FCB68C2FF2A009E5067692CBF0C0 +:109DA0003BB022E0BDBCE7B329C8376070D37A6D01 +:109DB000E8A994EB6DA4B769FF9814DDD485E54953 +:109DC0007714925E8D1AC7EE9801DF7F2EF09A6CA1 +:109DD000E37E2EF7EA40D6F2121CDF77F76B387E6F +:109DE0006914F929938036F6384ADBD12FE466AB43 +:109DF00024ACF7680CEF3FC120DF5157427297F255 +:109E0000711EC9BB13D29E6C27F76799590DC28981 +:109E1000DF693F069C81FB59F473613F49393C3D42 +:109E20009B1C5250406C65FD3BF6207FF6981D88C8 +:109E3000A7DA9E5F1E477D596B61DD32DA2B117602 +:109E4000C6CAF49987903FCF9D39B9E37EF8F6E80A +:109E50004D073D7EA28BDE7E88DC2FECC42AC92311 +:109E6000DB7BBFCBD6DB7B83F97FB8BDC7EDFAC008 +:109E70009E68754F983C6F14FBB4734BCEC7A09E81 +:109E8000F97890BF404F570CD92BF376477F88EB7A +:109E90006AD0EE8FB01B8E3D111D40FA9FEFB69237 +:109EA0009F4E41BB07E039631FF80122C765F27975 +:109EB00025DC3FEC337A56437F8D779EFEB901D681 +:109EC0009DD205764F2CDAFB6A2CC9D9D765B60727 +:109ED000ED32C5EB40BF8706BFE29CE2F696A05C80 +:109EE000E4F35F660AE5931D64624B281F13CA47BB +:109EF000BBE725A1779645411EBE37BBFD7F41BA22 +:109F0000A598B9BCC276F8BD4BD85B5D801207E25C +:109F1000E538ECBBB384FEC6FDCF83E9C1F5E4C7E9 +:109F2000B1103D3F7EC5BC13FD3C1F171A4226EE03 +:109F300097203F96DAAEB064A8AF1EB70655EEEF95 +:109F4000B21840FFCF7FF8AE37705F31FF15EEC714 +:109F50009A7FE7CAE9B8FFF878C61413CA9B85CC84 +:109F60004F7EE7C58CFBA197B220F757338701C717 +:109F7000BB0BC4C656143501C0FE55F059324868B3 +:109F800057A86D9027A3D9DB5103E3CE6B33D0BE26 +:109F9000647EBBDE9F7E61FDDD35A8C7D7B619B8EC +:109FA000FDD82E911E9FCFBC6EB43B34BC16E4C4CA +:109FB00073FF689BC18BE35C9F6322FE03120569FC +:109FC0007E226D330A3FBC80631533843035483CB4 +:109FD0005DEB506A86D3CF5A7F6DC6260BFAC30657 +:109FE000D20DE407BE60F2CE263F6A5C3E433F627C +:109FF0009BBDA9BD8697D39AB9601DF051F9B50AEA +:10A0000037F8981A87F2323D87DB0F91F35DD8A1BC +:10A01000CF479E4F2C0DEAF3F399BF203907FD4639 +:10A02000FAEFE9395C5E5D589F25CE013C740ED095 +:10A030006654DFCE4279B54E2179B92A8DE3CB90B3 +:10A04000CED36C67F56CE25F27D817042F873FFBF0 +:10A050005A97847AB3CDC9F9F27F0A7724BC37E4E2 +:10A06000E413BC6D68E4C1786DEBA420C71787FBCF +:10A070004AFD174B72F4726830FF8FDF77727E5C97 +:10A08000278BF5E6203934CFC1E7F4B1E479228497 +:10A09000DF6D601F00DCF3D7C96568A74C9A69A320 +:10A0A0007934BC62257F6BFDCAFE0CB267ABFAF354 +:10A0B0009B86C12B42AB68F20BEACD73C13E01D740 +:10A0C0006DBBFE9C0A342D0B3F779A99E6BD2F2776 +:10A0D00001F7231FEFFB25D27B9F95F413FCEF9034 +:10A0E00019E5D70B596437E5A7F9EFCF41BD1E1528 +:10A0F000DAF16416DA29DC4EAAEF3577A11D38AF04 +:10A100002DECDC0BFFD9A03F0763ED71E4DF609D10 +:10A11000FAEF4BB645B4BBE45C8CEBFB4D26FF2855 +:10A12000B4EFAEBFCE9B8C72F5CC520343FACE9700 +:10A130003D8B508E9CB1EAEDEF33764EAFDD8374EC +:10A14000F6E4239D778F48674F3ED279BE81F9C3ED +:10A15000FBA9473A037D97093A9F3970553ED2F9DA +:10A16000D37D57E5239D37193BBCB86E7665FAF76A +:10A17000221E4F4CF691FD04F22AFF9BF0E38B1157 +:10A18000FCF8E2FF1E3F52BB91F4E1D19CE1F5A146 +:10A19000CBA4A6A13C9C67317FAD5EC49F61FD6BE3 +:10A1A0001633F9255EF9F2F3879E403BA457263B10 +:10A1B00044EBEF15C59F837E85578EBB3D0169E457 +:10A1C000FEEF16FB18B78505D0FFA1D9FD9AFD1843 +:10A1D000298FDF17783C9DE3FD36ED1785BF768923 +:10A1E000E8D312FC9CDBA9BB25F2C75AD46E2FDA48 +:10A1F000BD0D2FCF75A0BFF65490FB671B0E8C25AD +:10A20000FFEDD2E0ABA154B40B7B2507EE1F96EE19 +:10A21000FE3006CFBB613FFA494ED87E74B2D88F6C +:10A220009E0A7E1C83E7E230FE54D4CBD1AE0113EC +:10A23000F26F03ECD3A00A6B50068E627F0D2EE600 +:10A2400009A0A8E8D1EFDBB4F3CBAD3E13C9BBAD99 +:10A25000BD5210F76989267F561AEA2796E6A07341 +:10A260002EB15EFE33C79B983B3EFCDCD8FB971CAF +:10A270007EAE4CEDFBB7C4121FF61B9997EC802DF8 +:10A280007621971492537FDEE6A47D0FFD40FD3FBB +:10A2900007B328AFE9EB450A0B2980F745B3BCEFBC +:10A2A00021DD507E8722E477787EF03C9AF571FDBF +:10A2B00002F23C34DCF9B838A7C6F3DDF0F60D6CD9 +:10A2C00080DAE139AFAE5F6D1FC09AC6AA00F75DB4 +:10A2D000B7DB3C68BF34025F37970DF1E1323115CF +:10A2E0008D0F1B849FB771C947B41F68EC911CE8A0 +:10A2F000DF5DE6E17CB80CF649E6D197AE5BD60DA2 +:10A300007C1806F748EB785CAE7E1D0FE6FF49FE31 +:10A31000CCEB72F5EB579BBFE6171F9C67AFC4D71A +:10A3200057C4BC22F79791FE6C6D7F78A572EDA69D +:10A33000087CDCF4BF8C8F91E4DADCDC91E49AFEDB +:10A34000BCE01BCBB5C873835CEE07C773033CD777 +:10A35000FD9F9E1B7CA276241A480F7A75E7A96898 +:10A36000A7E338EDDB65B20FA6C8FC1CBADE6E268B +:10A370003F6DE4796BA33A459C2FF6FDF66AD49FB6 +:10A38000FB8D0CF5FA12DB623ACF6C949F3139D415 +:10A3900061CE19954364BF7FD3F3F775B983E7EFB7 +:10A3A0005978FEFEAAEDF3787F185DAB4AC0D02F36 +:10A3B000A1389661E5F623824FA245FC8445093019 +:10A3C0006758FB91DAFD3497DBCBAF8A381AB7892F +:10A3D000B5637CC6C3F6682FEE4BDC061EE7D3924E +:10A3E000EDDB8E72D2A2723C3FFEC22DCC00F37F19 +:10A3F000DCD84DF224506FF3A05CD4FC305AFF56E9 +:10A40000B15FBD52FE3F30C8779CFF07F3FF247950 +:10A41000F06FDA78DFF49C6C33E046B74E189D8716 +:10A42000BD81E73B5997F2F348FD8CC4D76FE7FA3B +:10A43000DECC25B9E01D4DE7FE572877A2CB073EBD +:10A44000467F0FDB6F5671DF817E0FD2971B92B96B +:10A450001E533C158867B0F72A304EEA03FCEFD54F +:10A4600023DB87A706E513B70F4F8D289FFE3EFB22 +:10A47000F04799BED3C867272ABDF9A83FD7DA01AC +:10A480007EDCF73DC5E36BB659397F6E93385FB21A +:10A49000E678CD7F42F30A3CCBCFC723F98AE5E9C2 +:10A4A000F96A30FF4F96ABB64138FE97E5EA92FF66 +:10A4B0008A413FE8C8FD04886E15557D84B78197B1 +:10A4C00025B633CC3FDDD8C7E3D4D205BCDAF70BD1 +:10A4D000C2DE5D94E7CDC078AF4FDFB358582C98FB +:10A4E00042C8636897F96C743ED0D0CDE3481A56E1 +:10A4F000323A0F6E40FF6709FA05EB18DA7FCFA9F1 +:10A50000FEC2BCF1789E610BC8B1E8379FC1D0EEA6 +:10A510003BFB1ECF37A8FE122C6F5CD9AF3B87A840 +:10A52000F8EAF335E8D70078C94FE042BF4D189DEF +:10A5300066E7F1F84B2DBD29027EF4E313FF77CBDC +:10A5400041B417A3D53E3A1768D8CF8DB80AD94B76 +:10A55000FE7B76571C433E6AD85F39F635AA6F1DDD +:10A560008BF66EC5EF6B1DE8A7F8F45A17C51F648C +:10A57000C8FD4BD1DE3A92ED9F84F8B09707A7A2B1 +:10A58000BD9A09F62ADABF9FEE9B3A16E1D6E4DFC0 +:10A5900026F47F43BF9BEC7AFF36B378B3EE47FFD8 +:10A5A000F7CE24DA3FEE4BF17F1BE7BFC9CAE10DBE +:10A5B0006CB4F2F52AFCDE91EB5F5BF749B281C621 +:10A5C00049BACD42E7D49A5CD864647E4BCE903CC5 +:10A5D0001927E2E9001F3C9EAFB78EC78188BCCD2A +:10A5E000A58F6B3C9D33791CC2332E4FA1760B2D6A +:10A5F0000312FAE1178AF3F91B449C85166775C6A6 +:10A60000E15B80F8602B6B86CEE5B3B1BD83F3BF11 +:10A61000889F89BEC8EDE86C8789F8C6DECEF8B998 +:10A6200012F00DD267E240DFA458984F6E6768229F +:10A63000E2F3958B06C28752F7069DA7C422D9A0E4 +:10A640009F9C0DFDEB0AD09FE278F75AA48BDAE1CC +:10A65000A842D43DA7FAEEC9A375DE5488FBCBAA65 +:10A66000DF1879BCE0CBD1640774662CA378C1B342 +:10A67000EF03BF665DAA0FB434C056537C6076CF3B +:10A680003BE4D7B7EF97868DFB7C38CFC6E36F02EC +:10A690007D1487C626BA081FCACBBF0FA0FDA1AC88 +:10A6A00053C893D166F41AAC48D7558CFCF0799D09 +:10A6B0000E03D22553C49D9C7BE5BF47FB69BFA217 +:10A6C000F9F1833C4EC8D8BF06F75FCAAAFEEB601B +:10A6D00005B3FAFD4E4303FA3D8D030DE437793996 +:10A6E0009AFCA3993D39ABBF05F9CC76079350FE90 +:10A6F000BC785726F27500E69937CC3C9BF38CB4B6 +:10A700005E9497A30DA8B7948D8CE214156762151B +:10A71000C1FD28E4A19FE5826FB4F34900D78DFA0B +:10A7200068519E7F37D23B5AC801D61C45FE44BBB8 +:10A73000C2FD1EF6E6F79F5D05F91DC21F7BF89569 +:10A74000E219E4BF5BA74848870BCEB9990EF8FE23 +:10A750008B3C6E8FD8953EE6B085E3FF30C56566CD +:10A76000BFCCE3D61423E713659DAB0BFD835FA439 +:10A77000F929FEF4DAB6904CE75B8E138FD4A8610A +:10A78000FB9BCD5C8F34ECE5FBEAC8FDCCE5F4C760 +:10A79000B13CBD5D3E98FF27D925EF0C8EFF77EECB +:10A7A00053987E7F17699F44EEE72EB1BF23FA1BB3 +:10A7B000C94ED1E23CAA86C6217E78D5AED94101E8 +:10A7C0005D1C4C958D8FCB2CFAFE9F12F13B5A5C91 +:10A7D0004C62ABBA0AE3CF07EE63E46FD3E276B420 +:10A7E000389D4015DF47040C20F7B2F07CA883E2C7 +:10A7F0007352594892683FD0CFB07D12C6E940FBF2 +:10A80000FEBC6C827F3BF3B4CB24175509E1B762E1 +:10A810007C473CC21DDCB208C7BBC946E35931BE08 +:10A82000239EF611B48E537C3CAE73D2121E0F9A47 +:10A8300002FA17F329B99C2FADB34D14E7A9C56DE2 +:10A8400068F11D1A5EAA04BE530A1665E17E418BAB +:10A8500003D914157CCA2A63FC8790FB4B0D24F79F +:10A86000B5F8BACE3C3588FC7E0EE3406D571EEF3E +:10A8700011895F2DEEE3FA747F72FE788AFB203D2A +:10A88000AAC56B68FC1246C78015C6DFFA32B7DF6F +:10A89000AB969808FE734BA7917FF1DC5203C3750A +:10A8A00054D56BE6FC1731DED6D92616C27E95A0AC +:10A8B00015E5A7C60797B35F81AE85E8BF3DDCB25B +:10A8C00037E704ACF9232DDD949EB34ADDF2184C32 +:10A8D00007E6A0A41AFD64C64CE56A8C6319C8900B +:10A8E0008075CAF6E6CEA27CC2C007989FF6E4AC9B +:10A8F000590AE8897379033B24A8EF2FF87026E5FD +:10A90000912753189BF0C46F660668DEDC1F35493B +:10A91000F8A3CC4EFFB5F909785FA07F4D1FF97DF4 +:10A9200078DC3FC605223DDC3613D9376E118FC95E +:10A93000AA457C269ECC40BE35792C9D67DB98BA13 +:10A94000BF0FCBD3CC5CDF33CECFAD79DC5F4C2AED +:10A950001265679AE65FEA0FA0BC6ACD7252FB41AE +:10A96000B9BADF1CE47E2E3EFE5B074AE91C4A8B27 +:10A970003365CC913EAB94E25174F987ADFC5C94A5 +:10A98000298E74B41F5A8DC24E15F9A834FF77F37F +:10A99000C3ECA4B726FF4B09AE8733077F948B72B5 +:10A9A000EA0613D8F1C3C8A5D4422E97CE196DED8F +:10A9B00012D86D6FA4FAE723BE8E47CF99E284794F +:10A9C000CD8EAF343911DEC05332CAC904416FE7AE +:10A9D0002C0E9FB3DA272D847E5BADB09EA17D82C5 +:10A9E0005FF192BDEE9F25DD0470B74AC27E676AB3 +:10A9F0002CD9ED856A2C9EFB2D6B7E87E2AE6521FE +:10AA000007642107DE6EE9CF55F240E5766F94D1F9 +:10AA1000DE7E479C3FBF93C5EEA81B66FFBB299F08 +:10AA2000DB873364B514F9C875FFC4776A812F6476 +:10AA3000932748F44BB7ABC8EF87EC15EE7EE84799 +:10AA4000CABCAF1CE3965BD3EF2BC7B81339CEE378 +:10AA5000F685E537E5733EAEC67A88B7E8A672D4C8 +:10AA600063FFB0FE62A1BF92BFBFBFC17ECC1CAE70 +:10AA70006596810C05D6A7C7EDDF8A74BB30F74316 +:10AA80003A8FFD41CA5B1F60FCC45BC68E4931280A +:10AA900087B224C1B7DC5E3B5AA0F93D79DCFBD11B +:10AAA00062EEF70439C4E32B4BF93D9BDA598CD69F +:10AAB00073AD88BB98E2E0F796A69467795A616A0D +:10AAC000D3D98082727ACA715F0CD28FCDF297FB94 +:10AAD0004A47B6C398DBA886CB95A96A581EFEDE06 +:10AAE00058A8CF7FDBA3CF7F67C25F0BC2F31BDD0C +:10AAF000DEE771DE2F493C8E33703573D03C5D52FA +:10AB000000EDA5E2E753BA847F97E20D7F26F67346 +:10AB1000CF4F60549EB8D7B213EF1F687E7259941E +:10AB200017BB9925338EF0417A764012718B2E3AFD +:10AB30000B6207EF7670FC415D13F47370AE4AEB65 +:10AB400038D16660D7E15A2FB790FDA4AD8B562B54 +:10AB5000F037E0B122D51285FCDE6AF46CC6BEE4A3 +:10AB600028B38A7AB532C6427DCB3F56482FADB264 +:10AB70009A29F4F5F0835194AF50980FE33500C44F +:10AB80005998BE65F4049B70BE500FE7DBEA64245D +:10AB9000AFE40A13E969E897E87A78A321C868FE68 +:10ABA000950AC5630A98B5750723D1F7C7C4BA9645 +:10ABB0000D2C44722CC54272EC08F48FFD1E7E5D94 +:10ABC000EE223F5BA17A3B969FB714D0FD9CC6C195 +:10ABD0007B478A01812B147694B397DF0FD3D6B3CA +:10ABE000265F22D73348C15C5722E320AAF80F4CD6 +:10ABF0002311F53E237B5E3B3F4CB768E58A17C7C0 +:10AC0000491EACCFEF67258A7C6A4116AD37A81282 +:10AC10003294A1FDF1CBBF20DF6AF261C7DA1F9346 +:10AC20007CB814FF85DFA7FC34BB83E3BF200DD7BE +:10AC3000A11C559086FAAED5E9517D61F94258467E +:10AC4000B3E3103F500FF2336B3ECC55C2FC83A9E7 +:10AC5000052A094BA8E78D07380E5BD5345CAFC3D6 +:10AC60008C5BCFC78DFEC78EEB8671A1DE613B8CFE +:10AC70000BF5765BCD2143CC70E34F5071BCCB8D8F +:10AC80000BE824A44E137806BE08A05FEAB0DD40AE +:10AC9000FC394DC4EF1E4EE0E3B1427D7C4D6E1495 +:10ACA0008C4FFE587D3CCD0DD2B636D4CB8F596338 +:10ACB00076223FFE52F0C9D1E81FE7A25DF5CB39FD +:10ACC000F94750AE4C895DD5864C328D7593BCD119 +:10ACD000E4DE85E40F2B300FF2EF9A02A0FB0FB2F7 +:10ACE000DF9A839D1F713E968BFA0FE4C3B70A1259 +:10ACF0002E855FE3470D6EE4435C07837C1801BF3C +:10AD0000C6476C7A3705206E07BB1453CD4E65AC31 +:10AD100089C789ABE943F303269E6269E2F35815BC +:10AD200020B86F703E42F168D78EF2FB10DED96317 +:10AD30003ECB50B0B27B6E01EEC300DEBAFF9FF097 +:10AD400046DAE5978B97D6E08A5CC7DAF8D28CBDF5 +:10AD5000142FDD38CB46F1D39344DC69E31203C5ED +:10AD600011C1FE8DECFE066609A21CBE46D8D15A62 +:10AD70001CFF8B12F77F060E98D53D61F6F8A57182 +:10AD8000D42AC5690756F278EB417BBB9EDBDB8397 +:10AD90007A4DDC1BE81CCB6579E7DD2AC553BC2462 +:10ADA000F1FA81B98CDBEB75A27CA143C45BC05C7A +:10ADB0001287E2D93BBB18F17FA73D9BCA5364AE13 +:10ADC0007FD8B7B8FEE9CCE2F664E7ADF9540EFBE4 +:10ADD000825188F7F932D8CFFCFC9EEF0FF2F87859 +:10ADE000917EDA4D05DC2E1BB473443ED22FBB2B73 +:10ADF000D3BF05F9656189374302BE9A6FE27E577A +:10AE0000E0BB6D7867A68635ED5672F0FE45D3BB84 +:10AE1000861CE2BBC789EF8A81EF72747C172C18FD +:10AE2000CFE52F0A538DEF06F9AD30325ECEFF1419 +:10AE30008EDBE9ECFE7D03EE2B7ACD44072DEE315F +:10AE4000729D87C173C2C8E171C932C1B36F3878CE +:10AE5000AE84FFC3F92D89713E1F691D24292C6022 +:10AE60002F1B5A071BDDFE10C23FB81ED6F07DE433 +:10AE70002570CB36E28B9B6F9539BF46737D8EE78D +:10AE80004DC9307E9D18FFE675BE6A27D6AB930884 +:10AE90000F75BDF51417C6AAF9B99107FE203CAD90 +:10AEA00042CE69E75BB345FB998E3A23FAE366D558 +:10AEB000EACF9966DBF839D6CDB38C1F85DB3DB37D +:10AEC000D986CF308E71369E4369F5818FDE2F187B +:10AED0003C872AC073A823C2CF720EF81AF9FEB5B8 +:10AEE00084C5DBEE06BE2BF8694919FAE326272E46 +:10AEF000DDBD11F24F6E2DA2FC6B89B7DDF3169606 +:10AF0000EFC8A77CB541223E3D57CFDB1756DC3A50 +:10AF10002D2B06E5BFE817D713EED7A3FC9D755080 +:10AF2000CF3D3ABB0CE34BAB85DFE0DCDD8CCA6F79 +:10AF30001C63E721BB8B55F2FB554789F2EFF17E8D +:10AF4000DF18FBBB328C33AECE1E9883FCFD46D996 +:10AF50004B45983F227D3667B873AFE24229340AE9 +:10AF6000F0521DC7EBD7963D95827E98EA2A9E2F18 +:10AF7000F654AECBC172C3F939C3DDFF8D12FB9E0F +:10AF8000C1FB6C625D3FEFFD90EEAFF92C9207A71D +:10AF9000E89BF021F91D984D72A0EBCCE7CD52D083 +:10AFA000CF3DC9CBE350AB2CAB92517E4DF79BCA42 +:10AFB000319ED861197B04E30C6227548E47BA4E48 +:10AFC000B230A22BF0794C21FAB5AFFA2C230699B6 +:10AFD000CBA6E7738D8FEA34FEAED6F331AC4F5774 +:10AFE000E1F8CBCBDB91F818C6CFC0F6B3BFA5D73D +:10AFF0003783FD45ACB7C8FE479203F8132E178779 +:10B00000E0E8A6759586D17D39B8EE3AB475370675 +:10B01000E13019FAE81E4FA6E429A20BAD133C1645 +:10B02000D24711706BF0A5836C636597C2853F8A28 +:10B03000662F72081C8E441C9797433B2F8B1B82F4 +:10B040000BC6BF1EE9C0D67078B64B4D5C6E88FD4E +:10B0500081E6CF68D0E6DBA39F6F4514BFD7EE46ED +:10B06000BF13B6738D2DFA3AB81B853E9D65F13D31 +:10B07000688639DCE49C4FFC700B683427CCFF6F8A +:10B08000A9FE3AC447AB1478B93F8BFCF114FF0119 +:10B09000F49E51186607687045E2A36104791809A7 +:10B0A00077241E86E8D3978CA9761F6E705E11F305 +:10B0B00069B5F3F53A30DECCDFB550C01485FC9BA2 +:10B0C0005211C5A16870BD2971BF6440E2F78F3489 +:10B0D0007B2212BEC87B7A1A5CE8EFE3700CACC22C +:10B0E0003B820F166A7E3E4EAF24019FC9200D7B26 +:10B0F0001EFE60A141F3B3EAE819797F4DC39B16A8 +:10B10000E715892F2D4EEB9273B78873E591EA49C5 +:10B1100060A7A7C65D8A47EDDC2E6ED04FC9FD4003 +:10B1200003F7DA490EC60DFA298F2968DF4FF21CA2 +:10B1300052D02EAFAD8109000DDE147E1F0DDF0F42 +:10B1400064F8B71492DEEE1F8FFE959F4C7D82CE81 +:10B15000AB3E30703F7D247EF68C809F91F87D243D +:10B16000F8A3D27C4FE2B867A4BE0A2CECCC16E759 +:10B1700042CC9F85EBC1E9C8AA44FF11C8D7AFBE36 +:10B18000C24D2B16015DCB33FDBFC076B730DF64F7 +:10B19000A46F5C8DDFC8CF4918F9E1978BFDE3649C +:10B1A000A177CF6FE3F11ED5DE518F4D44BBF198EF +:10B1B000910569DD7B497FDE25E03F0F2A3684F566 +:10B1C0009FB193FE5DFCFA7C8AE328D86C187A4F15 +:10B1D00003FE8E0A46E9DED328DE1BA7CB9776A7AF +:10B1E000E8EA8FE9C9D6958F0D15E9CAC71D2BD39B +:10B1F000E5C7F75DA3AB7FD5F12A5DFEEAFE69BA2C +:10B20000FADF3A354397BF76E0BBBAFA1F0FFA0F61 +:10B2100084DD10F0F615C2BC1788795F7F719EAE91 +:10B22000FD9F62A61C437E5CB081C7A55702867451 +:10B23000EF8B7470FBA209FE207D27B3018A076C97 +:10B24000084A9E10C3F836BDFDB1B4A78BF078B99B +:10B25000FBF805AEB90634B94F170AFBE32A761599 +:10B260008F67FD7ABAE6B3BCBF8BAE66B79EAE56AB +:10B27000554FD7E8423D5DED1E3D5D6327E8E9EAA5 +:10B28000F4EAE91A5FA3A76B824F4FD7A4D97ABA21 +:10B2900026FBF5744D5DA2A76B7A939EAE99CD7A8D +:10B2A000BA6505EED4958F446F4D9EE6B42FD7D581 +:10B2B0001FA4BB6F09C537E575FC50D7BF46F70023 +:10B2C000FC41BA17301187F93FA47BE1283DBD410D +:10B2D0006F8D1A359EEC8D124C671708BBDE37BC9C +:10B2E000BDA1C99F70FD1EBEAF1D492E5DA2CFC47A +:10B2F0003E77447D16B1CF7D8F81BEA5413690DF6C +:10B30000EA56C19F87A338DE3FC7A2ABA11ED499DE +:10B310000070BD8770C338EF4515933FE2BBACDBCF +:10B3200088FDDFCEFA289DC30628F53307E9EF79BB +:10B33000CC43E902E63309FFC4F45109E8B7E8AFAA +:10B3400040FD7F61EE5B1FD0B9D61BF157F40EC5EF +:10B3500047787E92C7D849210F4EE0390AE4CF5A88 +:10B3600007F5ABEA0AC3DB49E16F9C3749223DCDC3 +:10B37000E4288AEF9A778B44E744F3FE93A78B4641 +:10B38000493C1E24226D6DD6F0C7F7473B47A90400 +:10B39000471AEB16F61CF3DB72A81F7EEEB1CB4406 +:10B3A000FB58B785C3F7ACC4940971741D8EE8EAE5 +:10B3B000B670789E35320BE2F369E65791180F2884 +:10B3C00020A2F83D8C22E48F79FFF95636FAE9A2E3 +:10B3D000A25E98557D359ECB0456919FFC7B4CEF29 +:10B3E00027BFBD49223FF9F7004E48DD0E8F1BED08 +:10B3F0007C2DFFB080B71AEBC1F7247793847EA928 +:10B400007F587FFB7FC8EBFD9DFD0DF6C3385CF8D0 +:10B4100083F4D3FC9E85061E27317037DF1FEDFEB7 +:10B420001EE3FEBBE6406500CF45653094308ECA12 +:10B43000C8EFC7EF1CC5FD9EC9AC8FFC0BECA8661E +:10B44000D7FA49FE9688FB1767C5B9E2A22E0BC34F +:10B45000389D927D87E2F01C7111F0601FEA61C592 +:10B460004FEFBF946C792D8EFBFD8C4EBC57A9E934 +:10B47000FF91F9546127C3EE3100DF350D677FBCC2 +:10B480005AC4E3035A5BFA46E139A006CFFD2DC743 +:10B49000282F2B1E86E797F83E5478FCA3C905E5B4 +:10B4A00061F24EB141FB303964B4F9E89195352D24 +:10B4B0007D74BE6814EF58AD4D5BEEF087D9898777 +:10B4C0004609FBC71260B84FE02A0A53E524CAB503 +:10B4D000FF627C1F6D76433FE1F2F362020B3F1F78 +:10B4E000686F394EF0AE91FC7EECC49CCB4256A006 +:10B4F0008F59C1BBC0F07DCB0DC7308ECB645FEEE2 +:10B5000009A923E3CDEC562E84CBD3B723E4E94F2E +:10B510005A068A719CD6967E0D5F0CCF6B03C9DCF0 +:10B52000BE6E6DF984BE1BC03E447E7B754BC1214F +:10B5300015CA3F80BFF8DE8ED9C5E162175DA457FA +:10B54000E7083E405F5C3AF0CF07CD46E2B315E92D +:10B55000363A2758F166DE212FAC67134C57FE06AA +:10B56000700F8DC3F16412F214F8C987F2C194A26E +:10B57000D079419C6306D1E9EFED4FC3AFC9CAE86A +:10B580009D2453BA8DEC822B85F36FA3F83B408347 +:10B59000F6C94517C9FF15022FDABB4F1FDCC3C818 +:10B5A000DFB3E25EEE375C51CFE81E026B869F8A06 +:10B5B00021BED1F44C02BE50031F3B5A60C5411757 +:10B5C0000FB55898BF00EC108CDBCF19A2638757DA +:10B5D000716288C1C66A571DA60F4D38D181E2EF4E +:10B5E000E1895FF4618A670438BEA38905D13EA66C +:10B5F000B37F18DFB904F2307E8C288FF1F37CAC76 +:10B60000288F9DCDF3E9DEE7A46A042CE23C2BDD14 +:10B6100016373517E5F402C6EF818B7720B60B7D20 +:10B62000916A8BABABC6F2DB19DD0BD1CA7F2ACA9C +:10B63000936D1FB5E7A01E99A56FBF45E021C9F620 +:10B6400051C7243AF7D2976BE74A09B6F3C7A87DEA +:10B6500089BEFC51D1DE6E3BDF3709CB73F5E33F8A +:10B6600028CAA36D5C1E321FE3EF1588F20744B9A8 +:10B6700015CB717C0F2F97B5773944BD75020E8CB1 +:10B68000A923BFEB28EE77DDD1622921BAB45C246F +:10B69000FA3CD4C2287F6B511CC909430DC7779C63 +:10B6A0008BF383A3990DFB4EC1AD42AEC5A8FD5EE1 +:10B6B000EF30724F2B8F73F0771864B789F8C96C2D +:10B6C000137243ACC741B92135793893713FFDE519 +:10B6D000F81A16DA05B48F32E007F93AED1E03F3D3 +:10B6E00087C9CB946551CC1F56DFBD204E974FBC08 +:10B6F0003D4557DF352B5B576E2B2FD295B35971D4 +:10B70000B46E960BFE8A2A29D3956BEF43B0DDA267 +:10B710009E58BFC6DC6B74F5CE17AAB1C8E327A745 +:10B7200082FEA178068F05E5C3727B7612EA9FA799 +:10B730005B2610729E857505462B7BC6C9E3DC9F90 +:10B74000C1F34328FF598B97BEEF817215D25DB0CC +:10B75000EE54A8DFD5E2A0FCE32D6E4AB7B7A8945B +:10B76000FEB4A590CAB7B47828FF18F48FE9A3D027 +:10B770000F7E7FA4A586F21B5B7C947FB86536E5BF +:10B780001F6CF153FA40CB12FABEAEA589F26B5B87 +:10B790009A29BDBF2540696B4B3B6F57C4F5CC332D +:10B7A000E25EED3395FCBE7C241D3B8B841F52C4AE +:10B7B000ADD887E2563A8B306EA5BB9FEC702D6EEC +:10B7C00005E74DFD59F9FC23FB7BAA88DB6F45ACEF +:10B7D0006F55345FCF743E9CD7E3591D0D7C9FDAC3 +:10B7E000C4E990D53340E5C94B382D9E12FCC95CA5 +:10B7F00001965641510254EFACD45715CDCFD529FF +:10B80000CE91B9619E15E2FD2662BBA001E15226F0 +:10B8100070FDA9D17570DE4E0E27CE7F3878F70BFC +:10B8200078E5F26EFE2E4B4D4708D93ECADB44EF59 +:10B83000B25866FB420AA42E9F9FDE8928BA3805BB +:10B840003667206F2E5EC75448D396E9F76D290BF3 +:10B85000CA74FB22F9E2434C0539602BD1EFAFA249 +:10B860007297EBDA59D27EA82B37B956EBCAE7DDCF +:10B8700095B5C68DF84CE5E74BE60DAB5832C0B533 +:10B88000B07323C1F59198C75949A5FBE5817D5A4D +:10B89000BC05DF5F3C29F40BB36C207BACC0C9B3A3 +:10B8A000F9B10103EA874FFF3596E4D2138F1B826B +:10B8B000E84706F164C0F55F0C661F9697B27ECA32 +:10B8C00063A80CE6C73255C6FC383640FB2BD85F60 +:10B8D000BC5F8471ABB2FF712BE4CFA4FB9FE4711A +:10B8E0007321D29FF9829EF9DA7E6AB312E95FEE84 +:10B8F0002F22FF8DFE7E5D9BD85FB459B99F6E9558 +:10B90000B32209EDD6B323C439DADDAF1E5D00F8EA +:10B91000B6271FA274D02FA71A86BD3FFE4504FF8D +:10B920008F026617FCFF05F2FF99F2B713D10DD510 +:10B93000903B40EBE0ACE475CF45FCBE2E737E84BB +:10B940001D17CE4F11F855F655BAE7021E953773FD +:10B950003C013634CE132DC773300E41CBE78B3804 +:10B96000DDBD2DC9B9D561DFD5624EC742D657833B +:10B97000FAAAB0C4E00962C75E87CE8F61CDEDF050 +:10B98000E27B084A19F3A0981BC53A56A3EE56FE6F +:10B9900026539C9572F86AA6C27EC6660B318C4B04 +:10B9A000D3FA65C21F728F909B5F38AA63E99DCB63 +:10B9B0009441F9873A927D61F3F6211F7DD169E4C4 +:10B9C000F33AAC2F2FB471BFE1A242535095F05D12 +:10B9D000B50E7AC751D921B1B42C846312E1811D0F +:10B9E0008C263E8CDE3C9A0560BD943BFD9662F44D +:10B9F000DB85D483861CC19350AFBED8B413EDB39E +:10BA000002C48B0DF1726B6E350E9D5B48F85D289C +:10BA1000E63DBE98D3AB2D3D021EE6F1E27BA78B3F +:10BA20003A353F8E7E9E0F96577D07DF856CED93EE +:10BA3000B95A8BC0E77A63DFE8B9D0F5997E804BBD +:10BA40002638C717A30DBAB98205488FF3F9D53F39 +:10BA50002EB1AD5924976A488F8F37B0F0F3532D2C +:10BA60009D58CCE5EFB1221E876A771F257E1CCA40 +:10BA70001F39BA00F0F1B48115D2B9B181EF8FB599 +:10BA8000781D19FD0078AFA158C845D6C6A6A1DE1D +:10BA9000761A28FE54EE8AA27BB3B253A1B8F736C9 +:10BAA0005BB5E34EECC7A1D039D11479621FDAD16E +:10BAB00066A7611CDAE14776FEB00FE386E4748581 +:10BAC000A1DFABCDA1703B24CD40F1808AB3DA82F7 +:10BAD000E74AF9B6139588CF435D3FA07722E4EF9C +:10BAE0008B981DE117330A92B5B126EA3F90A688DC +:10BAF000F766BCB56313C591888AFBA19A4F70BFE6 +:10BB00007DC471DE8AFB02D5B688FC81F715F37D12 +:10BB1000A211CF0F21FFF8CAF34E945FAF77AD8922 +:10BB2000CB427B3AA8902D52F8D7D6147A0FA1CBEE +:10BB300044EF356878CD0C28BA73C8F4667DDE1CF6 +:10BB4000711E698CB827B75C8C8F2797A1B0F91844 +:10BB5000DD7CFFC65C36DAFFDC572CDEE914F97BAE +:10BB6000447EAF3190E201FC1CEE5A9489F3BAF0A6 +:10BB7000829FE2CE47B2FF2715AB62BC80D540EF73 +:10BB80000287AC1887BEBB8579D0CEB30415BA073F +:10BB9000B047C8B35C1BE7FF3B4AF87A8D4C733B58 +:10BBA000F8BA539E890A4623DD1CDD650158E7C5B6 +:10BBB000AF4E652AE8C15C87D780FEF7DC66930745 +:10BBC000EDCF29BFB0119F9CB7F1382EA5F9011513 +:10BBD000BFB7EEAC2854C3E00EB6383C289F76B60B +:10BBE000583C181B1F1C41BEE6380D143FAF1A7895 +:10BBF0003CE72EB11E7715F3F788760A39B34B0967 +:10BC0000CC403877013D316EFFD0066E1F2F5F6547 +:10BC1000213896BF9E43F6D548787BA2C5EDC9452D +:10BC200078361852D05F55B92E773DBEDFB1DCCEE5 +:10BC3000DF3796638B1EC3AB11ECD74686F67C6B61 +:10BC4000CC359EF961F25D8E9D58887C25CB8114A0 +:10BC5000F4E7F43C7DE1268CE705FA6DC57CA8F895 +:10BC6000839B307E77AF3D9082F1BDC78A3FE2E58E +:10BC70000981AD18DFDB577C9297A707520C903FE4 +:10BC80005E7C9A97E705B662BEBFF82CCFE3D91B5E +:10BC9000C8CE53C5E76F0AA0BFC5E4598202F9E7D1 +:10BCA000007F092CB16E919E1678D1CA9FC3EFB068 +:10BCB00001DB2FD2C8F283A25DCF08E52F8AF2DE26 +:10BCC00011FA7F45B40B8DD0FEB068776484F647D7 +:10BCD00045BB632394FF4A94BF3142FFFF2EDAF540 +:10BCE0008DD0FE6DD1EEDD11DAFF56B43B3E42F948 +:10BCF000FBA2FC3F22FAFF40D4EF17DFB3ED1BDEBF +:10BD000047FF7D36C811944B85F60D71B8CE77B6D6 +:10BD10009713FFB756F0732A8DDFB32546EF0EDF7A +:10BD200056C2DF3BBBAD84CB71A584F339F0E1C3D0 +:10BD3000C877CBDF94299EA8D5E039154439BADEFF +:10BD400040F6C0F2D7F97E7DF93A25187E1F486B80 +:10BD5000AFC1BF06E103C66DC314D6DB97C5FC9C1B +:10BD6000D1EC767B6AC3E499D1A1CF83BC602877FC +:10BD7000417E53DC78E1BAAAF6C2723CEB339005FF +:10BD8000A2D45B42F88E8862177AC151DE5188F0E6 +:10BD9000D9147A3F4193F3CCE6D6F935DA6C0ABD73 +:10BDA0002727DB79F9945F4C74A09DD5C6FC7D5E96 +:10BDB0006CEF56C88E3FD45EE640B967B22F70E094 +:10BDC000FAFDB894E3BDBAA1300AE5B5FCA081E460 +:10BDD000F711075FEF3BDC3CCE0AF40ADDAF0279D6 +:10BDE000ED411D51C042AB506EEE7DE8E05CEEE7E8 +:10BDF00063F6B115747F493B579794B07D406D0948 +:10BE0000C74FA6D0230AEA174877958B7B3701EEF8 +:10BE10008FCA54983B35ECFE706D89CCEF3D69E7D5 +:10BE2000A1722DBDAB95B152D19D23A4DDA3CF9BB3 +:10BE300022F48612A15772DA414EEACE4F1CBAFCA8 +:10BE4000B74A849FC7C33C68C74EF9C5069287E7C7 +:10BE500051BF4923CBBD41F92BE4F12E4400CAD197 +:10BE600000BFDF7E6843D9AF90DECBD719E83DEB4A +:10BE70002B95A30AE218F090E797482FC0845270E0 +:10BE8000DF74393CE4197D71F4DEC765F091F76821 +:10BE9000791CCADB3CBF42FD5FA2372E83AF67250A +:10BEA000CF713FD2D11925EC6A6000F4DBC545752E +:10BEB000E1F9BE49F853B438652549E1EFF58B7BCC +:10BEC000B2B2E0E3FB99578DCBC1F78A9AC8BFBFE6 +:10BED00062DF3D6EB4DBD71AFC0ECC1F8B9B368025 +:10BEE000E32C874D3FE26F2FF641EF72BE7D33FAB0 +:10BEF0004DBA8326ED5DCD10FEB30FE38FB4773BD3 +:10BF0000DD64AF897CD5CDD530DF6EC5518C266818 +:10BF100047C9E44D46B049F799D8607DBCEFF7F4C6 +:10BF20001183E8EFC64DD52097F64531DDBBA5FB63 +:10BF3000D0CF4EF9E99BF09D5218EF4619F6663BBB +:10BF40009F99B5C976F5103CBB9FFDEEA655E8B0AC +:10BF500013FB1427E3EFCD9F51FB6390B4B05F59FF +:10BF60005F82FBF5AE1389E1FB75AD7EACA8DFD037 +:10BF70003BD0F08C4AF53B4A801FEA7B06624A08B8 +:10BF8000DF0315E1F563841F20ACFEA6AFAB5FA80D +:10BF9000C1F3CCDB3797F0FADBB0FE59B53F9162C5 +:10BFA0007A22E089BFB4FF9D04FF08FD1789FA6774 +:10BFB000426F53FDB3AC3FB1348BDA3D85E39C7BDC +:10BFC000E3ED0A31EF443CC779D7E6FD197E6FC136 +:10BFD0003E707FA734A9F8BDDBD2E140FBCD6AEC0F +:10BFE000F0A11CCEC5F7C7260CA5CFA2F2187FE999 +:10BFF000F7487EEEB6B0F85AE4D76603ED6F7AFAEA +:10C000000D0F205FEE489BE8C0FDF33E535F5909DA +:10C01000DAAF076C64BF1A323FB5A2DFDC5CC0D771 +:10C02000BFD5D9E42981BC35BD84DE0F95EF5DDE37 +:10C030004DEF98DFC7DFF7527E6CF2EF46FE0A2D18 +:10C040002F5C18B6BE7797F27B96EB5EB36DC0FDA2 +:10C05000C13AA3A7A300ED70BB42719FCA8F0F4ED8 +:10C0600023FBF0E70646F21FE65905FDB6CD55E87D +:10C07000F7300C94CEEB2B217CF87C55502F2341CC +:10C0800091F07ED0FD8ACF82E71D6661D7EDF0F09A +:10C09000FB61DAB81784FD79A184BFB7B623EDC27E +:10C0A0007B8B5DF8FE8389EE75DA961942A618BC83 +:10C0B000E7B6F3D462A46774FF3ABCE71C95A238D4 +:10C0C000707E3FAD85323A97EBA6EF817A03ED1B88 +:10C0D000E29719BCE87F8CCA35E9FC1D361827DCCD +:10C0E0001F1233DAFF47A4E7B837951B11CFEEBB19 +:10C0F0000DF43EEA83EE772D068033A65CDFDE3159 +:10C1000051DF3EAE5A5FEEAAD59727CED297BB6FCE +:10C110003745F875F4F9268DAF4026D8404F45F1E4 +:10C12000221665BBD082FB9EB5AF4531A2CFCA4D6A +:10C130001D05B83EA307085F514551E417589B6C95 +:10C1400022B9BEB694FBF50FA79B6EA43CCC0BF9AD +:10C150006347DA51DA8F5C8217DBA9BF62FF3616BC +:10C16000F61DFDF2A3BD96521E57C3DC15E8C7634A +:10C17000240F9F95BC9E4388EFB7B8BF624733F743 +:10C18000633F388BC741D20C2A70BDF3FA31960D4C +:10C190007DB82F8BB1B5DF8DF19D91784D14E70DF2 +:10C1A0003BF0762FF29D9FBF1BBD46BB6785DF2B03 +:10C1B000E8D604BD8B366BB478EF4FD809B1EEF8F2 +:10C1C00092B6B0FB1A89C26FF2F0C47956D41FFB45 +:10C1D000C43B2283FDA934280F79457F54A9E6AFDB +:10C1E000E1ED3769E73C229FE0E4F97D47E26EC468 +:10C1F000F5B569565C19EEF7D70AFB2E36CDE41D6E +:10C2000005F37AE49829208D81BCC28E18C12ED8FE +:10C2100017C7C735BD1E15C07B818FB8CBE99E619E +:10C22000AD80FBB94ACF3BB8DE07601DED84FE1F31 +:10C230007179AC65E2DC3400F051A8159828876A62 +:10C24000CB68BFFB88D76345BDF9489AC78A71DAC6 +:10C25000D664C581716B716E85DE897BC4E277A07F +:10C26000FD13078AD484E749E91D53E97E1DE0DA0E +:10C2700050C18F1A98886FC4F8C27881CF1DEE051F +:10C280000E7C97C195BBFF5FD04F1F8FFDC5F07629 +:10C290008827A7C0D3AC5295E07689FEE3173C47C8 +:10C2A000F5F1A7AD22AC3F4147D35416C47D9A3671 +:10C2B000BED6CF60FFCC4BE7006B7EC5F1B62A9DA2 +:10C2C000BF8F65BA8BD17EEEB94AFF5EE4B381E4DD +:10C2D00028927729EE942AE4A394635B67E0BD8BF0 +:10C2E00035BF8AE2E32CE4FC9EA230CB7538EF0424 +:10C2F000BF03F118B95E938F74D421536A74895CBB +:10C30000BFC90A6B97E32E5DC7C96E5755FEE8613A +:10C31000D673C47A493E36F07DEC3F725D6F8FFE76 +:10C32000602CD72361DFE5CBE7DBA4FE7524879380 +:10C33000155A67E911E3E13B7B98979841C5B8E846 +:10C34000DDA54EC1C7A0974A91EF1D936CFCBC9D23 +:10C35000F8ABEAF90DDFFD35E42FE0EFF3815AA9E0 +:10C36000C73AFA482FF6F80BB0FE36C5FF38FAD3B5 +:10C37000B71D4FA2F72BCDD1FCFD5153C47B299A99 +:10C38000BED85DCAFD486AC4BB9BDF34ED4E4B2B63 +:10C390007678B0BFB77F6B49F8C7DB3F6947BA57BC +:10C3A000D9604D3F5372F326BCFF6C7D93973F0DD0 +:10C3B000F980827859467E97C31977D2FC5BDF33C8 +:10C3C000933FAB54F66CC63CFBBD95FC717B0F4CA8 +:10C3D0009C8DEBA4D55EA1A2BD7F40ACE37F156927 +:10C3E000E4BC6493C78FF640E4F7674B35FF9BE7E7 +:10C3F0007817D0B7749789DE711A8C8FE8B2F2780B +:10C400005461872E10F26CC1C1F5198718BEC35153 +:10C41000F75A29B45F60AF4E4478522F4ACC0FF2DE +:10C420006F9B389F4D753D27A19C49731DA9447989 +:10C430009FCEFA56A1DC486FD29F97A55E54A8DD27 +:10C44000BE142FF5873F18076A62624DC7F9D92AD3 +:10C4500094F329FCBCC5E488E271A1EE6ADD3D6A73 +:10C46000ED7DDBB7851C35014E8D6590DA147E6F4E +:10C470003FA2FEEF443D19FDF6E8FC771C3D4EFD62 +:10C48000DA944FC3E34D715F4A426B193FFF043C9E +:10C4900005701FCA62E3F879A9D7AB86C7DFA68209 +:10C4A000DC359761FC4980E24492C5BD082DAE079A +:10C4B00030E044BF9B16F7B193E9ED112DD5F6E7B7 +:10C4C000B9CD32ED3B8A5FB5F2FD413B0B5A25F405 +:10C4D0008731923BB91BF8F9B4E617BB0D1713EA85 +:10C4E000257C0F97C6EBA6386ACDAE02FA92DC59CE +:10C4F00017F1CE94F68EB66134E78B6D2D0EA2A3A4 +:10C50000569EE68FA4A3FE9C53AB977A3195F9E330 +:10C51000C3FB0D527FA9CDFB891F522F6650F9B680 +:10C5200016F532FD678FD07F32F1CBC8FDA751F9E8 +:10C53000F6D0BBCEE9808A9F0EEC77FA54942BA1FB +:10C54000A99E61F09C7A8F5E4E8EE9D1CB5D0D2F56 +:10C55000DB14AFAB0EF0BDED1E83A78B61FCA9BE53 +:10C560005E4DD66F9CFC5D6BAD7EC83513EB2FE343 +:10C57000F5BF754A5FDF577920B23EC177FD457D33 +:10C58000BD48FA44C20B7025DC1406D7248BFEF795 +:10C59000DACD9E7B095C09B784C175835B5FDFBF21 +:10C5A0006A78B86E2C347F2D5C5ABDEF4CB8B27AE5 +:10C5B00091F39859631E01EFBCFE2DB3AFACDFDBE6 +:10C5C000967C7DBD3B9A23C7096871DB3A7B24BE0C +:10C5D00099DBEF0E364071269ADD11C71C22FE8BC7 +:10C5E000DB0DEFE07F93197B60B46FCEE804C4BF2E +:10C5F000F7F64755BC1FC3F515ABE5EF56C2BEA411 +:10C6000034FC5DEE21B85653BF2F61BC13E9598B42 +:10C6100007EDCEE254664946E3CB1DCCC6F7C7EA28 +:10C62000476BF29AC7971709DC3D9BD2BDDC49EBFB +:10C630003C1887F07CD371EF1DEDBD67F4F8A1FACB +:10C6400023F95B343C994CDDF47B1D06EA6D1ED466 +:10C650000FEF6211B4DB75B3398476B516877A3C77 +:10C660007ACED10495DE3D588DFDCFBE65EA1ACC59 +:10C670004B87E3D5E536BC37D5AFDD2F5D83785BDF +:10C6800066F167261AE87CB500F7C3CC172F2E2376 +:10C69000FB4A878BD3D0E0A99638FEA3D2FC0FE3E8 +:10C6A00038D586BE1D3EFCA6F4F17DB62381BFBB06 +:10C6B00084EFEB0CB3FE353C54897E0E193D5F0EC2 +:10C6C000C0FC0E6D8CA57BF80BE26F99836FB22CCA +:10C6D00034F812F1003D0CEEED04B76D6E6632C217 +:10C6E0006D14705B1204DEBDB95F07F760BCCC7DD2 +:10C6F00092F67E3AE59F0F38E9BEBBD9F0F9BB331D +:10C70000510F971A3C68776E03FB02DF77FB3F02FD +:10C71000DFDBF18C258EBED3BB6F6E71EFCBBDC955 +:10C7200040EFBCF8AA5E203AED6AB07970DF3E9720 +:10C73000A9F4EEEA7C710FE60F95FFFD723FCCEF96 +:10C74000A5D1FE83388F3BE20D19EF121CFE627AF1 +:10C75000476BE295C5CF6AE7F033847DB050E07156 +:10C7600026F352DCEE4DCC6FC471DF3E6BF2A25D5E +:10C77000FAB68847BE8505E8FBAD2C48E96D2C4428 +:10C78000F5BF872FCA42FEADE8D1E9CD005FDD637A +:10C790000579B81EC3F0FE06D219F8E50E17E79723 +:10C7A0003F2621DE3B13AE887FEB248EBF0746FB7E +:10C7B0007FC3D7ABEAF2204C8E4969E847195C3F4A +:10C7C000D5099CFF1447DED7AD9FBEF3DA7D7FAF5E +:10C7D0002DB902DFFBE23F3778EFA278718CCB777F +:10C7E000011DFA547ECF11C4863D0074AAA9942974 +:10C7F0006E6FED67E27E363A31A0DE2FC7CAF43E97 +:10C8000099762E395DF4373D8DDF57ACAD9CD91646 +:10C810000B7899F2657F7908D29A34FDFDC5A9AEEF +:10C820002E7AD27C5AAEFEFB8DAC830E886B4BF415 +:10C8300071E6D323FC9F87706CE0AB8BA345BC648F +:10C84000112B0ABF6FF01DD1F67CEDE7A673307E89 +:10C85000C918FF57488FE5DFFEC31CDAD729ECCD96 +:10C860007130BF867F97C99EFCA80566528071D53E +:10C8700016E60583FF24D815983FD5E2A6F434D8F0 +:10C8800001987EDA5248E5675B3C949F35C667198C +:10C8900003FDCE6BFF4C417DB4568BC7167068719B +:10C8A000856B45FCC40AFBF2E318BFB08202DE19B7 +:10C8B0002CF68E2908FE9D3DDD473185EF32EE4393 +:10C8C000566C94C8AFB3F0887F0D9279F11BFDD3FD +:10C8D000514C8CFFCD8944DCA7D7A31D0BACBF22E4 +:10C8E000CE9B340658C0DBFBE1D178A8FFC7960980 +:10C8F00004DF272D5E82EF4F2D3594D68FF1A5539F +:10C900003DF619BDF3F4ED673E54F0F7B34DF64A2A +:10C91000E4BFBFCECB8241C0EB662397EF9B41BE05 +:10C92000E3FAAC2C9DB1FD1E86F2D75F80F3BC29E3 +:10C930006EFEE478F83E7DC25C05EBDDF225E8A0F2 +:10C94000AC213EBC1C5F9F794522FC9C79C549F80F +:10C95000D0F0542FE875E660F177F0DDB3578EC95B +:10C96000147F7AFEA281E03B7F3C8AE25323DB2FD7 +:10C970003F909384F6D89F807E78F0B1FC4031F9E7 +:10C98000E3FFF4ECBFA8E171BF7F8AEBBEF03ECAC3 +:10C99000A9FFCBE514D89B27B7A21C4B4BA1F77B73 +:10C9A00006E3D5585334EAB10693585F206730FF49 +:10C9B000A728BE0FAEF8796A15AE171C0FE3BDCCE1 +:10C9C000E2F760407F1FFC10FA3BB8D54DEFFD7CCD +:10C9D000BAEFB16C1C7F6FF7C2F7B742FF6782FCFA +:10C9E000F7609C61DD675F4479BADB467ECBB512A8 +:10C9F000C085FA744F0AE50B2525AA999C19411E9A +:10CA00008722A90ABE7FB6ECB92D29C85F784F1DD1 +:10CA1000E3EA5FDA184D72EA25A3E78366EC6F3B21 +:10CA2000EFEFC987EEFDA807D307EBCBEE4539370B +:10CA300086C7312EF8C9D2226C0FFA9A7EDFF3D363 +:10CA4000CF4B21F48394761E5A8D714C63B67D686A +:10CA5000488174EC6EA915D3E2F469C7D07F70D712 +:10CA60001895DA8F7B264BC6D8F4A294E0FBD7F357 +:10CA7000B8119D7E2FE9FCAC0AB7999A9E2F92BA05 +:10CA80004F77E1BE38E37819BFDFC5DFAF3ED03B5B +:10CA9000F39DDB18CE032C08847BAE89E22E583040 +:10CAA000D085743EE32FF4D0BB2ABEC016E4AF336A +:10CAB000FE44BA5F78D01088C1DFE314F880FFBE6F +:10CAC000A1E777BF1583F114B1FB8D0C7F2F76FDA5 +:10CAD000D88129141F92AED27E3C7DC70D35889F28 +:10CAE00086FD07BAA89F65160FFA63971CF89CEE9F +:10CAF000BDB0A93C0EF5CC7E9E7FA0DA4BEF9D2FFA +:10CB0000E9FA33CFF7F928EF930359747F623EB700 +:10CB1000771E13FA8CF58F66E1EF2169F47A008AAB +:10CB2000B17C73562019DFBDD2F420E8AF8770FDC9 +:10CB3000A1DB91DA3B66F27BF257A8BF4C421F693A +:10CB4000FD3D66E2EFF4A218C1DF8BB3CDC4F5EE74 +:10CB50001E9037C82F9ADE857177E0BA3589FB328F +:10CB6000A9A064C7C27C521F3373F97D85E347DEF9 +:10CB700067D5EC90D9F1AD746FF5D354FFCF701C2D +:10CB8000EDFE2A533CF4AEE0EF53BD4F8F49E0EF8A +:10CB900075E01C402FFE02F30D32D85139617694B6 +:10CBA000E5CAF4E2DF52BD07709C2BAD1F29872731 +:10CBB0000AF857D80D8487158F9AC91F3651DC4360 +:10CBC0009D78FE7834CA93157F2E23B9D2CAD8B087 +:10CBD000F879B985C779FF1BFA1120BDF68B7E99CC +:10CBE000F623470CCB8E827E2510C87F38D01A5B87 +:10CBF0004E792F92FBBA2F0CC3EE17B514E8F52E21 +:10CC0000C9E92FF5FE87EBBF74D0EFCD64B6B82B22 +:10CC10009AF7D0FB3EFAF96BEF6CC1FCFA51BFAF4B +:10CC2000F8CC40FCBBE2B332929BBD57385FABCB34 +:10CC30007B12E18C9C0FC0FF29D22712FE417E1F80 +:10CC4000B832F8BF2F31FA7D43A0AEC8BFDD2BDE6E +:10CC500031E85D5A42EF691CC4F748506ECEE0F7E8 +:10CC60008E7AC5FDE4DE0407BDF7F19291E703B7C4 +:10CC70008AF6E27DC8DE5B53F87B1DE6A65F97620D +:10CC8000FFAD3C3EAED718A4DF53FBFF00D94A30BE +:10CC900097008000000000001F8B080000000000CB +:10CCA000000BE57D0B78D4D5B5EFFECF2B33C9242F +:10CCB000998490072161F220040D3879F10C3040FD +:10CCC0008268D10610058C71420284BC088FF6C4BC +:10CCD000969AC100A2C51A8E886851070A14156D6C +:10CCE000A888A8C13382505A5F69B51E5B2D4D04D8 +:10CCF0009F3C1282F6620FB7BDFBB7F6DE99F90FC3 +:10CD000089DADED3EFBBE7BBF1D3EDFEEFF75A6B69 +:10CD1000AFB5F65A7BED69FFD12097D7C998D13AC4 +:10CD200037E7743E63EFF90C5E7334632D9AFF5658 +:10CD3000630163DE0B16B63B8DB12D31FEE4E53C9D +:10CD4000BF65D95554FF3DC666B6E5E0BB3B2996A5 +:10CD5000A707FF66BCBDD4CEF3B93CCFD39734361A +:10CD60009FCA67BB9362787E6178D468760DCFEFF7 +:10CD7000F0EDDE1A87EFD9D4CF10236BA47A69A225 +:10CD80009F3F9A45BB3F30FE97C4D8A366E6B5C522 +:10CD90003236DEB568B8AB9031CF8D1126168D4294 +:10CDA0007792C6E7F348D57076AFC6B3AD0F3116AC +:10CDB000CFD87C2BA33F351E2A5AC730364F7C660E +:10CDC0000B16EFB679F87CE655DBBAB4D17C1DD5ED +:10CDD00077453AF978F33C467F5814AF705389BBD6 +:10CDE000335BD4FD7B3AC675D3B8AC6A10CFF0D4B0 +:10CDF000E4AF647CDC977BACEC5E0E97BFE36F4ADC +:10CE000020E510636C30639FDAC4F8F56D531F386A +:10CE1000ADFAE3FF565BEC1BB56894A7FA181F7FC9 +:10CE2000FF104F01FA5F7EE8BA074E5B03F5AA16C2 +:10CE30009764314360DCD07142C76B01DEF878C380 +:10CE40008047DEA485171880BF369B0FF863A69E27 +:10CE50003F2CE5F996F957B9EEE5D99973AC6E8D8B +:10CE6000E3A1F740982F4CC3F77037D6D57238D26C +:10CE700067E0F9DB3501FF168DD177EF7EB36F37B1 +:10CE8000FF5667F13DB187B7AB7B79A48B8FCC0E92 +:10CE90005AF87F50FE6284288F72A7AD2F40790226 +:10CEA000E1F725B3339ACA7F6D64541EEECF8AE151 +:10CEB000F06E4AF4CC71F1790F09E3F8B7A35FF192 +:10CEC000FDA4A4BF93BC5BE0D7DB1849FD3299F702 +:10CED000FC7090EF5E5A8F3B6931F2ABAEA6F578ED +:10CEE000300F3E2FD6A0D17A4F3A7CF764F1F293FF +:10CEF000ED83691E71921E4E96FEE58DB1BCDEC9B2 +:10CF0000434617FAFCA0C9E8B744A15CE0439B6321 +:10CF1000CDDAC6DB9D7A31D215C6CBCBEEAF7D1D07 +:10CF2000DFCBEEAA9F4569CD9A1B19AFDF79D7FBFE +:10CF3000A99E9C2BF15156C75B05E1F14E97BB1E94 +:10CF4000F87DC4E569C47A97E7742E619CAECE5B28 +:10CF50003A1E6346C6DE1DEA5985EFDD2F7CB20717 +:10CF6000DF399EB24A47F16598389D807E3B471372 +:10CF70005D2F97F49B9EEBB903FD713896B30CC6F9 +:10CF800022723A2C98075B33F85BD1C9E7EDBB0FEF +:10CF90006A7C9CDAF0F6064A8DBED1E8E78CE68F13 +:10CFA000D232088E1EECBFB30E7F14F0E131F03C9C +:10CFB000C74FED5EFDBAF067E2F3AAC5FFF076B5A4 +:10CFC0006D46B70DFB87F92C987F2DB304EAA7892E +:10CFD0007D083AE0FDECA4FD6AFFA0FC871C0F353C +:10CFE0004F8CCCBB97E3A736E6D04F26523DDE4EA2 +:10CFF000ED17E39579B59E2BE723D67756EE83B3ED +:10D00000FC8B19F4B32F4CD03F13F471FE892449E3 +:10D010003F826ECF3F31C287F9C4CB7D735EF31A76 +:10D02000C2D1EE47CCB59BCF8BB9DAC6CC1E85D921 +:10D03000B78D9913C9D856C9D76A07B58D01BF52A4 +:10D04000FC8B59DB46CFE6E52CBB6DF49C5101FE11 +:10D05000C74ADBB2E8BBAF2D0BED0F1A5835E0A97C +:10D06000E653F354F20E828755ECD79AA7AE26F812 +:10D07000A8715AC047C08FC12FA2AE5CF7CB2E4D0E +:10D08000ECFFC83109E06B03E13F3B71500E58C91A +:10D09000F90596DBDDBCDF11DB2CBA7E54BD913E79 +:10D0A000FDF75FA17F4E6FC342F039C4D8F34A1831 +:10D0B0009F2FFB198713BB72BC3765BB279FECC33F +:10D0C0009F51E09331A7A21B27C149E0E90F1685C4 +:10D0D000A7D5C99C5FD70226E901781DCCF524436A +:10D0E000AE9C471EF22686E779DA20E1AFF20AEE1F +:10D0F000A1F477D71F962477F2F6FFE532D0BC4231 +:10D10000E1BA96C30FE52D66767B296FFF79F38927 +:10D110008CD3E6C07A3E6E76BBB9A8E9CB2FD99600 +:10D120006BC5BE5BBA3DD7BA2808EE2D7BF34F38EE +:10D13000395ECFEE356124D662F2FD64421CBE1B1F +:10D14000DBBC8CCAAD6E5EFFACFDC89BA8B7647B30 +:10D150004C9ED11968BF745B89BB2A08FE57EFD576 +:10D16000E363549B3E7FCD217DDE9CCB881EFED1A8 +:10D1700076B97E7D3EFF843EFFC93BAB6FC63678F5 +:10D180007E9CD8379FFA227D560ED7EAF7679C809F +:10D190001CFDF4E0F351C057ED9FAA8E2733AC433A +:10D1A0004FA71C8F9A89AFD7BB47237A59E60BDD6F +:10D1B000BF926F5CB1AFD712BEB0B382E92614BF85 +:10D1C0006758DBCD6E4E5F754D6F67408FA99EC56A +:10D1D0000919F2BB6DB385D9AF1C6F20FEC1EC6E8F +:10D1E00027E3F457314E944D689ACE4EF1FED8A6FF +:10D1F000DFCEC07EADF8B146FA46C5B3235E05DD8D +:10D2000074ED5F703DA537CF24385432B705FC70FC +:10D2100069BBE68FE479C738E7A14EDE6EB14F7384 +:10D2200061DE8BD68505F819FFB76A53C83CB60492 +:10D2300095F3F92F3DF4CA571AEFBF7ABBBEDD3222 +:10D240000E2FC88F9A5D7F0F0BFECE152182D784DB +:10D25000F61D46AC7BB19CBF927FCC3B99617D13A0 +:10D260004413761AFFE172C332CC539C5B1890834F +:10D2700013B688F69CF15560DDF5768B13EBAEB7EF +:10D28000327F049FCF89488BDBC1BF5FDC1649FA30 +:10D29000C39230E6B5E651CA6C7968E78A46BB8F1F +:10D2A000DF32929E54CF790FF5F3B8E66B413F46DB +:10D2B0004DE47F26F2CB989FD603BA7107AFD3A770 +:10D2C000CFB3D641A497D499FCAF002E35AC93E0F0 +:10D2D000CD383EDD0A8E1C6E757C9DEFC542FFD2B7 +:10D2E000B75FCEDAA8FEF2437F0F0BFECEF54C6699 +:10D2F000E5F5B787F394E6EF23381A2DCC6DE0F30C +:10D3000034DE19EEF3921E521A0E3A354B7D79CB6C +:10D310003DEE2CCC7BBDE6CE72808F6DB6B9C0C71A +:10D3200016EE1072684B0CD75FE3486FA6F60BA1A0 +:10D330004F414F5920F8DD9698363FF8FE9607D3B7 +:10D34000843EF53723C1A5E73E9B6FA7067D5AE8CB +:10D350003D5B368FA0F6E097A44FDD1729DACF1694 +:10D3600070DD32D8E1F3F2FC1F31C524E8D9EE2C90 +:10D370002BB5E37A5A5A404E297DFA67C33C7701B0 +:10D38000DF6ABD4AFF66D5DF4EDFDC2DE567CF667D +:10D390003E4FDEFF69ADF4B821481F7E2057F0FFF5 +:10D3A00031D3DC7B643D17EA551966DF3B85CFB787 +:10D3B0006AABC1D99216803B73BBB300E7D39B6DB8 +:10D3C00079A0B331D3189D274EE60A7E1E51C0DCEA +:10D3D0003E9E6E97FD6ECF35E8D2C4704E7FBC9FE7 +:10D3E000D3257E33F01B59506A813CE4329CF87996 +:10D3F000E83AF6E60AB9596529FDCDA47EE6D34799 +:10D4000007C5426F39BD42DB29E625F03CE6DF6DFA +:10D41000AE165AB7989F823BA79B4292F7926FC570 +:10D42000F4D189EF091B47ED66A54F03FF9A8E4E95 +:10D43000089E5BEE1B45785C28F1CCEEB3493A615F +:10D44000ECAF282F7152F9379DB7D43A391D5039B6 +:10D45000C7B71FF80E3D6F297C3393AFB0347260AD +:10D460007C2F1A173346E3A04E36316F18870B64B2 +:10D470001EC1E51E93EF2E3E9FA12601FF1493A02F +:10D480002FCE9DBDE17954DF6DE1F98A07963237E1 +:10D49000AF5F91CC5C9AA8CFA2519F7763E42964D7 +:10D4A00006DA55448B7E2B1298EF2EA9F7835F6521 +:10D4B000224DA77EDD8658D13E2A8FDA7B0DA2BD94 +:10D4C000DBC4D3611962BFF4AC0FA3FD5371774A7B +:10D4D00016E860D6343D1DE4E709BA51E9E3794E18 +:10D4E00029675C89D8DF8BD68D24B9D1622BAD7FBB +:10D4F0000EF87A3A82F4C18A0DB7DD5088F93D33CF +:10D50000081A0EFBFCC6FD63406F8BD62DF8DEEFCC +:10D51000711ED96BA3EFED799EF3B9D0B73567F9DA +:10D5200073FCC3A279472D89BCBDA76DF6B91779E5 +:10D530007AA377FF9BD00B6EBCC948F56F646D7FF3 +:10D54000F923F8C23A31CE0DDE0BA644DEDF0D45DD +:10D550001A437997CD91BA82CFBF42E2EFAF721FE3 +:10D56000B4D8D8FC5FDA31AF94AC74FEFD0668AA7B +:10D57000FDE881E3F2A49E3855DB0EBD67D874B197 +:10D58000BF547DF4837E27031EBC9E59C245E539F6 +:10D590005CA97ED5C6B0AE8C28A466FF089E2E2E50 +:10D5A0009866CBE3F566A5B3193837F5DC61643BC3 +:10D5B00069BE3D15B4EF23B39CD8F71EC6FCC4F773 +:10D5C0007C2389EEBBA6F674DDCDF35D3B46B85AED +:10D5D00088AF8BF3FB620723F9DE3555F035C55F65 +:10D5E0004E3A3A23895EE579BE5292C6474DD3B78B +:10D5F0008EE5F52BED962EC883C50FCE8D72F27990 +:10D60000566EE1E7792EC7D826FD799E9FB733F293 +:10D61000065F792E0F3D7F83664047559B34A2C33A +:10D62000612D2E4B12F131CD81F555D9FD99907FA9 +:10D63000552E9B0BE5679BDD0F9CE6FAE1F9E69919 +:10D6400094B2CB1CEE7C9E5701797CDF8FCDF7B86E +:10D6500000A78AD60A3A4F46E478883F2D97743758 +:10D660008B835903BF317526611F76E5CAEFB18EF2 +:10D670002C3BD1B38D010E5D664716E6D5B5DE664F +:10D6800080DC9C7597A06BBECFAC26DEFE1E130B14 +:10D69000C77EFF1BDAF37596AD3595EEE0F9A1561E +:10D6A000668A8C055DE5125DFFBCC063061C3EFD0D +:10D6B000111B07BDA072D3669A8FA20B66EA281EC3 +:10D6C000043D6F775A1ECED78A8E7E5E30EDDABC6F +:10D6D000607AB849233AE0E92B19440F7366113D8B +:10D6E0004CF367AEE4F32A31D63137EC0C89CC1514 +:10D6F000C6E7DFCB7A489FE8E5FA04E499E2278A97 +:10D700006F703A705BE303F8DDD3CCA7C279F2DE29 +:10D71000662BA54F363B9889C3775F7322E59F69D7 +:10D720007652DAD69C4DDF7FD9ECA2FC81E671946B +:10D730003FD8ECA6FCA1E69994BED85C4ADF155F01 +:10D74000E270213EA4F88AE2478A9E145F0AA5A3EC +:10D750007227F606B527BEA7F81DD661C80BF023C1 +:10D7600085DF74ADD49B98063ED6B900FCA2C47880 +:10D77000F6E9E7397C7BABEDAE3027E022F85EAF0F +:10D78000DD4A723ED5C20EE1FCDFB2C2DD75779094 +:10D790005CBDB55A63A620BABDADD1C64C41747B01 +:10D7A0007B538C2E5FD6F4F6B104DEFFDF533C5E74 +:10D7B000E0E5E49D1F3FFA9FFCFBE3777E3E1CF80B +:10D7C000E6F3D8FD10C65D13DE378F58E4D79949CC +:10D7D000CE0C0B17E7A461E1E29C843FE0671113D4 +:10D7E000FBF4F13BFF4AFBBCAB29CC6984FE017C16 +:10D7F00071F87E20F1B5A8298CE058B1FED4D3CFC2 +:10D8000063BFAFB110BF5BB44EEECF8D1CAE417A9B +:10D81000DB87498CF433CDCD581387DF873FB2F8CF +:10D82000B9EC671F6A569FC61B6AFCD054C6BF7B03 +:10D8300036FEEA3DE8DB5AD309D28F3D56BBDF887E +:10D84000F979CD6783FBD39A8E533DD63934E6E31D +:10D8500008DA8A0C708C28705BC02740DBC0DFA21E +:10D86000EC230CFB9BB56A8EE17C5D55F27BD546C3 +:10D870008DF40E05FF27F28CB4AF4EE79A08AFD3B4 +:10D88000B0670713032339A5E896F30DB70FFBA381 +:10D8900035D7B224881F2F92DF2BB30D94AAEFA7A0 +:10D8A000F9B6443FD3B0B978BFF766A75B1613BF8C +:10D8B000735AC00F54FD45D9791BD20BD0CFD43841 +:10D8C00016B42F9FCB33C97939841CB37239C6DBA8 +:10D8D000D50D200F947EF229FE773CCD9FCE5F358B +:10D8E000CF3CF5CC8BB04BBC1F4678AAB946DA3793 +:10D8F000727C63E6925EE3B66B7C9D0D12FFC54FB2 +:10D90000FD29AA93972F3F20ECA73CED42DAB0A661 +:10D910009AEC650D2EBE4FB00F0E993FEC0CA2CBCA +:10D92000579F793FAA93CE17DE644322527F32E39A +:10D9300069C381533318FA633D1B1CF62BDB2DD7CB +:10D940002ED33953ADA3E4F097F134BE76299EEA85 +:10D950001F5E1FDF9F1D6439337DD8B77FC9CEE0BE +:10D96000D6D9D596B34D178C7CBECBD7CCFC0474DE +:10D970001E5AFF93BCC838D00F1BCBC6921DC3C420 +:10D980000CC0F74AAB8043AF6F7834FB1AFBCBF285 +:10D990006DBC1157B57A4DCE68179F6F37ECE7FD18 +:10D9A000D4CFC91772FD1CDF478C9FA5BAF719E9C0 +:10D9B000BCD0BD2F92E8BF61DF03C727F27CC32E26 +:10D9C0000DC3B27AD641706A386064D6607906FBBE +:10D9D000CEA081E759FB546423E869599BE6DECD6C +:10D9E000E7D36B75460F0E9A8F2D5FD0536D58DBC2 +:10D9F0001882AB9CFFDF253F53F596B53F6001BE13 +:10DA000078BDF3A4BFFC228291DD8CF5BC89799EA0 +:10DA1000D99EEF827D6F59DBFE0692FFFB221CC36D +:10DA2000F93A3E97767ED5CFE07CB19F06E70BBDF5 +:10DA3000E38CB4E79E79C6487C08F3C43EFC1C7AAC +:10DA40006ED03C93E53C93F3857E7304FBB130507C +:10DA50007F595B575426AFFFC9A1B7291D2EC7595F +:10DA600066EF180DB9F9C98188993E4A7F3AE325D6 +:10DA70003EDEB9B6A9715AD0BECACB3753BFE7B69E +:10DA80001B67025ECC3748EAF96DB49E33FB9235D2 +:10DA90003ADF02DE5CCF3F73E0D92803ED5BAF686D +:10DAA00027F168B00A3B6D588C53EA99D656E81BAB +:10DAB0000BB97617CDF95DFD810B247F43BFABFA1F +:10DAC000B4DF9270FEEE21BB06FF33807EEB1D02B9 +:10DAD000E725C69C04EC83F26B9CB7DC0A3EF69A01 +:10DAE00059E061A8F3219CABCADF1A44768B956696 +:10DAF0006702F25FBCCE0F827CDEE5F9727F27768B +:10DB000016C2CED99526E47ADD467E50E1EB19C2E5 +:10DB1000F1EEE54BAEF31999273FE0279A9F9F4E10 +:10DB2000EB7BA4DAE0B6909FC59F05BBE7490BF3FA +:10DB300092DFE89736E10F481776FD47A4BFA82E7D +:10DB4000D69F3508F62F89C7BA39BC3C089F753B6C +:10DB5000FD59D05FCE5A849D0FE50EA479A25E8B4D +:10DB6000A41BF4837EBBD21CE749CF7C2E9241DFFD +:10DB7000373C1F29EC0A3FB7ED0C0B929BD592AEB8 +:10DB8000B8CEE4C5FABDBBC5FC302FE8CFCB2CAD79 +:10DB900059D02FD5B8CBA25A69BCB372BC65E1ADE0 +:10DBA000C23F6111F648D4A7F1CD8CFC283D4F84CB +:10DBB000919EFA7952C7418CFFF9132319E47857E3 +:10DBC0009A6FC9212AE7FA1BC747CD93617ECCF72C +:10DBD000B327227D8CD7FFCC2CF4A1CF22E3491FA1 +:10DBE0003A11B9B59CFC32BBC234D8553ED3982506 +:10DBF00011E5BB851FA3A6B989FC0F357CBBB33CDF +:10DC00004A67B258948F247BCB67BFE6FB54A3EFDF +:10DC10001BF1DDC35ACB7F807DB73782EC6E9F3F0F +:10DC2000F95F23FBF35BD4ECD2DB97141DA8F27BE6 +:10DC3000245FBA47C2F1BE7C07E1BF3EA26D6B3ADA +:10DC4000AD53EC578E073A77F1FD110F7BF7C9B64C +:10DC500017E2353BE0ECCFFA29E0BE579C6F3EDF80 +:10DC60006726BF4BCDF3916EB2E3DC3DD600795110 +:10DC700063147A708D81838FA7DA9D7BB3A067B719 +:10DC80003C61CB033C38BCE91CD9B3DB28C711E3AA +:10DC90007EB62745D8F5FD327F7014D9F567C5B239 +:10DCA000DBE7909EB37D34E07A7157840174C1C77D +:10DCB000716B1C3E353FF8A18067F412D2CBF9FEA0 +:10DCC000237E5927F965FDDD13A327623FBD6564F7 +:10DCD000D00B2E9A5C09E087A1F0FA40F295DA8326 +:10DCE0008F5AE0B7ABE3FBC6C3F74DADF48FD53E1B +:10DCF000A9915E57BB61E243C407DF34B3E17C1EE8 +:10DD000067DB1E880AC6C771C9CF02ED5D54BF9696 +:10DD1000D717ED5F8BA2F9EC31BB309F503C7EEB07 +:10DD2000F64F1ABF55FB3EFA68E3727DF495EBBEE1 +:10DD3000C83ABEFF3EF8C93E1BD9AF38DE53A177C3 +:10DD40009C31B72DC1BACF3C6D233E732646ECF70C +:10DD50004F383FF48EC03CBE733FD9377E37974172 +:10DD60001E2CF5E9FB55E3BE26F96FFD205734EC78 +:10DD700064F51C0FE88FE3E5BBD4FE2D33B50F5DD2 +:10DD8000C793685718B43F9F8E207A393344E0E335 +:10DD9000CC332348AE74C5083AE7F34DC579E54C5A +:10DDA0008C481994114E0735F23C7A666A1B9DBF68 +:10DDB000CF68FB29ED328B76354DD26FCCE92E1131 +:10DDC00074039A843FCCBAA903FA04ECD563F22811 +:10DDD000F587C55E6977067D420E651408F9C53082 +:10DDE0005EBCF47F909ED266015FF6483DAE6EDF6A +:10DDF000957E38E0B76E9F467E2483EA87CF3A4E01 +:10DE0000D9CB393DD67A35B70DF359B76219F991A7 +:10DE10001A37DF0A7A57EBA835B199380F7569467A +:10DE20009A4F978DEF1BC02178BC20BD2B32300E4E +:10DE300073C4939E49CA754C819057C8B7F2FEEAE5 +:10DE4000D6699B689C3475AE14EB5370E260B1C028 +:10DE50005EC6CFFBA27C80F5AB7986AE5FCD6778DE +:10DE600081B05374A539EF2F02BEDF30BA704EBFB8 +:10DE700078393F3AF66BF4329CDCFAECC67CFE79DA +:10DE8000A0293EFF2F257FAB855D9ACF336BBBDE8C +:10DE90001F92BD4B9FBF6A9F3E9F73409F1FDDAE89 +:10DEA000CFBB5ED5E787C871159C70EE758E10E705 +:10DEB0005EA438F73AC3C4B917799C7B91E2DC8B36 +:10DEC000EF38F7228F732FF238F7228F732F529C7F +:10DED0007BF1BDB240F0EF3A6977041EE097612F05 +:10DEE000D8949F9DF64BF78278E29FCA4FDABD2CFB +:10DEF00087F27D769DD956B2EB90ED86EB25738740 +:10DF00007A6E282884FFB4634312F066EA247BEE1D +:10DF1000F217853DB72ECF66879DA173FD271BA005 +:10DF20003E650DF5CC41FD6E73CF1EA203939FF8A5 +:10DF300046E75AE75B5304FEC8DEC1ECB1743EA964 +:10DF400080BC8B1D188FA17E15B649EF4709F5AB34 +:10DF500084FA5342E940F9511E37F72481DF9F7A52 +:10DF6000C2BA09F33F25ED646CBE95F42FA557970F +:10DF700018ED04A795F7693B21A75615C452FBDE9F +:10DF8000135CDFEE47DEAAB4F252BED0AB557E93EF +:10DF900066203F8DC74D7268959C53AAD6D37537BE +:10DFA0006824D24072FCA2DD40E7828BEF18498FD3 +:10DFB00018B1CDA05BCF485FB88EBEAEDE1B1BE2B2 +:10DFC0000F1CA2AB7FCDA1F4107FE0557A3FD54D59 +:10DFD0006B5FC1F97AEEA67C5DBDAAD289217094EF +:10DFE000F3967A69CB9A6DA9E03FAB227B69FEABD1 +:10DFF0009EB3D1BD8B2A2E5FDC7CDDD5C870FE5868 +:10E000006D75DF08F855B7996360D7AA94F2873524 +:10E01000E9E571B589791DB101BAAB7630770C6F3E +:10E020007F2EB7758F81E3ED9C61FBD62227FC4BD9 +:10E030003B521D9CAE566B6DF1E3797FA7623C3B72 +:10E040000AF87E4E35FB7F52067EB93F83ADE5F57B +:10E050004E6D7A368AF46E4967A9664738F0BDA3DB +:10E06000D548E702D8A7600F52F4B0A3755078A640 +:10E070003DB0CE00FE2FD3FA385EE8DE48AFFDC8D3 +:10E08000D055D0E3DAC47AABA76A5ED293E57A566C +:10E090004AB9C2D6897E56CBFC69795E50EB3B3BD0 +:10E0A000F295D14EF8359B0FA51AC1C70DFBF6248A +:10E0B00041BF48F0B463FF54EF18FE9F457CDC9AE3 +:10E0C000DF1B19FCC81F6D991E351EFAE7D366D7F2 +:10E0D0002C9EBFBBF567169C0B6A4C3E0BCE9DD5A4 +:10E0E0004FECB0C0FF7FEDDE1DF47DC9DE0A3A6F54 +:10E0F0002F658D748EFCD42CE4B48247F5346DBB4F +:10E1000083CF3BB350F0D7EA70711FA4C458742C6E +:10E110000EEBDDABE562BD3795EEB754F0EFEF4A9D +:10E120003E1CBA3F7A5F9F5B321876A536E1071D29 +:10E13000683FCCF38FA4FD30F7521AA5375DBA9A29 +:10E14000CE55BF67A5A3884FE4849C675F370ABBA1 +:10E1500059BBD807D5167FDC5CEC9397CDB44FEA5A +:10E160004DB07DE39CCCD8049E96161975F4BABCCC +:10E17000384247CFF359ACCEAF7C331BA2CBDF3450 +:10E180002B4357FF969BAE0EA1FFBC4039F191097E +:10E19000BAFB2BF56BBC4E8DEC68D3F4DF79BA86F5 +:10E1A000E8EC7A5DFB7A3627500FE7E05DBF253853 +:10E1B00033D661C179ABDA20EEEBCCF774C9EF9DB1 +:10E1C000F49D2F44B70F8765B8FE53C84533D9E790 +:10E1D000957D7A3EFE3FA33FB9C8112DC78D360A03 +:10E1E000FB8247AF7774D0F993093CD44B7B4F7DCA +:10E1F000B6B0F7D47B3B2C8D7682BF299983A4A13E +:10E2000055237B1EAF6F4D8E15F935F87EC01CB0BF +:10E21000B330D1DF25949F305660BF849637F075B8 +:10E2200043CF6880BD86EC4C333F213B931A47F6C1 +:10E23000AFE874E936BDFDA801769D207C2E2B74D5 +:10E2400012BDD6ECDD7F7C0887CFDCD2985CECA3D6 +:10E25000BAB6D9E68A9C2BE94DF1F98BD506F27B4B +:10E26000F7BE7E94E8ADB7DA4474FD4D7069700B6B +:10E27000BB66281D2EE1EBB2F2F1971CD05C3E4D3F +:10E28000D4037C86803E43E093DC0FDC14BCFAE0D0 +:10E290001752BE14FF5380FB049ACF9FD61F5C42D7 +:10E2A000E0A9C60981171BA787C7128FF32DF09F1E +:10E2B00025278CCCF72DD6BF14EBC43CF83A318F10 +:10E2C000399784DD44F9136EBE64A27C1FDD94721D +:10E2D00078E561DFE9F7691F1D958A7D33EF523CD0 +:10E2E000B5FB57D1D337D1919ABFE2DB817D74174B +:10E2F000C98DE58591711F7356C1FFBF90F882E407 +:10E30000AF03EBA55EC1473D7A3933ECCE7174EFB4 +:10E31000A8D79E4E7A459F1C72E8CB5746A627A0E9 +:10E32000DC23ED768A1F7B643D354E052F770E0288 +:10E330005D0F8D873D76C3BA8CD4CE207DC5B3DE0C +:10E340001C0F7B61EADA419456D81CF19023156BBF +:10E350008DA5908F1FDE93103F0EF6F9F5E6B859A4 +:10E36000BCEB0FEF284865A3902FA1F4D4E6B0F9D9 +:10E37000C1766E956E2B147A68FD9DEF915C3B67BC +:10E38000783D6A3EF6DDFAE7A270F5A676FDDB631E +:10E390001C5C25B93BC6F35021F95177EC71006E36 +:10E3A0008E1DA361A7FE396C688303FA43CDFA92F0 +:10E3B00004D8C5EAFE76F431C87DCF5A733CF4CF59 +:10E3C000CFDEE1725123B9467AC3A73646E7A54F9F +:10E3D0007747F8E0BFFF54636EF87796195F19ED41 +:10E3E000D0C9D9F69B318FBD099E9F1716627CDF7D +:10E3F0009E448CEFF2D2FD4CCFDAE1D1FDD95154DD +:10E40000BA7C9BD0EBF6283BAEB4F7429F471EFA8E +:10E410003C1B21F479E4A1CF23853E8FEFC7A41DD7 +:10E420007F584B4F2ECEA3DE692CBB91E4AE3D1B33 +:10E43000FAFA2A2DDC457AA6E64A807D8CBD1323A4 +:10E44000E46D087E553AA987EB5C41743FE59295EF +:10E4500005DF339BCA6274F9E9D6245DFD12479A41 +:10E46000AEFCDAC491BAF2EB9CB9BAFC77B2C7EB56 +:10E47000EADFE09AAACB7F77DC75BAFAB3DDB37531 +:10E48000F9B93317E8EACF2BADD095DF327F99AEDB +:10E490007C8167852E7F6BF51DBAFAB735AED595B1 +:10E4A000BB99C304B9D78E731687FBCB3867F17459 +:10E4B000D51BC3EDC1782D9A6E68ECCF4E7F5EEA16 +:10E4C0004313C7BA3F037DA418041DF2D40D15E20F +:10E4D000B2942BC9CCAF89736E4712E826B45E683C +:10E4E0007951C4918B4E8EC32507636F35713E52AF +:10E4F00034F6487E06CF3F336681C84F3CF26C3A13 +:10E50000CF1F3CB8F55613E71F45D71CB988F2D189 +:10E5100063CB457E2E2395E3C898BF2DF4F2751486 +:10E520004D49DFE41276927EEF69AA1470C0FD4671 +:10E53000C001A99FD327D2239C3E91BECAE9B3CA8A +:10E54000CCD8714E9F484FF0F326BEFF869F37917F +:10E55000BECECF9B48DFE4E74DA41DFCBC89F47719 +:10E56000CDF3297DA7D943EDDE6DAEA6F4BDE64619 +:10E57000FAFEC7E6264A3F68F6D2F7C431CAAEE0D3 +:10E5800027FB8BF23335C0BF07FBDC21F3D9603F9B +:10E59000ACF2132ABF604B23EB8CC03EED34C57C3C +:10E5A0006C0DF8FB06E6B326F671901EB639D19DC8 +:10E5B0003186C61FEA207F8FFC3E4D9B9B02D7DF32 +:10E5C000ADA33D23C7707CCFCBAB5C1FCDF9C79407 +:10E5D000CB8D66D0CBEFE53DD5D0FE2F4B3A891BD6 +:10E5E000EB1E8D7693ADE21EDE64ABB86737D9D4EF +:10E5F000D9027ED4F22573E21ECD2B9116E24F2D67 +:10E60000F7987CB0536A5F30CA4F8A63946FF9B24F +:10E6100083EEE54D76B81249DEC87C9FFF1C7F4132 +:10E62000F765943F5BDD9329FEA2733AF480497647 +:10E630008B332CC4FF0EBFF52B91EFAAF9308CA7BA +:10E64000FCE4BBBE647EC3E8803F7CB2B5230D769C +:10E650008249ABADAEE0FB3FCAEFAD7DD161843CFA +:10E6600051F77CD4386ABE9126DE5F5EE01ECF642F +:10E67000475B2EEE35B4D4DBA9BF04FEDD9247F52F +:10E68000DC466AD7960B3BF0A43ABB0BF66DE56F00 +:10E690004F90EBE6F5689DC55F78E8BEC12479DF51 +:10E6A00000FD5845B917FD4C8AF32799B0FE468BFB +:10E6B0000BF6D04735DE3E2FE0FF47FD88A0FD8BEF +:10E6C00079A2DFCCBFF0F9426F77BB09BE73D5F9F1 +:10E6D000CD29F3523E33EB34B25F1965FEB7A33D4B +:10E6E000CB81F7D230C79F22689F67A4C0CE315B31 +:10E6F000EAED5F432FABFF7BE8C52DF03D94913DE4 +:10E700002D946E145E149E07A22385F7A0FB5A84F5 +:10E71000E7BEFB57B29F50FA1A88AE143D4DB60AB9 +:10E72000BC03AFB847A3E848FBA26D07ADA3CE4A30 +:10E73000724ED151281D5C4947822E5BBE67A5FEF3 +:10E74000AEA4A300FE018F7F9E8E3A8C90BBFF2863 +:10E75000FDDCDEC36644F3A27BAFF15C86DCA8B8C7 +:10E76000E43C8E7C259B3A0324A5CA1F40F9E02B8C +:10E77000CB43E94BD57F7180FE3C5FF498A383E8DF +:10E78000729294817F18A0FE6BF25EFC6B3675DF8F +:10E79000C36DCFE574305DF2E1552582BE66A619E2 +:10E7A000C99F313D6729E9F7CC2EF46327FF87EC39 +:10E7B0006DD2BF7EBD6C37E372E93A8C33234EAF26 +:10E7C0007F5F2FF5EE9921FEF6EB73AE253DFCFA47 +:10E7D000103DFBBD31528F4E6369E27CBD89F4DF91 +:10E7E00062B91F9325BE339C4656C4E15EC23C26E7 +:10E7F000088157CF5BDCE8EF5AE6A5FC75CC47E90A +:10E8000077989FF4801BB8C040FEBB8CD1FDD1A38C +:10E810001137962DE7FD4DCF9F9E89EF75D69E54FB +:10E820008B01B7033D9F413E34183D7F869E792E74 +:10E83000C53302E7E323C54ED2C38E5833482FC4F5 +:10E840007E3207D92B7FCDE56826977347B99C4563 +:10E850007A8CCBD94C2EEF7EC5E52CF2D767AF650D +:10E860006837C3A9BFDFA3DA7FC7319D99060D2C96 +:10E87000C7BE33FA85A1B063BD1633A218787B2DCD +:10E88000666C31D6FB5A4C8241A461164A473D9FC3 +:10E89000D99FDEAAE83530DE0C1A2F14BE0A9EA1DD +:10E8A0007054F0FD27E039686CE195F0BC0CFD1E5A +:10E8B000F653EBDB5189E9F033CA78BA08C107EBAC +:10E8C0009F1F958075D459055C26354DA47472D36D +:10E8D0007866CA273F9317F0FD0C4B80C139C4CE30 +:10E8E000C64CD328FF3D495BD9099EE198C7D93C66 +:10E8F0007F16D7C8D827DB5BA2703FF3DC334617FF +:10E90000CE357546E72617ECE4AF19455CD0E5A394 +:10E91000A9F06FB25DFDDF97AEB32AF87909AE3F7B +:10E92000BBC64DFB8DC13B1B1FD06B8686897BC64A +:10E93000E45EC81B58CF19132EF8CCD030C11F1578 +:10E94000BE783B2177793F63385F4BBE3F9CCE3525 +:10E9500005C3DC45580F3F2F505C516F7604D92B0F +:10E960007E23E31227FBAFA6B8BC9938B7F3EFC6F6 +:10E97000F0A89DD8F7BF917189BF18E4B916EDAF23 +:10E980004DCB4B043CA630E157B9CE6A76F9F99CE1 +:10E99000AE1B2BF7E168365AC6F5E8CE1FCA4ED239 +:10E9A0001B6724393499653D043B41F10933D9098A +:10E9B000FAEEBB250ABF68EF898B46F09592488D29 +:10E9C0000D4A0BC4E784251A9833486FB739C399A9 +:10E9D00033687F4464C7EAF291AE21BAFAD1E3D238 +:10E9E00075E531EEAB74E58366E6E9F2834B27E823 +:10E9F000EA27CC9FA6CB2779AED7D54FAE9EA3CB27 +:10EA00002BBE972C3EB194C685BAF6C39A16E9EA96 +:10EA1000A7796B74E50A0FCCEBEEC88E075F147F05 +:10EA2000191B57EAEAFD344AC49BCCB42F9985FDE3 +:10EA30003EBCF507FA79195FD7287ED429F8AD973F +:10EA4000FF033A2A49D4F3DFE90EBD5D23B9D1A40F +:10EA5000CB6FF847F1ECB94A87E7507870BCBBFC44 +:10EA6000A8CFE5B797E74B7E5D69827E01FF45F051 +:10EA7000FCE1BF085E2FFC17C179F82F82EBC37F42 +:10EA8000115C0EFF457079FE093D9E0B3BF4781E2C +:10EA9000FB9E1ECF8AFE06C2C7F84E3D1D84E26370 +:10EAA000E2A7217421F1309FFFD31F1EE828C2E99D +:10EAB0007F7A2323FBDC37E1E58510BC4C1AE9693A +:10EAC000C77E9D3FE862AA0578EAF18CC079F233EF +:10EAD000692709BDC7E9E5EA00C521FCC048F1374F +:10EAE000270DAD1AF8B23FC5736C2CAF7F7B4E2358 +:10EAF000D14F222BDDBF84CFA7FC3FC2C88F533E2E +:10EB00004CC4EBB29C4E8A7350FCAE3C59DC237A69 +:10EB100063AC3CBFB9C47DA28EB1429F8D7439E80D +:10EB2000DE71458E88E3E0C7AED4F251A09FD76D69 +:10EB300023400F5B84DFA413F1C271817861E89BED +:10EB4000D0EF52A47ED5F207AB15EB18B18DE9E4F6 +:10EB5000E4489F5577EFF5EABD0E5D7E545BA2AEAB +:10EB6000FE35879CBAF25C7FB6AE3CFF844B972F94 +:10EB7000EC18A7AB3FF63DB72E3FBE73A6AEFEC462 +:10EB80004F4B75F964D6F330E03B4C13E77D2BE730 +:10EB90004B740FCC29E281CAEF8E1171A0D20EA066 +:10EBA000F469751FDA23E92E544F1F66117A6A4BF8 +:10EBB0001213E730AB3C6F31BDBEEE91F799959ED5 +:10EBC000CABCFAFBCCEA1E739F5E2FF576A51F0721 +:10EBD000DD637607DF632E97F1DBA1F22F6E9CB029 +:10EBE000EF85CE7F9845ACB7E50E0BC58DA879852E +:10EBF000CE67799EA0DBDDD6FEE377D2C769D47FEE +:10EC0000516EE99071BCDE6366978FEC28578CE7F4 +:10EC1000EAF4E25CF9238BEB2EE7378F577E8D58B1 +:10EC20004F99C170FBEC1CBA2F36FF9741E3E78D7B +:10EC300013F41D3F41EB777DE5D1E23E178BB638EB +:10EC400041BF038F27E0996861EB28CE48DEFBBF08 +:10EC50006D53DB7D23785199A5D54CC60BE63383E4 +:10EC60001E664DE3FA542EEC822F3E62E7FAC6632D +:10EC70004D26B2F38C1F37AC8C6B627D711CC3F8D0 +:10EC80007903F4019D05E79427C71B699C85E3C4BC +:10EC9000FA4A8C97FBEEDF93FF8231C9BF19DD87FB +:10ECA000E987DE880ED53AFE55F7F115DD86C249B3 +:10ECB0009D2F99943B99725E0A7E6A3F28F8A97845 +:10ECC00008E70A73E94E3BC555CCC43D3285BF9772 +:10ECD000C70B7EB409F02814F5C08F06AA5762CC82 +:10ECE00089863DBC9739A31D5F63EFFD17C62910C8 +:10ECF000FC078AAF1A883F5CC1170688B71A883E9E +:10ED0000E9EF1F88BB0AE20FE25E8FC4872FD34072 +:10ED10007EF4BB23F5FBF8857102BE1EB98FB97C6A +:10ED2000B5E7EAF90483FDBE65BD51F2092157A19B +:10ED30006FE0FBE2F566D237182BDD8A38A28FB67A +:10ED400098E97EEB64B773864BF8E749EF20BF176D +:10ED50009F5A85572F4FB97CDF093D780A736D8024 +:10ED60003FA372A3BE7CA97DC66790E78B43CEA567 +:10ED70004BE5797569C8B9F4A971521EBB988BF43B +:10ED800024E9E7AF9675FAE8C897112DED2EB43F48 +:10ED9000794AF7C2145C9CF0D7E407F21C7EE1D9F3 +:10EDA00090D3EB4CFDDED7EB83DF00F711CEE23ED4 +:10EDB0008213FBBD97E2AD7A0FD8849F52F983642A +:10EDC000FDB3DE8B548EFAE8ED5C6EC768E8217DFA +:10EDD000FEA3103F54AFDD10350EFDED33537FEA37 +:10EDE000BE45CD5F7DA31D41FE644FA75177BFE5B2 +:10EDF0008AF9AF7D8EEE5FDC1DE379077CFC8CC960 +:10EE00006505FEEEB11F89479CFC2C69B7099D6F13 +:10EE10009FDE59A4093FAC57C4CDF6CED4E81E00FE +:10EE2000E7830CFB46DD1B98CDFC7148953FC6B3CC +:10EE3000713CC159F9632AFCE3699EF35A969AC35F +:10EE40007995CE87D794843B037E9ACE1471EF6771 +:10EE5000207FCDDC4BB9D4DF4D9726523F17C7A595 +:10EE600009BD6BDD7D2B404757ED6566ACB333E4E0 +:10EE7000DEBB4A2B25BFF18E577C5ADE275AAB11D9 +:10EE80009DAFD498BA5F447C5AE52FB6CA7C89C836 +:10EE9000AF5A2FF29D66F1CECC1E696FC03A9162D7 +:10EEA0003D3817EF93F608AC0329D681EFE04BC845 +:10EEB000832F210FBE843CF81252F0257C5FC44A98 +:10EEC00053738DC2AF541CB46FE0572A0ED27BE04F +:10EED000570ACEC3AF145C1F7EA5E072F89582CBB3 +:10EEE000E1570ACEC3AF145C1F7EA5E03C1B775DE3 +:10EEF000200F3EE69EADCBCFE5FA7771D0BE855FA1 +:10EF000029B87FF89574FD7956E8DADFCA9A74ED6E +:10EF1000E1570AAE7F7B93A6F33BDD2EDF03A8DC2F +:10EF20003688E8E3A5D1A5AEF17CBFFE39E26FDFFC +:10EF300033E31C606C5F06BA5D591FEE12786E9D5C +:10EF400029F06E6002CF3D0B08CF6B2C225F22EEC2 +:10EF50001FF7E7BF29360BFF0D52F86F90C27F8372 +:10EF600014FE9BE2E1C27F8314FE1B7C87FF06290F +:10EF7000FC3748E1BF410AFF0D52F86F90C27F8312 +:10EF800076F0DF2085FF06DFE1BF410AFF0DBE9F5F +:10EF9000841F29E8DD0CE8E999BA731DA743DDB9A0 +:10EFA000CEA1CB434F0FAE0F3D3DB81C7A7A7039DE +:10EFB000F4F4E03CF4F4E0FAD0D383F3ABC739893E +:10EFC0005F425F0F6E077D3D383FAAD57B0CB6A32D +:10EFD0001BB69F7F156967A4F698C659C18A170E9C +:10EFE00094C1CFD669D3526338A7346B2F9615F3EB +:10EFF000BC47DEE31BCD7A0CC037F9D939DE3C7E45 +:10F0000046F78E477D9544E5CAAF4B7F1CEFB907A5 +:10F0100018E9FDC764BCA76AEF620E2352553F9002 +:10F02000EFBF5EE8F8AA1EF1CBA079F083612EEE67 +:10F0300099E4AEB1E7E1BEFC1E8326EE9BDE25EE31 +:10F04000FB86D2D56EC997F618F61F09C7FDA10A2F +:10F05000CD8538862C133B61CE039C1AF3A01FDCB0 +:10F06000373E46AEAB7102EE1FA9792B3B20E7136A +:10F0700014BF56D4C32C557C9C495F30CB62F077CB +:10F080008BD00BD00EE7C5ABBD9A7B67107D3F34AC +:10F090005EC8378F77C5842AFEFDEA7D8D13101771 +:10F0A000372B5CB4FBF9E35104C71BD7693B117FD5 +:10F0B00058B48FB911EFEA93F3BE7A9FC35245E378 +:10F0C0003A289E4EF55BB13D95E2FF2A586731E242 +:10F0D0002B5881C6E01F5570E3EB7B15EBCBE25B51 +:10F0E000C54CFAA788CB099771392A1E272CA6B4DC +:10F0F0000A724BC5E54C2A8829C1BD38D6CE5C08BA +:10F1000003BEA1A062FD60DEBFC7E776E15ED1A4C9 +:10F110002F1A8F517E5729E5890CC6D03824D7463F +:10F1200078357A5FE346EF0E439C13F1BA6BCDF16D +:10F13000A8BF8FB9A0EE70514371A76A7E39ACC3E6 +:10F1400060D38077767450101D710E7013F09EEBB3 +:10F1500032D3FB1BB34D0E33F846A81CBFF2DE6260 +:10F16000889E1072BFA465CD7BA9C674DC2F31B810 +:10F17000FCE05BCF4590BEA0F49D0A79DFECE2BADB +:10F1800063836FE1E515FB857EE0D9A611FF53F798 +:10F190004DEA337CA906E80B43768C8E350AF90FCD +:10F1A000BE78C6FBECCDD8A215EB8F515C44C5FAF6 +:10F1B000C268111725FC1055124E55F25E11CB7125 +:10F1C000C443CFFC90F31DF708BA97184D7185AD75 +:10F1D000429F53F616A50FAAF7632ADEC83F0EBC5E +:10F1E000573C2ADF65D95841F157A1F77C6AA5BE83 +:10F1F000B76C9D99EE0F2D0BD1076BE57DA1DA1051 +:10F200007DF0DCF8107D509E5FD47DDE8A378ECE97 +:10F21000237DA5D14C7EB9B2B5427F61FB990FF138 +:10F220000C656BA71BF06E48D9736E97D60F9DBC0B +:10F2300025F598599D3682EB9C4BC994DE7C298933 +:10F24000D25B2E897B94887D011D74BEC0488F7E61 +:10F250005BEA2DF370AF12F188DE30797F9291DE98 +:10F2600094CB1C25E01F57B9B5A350FB66993DEB25 +:10F27000716F73D60E46F1473740BF41FC17F41D3E +:10F28000D8DD0BD24A280E63A646F12C3714AC9079 +:10F29000F4CDE99D81DEBD927E4B29DF2717249DA9 +:10F2A0007BBC5D26C0FD06AF66C13B7C1E798E55DA +:10F2B000741C4AEFE511D2FE6417F6A53EFB132637 +:10F2C0008B476DBCD1B7E17E6B396C764398403C7F +:10F2D0008779648E281FF162F46DEB70A8F9BFB4D2 +:10F2E0004B94190C22DE89EB5BE0ABB7ADCEB52CAD +:10F2F0000AE22F5F4C9C3663626100EF8B42E2F4BE +:10F3000056DE333CE1EBE2452B399CB14FCAA33BBF +:10F31000BFC729945D3B81B98BF999750163EAF107 +:10F320001E3FEE052E94F9D52F8EFBD3463BC187A9 +:10F33000F2D327A4DEE625BE2AF8D6ADE05B46F080 +:10F340002BCFD409C4AF3A67001F11393DF21D021B +:10F35000299742EC10AB2738C57A43EC11953982D6 +:10F360009F339333F5568A0B76923D4FCDFF43B3CF +:10F370003E4EB3CF2F3241CA93E67F4D7CC3FFCAC6 +:10F38000F0DC86F56D3588B8F921C65626ED42B415 +:10F39000FF15FF60F21D8900FEB99E467E74CD11F7 +:10F3A0008C7FCF464DC4A90F60BF61D93D0FEF865A +:10F3B000FDAED9C210E7FA7896A0A3C77F60213DC1 +:10F3C000BCCCD2710CEF642938BEDFF4EF66B2CB4F +:10F3D00033FF70BCFFB5B0D1E6027FFE6262E92A5E +:10F3E000CC3B22C745F898C1B719FA3F9952FA7D2C +:10F3F000C2D7A6571E43DCFEF2F6348A23AD3894FA +:10F40000BB01EF897C31D1F3C309F0E3DA1D16C8E3 +:10F41000F186753124D7CA13645C27EB213F9582AE +:10F42000FF031384FDEABA2241C7DDF23C028639AC +:10F430005B574FDEE30ED927CA2E186A5F087DC7D7 +:10F4400061A0FDA3EC08B01B5882EC8ACA2E61CEE5 +:10F45000FE7001E46899451F7FA8D25795DD4D9E47 +:10F460000717F7C9B19C1909D09B376B0EC8B12A91 +:10F47000BBF396F13C5F75C28C1B986C56AC53BCC9 +:10F48000DF718F78BF6311DFAFE03765F23E56D58D +:10F49000B6F1B4DFAA7C3CCD1F785FDEBAF968CA4A +:10F4A0000BA01FBF9BE2F2AB1C6E4B6CD0BEAF6CCF +:10F4B000D57471FD2A7F6082B0C39571351DF0BB94 +:10F4C0006D759A056FE89471F502F7FB5E9DE0D4C7 +:10F4D000C555F37A74AF61563A3B2EDE4FE2F34ED8 +:10F4E00013E3E505F5BFA855FF3E01AF4F7AD1CB39 +:10F4F0001322097F150EBEEE34A40E9A278703C18E +:10F50000A9E73EDE9F93C6217C54FA7D669CBBCB67 +:10F51000709F82E7173A7C668CB3689D782FC4B3DE +:10F52000498CE3D918631905BDC9E4B0A4007E383D +:10F530002CC7D1FC880F5671B820DE4AC55D86C243 +:10F54000A742CEB7AA3546AF8FB56E36031F0B065E +:10F5500078AFA047D2EDA2755329DEBCCAE4A678E5 +:10F56000068F84EF472B6CF7C22FB060CB43E63495 +:10F570009CB32708FB738FDC77B3D2FDC3E95DA092 +:10F58000153617E6B9C0D14AEBEB83EF831C1E1A80 +:10F59000DE9F2925F872BAF0E27E5ED5163D3E0365 +:10F5A000F311F0ADDA5241FB6D89C9637104CF6389 +:10F5B000DB2BC3710F6501DFDF78EF88393C14DF87 +:10F5C000F4F183B7A4D23AF93CE91E94CB3903EFA6 +:10F5D000FC703A213A56F4A2E2B2D578D689222EAE +:10F5E000D33AF19BF6A59BF49A168E5FD8BB07DA47 +:10F5F00097160476F1712D55E2FDB5D07DAAF6A7D8 +:10F60000DA976A9FAAFDFB98B9D49FA805F80C97D2 +:10F61000B78DBFEC074E33E47C174ABC72B8BE1AF4 +:10F620001CC775CD4481D7B274FD7E477FE837652E +:10F63000A2D8EF65D3FCC31177A9EAAB71CB6245C1 +:10F640003BD03DE82D65A2A1AFFE4AAAAF8F47A9E6 +:10F65000ECE317FBD6C7835FECD748EF5D79DFD1CA +:10F66000947F833EFBB4D067CFD4ED6E4882DE68D2 +:10F67000F2A506BF8B55E517FC6131D77FC02F96E9 +:10F680004839DD9EE7C99918B47FAB1E783ACB2381 +:10F69000F88B1FFCE583A75FFAFD0467407EAAF99B +:10F6A0002FDAF85B73853D185E627DF766F7529C32 +:10F6B0005DA5DDE2C4FDE5CA7515C46F59223F574B +:10F6C00068017C87D241C53A8DDE17AB6C1AE333F3 +:10F6D000FE37F2E5CA4DB3E94D248527F5DE899260 +:10F6E000A76AFEDF95F35F28E978CE44B1FF16568E +:10F6F000A75996D0BE4FB35482FE65F9822AFDF712 +:10F700003E3CF5F9977336607F206E88CE279BCC00 +:10F71000C2CEB72F92F4D5332B9F7FF3665EEFF303 +:10F72000AD3B52A19FA8792C95F6BCC5D22EB7440B +:10F73000EAAD1C4F15C1785AFAB8C053E5336FFCD7 +:10F7400009EF7295A54B7E769F88E75FD4B69FF050 +:10F75000B660E366731AAFB762629AEE9E4C652399 +:10F760003FE872782EDCB8C30C3EB062A2805B2802 +:10F77000BD97C9FBBE0AAE903B5A90DF42D507FF4A +:10F78000DBCFC759BDC21605FBB41AE71149D7959F +:10F790008D31B118AFB2B1E2273877287E1FBAEFAA +:10F7A0004ED9C47E58C4FBC3BE3C35D54571CDF09F +:10F7B0006BF52757374BBCFDD42CDE6F4C8E687B26 +:10F7C0000270485E1EEE027FC8CCEC24BF31E819FF +:10F7D000F3B618C47B8F99759D17300FAE52D3FDC9 +:10F7E00014A478670A2A763CCFEF3488F8AB74A368 +:10F7F000489F97F0E1E57E94B3B84E7A77AEEFDD9F +:10F80000A4107AB5B05D1BF1DE8D258EB95A9C012E +:10F81000FA54FD28FA54F43BD0FA7E21F9C837ADEA +:10F82000EF549AB44764BB5211A7527EFF0817ECFD +:10F8300033DFB44E8B7C7FB06FBD9C58C7C5F6B329 +:10F84000DE4C716E1978BD5B4AE2FB596FE83AD520 +:10F850003E5177DAFBFC0BADC2BF704AE3F28BB7C7 +:10F860003BB5C246F7BFD4BA94FDFBDBC621BC3D15 +:10F870003156DA133A23A1479685CBFDEF17797CF1 +:10F880009F1DF45DC97DF55E9BE2CFA71BA55C645F +:10F890009DF7613FB3A60C7A9FE464EBA948BC973F +:10F8A000726AAA989F6AB7DA2CE28C59A4C589F7C4 +:10F8B0000FF9F9EA6413FC3EEB12E81C795B53067E +:10F8C000F185DBBC31C2FE20F5FB25920F46ACAEC4 +:10F8D000D88077BE176F4B73687C9CC576D7C7DB23 +:10F8E000A8FDD52EE883115B665BD249EF15E700D2 +:10F8F000E5275AADB1528A1B039FC4FE32BC920960 +:10F90000B9B3749B3807CC32B08DF0130E6B299DC0 +:10F9100091043EF1B04671E66CBBFE1DABB1F9A59A +:10F92000E7E9FC17F20EDC6A739B3B017C9CEB1B46 +:10F93000B0372DB69792DE5E2FF9E4C92D5DF41E27 +:10F94000BD82EB15F13F161107DC1369203BDCB7D4 +:10F950008D03AA927E254537CA2FF508FE331E7007 +:10F9600032925C2B3196D17B4A1BB64CA7B46A739A +:10F97000C956EF28C41F97C64FA0799BC94E56554C +:10F980003F5DC4EBEE0C8BC1F926D5EC4D0DD64B8B +:10F99000AB76DC4DF13F9FEEB051FC4FB163767119 +:10F9A0004C1CBD774CF175AA5E6A91E03B35F5D3EE +:10F9B00075F13B8B799F7867F3CBB608BA1FA6E247 +:10F9C00072EA123C494583457CCE78A788CB49A290 +:10F9D000FACE7EEDE22AFDB859C47904C51BDDB824 +:10F9E00080B7AFAB7F360AFDD43EF8F6188781ECBE +:10F9F00050C3D17F5FBCD136116F9425CF4BB3621A +:10FA00004B6F5E00F8FFDA48F01F68BCEA439ACEFD +:10FA10008F779B2F9AF4568F9F59E047F63818E955 +:10FA2000C59F1A5913F400A5BFA8EFE3255C3E8DCE +:10FA30006E4D057D2CDBF3502AE4CB6791225FB637 +:10FA4000E796DF805F79768509FDDCC4481FAEF458 +:10FA50000AFD9A55C7AAF7486DE59C8EA6174588FA +:10FA6000778FB6E9E3CDD53BB79F99C4FB3C883788 +:10FA700002BDBF6FF22F067EDFE7FA2BCEB1A9459C +:10FA8000823EDF6F35CEA07B437CA3400F79BFF56C +:10FA9000D948C4432B7DADC4F8811BEFFFAC7C4E2D +:10FAA000C405E37D7A7A2B54DA411AA41D64E50B70 +:10FAB000E619C971A47FD1973A93DFD21FFE6AA4D9 +:10FAC0007ED5973FB09FCE6D75FB84FE50D7D6454F +:10FAD000FA83D24754DC61EDBE2ED22754BB860395 +:10FAE000022EF507C4F78A6C83B2A3B8B54C9CA765 +:10FAF00035CA7B5FCC2F5F6B0ACEE795AF05B39F0E +:10FB0000A0EC233DA40FDE9BFD3B3A87D7AF93FDCE +:10FB1000F2BC3968BC6A1051A1F89E61477BA7EE20 +:10FB20007C577F2086DAFBEBC33742CEBB1BEC262B +:10FB3000A42DF57692FBDB1B0DD9B8A7EED6C25DDE +:10FB4000D0E3DAE5FDADC1B5EFDA603F48623D478D +:10FB5000F1DEAE3FC5F3C322DE6F025E773106E20F +:10FB600089BA0F7F928FFE270FEBBC883735CCDA2E +:10FB70009472F8295A8AE43A723AF341D7838F088B +:10FB8000FEFCA8996DA4779B4DA50CF67BBFF42FC6 +:10FB90007ABF32D0FBB3ED9AFF67C1FAD521499FF6 +:10FBA000A561C2CFB873B46713E6F15DCD3C2A9767 +:10FBB000EE1D1A87A3FF6EE987547AEA34C99F5372 +:10FBC000E4F9CA3224D10E3A56F7ED34B79BE23D40 +:10FBD000EFCA395209F9FCE31E2BC50B4CEB092780 +:10FBE000BD3565C84C9267EADD7615F77324C7E02A +:10FBF000C57BF43F6656712FC01AA2DF1A6C743FA2 +:10FC0000596BFFD557E0EBC9C60B47A3715FF6DF11 +:10FC1000347A7FB4BCF7E347DF62380FFB72291EEA +:10FC20003AC5B307EB39D93BB3CBC351F763479B15 +:10FC3000D525E4050B5E47FB1D5F45C51A02F3EBB6 +:10FC4000EEF998DE75ECEEB192DD765ABB7CE730CA +:10FC5000643EDD894EBA27CDEBD1FBCFDD7603BD07 +:10FC6000EF36ADFD28BD57384DBD6768D5BF67C8B5 +:10FC70003A52626057265B2A570EE25B04FE264723 +:10FC8000EBCF8BAF15097DF1B522ADDFF7EE55DC7B +:10FC90008A922B2FDBF7DC26EC52629F2E577EFEDA +:10FCA0004BE9A44FF4B6677CED3B166F43AFE0FA27 +:10FCB000C2856BDC6F171506E4EA3C0927259F55C2 +:10FCC000DCC23C09AF797683804FC8EFAE28BA0911 +:10FCD000A58B50BC2B7CB21F741C433C16C7E3A8F9 +:10FCE000FB19E1EF24E1EFABD7D7E3D985214677C4 +:10FCF0009727EDFF45FCF96D23A0473C68203D4266 +:10FD0000DD77F4C8F7DAD5BD4796CD881F941BC3BD +:10FD1000C95EE891EFB4733E700C7C40EDFF613337 +:10FD20003B47418E9EE44774CCAFD3D046DF532788 +:10FD3000A5D37E1DCA3A92E4FD9C42E86FC6C0FB83 +:10FD4000D444F72D9AEFE125B87F39CF4EF7DCBBCD +:10FD50007D21EF53CB77CCBB99E40FF3D53BE67C09 +:10FD60003FF3765B1688F2BE77CC87333A476DC98E +:10FD70006559D0BFD4EFFE0CF88EF9B258B29B3E55 +:10FD8000F2886F24E4817ABF7A4A8A2771D2E02B05 +:10FD9000DFAFDEAA952EC0EFC0784789F9762E082E +:10FDA0007F668F00B71FF69E934D91F46EB7A253F6 +:10FDB00065E71EE6ED7A18705271B57F96F4A6E0FD +:10FDC000AFE20AE342F0A0E8CE6B6614870B7C201A +:10FDD000CEA8EFF763D648FEA2E23A5F763991FEED +:10FDE00038D5933B09FB70058733D9D13BBF87F5E5 +:10FDF0003E7A47A41BF33B297FD722745F154D320F +:10FE0000287F31C50D944BF956AEE2049AF4710285 +:10FE1000A1EF9C860F2D9D0CB89DD3DE1E838FAF66 +:10FE2000FF6F63BFF74FAE9D24F84466A267C624F8 +:10FE30009273D374FAE4EBB99FA4D0EFCC5C3E3A52 +:10FE400014F2EF9694D2EBD0AF2D53F80FFE9CD462 +:10FE500049711E7F5EF0D714B23FAF11EFB37EDB66 +:10FE6000795E19D72CE861D562712F319935121D51 +:10FE70002706E2656D98C7FFB4B8E640DCF15EFA8C +:10FE80007D91979BDB324E0FEF07EF61479E75F236 +:10FE9000938DF7F0CBE514F71B7D64551ACF6F3CBB +:10FEA0007CB49CE27C938F5C4CE3B8B9F7F0AB2256 +:10FEB0007FF5918B880BDE74F898A80FFFC110C6F0 +:10FEC0007E72F878B997E3E38ED19EFB81AF9B2FCA +:10FED000351E8338FEFDDA398BD328AE75764AB6E7 +:10FEE000886B5D07BCCF8B5FB43E5A0BC4B5EE9BED +:10FEF00024DA755F10FBA0FB82A0F330F083C1FF12 +:10FF00007CAAE27B151F1E885FAA7DF8AF8A4F5638 +:10FF1000FB99ED716D348318BDFF74DCF093936829 +:10FF20005DFAB8E16E73CF63E457BAC09CE013AFDB +:10FF300044BEEB84BC682914718D5A4F8713F73186 +:10FF40008A0A44BEE54287137C1E79D8B7BA634457 +:10FF5000BCA38A8B6DB9E04FC23E2942FC22AF5F41 +:10FF6000DCD3530E3E5A84FBBC69E8FFF851391EBE +:10FF7000437FBB2E88B8C36E5B87D321C7413F7CCC +:10FF8000DC34F0C7A2D556BA77D472A17105F55307 +:10FF900066EF1B570B19D7FAF5E34ED782C6CDECA7 +:10FFA00015F19D18D7A91BD74F71C1BC3F8A3FEDF2 +:10FFB0008E7125E2DCAFF2C528E7F987E4EF54142F +:10FFC00039FD46C8011527956091EF71CB730BAFD2 +:10FFD000477199BB7AC53ACF37FB6BB09F8A25DF53 +:10FFE0002EB608B9C90CE12EDCC72E315E3E9E8CC0 +:10FFF000F3C90BE27C521C56BA1DFBB1C124F80DAB +:020000023000CC +:100000008B53BF97D6B1ECE7BCDEEFE293E9F7C5BF +:1000100086261E6499381F2F9F9903B9C1F5EE33C8 +:10002000C0F7EF58AB267E874BB49F3B3382EEA1DF +:10003000741F1E5188FD3327CCF91CE3FBB677D221 +:1000400057B44FE7443B0B71E2E93DFC5F229FE070 +:100050007C0EFE5D2BFB8AF473E5AFBD25E0AFFDA2 +:100060005F18A77EE6398BD0CF7AE89DE6FF9A2409 +:10007000DEA7E3FA3BE91F3DD7C97737739C852894 +:100080004F35F744016EDD974DE2DD5AD6137553B7 +:10009000907FF6B176F19E6D285D1F9E2CE4C0F234 +:1000A0004C3BBD77D69068B552DA7E6106FD1E8C5A +:1000B000A93413E703B7A57FBBE32F260B7995B6C9 +:1000C000C112F0BF73F9E10E672AEF65E318DBF1A7 +:1000D000FDF0BEF317448C65B83C8F79131F2F36A3 +:1000E000E9EABB51BFAF9C8967DA54FB9C97ED8F5F +:1000F000AF33C9F180E725E2FE44A8BC689812DB63 +:10010000F75E21C9DD381BDDBBCA344A7B1EAFEB6D +:1001100020BBA0F0DF26FF878DE2E876D9041D66BC +:100120001A44BACB20E37DA5BD4F9D637E3CC53309 +:1001300069CA60EAC74FFD18F7E742AF48626D34FD +:10014000BED2CF543DAE87D988C9C8DF7B2B321AC7 +:10015000FA85E73B93A7964E2E045D7BD947417203 +:10016000E27C44545330FE1A8C7ABBE73B93A75190 +:100170003BD5BEBE693AFB88E211FD443FF59906C6 +:100180003AB73618D9ABF4BB03AC83FC99AADDBBF4 +:100190009C4F7E44EF36B8297D8FF3CB8FE8BEDFCE +:1001A0007C4A3F68F6D0F793CDD594763637D2F7B0 +:1001B0000F9B9B28BDF9D6C802D0FFF2436BD947ED +:1001C00041F2B1BECDEC09BE5FF3EED4FEE9E8FB2F +:1001D0009385DFE6DDB4FECBEF57E593053EBB1715 +:1001E0000B3D93D3E53A47ECC0FA4277A4B897F0B9 +:1001F000D234717EED4E12F9C6C9E2BD50B7816DA1 +:1002000043FB97A65928FF6EBA81DE7570C78A7EB8 +:10021000DFCD32909E76FD8CA90D80933B9E7FCFE3 +:100220000BE4DFBD4A94BB8788EF6ABEAA7CD294F8 +:100230003E3B4296381F0BFF3BA777EABF0FBFC577 +:10024000627EA1F5D57DFA5078FC56EE5BDA17D0C8 +:10025000DFB10FD282F6458393F685A243457F0D29 +:1002600053C47ECD0C9374CE6517C10F320CE7E3F7 +:10027000041BF907DDF05FF0F5EC92F1EE57EC07A7 +:10028000E90F50FB41ED0345EFC97C9F097F87587B +:10029000C72463FF76FA87268B7577C447927EDC86 +:1002A000DD6E7640DE4C320ABF4377FBBC02DC0BCE +:1002B0002FB9DBDED81FFF7A53B6FFA7E1A0F8C144 +:1002C0000070B862FD1669B7FF07D74FFC0D7C7B45 +:1002D000B1B897194AAFED9395DD5DD0ED3B93DD55 +:1002E00007413FDD9ACD84734AB7ADFF7BE42F4DC4 +:1002F00013FB42D14FC31426DFA1E1EBCCB892DF50 +:10030000A9F5F4AD732923BE9729E38D43F1ABD64C +:1003100015C4F75E9F3C38004FC6B8BEC2FB195AE1 +:1003200067A773AAA2DFF383BF5A02F9357FB253DE +:10033000F8990C46F91EAC90277DDF3523C55D0585 +:10034000C91906BDA5E7B0F0C7F9F93909FE2CD8DF +:10035000A083E3AE2D53C4BA7BE7171A602738FF9A +:1003600017BB1772EBFC909E93D04BCE6F13EF9D93 +:10037000F31E6769B83782F81F277EB745F8418CAE +:100380000F7F7912FAD092878DA4BF9CC7B199B71D +:100390005BFEA0F89D3B757FB04EB66BD976F166DB +:1003A000FA7D334E9FD07F3EB235A4432F9EFEF0A0 +:1003B0008327F0FEFA92E734989BD951D8DD79FE75 +:1003C000E3BD46F13BAB32EE6486BCDF5FB35BDC82 +:1003D000EFAF43BC09F497033BB6E2F727EBF79A7C +:1003E000998D7F9F8177D2F8384BDB22F94192F7C4 +:1003F000BB451F377A2DF36E803DB97ABBFE7BCDAE +:100400002E7DBE2EE4DEA23645FE9EC148964BF7F9 +:1004100013B7087BB1E2DB57EABB5E82AF7BA5BABC +:10042000AFFB05BDEF6D3CFC65EA8776919F2DF330 +:100430005D3C7FEE4B017F05B706C9F3CF25B18246 +:1004400036BEBE86C33607EC000D2F083BC1F9B699 +:100450006882F3F2F04EF22BB0178D0EE861F71CB4 +:1004600032925DA1BEDDF633FC2E6DC3731ABD570B +:100470005B7F28CC27E0736109CA971EB2399C289C +:100480007F318CC1FE7C9EE30DF762CFA77412FE14 +:100490008157D825F8DF2CFC7E85C2BFF161E14F82 +:1004A0005EF284C4CFB65526C2AB4F63096957E2EA +:1004B00049E1F95786A7FAF08476D31FFEFD7189CA +:1004C0007786789BA3DB2AE9773114BE2D873F4AD4 +:1004D00085DEABF06CE478FEA16AEF94EFE17D0D70 +:1004E0009EAB8167FB3F8EE73F423E1692DEFBF1FB +:1004F0004FA1F7465AC88FAEEC1ACA6E31B8F6DD76 +:1005000063717CE0E189CF929E5B1E7BA67E052312 +:100510003BDAB5536047BBEE0DFCAC2FFBDDF54F6E +:10052000E5823E5ACC9DF4BB31DE18F1AE7C77DA21 +:10053000ECEDCFF3F18A63BF4ADD8F7DF37218B91A +:100540004FE6CA7D893F6BF0BB80ED36B2B7D5B7B9 +:100550008709FBDA01BDFFAC3B49FC4E5F89A5A7CB +:100560007C05F472DE1FC651E7C1DA76F9FB2FF283 +:10057000FC56ABEC0CFB42DE8772BC41F5EAA68868 +:1005800078DB8C84494EF0A19605CC139EF175FC66 +:100590009E11BF57BF9737A01E3800DF57FA1FF3D1 +:1005A000EAED1C8AFF2C95BF2FD9B73F64BE7AAD08 +:1005B00037CA6A24BAA3771BEA1E15BFAFF809E849 +:1005C0002E2A404F0D323EEDD8F77F63C2EF3475CF +:1005D000EF12F7233887DC8A7BFA67DB443C5C4DFB +:1005E00041D718BF13BFD321F8D0B27D9ACF99D687 +:1005F0000F1D31DF06F1AE7D083DEDFBFA770FEF01 +:100600000DF091517FE7F0DC51C2A4DCF2F61B3F04 +:10061000D927BF427EC7E37F5A3C776F0E5FCFD7A3 +:10062000F81BAF4DD4BFE3729D53FF3B4DDFC9D6DE +:10063000FF4E53AF5DC247EA834A4F3D3445C8F190 +:10064000D054C1F706977E1C752EFEEE38FD78B3A8 +:10065000DDFAF1BE2D5EFE5571ADDF04BFE372DC45 +:100660001372DCDFC871FF5938A974A0F1FE7F4D09 +:10067000FF0F822563C60080000000001F8B08006A +:1006800000000000000BB55B0B7C94D595BFDF7CB0 +:10069000F3CC7308210904C2242421608803245464 +:1006A0002B94C9D300D6065C2D68840152C83B80C8 +:1006B000B5D2D6FE3208222F5BA8D1A2224E82E10B +:1006C000A1613B118289863A286411AD1B698BFDBB +:1006D000FD56DCF828F23213A374E5575DF6FCCF23 +:1006E000FD3E321942B5DDDDE4A737E7BEBE73CF6C +:1006F000FB9C7BA929CE317C394588DC9873E69E2A +:1007000008215CAB7A8A12B385E87B43154D0E2134 +:1007100084DB7BBC3E5688DA8EE1625332C1257D94 +:100720006F1A00B78DB36FA2F18DED7F781BE3BD1B +:1007300007558785C65F6BFF280AFB5CFC325C8827 +:10074000E158F7519420B8FAB2C2F0261A77103C5B +:10075000AB5515FE4CDACFE83363FC62AA0E7BCDB5 +:1007600082DA929656730FB5557B5B79FC0D9F69C3 +:10077000F0F8DEC641E376CCA7B6CAE88DB2537B6B +:10078000BE5DDFCFCFF3AB53159717FD7BFF10B7DF +:100790000CF35ADE895B4AED15FCCCBCB6FDF4D0F7 +:1007A0000B996E5A57D341FB440CEC53D361D26082 +:1007B0008977756A6B510CD14BB428228D9A8B6264 +:1007C000AB584DF4AC6A6FAE16D45F95718F49107B +:1007D0005D023EB518DFA71F8388A37576FA8BE804 +:1007E00077D1F779D452DAF755DFB1DB5DD4063A29 +:1007F0005F8FC2770307697EE6003ED35D44BF1C6E +:10080000B4662146D0BA83AF4739687CA3EF7549F7 +:100810006FA39FCFFD9A0607A8653AB7AB7CEE8A17 +:100820002F55A6BFBEDFAD2E95F799D59E168973BD +:100830009DF4C9EFCD7539647FEAE232E07F226131 +:10084000418E9ACC78BB000726CE69DE44A854F9C5 +:1008500068DFCC6BE9B654DBB7CB24E6FBC0B7D47A +:10086000035DA3483E4E140F9F4C2357E7DDE33250 +:10087000F0BC22B33B7505CD3B19E188B4D37E0FA4 +:10088000158F8B045F5F438BFEE25D6637B595077E +:10089000E5F74EDABBA3206F270F4E553DCAC07E49 +:1008A000776ADF15C2C3ED00DF3CCCA7726F63042B +:1008B000F619E09FEC9FEBB2F3FC13DE77EEBA87FC +:1008C000CE773223DC09BE749945B98FE5843E8228 +:1008D000EF752636820EFAF7E6821FB42E9061601D +:1008E000BEF6B69BB479F7348B41F34CCCB78BCFC3 +:1008F0000DC6C7EEFDE097F7D0FCEA675461A1EEA4 +:100900006AD38A389CFF931D83F12BD7E85C6DF284 +:10091000C7C505C96B75C7557D8960F9EED0F5C3AC +:10092000C1FCD4F978324395782558BC8250AE6E1C +:100930006D66B92675F3D8A6702BECD4268677277A +:100940002B74FEC407ACCEB584FF738A366EA03616 +:1009500086608384CDD45AA97DC624FBA1B6583FB6 +:1009600086D8A9106C2A1E976348A17DD4D6C9E009 +:10097000EBAB335D8FBA088FCD334B66CC043EA210 +:100980006F99A06FD65C8AF08868210AD5F79EC05F +:1009900077FB0F9A04EC478DB5A3F26392D37E27C1 +:1009A000290AE1DDBFC3E4F5B0FCB9229469422C09 +:1009B000BB49EACD270EF734751CCD5F63E0F355D4 +:1009C000B7A85E1BCDEBAD271210C93F6D4DFE01E0 +:1009D000E4B5FAB86AB7D2B9F37DC9BF9A0EB8C503 +:1009E000E4B4D0FA5A1F75125CBB57F13AE4FE0228 +:1009F0007A597313CBBA3863AB4D1159D4AEE9337E +:100A000063DE99C38A788CE66D0E8B6A02DE3599B7 +:100A1000B3CF2951D4AA5BD627D27ECBB79B3EEC6D +:100A2000B1CAB557E8BFBACE6D2CB715DEC1FD55BA +:100A30007B07C335C23800D3FECDF8E36621DA5C0C +:100A400091B1676EA0BF2788095754D0697A3CF4EA +:100A5000E104F84AF2241A88D82385B86F92331E2D +:100A60007ABFD1E8980D3A043A4D76D0ABEEF081DA +:100A70000AE0EDAD0E731AE8A8B5AB5F61BA06BE29 +:100A800020BADF486D82E0F30784A46FA05DCA79C5 +:100A90009D49F15AB19E68C8FB5915EF1A1A0A7898 +:100AA000FAA3D83E09510CBD58B520C7003B073505 +:100AB0001684CAAF747D506C46251AADD4FFEF1969 +:100AC0007BD4614176E23F5D298C7F8159B87DD42A +:100AD0007F5FA4331A723FD61A9505BCC65A93BCE1 +:100AE000A0FB5863DF1A7C7FF328C5F1106D7D24CD +:100AF000EBE5C90AE0DA0827E44449586C043D36BE +:100B00008F5A6C84BC8FB5FB324A3207E0028C43AB +:100B10001F8497BF5714E136E23BCF8D54FC06DAB1 +:100B20003F6023FCA02746BB09F8054C121662CD96 +:100B300020FCC82231FCFF8E9F9DF08B18C08FF8DF +:100B40001D8DF59F67137DA84D9A2B4437DB8515C6 +:100B50006C17747A5E24792F205EA529526EAA77CD +:100B60001C29C2788DE85E8F754551F21C45380FFF +:100B7000E030D9AAB9925FB95A7B7FAEF42FBAFDA3 +:100B8000ECC8751973A9DD9E5B62465BA866C6F763 +:100B90000C61EF5729569693CF49FF608FEF5DA107 +:100BA000D8533306E45BD7AB3AD975557FAA7EBFDD +:100BB000CB2C52F0395777068D970BA9D78B56DB84 +:100BC000ECA9C17A043D237A94DB2B6E13A46FEE5B +:100BD000D571F6D4A9D4AF5E340BC89EA65FB1F42C +:100BE0007B256508FDF285E865FB60D86F9372EEA2 +:100BF0008F54BC6B09FFD4DCC17A97A4E941A35B95 +:100C0000E1F3357E6564D853AA7841F33BA9737547 +:100C10008C7638CC2BCFF5C23FDE496029FA1B62B7 +:100C2000594F7990ECD7BF68E7BCD3E83F02FB711E +:100C3000CCE44BB6D3D0B11AAB13FB2F1014E89011 +:100C40005D2B15DDDC9E0AAF6DF3F3E69E3190AFB0 +:100C500077DD1627E2B0C6754D91B0E359629DFD70 +:100C60004C06820AB1F7CAD4EBC7332438E28CCEE3 +:100C70001738628A53C06F9DAFDB735D79B939D77E +:100C80005F5FF5A7B6DBBF03FB757FB3395E8A49AB +:100C900077C6B401BEE97CAD131EC65BE7D755FE2F +:100CA00011EEA3410FF5E25CB633CFAA82E30A8DC1 +:100CB0007F56FA1D8A7F3A7D676A7C58DE21ED51A6 +:100CC000285F757AFF9036C4F7C98FEE607E080BF7 +:100CD000DBBF50BE7F135F28C22CC5507EAC458061 +:100CE0009F8906691F1397919C10DEF708F7E11E94 +:100CF0006AEF0A7FCBC472A8F1E75EF087A6BE2B2D +:100D0000BCDFCF48FEBFE34F476EC903C17A18AAC4 +:100D100077D7D3B36A87F3DF75BF479686F42B4442 +:100D20003F43F44FE7977B7514EBD9553EAA2D52FC +:100D30005F357E45D0EF90FA863FE87B35ED8AD768 +:100D40009FFC2DF44F21C4896F8F85E89DCE9FEBCA +:100D5000D91DDD4E9D16FE63763AFFA9141907785A +:100D60007E62F136034E3794C3EE9D9A28DB039AD8 +:100D70007D0B6D4F539CA3901FDB94717204FCF5A7 +:100D800029B3BE8FCDDB4CF89F5ED33D6625AD3FCA +:100D90009D2BDB53880B836057985804BB7E7AA445 +:100DA000C5033A9D5626E4C13F9C561EB85DC2F16C +:100DB0006607E005F17976824F99E47CDDAFE8F6CD +:100DC000FFF482EF14F03C451C053D1C8A28E1EF3E +:100DD000284A4C31E173FAFEB4296BC5C0F99B7205 +:100DE0000DBCCEABD96FC283E9DEF753C5DB445DE2 +:100DF0008BE05208FFE4BCDF14A750FFFB3F1B371A +:100E000019FC75AD1AFC7DF8EBE41B016FE37DBEA8 +:100E1000F7659F6971905FBAEA270B3E93FD6539CC +:100E200006E84BB9C64357CC8468F0A7DF3B2E1ABF +:100E30007E47F743FDC70F44B883F8768EFC9418BD +:100E40001F044F783429D88F1DD9BD391DFB949BC1 +:100E50003D594EEA3FDBF87412E28DF2DD8FA47348 +:100E60001CBC7B633AF299F2A6CDE92E86C3DD9CC9 +:100E70004F19E5B92FECBF79D7A6A0B8BB2A5F659B +:100E8000FC4BAD470AE16F67DFF0E9C3769A97F64E +:100E900033C50EF1BA57743F0CFFB810F131F2B7F9 +:100EA000062BDB73DACF05FE374FF8FE73D0E31362 +:100EB000191F99CA68DEE55C23D367A1F06E89A784 +:100EC00071B141B1378BE0F9631A317FF13AC59CBA +:100ED000003BB062D864D58175C3188F251B267777 +:100EE000A17FE183B27FB6C57BF024F6F98DD9D915 +:100EF000EC607B9352326900FFCBB9665EB7688BBA +:100F0000C2F1BFFE9DB427E21A83CF7959E3BFF83F +:100F1000CAA2802F3FD0F872DB83EF1C4DA07DED7D +:100F2000B1EE2BB01B6F3F7E26D54FFD0531E7326A +:100F300021E76966F75315387793C5897364672588 +:100F4000AAF1347FCA8F731F43BBE8C1C54F55C098 +:100F5000DE6EB772DEA6E3B74A711A608F5F6FFC70 +:100F6000E112D0EDECE3568EDB57358E8F1743E858 +:100F7000A9DEEE21FE3B28D1D9576FE5F6857ABB75 +:100F800070903CECAF4F60F8B7F50E6EC57C295FF2 +:100F9000ABB4FCF87AFB4DFD325C38289ECDDE60A8 +:100FA000130EB2534971AE517974CEB489354D1BCD +:100FB000B573A5D1FAC99EE47CD0217BE3CA2E8407 +:100FC000BCE63C998FBD797243128CF2F2073FD890 +:100FD0005941E373F34AC6E551BF75C7675C57785B +:100FE000BDE39185A0777993459E4F3BF7D9C7D351 +:100FF000E39FA2FD3D6F9838DFAFDBF1C1CE8DD40A +:101000002EDDB2D21C2CEFDFF6BCC91A3EDFA4578E +:10101000D7A3C33FAE579B93587F9A48AF32FF790F +:10102000BDAA7B700DD3EF81BC92D9A0FB59932749 +:1010300009FA7476C20C9673CF6185E9AFDB717DD6 +:101040007DB176DE2A836FCBF4E4013B7E496433C5 +:101050007D8F747C928EB8F752FB82BF7BEE437417 +:101060006E3F9DBB9DE8EB1F7FEDF834B37B9C93F7 +:10107000CE37CD20E3DD6BE2D63C83562FE83697A2 +:10108000444A9A2BA8CB68FE93FC98279AF0A9EEC5 +:1010900054FC6159F067B79E3322DFA3BCF1C3E073 +:1010A00038827E3E0CF2DBD7C3F79BDA5AEC9336DC +:1010B0006077BFF36783F007F9E99B7BC2843FE861 +:1010C000BB57F313EA33139F7A3B46B25D00DF8CC4 +:1010D000A8C7754C68027CCE2CF9D87B88E22659CB +:1010E000C711EAB481739EEBB890053B1B7ADEDA38 +:1010F000972FB07C54B73FF299C2E79F75CE98F511 +:10110000CDE73FB2FB4216F877CED4330DF956AF98 +:10111000B9270B7CA87D45DAF37F940E7A7FC5064C +:101120003A08E979AD62653929542F72DDA0F7B824 +:10113000AC1BD476EC627BDADF29EB377586EEA246 +:1011400078D43B567CD0057BD69F20F328DADF0588 +:10115000BA4D1FA7F941635FD25CB26B2F5E950752 +:1011600099FF9D85FE8EC73EBE6AD80191152E104F +:10117000579C873E53FFC2D5C9EB21E767BD23A625 +:10118000C03EBE99F5B75AAEF7BD1A6E5739EEA1FB +:10119000DE20FE5D3D875715AE41F58070E10A9A6D +:1011A000576776FC80E3E313AA405C573751EA9314 +:1011B0007859EA53CDBA23E684A0FD76429F186F92 +:1011C000192FCE7EF56FAC975B66BA3AA197E1B066 +:1011D00085D82F21DAAB28DA3CE27FAD864344A7DD +:1011E00096F717AB3C5ED7AE8A91589310E94DA3A2 +:1011F00073148BAD46C4D3B3856F3AEA36C2D8F3C5 +:10120000CB5B687CCEABEAD44D82F3A745259C57D7 +:10121000BA5357213E32281A5D7DD97383FD599EFA +:10122000F453D35585FD58DFC8708E5366CDAF2972 +:1012300005BEFABCAC61721EEDC37196F0F665CDC9 +:10124000857EFAFBB2E6450ECCBBEBD5F015EC176C +:10125000852FFBAEA0EF84E5CBFAE8E7E447202733 +:10126000759764BDA350FDEA09C4E7AB0E93BC209B +:101270003E3424BF6B801D273A83AF1788AF2EF80A +:101280001FB770B9A03F934678A13F75FB15614425 +:101290009DA8C3D2843A52ADA9270EF2BCB1FD4F2E +:1012A00066C8735DDB3B66C724AC9775275248B6AA +:1012B000E3759AFFAA691FFF2EEA7C35C7A517AD13 +:1012C00031BEC3F97BD5C156CED3AB859FF3F4EACB +:1012D00096C1F2D29FE0E0BA48A87E84E53B06E9D9 +:1012E000C5ACED522FEE52C50AD839A1D569672594 +:1012F000C4733C32B04EC6BB2EF5C2C3885F022910 +:101300008A53A1AD02619E75888B3CE9329E09FC2F +:10131000EE85EC656C57BCD977D0B9025ABC3B6BF3 +:10132000C336A31A84CFAC4E59970C8489F243CCB0 +:101330006FF768F041B84A22F27358AFB2605703B2 +:101340000659470D3D47BD562F3A817A52E600DED9 +:10135000731213A51D135E969F2E83FCBECB40E334 +:101360005306D62FC997EB07F2215907BB9E5DD9CB +:101370004DFC2923FEEC253EA37D9EFC7119D999D5 +:1013800016F2C780FF95FC315A5F7D06F7BF58EF14 +:1013900064F860FD4D0C1FAA7731DC5E5FCCEDCBAD +:1013A000F525DC7F02A87E17FF7BBA11F2D0051D60 +:1013B0001B35009F8A0981470D9E7F2A46190C8F95 +:1013C00052787E76FED38D1ED48B66DA35FD764458 +:1013D00022FE3A6B9375A8B33659876A1DE5BE2580 +:1013E0009FC6CB66ADDD2DF350573AE615C42CE011 +:1013F000FCB59FF257D8A395F9EE3CF0E5F8F1FC67 +:10140000D46D6C276D5C073D75F70DD15C077C834F +:10141000F271FA746EC6D475D904E746282CBF64FD +:101420002F6E2CD1F34ADA27BF53DEA314AAD56559 +:10143000D87FD548DB54D8DFCF5DEEDB80874EEF19 +:10144000A251CB53110F75991CEFA28EEBF9BD4938 +:10145000209FD2EB7DFABC0E57EEDD58372B63DCB4 +:10146000BA29B03BA464B0732EB368015E2E43B8B2 +:10147000B296ED96C3083B70B726C7790E1917FBD5 +:10148000CD0E630CEA3761B9B11E5AD7A5F1F9B890 +:10149000C6E7131A9FDF429D8CDAB7A91F6D37F597 +:1014A000A39D01FA4A7965BA3D915752C6F22BFACB +:1014B0009200EB75C1D9D02F696F9220D75B34F9B8 +:1014C0004DD0EC4D576E49955CE7E37DAAB47ADBCD +:1014D00005ED1E443FAFBE6E60BDE076DE8DC2639B +:1014E000859D7F49E69D6234C52304CF7B299EED0F +:1014F000906ABD23F363D2F37953651E200E58E43E +:10150000BC04470EF464AD566FEDF51A3C26D4A723 +:1015100063BAD363E07F35FDD2E143FFADB2BDAE28 +:10152000994230B5AF28F27C35F3BAD38761BD62FA +:1015300033707DBB498E9FD4F4AF2645DB4F3B8F84 +:10154000B0FA92C08FC0E197929610BC29C2BF4CEE +:10155000DA7D7F3ADB6BE14F9F07BBA8F8DE174EC1 +:101560008A2B0BA62E318E043D7C3B015717E42CB1 +:1015700031DE8CF1D6F7EDC1E3237C498A1D70B6CC +:101580001C1FD1BA7398330836BDF83EC6CD869C71 +:10159000250504CFB1788FD7436E7E2BE5CBB6BF40 +:1015A000ED0CE856D521E3F6BCFD6D175F845F6E48 +:1015B0008B74C2BCEFCB4F667AAFEDD8B305F2D6D1 +:1015C000DB2AEF0336B5FC69E7CF799E05D724B453 +:1015D000AF2F5BD077561EFDE362E03527DCF705C1 +:1015E000E0878ECE643CE70C977AFDC8D1BC25D04D +:1015F000D3DEB6FD3F81FECD89A68016F8BC60E340 +:101600003A44E5810905D0D3DEC8EE85D8BFF67926 +:101610008B13725A79203E0FF58143F9B21E5E3169 +:10162000716B12FCACE1E57DBB7F8EFBD5E76D7C79 +:101630002F541723E3BC4AB571DA4AE6DFAEDD4F1B +:1016400003EF7D36BE9FAD40AD8AE08ADD695CC7A1 +:101650007FE5EB8F16820F85EA8EDDE8FFE2399B8E +:10166000017438697645CF801E9E3471BE59A1C180 +:1016700015A7864B7CC27B8A987FB15B93E0672B72 +:1016800087FFF476E03D47DDBA13F98ED863E1BBFE +:101690008973FB886EB4EE5CB3690AB8DCBB2FD2E9 +:1016A0000879B9A06C5DF814F66F96F32ED8B632AF +:1016B0003D3DCDE305BE47F304ECD60565DBA0FE5A +:1016C00073CD7BB2908F9E7F7E0EE7A5BAFCEAFABF +:1016D00052F99C65905F644B40F6A852FB5BD83D85 +:1016E0002282FC6D85069E3FF464EF536260FDF933 +:1016F0001693DF4C34AAB08875D698017DA84CBCEF +:10170000B518E7AB3434A6236EA998DAB3107A7112 +:10171000CE26AC0934EF4DCD6F551E5C3317F1EF7B +:10172000F5F0B9A2D9A34B09D27F5D6AB77983EFEF +:101730002543DBF7EA85FDADB401F8DE15168EE131 +:10174000F5FDDE34FBAA91A7D5C648FBF13ECD6F6F +:10175000213BF6B5E6EF16AD1E3CBF3F3F86BF5FAF +:101760006BEE4987FFD3F70FE46B7EC3D8930E7BF4 +:1017700015BA6E0EC211D8911714B6239507950F9E +:1017800054A253A5D5E355411761D6CF69BCA2C871 +:101790007509D334BAD3DA0D05C9FCDDCA169BCB63 +:1017A00046EBAAC27AA210175547F64421DEE97D1E +:1017B00059154D1ABB62E334FEA4682C0BAA3756A8 +:1017C000F84C2E5BD6107C46FC44F396E36FFAFE91 +:1017D0003305297C9EF2F670FE9EB0F74C839C96F2 +:1017E000EF18BC0EE7B207E95F6FFBAEB8E0BC3C98 +:1017F00045C33BA07CC07A12F8FAC324F0BDD220C6 +:10180000D6E1FEF23CADC1BD26C1C22A61BEF7AC35 +:10181000FC6B4418E4E5FCA56AD6DB5EA587EDDA2F +:10182000DB0573D92EF59A7AD8AEBD7EF42EB60FAD +:10183000BDC37A16C24EBD5DB05C8E8FEC59E8A078 +:10184000F1FD3A3C46B0DF7FEF680DDB8F39AA7CB3 +:1018500057217699ECB21EB4E1543DE71726477044 +:10186000FE7DBA40ABF70CF087F32E5D6F7A85638F +:10187000FF41E8617904D775288E6A7911F1DE821B +:101880003827DE6B94639D940373F07D636CCCE525 +:1018900065E0CF1DA3DD450539B8DFECE13C82A44E +:1018A0009AFD4DEDEF2C9C4F064C7DBB61A7D247B6 +:1018B000BB6717101ED5E6EEF5D984D245534F17F6 +:1018C0004AE4B355698FC41E2957BD99BBE43D8DC9 +:1018D000765F79B7467F41494C23E44291FC7DBD58 +:1018E000FDC05BB02BBDDDE3D81E87EACDB9F6C7DE +:1018F000A2601FFE4C7EDC1394EFFF79F11EBE67E1 +:101900009D8FF720D42E5937581EFABFBA83F33E65 +:10191000B125A81F72D830180E9523C8A37F90DD7B +:10192000F130DDB76B7A5595D75D0B3A5C85E711E1 +:10193000AC06C1AF85C021F345898C13B6C3FF1334 +:101940003DAAC7F84F719EBEDF2460C7D792FF62E1 +:10195000B82DDC8B7CC5B09FFC53ACF44FF00B551D +:1019600051DD5C9FEA6DB3F07DEF431D9F24E1FCE8 +:1019700024875C87A9EA78290EF9FB3E2D5F203F7A +:1019800018C7EF63DA3AE29077E8FDD5065F3AF0E0 +:10199000A28888E375BDBF46F5A703FF2AA53B0BC8 +:1019A000E3FBF2EDDA7C8255C082CF51AD487D1762 +:1019B0001D2ADBF350BE3DA9C92BD9852C7EDFF152 +:1019C000B2AC0FE876A042B327AFA13F53EABD5DAA +:1019D000BF57A2A515D0F721EC4342811E17AFE0F7 +:1019E000FACDE3050E096BEB795F595FE2F1DA5747 +:1019F0002E64A564629D362FD80E8D1BB02BD0FFB0 +:101A000004D6FF874C7174AECA9D8A732DEC54E9DD +:101A10009A229A2E961B571671DD4C78386F0BC59B +:101A20002B548E2617483A551A8615C606ED779E12 +:101A30006C7AC214B6337ED89D1FC53E5A843AC50F +:101A40000F4BE5BB81ABFE2658CF719E1DD28E4356 +:101A50006DAE18AE95E3E52B1AD7C70F8147289EC8 +:101A600015EEC6A238C7B5FD3ABEE76D3A7E79A637 +:101A700011C17498BFA66804B5CBADFF2C1DE479E5 +:101A8000CF7758FCF0AB15A52BD7470F2137D7F8E8 +:101A9000831D41FE2B05FCF5F2FDC6F5F00F6DAB85 +:101AA00015FF29D48B04E95533EB17E94B905FB848 +:101AB000B920A4EE50BE782CE26AE15E3C167E8628 +:101AC000F46AA17388FC920CE42803BF19F1701B1F +:101AD0008ACF5F0AE4BBA49B0BA49E6F99E90AC05E +:101AE0006ECE500D1C8787EEF765818C27BAE322F6 +:101AF000EFD7DF7380D9335449B74443FFDBD0B706 +:101B0000C4B84807EE830AF3C3E5BCC3363BEA37E3 +:101B100081C397B9BE1B783862BEBC378810236971 +:101B2000BC2B615253B01FF975A13C6F78B68C5B2A +:101B3000EA324C7FBF3E941979B53EC47143663892 +:101B4000DF97F4B67FCE7E2BD09963C7BD466F3743 +:101B50006587A44F755FFF571CFC6B6FE75FF81D2F +:101B60005AEF579FF0FBB48DDAFBC0D7DAB5F75DBB +:101B7000DD8E48F4078A3F2AC2BC4D5A3B5027905D +:101B8000F562BDD5F35FBD1E1094078F2E1C3A0F72 +:101B90008E714704D7091CF143D55582EB04A9691E +:101BA000B24E801675825493AC1300469D002DEA08 +:101BB00004E8479D0030EA04805127008C3A015A1E +:101BC000D409D0FFC57CF95E2640422CEB97116CFE +:101BD000DFEF6B56BD88CFEF3B2CEFA1EE6B54F8D7 +:101BE0009DD645FA3EFCDC35EF750E6AEF757CDB61 +:101BF000F85EAFAE4D75825575A6BE63A8EBD4B541 +:101C00002ACE35B02FF5F3F9FB1B3B73DE2D457F54 +:101C1000B3C96970804F97E250AFAAEC6CE6FA53F3 +:101C200041FC6133F3B74511A897DE6591796E8D5C +:101C30004ABD53F83E94E3E01A4B37E71F557B1536 +:101C40007B59F07DEE4D9FB11D586B8B6A029E351E +:101C50003E9BBD6C88F71F7C2FEC1057EF9B97C9FC +:101C600029A226A288EF9B97E19E995AA17E65E45E +:101C7000FB634A4C87431EF1AE2A0366DD2EF53E18 +:101C8000E43D556567EBFA4471ED3D342A03E07F8E +:101C9000E8FDB3BB3032F64C380C85988CB8A9F807 +:101CA000F1B2FD6DF4BDFEAD168E3B56E6BB97431B +:101CB0008E8E995C5C273976D8C6F9D1C7DBC60F02 +:101CC000AA937CEE725717F2FDFC68AE5BAC32292A +:101CD000EC97F38BC7C5F3BB81E326F63F1DAE92AD +:101CE0005ACC5B35C9C1F5A9428BB89FF7D1DE69E3 +:101CF00051CBFA54B856F11A085E2C9C66E8CF22F4 +:101D0000221BCB8B296203DE532D12F27D832E37EB +:101D1000ABB6291C1770A1200EF79292BE8B3AFF2A +:101D2000ED32DE2F2CB5C8F835D120EFB31337C90B +:101D3000F72D3F126E33FCED72F28B68C94FFEAE89 +:101D400087FADDE1A393647CEE88C7FE8B4F98F899 +:101D5000BD6F61FCF7D3DDECAF0BF81D83E2BF472D +:101D6000BD72C3F5F527F41DC33193B42F4447CE9C +:101D70008BBA20975C9F71737BA2BE9CDB1933A545 +:101D80009DBEFA2E91786407FEE17DEF235F4C8CB7 +:101D90008F74C2DEE97A7FCDFBC430D9EAEF13C776 +:101DA000502B82DE276E713978FF44C3C9A90ED04B +:101DB000E3AF114ED0437FA7B86566C92EF0C915B1 +:101DC000253CF82EEE51B6125D8B701005756E9F96 +:101DD0004B45DDFAB062E777D1D7D8C96D0FE31D67 +:101DE0004F5DAA62571CA8876F2D8C23BC8B529223 +:101DF00019EFBA76592F650AC5A19EAEE983CBDDEE +:101E0000563862A07F8EA617BD345FCAC92D5EC842 +:101E1000DBB7A8A33E87F91E6173366BF91AF83E4B +:101E2000E786315C4FD5E5A6BF25BE0972F346A112 +:101E3000F433A5A5EF98100774E5BA8FE2FC0BCB3D +:101E40003E7B388ECF37741D8BEC28DF4B86D6B1A6 +:101E500074BBBC5BAB83C37E1AB53AAB51ABB31A50 +:101E6000B53AAB51ABB31AB53AAB51ABB31AB53ABD +:101E7000AB51ABB31AB53AAB91EB772BB87DBB7EC8 +:101E800035B7DDF51E1E0FB2FFEF5DC7FE87D641E9 +:101E90003FC2BCD03AA8B03AA2D98F927ECBFA7397 +:101EA00048DDB378F8920D44BFFC06B3135D7A1D8C +:101EB00014EF97EF8B607B70B170C8FAA74EB7082C +:101EC000AE97F60BDB14D03F2F639CD140E37FD558 +:101ED000F8A0D71FA11F381FF4032DF4C39836A014 +:101EE0001FCF984985B3A5BFF7B0BFB7315FD7AF54 +:101EF00021FB41F052611F643F2E86D80F4A3CEE11 +:101F0000061ECB3AE5BB26FDFD661E355F4E19C2A7 +:101F10009EF8A43D1913E6DB87EF8CA90DE3F7C10A +:101F2000C7B4F758C736CA777165A284BF3B845DD2 +:101F300089023F960EEF7BFF699ABF747304C72D29 +:101F4000EB472E9BF6BFB12B9F150AA6DB6FEAFD70 +:101F5000951F132E056152FE0ACC2203F735C210DD +:101F6000C67A50A86E51703FBAEA5E31197C2EB025 +:101F700094EC009EF1DAFDB688D5EAADC6EE8A3D56 +:101F8000049F8C4B74E25E6B74C22181F74F8575A0 +:101F9000C599B08BFE31EE09453978BFBC55C1FA01 +:101FA000F04C79FE3B8AC39B205781C3E373C0EF9B +:101FB0007916471BEA00CEA284A5C8F3E7453B7219 +:101FC000500770768D9270BCA34D7122944D585A73 +:101FD000C0EFCFAC5B3FB6E2DD9A22A2E95C96612E +:101FE000EE1C7CA7A6F85399378B3EF6633717C9CA +:101FF000FC6BC46BC28F7BABBE59917C7F26321DBC +:102000003918A7B8F2BB45241F7FFC9EEB16AC4FD6 +:10201000D4F08CC72DA20AAE76DBD09ED0EEF3BAF8 +:102020000CEE52B445511E23F71BBCD968DF34F8BF +:102030007E8C7E92E722EC57F4D8E4891904275A63 +:102040007C6C273B5CAE5BB1FFAB335DC5180FAD5D +:102050009F83B7C8F3099FDB302FF41D96CECFA521 +:102060004552EECB8AA4FD98BE56DEC786F2BDACC3 +:10207000C8A0D9B7BF8F37E15B8AEFE9F88BAD8B8A +:10208000B3810FE17B2FF0247C17625C44C470BDE8 +:10209000E3FA72E6E1EF951549F9227B56F5B1B402 +:1020A00067DCA61BBDC3103F8EFA857718F01DD5DF +:1020B000D867C3BFC378D6D367837F7FF6C13E1B83 +:1020C000FA9F75C977D2A1FB3716C9F713E9D3FB7D +:1020D00078FD58FA5637C7E97DC31047A5977FBCEE +:1020E0005EDEBB64B07F19ABF997B1BF4869EF21E1 +:1020F000791BFB6434DF6F8B82581EAFB44A3DAD51 +:10210000FC45D9A1366AC76F277C83E2AF095EC25E +:102110007B505C64EC97EF2D09069DF69A1886CCEF +:1021200022BEAA11F2BDE528CD6E206E2B25BB5034 +:10213000537EF432BF03C07AEC8F3B5BC85FBB4970 +:10214000C2E4AE918F2E9FBFA68BF3C3ED57FBB5B4 +:102150007CB3753DF2678ADF06F557961DE982BFAD +:10216000A9DA3BB8BF66C5679CC752FC36A8FFDE3C +:102170001F7FC0EF6CEADA07F7137F9F029F75FE9F +:102180001E33F92620DF3B5613E694FF7EC0B712BC +:10219000FADE541DC1EF6777FD3A8FE546E737ADAC +:1021A0006FFA76F2B196E77BF24406F4E19BDA5ED1 +:1021B000D8A7B441F6C9C375BED9916C77EAB4FC0F +:1021C000AAB6CCCE7E3EB1D6CAF6AB500D7302AEE7 +:1021D000354A3B238A55CD4EF958FF4FDE3E8CEBF6 +:1021E000797C00C03193F8DD71DC5A09F78DB0B00D +:1021F0007D28349454EFA1F6A86105DB8104BCB8B6 +:1022000024BE3F03FBA0427F655DB5CEEC53E4FDE9 +:10221000BE2307F9AE7EDFD4B0D1DB7A10F9B2E28B +:102220007D7219EA8A7746F0FD4100F5463A4FC3C0 +:102230003069471B16A4B31F088892D2958843E6DD +:102240008771FDB16198E351DC2736544CE438FACC +:10225000D07F4BBFDB37D7EA441CD530D9B106EF6E +:10226000551A7EE1E0F15714B99FE751499F86B9AD +:10227000F2FC0D15319CF7E87C6868748DC4FDD4C0 +:10228000CC31EEFF00DF4769F7730DC9D44FED1372 +:102290004AC9821F619F4912DF19331DAC77C716E7 +:1022A0004C7C74B783DD891FF74475B32307E5C5FC +:1022B000FF033C759D8B10370000000000000000FC +:0822C00005020D000000000002 +:00000001FF -- cgit v1.2.3 From 3359fced77f6b4ba1c7de9deace1d7dfa7217bbc Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 13:35:01 -0800 Subject: bnx2x: Use firmware 5.2.13 Switch to the new firmware version (5.2.13). Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 4 ++-- drivers/net/bnx2x_fw_defs.h | 7 ++++++- drivers/net/bnx2x_hsi.h | 10 ++++++---- drivers/net/bnx2x_init_ops.h | 13 +++++++++---- drivers/net/bnx2x_main.c | 2 +- firmware/Makefile | 2 +- firmware/WHENCE | 6 +++--- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 602ab86b6392..d997d8472ee5 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -1,6 +1,6 @@ /* bnx2x.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -130,7 +130,7 @@ offset, len32); \ } while (0) -#define VIRT_WR_DMAE_LEN(bp, data, addr, len32) \ +#define VIRT_WR_DMAE_LEN(bp, data, addr, len32, le32_swap) \ do { \ memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \ bnx2x_write_big_buf_wb(bp, addr, len32); \ diff --git a/drivers/net/bnx2x_fw_defs.h b/drivers/net/bnx2x_fw_defs.h index 931dcace5628..08d71bf438d6 100644 --- a/drivers/net/bnx2x_fw_defs.h +++ b/drivers/net/bnx2x_fw_defs.h @@ -1,6 +1,6 @@ /* bnx2x_fw_defs.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -471,6 +471,11 @@ /* Host coalescing constants */ +#define HC_IGU_BC_MODE 0 +#define HC_IGU_NBC_MODE 1 + +#define HC_REGULAR_SEGMENT 0 +#define HC_DEFAULT_SEGMENT 1 /* index numbers */ #define HC_USTORM_DEF_SB_NUM_INDICES 8 diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index 52585338ada8..760069345b11 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h @@ -1,6 +1,6 @@ /* bnx2x_hsi.h: Broadcom Everest network driver. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1261,7 +1261,7 @@ struct host_func_stats { #define BCM_5710_FW_MAJOR_VERSION 5 #define BCM_5710_FW_MINOR_VERSION 2 -#define BCM_5710_FW_REVISION_VERSION 7 +#define BCM_5710_FW_REVISION_VERSION 13 #define BCM_5710_FW_ENGINEERING_VERSION 0 #define BCM_5710_FW_COMPILE_FLAGS 1 @@ -2433,8 +2433,10 @@ struct common_ramrod_eth_rx_cqe { u8 ramrod_type; #define COMMON_RAMROD_ETH_RX_CQE_TYPE (0x1<<0) #define COMMON_RAMROD_ETH_RX_CQE_TYPE_SHIFT 0 -#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x7F<<1) -#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 1 +#define COMMON_RAMROD_ETH_RX_CQE_ERROR (0x1<<1) +#define COMMON_RAMROD_ETH_RX_CQE_ERROR_SHIFT 1 +#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0 (0x3F<<2) +#define COMMON_RAMROD_ETH_RX_CQE_RESERVED0_SHIFT 2 u8 conn_type; __le16 reserved1; __le32 conn_and_cmd_data; diff --git a/drivers/net/bnx2x_init_ops.h b/drivers/net/bnx2x_init_ops.h index 38b970a14fd7..2b1363a6fe78 100644 --- a/drivers/net/bnx2x_init_ops.h +++ b/drivers/net/bnx2x_init_ops.h @@ -2,7 +2,7 @@ * Static functions needed during the initialization. * This file is "included" in bnx2x_main.c. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -138,11 +138,16 @@ static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len) static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, u32 len) { + const u32 *old_data = data; + data = (const u32 *)bnx2x_sel_blob(bp, addr, (const u8 *)data); - if (bp->dmae_ready) - VIRT_WR_DMAE_LEN(bp, data, addr, len); - else + if (bp->dmae_ready) { + if (old_data != data) + VIRT_WR_DMAE_LEN(bp, data, addr, len, 1); + else + VIRT_WR_DMAE_LEN(bp, data, addr, len, 0); + } else bnx2x_init_ind_wr(bp, addr, data, len); } diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 24fe083ee1be..164a5e875d4f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1,6 +1,6 @@ /* bnx2x_main.c: Broadcom Everest network driver. * - * Copyright (c) 2007-2009 Broadcom Corporation + * Copyright (c) 2007-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/firmware/Makefile b/firmware/Makefile index 1c0be73c8082..8af0fc7210b1 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -32,7 +32,7 @@ fw-shipped-$(CONFIG_ADAPTEC_STARFIRE) += adaptec/starfire_rx.bin \ adaptec/starfire_tx.bin fw-shipped-$(CONFIG_ATARI_DSP56K) += dsp56k/bootstrap.bin fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw -fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.2.7.0.fw bnx2x-e1h-5.2.7.0.fw +fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.2.13.0.fw bnx2x-e1h-5.2.13.0.fw fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j9.fw \ bnx2/bnx2-rv2p-09-5.0.0.j10.fw \ bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw \ diff --git a/firmware/WHENCE b/firmware/WHENCE index ac174feda7cb..e8e550fa2423 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -679,11 +679,11 @@ Found in hex form in kernel source. Driver: bnx2x: Broadcom Everest -File: bnx2x-e1-5.2.7.0.fw.ihex -File: bnx2x-e1h-5.2.7.0.fw.ihex +File: bnx2x-e1-5.2.13.0.fw +File: bnx2x-e1h-5.2.13.0.fw License: - Copyright (c) 2007-2009 Broadcom Corporation + Copyright (c) 2007-2010 Broadcom Corporation This file contains firmware data derived from proprietary unpublished source code, Copyright (c) 2007-2009 Broadcom Corporation. -- cgit v1.2.3 From a07da6df730b1fef933f66c03b0e51d5e7ad5b3e Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Wed, 17 Feb 2010 02:05:54 +0000 Subject: bnx2x: version number and date Updated release version and date: 1.52.1-6 and 2010/02/16 Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 164a5e875d4f..a4e8460ff656 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-5" -#define DRV_MODULE_RELDATE "2009/11/09" +#define DRV_MODULE_VERSION "1.52.1-6" +#define DRV_MODULE_RELDATE "2010/02/16" #define BNX2X_BC_VER 0x040200 #include -- cgit v1.2.3 From 7af3351f71f4b3b5dbccb66cdc9b097052760a7f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 17 Feb 2010 09:26:54 +0000 Subject: ethtool: Don't flush n-tuple list from ethtool_reset() The n-tuple list should be flushed if and only if the ETH_RESET_FILTER flag is set and the driver is able to reset filtering/flow direction hardware without also resetting a component whose flag is not set. This test is best left to the driver. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- net/core/ethtool.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d08a0c7675bf..31b1eddc1b84 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -654,9 +654,6 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) if (copy_from_user(&reset, useraddr, sizeof(reset))) return -EFAULT; - /* Clear ethtool n-tuple list */ - ethtool_ntuple_flush(dev); - ret = dev->ethtool_ops->reset(dev, &reset.data); if (ret) return ret; -- cgit v1.2.3 From 08326dbe7b5825295ec3711eec53b093549749e5 Mon Sep 17 00:00:00 2001 From: Riccardo Ghetta Date: Wed, 17 Feb 2010 09:28:58 +0000 Subject: SiS190/191 half-duplex initialization fix Adds half-duplex specific setup code (taken from SiS own GPL driver). Without those, half-duplex connections are very unreliable, often working on small transfers and failing after a while. Signed-off-by: Riccardo Ghetta Signed-off-by: David S. Miller --- drivers/net/sis190.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 8c4e38f9ebf7..bf2ffbb913ff 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -47,7 +47,7 @@ #define PHY_ID_ANY 0x1f #define MII_REG_ANY 0x1f -#define DRV_VERSION "1.3" +#define DRV_VERSION "1.4" #define DRV_NAME "sis190" #define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION #define PFX DRV_NAME ": " @@ -294,6 +294,7 @@ struct sis190_private { struct mii_if_info mii_if; struct list_head first_phy; u32 features; + u32 negotiated_lpa; }; struct sis190_phy { @@ -1004,6 +1005,8 @@ static void sis190_phy_task(struct work_struct *work) SIS_W32(RGDelay, 0x0440); } + tp->negotiated_lpa = p->val; + net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, p->msg); netif_carrier_on(dev); @@ -1211,6 +1214,12 @@ static netdev_tx_t sis190_start_xmit(struct sk_buff *skb, wmb(); desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit); + if (tp->negotiated_lpa & (LPA_1000HALF | LPA_100HALF | LPA_10HALF)) { + /* Half Duplex */ + desc->status |= cpu_to_le32(COLEN | CRSEN | BKFEN); + if (tp->negotiated_lpa & (LPA_1000HALF | LPA_1000FULL)) + desc->status |= cpu_to_le32(EXTEN | BSTEN); /* gigabit HD */ + } tp->cur_tx++; -- cgit v1.2.3 From 069c474e88bb7753183f1eadbd7786c27888c8e3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 17 Feb 2010 13:41:40 -0800 Subject: xfrm: Revert false event eliding commits. As reported by Alexey Dobriyan: -------------------- setkey now takes several seconds to run this simple script and it spits "recv: Resource temporarily unavailable" messages. #!/usr/sbin/setkey -f flush; spdflush; add A B ipcomp 44 -m tunnel -C deflate; add B A ipcomp 45 -m tunnel -C deflate; spdadd A B any -P in ipsec ipcomp/tunnel/192.168.1.2-192.168.1.3/use; spdadd B A any -P out ipsec ipcomp/tunnel/192.168.1.3-192.168.1.2/use; -------------------- Obviously applications want the events even when the table is empty. So we cannot make this behavioral change. Signed-off-by: David S. Miller --- net/key/af_key.c | 4 ++-- net/xfrm/xfrm_policy.c | 13 +++---------- net/xfrm/xfrm_state.c | 8 ++------ net/xfrm/xfrm_user.c | 4 ++-- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 8b8e26a9e401..79d2c0f3c334 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1751,7 +1751,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); if (err) - return 0; + return err; c.data.proto = proto; c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; @@ -2713,7 +2713,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); if (err) - return 0; + return err; c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index cfceb6616ec1..2c5d93181f13 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -771,8 +771,7 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) { - int dir, err = 0, cnt = 0; - struct xfrm_policy *dp; + int dir, err = 0; write_lock_bh(&xfrm_policy_lock); @@ -790,10 +789,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; - dp = __xfrm_policy_unlink(pol, dir); + __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); - if (dp) - cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, audit_info->sessionid, @@ -812,10 +809,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) bydst) { if (pol->type != type) continue; - dp = __xfrm_policy_unlink(pol, dir); + __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); - if (dp) - cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, @@ -829,8 +824,6 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) } } - if (!cnt) - err = -ESRCH; atomic_inc(&flow_cache_genid); out: write_unlock_bh(&xfrm_policy_lock); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 9fa3322b2a7d..c9d6a5f1348d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -603,14 +603,13 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) { - int i, err = 0, cnt = 0; + int i, err = 0; spin_lock_bh(&xfrm_state_lock); err = xfrm_state_flush_secctx_check(net, proto, audit_info); if (err) goto out; - err = -ESRCH; for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; @@ -627,16 +626,13 @@ restart: audit_info->sessionid, audit_info->secid); xfrm_state_put(x); - if (!err) - cnt++; spin_lock_bh(&xfrm_state_lock); goto restart; } } } - if (cnt) - err = 0; + err = 0; out: spin_unlock_bh(&xfrm_state_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b0fb7d3bc15e..943c8712bd97 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1525,7 +1525,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_state_flush(net, p->proto, &audit_info); if (err) - return 0; + return err; c.data.proto = p->proto; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; @@ -1677,7 +1677,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_policy_flush(net, type, &audit_info); if (err) - return 0; + return err; c.data.type = type; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- cgit v1.2.3 From 25cca5352712561fba97bd37c495593d641c1d39 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Thu, 11 Feb 2010 10:26:38 +0000 Subject: ipg: Remove device claimed by dl2k from pci id table This patch removes D-Link DGE-550T PCI ID (1186:4000) from the ipg driver. The ipg driver is for IP2000-based cards and the DGE-550T is a DL2000-based card. The driver loads and works for a few moments, but once a real workload is applied it stops operating. The ipg driver claimed this ID since it was introduced in 2.6.24 and it's forced many users to blacklist it. The correct driver for this hardware is the dl2k driver, which has been claiming this PCI ID since the 2.4 days. Signed-off-by: Jeff Mahoney Signed-off-by: David S. Miller --- drivers/net/ipg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index dbdebd5efe86..3ca49e348c9d 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -88,7 +88,6 @@ static const char *ipg_brand_name[] = { "Sundance Technology ST2021 based NIC", "Tamarack Microelectronics TC9020/9021 based NIC", "Tamarack Microelectronics TC9020/9021 based NIC", - "D-Link NIC", "D-Link NIC IP1000A" }; @@ -97,8 +96,7 @@ static DEFINE_PCI_DEVICE_TABLE(ipg_pci_tbl) = { { PCI_VDEVICE(SUNDANCE, 0x2021), 1 }, { PCI_VDEVICE(SUNDANCE, 0x1021), 2 }, { PCI_VDEVICE(DLINK, 0x9021), 3 }, - { PCI_VDEVICE(DLINK, 0x4000), 4 }, - { PCI_VDEVICE(DLINK, 0x4020), 5 }, + { PCI_VDEVICE(DLINK, 0x4020), 4 }, { 0, } }; -- cgit v1.2.3 From b6ca430599ea37843632b0eaa231dea5414dec25 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Thu, 11 Feb 2010 05:39:55 +0000 Subject: via-velocity: Enable scatter/gather IO by default Reduces CPU utilization significantly with sendfile for example. Signed-off-by: Simon Kagstrom Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index cd4e866321f8..4e47f2683b83 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2825,7 +2825,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | - NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM; + NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG; ret = register_netdev(dev); if (ret < 0) -- cgit v1.2.3 From d4c41139df6e74c6fff0cbac43e51cab782133be Mon Sep 17 00:00:00 2001 From: Kristoffer Glembo Date: Mon, 15 Feb 2010 03:33:44 +0000 Subject: net: Add Aeroflex Gaisler 10/100/1G Ethernet MAC driver Adds device driver for Aeroflex Gaisler 10/100 and 10/100/1G Ethernet MAC IP cores. Signed-off-by: Kristoffer Glembo Signed-off-by: David S. Miller --- MAINTAINERS | 6 + drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/greth.c | 1645 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/greth.h | 143 +++++ 5 files changed, 1803 insertions(+) create mode 100644 drivers/net/greth.c create mode 100644 drivers/net/greth.h diff --git a/MAINTAINERS b/MAINTAINERS index 64a237bb01ab..32f6915ae0eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2373,6 +2373,12 @@ F: Documentation/isdn/README.gigaset F: drivers/isdn/gigaset/ F: include/linux/gigaset_dev.h +GRETH 10/100/1G Ethernet MAC device driver +M: Kristoffer Glembo +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/greth* + HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER M: Frank Seidel L: lm-sensors@lm-sensors.org diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 069057796bd7..17ff15f6099a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -995,6 +995,14 @@ config ETHOC help Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC. +config GRETH + tristate "Aeroflex Gaisler GRETH Ethernet MAC support" + depends on OF + select PHYLIB + select CRC32 + help + Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC. + config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 622cfd450d48..478886234c28 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -250,6 +250,7 @@ pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o obj-$(CONFIG_MLX4_CORE) += mlx4/ obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_ETHOC) += ethoc.o +obj-$(CONFIG_GRETH) += greth.o obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o diff --git a/drivers/net/greth.c b/drivers/net/greth.c new file mode 100644 index 000000000000..457da1c2383c --- /dev/null +++ b/drivers/net/greth.c @@ -0,0 +1,1645 @@ +/* + * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC. + * + * 2005-2009 (c) Aeroflex Gaisler AB + * + * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs + * available in the GRLIB VHDL IP core library. + * + * Full documentation of both cores can be found here: + * http://www.gaisler.com/products/grlib/grip.pdf + * + * The Gigabit version supports scatter/gather DMA, any alignment of + * buffers and checksum offloading. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Contributors: Kristoffer Glembo + * Daniel Hellstrom + * Marko Isomaki + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SPARC +#include +#endif + +#include "greth.h" + +#define GRETH_DEF_MSG_ENABLE \ + (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR) + +static int greth_debug = -1; /* -1 == use GRETH_DEF_MSG_ENABLE as value */ +module_param(greth_debug, int, 0); +MODULE_PARM_DESC(greth_debug, "GRETH bitmapped debugging message enable value"); + +/* Accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */ +static int macaddr[6]; +module_param_array(macaddr, int, NULL, 0); +MODULE_PARM_DESC(macaddr, "GRETH Ethernet MAC address"); + +static int greth_edcl = 1; +module_param(greth_edcl, int, 0); +MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used."); + +static int greth_open(struct net_device *dev); +static int greth_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev); +static int greth_rx(struct net_device *dev, int limit); +static int greth_rx_gbit(struct net_device *dev, int limit); +static void greth_clean_tx(struct net_device *dev); +static void greth_clean_tx_gbit(struct net_device *dev); +static irqreturn_t greth_interrupt(int irq, void *dev_id); +static int greth_close(struct net_device *dev); +static int greth_set_mac_add(struct net_device *dev, void *p); +static void greth_set_multicast_list(struct net_device *dev); + +#define GRETH_REGLOAD(a) (be32_to_cpu(__raw_readl(&(a)))) +#define GRETH_REGSAVE(a, v) (__raw_writel(cpu_to_be32(v), &(a))) +#define GRETH_REGORIN(a, v) (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) | (v)))) +#define GRETH_REGANDIN(a, v) (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) & (v)))) + +#define NEXT_TX(N) (((N) + 1) & GRETH_TXBD_NUM_MASK) +#define SKIP_TX(N, C) (((N) + C) & GRETH_TXBD_NUM_MASK) +#define NEXT_RX(N) (((N) + 1) & GRETH_RXBD_NUM_MASK) + +static void greth_print_rx_packet(void *addr, int len) +{ + print_hex_dump(KERN_DEBUG, "RX: ", DUMP_PREFIX_OFFSET, 16, 1, + addr, len, true); +} + +static void greth_print_tx_packet(struct sk_buff *skb) +{ + int i; + int length; + + if (skb_shinfo(skb)->nr_frags == 0) + length = skb->len; + else + length = skb_headlen(skb); + + print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, length, true); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + + print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1, + phys_to_virt(page_to_phys(skb_shinfo(skb)->frags[i].page)) + + skb_shinfo(skb)->frags[i].page_offset, + length, true); + } +} + +static inline void greth_enable_tx(struct greth_private *greth) +{ + wmb(); + GRETH_REGORIN(greth->regs->control, GRETH_TXEN); +} + +static inline void greth_disable_tx(struct greth_private *greth) +{ + GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN); +} + +static inline void greth_enable_rx(struct greth_private *greth) +{ + wmb(); + GRETH_REGORIN(greth->regs->control, GRETH_RXEN); +} + +static inline void greth_disable_rx(struct greth_private *greth) +{ + GRETH_REGANDIN(greth->regs->control, ~GRETH_RXEN); +} + +static inline void greth_enable_irqs(struct greth_private *greth) +{ + GRETH_REGORIN(greth->regs->control, GRETH_RXI | GRETH_TXI); +} + +static inline void greth_disable_irqs(struct greth_private *greth) +{ + GRETH_REGANDIN(greth->regs->control, ~(GRETH_RXI|GRETH_TXI)); +} + +static inline void greth_write_bd(u32 *bd, u32 val) +{ + __raw_writel(cpu_to_be32(val), bd); +} + +static inline u32 greth_read_bd(u32 *bd) +{ + return be32_to_cpu(__raw_readl(bd)); +} + +static void greth_clean_rings(struct greth_private *greth) +{ + int i; + struct greth_bd *rx_bdp = greth->rx_bd_base; + struct greth_bd *tx_bdp = greth->tx_bd_base; + + if (greth->gbit_mac) { + + /* Free and unmap RX buffers */ + for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) { + if (greth->rx_skbuff[i] != NULL) { + dev_kfree_skb(greth->rx_skbuff[i]); + dma_unmap_single(greth->dev, + greth_read_bd(&rx_bdp->addr), + MAX_FRAME_SIZE+NET_IP_ALIGN, + DMA_FROM_DEVICE); + } + } + + /* TX buffers */ + while (greth->tx_free < GRETH_TXBD_NUM) { + + struct sk_buff *skb = greth->tx_skbuff[greth->tx_last]; + int nr_frags = skb_shinfo(skb)->nr_frags; + tx_bdp = greth->tx_bd_base + greth->tx_last; + greth->tx_last = NEXT_TX(greth->tx_last); + + dma_unmap_single(greth->dev, + greth_read_bd(&tx_bdp->addr), + skb_headlen(skb), + DMA_TO_DEVICE); + + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + tx_bdp = greth->tx_bd_base + greth->tx_last; + + dma_unmap_page(greth->dev, + greth_read_bd(&tx_bdp->addr), + frag->size, + DMA_TO_DEVICE); + + greth->tx_last = NEXT_TX(greth->tx_last); + } + greth->tx_free += nr_frags+1; + dev_kfree_skb(skb); + } + + + } else { /* 10/100 Mbps MAC */ + + for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) { + kfree(greth->rx_bufs[i]); + dma_unmap_single(greth->dev, + greth_read_bd(&rx_bdp->addr), + MAX_FRAME_SIZE, + DMA_FROM_DEVICE); + } + for (i = 0; i < GRETH_TXBD_NUM; i++, tx_bdp++) { + kfree(greth->tx_bufs[i]); + dma_unmap_single(greth->dev, + greth_read_bd(&tx_bdp->addr), + MAX_FRAME_SIZE, + DMA_TO_DEVICE); + } + } +} + +static int greth_init_rings(struct greth_private *greth) +{ + struct sk_buff *skb; + struct greth_bd *rx_bd, *tx_bd; + u32 dma_addr; + int i; + + rx_bd = greth->rx_bd_base; + tx_bd = greth->tx_bd_base; + + /* Initialize descriptor rings and buffers */ + if (greth->gbit_mac) { + + for (i = 0; i < GRETH_RXBD_NUM; i++) { + skb = netdev_alloc_skb(greth->netdev, MAX_FRAME_SIZE+NET_IP_ALIGN); + if (skb == NULL) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Error allocating DMA ring.\n"); + goto cleanup; + } + skb_reserve(skb, NET_IP_ALIGN); + dma_addr = dma_map_single(greth->dev, + skb->data, + MAX_FRAME_SIZE+NET_IP_ALIGN, + DMA_FROM_DEVICE); + + if (dma_mapping_error(greth->dev, dma_addr)) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Could not create initial DMA mapping\n"); + goto cleanup; + } + greth->rx_skbuff[i] = skb; + greth_write_bd(&rx_bd[i].addr, dma_addr); + greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE); + } + + } else { + + /* 10/100 MAC uses a fixed set of buffers and copy to/from SKBs */ + for (i = 0; i < GRETH_RXBD_NUM; i++) { + + greth->rx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL); + + if (greth->rx_bufs[i] == NULL) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Error allocating DMA ring.\n"); + goto cleanup; + } + + dma_addr = dma_map_single(greth->dev, + greth->rx_bufs[i], + MAX_FRAME_SIZE, + DMA_FROM_DEVICE); + + if (dma_mapping_error(greth->dev, dma_addr)) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Could not create initial DMA mapping\n"); + goto cleanup; + } + greth_write_bd(&rx_bd[i].addr, dma_addr); + greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE); + } + for (i = 0; i < GRETH_TXBD_NUM; i++) { + + greth->tx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL); + + if (greth->tx_bufs[i] == NULL) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Error allocating DMA ring.\n"); + goto cleanup; + } + + dma_addr = dma_map_single(greth->dev, + greth->tx_bufs[i], + MAX_FRAME_SIZE, + DMA_TO_DEVICE); + + if (dma_mapping_error(greth->dev, dma_addr)) { + if (netif_msg_ifup(greth)) + dev_err(greth->dev, "Could not create initial DMA mapping\n"); + goto cleanup; + } + greth_write_bd(&tx_bd[i].addr, dma_addr); + greth_write_bd(&tx_bd[i].stat, 0); + } + } + greth_write_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat, + greth_read_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat) | GRETH_BD_WR); + + /* Initialize pointers. */ + greth->rx_cur = 0; + greth->tx_next = 0; + greth->tx_last = 0; + greth->tx_free = GRETH_TXBD_NUM; + + /* Initialize descriptor base address */ + GRETH_REGSAVE(greth->regs->tx_desc_p, greth->tx_bd_base_phys); + GRETH_REGSAVE(greth->regs->rx_desc_p, greth->rx_bd_base_phys); + + return 0; + +cleanup: + greth_clean_rings(greth); + return -ENOMEM; +} + +static int greth_open(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + int err; + + err = greth_init_rings(greth); + if (err) { + if (netif_msg_ifup(greth)) + dev_err(&dev->dev, "Could not allocate memory for DMA rings\n"); + return err; + } + + err = request_irq(greth->irq, greth_interrupt, 0, "eth", (void *) dev); + if (err) { + if (netif_msg_ifup(greth)) + dev_err(&dev->dev, "Could not allocate interrupt %d\n", dev->irq); + greth_clean_rings(greth); + return err; + } + + if (netif_msg_ifup(greth)) + dev_dbg(&dev->dev, " starting queue\n"); + netif_start_queue(dev); + + napi_enable(&greth->napi); + + greth_enable_irqs(greth); + greth_enable_tx(greth); + greth_enable_rx(greth); + return 0; + +} + +static int greth_close(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + + napi_disable(&greth->napi); + + greth_disable_tx(greth); + + netif_stop_queue(dev); + + free_irq(greth->irq, (void *) dev); + + greth_clean_rings(greth); + + return 0; +} + +static int greth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + struct greth_bd *bdp; + int err = NETDEV_TX_OK; + u32 status, dma_addr; + + bdp = greth->tx_bd_base + greth->tx_next; + + if (unlikely(greth->tx_free <= 0)) { + netif_stop_queue(dev); + return NETDEV_TX_BUSY; + } + + if (netif_msg_pktdata(greth)) + greth_print_tx_packet(skb); + + + if (unlikely(skb->len > MAX_FRAME_SIZE)) { + dev->stats.tx_errors++; + goto out; + } + + dma_addr = greth_read_bd(&bdp->addr); + + memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len); + + dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE); + + status = GRETH_BD_EN | (skb->len & GRETH_BD_LEN); + + /* Wrap around descriptor ring */ + if (greth->tx_next == GRETH_TXBD_NUM_MASK) { + status |= GRETH_BD_WR; + } + + greth->tx_next = NEXT_TX(greth->tx_next); + greth->tx_free--; + + /* No more descriptors */ + if (unlikely(greth->tx_free == 0)) { + + /* Free transmitted descriptors */ + greth_clean_tx(dev); + + /* If nothing was cleaned, stop queue & wait for irq */ + if (unlikely(greth->tx_free == 0)) { + status |= GRETH_BD_IE; + netif_stop_queue(dev); + } + } + + /* Write descriptor control word and enable transmission */ + greth_write_bd(&bdp->stat, status); + greth_enable_tx(greth); + +out: + dev_kfree_skb(skb); + return err; +} + + +static int greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + struct greth_bd *bdp; + u32 status = 0, dma_addr; + int curr_tx, nr_frags, i, err = NETDEV_TX_OK; + + nr_frags = skb_shinfo(skb)->nr_frags; + + if (greth->tx_free < nr_frags + 1) { + netif_stop_queue(dev); + err = NETDEV_TX_BUSY; + goto out; + } + + if (netif_msg_pktdata(greth)) + greth_print_tx_packet(skb); + + if (unlikely(skb->len > MAX_FRAME_SIZE)) { + dev->stats.tx_errors++; + goto out; + } + + /* Save skb pointer. */ + greth->tx_skbuff[greth->tx_next] = skb; + + /* Linear buf */ + if (nr_frags != 0) + status = GRETH_TXBD_MORE; + + status |= GRETH_TXBD_CSALL; + status |= skb_headlen(skb) & GRETH_BD_LEN; + if (greth->tx_next == GRETH_TXBD_NUM_MASK) + status |= GRETH_BD_WR; + + + bdp = greth->tx_bd_base + greth->tx_next; + greth_write_bd(&bdp->stat, status); + dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(greth->dev, dma_addr))) + goto map_error; + + greth_write_bd(&bdp->addr, dma_addr); + + curr_tx = NEXT_TX(greth->tx_next); + + /* Frags */ + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + greth->tx_skbuff[curr_tx] = NULL; + bdp = greth->tx_bd_base + curr_tx; + + status = GRETH_TXBD_CSALL; + status |= frag->size & GRETH_BD_LEN; + + /* Wrap around descriptor ring */ + if (curr_tx == GRETH_TXBD_NUM_MASK) + status |= GRETH_BD_WR; + + /* More fragments left */ + if (i < nr_frags - 1) + status |= GRETH_TXBD_MORE; + + /* ... last fragment, check if out of descriptors */ + else if (greth->tx_free - nr_frags - 1 < (MAX_SKB_FRAGS + 1)) { + + /* Enable interrupts and stop queue */ + status |= GRETH_BD_IE; + netif_stop_queue(dev); + } + + greth_write_bd(&bdp->stat, status); + + dma_addr = dma_map_page(greth->dev, + frag->page, + frag->page_offset, + frag->size, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(greth->dev, dma_addr))) + goto frag_map_error; + + greth_write_bd(&bdp->addr, dma_addr); + + curr_tx = NEXT_TX(curr_tx); + } + + wmb(); + + /* Enable the descriptors that we configured ... */ + for (i = 0; i < nr_frags + 1; i++) { + bdp = greth->tx_bd_base + greth->tx_next; + greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); + greth->tx_next = NEXT_TX(greth->tx_next); + greth->tx_free--; + } + + greth_enable_tx(greth); + + return NETDEV_TX_OK; + +frag_map_error: + /* Unmap SKB mappings that succeeded */ + for (i = 0; greth->tx_next + i != curr_tx; i++) { + bdp = greth->tx_bd_base + greth->tx_next + i; + dma_unmap_single(greth->dev, + greth_read_bd(&bdp->addr), + greth_read_bd(&bdp->stat) & GRETH_BD_LEN, + DMA_TO_DEVICE); + } +map_error: + if (net_ratelimit()) + dev_warn(greth->dev, "Could not create TX DMA mapping\n"); + dev_kfree_skb(skb); + return NETDEV_TX_OK; + +out: + return err; +} + + +static irqreturn_t greth_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct greth_private *greth; + u32 status; + irqreturn_t retval = IRQ_NONE; + + greth = netdev_priv(dev); + + spin_lock(&greth->devlock); + + /* Get the interrupt events that caused us to be here. */ + status = GRETH_REGLOAD(greth->regs->status); + + /* Handle rx and tx interrupts through poll */ + if (status & (GRETH_INT_RX | GRETH_INT_TX)) { + + /* Clear interrupt status */ + GRETH_REGORIN(greth->regs->status, + status & (GRETH_INT_RX | GRETH_INT_TX)); + + retval = IRQ_HANDLED; + + /* Disable interrupts and schedule poll() */ + greth_disable_irqs(greth); + napi_schedule(&greth->napi); + } + + mmiowb(); + spin_unlock(&greth->devlock); + + return retval; +} + +static void greth_clean_tx(struct net_device *dev) +{ + struct greth_private *greth; + struct greth_bd *bdp; + u32 stat; + + greth = netdev_priv(dev); + + while (1) { + bdp = greth->tx_bd_base + greth->tx_last; + stat = greth_read_bd(&bdp->stat); + + if (unlikely(stat & GRETH_BD_EN)) + break; + + if (greth->tx_free == GRETH_TXBD_NUM) + break; + + /* Check status for errors */ + if (unlikely(stat & GRETH_TXBD_STATUS)) { + dev->stats.tx_errors++; + if (stat & GRETH_TXBD_ERR_AL) + dev->stats.tx_aborted_errors++; + if (stat & GRETH_TXBD_ERR_UE) + dev->stats.tx_fifo_errors++; + } + dev->stats.tx_packets++; + greth->tx_last = NEXT_TX(greth->tx_last); + greth->tx_free++; + } + + if (greth->tx_free > 0) { + netif_wake_queue(dev); + } + +} + +static inline void greth_update_tx_stats(struct net_device *dev, u32 stat) +{ + /* Check status for errors */ + if (unlikely(stat & GRETH_TXBD_STATUS)) { + dev->stats.tx_errors++; + if (stat & GRETH_TXBD_ERR_AL) + dev->stats.tx_aborted_errors++; + if (stat & GRETH_TXBD_ERR_UE) + dev->stats.tx_fifo_errors++; + if (stat & GRETH_TXBD_ERR_LC) + dev->stats.tx_aborted_errors++; + } + dev->stats.tx_packets++; +} + +static void greth_clean_tx_gbit(struct net_device *dev) +{ + struct greth_private *greth; + struct greth_bd *bdp, *bdp_last_frag; + struct sk_buff *skb; + u32 stat; + int nr_frags, i; + + greth = netdev_priv(dev); + + while (greth->tx_free < GRETH_TXBD_NUM) { + + skb = greth->tx_skbuff[greth->tx_last]; + + nr_frags = skb_shinfo(skb)->nr_frags; + + /* We only clean fully completed SKBs */ + bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags); + stat = bdp_last_frag->stat; + + if (stat & GRETH_BD_EN) + break; + + greth->tx_skbuff[greth->tx_last] = NULL; + + greth_update_tx_stats(dev, stat); + + bdp = greth->tx_bd_base + greth->tx_last; + + greth->tx_last = NEXT_TX(greth->tx_last); + + dma_unmap_single(greth->dev, + greth_read_bd(&bdp->addr), + skb_headlen(skb), + DMA_TO_DEVICE); + + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + bdp = greth->tx_bd_base + greth->tx_last; + + dma_unmap_page(greth->dev, + greth_read_bd(&bdp->addr), + frag->size, + DMA_TO_DEVICE); + + greth->tx_last = NEXT_TX(greth->tx_last); + } + greth->tx_free += nr_frags+1; + dev_kfree_skb(skb); + } + if (greth->tx_free > (MAX_SKB_FRAGS + 1)) { + netif_wake_queue(dev); + } +} + +static int greth_pending_packets(struct greth_private *greth) +{ + struct greth_bd *bdp; + u32 status; + bdp = greth->rx_bd_base + greth->rx_cur; + status = greth_read_bd(&bdp->stat); + if (status & GRETH_BD_EN) + return 0; + else + return 1; +} + +static int greth_rx(struct net_device *dev, int limit) +{ + struct greth_private *greth; + struct greth_bd *bdp; + struct sk_buff *skb; + int pkt_len; + int bad, count; + u32 status, dma_addr; + + greth = netdev_priv(dev); + + for (count = 0; count < limit; ++count) { + + bdp = greth->rx_bd_base + greth->rx_cur; + status = greth_read_bd(&bdp->stat); + dma_addr = greth_read_bd(&bdp->addr); + bad = 0; + + if (unlikely(status & GRETH_BD_EN)) { + break; + } + + /* Check status for errors. */ + if (unlikely(status & GRETH_RXBD_STATUS)) { + if (status & GRETH_RXBD_ERR_FT) { + dev->stats.rx_length_errors++; + bad = 1; + } + if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) { + dev->stats.rx_frame_errors++; + bad = 1; + } + if (status & GRETH_RXBD_ERR_CRC) { + dev->stats.rx_crc_errors++; + bad = 1; + } + } + if (unlikely(bad)) { + dev->stats.rx_errors++; + + } else { + + pkt_len = status & GRETH_BD_LEN; + + skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN); + + if (unlikely(skb == NULL)) { + + if (net_ratelimit()) + dev_warn(&dev->dev, "low on memory - " "packet dropped\n"); + + dev->stats.rx_dropped++; + + } else { + skb_reserve(skb, NET_IP_ALIGN); + skb->dev = dev; + + dma_sync_single_for_cpu(greth->dev, + dma_addr, + pkt_len, + DMA_FROM_DEVICE); + + if (netif_msg_pktdata(greth)) + greth_print_rx_packet(phys_to_virt(dma_addr), pkt_len); + + memcpy(skb_put(skb, pkt_len), phys_to_virt(dma_addr), pkt_len); + + skb->protocol = eth_type_trans(skb, dev); + dev->stats.rx_packets++; + netif_receive_skb(skb); + } + } + + status = GRETH_BD_EN | GRETH_BD_IE; + if (greth->rx_cur == GRETH_RXBD_NUM_MASK) { + status |= GRETH_BD_WR; + } + + wmb(); + greth_write_bd(&bdp->stat, status); + + dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE); + + greth_enable_rx(greth); + + greth->rx_cur = NEXT_RX(greth->rx_cur); + } + + return count; +} + +static inline int hw_checksummed(u32 status) +{ + + if (status & GRETH_RXBD_IP_FRAG) + return 0; + + if (status & GRETH_RXBD_IP && status & GRETH_RXBD_IP_CSERR) + return 0; + + if (status & GRETH_RXBD_UDP && status & GRETH_RXBD_UDP_CSERR) + return 0; + + if (status & GRETH_RXBD_TCP && status & GRETH_RXBD_TCP_CSERR) + return 0; + + return 1; +} + +static int greth_rx_gbit(struct net_device *dev, int limit) +{ + struct greth_private *greth; + struct greth_bd *bdp; + struct sk_buff *skb, *newskb; + int pkt_len; + int bad, count = 0; + u32 status, dma_addr; + + greth = netdev_priv(dev); + + for (count = 0; count < limit; ++count) { + + bdp = greth->rx_bd_base + greth->rx_cur; + skb = greth->rx_skbuff[greth->rx_cur]; + status = greth_read_bd(&bdp->stat); + bad = 0; + + if (status & GRETH_BD_EN) + break; + + /* Check status for errors. */ + if (unlikely(status & GRETH_RXBD_STATUS)) { + + if (status & GRETH_RXBD_ERR_FT) { + dev->stats.rx_length_errors++; + bad = 1; + } else if (status & + (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE | GRETH_RXBD_ERR_LE)) { + dev->stats.rx_frame_errors++; + bad = 1; + } else if (status & GRETH_RXBD_ERR_CRC) { + dev->stats.rx_crc_errors++; + bad = 1; + } + } + + /* Allocate new skb to replace current */ + newskb = netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN); + + if (!bad && newskb) { + skb_reserve(newskb, NET_IP_ALIGN); + + dma_addr = dma_map_single(greth->dev, + newskb->data, + MAX_FRAME_SIZE + NET_IP_ALIGN, + DMA_FROM_DEVICE); + + if (!dma_mapping_error(greth->dev, dma_addr)) { + /* Process the incoming frame. */ + pkt_len = status & GRETH_BD_LEN; + + dma_unmap_single(greth->dev, + greth_read_bd(&bdp->addr), + MAX_FRAME_SIZE + NET_IP_ALIGN, + DMA_FROM_DEVICE); + + if (netif_msg_pktdata(greth)) + greth_print_rx_packet(phys_to_virt(greth_read_bd(&bdp->addr)), pkt_len); + + skb_put(skb, pkt_len); + + if (greth->flags & GRETH_FLAG_RX_CSUM && hw_checksummed(status)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + dev->stats.rx_packets++; + netif_receive_skb(skb); + + greth->rx_skbuff[greth->rx_cur] = newskb; + greth_write_bd(&bdp->addr, dma_addr); + } else { + if (net_ratelimit()) + dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n"); + dev_kfree_skb(newskb); + dev->stats.rx_dropped++; + } + } else { + if (net_ratelimit()) + dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n"); + dev->stats.rx_dropped++; + } + + status = GRETH_BD_EN | GRETH_BD_IE; + if (greth->rx_cur == GRETH_RXBD_NUM_MASK) { + status |= GRETH_BD_WR; + } + + wmb(); + greth_write_bd(&bdp->stat, status); + greth_enable_rx(greth); + greth->rx_cur = NEXT_RX(greth->rx_cur); + } + + return count; + +} + +static int greth_poll(struct napi_struct *napi, int budget) +{ + struct greth_private *greth; + int work_done = 0; + greth = container_of(napi, struct greth_private, napi); + + if (greth->gbit_mac) { + greth_clean_tx_gbit(greth->netdev); + } else { + greth_clean_tx(greth->netdev); + } + +restart_poll: + if (greth->gbit_mac) { + work_done += greth_rx_gbit(greth->netdev, budget - work_done); + } else { + work_done += greth_rx(greth->netdev, budget - work_done); + } + + if (work_done < budget) { + + napi_complete(napi); + + if (greth_pending_packets(greth)) { + napi_reschedule(napi); + goto restart_poll; + } + } + + greth_enable_irqs(greth); + return work_done; +} + +static int greth_set_mac_add(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct greth_private *greth; + struct greth_regs *regs; + + greth = (struct greth_private *) netdev_priv(dev); + regs = (struct greth_regs *) greth->regs; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + GRETH_REGSAVE(regs->esa_msb, addr->sa_data[0] << 8 | addr->sa_data[1]); + GRETH_REGSAVE(regs->esa_lsb, + addr->sa_data[2] << 24 | addr-> + sa_data[3] << 16 | addr->sa_data[4] << 8 | addr->sa_data[5]); + return 0; +} + +static u32 greth_hash_get_index(__u8 *addr) +{ + return (ether_crc(6, addr)) & 0x3F; +} + +static void greth_set_hash_filter(struct net_device *dev) +{ + struct dev_mc_list *curr; + struct greth_private *greth = (struct greth_private *) netdev_priv(dev); + struct greth_regs *regs = (struct greth_regs *) greth->regs; + u32 mc_filter[2]; + unsigned int i, bitnr; + + mc_filter[0] = mc_filter[1] = 0; + + curr = dev->mc_list; + + for (i = 0; i < dev->mc_count; i++, curr = curr->next) { + + if (!curr) + break; /* unexpected end of list */ + + bitnr = greth_hash_get_index(curr->dmi_addr); + mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); + } + + GRETH_REGSAVE(regs->hash_msb, mc_filter[1]); + GRETH_REGSAVE(regs->hash_lsb, mc_filter[0]); +} + +static void greth_set_multicast_list(struct net_device *dev) +{ + int cfg; + struct greth_private *greth = netdev_priv(dev); + struct greth_regs *regs = (struct greth_regs *) greth->regs; + + cfg = GRETH_REGLOAD(regs->control); + if (dev->flags & IFF_PROMISC) + cfg |= GRETH_CTRL_PR; + else + cfg &= ~GRETH_CTRL_PR; + + if (greth->multicast) { + if (dev->flags & IFF_ALLMULTI) { + GRETH_REGSAVE(regs->hash_msb, -1); + GRETH_REGSAVE(regs->hash_lsb, -1); + cfg |= GRETH_CTRL_MCEN; + GRETH_REGSAVE(regs->control, cfg); + return; + } + + if (dev->mc_count == 0) { + cfg &= ~GRETH_CTRL_MCEN; + GRETH_REGSAVE(regs->control, cfg); + return; + } + + /* Setup multicast filter */ + greth_set_hash_filter(dev); + cfg |= GRETH_CTRL_MCEN; + } + GRETH_REGSAVE(regs->control, cfg); +} + +static u32 greth_get_msglevel(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + return greth->msg_enable; +} + +static void greth_set_msglevel(struct net_device *dev, u32 value) +{ + struct greth_private *greth = netdev_priv(dev); + greth->msg_enable = value; +} +static int greth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct greth_private *greth = netdev_priv(dev); + struct phy_device *phy = greth->phy; + + if (!phy) + return -ENODEV; + + return phy_ethtool_gset(phy, cmd); +} + +static int greth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct greth_private *greth = netdev_priv(dev); + struct phy_device *phy = greth->phy; + + if (!phy) + return -ENODEV; + + return phy_ethtool_sset(phy, cmd); +} + +static int greth_get_regs_len(struct net_device *dev) +{ + return sizeof(struct greth_regs); +} + +static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct greth_private *greth = netdev_priv(dev); + + strncpy(info->driver, dev_driver_string(greth->dev), 32); + strncpy(info->version, "revision: 1.0", 32); + strncpy(info->bus_info, greth->dev->bus->name, 32); + strncpy(info->fw_version, "N/A", 32); + info->eedump_len = 0; + info->regdump_len = sizeof(struct greth_regs); +} + +static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) +{ + int i; + struct greth_private *greth = netdev_priv(dev); + u32 __iomem *greth_regs = (u32 __iomem *) greth->regs; + u32 *buff = p; + + for (i = 0; i < sizeof(struct greth_regs) / sizeof(u32); i++) + buff[i] = greth_read_bd(&greth_regs[i]); +} + +static u32 greth_get_rx_csum(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + return (greth->flags & GRETH_FLAG_RX_CSUM) != 0; +} + +static int greth_set_rx_csum(struct net_device *dev, u32 data) +{ + struct greth_private *greth = netdev_priv(dev); + + spin_lock_bh(&greth->devlock); + + if (data) + greth->flags |= GRETH_FLAG_RX_CSUM; + else + greth->flags &= ~GRETH_FLAG_RX_CSUM; + + spin_unlock_bh(&greth->devlock); + + return 0; +} + +static u32 greth_get_tx_csum(struct net_device *dev) +{ + return (dev->features & NETIF_F_IP_CSUM) != 0; +} + +static int greth_set_tx_csum(struct net_device *dev, u32 data) +{ + netif_tx_lock_bh(dev); + ethtool_op_set_tx_csum(dev, data); + netif_tx_unlock_bh(dev); + return 0; +} + +static const struct ethtool_ops greth_ethtool_ops = { + .get_msglevel = greth_get_msglevel, + .set_msglevel = greth_set_msglevel, + .get_settings = greth_get_settings, + .set_settings = greth_set_settings, + .get_drvinfo = greth_get_drvinfo, + .get_regs_len = greth_get_regs_len, + .get_regs = greth_get_regs, + .get_rx_csum = greth_get_rx_csum, + .set_rx_csum = greth_set_rx_csum, + .get_tx_csum = greth_get_tx_csum, + .set_tx_csum = greth_set_tx_csum, + .get_link = ethtool_op_get_link, +}; + +static struct net_device_ops greth_netdev_ops = { + .ndo_open = greth_open, + .ndo_stop = greth_close, + .ndo_start_xmit = greth_start_xmit, + .ndo_set_mac_address = greth_set_mac_add, +}; + +static inline int wait_for_mdio(struct greth_private *greth) +{ + unsigned long timeout = jiffies + 4*HZ/100; + while (GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_BUSY) { + if (time_after(jiffies, timeout)) + return 0; + } + return 1; +} + +static int greth_mdio_read(struct mii_bus *bus, int phy, int reg) +{ + struct greth_private *greth = bus->priv; + int data; + + if (!wait_for_mdio(greth)) + return -EBUSY; + + GRETH_REGSAVE(greth->regs->mdio, ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 2); + + if (!wait_for_mdio(greth)) + return -EBUSY; + + if (!(GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_NVALID)) { + data = (GRETH_REGLOAD(greth->regs->mdio) >> 16) & 0xFFFF; + return data; + + } else { + return -1; + } +} + +static int greth_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val) +{ + struct greth_private *greth = bus->priv; + + if (!wait_for_mdio(greth)) + return -EBUSY; + + GRETH_REGSAVE(greth->regs->mdio, + ((val & 0xFFFF) << 16) | ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 1); + + if (!wait_for_mdio(greth)) + return -EBUSY; + + return 0; +} + +static int greth_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static void greth_link_change(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + struct phy_device *phydev = greth->phy; + unsigned long flags; + + int status_change = 0; + + spin_lock_irqsave(&greth->devlock, flags); + + if (phydev->link) { + + if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) { + + GRETH_REGANDIN(greth->regs->control, + ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB)); + + if (phydev->duplex) + GRETH_REGORIN(greth->regs->control, GRETH_CTRL_FD); + + if (phydev->speed == SPEED_100) { + + GRETH_REGORIN(greth->regs->control, GRETH_CTRL_SP); + } + + else if (phydev->speed == SPEED_1000) + GRETH_REGORIN(greth->regs->control, GRETH_CTRL_GB); + + greth->speed = phydev->speed; + greth->duplex = phydev->duplex; + status_change = 1; + } + } + + if (phydev->link != greth->link) { + if (!phydev->link) { + greth->speed = 0; + greth->duplex = -1; + } + greth->link = phydev->link; + + status_change = 1; + } + + spin_unlock_irqrestore(&greth->devlock, flags); + + if (status_change) { + if (phydev->link) + pr_debug("%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + pr_debug("%s: link down\n", dev->name); + } +} + +static int greth_mdio_probe(struct net_device *dev) +{ + struct greth_private *greth = netdev_priv(dev); + struct phy_device *phy = NULL; + u32 interface; + int i; + + /* Find the first PHY */ + for (i = 0; i < PHY_MAX_ADDR; i++) { + if (greth->mdio->phy_map[i]) { + phy = greth->mdio->phy_map[i]; + break; + } + } + if (!phy) { + if (netif_msg_probe(greth)) + dev_err(&dev->dev, "no PHY found\n"); + return -ENXIO; + } + + if (greth->gbit_mac) + interface = PHY_INTERFACE_MODE_GMII; + else + interface = PHY_INTERFACE_MODE_MII; + + phy = phy_connect(dev, dev_name(&phy->dev), &greth_link_change, 0, interface); + + if (greth->gbit_mac) + phy->supported &= PHY_GBIT_FEATURES; + else + phy->supported &= PHY_BASIC_FEATURES; + + phy->advertising = phy->supported; + + if (IS_ERR(phy)) { + if (netif_msg_ifup(greth)) + dev_err(&dev->dev, "could not attach to PHY\n"); + return PTR_ERR(phy); + } + + greth->link = 0; + greth->speed = 0; + greth->duplex = -1; + greth->phy = phy; + + return 0; +} + +static inline int phy_aneg_done(struct phy_device *phydev) +{ + int retval; + + retval = phy_read(phydev, MII_BMSR); + + return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE); +} + +static int greth_mdio_init(struct greth_private *greth) +{ + int ret, phy; + unsigned long timeout; + + greth->mdio = mdiobus_alloc(); + if (!greth->mdio) { + return -ENOMEM; + } + + greth->mdio->name = "greth-mdio"; + snprintf(greth->mdio->id, MII_BUS_ID_SIZE, "%s-%d", greth->mdio->name, greth->irq); + greth->mdio->read = greth_mdio_read; + greth->mdio->write = greth_mdio_write; + greth->mdio->reset = greth_mdio_reset; + greth->mdio->priv = greth; + + greth->mdio->irq = greth->mdio_irqs; + + for (phy = 0; phy < PHY_MAX_ADDR; phy++) + greth->mdio->irq[phy] = PHY_POLL; + + ret = mdiobus_register(greth->mdio); + if (ret) { + goto error; + } + + ret = greth_mdio_probe(greth->netdev); + if (ret) { + if (netif_msg_probe(greth)) + dev_err(&greth->netdev->dev, "failed to probe MDIO bus\n"); + goto unreg_mdio; + } + + phy_start(greth->phy); + + /* If Ethernet debug link is used make autoneg happen right away */ + if (greth->edcl && greth_edcl == 1) { + phy_start_aneg(greth->phy); + timeout = jiffies + 6*HZ; + while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) { + } + genphy_read_status(greth->phy); + greth_link_change(greth->netdev); + } + + return 0; + +unreg_mdio: + mdiobus_unregister(greth->mdio); +error: + mdiobus_free(greth->mdio); + return ret; +} + +/* Initialize the GRETH MAC */ +static int __devinit greth_of_probe(struct of_device *ofdev, const struct of_device_id *match) +{ + struct net_device *dev; + struct greth_private *greth; + struct greth_regs *regs; + + int i; + int err; + int tmp; + unsigned long timeout; + + dev = alloc_etherdev(sizeof(struct greth_private)); + + if (dev == NULL) + return -ENOMEM; + + greth = netdev_priv(dev); + greth->netdev = dev; + greth->dev = &ofdev->dev; + + if (greth_debug > 0) + greth->msg_enable = greth_debug; + else + greth->msg_enable = GRETH_DEF_MSG_ENABLE; + + spin_lock_init(&greth->devlock); + + greth->regs = of_ioremap(&ofdev->resource[0], 0, + resource_size(&ofdev->resource[0]), + "grlib-greth regs"); + + if (greth->regs == NULL) { + if (netif_msg_probe(greth)) + dev_err(greth->dev, "ioremap failure.\n"); + err = -EIO; + goto error1; + } + + regs = (struct greth_regs *) greth->regs; + greth->irq = ofdev->irqs[0]; + + dev_set_drvdata(greth->dev, dev); + SET_NETDEV_DEV(dev, greth->dev); + + if (netif_msg_probe(greth)) + dev_dbg(greth->dev, "reseting controller.\n"); + + /* Reset the controller. */ + GRETH_REGSAVE(regs->control, GRETH_RESET); + + /* Wait for MAC to reset itself */ + timeout = jiffies + HZ/100; + while (GRETH_REGLOAD(regs->control) & GRETH_RESET) { + if (time_after(jiffies, timeout)) { + err = -EIO; + if (netif_msg_probe(greth)) + dev_err(greth->dev, "timeout when waiting for reset.\n"); + goto error2; + } + } + + /* Get default PHY address */ + greth->phyaddr = (GRETH_REGLOAD(regs->mdio) >> 11) & 0x1F; + + /* Check if we have GBIT capable MAC */ + tmp = GRETH_REGLOAD(regs->control); + greth->gbit_mac = (tmp >> 27) & 1; + + /* Check for multicast capability */ + greth->multicast = (tmp >> 25) & 1; + + greth->edcl = (tmp >> 31) & 1; + + /* If we have EDCL we disable the EDCL speed-duplex FSM so + * it doesn't interfere with the software */ + if (greth->edcl != 0) + GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX); + + /* Check if MAC can handle MDIO interrupts */ + greth->mdio_int_en = (tmp >> 26) & 1; + + err = greth_mdio_init(greth); + if (err) { + if (netif_msg_probe(greth)) + dev_err(greth->dev, "failed to register MDIO bus\n"); + goto error2; + } + + /* Allocate TX descriptor ring in coherent memory */ + greth->tx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev, + 1024, + &greth->tx_bd_base_phys, + GFP_KERNEL); + + if (!greth->tx_bd_base) { + if (netif_msg_probe(greth)) + dev_err(&dev->dev, "could not allocate descriptor memory.\n"); + err = -ENOMEM; + goto error3; + } + + memset(greth->tx_bd_base, 0, 1024); + + /* Allocate RX descriptor ring in coherent memory */ + greth->rx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev, + 1024, + &greth->rx_bd_base_phys, + GFP_KERNEL); + + if (!greth->rx_bd_base) { + if (netif_msg_probe(greth)) + dev_err(greth->dev, "could not allocate descriptor memory.\n"); + err = -ENOMEM; + goto error4; + } + + memset(greth->rx_bd_base, 0, 1024); + + /* Get MAC address from: module param, OF property or ID prom */ + for (i = 0; i < 6; i++) { + if (macaddr[i] != 0) + break; + } + if (i == 6) { + const unsigned char *addr; + int len; + addr = of_get_property(ofdev->node, "local-mac-address", &len); + if (addr != NULL && len == 6) { + for (i = 0; i < 6; i++) + macaddr[i] = (unsigned int) addr[i]; + } else { +#ifdef CONFIG_SPARC + for (i = 0; i < 6; i++) + macaddr[i] = (unsigned int) idprom->id_ethaddr[i]; +#endif + } + } + + for (i = 0; i < 6; i++) + dev->dev_addr[i] = macaddr[i]; + + macaddr[5]++; + + if (!is_valid_ether_addr(&dev->dev_addr[0])) { + if (netif_msg_probe(greth)) + dev_err(greth->dev, "no valid ethernet address, aborting.\n"); + err = -EINVAL; + goto error5; + } + + GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]); + GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 | + dev->dev_addr[4] << 8 | dev->dev_addr[5]); + + /* Clear all pending interrupts except PHY irq */ + GRETH_REGSAVE(regs->status, 0xFF); + + if (greth->gbit_mac) { + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HIGHDMA; + greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit; + greth->flags = GRETH_FLAG_RX_CSUM; + } + + if (greth->multicast) { + greth_netdev_ops.ndo_set_multicast_list = greth_set_multicast_list; + dev->flags |= IFF_MULTICAST; + } else { + dev->flags &= ~IFF_MULTICAST; + } + + dev->netdev_ops = &greth_netdev_ops; + dev->ethtool_ops = &greth_ethtool_ops; + + if (register_netdev(dev)) { + if (netif_msg_probe(greth)) + dev_err(greth->dev, "netdevice registration failed.\n"); + err = -ENOMEM; + goto error5; + } + + /* setup NAPI */ + memset(&greth->napi, 0, sizeof(greth->napi)); + netif_napi_add(dev, &greth->napi, greth_poll, 64); + + return 0; + +error5: + dma_free_coherent(greth->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys); +error4: + dma_free_coherent(greth->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys); +error3: + mdiobus_unregister(greth->mdio); +error2: + of_iounmap(&ofdev->resource[0], greth->regs, resource_size(&ofdev->resource[0])); +error1: + free_netdev(dev); + return err; +} + +static int __devexit greth_of_remove(struct of_device *of_dev) +{ + struct net_device *ndev = dev_get_drvdata(&of_dev->dev); + struct greth_private *greth = netdev_priv(ndev); + + /* Free descriptor areas */ + dma_free_coherent(&of_dev->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys); + + dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys); + + dev_set_drvdata(&of_dev->dev, NULL); + + if (greth->phy) + phy_stop(greth->phy); + mdiobus_unregister(greth->mdio); + + unregister_netdev(ndev); + free_netdev(ndev); + + of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0])); + + return 0; +} + +static struct of_device_id greth_of_match[] = { + { + .name = "GAISLER_ETHMAC", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, greth_of_match); + +static struct of_platform_driver greth_of_driver = { + .name = "grlib-greth", + .match_table = greth_of_match, + .probe = greth_of_probe, + .remove = __devexit_p(greth_of_remove), + .driver = { + .owner = THIS_MODULE, + .name = "grlib-greth", + }, +}; + +static int __init greth_init(void) +{ + return of_register_platform_driver(&greth_of_driver); +} + +static void __exit greth_cleanup(void) +{ + of_unregister_platform_driver(&greth_of_driver); +} + +module_init(greth_init); +module_exit(greth_cleanup); + +MODULE_AUTHOR("Aeroflex Gaisler AB."); +MODULE_DESCRIPTION("Aeroflex Gaisler Ethernet MAC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/greth.h b/drivers/net/greth.h new file mode 100644 index 000000000000..973388d6abca --- /dev/null +++ b/drivers/net/greth.h @@ -0,0 +1,143 @@ +#ifndef GRETH_H +#define GRETH_H + +#include + +/* Register bits and masks */ +#define GRETH_RESET 0x40 +#define GRETH_MII_BUSY 0x8 +#define GRETH_MII_NVALID 0x10 + +#define GRETH_CTRL_FD 0x10 +#define GRETH_CTRL_PR 0x20 +#define GRETH_CTRL_SP 0x80 +#define GRETH_CTRL_GB 0x100 +#define GRETH_CTRL_PSTATIEN 0x400 +#define GRETH_CTRL_MCEN 0x800 +#define GRETH_CTRL_DISDUPLEX 0x1000 +#define GRETH_STATUS_PHYSTAT 0x100 + +#define GRETH_BD_EN 0x800 +#define GRETH_BD_WR 0x1000 +#define GRETH_BD_IE 0x2000 +#define GRETH_BD_LEN 0x7FF + +#define GRETH_TXEN 0x1 +#define GRETH_INT_TX 0x8 +#define GRETH_TXI 0x4 +#define GRETH_TXBD_STATUS 0x0001C000 +#define GRETH_TXBD_MORE 0x20000 +#define GRETH_TXBD_IPCS 0x40000 +#define GRETH_TXBD_TCPCS 0x80000 +#define GRETH_TXBD_UDPCS 0x100000 +#define GRETH_TXBD_CSALL (GRETH_TXBD_IPCS | GRETH_TXBD_TCPCS | GRETH_TXBD_UDPCS) +#define GRETH_TXBD_ERR_LC 0x10000 +#define GRETH_TXBD_ERR_UE 0x4000 +#define GRETH_TXBD_ERR_AL 0x8000 + +#define GRETH_INT_RX 0x4 +#define GRETH_RXEN 0x2 +#define GRETH_RXI 0x8 +#define GRETH_RXBD_STATUS 0xFFFFC000 +#define GRETH_RXBD_ERR_AE 0x4000 +#define GRETH_RXBD_ERR_FT 0x8000 +#define GRETH_RXBD_ERR_CRC 0x10000 +#define GRETH_RXBD_ERR_OE 0x20000 +#define GRETH_RXBD_ERR_LE 0x40000 +#define GRETH_RXBD_IP 0x80000 +#define GRETH_RXBD_IP_CSERR 0x100000 +#define GRETH_RXBD_UDP 0x200000 +#define GRETH_RXBD_UDP_CSERR 0x400000 +#define GRETH_RXBD_TCP 0x800000 +#define GRETH_RXBD_TCP_CSERR 0x1000000 +#define GRETH_RXBD_IP_FRAG 0x2000000 +#define GRETH_RXBD_MCAST 0x4000000 + +/* Descriptor parameters */ +#define GRETH_TXBD_NUM 128 +#define GRETH_TXBD_NUM_MASK (GRETH_TXBD_NUM-1) +#define GRETH_TX_BUF_SIZE 2048 +#define GRETH_RXBD_NUM 128 +#define GRETH_RXBD_NUM_MASK (GRETH_RXBD_NUM-1) +#define GRETH_RX_BUF_SIZE 2048 + +/* Buffers per page */ +#define GRETH_RX_BUF_PPGAE (PAGE_SIZE/GRETH_RX_BUF_SIZE) +#define GRETH_TX_BUF_PPGAE (PAGE_SIZE/GRETH_TX_BUF_SIZE) + +/* How many pages are needed for buffers */ +#define GRETH_RX_BUF_PAGE_NUM (GRETH_RXBD_NUM/GRETH_RX_BUF_PPGAE) +#define GRETH_TX_BUF_PAGE_NUM (GRETH_TXBD_NUM/GRETH_TX_BUF_PPGAE) + +/* Buffer size. + * Gbit MAC uses tagged maximum frame size which is 1518 excluding CRC. + * Set to 1520 to make all buffers word aligned for non-gbit MAC. + */ +#define MAX_FRAME_SIZE 1520 + +/* Flags */ +#define GRETH_FLAG_RX_CSUM 0x1 + +/* GRETH APB registers */ +struct greth_regs { + u32 control; + u32 status; + u32 esa_msb; + u32 esa_lsb; + u32 mdio; + u32 tx_desc_p; + u32 rx_desc_p; + u32 edclip; + u32 hash_msb; + u32 hash_lsb; +}; + +/* GRETH buffer descriptor */ +struct greth_bd { + u32 stat; + u32 addr; +}; + +struct greth_private { + struct sk_buff *rx_skbuff[GRETH_RXBD_NUM]; + struct sk_buff *tx_skbuff[GRETH_TXBD_NUM]; + + unsigned char *tx_bufs[GRETH_TXBD_NUM]; + unsigned char *rx_bufs[GRETH_RXBD_NUM]; + + u16 tx_next; + u16 tx_last; + u16 tx_free; + u16 rx_cur; + + struct greth_regs *regs; /* Address of controller registers. */ + struct greth_bd *rx_bd_base; /* Address of Rx BDs. */ + struct greth_bd *tx_bd_base; /* Address of Tx BDs. */ + dma_addr_t rx_bd_base_phys; + dma_addr_t tx_bd_base_phys; + + int irq; + + struct device *dev; /* Pointer to of_device->dev */ + struct net_device *netdev; + struct napi_struct napi; + spinlock_t devlock; + + struct phy_device *phy; + struct mii_bus *mdio; + int mdio_irqs[PHY_MAX_ADDR]; + unsigned int link; + unsigned int speed; + unsigned int duplex; + + u32 msg_enable; + u32 flags; + + u8 phyaddr; + u8 multicast; + u8 gbit_mac; + u8 mdio_int_en; + u8 edcl; +}; + +#endif -- cgit v1.2.3 From 1d4bd947c501ea1da81300280fb6aeec2cca9335 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Tue, 16 Feb 2010 20:40:11 +0000 Subject: mv643xx_eth: fix missing validate_addr hook Fix missing validate_addr hook. Signed-off-by: Denis Kirjanov Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e24072a9a979..2733b0a3b703 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2846,6 +2846,7 @@ static const struct net_device_ops mv643xx_eth_netdev_ops = { .ndo_start_xmit = mv643xx_eth_xmit, .ndo_set_rx_mode = mv643xx_eth_set_rx_mode, .ndo_set_mac_address = mv643xx_eth_set_mac_address, + .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = mv643xx_eth_ioctl, .ndo_change_mtu = mv643xx_eth_change_mtu, .ndo_tx_timeout = mv643xx_eth_tx_timeout, -- cgit v1.2.3 From e76b69cc0133952c98aa1ad6330cacacd269fd64 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 16 Feb 2010 20:25:43 +0000 Subject: net: bug fix for vlan + gro issue Traffic (tcp) doesnot start on a vlan interface when gro is enabled. Even the tcp handshake was not taking place. This is because, the eth_type_trans call before the netif_receive_skb in napi_gro_finish() resets the skb->dev to napi->dev from the previously set vlan netdev interface. This causes the ip_route_input to drop the incoming packet considering it as a packet coming from a martian source. I could repro this on 2.6.32.7 (stable) and 2.6.33-rc7. With this fix, the traffic starts and the test runs fine on both vlan and non-vlan interfaces. CC: Herbert Xu CC: Patrick McHardy Signed-off-by: Ajit Khaparde Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index d1cf53d0d597..1968980f513a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2813,7 +2813,7 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, switch (ret) { case GRO_NORMAL: case GRO_HELD: - skb->protocol = eth_type_trans(skb, napi->dev); + skb->protocol = eth_type_trans(skb, skb->dev); if (ret == GRO_HELD) skb_gro_pull(skb, -ETH_HLEN); -- cgit v1.2.3 From e4a474f82ddaaef65433b0b4f5169f2f6cd8ddb0 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Tue, 16 Feb 2010 21:54:58 +0000 Subject: smsc911x: replace manual phy lookup. Use phy_find_first() function instead of manual lookup. Signed-off-by: Denis Kirjanov Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 3c1f9aa84cf5..13c0b76dec41 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -770,29 +770,25 @@ static int smsc911x_mii_probe(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); struct phy_device *phydev = NULL; - int phy_addr; + int ret; /* find the first phy */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (pdata->mii_bus->phy_map[phy_addr]) { - phydev = pdata->mii_bus->phy_map[phy_addr]; - SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X", - phy_addr, phydev->addr, phydev->phy_id); - break; - } - } - + phydev = phy_find_first(pdata->mii_bus); if (!phydev) { pr_err("%s: no PHY found\n", dev->name); return -ENODEV; } - phydev = phy_connect(dev, dev_name(&phydev->dev), - &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); + SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X", + phy_addr, phydev->addr, phydev->phy_id); + + ret = phy_connect_direct(dev, phydev, + &smsc911x_phy_adjust_link, 0, + pdata->config.phy_interface); - if (IS_ERR(phydev)) { + if (ret) { pr_err("%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); + return ret; } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", -- cgit v1.2.3 From 0988d26978561d568efed45cc5576d85ea7b609d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 12:27:14 +0000 Subject: cxgb3: convert to use netdev_for_each_addr Removed whole t3_rx_mode structure and appropriate helpers cause they are no longer needed. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/cxgb3/common.h | 28 +--------------------------- drivers/net/cxgb3/cxgb3_main.c | 8 ++------ drivers/net/cxgb3/xgmac.c | 15 ++++++++------- 3 files changed, 11 insertions(+), 40 deletions(-) diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 6ff356d4c7ab..fe08a004b0dd 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -67,32 +67,6 @@ /* Additional NETIF_MSG_* categories */ #define NETIF_MSG_MMIO 0x8000000 -struct t3_rx_mode { - struct net_device *dev; - struct dev_mc_list *mclist; - unsigned int idx; -}; - -static inline void init_rx_mode(struct t3_rx_mode *p, struct net_device *dev, - struct dev_mc_list *mclist) -{ - p->dev = dev; - p->mclist = mclist; - p->idx = 0; -} - -static inline u8 *t3_get_next_mcaddr(struct t3_rx_mode *rm) -{ - u8 *addr = NULL; - - if (rm->mclist && rm->idx < rm->dev->mc_count) { - addr = rm->mclist->dmi_addr; - rm->mclist = rm->mclist->next; - rm->idx++; - } - return addr; -} - enum { MAX_NPORTS = 2, /* max # of ports */ MAX_FRAME_SIZE = 10240, /* max MAC frame size, including header + FCS */ @@ -746,7 +720,7 @@ void t3_mac_enable_exact_filters(struct cmac *mac); int t3_mac_enable(struct cmac *mac, int which); int t3_mac_disable(struct cmac *mac, int which); int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu); -int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm); +int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev); int t3_mac_set_address(struct cmac *mac, unsigned int idx, u8 addr[6]); int t3_mac_set_num_ucast(struct cmac *mac, int n); const struct mac_stats *t3_mac_update_stats(struct cmac *mac); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 73622f5312cb..6fd968abb073 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -324,11 +324,9 @@ void t3_os_phymod_changed(struct adapter *adap, int port_id) static void cxgb_set_rxmode(struct net_device *dev) { - struct t3_rx_mode rm; struct port_info *pi = netdev_priv(dev); - init_rx_mode(&rm, dev, dev->mc_list); - t3_mac_set_rx_mode(&pi->mac, &rm); + t3_mac_set_rx_mode(&pi->mac, dev); } /** @@ -339,17 +337,15 @@ static void cxgb_set_rxmode(struct net_device *dev) */ static void link_start(struct net_device *dev) { - struct t3_rx_mode rm; struct port_info *pi = netdev_priv(dev); struct cmac *mac = &pi->mac; - init_rx_mode(&rm, dev, dev->mc_list); t3_mac_reset(mac); t3_mac_set_num_ucast(mac, MAX_MAC_IDX); t3_mac_set_mtu(mac, dev->mtu); t3_mac_set_address(mac, LAN_MAC_IDX, dev->dev_addr); t3_mac_set_address(mac, SAN_MAC_IDX, pi->iscsic.mac_addr); - t3_mac_set_rx_mode(mac, &rm); + t3_mac_set_rx_mode(mac, dev); t3_link_start(&pi->phy, mac, &pi->link_config); t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); } diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c index 0c08de5d09fd..c142a2132e9f 100644 --- a/drivers/net/cxgb3/xgmac.c +++ b/drivers/net/cxgb3/xgmac.c @@ -297,29 +297,30 @@ static int hash_hw_addr(const u8 * addr) return hash; } -int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm) +int t3_mac_set_rx_mode(struct cmac *mac, struct net_device *dev) { u32 val, hash_lo, hash_hi; struct adapter *adap = mac->adapter; unsigned int oft = mac->offset; val = t3_read_reg(adap, A_XGM_RX_CFG + oft) & ~F_COPYALLFRAMES; - if (rm->dev->flags & IFF_PROMISC) + if (dev->flags & IFF_PROMISC) val |= F_COPYALLFRAMES; t3_write_reg(adap, A_XGM_RX_CFG + oft, val); - if (rm->dev->flags & IFF_ALLMULTI) + if (dev->flags & IFF_ALLMULTI) hash_lo = hash_hi = 0xffffffff; else { - u8 *addr; + struct dev_mc_list *dmi; int exact_addr_idx = mac->nucast; hash_lo = hash_hi = 0; - while ((addr = t3_get_next_mcaddr(rm))) + netdev_for_each_mc_addr(dmi, dev) if (exact_addr_idx < EXACT_ADDR_FILTERS) - set_addr_filter(mac, exact_addr_idx++, addr); + set_addr_filter(mac, exact_addr_idx++, + dmi->dmi_addr); else { - int hash = hash_hw_addr(addr); + int hash = hash_hw_addr(dmi->dmi_addr); if (hash < 32) hash_lo |= (1 << hash); -- cgit v1.2.3 From 305b0160932af0ed67259b4b13c471aed2a86588 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 11:56:45 +0000 Subject: chelsio: convert to use netdev_for_each_mc_addr Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/chelsio/common.h | 16 ++-------------- drivers/net/chelsio/cxgb2.c | 2 -- drivers/net/chelsio/pm3393.c | 6 +++--- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index bb159d9603bf..9f89fd600643 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -90,25 +90,13 @@ typedef struct adapter adapter_t; struct t1_rx_mode { - struct net_device *dev; - u32 idx; - struct dev_mc_list *list; + struct net_device *dev; }; #define t1_rx_mode_promisc(rm) (rm->dev->flags & IFF_PROMISC) #define t1_rx_mode_allmulti(rm) (rm->dev->flags & IFF_ALLMULTI) #define t1_rx_mode_mc_cnt(rm) (netdev_mc_count(rm->dev)) - -static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm) -{ - u8 *addr = NULL; - - if (rm->idx++ < t1_rx_mode_mc_cnt(rm)) { - addr = rm->list->dmi_addr; - rm->list = rm->list->next; - } - return addr; -} +#define t1_get_netdev(rm) (rm->dev) #define MAX_NPORTS 4 #define PORT_MASK ((1 << MAX_NPORTS) - 1) diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 082cdb28b510..a54a32b16498 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -125,8 +125,6 @@ static void t1_set_rxmode(struct net_device *dev) struct t1_rx_mode rm; rm.dev = dev; - rm.idx = 0; - rm.list = dev->mc_list; mac->ops->set_rx_mode(mac, &rm); } diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 2117c4fbb107..33d674f36722 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -375,12 +375,12 @@ static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN; } else if (t1_rx_mode_mc_cnt(rm)) { /* Accept one or more multicast(s). */ - u8 *addr; + struct dev_mc_list *dmi; int bit; u16 mc_filter[4] = { 0, }; - while ((addr = t1_get_next_mcaddr(rm))) { - bit = (ether_crc(ETH_ALEN, addr) >> 23) & 0x3f; /* bit[23:28] */ + netdev_for_each_mc_addr(dmi, t1_get_netdev(rm)) { + bit = (ether_crc(ETH_ALEN, dmi->dmi_addr) >> 23) & 0x3f; /* bit[23:28] */ mc_filter[bit >> 4] |= 1 << (bit & 0xf); } pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]); -- cgit v1.2.3 From 5ff3f073670b544a9c0547cc6fef1f7eed5762ed Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 14 Feb 2010 01:01:00 +0000 Subject: net: export attach/detach filter routines Export sk_attach_filter/sk_detach_filter routines, so that tun module can use them. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- net/core/filter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index 08db7b9143a3..7517110ff4ae 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -529,6 +529,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) sk_filter_delayed_uncharge(sk, old_fp); return 0; } +EXPORT_SYMBOL_GPL(sk_attach_filter); int sk_detach_filter(struct sock *sk) { @@ -545,3 +546,4 @@ int sk_detach_filter(struct sock *sk) rcu_read_unlock_bh(); return ret; } +EXPORT_SYMBOL_GPL(sk_detach_filter); -- cgit v1.2.3 From 99405162598176e830d17ae6d4f3d9e070ad900c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 14 Feb 2010 01:01:10 +0000 Subject: tun: socket filter support This patch adds Linux Socket Filter support to tun driver. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 26 ++++++++++++++++++++++++++ include/linux/if_tun.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5adb3d150552..ce1efa4c0b0d 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -366,6 +367,10 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) if (!check_filter(&tun->txflt, skb)) goto drop; + if (tun->socket.sk->sk_filter && + sk_filter(tun->socket.sk, skb)) + goto drop; + if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) { if (!(tun->flags & TUN_ONE_QUEUE)) { /* Normal queueing mode. */ @@ -1162,6 +1167,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, struct tun_file *tfile = file->private_data; struct tun_struct *tun; void __user* argp = (void __user*)arg; + struct sock_fprog fprog; struct ifreq ifr; int sndbuf; int ret; @@ -1309,6 +1315,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, tun->socket.sk->sk_sndbuf = sndbuf; break; + case TUNATTACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = -EFAULT; + if (copy_from_user(&fprog, argp, sizeof(fprog))) + break; + + ret = sk_attach_filter(&fprog, tun->socket.sk); + break; + + case TUNDETACHFILTER: + /* Can be set only for TAPs */ + ret = -EINVAL; + if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV) + break; + ret = sk_detach_filter(tun->socket.sk); + break; + default: ret = -EINVAL; break; diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 404abe00162c..1350a246893a 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -18,6 +18,7 @@ #include #include +#include /* Read queue size */ #define TUN_READQ_SIZE 500 @@ -48,6 +49,8 @@ #define TUNGETIFF _IOR('T', 210, unsigned int) #define TUNGETSNDBUF _IOR('T', 211, int) #define TUNSETSNDBUF _IOW('T', 212, int) +#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) +#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 -- cgit v1.2.3 From 61e800cf949926b3d463ca3cf3025d964872774b Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:54 +0000 Subject: tg3: Enforce DMA mapping / skb assignment ordering Michael Chan noted that there is nothing in the code that would prevent the compiler from delaying the access of the "mapping" member of the newly arrived packet until much later. If this happened after the skb = NULL assignment, it is possible for the driver to pass a bad dma_addr value to pci_unmap_single(). To enforce this ordering, we need a write memory barrier. The pairing read memory barrier already exists in tg3_rx_prodring_xfer() under the comments starting with "Ensure that updates to the...". Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 385434ff3960..344490e872b4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4659,11 +4659,16 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) if (skb_size < 0) goto drop_it; - ri->skb = NULL; - pci_unmap_single(tp->pdev, dma_addr, skb_size, PCI_DMA_FROMDEVICE); + /* Ensure that the update to the skb happens + * after the usage of the old DMA mapping. + */ + smp_wmb(); + + ri->skb = NULL; + skb_put(skb, len); } else { struct sk_buff *copy_skb; -- cgit v1.2.3 From d110114281fad580dd9ce629507d17b123169cff Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:55 +0000 Subject: tg3: Make 57791 and 57795 10/100 only This patch adds the 57791 and 57795 to the list of devices that only support 10 and 100 Mbps speeds. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 344490e872b4..051b18ad3f0c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13588,6 +13588,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F || tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || (tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET)) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; -- cgit v1.2.3 From a4153d401ac440c73e0721db0b6b031e8e6f77d1 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:56 +0000 Subject: tg3: Add support for 2 new selfboot formats This patch adds new offsets to the bootcode version extraction code to support NVRAM format versions 4 and 5. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++++ drivers/net/tg3.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 051b18ad3f0c..f08e4b846458 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12753,6 +12753,12 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val) case TG3_EEPROM_SB_REVISION_3: offset = TG3_EEPROM_SB_F1R3_EDH_OFF; break; + case TG3_EEPROM_SB_REVISION_4: + offset = TG3_EEPROM_SB_F1R4_EDH_OFF; + break; + case TG3_EEPROM_SB_REVISION_5: + offset = TG3_EEPROM_SB_F1R5_EDH_OFF; + break; default: return; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index b4fd59623cfb..ffc12b1cb388 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1864,6 +1864,8 @@ #define TG3_EEPROM_SB_REVISION_0 0x00000000 #define TG3_EEPROM_SB_REVISION_2 0x00020000 #define TG3_EEPROM_SB_REVISION_3 0x00030000 +#define TG3_EEPROM_SB_REVISION_4 0x00040000 +#define TG3_EEPROM_SB_REVISION_5 0x00050000 #define TG3_EEPROM_MAGIC_HW 0xabcd #define TG3_EEPROM_MAGIC_HW_MSK 0xffff @@ -1881,6 +1883,8 @@ #define TG3_EEPROM_SB_F1R2_EDH_OFF 0x14 #define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 #define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18 +#define TG3_EEPROM_SB_F1R4_EDH_OFF 0x1c +#define TG3_EEPROM_SB_F1R5_EDH_OFF 0x20 #define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700 #define TG3_EEPROM_SB_EDH_MAJ_SHFT 8 #define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff -- cgit v1.2.3 From 2712168f856e8cd42265e7ef855d64702da20089 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:57 +0000 Subject: tg3: Allow phylib flowctrl changes anytime This patch loosens the restriction that the phylib interface must be up and running to change the flow control parameters. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 94 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f08e4b846458..11ee44bfa2f3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10093,56 +10093,66 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam int err = 0; if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { - if (!(tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)) - return -EAGAIN; + u32 newadv; + struct phy_device *phydev; - if (epause->autoneg) { - u32 newadv; - struct phy_device *phydev; + phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; - phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; + if (!(phydev->supported & SUPPORTED_Pause) || + (!(phydev->supported & SUPPORTED_Asym_Pause) && + ((epause->rx_pause && !epause->tx_pause) || + (!epause->rx_pause && epause->tx_pause)))) + return -EINVAL; - if (epause->rx_pause) { - if (epause->tx_pause) - newadv = ADVERTISED_Pause; - else - newadv = ADVERTISED_Pause | - ADVERTISED_Asym_Pause; - } else if (epause->tx_pause) { - newadv = ADVERTISED_Asym_Pause; + tp->link_config.flowctrl = 0; + if (epause->rx_pause) { + tp->link_config.flowctrl |= FLOW_CTRL_RX; + + if (epause->tx_pause) { + tp->link_config.flowctrl |= FLOW_CTRL_TX; + newadv = ADVERTISED_Pause; } else - newadv = 0; - - if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { - u32 oldadv = phydev->advertising & - (ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - if (oldadv != newadv) { - phydev->advertising &= - ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - phydev->advertising |= newadv; - err = phy_start_aneg(phydev); + newadv = ADVERTISED_Pause | + ADVERTISED_Asym_Pause; + } else if (epause->tx_pause) { + tp->link_config.flowctrl |= FLOW_CTRL_TX; + newadv = ADVERTISED_Asym_Pause; + } else + newadv = 0; + + if (epause->autoneg) + tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; + else + tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG; + + if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { + u32 oldadv = phydev->advertising & + (ADVERTISED_Pause | ADVERTISED_Asym_Pause); + if (oldadv != newadv) { + phydev->advertising &= + ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + phydev->advertising |= newadv; + if (phydev->autoneg) { + /* + * Always renegotiate the link to + * inform our link partner of our + * flow control settings, even if the + * flow control is forced. Let + * tg3_adjust_link() do the final + * flow control setup. + */ + return phy_start_aneg(phydev); } - } else { - tp->link_config.advertising &= - ~(ADVERTISED_Pause | - ADVERTISED_Asym_Pause); - tp->link_config.advertising |= newadv; } - } else { - if (epause->rx_pause) - tp->link_config.flowctrl |= FLOW_CTRL_RX; - else - tp->link_config.flowctrl &= ~FLOW_CTRL_RX; - - if (epause->tx_pause) - tp->link_config.flowctrl |= FLOW_CTRL_TX; - else - tp->link_config.flowctrl &= ~FLOW_CTRL_TX; - if (netif_running(dev)) + if (!epause->autoneg) tg3_setup_flow_control(tp, 0, 0); + } else { + tp->link_config.orig_advertising &= + ~(ADVERTISED_Pause | + ADVERTISED_Asym_Pause); + tp->link_config.orig_advertising |= newadv; } } else { int irq_sync = 0; -- cgit v1.2.3 From b474eca74cf647df0a7fd56bc975ee4a812741b7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:58 +0000 Subject: tg3: Add more partno entries for fallback path This patch adds 57765 asic partno entries for the path executed if VPD is not present in NVRAM. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 11ee44bfa2f3..c9974a7697c9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12659,8 +12659,24 @@ out_not_found: else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 && tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788) strcpy(tp->board_part_number, "BCM57788"); - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761) + strcpy(tp->board_part_number, "BCM57761"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765) strcpy(tp->board_part_number, "BCM57765"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781) + strcpy(tp->board_part_number, "BCM57781"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785) + strcpy(tp->board_part_number, "BCM57785"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791) + strcpy(tp->board_part_number, "BCM57791"); + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 && + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795) + strcpy(tp->board_part_number, "BCM57795"); else strcpy(tp->board_part_number, "none"); } -- cgit v1.2.3 From 144170635b543ceadfe6ba907ac496b40795764e Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:16:59 +0000 Subject: tg3: Rename TG3_FLG3_RGMII_STD_IBND_DISABLE The STD part of this preprocessor definition is a bit of a misnomer. This flag is a coarse control of the RGMII inband status facilities. This patch renames the definition to be more accurate. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 12 ++++++------ drivers/net/tg3.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c9974a7697c9..09e3af0d1743 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -984,7 +984,7 @@ static void tg3_mdio_config_5785(struct tg3 *tp) return; } - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) + if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) val |= MAC_PHYCFG2_EMODE_MASK_MASK | MAC_PHYCFG2_FMODE_MASK_MASK | MAC_PHYCFG2_GMODE_MASK_MASK | @@ -997,7 +997,7 @@ static void tg3_mdio_config_5785(struct tg3 *tp) val = tr32(MAC_PHYCFG1); val &= ~(MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK | MAC_PHYCFG1_RGMII_EXT_RX_DEC | MAC_PHYCFG1_RGMII_SND_STAT_EN); - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) { + if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) { if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) @@ -1015,7 +1015,7 @@ static void tg3_mdio_config_5785(struct tg3 *tp) MAC_RGMII_MODE_TX_ENABLE | MAC_RGMII_MODE_TX_LOWPWR | MAC_RGMII_MODE_TX_RESET); - if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) { + if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE)) { if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) val |= MAC_RGMII_MODE_RX_INT_B | MAC_RGMII_MODE_RX_QUALITY | @@ -1125,7 +1125,7 @@ static int tg3_mdio_init(struct tg3 *tp) PHY_BRCM_RX_REFCLK_UNUSED | PHY_BRCM_DIS_TXCRXC_NOENRGY | PHY_BRCM_AUTO_PWRDWN_ENABLE; - if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) + if (tp->tg3_flags3 & TG3_FLG3_RGMII_INBAND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE; @@ -12365,8 +12365,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND; } - if (cfg4 & NIC_SRAM_RGMII_STD_IBND_DISABLE) - tp->tg3_flags3 |= TG3_FLG3_RGMII_STD_IBND_DISABLE; + if (cfg4 & NIC_SRAM_RGMII_INBAND_DISABLE) + tp->tg3_flags3 |= TG3_FLG3_RGMII_INBAND_DISABLE; if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_RX_EN) tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_RX_EN; if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ffc12b1cb388..d2712c5b78ec 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1979,7 +1979,7 @@ #define NIC_SRAM_DATA_CFG_4 0x00000d60 #define NIC_SRAM_GMII_MODE 0x00000002 -#define NIC_SRAM_RGMII_STD_IBND_DISABLE 0x00000004 +#define NIC_SRAM_RGMII_INBAND_DISABLE 0x00000004 #define NIC_SRAM_RGMII_EXT_IBND_RX_EN 0x00000008 #define NIC_SRAM_RGMII_EXT_IBND_TX_EN 0x00000010 @@ -2825,7 +2825,7 @@ struct tg3 { #define TG3_FLG3_USE_PHYLIB 0x00000010 #define TG3_FLG3_MDIOBUS_INITED 0x00000020 #define TG3_FLG3_PHY_CONNECTED 0x00000080 -#define TG3_FLG3_RGMII_STD_IBND_DISABLE 0x00000100 +#define TG3_FLG3_RGMII_INBAND_DISABLE 0x00000100 #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 #define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 #define TG3_FLG3_CLKREQ_BUG 0x00000800 -- cgit v1.2.3 From 0d86df808886d4e56c46a9c356dfb81146e3b6d1 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:00 +0000 Subject: tg3: Reduce indent level of tg3_rx_prodring_alloc This patch adds an inverted "jumbo ring enable" test and jumps to the exit if it succeeds. The change reduces the indent level of the remaining code making it more readable. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 09e3af0d1743..c38143b7b600 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6087,31 +6087,31 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, memset(tpr->rx_jmb, 0, TG3_RX_JUMBO_RING_BYTES); - if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE) { - for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { - struct tg3_rx_buffer_desc *rxd; - - rxd = &tpr->rx_jmb[i].std; - rxd->idx_len = TG3_RX_JMB_DMA_SZ << RXD_LEN_SHIFT; - rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | - RXD_FLAG_JUMBO; - rxd->opaque = (RXD_OPAQUE_RING_JUMBO | - (i << RXD_OPAQUE_INDEX_SHIFT)); - } + if (!(tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)) + goto done; - for (i = 0; i < tp->rx_jumbo_pending; i++) { - if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, - i) < 0) { - printk(KERN_WARNING PFX - "%s: Using a smaller RX jumbo ring, " - "only %d out of %d buffers were " - "allocated successfully.\n", - tp->dev->name, i, tp->rx_jumbo_pending); - if (i == 0) - goto initfail; - tp->rx_jumbo_pending = i; - break; - } + for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) { + struct tg3_rx_buffer_desc *rxd; + + rxd = &tpr->rx_jmb[i].std; + rxd->idx_len = TG3_RX_JMB_DMA_SZ << RXD_LEN_SHIFT; + rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT) | + RXD_FLAG_JUMBO; + rxd->opaque = (RXD_OPAQUE_RING_JUMBO | + (i << RXD_OPAQUE_INDEX_SHIFT)); + } + + for (i = 0; i < tp->rx_jumbo_pending; i++) { + if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) { + printk(KERN_WARNING PFX + "%s: Using a smaller RX jumbo ring, " + "only %d out of %d buffers were " + "allocated successfully.\n", + tp->dev->name, i, tp->rx_jumbo_pending); + if (i == 0) + goto initfail; + tp->rx_jumbo_pending = i; + break; } } -- cgit v1.2.3 From 9ea4818dd39cc8c6b31c38c9f51d19d5d4ee0be6 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:01 +0000 Subject: tg3: Discover phy address once The phy address will not change after it has been identified. Move the discovery code to a location that only gets executed once. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c38143b7b600..3a62cc50c210 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1035,6 +1035,17 @@ static void tg3_mdio_start(struct tg3 *tp) tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); + if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) + tg3_mdio_config_5785(tp); +} + +static int tg3_mdio_init(struct tg3 *tp) +{ + int i; + u32 reg; + struct phy_device *phydev; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) { u32 funcnum, is_serdes; @@ -1054,17 +1065,6 @@ static void tg3_mdio_start(struct tg3 *tp) } else tp->phy_addr = TG3_PHY_MII_ADDR; - if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) && - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) - tg3_mdio_config_5785(tp); -} - -static int tg3_mdio_init(struct tg3 *tp) -{ - int i; - u32 reg; - struct phy_device *phydev; - tg3_mdio_start(tp); if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) || -- cgit v1.2.3 From 24daf2b0a4005f3a4e757752fcfed9da276cf202 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:02 +0000 Subject: tg3: Reformat SSID to phy ID table This patch reformats the SSID to phy ID table, replacing constants with preprocessor definitions. This patch is also prep work for the following patch, which will push line lengths beyond 80 chars. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 84 ++++++++++++++++++++++++++++++++++++------------------- drivers/net/tg3.h | 34 +++++++++++++++++++++- 2 files changed, 88 insertions(+), 30 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3a62cc50c210..b545ea7e0ad6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12112,45 +12112,71 @@ struct subsys_tbl_ent { u32 phy_id; }; -static struct subsys_tbl_ent subsys_id_to_phy_id[] = { +static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { /* Broadcom boards. */ - { PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */ - { PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */ - { PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */ - { PCI_VENDOR_ID_BROADCOM, 0x0003, 0 }, /* BCM95700A9 */ - { PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */ - { PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */ - { PCI_VENDOR_ID_BROADCOM, 0x0007, 0 }, /* BCM95701A7 */ - { PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */ - { PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */ - { PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */ - { PCI_VENDOR_ID_BROADCOM, 0x8009, PHY_ID_BCM5703 }, /* BCM95703Ax2 */ + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, PHY_ID_BCM5401 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, PHY_ID_BCM8002 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, PHY_ID_BCM5703 }, + { TG3PCI_SUBVENDOR_ID_BROADCOM, + TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, PHY_ID_BCM5703 }, /* 3com boards. */ - { PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */ - { PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */ - { PCI_VENDOR_ID_3COM, 0x1004, 0 }, /* 3C996SX */ - { PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */ - { PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */ + { TG3PCI_SUBVENDOR_ID_3COM, + TG3PCI_SUBDEVICE_ID_3COM_3C996T, PHY_ID_BCM5401 }, + { TG3PCI_SUBVENDOR_ID_3COM, + TG3PCI_SUBDEVICE_ID_3COM_3C996BT, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_3COM, + TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 }, + { TG3PCI_SUBVENDOR_ID_3COM, + TG3PCI_SUBDEVICE_ID_3COM_3C1000T, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_3COM, + TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, PHY_ID_BCM5701 }, /* DELL boards. */ - { PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */ - { PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */ - { PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */ - { PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */ + { TG3PCI_SUBVENDOR_ID_DELL, + TG3PCI_SUBDEVICE_ID_DELL_VIPER, PHY_ID_BCM5401 }, + { TG3PCI_SUBVENDOR_ID_DELL, + TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, PHY_ID_BCM5401 }, + { TG3PCI_SUBVENDOR_ID_DELL, + TG3PCI_SUBDEVICE_ID_DELL_MERLOT, PHY_ID_BCM5411 }, + { TG3PCI_SUBVENDOR_ID_DELL, + TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, PHY_ID_BCM5411 }, /* Compaq boards. */ - { PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */ - { PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */ - { PCI_VENDOR_ID_COMPAQ, 0x007d, 0 }, /* CHANGELING */ - { PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */ - { PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */ + { TG3PCI_SUBVENDOR_ID_COMPAQ, + TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_COMPAQ, + TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_COMPAQ, + TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 }, + { TG3PCI_SUBVENDOR_ID_COMPAQ, + TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, PHY_ID_BCM5701 }, + { TG3PCI_SUBVENDOR_ID_COMPAQ, + TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, PHY_ID_BCM5701 }, /* IBM boards. */ - { PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */ + { TG3PCI_SUBVENDOR_ID_IBM, + TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 } }; -static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp) +static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp) { int i; @@ -12476,7 +12502,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) /* No eeprom signature? Try the hardcoded * subsys device table. */ - p = lookup_by_subsys(tp); + p = tg3_lookup_by_subsys(tp); if (!p) return -ENODEV; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index d2712c5b78ec..12ce22644ac8 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -56,7 +56,39 @@ #define TG3PCI_DEVICE_TIGON3_57765 0x16b4 #define TG3PCI_DEVICE_TIGON3_57791 0x16b2 #define TG3PCI_DEVICE_TIGON3_57795 0x16b6 -/* 0x04 --> 0x64 unused */ +/* 0x04 --> 0x2c unused */ +#define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5 0x0001 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6 0x0002 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9 0x0003 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1 0x0005 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8 0x0006 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7 0x0007 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10 0x0008 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12 0x8008 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1 0x0009 +#define TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2 0x8009 +#define TG3PCI_SUBVENDOR_ID_3COM PCI_VENDOR_ID_3COM +#define TG3PCI_SUBDEVICE_ID_3COM_3C996T 0x1000 +#define TG3PCI_SUBDEVICE_ID_3COM_3C996BT 0x1006 +#define TG3PCI_SUBDEVICE_ID_3COM_3C996SX 0x1004 +#define TG3PCI_SUBDEVICE_ID_3COM_3C1000T 0x1007 +#define TG3PCI_SUBDEVICE_ID_3COM_3C940BR01 0x1008 +#define TG3PCI_SUBVENDOR_ID_DELL PCI_VENDOR_ID_DELL +#define TG3PCI_SUBDEVICE_ID_DELL_VIPER 0x00d1 +#define TG3PCI_SUBDEVICE_ID_DELL_JAGUAR 0x0106 +#define TG3PCI_SUBDEVICE_ID_DELL_MERLOT 0x0109 +#define TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT 0x010a +#define TG3PCI_SUBVENDOR_ID_COMPAQ PCI_VENDOR_ID_COMPAQ +#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE 0x007c +#define TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2 0x009a +#define TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING 0x007d +#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780 0x0085 +#define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2 0x0099 +#define TG3PCI_SUBVENDOR_ID_IBM PCI_VENDOR_ID_IBM +#define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2 0x0281 +/* 0x30 --> 0x64 unused */ #define TG3PCI_MSI_DATA 0x00000064 /* 0x66 --> 0x68 unused */ #define TG3PCI_MISC_HOST_CTRL 0x00000068 -- cgit v1.2.3 From 79eb6904361fe4e54e589919a9b62c5e036c42c3 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:03 +0000 Subject: tg3: Rename tg3 phy ID preprocessor definitions The phylib presents the phy ID in a different format than the one tg3 has traditionally used. To highlight the distinction, this patch prepends the tg3 native phy ID format with TG3. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 122 +++++++++++++++++++++++++++--------------------------- drivers/net/tg3.h | 91 ++++++++++++++++++++-------------------- 2 files changed, 106 insertions(+), 107 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b545ea7e0ad6..965efa92b020 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1995,7 +1995,7 @@ out: } /* Set Extended packet length bit (bit 14) on all chips that */ /* support jumbo frames */ - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { /* Cannot do read-modify-write on 5401 */ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20); } else if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) { @@ -2147,7 +2147,7 @@ static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed) { if (tp->led_ctrl == LED_CTRL_MODE_PHY_2) return 1; - else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) { + else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) { if (speed != SPEED_10) return 1; } else if (speed == SPEED_10) @@ -3077,7 +3077,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if (force_reset) tg3_phy_reset(tp); - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { tg3_readphy(tp, MII_BMSR, &bmsr); if (tg3_readphy(tp, MII_BMSR, &bmsr) || !(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) @@ -3098,7 +3098,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) } } - if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 && + if ((tp->phy_id & TG3_PHY_ID_REV_MASK) == + TG3_PHY_REV_BCM5401_B0 && !(bmsr & BMSR_LSTATUS) && tp->link_config.active_speed == SPEED_1000) { err = tg3_phy_reset(tp); @@ -3253,7 +3254,7 @@ relink: /* ??? Without this setting Netgear GA302T PHY does not * ??? send/receive packets... */ - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 && + if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 && tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) { tp->mi_mode |= MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); @@ -3968,7 +3969,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - if (tp->phy_id == PHY_ID_BCM8002) + if (tp->phy_id == TG3_PHY_ID_BCM8002) tg3_init_bcm8002(tp); /* Enable link change event even when serdes polling. */ @@ -10854,9 +10855,10 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tw32_f(MAC_RX_MODE, tp->rx_mode); } if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) { - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + u32 masked_phy_id = tp->phy_id & TG3_PHY_ID_MASK; + if (masked_phy_id == TG3_PHY_ID_BCM5401) mac_mode &= ~MAC_MODE_LINK_POLARITY; - else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) + else if (masked_phy_id == TG3_PHY_ID_BCM5411) mac_mode |= MAC_MODE_LINK_POLARITY; tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_LNK3_LED_MODE); @@ -12115,61 +12117,61 @@ struct subsys_tbl_ent { static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = { /* Broadcom boards. */ { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, PHY_ID_BCM5401 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A5, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, PHY_ID_BCM8002 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95700T6, TG3_PHY_ID_BCM8002 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, TG3PCI_SUBDEVICE_ID_BROADCOM_95700A9, 0 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701T1, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701T8, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, TG3PCI_SUBDEVICE_ID_BROADCOM_95701A7, 0 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A10, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95701A12, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, PHY_ID_BCM5703 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX1, TG3_PHY_ID_BCM5703 }, { TG3PCI_SUBVENDOR_ID_BROADCOM, - TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, PHY_ID_BCM5703 }, + TG3PCI_SUBDEVICE_ID_BROADCOM_95703AX2, TG3_PHY_ID_BCM5703 }, /* 3com boards. */ { TG3PCI_SUBVENDOR_ID_3COM, - TG3PCI_SUBDEVICE_ID_3COM_3C996T, PHY_ID_BCM5401 }, + TG3PCI_SUBDEVICE_ID_3COM_3C996T, TG3_PHY_ID_BCM5401 }, { TG3PCI_SUBVENDOR_ID_3COM, - TG3PCI_SUBDEVICE_ID_3COM_3C996BT, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_3COM_3C996BT, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_3COM, TG3PCI_SUBDEVICE_ID_3COM_3C996SX, 0 }, { TG3PCI_SUBVENDOR_ID_3COM, - TG3PCI_SUBDEVICE_ID_3COM_3C1000T, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_3COM_3C1000T, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_3COM, - TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_3COM_3C940BR01, TG3_PHY_ID_BCM5701 }, /* DELL boards. */ { TG3PCI_SUBVENDOR_ID_DELL, - TG3PCI_SUBDEVICE_ID_DELL_VIPER, PHY_ID_BCM5401 }, + TG3PCI_SUBDEVICE_ID_DELL_VIPER, TG3_PHY_ID_BCM5401 }, { TG3PCI_SUBVENDOR_ID_DELL, - TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, PHY_ID_BCM5401 }, + TG3PCI_SUBDEVICE_ID_DELL_JAGUAR, TG3_PHY_ID_BCM5401 }, { TG3PCI_SUBVENDOR_ID_DELL, - TG3PCI_SUBDEVICE_ID_DELL_MERLOT, PHY_ID_BCM5411 }, + TG3PCI_SUBDEVICE_ID_DELL_MERLOT, TG3_PHY_ID_BCM5411 }, { TG3PCI_SUBVENDOR_ID_DELL, - TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, PHY_ID_BCM5411 }, + TG3PCI_SUBDEVICE_ID_DELL_SLIM_MERLOT, TG3_PHY_ID_BCM5411 }, /* Compaq boards. */ { TG3PCI_SUBVENDOR_ID_COMPAQ, - TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_COMPAQ, - TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_COMPAQ_BANSHEE_2, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_COMPAQ, TG3PCI_SUBDEVICE_ID_COMPAQ_CHANGELING, 0 }, { TG3PCI_SUBVENDOR_ID_COMPAQ, - TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780, TG3_PHY_ID_BCM5701 }, { TG3PCI_SUBVENDOR_ID_COMPAQ, - TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, PHY_ID_BCM5701 }, + TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2, TG3_PHY_ID_BCM5701 }, /* IBM boards. */ { TG3PCI_SUBVENDOR_ID_IBM, @@ -12217,7 +12219,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) val = tr32(MEMARB_MODE); tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); - tp->phy_id = PHY_ID_INVALID; + tp->phy_id = TG3_PHY_ID_INVALID; tp->led_ctrl = LED_CTRL_MODE_PHY_1; /* Assume an onboard device and WOL capable by default. */ @@ -12468,7 +12470,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) err = 0; if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) || (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { - hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID; + hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID; } else { /* Now read the physical PHY_ID from the chip and verify * that it is sane. If it doesn't look good, we fall back @@ -12482,17 +12484,17 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16; hw_phy_id |= (hw_phy_id_2 & 0x03ff) << 0; - hw_phy_id_masked = hw_phy_id & PHY_ID_MASK; + hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK; } - if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) { + if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) { tp->phy_id = hw_phy_id; - if (hw_phy_id_masked == PHY_ID_BCM8002) + if (hw_phy_id_masked == TG3_PHY_ID_BCM8002) tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; else tp->tg3_flags2 &= ~TG3_FLG2_PHY_SERDES; } else { - if (tp->phy_id != PHY_ID_INVALID) { + if (tp->phy_id != TG3_PHY_ID_INVALID) { /* Do nothing, phy ID already set up in * tg3_get_eeprom_hw_cfg(). */ @@ -12508,7 +12510,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tp->phy_id = p->phy_id; if (!tp->phy_id || - tp->phy_id == PHY_ID_BCM8002) + tp->phy_id == TG3_PHY_ID_BCM8002) tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; } } @@ -12560,13 +12562,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) } skip_phy_reset: - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { + if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) { err = tg3_init_5401phy_dsp(tp); if (err) return err; - } - if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) { err = tg3_init_5401phy_dsp(tp); } @@ -14317,28 +14317,28 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp) static char * __devinit tg3_phy_string(struct tg3 *tp) { - switch (tp->phy_id & PHY_ID_MASK) { - case PHY_ID_BCM5400: return "5400"; - case PHY_ID_BCM5401: return "5401"; - case PHY_ID_BCM5411: return "5411"; - case PHY_ID_BCM5701: return "5701"; - case PHY_ID_BCM5703: return "5703"; - case PHY_ID_BCM5704: return "5704"; - case PHY_ID_BCM5705: return "5705"; - case PHY_ID_BCM5750: return "5750"; - case PHY_ID_BCM5752: return "5752"; - case PHY_ID_BCM5714: return "5714"; - case PHY_ID_BCM5780: return "5780"; - case PHY_ID_BCM5755: return "5755"; - case PHY_ID_BCM5787: return "5787"; - case PHY_ID_BCM5784: return "5784"; - case PHY_ID_BCM5756: return "5722/5756"; - case PHY_ID_BCM5906: return "5906"; - case PHY_ID_BCM5761: return "5761"; - case PHY_ID_BCM5718C: return "5718C"; - case PHY_ID_BCM5718S: return "5718S"; - case PHY_ID_BCM57765: return "57765"; - case PHY_ID_BCM8002: return "8002/serdes"; + switch (tp->phy_id & TG3_PHY_ID_MASK) { + case TG3_PHY_ID_BCM5400: return "5400"; + case TG3_PHY_ID_BCM5401: return "5401"; + case TG3_PHY_ID_BCM5411: return "5411"; + case TG3_PHY_ID_BCM5701: return "5701"; + case TG3_PHY_ID_BCM5703: return "5703"; + case TG3_PHY_ID_BCM5704: return "5704"; + case TG3_PHY_ID_BCM5705: return "5705"; + case TG3_PHY_ID_BCM5750: return "5750"; + case TG3_PHY_ID_BCM5752: return "5752"; + case TG3_PHY_ID_BCM5714: return "5714"; + case TG3_PHY_ID_BCM5780: return "5780"; + case TG3_PHY_ID_BCM5755: return "5755"; + case TG3_PHY_ID_BCM5787: return "5787"; + case TG3_PHY_ID_BCM5784: return "5784"; + case TG3_PHY_ID_BCM5756: return "5722/5756"; + case TG3_PHY_ID_BCM5906: return "5906"; + case TG3_PHY_ID_BCM5761: return "5761"; + case TG3_PHY_ID_BCM5718C: return "5718C"; + case TG3_PHY_ID_BCM5718S: return "5718S"; + case TG3_PHY_ID_BCM57765: return "57765"; + case TG3_PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 12ce22644ac8..800dec463e98 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2921,45 +2921,59 @@ struct tg3 { /* PHY info */ u32 phy_id; -#define PHY_ID_MASK 0xfffffff0 -#define PHY_ID_BCM5400 0x60008040 -#define PHY_ID_BCM5401 0x60008050 -#define PHY_ID_BCM5411 0x60008070 -#define PHY_ID_BCM5701 0x60008110 -#define PHY_ID_BCM5703 0x60008160 -#define PHY_ID_BCM5704 0x60008190 -#define PHY_ID_BCM5705 0x600081a0 -#define PHY_ID_BCM5750 0x60008180 -#define PHY_ID_BCM5752 0x60008100 -#define PHY_ID_BCM5714 0x60008340 -#define PHY_ID_BCM5780 0x60008350 -#define PHY_ID_BCM5755 0xbc050cc0 -#define PHY_ID_BCM5787 0xbc050ce0 -#define PHY_ID_BCM5756 0xbc050ed0 -#define PHY_ID_BCM5784 0xbc050fa0 -#define PHY_ID_BCM5761 0xbc050fd0 -#define PHY_ID_BCM5718C 0x5c0d8a00 -#define PHY_ID_BCM5718S 0xbc050ff0 -#define PHY_ID_BCM57765 0x5c0d8a40 -#define PHY_ID_BCM5906 0xdc00ac40 -#define PHY_ID_BCM8002 0x60010140 -#define PHY_ID_INVALID 0xffffffff -#define PHY_ID_REV_MASK 0x0000000f -#define PHY_REV_BCM5401_B0 0x1 -#define PHY_REV_BCM5401_B2 0x3 -#define PHY_REV_BCM5401_C0 0x6 -#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ -#define TG3_PHY_ID_BCM50610 0x143bd60 -#define TG3_PHY_ID_BCM50610M 0x143bd70 -#define TG3_PHY_ID_BCMAC131 0x143bc70 +#define TG3_PHY_ID_MASK 0xfffffff0 +#define TG3_PHY_ID_BCM5400 0x60008040 +#define TG3_PHY_ID_BCM5401 0x60008050 +#define TG3_PHY_ID_BCM5411 0x60008070 +#define TG3_PHY_ID_BCM5701 0x60008110 +#define TG3_PHY_ID_BCM5703 0x60008160 +#define TG3_PHY_ID_BCM5704 0x60008190 +#define TG3_PHY_ID_BCM5705 0x600081a0 +#define TG3_PHY_ID_BCM5750 0x60008180 +#define TG3_PHY_ID_BCM5752 0x60008100 +#define TG3_PHY_ID_BCM5714 0x60008340 +#define TG3_PHY_ID_BCM5780 0x60008350 +#define TG3_PHY_ID_BCM5755 0xbc050cc0 +#define TG3_PHY_ID_BCM5787 0xbc050ce0 +#define TG3_PHY_ID_BCM5756 0xbc050ed0 +#define TG3_PHY_ID_BCM5784 0xbc050fa0 +#define TG3_PHY_ID_BCM5761 0xbc050fd0 +#define TG3_PHY_ID_BCM5718C 0x5c0d8a00 +#define TG3_PHY_ID_BCM5718S 0xbc050ff0 +#define TG3_PHY_ID_BCM57765 0x5c0d8a40 +#define TG3_PHY_ID_BCM5906 0xdc00ac40 +#define TG3_PHY_ID_BCM8002 0x60010140 +#define TG3_PHY_ID_BCM50610 0x0143bd60 +#define TG3_PHY_ID_BCM50610M 0x0143bd70 +#define TG3_PHY_ID_BCMAC131 0x0143bc70 #define TG3_PHY_ID_RTL8211C 0x001cc910 #define TG3_PHY_ID_RTL8201E 0x00008200 #define TG3_PHY_ID_BCM57780 0x03625d90 +#define TG3_PHY_ID_INVALID 0xffffffff + +#define TG3_PHY_ID_REV_MASK 0x0000000f +#define TG3_PHY_REV_BCM5401_B0 0x1 + #define TG3_PHY_OUI_MASK 0xfffffc00 #define TG3_PHY_OUI_1 0x00206000 #define TG3_PHY_OUI_2 0x0143bc00 #define TG3_PHY_OUI_3 0x03625c00 + /* This macro assumes the passed PHY ID is + * already masked with TG3_PHY_ID_MASK. + */ +#define TG3_KNOWN_PHY_ID(X) \ + ((X) == TG3_PHY_ID_BCM5400 || (X) == TG3_PHY_ID_BCM5401 || \ + (X) == TG3_PHY_ID_BCM5411 || (X) == TG3_PHY_ID_BCM5701 || \ + (X) == TG3_PHY_ID_BCM5703 || (X) == TG3_PHY_ID_BCM5704 || \ + (X) == TG3_PHY_ID_BCM5705 || (X) == TG3_PHY_ID_BCM5750 || \ + (X) == TG3_PHY_ID_BCM5752 || (X) == TG3_PHY_ID_BCM5714 || \ + (X) == TG3_PHY_ID_BCM5780 || (X) == TG3_PHY_ID_BCM5787 || \ + (X) == TG3_PHY_ID_BCM5755 || (X) == TG3_PHY_ID_BCM5756 || \ + (X) == TG3_PHY_ID_BCM5906 || (X) == TG3_PHY_ID_BCM5761 || \ + (X) == TG3_PHY_ID_BCM5718C || (X) == TG3_PHY_ID_BCM5718S || \ + (X) == TG3_PHY_ID_BCM57765 || (X) == TG3_PHY_ID_BCM8002) + u32 led_ctrl; u32 phy_otp; @@ -2971,21 +2985,6 @@ struct tg3 { u32 pci_clock_ctrl; struct pci_dev *pdev_peer; - /* This macro assumes the passed PHY ID is already masked - * with PHY_ID_MASK. - */ -#define KNOWN_PHY_ID(X) \ - ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \ - (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ - (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ - (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ - (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5714 || \ - (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ - (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ - (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \ - (X) == PHY_ID_BCM5718C || (X) == PHY_ID_BCM5718S || \ - (X) == PHY_ID_BCM57765 || (X) == PHY_ID_BCM8002) - struct tg3_hw_stats *hw_stats; dma_addr_t stats_mapping; struct work_struct reset_task; -- cgit v1.2.3 From 6a443a0f72ad7706345412dbd2e4d4981fdfce39 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:04 +0000 Subject: tg3: Push phylib definitions to phylib This patch pushes phylib definitions out to phylib headers. For phy IDs, this removes some code duplication. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 5 +---- drivers/net/tg3.c | 32 ++++++++++++++++---------------- drivers/net/tg3.h | 14 +++----------- include/linux/brcmphy.h | 11 +++++++++++ 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 33c4b12a63ba..f482fc4f8cf1 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -18,9 +18,6 @@ #include #include -#define PHY_ID_BCM50610 0x0143bd60 -#define PHY_ID_BCM50610M 0x0143bd70 -#define PHY_ID_BCM57780 0x03625d90 #define BRCM_PHY_MODEL(phydev) \ ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) @@ -823,7 +820,7 @@ static struct phy_driver bcm57780_driver = { }; static struct phy_driver bcmac131_driver = { - .phy_id = 0x0143bc70, + .phy_id = PHY_ID_BCMAC131, .phy_id_mask = 0xfffffff0, .name = "Broadcom BCMAC131", .features = PHY_BASIC_FEATURES | diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 965efa92b020..994bac0b018b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -955,17 +955,17 @@ static void tg3_mdio_config_5785(struct tg3 *tp) phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { - case TG3_PHY_ID_BCM50610: - case TG3_PHY_ID_BCM50610M: + case PHY_ID_BCM50610: + case PHY_ID_BCM50610M: val = MAC_PHYCFG2_50610_LED_MODES; break; - case TG3_PHY_ID_BCMAC131: + case PHY_ID_BCMAC131: val = MAC_PHYCFG2_AC131_LED_MODES; break; - case TG3_PHY_ID_RTL8211C: + case PHY_ID_RTL8211C: val = MAC_PHYCFG2_RTL8211C_LED_MODES; break; - case TG3_PHY_ID_RTL8201E: + case PHY_ID_RTL8201E: val = MAC_PHYCFG2_RTL8201E_LED_MODES; break; default: @@ -1115,12 +1115,12 @@ static int tg3_mdio_init(struct tg3 *tp) } switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { - case TG3_PHY_ID_BCM57780: + case PHY_ID_BCM57780: phydev->interface = PHY_INTERFACE_MODE_GMII; phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; break; - case TG3_PHY_ID_BCM50610: - case TG3_PHY_ID_BCM50610M: + case PHY_ID_BCM50610: + case PHY_ID_BCM50610M: phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE | PHY_BRCM_RX_REFCLK_UNUSED | PHY_BRCM_DIS_TXCRXC_NOENRGY | @@ -1132,11 +1132,11 @@ static int tg3_mdio_init(struct tg3 *tp) if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN) phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE; /* fallthru */ - case TG3_PHY_ID_RTL8211C: + case PHY_ID_RTL8211C: phydev->interface = PHY_INTERFACE_MODE_RGMII; break; - case TG3_PHY_ID_RTL8201E: - case TG3_PHY_ID_BCMAC131: + case PHY_ID_RTL8201E: + case PHY_ID_BCMAC131: phydev->interface = PHY_INTERFACE_MODE_MII; phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; tp->tg3_flags3 |= TG3_FLG3_PHY_IS_FET; @@ -2563,11 +2563,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) phy_start_aneg(phydev); phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask; - if (phyid != TG3_PHY_ID_BCMAC131) { - phyid &= TG3_PHY_OUI_MASK; - if (phyid == TG3_PHY_OUI_1 || - phyid == TG3_PHY_OUI_2 || - phyid == TG3_PHY_OUI_3) + if (phyid != PHY_ID_BCMAC131) { + phyid &= PHY_BCM_OUI_MASK; + if (phyid == PHY_BCM_OUI_1 || + phyid == PHY_BCM_OUI_2 || + phyid == PHY_BCM_OUI_3) do_low_power = true; } } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 800dec463e98..574a1cc4d353 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2943,22 +2943,14 @@ struct tg3 { #define TG3_PHY_ID_BCM57765 0x5c0d8a40 #define TG3_PHY_ID_BCM5906 0xdc00ac40 #define TG3_PHY_ID_BCM8002 0x60010140 -#define TG3_PHY_ID_BCM50610 0x0143bd60 -#define TG3_PHY_ID_BCM50610M 0x0143bd70 -#define TG3_PHY_ID_BCMAC131 0x0143bc70 -#define TG3_PHY_ID_RTL8211C 0x001cc910 -#define TG3_PHY_ID_RTL8201E 0x00008200 -#define TG3_PHY_ID_BCM57780 0x03625d90 #define TG3_PHY_ID_INVALID 0xffffffff +#define PHY_ID_RTL8211C 0x001cc910 +#define PHY_ID_RTL8201E 0x00008200 + #define TG3_PHY_ID_REV_MASK 0x0000000f #define TG3_PHY_REV_BCM5401_B0 0x1 -#define TG3_PHY_OUI_MASK 0xfffffc00 -#define TG3_PHY_OUI_1 0x00206000 -#define TG3_PHY_OUI_2 0x0143bc00 -#define TG3_PHY_OUI_3 0x03625c00 - /* This macro assumes the passed PHY ID is * already masked with TG3_PHY_ID_MASK. */ diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 2b31b91f5871..7f437ca1ed44 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -1,3 +1,14 @@ +#define PHY_ID_BCM50610 0x0143bd60 +#define PHY_ID_BCM50610M 0x0143bd70 +#define PHY_ID_BCMAC131 0x0143bc70 +#define PHY_ID_BCM57780 0x03625d90 + +#define PHY_BCM_OUI_MASK 0xfffffc00 +#define PHY_BCM_OUI_1 0x00206000 +#define PHY_BCM_OUI_2 0x0143bc00 +#define PHY_BCM_OUI_3 0x03625c00 + + #define PHY_BCM_FLAGS_MODE_COPPER 0x00000001 #define PHY_BCM_FLAGS_MODE_1000BX 0x00000002 #define PHY_BCM_FLAGS_INTF_SGMII 0x00000010 -- cgit v1.2.3 From be7ce5307ded2e416224baab0bd1e5072591f33f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Wed, 17 Feb 2010 15:17:05 +0000 Subject: tg3: Update version to 3.108 This patch updates the tg3 version to 3.108. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 994bac0b018b..ddf66155f5e2 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.107" -#define DRV_MODULE_RELDATE "February 12, 2010" +#define DRV_MODULE_VERSION "3.108" +#define DRV_MODULE_RELDATE "February 17, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From b4f18b3faccae13c0530ae8f7f20fe81d18f2bd5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:48 +0000 Subject: drivers/net/8139cp.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Remove periods from formats Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/8139cp.c | 72 ++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 60bc0b0ad4f3..3d4406b16658 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c @@ -46,6 +46,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "8139cp" #define DRV_VERSION "1.3" #define DRV_RELDATE "Mar 22, 2004" @@ -104,8 +106,6 @@ static int multicast_filter_limit = 32; module_param(multicast_filter_limit, int, 0); MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses"); -#define PFX DRV_NAME ": " - #define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK) @@ -470,9 +470,8 @@ static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb, static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail, u32 status, u32 len) { - if (netif_msg_rx_err (cp)) - pr_debug("%s: rx err, slot %d status 0x%x len %d\n", - cp->dev->name, rx_tail, status, len); + netif_dbg(cp, rx_err, cp->dev, "rx err, slot %d status 0x%x len %d\n", + rx_tail, status, len); cp->dev->stats.rx_errors++; if (status & RxErrFrame) cp->dev->stats.rx_frame_errors++; @@ -545,9 +544,8 @@ rx_status_loop: goto rx_next; } - if (netif_msg_rx_status(cp)) - pr_debug("%s: rx slot %d status 0x%x len %d\n", - dev->name, rx_tail, status, len); + netif_dbg(cp, rx_status, dev, "rx slot %d status 0x%x len %d\n", + rx_tail, status, len); new_skb = netdev_alloc_skb_ip_align(dev, buflen); if (!new_skb) { @@ -621,9 +619,8 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) if (!status || (status == 0xFFFF)) return IRQ_NONE; - if (netif_msg_intr(cp)) - pr_debug("%s: intr, status %04x cmd %02x cpcmd %04x\n", - dev->name, status, cpr8(Cmd), cpr16(CpCmd)); + netif_dbg(cp, intr, dev, "intr, status %04x cmd %02x cpcmd %04x\n", + status, cpr8(Cmd), cpr16(CpCmd)); cpw16(IntrStatus, status & ~cp_rx_intr_mask); @@ -654,8 +651,8 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance) pci_read_config_word(cp->pdev, PCI_STATUS, &pci_status); pci_write_config_word(cp->pdev, PCI_STATUS, pci_status); - pr_err("%s: PCI bus error, status=%04x, PCI status=%04x\n", - dev->name, status, pci_status); + netdev_err(dev, "PCI bus error, status=%04x, PCI status=%04x\n", + status, pci_status); /* TODO: reset hardware */ } @@ -700,9 +697,8 @@ static void cp_tx (struct cp_private *cp) if (status & LastFrag) { if (status & (TxError | TxFIFOUnder)) { - if (netif_msg_tx_err(cp)) - pr_debug("%s: tx err, status 0x%x\n", - cp->dev->name, status); + netif_dbg(cp, tx_err, cp->dev, + "tx err, status 0x%x\n", status); cp->dev->stats.tx_errors++; if (status & TxOWC) cp->dev->stats.tx_window_errors++; @@ -717,8 +713,8 @@ static void cp_tx (struct cp_private *cp) ((status >> TxColCntShift) & TxColCntMask); cp->dev->stats.tx_packets++; cp->dev->stats.tx_bytes += skb->len; - if (netif_msg_tx_done(cp)) - pr_debug("%s: tx done, slot %d\n", cp->dev->name, tx_tail); + netif_dbg(cp, tx_done, cp->dev, + "tx done, slot %d\n", tx_tail); } dev_kfree_skb_irq(skb); } @@ -752,8 +748,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, if (TX_BUFFS_AVAIL(cp) <= (skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); spin_unlock_irqrestore(&cp->lock, intr_flags); - pr_err(PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -878,9 +873,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, wmb(); } cp->tx_head = entry; - if (netif_msg_tx_queued(cp)) - pr_debug("%s: tx queued, slot %d, skblen %d\n", - dev->name, entry, skb->len); + netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n", + entry, skb->len); if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); @@ -992,7 +986,7 @@ static void cp_reset_hw (struct cp_private *cp) schedule_timeout_uninterruptible(10); } - pr_err("%s: hardware reset timeout\n", cp->dev->name); + netdev_err(cp->dev, "hardware reset timeout\n"); } static inline void cp_start_hw (struct cp_private *cp) @@ -1159,8 +1153,7 @@ static int cp_open (struct net_device *dev) struct cp_private *cp = netdev_priv(dev); int rc; - if (netif_msg_ifup(cp)) - pr_debug("%s: enabling interface\n", dev->name); + netif_dbg(cp, ifup, dev, "enabling interface\n"); rc = cp_alloc_rings(cp); if (rc) @@ -1194,8 +1187,7 @@ static int cp_close (struct net_device *dev) napi_disable(&cp->napi); - if (netif_msg_ifdown(cp)) - pr_debug("%s: disabling interface\n", dev->name); + netif_dbg(cp, ifdown, dev, "disabling interface\n"); spin_lock_irqsave(&cp->lock, flags); @@ -1218,9 +1210,9 @@ static void cp_tx_timeout(struct net_device *dev) unsigned long flags; int rc; - pr_warning("%s: Transmit timeout, status %2x %4x %4x %4x\n", - dev->name, cpr8(Cmd), cpr16(CpCmd), - cpr16(IntrStatus), cpr16(IntrMask)); + netdev_warn(dev, "Transmit timeout, status %2x %4x %4x %4x\n", + cpr8(Cmd), cpr16(CpCmd), + cpr16(IntrStatus), cpr16(IntrMask)); spin_lock_irqsave(&cp->lock, flags); @@ -1873,8 +1865,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (pdev->vendor == PCI_VENDOR_ID_REALTEK && pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) { dev_info(&pdev->dev, - "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip, use 8139too\n", - pdev->vendor, pdev->device, pdev->revision); + "This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip, use 8139too\n", + pdev->vendor, pdev->device, pdev->revision); return -ENODEV; } @@ -1932,14 +1924,13 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, - "No usable DMA configuration, aborting.\n"); + "No usable DMA configuration, aborting\n"); goto err_out_res; } rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc) { dev_err(&pdev->dev, - "No usable consistent DMA configuration, " - "aborting.\n"); + "No usable consistent DMA configuration, aborting\n"); goto err_out_res; } } @@ -1951,7 +1942,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!regs) { rc = -EIO; dev_err(&pdev->dev, "Cannot map PCI MMIO (%Lx@%Lx)\n", - (unsigned long long)pci_resource_len(pdev, 1), + (unsigned long long)pci_resource_len(pdev, 1), (unsigned long long)pciaddr); goto err_out_res; } @@ -1989,11 +1980,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_iomap; - pr_info("%s: RTL-8139C+ at 0x%lx, %pM, IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr, - dev->irq); + netdev_info(dev, "RTL-8139C+ at 0x%lx, %pM, IRQ %d\n", + dev->base_addr, dev->dev_addr, dev->irq); pci_set_drvdata(pdev, dev); -- cgit v1.2.3 From 497159aff6c81b61fe88463a64e7dad6f86297e3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:49 +0000 Subject: drivers/net/8139too.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Convert formats like %8.8 to %08 Remove periods from formats Coalesce long formats Use print_hex_dump Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/8139too.c | 187 ++++++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 106 deletions(-) diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index c7d6f094cc7a..b4efc913978b 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -89,6 +89,8 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "8139too" #define DRV_VERSION "0.9.28" @@ -111,7 +113,6 @@ #include #define RTL8139_DRIVER_NAME DRV_NAME " Fast Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " /* Default Message level */ #define RTL8139_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ @@ -130,9 +131,9 @@ # define assert(expr) do {} while (0) #else # define assert(expr) \ - if(unlikely(!(expr))) { \ - pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ - #expr, __FILE__, __func__, __LINE__); \ + if (unlikely(!(expr))) { \ + pr_err("Assertion failed! %s,%s,%s,line=%d\n", \ + #expr, __FILE__, __func__, __LINE__); \ } #endif @@ -957,7 +958,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->subsystem_vendor == PCI_VENDOR_ID_ATHEROS && pdev->subsystem_device == PCI_DEVICE_ID_REALTEK_8139) { - pr_info("8139too: OQO Model 2 detected. Forcing PIO\n"); + pr_info("OQO Model 2 detected. Forcing PIO\n"); use_io = 1; } @@ -1010,21 +1011,19 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, tp->mii.reg_num_mask = 0x1f; /* dev is fully set up and ready to use now */ - pr_debug("about to register device named %s (%p)...\n", dev->name, dev); + pr_debug("about to register device named %s (%p)...\n", + dev->name, dev); i = register_netdev (dev); if (i) goto err_out; pci_set_drvdata (pdev, dev); - pr_info("%s: %s at 0x%lx, %pM, IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); + netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", + board_info[ent->driver_data].name, + dev->base_addr, dev->dev_addr, dev->irq); - pr_debug("%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); + netdev_dbg(dev, "Identified 8139 chip type '%s'\n", + rtl_chip_info[tp->chipset].name); /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -1037,13 +1036,12 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, if (mii_status != 0xffff && mii_status != 0x0000) { u16 advertising = mdio_read(dev, phy, 4); tp->phys[phy_idx++] = phy; - pr_info("%s: MII transceiver %d status 0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, advertising); + netdev_info(dev, "MII transceiver %d status 0x%04x advertising %04x\n", + phy, mii_status, advertising); } } if (phy_idx == 0) { - pr_info("%s: No MII transceivers found! Assuming SYM transceiver.\n", - dev->name); + netdev_info(dev, "No MII transceivers found! Assuming SYM transceiver\n"); tp->phys[0] = 32; } } else @@ -1062,15 +1060,15 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev, if (board_idx < MAX_UNITS && full_duplex[board_idx] > 0) tp->mii.full_duplex = full_duplex[board_idx]; if (tp->mii.full_duplex) { - pr_info("%s: Media type forced to Full Duplex.\n", dev->name); + netdev_info(dev, "Media type forced to Full Duplex\n"); /* Changing the MII-advertised media because might prevent re-connection. */ tp->mii.force_media = 1; } if (tp->default_port) { - pr_info(" Forcing %dMbps %s-duplex operation.\n", - (option & 0x20 ? 100 : 10), - (option & 0x10 ? "full" : "half")); + netdev_info(dev, " Forcing %dMbps %s-duplex operation\n", + (option & 0x20 ? 100 : 10), + (option & 0x10 ? "full" : "half")); mdio_write(dev, tp->phys[0], 0, ((option & 0x20) ? 0x2000 : 0) | /* 100Mbps? */ ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ @@ -1330,12 +1328,12 @@ static int rtl8139_open (struct net_device *dev) rtl8139_hw_start (dev); netif_start_queue (dev); - if (netif_msg_ifup(tp)) - pr_debug("%s: rtl8139_open() ioaddr %#llx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", dev->name, - (unsigned long long)pci_resource_start (tp->pci_dev, 1), - dev->irq, RTL_R8 (MediaStatus), - tp->mii.full_duplex ? "full" : "half"); + netif_dbg(tp, ifup, dev, + "%s() ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", + __func__, + (unsigned long long)pci_resource_start (tp->pci_dev, 1), + dev->irq, RTL_R8 (MediaStatus), + tp->mii.full_duplex ? "full" : "half"); rtl8139_start_thread(tp); @@ -1393,7 +1391,7 @@ static void rtl8139_hw_start (struct net_device *dev) RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic); } - pr_debug("init buffer addresses\n"); + netdev_dbg(dev, "init buffer addresses\n"); /* Lock Config[01234] and BMCR register writes */ RTL_W8 (Cfg9346, Cfg9346_Lock); @@ -1555,14 +1553,11 @@ static inline void rtl8139_thread_iter (struct net_device *dev, tp->mii.full_duplex = duplex; if (mii_lpa) { - pr_info("%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", - dev->name, - tp->mii.full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); + netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", + tp->mii.full_duplex ? "full" : "half", + tp->phys[0], mii_lpa); } else { - pr_info("%s: media is unconnected, link down, or incompatible connection\n", - dev->name); + netdev_info(dev, "media is unconnected, link down, or incompatible connection\n"); } #if 0 RTL_W8 (Cfg9346, Cfg9346_Unlock); @@ -1576,13 +1571,12 @@ static inline void rtl8139_thread_iter (struct net_device *dev, rtl8139_tune_twister (dev, tp); - pr_debug("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, RTL_R16 (NWayLPAR)); - pr_debug("%s: Other registers are IntMask %4.4x IntStatus %4.4x\n", - dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus)); - pr_debug("%s: Chip config %2.2x %2.2x.\n", - dev->name, RTL_R8 (Config0), - RTL_R8 (Config1)); + netdev_dbg(dev, "Media selection tick, Link partner %04x\n", + RTL_R16(NWayLPAR)); + netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x\n", + RTL_R16(IntrMask), RTL_R16(IntrStatus)); + netdev_dbg(dev, "Chip config %02x %02x\n", + RTL_R8(Config0), RTL_R8(Config1)); } static void rtl8139_thread (struct work_struct *work) @@ -1640,17 +1634,17 @@ static void rtl8139_tx_timeout_task (struct work_struct *work) int i; u8 tmp8; - pr_debug("%s: Transmit timeout, status %2.2x %4.4x %4.4x media %2.2x.\n", - dev->name, RTL_R8 (ChipCmd), - RTL_R16(IntrStatus), RTL_R16(IntrMask), RTL_R8(MediaStatus)); + netdev_dbg(dev, "Transmit timeout, status %02x %04x %04x media %02x\n", + RTL_R8(ChipCmd), RTL_R16(IntrStatus), + RTL_R16(IntrMask), RTL_R8(MediaStatus)); /* Emit info to figure out what went wrong. */ - pr_debug("%s: Tx queue start entry %ld dirty entry %ld.\n", - dev->name, tp->cur_tx, tp->dirty_tx); + netdev_dbg(dev, "Tx queue start entry %ld dirty entry %ld\n", + tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++) - pr_debug("%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == tp->dirty_tx % NUM_TX_DESC ? - " (queue head)" : ""); + netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n", + i, RTL_R32(TxStatus0 + (i * 4)), + i == tp->dirty_tx % NUM_TX_DESC ? + " (queue head)" : ""); tp->xstats.tx_timeouts++; @@ -1729,9 +1723,8 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb, netif_stop_queue (dev); spin_unlock_irqrestore(&tp->lock, flags); - if (netif_msg_tx_queued(tp)) - pr_debug("%s: Queued Tx packet size %u to slot %d.\n", - dev->name, len, entry); + netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n", + len, entry); return NETDEV_TX_OK; } @@ -1760,9 +1753,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev, /* Note: TxCarrierLost is always asserted at 100mbps. */ if (txstatus & (TxOutOfWindow | TxAborted)) { /* There was an major error, log it. */ - if (netif_msg_tx_err(tp)) - pr_debug("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); + netif_dbg(tp, tx_err, dev, "Transmit error, Tx status %08x\n", + txstatus); dev->stats.tx_errors++; if (txstatus & TxAborted) { dev->stats.tx_aborted_errors++; @@ -1792,8 +1784,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev, #ifndef RTL8139_NDEBUG if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { - pr_err("%s: Out-of-sync dirty pointer, %ld vs. %ld.\n", - dev->name, dirty_tx, tp->cur_tx); + netdev_err(dev, "Out-of-sync dirty pointer, %ld vs. %ld\n", + dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; } #endif /* RTL8139_NDEBUG */ @@ -1816,14 +1808,13 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, int tmp_work; #endif - if (netif_msg_rx_err (tp)) - pr_debug("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); + netif_dbg(tp, rx_err, dev, "Ethernet frame had errors, status %08x\n", + rx_status); dev->stats.rx_errors++; if (!(rx_status & RxStatusOK)) { if (rx_status & RxTooLong) { - pr_debug("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); + netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", + rx_status); /* A.C.: The chip hangs here. */ } if (rx_status & (RxBadSymbol | RxBadAlign)) @@ -1855,7 +1846,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, break; } if (tmp_work <= 0) - pr_warning(PFX "rx stop wait too long\n"); + netdev_warn(dev, "rx stop wait too long\n"); /* restart receive */ tmp_work = 200; while (--tmp_work > 0) { @@ -1866,7 +1857,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, break; } if (tmp_work <= 0) - pr_warning(PFX "tx/rx enable wait too long\n"); + netdev_warn(dev, "tx/rx enable wait too long\n"); /* and reinitialize all rx related registers */ RTL_W8_F (Cfg9346, Cfg9346_Unlock); @@ -1877,7 +1868,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev, RTL_W32 (RxConfig, tp->rx_config); tp->cur_rx = 0; - pr_debug("init buffer addresses\n"); + netdev_dbg(dev, "init buffer addresses\n"); /* Lock Config[01234] and BMCR register writes */ RTL_W8 (Cfg9346, Cfg9346_Lock); @@ -1931,10 +1922,9 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, unsigned int cur_rx = tp->cur_rx; unsigned int rx_size = 0; - pr_debug("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); + netdev_dbg(dev, "In %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", + __func__, (u16)cur_rx, + RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); while (netif_running(dev) && received < budget && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { @@ -1950,19 +1940,12 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, rx_size = rx_status >> 16; pkt_size = rx_size - 4; - if (netif_msg_rx_status(tp)) - pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); + netif_dbg(tp, rx_status, dev, "%s() status %04x, size %04x, cur %04x\n", + __func__, rx_status, rx_size, cur_rx); #if RTL8139_DEBUG > 2 - { - int i; - pr_debug("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - pr_cont(" %2.2x", - rx_ring[ring_offset + i]); - pr_cont(".\n"); - } + print_dump_hex(KERN_DEBUG, "Frame contents: ", + DUMP_PREFIX_OFFSET, 16, 1, + &rx_ring[ring_offset], 70, true); #endif /* Packet copy from FIFO still in progress. @@ -1973,14 +1956,11 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, if (!tp->fifo_copy_timeout) tp->fifo_copy_timeout = jiffies + 2; else if (time_after(jiffies, tp->fifo_copy_timeout)) { - pr_debug("%s: hung FIFO. Reset.", dev->name); + netdev_dbg(dev, "hung FIFO. Reset\n"); rx_size = 0; goto no_early_rx; } - if (netif_msg_intr(tp)) { - pr_debug("%s: fifo copy in progress.", - dev->name); - } + netif_dbg(tp, intr, dev, "fifo copy in progress\n"); tp->xstats.early_rx++; break; } @@ -2021,8 +2001,7 @@ no_early_rx: netif_receive_skb (skb); } else { if (net_ratelimit()) - pr_warning("%s: Memory squeeze, dropping packet.\n", - dev->name); + netdev_warn(dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; } received++; @@ -2036,10 +2015,9 @@ no_early_rx: if (unlikely(!received || rx_size == 0xfff0)) rtl8139_isr_ack(tp); - pr_debug("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - RTL_R16 (RxBufAddr), - RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); + netdev_dbg(dev, "Done %s(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", + __func__, cur_rx, + RTL_R16(RxBufAddr), RTL_R16(RxBufPtr), RTL_R8(ChipCmd)); tp->cur_rx = cur_rx; @@ -2060,8 +2038,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev, void __iomem *ioaddr, int status, int link_changed) { - pr_debug("%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); + netdev_dbg(dev, "Abnormal interrupt, status %08x\n", status); assert (dev != NULL); assert (tp != NULL); @@ -2089,8 +2066,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev, pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status); - pr_err("%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); + netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); } } @@ -2183,8 +2159,8 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance) out: spin_unlock (&tp->lock); - pr_debug("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); + netdev_dbg(dev, "exiting interrupt, intr_status=%#4.4x\n", + RTL_R16(IntrStatus)); return IRQ_RETVAL(handled); } @@ -2233,9 +2209,8 @@ static int rtl8139_close (struct net_device *dev) netif_stop_queue(dev); napi_disable(&tp->napi); - if (netif_msg_ifdown(tp)) - pr_debug("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, RTL_R16 (IntrStatus)); + netif_dbg(tp, ifdown, dev, "Shutting down ethercard, status was 0x%04x\n", + RTL_R16(IntrStatus)); spin_lock_irqsave (&tp->lock, flags); @@ -2512,8 +2487,8 @@ static void __set_rx_mode (struct net_device *dev) int rx_mode; u32 tmp; - pr_debug("%s: rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n", - dev->name, dev->flags, RTL_R32 (RxConfig)); + netdev_dbg(dev, "rtl8139_set_rx_mode(%04x) done -- Rx config %08lx\n", + dev->flags, RTL_R32(RxConfig)); /* Note: do not reorder, GCC is clever about common statements. */ if (dev->flags & IFF_PROMISC) { -- cgit v1.2.3 From 2fc96fff4483971aa81795382c368ea7d8100dde Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:50 +0000 Subject: drivers/net/b44.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Remove periods from formats Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/b44.c | 72 ++++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index f21cbe63c7b1..180510ed92a5 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -10,6 +10,8 @@ * Distribute under GPL. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -34,7 +36,6 @@ #include "b44.h" #define DRV_MODULE_NAME "b44" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "2.0" #define B44_DEF_MSG_ENABLE \ @@ -190,12 +191,9 @@ static int b44_wait_bit(struct b44 *bp, unsigned long reg, } if (i == timeout) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: BUG! Timeout waiting for bit " - "%08x of register " - "%lx to %s.\n", - bp->dev->name, - bit, reg, - (clear ? "clear" : "set")); + netdev_err(bp->dev, "BUG! Timeout waiting for bit %08x of register %lx to %s\n", + bit, reg, clear ? "clear" : "set"); + return -ENODEV; } return 0; @@ -335,8 +333,7 @@ static int b44_phy_reset(struct b44 *bp) err = b44_readphy(bp, MII_BMCR, &val); if (!err) { if (val & BMCR_RESET) { - printk(KERN_ERR PFX "%s: PHY Reset would not complete.\n", - bp->dev->name); + netdev_err(bp->dev, "PHY Reset would not complete\n"); err = -ENODEV; } } @@ -415,7 +412,7 @@ static void b44_wap54g10_workaround(struct b44 *bp) } return; error: - printk(KERN_WARNING PFX "PHY: cannot reset MII transceiver isolate bit.\n"); + pr_warning("PHY: cannot reset MII transceiver isolate bit\n"); } #else static inline void b44_wap54g10_workaround(struct b44 *bp) @@ -508,18 +505,15 @@ static void b44_stats_update(struct b44 *bp) static void b44_link_report(struct b44 *bp) { if (!netif_carrier_ok(bp->dev)) { - printk(KERN_INFO PFX "%s: Link is down.\n", bp->dev->name); + netdev_info(bp->dev, "Link is down\n"); } else { - printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", - bp->dev->name, - (bp->flags & B44_FLAG_100_BASE_T) ? 100 : 10, - (bp->flags & B44_FLAG_FULL_DUPLEX) ? "full" : "half"); - - printk(KERN_INFO PFX "%s: Flow control is %s for TX and " - "%s for RX.\n", - bp->dev->name, - (bp->flags & B44_FLAG_TX_PAUSE) ? "on" : "off", - (bp->flags & B44_FLAG_RX_PAUSE) ? "on" : "off"); + netdev_info(bp->dev, "Link is up at %d Mbps, %s duplex\n", + (bp->flags & B44_FLAG_100_BASE_T) ? 100 : 10, + (bp->flags & B44_FLAG_FULL_DUPLEX) ? "full" : "half"); + + netdev_info(bp->dev, "Flow control is %s for TX and %s for RX\n", + (bp->flags & B44_FLAG_TX_PAUSE) ? "on" : "off", + (bp->flags & B44_FLAG_RX_PAUSE) ? "on" : "off"); } } @@ -578,11 +572,9 @@ static void b44_check_phy(struct b44 *bp) } if (bmsr & BMSR_RFAULT) - printk(KERN_WARNING PFX "%s: Remote fault detected in PHY\n", - bp->dev->name); + netdev_warn(bp->dev, "Remote fault detected in PHY\n"); if (bmsr & BMSR_JCD) - printk(KERN_WARNING PFX "%s: Jabber detected in PHY\n", - bp->dev->name); + netdev_warn(bp->dev, "Jabber detected in PHY\n"); } } @@ -903,7 +895,7 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id) handled = 1; if (unlikely(!netif_running(dev))) { - printk(KERN_INFO "%s: late interrupt.\n", dev->name); + netdev_info(dev, "late interrupt\n"); goto irq_ack; } @@ -928,8 +920,7 @@ static void b44_tx_timeout(struct net_device *dev) { struct b44 *bp = netdev_priv(dev); - printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", - dev->name); + netdev_err(dev, "transmit timed out, resetting\n"); spin_lock_irq(&bp->lock); @@ -958,8 +949,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev) /* This is a hard error, log it. */ if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) { netif_stop_queue(dev); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); goto err_out; } @@ -1335,7 +1325,7 @@ static void b44_halt(struct b44 *bp) /* reset PHY */ b44_phy_reset(bp); /* power down PHY */ - printk(KERN_INFO PFX "%s: powering down PHY\n", bp->dev->name); + netdev_info(bp->dev, "powering down PHY\n"); bw32(bp, B44_MAC_CTRL, MAC_CTRL_PHY_PDOWN); /* now reset the chip, but without enabling the MAC&PHY * part of it. This has to be done _after_ we shut down the PHY */ @@ -1526,7 +1516,7 @@ static void b44_setup_pseudo_magicp(struct b44 *bp) pwol_pattern = kzalloc(B44_PATTERN_SIZE, GFP_KERNEL); if (!pwol_pattern) { - printk(KERN_ERR PFX "Memory not available for WOL\n"); + pr_err("Memory not available for WOL\n"); return; } @@ -2099,7 +2089,7 @@ static int __devinit b44_get_invariants(struct b44 *bp) memcpy(bp->dev->dev_addr, addr, 6); if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ - printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n"); + pr_err("Invalid MAC address found in EEPROM\n"); return -EINVAL; } @@ -2144,12 +2134,12 @@ static int __devinit b44_init_one(struct ssb_device *sdev, instance++; if (b44_version_printed++ == 0) - printk(KERN_INFO "%s", version); + pr_info("%s", version); dev = alloc_etherdev(sizeof(*bp)); if (!dev) { - dev_err(sdev->dev, "Etherdev alloc failed, aborting.\n"); + dev_err(sdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto out; } @@ -2188,13 +2178,13 @@ static int __devinit b44_init_one(struct ssb_device *sdev, err = ssb_dma_set_mask(sdev, DMA_BIT_MASK(30)); if (err) { dev_err(sdev->dev, - "Required 30BIT DMA mask unsupported by the system.\n"); + "Required 30BIT DMA mask unsupported by the system\n"); goto err_out_powerdown; } err = b44_get_invariants(bp); if (err) { dev_err(sdev->dev, - "Problem fetching invariants of chip, aborting.\n"); + "Problem fetching invariants of chip, aborting\n"); goto err_out_powerdown; } @@ -2214,7 +2204,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev, err = register_netdev(dev); if (err) { - dev_err(sdev->dev, "Cannot register net device, aborting.\n"); + dev_err(sdev->dev, "Cannot register net device, aborting\n"); goto err_out_powerdown; } @@ -2225,8 +2215,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev, */ b44_chip_reset(bp, B44_CHIP_RESET_FULL); - printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n", - dev->name, dev->dev_addr); + netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n", + dev->dev_addr); return 0; @@ -2299,7 +2289,7 @@ static int b44_resume(struct ssb_device *sdev) rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev); if (rc) { - printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name); + netdev_err(dev, "request_irq failed\n"); return rc; } -- cgit v1.2.3 From 3a9c6a4915e584663aebdb9016bcb9d3897dd779 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:51 +0000 Subject: drivers/net/bnx2.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Remove periods from formats Coalesce long formats Coalesce some printks Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 145 ++++++++++++++++++++++------------------------------- 1 file changed, 61 insertions(+), 84 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5f0dda10f20d..a6cc9d02e589 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -9,6 +9,7 @@ * Written by: Michael Chan (mchan@broadcom.com) */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -57,7 +58,6 @@ #include "bnx2_fw.h" #define DRV_MODULE_NAME "bnx2" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "2.0.8" #define DRV_MODULE_RELDATE "Feb 15, 2010" #define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j6.fw" @@ -979,33 +979,27 @@ bnx2_report_link(struct bnx2 *bp) { if (bp->link_up) { netif_carrier_on(bp->dev); - printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name, - bnx2_xceiver_str(bp)); - - printk("%d Mbps ", bp->line_speed); - - if (bp->duplex == DUPLEX_FULL) - printk("full duplex"); - else - printk("half duplex"); + netdev_info(bp->dev, "NIC %s Link is Up, %d Mbps %s duplex", + bnx2_xceiver_str(bp), + bp->line_speed, + bp->duplex == DUPLEX_FULL ? "full" : "half"); if (bp->flow_ctrl) { if (bp->flow_ctrl & FLOW_CTRL_RX) { - printk(", receive "); + pr_cont(", receive "); if (bp->flow_ctrl & FLOW_CTRL_TX) - printk("& transmit "); + pr_cont("& transmit "); } else { - printk(", transmit "); + pr_cont(", transmit "); } - printk("flow control ON"); + pr_cont("flow control ON"); } - printk("\n"); - } - else { + pr_cont("\n"); + } else { netif_carrier_off(bp->dev); - printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name, - bnx2_xceiver_str(bp)); + netdev_err(bp->dev, "NIC %s Link is Down\n", + bnx2_xceiver_str(bp)); } bnx2_report_fw_link(bp); @@ -2482,8 +2476,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent) /* If we timed out, inform the firmware that this is the case. */ if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) { if (!silent) - printk(KERN_ERR PFX "fw sync timeout, reset code = " - "%x\n", msg_data); + pr_err("fw sync timeout, reset code = %x\n", msg_data); msg_data &= ~BNX2_DRV_MSG_CODE; msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT; @@ -2599,8 +2592,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); if (good_mbuf == NULL) { - printk(KERN_ERR PFX "Failed to allocate memory in " - "bnx2_alloc_bad_rbuf\n"); + pr_err("Failed to allocate memory in %s\n", __func__); return -ENOMEM; } @@ -3656,15 +3648,13 @@ bnx2_request_firmware(struct bnx2 *bp) rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev); if (rc) { - printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n", - mips_fw_file); + pr_err("Can't load firmware file \"%s\"\n", mips_fw_file); return rc; } rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev); if (rc) { - printk(KERN_ERR PFX "Can't load firmware file \"%s\"\n", - rv2p_fw_file); + pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file); return rc; } mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data; @@ -3675,15 +3665,13 @@ bnx2_request_firmware(struct bnx2 *bp) check_mips_fw_entry(bp->mips_firmware, &mips_fw->rxp) || check_mips_fw_entry(bp->mips_firmware, &mips_fw->tpat) || check_mips_fw_entry(bp->mips_firmware, &mips_fw->txp)) { - printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n", - mips_fw_file); + pr_err("Firmware file \"%s\" is invalid\n", mips_fw_file); return -EINVAL; } if (bp->rv2p_firmware->size < sizeof(*rv2p_fw) || check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc1.rv2p, 8, true) || check_fw_section(bp->rv2p_firmware, &rv2p_fw->proc2.rv2p, 8, true)) { - printk(KERN_ERR PFX "Firmware file \"%s\" is invalid\n", - rv2p_fw_file); + pr_err("Firmware file \"%s\" is invalid\n", rv2p_fw_file); return -EINVAL; } @@ -4317,7 +4305,7 @@ bnx2_init_nvram(struct bnx2 *bp) if (j == entry_count) { bp->flash_info = NULL; - printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n"); + pr_alert("Unknown flash/EEPROM type\n"); return -ENODEV; } @@ -4737,7 +4725,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { - printk(KERN_ERR PFX "Chip reset did not complete\n"); + pr_err("Chip reset did not complete\n"); return -EBUSY; } } @@ -4745,7 +4733,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) /* Make sure byte swapping is properly configured. */ val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0); if (val != 0x01020304) { - printk(KERN_ERR PFX "Chip not in correct endian mode\n"); + pr_err("Chip not in correct endian mode\n"); return -ENODEV; } @@ -5166,9 +5154,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) ring_prod = prod = rxr->rx_pg_prod; for (i = 0; i < bp->rx_pg_ring_size; i++) { if (bnx2_alloc_rx_page(bp, rxr, ring_prod) < 0) { - printk(KERN_WARNING PFX "%s: init'ed rx page ring %d " - "with %d/%d pages only\n", - bp->dev->name, ring_num, i, bp->rx_pg_ring_size); + netdev_warn(bp->dev, "init'ed rx page ring %d with %d/%d pages only\n", + ring_num, i, bp->rx_pg_ring_size); break; } prod = NEXT_RX_BD(prod); @@ -5179,9 +5166,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num) ring_prod = prod = rxr->rx_prod; for (i = 0; i < bp->rx_ring_size; i++) { if (bnx2_alloc_rx_skb(bp, rxr, ring_prod) < 0) { - printk(KERN_WARNING PFX "%s: init'ed rx ring %d with " - "%d/%d skbs only\n", - bp->dev->name, ring_num, i, bp->rx_ring_size); + netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d skbs only\n", + ring_num, i, bp->rx_ring_size); break; } prod = NEXT_RX_BD(prod); @@ -6239,11 +6225,7 @@ bnx2_open(struct net_device *dev) * If MSI test fails, go back to INTx mode */ if (bnx2_test_intr(bp) != 0) { - printk(KERN_WARNING PFX "%s: No interrupt was generated" - " using MSI, switching to INTx mode. Please" - " report this failure to the PCI maintainer" - " and include system chipset information.\n", - bp->dev->name); + netdev_warn(bp->dev, "No interrupt was generated using MSI, switching to INTx mode. Please report this failure to the PCI maintainer and include system chipset information.\n"); bnx2_disable_int(bp); bnx2_free_irq(bp); @@ -6263,9 +6245,9 @@ bnx2_open(struct net_device *dev) } } if (bp->flags & BNX2_FLAG_USING_MSI) - printk(KERN_INFO PFX "%s: using MSI\n", dev->name); + netdev_info(dev, "using MSI\n"); else if (bp->flags & BNX2_FLAG_USING_MSIX) - printk(KERN_INFO PFX "%s: using MSIX\n", dev->name); + netdev_info(dev, "using MSIX\n"); netif_tx_start_all_queues(dev); @@ -6304,20 +6286,18 @@ bnx2_dump_state(struct bnx2 *bp) { struct net_device *dev = bp->dev; - printk(KERN_ERR PFX "%s DEBUG: intr_sem[%x]\n", dev->name, - atomic_read(&bp->intr_sem)); - printk(KERN_ERR PFX "%s DEBUG: EMAC_TX_STATUS[%08x] " - "RPM_MGMT_PKT_CTRL[%08x]\n", dev->name, - REG_RD(bp, BNX2_EMAC_TX_STATUS), - REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL)); - printk(KERN_ERR PFX "%s DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n", - dev->name, bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P0), - bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P1)); - printk(KERN_ERR PFX "%s DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n", - dev->name, REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS)); + netdev_err(dev, "DEBUG: intr_sem[%x]\n", atomic_read(&bp->intr_sem)); + netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] RPM_MGMT_PKT_CTRL[%08x]\n", + REG_RD(bp, BNX2_EMAC_TX_STATUS), + REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL)); + netdev_err(dev, "DEBUG: MCP_STATE_P0[%08x] MCP_STATE_P1[%08x]\n", + bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P0), + bnx2_reg_rd_ind(bp, BNX2_MCP_STATE_P1)); + netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n", + REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS)); if (bp->flags & BNX2_FLAG_USING_MSIX) - printk(KERN_ERR PFX "%s DEBUG: PBA[%08x]\n", dev->name, - REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE)); + netdev_err(dev, "DEBUG: PBA[%08x]\n", + REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE)); } static void @@ -6381,8 +6361,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(bnx2_tx_avail(bp, txr) < (skb_shinfo(skb)->nr_frags + 1))) { netif_tx_stop_queue(txq); - printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n", - dev->name); + netdev_err(dev, "BUG! Tx ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -7869,20 +7848,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) /* enable device (incl. PCI PM wakeup), and bus-mastering */ rc = pci_enable_device(pdev); if (rc) { - dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n"); + dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); goto err_out; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { dev_err(&pdev->dev, - "Cannot find PCI device base address, aborting.\n"); + "Cannot find PCI device base address, aborting\n"); rc = -ENODEV; goto err_out_disable; } rc = pci_request_regions(pdev, DRV_MODULE_NAME); if (rc) { - dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); goto err_out_disable; } @@ -7892,7 +7871,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (bp->pm_cap == 0) { dev_err(&pdev->dev, - "Cannot find power management capability, aborting.\n"); + "Cannot find power management capability, aborting\n"); rc = -EIO; goto err_out_release; } @@ -7915,7 +7894,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->regview = ioremap_nocache(dev->base_addr, mem_len); if (!bp->regview) { - dev_err(&pdev->dev, "Cannot map register space, aborting.\n"); + dev_err(&pdev->dev, "Cannot map register space, aborting\n"); rc = -ENOMEM; goto err_out_release; } @@ -7935,7 +7914,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if (CHIP_NUM(bp) == CHIP_NUM_5709) { if (pci_find_capability(pdev, PCI_CAP_ID_EXP) == 0) { dev_err(&pdev->dev, - "Cannot find PCIE capability, aborting.\n"); + "Cannot find PCIE capability, aborting\n"); rc = -EIO; goto err_out_unmap; } @@ -7946,7 +7925,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); if (bp->pcix_cap == 0) { dev_err(&pdev->dev, - "Cannot find PCIX capability, aborting.\n"); + "Cannot find PCIX capability, aborting\n"); rc = -EIO; goto err_out_unmap; } @@ -7975,11 +7954,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask); if (rc) { dev_err(&pdev->dev, - "pci_set_consistent_dma_mask failed, aborting.\n"); + "pci_set_consistent_dma_mask failed, aborting\n"); goto err_out_unmap; } } else if ((rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { - dev_err(&pdev->dev, "System does not support DMA, aborting.\n"); + dev_err(&pdev->dev, "System does not support DMA, aborting\n"); goto err_out_unmap; } @@ -7996,7 +7975,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) !(bp->flags & BNX2_FLAG_PCIX)) { dev_err(&pdev->dev, - "5706 A1 can only be used in a PCIX bus, aborting.\n"); + "5706 A1 can only be used in a PCIX bus, aborting\n"); goto err_out_unmap; } @@ -8019,7 +7998,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != BNX2_DEV_INFO_SIGNATURE_MAGIC) { - dev_err(&pdev->dev, "Firmware not running, aborting.\n"); + dev_err(&pdev->dev, "Firmware not running, aborting\n"); rc = -ENODEV; goto err_out_unmap; } @@ -8292,7 +8271,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) char str[40]; if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + pr_info("%s", version); /* dev zeroed in init_etherdev */ dev = alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS); @@ -8342,15 +8321,13 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto error; } - printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, " - "IRQ %d, node addr %pM\n", - dev->name, - board_info[ent->driver_data].name, - ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', - ((CHIP_ID(bp) & 0x0ff0) >> 4), - bnx2_bus_string(bp, str), - dev->base_addr, - bp->pdev->irq, dev->dev_addr); + netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, node addr %pM\n", + board_info[ent->driver_data].name, + ((CHIP_ID(bp) & 0xf000) >> 12) + 'A', + ((CHIP_ID(bp) & 0x0ff0) >> 4), + bnx2_bus_string(bp, str), + dev->base_addr, + bp->pdev->irq, dev->dev_addr); return 0; @@ -8485,7 +8462,7 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) rtnl_lock(); if (pci_enable_device(pdev)) { dev_err(&pdev->dev, - "Cannot re-enable PCI device after reset.\n"); + "Cannot re-enable PCI device after reset\n"); rtnl_unlock(); return PCI_ERS_RESULT_DISCONNECT; } -- cgit v1.2.3 From 7995c64e5b56ec7fe6032e5fc586f726cde2152b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:52 +0000 Subject: drivers/net/bnx2x: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Convert struct bnx2x member msglevel to msg_enable for netif_msg_ macros Remove #define PFX Use pr_ Use netdev_ Use netif_ Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 49 ++++++++----- drivers/net/bnx2x_link.c | 21 ++---- drivers/net/bnx2x_main.c | 185 +++++++++++++++++++++-------------------------- 3 files changed, 117 insertions(+), 138 deletions(-) diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index d997d8472ee5..3c48a7a68308 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -44,7 +44,6 @@ /* error/debug prints */ #define DRV_MODULE_NAME "bnx2x" -#define PFX DRV_MODULE_NAME ": " /* for messages that are currently off */ #define BNX2X_MSG_OFF 0 @@ -58,30 +57,40 @@ #define DP_LEVEL KERN_NOTICE /* was: KERN_DEBUG */ /* regular debug print */ -#define DP(__mask, __fmt, __args...) do { \ - if (bp->msglevel & (__mask)) \ - printk(DP_LEVEL "[%s:%d(%s)]" __fmt, __func__, __LINE__, \ - bp->dev ? (bp->dev->name) : "?", ##__args); \ - } while (0) +#define DP(__mask, __fmt, __args...) \ +do { \ + if (bp->msg_enable & (__mask)) \ + printk(DP_LEVEL "[%s:%d(%s)]" __fmt, \ + __func__, __LINE__, \ + bp->dev ? (bp->dev->name) : "?", \ + ##__args); \ +} while (0) /* errors debug print */ -#define BNX2X_DBG_ERR(__fmt, __args...) do { \ - if (bp->msglevel & NETIF_MSG_PROBE) \ - printk(KERN_ERR "[%s:%d(%s)]" __fmt, __func__, __LINE__, \ - bp->dev ? (bp->dev->name) : "?", ##__args); \ - } while (0) +#define BNX2X_DBG_ERR(__fmt, __args...) \ +do { \ + if (netif_msg_probe(bp)) \ + pr_err("[%s:%d(%s)]" __fmt, \ + __func__, __LINE__, \ + bp->dev ? (bp->dev->name) : "?", \ + ##__args); \ +} while (0) /* for errors (never masked) */ -#define BNX2X_ERR(__fmt, __args...) do { \ - printk(KERN_ERR "[%s:%d(%s)]" __fmt, __func__, __LINE__, \ - bp->dev ? (bp->dev->name) : "?", ##__args); \ - } while (0) +#define BNX2X_ERR(__fmt, __args...) \ +do { \ + pr_err("[%s:%d(%s)]" __fmt, \ + __func__, __LINE__, \ + bp->dev ? (bp->dev->name) : "?", \ + ##__args); \ +} while (0) /* before we have a dev->name use dev_info() */ -#define BNX2X_DEV_INFO(__fmt, __args...) do { \ - if (bp->msglevel & NETIF_MSG_PROBE) \ - dev_info(&bp->pdev->dev, __fmt, ##__args); \ - } while (0) +#define BNX2X_DEV_INFO(__fmt, __args...) \ +do { \ + if (netif_msg_probe(bp)) \ + dev_info(&bp->pdev->dev, __fmt, ##__args); \ +} while (0) #ifdef BNX2X_STOP_ON_ERROR @@ -882,7 +891,7 @@ struct bnx2x { /* End of fields used in the performance code paths */ int panic; - int msglevel; + int msg_enable; u32 flags; #define PCIX_FLAG 1 diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index cf5778919b4b..32e79c359e89 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -14,6 +14,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -2987,11 +2989,8 @@ static u8 bnx2x_verify_sfp_module(struct link_params *params) else vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0'; - printk(KERN_INFO PFX "Warning: " - "Unqualified SFP+ module " - "detected on %s, Port %d from %s part number %s\n" - , bp->dev->name, params->port, - vendor_name, vendor_pn); + netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected, Port %d from %s part number %s\n", + params->port, vendor_name, vendor_pn); return -EINVAL; } @@ -4846,16 +4845,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, " has been detected on " "port %d\n", params->port); - printk(KERN_ERR PFX "Error: Power" - " fault on %s Port %d has" - " been detected and the" - " power to that SFP+ module" - " has been removed to prevent" - " failure of the card. Please" - " remove the SFP+ module and" - " restart the system to clear" - " this error.\n" - , bp->dev->name, params->port); + netdev_err(bp->dev, "Error: Power fault on Port %d has been detected and the power to that SFP+ module has been removed to prevent failure of the card. Please remove the SFP+ module and restart the system to clear this error.\n", + params->port); /* * Disable all RX_ALARMs except for * mod_abs diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index a4e8460ff656..7f9db47e8cc3 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -514,24 +514,24 @@ static void bnx2x_fw_dump(struct bnx2x *bp) mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104); mark = ((mark + 0x3) & ~0x3); - printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark); + pr_err("begin fw dump (mark 0x%x)\n", mark); - printk(KERN_ERR PFX); + pr_err(""); for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + offset + 4*word)); data[8] = 0x0; - printk(KERN_CONT "%s", (char *)data); + pr_cont("%s", (char *)data); } for (offset = 0xF108; offset <= mark - 0x08000000; offset += 0x8*4) { for (word = 0; word < 8; word++) data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH + offset + 4*word)); data[8] = 0x0; - printk(KERN_CONT "%s", (char *)data); + pr_cont("%s", (char *)data); } - printk(KERN_ERR PFX "end of fw dump\n"); + pr_err("end of fw dump\n"); } static void bnx2x_panic_dump(struct bnx2x *bp) @@ -2136,7 +2136,7 @@ static void bnx2x_link_report(struct bnx2x *bp) { if (bp->flags & MF_FUNC_DIS) { netif_carrier_off(bp->dev); - printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); + netdev_err(bp->dev, "NIC Link is Down\n"); return; } @@ -2145,7 +2145,7 @@ static void bnx2x_link_report(struct bnx2x *bp) if (bp->state == BNX2X_STATE_OPEN) netif_carrier_on(bp->dev); - printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name); + netdev_info(bp->dev, "NIC Link is Up, "); line_speed = bp->link_vars.line_speed; if (IS_E1HMF(bp)) { @@ -2157,29 +2157,29 @@ static void bnx2x_link_report(struct bnx2x *bp) if (vn_max_rate < line_speed) line_speed = vn_max_rate; } - printk("%d Mbps ", line_speed); + pr_cont("%d Mbps ", line_speed); if (bp->link_vars.duplex == DUPLEX_FULL) - printk("full duplex"); + pr_cont("full duplex"); else - printk("half duplex"); + pr_cont("half duplex"); if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) { if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) { - printk(", receive "); + pr_cont(", receive "); if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) - printk("& transmit "); + pr_cont("& transmit "); } else { - printk(", transmit "); + pr_cont(", transmit "); } - printk("flow control ON"); + pr_cont("flow control ON"); } - printk("\n"); + pr_cont("\n"); } else { /* link_down */ netif_carrier_off(bp->dev); - printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name); + netdev_err(bp->dev, "NIC Link is Down\n"); } } @@ -2898,10 +2898,8 @@ static inline void bnx2x_fan_failure(struct bnx2x *bp) bp->link_params.ext_phy_config); /* log the failure */ - printk(KERN_ERR PFX "Fan Failure on Network Controller %s has caused" - " the driver to shutdown the card to prevent permanent" - " damage. Please contact Dell Support for assistance\n", - bp->dev->name); + netdev_err(bp->dev, "Fan Failure on Network Controller has caused the driver to shutdown the card to prevent permanent damage.\n" + "Please contact Dell Support for assistance.\n"); } static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) @@ -4296,7 +4294,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) bnx2x_net_stats_update(bp); bnx2x_drv_stats_update(bp); - if (bp->msglevel & NETIF_MSG_TIMER) { + if (netif_msg_timer(bp)) { struct bnx2x_fastpath *fp0_rx = bp->fp; struct bnx2x_fastpath *fp0_tx = bp->fp; struct tstorm_per_client_stats *old_tclient = @@ -4306,7 +4304,7 @@ static void bnx2x_stats_update(struct bnx2x *bp) struct net_device_stats *nstats = &bp->dev->stats; int i; - printk(KERN_DEBUG "%s:\n", bp->dev->name); + netdev_printk(KERN_DEBUG, bp->dev, "\n"); printk(KERN_DEBUG " tx avail (%4x) tx hc idx (%x)" " tx pkt (%lx)\n", bnx2x_tx_avail(fp0_tx), @@ -4464,7 +4462,7 @@ static void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event) /* Make sure the state has been "changed" */ smp_wmb(); - if ((event != STATS_EVENT_UPDATE) || (bp->msglevel & NETIF_MSG_TIMER)) + if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp)) DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n", state, event, bp->stats_state); } @@ -5674,8 +5672,7 @@ gunzip_nomem2: bp->gunzip_buf = NULL; gunzip_nomem1: - printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for" - " un-compression\n", bp->dev->name); + netdev_err(bp->dev, "Cannot allocate firmware buffer for un-compression\n"); return -ENOMEM; } @@ -5721,14 +5718,13 @@ static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len) rc = zlib_inflate(bp->strm, Z_FINISH); if ((rc != Z_OK) && (rc != Z_STREAM_END)) - printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n", - bp->dev->name, bp->strm->msg); + netdev_err(bp->dev, "Firmware decompression error: %s\n", + bp->strm->msg); bp->gunzip_outlen = (FW_BUF_SIZE - bp->strm->avail_out); if (bp->gunzip_outlen & 0x3) - printk(KERN_ERR PFX "%s: Firmware decompression error:" - " gunzip_outlen (%d) not aligned\n", - bp->dev->name, bp->gunzip_outlen); + netdev_err(bp->dev, "Firmware decompression error: gunzip_outlen (%d) not aligned\n", + bp->gunzip_outlen); bp->gunzip_outlen >>= 2; zlib_inflateEnd(bp->strm); @@ -6213,8 +6209,8 @@ static int bnx2x_init_common(struct bnx2x *bp) if (sizeof(union cdu_context) != 1024) /* we currently assume that a context is 1024 bytes */ - printk(KERN_ALERT PFX "please adjust the size of" - " cdu_context(%ld)\n", (long)sizeof(union cdu_context)); + pr_alert("please adjust the size of cdu_context(%ld)\n", + (long)sizeof(union cdu_context)); bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE); val = (4 << 24) + (0 << 12) + 1024; @@ -7020,11 +7016,10 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) } i = BNX2X_NUM_QUEUES(bp); - printk(KERN_INFO PFX "%s: using MSI-X IRQs: sp %d fp[%d] %d" - " ... fp[%d] %d\n", - bp->dev->name, bp->msix_table[0].vector, - 0, bp->msix_table[offset].vector, - i - 1, bp->msix_table[offset + i - 1].vector); + netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n", + bp->msix_table[0].vector, + 0, bp->msix_table[offset].vector, + i - 1, bp->msix_table[offset + i - 1].vector); return 0; } @@ -7480,8 +7475,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } if (bp->flags & USING_MSI_FLAG) { bp->dev->irq = bp->pdev->irq; - printk(KERN_INFO PFX "%s: using MSI IRQ %d\n", - bp->dev->name, bp->pdev->irq); + netdev_info(bp->dev, "using MSI IRQ %d\n", + bp->pdev->irq); } } @@ -8303,8 +8298,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]); val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]); - printk(KERN_INFO PFX "part number %X-%X-%X-%X\n", - val, val2, val3, val4); + pr_info("part number %X-%X-%X-%X\n", val, val2, val3, val4); } static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, @@ -8915,17 +8909,15 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) bnx2x_undi_unload(bp); if (CHIP_REV_IS_FPGA(bp)) - printk(KERN_ERR PFX "FPGA detected\n"); + pr_err("FPGA detected\n"); if (BP_NOMCP(bp) && (func == 0)) - printk(KERN_ERR PFX - "MCP disabled, must load devices in order!\n"); + pr_err("MCP disabled, must load devices in order!\n"); /* Set multi queue mode */ if ((multi_mode != ETH_RSS_MODE_DISABLED) && ((int_mode == INT_MODE_INTx) || (int_mode == INT_MODE_MSI))) { - printk(KERN_ERR PFX - "Multi disabled since int_mode requested is not MSI-X\n"); + pr_err("Multi disabled since int_mode requested is not MSI-X\n"); multi_mode = ETH_RSS_MODE_DISABLED; } bp->multi_mode = multi_mode; @@ -9351,7 +9343,7 @@ static u32 bnx2x_get_msglevel(struct net_device *dev) { struct bnx2x *bp = netdev_priv(dev); - return bp->msglevel; + return bp->msg_enable; } static void bnx2x_set_msglevel(struct net_device *dev, u32 level) @@ -9359,7 +9351,7 @@ static void bnx2x_set_msglevel(struct net_device *dev, u32 level) struct bnx2x *bp = netdev_priv(dev); if (capable(CAP_NET_ADMIN)) - bp->msglevel = level; + bp->msg_enable = level; } static int bnx2x_nway_reset(struct net_device *dev) @@ -10653,7 +10645,7 @@ static const struct { ((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT) #define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC) #define IS_E1HMF_MODE_STAT(bp) \ - (IS_E1HMF(bp) && !(bp->msglevel & BNX2X_MSG_STATS)) + (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS)) static int bnx2x_get_sset_count(struct net_device *dev, int stringset) { @@ -11786,20 +11778,18 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "Cannot enable PCI device, aborting\n"); + pr_err("Cannot enable PCI device, aborting\n"); goto err_out; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find PCI device base address," - " aborting\n"); + pr_err("Cannot find PCI device base address, aborting\n"); rc = -ENODEV; goto err_out_disable; } if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find second PCI device" - " base address, aborting\n"); + pr_err("Cannot find second PCI device base address, aborting\n"); rc = -ENODEV; goto err_out_disable; } @@ -11807,8 +11797,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, if (atomic_read(&pdev->enable_cnt) == 1) { rc = pci_request_regions(pdev, DRV_MODULE_NAME); if (rc) { - printk(KERN_ERR PFX "Cannot obtain PCI resources," - " aborting\n"); + pr_err("Cannot obtain PCI resources, aborting\n"); goto err_out_disable; } @@ -11818,16 +11807,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (bp->pm_cap == 0) { - printk(KERN_ERR PFX "Cannot find power management" - " capability, aborting\n"); + pr_err("Cannot find power management capability, aborting\n"); rc = -EIO; goto err_out_release; } bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); if (bp->pcie_cap == 0) { - printk(KERN_ERR PFX "Cannot find PCI Express capability," - " aborting\n"); + pr_err("Cannot find PCI Express capability, aborting\n"); rc = -EIO; goto err_out_release; } @@ -11835,15 +11822,13 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) { bp->flags |= USING_DAC_FLAG; if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { - printk(KERN_ERR PFX "pci_set_consistent_dma_mask" - " failed, aborting\n"); + pr_err("pci_set_consistent_dma_mask failed, aborting\n"); rc = -EIO; goto err_out_release; } } else if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { - printk(KERN_ERR PFX "System does not support DMA," - " aborting\n"); + pr_err("System does not support DMA, aborting\n"); rc = -EIO; goto err_out_release; } @@ -11856,7 +11841,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, bp->regview = pci_ioremap_bar(pdev, 0); if (!bp->regview) { - printk(KERN_ERR PFX "Cannot map register space, aborting\n"); + pr_err("Cannot map register space, aborting\n"); rc = -ENOMEM; goto err_out_release; } @@ -11865,7 +11850,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, min_t(u64, BNX2X_DB_SIZE, pci_resource_len(pdev, 2))); if (!bp->doorbells) { - printk(KERN_ERR PFX "Cannot map doorbell space, aborting\n"); + pr_err("Cannot map doorbell space, aborting\n"); rc = -ENOMEM; goto err_out_unmap; } @@ -11967,8 +11952,7 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp) offset = be32_to_cpu(sections[i].offset); len = be32_to_cpu(sections[i].len); if (offset + len > firmware->size) { - printk(KERN_ERR PFX "Section %d length is out of " - "bounds\n", i); + pr_err("Section %d length is out of bounds\n", i); return -EINVAL; } } @@ -11980,8 +11964,7 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp) for (i = 0; i < be32_to_cpu(fw_hdr->init_ops_offsets.len) / 2; i++) { if (be16_to_cpu(ops_offsets[i]) > num_ops) { - printk(KERN_ERR PFX "Section offset %d is out of " - "bounds\n", i); + pr_err("Section offset %d is out of bounds\n", i); return -EINVAL; } } @@ -11993,8 +11976,7 @@ static int __devinit bnx2x_check_firmware(struct bnx2x *bp) (fw_ver[1] != BCM_5710_FW_MINOR_VERSION) || (fw_ver[2] != BCM_5710_FW_REVISION_VERSION) || (fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) { - printk(KERN_ERR PFX "Bad FW version:%d.%d.%d.%d." - " Should be %d.%d.%d.%d\n", + pr_err("Bad FW version:%d.%d.%d.%d. Should be %d.%d.%d.%d\n", fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3], BCM_5710_FW_MAJOR_VERSION, BCM_5710_FW_MINOR_VERSION, @@ -12044,18 +12026,17 @@ static inline void be16_to_cpu_n(const u8 *_source, u8 *_target, u32 n) target[i] = be16_to_cpu(source[i]); } -#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \ - do { \ - u32 len = be32_to_cpu(fw_hdr->arr.len); \ - bp->arr = kmalloc(len, GFP_KERNEL); \ - if (!bp->arr) { \ - printk(KERN_ERR PFX "Failed to allocate %d bytes " \ - "for "#arr"\n", len); \ - goto lbl; \ - } \ - func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \ - (u8 *)bp->arr, len); \ - } while (0) +#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \ +do { \ + u32 len = be32_to_cpu(fw_hdr->arr.len); \ + bp->arr = kmalloc(len, GFP_KERNEL); \ + if (!bp->arr) { \ + pr_err("Failed to allocate %d bytes for "#arr"\n", len); \ + goto lbl; \ + } \ + func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \ + (u8 *)bp->arr, len); \ +} while (0) static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) { @@ -12068,18 +12049,17 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) else fw_file_name = FW_FILE_NAME_E1H; - printk(KERN_INFO PFX "Loading %s\n", fw_file_name); + pr_info("Loading %s\n", fw_file_name); rc = request_firmware(&bp->firmware, fw_file_name, dev); if (rc) { - printk(KERN_ERR PFX "Can't load firmware file %s\n", - fw_file_name); + pr_err("Can't load firmware file %s\n", fw_file_name); goto request_firmware_exit; } rc = bnx2x_check_firmware(bp); if (rc) { - printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name); + pr_err("Corrupt firmware file %s\n", fw_file_name); goto request_firmware_exit; } @@ -12138,12 +12118,12 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* dev zeroed in init_etherdev */ dev = alloc_etherdev_mq(sizeof(*bp), MAX_CONTEXT); if (!dev) { - printk(KERN_ERR PFX "Cannot allocate net device\n"); + pr_err("Cannot allocate net device\n"); return -ENOMEM; } bp = netdev_priv(dev); - bp->msglevel = debug; + bp->msg_enable = debug; pci_set_drvdata(pdev, dev); @@ -12160,7 +12140,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* Set init arrays */ rc = bnx2x_init_firmware(bp, &pdev->dev); if (rc) { - printk(KERN_ERR PFX "Error loading firmware\n"); + pr_err("Error loading firmware\n"); goto init_one_exit; } @@ -12171,12 +12151,11 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, } bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed); - printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," - " IRQ %d, ", dev->name, board_info[ent->driver_data].name, - (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4), - pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz", - dev->base_addr, bp->pdev->irq); - printk(KERN_CONT "node addr %pM\n", dev->dev_addr); + netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n", + board_info[ent->driver_data].name, + (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4), + pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz", + dev->base_addr, bp->pdev->irq, dev->dev_addr); return 0; @@ -12204,7 +12183,7 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) struct bnx2x *bp; if (!dev) { - printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); + pr_err("BAD net device from bnx2x_init_one\n"); return; } bp = netdev_priv(dev); @@ -12237,7 +12216,7 @@ static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) struct bnx2x *bp; if (!dev) { - printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); + pr_err("BAD net device from bnx2x_init_one\n"); return -ENODEV; } bp = netdev_priv(dev); @@ -12269,7 +12248,7 @@ static int bnx2x_resume(struct pci_dev *pdev) int rc; if (!dev) { - printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); + pr_err("BAD net device from bnx2x_init_one\n"); return -ENODEV; } bp = netdev_priv(dev); @@ -12472,17 +12451,17 @@ static int __init bnx2x_init(void) { int ret; - printk(KERN_INFO "%s", version); + pr_info("%s", version); bnx2x_wq = create_singlethread_workqueue("bnx2x"); if (bnx2x_wq == NULL) { - printk(KERN_ERR PFX "Cannot create workqueue\n"); + pr_err("Cannot create workqueue\n"); return -ENOMEM; } ret = pci_register_driver(&bnx2x_pci_driver); if (ret) { - printk(KERN_ERR PFX "Cannot register driver\n"); + pr_err("Cannot register driver\n"); destroy_workqueue(bnx2x_wq); } return ret; -- cgit v1.2.3 From 436d27d1db147713e4cd17b2fa491d22374bda98 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:53 +0000 Subject: drivers/net/cassini.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Remove periods from formats Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/cassini.c | 361 +++++++++++++++++++++----------------------------- 1 file changed, 151 insertions(+), 210 deletions(-) diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index f90cac43130d..7cbcfb0ade1c 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -66,6 +66,7 @@ * by default, the selective clear mask is set up to process rx packets. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -143,7 +144,6 @@ #undef RX_COUNT_BUFFERS /* define to calculate RX buffer stats */ #define DRV_MODULE_NAME "cassini" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "1.6" #define DRV_MODULE_RELDATE "21 May 2008" @@ -649,9 +649,8 @@ static cas_page_t *cas_page_dequeue(struct cas *cp) cas_spare_recover(cp, GFP_ATOMIC); spin_lock(&cp->rx_spare_lock); if (list_empty(&cp->rx_spare_list)) { - if (netif_msg_rx_err(cp)) - printk(KERN_ERR "%s: no spare buffers " - "available.\n", cp->dev->name); + netif_err(cp, rx_err, cp->dev, + "no spare buffers available\n"); spin_unlock(&cp->rx_spare_lock); return NULL; } @@ -728,12 +727,10 @@ static void cas_begin_auto_negotiation(struct cas *cp, struct ethtool_cmd *ep) #endif start_aneg: if (cp->lstate == link_up) { - printk(KERN_INFO "%s: PCS link down.\n", - cp->dev->name); + netdev_info(cp->dev, "PCS link down\n"); } else { if (changed) { - printk(KERN_INFO "%s: link configuration changed\n", - cp->dev->name); + netdev_info(cp->dev, "link configuration changed\n"); } } cp->lstate = link_down; @@ -826,12 +823,12 @@ static int cas_saturn_firmware_init(struct cas *cp) err = request_firmware(&fw, fw_name, &cp->pdev->dev); if (err) { - printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n", + pr_err("Failed to load firmware \"%s\"\n", fw_name); return err; } if (fw->size < 2) { - printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n", + pr_err("bogus length %zu in \"%s\"\n", fw->size, fw_name); err = -EINVAL; goto out; @@ -841,7 +838,7 @@ static int cas_saturn_firmware_init(struct cas *cp) cp->fw_data = vmalloc(cp->fw_size); if (!cp->fw_data) { err = -ENOMEM; - printk(KERN_ERR "cassini: \"%s\" Failed %d\n", fw_name, err); + pr_err("\"%s\" Failed %d\n", fw_name, err); goto out; } memcpy(cp->fw_data, &fw->data[2], cp->fw_size); @@ -986,9 +983,8 @@ static void cas_phy_init(struct cas *cp) break; } if (limit <= 0) - printk(KERN_WARNING "%s: PCS reset bit would not " - "clear [%08x].\n", cp->dev->name, - readl(cp->regs + REG_PCS_STATE_MACHINE)); + netdev_warn(cp->dev, "PCS reset bit would not clear [%08x]\n", + readl(cp->regs + REG_PCS_STATE_MACHINE)); /* Make sure PCS is disabled while changing advertisement * configuration. @@ -1030,11 +1026,8 @@ static int cas_pcs_link_check(struct cas *cp) */ if ((stat & (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) == - (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) { - if (netif_msg_link(cp)) - printk(KERN_INFO "%s: PCS RemoteFault\n", - cp->dev->name); - } + (PCS_MII_STATUS_AUTONEG_COMP | PCS_MII_STATUS_REMOTE_FAULT)) + netif_info(cp, link, cp->dev, "PCS RemoteFault\n"); /* work around link detection issue by querying the PCS state * machine directly. @@ -1081,10 +1074,8 @@ static int cas_pcs_link_check(struct cas *cp) cp->link_transition = LINK_TRANSITION_ON_FAILURE; } netif_carrier_off(cp->dev); - if (cp->opened && netif_msg_link(cp)) { - printk(KERN_INFO "%s: PCS link down.\n", - cp->dev->name); - } + if (cp->opened) + netif_info(cp, link, cp->dev, "PCS link down\n"); /* Cassini only: if you force a mode, there can be * sync problems on link down. to fix that, the following @@ -1139,9 +1130,8 @@ static int cas_txmac_interrupt(struct net_device *dev, if (!txmac_stat) return 0; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: txmac interrupt, txmac_stat: 0x%x\n", - cp->dev->name, txmac_stat); + netif_printk(cp, intr, KERN_DEBUG, cp->dev, + "txmac interrupt, txmac_stat: 0x%x\n", txmac_stat); /* Defer timer expiration is quite normal, * don't even log the event. @@ -1152,14 +1142,12 @@ static int cas_txmac_interrupt(struct net_device *dev, spin_lock(&cp->stat_lock[0]); if (txmac_stat & MAC_TX_UNDERRUN) { - printk(KERN_ERR "%s: TX MAC xmit underrun.\n", - dev->name); + netdev_err(dev, "TX MAC xmit underrun\n"); cp->net_stats[0].tx_fifo_errors++; } if (txmac_stat & MAC_TX_MAX_PACKET_ERR) { - printk(KERN_ERR "%s: TX MAC max packet size error.\n", - dev->name); + netdev_err(dev, "TX MAC max packet size error\n"); cp->net_stats[0].tx_errors++; } @@ -1487,8 +1475,7 @@ static int cas_rxmac_reset(struct cas *cp) udelay(10); } if (limit == STOP_TRIES) { - printk(KERN_ERR "%s: RX MAC will not disable, resetting whole " - "chip.\n", dev->name); + netdev_err(dev, "RX MAC will not disable, resetting whole chip\n"); return 1; } @@ -1500,8 +1487,7 @@ static int cas_rxmac_reset(struct cas *cp) udelay(10); } if (limit == STOP_TRIES) { - printk(KERN_ERR "%s: RX DMA will not disable, resetting whole " - "chip.\n", dev->name); + netdev_err(dev, "RX DMA will not disable, resetting whole chip\n"); return 1; } @@ -1515,8 +1501,7 @@ static int cas_rxmac_reset(struct cas *cp) udelay(10); } if (limit == STOP_TRIES) { - printk(KERN_ERR "%s: RX reset command will not execute, " - "resetting whole chip.\n", dev->name); + netdev_err(dev, "RX reset command will not execute, resetting whole chip\n"); return 1; } @@ -1545,9 +1530,7 @@ static int cas_rxmac_interrupt(struct net_device *dev, struct cas *cp, if (!stat) return 0; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: rxmac interrupt, stat: 0x%x\n", - cp->dev->name, stat); + netif_dbg(cp, intr, cp->dev, "rxmac interrupt, stat: 0x%x\n", stat); /* these are all rollovers */ spin_lock(&cp->stat_lock[0]); @@ -1580,9 +1563,8 @@ static int cas_mac_interrupt(struct net_device *dev, struct cas *cp, if (!stat) return 0; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: mac interrupt, stat: 0x%x\n", - cp->dev->name, stat); + netif_printk(cp, intr, KERN_DEBUG, cp->dev, + "mac interrupt, stat: 0x%x\n", stat); /* This interrupt is just for pause frame and pause * tracking. It is useful for diagnostics and debug @@ -1605,9 +1587,7 @@ static inline int cas_mdio_link_not_up(struct cas *cp) switch (cp->lstate) { case link_force_ret: - if (netif_msg_link(cp)) - printk(KERN_INFO "%s: Autoneg failed again, keeping" - " forced mode\n", cp->dev->name); + netif_info(cp, link, cp->dev, "Autoneg failed again, keeping forced mode\n"); cas_phy_write(cp, MII_BMCR, cp->link_fcntl); cp->timer_ticks = 5; cp->lstate = link_force_ok; @@ -1675,9 +1655,9 @@ static int cas_mii_link_check(struct cas *cp, const u16 bmsr) cas_mif_poll(cp, 0); cp->link_fcntl = cas_phy_read(cp, MII_BMCR); cp->timer_ticks = 5; - if (cp->opened && netif_msg_link(cp)) - printk(KERN_INFO "%s: Got link after fallback, retrying" - " autoneg once...\n", cp->dev->name); + if (cp->opened) + netif_info(cp, link, cp->dev, + "Got link after fallback, retrying autoneg once...\n"); cas_phy_write(cp, MII_BMCR, cp->link_fcntl | BMCR_ANENABLE | BMCR_ANRESTART); @@ -1704,9 +1684,8 @@ static int cas_mii_link_check(struct cas *cp, const u16 bmsr) cp->link_transition = LINK_TRANSITION_LINK_DOWN; netif_carrier_off(cp->dev); - if (cp->opened && netif_msg_link(cp)) - printk(KERN_INFO "%s: Link down\n", - cp->dev->name); + if (cp->opened) + netif_info(cp, link, cp->dev, "Link down\n"); restart = 1; } else if (++cp->timer_ticks > 10) @@ -1737,23 +1716,23 @@ static int cas_pci_interrupt(struct net_device *dev, struct cas *cp, if (!stat) return 0; - printk(KERN_ERR "%s: PCI error [%04x:%04x] ", dev->name, stat, - readl(cp->regs + REG_BIM_DIAG)); + netdev_err(dev, "PCI error [%04x:%04x]", + stat, readl(cp->regs + REG_BIM_DIAG)); /* cassini+ has this reserved */ if ((stat & PCI_ERR_BADACK) && ((cp->cas_flags & CAS_FLAG_REG_PLUS) == 0)) - printk(" "); + pr_cont(" "); if (stat & PCI_ERR_DTRTO) - printk(" "); + pr_cont(" "); if (stat & PCI_ERR_OTHER) - printk(" "); + pr_cont(" "); if (stat & PCI_ERR_BIM_DMA_WRITE) - printk(" "); + pr_cont(" "); if (stat & PCI_ERR_BIM_DMA_READ) - printk(" "); - printk("\n"); + pr_cont(" "); + pr_cont("\n"); if (stat & PCI_ERR_OTHER) { u16 cfg; @@ -1762,25 +1741,19 @@ static int cas_pci_interrupt(struct net_device *dev, struct cas *cp, * true cause. */ pci_read_config_word(cp->pdev, PCI_STATUS, &cfg); - printk(KERN_ERR "%s: Read PCI cfg space status [%04x]\n", - dev->name, cfg); + netdev_err(dev, "Read PCI cfg space status [%04x]\n", cfg); if (cfg & PCI_STATUS_PARITY) - printk(KERN_ERR "%s: PCI parity error detected.\n", - dev->name); + netdev_err(dev, "PCI parity error detected\n"); if (cfg & PCI_STATUS_SIG_TARGET_ABORT) - printk(KERN_ERR "%s: PCI target abort.\n", - dev->name); + netdev_err(dev, "PCI target abort\n"); if (cfg & PCI_STATUS_REC_TARGET_ABORT) - printk(KERN_ERR "%s: PCI master acks target abort.\n", - dev->name); + netdev_err(dev, "PCI master acks target abort\n"); if (cfg & PCI_STATUS_REC_MASTER_ABORT) - printk(KERN_ERR "%s: PCI master abort.\n", dev->name); + netdev_err(dev, "PCI master abort\n"); if (cfg & PCI_STATUS_SIG_SYSTEM_ERROR) - printk(KERN_ERR "%s: PCI system error SERR#.\n", - dev->name); + netdev_err(dev, "PCI system error SERR#\n"); if (cfg & PCI_STATUS_DETECTED_PARITY) - printk(KERN_ERR "%s: PCI parity error.\n", - dev->name); + netdev_err(dev, "PCI parity error\n"); /* Write the error bits back to clear them. */ cfg &= (PCI_STATUS_PARITY | @@ -1806,9 +1779,8 @@ static int cas_abnormal_irq(struct net_device *dev, struct cas *cp, { if (status & INTR_RX_TAG_ERROR) { /* corrupt RX tag framing */ - if (netif_msg_rx_err(cp)) - printk(KERN_DEBUG "%s: corrupt rx tag framing\n", - cp->dev->name); + netif_printk(cp, rx_err, KERN_DEBUG, cp->dev, + "corrupt rx tag framing\n"); spin_lock(&cp->stat_lock[0]); cp->net_stats[0].rx_errors++; spin_unlock(&cp->stat_lock[0]); @@ -1817,9 +1789,8 @@ static int cas_abnormal_irq(struct net_device *dev, struct cas *cp, if (status & INTR_RX_LEN_MISMATCH) { /* length mismatch. */ - if (netif_msg_rx_err(cp)) - printk(KERN_DEBUG "%s: length mismatch for rx frame\n", - cp->dev->name); + netif_printk(cp, rx_err, KERN_DEBUG, cp->dev, + "length mismatch for rx frame\n"); spin_lock(&cp->stat_lock[0]); cp->net_stats[0].rx_errors++; spin_unlock(&cp->stat_lock[0]); @@ -1861,12 +1832,11 @@ do_reset: #if 1 atomic_inc(&cp->reset_task_pending); atomic_inc(&cp->reset_task_pending_all); - printk(KERN_ERR "%s:reset called in cas_abnormal_irq [0x%x]\n", - dev->name, status); + netdev_err(dev, "reset called in cas_abnormal_irq [0x%x]\n", status); schedule_work(&cp->reset_task); #else atomic_set(&cp->reset_task_pending, CAS_RESET_ALL); - printk(KERN_ERR "reset called in cas_abnormal_irq\n"); + netdev_err(dev, "reset called in cas_abnormal_irq\n"); schedule_work(&cp->reset_task); #endif return 1; @@ -1920,9 +1890,8 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit) if (count < 0) break; - if (netif_msg_tx_done(cp)) - printk(KERN_DEBUG "%s: tx[%d] done, slot %d\n", - cp->dev->name, ring, entry); + netif_printk(cp, tx_done, KERN_DEBUG, cp->dev, + "tx[%d] done, slot %d\n", ring, entry); skbs[entry] = NULL; cp->tx_tiny_use[ring][entry].nbufs = 0; @@ -1969,9 +1938,9 @@ static void cas_tx(struct net_device *dev, struct cas *cp, #ifdef USE_TX_COMPWB u64 compwb = le64_to_cpu(cp->init_block->tx_compwb); #endif - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %llx\n", - cp->dev->name, status, (unsigned long long)compwb); + netif_printk(cp, intr, KERN_DEBUG, cp->dev, + "tx interrupt, status: 0x%x, %llx\n", + status, (unsigned long long)compwb); /* process all the rings */ for (ring = 0; ring < N_TX_RINGS; ring++) { #ifdef USE_TX_COMPWB @@ -2050,10 +2019,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, hlen = min(cp->page_size - off, dlen); if (hlen < 0) { - if (netif_msg_rx_err(cp)) { - printk(KERN_DEBUG "%s: rx page overflow: " - "%d\n", cp->dev->name, hlen); - } + netif_printk(cp, rx_err, KERN_DEBUG, cp->dev, + "rx page overflow: %d\n", hlen); dev_kfree_skb_irq(skb); return -1; } @@ -2130,10 +2097,8 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, off = CAS_VAL(RX_COMP1_DATA_OFF, words[0]) + swivel; hlen = min(cp->page_size - off, dlen); if (hlen < 0) { - if (netif_msg_rx_err(cp)) { - printk(KERN_DEBUG "%s: rx page overflow: " - "%d\n", cp->dev->name, hlen); - } + netif_printk(cp, rx_err, KERN_DEBUG, cp->dev, + "rx page overflow: %d\n", hlen); dev_kfree_skb_irq(skb); return -1; } @@ -2265,9 +2230,8 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num) entry = cp->rx_old[ring]; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: rxd[%d] interrupt, done: %d\n", - cp->dev->name, ring, entry); + netif_printk(cp, intr, KERN_DEBUG, cp->dev, + "rxd[%d] interrupt, done: %d\n", ring, entry); cluster = -1; count = entry & 0x3; @@ -2337,11 +2301,10 @@ static int cas_rx_ringN(struct cas *cp, int ring, int budget) int entry, drops; int npackets = 0; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: rx[%d] interrupt, done: %d/%d\n", - cp->dev->name, ring, - readl(cp->regs + REG_RX_COMP_HEAD), - cp->rx_new[ring]); + netif_printk(cp, intr, KERN_DEBUG, cp->dev, + "rx[%d] interrupt, done: %d/%d\n", + ring, + readl(cp->regs + REG_RX_COMP_HEAD), cp->rx_new[ring]); entry = cp->rx_new[ring]; drops = 0; @@ -2442,8 +2405,7 @@ static int cas_rx_ringN(struct cas *cp, int ring, int budget) cp->rx_new[ring] = entry; if (drops) - printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", - cp->dev->name); + netdev_info(cp->dev, "Memory squeeze, deferring packet\n"); return npackets; } @@ -2457,10 +2419,9 @@ static void cas_post_rxcs_ringN(struct net_device *dev, last = cp->rx_cur[ring]; entry = cp->rx_new[ring]; - if (netif_msg_intr(cp)) - printk(KERN_DEBUG "%s: rxc[%d] interrupt, done: %d/%d\n", - dev->name, ring, readl(cp->regs + REG_RX_COMP_HEAD), - entry); + netif_printk(cp, intr, KERN_DEBUG, dev, + "rxc[%d] interrupt, done: %d/%d\n", + ring, readl(cp->regs + REG_RX_COMP_HEAD), entry); /* zero and re-mark descriptors */ while (last != entry) { @@ -2729,42 +2690,38 @@ static void cas_tx_timeout(struct net_device *dev) { struct cas *cp = netdev_priv(dev); - printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); + netdev_err(dev, "transmit timed out, resetting\n"); if (!cp->hw_running) { - printk("%s: hrm.. hw not running!\n", dev->name); + netdev_err(dev, "hrm.. hw not running!\n"); return; } - printk(KERN_ERR "%s: MIF_STATE[%08x]\n", - dev->name, readl(cp->regs + REG_MIF_STATE_MACHINE)); - - printk(KERN_ERR "%s: MAC_STATE[%08x]\n", - dev->name, readl(cp->regs + REG_MAC_STATE_MACHINE)); - - printk(KERN_ERR "%s: TX_STATE[%08x:%08x:%08x] " - "FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n", - dev->name, - readl(cp->regs + REG_TX_CFG), - readl(cp->regs + REG_MAC_TX_STATUS), - readl(cp->regs + REG_MAC_TX_CFG), - readl(cp->regs + REG_TX_FIFO_PKT_CNT), - readl(cp->regs + REG_TX_FIFO_WRITE_PTR), - readl(cp->regs + REG_TX_FIFO_READ_PTR), - readl(cp->regs + REG_TX_SM_1), - readl(cp->regs + REG_TX_SM_2)); - - printk(KERN_ERR "%s: RX_STATE[%08x:%08x:%08x]\n", - dev->name, - readl(cp->regs + REG_RX_CFG), - readl(cp->regs + REG_MAC_RX_STATUS), - readl(cp->regs + REG_MAC_RX_CFG)); - - printk(KERN_ERR "%s: HP_STATE[%08x:%08x:%08x:%08x]\n", - dev->name, - readl(cp->regs + REG_HP_STATE_MACHINE), - readl(cp->regs + REG_HP_STATUS0), - readl(cp->regs + REG_HP_STATUS1), - readl(cp->regs + REG_HP_STATUS2)); + netdev_err(dev, "MIF_STATE[%08x]\n", + readl(cp->regs + REG_MIF_STATE_MACHINE)); + + netdev_err(dev, "MAC_STATE[%08x]\n", + readl(cp->regs + REG_MAC_STATE_MACHINE)); + + netdev_err(dev, "TX_STATE[%08x:%08x:%08x] FIFO[%08x:%08x:%08x] SM1[%08x] SM2[%08x]\n", + readl(cp->regs + REG_TX_CFG), + readl(cp->regs + REG_MAC_TX_STATUS), + readl(cp->regs + REG_MAC_TX_CFG), + readl(cp->regs + REG_TX_FIFO_PKT_CNT), + readl(cp->regs + REG_TX_FIFO_WRITE_PTR), + readl(cp->regs + REG_TX_FIFO_READ_PTR), + readl(cp->regs + REG_TX_SM_1), + readl(cp->regs + REG_TX_SM_2)); + + netdev_err(dev, "RX_STATE[%08x:%08x:%08x]\n", + readl(cp->regs + REG_RX_CFG), + readl(cp->regs + REG_MAC_RX_STATUS), + readl(cp->regs + REG_MAC_RX_CFG)); + + netdev_err(dev, "HP_STATE[%08x:%08x:%08x:%08x]\n", + readl(cp->regs + REG_HP_STATE_MACHINE), + readl(cp->regs + REG_HP_STATUS0), + readl(cp->regs + REG_HP_STATUS1), + readl(cp->regs + REG_HP_STATUS2)); #if 1 atomic_inc(&cp->reset_task_pending); @@ -2830,8 +2787,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, CAS_TABORT(cp)*(skb_shinfo(skb)->nr_frags + 1)) { netif_stop_queue(dev); spin_unlock_irqrestore(&cp->tx_lock[ring], flags); - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " - "queue awake!\n", dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); return 1; } @@ -2908,11 +2864,9 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, if (TX_BUFFS_AVAIL(cp, ring) <= CAS_TABORT(cp)*(MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); - if (netif_msg_tx_queued(cp)) - printk(KERN_DEBUG "%s: tx[%d] queued, slot %d, skblen %d, " - "avail %d\n", - dev->name, ring, entry, skb->len, - TX_BUFFS_AVAIL(cp, ring)); + netif_printk(cp, tx_queued, KERN_DEBUG, dev, + "tx[%d] queued, slot %d, skblen %d, avail %d\n", + ring, entry, skb->len, TX_BUFFS_AVAIL(cp, ring)); writel(entry, cp->regs + REG_TX_KICKN(ring)); spin_unlock_irqrestore(&cp->tx_lock[ring], flags); return 0; @@ -3098,10 +3052,10 @@ static void cas_mac_reset(struct cas *cp) if (readl(cp->regs + REG_MAC_TX_RESET) | readl(cp->regs + REG_MAC_RX_RESET)) - printk(KERN_ERR "%s: mac tx[%d]/rx[%d] reset failed [%08x]\n", - cp->dev->name, readl(cp->regs + REG_MAC_TX_RESET), - readl(cp->regs + REG_MAC_RX_RESET), - readl(cp->regs + REG_MAC_STATE_MACHINE)); + netdev_err(cp->dev, "mac tx[%d]/rx[%d] reset failed [%08x]\n", + readl(cp->regs + REG_MAC_TX_RESET), + readl(cp->regs + REG_MAC_RX_RESET), + readl(cp->regs + REG_MAC_STATE_MACHINE)); } @@ -3421,7 +3375,7 @@ use_random_mac_addr: goto done; /* Sun MAC prefix then 3 random bytes. */ - printk(PFX "MAC address not found in ROM VPD\n"); + pr_info("MAC address not found in ROM VPD\n"); dev_addr[0] = 0x08; dev_addr[1] = 0x00; dev_addr[2] = 0x20; @@ -3482,7 +3436,7 @@ static int cas_check_invariants(struct cas *cp) __free_pages(page, CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT); cp->page_order = CAS_JUMBO_PAGE_SHIFT - PAGE_SHIFT; } else { - printk(PFX "MTU limited to %d bytes\n", CAS_MAX_MTU); + printk("MTU limited to %d bytes\n", CAS_MAX_MTU); } } #endif @@ -3527,7 +3481,7 @@ static int cas_check_invariants(struct cas *cp) } } } - printk(KERN_ERR PFX "MII phy did not respond [%08x]\n", + pr_err("MII phy did not respond [%08x]\n", readl(cp->regs + REG_MIF_STATE_MACHINE)); return -1; @@ -3572,21 +3526,19 @@ static inline void cas_start_dma(struct cas *cp) val = readl(cp->regs + REG_MAC_RX_CFG); if ((val & MAC_RX_CFG_EN)) { if (txfailed) { - printk(KERN_ERR - "%s: enabling mac failed [tx:%08x:%08x].\n", - cp->dev->name, - readl(cp->regs + REG_MIF_STATE_MACHINE), - readl(cp->regs + REG_MAC_STATE_MACHINE)); + netdev_err(cp->dev, + "enabling mac failed [tx:%08x:%08x]\n", + readl(cp->regs + REG_MIF_STATE_MACHINE), + readl(cp->regs + REG_MAC_STATE_MACHINE)); } goto enable_rx_done; } udelay(10); } - printk(KERN_ERR "%s: enabling mac failed [%s:%08x:%08x].\n", - cp->dev->name, - (txfailed? "tx,rx":"rx"), - readl(cp->regs + REG_MIF_STATE_MACHINE), - readl(cp->regs + REG_MAC_STATE_MACHINE)); + netdev_err(cp->dev, "enabling mac failed [%s:%08x:%08x]\n", + (txfailed ? "tx,rx" : "rx"), + readl(cp->regs + REG_MIF_STATE_MACHINE), + readl(cp->regs + REG_MAC_STATE_MACHINE)); enable_rx_done: cas_unmask_intr(cp); /* enable interrupts */ @@ -3688,9 +3640,8 @@ static void cas_set_link_modes(struct cas *cp) } } - if (netif_msg_link(cp)) - printk(KERN_INFO "%s: Link up at %d Mbps, %s-duplex.\n", - cp->dev->name, speed, (full_duplex ? "full" : "half")); + netif_info(cp, link, cp->dev, "Link up at %d Mbps, %s-duplex\n", + speed, full_duplex ? "full" : "half"); val = MAC_XIF_TX_MII_OUTPUT_EN | MAC_XIF_LINK_LED; if (CAS_PHY_MII(cp->phy_type)) { @@ -3760,18 +3711,14 @@ static void cas_set_link_modes(struct cas *cp) if (netif_msg_link(cp)) { if (pause & 0x01) { - printk(KERN_INFO "%s: Pause is enabled " - "(rxfifo: %d off: %d on: %d)\n", - cp->dev->name, - cp->rx_fifo_size, - cp->rx_pause_off, - cp->rx_pause_on); + netdev_info(cp->dev, "Pause is enabled (rxfifo: %d off: %d on: %d)\n", + cp->rx_fifo_size, + cp->rx_pause_off, + cp->rx_pause_on); } else if (pause & 0x10) { - printk(KERN_INFO "%s: TX pause enabled\n", - cp->dev->name); + netdev_info(cp->dev, "TX pause enabled\n"); } else { - printk(KERN_INFO "%s: Pause is disabled\n", - cp->dev->name); + netdev_info(cp->dev, "Pause is disabled\n"); } } @@ -3847,7 +3794,7 @@ static void cas_global_reset(struct cas *cp, int blkflag) goto done; udelay(10); } - printk(KERN_ERR "%s: sw reset failed.\n", cp->dev->name); + netdev_err(cp->dev, "sw reset failed\n"); done: /* enable various BIM interrupts */ @@ -3953,7 +3900,7 @@ static int cas_change_mtu(struct net_device *dev, int new_mtu) #else atomic_set(&cp->reset_task_pending, (cp->phy_type & CAS_PHY_SERDES) ? CAS_RESET_ALL : CAS_RESET_MTU); - printk(KERN_ERR "reset called in cas_change_mtu\n"); + pr_err("reset called in cas_change_mtu\n"); schedule_work(&cp->reset_task); #endif @@ -4235,10 +4182,8 @@ static void cas_link_timer(unsigned long data) if (((tlm == 0x5) || (tlm == 0x3)) && (CAS_VAL(MAC_SM_ENCAP_SM, val) == 0)) { - if (netif_msg_tx_err(cp)) - printk(KERN_DEBUG "%s: tx err: " - "MAC_STATE[%08x]\n", - cp->dev->name, val); + netif_printk(cp, tx_err, KERN_DEBUG, cp->dev, + "tx err: MAC_STATE[%08x]\n", val); reset = 1; goto done; } @@ -4247,10 +4192,9 @@ static void cas_link_timer(unsigned long data) wptr = readl(cp->regs + REG_TX_FIFO_WRITE_PTR); rptr = readl(cp->regs + REG_TX_FIFO_READ_PTR); if ((val == 0) && (wptr != rptr)) { - if (netif_msg_tx_err(cp)) - printk(KERN_DEBUG "%s: tx err: " - "TX_FIFO[%08x:%08x:%08x]\n", - cp->dev->name, val, wptr, rptr); + netif_printk(cp, tx_err, KERN_DEBUG, cp->dev, + "tx err: TX_FIFO[%08x:%08x:%08x]\n", + val, wptr, rptr); reset = 1; } @@ -4266,7 +4210,7 @@ done: schedule_work(&cp->reset_task); #else atomic_set(&cp->reset_task_pending, CAS_RESET_ALL); - printk(KERN_ERR "reset called in cas_link_timer\n"); + pr_err("reset called in cas_link_timer\n"); schedule_work(&cp->reset_task); #endif } @@ -4359,8 +4303,7 @@ static int cas_open(struct net_device *dev) */ if (request_irq(cp->pdev->irq, cas_interrupt, IRQF_SHARED, dev->name, (void *) dev)) { - printk(KERN_ERR "%s: failed to request irq !\n", - cp->dev->name); + netdev_err(cp->dev, "failed to request irq !\n"); err = -EAGAIN; goto err_spare; } @@ -5000,24 +4943,24 @@ static int __devinit cas_init_one(struct pci_dev *pdev, u8 orig_cacheline_size = 0, cas_cacheline_size = 0; if (cas_version_printed++ == 0) - printk(KERN_INFO "%s", version); + pr_info("%s", version); err = pci_enable_device(pdev); if (err) { - dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n"); + dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); return err; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { dev_err(&pdev->dev, "Cannot find proper PCI device " - "base address, aborting.\n"); + "base address, aborting\n"); err = -ENODEV; goto err_out_disable_pdev; } dev = alloc_etherdev(sizeof(*cp)); if (!dev) { - dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n"); + dev_err(&pdev->dev, "Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_out_disable_pdev; } @@ -5025,7 +4968,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, err = pci_request_regions(pdev, dev->name); if (err) { - dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); goto err_out_free_netdev; } pci_set_master(pdev); @@ -5039,8 +4982,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, pci_cmd |= PCI_COMMAND_PARITY; pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); if (pci_try_set_mwi(pdev)) - printk(KERN_WARNING PFX "Could not enable MWI for %s\n", - pci_name(pdev)); + pr_warning("Could not enable MWI for %s\n", pci_name(pdev)); cas_program_bridge(pdev); @@ -5083,7 +5025,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "No usable DMA configuration, " - "aborting.\n"); + "aborting\n"); goto err_out_free_res; } pci_using_dac = 0; @@ -5142,7 +5084,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, /* give us access to cassini registers */ cp->regs = pci_iomap(pdev, 0, casreg_len); if (!cp->regs) { - dev_err(&pdev->dev, "Cannot map device registers, aborting.\n"); + dev_err(&pdev->dev, "Cannot map device registers, aborting\n"); goto err_out_free_res; } cp->casreg_len = casreg_len; @@ -5161,7 +5103,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, pci_alloc_consistent(pdev, sizeof(struct cas_init_block), &cp->block_dvma); if (!cp->init_block) { - dev_err(&pdev->dev, "Cannot allocate init block, aborting.\n"); + dev_err(&pdev->dev, "Cannot allocate init block, aborting\n"); goto err_out_iounmap; } @@ -5195,18 +5137,17 @@ static int __devinit cas_init_one(struct pci_dev *pdev, dev->features |= NETIF_F_HIGHDMA; if (register_netdev(dev)) { - dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); + dev_err(&pdev->dev, "Cannot register net device, aborting\n"); goto err_out_free_consistent; } i = readl(cp->regs + REG_BIM_CFG); - printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) " - "Ethernet[%d] %pM\n", dev->name, - (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "", - (i & BIM_CFG_32BIT) ? "32" : "64", - (i & BIM_CFG_66MHZ) ? "66" : "33", - (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq, - dev->dev_addr); + netdev_info(dev, "Sun Cassini%s (%sbit/%sMHz PCI/%s) Ethernet[%d] %pM\n", + (cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "", + (i & BIM_CFG_32BIT) ? "32" : "64", + (i & BIM_CFG_66MHZ) ? "66" : "33", + (cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq, + dev->dev_addr); pci_set_drvdata(pdev, dev); cp->hw_running = 1; @@ -5320,7 +5261,7 @@ static int cas_resume(struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); struct cas *cp = netdev_priv(dev); - printk(KERN_INFO "%s: resuming\n", dev->name); + netdev_info(dev, "resuming\n"); mutex_lock(&cp->pm_mutex); cas_hard_reset(cp); -- cgit v1.2.3 From ddf79b20eefd27797ce461411679a48e998701ca Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:54 +0000 Subject: drivers/net/cnic.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Remove periods from formats Coalesce long formats Use __func__ Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/cnic.c | 87 +++++++++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 4332b3a2fafb..6aecef930fa8 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -10,6 +10,8 @@ * Modified and maintained by: Michael Chan */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include @@ -47,7 +49,6 @@ #include "cnic_defs.h" #define DRV_MODULE_NAME "cnic" -#define PFX DRV_MODULE_NAME ": " static char version[] __devinitdata = "Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n"; @@ -409,14 +410,13 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) struct cnic_dev *dev; if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) { - printk(KERN_ERR PFX "cnic_register_driver: Bad type %d\n", - ulp_type); + pr_err("%s: Bad type %d\n", __func__, ulp_type); return -EINVAL; } mutex_lock(&cnic_lock); if (cnic_ulp_tbl[ulp_type]) { - printk(KERN_ERR PFX "cnic_register_driver: Type %d has already " - "been registered\n", ulp_type); + pr_err("%s: Type %d has already been registered\n", + __func__, ulp_type); mutex_unlock(&cnic_lock); return -EBUSY; } @@ -455,15 +455,14 @@ int cnic_unregister_driver(int ulp_type) int i = 0; if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) { - printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n", - ulp_type); + pr_err("%s: Bad type %d\n", __func__, ulp_type); return -EINVAL; } mutex_lock(&cnic_lock); ulp_ops = cnic_ulp_tbl[ulp_type]; if (!ulp_ops) { - printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not " - "been registered\n", ulp_type); + pr_err("%s: Type %d has not been registered\n", + __func__, ulp_type); goto out_unlock; } read_lock(&cnic_dev_lock); @@ -471,8 +470,8 @@ int cnic_unregister_driver(int ulp_type) struct cnic_local *cp = dev->cnic_priv; if (rcu_dereference(cp->ulp_ops[ulp_type])) { - printk(KERN_ERR PFX "cnic_unregister_driver: Type %d " - "still has devices registered\n", ulp_type); + pr_err("%s: Type %d still has devices registered\n", + __func__, ulp_type); read_unlock(&cnic_dev_lock); goto out_unlock; } @@ -492,8 +491,7 @@ int cnic_unregister_driver(int ulp_type) } if (atomic_read(&ulp_ops->ref_count) != 0) - printk(KERN_WARNING PFX "%s: Failed waiting for ref count to go" - " to zero.\n", dev->netdev->name); + netdev_warn(dev->netdev, "Failed waiting for ref count to go to zero\n"); return 0; out_unlock: @@ -511,20 +509,19 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type, struct cnic_ulp_ops *ulp_ops; if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) { - printk(KERN_ERR PFX "cnic_register_device: Bad type %d\n", - ulp_type); + pr_err("%s: Bad type %d\n", __func__, ulp_type); return -EINVAL; } mutex_lock(&cnic_lock); if (cnic_ulp_tbl[ulp_type] == NULL) { - printk(KERN_ERR PFX "cnic_register_device: Driver with type %d " - "has not been registered\n", ulp_type); + pr_err("%s: Driver with type %d has not been registered\n", + __func__, ulp_type); mutex_unlock(&cnic_lock); return -EAGAIN; } if (rcu_dereference(cp->ulp_ops[ulp_type])) { - printk(KERN_ERR PFX "cnic_register_device: Type %d has already " - "been registered to this device\n", ulp_type); + pr_err("%s: Type %d has already been registered to this device\n", + __func__, ulp_type); mutex_unlock(&cnic_lock); return -EBUSY; } @@ -552,8 +549,7 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) int i = 0; if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) { - printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n", - ulp_type); + pr_err("%s: Bad type %d\n", __func__, ulp_type); return -EINVAL; } mutex_lock(&cnic_lock); @@ -561,8 +557,8 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) rcu_assign_pointer(cp->ulp_ops[ulp_type], NULL); cnic_put(dev); } else { - printk(KERN_ERR PFX "cnic_unregister_device: device not " - "registered to this ulp type %d\n", ulp_type); + pr_err("%s: device not registered to this ulp type %d\n", + __func__, ulp_type); mutex_unlock(&cnic_lock); return -EINVAL; } @@ -576,8 +572,7 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) i++; } if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type])) - printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call" - " to complete.\n", dev->netdev->name); + netdev_warn(dev->netdev, "Failed waiting for ULP up call to complete\n"); return 0; } @@ -1865,8 +1860,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[], } if (sizeof(*conn_buf) > CNIC_KWQ16_DATA_SIZE) { - printk(KERN_ERR PFX "%s: conn_buf size too big\n", - dev->netdev->name); + netdev_err(dev->netdev, "conn_buf size too big\n"); return -ENOMEM; } conn_buf = cnic_get_kwqe_16_data(cp, l5_cid, &l5_data); @@ -2026,13 +2020,13 @@ static int cnic_submit_bnx2x_kwqes(struct cnic_dev *dev, struct kwqe *wqes[], break; default: ret = 0; - printk(KERN_ERR PFX "%s: Unknown type of KWQE(0x%x)\n", - dev->netdev->name, opcode); + netdev_err(dev->netdev, "Unknown type of KWQE(0x%x)\n", + opcode); break; } if (ret < 0) - printk(KERN_ERR PFX "%s: KWQE(0x%x) failed\n", - dev->netdev->name, opcode); + netdev_err(dev->netdev, "KWQE(0x%x) failed\n", + opcode); i += work; } return 0; @@ -2074,8 +2068,8 @@ static void service_kcqes(struct cnic_dev *dev, int num_cqes) else if (kcqe_layer == KCQE_FLAGS_LAYER_MASK_L2) goto end; else { - printk(KERN_ERR PFX "%s: Unknown type of KCQE(0x%x)\n", - dev->netdev->name, kcqe_op_flag); + netdev_err(dev->netdev, "Unknown type of KCQE(0x%x)\n", + kcqe_op_flag); goto end; } @@ -3435,8 +3429,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) return 0; failed: - printk(KERN_ERR PFX "%s: " "KCQ index not resetting to 0.\n", - dev->netdev->name); + netdev_err(dev->netdev, "KCQ index not resetting to 0\n"); return -EBUSY; } @@ -3758,8 +3751,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) err = cnic_init_bnx2_irq(dev); if (err) { - printk(KERN_ERR PFX "%s: cnic_init_irq failed\n", - dev->netdev->name); + netdev_err(dev->netdev, "cnic_init_irq failed\n"); cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0); cnic_reg_wr_ind(dev, BNX2_COM_SCRATCH + 0x20, 0); return err; @@ -4122,8 +4114,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) offsetof(struct cstorm_status_block_c, index_values[HC_INDEX_C_ISCSI_EQ_CONS])); if (eq_idx != 0) { - printk(KERN_ERR PFX "%s: EQ cons index %x != 0\n", - dev->netdev->name, eq_idx); + netdev_err(dev->netdev, "EQ cons index %x != 0\n", eq_idx); return -EBUSY; } ret = cnic_init_bnx2x_irq(dev); @@ -4208,8 +4199,7 @@ static int cnic_register_netdev(struct cnic_dev *dev) err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev); if (err) - printk(KERN_ERR PFX "%s: register_cnic failed\n", - dev->netdev->name); + netdev_err(dev->netdev, "register_cnic failed\n"); return err; } @@ -4243,8 +4233,7 @@ static int cnic_start_hw(struct cnic_dev *dev) err = cp->alloc_resc(dev); if (err) { - printk(KERN_ERR PFX "%s: allocate resource failure\n", - dev->netdev->name); + netdev_err(dev->netdev, "allocate resource failure\n"); goto err1; } @@ -4326,10 +4315,9 @@ static void cnic_free_dev(struct cnic_dev *dev) i++; } if (atomic_read(&dev->ref_count) != 0) - printk(KERN_ERR PFX "%s: Failed waiting for ref count to go" - " to zero.\n", dev->netdev->name); + netdev_err(dev->netdev, "Failed waiting for ref count to go to zero\n"); - printk(KERN_INFO PFX "Removed CNIC device: %s\n", dev->netdev->name); + netdev_info(dev->netdev, "Removed CNIC device\n"); dev_put(dev->netdev); kfree(dev); } @@ -4345,8 +4333,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev, cdev = kzalloc(alloc_size , GFP_KERNEL); if (cdev == NULL) { - printk(KERN_ERR PFX "%s: allocate dev struct failure\n", - dev->name); + netdev_err(dev, "allocate dev struct failure\n"); return NULL; } @@ -4364,7 +4351,7 @@ static struct cnic_dev *cnic_alloc_dev(struct net_device *dev, spin_lock_init(&cp->cnic_ulp_lock); - printk(KERN_INFO PFX "Added CNIC device: %s\n", dev->name); + netdev_info(dev, "Added CNIC device\n"); return cdev; } @@ -4605,7 +4592,7 @@ static int __init cnic_init(void) { int rc = 0; - printk(KERN_INFO "%s", version); + pr_info("%s", version); rc = register_netdevice_notifier(&cnic_netdev_notifier); if (rc) { -- cgit v1.2.3 From 9cd31f078ee8b8dd68bbb39680b5c9a51f85f1ea Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:55 +0000 Subject: drivers/net/pci-skeleton.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ Checkpatch cleaning Convert formats like 0x%08x to %#08x Remove periods from formats Coalesce long formats Use print_hex_dump Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/pci-skeleton.c | 1019 ++++++++++++++++++++++---------------------- 1 file changed, 503 insertions(+), 516 deletions(-) diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index bbdf0398c93f..11d4398eac94 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -11,7 +11,7 @@ ---------- - Written 1997-2000 by Donald Becker. + Written 1997-2000 by Donald Becker. This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Drivers based on or derived from this @@ -85,6 +85,8 @@ IVc. Errata */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -96,16 +98,15 @@ IVc. Errata #include #include #include -#include +#include #define NETDRV_VERSION "1.0.1" #define MODNAME "netdrv" #define NETDRV_DRIVER_LOAD_MSG "MyVendor Fast Ethernet driver " NETDRV_VERSION " loaded" -#define PFX MODNAME ": " static char version[] __devinitdata = -KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" -" Support available from http://foo.com/bar/baz.html\n"; + KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" + " Support available from http://foo.com/bar/baz.html\n"; /* define to 1 to enable PIO instead of MMIO */ #undef USE_IO_OPS @@ -119,19 +120,24 @@ KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n" #ifdef NETDRV_DEBUG /* note: prints function name for you */ -# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) +#define DPRINTK(fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) #else -# define DPRINTK(fmt, args...) +#define DPRINTK(fmt, args...) \ +do { \ + if (0) \ + printk(KERN_DEBUG fmt, ##args); \ +} while (0) #endif #ifdef NETDRV_NDEBUG -# define assert(expr) do {} while (0) +#define assert(expr) do {} while (0) #else -# define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } +#define assert(expr) \ + if (!(expr)) { \ + printk("Assertion failed! %s,%s,%s,line=%d\n", \ + #expr, __FILE__, __func__, __LINE__); \ + } #endif @@ -148,10 +154,10 @@ static int multicast_filter_limit = 32; /* Size of the in-memory receive ring. */ #define RX_BUF_LEN_IDX 2 /* 0==8K, 1==16K, 2==32K, 3==64K */ -#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) -#define RX_BUF_PAD 16 +#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX) +#define RX_BUF_PAD 16 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ -#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) +#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) /* Number of Tx descriptor registers. */ #define NUM_TX_DESC 4 @@ -165,9 +171,11 @@ static int multicast_filter_limit = 32; /* PCI Tuning Parameters Threshold is bytes transferred to chip before transmission starts. */ -#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ +#define TX_FIFO_THRESH 256 /* In bytes, rounded down to 32 byte units. */ -/* The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024, 7==end of packet. */ +/* The following settings are log_2(bytes)-4: + 0==16 bytes 1==32 2==64 3==128 4==256 5==512 6==1024 7==end of packet. +*/ #define RX_FIFO_THRESH 6 /* Rx buffer level before first PCI xfer. */ #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ @@ -175,8 +183,7 @@ static int multicast_filter_limit = 32; /* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT (6*HZ) - +#define TX_TIMEOUT (6 * HZ) enum { HAS_CHIP_XCVR = 0x020000, @@ -186,7 +193,7 @@ enum { #define NETDRV_MIN_IO_SIZE 0x80 #define RTL8139B_IO_SIZE 256 -#define NETDRV_CAPS HAS_CHIP_XCVR|HAS_LNK_CHNG +#define NETDRV_CAPS (HAS_CHIP_XCVR | HAS_LNK_CHNG) typedef enum { RTL8139 = 0, @@ -220,7 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(netdrv_pci_tbl) = { {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, {0,} }; -MODULE_DEVICE_TABLE (pci, netdrv_pci_tbl); +MODULE_DEVICE_TABLE(pci, netdrv_pci_tbl); /* The rest of these values should never change. */ @@ -270,7 +277,7 @@ enum NETDRV_registers { enum ClearBitMasks { MultiIntrClear = 0xF000, ChipCmdClear = 0xE2, - Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1), + Config1Clear = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1), }; enum ChipCmdBits { @@ -329,7 +336,7 @@ enum tx_config_bits { TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ TxClearAbt = (1 << 0), /* Clear abort (WO) */ - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ + TxDMAShift = 8, /* DMA burst value(0-7) is shift this many bits */ TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ }; @@ -481,41 +488,44 @@ struct netdrv_private { chip_t chipset; }; -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("Skeleton for a PCI Fast Ethernet driver"); +MODULE_AUTHOR("Jeff Garzik "); +MODULE_DESCRIPTION("Skeleton for a PCI Fast Ethernet driver"); MODULE_LICENSE("GPL"); module_param(multicast_filter_limit, int, 0); module_param(max_interrupt_work, int, 0); module_param_array(media, int, NULL, 0); -MODULE_PARM_DESC (multicast_filter_limit, "pci-skeleton maximum number of filtered multicast addresses"); -MODULE_PARM_DESC (max_interrupt_work, "pci-skeleton maximum events handled per interrupt"); -MODULE_PARM_DESC (media, "pci-skeleton: Bits 0-3: media type, bit 17: full duplex"); - -static int read_eeprom (void *ioaddr, int location, int addr_len); -static int netdrv_open (struct net_device *dev); -static int mdio_read (struct net_device *dev, int phy_id, int location); -static void mdio_write (struct net_device *dev, int phy_id, int location, - int val); -static void netdrv_timer (unsigned long data); -static void netdrv_tx_timeout (struct net_device *dev); -static void netdrv_init_ring (struct net_device *dev); -static int netdrv_start_xmit (struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t netdrv_interrupt (int irq, void *dev_instance); -static int netdrv_close (struct net_device *dev); -static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); -static void netdrv_set_rx_mode (struct net_device *dev); -static void netdrv_hw_start (struct net_device *dev); +MODULE_PARM_DESC(multicast_filter_limit, + MODNAME " maximum number of filtered multicast addresses"); +MODULE_PARM_DESC(max_interrupt_work, + MODNAME " maximum events handled per interrupt"); +MODULE_PARM_DESC(media, + MODNAME " Bits 0-3: media type, bit 17: full duplex"); + +static int read_eeprom(void *ioaddr, int location, int addr_len); +static int netdrv_open(struct net_device *dev); +static int mdio_read(struct net_device *dev, int phy_id, int location); +static void mdio_write(struct net_device *dev, int phy_id, int location, + int val); +static void netdrv_timer(unsigned long data); +static void netdrv_tx_timeout(struct net_device *dev); +static void netdrv_init_ring(struct net_device *dev); +static int netdrv_start_xmit(struct sk_buff *skb, + struct net_device *dev); +static irqreturn_t netdrv_interrupt(int irq, void *dev_instance); +static int netdrv_close(struct net_device *dev); +static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static void netdrv_set_rx_mode(struct net_device *dev); +static void netdrv_hw_start(struct net_device *dev); #ifdef USE_IO_OPS -#define NETDRV_R8(reg) inb (((unsigned long)ioaddr) + (reg)) -#define NETDRV_R16(reg) inw (((unsigned long)ioaddr) + (reg)) -#define NETDRV_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg))) -#define NETDRV_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg)) -#define NETDRV_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg)) -#define NETDRV_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg)) +#define NETDRV_R8(reg) inb(((unsigned long)ioaddr) + (reg)) +#define NETDRV_R16(reg) inw(((unsigned long)ioaddr) + (reg)) +#define NETDRV_R32(reg) ((unsigned long)inl(((unsigned long)ioaddr) + (reg))) +#define NETDRV_W8(reg, val8) outb((val8), ((unsigned long)ioaddr) + (reg)) +#define NETDRV_W16(reg, val16) outw((val16), ((unsigned long)ioaddr) + (reg)) +#define NETDRV_W32(reg, val32) outl((val32), ((unsigned long)ioaddr) + (reg)) #define NETDRV_W8_F NETDRV_W8 #define NETDRV_W16_F NETDRV_W16 #define NETDRV_W32_F NETDRV_W32 @@ -528,25 +538,37 @@ static void netdrv_hw_start (struct net_device *dev); #define readb(addr) inb((unsigned long)(addr)) #define readw(addr) inw((unsigned long)(addr)) #define readl(addr) inl((unsigned long)(addr)) -#define writeb(val,addr) outb((val),(unsigned long)(addr)) -#define writew(val,addr) outw((val),(unsigned long)(addr)) -#define writel(val,addr) outl((val),(unsigned long)(addr)) +#define writeb(val, addr) outb((val), (unsigned long)(addr)) +#define writew(val, addr) outw((val), (unsigned long)(addr)) +#define writel(val, addr) outl((val), (unsigned long)(addr)) #else /* write MMIO register, with flush */ /* Flush avoids rtl8139 bug w/ posted MMIO writes */ -#define NETDRV_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0) -#define NETDRV_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0) -#define NETDRV_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0) +#define NETDRV_W8_F(reg, val8) \ +do { \ + writeb((val8), ioaddr + (reg)); \ + readb(ioaddr + (reg)); \ +} while (0) +#define NETDRV_W16_F(reg, val16) \ +do { \ + writew((val16), ioaddr + (reg)); \ + readw(ioaddr + (reg)); \ +} while (0) +#define NETDRV_W32_F(reg, val32) \ +do { \ + writel((val32), ioaddr + (reg)); \ + readl(ioaddr + (reg)); \ +} while (0) #ifdef MMIO_FLUSH_AUDIT_COMPLETE /* write MMIO register */ -#define NETDRV_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define NETDRV_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define NETDRV_W32(reg, val32) writel ((val32), ioaddr + (reg)) +#define NETDRV_W8(reg, val8) writeb((val8), ioaddr + (reg)) +#define NETDRV_W16(reg, val16) writew((val16), ioaddr + (reg)) +#define NETDRV_W32(reg, val32) writel((val32), ioaddr + (reg)) #else @@ -558,9 +580,9 @@ static void netdrv_hw_start (struct net_device *dev); #endif /* MMIO_FLUSH_AUDIT_COMPLETE */ /* read MMIO register */ -#define NETDRV_R8(reg) readb (ioaddr + (reg)) -#define NETDRV_R16(reg) readw (ioaddr + (reg)) -#define NETDRV_R32(reg) ((unsigned long) readl (ioaddr + (reg))) +#define NETDRV_R8(reg) readb(ioaddr + (reg)) +#define NETDRV_R16(reg) readw(ioaddr + (reg)) +#define NETDRV_R32(reg) ((unsigned long) readl(ioaddr + (reg))) #endif /* USE_IO_OPS */ @@ -570,14 +592,14 @@ static const u16 netdrv_intr_mask = TxErr | TxOK | RxErr | RxOK; static const unsigned int netdrv_rx_config = - RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap | - (RX_FIFO_THRESH << RxCfgFIFOShift) | - (RX_DMA_BURST << RxCfgDMAShift); + RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap | + (RX_FIFO_THRESH << RxCfgFIFOShift) | + (RX_DMA_BURST << RxCfgDMAShift); -static int __devinit netdrv_init_board (struct pci_dev *pdev, - struct net_device **dev_out, - void **ioaddr_out) +static int __devinit netdrv_init_board(struct pci_dev *pdev, + struct net_device **dev_out, + void **ioaddr_out) { void *ioaddr = NULL; struct net_device *dev; @@ -587,43 +609,43 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev, unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; u32 tmp; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - assert (pdev != NULL); - assert (ioaddr_out != NULL); + assert(pdev != NULL); + assert(ioaddr_out != NULL); *ioaddr_out = NULL; *dev_out = NULL; /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev (sizeof (*tp)); + dev = alloc_etherdev(sizeof(*tp)); if (dev == NULL) { dev_err(&pdev->dev, "unable to alloc new ethernet\n"); - DPRINTK ("EXIT, returning -ENOMEM\n"); + DPRINTK("EXIT, returning -ENOMEM\n"); return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); - /* enable device (incl. PCI PM wakeup), and bus-mastering */ - rc = pci_enable_device (pdev); + /* enable device(incl. PCI PM wakeup), and bus-mastering */ + rc = pci_enable_device(pdev); if (rc) goto err_out; - pio_start = pci_resource_start (pdev, 0); - pio_end = pci_resource_end (pdev, 0); - pio_flags = pci_resource_flags (pdev, 0); - pio_len = pci_resource_len (pdev, 0); + pio_start = pci_resource_start(pdev, 0); + pio_end = pci_resource_end(pdev, 0); + pio_flags = pci_resource_flags(pdev, 0); + pio_len = pci_resource_len(pdev, 0); - mmio_start = pci_resource_start (pdev, 1); - mmio_end = pci_resource_end (pdev, 1); - mmio_flags = pci_resource_flags (pdev, 1); - mmio_len = pci_resource_len (pdev, 1); + mmio_start = pci_resource_start(pdev, 1); + mmio_end = pci_resource_end(pdev, 1); + mmio_flags = pci_resource_flags(pdev, 1); + mmio_len = pci_resource_len(pdev, 1); /* set this immediately, we need to know before * we talk to the chip directly */ - DPRINTK("PIO region size == 0x%02X\n", pio_len); - DPRINTK("MMIO region size == 0x%02lX\n", mmio_len); + DPRINTK("PIO region size == %#02X\n", pio_len); + DPRINTK("MMIO region size == %#02lX\n", mmio_len); /* make sure PCI base addr 0 is PIO */ if (!(pio_flags & IORESOURCE_IO)) { @@ -647,17 +669,17 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev, goto err_out; } - rc = pci_request_regions (pdev, MODNAME); + rc = pci_request_regions(pdev, MODNAME); if (rc) goto err_out; - pci_set_master (pdev); + pci_set_master(pdev); #ifdef USE_IO_OPS - ioaddr = (void *) pio_start; + ioaddr = (void *)pio_start; #else /* ioremap MMIO region */ - ioaddr = ioremap (mmio_start, mmio_len); + ioaddr = ioremap(mmio_start, mmio_len); if (ioaddr == NULL) { dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); rc = -EIO; @@ -666,52 +688,50 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev, #endif /* USE_IO_OPS */ /* Soft reset the chip. */ - NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | CmdReset); + NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset); /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) - if ((NETDRV_R8 (ChipCmd) & CmdReset) == 0) + if ((NETDRV_R8(ChipCmd) & CmdReset) == 0) break; else - udelay (10); + udelay(10); /* Bring the chip out of low-power mode. */ /* */ #ifndef USE_IO_OPS /* sanity checks -- ensure PIO and MMIO registers agree */ - assert (inb (pio_start+Config0) == readb (ioaddr+Config0)); - assert (inb (pio_start+Config1) == readb (ioaddr+Config1)); - assert (inb (pio_start+TxConfig) == readb (ioaddr+TxConfig)); - assert (inb (pio_start+RxConfig) == readb (ioaddr+RxConfig)); + assert(inb(pio_start+Config0) == readb(ioaddr+Config0)); + assert(inb(pio_start+Config1) == readb(ioaddr+Config1)); + assert(inb(pio_start+TxConfig) == readb(ioaddr+TxConfig)); + assert(inb(pio_start+RxConfig) == readb(ioaddr+RxConfig)); #endif /* !USE_IO_OPS */ /* identify chip attached to board */ - tmp = NETDRV_R8 (ChipVersion); - for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--) + tmp = NETDRV_R8(ChipVersion); + for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) if (tmp == rtl_chip_info[i].version) { tp->chipset = i; goto match; } /* if unknown chip, assume array element #0, original RTL-8139 in this case */ - dev_printk (KERN_DEBUG, &pdev->dev, - "unknown chip version, assuming RTL-8139\n"); - dev_printk (KERN_DEBUG, &pdev->dev, "TxConfig = 0x%lx\n", - NETDRV_R32 (TxConfig)); + dev_printk(KERN_DEBUG, &pdev->dev, + "unknown chip version, assuming RTL-8139\n"); + dev_printk(KERN_DEBUG, &pdev->dev, "TxConfig = %#lx\n", + NETDRV_R32(TxConfig)); tp->chipset = 0; match: - DPRINTK ("chipset id (%d) == index %d, '%s'\n", - tmp, - tp->chipset, - rtl_chip_info[tp->chipset].name); + DPRINTK("chipset id(%d) == index %d, '%s'\n", + tmp, tp->chipset, rtl_chip_info[tp->chipset].name); - rc = register_netdev (dev); + rc = register_netdev(dev); if (rc) goto err_out_unmap; - DPRINTK ("EXIT, returning 0\n"); + DPRINTK("EXIT, returning 0\n"); *ioaddr_out = ioaddr; *dev_out = dev; return 0; @@ -721,10 +741,10 @@ err_out_unmap: iounmap(ioaddr); err_out_free_res: #endif - pci_release_regions (pdev); + pci_release_regions(pdev); err_out: - free_netdev (dev); - DPRINTK ("EXIT, returning %d\n", rc); + free_netdev(dev); + DPRINTK("EXIT, returning %d\n", rc); return rc; } @@ -740,8 +760,8 @@ static const struct net_device_ops netdrv_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, }; -static int __devinit netdrv_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit netdrv_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct net_device *dev = NULL; struct netdrv_private *tp; @@ -756,29 +776,29 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, printk(version); #endif - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - assert (pdev != NULL); - assert (ent != NULL); + assert(pdev != NULL); + assert(ent != NULL); board_idx++; - i = netdrv_init_board (pdev, &dev, &ioaddr); + i = netdrv_init_board(pdev, &dev, &ioaddr); if (i < 0) { - DPRINTK ("EXIT, returning %d\n", i); + DPRINTK("EXIT, returning %d\n", i); return i; } tp = netdev_priv(dev); - assert (ioaddr != NULL); - assert (dev != NULL); - assert (tp != NULL); + assert(ioaddr != NULL); + assert(dev != NULL); + assert(tp != NULL); - addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6; + addr_len = read_eeprom(ioaddr, 0, 8) == 0x8129 ? 8 : 6; for (i = 0; i < 3; i++) - ((u16 *) (dev->dev_addr))[i] = - le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len)); + ((u16 *)(dev->dev_addr))[i] = + le16_to_cpu(read_eeprom(ioaddr, i + 7, addr_len)); dev->netdev_ops = &netdrv_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; @@ -791,7 +811,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, /* note: tp->chipset set in netdrv_init_board */ tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | NETDRV_CAPS; + PCI_COMMAND_MASTER | NETDRV_CAPS; tp->pci_dev = pdev; tp->board = ent->driver_data; tp->mmio_addr = ioaddr; @@ -801,18 +821,15 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, tp->phys[0] = 32; - printk (KERN_INFO "%s: %s at 0x%lx, %pM IRQ %d\n", - dev->name, - board_info[ent->driver_data].name, - dev->base_addr, - dev->dev_addr, - dev->irq); + netdev_info(dev, "%s at %#lx, %pM IRQ %d\n", + board_info[ent->driver_data].name, + dev->base_addr, dev->dev_addr, dev->irq); - printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n", - dev->name, rtl_chip_info[tp->chipset].name); + netdev_printk(KERN_DEBUG, dev, "Identified 8139 chip type '%s'\n", + rtl_chip_info[tp->chipset].name); /* Put the chip into low-power mode. */ - NETDRV_W8_F (Cfg9346, Cfg9346_Unlock); + NETDRV_W8_F(Cfg9346, Cfg9346_Unlock); /* The lower four bits are the media type. */ option = (board_idx > 7) ? 0 : media[board_idx]; @@ -824,45 +841,43 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev, } if (tp->full_duplex) { - printk (KERN_INFO - "%s: Media type forced to Full Duplex.\n", - dev->name); - mdio_write (dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL); + netdev_info(dev, "Media type forced to Full Duplex\n"); + mdio_write(dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL); tp->duplex_lock = 1; } - DPRINTK ("EXIT - returning 0\n"); + DPRINTK("EXIT - returning 0\n"); return 0; } -static void __devexit netdrv_remove_one (struct pci_dev *pdev) +static void __devexit netdrv_remove_one(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata (pdev); + struct net_device *dev = pci_get_drvdata(pdev); struct netdrv_private *np; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - assert (dev != NULL); + assert(dev != NULL); np = netdev_priv(dev); - assert (np != NULL); + assert(np != NULL); - unregister_netdev (dev); + unregister_netdev(dev); #ifndef USE_IO_OPS - iounmap (np->mmio_addr); + iounmap(np->mmio_addr); #endif /* !USE_IO_OPS */ - pci_release_regions (pdev); + pci_release_regions(pdev); - free_netdev (dev); + free_netdev(dev); - pci_set_drvdata (pdev, NULL); + pci_set_drvdata(pdev, NULL); - pci_disable_device (pdev); + pci_disable_device(pdev); - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } @@ -870,63 +885,63 @@ static void __devexit netdrv_remove_one (struct pci_dev *pdev) /* EEPROM_Ctrl bits. */ #define EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */ -#define EE_CS 0x08 /* EEPROM chip select. */ +#define EE_CS 0x08 /* EEPROM chip select. */ #define EE_DATA_WRITE 0x02 /* EEPROM chip data in. */ -#define EE_WRITE_0 0x00 -#define EE_WRITE_1 0x02 +#define EE_WRITE_0 0x00 +#define EE_WRITE_1 0x02 #define EE_DATA_READ 0x01 /* EEPROM chip data out. */ -#define EE_ENB (0x80 | EE_CS) +#define EE_ENB (0x80 | EE_CS) /* Delay between EEPROM clock transitions. No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. - */ +*/ #define eeprom_delay() readl(ee_addr) /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5) -#define EE_READ_CMD (6) +#define EE_READ_CMD (6) #define EE_ERASE_CMD (7) -static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) +static int __devinit read_eeprom(void *ioaddr, int location, int addr_len) { int i; unsigned retval = 0; void *ee_addr = ioaddr + Cfg9346; int read_cmd = location | (EE_READ_CMD << addr_len); - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - writeb (EE_ENB & ~EE_CS, ee_addr); - writeb (EE_ENB, ee_addr); - eeprom_delay (); + writeb(EE_ENB & ~EE_CS, ee_addr); + writeb(EE_ENB, ee_addr); + eeprom_delay(); /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - writeb (EE_ENB | dataval, ee_addr); - eeprom_delay (); - writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay (); + writeb(EE_ENB | dataval, ee_addr); + eeprom_delay(); + writeb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); } - writeb (EE_ENB, ee_addr); - eeprom_delay (); + writeb(EE_ENB, ee_addr); + eeprom_delay(); for (i = 16; i > 0; i--) { - writeb (EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay (); + writeb(EE_ENB | EE_SHIFT_CLK, ee_addr); + eeprom_delay(); retval = - (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : - 0); - writeb (EE_ENB, ee_addr); - eeprom_delay (); + (retval << 1) | ((readb(ee_addr) & EE_DATA_READ) ? 1 : + 0); + writeb(EE_ENB, ee_addr); + eeprom_delay(); } /* Terminate the EEPROM access. */ - writeb (~EE_CS, ee_addr); - eeprom_delay (); + writeb(~EE_CS, ee_addr); + eeprom_delay(); - DPRINTK ("EXIT - returning %d\n", retval); + DPRINTK("EXIT - returning %d\n", retval); return retval; } @@ -936,12 +951,12 @@ static int __devinit read_eeprom (void *ioaddr, int location, int addr_len) The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back PCI I/O cycles, but we insert a delay to avoid "overclocking" issues. */ -#define MDIO_DIR 0x80 +#define MDIO_DIR 0x80 #define MDIO_DATA_OUT 0x04 #define MDIO_DATA_IN 0x02 -#define MDIO_CLK 0x01 -#define MDIO_WRITE0 (MDIO_DIR) -#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) +#define MDIO_CLK 0x01 +#define MDIO_WRITE0 (MDIO_DIR) +#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT) #define mdio_delay() readb(mdio_addr) @@ -959,24 +974,24 @@ static char mii_2_8139_map[8] = { /* Syncronize the MII management interface by shifting 32 one bits out. */ -static void mdio_sync (void *mdio_addr) +static void mdio_sync(void *mdio_addr) { int i; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); for (i = 32; i >= 0; i--) { - writeb (MDIO_WRITE1, mdio_addr); - mdio_delay (); - writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr); - mdio_delay (); + writeb(MDIO_WRITE1, mdio_addr); + mdio_delay(); + writeb(MDIO_WRITE1 | MDIO_CLK, mdio_addr); + mdio_delay(); } - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } -static int mdio_read (struct net_device *dev, int phy_id, int location) +static int mdio_read(struct net_device *dev, int phy_id, int location) { struct netdrv_private *tp = netdev_priv(dev); void *mdio_addr = tp->mmio_addr + Config4; @@ -984,97 +999,94 @@ static int mdio_read (struct net_device *dev, int phy_id, int location) int retval = 0; int i; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); if (phy_id > 31) { /* Really a 8139. Use internal registers. */ - DPRINTK ("EXIT after directly using 8139 internal regs\n"); + DPRINTK("EXIT after directly using 8139 internal regs\n"); return location < 8 && mii_2_8139_map[location] ? - readw (tp->mmio_addr + mii_2_8139_map[location]) : 0; + readw(tp->mmio_addr + mii_2_8139_map[location]) : 0; } - mdio_sync (mdio_addr); + mdio_sync(mdio_addr); /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0; - writeb (MDIO_DIR | dataval, mdio_addr); - mdio_delay (); - writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr); - mdio_delay (); + writeb(MDIO_DIR | dataval, mdio_addr); + mdio_delay(); + writeb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr); + mdio_delay(); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (); - retval = - (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 - : 0); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (); + writeb(0, mdio_addr); + mdio_delay(); + retval = ((retval << 1) | ((readb(mdio_addr) & MDIO_DATA_IN)) + ? 1 : 0); + writeb(MDIO_CLK, mdio_addr); + mdio_delay(); } - DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff); + DPRINTK("EXIT, returning %d\n", (retval >> 1) & 0xffff); return (retval >> 1) & 0xffff; } -static void mdio_write (struct net_device *dev, int phy_id, int location, - int value) +static void mdio_write(struct net_device *dev, int phy_id, int location, + int value) { struct netdrv_private *tp = netdev_priv(dev); void *mdio_addr = tp->mmio_addr + Config4; int mii_cmd = - (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; + (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; int i; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); if (phy_id > 31) { /* Really a 8139. Use internal registers. */ if (location < 8 && mii_2_8139_map[location]) { - writew (value, - tp->mmio_addr + mii_2_8139_map[location]); - readw (tp->mmio_addr + mii_2_8139_map[location]); + writew(value, + tp->mmio_addr + mii_2_8139_map[location]); + readw(tp->mmio_addr + mii_2_8139_map[location]); } - DPRINTK ("EXIT after directly using 8139 internal regs\n"); + DPRINTK("EXIT after directly using 8139 internal regs\n"); return; } - mdio_sync (mdio_addr); + mdio_sync(mdio_addr); /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = - (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writeb (dataval, mdio_addr); - mdio_delay (); - writeb (dataval | MDIO_CLK, mdio_addr); - mdio_delay (); + (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; + writeb(dataval, mdio_addr); + mdio_delay(); + writeb(dataval | MDIO_CLK, mdio_addr); + mdio_delay(); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - writeb (0, mdio_addr); - mdio_delay (); - writeb (MDIO_CLK, mdio_addr); - mdio_delay (); + writeb(0, mdio_addr); + mdio_delay(); + writeb(MDIO_CLK, mdio_addr); + mdio_delay(); } - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } -static int netdrv_open (struct net_device *dev) +static int netdrv_open(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); int retval; -#ifdef NETDRV_DEBUG void *ioaddr = tp->mmio_addr; -#endif - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - retval = request_irq (dev->irq, netdrv_interrupt, IRQF_SHARED, dev->name, dev); + retval = request_irq(dev->irq, netdrv_interrupt, IRQF_SHARED, dev->name, dev); if (retval) { - DPRINTK ("EXIT, returning %d\n", retval); + DPRINTK("EXIT, returning %d\n", retval); return retval; } @@ -1092,7 +1104,7 @@ static int netdrv_open (struct net_device *dev) pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, tp->rx_ring, tp->rx_ring_dma); - DPRINTK ("EXIT, returning -ENOMEM\n"); + DPRINTK("EXIT, returning -ENOMEM\n"); return -ENOMEM; } @@ -1100,109 +1112,108 @@ static int netdrv_open (struct net_device *dev) tp->full_duplex = tp->duplex_lock; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; - netdrv_init_ring (dev); - netdrv_hw_start (dev); + netdrv_init_ring(dev); + netdrv_hw_start(dev); - DPRINTK ("%s: netdrv_open() ioaddr %#lx IRQ %d" - " GP Pins %2.2x %s-duplex.\n", - dev->name, pci_resource_start (tp->pci_dev, 1), - dev->irq, NETDRV_R8 (MediaStatus), - tp->full_duplex ? "full" : "half"); + netdev_dbg(dev, "ioaddr %#llx IRQ %d GP Pins %02x %s-duplex\n", + (unsigned long long)pci_resource_start(tp->pci_dev, 1), + dev->irq, NETDRV_R8(MediaStatus), + tp->full_duplex ? "full" : "half"); /* Set the timer to switch to check for link beat and perhaps switch to an alternate media type. */ - init_timer (&tp->timer); + init_timer(&tp->timer); tp->timer.expires = jiffies + 3 * HZ; tp->timer.data = (unsigned long) dev; tp->timer.function = &netdrv_timer; - add_timer (&tp->timer); + add_timer(&tp->timer); - DPRINTK ("EXIT, returning 0\n"); + DPRINTK("EXIT, returning 0\n"); return 0; } /* Start the hardware at open or resume. */ -static void netdrv_hw_start (struct net_device *dev) +static void netdrv_hw_start(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); /* Soft reset the chip. */ - NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | CmdReset); - udelay (100); + NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | CmdReset); + udelay(100); /* Check that the chip has finished the reset. */ for (i = 1000; i > 0; i--) - if ((NETDRV_R8 (ChipCmd) & CmdReset) == 0) + if ((NETDRV_R8(ChipCmd) & CmdReset) == 0) break; /* Restore our idea of the MAC address. */ - NETDRV_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0))); - NETDRV_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4))); + NETDRV_W32_F(MAC0 + 0, cpu_to_le32(*(u32 *)(dev->dev_addr + 0))); + NETDRV_W32_F(MAC0 + 4, cpu_to_le32(*(u32 *)(dev->dev_addr + 4))); /* Must enable Tx/Rx before setting transfer thresholds! */ - NETDRV_W8_F (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | - CmdRxEnb | CmdTxEnb); + NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | + CmdRxEnb | CmdTxEnb); i = netdrv_rx_config | - (NETDRV_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - NETDRV_W32_F (RxConfig, i); + (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + NETDRV_W32_F(RxConfig, i); /* Check this value: the documentation for IFG contradicts ifself. */ - NETDRV_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift)); + NETDRV_W32(TxConfig, (TX_DMA_BURST << TxDMAShift)); /* unlock Config[01234] and BMCR register writes */ - NETDRV_W8_F (Cfg9346, Cfg9346_Unlock); - udelay (10); + NETDRV_W8_F(Cfg9346, Cfg9346_Unlock); + udelay(10); tp->cur_rx = 0; /* Lock Config[01234] and BMCR register writes */ - NETDRV_W8_F (Cfg9346, Cfg9346_Lock); - udelay (10); + NETDRV_W8_F(Cfg9346, Cfg9346_Lock); + udelay(10); /* init Rx ring buffer DMA address */ - NETDRV_W32_F (RxBuf, tp->rx_ring_dma); + NETDRV_W32_F(RxBuf, tp->rx_ring_dma); /* init Tx buffer DMA addresses */ for (i = 0; i < NUM_TX_DESC; i++) - NETDRV_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); + NETDRV_W32_F(TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs)); - NETDRV_W32_F (RxMissed, 0); + NETDRV_W32_F(RxMissed, 0); - netdrv_set_rx_mode (dev); + netdrv_set_rx_mode(dev); /* no early-rx interrupts */ - NETDRV_W16 (MultiIntr, NETDRV_R16 (MultiIntr) & MultiIntrClear); + NETDRV_W16(MultiIntr, NETDRV_R16(MultiIntr) & MultiIntrClear); /* make sure RxTx has started */ - NETDRV_W8_F (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | - CmdRxEnb | CmdTxEnb); + NETDRV_W8_F(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear) | + CmdRxEnb | CmdTxEnb); /* Enable all known interrupts by setting the interrupt mask. */ - NETDRV_W16_F (IntrMask, netdrv_intr_mask); + NETDRV_W16_F(IntrMask, netdrv_intr_mask); - netif_start_queue (dev); + netif_start_queue(dev); - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ -static void netdrv_init_ring (struct net_device *dev) +static void netdrv_init_ring(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); int i; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); tp->cur_rx = 0; - atomic_set (&tp->cur_tx, 0); - atomic_set (&tp->dirty_tx, 0); + atomic_set(&tp->cur_tx, 0); + atomic_set(&tp->dirty_tx, 0); for (i = 0; i < NUM_TX_DESC; i++) { tp->tx_info[i].skb = NULL; @@ -1210,11 +1221,11 @@ static void netdrv_init_ring (struct net_device *dev) tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE]; } - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } -static void netdrv_timer (unsigned long data) +static void netdrv_timer(unsigned long data) { struct net_device *dev = (struct net_device *) data; struct netdrv_private *tp = netdev_priv(dev); @@ -1222,58 +1233,54 @@ static void netdrv_timer (unsigned long data) int next_tick = 60 * HZ; int mii_lpa; - mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA); + mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA); if (!tp->duplex_lock && mii_lpa != 0xffff) { int duplex = ((mii_lpa & LPA_100FULL) || - (mii_lpa & 0x01C0) == 0x0040); + (mii_lpa & 0x01C0) == 0x0040); if (tp->full_duplex != duplex) { tp->full_duplex = duplex; - printk (KERN_INFO - "%s: Setting %s-duplex based on MII #%d link" - " partner ability of %4.4x.\n", dev->name, - tp->full_duplex ? "full" : "half", - tp->phys[0], mii_lpa); - NETDRV_W8 (Cfg9346, Cfg9346_Unlock); - NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); - NETDRV_W8 (Cfg9346, Cfg9346_Lock); + netdev_info(dev, "Setting %s-duplex based on MII #%d link partner ability of %04x\n", + tp->full_duplex ? "full" : "half", + tp->phys[0], mii_lpa); + NETDRV_W8(Cfg9346, Cfg9346_Unlock); + NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20); + NETDRV_W8(Cfg9346, Cfg9346_Lock); } } - DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", - dev->name, NETDRV_R16 (NWayLPAR)); - DPRINTK ("%s: Other registers are IntMask %4.4x IntStatus %4.4x" - " RxStatus %4.4x.\n", dev->name, - NETDRV_R16 (IntrMask), - NETDRV_R16 (IntrStatus), - NETDRV_R32 (RxEarlyStatus)); - DPRINTK ("%s: Chip config %2.2x %2.2x.\n", - dev->name, NETDRV_R8 (Config0), - NETDRV_R8 (Config1)); + netdev_dbg(dev, "Media selection tick, Link partner %04x\n", + NETDRV_R16(NWayLPAR)); + netdev_dbg(dev, "Other registers are IntMask %04x IntStatus %04x RxStatus %04lx\n", + NETDRV_R16(IntrMask), + NETDRV_R16(IntrStatus), + NETDRV_R32(RxEarlyStatus)); + netdev_dbg(dev, "Chip config %02x %02x\n", + NETDRV_R8(Config0), NETDRV_R8(Config1)); tp->timer.expires = jiffies + next_tick; - add_timer (&tp->timer); + add_timer(&tp->timer); } -static void netdrv_tx_clear (struct net_device *dev) +static void netdrv_tx_clear(struct net_device *dev) { int i; struct netdrv_private *tp = netdev_priv(dev); - atomic_set (&tp->cur_tx, 0); - atomic_set (&tp->dirty_tx, 0); + atomic_set(&tp->cur_tx, 0); + atomic_set(&tp->dirty_tx, 0); /* Dump the unsent Tx packets. */ for (i = 0; i < NUM_TX_DESC; i++) { struct ring_info *rp = &tp->tx_info[i]; if (rp->mapping != 0) { - pci_unmap_single (tp->pci_dev, rp->mapping, - rp->skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(tp->pci_dev, rp->mapping, + rp->skb->len, PCI_DMA_TODEVICE); rp->mapping = 0; } if (rp->skb) { - dev_kfree_skb (rp->skb); + dev_kfree_skb(rp->skb); rp->skb = NULL; dev->stats.tx_dropped++; } @@ -1281,7 +1288,7 @@ static void netdrv_tx_clear (struct net_device *dev) } -static void netdrv_tx_timeout (struct net_device *dev) +static void netdrv_tx_timeout(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; @@ -1289,96 +1296,95 @@ static void netdrv_tx_timeout (struct net_device *dev) u8 tmp8; unsigned long flags; - DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " - "media %2.2x.\n", dev->name, - NETDRV_R8 (ChipCmd), - NETDRV_R16 (IntrStatus), - NETDRV_R8 (MediaStatus)); + netdev_dbg(dev, "Transmit timeout, status %02x %04x media %02x\n", + NETDRV_R8(ChipCmd), + NETDRV_R16(IntrStatus), + NETDRV_R8(MediaStatus)); /* disable Tx ASAP, if not already */ - tmp8 = NETDRV_R8 (ChipCmd); + tmp8 = NETDRV_R8(ChipCmd); if (tmp8 & CmdTxEnb) - NETDRV_W8 (ChipCmd, tmp8 & ~CmdTxEnb); + NETDRV_W8(ChipCmd, tmp8 & ~CmdTxEnb); /* Disable interrupts by clearing the interrupt mask. */ - NETDRV_W16 (IntrMask, 0x0000); + NETDRV_W16(IntrMask, 0x0000); /* Emit info to figure out what went wrong. */ - printk (KERN_DEBUG "%s: Tx queue start entry %d dirty entry %d.\n", - dev->name, atomic_read (&tp->cur_tx), - atomic_read (&tp->dirty_tx)); + netdev_dbg(dev, "Tx queue start entry %d dirty entry %d\n", + atomic_read(&tp->cur_tx), + atomic_read(&tp->dirty_tx)); for (i = 0; i < NUM_TX_DESC; i++) - printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", - dev->name, i, NETDRV_R32 (TxStatus0 + (i * 4)), - i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ? - " (queue head)" : ""); + netdev_dbg(dev, "Tx descriptor %d is %08lx%s\n", + i, NETDRV_R32(TxStatus0 + (i * 4)), + i == atomic_read(&tp->dirty_tx) % NUM_TX_DESC ? + "(queue head)" : ""); /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irqsave(&tp->lock, flags); - netdrv_tx_clear (dev); + netdrv_tx_clear(dev); - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irqrestore(&tp->lock, flags); /* ...and finally, reset everything */ - netdrv_hw_start (dev); + netdrv_hw_start(dev); - netif_wake_queue (dev); + netif_wake_queue(dev); } -static int netdrv_start_xmit (struct sk_buff *skb, struct net_device *dev) +static int netdrv_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; int entry; /* Calculate the next Tx descriptor entry. */ - entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC; + entry = atomic_read(&tp->cur_tx) % NUM_TX_DESC; - assert (tp->tx_info[entry].skb == NULL); - assert (tp->tx_info[entry].mapping == 0); + assert(tp->tx_info[entry].skb == NULL); + assert(tp->tx_info[entry].mapping == 0); tp->tx_info[entry].skb = skb; /* tp->tx_info[entry].mapping = 0; */ skb_copy_from_linear_data(skb, tp->tx_buf[entry], skb->len); /* Note: the chip doesn't have auto-pad! */ - NETDRV_W32 (TxStatus0 + (entry * sizeof(u32)), - tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + NETDRV_W32(TxStatus0 + (entry * sizeof(u32)), + tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); dev->trans_start = jiffies; - atomic_inc (&tp->cur_tx); - if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC) - netif_stop_queue (dev); + atomic_inc(&tp->cur_tx); + if ((atomic_read(&tp->cur_tx) - atomic_read(&tp->dirty_tx)) >= NUM_TX_DESC) + netif_stop_queue(dev); - DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n", - dev->name, skb->data, skb->len, entry); + netdev_dbg(dev, "Queued Tx packet at %p size %u to slot %d\n", + skb->data, skb->len, entry); return NETDEV_TX_OK; } -static void netdrv_tx_interrupt (struct net_device *dev, - struct netdrv_private *tp, - void *ioaddr) +static void netdrv_tx_interrupt(struct net_device *dev, + struct netdrv_private *tp, + void *ioaddr) { int cur_tx, dirty_tx, tx_left; - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); + assert(dev != NULL); + assert(tp != NULL); + assert(ioaddr != NULL); - dirty_tx = atomic_read (&tp->dirty_tx); + dirty_tx = atomic_read(&tp->dirty_tx); - cur_tx = atomic_read (&tp->cur_tx); + cur_tx = atomic_read(&tp->cur_tx); tx_left = cur_tx - dirty_tx; while (tx_left > 0) { int entry = dirty_tx % NUM_TX_DESC; int txstatus; - txstatus = NETDRV_R32 (TxStatus0 + (entry * sizeof (u32))); + txstatus = NETDRV_R32(TxStatus0 + (entry * sizeof(u32))); if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted))) break; /* It still hasn't been Txed */ @@ -1386,12 +1392,12 @@ static void netdrv_tx_interrupt (struct net_device *dev, /* Note: TxCarrierLost is always asserted at 100mbps. */ if (txstatus & (TxOutOfWindow | TxAborted)) { /* There was an major error, log it. */ - DPRINTK ("%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); + netdev_dbg(dev, "Transmit error, Tx status %#08x\n", + txstatus); dev->stats.tx_errors++; if (txstatus & TxAborted) { dev->stats.tx_aborted_errors++; - NETDRV_W32 (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift)); + NETDRV_W32(TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift)); } if (txstatus & TxCarrierLost) dev->stats.tx_carrier_errors++; @@ -1417,48 +1423,45 @@ static void netdrv_tx_interrupt (struct net_device *dev, PCI_DMA_TODEVICE); tp->tx_info[entry].mapping = 0; } - dev_kfree_skb_irq (tp->tx_info[entry].skb); + dev_kfree_skb_irq(tp->tx_info[entry].skb); tp->tx_info[entry].skb = NULL; dirty_tx++; if (dirty_tx < 0) { /* handle signed int overflow */ - atomic_sub (cur_tx, &tp->cur_tx); /* XXX racy? */ + atomic_sub(cur_tx, &tp->cur_tx); /* XXX racy? */ dirty_tx = cur_tx - tx_left + 1; } - if (netif_queue_stopped (dev)) - netif_wake_queue (dev); + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); - cur_tx = atomic_read (&tp->cur_tx); + cur_tx = atomic_read(&tp->cur_tx); tx_left = cur_tx - dirty_tx; } #ifndef NETDRV_NDEBUG - if (atomic_read (&tp->cur_tx) - dirty_tx > NUM_TX_DESC) { - printk (KERN_ERR - "%s: Out-of-sync dirty pointer, %d vs. %d.\n", - dev->name, dirty_tx, atomic_read (&tp->cur_tx)); + if (atomic_read(&tp->cur_tx) - dirty_tx > NUM_TX_DESC) { + netdev_err(dev, "Out-of-sync dirty pointer, %d vs. %d\n", + dirty_tx, atomic_read(&tp->cur_tx)); dirty_tx += NUM_TX_DESC; } #endif /* NETDRV_NDEBUG */ - atomic_set (&tp->dirty_tx, dirty_tx); + atomic_set(&tp->dirty_tx, dirty_tx); } /* TODO: clean this up! Rx reset need not be this intensive */ -static void netdrv_rx_err (u32 rx_status, struct net_device *dev, - struct netdrv_private *tp, void *ioaddr) +static void netdrv_rx_err(u32 rx_status, struct net_device *dev, + struct netdrv_private *tp, void *ioaddr) { u8 tmp8; int tmp_work = 1000; - DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n", - dev->name, rx_status); - if (rx_status & RxTooLong) { - DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n", - dev->name, rx_status); + netdev_dbg(dev, "Ethernet frame had errors, status %08x\n", rx_status); + if (rx_status & RxTooLong) + netdev_dbg(dev, "Oversized Ethernet frame, status %04x!\n", + rx_status); /* A.C.: The chip hangs here. */ - } dev->stats.rx_errors++; if (rx_status & (RxBadSymbol | RxBadAlign)) dev->stats.rx_frame_errors++; @@ -1466,56 +1469,55 @@ static void netdrv_rx_err (u32 rx_status, struct net_device *dev, dev->stats.rx_length_errors++; if (rx_status & RxCRCErr) dev->stats.rx_crc_errors++; - /* Reset the receiver, based on RealTek recommendation. (Bug?) */ + /* Reset the receiver, based on RealTek recommendation.(Bug?) */ tp->cur_rx = 0; /* disable receive */ - tmp8 = NETDRV_R8 (ChipCmd) & ChipCmdClear; - NETDRV_W8_F (ChipCmd, tmp8 | CmdTxEnb); + tmp8 = NETDRV_R8(ChipCmd) & ChipCmdClear; + NETDRV_W8_F(ChipCmd, tmp8 | CmdTxEnb); /* A.C.: Reset the multicast list. */ - netdrv_set_rx_mode (dev); + netdrv_set_rx_mode(dev); /* XXX potentially temporary hack to * restart hung receiver */ while (--tmp_work > 0) { - tmp8 = NETDRV_R8 (ChipCmd); + tmp8 = NETDRV_R8(ChipCmd); if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) break; - NETDRV_W8_F (ChipCmd, - (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb); + NETDRV_W8_F(ChipCmd, + (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb); } /* G.S.: Re-enable receiver */ /* XXX temporary hack to work around receiver hang */ - netdrv_set_rx_mode (dev); + netdrv_set_rx_mode(dev); if (tmp_work <= 0) - printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); + netdev_warn(dev, "tx/rx enable wait too long\n"); } /* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the field alignments and semantics. */ -static void netdrv_rx_interrupt (struct net_device *dev, - struct netdrv_private *tp, void *ioaddr) +static void netdrv_rx_interrupt(struct net_device *dev, + struct netdrv_private *tp, void *ioaddr) { unsigned char *rx_ring; u16 cur_rx; - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); + assert(dev != NULL); + assert(tp != NULL); + assert(ioaddr != NULL); rx_ring = tp->rx_ring; cur_rx = tp->cur_rx; - DPRINTK ("%s: In netdrv_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - NETDRV_R16 (RxBufAddr), - NETDRV_R16 (RxBufPtr), NETDRV_R8 (ChipCmd)); + netdev_dbg(dev, "In netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", + cur_rx, NETDRV_R16(RxBufAddr), + NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd)); - while ((NETDRV_R8 (ChipCmd) & RxBufEmpty) == 0) { + while ((NETDRV_R8(ChipCmd) & RxBufEmpty) == 0) { int ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; unsigned int rx_size; @@ -1523,32 +1525,25 @@ static void netdrv_rx_interrupt (struct net_device *dev, struct sk_buff *skb; /* read size+status of next frame from DMA ring buffer */ - rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); + rx_status = le32_to_cpu(*(u32 *)(rx_ring + ring_offset)); rx_size = rx_status >> 16; pkt_size = rx_size - 4; - DPRINTK ("%s: netdrv_rx() status %4.4x, size %4.4x," - " cur %4.4x.\n", dev->name, rx_status, - rx_size, cur_rx); + netdev_dbg(dev, "netdrv_rx() status %04x, size %04x, cur %04x\n", + rx_status, rx_size, cur_rx); #if defined(NETDRV_DEBUG) && (NETDRV_DEBUG > 2) - { - int i; - DPRINTK ("%s: Frame contents ", dev->name); - for (i = 0; i < 70; i++) - printk (" %2.2x", - rx_ring[ring_offset + i]); - printk (".\n"); - } + print_hex_dump_bytes("Frame contents: ", HEX_DUMP_OFFSET, + &rx_ring[ring_offset], 70); #endif /* If Rx err or invalid rx_size/rx_status received - * (which happens if we get lost in the ring), + *(which happens if we get lost in the ring), * Rx process gets reset, so we abort any further * Rx processing. */ if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) || (!(rx_status & RxStatusOK))) { - netdrv_rx_err (rx_status, dev, tp, ioaddr); + netdrv_rx_err(rx_status, dev, tp, ioaddr); return; } @@ -1561,71 +1556,67 @@ static void netdrv_rx_interrupt (struct net_device *dev, * drop packets here under memory pressure. */ - skb = dev_alloc_skb (pkt_size + 2); + skb = dev_alloc_skb(pkt_size + 2); if (skb) { - skb_reserve (skb, 2); /* 16 byte align the IP fields. */ + skb_reserve(skb, 2); /* 16 byte align the IP fields. */ - skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size); - skb_put (skb, pkt_size); + skb_copy_to_linear_data(skb, &rx_ring[ring_offset + 4], pkt_size); + skb_put(skb, pkt_size); - skb->protocol = eth_type_trans (skb, dev); - netif_rx (skb); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); dev->stats.rx_bytes += pkt_size; dev->stats.rx_packets++; } else { - printk (KERN_WARNING - "%s: Memory squeeze, dropping packet.\n", - dev->name); + netdev_warn(dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; } cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; - NETDRV_W16_F (RxBufPtr, cur_rx - 16); + NETDRV_W16_F(RxBufPtr, cur_rx - 16); } - DPRINTK ("%s: Done netdrv_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, - NETDRV_R16 (RxBufAddr), - NETDRV_R16 (RxBufPtr), NETDRV_R8 (ChipCmd)); + netdev_dbg(dev, "Done netdrv_rx(), current %04x BufAddr %04x, free to %04x, Cmd %02x\n", + cur_rx, NETDRV_R16(RxBufAddr), + NETDRV_R16(RxBufPtr), NETDRV_R8(ChipCmd)); tp->cur_rx = cur_rx; } -static void netdrv_weird_interrupt (struct net_device *dev, - struct netdrv_private *tp, - void *ioaddr, - int status, int link_changed) +static void netdrv_weird_interrupt(struct net_device *dev, + struct netdrv_private *tp, + void *ioaddr, + int status, int link_changed) { - printk (KERN_DEBUG "%s: Abnormal interrupt, status %8.8x.\n", - dev->name, status); + netdev_printk(KERN_DEBUG, dev, "Abnormal interrupt, status %08x\n", + status); - assert (dev != NULL); - assert (tp != NULL); - assert (ioaddr != NULL); + assert(dev != NULL); + assert(tp != NULL); + assert(ioaddr != NULL); /* Update the error count. */ - dev->stats.rx_missed_errors += NETDRV_R32 (RxMissed); - NETDRV_W32 (RxMissed, 0); + dev->stats.rx_missed_errors += NETDRV_R32(RxMissed); + NETDRV_W32(RxMissed, 0); if ((status & RxUnderrun) && link_changed && (tp->drv_flags & HAS_LNK_CHNG)) { /* Really link-change on new chips. */ - int lpar = NETDRV_R16 (NWayLPAR); + int lpar = NETDRV_R16(NWayLPAR); int duplex = ((lpar & 0x0100) || (lpar & 0x01C0) == 0x0040 || - tp->duplex_lock); + tp->duplex_lock); if (tp->full_duplex != duplex) { tp->full_duplex = duplex; - NETDRV_W8 (Cfg9346, Cfg9346_Unlock); - NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); - NETDRV_W8 (Cfg9346, Cfg9346_Lock); + NETDRV_W8(Cfg9346, Cfg9346_Unlock); + NETDRV_W8(Config1, tp->full_duplex ? 0x60 : 0x20); + NETDRV_W8(Cfg9346, Cfg9346_Lock); } status &= ~RxUnderrun; } /* XXX along with netdrv_rx_err, are we double-counting errors? */ - if (status & - (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) + if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver)) dev->stats.rx_errors++; if (status & (PCSTimeout)) @@ -1634,22 +1625,21 @@ static void netdrv_weird_interrupt (struct net_device *dev, dev->stats.rx_fifo_errors++; if (status & RxOverflow) { dev->stats.rx_over_errors++; - tp->cur_rx = NETDRV_R16 (RxBufAddr) % RX_BUF_LEN; - NETDRV_W16_F (RxBufPtr, tp->cur_rx - 16); + tp->cur_rx = NETDRV_R16(RxBufAddr) % RX_BUF_LEN; + NETDRV_W16_F(RxBufPtr, tp->cur_rx - 16); } if (status & PCIErr) { u16 pci_cmd_status; - pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status); + pci_read_config_word(tp->pci_dev, PCI_STATUS, &pci_cmd_status); - printk (KERN_ERR "%s: PCI Bus error %4.4x.\n", - dev->name, pci_cmd_status); + netdev_err(dev, "PCI Bus error %04x\n", pci_cmd_status); } } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static irqreturn_t netdrv_interrupt (int irq, void *dev_instance) +static irqreturn_t netdrv_interrupt(int irq, void *dev_instance) { struct net_device *dev = (struct net_device *) dev_instance; struct netdrv_private *tp = netdev_priv(dev); @@ -1658,22 +1648,21 @@ static irqreturn_t netdrv_interrupt (int irq, void *dev_instance) int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */ int handled = 0; - spin_lock (&tp->lock); + spin_lock(&tp->lock); do { - status = NETDRV_R16 (IntrStatus); + status = NETDRV_R16(IntrStatus); - /* h/w no longer present (hotplug?) or major error, bail */ + /* h/w no longer present(hotplug?) or major error, bail */ if (status == 0xFFFF) break; handled = 1; /* Acknowledge all of the current interrupt sources ASAP */ - NETDRV_W16_F (IntrStatus, status); + NETDRV_W16_F(IntrStatus, status); - DPRINTK ("%s: interrupt status=%#4.4x new intstat=%#4.4x.\n", - dev->name, status, - NETDRV_R16 (IntrStatus)); + netdev_dbg(dev, "interrupt status=%#04x new intstat=%#04x\n", + status, NETDRV_R16(IntrStatus)); if ((status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | @@ -1682,69 +1671,67 @@ static irqreturn_t netdrv_interrupt (int irq, void *dev_instance) /* Check uncommon events with one test. */ if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow | - RxFIFOOver | TxErr | RxErr)) - netdrv_weird_interrupt (dev, tp, ioaddr, - status, link_changed); + RxFIFOOver | TxErr | RxErr)) + netdrv_weird_interrupt(dev, tp, ioaddr, + status, link_changed); if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) /* Rx interrupt */ - netdrv_rx_interrupt (dev, tp, ioaddr); + netdrv_rx_interrupt(dev, tp, ioaddr); if (status & (TxOK | TxErr)) - netdrv_tx_interrupt (dev, tp, ioaddr); + netdrv_tx_interrupt(dev, tp, ioaddr); boguscnt--; } while (boguscnt > 0); if (boguscnt <= 0) { - printk (KERN_WARNING - "%s: Too much work at interrupt, " - "IntrStatus=0x%4.4x.\n", dev->name, - status); + netdev_warn(dev, "Too much work at interrupt, IntrStatus=%#04x\n", + status); /* Clear all interrupt sources. */ - NETDRV_W16 (IntrStatus, 0xffff); + NETDRV_W16(IntrStatus, 0xffff); } - spin_unlock (&tp->lock); + spin_unlock(&tp->lock); - DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, NETDRV_R16 (IntrStatus)); + netdev_dbg(dev, "exiting interrupt, intr_status=%#04x\n", + NETDRV_R16(IntrStatus)); return IRQ_RETVAL(handled); } -static int netdrv_close (struct net_device *dev) +static int netdrv_close(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - netif_stop_queue (dev); + netif_stop_queue(dev); - DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n", - dev->name, NETDRV_R16 (IntrStatus)); + netdev_dbg(dev, "Shutting down ethercard, status was %#04x\n", + NETDRV_R16(IntrStatus)); - del_timer_sync (&tp->timer); + del_timer_sync(&tp->timer); - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irqsave(&tp->lock, flags); /* Stop the chip's Tx and Rx DMA processes. */ - NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear)); + NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear)); /* Disable interrupts by clearing the interrupt mask. */ - NETDRV_W16 (IntrMask, 0x0000); + NETDRV_W16(IntrMask, 0x0000); /* Update the error counts. */ - dev->stats.rx_missed_errors += NETDRV_R32 (RxMissed); - NETDRV_W32 (RxMissed, 0); + dev->stats.rx_missed_errors += NETDRV_R32(RxMissed); + NETDRV_W32(RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irqrestore(&tp->lock, flags); - free_irq (dev->irq, dev); + free_irq(dev->irq, dev); - netdrv_tx_clear (dev); + netdrv_tx_clear(dev); pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN, tp->rx_ring, tp->rx_ring_dma); @@ -1754,23 +1741,23 @@ static int netdrv_close (struct net_device *dev) tp->tx_bufs = NULL; /* Green! Put the chip in low-power mode. */ - NETDRV_W8 (Cfg9346, Cfg9346_Unlock); - NETDRV_W8 (Config1, 0x03); - NETDRV_W8 (Cfg9346, Cfg9346_Lock); + NETDRV_W8(Cfg9346, Cfg9346_Unlock); + NETDRV_W8(Config1, 0x03); + NETDRV_W8(Cfg9346, Cfg9346_Lock); - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); return 0; } -static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) +static int netdrv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct netdrv_private *tp = netdev_priv(dev); struct mii_ioctl_data *data = if_mii(rq); unsigned long flags; int rc = 0; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); switch (cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ @@ -1778,15 +1765,15 @@ static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) /* Fall Through */ case SIOCGMIIREG: /* Read MII PHY register. */ - spin_lock_irqsave (&tp->lock, flags); - data->val_out = mdio_read (dev, data->phy_id & 0x1f, data->reg_num & 0x1f); - spin_unlock_irqrestore (&tp->lock, flags); + spin_lock_irqsave(&tp->lock, flags); + data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f); + spin_unlock_irqrestore(&tp->lock, flags); break; case SIOCSMIIREG: /* Write MII PHY register. */ - spin_lock_irqsave (&tp->lock, flags); - mdio_write (dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); - spin_unlock_irqrestore (&tp->lock, flags); + spin_lock_irqsave(&tp->lock, flags); + mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); + spin_unlock_irqrestore(&tp->lock, flags); break; default: @@ -1794,14 +1781,14 @@ static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) break; } - DPRINTK ("EXIT, returning %d\n", rc); + DPRINTK("EXIT, returning %d\n", rc); return rc; } /* Set or clear the multicast filter for this adaptor. This routine is not state sensitive and need not be SMP locked. */ -static void netdrv_set_rx_mode (struct net_device *dev) +static void netdrv_set_rx_mode(struct net_device *dev) { struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; @@ -1809,16 +1796,16 @@ static void netdrv_set_rx_mode (struct net_device *dev) int i, rx_mode; u32 tmp; - DPRINTK ("ENTER\n"); + DPRINTK("ENTER\n"); - DPRINTK ("%s: netdrv_set_rx_mode(%4.4x) done -- Rx config %8.8x.\n", - dev->name, dev->flags, NETDRV_R32 (RxConfig)); + netdev_dbg(dev, "%s(%04x) done -- Rx config %08lx\n", + __func__, dev->flags, NETDRV_R32(RxConfig)); /* Note: do not reorder, GCC is clever about common statements. */ if (dev->flags & IFF_PROMISC) { rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; + AcceptBroadcast | AcceptMulticast | AcceptMyPhys | + AcceptAllPhys; mc_filter[1] = mc_filter[0] = 0xffffffff; } else if ((netdev_mc_count(dev) > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { @@ -1838,66 +1825,66 @@ static void netdrv_set_rx_mode (struct net_device *dev) } /* if called from irq handler, lock already acquired */ - if (!in_irq ()) - spin_lock_irq (&tp->lock); + if (!in_irq()) + spin_lock_irq(&tp->lock); /* We can safely update without stopping the chip. */ tmp = netdrv_rx_config | rx_mode | - (NETDRV_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - NETDRV_W32_F (RxConfig, tmp); - NETDRV_W32_F (MAR0 + 0, mc_filter[0]); - NETDRV_W32_F (MAR0 + 4, mc_filter[1]); + (NETDRV_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + NETDRV_W32_F(RxConfig, tmp); + NETDRV_W32_F(MAR0 + 0, mc_filter[0]); + NETDRV_W32_F(MAR0 + 4, mc_filter[1]); - if (!in_irq ()) - spin_unlock_irq (&tp->lock); + if (!in_irq()) + spin_unlock_irq(&tp->lock); - DPRINTK ("EXIT\n"); + DPRINTK("EXIT\n"); } #ifdef CONFIG_PM -static int netdrv_suspend (struct pci_dev *pdev, pm_message_t state) +static int netdrv_suspend(struct pci_dev *pdev, pm_message_t state) { - struct net_device *dev = pci_get_drvdata (pdev); + struct net_device *dev = pci_get_drvdata(pdev); struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; if (!netif_running(dev)) return 0; - netif_device_detach (dev); + netif_device_detach(dev); - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irqsave(&tp->lock, flags); /* Disable interrupts, stop Tx and Rx. */ - NETDRV_W16 (IntrMask, 0x0000); - NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear)); + NETDRV_W16(IntrMask, 0x0000); + NETDRV_W8(ChipCmd, (NETDRV_R8(ChipCmd) & ChipCmdClear)); /* Update the error counts. */ - dev->stats.rx_missed_errors += NETDRV_R32 (RxMissed); - NETDRV_W32 (RxMissed, 0); + dev->stats.rx_missed_errors += NETDRV_R32(RxMissed); + NETDRV_W32(RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irqrestore(&tp->lock, flags); - pci_save_state (pdev); - pci_set_power_state (pdev, PCI_D3hot); + pci_save_state(pdev); + pci_set_power_state(pdev, PCI_D3hot); return 0; } -static int netdrv_resume (struct pci_dev *pdev) +static int netdrv_resume(struct pci_dev *pdev) { - struct net_device *dev = pci_get_drvdata (pdev); + struct net_device *dev = pci_get_drvdata(pdev); /*struct netdrv_private *tp = netdev_priv(dev);*/ if (!netif_running(dev)) return 0; - pci_set_power_state (pdev, PCI_D0); - pci_restore_state (pdev); - netif_device_attach (dev); - netdrv_hw_start (dev); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + netif_device_attach(dev); + netdrv_hw_start(dev); return 0; } @@ -1917,7 +1904,7 @@ static struct pci_driver netdrv_pci_driver = { }; -static int __init netdrv_init_module (void) +static int __init netdrv_init_module(void) { /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE @@ -1927,9 +1914,9 @@ static int __init netdrv_init_module (void) } -static void __exit netdrv_cleanup_module (void) +static void __exit netdrv_cleanup_module(void) { - pci_unregister_driver (&netdrv_pci_driver); + pci_unregister_driver(&netdrv_pci_driver); } -- cgit v1.2.3 From f15063cdd6bd541b4f35cec7e9a6c96f3c644c8d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:57 +0000 Subject: drivers/net/skge.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/skge.c | 50 +++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index ffa55df4d607..8aa24c52f319 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -23,6 +23,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -46,7 +48,6 @@ #define DRV_NAME "skge" #define DRV_VERSION "1.13" -#define PFX DRV_NAME " " #define DEFAULT_TX_RING_SIZE 128 #define DEFAULT_RX_RING_SIZE 512 @@ -1129,8 +1130,7 @@ static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) { u16 v = 0; if (__xm_phy_read(hw, port, reg, &v)) - printk(KERN_WARNING PFX "%s: phy read timed out\n", - hw->dev[port]->name); + pr_warning("%s: phy read timed out\n", hw->dev[port]->name); return v; } @@ -1252,8 +1252,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); if (lpa & PHY_B_AN_RF) { - printk(KERN_NOTICE PFX "%s: remote fault\n", - dev->name); + netdev_notice(dev, "remote fault\n"); return; } @@ -1268,8 +1267,7 @@ static void bcom_check_link(struct skge_hw *hw, int port) skge->duplex = DUPLEX_HALF; break; default: - printk(KERN_NOTICE PFX "%s: duplex mismatch\n", - dev->name); + netdev_notice(dev, "duplex mismatch\n"); return; } @@ -1461,8 +1459,7 @@ static int xm_check_link(struct net_device *dev) lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); if (lpa & PHY_B_AN_RF) { - printk(KERN_NOTICE PFX "%s: remote fault\n", - dev->name); + netdev_notice(dev, "remote fault\n"); return 0; } @@ -1477,8 +1474,7 @@ static int xm_check_link(struct net_device *dev) skge->duplex = DUPLEX_HALF; break; default: - printk(KERN_NOTICE PFX "%s: duplex mismatch\n", - dev->name); + netdev_notice(dev, "duplex mismatch\n"); return 0; } @@ -1566,7 +1562,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) udelay(1); } - printk(KERN_WARNING PFX "%s: genesis reset failed\n", dev->name); + netdev_warn(dev, "genesis reset failed\n"); reset_ok: /* Unreset the XMAC. */ @@ -1898,7 +1894,7 @@ static inline void bcom_phy_intr(struct skge_port *skge) "phy interrupt status 0x%x\n", isrc); if (isrc & PHY_B_IS_PSE) - printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n", + pr_err("%s: uncorrectable pair swap error\n", hw->dev[port]->name); /* Workaround BCom Errata: @@ -1931,8 +1927,7 @@ static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) return 0; } - printk(KERN_WARNING PFX "%s: phy write timeout\n", - hw->dev[port]->name); + pr_warning("%s: phy write timeout\n", hw->dev[port]->name); return -EIO; } @@ -1960,8 +1955,7 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) { u16 v = 0; if (__gm_phy_read(hw, port, reg, &v)) - printk(KERN_WARNING PFX "%s: phy read timeout\n", - hw->dev[port]->name); + pr_warning("%s: phy read timeout\n", hw->dev[port]->name); return v; } @@ -2434,8 +2428,7 @@ static void yukon_phy_intr(struct skge_port *skge) } return; failed: - printk(KERN_ERR PFX "%s: autonegotiation failed (%s)\n", - skge->netdev->name, reason); + pr_err("%s: autonegotiation failed (%s)\n", skge->netdev->name, reason); /* XXX restart autonegotiation? */ } @@ -2824,7 +2817,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, smp_wmb(); if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) { - pr_debug("%s: transmit queue full\n", dev->name); + netdev_dbg(dev, "transmit queue full\n"); netif_stop_queue(dev); } @@ -3724,7 +3717,7 @@ static int skge_device_event(struct notifier_block *unused, if (d) skge->debugfs = d; else { - pr_info(PFX "%s: rename failed\n", dev->name); + netdev_info(dev, "rename failed\n"); debugfs_remove(skge->debugfs); } } @@ -3742,8 +3735,7 @@ static int skge_device_event(struct notifier_block *unused, skge_debug, dev, &skge_debug_fops); if (!d || IS_ERR(d)) - pr_info(PFX "%s: debugfs create failed\n", - dev->name); + netdev_info(dev, "debugfs create failed\n"); else skge->debugfs = d; break; @@ -3764,7 +3756,7 @@ static __init void skge_debug_init(void) ent = debugfs_create_dir("skge", NULL); if (!ent || IS_ERR(ent)) { - pr_info(PFX "debugfs create directory failed\n"); + pr_info("debugfs create directory failed\n"); return; } @@ -3945,9 +3937,10 @@ static int __devinit skge_probe(struct pci_dev *pdev, if (err) goto err_out_iounmap; - printk(KERN_INFO PFX DRV_VERSION " addr 0x%llx irq %d chip %s rev %d\n", - (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, - skge_board_name(hw), hw->chip_rev); + pr_info("%s addr 0x%llx irq %d chip %s rev %d\n", + DRV_VERSION, + (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, + skge_board_name(hw), hw->chip_rev); dev = skge_devinit(hw, 0, using_dac); if (!dev) @@ -4104,8 +4097,7 @@ static int skge_resume(struct pci_dev *pdev) err = skge_up(dev); if (err) { - printk(KERN_ERR PFX "%s: could not up: %d\n", - dev->name, err); + netdev_err(dev, "could not up: %d\n", err); dev_close(dev); goto out; } -- cgit v1.2.3 From 67777f9bf255d7561375500a4e117bdb08a883db Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:58 +0000 Subject: drivers/net/skge.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Checkpatch cleaning Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/skge.c | 81 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 8aa24c52f319..720af1c7854b 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -71,9 +71,9 @@ MODULE_AUTHOR("Stephen Hemminger "); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -static const u32 default_msg - = NETIF_MSG_DRV| NETIF_MSG_PROBE| NETIF_MSG_LINK - | NETIF_MSG_IFUP| NETIF_MSG_IFDOWN; +static const u32 default_msg = (NETIF_MSG_DRV | NETIF_MSG_PROBE | + NETIF_MSG_LINK | NETIF_MSG_IFUP | + NETIF_MSG_IFDOWN); static int debug = -1; /* defaults above */ module_param(debug, int, 0); @@ -188,8 +188,8 @@ static void skge_wol_init(struct skge_port *skge) /* Force to 10/100 skge_reset will re-enable on resume */ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, - PHY_AN_100FULL | PHY_AN_100HALF | - PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA); + (PHY_AN_100FULL | PHY_AN_100HALF | + PHY_AN_10FULL | PHY_AN_10HALF | PHY_AN_CSMA)); /* no 1000 HD/FD */ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); gm_phy_write(hw, port, PHY_MARV_CTRL, @@ -258,25 +258,28 @@ static u32 skge_supported_modes(const struct skge_hw *hw) u32 supported; if (hw->copper) { - supported = SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full - | SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full - | SUPPORTED_Autoneg| SUPPORTED_TP; + supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full | + SUPPORTED_Autoneg | + SUPPORTED_TP); if (hw->chip_id == CHIP_ID_GENESIS) - supported &= ~(SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full - | SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full); + supported &= ~(SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full); else if (hw->chip_id == CHIP_ID_YUKON) supported &= ~SUPPORTED_1000baseT_Half; } else - supported = SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half - | SUPPORTED_FIBRE | SUPPORTED_Autoneg; + supported = (SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_FIBRE | + SUPPORTED_Autoneg); return supported; } @@ -366,7 +369,7 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } } - return (0); + return 0; } static void skge_get_drvinfo(struct net_device *dev, @@ -813,7 +816,7 @@ static int skge_get_eeprom_len(struct net_device *dev) u32 reg2; pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, ®2); - return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); + return 1 << (((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); } static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset) @@ -1044,7 +1047,7 @@ static int skge_rx_fill(struct net_device *dev) skb_reserve(skb, NET_IP_ALIGN); skge_rx_setup(skge, e, skb, skge->rx_buf_size); - } while ( (e = e->next) != ring->start); + } while ((e = e->next) != ring->start); ring->to_clean = ring->start; return 0; @@ -1052,7 +1055,7 @@ static int skge_rx_fill(struct net_device *dev) static const char *skge_pause(enum pause_status status) { - switch(status) { + switch (status) { case FLOW_STAT_NONE: return "none"; case FLOW_STAT_REM_SEND: @@ -1322,7 +1325,7 @@ static void bcom_phy_init(struct skge_port *skge) /* Optimize MDIO transfer by suppressing preamble. */ r = xm_read16(hw, port, XM_MMU_CMD); r |= XM_MMU_NO_PRE; - xm_write16(hw, port, XM_MMU_CMD,r); + xm_write16(hw, port, XM_MMU_CMD, r); switch (id1) { case PHY_BCOM_ID1_C0: @@ -1512,7 +1515,7 @@ static void xm_link_timer(unsigned long arg) { struct skge_port *skge = (struct skge_port *) arg; struct net_device *dev = skge->netdev; - struct skge_hw *hw = skge->hw; + struct skge_hw *hw = skge->hw; int port = skge->port; int i; unsigned long flags; @@ -1531,7 +1534,7 @@ static void xm_link_timer(unsigned long arg) goto link_down; } - /* Re-enable interrupt to detect link down */ + /* Re-enable interrupt to detect link down */ if (xm_check_link(dev)) { u16 msk = xm_read16(hw, port, XM_IMSK); msk &= ~XM_IS_INP_ASS; @@ -1588,7 +1591,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) } - switch(hw->phy_type) { + switch (hw->phy_type) { case SK_PHY_XMAC: xm_phy_init(skge); break; @@ -1695,7 +1698,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) if (jumbo) { /* Enable frame flushing if jumbo frames used */ - skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); + skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_FLUSH); } else { /* enable timeout timers if normal frames */ skge_write16(hw, B3_PA_CTRL, @@ -1710,7 +1713,7 @@ static void genesis_stop(struct skge_port *skge) unsigned retries = 1000; u16 cmd; - /* Disable Tx and Rx */ + /* Disable Tx and Rx */ cmd = xm_read16(hw, port, XM_MMU_CMD); cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); xm_write16(hw, port, XM_MMU_CMD, cmd); @@ -1789,7 +1792,7 @@ static void genesis_mac_intr(struct skge_hw *hw, int port) "mac interrupt status 0x%x\n", status); if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { - xm_link_down(hw, port); + xm_link_down(hw, port); mod_timer(&skge->link_timer, jiffies + 1); } @@ -1823,7 +1826,7 @@ static void genesis_link_up(struct skge_port *skge) xm_write16(hw, port, XM_MMU_CMD, cmd); mode = xm_read32(hw, port, XM_MODE); - if (skge->flow_status== FLOW_STAT_SYMMETRIC || + if (skge->flow_status == FLOW_STAT_SYMMETRIC || skge->flow_status == FLOW_STAT_LOC_SEND) { /* * Configure Pause Frame Generation @@ -2466,7 +2469,7 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (!netif_running(dev)) return -ENODEV; /* Phy still in reset */ - switch(cmd) { + switch (cmd) { case SIOCGMIIPHY: data->phy_id = hw->phy_addr; @@ -2765,7 +2768,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, * does. Looks like hardware is wrong? */ if (ipip_hdr(skb)->protocol == IPPROTO_UDP && - hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) + hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) control = BMU_TCP_CHECK; else control = BMU_UDP_CHECK; @@ -2777,7 +2780,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, control = BMU_CHECK; if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */ - control |= BMU_EOF| BMU_IRQ_EOF; + control |= BMU_EOF | BMU_IRQ_EOF; else { struct skge_tx_desc *tf = td; @@ -3077,7 +3080,7 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, pci_unmap_len(e, maplen), PCI_DMA_FROMDEVICE); skb = e->skb; - prefetch(skb->data); + prefetch(skb->data); skge_rx_setup(skge, e, nskb, skge->rx_buf_size); } @@ -3554,8 +3557,7 @@ static int skge_reset(struct skge_hw *hw) hw->ram_offset = 0x80000; } else hw->ram_size = t8 * 512; - } - else if (t8 == 0) + } else if (t8 == 0) hw->ram_size = 0x20000; else hw->ram_size = t8 * 4096; @@ -3709,7 +3711,7 @@ static int skge_device_event(struct notifier_block *unused, goto done; skge = netdev_priv(dev); - switch(event) { + switch (event) { case NETDEV_CHANGENAME: if (skge->debugfs) { d = debugfs_rename(skge_debug, skge->debugfs, @@ -3914,7 +3916,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, err = -ENOMEM; /* space for skge@pci:0000:04:00.0 */ - hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:" ) + hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:") + strlen(pci_name(pdev)) + 1, GFP_KERNEL); if (!hw) { dev_err(&pdev->dev, "cannot allocate hardware struct\n"); @@ -4010,7 +4012,8 @@ static void __devexit skge_remove(struct pci_dev *pdev) flush_scheduled_work(); - if ((dev1 = hw->dev[1])) + dev1 = hw->dev[1]; + if (dev1) unregister_netdev(dev1); dev0 = hw->dev[0]; unregister_netdev(dev0); -- cgit v1.2.3 From ada1db5c6fac4d400ec284729af19b47488b332d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:01:59 +0000 Subject: drivers/net/sky2.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/sky2.c | 63 +++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a1198f141996..d1e98e2170ce 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -22,6 +22,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -51,7 +53,6 @@ #define DRV_NAME "sky2" #define DRV_VERSION "1.27" -#define PFX DRV_NAME " " /* * The Yukon II chipset takes 64 bit command blocks (called list elements) @@ -1212,8 +1213,7 @@ static void sky2_rx_stop(struct sky2_port *sky2) == sky2_read8(hw, RB_ADDR(rxq, Q_RL))) goto stopped; - printk(KERN_WARNING PFX "%s: receiver stop failed\n", - sky2->netdev->name); + netdev_warn(sky2->netdev, "receiver stop failed\n"); stopped: sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST); @@ -1555,7 +1555,7 @@ static void sky2_hw_up(struct sky2_port *sky2) if (ramsize > 0) { u32 rxspace; - pr_debug(PFX "%s: ram buffer %dK\n", sky2->netdev->name, ramsize); + netdev_dbg(sky2->netdev, "ram buffer %dK\n", ramsize); if (ramsize < 16) rxspace = ramsize / 2; else @@ -2070,13 +2070,12 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) advert = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP); if (lpa & PHY_M_AN_RF) { - printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name); + netdev_err(sky2->netdev, "remote fault\n"); return -1; } if (!(aux & PHY_M_PS_SPDUP_RES)) { - printk(KERN_ERR PFX "%s: speed/duplex mismatch", - sky2->netdev->name); + netdev_err(sky2->netdev, "speed/duplex mismatch\n"); return -1; } @@ -2195,10 +2194,10 @@ static void sky2_tx_timeout(struct net_device *dev) netif_err(sky2, timer, dev, "tx timeout\n"); - printk(KERN_DEBUG PFX "%s: transmit ring %u .. %u report=%u done=%u\n", - dev->name, sky2->tx_cons, sky2->tx_prod, - sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), - sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); + netdev_printk(KERN_DEBUG, dev, "transmit ring %u .. %u report=%u done=%u\n", + sky2->tx_cons, sky2->tx_prod, + sky2_read16(hw, sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX), + sky2_read16(hw, Q_ADDR(txqaddr[sky2->port], Q_DONE))); /* can't restart safely under softirq */ schedule_work(&hw->restart_work); @@ -2614,8 +2613,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) default: if (net_ratelimit()) - printk(KERN_WARNING PFX - "unknown status opcode 0x%x\n", opcode); + pr_warning("unknown status opcode 0x%x\n", opcode); } } while (hw->st_idx != idx); @@ -2634,41 +2632,37 @@ static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status) struct net_device *dev = hw->dev[port]; if (net_ratelimit()) - printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n", - dev->name, status); + netdev_info(dev, "hw error interrupt status 0x%x\n", status); if (status & Y2_IS_PAR_RD1) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: ram data read parity error\n", - dev->name); + netdev_err(dev, "ram data read parity error\n"); /* Clear IRQ */ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR); } if (status & Y2_IS_PAR_WR1) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: ram data write parity error\n", - dev->name); + netdev_err(dev, "ram data write parity error\n"); sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR); } if (status & Y2_IS_PAR_MAC1) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name); + netdev_err(dev, "MAC parity error\n"); sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE); } if (status & Y2_IS_PAR_RX1) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: RX parity error\n", dev->name); + netdev_err(dev, "RX parity error\n"); sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR); } if (status & Y2_IS_TCP_TXA1) { if (net_ratelimit()) - printk(KERN_ERR PFX "%s: TCP segmentation error\n", - dev->name); + netdev_err(dev, "TCP segmentation error\n"); sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP); } } @@ -2751,8 +2745,7 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, u16 q) struct net_device *dev = hw->dev[port]; u16 idx = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX)); - dev_err(&hw->pdev->dev, PFX - "%s: descriptor error q=%#x get=%u put=%u\n", + dev_err(&hw->pdev->dev, "%s: descriptor error q=%#x get=%u put=%u\n", dev->name, (unsigned) q, (unsigned) idx, (unsigned) sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX))); @@ -2777,9 +2770,10 @@ static int sky2_rx_hung(struct net_device *dev) /* Check if the PCI RX hang */ (fifo_rp == sky2->check.fifo_rp && fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) { - printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n", - dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp, - sky2_read8(hw, Q_ADDR(rxq, Q_WP))); + netdev_printk(KERN_DEBUG, dev, + "hung mac %d:%d fifo %d (%d:%d)\n", + mac_lev, mac_rp, fifo_lev, + fifo_rp, sky2_read8(hw, Q_ADDR(rxq, Q_WP))); return 1; } else { sky2->check.last = dev->last_rx; @@ -2810,8 +2804,7 @@ static void sky2_watchdog(unsigned long arg) /* For chips with Rx FIFO, check if stuck */ if ((hw->flags & SKY2_HW_RAM_BUFFER) && sky2_rx_hung(dev)) { - pr_info(PFX "%s: receiver hang detected\n", - dev->name); + netdev_info(dev, "receiver hang detected\n"); schedule_work(&hw->restart_work); return; } @@ -3253,8 +3246,7 @@ static int sky2_reattach(struct net_device *dev) if (netif_running(dev)) { err = sky2_up(dev); if (err) { - printk(KERN_INFO PFX "%s: could not restart %d\n", - dev->name, err); + netdev_info(dev, "could not restart %d\n", err); dev_close(dev); } else { netif_device_attach(dev); @@ -4032,7 +4024,7 @@ static int sky2_vpd_wait(const struct sky2_hw *hw, int cap, u16 busy) while ( (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F) == busy) { /* Can take up to 10.6 ms for write */ if (time_after(jiffies, start + HZ/4)) { - dev_err(&hw->pdev->dev, PFX "VPD cycle timed out"); + dev_err(&hw->pdev->dev, "VPD cycle timed out\n"); return -ETIMEDOUT; } mdelay(1); @@ -4366,8 +4358,7 @@ static int sky2_device_event(struct notifier_block *unused, case NETDEV_GOING_DOWN: if (sky2->debugfs) { - printk(KERN_DEBUG PFX "%s: remove debugfs\n", - dev->name); + netdev_printk(KERN_DEBUG, dev, "remove debugfs\n"); debugfs_remove(sky2->debugfs); sky2->debugfs = NULL; } @@ -4931,7 +4922,7 @@ static struct pci_driver sky2_driver = { static int __init sky2_init_module(void) { - pr_info(PFX "driver version " DRV_VERSION "\n"); + pr_info("driver version " DRV_VERSION "\n"); sky2_debug_init(); return pci_register_driver(&sky2_driver); -- cgit v1.2.3 From acbbf1f1fd63391eeba70fec991568e4334c80d4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 15:02:02 +0000 Subject: drivers/net/yellowfin.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Convert formats like %8.8 to %08 Remove periods from formats Coalesce long formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/yellowfin.c | 162 +++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 84 deletions(-) diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 5c880240a642..e4aab4d5b553 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -23,12 +23,12 @@ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #define DRV_NAME "yellowfin" #define DRV_VERSION "2.1" #define DRV_RELDATE "Sep 11, 2006" -#define PFX DRV_NAME ": " - /* The user-configurable values. These may be modified when a driver module is loaded.*/ @@ -399,7 +399,7 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, dev = alloc_etherdev(sizeof(*np)); if (!dev) { - printk (KERN_ERR PFX "cannot allocate ethernet device\n"); + pr_err("cannot allocate ethernet device\n"); return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -487,10 +487,10 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, if (i) goto err_out_unmap_status; - printk(KERN_INFO "%s: %s type %8x at %p, %pM, IRQ %d.\n", - dev->name, pci_id_tbl[chip_idx].name, - ioread32(ioaddr + ChipRev), ioaddr, - dev->dev_addr, irq); + netdev_info(dev, "%s type %8x at %p, %pM, IRQ %d\n", + pci_id_tbl[chip_idx].name, + ioread32(ioaddr + ChipRev), ioaddr, + dev->dev_addr, irq); if (np->drv_flags & HasMII) { int phy, phy_idx = 0; @@ -499,9 +499,8 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev, if (mii_status != 0xffff && mii_status != 0x0000) { np->phys[phy_idx++] = phy; np->advertising = mdio_read(ioaddr, phy, 4); - printk(KERN_INFO "%s: MII PHY found at address %d, status " - "0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, np->advertising); + netdev_info(dev, "MII PHY found at address %d, status 0x%04x advertising %04x\n", + phy, mii_status, np->advertising); } } np->mii_cnt = phy_idx; @@ -584,8 +583,8 @@ static int yellowfin_open(struct net_device *dev) return ret; if (yellowfin_debug > 1) - printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n", - dev->name, dev->irq); + netdev_printk(KERN_DEBUG, dev, "%s() irq %d\n", + __func__, dev->irq); ret = yellowfin_init_ring(dev); if (ret) { @@ -642,8 +641,7 @@ static int yellowfin_open(struct net_device *dev) iowrite32(0x80008000, ioaddr + TxCtrl); if (yellowfin_debug > 2) { - printk(KERN_DEBUG "%s: Done yellowfin_open().\n", - dev->name); + netdev_printk(KERN_DEBUG, dev, "Done %s()\n", __func__); } /* Set the timer to check for link beat. */ @@ -664,8 +662,8 @@ static void yellowfin_timer(unsigned long data) int next_tick = 60*HZ; if (yellowfin_debug > 3) { - printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n", - dev->name, ioread16(ioaddr + IntrStatus)); + netdev_printk(KERN_DEBUG, dev, "Yellowfin timer tick, status %08x\n", + ioread16(ioaddr + IntrStatus)); } if (yp->mii_cnt) { @@ -673,9 +671,8 @@ static void yellowfin_timer(unsigned long data) int lpa = mdio_read(ioaddr, yp->phys[0], MII_LPA); int negotiated = lpa & yp->advertising; if (yellowfin_debug > 1) - printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, " - "link partner capability %4.4x.\n", - dev->name, yp->phys[0], bmsr, lpa); + netdev_printk(KERN_DEBUG, dev, "MII #%d status register is %04x, link partner capability %04x\n", + yp->phys[0], bmsr, lpa); yp->full_duplex = mii_duplex(yp->duplex_lock, negotiated); @@ -696,25 +693,24 @@ static void yellowfin_tx_timeout(struct net_device *dev) struct yellowfin_private *yp = netdev_priv(dev); void __iomem *ioaddr = yp->base; - printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx " - "status %4.4x, Rx status %4.4x, resetting...\n", - dev->name, yp->cur_tx, yp->dirty_tx, - ioread32(ioaddr + TxStatus), ioread32(ioaddr + RxStatus)); + netdev_warn(dev, "Yellowfin transmit timed out at %d/%d Tx status %04x, Rx status %04x, resetting...\n", + yp->cur_tx, yp->dirty_tx, + ioread32(ioaddr + TxStatus), + ioread32(ioaddr + RxStatus)); /* Note: these should be KERN_DEBUG. */ if (yellowfin_debug) { int i; - printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring); + pr_warning(" Rx ring %p: ", yp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) - printk(KERN_CONT " %8.8x", - yp->rx_ring[i].result_status); - printk(KERN_CONT "\n"); - printk(KERN_WARNING" Tx ring %p: ", yp->tx_ring); + pr_cont(" %08x", yp->rx_ring[i].result_status); + pr_cont("\n"); + pr_warning(" Tx ring %p: ", yp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_CONT " %4.4x /%8.8x", + pr_cont(" %04x /%08x", yp->tx_status[i].tx_errs, yp->tx_ring[i].result_status); - printk(KERN_CONT "\n"); + pr_cont("\n"); } /* If the hardware is found to hang regularly, we will update the code @@ -891,8 +887,8 @@ static netdev_tx_t yellowfin_start_xmit(struct sk_buff *skb, yp->tx_full = 1; if (yellowfin_debug > 4) { - printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n", - dev->name, yp->cur_tx, entry); + netdev_printk(KERN_DEBUG, dev, "Yellowfin transmit frame #%d queued in slot %d\n", + yp->cur_tx, entry); } return NETDEV_TX_OK; } @@ -916,8 +912,8 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) u16 intr_status = ioread16(ioaddr + IntrClear); if (yellowfin_debug > 4) - printk(KERN_DEBUG "%s: Yellowfin interrupt, status %4.4x.\n", - dev->name, intr_status); + netdev_printk(KERN_DEBUG, dev, "Yellowfin interrupt, status %04x\n", + intr_status); if (intr_status == 0) break; @@ -963,13 +959,12 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) #ifndef final_version if (yellowfin_debug > 5) - printk(KERN_DEBUG "%s: Tx queue %d check, Tx status " - "%4.4x %4.4x %4.4x %4.4x.\n", - dev->name, entry, - yp->tx_status[entry].tx_cnt, - yp->tx_status[entry].tx_errs, - yp->tx_status[entry].total_tx_cnt, - yp->tx_status[entry].paused); + netdev_printk(KERN_DEBUG, dev, "Tx queue %d check, Tx status %04x %04x %04x %04x\n", + entry, + yp->tx_status[entry].tx_cnt, + yp->tx_status[entry].tx_errs, + yp->tx_status[entry].total_tx_cnt, + yp->tx_status[entry].paused); #endif if (tx_errs == 0) break; /* It still hasn't been Txed */ @@ -978,8 +973,8 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) /* There was an major error, log it. */ #ifndef final_version if (yellowfin_debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %4.4x.\n", - dev->name, tx_errs); + netdev_printk(KERN_DEBUG, dev, "Transmit error, Tx status %04x\n", + tx_errs); #endif dev->stats.tx_errors++; if (tx_errs & 0xF800) dev->stats.tx_aborted_errors++; @@ -989,8 +984,8 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) } else { #ifndef final_version if (yellowfin_debug > 4) - printk(KERN_DEBUG "%s: Normal transmit, Tx status %4.4x.\n", - dev->name, tx_errs); + netdev_printk(KERN_DEBUG, dev, "Normal transmit, Tx status %04x\n", + tx_errs); #endif dev->stats.tx_bytes += skb->len; dev->stats.collisions += tx_errs & 15; @@ -1008,8 +1003,8 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) #ifndef final_version if (yp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, yp->cur_tx, yp->tx_full); + netdev_err(dev, "Out-of-sync dirty pointer, %d vs. %d, full=%d\n", + dirty_tx, yp->cur_tx, yp->tx_full); dirty_tx += TX_RING_SIZE; } #endif @@ -1031,16 +1026,15 @@ static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance) yellowfin_error(dev, intr_status); if (--boguscnt < 0) { - printk(KERN_WARNING "%s: Too much work at interrupt, " - "status=0x%4.4x.\n", - dev->name, intr_status); + netdev_warn(dev, "Too much work at interrupt, status=%#04x\n", + intr_status); break; } } while (1); if (yellowfin_debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, ioread16(ioaddr + IntrStatus)); + netdev_printk(KERN_DEBUG, dev, "exiting interrupt, status=%#04x\n", + ioread16(ioaddr + IntrStatus)); spin_unlock (&yp->lock); return IRQ_RETVAL(handled); @@ -1055,9 +1049,9 @@ static int yellowfin_rx(struct net_device *dev) int boguscnt = yp->dirty_rx + RX_RING_SIZE - yp->cur_rx; if (yellowfin_debug > 4) { - printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %8.8x.\n", + printk(KERN_DEBUG " In yellowfin_rx(), entry %d status %08x\n", entry, yp->rx_ring[entry].result_status); - printk(KERN_DEBUG " #%d desc. %8.8x %8.8x %8.8x.\n", + printk(KERN_DEBUG " #%d desc. %08x %08x %08x\n", entry, yp->rx_ring[entry].dbdma_cmd, yp->rx_ring[entry].addr, yp->rx_ring[entry].result_status); } @@ -1081,20 +1075,20 @@ static int yellowfin_rx(struct net_device *dev) le32_to_cpu(desc->result_status)) & 0xffff; frame_status = get_unaligned_le16(&(buf_addr[data_size - 2])); if (yellowfin_debug > 4) - printk(KERN_DEBUG " yellowfin_rx() status was %4.4x.\n", - frame_status); + printk(KERN_DEBUG " %s() status was %04x\n", + __func__, frame_status); if (--boguscnt < 0) break; if ( ! (desc_status & RX_EOP)) { if (data_size != 0) - printk(KERN_WARNING "%s: Oversized Ethernet frame spanned multiple buffers," - " status %4.4x, data_size %d!\n", dev->name, desc_status, data_size); + netdev_warn(dev, "Oversized Ethernet frame spanned multiple buffers, status %04x, data_size %d!\n", + desc_status, data_size); dev->stats.rx_length_errors++; } else if ((yp->drv_flags & IsGigabit) && (frame_status & 0x0038)) { /* There was a error. */ if (yellowfin_debug > 3) - printk(KERN_DEBUG " yellowfin_rx() Rx error was %4.4x.\n", - frame_status); + printk(KERN_DEBUG " %s() Rx error was %04x\n", + __func__, frame_status); dev->stats.rx_errors++; if (frame_status & 0x0060) dev->stats.rx_length_errors++; if (frame_status & 0x0008) dev->stats.rx_frame_errors++; @@ -1118,8 +1112,8 @@ static int yellowfin_rx(struct net_device *dev) entry*sizeof(struct yellowfin_desc)), "\377\377\377\377\377\377", 6) != 0) { if (bogus_rx++ == 0) - printk(KERN_WARNING "%s: Bad frame to %pM\n", - dev->name, buf_addr); + netdev_warn(dev, "Bad frame to %pM\n", + buf_addr); #endif } else { struct sk_buff *skb; @@ -1129,9 +1123,8 @@ static int yellowfin_rx(struct net_device *dev) #ifndef final_version if (yellowfin_debug > 4) - printk(KERN_DEBUG " yellowfin_rx() normal Rx pkt length %d" - " of %d, bogus_cnt %d.\n", - pkt_len, data_size, boguscnt); + printk(KERN_DEBUG " %s() normal Rx pkt length %d of %d, bogus_cnt %d\n", + __func__, pkt_len, data_size, boguscnt); #endif /* Check if the packet is long enough to just pass up the skbuff without copying to a properly sized skbuff. */ @@ -1191,8 +1184,7 @@ static int yellowfin_rx(struct net_device *dev) static void yellowfin_error(struct net_device *dev, int intr_status) { - printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", - dev->name, intr_status); + netdev_err(dev, "Something Wicked happened! %04x\n", intr_status); /* Hmmmmm, it's not clear what to do here. */ if (intr_status & (IntrTxPCIErr | IntrTxPCIFault)) dev->stats.tx_errors++; @@ -1209,13 +1201,13 @@ static int yellowfin_close(struct net_device *dev) netif_stop_queue (dev); if (yellowfin_debug > 1) { - printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x " - "Rx %4.4x Int %2.2x.\n", - dev->name, ioread16(ioaddr + TxStatus), - ioread16(ioaddr + RxStatus), - ioread16(ioaddr + IntrStatus)); - printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", - dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx); + netdev_printk(KERN_DEBUG, dev, "Shutting down ethercard, status was Tx %04x Rx %04x Int %02x\n", + ioread16(ioaddr + TxStatus), + ioread16(ioaddr + RxStatus), + ioread16(ioaddr + IntrStatus)); + netdev_printk(KERN_DEBUG, dev, "Queue pointers were Tx %d / %d, Rx %d / %d\n", + yp->cur_tx, yp->dirty_tx, + yp->cur_rx, yp->dirty_rx); } /* Disable interrupts by clearing the interrupt mask. */ @@ -1229,33 +1221,35 @@ static int yellowfin_close(struct net_device *dev) #if defined(__i386__) if (yellowfin_debug > 2) { - printk(KERN_DEBUG" Tx ring at %8.8llx:\n", + printk(KERN_DEBUG " Tx ring at %08llx:\n", (unsigned long long)yp->tx_ring_dma); for (i = 0; i < TX_RING_SIZE*2; i++) - printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n", + printk(KERN_DEBUG " %c #%d desc. %08x %08x %08x %08x\n", ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ', i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr, yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status); printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status); for (i = 0; i < TX_RING_SIZE; i++) - printk(KERN_DEBUG " #%d status %4.4x %4.4x %4.4x %4.4x.\n", + printk(KERN_DEBUG " #%d status %04x %04x %04x %04x\n", i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs, yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused); - printk(KERN_DEBUG " Rx ring %8.8llx:\n", + printk(KERN_DEBUG " Rx ring %08llx:\n", (unsigned long long)yp->rx_ring_dma); for (i = 0; i < RX_RING_SIZE; i++) { - printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n", + printk(KERN_DEBUG " %c #%d desc. %08x %08x %08x\n", ioread32(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ', i, yp->rx_ring[i].dbdma_cmd, yp->rx_ring[i].addr, yp->rx_ring[i].result_status); if (yellowfin_debug > 6) { if (get_unaligned((u8*)yp->rx_ring[i].addr) != 0x69) { int j; + + printk(KERN_DEBUG); for (j = 0; j < 0x50; j++) - printk(" %4.4x", - get_unaligned(((u16*)yp->rx_ring[i].addr) + j)); - printk("\n"); + pr_cont(" %04x", + get_unaligned(((u16*)yp->rx_ring[i].addr) + j)); + pr_cont("\n"); } } } @@ -1281,8 +1275,8 @@ static int yellowfin_close(struct net_device *dev) #ifdef YF_PROTOTYPE /* Support for prototype hardware errata. */ if (yellowfin_debug > 0) { - printk(KERN_DEBUG "%s: Received %d frames that we should not have.\n", - dev->name, bogus_rx); + netdev_printk(KERN_DEBUG, dev, "Received %d frames that we should not have\n", + bogus_rx); } #endif -- cgit v1.2.3 From dfa1a041094f4a6e5845a19a1b10e317676722e7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 18:48:11 -0800 Subject: drivers/net/tehuti.c: Reapply use DEFINE_PCI_DEVICE_TABLE() Commit 865a21a5e3d1b384c559a44c898fcad93e187b82 overwrote commit a3aa18842a5303fc28fcc4d57dbd16618bd830a0 Fix it. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tehuti.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index b295b926bc45..2517cc00ac2a 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -66,7 +66,7 @@ #include "tehuti.h" -static struct pci_device_id __devinitdata bdx_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(bdx_pci_tbl) = { {0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x1FC9, 0x3014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, -- cgit v1.2.3 From 6457d26bd40077238799e31df2b800bcf4ef9177 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 Feb 2010 18:48:44 -0800 Subject: IPv6: convert mc_lock to spinlock Only used for writing, so convert to spinlock Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/if_inet6.h | 2 +- net/ipv6/mcast.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index e9d69d198495..545d8b059bef 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -157,7 +157,7 @@ struct inet6_dev { struct ifmcaddr6 *mc_list; struct ifmcaddr6 *mc_tomb; - rwlock_t mc_lock; + spinlock_t mc_lock; unsigned char mc_qrv; unsigned char mc_gq_running; unsigned char mc_ifc_count; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 25f6cca79e6b..bcd971915969 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -793,10 +793,10 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) } spin_unlock_bh(&im->mca_lock); - write_lock_bh(&idev->mc_lock); + spin_lock_bh(&idev->mc_lock); pmc->next = idev->mc_tomb; idev->mc_tomb = pmc; - write_unlock_bh(&idev->mc_lock); + spin_unlock_bh(&idev->mc_lock); } static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) @@ -804,7 +804,7 @@ static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) struct ifmcaddr6 *pmc, *pmc_prev; struct ip6_sf_list *psf, *psf_next; - write_lock_bh(&idev->mc_lock); + spin_lock_bh(&idev->mc_lock); pmc_prev = NULL; for (pmc=idev->mc_tomb; pmc; pmc=pmc->next) { if (ipv6_addr_equal(&pmc->mca_addr, pmca)) @@ -817,7 +817,8 @@ static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) else idev->mc_tomb = pmc->next; } - write_unlock_bh(&idev->mc_lock); + spin_unlock_bh(&idev->mc_lock); + if (pmc) { for (psf=pmc->mca_tomb; psf; psf=psf_next) { psf_next = psf->sf_next; @@ -832,10 +833,10 @@ static void mld_clear_delrec(struct inet6_dev *idev) { struct ifmcaddr6 *pmc, *nextpmc; - write_lock_bh(&idev->mc_lock); + spin_lock_bh(&idev->mc_lock); pmc = idev->mc_tomb; idev->mc_tomb = NULL; - write_unlock_bh(&idev->mc_lock); + spin_unlock_bh(&idev->mc_lock); for (; pmc; pmc = nextpmc) { nextpmc = pmc->next; @@ -1696,7 +1697,7 @@ static void mld_send_cr(struct inet6_dev *idev) int type, dtype; read_lock_bh(&idev->lock); - write_lock_bh(&idev->mc_lock); + spin_lock(&idev->mc_lock); /* deleted MCA's */ pmc_prev = NULL; @@ -1730,7 +1731,7 @@ static void mld_send_cr(struct inet6_dev *idev) } else pmc_prev = pmc; } - write_unlock_bh(&idev->mc_lock); + spin_unlock(&idev->mc_lock); /* change recs */ for (pmc=idev->mc_list; pmc; pmc=pmc->next) { @@ -2311,7 +2312,7 @@ void ipv6_mc_up(struct inet6_dev *idev) void ipv6_mc_init_dev(struct inet6_dev *idev) { write_lock_bh(&idev->lock); - rwlock_init(&idev->mc_lock); + spin_lock_init(&idev->mc_lock); idev->mc_gq_running = 0; setup_timer(&idev->mc_gq_timer, mld_gq_timer_expire, (unsigned long)idev); -- cgit v1.2.3 From 2906f66a5682e5670a5eefe991843689b8d8563f Mon Sep 17 00:00:00 2001 From: Venkata Mohan Reddy Date: Thu, 18 Feb 2010 12:31:05 +0100 Subject: ipvs: SCTP Trasport Loadbalancing Support Enhance IPVS to load balance SCTP transport protocol packets. This is done based on the SCTP rfc 4960. All possible control chunks have been taken care. The state machine used in this code looks some what lengthy. I tried to make the state machine easy to understand. Signed-off-by: Venkata Mohan Reddy Koppula Signed-off-by: Simon Horman Signed-off-by: Patrick McHardy --- include/net/ip_vs.h | 22 +- net/netfilter/ipvs/Kconfig | 7 + net/netfilter/ipvs/Makefile | 1 + net/netfilter/ipvs/ip_vs_core.c | 62 +- net/netfilter/ipvs/ip_vs_ctl.c | 5 +- net/netfilter/ipvs/ip_vs_proto.c | 3 + net/netfilter/ipvs/ip_vs_proto_sctp.c | 1183 +++++++++++++++++++++++++++++++++ net/netfilter/ipvs/ip_vs_sync.c | 14 + 8 files changed, 1285 insertions(+), 12 deletions(-) create mode 100644 net/netfilter/ipvs/ip_vs_proto_sctp.c diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index a816c37417bb..fe82b1e10a29 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -224,6 +224,26 @@ enum { IP_VS_ICMP_S_LAST, }; +/* + * SCTP State Values + */ +enum ip_vs_sctp_states { + IP_VS_SCTP_S_NONE, + IP_VS_SCTP_S_INIT_CLI, + IP_VS_SCTP_S_INIT_SER, + IP_VS_SCTP_S_INIT_ACK_CLI, + IP_VS_SCTP_S_INIT_ACK_SER, + IP_VS_SCTP_S_ECHO_CLI, + IP_VS_SCTP_S_ECHO_SER, + IP_VS_SCTP_S_ESTABLISHED, + IP_VS_SCTP_S_SHUT_CLI, + IP_VS_SCTP_S_SHUT_SER, + IP_VS_SCTP_S_SHUT_ACK_CLI, + IP_VS_SCTP_S_SHUT_ACK_SER, + IP_VS_SCTP_S_CLOSED, + IP_VS_SCTP_S_LAST +}; + /* * Delta sequence info structure * Each ip_vs_conn has 2 (output AND input seq. changes). @@ -741,7 +761,7 @@ extern struct ip_vs_protocol ip_vs_protocol_udp; extern struct ip_vs_protocol ip_vs_protocol_icmp; extern struct ip_vs_protocol ip_vs_protocol_esp; extern struct ip_vs_protocol ip_vs_protocol_ah; - +extern struct ip_vs_protocol ip_vs_protocol_sctp; /* * Registering/unregistering scheduler functions diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 817a8898203b..712ccad13344 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig @@ -104,6 +104,13 @@ config IP_VS_PROTO_AH This option enables support for load balancing AH (Authentication Header) transport protocol. Say Y if unsure. +config IP_VS_PROTO_SCTP + bool "SCTP load balancing support" + select LIBCRC32C + ---help--- + This option enables support for load balancing SCTP transport + protocol. Say Y if unsure. + comment "IPVS scheduler" config IP_VS_RR diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile index 73a46fe1fe4c..e3baefd7066e 100644 --- a/net/netfilter/ipvs/Makefile +++ b/net/netfilter/ipvs/Makefile @@ -7,6 +7,7 @@ ip_vs_proto-objs-y := ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_TCP) += ip_vs_proto_tcp.o ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_UDP) += ip_vs_proto_udp.o ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH_ESP) += ip_vs_proto_ah_esp.o +ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_SCTP) += ip_vs_proto_sctp.o ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \ ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \ diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 847ffca40184..72e96d823ebf 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,8 @@ const char *ip_vs_proto_name(unsigned proto) return "UDP"; case IPPROTO_TCP: return "TCP"; + case IPPROTO_SCTP: + return "SCTP"; case IPPROTO_ICMP: return "ICMP"; #ifdef CONFIG_IP_VS_IPV6 @@ -589,8 +592,9 @@ void ip_vs_nat_icmp(struct sk_buff *skb, struct ip_vs_protocol *pp, ip_send_check(ciph); } - /* the TCP/UDP port */ - if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol) { + /* the TCP/UDP/SCTP port */ + if (IPPROTO_TCP == ciph->protocol || IPPROTO_UDP == ciph->protocol || + IPPROTO_SCTP == ciph->protocol) { __be16 *ports = (void *)ciph + ciph->ihl*4; if (inout) @@ -630,8 +634,9 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, ciph->saddr = cp->daddr.in6; } - /* the TCP/UDP port */ - if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr) { + /* the TCP/UDP/SCTP port */ + if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr || + IPPROTO_SCTP == ciph->nexthdr) { __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr); if (inout) @@ -679,7 +684,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb, goto out; } - if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol) + if (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol || + IPPROTO_SCTP == protocol) offset += 2 * sizeof(__u16); if (!skb_make_writable(skb, offset)) goto out; @@ -857,6 +863,21 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related) } #endif +/* + * Check if sctp chunc is ABORT chunk + */ +static inline int is_sctp_abort(const struct sk_buff *skb, int nh_len) +{ + sctp_chunkhdr_t *sch, schunk; + sch = skb_header_pointer(skb, nh_len + sizeof(sctp_sctphdr_t), + sizeof(schunk), &schunk); + if (sch == NULL) + return 0; + if (sch->type == SCTP_CID_ABORT) + return 1; + return 0; +} + static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len) { struct tcphdr _tcph, *th; @@ -999,7 +1020,8 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, if (unlikely(!cp)) { if (sysctl_ip_vs_nat_icmp_send && (pp->protocol == IPPROTO_TCP || - pp->protocol == IPPROTO_UDP)) { + pp->protocol == IPPROTO_UDP || + pp->protocol == IPPROTO_SCTP)) { __be16 _ports[2], *pptr; pptr = skb_header_pointer(skb, iph.len, @@ -1014,8 +1036,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, * existing entry if it is not RST * packet or not TCP packet. */ - if (iph.protocol != IPPROTO_TCP - || !is_tcp_reset(skb, iph.len)) { + if ((iph.protocol != IPPROTO_TCP && + iph.protocol != IPPROTO_SCTP) + || ((iph.protocol == IPPROTO_TCP + && !is_tcp_reset(skb, iph.len)) + || (iph.protocol == IPPROTO_SCTP + && !is_sctp_abort(skb, + iph.len)))) { #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) icmpv6_send(skb, @@ -1235,7 +1262,8 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); - if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr) + if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || + IPPROTO_SCTP == cih->nexthdr) offset += 2 * sizeof(__u16); verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); /* do not touch skb anymore */ @@ -1358,6 +1386,21 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, * encorage the standby servers to update the connections timeout */ pkts = atomic_add_return(1, &cp->in_pkts); + if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) && + cp->protocol == IPPROTO_SCTP) { + if ((cp->state == IP_VS_SCTP_S_ESTABLISHED && + (atomic_read(&cp->in_pkts) % + sysctl_ip_vs_sync_threshold[1] + == sysctl_ip_vs_sync_threshold[0])) || + (cp->old_state != cp->state && + ((cp->state == IP_VS_SCTP_S_CLOSED) || + (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) || + (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) { + ip_vs_sync_conn(cp); + goto out; + } + } + if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) && (((cp->protocol != IPPROTO_TCP || @@ -1370,6 +1413,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, (cp->state == IP_VS_TCP_S_CLOSE_WAIT) || (cp->state == IP_VS_TCP_S_TIME_WAIT))))) ip_vs_sync_conn(cp); +out: cp->old_state = cp->state; ip_vs_conn_put(cp); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 00d0b152db39..7ee9c3426f44 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2132,8 +2132,9 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) } } - /* Check for valid protocol: TCP or UDP, even for fwmark!=0 */ - if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) { + /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ + if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && + usvc.protocol != IPPROTO_SCTP) { pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", usvc.protocol, &usvc.addr.ip, ntohs(usvc.port), usvc.sched_name); diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 3e7671674549..0e584553819d 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c @@ -257,6 +257,9 @@ int __init ip_vs_protocol_init(void) #ifdef CONFIG_IP_VS_PROTO_UDP REGISTER_PROTOCOL(&ip_vs_protocol_udp); #endif +#ifdef CONFIG_IP_VS_PROTO_SCTP + REGISTER_PROTOCOL(&ip_vs_protocol_sctp); +#endif #ifdef CONFIG_IP_VS_PROTO_AH REGISTER_PROTOCOL(&ip_vs_protocol_ah); #endif diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c new file mode 100644 index 000000000000..c9a3f7a21d53 --- /dev/null +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -0,0 +1,1183 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static struct ip_vs_conn * +sctp_conn_in_get(int af, + const struct sk_buff *skb, + struct ip_vs_protocol *pp, + const struct ip_vs_iphdr *iph, + unsigned int proto_off, + int inverse) +{ + __be16 _ports[2], *pptr; + + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); + if (pptr == NULL) + return NULL; + + if (likely(!inverse)) + return ip_vs_conn_in_get(af, iph->protocol, + &iph->saddr, pptr[0], + &iph->daddr, pptr[1]); + else + return ip_vs_conn_in_get(af, iph->protocol, + &iph->daddr, pptr[1], + &iph->saddr, pptr[0]); +} + +static struct ip_vs_conn * +sctp_conn_out_get(int af, + const struct sk_buff *skb, + struct ip_vs_protocol *pp, + const struct ip_vs_iphdr *iph, + unsigned int proto_off, + int inverse) +{ + __be16 _ports[2], *pptr; + + pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports); + if (pptr == NULL) + return NULL; + + if (likely(!inverse)) + return ip_vs_conn_out_get(af, iph->protocol, + &iph->saddr, pptr[0], + &iph->daddr, pptr[1]); + else + return ip_vs_conn_out_get(af, iph->protocol, + &iph->daddr, pptr[1], + &iph->saddr, pptr[0]); +} + +static int +sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, + int *verdict, struct ip_vs_conn **cpp) +{ + struct ip_vs_service *svc; + sctp_chunkhdr_t _schunkh, *sch; + sctp_sctphdr_t *sh, _sctph; + struct ip_vs_iphdr iph; + + ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); + + sh = skb_header_pointer(skb, iph.len, sizeof(_sctph), &_sctph); + if (sh == NULL) + return 0; + + sch = skb_header_pointer(skb, iph.len + sizeof(sctp_sctphdr_t), + sizeof(_schunkh), &_schunkh); + if (sch == NULL) + return 0; + + if ((sch->type == SCTP_CID_INIT) && + (svc = ip_vs_service_get(af, skb->mark, iph.protocol, + &iph.daddr, sh->dest))) { + if (ip_vs_todrop()) { + /* + * It seems that we are very loaded. + * We have to drop this packet :( + */ + ip_vs_service_put(svc); + *verdict = NF_DROP; + return 0; + } + /* + * Let the virtual server select a real server for the + * incoming connection, and create a connection entry. + */ + *cpp = ip_vs_schedule(svc, skb); + if (!*cpp) { + *verdict = ip_vs_leave(svc, skb, pp); + return 0; + } + ip_vs_service_put(svc); + } + + return 1; +} + +static int +sctp_snat_handler(struct sk_buff *skb, + struct ip_vs_protocol *pp, struct ip_vs_conn *cp) +{ + sctp_sctphdr_t *sctph; + unsigned int sctphoff; + __be32 crc32; + +#ifdef CONFIG_IP_VS_IPV6 + if (cp->af == AF_INET6) + sctphoff = sizeof(struct ipv6hdr); + else +#endif + sctphoff = ip_hdrlen(skb); + + /* csum_check requires unshared skb */ + if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) + return 0; + + if (unlikely(cp->app != NULL)) { + /* Some checks before mangling */ + if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) + return 0; + + /* Call application helper if needed */ + if (!ip_vs_app_pkt_out(cp, skb)) + return 0; + } + + sctph = (void *) skb_network_header(skb) + sctphoff; + sctph->source = cp->vport; + + /* Calculate the checksum */ + crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff); + for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) + crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb), + crc32); + crc32 = sctp_end_cksum(crc32); + sctph->checksum = crc32; + + return 1; +} + +static int +sctp_dnat_handler(struct sk_buff *skb, + struct ip_vs_protocol *pp, struct ip_vs_conn *cp) +{ + + sctp_sctphdr_t *sctph; + unsigned int sctphoff; + __be32 crc32; + +#ifdef CONFIG_IP_VS_IPV6 + if (cp->af == AF_INET6) + sctphoff = sizeof(struct ipv6hdr); + else +#endif + sctphoff = ip_hdrlen(skb); + + /* csum_check requires unshared skb */ + if (!skb_make_writable(skb, sctphoff + sizeof(*sctph))) + return 0; + + if (unlikely(cp->app != NULL)) { + /* Some checks before mangling */ + if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) + return 0; + + /* Call application helper if needed */ + if (!ip_vs_app_pkt_out(cp, skb)) + return 0; + } + + sctph = (void *) skb_network_header(skb) + sctphoff; + sctph->dest = cp->dport; + + /* Calculate the checksum */ + crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff); + for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) + crc32 = sctp_update_cksum((u8 *) skb->data, skb_headlen(skb), + crc32); + crc32 = sctp_end_cksum(crc32); + sctph->checksum = crc32; + + return 1; +} + +static int +sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) +{ + struct sk_buff *list = skb_shinfo(skb)->frag_list; + unsigned int sctphoff; + struct sctphdr *sh, _sctph; + __le32 cmp; + __le32 val; + __u32 tmp; + +#ifdef CONFIG_IP_VS_IPV6 + if (af == AF_INET6) + sctphoff = sizeof(struct ipv6hdr); + else +#endif + sctphoff = ip_hdrlen(skb); + + sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph); + if (sh == NULL) + return 0; + + cmp = sh->checksum; + + tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb)); + for (; list; list = list->next) + tmp = sctp_update_cksum((__u8 *) list->data, + skb_headlen(list), tmp); + + val = sctp_end_cksum(tmp); + + if (val != cmp) { + /* CRC failure, dump it. */ + IP_VS_DBG_RL_PKT(0, pp, skb, 0, + "Failed checksum for"); + return 0; + } + return 1; +} + +struct ipvs_sctp_nextstate { + int next_state; +}; +enum ipvs_sctp_event_t { + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_DATA_SER, + IP_VS_SCTP_EVE_INIT_CLI, + IP_VS_SCTP_EVE_INIT_SER, + IP_VS_SCTP_EVE_INIT_ACK_CLI, + IP_VS_SCTP_EVE_INIT_ACK_SER, + IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, + IP_VS_SCTP_EVE_COOKIE_ECHO_SER, + IP_VS_SCTP_EVE_COOKIE_ACK_CLI, + IP_VS_SCTP_EVE_COOKIE_ACK_SER, + IP_VS_SCTP_EVE_ABORT_CLI, + IP_VS_SCTP_EVE__ABORT_SER, + IP_VS_SCTP_EVE_SHUT_CLI, + IP_VS_SCTP_EVE_SHUT_SER, + IP_VS_SCTP_EVE_SHUT_ACK_CLI, + IP_VS_SCTP_EVE_SHUT_ACK_SER, + IP_VS_SCTP_EVE_SHUT_COM_CLI, + IP_VS_SCTP_EVE_SHUT_COM_SER, + IP_VS_SCTP_EVE_LAST +}; + +static enum ipvs_sctp_event_t sctp_events[255] = { + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_INIT_CLI, + IP_VS_SCTP_EVE_INIT_ACK_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_ABORT_CLI, + IP_VS_SCTP_EVE_SHUT_CLI, + IP_VS_SCTP_EVE_SHUT_ACK_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_COOKIE_ECHO_CLI, + IP_VS_SCTP_EVE_COOKIE_ACK_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_DATA_CLI, + IP_VS_SCTP_EVE_SHUT_COM_CLI, +}; + +static struct ipvs_sctp_nextstate + sctp_states_table[IP_VS_SCTP_S_LAST][IP_VS_SCTP_EVE_LAST] = { + /* + * STATE : IP_VS_SCTP_S_NONE + */ + /*next state *//*event */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ }, + }, + /* + * STATE : IP_VS_SCTP_S_INIT_CLI + * Cient sent INIT and is waiting for reply from server(In ECHO_WAIT) + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ECHO_CLI */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_ECHO_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_INIT_SER + * Server sent INIT and waiting for INIT ACK from the client + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_INIT_ACK_CLI + * Client sent INIT ACK and waiting for ECHO from the server + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK has been resent by the client, let us stay is in + * the same state + */ + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + /* + * INIT_ACK sent by the server, close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * ECHO by client, it should not happen, close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + /* + * ECHO by server, this is what we are expecting, move to ECHO_SER + */ + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, it should not happen, close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + /* + * Unexpected COOKIE ACK from server, staty in the same state + */ + {IP_VS_SCTP_S_INIT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_INIT_ACK_SER + * Server sent INIT ACK and waiting for ECHO from the client + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * Unexpected INIT_ACK by the client, let us close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + /* + * INIT_ACK resent by the server, let us move to same state + */ + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client send the ECHO, this is what we are expecting, + * move to ECHO_CLI + */ + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + /* + * ECHO received from the server, Not sure what to do, + * let us close it + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, let us stay in the same state + */ + {IP_VS_SCTP_S_INIT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + /* + * COOKIE ACK from server, hmm... this should not happen, lets close + * the connection. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_ECHO_CLI + * Cient sent ECHO and waiting COOKEI ACK from the Server + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK has been by the client, let us close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client resent the ECHO, let us stay in the same state + */ + {IP_VS_SCTP_S_ECHO_CLI /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + /* + * ECHO received from the server, Not sure what to do, + * let us close it + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, this shoud not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + /* + * COOKIE ACK from server, this is what we are awaiting,lets move to + * ESTABLISHED. + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_ECHO_SER + * Server sent ECHO and waiting COOKEI ACK from the client + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + /* + * INIT_ACK has been by the server, let us close the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent the ECHO, not sure what to do, let's close the + * connection. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + /* + * ECHO resent by the server, stay in the same state + */ + {IP_VS_SCTP_S_ECHO_SER /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, this is what we are expecting, let's move + * to ESTABLISHED. + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + /* + * COOKIE ACK from server, this should not happen, lets close the + * connection. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_ESTABLISHED + * Association established + */ + {{IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the + * peer and peer shall move to the ESTABISHED. if it doesn't handle + * it will send ERROR chunk. So, stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, not sure what to do stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + /* + * SHUTDOWN from the client, move to SHUDDOWN_CLI + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + /* + * SHUTDOWN from the server, move to SHUTDOWN_SER + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, + /* + * client sent SHUDTDOWN_ACK, this should not happen, let's close + * the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_SHUT_CLI + * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server + */ + /* + * We recieved the data chuck, keep the state unchanged. I assume + * that still data chuncks can be received by both the peers in + * SHUDOWN state + */ + + {{IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the + * peer and peer shall move to the ESTABISHED. if it doesn't handle + * it will send ERROR chunk. So, stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, not sure what to do stay in the same state + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + /* + * SHUTDOWN resent from the client, move to SHUDDOWN_CLI + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + /* + * SHUTDOWN from the server, move to SHUTDOWN_SER + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, + /* + * client sent SHUDTDOWN_ACK, this should not happen, let's close + * the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + /* + * Server sent SHUTDOWN ACK, this is what we are expecting, let's move + * to SHUDOWN_ACK_SER + */ + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + /* + * SHUTDOWN COM from client, this should not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_SHUT_SER + * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client + */ + /* + * We recieved the data chuck, keep the state unchanged. I assume + * that still data chuncks can be received by both the peers in + * SHUDOWN state + */ + + {{IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the + * peer and peer shall move to the ESTABISHED. if it doesn't handle + * it will send ERROR chunk. So, stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, not sure what to do stay in the same state + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + /* + * SHUTDOWN resent from the client, move to SHUDDOWN_CLI + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + /* + * SHUTDOWN resent from the server, move to SHUTDOWN_SER + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, + /* + * client sent SHUDTDOWN_ACK, this is what we are expecting, let's + * move to SHUT_ACK_CLI + */ + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + /* + * Server sent SHUTDOWN ACK, this should not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + /* + * SHUTDOWN COM from client, this should not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + + /* + * State : IP_VS_SCTP_S_SHUT_ACK_CLI + * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server + */ + /* + * We recieved the data chuck, keep the state unchanged. I assume + * that still data chuncks can be received by both the peers in + * SHUDOWN state + */ + + {{IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the + * peer and peer shall move to the ESTABISHED. if it doesn't handle + * it will send ERROR chunk. So, stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, not sure what to do stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + /* + * SHUTDOWN sent from the client, move to SHUDDOWN_CLI + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + /* + * SHUTDOWN sent from the server, move to SHUTDOWN_SER + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, + /* + * client resent SHUDTDOWN_ACK, let's stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_CLI /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + /* + * Server sent SHUTDOWN ACK, this should not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + /* + * SHUTDOWN COM from client, this should not happen, let's close the + * connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + /* + * SHUTDOWN COMPLETE from server this is what we are expecting. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + + /* + * State : IP_VS_SCTP_S_SHUT_ACK_SER + * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client + */ + /* + * We recieved the data chuck, keep the state unchanged. I assume + * that still data chuncks can be received by both the peers in + * SHUDOWN state + */ + + {{IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_DATA_SER */ }, + /* + * We have got an INIT from client. From the spec.“Upon receipt of + * an INIT in the COOKIE-WAIT state, an endpoint MUST respond with + * an INIT ACK using the same parameters it sent in its original + * INIT chunk (including its Initiate Tag, unchanged”). + */ + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + /* + * INIT_ACK sent by the server, Unexpected INIT ACK, spec says, + * “If an INIT ACK is received by an endpoint in any state other + * than the COOKIE-WAIT state, the endpoint should discard the + * INIT ACK chunk”. Stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + /* + * Client sent ECHO, Spec(sec 5.2.4) says it may be handled by the + * peer and peer shall move to the ESTABISHED. if it doesn't handle + * it will send ERROR chunk. So, stay in the same state + */ + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_ESTABLISHED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + /* + * COOKIE ACK from client, not sure what to do stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + /* + * SHUTDOWN sent from the client, move to SHUDDOWN_CLI + */ + {IP_VS_SCTP_S_SHUT_CLI /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + /* + * SHUTDOWN sent from the server, move to SHUTDOWN_SER + */ + {IP_VS_SCTP_S_SHUT_SER /* IP_VS_SCTP_EVE_SHUT_SER */ }, + /* + * client sent SHUDTDOWN_ACK, this should not happen let's close + * the connection. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + /* + * Server resent SHUTDOWN ACK, stay in the same state + */ + {IP_VS_SCTP_S_SHUT_ACK_SER /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + /* + * SHUTDOWN COM from client, this what we are expecting, let's close + * the connection + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + /* + * SHUTDOWN COMPLETE from server this should not happen. + */ + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + }, + /* + * State : IP_VS_SCTP_S_CLOSED + */ + {{IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_DATA_SER */ }, + {IP_VS_SCTP_S_INIT_CLI /* IP_VS_SCTP_EVE_INIT_CLI */ }, + {IP_VS_SCTP_S_INIT_SER /* IP_VS_SCTP_EVE_INIT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_INIT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ECHO_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_COOKIE_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_ABORT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_ACK_SER */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_CLI */ }, + {IP_VS_SCTP_S_CLOSED /* IP_VS_SCTP_EVE_SHUT_COM_SER */ } + } +}; + +/* + * Timeout table[state] + */ +static int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = { + [IP_VS_SCTP_S_NONE] = 2 * HZ, + [IP_VS_SCTP_S_INIT_CLI] = 1 * 60 * HZ, + [IP_VS_SCTP_S_INIT_SER] = 1 * 60 * HZ, + [IP_VS_SCTP_S_INIT_ACK_CLI] = 1 * 60 * HZ, + [IP_VS_SCTP_S_INIT_ACK_SER] = 1 * 60 * HZ, + [IP_VS_SCTP_S_ECHO_CLI] = 1 * 60 * HZ, + [IP_VS_SCTP_S_ECHO_SER] = 1 * 60 * HZ, + [IP_VS_SCTP_S_ESTABLISHED] = 15 * 60 * HZ, + [IP_VS_SCTP_S_SHUT_CLI] = 1 * 60 * HZ, + [IP_VS_SCTP_S_SHUT_SER] = 1 * 60 * HZ, + [IP_VS_SCTP_S_SHUT_ACK_CLI] = 1 * 60 * HZ, + [IP_VS_SCTP_S_SHUT_ACK_SER] = 1 * 60 * HZ, + [IP_VS_SCTP_S_CLOSED] = 10 * HZ, + [IP_VS_SCTP_S_LAST] = 2 * HZ, +}; + +static const char *sctp_state_name_table[IP_VS_SCTP_S_LAST + 1] = { + [IP_VS_SCTP_S_NONE] = "NONE", + [IP_VS_SCTP_S_INIT_CLI] = "INIT_CLI", + [IP_VS_SCTP_S_INIT_SER] = "INIT_SER", + [IP_VS_SCTP_S_INIT_ACK_CLI] = "INIT_ACK_CLI", + [IP_VS_SCTP_S_INIT_ACK_SER] = "INIT_ACK_SER", + [IP_VS_SCTP_S_ECHO_CLI] = "COOKIE_ECHO_CLI", + [IP_VS_SCTP_S_ECHO_SER] = "COOKIE_ECHO_SER", + [IP_VS_SCTP_S_ESTABLISHED] = "ESTABISHED", + [IP_VS_SCTP_S_SHUT_CLI] = "SHUTDOWN_CLI", + [IP_VS_SCTP_S_SHUT_SER] = "SHUTDOWN_SER", + [IP_VS_SCTP_S_SHUT_ACK_CLI] = "SHUTDOWN_ACK_CLI", + [IP_VS_SCTP_S_SHUT_ACK_SER] = "SHUTDOWN_ACK_SER", + [IP_VS_SCTP_S_CLOSED] = "CLOSED", + [IP_VS_SCTP_S_LAST] = "BUG!" +}; + + +static const char *sctp_state_name(int state) +{ + if (state >= IP_VS_SCTP_S_LAST) + return "ERR!"; + if (sctp_state_name_table[state]) + return sctp_state_name_table[state]; + return "?"; +} + +static void sctp_timeout_change(struct ip_vs_protocol *pp, int flags) +{ +} + +static int +sctp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to) +{ + +return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_SCTP_S_LAST, + sctp_state_name_table, sname, to); +} + +static inline int +set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp, + int direction, const struct sk_buff *skb) +{ + sctp_chunkhdr_t _sctpch, *sch; + unsigned char chunk_type; + int event, next_state; + int ihl; + +#ifdef CONFIG_IP_VS_IPV6 + ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr); +#else + ihl = ip_hdrlen(skb); +#endif + + sch = skb_header_pointer(skb, ihl + sizeof(sctp_sctphdr_t), + sizeof(_sctpch), &_sctpch); + if (sch == NULL) + return 0; + + chunk_type = sch->type; + /* + * Section 3: Multiple chunks can be bundled into one SCTP packet + * up to the MTU size, except for the INIT, INIT ACK, and + * SHUTDOWN COMPLETE chunks. These chunks MUST NOT be bundled with + * any other chunk in a packet. + * + * Section 3.3.7: DATA chunks MUST NOT be bundled with ABORT. Control + * chunks (except for INIT, INIT ACK, and SHUTDOWN COMPLETE) MAY be + * bundled with an ABORT, but they MUST be placed before the ABORT + * in the SCTP packet or they will be ignored by the receiver. + */ + if ((sch->type == SCTP_CID_COOKIE_ECHO) || + (sch->type == SCTP_CID_COOKIE_ACK)) { + sch = skb_header_pointer(skb, (ihl + sizeof(sctp_sctphdr_t) + + sch->length), sizeof(_sctpch), &_sctpch); + if (sch) { + if (sch->type == SCTP_CID_ABORT) + chunk_type = sch->type; + } + } + + event = sctp_events[chunk_type]; + + /* + * If the direction is IP_VS_DIR_OUTPUT, this event is from server + */ + if (direction == IP_VS_DIR_OUTPUT) + event++; + /* + * get next state + */ + next_state = sctp_states_table[cp->state][event].next_state; + + if (next_state != cp->state) { + struct ip_vs_dest *dest = cp->dest; + + IP_VS_DBG_BUF(8, "%s %s %s:%d->" + "%s:%d state: %s->%s conn->refcnt:%d\n", + pp->name, + ((direction == IP_VS_DIR_OUTPUT) ? + "output " : "input "), + IP_VS_DBG_ADDR(cp->af, &cp->daddr), + ntohs(cp->dport), + IP_VS_DBG_ADDR(cp->af, &cp->caddr), + ntohs(cp->cport), + sctp_state_name(cp->state), + sctp_state_name(next_state), + atomic_read(&cp->refcnt)); + if (dest) { + if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && + (next_state != IP_VS_SCTP_S_ESTABLISHED)) { + atomic_dec(&dest->activeconns); + atomic_inc(&dest->inactconns); + cp->flags |= IP_VS_CONN_F_INACTIVE; + } else if ((cp->flags & IP_VS_CONN_F_INACTIVE) && + (next_state == IP_VS_SCTP_S_ESTABLISHED)) { + atomic_inc(&dest->activeconns); + atomic_dec(&dest->inactconns); + cp->flags &= ~IP_VS_CONN_F_INACTIVE; + } + } + } + + cp->timeout = pp->timeout_table[cp->state = next_state]; + + return 1; +} + +static int +sctp_state_transition(struct ip_vs_conn *cp, int direction, + const struct sk_buff *skb, struct ip_vs_protocol *pp) +{ + int ret = 0; + + spin_lock(&cp->lock); + ret = set_sctp_state(pp, cp, direction, skb); + spin_unlock(&cp->lock); + + return ret; +} + +/* + * Hash table for SCTP application incarnations + */ +#define SCTP_APP_TAB_BITS 4 +#define SCTP_APP_TAB_SIZE (1 << SCTP_APP_TAB_BITS) +#define SCTP_APP_TAB_MASK (SCTP_APP_TAB_SIZE - 1) + +static struct list_head sctp_apps[SCTP_APP_TAB_SIZE]; +static DEFINE_SPINLOCK(sctp_app_lock); + +static inline __u16 sctp_app_hashkey(__be16 port) +{ + return (((__force u16)port >> SCTP_APP_TAB_BITS) ^ (__force u16)port) + & SCTP_APP_TAB_MASK; +} + +static int sctp_register_app(struct ip_vs_app *inc) +{ + struct ip_vs_app *i; + __u16 hash; + __be16 port = inc->port; + int ret = 0; + + hash = sctp_app_hashkey(port); + + spin_lock_bh(&sctp_app_lock); + list_for_each_entry(i, &sctp_apps[hash], p_list) { + if (i->port == port) { + ret = -EEXIST; + goto out; + } + } + list_add(&inc->p_list, &sctp_apps[hash]); + atomic_inc(&ip_vs_protocol_sctp.appcnt); +out: + spin_unlock_bh(&sctp_app_lock); + + return ret; +} + +static void sctp_unregister_app(struct ip_vs_app *inc) +{ + spin_lock_bh(&sctp_app_lock); + atomic_dec(&ip_vs_protocol_sctp.appcnt); + list_del(&inc->p_list); + spin_unlock_bh(&sctp_app_lock); +} + +static int sctp_app_conn_bind(struct ip_vs_conn *cp) +{ + int hash; + struct ip_vs_app *inc; + int result = 0; + + /* Default binding: bind app only for NAT */ + if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) + return 0; + /* Lookup application incarnations and bind the right one */ + hash = sctp_app_hashkey(cp->vport); + + spin_lock(&sctp_app_lock); + list_for_each_entry(inc, &sctp_apps[hash], p_list) { + if (inc->port == cp->vport) { + if (unlikely(!ip_vs_app_inc_get(inc))) + break; + spin_unlock(&sctp_app_lock); + + IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->" + "%s:%u to app %s on port %u\n", + __func__, + IP_VS_DBG_ADDR(cp->af, &cp->caddr), + ntohs(cp->cport), + IP_VS_DBG_ADDR(cp->af, &cp->vaddr), + ntohs(cp->vport), + inc->name, ntohs(inc->port)); + cp->app = inc; + if (inc->init_conn) + result = inc->init_conn(inc, cp); + goto out; + } + } + spin_unlock(&sctp_app_lock); +out: + return result; +} + +static void ip_vs_sctp_init(struct ip_vs_protocol *pp) +{ + IP_VS_INIT_HASH_TABLE(sctp_apps); + pp->timeout_table = sctp_timeouts; +} + + +static void ip_vs_sctp_exit(struct ip_vs_protocol *pp) +{ + +} + +struct ip_vs_protocol ip_vs_protocol_sctp = { + .name = "SCTP", + .protocol = IPPROTO_SCTP, + .num_states = IP_VS_SCTP_S_LAST, + .dont_defrag = 0, + .appcnt = ATOMIC_INIT(0), + .init = ip_vs_sctp_init, + .exit = ip_vs_sctp_exit, + .register_app = sctp_register_app, + .unregister_app = sctp_unregister_app, + .conn_schedule = sctp_conn_schedule, + .conn_in_get = sctp_conn_in_get, + .conn_out_get = sctp_conn_out_get, + .snat_handler = sctp_snat_handler, + .dnat_handler = sctp_dnat_handler, + .csum_check = sctp_csum_check, + .state_name = sctp_state_name, + .state_transition = sctp_state_transition, + .app_conn_bind = sctp_app_conn_bind, + .debug_packet = ip_vs_tcpudp_debug_packet, + .timeout_change = sctp_timeout_change, + .set_state_timeout = sctp_set_state_timeout, +}; diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index e177f0dc2084..8fb0ae616761 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -400,6 +400,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) flags |= IP_VS_CONN_F_INACTIVE; else flags &= ~IP_VS_CONN_F_INACTIVE; + } else if (s->protocol == IPPROTO_SCTP) { + if (state != IP_VS_SCTP_S_ESTABLISHED) + flags |= IP_VS_CONN_F_INACTIVE; + else + flags &= ~IP_VS_CONN_F_INACTIVE; } cp = ip_vs_conn_new(AF_INET, s->protocol, (union nf_inet_addr *)&s->caddr, @@ -434,6 +439,15 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) atomic_dec(&dest->inactconns); cp->flags &= ~IP_VS_CONN_F_INACTIVE; } + } else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) && + (cp->state != state)) { + dest = cp->dest; + if (!(cp->flags & IP_VS_CONN_F_INACTIVE) && + (state != IP_VS_SCTP_S_ESTABLISHED)) { + atomic_dec(&dest->activeconns); + atomic_inc(&dest->inactconns); + cp->flags &= ~IP_VS_CONN_F_INACTIVE; + } } if (opt) -- cgit v1.2.3 From 37ee3d5b3e979a168536e7e2f15bd1e769cb4122 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 18 Feb 2010 19:04:44 +0100 Subject: netfilter: nf_defrag_ipv4: fix compilation error with NF_CONNTRACK=n As reported by Randy Dunlap , compilation of nf_defrag_ipv4 fails with: include/net/netfilter/nf_conntrack.h:94: error: field 'ct_general' has incomplete type include/net/netfilter/nf_conntrack.h:178: error: 'const struct sk_buff' has no member named 'nfct' include/net/netfilter/nf_conntrack.h:185: error: implicit declaration of function 'nf_conntrack_put' include/net/netfilter/nf_conntrack.h:294: error: 'const struct sk_buff' has no member named 'nfct' net/ipv4/netfilter/nf_defrag_ipv4.c:45: error: 'struct sk_buff' has no member named 'nfct' net/ipv4/netfilter/nf_defrag_ipv4.c:46: error: 'struct sk_buff' has no member named 'nfct' net/nf_conntrack.h must not be included with NF_CONNTRACK=n, add a few #ifdefs. Long term the header file should be fixed to be usable even with NF_CONNTRACK=n. Tested-by: Randy Dunlap Signed-off-by: Patrick McHardy --- include/net/netfilter/nf_conntrack_zones.h | 6 ++++-- net/ipv4/netfilter/nf_defrag_ipv4.c | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h index 0bbb2bd51e89..034efe8d45a5 100644 --- a/include/net/netfilter/nf_conntrack_zones.h +++ b/include/net/netfilter/nf_conntrack_zones.h @@ -1,10 +1,11 @@ #ifndef _NF_CONNTRACK_ZONES_H #define _NF_CONNTRACK_ZONES_H -#include - #define NF_CT_DEFAULT_ZONE 0 +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) +#include + struct nf_conntrack_zone { u16 id; }; @@ -20,4 +21,5 @@ static inline u16 nf_ct_zone(const struct nf_conn *ct) return NF_CT_DEFAULT_ZONE; } +#endif /* CONFIG_NF_CONNTRACK || CONFIG_NF_CONNTRACK_MODULE */ #endif /* _NF_CONNTRACK_ZONES_H */ diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index d498a704d456..cb763ae9ed90 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c @@ -16,9 +16,11 @@ #include #include -#include #include +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #include +#endif +#include /* Returns new sk_buff, or NULL */ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) @@ -42,8 +44,10 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, { u16 zone = NF_CT_DEFAULT_ZONE; +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) if (skb->nfct) zone = nf_ct_zone((struct nf_conn *)skb->nfct); +#endif #ifdef CONFIG_BRIDGE_NETFILTER if (skb->nf_bridge && -- cgit v1.2.3 From 02df55d28c6001a3cdb7a997a34a0b01f01d015e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 Feb 2010 05:45:36 +0000 Subject: macvtap: rework object lifetime rules This reworks the change done by the previous patch in a more complete way. The original macvtap code has a number of problems resulting from the use of RCU for protecting the access to struct macvtap_queue from open files. This includes - need for GFP_ATOMIC allocations for skbs - potential deadlocks when copy_*_user sleeps - inability to work with vhost-net Changing the lifetime of macvtap_queue to always depend on the open file solves all these. The RCU reference simply moves one step down to the reference on the macvlan_dev, which we only need for nonblocking operations. Signed-off-by: Arnd Bergmann Acked-by: Sridhar Samudrala Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 183 +++++++++++++++++++++++++------------------------- 1 file changed, 91 insertions(+), 92 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index fe7656bf68c6..705099749766 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -60,30 +60,19 @@ static struct cdev macvtap_cdev; /* * RCU usage: - * The macvtap_queue is referenced both from the chardev struct file - * and from the struct macvlan_dev using rcu_read_lock. + * The macvtap_queue and the macvlan_dev are loosely coupled, the + * pointers from one to the other can only be read while rcu_read_lock + * or macvtap_lock is held. * - * We never actually update the contents of a macvtap_queue atomically - * with RCU but it is used for race-free destruction of a queue when - * either the file or the macvlan_dev goes away. Pointers back to - * the dev and the file are implicitly valid as long as the queue - * exists. + * Both the file and the macvlan_dev hold a reference on the macvtap_queue + * through sock_hold(&q->sk). When the macvlan_dev goes away first, + * q->vlan becomes inaccessible. When the files gets closed, + * macvtap_get_queue() fails. * - * The callbacks from macvlan are always done with rcu_read_lock held - * already. For calls from file_operations, we use the rcu_read_lock_bh - * to get a reference count on the socket and the device. - * - * When destroying a queue, we remove the pointers from the file and - * from the dev and then synchronize_rcu to make sure no thread is - * still using the queue. There may still be references to the struct - * sock inside of the queue from outbound SKBs, but these never - * reference back to the file or the dev. The data structure is freed - * through __sk_free when both our references and any pending SKBs - * are gone. - * - * macvtap_lock is only used to prevent multiple concurrent open() - * calls to assign a new vlan->tap pointer. It could be moved into - * the macvlan_dev itself but is extremely rarely used. + * There may still be references to the struct sock inside of the + * queue from outbound SKBs, but these never reference back to the + * file or the dev. The data structure is freed through __sk_free + * when both our references and any pending SKBs are gone. */ static DEFINE_SPINLOCK(macvtap_lock); @@ -101,11 +90,12 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file, goto out; err = 0; - q->vlan = vlan; + rcu_assign_pointer(q->vlan, vlan); rcu_assign_pointer(vlan->tap, q); + sock_hold(&q->sk); q->file = file; - rcu_assign_pointer(file->private_data, q); + file->private_data = q; out: spin_unlock(&macvtap_lock); @@ -113,28 +103,25 @@ out: } /* - * We must destroy each queue exactly once, when either - * the netdev or the file go away. + * The file owning the queue got closed, give up both + * the reference that the files holds as well as the + * one from the macvlan_dev if that still exists. * * Using the spinlock makes sure that we don't get * to the queue again after destroying it. - * - * synchronize_rcu serializes with the packet flow - * that uses rcu_read_lock. */ -static void macvtap_del_queue(struct macvtap_queue **qp) +static void macvtap_put_queue(struct macvtap_queue *q) { - struct macvtap_queue *q; + struct macvlan_dev *vlan; spin_lock(&macvtap_lock); - q = rcu_dereference(*qp); - if (!q) { - spin_unlock(&macvtap_lock); - return; + vlan = rcu_dereference(q->vlan); + if (vlan) { + rcu_assign_pointer(vlan->tap, NULL); + rcu_assign_pointer(q->vlan, NULL); + sock_put(&q->sk); } - rcu_assign_pointer(q->vlan->tap, NULL); - rcu_assign_pointer(q->file->private_data, NULL); spin_unlock(&macvtap_lock); synchronize_rcu(); @@ -152,29 +139,29 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, return rcu_dereference(vlan->tap); } +/* + * The net_device is going away, give up the reference + * that it holds on the queue (all the queues one day) + * and safely set the pointer from the queues to NULL. + */ static void macvtap_del_queues(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); - macvtap_del_queue(&vlan->tap); -} - -static inline struct macvtap_queue *macvtap_file_get_queue(struct file *file) -{ struct macvtap_queue *q; - rcu_read_lock_bh(); - q = rcu_dereference(file->private_data); - if (q) { - sock_hold(&q->sk); - dev_hold(q->vlan->dev); + + spin_lock(&macvtap_lock); + q = rcu_dereference(vlan->tap); + if (!q) { + spin_unlock(&macvtap_lock); + return; } - rcu_read_unlock_bh(); - return q; -} -static inline void macvtap_file_put_queue(struct macvtap_queue *q) -{ + rcu_assign_pointer(vlan->tap, NULL); + rcu_assign_pointer(q->vlan, NULL); + spin_unlock(&macvtap_lock); + + synchronize_rcu(); sock_put(&q->sk); - dev_put(q->vlan->dev); } /* @@ -284,7 +271,6 @@ static int macvtap_open(struct inode *inode, struct file *file) q->sock.type = SOCK_RAW; q->sock.state = SS_CONNECTED; sock_init_data(&q->sock, &q->sk); - q->sk.sk_allocation = GFP_ATOMIC; /* for now */ q->sk.sk_write_space = macvtap_sock_write_space; err = macvtap_set_queue(dev, file, q); @@ -300,13 +286,14 @@ out: static int macvtap_release(struct inode *inode, struct file *file) { - macvtap_del_queue((struct macvtap_queue **)&file->private_data); + struct macvtap_queue *q = file->private_data; + macvtap_put_queue(q); return 0; } static unsigned int macvtap_poll(struct file *file, poll_table * wait) { - struct macvtap_queue *q = macvtap_file_get_queue(file); + struct macvtap_queue *q = file->private_data; unsigned int mask = POLLERR; if (!q) @@ -323,7 +310,6 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait) sock_writeable(&q->sk))) mask |= POLLOUT | POLLWRNORM; - macvtap_file_put_queue(q); out: return mask; } @@ -334,6 +320,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, int noblock) { struct sk_buff *skb; + struct macvlan_dev *vlan; size_t len = count; int err; @@ -341,26 +328,37 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, return -EINVAL; skb = sock_alloc_send_skb(&q->sk, NET_IP_ALIGN + len, noblock, &err); - - if (!skb) { - macvlan_count_rx(q->vlan, 0, false, false); - return err; - } + if (!skb) + goto err; skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, count); - if (skb_copy_datagram_from_iovec(skb, 0, iv, 0, len)) { - macvlan_count_rx(q->vlan, 0, false, false); - kfree_skb(skb); - return -EFAULT; - } + err = skb_copy_datagram_from_iovec(skb, 0, iv, 0, len); + if (err) + goto err; skb_set_network_header(skb, ETH_HLEN); - - macvlan_start_xmit(skb, q->vlan->dev); + rcu_read_lock_bh(); + vlan = rcu_dereference(q->vlan); + if (vlan) + macvlan_start_xmit(skb, vlan->dev); + else + kfree_skb(skb); + rcu_read_unlock_bh(); return count; + +err: + rcu_read_lock_bh(); + vlan = rcu_dereference(q->vlan); + if (vlan) + macvlan_count_rx(q->vlan, 0, false, false); + rcu_read_unlock_bh(); + + kfree_skb(skb); + + return err; } static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, @@ -368,15 +366,10 @@ static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, { struct file *file = iocb->ki_filp; ssize_t result = -ENOLINK; - struct macvtap_queue *q = macvtap_file_get_queue(file); - - if (!q) - goto out; + struct macvtap_queue *q = file->private_data; result = macvtap_get_user(q, iv, iov_length(iv, count), file->f_flags & O_NONBLOCK); - macvtap_file_put_queue(q); -out: return result; } @@ -385,14 +378,17 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, const struct sk_buff *skb, const struct iovec *iv, int len) { - struct macvlan_dev *vlan = q->vlan; + struct macvlan_dev *vlan; int ret; len = min_t(int, skb->len, len); ret = skb_copy_datagram_const_iovec(skb, 0, iv, 0, len); + rcu_read_lock_bh(); + vlan = rcu_dereference(q->vlan); macvlan_count_rx(vlan, len, ret == 0, 0); + rcu_read_unlock_bh(); return ret ? ret : len; } @@ -401,14 +397,16 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, unsigned long count, loff_t pos) { struct file *file = iocb->ki_filp; - struct macvtap_queue *q = macvtap_file_get_queue(file); + struct macvtap_queue *q = file->private_data; DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; ssize_t len, ret = 0; - if (!q) - return -ENOLINK; + if (!q) { + ret = -ENOLINK; + goto out; + } len = iov_length(iv, count); if (len < 0) { @@ -444,7 +442,6 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, remove_wait_queue(q->sk.sk_sleep, &wait); out: - macvtap_file_put_queue(q); return ret; } @@ -454,12 +451,13 @@ out: static long macvtap_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct macvtap_queue *q; + struct macvtap_queue *q = file->private_data; + struct macvlan_dev *vlan; void __user *argp = (void __user *)arg; struct ifreq __user *ifr = argp; unsigned int __user *up = argp; unsigned int u; - char devname[IFNAMSIZ]; + int ret; switch (cmd) { case TUNSETIFF: @@ -471,16 +469,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, return 0; case TUNGETIFF: - q = macvtap_file_get_queue(file); - if (!q) + rcu_read_lock_bh(); + vlan = rcu_dereference(q->vlan); + if (vlan) + dev_hold(vlan->dev); + rcu_read_unlock_bh(); + + if (!vlan) return -ENOLINK; - memcpy(devname, q->vlan->dev->name, sizeof(devname)); - macvtap_file_put_queue(q); + ret = 0; if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) || put_user((TUN_TAP_DEV | TUN_NO_PI), &ifr->ifr_flags)) - return -EFAULT; - return 0; + ret = -EFAULT; + dev_put(vlan->dev); + return ret; case TUNGETFEATURES: if (put_user((IFF_TAP | IFF_NO_PI), up)) @@ -491,11 +494,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, if (get_user(u, up)) return -EFAULT; - q = macvtap_file_get_queue(file); - if (!q) - return -ENOLINK; q->sk.sk_sndbuf = u; - macvtap_file_put_queue(q); return 0; case TUNSETOFFLOAD: -- cgit v1.2.3 From 501c774cb13c3ef8fb7fc5f08fa19473f7d9a0db Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 Feb 2010 05:46:50 +0000 Subject: net/macvtap: add vhost support This adds support for passing a macvtap file descriptor into vhost-net, much like we already do for tun/tap. Most of the new code is taken from the respective patch in the tun driver and may get consolidated in the future. Signed-off-by: Arnd Bergmann Acked-by: Sridhar Samudrala Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 98 ++++++++++++++++++++++++++++++++++++---------- drivers/vhost/Kconfig | 2 +- drivers/vhost/net.c | 8 +++- include/linux/if_macvlan.h | 13 ++++++ 4 files changed, 97 insertions(+), 24 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 705099749766..e354501ab297 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -58,6 +58,8 @@ static unsigned int macvtap_major; static struct class *macvtap_class; static struct cdev macvtap_cdev; +static const struct proto_ops macvtap_socket_ops; + /* * RCU usage: * The macvtap_queue and the macvlan_dev are loosely coupled, the @@ -176,7 +178,7 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) return -ENOLINK; skb_queue_tail(&q->sk.sk_receive_queue, skb); - wake_up(q->sk.sk_sleep); + wake_up_interruptible_poll(q->sk.sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND); return 0; } @@ -242,7 +244,7 @@ static void macvtap_sock_write_space(struct sock *sk) return; if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible_sync(sk->sk_sleep); + wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND); } static int macvtap_open(struct inode *inode, struct file *file) @@ -270,6 +272,8 @@ static int macvtap_open(struct inode *inode, struct file *file) init_waitqueue_head(&q->sock.wait); q->sock.type = SOCK_RAW; q->sock.state = SS_CONNECTED; + q->sock.file = file; + q->sock.ops = &macvtap_socket_ops; sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; @@ -387,32 +391,20 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); - macvlan_count_rx(vlan, len, ret == 0, 0); + if (vlan) + macvlan_count_rx(vlan, len, ret == 0, 0); rcu_read_unlock_bh(); return ret ? ret : len; } -static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, - unsigned long count, loff_t pos) +static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, + const struct iovec *iv, unsigned long len, + int noblock) { - struct file *file = iocb->ki_filp; - struct macvtap_queue *q = file->private_data; - DECLARE_WAITQUEUE(wait, current); struct sk_buff *skb; - ssize_t len, ret = 0; - - if (!q) { - ret = -ENOLINK; - goto out; - } - - len = iov_length(iv, count); - if (len < 0) { - ret = -EINVAL; - goto out; - } + ssize_t ret = 0; add_wait_queue(q->sk.sk_sleep, &wait); while (len) { @@ -421,7 +413,7 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, /* Read frames from the queue */ skb = skb_dequeue(&q->sk.sk_receive_queue); if (!skb) { - if (file->f_flags & O_NONBLOCK) { + if (noblock) { ret = -EAGAIN; break; } @@ -440,7 +432,24 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, current->state = TASK_RUNNING; remove_wait_queue(q->sk.sk_sleep, &wait); + return ret; +} + +static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, + unsigned long count, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct macvtap_queue *q = file->private_data; + ssize_t len, ret = 0; + len = iov_length(iv, count); + if (len < 0) { + ret = -EINVAL; + goto out; + } + + ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); + ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ out: return ret; } @@ -538,6 +547,53 @@ static const struct file_operations macvtap_fops = { #endif }; +static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len) +{ + struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); + return macvtap_get_user(q, m->msg_iov, total_len, + m->msg_flags & MSG_DONTWAIT); +} + +static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, size_t total_len, + int flags) +{ + struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); + int ret; + if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) + return -EINVAL; + ret = macvtap_do_read(q, iocb, m->msg_iov, total_len, + flags & MSG_DONTWAIT); + if (ret > total_len) { + m->msg_flags |= MSG_TRUNC; + ret = flags & MSG_TRUNC ? ret : total_len; + } + return ret; +} + +/* Ops structure to mimic raw sockets with tun */ +static const struct proto_ops macvtap_socket_ops = { + .sendmsg = macvtap_sendmsg, + .recvmsg = macvtap_recvmsg, +}; + +/* Get an underlying socket object from tun file. Returns error unless file is + * attached to a device. The returned object works like a packet socket, it + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for + * holding a reference to the file for as long as the socket is in use. */ +struct socket *macvtap_get_socket(struct file *file) +{ + struct macvtap_queue *q; + if (file->f_op != &macvtap_fops) + return ERR_PTR(-EINVAL); + q = file->private_data; + if (!q) + return ERR_PTR(-EBADFD); + return &q->sock; +} +EXPORT_SYMBOL_GPL(macvtap_get_socket); + static int macvtap_init(void) { int err; diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 9e9355367bb3..e4e2fd1b5107 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -1,6 +1,6 @@ config VHOST_NET tristate "Host kernel accelerator for virtio net (EXPERIMENTAL)" - depends on NET && EVENTFD && (TUN || !TUN) && EXPERIMENTAL + depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP) && EXPERIMENTAL ---help--- This kernel module can be loaded in host kernel to accelerate guest networking with virtio_net. Not to be confused with virtio_net diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 4c8928319e1d..91a324cc2298 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -452,13 +453,16 @@ err: return ERR_PTR(r); } -static struct socket *get_tun_socket(int fd) +static struct socket *get_tap_socket(int fd) { struct file *file = fget(fd); struct socket *sock; if (!file) return ERR_PTR(-EBADF); sock = tun_get_socket(file); + if (!IS_ERR(sock)) + return sock; + sock = macvtap_get_socket(file); if (IS_ERR(sock)) fput(file); return sock; @@ -473,7 +477,7 @@ static struct socket *get_socket(int fd) sock = get_raw_socket(fd); if (!IS_ERR(sock)) return sock; - sock = get_tun_socket(fd); + sock = get_tap_socket(fd); if (!IS_ERR(sock)) return sock; return ERR_PTR(-ENOTSOCK); diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index f9cb9ba1475d..b78a712247da 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -7,6 +7,19 @@ #include #include +#if defined(CONFIG_MACVTAP) || defined(CONFIG_MACVTAP_MODULE) +struct socket *macvtap_get_socket(struct file *); +#else +#include +#include +struct file; +struct socket; +static inline struct socket *macvtap_get_socket(struct file *f) +{ + return ERR_PTR(-EINVAL); +} +#endif /* CONFIG_MACVTAP */ + struct macvlan_port; struct macvtap_queue; -- cgit v1.2.3 From b9fb9ee07e67fce0b7bfd517a48710465706c30a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 18 Feb 2010 05:48:17 +0000 Subject: macvtap: add GSO/csum offload support Added flags field to macvtap_queue to enable/disable processing of virtio_net_hdr via IFF_VNET_HDR. This flag is checked to prepend virtio_net_hdr in the receive path and process/skip virtio_net_hdr in the send path. Original patch by Sridhar, further changes by Arnd. Signed-off-by: Sridhar Samudrala Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 206 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 182 insertions(+), 24 deletions(-) diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index e354501ab297..55ceae09738e 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -17,6 +17,7 @@ #include #include #include +#include /* * A macvtap queue is the central object of this driver, it connects @@ -37,6 +38,7 @@ struct macvtap_queue { struct socket sock; struct macvlan_dev *vlan; struct file *file; + unsigned int flags; }; static struct proto macvtap_proto = { @@ -276,6 +278,7 @@ static int macvtap_open(struct inode *inode, struct file *file) q->sock.ops = &macvtap_socket_ops; sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; + q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; err = macvtap_set_queue(dev, file, q); if (err) @@ -318,6 +321,111 @@ out: return mask; } +static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad, + size_t len, size_t linear, + int noblock, int *err) +{ + struct sk_buff *skb; + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE || !linear) + linear = len; + + skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock, + err); + if (!skb) + return NULL; + + skb_reserve(skb, prepad); + skb_put(skb, linear); + skb->data_len = len - linear; + skb->len += len - linear; + + return skb; +} + +/* + * macvtap_skb_from_vnet_hdr and macvtap_skb_to_vnet_hdr should + * be shared with the tun/tap driver. + */ +static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, + struct virtio_net_hdr *vnet_hdr) +{ + unsigned short gso_type = 0; + if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + switch (vnet_hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { + case VIRTIO_NET_HDR_GSO_TCPV4: + gso_type = SKB_GSO_TCPV4; + break; + case VIRTIO_NET_HDR_GSO_TCPV6: + gso_type = SKB_GSO_TCPV6; + break; + case VIRTIO_NET_HDR_GSO_UDP: + gso_type = SKB_GSO_UDP; + break; + default: + return -EINVAL; + } + + if (vnet_hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) + gso_type |= SKB_GSO_TCP_ECN; + + if (vnet_hdr->gso_size == 0) + return -EINVAL; + } + + if (vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + if (!skb_partial_csum_set(skb, vnet_hdr->csum_start, + vnet_hdr->csum_offset)) + return -EINVAL; + } + + if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { + skb_shinfo(skb)->gso_size = vnet_hdr->gso_size; + skb_shinfo(skb)->gso_type = gso_type; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + } + return 0; +} + +static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, + struct virtio_net_hdr *vnet_hdr) +{ + memset(vnet_hdr, 0, sizeof(*vnet_hdr)); + + if (skb_is_gso(skb)) { + struct skb_shared_info *sinfo = skb_shinfo(skb); + + /* This is a hint as to how much should be linear. */ + vnet_hdr->hdr_len = skb_headlen(skb); + vnet_hdr->gso_size = sinfo->gso_size; + if (sinfo->gso_type & SKB_GSO_TCPV4) + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; + else if (sinfo->gso_type & SKB_GSO_TCPV6) + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; + else if (sinfo->gso_type & SKB_GSO_UDP) + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; + else + BUG(); + if (sinfo->gso_type & SKB_GSO_TCP_ECN) + vnet_hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; + } else + vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; + vnet_hdr->csum_start = skb->csum_start - + skb_headroom(skb); + vnet_hdr->csum_offset = skb->csum_offset; + } /* else everything is zero */ + + return 0; +} + + /* Get packet from user space buffer */ static ssize_t macvtap_get_user(struct macvtap_queue *q, const struct iovec *iv, size_t count, @@ -327,22 +435,53 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct macvlan_dev *vlan; size_t len = count; int err; + struct virtio_net_hdr vnet_hdr = { 0 }; + int vnet_hdr_len = 0; + + if (q->flags & IFF_VNET_HDR) { + vnet_hdr_len = sizeof(vnet_hdr); + + err = -EINVAL; + if ((len -= vnet_hdr_len) < 0) + goto err; + + err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, + vnet_hdr_len); + if (err < 0) + goto err; + if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > + vnet_hdr.hdr_len) + vnet_hdr.hdr_len = vnet_hdr.csum_start + + vnet_hdr.csum_offset + 2; + err = -EINVAL; + if (vnet_hdr.hdr_len > len) + goto err; + } + err = -EINVAL; if (unlikely(len < ETH_HLEN)) - return -EINVAL; + goto err; - skb = sock_alloc_send_skb(&q->sk, NET_IP_ALIGN + len, noblock, &err); + skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, len, vnet_hdr.hdr_len, + noblock, &err); if (!skb) goto err; - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, count); - - err = skb_copy_datagram_from_iovec(skb, 0, iv, 0, len); + err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len); if (err) - goto err; + goto err_kfree; skb_set_network_header(skb, ETH_HLEN); + skb_reset_mac_header(skb); + skb->protocol = eth_hdr(skb)->h_proto; + + if (vnet_hdr_len) { + err = macvtap_skb_from_vnet_hdr(skb, &vnet_hdr); + if (err) + goto err_kfree; + } + rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); if (vlan) @@ -353,15 +492,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, return count; +err_kfree: + kfree_skb(skb); + err: rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); if (vlan) - macvlan_count_rx(q->vlan, 0, false, false); + netdev_get_tx_queue(vlan->dev, 0)->tx_dropped++; rcu_read_unlock_bh(); - kfree_skb(skb); - return err; } @@ -384,10 +524,25 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, { struct macvlan_dev *vlan; int ret; + int vnet_hdr_len = 0; + + if (q->flags & IFF_VNET_HDR) { + struct virtio_net_hdr vnet_hdr; + vnet_hdr_len = sizeof (vnet_hdr); + if ((len -= vnet_hdr_len) < 0) + return -EINVAL; + + ret = macvtap_skb_to_vnet_hdr(skb, &vnet_hdr); + if (ret) + return ret; + + if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) + return -EFAULT; + } len = min_t(int, skb->len, len); - ret = skb_copy_datagram_const_iovec(skb, 0, iv, 0, len); + ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len); rcu_read_lock_bh(); vlan = rcu_dereference(q->vlan); @@ -395,7 +550,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, macvlan_count_rx(vlan, len, ret == 0, 0); rcu_read_unlock_bh(); - return ret ? ret : len; + return ret ? ret : (len + vnet_hdr_len); } static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, @@ -473,9 +628,14 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, /* ignore the name, just look at flags */ if (get_user(u, &ifr->ifr_flags)) return -EFAULT; - if (u != (IFF_TAP | IFF_NO_PI)) - return -EINVAL; - return 0; + + ret = 0; + if ((u & ~IFF_VNET_HDR) != (IFF_NO_PI | IFF_TAP)) + ret = -EINVAL; + else + q->flags = u; + + return ret; case TUNGETIFF: rcu_read_lock_bh(); @@ -489,13 +649,13 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, ret = 0; if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) || - put_user((TUN_TAP_DEV | TUN_NO_PI), &ifr->ifr_flags)) + put_user(q->flags, &ifr->ifr_flags)) ret = -EFAULT; dev_put(vlan->dev); return ret; case TUNGETFEATURES: - if (put_user((IFF_TAP | IFF_NO_PI), up)) + if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR, up)) return -EFAULT; return 0; @@ -509,15 +669,13 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, case TUNSETOFFLOAD: /* let the user check for future flags */ if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | - TUN_F_TSO_ECN | TUN_F_UFO)) - return -EINVAL; - - /* TODO: add support for these, so far we don't - support any offload */ - if (arg & (TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | - TUN_F_TSO_ECN | TUN_F_UFO)) + TUN_F_TSO_ECN | TUN_F_UFO)) return -EINVAL; + /* TODO: only accept frames with the features that + got enabled for forwarded frames */ + if (!(q->flags & IFF_VNET_HDR)) + return -EINVAL; return 0; default: -- cgit v1.2.3 From 663717f65c075eb4c6da7a123041295bd5295cc0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 18 Feb 2010 14:12:06 -0800 Subject: AF_UNIX: update locking comment The lock used in unix_state_lock() is a spin_lock not reader-writer. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 9bc9b92bc099..3d9122e78f41 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -144,7 +144,7 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) /* * SMP locking strategy: * hash table is protected with spinlock unix_table_lock - * each socket state is protected by separate rwlock. + * each socket state is protected by separate spin lock. */ static inline unsigned unix_hash_fold(__wsum n) -- cgit v1.2.3 From bc417d99bf279f034474bc2d7dedd390838a5480 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 18 Feb 2010 08:12:20 +0000 Subject: ipv6: remove stale MIB definitions ICMP6 MIB statistics was per-netns for quite a time. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv6/icmp.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 217dbc2e28d4..9a37379d741a 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -67,11 +67,6 @@ #include #include -DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; -EXPORT_SYMBOL(icmpv6_statistics); -DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics) __read_mostly; -EXPORT_SYMBOL(icmpv6msg_statistics); - /* * The ICMP socket(s). This is the most convenient way to flow control * our ICMP output as well as maintain a clean interface throughout -- cgit v1.2.3 From bbef49daca35d4fd21bf606a10b6980f17d9df5d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 18 Feb 2010 08:13:30 +0000 Subject: ipv6: use standard lists for FIB walks Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 2 +- net/ipv6/ip6_fib.c | 17 ++++------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 8f279ddb3593..86f46c49e318 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -124,7 +124,7 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) } struct fib6_walker_t { - struct fib6_walker_t *prev, *next; + struct list_head lh; struct fib6_node *root, *node; struct rt6_info *leaf; unsigned char state; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 77e122f53ea6..2f9847924fa5 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -93,29 +93,20 @@ static __u32 rt_sernum; static void fib6_gc_timer_cb(unsigned long arg); -static struct fib6_walker_t fib6_walker_list = { - .prev = &fib6_walker_list, - .next = &fib6_walker_list, -}; - -#define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next) +static LIST_HEAD(fib6_walkers); +#define FOR_WALKERS(w) list_for_each_entry(w, &fib6_walkers, lh) static inline void fib6_walker_link(struct fib6_walker_t *w) { write_lock_bh(&fib6_walker_lock); - w->next = fib6_walker_list.next; - w->prev = &fib6_walker_list; - w->next->prev = w; - w->prev->next = w; + list_add(&w->lh, &fib6_walkers); write_unlock_bh(&fib6_walker_lock); } static inline void fib6_walker_unlink(struct fib6_walker_t *w) { write_lock_bh(&fib6_walker_lock); - w->next->prev = w->prev; - w->prev->next = w->next; - w->prev = w->next = w; + list_del(&w->lh); write_unlock_bh(&fib6_walker_lock); } static __inline__ u32 fib6_new_sernum(void) -- cgit v1.2.3 From 3ffe533c87281b68d469b279ff3a5056f9c75862 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 18 Feb 2010 08:25:24 +0000 Subject: ipv6: drop unused "dev" arg of icmpv6_send() Dunno, what was the idea, it wasn't used for a long time. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 2 +- include/linux/icmpv6.h | 3 +-- net/ipv4/ip_gre.c | 2 +- net/ipv6/exthdrs.c | 2 +- net/ipv6/icmp.c | 5 ++--- net/ipv6/ip6_input.c | 3 +-- net/ipv6/ip6_output.c | 11 +++++------ net/ipv6/ip6_tunnel.c | 6 +++--- net/ipv6/mip6.c | 2 +- net/ipv6/netfilter/ip6t_REJECT.c | 2 +- net/ipv6/reassembly.c | 2 +- net/ipv6/route.c | 4 ++-- net/ipv6/sit.c | 2 +- net/ipv6/tunnel6.c | 4 ++-- net/ipv6/udp.c | 5 ++--- net/ipv6/xfrm6_output.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 5 ++--- net/netfilter/ipvs/ip_vs_xmit.c | 10 +++++----- 18 files changed, 33 insertions(+), 39 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 30bdf427ee6d..83a7751c38d6 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1374,7 +1374,7 @@ static void ipoib_cm_skb_reap(struct work_struct *work) icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); #endif dev_kfree_skb_any(skb); diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index c0d8357917e2..4c4c74ec5987 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -174,8 +174,7 @@ struct icmp6_filter { extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, - __u32 info, - struct net_device *dev); + __u32 info); extern int icmpv6_init(void); extern int icmpv6_err_convert(u8 type, u8 code, diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a2a5983dbf03..c0c5274d0271 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -793,7 +793,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev } if (mtu >= IPV6_MIN_MTU && mtu < skb->len - tunnel->hlen + gre_hlen) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); ip_rt_put(rt); goto tx_error; } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 4bac362b1335..074f2c084f9f 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -481,7 +481,7 @@ looped_back: IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, - 0, skb->dev); + 0); kfree_skb(skb); return -1; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 9a37379d741a..eb9abe24bdf0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -114,7 +114,7 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk) */ void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) { - icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); + icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos); kfree_skb(skb); } @@ -300,8 +300,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {} /* * Send an ICMP message in response to a packet in error */ -void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - struct net_device *dev) +void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) { struct net *net = dev_net(skb->dev); struct inet6_dev *idev = NULL; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 237e2dba6e94..e28f9203deca 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -216,8 +216,7 @@ resubmit: IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INUNKNOWNPROTOS); icmpv6_send(skb, ICMPV6_PARAMPROB, - ICMPV6_UNK_NEXTHDR, nhoff, - skb->dev); + ICMPV6_UNK_NEXTHDR, nhoff); } } else IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index eb6d09728633..1a5fe9ad1947 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -267,7 +267,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, if (net_ratelimit()) printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); return -EMSGSIZE; @@ -441,8 +441,7 @@ int ip6_forward(struct sk_buff *skb) if (hdr->hop_limit <= 1) { /* Force OUTPUT device used as source address */ skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, - 0, skb->dev); + icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0); IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); @@ -504,7 +503,7 @@ int ip6_forward(struct sk_buff *skb) goto error; if (addrtype & IPV6_ADDR_LINKLOCAL) { icmpv6_send(skb, ICMPV6_DEST_UNREACH, - ICMPV6_NOT_NEIGHBOUR, 0, skb->dev); + ICMPV6_NOT_NEIGHBOUR, 0); goto error; } } @@ -512,7 +511,7 @@ int ip6_forward(struct sk_buff *skb) if (skb->len > dst_mtu(dst)) { /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst)); IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); IP6_INC_STATS_BH(net, @@ -627,7 +626,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) */ if (!skb->local_df) { skb->dev = skb_dst(skb)->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS); kfree_skb(skb); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9b02492d8706..138980eec214 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -622,7 +622,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (rt && rt->rt6i_dev) skb2->dev = rt->rt6i_dev; - icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); + icmpv6_send(skb2, rel_type, rel_code, rel_info); if (rt) dst_release(&rt->u.dst); @@ -1014,7 +1014,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; if (tel->encap_limit == 0) { icmpv6_send(skb, ICMPV6_PARAMPROB, - ICMPV6_HDR_FIELD, offset + 2, skb->dev); + ICMPV6_HDR_FIELD, offset + 2); return -1; } encap_limit = tel->encap_limit - 1; @@ -1033,7 +1033,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu); if (err != 0) { if (err == -EMSGSIZE) - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); return -1; } diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index f797e8c6f3b3..2794b6002836 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -56,7 +56,7 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen) static inline void mip6_param_prob(struct sk_buff *skb, u8 code, int pos) { - icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); + icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos); } static int mip6_mh_len(int type) diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 8311ca31816a..dd8afbaf00a8 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c @@ -169,7 +169,7 @@ send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code, if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) skb_in->dev = net->loopback_dev; - icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); + icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); } static unsigned int diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index b2847ed6a7d9..a555156e9779 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -228,7 +228,7 @@ static void ip6_frag_expire(unsigned long data) pointer directly, device might already disappeared. */ fq->q.fragments->dev = dev; - icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); + icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); out_rcu_unlock: rcu_read_unlock(); out: diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8500156f2637..88c0a5c49ae8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -909,7 +909,7 @@ static void ip6_link_failure(struct sk_buff *skb) { struct rt6_info *rt; - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0); rt = (struct rt6_info *) skb_dst(skb); if (rt) { @@ -1884,7 +1884,7 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) ipstats_mib_noroutes); break; } - icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0); kfree_skb(skb); return 0; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 96eb2d4641c4..b1eea811be48 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -743,7 +743,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (skb->len > mtu) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); ip_rt_put(rt); goto tx_error; } diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 51e2832d13a6..e17bc1dfc1a4 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c @@ -98,7 +98,7 @@ static int tunnel6_rcv(struct sk_buff *skb) if (!handler->handler(skb)) return 0; - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); drop: kfree_skb(skb); @@ -116,7 +116,7 @@ static int tunnel46_rcv(struct sk_buff *skb) if (!handler->handler(skb)) return 0; - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); drop: kfree_skb(skb); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index a7af9d68cd6c..52b8347ae3b2 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -680,12 +680,11 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, int proto) { + struct net *net = dev_net(skb->dev); struct sock *sk; struct udphdr *uh; - struct net_device *dev = skb->dev; struct in6_addr *saddr, *daddr; u32 ulen = 0; - struct net *net = dev_net(skb->dev); if (!pskb_may_pull(skb, sizeof(struct udphdr))) goto short_packet; @@ -744,7 +743,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); kfree_skb(skb); return 0; diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index c4f4eef032a3..0c92112dcba3 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -38,7 +38,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) if (!skb->local_df && skb->len > mtu) { skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); ret = -EMSGSIZE; } diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 72e96d823ebf..44590887a92c 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -515,8 +515,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, */ #ifdef CONFIG_IP_VS_IPV6 if (svc->af == AF_INET6) - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, - skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); else #endif icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); @@ -1048,7 +1047,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, - 0, skb->dev); + 0); else #endif icmp_send(skb, diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 30b3189bd29c..223b5018c7dc 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -311,7 +311,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, mtu = dst_mtu(&rt->u.dst); if (skb->len > mtu) { dst_release(&rt->u.dst); - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP_VS_DBG_RL("%s(): frag needed\n", __func__); goto tx_error; } @@ -454,7 +454,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, mtu = dst_mtu(&rt->u.dst); if (skb->len > mtu) { dst_release(&rt->u.dst); - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP_VS_DBG_RL_PKT(0, pp, skb, 0, "ip_vs_nat_xmit_v6(): frag needed for"); goto tx_error; @@ -672,7 +672,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); dst_release(&rt->u.dst); IP_VS_DBG_RL("%s(): frag needed\n", __func__); goto tx_error; @@ -814,7 +814,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, /* MTU checking */ mtu = dst_mtu(&rt->u.dst); if (skb->len > mtu) { - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); dst_release(&rt->u.dst); IP_VS_DBG_RL("%s(): frag needed\n", __func__); goto tx_error; @@ -965,7 +965,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, mtu = dst_mtu(&rt->u.dst); if (skb->len > mtu) { dst_release(&rt->u.dst); - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP_VS_DBG_RL("%s(): frag needed\n", __func__); goto tx_error; } -- cgit v1.2.3 From b54452b07a7b1b8cc1385edba3ef2ef6d4679d5a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 18 Feb 2010 08:14:31 +0000 Subject: const: struct nla_policy Make remaining netlink policies as const. Fixup coding style where needed. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/netlink.h | 2 +- kernel/taskstats.c | 6 ++---- net/dcb/dcbnl.c | 16 ++++++++-------- net/irda/irnetlink.c | 2 +- net/wimax/op-msg.c | 3 +-- net/wimax/op-reset.c | 3 +-- net/wimax/op-rfkill.c | 3 +-- net/wimax/op-state-get.c | 3 +-- net/wimax/stack.c | 3 +-- net/wireless/nl80211.c | 14 +++++--------- 10 files changed, 22 insertions(+), 33 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index a63b2192ac1c..f82e463c875a 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -196,7 +196,7 @@ enum { * All other Exact length of attribute payload * * Example: - * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = { + * static const struct nla_policy my_policy[ATTR_MAX+1] = { * [ATTR_FOO] = { .type = NLA_U16 }, * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, diff --git a/kernel/taskstats.c b/kernel/taskstats.c index ea8384d3caa7..899ca51be5e8 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -46,15 +46,13 @@ static struct genl_family family = { .maxattr = TASKSTATS_CMD_ATTR_MAX, }; -static struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] -__read_mostly = { +static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = { [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 }, [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; -static struct nla_policy -cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] __read_mostly = { +static const struct nla_policy cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] = { [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 }, }; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index db9f5b39388f..813e399220a7 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); /**************** DCB attribute policies *************************************/ /* DCB netlink attributes policy */ -static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { [DCB_ATTR_IFNAME] = {.type = NLA_NUL_STRING, .len = IFNAMSIZ - 1}, [DCB_ATTR_STATE] = {.type = NLA_U8}, [DCB_ATTR_PFC_CFG] = {.type = NLA_NESTED}, @@ -68,7 +68,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { }; /* DCB priority flow control to User Priority nested attributes */ -static struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { [DCB_PFC_UP_ATTR_0] = {.type = NLA_U8}, [DCB_PFC_UP_ATTR_1] = {.type = NLA_U8}, [DCB_PFC_UP_ATTR_2] = {.type = NLA_U8}, @@ -81,7 +81,7 @@ static struct nla_policy dcbnl_pfc_up_nest[DCB_PFC_UP_ATTR_MAX + 1] = { }; /* DCB priority grouping nested attributes */ -static struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { [DCB_PG_ATTR_TC_0] = {.type = NLA_NESTED}, [DCB_PG_ATTR_TC_1] = {.type = NLA_NESTED}, [DCB_PG_ATTR_TC_2] = {.type = NLA_NESTED}, @@ -103,7 +103,7 @@ static struct nla_policy dcbnl_pg_nest[DCB_PG_ATTR_MAX + 1] = { }; /* DCB traffic class nested attributes. */ -static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { +static const struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { [DCB_TC_ATTR_PARAM_PGID] = {.type = NLA_U8}, [DCB_TC_ATTR_PARAM_UP_MAPPING] = {.type = NLA_U8}, [DCB_TC_ATTR_PARAM_STRICT_PRIO] = {.type = NLA_U8}, @@ -112,7 +112,7 @@ static struct nla_policy dcbnl_tc_param_nest[DCB_TC_ATTR_PARAM_MAX + 1] = { }; /* DCB capabilities nested attributes. */ -static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { [DCB_CAP_ATTR_ALL] = {.type = NLA_FLAG}, [DCB_CAP_ATTR_PG] = {.type = NLA_U8}, [DCB_CAP_ATTR_PFC] = {.type = NLA_U8}, @@ -124,14 +124,14 @@ static struct nla_policy dcbnl_cap_nest[DCB_CAP_ATTR_MAX + 1] = { }; /* DCB capabilities nested attributes. */ -static struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_numtcs_nest[DCB_NUMTCS_ATTR_MAX + 1] = { [DCB_NUMTCS_ATTR_ALL] = {.type = NLA_FLAG}, [DCB_NUMTCS_ATTR_PG] = {.type = NLA_U8}, [DCB_NUMTCS_ATTR_PFC] = {.type = NLA_U8}, }; /* DCB BCN nested attributes. */ -static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { [DCB_BCN_ATTR_RP_0] = {.type = NLA_U8}, [DCB_BCN_ATTR_RP_1] = {.type = NLA_U8}, [DCB_BCN_ATTR_RP_2] = {.type = NLA_U8}, @@ -160,7 +160,7 @@ static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { }; /* DCB APP nested attributes. */ -static struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { +static const struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8}, [DCB_APP_ATTR_ID] = {.type = NLA_U16}, [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c index 476b307bd801..69b5b75f5431 100644 --- a/net/irda/irnetlink.c +++ b/net/irda/irnetlink.c @@ -124,7 +124,7 @@ static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) return ret; } -static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = { +static const struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = { [IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, [IRDA_NL_ATTR_MODE] = { .type = NLA_U32 }, diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index d3bfb6ef13ae..7718657e93dc 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -320,8 +320,7 @@ int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name, EXPORT_SYMBOL_GPL(wimax_msg); -static const -struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = { +static const struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = { [WIMAX_GNL_MSG_IFIDX] = { .type = NLA_U32, }, diff --git a/net/wimax/op-reset.c b/net/wimax/op-reset.c index 35f370091f4f..4dc82a54ba30 100644 --- a/net/wimax/op-reset.c +++ b/net/wimax/op-reset.c @@ -91,8 +91,7 @@ int wimax_reset(struct wimax_dev *wimax_dev) EXPORT_SYMBOL(wimax_reset); -static const -struct nla_policy wimax_gnl_reset_policy[WIMAX_GNL_ATTR_MAX + 1] = { +static const struct nla_policy wimax_gnl_reset_policy[WIMAX_GNL_ATTR_MAX + 1] = { [WIMAX_GNL_RESET_IFIDX] = { .type = NLA_U32, }, diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index ae752a64d920..e978c7136c97 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c @@ -410,8 +410,7 @@ void wimax_rfkill_rm(struct wimax_dev *wimax_dev) * just query). */ -static const -struct nla_policy wimax_gnl_rfkill_policy[WIMAX_GNL_ATTR_MAX + 1] = { +static const struct nla_policy wimax_gnl_rfkill_policy[WIMAX_GNL_ATTR_MAX + 1] = { [WIMAX_GNL_RFKILL_IFIDX] = { .type = NLA_U32, }, diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c index a76b8fcb056d..11ad3356eb56 100644 --- a/net/wimax/op-state-get.c +++ b/net/wimax/op-state-get.c @@ -33,8 +33,7 @@ #include "debug-levels.h" -static const -struct nla_policy wimax_gnl_state_get_policy[WIMAX_GNL_ATTR_MAX + 1] = { +static const struct nla_policy wimax_gnl_state_get_policy[WIMAX_GNL_ATTR_MAX + 1] = { [WIMAX_GNL_STGET_IFIDX] = { .type = NLA_U32, }, diff --git a/net/wimax/stack.c b/net/wimax/stack.c index c8866412f830..813e1eaea29b 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -75,8 +75,7 @@ MODULE_PARM_DESC(debug, * close to where the data is generated. */ /* -static const -struct nla_policy wimax_gnl_re_status_change[WIMAX_GNL_ATTR_MAX + 1] = { +static const struct nla_policy wimax_gnl_re_status_change[WIMAX_GNL_ATTR_MAX + 1] = { [WIMAX_GNL_STCH_STATE_OLD] = { .type = NLA_U8 }, [WIMAX_GNL_STCH_STATE_NEW] = { .type = NLA_U8 }, }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5b79ecf17bea..a001ea32cb7d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -58,7 +58,7 @@ static int get_rdev_dev_by_info_ifindex(struct genl_info *info, } /* policy for the attributes */ -static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { +static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, .len = 20-1 }, @@ -148,8 +148,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { }; /* policy for the attributes */ -static struct nla_policy -nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = { +static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, [NL80211_KEY_IDX] = { .type = NLA_U8 }, [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, @@ -2501,8 +2500,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) return err; } -static const struct nla_policy - reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { +static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = { [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, @@ -2671,8 +2669,7 @@ do {\ } \ } while (0);\ -static struct nla_policy -nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] __read_mostly = { +static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_ATTR_MAX+1] = { [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 }, [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 }, [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 }, @@ -4470,8 +4467,7 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband, return mask; } -static struct nla_policy -nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] __read_mostly = { +static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY, .len = NL80211_MAX_SUPP_RATES }, }; -- cgit v1.2.3 From bf473a268af5d19c3730742a0c4f9aca274843da Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 22:55:07 +0000 Subject: depca: remove forgotten needless inicialization Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/depca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/depca.c b/drivers/net/depca.c index 64a569bc92a6..744c1928dfca 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1272,7 +1272,7 @@ static void set_multicast_list(struct net_device *dev) static void SetMulticastFilter(struct net_device *dev) { struct depca_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; int i, j, bit, byte; u16 hashcode; -- cgit v1.2.3 From 59ce25d9eb2e17b901a404766f9e134759407d26 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 23:12:15 +0000 Subject: 3c5xx: use netdev_mc_* helpers Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/3c501.c | 2 +- drivers/net/3c505.c | 9 ++++----- drivers/net/3c515.c | 2 +- drivers/net/3c523.c | 9 ++++----- drivers/net/3c527.c | 8 ++------ drivers/net/3c59x.c | 2 +- 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c index 4d4cad393dce..b6de7b1e2a5c 100644 --- a/drivers/net/3c501.c +++ b/drivers/net/3c501.c @@ -812,7 +812,7 @@ static void set_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) { outb(RX_PROM, RX_CMD); inb(RX_STATUS); - } else if (dev->mc_list || dev->flags & IFF_ALLMULTI) { + } else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) { /* Multicast or all multicast is the same */ outb(RX_MULT, RX_CMD); inb(RX_STATUS); /* Clear status. */ diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c index dadb46a8833a..04b5bba19021 100644 --- a/drivers/net/3c505.c +++ b/drivers/net/3c505.c @@ -1216,7 +1216,7 @@ static int elp_close(struct net_device *dev) static void elp_set_mc_list(struct net_device *dev) { elp_device *adapter = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; int i; unsigned long flags; @@ -1230,10 +1230,9 @@ static void elp_set_mc_list(struct net_device *dev) /* if num_addrs==0 the list will be cleared */ adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; adapter->tx_pcb.length = 6 * netdev_mc_count(dev); - for (i = 0; i < netdev_mc_count(dev); i++) { - memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr, 6); - dmi = dmi->next; - } + i = 0; + netdev_for_each_mc_addr(dmi, dev) + memcpy(adapter->tx_pcb.data.multicast[i++], dmi->dmi_addr, 6); adapter->got[CMD_LOAD_MULTICAST_LIST] = 0; if (!send_pcb(dev, &adapter->tx_pcb)) pr_err("%s: couldn't send set_multicast command\n", dev->name); diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 063b049ffe55..1e898b1c8068 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -1536,7 +1536,7 @@ static void set_rx_mode(struct net_device *dev) pr_debug("%s: Setting promiscuous mode.\n", dev->name); new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm; - } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + } else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) { new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast; } else new_mode = SetRxFilter | RxStation | RxBroadcast; diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c index 6948d667fc5e..beed4fa10c6e 100644 --- a/drivers/net/3c523.c +++ b/drivers/net/3c523.c @@ -625,7 +625,7 @@ static int init586(struct net_device *dev) volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; int num_addrs = netdev_mc_count(dev); ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); @@ -787,10 +787,9 @@ static int init586(struct net_device *dev) mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; mc_cmd->cmd_link = 0xffff; mc_cmd->mc_cnt = num_addrs * 6; - for (i = 0; i < num_addrs; i++) { - memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr, 6); - dmi = dmi->next; - } + i = 0; + netdev_for_each_mc_addr(dmi, dev) + memcpy((char *) mc_cmd->mc_list[i++], dmi->dmi_addr, 6); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd = CUC_START; elmc_id_attn586(); diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index ce9826980517..5c07b147ec99 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -1533,9 +1533,7 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) { unsigned char block[62]; unsigned char *bp; - struct dev_mc_list *dmc=dev->mc_list; - - int i; + struct dev_mc_list *dmc; if(retry==0) lp->mc_list_valid = 0; @@ -1545,11 +1543,9 @@ static void do_mc32_set_multicast_list(struct net_device *dev, int retry) block[0]=netdev_mc_count(dev); bp=block+2; - for(i=0;idmi_addr, 6); bp+=6; - dmc=dmc->next; } if(mc32_command_nowait(dev, 2, block, 2+6*netdev_mc_count(dev))==-1) diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 5df46c230b07..f965431f4924 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2970,7 +2970,7 @@ static void set_rx_mode(struct net_device *dev) if (vortex_debug > 3) pr_notice("%s: Setting promiscuous mode.\n", dev->name); new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; - } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + } else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) { new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; } else new_mode = SetRxFilter | RxStation | RxBroadcast; -- cgit v1.2.3 From 2a0d18f97cc15d57ad0c93259a3df4cb72c5a28b Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 17 Feb 2010 23:22:38 +0000 Subject: smsc911x: convert to use netdev_for_each_mc_addr also removed unnecessary checks Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 13c0b76dec41..4fd1d8b38788 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1383,29 +1383,20 @@ static void smsc911x_set_multicast_list(struct net_device *dev) /* Enabling specific multicast addresses */ unsigned int hash_high = 0; unsigned int hash_low = 0; - unsigned int count = 0; - struct dev_mc_list *mc_list = dev->mc_list; + struct dev_mc_list *mc_list; pdata->set_bits_mask = MAC_CR_HPFILT_; pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_); - while (mc_list) { - count++; - if ((mc_list->dmi_addrlen) == ETH_ALEN) { - unsigned int bitnum = - smsc911x_hash(mc_list->dmi_addr); - unsigned int mask = 0x01 << (bitnum & 0x1F); - if (bitnum & 0x20) - hash_high |= mask; - else - hash_low |= mask; - } else { - SMSC_WARNING(DRV, "dmi_addrlen != 6"); - } - mc_list = mc_list->next; + netdev_for_each_mc_addr(mc_list, dev) { + unsigned int bitnum = smsc911x_hash(mc_list->dmi_addr); + unsigned int mask = 0x01 << (bitnum & 0x1F); + + if (bitnum & 0x20) + hash_high |= mask; + else + hash_low |= mask; } - if (count != (unsigned int)netdev_mc_count(dev)) - SMSC_WARNING(DRV, "mc_count != dev->mc_count"); pdata->hashhi = hash_high; pdata->hashlo = hash_low; -- cgit v1.2.3 From 5508590c193661bc1484ad7b952af5fceacea40d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 18 Feb 2010 00:42:54 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part2 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/s2io.c | 5 +++-- drivers/net/sb1250-mac.c | 6 +++--- drivers/net/sc92031.c | 2 +- drivers/net/sfc/efx.c | 6 ++---- drivers/net/sis190.c | 4 +--- drivers/net/sis900.c | 5 ++--- drivers/net/skfp/skfddi.c | 10 +++------- drivers/net/skge.c | 10 ++++------ drivers/net/sky2.c | 5 ++--- drivers/net/smsc9420.c | 5 ++--- drivers/net/sonic.c | 7 ++++--- drivers/net/spider_net.c | 2 +- drivers/net/starfire.c | 4 ++-- drivers/net/stmmac/dwmac100.c | 4 +--- drivers/net/stmmac/dwmac1000_core.c | 4 +--- drivers/net/sun3_82586.c | 8 +++++--- drivers/net/sunbmac.c | 5 ++--- drivers/net/sundance.c | 3 +-- drivers/net/sungem.c | 10 +++------- drivers/net/sunhme.c | 20 ++++++-------------- drivers/net/sunlance.c | 6 ++---- drivers/net/sunqe.c | 9 +++------ drivers/net/sunvnet.c | 2 +- 23 files changed, 55 insertions(+), 87 deletions(-) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 102be16e9b52..43bc66aa8405 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5092,8 +5092,8 @@ static void s2io_set_multicast(struct net_device *dev) } /* Create the new Rx filter list and update the same in H/W. */ - for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + i = 0; + netdev_for_each_mc_addr(mclist, dev) { memcpy(sp->usr_addrs[i].addr, mclist->dmi_addr, ETH_ALEN); mac_addr = 0; @@ -5121,6 +5121,7 @@ static void s2io_set_multicast(struct net_device *dev) dev->name); return; } + i++; } } } diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 564d4d7f855b..9944e5d662c0 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2161,13 +2161,13 @@ static void sbmac_setmulti(struct sbmac_softc *sc) * XXX if the table overflows */ idx = 1; /* skip station address */ - mclist = dev->mc_list; - while (mclist && (idx < MAC_ADDR_COUNT)) { + netdev_for_each_mc_addr(mclist, dev) { + if (idx == MAC_ADDR_COUNT) + break; reg = sbmac_addr2reg(mclist->dmi_addr); port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); __raw_writeq(reg, port); idx++; - mclist = mclist->next; } /* diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 00ff8995ad69..d87c4787fffa 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -435,7 +435,7 @@ static void _sc92031_set_mar(struct net_device *dev) else if (dev->flags & IFF_MULTICAST) { struct dev_mc_list *mc_list; - for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { + netdev_for_each_mc_addr(mc_list, dev) { u32 crc; unsigned bit = 0; diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index dc58d9fd0f32..88f2fb193abe 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1602,11 +1602,10 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) static void efx_set_multicast_list(struct net_device *net_dev) { struct efx_nic *efx = netdev_priv(net_dev); - struct dev_mc_list *mc_list = net_dev->mc_list; + struct dev_mc_list *mc_list; union efx_multicast_hash *mc_hash = &efx->multicast_hash; u32 crc; int bit; - int i; efx->promiscuous = !!(net_dev->flags & IFF_PROMISC); @@ -1615,11 +1614,10 @@ static void efx_set_multicast_list(struct net_device *net_dev) memset(mc_hash, 0xff, sizeof(*mc_hash)); } else { memset(mc_hash, 0x00, sizeof(*mc_hash)); - for (i = 0; i < netdev_mc_count(net_dev); i++) { + netdev_for_each_mc_addr(mc_list, net_dev) { crc = ether_crc_le(ETH_ALEN, mc_list->dmi_addr); bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); set_bit_le(bit, mc_hash->byte); - mc_list = mc_list->next; } /* Broadcast packets go through the multicast hash filter. diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index bf2ffbb913ff..ead1d31308f8 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -849,12 +849,10 @@ static void sis190_set_rx_mode(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; - unsigned int i; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 32ae87c09f5e..cc0c731c4f09 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -2300,9 +2300,8 @@ static void set_rx_mode(struct net_device *net_dev) * packets */ struct dev_mc_list *mclist; rx_mode = RFAAB; - for (i = 0, mclist = net_dev->mc_list; - mclist && i < netdev_mc_count(net_dev); - i++, mclist = mclist->next) { + + netdev_for_each_mc_addr(mclist, net_dev) { unsigned int bit_nr = sis900_mcast_bitnr(mclist->dmi_addr, sis_priv->chipset_rev); mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf)); diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 346adfae986f..1921a54ea995 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -852,8 +852,7 @@ static void skfp_ctl_set_multicast_list(struct net_device *dev) static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) { struct s_smc *smc = netdev_priv(dev); - struct dev_mc_list *dmi; /* ptr to multicast addr entry */ - int i; + struct dev_mc_list *dmi; /* Enable promiscuous mode, if necessary */ if (dev->flags & IFF_PROMISC) { @@ -877,17 +876,14 @@ static void skfp_ctl_set_multicast_list_wo_lock(struct net_device *dev) /* use exact filtering */ // point to first multicast addr - dmi = dev->mc_list; - - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { mac_add_multicast(smc, (struct fddi_addr *)dmi->dmi_addr, 1); pr_debug(KERN_INFO "ENABLE MC ADDRESS: %pMF\n", dmi->dmi_addr); - dmi = dmi->next; - } // for + } } else { // more MC addresses than HW supports diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 720af1c7854b..d0058e5bb6ae 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2917,8 +2917,7 @@ static void genesis_set_multicast(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - int i, count = netdev_mc_count(dev); - struct dev_mc_list *list = dev->mc_list; + struct dev_mc_list *list; u32 mode; u8 filter[8]; @@ -2938,7 +2937,7 @@ static void genesis_set_multicast(struct net_device *dev) skge->flow_status == FLOW_STAT_SYMMETRIC) genesis_add_filter(filter, pause_mc_addr); - for (i = 0; list && i < count; i++, list = list->next) + netdev_for_each_mc_addr(list, dev) genesis_add_filter(filter, list->dmi_addr); } @@ -2957,7 +2956,7 @@ static void yukon_set_multicast(struct net_device *dev) struct skge_port *skge = netdev_priv(dev); struct skge_hw *hw = skge->hw; int port = skge->port; - struct dev_mc_list *list = dev->mc_list; + struct dev_mc_list *list; int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND || skge->flow_status == FLOW_STAT_SYMMETRIC); u16 reg; @@ -2975,13 +2974,12 @@ static void yukon_set_multicast(struct net_device *dev) else if (netdev_mc_empty(dev) && !rx_pause)/* no multicast */ reg &= ~GM_RXCR_MCF_ENA; else { - int i; reg |= GM_RXCR_MCF_ENA; if (rx_pause) yukon_add_filter(filter, pause_mc_addr); - for (i = 0; list && i < netdev_mc_count(dev); i++, list = list->next) + netdev_for_each_mc_addr(list, dev) yukon_add_filter(filter, list->dmi_addr); } diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index d1e98e2170ce..653bdd76ef46 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3621,7 +3621,7 @@ static void sky2_set_multicast(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - struct dev_mc_list *list = dev->mc_list; + struct dev_mc_list *list; u16 reg; u8 filter[8]; int rx_pause; @@ -3640,13 +3640,12 @@ static void sky2_set_multicast(struct net_device *dev) else if (netdev_mc_empty(dev) && !rx_pause) reg &= ~GM_RXCR_MCF_ENA; else { - int i; reg |= GM_RXCR_MCF_ENA; if (rx_pause) sky2_add_filter(filter, pause_mc_addr); - for (i = 0; list && i < netdev_mc_count(dev); i++, list = list->next) + netdev_for_each_mc_addr(list, dev) sky2_add_filter(filter, list->dmi_addr); } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 2bd3c986559a..30110a11d737 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1063,11 +1063,11 @@ static void smsc9420_set_multicast_list(struct net_device *dev) mac_cr |= MAC_CR_MCPAS_; mac_cr &= (~MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *mc_list = dev->mc_list; + struct dev_mc_list *mc_list; u32 hash_lo = 0, hash_hi = 0; smsc_dbg(HW, "Multicast filter enabled"); - while (mc_list) { + netdev_for_each_mc_addr(mc_list, dev) { u32 bit_num = smsc9420_hash(mc_list->dmi_addr); u32 mask = 1 << (bit_num & 0x1F); @@ -1076,7 +1076,6 @@ static void smsc9420_set_multicast_list(struct net_device *dev) else hash_lo |= mask; - mc_list = mc_list->next; } smsc9420_reg_write(pd, HASHH, hash_hi); smsc9420_reg_write(pd, HASHL, hash_lo); diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index bd8bc66f2e00..287c251075e5 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c @@ -531,7 +531,7 @@ static void sonic_multicast_list(struct net_device *dev) { struct sonic_local *lp = netdev_priv(dev); unsigned int rcr; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; unsigned char *addr; int i; @@ -549,13 +549,14 @@ static void sonic_multicast_list(struct net_device *dev) printk("sonic_multicast_list: mc_count %d\n", netdev_mc_count(dev)); sonic_set_cam_enable(dev, 1); /* always enable our own address */ - for (i = 1; i <= netdev_mc_count(dev); i++) { + i = 1; + netdev_for_each_mc_addr(dmi, dev) { addr = dmi->dmi_addr; - dmi = dmi->next; sonic_cda_put(dev, i, SONIC_CD_CAP0, addr[1] << 8 | addr[0]); sonic_cda_put(dev, i, SONIC_CD_CAP1, addr[3] << 8 | addr[2]); sonic_cda_put(dev, i, SONIC_CD_CAP2, addr[5] << 8 | addr[4]); sonic_set_cam_enable(dev, sonic_get_cam_enable(dev) | (1 << i)); + i++; } SONIC_WRITE(SONIC_CDC, 16); /* issue Load CAM command */ diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 16191998ac67..2f8a8c32021e 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -646,7 +646,7 @@ spider_net_set_multi(struct net_device *netdev) hash = spider_net_get_multicast_hash(netdev, netdev->broadcast); */ set_bit(0xfd, bitmask); - for (mc = netdev->mc_list; mc; mc = mc->next) { + netdev_for_each_mc_addr(mc, netdev) { hash = spider_net_get_multicast_hash(netdev, mc->dmi_addr); set_bit(hash, bitmask); } diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 58bc7ac086cf..0f405ef51858 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1804,14 +1804,14 @@ static void set_rx_mode(struct net_device *dev) /* Use the 16 element perfect filter, skip first two entries. */ void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16; __be16 *eaddrs; - for (i = 2, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev) + 2; - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { eaddrs = (__be16 *)mclist->dmi_addr; writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8; } eaddrs = (__be16 *)dev->dev_addr; + i = netdev_mc_count(dev) + 2; while (i++ < 16) { writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4; writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4; diff --git a/drivers/net/stmmac/dwmac100.c b/drivers/net/stmmac/dwmac100.c index 576b256ee388..803b0373d843 100644 --- a/drivers/net/stmmac/dwmac100.c +++ b/drivers/net/stmmac/dwmac100.c @@ -315,7 +315,6 @@ static void dwmac100_set_filter(struct net_device *dev) value &= ~(MAC_CONTROL_PM | MAC_CONTROL_PR | MAC_CONTROL_IF | MAC_CONTROL_HO | MAC_CONTROL_HP); } else { - int i; u32 mc_filter[2]; struct dev_mc_list *mclist; @@ -326,8 +325,7 @@ static void dwmac100_set_filter(struct net_device *dev) MAC_CONTROL_IF | MAC_CONTROL_HO); memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { /* The upper 6 bits of the calculated CRC are used to * index the contens of the hash table */ int bit_nr = diff --git a/drivers/net/stmmac/dwmac1000_core.c b/drivers/net/stmmac/dwmac1000_core.c index 90dbb4f41ef3..a6538ae4694c 100644 --- a/drivers/net/stmmac/dwmac1000_core.c +++ b/drivers/net/stmmac/dwmac1000_core.c @@ -93,7 +93,6 @@ static void dwmac1000_set_filter(struct net_device *dev) writel(0xffffffff, ioaddr + GMAC_HASH_HIGH); writel(0xffffffff, ioaddr + GMAC_HASH_LOW); } else if (!netdev_mc_empty(dev)) { - int i; u32 mc_filter[2]; struct dev_mc_list *mclist; @@ -101,8 +100,7 @@ static void dwmac1000_set_filter(struct net_device *dev) value = GMAC_FRAME_FILTER_HMC; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { /* The upper 6 bits of the calculated CRC are used to index the contens of the hash table */ int bit_nr = diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index efedc252e4be..2f6a760e5f21 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c @@ -413,7 +413,7 @@ static int init586(struct net_device *dev) volatile struct iasetup_cmd_struct *ias_cmd; volatile struct tdr_cmd_struct *tdr_cmd; volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi=dev->mc_list; + struct dev_mc_list *dmi; int num_addrs=netdev_mc_count(dev); ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); @@ -536,8 +536,10 @@ static int init586(struct net_device *dev) mc_cmd->cmd_link = 0xffff; mc_cmd->mc_cnt = swab16(num_addrs * 6); - for(i=0;inext) - memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6); + i = 0; + netdev_for_each_mc_addr(dmi, dev) + memcpy((char *) mc_cmd->mc_list[i++], + dmi->dmi_addr, ETH_ALEN); p->scb->cbl_offset = make16(mc_cmd); p->scb->cmd_cuc = CUC_START; diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index dfea56fa39e3..a0bd361d5eca 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -999,7 +999,7 @@ static void bigmac_set_multicast(struct net_device *dev) { struct bigmac *bp = netdev_priv(dev); void __iomem *bregs = bp->bregs; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; int i; u32 tmp, crc; @@ -1028,9 +1028,8 @@ static void bigmac_set_multicast(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 4171259590b2..a855934dfc3b 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1528,8 +1528,7 @@ static void set_rx_mode(struct net_device *dev) int index; int crc; memset (mc_filter, 0, sizeof (mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr); for (index=0, bit=0; bit < 6; bit++, crc <<= 1) if (crc & 0x80000000) index |= 1 << bit; diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index d497ec053953..4344017bfaef 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1846,17 +1846,13 @@ static u32 gem_setup_multicast(struct gem *gp) } else { u16 hash_table[16]; u32 crc; - struct dev_mc_list *dmi = gp->dev->mc_list; + struct dev_mc_list *dmi; int i; - for (i = 0; i < 16; i++) - hash_table[i] = 0; - - for (i = 0; i < netdev_mc_count(gp->dev); i++) { + memset(hash_table, 0, sizeof(hash_table)); + netdev_for_each_mc_addr(dmi, gp->dev) { char *addrs = dmi->dmi_addr; - dmi = dmi->next; - if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 905df35ff78a..b17dbb11bd67 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1523,17 +1523,13 @@ static int happy_meal_init(struct happy_meal *hp) hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff); } else if ((hp->dev->flags & IFF_PROMISC) == 0) { u16 hash_table[4]; - struct dev_mc_list *dmi = hp->dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; - for (i = 0; i < 4; i++) - hash_table[i] = 0; - - for (i = 0; i < netdev_mc_count(hp->dev); i++) { + memset(hash_table, 0, sizeof(hash_table)); + netdev_for_each_mc_addr(dmi, hp->dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if (!(*addrs & 1)) continue; @@ -2366,9 +2362,8 @@ static void happy_meal_set_multicast(struct net_device *dev) { struct happy_meal *hp = netdev_priv(dev); void __iomem *bregs = hp->bigmacregs; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; spin_lock_irq(&hp->happy_lock); @@ -2384,12 +2379,9 @@ static void happy_meal_set_multicast(struct net_device *dev) } else { u16 hash_table[4]; - for (i = 0; i < 4; i++) - hash_table[i] = 0; - - for (i = 0; i < netdev_mc_count(dev); i++) { + memset(hash_table, 0, sizeof(hash_table)); + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index cf9d5bb9e1e9..d7c73f478ef5 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -1170,9 +1170,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) static void lance_load_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; u32 val; @@ -1196,9 +1195,8 @@ static void lance_load_multicast(struct net_device *dev) return; /* Add addresses */ - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index 3bc35d86ed66..be637dce944c 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c @@ -627,7 +627,7 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev) static void qe_set_multicast(struct net_device *dev) { struct sunqe *qep = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; u8 new_mconfig = qep->mconfig; char *addrs; int i; @@ -650,12 +650,9 @@ static void qe_set_multicast(struct net_device *dev) u16 hash_table[4]; u8 *hbytes = (unsigned char *) &hash_table[0]; - for (i = 0; i < 4; i++) - hash_table[i] = 0; - - for (i = 0; i < netdev_mc_count(dev); i++) { + memset(hash_table, 0, sizeof(hash_table)); + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if (!(*addrs & 1)) continue; diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index d65764ea1d83..6b1b7cea7f6b 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c @@ -765,7 +765,7 @@ static void __update_mc_list(struct vnet *vp, struct net_device *dev) { struct dev_addr_list *p; - for (p = dev->mc_list; p; p = p->next) { + netdev_for_each_mc_addr(p, dev) { struct vnet_mcast_entry *m; m = __vnet_mc_find(vp, p->dmi_addr); -- cgit v1.2.3 From 4302b67e041ea81c8fc233bee1296516e1294a27 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 18 Feb 2010 03:34:54 +0000 Subject: tulip: convert to use netdev_for_each_mc_addr also bug in de2104x.c was corrected: for (i = 0; i < 32; i++) loop should be outside mc_list iteration. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/tulip/de2104x.c | 19 ++++++++----------- drivers/net/tulip/de4x5.c | 14 ++++++-------- drivers/net/tulip/dmfe.c | 27 +++++++++++++-------------- drivers/net/tulip/tulip_core.c | 15 ++++----------- drivers/net/tulip/uli526x.c | 4 ++-- drivers/net/tulip/winbond-840.c | 6 ++---- 6 files changed, 35 insertions(+), 50 deletions(-) diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index a4cff23dcdf9..cb429723b2c8 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -677,18 +677,17 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; set_bit_le(index, hash_table); + } - for (i = 0; i < 32; i++) { - *setup_frm++ = hash_table[i]; - *setup_frm++ = hash_table[i]; - } - setup_frm = &de->setup_frame[13*6]; + for (i = 0; i < 32; i++) { + *setup_frm++ = hash_table[i]; + *setup_frm++ = hash_table[i]; } + setup_frm = &de->setup_frame[13*6]; /* Fill the final entry with our physical address. */ eaddrs = (u16 *)dev->dev_addr; @@ -701,20 +700,18 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) { struct de_private *de = netdev_priv(dev); struct dev_mc_list *mclist; - int i; u16 *eaddrs; /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { eaddrs = (u16 *)mclist->dmi_addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; } /* Fill the unused entries with the broadcast address. */ - memset(setup_frm, 0xff, (15-i)*12); + memset(setup_frm, 0xff, (15 - netdev_mc_count(dev)) * 12); setup_frm = &de->setup_frame[15*6]; /* Fill the final entry with our physical address. */ diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index 0b6a9731091c..c4ecb9a95409 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1951,9 +1951,9 @@ static void SetMulticastFilter(struct net_device *dev) { struct de4x5_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi=dev->mc_list; + struct dev_mc_list *dmi; u_long iobase = dev->base_addr; - int i, j, bit, byte; + int i, bit, byte; u16 hashcode; u32 omr, crc; char *pa; @@ -1966,9 +1966,8 @@ SetMulticastFilter(struct net_device *dev) if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 14)) { omr |= OMR_PM; /* Pass all multicasts */ } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */ - for (i = 0; i < netdev_mc_count(dev) ;i++) { - addrs=dmi->dmi_addr; - dmi=dmi->next; + netdev_for_each_mc_addr(dmi, dev) { + addrs = dmi->dmi_addr; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ @@ -1984,9 +1983,8 @@ SetMulticastFilter(struct net_device *dev) } } } else { /* Perfect filtering */ - for (j=0; jdmi_addr; - dmi=dmi->next; + netdev_for_each_mc_addr(dmi, dev) { + addrs = dmi->dmi_addr; for (i=0; ichip_id == PCI_DM9132_ID) - dm9132_id_table(dev, netdev_mc_count(dev)); /* DM9132 */ + dm9132_id_table(dev); /* DM9132 */ else - send_filter_frame(dev, netdev_mc_count(dev)); /* DM9102/DM9102A */ + send_filter_frame(dev); /* DM9102/DM9102A */ /* Init CR7, interrupt active bit */ db->cr7_data = CR7_DEFAULT; @@ -1075,9 +1075,9 @@ static void dmfe_set_filter_mode(struct DEVICE * dev) DMFE_DBUG(0, "Set multicast address", mc_count); if (db->chip_id == PCI_DM9132_ID) - dm9132_id_table(dev, mc_count); /* DM9132 */ + dm9132_id_table(dev); /* DM9132 */ else - send_filter_frame(dev, mc_count); /* DM9102/DM9102A */ + send_filter_frame(dev); /* DM9102/DM9102A */ spin_unlock_irqrestore(&db->lock, flags); } @@ -1452,7 +1452,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr) * This setup frame initilize DM910X address filter mode */ -static void dm9132_id_table(struct DEVICE *dev, int mc_cnt) +static void dm9132_id_table(struct DEVICE *dev) { struct dev_mc_list *mcptr; u16 * addrptr; @@ -1472,15 +1472,14 @@ static void dm9132_id_table(struct DEVICE *dev, int mc_cnt) ioaddr += 4; /* Clear Hash Table */ - for (i = 0; i < 4; i++) - hash_table[i] = 0x0; + memset(hash_table, 0, sizeof(hash_table)); /* broadcast address */ hash_table[3] = 0x8000; /* the multicast address in Hash Table : 64 bits */ - for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { - hash_val = cal_CRC( (char *) mcptr->dmi_addr, 6, 0) & 0x3f; + netdev_for_each_mc_addr(mcptr, dev) { + hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } @@ -1495,7 +1494,7 @@ static void dm9132_id_table(struct DEVICE *dev, int mc_cnt) * This setup frame initilize DM910X address filter mode */ -static void send_filter_frame(struct DEVICE *dev, int mc_cnt) +static void send_filter_frame(struct DEVICE *dev) { struct dmfe_board_info *db = netdev_priv(dev); struct dev_mc_list *mcptr; @@ -1521,14 +1520,14 @@ static void send_filter_frame(struct DEVICE *dev, int mc_cnt) *suptr++ = 0xffff; /* fit the multicast address */ - for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { + netdev_for_each_mc_addr(mcptr, dev) { addrptr = (u16 *) mcptr->dmi_addr; *suptr++ = addrptr[0]; *suptr++ = addrptr[1]; *suptr++ = addrptr[2]; } - for (; i<14; i++) { + for (i = netdev_mc_count(dev); i < 14; i++) { *suptr++ = 0xffff; *suptr++ = 0xffff; *suptr++ = 0xffff; diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index cce2ada07950..7f544ef2f5fc 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -997,12 +997,10 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) memset(hash_table, 0, sizeof(hash_table)); set_bit_le(255, hash_table); /* Broadcast entry */ /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; set_bit_le(index, hash_table); - } for (i = 0; i < 32; i++) { *setup_frm++ = hash_table[i]; @@ -1021,20 +1019,18 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); struct dev_mc_list *mclist; - int i; u16 *eaddrs; /* We have <= 14 addresses so we can use the wonderful 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { eaddrs = (u16 *)mclist->dmi_addr; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; } /* Fill the unused entries with the broadcast address. */ - memset(setup_frm, 0xff, (15-i)*12); + memset(setup_frm, 0xff, (15 - netdev_mc_count(dev)) * 12); setup_frm = &tp->setup_frame[15*6]; /* Fill the final entry with our physical address. */ @@ -1066,7 +1062,6 @@ static void set_rx_mode(struct net_device *dev) /* Some work-alikes have only a 64-entry hash filter table. */ /* Should verify correctness on big-endian/__powerpc__ */ struct dev_mc_list *mclist; - int i; if (netdev_mc_count(dev) > 64) { /* Arbitrary non-effective limit. */ tp->csr6 |= AcceptAllMulticast; @@ -1074,9 +1069,7 @@ static void set_rx_mode(struct net_device *dev) } else { u32 mc_filter[2] = {0, 0}; /* Multicast hash filter */ int filterbit; - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { if (tp->flags & COMET_MAC_ADDR) filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr); else diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 216ceb322ed4..0ab05af237e5 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -1415,14 +1415,14 @@ static void send_filter_frame(struct net_device *dev, int mc_cnt) *suptr++ = 0xffff << FLT_SHIFT; /* fit the multicast address */ - for (mcptr = dev->mc_list, i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { + netdev_for_each_mc_addr(mcptr, dev) { addrptr = (u16 *) mcptr->dmi_addr; *suptr++ = addrptr[0] << FLT_SHIFT; *suptr++ = addrptr[1] << FLT_SHIFT; *suptr++ = addrptr[2] << FLT_SHIFT; } - for (; i<14; i++) { + for (i = netdev_mc_count(dev); i < 14; i++) { *suptr++ = 0xffff << FLT_SHIFT; *suptr++ = 0xffff << FLT_SHIFT; *suptr++ = 0xffff << FLT_SHIFT; diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index 98711a9f35ac..304f43866c44 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -1368,11 +1368,9 @@ static u32 __set_rx_mode(struct net_device *dev) rx_mode = RxAcceptBroadcast | AcceptMulticast | AcceptMyPhys; } else { struct dev_mc_list *mclist; - int i; + memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int filterbit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; filterbit &= 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); -- cgit v1.2.3 From a92635dc77b14f0f28d45c0fbf91b5064d9d7617 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 18 Feb 2010 04:02:26 +0000 Subject: net/usb: convert to use netdev_for_each_mc_addr also removed needless checks in smsc95xx Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 12 ++++-------- drivers/net/usb/catc.c | 5 +---- drivers/net/usb/mcs7830.c | 6 ++---- drivers/net/usb/smsc95xx.c | 26 ++++++++------------------ 4 files changed, 15 insertions(+), 34 deletions(-) diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index f605204de3e5..20e34608fa4a 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -555,20 +555,18 @@ static void asix_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list = net->mc_list; + struct dev_mc_list *mc_list; u32 crc_bits; - int i; memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - for (i = 0; i < netdev_mc_count(net); i++) { + netdev_for_each_mc_addr(mc_list, net) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); - mc_list = mc_list->next; } asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, @@ -769,20 +767,18 @@ static void ax88172_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list = net->mc_list; + struct dev_mc_list *mc_list; u32 crc_bits; - int i; memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); /* Build the multicast hash filter. */ - for (i = 0; i < netdev_mc_count(net); i++) { + netdev_for_each_mc_addr(mc_list, net) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); - mc_list = mc_list->next; } asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 5a13660ebd17..96f1ebe0d348 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -632,7 +632,6 @@ static void catc_set_multicast_list(struct net_device *netdev) struct dev_mc_list *mc; u8 broadcast[6]; u8 rx = RxEnable | RxPolarity | RxMultiCast; - int i; memset(broadcast, 0xff, 6); memset(catc->multicast, 0, 64); @@ -648,9 +647,7 @@ static void catc_set_multicast_list(struct net_device *netdev) if (netdev->flags & IFF_ALLMULTI) { memset(catc->multicast, 0xff, 64); } else { - for (i = 0, mc = netdev->mc_list; - mc && i < netdev_mc_count(netdev); - i++, mc = mc->next) { + netdev_for_each_mc_addr(mc, netdev) { u32 crc = ether_crc_le(6, mc->dmi_addr); if (!catc->is_f5u011) { catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 34665137f2c3..70978219e98a 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -452,15 +452,13 @@ static void mcs7830_data_set_multicast(struct net_device *net) * for our 8 byte filter buffer * to avoid allocating memory that * is tricky to free later */ - struct dev_mc_list *mc_list = net->mc_list; + struct dev_mc_list *mc_list; u32 crc_bits; - int i; /* Build the multicast hash filter. */ - for (i = 0; i < netdev_mc_count(net); i++) { + netdev_for_each_mc_addr(mc_list, net) { crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); - mc_list = mc_list->next; } } } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 1ada51eb71f7..df9179a1c93b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -384,30 +384,20 @@ static void smsc95xx_set_multicast(struct net_device *netdev) pdata->mac_cr |= MAC_CR_MCPAS_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); } else if (!netdev_mc_empty(dev->net)) { - struct dev_mc_list *mc_list = dev->net->mc_list; - int count = 0; + struct dev_mc_list *mc_list; pdata->mac_cr |= MAC_CR_HPFILT_; pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); - while (mc_list) { - count++; - if (mc_list->dmi_addrlen == ETH_ALEN) { - u32 bitnum = smsc95xx_hash(mc_list->dmi_addr); - u32 mask = 0x01 << (bitnum & 0x1F); - if (bitnum & 0x20) - hash_hi |= mask; - else - hash_lo |= mask; - } else { - netdev_warn(dev->net, "dmi_addrlen != 6\n"); - } - mc_list = mc_list->next; + netdev_for_each_mc_addr(mc_list, netdev) { + u32 bitnum = smsc95xx_hash(mc_list->dmi_addr); + u32 mask = 0x01 << (bitnum & 0x1F); + if (bitnum & 0x20) + hash_hi |= mask; + else + hash_lo |= mask; } - if (count != ((u32) netdev_mc_count(dev->net))) - netdev_warn(dev->net, "mc_count != dev->mc_count\n"); - netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n", hash_hi, hash_lo); } else { -- cgit v1.2.3 From d59079425f6f1be0da995926b5ad1d54d9e4545d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 18 Feb 2010 05:10:14 +0000 Subject: staging: convert to use netdev_for_each_mc_addr removed needless checks in arlan-main.c and slicoss.c fixed bug in et131x_netdev.c to actually fill addresses in. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/staging/arlan/arlan-main.c | 25 ++++++++++--------------- drivers/staging/et131x/et131x_netdev.c | 15 ++++++++------- drivers/staging/octeon/ethernet.c | 2 +- drivers/staging/slicoss/slicoss.c | 16 ++++------------ drivers/staging/vt6655/device_main.c | 6 ++---- drivers/staging/vt6656/main_usb.c | 5 ++--- drivers/staging/wavelan/wavelan.c | 6 +++--- drivers/staging/wavelan/wavelan_cs.c | 9 ++++----- drivers/staging/wlags49_h2/wl_netdev.c | 16 ++++++---------- 9 files changed, 40 insertions(+), 60 deletions(-) diff --git a/drivers/staging/arlan/arlan-main.c b/drivers/staging/arlan/arlan-main.c index 921a082487a1..88fdd53cf5d3 100644 --- a/drivers/staging/arlan/arlan-main.c +++ b/drivers/staging/arlan/arlan-main.c @@ -1455,10 +1455,10 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short #ifdef ARLAN_MULTICAST if (!(dev->flags & IFF_ALLMULTI) && !(dev->flags & IFF_PROMISC) && - dev->mc_list) + !netdev_mc_empty(dev)) { char hw_dst_addr[6]; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; int i; memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6); @@ -1469,20 +1469,15 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short printk(KERN_ERR "%s mcast 0x0100 \n", dev->name); else if (hw_dst_addr[1] == 0x40) printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name); - while (dmi) - { - if (dmi->dmi_addrlen == 6) { - if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) - printk(KERN_ERR "%s mcl %pM\n", - dev->name, dmi->dmi_addr); - for (i = 0; i < 6; i++) - if (dmi->dmi_addr[i] != hw_dst_addr[i]) - break; - if (i == 6) + netdev_for_each_mc_entry(dmi, dev) { + if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) + printk(KERN_ERR "%s mcl %pM\n", + dev->name, dmi->dmi_addr); + for (i = 0; i < 6; i++) + if (dmi->dmi_addr[i] != hw_dst_addr[i]) break; - } else - printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name); - dmi = dmi->next; + if (i == 6) + break; } /* we reach here if multicast filtering is on and packet * is multicast and not for receive */ diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c index bc1fad248952..edb78ae9e593 100644 --- a/drivers/staging/et131x/et131x_netdev.c +++ b/drivers/staging/et131x/et131x_netdev.c @@ -411,9 +411,9 @@ void et131x_multicast(struct net_device *netdev) { struct et131x_adapter *adapter = netdev_priv(netdev); uint32_t PacketFilter = 0; - uint32_t count; unsigned long flags; - struct dev_mc_list *mclist = netdev->mc_list; + struct dev_mc_list *mclist; + int i; spin_lock_irqsave(&adapter->Lock, flags); @@ -456,12 +456,13 @@ void et131x_multicast(struct net_device *netdev) } /* Set values in the private adapter struct */ - adapter->MCAddressCount = netdev_mc_count(netdev); - - if (!netdev_mc_empty(netdev)) { - count = netdev_mc_count(netdev) - 1; - memcpy(adapter->MCList[count], mclist->dmi_addr, ETH_ALEN); + i = 0; + netdev_for_each_mc_addr(mclist, netdev) { + if (i == NIC_MAX_MCAST_LIST) + break; + memcpy(adapter->MCList[i++], mclist->dmi_addr, ETH_ALEN); } + adapter->MCAddressCount = i; /* Are the new flags different from the previous ones? If not, then no * action is required diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 4cfd4b136b32..220de133a6a5 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -382,7 +382,7 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) control.u64 = 0; control.s.bcst = 1; /* Allow broadcast MAC addresses */ - if (dev->mc_list || (dev->flags & IFF_ALLMULTI) || + if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) /* Force accept multicast packets */ control.s.mcst = 2; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index 8c9d5e5c7702..f5cc01ba4145 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -1362,25 +1362,17 @@ static void slic_mcast_set_list(struct net_device *dev) { struct adapter *adapter = (struct adapter *)netdev_priv(dev); int status = STATUS_SUCCESS; - int i; char *addresses; - struct dev_mc_list *mc_list = dev->mc_list; - int mc_count = netdev_mc_count(dev); + struct dev_mc_list *mc_list; ASSERT(adapter); - for (i = 1; i <= mc_count; i++) { + netdev_for_each_mc_addr(mc_list, dev) { addresses = (char *) &mc_list->dmi_addr; - if (mc_list->dmi_addrlen == 6) { - status = slic_mcast_add_list(adapter, addresses); - if (status != STATUS_SUCCESS) - break; - } else { - status = -EINVAL; + status = slic_mcast_add_list(adapter, addresses); + if (status != STATUS_SUCCESS) break; - } slic_mcast_set_bit(adapter, addresses); - mc_list = mc_list->next; } if (adapter->devflags_prev != dev->flags) { diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 82b3a6e0b15a..0dadb765fece 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -3082,8 +3082,7 @@ static void device_set_multi(struct net_device *dev) { PSMgmtObject pMgmt = pDevice->pMgmt; u32 mc_filter[2]; - int i; - struct dev_mc_list *mclist; + struct dev_mc_list *mclist; VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); @@ -3103,8 +3102,7 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); } diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 2c6a5350547c..a8e1adbc9592 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1596,7 +1596,7 @@ static void device_set_multi(struct net_device *dev) { PSMgmtObject pMgmt = &(pDevice->sMgmtObj); u32 mc_filter[2]; int ii; - struct dev_mc_list *mclist; + struct dev_mc_list *mclist; BYTE pbyData[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; BYTE byTmpMode = 0; int rc; @@ -1632,8 +1632,7 @@ static void device_set_multi(struct net_device *dev) { } else { memset(mc_filter, 0, sizeof(mc_filter)); - for (ii = 0, mclist = dev->mc_list; mclist && ii < netdev_mc_count(dev); - ii++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); } diff --git a/drivers/staging/wavelan/wavelan.c b/drivers/staging/wavelan/wavelan.c index 961f1417fb58..54ca63196fdd 100644 --- a/drivers/staging/wavelan/wavelan.c +++ b/drivers/staging/wavelan/wavelan.c @@ -1387,7 +1387,7 @@ static void wavelan_set_multicast_list(struct net_device * dev) } } else /* Are there multicast addresses to send? */ - if (dev->mc_list != (struct dev_mc_list *) NULL) { + if (!netdev_mc_empty(dev)) { /* * Disable promiscuous mode, but receive all packets * in multicast list @@ -3531,7 +3531,7 @@ static void wv_82586_config(struct net_device * dev) /* Any address to set? */ if (lp->mc_count) { - for (dmi = dev->mc_list; dmi; dmi = dmi->next) + netdev_for_each_mc_addr(dmi, dev) outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr, WAVELAN_ADDR_SIZE >> 1); @@ -3539,7 +3539,7 @@ static void wv_82586_config(struct net_device * dev) printk(KERN_DEBUG "%s: wv_82586_config(): set %d multicast addresses:\n", dev->name, lp->mc_count); - for (dmi = dev->mc_list; dmi; dmi = dmi->next) + netdev_for_each_mc_addr(dmi, dev) printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); #endif } diff --git a/drivers/staging/wavelan/wavelan_cs.c b/drivers/staging/wavelan/wavelan_cs.c index 08fcb226d7d6..04f691d127b4 100644 --- a/drivers/staging/wavelan/wavelan_cs.c +++ b/drivers/staging/wavelan/wavelan_cs.c @@ -1410,8 +1410,7 @@ wavelan_set_multicast_list(struct net_device * dev) } else /* If there is some multicast addresses to send */ - if(dev->mc_list != (struct dev_mc_list *) NULL) - { + if (!netdev_mc_empty(dev)) { /* * Disable promiscuous mode, but receive all packets * in multicast list @@ -3598,13 +3597,13 @@ wv_82593_config(struct net_device * dev) /* If any multicast address to set */ if(lp->mc_count) { - struct dev_mc_list * dmi; + struct dev_mc_list *dmi; int addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count; #ifdef DEBUG_CONFIG_INFO printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n", dev->name, lp->mc_count); - for(dmi=dev->mc_list; dmi; dmi=dmi->next) + netdev_for_each_mc_addr(dmi, dev) printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); #endif @@ -3613,7 +3612,7 @@ wv_82593_config(struct net_device * dev) outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); outb(addrs_len & 0xff, PIOP(base)); /* byte count lsb */ outb((addrs_len >> 8), PIOP(base)); /* byte count msb */ - for(dmi=dev->mc_list; dmi; dmi=dmi->next) + netdev_for_each_mc_addr(dmi, dev) outsb(PIOP(base), dmi->dmi_addr, dmi->dmi_addrlen); /* reset transmit DMA pointer */ diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c index a95ebf881fcd..c33e225bc0e6 100644 --- a/drivers/staging/wlags49_h2/wl_netdev.c +++ b/drivers/staging/wlags49_h2/wl_netdev.c @@ -1049,7 +1049,7 @@ void wl_multicast( struct net_device *dev ) //;?seems reasonable that even an AP-only driver could afford this small additional footprint int x; - struct dev_mc_list *mclist; + struct dev_mc_list *mclist; struct wl_private *lp = wl_priv(dev); unsigned long flags; /*------------------------------------------------------------------------*/ @@ -1072,11 +1072,9 @@ void wl_multicast( struct net_device *dev ) DBG_PRINT( " mc_count: %d\n", netdev_mc_count(dev)); - for( x = 0, mclist = dev->mc_list; mclist && x < netdev_mc_count(dev); - x++, mclist = mclist->next ) { + netdev_for_each_mc_addr(mclist, dev) DBG_PRINT( " %s (%d)\n", DbgHwAddr(mclist->dmi_addr), mclist->dmi_addrlen ); - } } #endif /* DBG */ @@ -1120,12 +1118,10 @@ void wl_multicast( struct net_device *dev ) lp->ltvRecord.len = ( netdev_mc_count(dev) * 3 ) + 1; lp->ltvRecord.typ = CFG_GROUP_ADDR; - for( x = 0, mclist = dev->mc_list; - ( x < netdev_mc_count(dev)) && ( mclist != NULL ); - x++, mclist = mclist->next ) { - memcpy( &( lp->ltvRecord.u.u8[x * ETH_ALEN] ), - mclist->dmi_addr, ETH_ALEN ); - } + x = 0; + netdev_for_each_mc_addr(mclist, dev) + memcpy(&(lp->ltvRecord.u.u8[x++ * ETH_ALEN]), + mclist->dmi_addr, ETH_ALEN); DBG_PRINT( "Setting multicast list\n" ); hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord )); } else { -- cgit v1.2.3 From 16cad981863344ef779ab703545bb6f261a0f0ce Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 18 Feb 2010 02:47:07 +0000 Subject: tokenring: convert to use netdev_for_each_mc_addr Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/tokenring/3c359.c | 5 ++--- drivers/net/tokenring/ibmtr.c | 4 +--- drivers/net/tokenring/lanstreamer.c | 4 +--- drivers/net/tokenring/olympic.c | 5 ++--- drivers/net/tokenring/tms380tr.c | 8 +++----- 5 files changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c index eff68e1d107b..0fb930feea45 100644 --- a/drivers/net/tokenring/3c359.c +++ b/drivers/net/tokenring/3c359.c @@ -1390,10 +1390,9 @@ static int xl_close(struct net_device *dev) static void xl_set_rx_mode(struct net_device *dev) { struct xl_private *xl_priv = netdev_priv(dev); - struct dev_mc_list *dmi ; + struct dev_mc_list *dmi; unsigned char dev_mc_address[4] ; u16 options ; - int i ; if (dev->flags & IFF_PROMISC) options = 0x0004 ; @@ -1408,7 +1407,7 @@ static void xl_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) { + netdev_for_each_mc_addr(dmi, dev) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index 1ce8f85a89aa..1a0967246e2f 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -995,13 +995,11 @@ static void tok_set_multicast_list(struct net_device *dev) /*BMS ifconfig tr down or hot unplug a PCMCIA card ??hownowbrowncow*/ if (/*BMSHELPdev->start == 0 ||*/ ti->open_status != OPEN) return; address[0] = address[1] = address[2] = address[3] = 0; - mclist = dev->mc_list; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(mclist, dev) { address[0] |= mclist->dmi_addr[2]; address[1] |= mclist->dmi_addr[3]; address[2] |= mclist->dmi_addr[4]; address[3] |= mclist->dmi_addr[5]; - mclist = mclist->next; } SET_PAGE(ti->srb_page); for (i = 0; i < sizeof(struct srb_set_funct_addr); i++) diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 26d84daf660b..dd028fee9dc2 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -1268,7 +1268,6 @@ static void streamer_set_rx_mode(struct net_device *dev) __u8 options = 0; struct dev_mc_list *dmi; unsigned char dev_mc_address[5]; - int i; writel(streamer_priv->srb, streamer_mmio + LAPA); options = streamer_priv->streamer_copy_all_options; @@ -1303,8 +1302,7 @@ static void streamer_set_rx_mode(struct net_device *dev) writel(streamer_priv->srb,streamer_mmio+LAPA); dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) - { + netdev_for_each_mc_addr(dmi, dev) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index a242d125b34c..3a25e0434ae2 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1139,9 +1139,8 @@ static void olympic_set_rx_mode(struct net_device *dev) u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; u8 options = 0; u8 __iomem *srb; - struct dev_mc_list *dmi ; + struct dev_mc_list *dmi; unsigned char dev_mc_address[4] ; - int i ; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); @@ -1178,7 +1177,7 @@ static void olympic_set_rx_mode(struct net_device *dev) dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; - for (i=0,dmi=dev->mc_list;i < netdev_mc_count(dev); i++,dmi = dmi->next) { + netdev_for_each_mc_addr(dmi, dev) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c index 6b8868959b85..21a01753312a 100644 --- a/drivers/net/tokenring/tms380tr.c +++ b/drivers/net/tokenring/tms380tr.c @@ -1212,10 +1212,9 @@ static void tms380tr_set_multicast_list(struct net_device *dev) } else { - int i; - struct dev_mc_list *mclist = dev->mc_list; - for (i=0; i< netdev_mc_count(dev); i++) - { + struct dev_mc_list *mclist; + + netdev_for_each_mc_addr(mclist, dev) { ((char *)(&tp->ocpl.FunctAddr))[0] |= mclist->dmi_addr[2]; ((char *)(&tp->ocpl.FunctAddr))[1] |= @@ -1224,7 +1223,6 @@ static void tms380tr_set_multicast_list(struct net_device *dev) mclist->dmi_addr[4]; ((char *)(&tp->ocpl.FunctAddr))[3] |= mclist->dmi_addr[5]; - mclist = mclist->next; } } tms380tr_exec_cmd(dev, OC_SET_FUNCT_ADDR); -- cgit v1.2.3 From 5aa4b32fc86408705337e941ed716880c63d1590 Mon Sep 17 00:00:00 2001 From: Andreas Petlund Date: Thu, 18 Feb 2010 02:45:45 +0000 Subject: net: TCP thin-stream detection Inline function to dynamically detect thin streams based on the number of packets in flight. Used to dynamically trigger thin-stream mechanisms if enabled by ioctl or sysctl. Signed-off-by: Andreas Petlund Signed-off-by: David S. Miller --- Documentation/networking/tcp-thin.txt | 47 +++++++++++++++++++++++++++++++++++ include/net/tcp.h | 8 ++++++ 2 files changed, 55 insertions(+) create mode 100644 Documentation/networking/tcp-thin.txt diff --git a/Documentation/networking/tcp-thin.txt b/Documentation/networking/tcp-thin.txt new file mode 100644 index 000000000000..151e229980f1 --- /dev/null +++ b/Documentation/networking/tcp-thin.txt @@ -0,0 +1,47 @@ +Thin-streams and TCP +==================== +A wide range of Internet-based services that use reliable transport +protocols display what we call thin-stream properties. This means +that the application sends data with such a low rate that the +retransmission mechanisms of the transport protocol are not fully +effective. In time-dependent scenarios (like online games, control +systems, stock trading etc.) where the user experience depends +on the data delivery latency, packet loss can be devastating for +the service quality. Extreme latencies are caused by TCP's +dependency on the arrival of new data from the application to trigger +retransmissions effectively through fast retransmit instead of +waiting for long timeouts. + +After analysing a large number of time-dependent interactive +applications, we have seen that they often produce thin streams +and also stay with this traffic pattern throughout its entire +lifespan. The combination of time-dependency and the fact that the +streams provoke high latencies when using TCP is unfortunate. + +In order to reduce application-layer latency when packets are lost, +a set of mechanisms has been made, which address these latency issues +for thin streams. In short, if the kernel detects a thin stream, +the retransmission mechanisms are modified in the following manner: + +1) If the stream is thin, fast retransmit on the first dupACK. +2) If the stream is thin, do not apply exponential backoff. + +These enhancements are applied only if the stream is detected as +thin. This is accomplished by defining a threshold for the number +of packets in flight. If there are less than 4 packets in flight, +fast retransmissions can not be triggered, and the stream is prone +to experience high retransmission latencies. + +Since these mechanisms are targeted at time-dependent applications, +they must be specifically activated by the application using the +TCP_THIN_LINEAR_TIMEOUTS and TCP_THIN_DUPACK IOCTLS or the +tcp_thin_linear_timeouts and tcp_thin_dupack sysctls. Both +modifications are turned off by default. + +References +========== +More information on the modifications, as well as a wide range of +experimental data can be found here: +"Improving latency for interactive, thin-stream applications over +reliable transport" +http://simula.no/research/nd/publications/Simula.nd.477/simula_pdf_file diff --git a/include/net/tcp.h b/include/net/tcp.h index 75a00c80bdda..0bdc3f640247 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1386,6 +1386,14 @@ static inline void tcp_highest_sack_combine(struct sock *sk, tcp_sk(sk)->highest_sack = new; } +/* Determines whether this is a thin stream (which may suffer from + * increased latency). Used to trigger latency-reducing mechanisms. + */ +static inline unsigned int tcp_stream_is_thin(struct tcp_sock *tp) +{ + return tp->packets_out < 4 && !tcp_in_initial_slowstart(tp); +} + /* /proc */ enum tcp_seq_states { TCP_SEQ_STATE_LISTENING, -- cgit v1.2.3 From 36e31b0af58728071e8023cf8e20c5166b700717 Mon Sep 17 00:00:00 2001 From: Andreas Petlund Date: Thu, 18 Feb 2010 02:47:01 +0000 Subject: net: TCP thin linear timeouts This patch will make TCP use only linear timeouts if the stream is thin. This will help to avoid the very high latencies that thin stream suffer because of exponential backoff. This mechanism is only active if enabled by iocontrol or syscontrol and the stream is identified as thin. A maximum of 6 linear timeouts is tried before exponential backoff is resumed. Signed-off-by: Andreas Petlund Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 12 ++++++++++++ include/linux/tcp.h | 5 ++++- include/net/tcp.h | 4 ++++ net/ipv4/sysctl_net_ipv4.c | 7 +++++++ net/ipv4/tcp.c | 7 +++++++ net/ipv4/tcp_timer.c | 21 ++++++++++++++++++++- 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 2dc7a1d97686..f147310d9af4 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -487,6 +487,18 @@ tcp_dma_copybreak - INTEGER and CONFIG_NET_DMA is enabled. Default: 4096 +tcp_thin_linear_timeouts - BOOLEAN + Enable dynamic triggering of linear timeouts for thin streams. + If set, a check is performed upon retransmission by timeout to + determine if the stream is thin (less than 4 packets in flight). + As long as the stream is found to be thin, up to 6 linear + timeouts may be performed before exponential backoff mode is + initiated. This improves retransmission latency for + non-aggressive thin streams, often found to be time-dependent. + For more information on thin streams, see + Documentation/networking/tcp-thin.txt + Default: 0 + UDP variables: udp_mem - vector of 3 INTEGERs: min, pressure, max diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 7fee8a4df931..3ba8b074612f 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -103,6 +103,7 @@ enum { #define TCP_CONGESTION 13 /* Congestion control algorithm */ #define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ #define TCP_COOKIE_TRANSACTIONS 15 /* TCP Cookie Transactions */ +#define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/ /* for TCP_INFO socket option */ #define TCPI_OPT_TIMESTAMPS 1 @@ -340,7 +341,9 @@ struct tcp_sock { u32 frto_highmark; /* snd_nxt when RTO occurred */ u16 advmss; /* Advertised MSS */ u8 frto_counter; /* Number of new acks after RTO */ - u8 nonagle; /* Disable Nagle algorithm? */ + u8 nonagle : 4,/* Disable Nagle algorithm? */ + thin_lto : 1,/* Use linear timeouts for thin streams */ + unused : 3; /* RTT measurement */ u32 srtt; /* smoothed round trip time << 3 */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 0bdc3f640247..6278fc734abd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -196,6 +196,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCP_NAGLE_CORK 2 /* Socket is corked */ #define TCP_NAGLE_PUSH 4 /* Cork is overridden for already queued data */ +/* TCP thin-stream limits */ +#define TCP_THIN_LINEAR_RETRIES 6 /* After 6 linear retries, do exp. backoff */ + extern struct inet_timewait_death_row tcp_death_row; /* sysctl variables for tcp */ @@ -241,6 +244,7 @@ extern int sysctl_tcp_workaround_signed_windows; extern int sysctl_tcp_slow_start_after_idle; extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; +extern int sysctl_tcp_thin_linear_timeouts; extern atomic_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7e3712ce3994..e6a2460587d4 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -575,6 +575,13 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_thin_linear_timeouts", + .data = &sysctl_tcp_thin_linear_timeouts, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { .procname = "udp_mem", .data = &sysctl_udp_mem, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e471d037fcc9..21bae9afefea 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2229,6 +2229,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, } break; + case TCP_THIN_LINEAR_TIMEOUTS: + if (val < 0 || val > 1) + err = -EINVAL; + else + tp->thin_lto = val; + break; + case TCP_CORK: /* When set indicates to always queue non-full frames. * Later the user clears this option and we transmit diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index de7d1bf9114f..a17629b8912e 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -29,6 +29,7 @@ int sysctl_tcp_keepalive_intvl __read_mostly = TCP_KEEPALIVE_INTVL; int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; int sysctl_tcp_orphan_retries __read_mostly; +int sysctl_tcp_thin_linear_timeouts __read_mostly; static void tcp_write_timer(unsigned long); static void tcp_delack_timer(unsigned long); @@ -415,7 +416,25 @@ void tcp_retransmit_timer(struct sock *sk) icsk->icsk_retransmits++; out_reset_timer: - icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); + /* If stream is thin, use linear timeouts. Since 'icsk_backoff' is + * used to reset timer, set to 0. Recalculate 'icsk_rto' as this + * might be increased if the stream oscillates between thin and thick, + * thus the old value might already be too high compared to the value + * set by 'tcp_set_rto' in tcp_input.c which resets the rto without + * backoff. Limit to TCP_THIN_LINEAR_RETRIES before initiating + * exponential backoff behaviour to avoid continue hammering + * linear-timeout retransmissions into a black hole + */ + if (sk->sk_state == TCP_ESTABLISHED && + (tp->thin_lto || sysctl_tcp_thin_linear_timeouts) && + tcp_stream_is_thin(tp) && + icsk->icsk_retransmits <= TCP_THIN_LINEAR_RETRIES) { + icsk->icsk_backoff = 0; + icsk->icsk_rto = min(__tcp_set_rto(tp), TCP_RTO_MAX); + } else { + /* Use normal (exponential) backoff */ + icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); + } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1)) __sk_dst_reset(sk); -- cgit v1.2.3 From 7e38017557bc0b87434d184f8804cadb102bb903 Mon Sep 17 00:00:00 2001 From: Andreas Petlund Date: Thu, 18 Feb 2010 04:48:19 +0000 Subject: net: TCP thin dupack This patch enables fast retransmissions after one dupACK for TCP if the stream is identified as thin. This will reduce latencies for thin streams that are not able to trigger fast retransmissions due to high packet interarrival time. This mechanism is only active if enabled by iocontrol or syscontrol and the stream is identified as thin. Signed-off-by: Andreas Petlund Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 12 ++++++++++++ include/linux/tcp.h | 4 +++- include/net/tcp.h | 1 + net/ipv4/sysctl_net_ipv4.c | 7 +++++++ net/ipv4/tcp.c | 7 +++++++ net/ipv4/tcp_input.c | 12 ++++++++++++ 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index f147310d9af4..2571a62d923e 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -499,6 +499,18 @@ tcp_thin_linear_timeouts - BOOLEAN Documentation/networking/tcp-thin.txt Default: 0 +tcp_thin_dupack - BOOLEAN + Enable dynamic triggering of retransmissions after one dupACK + for thin streams. If set, a check is performed upon reception + of a dupACK to determine if the stream is thin (less than 4 + packets in flight). As long as the stream is found to be thin, + data is retransmitted on the first received dupACK. This + improves retransmission latency for non-aggressive thin + streams, often found to be time-dependent. + For more information on thin streams, see + Documentation/networking/tcp-thin.txt + Default: 0 + UDP variables: udp_mem - vector of 3 INTEGERs: min, pressure, max diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 3ba8b074612f..a778ee024590 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -104,6 +104,7 @@ enum { #define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ #define TCP_COOKIE_TRANSACTIONS 15 /* TCP Cookie Transactions */ #define TCP_THIN_LINEAR_TIMEOUTS 16 /* Use linear timeouts for thin streams*/ +#define TCP_THIN_DUPACK 17 /* Fast retrans. after 1 dupack */ /* for TCP_INFO socket option */ #define TCPI_OPT_TIMESTAMPS 1 @@ -343,7 +344,8 @@ struct tcp_sock { u8 frto_counter; /* Number of new acks after RTO */ u8 nonagle : 4,/* Disable Nagle algorithm? */ thin_lto : 1,/* Use linear timeouts for thin streams */ - unused : 3; + thin_dupack : 1,/* Fast retransmit on first dupack */ + unused : 2; /* RTT measurement */ u32 srtt; /* smoothed round trip time << 3 */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 6278fc734abd..56f0aec40ed6 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -245,6 +245,7 @@ extern int sysctl_tcp_slow_start_after_idle; extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; +extern int sysctl_tcp_thin_dupack; extern atomic_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index e6a2460587d4..c1bc074f61b7 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -582,6 +582,13 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_thin_dupack", + .data = &sysctl_tcp_thin_dupack, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { .procname = "udp_mem", .data = &sysctl_udp_mem, diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 21bae9afefea..5901010fad55 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2236,6 +2236,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, tp->thin_lto = val; break; + case TCP_THIN_DUPACK: + if (val < 0 || val > 1) + err = -EINVAL; + else + tp->thin_dupack = val; + break; + case TCP_CORK: /* When set indicates to always queue non-full frames. * Later the user clears this option and we transmit diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3fddc69ccccc..788851ca8c5d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -89,6 +89,8 @@ int sysctl_tcp_frto __read_mostly = 2; int sysctl_tcp_frto_response __read_mostly; int sysctl_tcp_nometrics_save __read_mostly; +int sysctl_tcp_thin_dupack __read_mostly; + int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; int sysctl_tcp_abc __read_mostly; @@ -2447,6 +2449,16 @@ static int tcp_time_to_recover(struct sock *sk) return 1; } + /* If a thin stream is detected, retransmit after first + * received dupack. Employ only if SACK is supported in order + * to avoid possible corner-case series of spurious retransmissions + * Use only if there are no unsent data. + */ + if ((tp->thin_dupack || sysctl_tcp_thin_dupack) && + tcp_stream_is_thin(tp) && tcp_dupack_heuristics(tp) > 1 && + tcp_is_sack(tp) && !tcp_send_head(sk)) + return 1; + return 0; } -- cgit v1.2.3 From 72032fdbcde8b333e65b3430e1bcb4358e2d6716 Mon Sep 17 00:00:00 2001 From: jamal Date: Thu, 18 Feb 2010 03:35:07 +0000 Subject: xfrm: Introduce LINUX_MIB_XFRMFWDHDRERROR XFRMINHDRERROR counter is ambigous when validating forwarding path. It makes it tricky to debug when you have both in and fwd validation. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/snmp.h | 1 + net/xfrm/xfrm_policy.c | 3 +-- net/xfrm/xfrm_proc.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 0f953fe40413..e28f5a0182e8 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -257,6 +257,7 @@ enum LINUX_MIB_XFRMOUTPOLBLOCK, /* XfrmOutPolBlock */ LINUX_MIB_XFRMOUTPOLDEAD, /* XfrmOutPolDead */ LINUX_MIB_XFRMOUTPOLERROR, /* XfrmOutPolError */ + LINUX_MIB_XFRMFWDHDRERROR, /* XfrmFwdHdrError*/ __LINUX_MIB_XFRMMAX }; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2c5d93181f13..4368e7b88469 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2045,8 +2045,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) int res; if (xfrm_decode_session(skb, &fl, family) < 0) { - /* XXX: we should have something like FWDHDRERROR here. */ - XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); + XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR); return 0; } diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index 003f2c437ac3..58d9ae005597 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c @@ -41,6 +41,7 @@ static const struct snmp_mib xfrm_mib_list[] = { SNMP_MIB_ITEM("XfrmOutPolBlock", LINUX_MIB_XFRMOUTPOLBLOCK), SNMP_MIB_ITEM("XfrmOutPolDead", LINUX_MIB_XFRMOUTPOLDEAD), SNMP_MIB_ITEM("XfrmOutPolError", LINUX_MIB_XFRMOUTPOLERROR), + SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR), SNMP_MIB_SENTINEL }; -- cgit v1.2.3 From b03388d6389e8853ddd9ae19d2ba15a6dbbe5d21 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 18 Feb 2010 00:37:17 +0000 Subject: be2net: free tx buffers when completions never arrive be2net: free tx buffers when completions never arrive In cases like when a pci device is disconnected on an error, pending tx completions will never arrive. Unmap and free such buffers in the tx cleanup path. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 68e7848ac0b0..545c8417fc26 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1128,6 +1128,9 @@ static void be_tx_compl_clean(struct be_adapter *adapter) struct be_queue_info *txq = &adapter->tx_obj.q; struct be_eth_tx_compl *txcp; u16 end_idx, cmpl = 0, timeo = 0; + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + bool dummy_wrb; /* Wait for a max of 200ms for all the tx-completions to arrive. */ do { @@ -1151,6 +1154,15 @@ static void be_tx_compl_clean(struct be_adapter *adapter) if (atomic_read(&txq->used)) dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", atomic_read(&txq->used)); + + /* free posted tx for which compls will never arrive */ + while (atomic_read(&txq->used)) { + sent_skb = sent_skbs[txq->tail]; + end_idx = txq->tail; + index_adv(&end_idx, + wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + be_tx_compl_process(adapter, end_idx); + } } static void be_mcc_queues_destroy(struct be_adapter *adapter) -- cgit v1.2.3 From f546444d0b4f46d812a374a6eb2c46b7d24541f4 Mon Sep 17 00:00:00 2001 From: Chrissie Caulfield Date: Thu, 18 Feb 2010 01:33:13 +0000 Subject: Orphan DECnet Due to lack of time, space, motivation, hardware and probably expertise, I have reluctantly decided to orphan the DECnet code in the kernel. Judging by the deafening silence on the linux-decnet mailing list I suspect it's either not being used anyway, or the few people that are using it are happy with their older kernels. Signed-Off-By: Christine Caulfield Signed-off-by: David S. Miller --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 32f6915ae0eb..2c8b0d3d7128 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1733,10 +1733,9 @@ F: include/linux/tfrc.h F: net/dccp/ DECnet NETWORK LAYER -M: Christine Caulfield W: http://linux-decnet.sourceforge.net L: linux-decnet-user@lists.sourceforge.net -S: Maintained +S: Orphan F: Documentation/networking/decnet.txt F: net/decnet/ -- cgit v1.2.3 From 05dbe005386e7521153dce6c5ad95c98b73b80c7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 19:44:19 +0000 Subject: drivers/net/tg3.c: Use (pr|netdev)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Remove periods from most formats Coalesce long formats Use printk_once Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/tg3.c | 270 ++++++++++++++++++++++-------------------------------- 1 file changed, 109 insertions(+), 161 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ddf66155f5e2..f204f73c4f99 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,7 +67,6 @@ #include "tg3.h" #define DRV_MODULE_NAME "tg3" -#define PFX DRV_MODULE_NAME ": " #define DRV_MODULE_VERSION "3.108" #define DRV_MODULE_RELDATE "February 17, 2010" @@ -158,7 +157,7 @@ #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" static char version[] __devinitdata = - DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")"; MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)"); MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); @@ -1099,8 +1098,7 @@ static int tg3_mdio_init(struct tg3 *tp) i = mdiobus_register(tp->mdio_bus); if (i) { - printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n", - tp->dev->name, i); + netdev_warn(tp->dev, "mdiobus_reg failed (0x%x)\n", i); mdiobus_free(tp->mdio_bus); return i; } @@ -1108,7 +1106,7 @@ static int tg3_mdio_init(struct tg3 *tp) phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; if (!phydev || !phydev->drv) { - printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name); + netdev_warn(tp->dev, "No PHY devices\n"); mdiobus_unregister(tp->mdio_bus); mdiobus_free(tp->mdio_bus); return -ENODEV; @@ -1252,27 +1250,22 @@ static void tg3_ump_link_report(struct tg3 *tp) static void tg3_link_report(struct tg3 *tp) { if (!netif_carrier_ok(tp->dev)) { - if (netif_msg_link(tp)) - printk(KERN_INFO PFX "%s: Link is down.\n", - tp->dev->name); + netif_info(tp, link, tp->dev, "Link is down\n"); tg3_ump_link_report(tp); } else if (netif_msg_link(tp)) { - printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", - tp->dev->name, - (tp->link_config.active_speed == SPEED_1000 ? - 1000 : - (tp->link_config.active_speed == SPEED_100 ? - 100 : 10)), - (tp->link_config.active_duplex == DUPLEX_FULL ? - "full" : "half")); - - printk(KERN_INFO PFX - "%s: Flow control is %s for TX and %s for RX.\n", - tp->dev->name, - (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ? - "on" : "off", - (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ? - "on" : "off"); + netdev_info(tp->dev, "Link is up at %d Mbps, %s duplex\n", + (tp->link_config.active_speed == SPEED_1000 ? + 1000 : + (tp->link_config.active_speed == SPEED_100 ? + 100 : 10)), + (tp->link_config.active_duplex == DUPLEX_FULL ? + "full" : "half")); + + netdev_info(tp->dev, "Flow control is %s for TX and %s for RX\n", + (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ? + "on" : "off", + (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ? + "on" : "off"); tg3_ump_link_report(tp); } } @@ -1471,7 +1464,7 @@ static int tg3_phy_init(struct tg3 *tp) phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link, phydev->dev_flags, phydev->interface); if (IS_ERR(phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name); + netdev_err(tp->dev, "Could not attach to PHY\n"); return PTR_ERR(phydev); } @@ -2500,8 +2493,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) break; default: - printk(KERN_ERR PFX "%s: Invalid power state (D%d) requested\n", - tp->dev->name, state); + netdev_err(tp->dev, "Invalid power state (D%d) requested\n", + state); return -EINVAL; } @@ -4342,10 +4335,8 @@ static void tg3_tx_recover(struct tg3 *tp) BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || tp->write32_tx_mbox == tg3_write_indirect_mbox); - printk(KERN_WARNING PFX "%s: The system may be re-ordering memory-" - "mapped I/O cycles to the network device, attempting to " - "recover. Please report the problem to the driver maintainer " - "and include system chipset information.\n", tp->dev->name); + netdev_warn(tp->dev, "The system may be re-ordering memory-mapped I/O cycles to the network device, attempting to recover\n" + "Please report the problem to the driver maintainer and include system chipset information.\n"); spin_lock(&tp->lock); tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING; @@ -5269,8 +5260,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy) err = tg3_init_hw(tp, reset_phy); if (err) { - printk(KERN_ERR PFX "%s: Failed to re-initialize device, " - "aborting.\n", tp->dev->name); + netdev_err(tp->dev, "Failed to re-initialize device, aborting\n"); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); tg3_full_unlock(tp); del_timer_sync(&tp->timer); @@ -5343,10 +5333,10 @@ out: static void tg3_dump_short_state(struct tg3 *tp) { - printk(KERN_ERR PFX "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n", - tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS)); - printk(KERN_ERR PFX "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n", - tr32(RDMAC_STATUS), tr32(WDMAC_STATUS)); + netdev_err(tp->dev, "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n", + tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS)); + netdev_err(tp->dev, "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n", + tr32(RDMAC_STATUS), tr32(WDMAC_STATUS)); } static void tg3_tx_timeout(struct net_device *dev) @@ -5354,8 +5344,7 @@ static void tg3_tx_timeout(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); if (netif_msg_tx_err(tp)) { - printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", - dev->name); + netdev_err(dev, "transmit timed out, resetting\n"); tg3_dump_short_state(tp); } @@ -5519,8 +5508,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, netif_tx_stop_queue(txq); /* This is a hard error, log it. */ - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " - "queue awake!\n", dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); } return NETDEV_TX_BUSY; } @@ -5723,8 +5711,7 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, netif_tx_stop_queue(txq); /* This is a hard error, log it. */ - printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " - "queue awake!\n", dev->name); + netdev_err(dev, "BUG! Tx Ring full when queue awake!\n"); } return NETDEV_TX_BUSY; } @@ -6071,11 +6058,8 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, /* Now allocate fresh SKBs for each rx ring. */ for (i = 0; i < tp->rx_pending; i++) { if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_STD, i) < 0) { - printk(KERN_WARNING PFX - "%s: Using a smaller RX standard ring, " - "only %d out of %d buffers were allocated " - "successfully.\n", - tp->dev->name, i, tp->rx_pending); + netdev_warn(tp->dev, "Using a smaller RX standard ring, only %d out of %d buffers were allocated successfully\n", + i, tp->rx_pending); if (i == 0) goto initfail; tp->rx_pending = i; @@ -6104,11 +6088,8 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp, for (i = 0; i < tp->rx_jumbo_pending; i++) { if (tg3_alloc_rx_skb(tp, tpr, RXD_OPAQUE_RING_JUMBO, i) < 0) { - printk(KERN_WARNING PFX - "%s: Using a smaller RX jumbo ring, " - "only %d out of %d buffers were " - "allocated successfully.\n", - tp->dev->name, i, tp->rx_jumbo_pending); + netdev_warn(tp->dev, "Using a smaller RX jumbo ring, only %d out of %d buffers were allocated successfully\n", + i, tp->rx_jumbo_pending); if (i == 0) goto initfail; tp->rx_jumbo_pending = i; @@ -6452,8 +6433,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int } if (i == MAX_WAIT_CNT && !silent) { - printk(KERN_ERR PFX "tg3_stop_block timed out, " - "ofs=%lx enable_bit=%x\n", + pr_err("tg3_stop_block timed out, ofs=%lx enable_bit=%x\n", ofs, enable_bit); return -ENODEV; } @@ -6500,9 +6480,8 @@ static int tg3_abort_hw(struct tg3 *tp, int silent) break; } if (i >= MAX_WAIT_CNT) { - printk(KERN_ERR PFX "tg3_abort_hw timed out for %s, " - "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n", - tp->dev->name, tr32(MAC_TX_MODE)); + netdev_err(tp->dev, "%s timed out, TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n", + __func__, tr32(MAC_TX_MODE)); err |= -ENODEV; } @@ -6723,8 +6702,7 @@ static int tg3_poll_fw(struct tg3 *tp) !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; - printk(KERN_INFO PFX "%s: No firmware running.\n", - tp->dev->name); + netdev_info(tp->dev, "No firmware running\n"); } if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { @@ -7152,10 +7130,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) } if (i >= 10000) { - printk(KERN_ERR PFX "tg3_reset_cpu timed out for %s, " - "and %s CPU\n", - tp->dev->name, - (offset == RX_CPU_BASE ? "RX" : "TX")); + netdev_err(tp->dev, "%s timed out, %s CPU\n", + __func__, offset == RX_CPU_BASE ? "RX" : "TX"); return -ENODEV; } @@ -7180,9 +7156,8 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b if (cpu_base == TX_CPU_BASE && (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { - printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load " - "TX cpu firmware on %s which is 5705.\n", - tp->dev->name); + netdev_err(tp->dev, "%s: Trying to load TX cpu firmware which is 5705\n", + __func__); return -EINVAL; } @@ -7261,10 +7236,8 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) udelay(1000); } if (i >= 5) { - printk(KERN_ERR PFX "tg3_load_firmware fails for %s " - "to set RX CPU PC, is %08x should be %08x\n", - tp->dev->name, tr32(RX_CPU_BASE + CPU_PC), - info.fw_base); + netdev_err(tp->dev, "tg3_load_firmware fails to set RX CPU PC, is %08x should be %08x\n", + tr32(RX_CPU_BASE + CPU_PC), info.fw_base); return -ENODEV; } tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); @@ -7327,10 +7300,8 @@ static int tg3_load_tso_firmware(struct tg3 *tp) udelay(1000); } if (i >= 5) { - printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s " - "to set CPU PC, is %08x should be %08x\n", - tp->dev->name, tr32(cpu_base + CPU_PC), - info.fw_base); + netdev_err(tp->dev, "%s fails to set CPU PC, is %08x should be %08x\n", + __func__, tr32(cpu_base + CPU_PC), info.fw_base); return -ENODEV; } tw32(cpu_base + CPU_STATE, 0xffffffff); @@ -7791,8 +7762,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); } if (i >= 2000) { - printk(KERN_ERR PFX "tg3_reset_hw cannot enable BUFMGR for %s.\n", - tp->dev->name); + netdev_err(tp->dev, "%s cannot enable BUFMGR\n", __func__); return -ENODEV; } @@ -8655,10 +8625,8 @@ static int tg3_test_msi(struct tg3 *tp) return err; /* MSI test failed, go back to INTx mode */ - printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " - "switching to INTx mode. Please report this failure to " - "the PCI maintainer and include system chipset information.\n", - tp->dev->name); + netdev_warn(tp->dev, "No interrupt was generated using MSI, switching to INTx mode\n" + "Please report this failure to the PCI maintainer and include system chipset information\n"); free_irq(tp->napi[0].irq_vec, &tp->napi[0]); @@ -8691,8 +8659,8 @@ static int tg3_request_firmware(struct tg3 *tp) const __be32 *fw_data; if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { - printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", - tp->dev->name, tp->fw_needed); + netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", + tp->fw_needed); return -ENOENT; } @@ -8705,8 +8673,8 @@ static int tg3_request_firmware(struct tg3 *tp) tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ if (tp->fw_len < (tp->fw->size - 12)) { - printk(KERN_ERR "%s: bogus length %d in \"%s\"\n", - tp->dev->name, tp->fw_len, tp->fw_needed); + netdev_err(tp->dev, "bogus length %d in \"%s\"\n", + tp->fw_len, tp->fw_needed); release_firmware(tp->fw); tp->fw = NULL; return -EINVAL; @@ -8744,9 +8712,8 @@ static bool tg3_enable_msix(struct tg3 *tp) return false; if (pci_enable_msix(tp->pdev, msix_ent, rc)) return false; - printk(KERN_NOTICE - "%s: Requested %d MSI-X vectors, received %d\n", - tp->dev->name, tp->irq_cnt, rc); + netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n", + tp->irq_cnt, rc); tp->irq_cnt = rc; } @@ -8771,8 +8738,7 @@ static void tg3_ints_init(struct tg3 *tp) /* All MSI supporting chips should support tagged * status. Assert that this is the case. */ - printk(KERN_WARNING PFX "%s: MSI without TAGGED? " - "Not using MSI.\n", tp->dev->name); + netdev_warn(tp->dev, "MSI without TAGGED? Not using MSI\n"); goto defcfg; } @@ -8817,12 +8783,10 @@ static int tg3_open(struct net_device *dev) if (err) return err; } else if (err) { - printk(KERN_WARNING "%s: TSO capability disabled.\n", - tp->dev->name); + netdev_warn(tp->dev, "TSO capability disabled\n"); tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { - printk(KERN_NOTICE "%s: TSO capability restored.\n", - tp->dev->name); + netdev_notice(tp->dev, "TSO capability restored\n"); tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; } } @@ -10687,8 +10651,7 @@ static int tg3_test_registers(struct tg3 *tp) out: if (netif_msg_hw(tp)) - printk(KERN_ERR PFX "Register test failed at offset %x\n", - offset); + pr_err("Register test failed at offset %x\n", offset); tw32(offset, save_val); return -EIO; } @@ -11815,8 +11778,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_NVRAM; if (tg3_nvram_lock(tp)) { - printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, " - "tg3_nvram_init failed.\n", tp->dev->name); + netdev_warn(tp->dev, "Cannot get nvram lock, %s failed\n", + __func__); return; } tg3_enable_nvram_access(tp); @@ -13280,8 +13243,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) { tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX); if (!tp->pcix_cap) { - printk(KERN_ERR PFX "Cannot find PCI-X " - "capability, aborting.\n"); + pr_err("Cannot find PCI-X capability, aborting\n"); return -EIO; } @@ -13478,8 +13440,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { - printk(KERN_ERR PFX "(%s) transition to D0 failed\n", - pci_name(tp->pdev)); + pr_err("(%s) transition to D0 failed\n", pci_name(tp->pdev)); return err; } @@ -13653,7 +13614,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) err = tg3_phy_probe(tp); if (err) { - printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n", + pr_err("(%s) phy probe failed, err %d\n", pci_name(tp->pdev), err); /* ... but do not return immediately ... */ tg3_mdio_fini(tp); @@ -14163,7 +14124,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) /* Send the buffer to the chip. */ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 1); if (ret) { - printk(KERN_ERR "tg3_test_dma() Write the buffer failed %d\n", ret); + pr_err("tg3_test_dma() Write the buffer failed %d\n", + ret); break; } @@ -14173,7 +14135,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) u32 val; tg3_read_mem(tp, 0x2100 + (i*4), &val); if (le32_to_cpu(val) != p[i]) { - printk(KERN_ERR " tg3_test_dma() Card buffer corrupted on write! (%d != %d)\n", val, i); + pr_err(" tg3_test_dma() Card buffer corrupted on write! (%d != %d)\n", + val, i); /* ret = -ENODEV here? */ } p[i] = 0; @@ -14182,7 +14145,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) /* Now read it back. */ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0); if (ret) { - printk(KERN_ERR "tg3_test_dma() Read the buffer failed %d\n", ret); + pr_err("tg3_test_dma() Read the buffer failed %d\n", + ret); break; } @@ -14199,7 +14163,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); break; } else { - printk(KERN_ERR "tg3_test_dma() buffer corrupted on read back! (%d != %d)\n", p[i], i); + pr_err("tg3_test_dma() buffer corrupted on read back! (%d != %d)\n", + p[i], i); ret = -ENODEV; goto out; } @@ -14480,7 +14445,6 @@ static const struct net_device_ops tg3_netdev_ops_dma_bug = { static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int tg3_version_printed = 0; struct net_device *dev; struct tg3 *tp; int i, err, pm_cap; @@ -14488,20 +14452,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, char str[40]; u64 dma_mask, persist_dma_mask; - if (tg3_version_printed++ == 0) - printk(KERN_INFO "%s", version); + printk_once(KERN_INFO "%s\n", version); err = pci_enable_device(pdev); if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device, " - "aborting.\n"); + pr_err("Cannot enable PCI device, aborting\n"); return err; } err = pci_request_regions(pdev, DRV_MODULE_NAME); if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources, " - "aborting.\n"); + pr_err("Cannot obtain PCI resources, aborting\n"); goto err_out_disable_pdev; } @@ -14510,15 +14471,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, /* Find power-management capability. */ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm_cap == 0) { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, " - "aborting.\n"); + pr_err("Cannot find PowerManagement capability, aborting\n"); err = -EIO; goto err_out_free_res; } dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS); if (!dev) { - printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); + pr_err("Etherdev alloc failed, aborting\n"); err = -ENOMEM; goto err_out_free_res; } @@ -14568,8 +14528,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->regs = pci_ioremap_bar(pdev, BAR_0); if (!tp->regs) { - printk(KERN_ERR PFX "Cannot map device registers, " - "aborting.\n"); + netdev_err(dev, "Cannot map device registers, aborting\n"); err = -ENOMEM; goto err_out_free_dev; } @@ -14585,8 +14544,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_get_invariants(tp); if (err) { - printk(KERN_ERR PFX "Problem fetching invariants of chip, " - "aborting.\n"); + netdev_err(dev, "Problem fetching invariants of chip, aborting\n"); goto err_out_iounmap; } @@ -14621,8 +14579,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = pci_set_consistent_dma_mask(pdev, persist_dma_mask); if (err < 0) { - printk(KERN_ERR PFX "Unable to obtain 64 bit " - "DMA for consistent allocations\n"); + netdev_err(dev, "Unable to obtain 64 bit DMA for consistent allocations\n"); goto err_out_iounmap; } } @@ -14630,8 +14587,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, if (err || dma_mask == DMA_BIT_MASK(32)) { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { - printk(KERN_ERR PFX "No usable DMA configuration, " - "aborting.\n"); + netdev_err(dev, "No usable DMA configuration, aborting\n"); goto err_out_iounmap; } } @@ -14680,16 +14636,14 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_get_device_address(tp); if (err) { - printk(KERN_ERR PFX "Could not obtain valid ethernet address, " - "aborting.\n"); + netdev_err(dev, "Could not obtain valid ethernet address, aborting\n"); goto err_out_iounmap; } if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { tp->aperegs = pci_ioremap_bar(pdev, BAR_2); if (!tp->aperegs) { - printk(KERN_ERR PFX "Cannot map APE registers, " - "aborting.\n"); + netdev_err(dev, "Cannot map APE registers, aborting\n"); err = -ENOMEM; goto err_out_iounmap; } @@ -14713,7 +14667,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = tg3_test_dma(tp); if (err) { - printk(KERN_ERR PFX "DMA engine test failed, aborting.\n"); + netdev_err(dev, "DMA engine test failed, aborting\n"); goto err_out_apeunmap; } @@ -14774,45 +14728,39 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, err = register_netdev(dev); if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); + netdev_err(dev, "Cannot register net device, aborting\n"); goto err_out_apeunmap; } - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n", - dev->name, - tp->board_part_number, - tp->pci_chip_rev_id, - tg3_bus_string(tp, str), - dev->dev_addr); + netdev_info(dev, "Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n", + tp->board_part_number, + tp->pci_chip_rev_id, + tg3_bus_string(tp, str), + dev->dev_addr); if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) { struct phy_device *phydev; phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]; - printk(KERN_INFO - "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", - tp->dev->name, phydev->drv->name, - dev_name(&phydev->dev)); + netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", + phydev->drv->name, dev_name(&phydev->dev)); } else - printk(KERN_INFO - "%s: attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n", - tp->dev->name, tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : - ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : - "10/100/1000Base-T")), - (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0); - - printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", - dev->name, - (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, - (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, - (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, - (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, - (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); - printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n", - dev->name, tp->dma_rwctrl, - (pdev->dma_mask == DMA_BIT_MASK(32)) ? 32 : - (((u64) pdev->dma_mask == DMA_BIT_MASK(40)) ? 40 : 64)); + netdev_info(dev, "attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n", + tg3_phy_string(tp), + ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : + ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : + "10/100/1000Base-T")), + (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0); + + netdev_info(dev, "RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n", + (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, + (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, + (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, + (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, + (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); + netdev_info(dev, "dma_rwctrl[%08x] dma_mask[%d-bit]\n", + tp->dma_rwctrl, + pdev->dma_mask == DMA_BIT_MASK(32) ? 32 : + ((u64)pdev->dma_mask) == DMA_BIT_MASK(40) ? 40 : 64); return 0; -- cgit v1.2.3 From ad06ab2a1c74a9e0f1136f8260e411bf01c4502f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 17 Feb 2010 20:00:17 +0000 Subject: drivers/net/sis190.c: Use (pr|netdev|netif)_ macro helpers Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Use pr_ Use netdev_ Use netif_ and netif_msg_ Remove local #define net_ macros Remove periods from formats Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/sis190.c | 152 +++++++++++++++++++++++++-------------------------- 1 file changed, 75 insertions(+), 77 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index ead1d31308f8..4487b065ef72 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -17,7 +17,9 @@ See the file COPYING in this distribution for more information. - */ +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -32,17 +34,6 @@ #include #include -#define net_drv(p, arg...) if (netif_msg_drv(p)) \ - printk(arg) -#define net_probe(p, arg...) if (netif_msg_probe(p)) \ - printk(arg) -#define net_link(p, arg...) if (netif_msg_link(p)) \ - printk(arg) -#define net_intr(p, arg...) if (netif_msg_intr(p)) \ - printk(arg) -#define net_tx_err(p, arg...) if (netif_msg_tx_err(p)) \ - printk(arg) - #define PHY_MAX_ADDR 32 #define PHY_ID_ANY 0x1f #define MII_REG_ANY 0x1f @@ -50,7 +41,6 @@ #define DRV_VERSION "1.4" #define DRV_NAME "sis190" #define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION -#define PFX DRV_NAME ": " #define sis190_rx_skb netif_rx #define sis190_rx_quota(count, quota) count @@ -382,7 +372,7 @@ static void __mdio_cmd(void __iomem *ioaddr, u32 ctl) } if (i > 99) - printk(KERN_ERR PFX "PHY command failed !\n"); + pr_err("PHY command failed !\n"); } static void mdio_write(void __iomem *ioaddr, int phy_id, int reg, int val) @@ -590,8 +580,7 @@ static int sis190_rx_interrupt(struct net_device *dev, status = le32_to_cpu(desc->PSize); - // net_intr(tp, KERN_INFO "%s: Rx PSize = %08x.\n", dev->name, - // status); + //netif_info(tp, intr, dev, "Rx PSize = %08x\n", status); if (sis190_rx_pkt_err(status, stats) < 0) sis190_give_to_asic(desc, tp->rx_buf_sz); @@ -602,9 +591,8 @@ static int sis190_rx_interrupt(struct net_device *dev, struct pci_dev *pdev = tp->pci_dev; if (unlikely(pkt_size > tp->rx_buf_sz)) { - net_intr(tp, KERN_INFO - "%s: (frag) status = %08x.\n", - dev->name, status); + netif_info(tp, intr, dev, + "(frag) status = %08x\n", status); stats->rx_dropped++; stats->rx_length_errors++; sis190_give_to_asic(desc, tp->rx_buf_sz); @@ -638,12 +626,12 @@ static int sis190_rx_interrupt(struct net_device *dev, tp->cur_rx = cur_rx; delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated.\n", dev->name); + if (!delta && count) + netif_info(tp, intr, dev, "no Rx buffer allocated\n"); tp->dirty_rx += delta; - if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted.\n", dev->name); + if ((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx) + netif_emerg(tp, intr, dev, "Rx buffers exhausted\n"); return count; } @@ -752,10 +740,10 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev) SIS_W32(IntrStatus, status); - // net_intr(tp, KERN_INFO "%s: status = %08x.\n", dev->name, status); +// netif_info(tp, intr, dev, "status = %08x\n", status); if (status & LinkChange) { - net_intr(tp, KERN_INFO "%s: link change.\n", dev->name); + netif_info(tp, intr, dev, "link change\n"); schedule_work(&tp->phy_task); } @@ -931,8 +919,7 @@ static void sis190_phy_task(struct work_struct *work) } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) & BMSR_ANEGCOMPLETE)) { netif_carrier_off(dev); - net_link(tp, KERN_WARNING "%s: auto-negotiating...\n", - dev->name); + netif_warn(tp, link, dev, "auto-negotiating...\n"); mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); } else { /* Rejoice ! */ @@ -958,13 +945,13 @@ static void sis190_phy_task(struct work_struct *work) u16 adv, autoexp, gigadv, gigrec; val = mdio_read(ioaddr, phy_id, 0x1f); - net_link(tp, KERN_INFO "%s: mii ext = %04x.\n", dev->name, val); + netif_info(tp, link, dev, "mii ext = %04x\n", val); val = mdio_read(ioaddr, phy_id, MII_LPA); adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE); autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION); - net_link(tp, KERN_INFO "%s: mii lpa=%04x adv=%04x exp=%04x.\n", - dev->name, val, adv, autoexp); + netif_info(tp, link, dev, "mii lpa=%04x adv=%04x exp=%04x\n", + val, adv, autoexp); if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) { /* check for gigabit speed */ @@ -1005,8 +992,7 @@ static void sis190_phy_task(struct work_struct *work) tp->negotiated_lpa = p->val; - net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, - p->msg); + netif_info(tp, link, dev, "link on %s mode\n", p->msg); netif_carrier_on(dev); } @@ -1192,9 +1178,8 @@ static netdev_tx_t sis190_start_xmit(struct sk_buff *skb, if (unlikely(le32_to_cpu(desc->status) & OWNbit)) { netif_stop_queue(dev); - net_tx_err(tp, KERN_ERR PFX - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); + netif_err(tp, tx_err, dev, + "BUG! Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -1294,9 +1279,9 @@ static u16 sis190_default_phy(struct net_device *dev) if (mii_if->phy_id != phy_default->phy_id) { mii_if->phy_id = phy_default->phy_id; - net_probe(tp, KERN_INFO - "%s: Using transceiver at address %d as default.\n", - pci_name(tp->pci_dev), mii_if->phy_id); + if (netif_msg_probe(tp)) + pr_info("%s: Using transceiver at address %d as default\n", + pci_name(tp->pci_dev), mii_if->phy_id); } status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR); @@ -1334,14 +1319,15 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ? LAN : HOME) : p->type; tp->features |= p->feature; - net_probe(tp, KERN_INFO "%s: %s transceiver at address %d.\n", - pci_name(tp->pci_dev), p->name, phy_id); + if (netif_msg_probe(tp)) + pr_info("%s: %s transceiver at address %d\n", + pci_name(tp->pci_dev), p->name, phy_id); } else { phy->type = UNKNOWN; - net_probe(tp, KERN_INFO - "%s: unknown PHY 0x%x:0x%x transceiver at address %d\n", - pci_name(tp->pci_dev), - phy->id[0], (phy->id[1] & 0xfff0), phy_id); + if (netif_msg_probe(tp)) + pr_info("%s: unknown PHY 0x%x:0x%x transceiver at address %d\n", + pci_name(tp->pci_dev), + phy->id[0], (phy->id[1] & 0xfff0), phy_id); } } @@ -1405,8 +1391,9 @@ static int __devinit sis190_mii_probe(struct net_device *dev) } if (list_empty(&tp->first_phy)) { - net_probe(tp, KERN_INFO "%s: No MII transceivers found!\n", - pci_name(tp->pci_dev)); + if (netif_msg_probe(tp)) + pr_info("%s: No MII transceivers found!\n", + pci_name(tp->pci_dev)); rc = -EIO; goto out; } @@ -1452,7 +1439,8 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) dev = alloc_etherdev(sizeof(*tp)); if (!dev) { - net_drv(&debug, KERN_ERR PFX "unable to alloc new ethernet\n"); + if (netif_msg_drv(&debug)) + pr_err("unable to alloc new ethernet\n"); rc = -ENOMEM; goto err_out_0; } @@ -1465,34 +1453,39 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) rc = pci_enable_device(pdev); if (rc < 0) { - net_probe(tp, KERN_ERR "%s: enable failure\n", pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: enable failure\n", pci_name(pdev)); goto err_free_dev_1; } rc = -ENODEV; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - net_probe(tp, KERN_ERR "%s: region #0 is no MMIO resource.\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: region #0 is no MMIO resource\n", + pci_name(pdev)); goto err_pci_disable_2; } if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) { - net_probe(tp, KERN_ERR "%s: invalid PCI region size(s).\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: invalid PCI region size(s)\n", + pci_name(pdev)); goto err_pci_disable_2; } rc = pci_request_regions(pdev, DRV_NAME); if (rc < 0) { - net_probe(tp, KERN_ERR PFX "%s: could not request regions.\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: could not request regions\n", + pci_name(pdev)); goto err_pci_disable_2; } rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (rc < 0) { - net_probe(tp, KERN_ERR "%s: DMA configuration failed.\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: DMA configuration failed\n", + pci_name(pdev)); goto err_free_res_3; } @@ -1500,8 +1493,9 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE); if (!ioaddr) { - net_probe(tp, KERN_ERR "%s: cannot remap MMIO, aborting\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_err("%s: cannot remap MMIO, aborting\n", + pci_name(pdev)); rc = -EIO; goto err_free_res_3; } @@ -1537,9 +1531,8 @@ static void sis190_tx_timeout(struct net_device *dev) if (tmp8 & CmdTxEnb) SIS_W8(TxControl, tmp8 & ~CmdTxEnb); - - net_tx_err(tp, KERN_INFO "%s: Transmit timeout, status %08x %08x.\n", - dev->name, SIS_R32(TxControl), SIS_R32(TxSts)); + netif_info(tp, tx_err, dev, "Transmit timeout, status %08x %08x\n", + SIS_R32(TxControl), SIS_R32(TxSts)); /* Disable interrupts by clearing the interrupt mask. */ SIS_W32(IntrMask, 0x0000); @@ -1568,15 +1561,16 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, u16 sig; int i; - net_probe(tp, KERN_INFO "%s: Read MAC address from EEPROM\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_info("%s: Read MAC address from EEPROM\n", pci_name(pdev)); /* Check to see if there is a sane EEPROM */ sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature); if ((sig == 0xffff) || (sig == 0x0000)) { - net_probe(tp, KERN_INFO "%s: Error EEPROM read %x.\n", - pci_name(pdev), sig); + if (netif_msg_probe(tp)) + pr_info("%s: Error EEPROM read %x\n", + pci_name(pdev), sig); return -EIO; } @@ -1610,8 +1604,8 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, u8 reg, tmp8; unsigned int i; - net_probe(tp, KERN_INFO "%s: Read MAC address from APC.\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_info("%s: Read MAC address from APC\n", pci_name(pdev)); for (i = 0; i < ARRAY_SIZE(ids); i++) { isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, ids[i], NULL); @@ -1620,8 +1614,9 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, } if (!isa_bridge) { - net_probe(tp, KERN_INFO "%s: Can not find ISA bridge.\n", - pci_name(pdev)); + if (netif_msg_probe(tp)) + pr_info("%s: Can not find ISA bridge\n", + pci_name(pdev)); return -EIO; } @@ -1702,7 +1697,7 @@ static void sis190_set_speed_auto(struct net_device *dev) int phy_id = tp->mii_if.phy_id; int val; - net_link(tp, KERN_INFO "%s: Enabling Auto-negotiation.\n", dev->name); + netif_info(tp, link, dev, "Enabling Auto-negotiation\n"); val = mdio_read(ioaddr, phy_id, MII_ADVERTISE); @@ -1829,7 +1824,8 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, int rc; if (!printed_version) { - net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n"); + if (netif_msg_drv(&debug)) + pr_info(SIS190_DRIVER_NAME " loaded\n"); printed_version = 1; } @@ -1869,12 +1865,14 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, if (rc < 0) goto err_remove_mii; - net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), %pM\n", - pci_name(pdev), sis_chip_info[ent->driver_data].name, - ioaddr, dev->irq, dev->dev_addr); - - net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name, - (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII"); + if (netif_msg_probe(tp)) { + netdev_info(dev, "%s: %s at %p (IRQ: %d), %pM\n", + pci_name(pdev), + sis_chip_info[ent->driver_data].name, + ioaddr, dev->irq, dev->dev_addr); + netdev_info(dev, "%s mode.\n", + (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII"); + } netif_carrier_off(dev); -- cgit v1.2.3 From 4bac6b180771f7ef5275b1a6d88e630ca3a3d6f0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 19 Feb 2010 08:03:28 +0100 Subject: netfilter: restore POST_ROUTING hook in NF_HOOK_COND Commit 2249065 ("netfilter: get rid of the grossness in netfilter.h") inverted the logic for conditional hook invocation, breaking the POST_ROUTING hook invoked by ip_output(). Correct the logic and remove an unnecessary initialization. Reported-by: Stephen Hemminger Signed-off-by: Patrick McHardy --- include/linux/netfilter.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 70079454ffd0..89341c32631a 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -212,8 +212,9 @@ NF_HOOK_COND(uint8_t pf, unsigned int hook, struct sk_buff *skb, struct net_device *in, struct net_device *out, int (*okfn)(struct sk_buff *), bool cond) { - int ret = 1; - if (cond || + int ret; + + if (!cond || (ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, INT_MIN) == 1)) ret = okfn(skb); return ret; -- cgit v1.2.3 From cf261b2392daa7b1a18b91707485e3648dda34d3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 18 Feb 2010 23:32:26 -0800 Subject: net: Make GRETH driver depend on SPARC. Reported by Stephen Rothwell. Signed-off-by: David S. Miller --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 17ff15f6099a..46af867af85f 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -997,7 +997,7 @@ config ETHOC config GRETH tristate "Aeroflex Gaisler GRETH Ethernet MAC support" - depends on OF + depends on SPARC select PHYLIB select CRC32 help -- cgit v1.2.3 From a88e22adf5aad79b6e2ddd1bf0109c2ba8b46b0e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 19 Feb 2010 14:24:39 +0100 Subject: netfilter: ctnetlink: fix creation of conntrack with helpers This patch fixes a bug that triggers an assertion if you create a conntrack entry with a helper and netfilter debugging is enabled. Basically, we hit the assertion because the confirmation flag is set before the conntrack extensions are added. To fix this, we move the extension addition before the aforementioned flag is set. This patch also removes the possibility of setting a helper for existing conntracks. This operation would also trigger the assertion since we are not allowed to add new extensions for existing conntracks. We know noone that could benefit from this operation sanely. Thanks to Eric Dumazet for initial posting a preliminary patch to address this issue. Reported-by: David Ramblewski Signed-off-by: Pablo Neira Ayuso Signed-off-by: Eric Dumazet Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_netlink.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 8b05f364b2f2..2b2af631d2b8 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1077,9 +1077,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) /* need to zero data of old helper */ memset(&help->help, 0, sizeof(help->help)); } else { - help = nf_ct_helper_ext_add(ct, GFP_ATOMIC); - if (help == NULL) - return -ENOMEM; + /* we cannot set a helper for an existing conntrack */ + return -EOPNOTSUPP; } rcu_assign_pointer(help->helper, helper); @@ -1263,7 +1262,6 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, ct->timeout.expires = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); ct->timeout.expires = jiffies + ct->timeout.expires * HZ; - ct->status |= IPS_CONFIRMED; rcu_read_lock(); if (cda[CTA_HELP]) { @@ -1314,14 +1312,19 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } - if (cda[CTA_STATUS]) { - err = ctnetlink_change_status(ct, cda); + if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { + err = ctnetlink_change_nat(ct, cda); if (err < 0) goto err2; } - if (cda[CTA_NAT_SRC] || cda[CTA_NAT_DST]) { - err = ctnetlink_change_nat(ct, cda); + nf_ct_acct_ext_add(ct, GFP_ATOMIC); + nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); + /* we must add conntrack extensions before confirmation. */ + ct->status |= IPS_CONFIRMED; + + if (cda[CTA_STATUS]) { + err = ctnetlink_change_status(ct, cda); if (err < 0) goto err2; } @@ -1340,9 +1343,6 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, goto err2; } - nf_ct_acct_ext_add(ct, GFP_ATOMIC); - nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); - #if defined(CONFIG_NF_CONNTRACK_MARK) if (cda[CTA_MARK]) ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); -- cgit v1.2.3 From 64507fdbc29c3a622180378210ecea8659b14e40 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 19 Feb 2010 15:28:38 +0100 Subject: netfilter: nf_queue: fix NF_STOLEN skb leak commit 3bc38712e3a6e059 (handle NF_STOP and unknown verdicts in nf_reinject) was a partial fix to packet leaks. If user asks NF_STOLEN status, we must free the skb as well. Reported-by: Afi Gjermund Signed-off-by: Eric DUmazet Signed-off-by: Patrick McHardy --- net/netfilter/nf_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 3a6fd77f7761..ba095fd014e5 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -265,7 +265,6 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) local_bh_disable(); entry->okfn(skb); local_bh_enable(); - case NF_STOLEN: break; case NF_QUEUE: if (!__nf_queue(skb, elem, entry->pf, entry->hook, @@ -273,6 +272,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) verdict >> NF_VERDICT_BITS)) goto next_hook; break; + case NF_STOLEN: default: kfree_skb(skb); } -- cgit v1.2.3 From 9e2dcf72023d1447f09c47d77c99b0c49659e5ce Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 19 Feb 2010 18:18:37 +0100 Subject: netfilter: nf_conntrack_reasm: properly handle packets fragmented into a single fragment When an ICMPV6_PKT_TOOBIG message is received with a MTU below 1280, all further packets include a fragment header. Unlike regular defragmentation, conntrack also needs to "reassemble" those fragments in order to obtain a packet without the fragment header for connection tracking. Currently nf_conntrack_reasm checks whether a fragment has either IP6_MF set or an offset != 0, which makes it ignore those fragments. Remove the invalid check and make reassembly handle fragment queues containing only a single fragment. Reported-and-tested-by: Ulrich Weber Signed-off-by: Patrick McHardy --- net/ipv6/netfilter/nf_conntrack_reasm.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index ad1fcda6898b..f1171b744650 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -469,7 +469,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */ fp = skb_shinfo(head)->frag_list; - if (NFCT_FRAG6_CB(fp)->orig == NULL) + if (fp && NFCT_FRAG6_CB(fp)->orig == NULL) /* at above code, head skb is divided into two skbs. */ fp = fp->next; @@ -595,12 +595,6 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) hdr = ipv6_hdr(clone); fhdr = (struct frag_hdr *)skb_transport_header(clone); - if (!(fhdr->frag_off & htons(0xFFF9))) { - pr_debug("Invalid fragment offset\n"); - /* It is not a fragmented frame */ - goto ret_orig; - } - if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh) nf_ct_frag6_evictor(); -- cgit v1.2.3 From fbc87d67af5ccd733f894273b215564c67e3a749 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Thu, 11 Feb 2010 17:56:06 -0500 Subject: Introduce PCMCIA_DEVICE_PROD_ID3 ...and use it in hostap_cs and orinoco_cs. Another PCMCIA device with Intersil Prism chipset has been reported: Socket 0: product info: "Gigabyte", "GN-WLM01_P25L_ADAPTER", "ISL37300P", "Eval-RevA" manfid: 0x02e0, 0x1011 function: 6 (network) As it's the case with some other Prism based devices, the third ID string contains a design name that should be sufficient to identify the card as having Intersil Prism chipset and thus compatible with both orinoco_cs and hostap_cs. Introduce PCMCIA_DEVICE_PROD_ID3 that matches the third ID string only. Use it in orinoco_cs and hostap_cs to match cards with the third ID string indicating Prism chipset. Remove corresponding entries that use PCMCIA_DEVICE_PROD_ID123. Reported-by: Ozzy Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_cs.c | 17 ++++------------- drivers/net/wireless/orinoco/orinoco_cs.c | 9 ++++----- include/pcmcia/device_id.h | 5 +++++ 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index c9640a3e02c9..d19748d90aaf 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -793,13 +793,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = { 0x4b801a17), PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), - PCMCIA_DEVICE_PROD_ID123( - "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", - 0x4b801a17, 0x6345a0bf, 0xc9049a39), - /* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */ - PCMCIA_DEVICE_PROD_ID123( - "D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", - 0x1a424a1c, 0x6ea57632, 0xdd97a26b), PCMCIA_DEVICE_PROD_ID123( "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x08649af2, 0x4b74baa0), @@ -833,15 +826,13 @@ static struct pcmcia_device_id hostap_cs_ids[] = { "Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", "Ver. 1.00", 0x5cd01705, 0x4271660f, 0x9d08ee12), - PCMCIA_DEVICE_PROD_ID123( - "corega", "WL PCCL-11", "ISL37300P", - 0xa21501a, 0x59868926, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID123( - "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", - 0xa5f472c2, 0x9c05598d, 0xc9049a39), PCMCIA_DEVICE_PROD_ID123( "Wireless LAN" , "11Mbps PC Card", "Version 01.02", 0x4b8870ff, 0x70e946d1, 0x4b74baa0), + PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), + PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), + PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), + PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f27bb8367c98..1d4ada188eda 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -407,7 +407,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), - PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092), PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), @@ -417,7 +416,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), - PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), @@ -432,7 +430,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), - PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), @@ -445,7 +442,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39), PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), @@ -454,8 +450,11 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), - PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), + PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), + PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), + PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), + PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); diff --git a/include/pcmcia/device_id.h b/include/pcmcia/device_id.h index c33ea08352b8..63e5b8f6b7dd 100644 --- a/include/pcmcia/device_id.h +++ b/include/pcmcia/device_id.h @@ -34,6 +34,11 @@ .prod_id = { NULL, (v2), NULL, NULL }, \ .prod_id_hash = { 0, (vh2), 0, 0 }, } +#define PCMCIA_DEVICE_PROD_ID3(v3, vh3) { \ + .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID3, \ + .prod_id = { NULL, NULL, (v3), NULL }, \ + .prod_id_hash = { 0, 0, (vh3), 0 }, } + #define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ PCMCIA_DEV_ID_MATCH_PROD_ID2, \ -- cgit v1.2.3 From 088ea189c4c75cdf211146faa4b341a0f7476be6 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 17 Feb 2010 23:40:15 +1100 Subject: drivers/net/wireless/p54/txrx.c Fix off by one error fix off by one error in the queue size check of p54_tx_qos_accounting_alloc() Coverity CID: 13314 Signed-off-by: Darren Jenkins Signed-off-by: John W. Linville --- drivers/net/wireless/p54/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 0e8f69461ffe..66057999a93c 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -186,7 +186,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, struct p54_tx_queue_stats *queue; unsigned long flags; - if (WARN_ON(p54_queue > P54_QUEUE_NUM)) + if (WARN_ON(p54_queue >= P54_QUEUE_NUM)) return -EINVAL; queue = &priv->tx_stats[p54_queue]; -- cgit v1.2.3 From ffb9eb3d8b450c22bbbc688c6b630141ac476fd9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 17 Feb 2010 17:58:10 +0200 Subject: nl80211: add power save commands The most needed command from nl80211, which Wireless Extensions had, is support for power save mode. Add a simple command to make it possible to enable and disable power save via nl80211. I was also planning about extending the interface, for example adding the timeout value, but after thinking more about this I decided not to do it. Basically there were three reasons: Firstly, the parameters for power save are very much hardware dependent. Trying to find a unified interface which would work with all hardware, and still make sense to users, will be very difficult. Secondly, IEEE 802.11 power save implementation in Linux is still in state of flux. We have a long way to still to go and there is no way to predict what kind of implementation we will have after few years. And because we need to support nl80211 interface a long time, practically forever, adding now parameters to nl80211 might create maintenance problems later on. Third issue are the users. Power save parameters are mostly used for debugging, so debugfs is better, more flexible, interface for this. For example, wpa_supplicant currently doesn't configure anything related to power save mode. It's better to strive that kernel can automatically optimise the power save parameters, like with help of pm qos network and other traffic parameters. Later on, when we have better understanding of power save, we can extend this command with more features, if there's a need for that. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- include/linux/nl80211.h | 10 ++++ include/net/cfg80211.h | 7 +-- net/wireless/core.c | 16 +++--- net/wireless/nl80211.c | 131 +++++++++++++++++++++++++++++++++++++++++++++ net/wireless/wext-compat.c | 10 ++-- 5 files changed, 159 insertions(+), 15 deletions(-) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 8e6384f8fda6..28ba20fda3e2 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -416,6 +416,9 @@ enum nl80211_commands { NL80211_CMD_ACTION, NL80211_CMD_ACTION_TX_STATUS, + NL80211_CMD_SET_POWER_SAVE, + NL80211_CMD_GET_POWER_SAVE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -837,6 +840,8 @@ enum nl80211_attrs { NL80211_ATTR_ACK, + NL80211_ATTR_PS_STATE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1573,4 +1578,9 @@ enum nl80211_band { NL80211_BAND_5GHZ, }; +enum nl80211_ps_state { + NL80211_PS_DISABLED, + NL80211_PS_ENABLED, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7188934b64d3..3d134a1fb96b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1150,7 +1150,6 @@ struct cfg80211_ops { enum nl80211_channel_type channel_type, const u8 *buf, size_t len, u64 *cookie); - /* some temporary stuff to finish wext */ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); }; @@ -1489,6 +1488,9 @@ struct wireless_dev { struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; struct cfg80211_internal_bss *current_bss; /* associated / joined */ + bool ps; + int ps_timeout; + #ifdef CONFIG_CFG80211_WEXT /* wext data */ struct { @@ -1500,8 +1502,7 @@ struct wireless_dev { u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; s8 default_key, default_mgmt_key; - bool ps, prev_bssid_valid; - int ps_timeout; + bool prev_bssid_valid; } wext; #endif }; diff --git a/net/wireless/core.c b/net/wireless/core.c index 51908dc2ea00..7fdb9409ad2a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -698,19 +698,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, wdev->wext.default_key = -1; wdev->wext.default_mgmt_key = -1; wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; +#endif + if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) - wdev->wext.ps = true; + wdev->ps = true; else - wdev->wext.ps = false; - wdev->wext.ps_timeout = 100; + wdev->ps = false; + wdev->ps_timeout = 100; if (rdev->ops->set_power_mgmt) if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, - wdev->wext.ps, - wdev->wext.ps_timeout)) { + wdev->ps, + wdev->ps_timeout)) { /* assume this means it's off */ - wdev->wext.ps = false; + wdev->ps = false; } -#endif + if (!dev->ethtool_ops) dev->ethtool_ops = &cfg80211_ethtool_ops; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 328112081358..b0495a1da22e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -148,6 +148,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_FRAME] = { .type = NLA_BINARY, .len = IEEE80211_MAX_DATA_LEN }, [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, + [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, }; /* policy for the attributes */ @@ -4663,6 +4664,124 @@ unlock_rtnl: return err; } +static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + struct wireless_dev *wdev; + struct net_device *dev; + u8 ps_state; + bool state; + int err; + + if (!info->attrs[NL80211_ATTR_PS_STATE]) { + err = -EINVAL; + goto out; + } + + ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); + + if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) { + err = -EINVAL; + goto out; + } + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rdev; + + wdev = dev->ieee80211_ptr; + + if (!rdev->ops->set_power_mgmt) { + err = -EOPNOTSUPP; + goto unlock_rdev; + } + + state = (ps_state == NL80211_PS_ENABLED) ? true : false; + + if (state == wdev->ps) + goto unlock_rdev; + + wdev->ps = state; + + if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, + wdev->ps_timeout)) + /* assume this means it's off */ + wdev->ps = false; + +unlock_rdev: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + rtnl_unlock(); + +out: + return err; +} + +static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev; + enum nl80211_ps_state ps_state; + struct wireless_dev *wdev; + struct net_device *dev; + struct sk_buff *msg; + void *hdr; + int err; + + rtnl_lock(); + + err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + if (err) + goto unlock_rtnl; + + wdev = dev->ieee80211_ptr; + + if (!rdev->ops->set_power_mgmt) { + err = -EOPNOTSUPP; + goto out; + } + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) { + err = -ENOMEM; + goto out; + } + + hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, + NL80211_CMD_GET_POWER_SAVE); + if (!hdr) { + err = -ENOMEM; + goto free_msg; + } + + if (wdev->ps) + ps_state = NL80211_PS_ENABLED; + else + ps_state = NL80211_PS_DISABLED; + + NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); + + genlmsg_end(msg, hdr); + err = genlmsg_reply(msg, info); + goto out; + +nla_put_failure: + err = -ENOBUFS; + +free_msg: + nlmsg_free(msg); + +out: + cfg80211_unlock_rdev(rdev); + dev_put(dev); + +unlock_rtnl: + rtnl_unlock(); + + return err; +} + static struct genl_ops nl80211_ops[] = { { .cmd = NL80211_CMD_GET_WIPHY, @@ -4955,6 +5074,18 @@ static struct genl_ops nl80211_ops[] = { .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, }, + { + .cmd = NL80211_CMD_SET_POWER_SAVE, + .doit = nl80211_set_power_save, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = NL80211_CMD_GET_POWER_SAVE, + .doit = nl80211_get_power_save, + .policy = nl80211_policy, + /* can be retrieved by unprivileged users */ + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index b17eeae448d5..9ab51838849e 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1099,8 +1099,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - bool ps = wdev->wext.ps; - int timeout = wdev->wext.ps_timeout; + bool ps = wdev->ps; + int timeout = wdev->ps_timeout; int err; if (wdev->iftype != NL80211_IFTYPE_STATION) @@ -1133,8 +1133,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, if (err) return err; - wdev->wext.ps = ps; - wdev->wext.ps_timeout = timeout; + wdev->ps = ps; + wdev->ps_timeout = timeout; return 0; @@ -1147,7 +1147,7 @@ int cfg80211_wext_giwpower(struct net_device *dev, { struct wireless_dev *wdev = dev->ieee80211_ptr; - wrq->disabled = !wdev->wext.ps; + wrq->disabled = !wdev->ps; return 0; } -- cgit v1.2.3 From 5b9a919a97ac8bdda8020c9b366491b5b91b196e Mon Sep 17 00:00:00 2001 From: Jean-François Moine Date: Wed, 17 Feb 2010 10:59:31 -0600 Subject: p54usb: Add the USB ID for Belkin (Accton) FD7050E ver 1010ec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yet another USB ID. Signed-off-by: Jean-François Moine Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index dcb484bd5984..b3c4fbd80d8d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -61,6 +61,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ -- cgit v1.2.3 From e2117cea27c6b27e1a379acac5eb0433eeb7033a Mon Sep 17 00:00:00 2001 From: Frederic Leroy Date: Thu, 18 Feb 2010 00:25:26 +0100 Subject: staging: rtl8192su: fix compile error from wireless-testing commit In wireless-testing, commit 7044cc56 added struct ieee80211_hdr_3addr to include/linux/ieee80211.h. This definition collides with one that is in the rtl8192su driver in staging. The conflict is resolved by changing rtl8192su to use the definition from include/linux/ieee80211.h. Signed-off-by: John W. Linville --- drivers/staging/rtl8192su/ieee80211/ieee80211.h | 12 +------ .../staging/rtl8192su/ieee80211/ieee80211_r8192s.h | 2 +- drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c | 18 +++++----- .../rtl8192su/ieee80211/ieee80211_softmac.c | 38 +++++++++++----------- .../staging/rtl8192su/ieee80211/rtl819x_BAProc.c | 4 +-- drivers/staging/rtl8192su/r8192U_core.c | 4 +-- 6 files changed, 34 insertions(+), 44 deletions(-) diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/drivers/staging/rtl8192su/ieee80211/ieee80211.h index f22d024b1c39..6963e5448f34 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211.h @@ -609,16 +609,6 @@ struct ieee80211_hdr_2addr { u8 payload[0]; } __attribute__ ((packed)); -struct ieee80211_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 payload[0]; -} __attribute__ ((packed)); - struct ieee80211_hdr_4addr { __le16 frame_ctl; __le16 duration_id; @@ -1672,7 +1662,7 @@ static inline u8 *ieee80211_get_payload(struct rtl_ieee80211_hdr *hdr) case IEEE80211_2ADDR_LEN: return ((struct ieee80211_hdr_2addr *)hdr)->payload; case IEEE80211_3ADDR_LEN: - return ((struct ieee80211_hdr_3addr *)hdr)->payload; + return (void *)hdr+sizeof(struct ieee80211_hdr_3addr); case IEEE80211_4ADDR_LEN: return ((struct ieee80211_hdr_4addr *)hdr)->payload; } diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h b/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h index 123abcf0f497..7d6c3bc143ae 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h @@ -201,7 +201,7 @@ typedef union _frameqos { static inline u8 Frame_QoSTID(u8 *buf) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf; - u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 fc = le16_to_cpu(hdr->frame_control); return (u8)((frameqos *)(buf + (((fc & IEEE80211_FCTL_TODS) && diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c index 8e56f97a8f57..72498e8e0ded 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c @@ -745,7 +745,7 @@ u8 parse_subframe(struct sk_buff *skb, struct ieee80211_rxb *rxb,u8* src,u8* dst) { struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data; - u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 fc = le16_to_cpu(hdr->frame_control); u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr); u16 ChkLength; @@ -757,7 +757,7 @@ u8 parse_subframe(struct sk_buff *skb, struct sk_buff *sub_skb; u8 *data_ptr; /* just for debug purpose */ - SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); + SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctrl)); if((IEEE80211_QOS_HAS_SEQ(fc))&&\ (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) { @@ -2371,7 +2371,7 @@ static inline void ieee80211_process_probe_response( escape_essid(info_element->data, info_element->len), MAC_ARG(beacon->header.addr3), - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); return; @@ -2388,7 +2388,7 @@ static inline void ieee80211_process_probe_response( return; if(ieee->bGlobalDomain) { - if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) + if (WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP) { // Case 1: Country code if(IS_COUNTRY_IE_VALID(ieee) ) @@ -2455,7 +2455,7 @@ static inline void ieee80211_process_probe_response( else ieee->current_network.buseprotection = false; } - if(is_beacon(beacon->header.frame_ctl)) + if(is_beacon(beacon->header.frame_control)) { if(ieee->state == IEEE80211_LINKED) ieee->LinkDetectInfo.NumRecvBcnInPeriod++; @@ -2497,7 +2497,7 @@ static inline void ieee80211_process_probe_response( escape_essid(network.ssid, network.ssid_len), MAC_ARG(network.bssid), - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); #endif @@ -2510,7 +2510,7 @@ static inline void ieee80211_process_probe_response( escape_essid(target->ssid, target->ssid_len), MAC_ARG(target->bssid), - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP ? "PROBE RESPONSE" : "BEACON"); @@ -2520,7 +2520,7 @@ static inline void ieee80211_process_probe_response( */ renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); //YJ,add,080819,for hidden ap - if(is_beacon(beacon->header.frame_ctl) == 0) + if(is_beacon(beacon->header.frame_control) == 0) network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); //if(strncmp(network.ssid, "linksys-c",9) == 0) // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); @@ -2536,7 +2536,7 @@ static inline void ieee80211_process_probe_response( } spin_unlock_irqrestore(&ieee->lock, flags); - if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\ + if (is_beacon(beacon->header.frame_control)&&is_same_network(&ieee->current_network, &network, ieee)&&\ (ieee->state == IEEE80211_LINKED)) { if(ieee->handle_beacon != NULL) { ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c index fd8e11252f1b..8da0c4c83673 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c @@ -242,7 +242,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee if(ieee->queue_stop){ enqueue_mgmt(ieee,skb); }else{ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -260,7 +260,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee spin_unlock_irqrestore(&ieee->lock, flags); spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -302,7 +302,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i //printk("=============>%s()\n", __FUNCTION__); if(single){ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -315,7 +315,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i }else{ - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -347,7 +347,7 @@ inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) skb_reserve(skb, ieee->tx_headroom); req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); - req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); + req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); req->header.duration_id = 0; //FIXME: is this OK ? memset(req->header.addr1, 0xff, ETH_ALEN); @@ -662,8 +662,8 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be auth = (struct ieee80211_authentication *) skb_put(skb, sizeof(struct ieee80211_authentication)); - auth->header.frame_ctl = IEEE80211_STYPE_AUTH; - if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP; + auth->header.frame_control = IEEE80211_STYPE_AUTH; + if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP; auth->header.duration_id = 0x013a; //FIXME @@ -801,7 +801,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); + beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); beacon_buf->info_element[0].id = MFIE_TYPE_SSID; beacon_buf->info_element[0].len = ssid_len; @@ -880,7 +880,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) assoc = (struct ieee80211_assoc_response_frame *) skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); - assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); + assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); memcpy(assoc->header.addr1, dest,ETH_ALEN); memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); @@ -935,7 +935,7 @@ struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(auth->header.addr1, dest, ETH_ALEN); - auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); + auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH); return skb; @@ -957,7 +957,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); - hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | (pwr ? IEEE80211_FCTL_PM:0)); @@ -1083,7 +1083,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2); - hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; + hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ; hdr->header.duration_id= 37; //FIXME memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); @@ -1940,13 +1940,13 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, if(!ieee->proto_started) return 0; - switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + switch (WLAN_FC_GET_STYPE(header->frame_control)) { case IEEE80211_STYPE_ASSOC_RESP: case IEEE80211_STYPE_REASSOC_RESP: IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); + WLAN_FC_GET_STYPE(header->frame_control)); if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && ieee->iw_mode == IW_MODE_INFRA){ @@ -2088,7 +2088,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA){ - printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason); + printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason); ieee->state = IEEE80211_ASSOCIATING; ieee->softmac_stats.reassoc++; ieee->is_roaming = true; @@ -2239,7 +2239,7 @@ void ieee80211_wake_queue(struct ieee80211_device *ieee) header = (struct ieee80211_hdr_3addr *) skb->data; - header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -2574,7 +2574,7 @@ struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) return NULL; b = (struct ieee80211_probe_response *) skb->data; - b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); + b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON); return skb; @@ -2590,7 +2590,7 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) return NULL; b = (struct ieee80211_probe_response *) skb->data; - b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); if (ieee->seq_ctrl[0] == 0xFFF) ieee->seq_ctrl[0] = 0; @@ -3139,7 +3139,7 @@ inline struct sk_buff *ieee80211_disassociate_skb( return NULL; disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc)); - disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC); + disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); disass->header.duration_id = 0; memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c index 8d12ffca18fa..c6962450e06f 100644 --- a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c @@ -136,7 +136,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); - BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame + BAReq->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field tag = (u8*)skb_put(skb, 9); @@ -221,7 +221,7 @@ static struct sk_buff* ieee80211_DELBA( memcpy(Delba->addr1, dst, ETH_ALEN); memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); - Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame + Delba->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame tag = (u8*)skb_put(skb, 6); diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 66274d7666ff..2b079fb67d31 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -6166,7 +6166,7 @@ void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee802 u16 sc ; unsigned int frag,seq; hdr = (struct ieee80211_hdr_3addr *)buffer; - sc = le16_to_cpu(hdr->seq_ctl); + sc = le16_to_cpu(hdr->seq_ctrl); frag = WLAN_GET_SEQ_FRAG(sc); seq = WLAN_GET_SEQ_SEQ(sc); //cosa add 04292008 to record the sequence number @@ -6825,7 +6825,7 @@ void rtl8192SU_TranslateRxSignalStuff(struct sk_buff *skb, tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats); hdr = (struct ieee80211_hdr_3addr *)tmp_buf; - fc = le16_to_cpu(hdr->frame_ctl); + fc = le16_to_cpu(hdr->frame_control); type = WLAN_FC_GET_TYPE(fc); praddr = hdr->addr1; -- cgit v1.2.3 From d8c42c0c282a5edd9ea2eef4c929d9cec2798653 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:36 +0200 Subject: wl1271: Fix PSM entry Currently the PSM entry function assumes successful operation, and enables ELP, BET and beacon filtering right away. This is bad, because the PSM entry may fail due to environmental issues, which will cause the ELP, BET and beacon filtering to be illegally enabled (because FW remains in active state.) Fix this by enabling ELP, BET and beacon filtering only after successful entry, and by ensuring the firmware is in active mode after the failure. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 ++-- drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +- drivers/net/wireless/wl12xx/wl1271_event.c | 35 ++++++++++++++++++++++++++++-- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++--- drivers/net/wireless/wl12xx/wl1271_ps.c | 21 ++++-------------- drivers/net/wireless/wl12xx/wl1271_ps.h | 3 ++- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index a74259bb596b..dd2b5f0540a5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -555,7 +555,7 @@ out: return ret; } -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) +int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; @@ -576,7 +576,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) } ps_params->ps_mode = ps_mode; - ps_params->send_null_data = 1; + ps_params->send_null_data = send; ps_params->retries = 5; ps_params->hang_over_period = 128; ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 09fe91297acf..ba433f423c8b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -38,7 +38,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); +int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 0a145afc9905..cecbae2ded35 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -78,24 +78,55 @@ static int wl1271_event_ps_report(struct wl1271 *wl, switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: + wl1271_debug(DEBUG_PSM, "PSM entry failed"); + if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { + /* remain in active mode */ wl->psm_entry_retry = 0; break; } if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { wl->psm_entry_retry++; - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + true); } else { wl1271_error("PSM entry failed, giving up.\n"); + /* make sure the firmware goes into active mode */ + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + false); wl->psm_entry_retry = 0; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: wl->psm_entry_retry = 0; + + /* enable beacon filtering */ + ret = wl1271_acx_beacon_filter_opt(wl, true); + if (ret < 0) + break; + + /* enable beacon early termination */ + ret = wl1271_acx_bet_enable(wl, true); + if (ret < 0) + break; + + /* go to extremely low power mode */ + wl1271_ps_elp_sleep(wl); + if (ret < 0) + break; break; case EVENT_EXIT_POWER_SAVE_FAIL: - wl1271_info("PSM exit failed"); + wl1271_debug(DEBUG_PSM, "PSM exit failed"); + + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { + wl->psm_entry_retry = 0; + break; + } + + /* make sure the firmware goes to active mode */ + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + false); break; case EVENT_EXIT_POWER_SAVE_SUCCESS: default: diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index e4867b895c43..6f026fe63d7f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1248,7 +1248,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) */ if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_info("psm enabled"); - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { @@ -1257,7 +1258,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); if (test_bit(WL1271_FLAG_PSM, &wl->flags)) - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + true); } if (conf->power_level != wl->power_level) { @@ -1637,7 +1639,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && !test_bit(WL1271_FLAG_PSM, &wl->flags)) { mode = STATION_POWER_SAVE_MODE; - ret = wl1271_ps_set_mode(wl, mode); + ret = wl1271_ps_set_mode(wl, mode, true); if (ret < 0) goto out_sleep; } diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index e407790f6771..29f670099d94 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -118,7 +118,8 @@ out: return 0; } -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) +int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, + bool send) { int ret; @@ -126,21 +127,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) case STATION_POWER_SAVE_MODE: wl1271_debug(DEBUG_PSM, "entering psm"); - /* enable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, true); - if (ret < 0) - return ret; - - /* enable beacon early termination */ - ret = wl1271_acx_bet_enable(wl, true); - if (ret < 0) - return ret; - - ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); - if (ret < 0) - return ret; - - wl1271_ps_elp_sleep(wl); + ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send); if (ret < 0) return ret; @@ -163,7 +150,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) if (ret < 0) return ret; - ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); + ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send); if (ret < 0) return ret; diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index 779653d0ae85..940276f517a4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h @@ -27,7 +27,8 @@ #include "wl1271.h" #include "wl1271_acx.h" -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); +int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, + bool send); void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); void wl1271_elp_work(struct work_struct *work); -- cgit v1.2.3 From ddb01a5b368270f3cc86b606ba6f7ee8795a8a99 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:37 +0200 Subject: wl1271: Fix channel changing code The channel changing code would a) change the BSSID to a dummy on upon channel change, breaking connectivity, and b) not update the channel number at all for ad-hoc, breaking adhoc. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 6f026fe63d7f..8b46b7069f1f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1234,8 +1234,16 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } /* if the channel changes while joined, join again */ - if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) - wl1271_join_channel(wl, channel); + if (channel != wl->channel && + test_bit(WL1271_FLAG_JOINED, &wl->flags)) { + wl->channel = channel; + /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ + ret = wl1271_cmd_join(wl); + if (ret < 0) + wl1271_warning("cmd join to update channel failed %d", + ret); + } else + wl->channel = channel; if (conf->flags & IEEE80211_CONF_PS && !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { -- cgit v1.2.3 From 30240fc76a57e37a4bb42976ff7162b5e45e6117 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:38 +0200 Subject: wl1271: Add SSID configuration for JOIN in ad-hoc This patch adds code to extract the SSID from the beacon template used for ad-hoc. The mac80211 currently does not provide the SSID, so this is a workaround for that, for now. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_event.c | 10 ++++- drivers/net/wireless/wl12xx/wl1271_main.c | 69 +++++++++++++++++++----------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index cecbae2ded35..2803e700a75a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -92,7 +92,12 @@ static int wl1271_event_ps_report(struct wl1271 *wl, true); } else { wl1271_error("PSM entry failed, giving up.\n"); - /* make sure the firmware goes into active mode */ + /* FIXME: this may need to be reconsidered. for now it + is not possible to indicate to the mac80211 + afterwards that PSM entry failed. To maximize + functionality (receiving data and remaining + associated) make sure that we are in sync with the + AP in regard of PSM mode. */ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, false); wl->psm_entry_retry = 0; @@ -124,7 +129,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl, break; } - /* make sure the firmware goes to active mode */ + /* make sure the firmware goes to active mode - the frame to + be sent next will indicate to the AP, that we are active. */ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, false); break; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 8b46b7069f1f..a3742c8052d4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1549,6 +1549,23 @@ out: return ret; } +static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) +{ + u8 *ptr = beacon->data + + offsetof(struct ieee80211_mgmt, u.beacon.variable); + + /* find the location of the ssid in the beacon */ + while (ptr < beacon->data + beacon->len) { + if (ptr[0] == WLAN_EID_SSID) { + wl->ssid_len = ptr[1]; + memcpy(wl->ssid, ptr+2, wl->ssid_len); + return; + } + ptr += ptr[1]; + } + wl1271_error("ad-hoc beacon template has no SSID!\n"); +} + static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1566,40 +1583,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; - if ((changed & BSS_CHANGED_BSSID) && - /* - * Now we know the correct bssid, so we send a new join command - * and enable the BSSID filter - */ - memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { - wl->rx_config |= CFG_BSSID_FILTER_EN; - memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) { - wl1271_warning("cmd buld null data failed %d", - ret); - goto out_sleep; - } - ret = wl1271_cmd_join(wl); - if (ret < 0) { - wl1271_warning("cmd join failed %d", ret); - goto out_sleep; - } - set_bit(WL1271_FLAG_JOINED, &wl->flags); - } - if (wl->bss_type == BSS_TYPE_IBSS) { /* FIXME: This implements rudimentary ad-hoc support - proper templates are on the wish list and notification on when they change. This patch will update the templates - on every call to this function. Also, the firmware will not - answer to probe-requests as it does not have the proper - SSID set in the JOIN command. The probe-response template - is set nevertheless, as the FW will ASSERT without it */ + on every call to this function. */ struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); if (beacon) { struct ieee80211_hdr *hdr; + + wl1271_ssid_set(wl, beacon); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, beacon->data, beacon->len); @@ -1624,6 +1618,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } + if ((changed & BSS_CHANGED_BSSID) && + /* + * Now we know the correct bssid, so we send a new join command + * and enable the BSSID filter + */ + memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + ret = wl1271_cmd_build_null_data(wl); + if (ret < 0) { + wl1271_warning("cmd buld null data failed %d", + ret); + goto out_sleep; + } + + ret = wl1271_cmd_join(wl); + if (ret < 0) { + wl1271_warning("cmd join failed %d", ret); + goto out_sleep; + } + set_bit(WL1271_FLAG_JOINED, &wl->flags); + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; -- cgit v1.2.3 From 243eeb51eaa0a33caeff3e2275b2460eea5579ec Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 13:25:39 +0200 Subject: wl1271: modify wl1271_acx_ac_cfg() to use function parameters For WMM we need to configure each queue separately so modify wl1271_acx_ac_cfg() to take the configuration from function parameters instead. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 31 ++++++++++++++----------------- drivers/net/wireless/wl12xx/wl1271_acx.h | 3 ++- drivers/net/wireless/wl12xx/wl1271_init.c | 14 ++++++++++---- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 0b3434843476..4b052eedbd4b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -830,12 +830,14 @@ out: return ret; } -int wl1271_acx_ac_cfg(struct wl1271 *wl) +int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifsn, u16 txop) { struct acx_ac_cfg *acx; - int i, ret = 0; + int ret = 0; - wl1271_debug(DEBUG_ACX, "acx access category config"); + wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " + "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop); acx = kzalloc(sizeof(*acx), GFP_KERNEL); @@ -844,21 +846,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl) goto out; } - for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { - struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]); - acx->ac = c->ac; - acx->cw_min = c->cw_min; - acx->cw_max = cpu_to_le16(c->cw_max); - acx->aifsn = c->aifsn; - acx->reserved = 0; - acx->tx_op_limit = cpu_to_le16(c->tx_op_limit); + acx->ac = ac; + acx->cw_min = cw_min; + acx->cw_max = cpu_to_le16(cw_max); + acx->aifsn = aifsn; + acx->tx_op_limit = cpu_to_le16(txop); - ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of access category " - "config: %d", ret); - goto out; - } + ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("acx ac cfg failed: %d", ret); + goto out; } out: diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 1bb63af64f0e..e5f5cbd7f0ea 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -1070,7 +1070,8 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_rate_policies(struct wl1271 *wl); -int wl1271_acx_ac_cfg(struct wl1271 *wl); +int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifsn, u16 txop); int wl1271_acx_tid_cfg(struct wl1271 *wl); int wl1271_acx_frag_threshold(struct wl1271 *wl); int wl1271_acx_tx_config_options(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index c9848eecb767..2b56a9ecd7f2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -195,7 +195,8 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) int wl1271_hw_init(struct wl1271 *wl) { - int ret; + struct conf_tx_ac_category *conf_ac; + int ret, i; ret = wl1271_cmd_general_parms(wl); if (ret < 0) @@ -279,9 +280,14 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Default AC configuration */ - ret = wl1271_acx_ac_cfg(wl); - if (ret < 0) - goto out_free_memmap; + for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { + conf_ac = &wl->conf.tx.ac_conf[i]; + ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + conf_ac->cw_max, conf_ac->aifsn, + conf_ac->tx_op_limit); + if (ret < 0) + goto out_free_memmap; + } /* Configure TX rate classes */ ret = wl1271_acx_rate_policies(wl); -- cgit v1.2.3 From f2054df5170734eacd1db82138c70746ec8387de Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 13:25:40 +0200 Subject: wl1271: modify wl1271_acx_tid_cfg() to use function parameters For WMM we need to configure each tid separately so modify wl1271_acx_tid_cfg() to take the configuration from function parameters instead. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.c | 31 +++++++++++++++---------------- drivers/net/wireless/wl12xx/wl1271_acx.h | 4 +++- drivers/net/wireless/wl12xx/wl1271_init.c | 16 +++++++++++++--- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 4b052eedbd4b..60f10dce4800 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -863,10 +863,12 @@ out: return ret; } -int wl1271_acx_tid_cfg(struct wl1271 *wl) +int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, + u8 tsid, u8 ps_scheme, u8 ack_policy, + u32 apsd_conf0, u32 apsd_conf1) { struct acx_tid_config *acx; - int i, ret = 0; + int ret = 0; wl1271_debug(DEBUG_ACX, "acx tid config"); @@ -877,21 +879,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl) goto out; } - for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { - struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]); - acx->queue_id = c->queue_id; - acx->channel_type = c->channel_type; - acx->tsid = c->tsid; - acx->ps_scheme = c->ps_scheme; - acx->ack_policy = c->ack_policy; - acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]); - acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]); + acx->queue_id = queue_id; + acx->channel_type = channel_type; + acx->tsid = tsid; + acx->ps_scheme = ps_scheme; + acx->ack_policy = ack_policy; + acx->apsd_conf[0] = cpu_to_le32(apsd_conf0); + acx->apsd_conf[1] = cpu_to_le32(apsd_conf1); - ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of tid config failed: %d", ret); - goto out; - } + ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); + if (ret < 0) { + wl1271_warning("Setting of tid config failed: %d", ret); + goto out; } out: diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index e5f5cbd7f0ea..ac94a13ea747 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -1072,7 +1072,9 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_rate_policies(struct wl1271 *wl); int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop); -int wl1271_acx_tid_cfg(struct wl1271 *wl); +int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, + u8 tsid, u8 ps_scheme, u8 ack_policy, + u32 apsd_conf0, u32 apsd_conf1); int wl1271_acx_frag_threshold(struct wl1271 *wl); int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_mem_cfg(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 2b56a9ecd7f2..78403daab949 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -196,6 +196,7 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) int wl1271_hw_init(struct wl1271 *wl) { struct conf_tx_ac_category *conf_ac; + struct conf_tx_tid *conf_tid; int ret, i; ret = wl1271_cmd_general_parms(wl); @@ -275,9 +276,18 @@ int wl1271_hw_init(struct wl1271 *wl) goto out_free_memmap; /* Default TID configuration */ - ret = wl1271_acx_tid_cfg(wl); - if (ret < 0) - goto out_free_memmap; + for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { + conf_tid = &wl->conf.tx.tid_conf[i]; + ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, + conf_tid->channel_type, + conf_tid->tsid, + conf_tid->ps_scheme, + conf_tid->ack_policy, + conf_tid->apsd_conf[0], + conf_tid->apsd_conf[1]); + if (ret < 0) + goto out_free_memmap; + } /* Default AC configuration */ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { -- cgit v1.2.3 From c6999d831ab9ae5e368b20f3bc11b0ca9c17a7ec Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 13:25:41 +0200 Subject: wl1271: implement WMM Now that necessary commands for WMM are implemented, implement queue handling for WMM. But WMM is not enabled yet, only one queue is used. Based on a similar patch from wl1251. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 31 ++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_tx.c | 10 +++++---- drivers/net/wireless/wl12xx/wl1271_tx.h | 36 +++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index a3742c8052d4..6f7a7d946359 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1712,6 +1712,36 @@ out: mutex_unlock(&wl->mutex); } +static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct wl1271 *wl = hw->priv; + int ret; + + mutex_lock(&wl->mutex); + + wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); + + ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), + params->cw_min, params->cw_max, + params->aifs, params->txop); + if (ret < 0) + goto out; + + ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), + CONF_CHANNEL_TYPE_EDCF, + wl1271_tx_get_queue(queue), + CONF_PS_SCHEME_LEGACY_PSPOLL, + CONF_ACK_POLICY_LEGACY, 0, 0); + if (ret < 0) + goto out; + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + /* can't be const, mac80211 writes to this */ static struct ieee80211_rate wl1271_rates[] = { @@ -1877,6 +1907,7 @@ static const struct ieee80211_ops wl1271_ops = { .hw_scan = wl1271_op_hw_scan, .bss_info_changed = wl1271_op_bss_info_changed, .set_rts_threshold = wl1271_op_set_rts_threshold, + .conf_tx = wl1271_op_conf_tx, }; static int wl1271_register_hw(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index a288cc317d7b..f6815a9239e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -87,7 +87,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, u32 extra, struct ieee80211_tx_info *control) { struct wl1271_tx_hw_descr *desc; - int pad; + int pad, ac; u16 tx_attr; desc = (struct wl1271_tx_hw_descr *) skb->data; @@ -107,9 +107,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, /* configure the tx attributes */ tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; - /* FIXME: do we know the packet priority? can we identify mgmt - packets, and use max prio for them at least? */ - desc->tid = 0; + + /* queue */ + ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + desc->tid = wl1271_tx_ac_to_tid(ac); + desc->aid = TX_HW_DEFAULT_AID; desc->reserved = 0; diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 416396caf0a0..17e405a09caa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h @@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if { struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; } __attribute__ ((packed)); +static inline int wl1271_tx_get_queue(int queue) +{ + /* FIXME: use best effort until WMM is enabled */ + return CONF_TX_AC_BE; + + switch (queue) { + case 0: + return CONF_TX_AC_VO; + case 1: + return CONF_TX_AC_VI; + case 2: + return CONF_TX_AC_BE; + case 3: + return CONF_TX_AC_BK; + default: + return CONF_TX_AC_BE; + } +} + +/* wl1271 tx descriptor needs the tid and we need to convert it from ac */ +static inline int wl1271_tx_ac_to_tid(int ac) +{ + switch (ac) { + case 0: + return 0; + case 1: + return 2; + case 2: + return 4; + case 3: + return 6; + default: + return 0; + } +} + void wl1271_tx_work(struct work_struct *work); void wl1271_tx_complete(struct wl1271 *wl, u32 count); void wl1271_tx_flush(struct wl1271 *wl); -- cgit v1.2.3 From 152ee6e09e2ce54d7d1cc9d338b82c0bf3cbbc95 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:42 +0200 Subject: wl1271: Use NVS INI file configuration Replace the hardcoded general and radio parameter configuration in the driver with configuration taken from the NVS file directly. Also remove the driver dependency to the structures with the parameter data. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271.h | 32 ++++++- drivers/net/wireless/wl12xx/wl1271_boot.c | 29 +++--- drivers/net/wireless/wl12xx/wl1271_cmd.c | 117 ++++-------------------- drivers/net/wireless/wl12xx/wl1271_cmd.h | 86 +++--------------- drivers/net/wireless/wl12xx/wl1271_conf.h | 144 +----------------------------- drivers/net/wireless/wl12xx/wl1271_main.c | 101 ++------------------- 6 files changed, 77 insertions(+), 432 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index d0938db043b3..b3a3402593dd 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -109,7 +109,33 @@ enum { #define WL1271_FW_NAME "wl1271-fw.bin" #define WL1271_NVS_NAME "wl1271-nvs.bin" -#define WL1271_NVS_LEN 468 + +/* NVS data structure */ +#define WL1271_NVS_SECTION_SIZE 468 + +#define WL1271_NVS_GENERAL_PARAMS_SIZE 57 +#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \ + (WL1271_NVS_GENERAL_PARAMS_SIZE + 1) +#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17 +#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \ + (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1) +#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65 +#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \ + (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1) +#define WL1271_NVS_FEM_COUNT 2 +#define WL1271_NVS_INI_SPARE_SIZE 124 + +struct wl1271_nvs_file { + /* NVS section */ + u8 nvs[WL1271_NVS_SECTION_SIZE]; + + /* INI section */ + u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED]; + u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED]; + u8 dyn_radio_params[WL1271_NVS_FEM_COUNT] + [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED]; + u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE]; +} __attribute__ ((packed)); /* * Enable/disable 802.11a support for WL1273 @@ -342,8 +368,7 @@ struct wl1271 { u8 *fw; size_t fw_len; - u8 *nvs; - size_t nvs_len; + struct wl1271_nvs_file *nvs; u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; @@ -461,6 +486,7 @@ int wl1271_plt_stop(struct wl1271 *wl); static inline bool wl1271_11a_enabled(void) { + /* FIXME: this could be determined based on the NVS-INI file */ #ifdef WL1271_80211A_ENABLED return true; #else diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index e803b876f3f0..bc3fe0275cac 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -219,29 +219,22 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) size_t nvs_len, burst_len; int i; u32 dest_addr, val; - u8 *nvs_ptr, *nvs, *nvs_aligned; + u8 *nvs_ptr, *nvs_aligned; - nvs = wl->nvs; - if (nvs == NULL) + if (wl->nvs == NULL) return -ENODEV; - if (wl->nvs_len < WL1271_NVS_LEN) - return -EINVAL; - - nvs_ptr = nvs; - /* only the first part of the NVS needs to be uploaded */ - nvs_len = WL1271_NVS_LEN; - - /* FIXME: read init settings from the remaining part of the NVS */ + nvs_len = sizeof(wl->nvs->nvs); + nvs_ptr = (u8 *)wl->nvs->nvs; /* Update the device MAC address into the nvs */ - nvs[11] = wl->mac_addr[0]; - nvs[10] = wl->mac_addr[1]; - nvs[6] = wl->mac_addr[2]; - nvs[5] = wl->mac_addr[3]; - nvs[4] = wl->mac_addr[4]; - nvs[3] = wl->mac_addr[5]; + nvs_ptr[11] = wl->mac_addr[0]; + nvs_ptr[10] = wl->mac_addr[1]; + nvs_ptr[6] = wl->mac_addr[2]; + nvs_ptr[5] = wl->mac_addr[3]; + nvs_ptr[4] = wl->mac_addr[4]; + nvs_ptr[3] = wl->mac_addr[5]; /* * Layout before the actual NVS tables: @@ -283,7 +276,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) * is 7 bytes further. */ nvs_ptr += 7; - nvs_len -= nvs_ptr - nvs; + nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; nvs_len = ALIGN(nvs_len, 4); /* FIXME: The driver sets the partition here, but this is not needed, diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index dd2b5f0540a5..54b5124fc0c0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -191,43 +191,19 @@ static int wl1271_cmd_cal(struct wl1271 *wl) int wl1271_cmd_general_parms(struct wl1271 *wl) { struct wl1271_general_parms_cmd *gen_parms; - struct conf_general_parms *g = &wl->conf.init.genparam; int ret; + if (!wl->nvs) + return -ENODEV; + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; - gen_parms->ref_clk = g->ref_clk; - gen_parms->settling_time = g->settling_time; - gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup; - gen_parms->dc2dcmode = g->dc2dcmode; - gen_parms->single_dual_band = g->single_dual_band; - gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect; - gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; - gen_parms->settings = g->settings; - - gen_parms->sr_state = g->sr_state; - - memcpy(gen_parms->srf1, - g->srf1, - CONF_MAX_SMART_REFLEX_PARAMS); - memcpy(gen_parms->srf2, - g->srf2, - CONF_MAX_SMART_REFLEX_PARAMS); - memcpy(gen_parms->srf3, - g->srf3, - CONF_MAX_SMART_REFLEX_PARAMS); - memcpy(gen_parms->sr_debug_table, - g->sr_debug_table, - CONF_MAX_SMART_REFLEX_PARAMS); - - gen_parms->sr_sen_n_p = g->sr_sen_n_p; - gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; - gen_parms->sr_sen_nrn = g->sr_sen_nrn; - gen_parms->sr_sen_prn = g->sr_sen_prn; + memcpy(gen_parms->params, wl->nvs->general_params, + WL1271_NVS_GENERAL_PARAMS_SIZE); ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); if (ret < 0) @@ -240,8 +216,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) int wl1271_cmd_radio_parms(struct wl1271 *wl) { struct wl1271_radio_parms_cmd *radio_parms; - struct conf_radio_parms *r = &wl->conf.init.radioparam; - int i, ret; + struct conf_radio_parms *rparam = &wl->conf.init.radioparam; + int ret; + + if (!wl->nvs) + return -ENODEV; radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); if (!radio_parms) @@ -249,73 +228,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; - /* Static radio parameters */ - radio_parms->rx_trace_loss = r->rx_trace_loss; - radio_parms->tx_trace_loss = r->tx_trace_loss; - memcpy(radio_parms->rx_rssi_and_proc_compens, - r->rx_rssi_and_proc_compens, - CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); - - memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5, - CONF_NUMBER_OF_SUB_BANDS_5); - memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5, - CONF_NUMBER_OF_SUB_BANDS_5); - memcpy(radio_parms->rx_rssi_and_proc_compens_5, - r->rx_rssi_and_proc_compens_5, - CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); - - /* Dynamic radio parameters */ - radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage); - radio_parms->tx_ref_power = r->tx_ref_power; - radio_parms->tx_offset_db = r->tx_offset_db; - - memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal, - CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, - CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, - CONF_NUMBER_OF_RATE_GROUPS); - - memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, - CONF_NUMBER_OF_CHANNELS_2_4); - memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm, - CONF_NUMBER_OF_CHANNELS_2_4); - memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets, - CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); - - radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; - radio_parms->degraded_low_to_normal_threshold = - r->degraded_low_to_normal_threshold; - radio_parms->degraded_normal_to_high_threshold = - r->degraded_normal_to_high_threshold; - - - for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) - radio_parms->tx_ref_pd_voltage_5[i] = - cpu_to_le16(r->tx_ref_pd_voltage_5[i]); - memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5, - CONF_NUMBER_OF_SUB_BANDS_5); - memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5, - CONF_NUMBER_OF_SUB_BANDS_5); - memcpy(radio_parms->tx_rate_limits_normal_5, - r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_rate_limits_degraded_5, - r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_rate_limits_extreme_5, - r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_channel_limits_ofdm_5, - r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); - memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, - CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5, - CONF_NUMBER_OF_RATE_GROUPS); - memcpy(radio_parms->rx_fem_insertion_loss_5, - r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); - radio_parms->degraded_low_to_normal_threshold_5 = - r->degraded_low_to_normal_threshold_5; - radio_parms->degraded_normal_to_high_threshold_5 = - r->degraded_normal_to_high_threshold_5; + memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, + WL1271_NVS_STAT_RADIO_PARAMS_SIZE); + memcpy(radio_parms->dyn_radio_params, + wl->nvs->dyn_radio_params[rparam->fem], + WL1271_NVS_DYN_RADIO_PARAMS_SIZE); + + /* FIXME: current NVS is missing 5GHz parameters */ wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", radio_parms, sizeof(*radio_parms)); @@ -1022,7 +941,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_warning("could not set keys"); - goto out; + goto out; } out: diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index ba433f423c8b..2dc06c73532b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h @@ -428,90 +428,24 @@ struct wl1271_general_parms_cmd { struct wl1271_cmd_test_header test; - u8 ref_clk; - u8 settling_time; - u8 clk_valid_on_wakeup; - u8 dc2dcmode; - u8 single_dual_band; - - u8 tx_bip_fem_autodetect; - u8 tx_bip_fem_manufacturer; - u8 settings; - - u8 sr_state; - - s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; - s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; - s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; - - s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; - - u8 sr_sen_n_p; - u8 sr_sen_n_p_gain; - u8 sr_sen_nrn; - u8 sr_sen_prn; - - u8 padding[3]; + u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE]; + s8 reserved[23]; } __attribute__ ((packed)); +#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29 +#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104 + struct wl1271_radio_parms_cmd { struct wl1271_cmd_header header; struct wl1271_cmd_test_header test; - /* Static radio parameters */ - /* 2.4GHz */ - u8 rx_trace_loss; - u8 tx_trace_loss; - s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* 5GHz */ - u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* Dynamic radio parameters */ - /* 2.4GHz */ - __le16 tx_ref_pd_voltage; - u8 tx_ref_power; - s8 tx_offset_db; - - s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; + u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE]; + u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE]; - s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; - s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; - s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; - - u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; - u8 rx_fem_insertion_loss; - - u8 degraded_low_to_normal_threshold; - u8 degraded_normal_to_high_threshold; - - u8 padding1; /* our own padding, not in ref driver */ - - /* 5GHz */ - __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; - u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; - - s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; - - s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; - s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; - - /* FIXME: this is inconsistent with the types for 2.4GHz */ - s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - - u8 degraded_low_to_normal_threshold_5; - u8 degraded_normal_to_high_threshold_5; - - u8 padding2[2]; + u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE]; + u8 reserved; + u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE]; } __attribute__ ((packed)); struct wl1271_cmd_cal_channel_tune { diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 1993d63c214e..6f9e75cc5640 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -735,81 +735,6 @@ enum single_dual_band_enum { CONF_DUAL_BAND }; - -#define CONF_MAX_SMART_REFLEX_PARAMS 16 - -struct conf_general_parms { - /* - * RF Reference Clock type / speed - * - * Range: CONF_REF_CLK_* - */ - u8 ref_clk; - - /* - * Settling time of the reference clock after boot. - * - * Range: u8 - */ - u8 settling_time; - - /* - * Flag defining whether clock is valid on wakeup. - * - * Range: 0 - not valid on wakeup, 1 - valid on wakeup - */ - u8 clk_valid_on_wakeup; - - /* - * DC-to-DC mode. - * - * Range: Unknown - */ - u8 dc2dcmode; - - /* - * Flag defining whether used as single or dual-band. - * - * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND - */ - u8 single_dual_band; - - /* - * TX bip fem autodetect flag. - * - * Range: Unknown - */ - u8 tx_bip_fem_autodetect; - - /* - * TX bip gem manufacturer. - * - * Range: Unknown - */ - u8 tx_bip_fem_manufacturer; - - /* - * Settings flags. - * - * Range: Unknown - */ - u8 settings; - - /* Smart reflex settings */ - u8 sr_state; - - s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; - s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; - s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; - - s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; - - u8 sr_sen_n_p; - u8 sr_sen_n_p_gain; - u8 sr_sen_nrn; - u8 sr_sen_prn; -}; - #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 #define CONF_NUMBER_OF_SUB_BANDS_5 7 #define CONF_NUMBER_OF_RATE_GROUPS 6 @@ -818,77 +743,14 @@ struct conf_general_parms { struct conf_radio_parms { /* - * Static radio parameters for 2.4GHz - * - * Range: unknown - */ - u8 rx_trace_loss; - u8 tx_trace_loss; - s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* - * Static radio parameters for 5GHz - * - * Range: unknown - */ - u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* - * Dynamic radio parameters for 2.4GHz + * FEM parameter set to use * - * Range: unknown + * Range: 0 or 1 */ - u16 tx_ref_pd_voltage; - u8 tx_ref_power; - s8 tx_offset_db; - - s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; - - s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; - s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; - s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; - - u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; - u8 rx_fem_insertion_loss; - - u8 degraded_low_to_normal_threshold; - u8 degraded_normal_to_high_threshold; - - - /* - * Dynamic radio parameters for 5GHz - * - * Range: unknown - */ - u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; - u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; - s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; - - s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; - - s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; - s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; - - /* FIXME: this is inconsistent with the types for 2.4GHz */ - s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; - s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; - - u8 degraded_low_to_normal_threshold_5; - u8 degraded_normal_to_high_threshold_5; + u8 fem; }; struct conf_init_settings { - /* - * Configure general parameters. - */ - struct conf_general_parms genparam; - /* * Configure radio parameters. */ diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 6f7a7d946359..282c2bbfec86 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -229,93 +229,8 @@ static struct conf_drv_settings default_conf = { .psm_entry_retries = 3 }, .init = { - .genparam = { - .ref_clk = CONF_REF_CLK_38_4_E, - .settling_time = 5, - .clk_valid_on_wakeup = 0, - .dc2dcmode = 0, - .single_dual_band = CONF_SINGLE_BAND, - .tx_bip_fem_autodetect = 1, - .tx_bip_fem_manufacturer = 1, - .settings = 1, - .sr_state = 1, - .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, - 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, - 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, - 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, - .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, - .sr_sen_n_p = 0, - .sr_sen_n_p_gain = 0, - .sr_sen_nrn = 0, - .sr_sen_prn = 0, - }, .radioparam = { - .rx_trace_loss = 0x24, - .tx_trace_loss = 0x0, - .rx_rssi_and_proc_compens = { - 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, - 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, - 0x00, 0x0a, 0x14 }, - .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, - .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, - .rx_rssi_and_proc_compens_5 = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 }, - .tx_ref_pd_voltage = 0x1a9, - .tx_ref_power = 0x80, - .tx_offset_db = 0x0, - .tx_rate_limits_normal = { - 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, - .tx_rate_limits_degraded = { - 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, - .tx_rate_limits_extreme = { - 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, - .tx_channel_limits_11b = { - 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, - 0x22, 0x50 }, - .tx_channel_limits_ofdm = { - 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, - 0x20, 0x50 }, - .tx_pdv_rate_offsets = { - 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, - .tx_ibias = { - 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, - .rx_fem_insertion_loss = 0x0e, - .degraded_low_to_normal_threshold = 0x1e, - .degraded_normal_to_high_threshold = 0x2d, - .tx_ref_pd_voltage_5 = { - 0x0190, 0x01a4, 0x01c3, 0x01d8, - 0x020a, 0x021c }, - .tx_ref_power_5 = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, - .tx_offset_db_5 = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - .tx_rate_limits_normal_5 = { - 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, - .tx_rate_limits_degraded_5 = { - 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, - .tx_rate_limits_extreme_5 = { - 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, - .tx_channel_limits_ofdm_5 = { - 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50 }, - .tx_pdv_rate_offsets_5 = { - 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, - .tx_ibias_5 = { - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, - .rx_fem_insertion_loss_5 = { - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, - .degraded_low_to_normal_threshold_5 = 0x00, - .degraded_normal_to_high_threshold_5 = 0x00 + .fem = 1, } }, .itrim = { @@ -345,9 +260,6 @@ static void wl1271_conf_init(struct wl1271 *wl) /* apply driver default configuration */ memcpy(&wl->conf, &default_conf, sizeof(default_conf)); - - if (wl1271_11a_enabled()) - wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND; } @@ -567,15 +479,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) return ret; } - if (fw->size % 4) { - wl1271_error("nvs size is not multiple of 32 bits: %zu", - fw->size); + if (fw->size != sizeof(struct wl1271_nvs_file)) { + wl1271_error("nvs size is not as expected: %zu != %zu", + fw->size, sizeof(struct wl1271_nvs_file)); ret = -EILSEQ; goto out; } - wl->nvs_len = fw->size; - wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); + wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); @@ -583,7 +494,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) goto out; } - memcpy(wl->nvs, fw->data, wl->nvs_len); + memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); ret = 0; -- cgit v1.2.3 From 7b21b6f8216494ab6b8b4dc9d15e48051a0f0a66 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:43 +0200 Subject: wl1271: Retrieve device mac address from the nvs file Instead of always randomizing the MAC address, retrieve and configure the MAC address from the device specific nvs file. For now, randomize an address only if the address in the NVS is zero. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ------- drivers/net/wireless/wl12xx/wl1271_main.c | 36 +++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index bc3fe0275cac..57ba78d83e87 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -228,14 +228,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_len = sizeof(wl->nvs->nvs); nvs_ptr = (u8 *)wl->nvs->nvs; - /* Update the device MAC address into the nvs */ - nvs_ptr[11] = wl->mac_addr[0]; - nvs_ptr[10] = wl->mac_addr[1]; - nvs_ptr[6] = wl->mac_addr[2]; - nvs_ptr[5] = wl->mac_addr[3]; - nvs_ptr[4] = wl->mac_addr[4]; - nvs_ptr[3] = wl->mac_addr[5]; - /* * Layout before the actual NVS tables: * 1 byte : burst length. diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 282c2bbfec86..b5d53a3fcc5d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -467,6 +467,32 @@ out: return ret; } +static int wl1271_update_mac_addr(struct wl1271 *wl) +{ + int ret = 0; + u8 *nvs_ptr = (u8 *)wl->nvs->nvs; + + /* get mac address from the NVS */ + wl->mac_addr[0] = nvs_ptr[11]; + wl->mac_addr[1] = nvs_ptr[10]; + wl->mac_addr[2] = nvs_ptr[6]; + wl->mac_addr[3] = nvs_ptr[5]; + wl->mac_addr[4] = nvs_ptr[4]; + wl->mac_addr[5] = nvs_ptr[3]; + + /* FIXME: if it is a zero-address, we should bail out. Now, instead, + we randomize an address */ + if (is_zero_ether_addr(wl->mac_addr)) { + static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; + memcpy(wl->mac_addr, nokia_oui, 3); + get_random_bytes(wl->mac_addr + 3, 3); + } + + SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); + + return ret; +} + static int wl1271_fetch_nvs(struct wl1271 *wl) { const struct firmware *fw; @@ -496,7 +522,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); - ret = 0; + ret = wl1271_update_mac_addr(wl); out: release_firmware(fw); @@ -1893,7 +1919,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) struct ieee80211_hw *hw; struct wl1271 *wl; int ret, i; - static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; pdata = spi->dev.platform_data; if (!pdata) { @@ -1938,13 +1963,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) spin_lock_init(&wl->wl_lock); - /* - * In case our MAC address is not correctly set, - * we use a random but Nokia MAC. - */ - memcpy(wl->mac_addr, nokia_oui, 3); - get_random_bytes(wl->mac_addr + 3, 3); - wl->state = WL1271_STATE_OFF; mutex_init(&wl->mutex); -- cgit v1.2.3 From 12419cce88fa591a846a542d35cff43b69d9e271 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 18 Feb 2010 13:25:44 +0200 Subject: wl1271: add most of the normal initialization commands to PLT mode We need to configure PLT mode almost in the same way as normal mode. Most of the configuration functions need to be called also when entering PLT, with the exception of a few RX and TX configuration (which cause mac80211 warnings if enable while runnning PLT tests). Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_init.c | 8 +-- drivers/net/wireless/wl12xx/wl1271_init.h | 4 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 85 ++++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 78403daab949..86c30a86a456 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c @@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) return 0; } -static int wl1271_init_templates_config(struct wl1271 *wl) +int wl1271_init_templates_config(struct wl1271 *wl) { int ret; @@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) return 0; } -static int wl1271_init_phy_config(struct wl1271 *wl) +int wl1271_init_phy_config(struct wl1271 *wl) { int ret; @@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl) return 0; } -static int wl1271_init_pta(struct wl1271 *wl) +int wl1271_init_pta(struct wl1271 *wl) { int ret; @@ -171,7 +171,7 @@ static int wl1271_init_pta(struct wl1271 *wl) return 0; } -static int wl1271_init_energy_detection(struct wl1271 *wl) +int wl1271_init_energy_detection(struct wl1271 *wl) { int ret; diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h index 930677fbe852..bc26f8c53b91 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/wl1271_init.h @@ -27,6 +27,10 @@ #include "wl1271.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); +int wl1271_init_templates_config(struct wl1271 *wl); +int wl1271_init_phy_config(struct wl1271 *wl); +int wl1271_init_pta(struct wl1271 *wl); +int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b5d53a3fcc5d..e698dec40511 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -265,7 +265,9 @@ static void wl1271_conf_init(struct wl1271 *wl) static int wl1271_plt_init(struct wl1271 *wl) { - int ret; + struct conf_tx_ac_category *conf_ac; + struct conf_tx_tid *conf_tid; + int ret, i; ret = wl1271_cmd_general_parms(wl); if (ret < 0) @@ -275,15 +277,89 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; + ret = wl1271_init_templates_config(wl); + if (ret < 0) + return ret; + ret = wl1271_acx_init_mem_config(wl); if (ret < 0) return ret; + /* PHY layer config */ + ret = wl1271_init_phy_config(wl); + if (ret < 0) + goto out_free_memmap; + + ret = wl1271_acx_dco_itrim_params(wl); + if (ret < 0) + goto out_free_memmap; + + /* Initialize connection monitoring thresholds */ + ret = wl1271_acx_conn_monit_params(wl); + if (ret < 0) + goto out_free_memmap; + + /* Bluetooth WLAN coexistence */ + ret = wl1271_init_pta(wl); + if (ret < 0) + goto out_free_memmap; + + /* Energy detection */ + ret = wl1271_init_energy_detection(wl); + if (ret < 0) + goto out_free_memmap; + + /* Default fragmentation threshold */ + ret = wl1271_acx_frag_threshold(wl); + if (ret < 0) + goto out_free_memmap; + + /* Default TID configuration */ + for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { + conf_tid = &wl->conf.tx.tid_conf[i]; + ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, + conf_tid->channel_type, + conf_tid->tsid, + conf_tid->ps_scheme, + conf_tid->ack_policy, + conf_tid->apsd_conf[0], + conf_tid->apsd_conf[1]); + if (ret < 0) + goto out_free_memmap; + } + + /* Default AC configuration */ + for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { + conf_ac = &wl->conf.tx.ac_conf[i]; + ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + conf_ac->cw_max, conf_ac->aifsn, + conf_ac->tx_op_limit); + if (ret < 0) + goto out_free_memmap; + } + + /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) - return ret; + goto out_free_memmap; + + /* Configure for CAM power saving (ie. always active) */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + goto out_free_memmap; + + /* configure PM */ + ret = wl1271_acx_pm_config(wl); + if (ret < 0) + goto out_free_memmap; return 0; + + out_free_memmap: + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; + + return ret; } static void wl1271_disable_interrupts(struct wl1271 *wl) @@ -653,11 +729,6 @@ int wl1271_plt_start(struct wl1271 *wl) if (ret < 0) goto irq_disable; - /* Make sure power saving is disabled */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - goto irq_disable; - wl->state = WL1271_STATE_PLT; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); -- cgit v1.2.3 From 6f8434a754894f5743efc281fda3925ecac258b9 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 18 Feb 2010 13:25:45 +0200 Subject: wl1271: skip 3 unused bytes from the NVS Our NVS uploading mechanism had a bug that was causing it to pass three extra zeros at the start of the NVS. This may be a problem in the NVS generation application, but for now we fix it in the driver. Signed-off-by: Luciano Coelho Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 57ba78d83e87..fb3090c3ed15 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -277,9 +277,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) wl1271_set_partition(wl, &part_table[PART_WORK]); /* Copy the NVS tables to a new block to ensure alignment */ - nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); - if (!nvs_aligned) - return -ENOMEM; + /* FIXME: We jump 3 more bytes before uploading the NVS. It seems + that our NVS files have three extra zeros here. I'm not sure whether + the problem is in our NVS generation or we should really jumpt these + 3 bytes here */ + nvs_ptr += 3; + + nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if + (!nvs_aligned) return -ENOMEM; /* And finally we upload the NVS tables */ /* FIXME: In wl1271, we upload everything at once. -- cgit v1.2.3 From e2e77b5ffb14211306ee093f01230f6ec69fab30 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:46 +0200 Subject: wl1271: Fix random MAC address setting If reverting to a random MAC address, the driver would not update it to the NVS file, and hence the firmware frame filtering would not work properly. So update the randomized MAC address to the NVS image. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index e698dec40511..c7f5191e7dbf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -562,6 +562,14 @@ static int wl1271_update_mac_addr(struct wl1271 *wl) static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; memcpy(wl->mac_addr, nokia_oui, 3); get_random_bytes(wl->mac_addr + 3, 3); + + /* update this address to the NVS */ + nvs_ptr[11] = wl->mac_addr[0]; + nvs_ptr[10] = wl->mac_addr[1]; + nvs_ptr[6] = wl->mac_addr[2]; + nvs_ptr[5] = wl->mac_addr[3]; + nvs_ptr[4] = wl->mac_addr[4]; + nvs_ptr[3] = wl->mac_addr[5]; } SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); -- cgit v1.2.3 From c82c1dde3024715c4cd8b6dd8cc7c75d8d7d93c8 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 13:25:47 +0200 Subject: wl1271: wakeup chip in op_conf_tx() elp_wakeup() was missing in op_conf_tx() which caused wakeup problems in power save. I forgot to add this part when porting the patch from wl1251. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index c7f5191e7dbf..9de7df76f53b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1738,11 +1738,15 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); + ret = wl1271_ps_elp_wakeup(wl, false); + if (ret < 0) + goto out; + ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), params->cw_min, params->cw_max, params->aifs, params->txop); if (ret < 0) - goto out; + goto out_sleep; ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), CONF_CHANNEL_TYPE_EDCF, @@ -1750,7 +1754,10 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, CONF_PS_SCHEME_LEGACY_PSPOLL, CONF_ACK_POLICY_LEGACY, 0, 0); if (ret < 0) - goto out; + goto out_sleep; + +out_sleep: + wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); -- cgit v1.2.3 From 6c71b0ea761da416af54df4f72f48e71050cc012 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:48 +0200 Subject: wl1271: Optimized RX path packet retrieval Instead of acking RX packets read from the FW once all (of several possible) buffered packets are retrieved, ack packets one by one as they are read. This enables the FW to start receiving more packets from the network while the host read operation is still ongoing. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index ca645f38109b..e8eee883848f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -218,7 +218,7 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) wl->rx_counter++; drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; + wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, + wl->rx_counter); } - - wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); } -- cgit v1.2.3 From fddc7dd7deaa400db314b214d92de95f865a8af0 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:49 +0200 Subject: wl1271: Fix key-remove error The new firmware does not allow removal of unicast keys - they will be automatically removed on the next CMD_JOIN. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9de7df76f53b..4a0a15bcd67e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1478,6 +1478,13 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: + /* The wl1271 does not allow to remove unicast keys - they + will be cleared automatically on next CMD_JOIN. Ignore the + request silently, as we dont want the mac80211 to emit + an error message. */ + if (!is_broadcast_ether_addr(addr)) + break; + ret = wl1271_cmd_set_key(wl, KEY_REMOVE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, -- cgit v1.2.3 From ee444cf0501183df1640cd35bebd4250989bfe99 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:50 +0200 Subject: wl1271: Fix WEP key handling WEP key index handling was broken: the default key when using key 0 was never specified to the FW, and if using other default than 0, it would be set on the TX path for every single TX'd frame. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++++ drivers/net/wireless/wl12xx/wl1271_tx.c | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4a0a15bcd67e..459d9a0931f4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1475,6 +1475,14 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, wl1271_error("Could not add or replace key"); goto out_sleep; } + + /* the default WEP key needs to be configured at least once */ + if (key_type == KEY_WEP) { + ret = wl1271_cmd_set_default_wep_key(wl, + wl->default_key); + if (ret < 0) + goto out_sleep; + } break; case DISABLE_KEY: diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index f6815a9239e5..f9e06385d9fe 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -203,6 +203,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) ret = wl1271_cmd_set_default_wep_key(wl, idx); if (ret < 0) return ret; + wl->default_key = idx; } } -- cgit v1.2.3 From 8bf29b0eb3ba38c8cf55e60976f124672cda7ab2 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:51 +0200 Subject: wl1271: Fix ad-hoc SSID update If re-configuring the SSID while ad-hoc was already enabled, the beacon template would be properly updated, but the SSID passed in the CMD_JOIN would not - hence filtering etc would not work properly. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 459d9a0931f4..fb1e6a8088d8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1,7 +1,7 @@ /* * This file is part of wl1271 * - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Nokia Corporation * * Contact: Luciano Coelho * @@ -1604,6 +1604,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, { enum wl1271_cmd_ps_mode mode; struct wl1271 *wl = hw->priv; + bool do_join = false; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1646,6 +1647,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, dev_kfree_skb(beacon); if (ret < 0) goto out_sleep; + + /* Need to update the SSID (for filtering etc) */ + do_join = true; } } @@ -1664,12 +1668,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, goto out_sleep; } - ret = wl1271_cmd_join(wl); - if (ret < 0) { - wl1271_warning("cmd join failed %d", ret); - goto out_sleep; - } - set_bit(WL1271_FLAG_JOINED, &wl->flags); + /* Need to update the BSSID (for filtering etc) */ + do_join = true; } if (changed & BSS_CHANGED_ASSOC) { @@ -1736,6 +1736,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } + if (do_join) { + ret = wl1271_cmd_join(wl); + if (ret < 0) { + wl1271_warning("cmd join failed %d", ret); + goto out_sleep; + } + set_bit(WL1271_FLAG_JOINED, &wl->flags); + } + out_sleep: wl1271_ps_elp_sleep(wl); -- cgit v1.2.3 From 1937e742639c03a6fe77239c3003ce9602302117 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Thu, 18 Feb 2010 13:25:52 +0200 Subject: wl1271: Fix beacon filter table configuration The beacon filter table configuration ACX structure had certain elements reversed, resulting in firmware instability in regard of the feature. Fix the structure. Signed-off-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_acx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index ac94a13ea747..aeccc98581eb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h @@ -2,7 +2,7 @@ * This file is part of wl1271 * * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Nokia Corporation * * Contact: Luciano Coelho * @@ -348,7 +348,7 @@ struct acx_beacon_filter_option { * ACXBeaconFilterEntry (not 221) * Byte Offset Size (Bytes) Definition * =========== ============ ========== - * 0 1 IE identifier + * 0 1 IE identifier * 1 1 Treatment bit mask * * ACXBeaconFilterEntry (221) @@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table { struct acx_header header; u8 num_ie; - u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; u8 pad[3]; + u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; } __attribute__ ((packed)); struct acx_conn_monit_params { -- cgit v1.2.3 From c8c90873520ef4c201cfd03b4892ca8bbf551e2e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 13:25:53 +0200 Subject: wl1271: add testmode support Testmode will be used to send PLT (Production Line Testing) commands from user space. Signed-off-by: Kalle Valo Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/Makefile | 1 + drivers/net/wireless/wl12xx/wl1271.h | 2 +- drivers/net/wireless/wl12xx/wl1271_main.c | 2 + drivers/net/wireless/wl12xx/wl1271_testmode.c | 283 ++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_testmode.h | 31 +++ 5 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.c create mode 100644 drivers/net/wireless/wl12xx/wl1271_testmode.h diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 62e37ad01cc0..d089b5d6a513 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -11,4 +11,5 @@ wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ wl1271_event.o wl1271_tx.o wl1271_rx.o \ wl1271_ps.o wl1271_acx.o wl1271_boot.o \ wl1271_init.o wl1271_debugfs.o +wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o obj-$(CONFIG_WL1271) += wl1271.o diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index b3a3402593dd..97ea5096bc8c 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h @@ -43,7 +43,7 @@ enum { DEBUG_SPI = BIT(1), DEBUG_BOOT = BIT(2), DEBUG_MAILBOX = BIT(3), - DEBUG_NETLINK = BIT(4), + DEBUG_TESTMODE = BIT(4), DEBUG_EVENT = BIT(5), DEBUG_TX = BIT(6), DEBUG_RX = BIT(7), diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index fb1e6a8088d8..aa8f79c4c98a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -46,6 +46,7 @@ #include "wl1271_debugfs.h" #include "wl1271_cmd.h" #include "wl1271_boot.h" +#include "wl1271_testmode.h" #define WL1271_BOOT_RETRIES 3 @@ -1955,6 +1956,7 @@ static const struct ieee80211_ops wl1271_ops = { .bss_info_changed = wl1271_op_bss_info_changed, .set_rts_threshold = wl1271_op_set_rts_threshold, .conf_tx = wl1271_op_conf_tx, + CFG80211_TESTMODE_CMD(wl1271_tm_cmd) }; static int wl1271_register_hw(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c new file mode 100644 index 000000000000..3919102e942e --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c @@ -0,0 +1,283 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#include "wl1271_testmode.h" + +#include + +#include "wl1271.h" +#include "wl1271_spi.h" +#include "wl1271_acx.h" + +#define WL1271_TM_MAX_DATA_LENGTH 1024 + +enum wl1271_tm_commands { + WL1271_TM_CMD_UNSPEC, + WL1271_TM_CMD_TEST, + WL1271_TM_CMD_INTERROGATE, + WL1271_TM_CMD_CONFIGURE, + WL1271_TM_CMD_NVS_PUSH, + WL1271_TM_CMD_SET_PLT_MODE, + + __WL1271_TM_CMD_AFTER_LAST +}; +#define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1) + +enum wl1271_tm_attrs { + WL1271_TM_ATTR_UNSPEC, + WL1271_TM_ATTR_CMD_ID, + WL1271_TM_ATTR_ANSWER, + WL1271_TM_ATTR_DATA, + WL1271_TM_ATTR_IE_ID, + WL1271_TM_ATTR_PLT_MODE, + + __WL1271_TM_ATTR_AFTER_LAST +}; +#define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1) + +static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = { + [WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 }, + [WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 }, + [WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = WL1271_TM_MAX_DATA_LENGTH }, + [WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 }, + [WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 }, +}; + + +static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) +{ + int buf_len, ret, len; + struct sk_buff *skb; + void *buf; + u8 answer = 0; + + wl1271_debug(DEBUG_TESTMODE, "testmode cmd test"); + + if (!tb[WL1271_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[WL1271_TM_ATTR_DATA]); + buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); + + if (tb[WL1271_TM_ATTR_ANSWER]) + answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]); + + if (buf_len > sizeof(struct wl1271_command)) + return -EMSGSIZE; + + mutex_lock(&wl->mutex); + ret = wl1271_cmd_test(wl, buf, buf_len, answer); + mutex_unlock(&wl->mutex); + + if (ret < 0) { + wl1271_warning("testmode cmd test failed: %d", ret); + return ret; + } + + if (answer) { + len = nla_total_size(buf_len); + skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); + if (!skb) + return -ENOMEM; + + NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); + ret = cfg80211_testmode_reply(skb); + if (ret < 0) + return ret; + } + + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + +static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) +{ + int ret; + struct wl1271_command *cmd; + struct sk_buff *skb; + u8 ie_id; + + wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate"); + + if (!tb[WL1271_TM_ATTR_IE_ID]) + return -EINVAL; + + ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + mutex_lock(&wl->mutex); + ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); + mutex_unlock(&wl->mutex); + + if (ret < 0) { + wl1271_warning("testmode cmd interrogate failed: %d", ret); + return ret; + } + + skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); + + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + +static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) +{ + int buf_len, ret; + void *buf; + u8 ie_id; + + wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure"); + + if (!tb[WL1271_TM_ATTR_DATA]) + return -EINVAL; + if (!tb[WL1271_TM_ATTR_IE_ID]) + return -EINVAL; + + ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); + buf = nla_data(tb[WL1271_TM_ATTR_DATA]); + buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); + + if (buf_len > sizeof(struct wl1271_command)) + return -EMSGSIZE; + + mutex_lock(&wl->mutex); + ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len); + mutex_unlock(&wl->mutex); + + if (ret < 0) { + wl1271_warning("testmode cmd configure failed: %d", ret); + return ret; + } + + return 0; +} + +static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) +{ + int ret = 0; + size_t len; + void *buf; + + wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push"); + + if (!tb[WL1271_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[WL1271_TM_ATTR_DATA]); + len = nla_len(tb[WL1271_TM_ATTR_DATA]); + + if (len != sizeof(struct wl1271_nvs_file)) { + wl1271_error("nvs size is not as expected: %zu != %zu", + len, sizeof(struct wl1271_nvs_file)); + return -EMSGSIZE; + } + + mutex_lock(&wl->mutex); + + kfree(wl->nvs); + + wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); + if (!wl->nvs) { + wl1271_error("could not allocate memory for the nvs file"); + ret = -ENOMEM; + goto out; + } + + memcpy(wl->nvs, buf, len); + + wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); + +out: + mutex_unlock(&wl->mutex); + + return ret; +} + +static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) +{ + u32 val; + int ret; + + wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode"); + + if (!tb[WL1271_TM_ATTR_PLT_MODE]) + return -EINVAL; + + val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]); + + switch (val) { + case 0: + ret = wl1271_plt_stop(wl); + break; + case 1: + ret = wl1271_plt_start(wl); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) +{ + struct wl1271 *wl = hw->priv; + struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; + int err; + + err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); + if (err) + return err; + + if (!tb[WL1271_TM_ATTR_CMD_ID]) + return -EINVAL; + + switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) { + case WL1271_TM_CMD_TEST: + return wl1271_tm_cmd_test(wl, tb); + case WL1271_TM_CMD_INTERROGATE: + return wl1271_tm_cmd_interrogate(wl, tb); + case WL1271_TM_CMD_CONFIGURE: + return wl1271_tm_cmd_configure(wl, tb); + case WL1271_TM_CMD_NVS_PUSH: + return wl1271_tm_cmd_nvs_push(wl, tb); + case WL1271_TM_CMD_SET_PLT_MODE: + return wl1271_tm_cmd_set_plt_mode(wl, tb); + default: + return -EOPNOTSUPP; + } +} diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/wl1271_testmode.h new file mode 100644 index 000000000000..c196d28f9d9d --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.h @@ -0,0 +1,31 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL1271_TESTMODE_H__ +#define __WL1271_TESTMODE_H__ + +#include + +int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len); + +#endif /* __WL1271_TESTMODE_H__ */ -- cgit v1.2.3 From 521a5b2137cc15430e3b1ea4c148663d1dbe077f Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Feb 2010 13:25:54 +0200 Subject: wl1271: Moved common IO functions from wl271_spi.c to wl1271_io.c In prepraration for integration of SDIO implementation moved some IO functions common for SPI and SDIO to separate file. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/Makefile | 3 +- drivers/net/wireless/wl12xx/wl1271_io.c | 203 +++++++++++++++++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_io.h | 37 ++++++ drivers/net/wireless/wl12xx/wl1271_spi.c | 157 ------------------------ 4 files changed, 242 insertions(+), 158 deletions(-) create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.c create mode 100644 drivers/net/wireless/wl12xx/wl1271_io.h diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index d089b5d6a513..f47ec94c16dc 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ wl1271_event.o wl1271_tx.o wl1271_rx.o \ wl1271_ps.o wl1271_acx.o wl1271_boot.o \ - wl1271_init.o wl1271_debugfs.o + wl1271_init.o wl1271_debugfs.o wl1271_io.o + wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o obj-$(CONFIG_WL1271) += wl1271.o diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c new file mode 100644 index 000000000000..dcb588b4670d --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -0,0 +1,203 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 2008-2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include "wl1271.h" +#include "wl12xx_80211.h" +#include "wl1271_spi.h" +#include "wl1271_io.h" + +static int wl1271_translate_addr(struct wl1271 *wl, int addr) +{ + /* + * To translate, first check to which window of addresses the + * particular address belongs. Then subtract the starting address + * of that window from the address. Then, add offset of the + * translated region. + * + * The translated regions occur next to each other in physical device + * memory, so just add the sizes of the preceeding address regions to + * get the offset to the new region. + * + * Currently, only the two first regions are addressed, and the + * assumption is that all addresses will fall into either of those + * two. + */ + if ((addr >= wl->part.reg.start) && + (addr < wl->part.reg.start + wl->part.reg.size)) + return addr - wl->part.reg.start + wl->part.mem.size; + else + return addr - wl->part.mem.start; +} + +/* Set the SPI partitions to access the chip addresses + * + * To simplify driver code, a fixed (virtual) memory map is defined for + * register and memory addresses. Because in the chipset, in different stages + * of operation, those addresses will move around, an address translation + * mechanism is required. + * + * There are four partitions (three memory and one register partition), + * which are mapped to two different areas of the hardware memory. + * + * Virtual address + * space + * + * | | + * ...+----+--> mem.start + * Physical address ... | | + * space ... | | [PART_0] + * ... | | + * 00000000 <--+----+... ...+----+--> mem.start + mem.size + * | | ... | | + * |MEM | ... | | + * | | ... | | + * mem.size <--+----+... | | {unused area) + * | | ... | | + * |REG | ... | | + * mem.size | | ... | | + * + <--+----+... ...+----+--> reg.start + * reg.size | | ... | | + * |MEM2| ... | | [PART_1] + * | | ... | | + * ...+----+--> reg.start + reg.size + * | | + * + */ +int wl1271_set_partition(struct wl1271 *wl, + struct wl1271_partition_set *p) +{ + /* copy partition info */ + memcpy(&wl->part, p, sizeof(*p)); + + wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", + p->mem.start, p->mem.size); + wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", + p->reg.start, p->reg.size); + wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", + p->mem2.start, p->mem2.size); + wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", + p->mem3.start, p->mem3.size); + + /* write partition info to the chipset */ + wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); + wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); + wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); + wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); + wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); + wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); + wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); + + return 0; +} + +void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + wl1271_spi_raw_write(wl, addr, buf, len, fixed); +} + +void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + wl1271_spi_read(wl, addr, buf, len, fixed); +} + +void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed) +{ + int physical; + + physical = wl1271_translate_addr(wl, addr); + + wl1271_spi_raw_read(wl, physical, buf, len, fixed); +} + +void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed) +{ + int physical; + + physical = wl1271_translate_addr(wl, addr); + + wl1271_spi_raw_write(wl, physical, buf, len, fixed); +} + +u32 wl1271_spi_read32(struct wl1271 *wl, int addr) +{ + return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); +} + +void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) +{ + wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); +} + +void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) +{ + /* write address >> 1 + 0x30000 to OCP_POR_CTR */ + addr = (addr >> 1) + 0x30000; + wl1271_spi_write32(wl, OCP_POR_CTR, addr); + + /* write value to OCP_POR_WDATA */ + wl1271_spi_write32(wl, OCP_DATA_WRITE, val); + + /* write 1 to OCP_CMD */ + wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); +} + +u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) +{ + u32 val; + int timeout = OCP_CMD_LOOP; + + /* write address >> 1 + 0x30000 to OCP_POR_CTR */ + addr = (addr >> 1) + 0x30000; + wl1271_spi_write32(wl, OCP_POR_CTR, addr); + + /* write 2 to OCP_CMD */ + wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); + + /* poll for data ready */ + do { + val = wl1271_spi_read32(wl, OCP_DATA_READ); + } while (!(val & OCP_READY_MASK) && --timeout); + + if (!timeout) { + wl1271_warning("Top register access timed out."); + return 0xffff; + } + + /* check data status and return if OK */ + if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) + return val & 0xffff; + else { + wl1271_warning("Top register access returned error."); + return 0xffff; + } +} + diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h new file mode 100644 index 000000000000..2dc6abbe4dd5 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -0,0 +1,37 @@ +/* + * This file is part of wl1271 + * + * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. + * Copyright (C) 2008-2010 Nokia Corporation + * + * Contact: Luciano Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __WL1271_IO_H__ +#define __WL1271_IO_H__ + +struct wl1271; + + +/* Raw target IO, address is not translated */ +void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed); +void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed); + +#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index ee9564aa6ecc..67a82934f36e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c @@ -30,28 +30,6 @@ #include "wl12xx_80211.h" #include "wl1271_spi.h" -static int wl1271_translate_addr(struct wl1271 *wl, int addr) -{ - /* - * To translate, first check to which window of addresses the - * particular address belongs. Then subtract the starting address - * of that window from the address. Then, add offset of the - * translated region. - * - * The translated regions occur next to each other in physical device - * memory, so just add the sizes of the preceeding address regions to - * get the offset to the new region. - * - * Currently, only the two first regions are addressed, and the - * assumption is that all addresses will fall into either of those - * two. - */ - if ((addr >= wl->part.reg.start) && - (addr < wl->part.reg.start + wl->part.reg.size)) - return addr - wl->part.reg.start + wl->part.mem.size; - else - return addr - wl->part.mem.start; -} void wl1271_spi_reset(struct wl1271 *wl) { @@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl) wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); } -/* Set the SPI partitions to access the chip addresses - * - * To simplify driver code, a fixed (virtual) memory map is defined for - * register and memory addresses. Because in the chipset, in different stages - * of operation, those addresses will move around, an address translation - * mechanism is required. - * - * There are four partitions (three memory and one register partition), - * which are mapped to two different areas of the hardware memory. - * - * Virtual address - * space - * - * | | - * ...+----+--> mem.start - * Physical address ... | | - * space ... | | [PART_0] - * ... | | - * 00000000 <--+----+... ...+----+--> mem.start + mem.size - * | | ... | | - * |MEM | ... | | - * | | ... | | - * mem.size <--+----+... | | {unused area) - * | | ... | | - * |REG | ... | | - * mem.size | | ... | | - * + <--+----+... ...+----+--> reg.start - * reg.size | | ... | | - * |MEM2| ... | | [PART_1] - * | | ... | | - * ...+----+--> reg.start + reg.size - * | | - * - */ -int wl1271_set_partition(struct wl1271 *wl, - struct wl1271_partition_set *p) -{ - /* copy partition info */ - memcpy(&wl->part, p, sizeof(*p)); - - wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - p->mem.start, p->mem.size); - wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - p->reg.start, p->reg.size); - wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", - p->mem2.start, p->mem2.size); - wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", - p->mem3.start, p->mem3.size); - - /* write partition info to the chipset */ - wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); - wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); - wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); - wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); - wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); - wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); - wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); - - return 0; -} - #define WL1271_BUSY_WORD_TIMEOUT 1000 /* FIXME: Check busy words, removed due to SPI bug */ @@ -338,77 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); } - -void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_addr(wl, addr); - - wl1271_spi_raw_read(wl, physical, buf, len, fixed); -} - -void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_addr(wl, addr); - - wl1271_spi_raw_write(wl, physical, buf, len, fixed); -} - -u32 wl1271_spi_read32(struct wl1271 *wl, int addr) -{ - return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); -} - -void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); -} - -void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) -{ - /* write address >> 1 + 0x30000 to OCP_POR_CTR */ - addr = (addr >> 1) + 0x30000; - wl1271_spi_write32(wl, OCP_POR_CTR, addr); - - /* write value to OCP_POR_WDATA */ - wl1271_spi_write32(wl, OCP_DATA_WRITE, val); - - /* write 1 to OCP_CMD */ - wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); -} - -u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) -{ - u32 val; - int timeout = OCP_CMD_LOOP; - - /* write address >> 1 + 0x30000 to OCP_POR_CTR */ - addr = (addr >> 1) + 0x30000; - wl1271_spi_write32(wl, OCP_POR_CTR, addr); - - /* write 2 to OCP_CMD */ - wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); - - /* poll for data ready */ - do { - val = wl1271_spi_read32(wl, OCP_DATA_READ); - } while (!(val & OCP_READY_MASK) && --timeout); - - if (!timeout) { - wl1271_warning("Top register access timed out."); - return 0xffff; - } - - /* check data status and return if OK */ - if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) - return val & 0xffff; - else { - wl1271_warning("Top register access returned error."); - return 0xffff; - } -} -- cgit v1.2.3 From 7b048c52d7283ebf07c826a45c631a6ba225c057 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Feb 2010 13:25:55 +0200 Subject: wl1271: Renamed IO functions In preparation for integration of SDIO implementation renamed some IO functions from wl1271_spi_* form to wl1271_*. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_boot.c | 70 +++++++++++++++--------------- drivers/net/wireless/wl12xx/wl1271_cmd.c | 15 ++++--- drivers/net/wireless/wl12xx/wl1271_event.c | 9 ++-- drivers/net/wireless/wl12xx/wl1271_io.c | 24 +++++----- drivers/net/wireless/wl12xx/wl1271_io.h | 29 +++++++++++++ drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++--- drivers/net/wireless/wl12xx/wl1271_ps.c | 1 + drivers/net/wireless/wl12xx/wl1271_rx.c | 11 +++-- drivers/net/wireless/wl12xx/wl1271_spi.h | 30 ------------- drivers/net/wireless/wl12xx/wl1271_tx.c | 17 ++++---- 10 files changed, 109 insertions(+), 109 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index fb3090c3ed15..2be76ee42bb9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -27,6 +27,7 @@ #include "wl1271_reg.h" #include "wl1271_boot.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #include "wl1271_event.h" static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { @@ -93,19 +94,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) u32 cpu_ctrl; /* 10.5.0 run the firmware (I) */ - cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL); + cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); /* 10.5.1 run the firmware (II) */ cpu_ctrl |= flag; - wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); + wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); } static void wl1271_boot_fw_version(struct wl1271 *wl) { struct wl1271_static_data static_data; - wl1271_spi_read(wl, wl->cmd_box_addr, - &static_data, sizeof(static_data), false); + wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), + false); strncpy(wl->chip.fw_ver, static_data.fw_version, sizeof(wl->chip.fw_ver)); @@ -164,7 +165,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, memcpy(chunk, p, CHUNK_SIZE); wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", p, addr); - wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false); + wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); chunk_num++; } @@ -175,7 +176,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, memcpy(chunk, p, fw_data_len % CHUNK_SIZE); wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", fw_data_len % CHUNK_SIZE, p, addr); - wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); + wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); kfree(chunk); return 0; @@ -256,7 +257,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "nvs burst write 0x%x: 0x%x", dest_addr, val); - wl1271_spi_write32(wl, dest_addr, val); + wl1271_write32(wl, dest_addr, val); nvs_ptr += 4; dest_addr += 4; @@ -290,7 +291,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) /* FIXME: In wl1271, we upload everything at once. No endianness handling needed here?! The ref driver doesn't do anything about it at this point */ - wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); + wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); kfree(nvs_aligned); return 0; @@ -299,9 +300,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) static void wl1271_boot_enable_interrupts(struct wl1271 *wl) { enable_irq(wl->irq); - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); - wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL); + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, + WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); + wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); } static int wl1271_boot_soft_reset(struct wl1271 *wl) @@ -310,13 +311,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) u32 boot_data; /* perform soft reset */ - wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET, - ACX_SLV_SOFT_RESET_BIT); + wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); /* SOFT_RESET is self clearing */ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); while (1) { - boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET); + boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) break; @@ -332,10 +332,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) } /* disable Rx/Tx */ - wl1271_spi_write32(wl, ENABLE, 0x0); + wl1271_write32(wl, ENABLE, 0x0); /* disable auto calibration on start*/ - wl1271_spi_write32(wl, SPARE_A2, 0xffff); + wl1271_write32(wl, SPARE_A2, 0xffff); return 0; } @@ -347,7 +347,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); - chip_id = wl1271_spi_read32(wl, CHIP_ID_B); + chip_id = wl1271_read32(wl, CHIP_ID_B); wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); @@ -360,8 +360,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) loop = 0; while (loop++ < INIT_LOOP) { udelay(INIT_LOOP_DELAY); - interrupt = wl1271_spi_read32(wl, - ACX_REG_INTERRUPT_NO_CLEAR); + interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); if (interrupt == 0xffffffff) { wl1271_error("error reading hardware complete " @@ -370,8 +369,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) } /* check that ACX_INTR_INIT_COMPLETE is enabled */ else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_INIT_COMPLETE); + wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, + WL1271_ACX_INTR_INIT_COMPLETE); break; } } @@ -383,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) } /* get hardware config command mail box */ - wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR); + wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); /* get hardware config event mail box */ - wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); + wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); /* set the working partition to its "running" mode offset */ wl1271_set_partition(wl, &part_table[PART_WORK]); @@ -459,9 +458,9 @@ int wl1271_boot(struct wl1271 *wl) wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); } - wl1271_spi_write32(wl, PLL_PARAMETERS, clk); + wl1271_write32(wl, PLL_PARAMETERS, clk); - pause = wl1271_spi_read32(wl, PLL_PARAMETERS); + pause = wl1271_read32(wl, PLL_PARAMETERS); wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); @@ -470,10 +469,10 @@ int wl1271_boot(struct wl1271 *wl) * 0x3ff (magic number ). How does * this work?! */ pause |= WU_COUNTER_PAUSE_VAL; - wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause); + wl1271_write32(wl, WU_COUNTER_PAUSE, pause); /* Continue the ELP wake up sequence */ - wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); + wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); wl1271_set_partition(wl, &part_table[PART_DRPW]); @@ -483,18 +482,18 @@ int wl1271_boot(struct wl1271 *wl) before taking DRPw out of reset */ wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); - clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START); + clk = wl1271_read32(wl, DRPW_SCRATCH_START); wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); /* 2 */ clk |= (REF_CLOCK << 1) << 4; - wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk); + wl1271_write32(wl, DRPW_SCRATCH_START, clk); wl1271_set_partition(wl, &part_table[PART_WORK]); /* Disable interrupts */ - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); ret = wl1271_boot_soft_reset(wl); if (ret < 0) @@ -509,23 +508,22 @@ int wl1271_boot(struct wl1271 *wl) * ACX_EEPROMLESS_IND_REG */ wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); - wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG, - ACX_EEPROMLESS_IND_REG); + wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); - tmp = wl1271_spi_read32(wl, CHIP_ID_B); + tmp = wl1271_read32(wl, CHIP_ID_B); wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); /* 6. read the EEPROM parameters */ - tmp = wl1271_spi_read32(wl, SCR_PAD2); + tmp = wl1271_read32(wl, SCR_PAD2); ret = wl1271_boot_write_irq_polarity(wl); if (ret < 0) goto out; /* FIXME: Need to check whether this is really what we want */ - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_ALL_EVENTS_VECTOR); + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, + WL1271_ACX_ALL_EVENTS_VECTOR); /* WL1271: The reference driver skips steps 7 to 10 (jumps directly * to upload_fw) */ diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 54b5124fc0c0..36a64e06f290 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -30,6 +30,7 @@ #include "wl1271.h" #include "wl1271_reg.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #include "wl1271_acx.h" #include "wl12xx_80211.h" #include "wl1271_cmd.h" @@ -57,13 +58,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, WARN_ON(len % 4 != 0); - wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false); + wl1271_write(wl, wl->cmd_box_addr, buf, len, false); - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); + wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); - intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { if (time_after(jiffies, timeout)) { wl1271_error("command complete timeout"); @@ -73,13 +74,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, msleep(1); - intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); + intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); } /* read back the status code of the command */ if (res_len == 0) res_len = sizeof(struct wl1271_cmd_header); - wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false); + wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); status = le16_to_cpu(cmd->status); if (status != CMD_STATUS_SUCCESS) { @@ -87,8 +88,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, ret = -EIO; } - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_CMD_COMPLETE); + wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, + WL1271_ACX_INTR_CMD_COMPLETE); out: return ret; diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 2803e700a75a..7468ef10194b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -24,6 +24,7 @@ #include "wl1271.h" #include "wl1271_reg.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #include "wl1271_event.h" #include "wl1271_ps.h" #include "wl12xx_80211.h" @@ -214,7 +215,7 @@ int wl1271_event_unmask(struct wl1271 *wl) void wl1271_event_mbox_config(struct wl1271 *wl) { - wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); + wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", @@ -232,8 +233,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) return -EINVAL; /* first we read the mbox descriptor */ - wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox, - sizeof(struct event_mailbox), false); + wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox, + sizeof(struct event_mailbox), false); /* process the descriptor */ ret = wl1271_event_process(wl, &mbox); @@ -241,7 +242,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) return ret; /* then we let the firmware know it can go on...*/ - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); + wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); return 0; } diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index dcb588b4670d..00f98bdc48f7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -124,10 +124,10 @@ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl1271_spi_read(wl, addr, buf, len, fixed); + wl1271_spi_raw_read(wl, addr, buf, len, fixed); } -void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, +void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { int physical; @@ -137,8 +137,8 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, wl1271_spi_raw_read(wl, physical, buf, len, fixed); } -void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) +void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed) { int physical; @@ -147,12 +147,12 @@ void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, wl1271_spi_raw_write(wl, physical, buf, len, fixed); } -u32 wl1271_spi_read32(struct wl1271 *wl, int addr) +u32 wl1271_read32(struct wl1271 *wl, int addr) { return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); } -void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) +void wl1271_write32(struct wl1271 *wl, int addr, u32 val) { wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); } @@ -161,13 +161,13 @@ void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) { /* write address >> 1 + 0x30000 to OCP_POR_CTR */ addr = (addr >> 1) + 0x30000; - wl1271_spi_write32(wl, OCP_POR_CTR, addr); + wl1271_write32(wl, OCP_POR_CTR, addr); /* write value to OCP_POR_WDATA */ - wl1271_spi_write32(wl, OCP_DATA_WRITE, val); + wl1271_write32(wl, OCP_DATA_WRITE, val); /* write 1 to OCP_CMD */ - wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); + wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); } u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) @@ -177,14 +177,14 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) /* write address >> 1 + 0x30000 to OCP_POR_CTR */ addr = (addr >> 1) + 0x30000; - wl1271_spi_write32(wl, OCP_POR_CTR, addr); + wl1271_write32(wl, OCP_POR_CTR, addr); /* write 2 to OCP_CMD */ - wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); + wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); /* poll for data ready */ do { - val = wl1271_spi_read32(wl, OCP_DATA_READ); + val = wl1271_read32(wl, OCP_DATA_READ); } while (!(val & OCP_READY_MASK) && --timeout); if (!timeout) { diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 2dc6abbe4dd5..859d571dc413 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -34,4 +34,33 @@ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); +/* Translated target IO */ +void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed); +void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, + bool fixed); +u32 wl1271_read32(struct wl1271 *wl, int addr); +void wl1271_write32(struct wl1271 *wl, int addr, u32 val); + +/* Top Register IO */ +void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); +u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); + +int wl1271_set_partition(struct wl1271 *wl, + struct wl1271_partition_set *p); + +static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) +{ + wl1271_raw_read(wl, addr, &wl->buffer_32, + sizeof(wl->buffer_32), false); + + return wl->buffer_32; +} + +static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) +{ + wl->buffer_32 = val; + wl1271_raw_write(wl, addr, &wl->buffer_32, + sizeof(wl->buffer_32), false); +} #endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index aa8f79c4c98a..46968958aeff 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -38,6 +38,7 @@ #include "wl12xx_80211.h" #include "wl1271_reg.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #include "wl1271_event.h" #include "wl1271_tx.h" #include "wl1271_rx.h" @@ -386,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl, u32 total = 0; int i; - wl1271_spi_read(wl, FW_STATUS_ADDR, status, - sizeof(*status), false); + wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", @@ -434,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); wl1271_fw_status(wl, wl->fw_status); intr = le32_to_cpu(wl->fw_status->intr); @@ -476,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work) } out_sleep: - wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); + wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, + WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); wl1271_ps_elp_sleep(wl); out: @@ -664,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) /* whal_FwCtrl_BootSm() */ /* 0. read chip id from CHIP_ID */ - wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B); + wl->chip.id = wl1271_read32(wl, CHIP_ID_B); /* 1. check if chip id is valid */ diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 29f670099d94..e2b1ebf096e8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -24,6 +24,7 @@ #include "wl1271_reg.h" #include "wl1271_ps.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #define WL1271_WAKEUP_TIMEOUT 500 diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index e8eee883848f..6730f5b96e76 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c @@ -26,6 +26,7 @@ #include "wl1271_reg.h" #include "wl1271_rx.h" #include "wl1271_spi.h" +#include "wl1271_io.h" static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, u32 drv_rx_counter) @@ -166,7 +167,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) } buf = skb_put(skb, length); - wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); + wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); /* the data read starts with the descriptor */ desc = (struct wl1271_rx_descriptor *) buf; @@ -210,15 +211,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) wl->rx_mem_pool_addr.addr + 4; /* Choose the block we want to read */ - wl1271_spi_write(wl, WL1271_SLV_REG_DATA, - &wl->rx_mem_pool_addr, - sizeof(wl->rx_mem_pool_addr), false); + wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, + sizeof(wl->rx_mem_pool_addr), false); wl1271_rx_handle_data(wl, buf_size); wl->rx_counter++; drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; - wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, - wl->rx_counter); + wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); } } diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h index cb7df1c56314..a803596dad4a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ b/drivers/net/wireless/wl12xx/wl1271_spi.h @@ -90,37 +90,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); -/* Translated target IO */ -void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -u32 wl1271_spi_read32(struct wl1271 *wl, int addr); -void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val); - -/* Top Register IO */ -void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); -u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); - /* INIT and RESET words */ void wl1271_spi_reset(struct wl1271 *wl); void wl1271_spi_init(struct wl1271 *wl); -int wl1271_set_partition(struct wl1271 *wl, - struct wl1271_partition_set *p); - -static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) -{ - wl1271_spi_raw_read(wl, addr, &wl->buffer_32, - sizeof(wl->buffer_32), false); - - return wl->buffer_32; -} - -static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl->buffer_32 = val; - wl1271_spi_raw_write(wl, addr, &wl->buffer_32, - sizeof(wl->buffer_32), false); -} - #endif /* __WL1271_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index f9e06385d9fe..811e739d05bf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -26,6 +26,7 @@ #include "wl1271.h" #include "wl1271_spi.h" +#include "wl1271_io.h" #include "wl1271_reg.h" #include "wl1271_ps.h" #include "wl1271_tx.h" @@ -165,11 +166,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, len = WL1271_TX_ALIGN(skb->len); /* perform a fixed address block write with the packet */ - wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); + wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); /* write packet new counter into the write access register */ wl->tx_packets_count++; - wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); + wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); desc = (struct wl1271_tx_hw_descr *) skb->data; wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", @@ -375,8 +376,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); /* read the tx results from the chipset */ - wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result), - wl->tx_res_if, sizeof(*wl->tx_res_if), false); + wl1271_read(wl, le32_to_cpu(memmap->tx_result), + wl->tx_res_if, sizeof(*wl->tx_res_if), false); /* verify that the result buffer is not getting overrun */ if (count > TX_HW_RESULT_QUEUE_LEN) { @@ -397,10 +398,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) } /* write host counter to chipset (to ack) */ - wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) + - offsetof(struct wl1271_tx_hw_res_if, - tx_result_host_counter), - le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); + wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + + offsetof(struct wl1271_tx_hw_res_if, + tx_result_host_counter), + le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); } /* caller must hold wl->mutex */ -- cgit v1.2.3 From 9b28072220d56fda3249cb7e4e164038b456414d Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Feb 2010 13:25:56 +0200 Subject: wl1271: Added IO reset and init functions Added reset and init functions to IO layer of the driver. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_io.c | 10 ++++++++++ drivers/net/wireless/wl12xx/wl1271_io.h | 2 ++ drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c index 00f98bdc48f7..5cd94d5666c2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.c +++ b/drivers/net/wireless/wl12xx/wl1271_io.c @@ -115,6 +115,16 @@ int wl1271_set_partition(struct wl1271 *wl, return 0; } +void wl1271_io_reset(struct wl1271 *wl) +{ + wl1271_spi_reset(wl); +} + +void wl1271_io_init(struct wl1271 *wl) +{ + wl1271_spi_init(wl); +} + void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h index 859d571dc413..fa9a0b35788f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_io.h +++ b/drivers/net/wireless/wl12xx/wl1271_io.h @@ -27,6 +27,8 @@ struct wl1271; +void wl1271_io_reset(struct wl1271 *wl); +void wl1271_io_init(struct wl1271 *wl); /* Raw target IO, address is not translated */ void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 46968958aeff..66fb9a0a8efa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -648,8 +648,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) msleep(WL1271_PRE_POWER_ON_SLEEP); wl1271_power_on(wl); msleep(WL1271_POWER_ON_SLEEP); - wl1271_spi_reset(wl); - wl1271_spi_init(wl); + wl1271_io_reset(wl); + wl1271_io_init(wl); /* We don't need a real memory partition here, because we only want * to use the registers at this point. */ -- cgit v1.2.3 From c332a4b8eed69a6853dbdbdf16696a45b93e2bf8 Mon Sep 17 00:00:00 2001 From: Teemu Paasikivi Date: Thu, 18 Feb 2010 13:25:57 +0200 Subject: wl1271: Added alloc and free hw functions Moved allocation and freeing of context structure of the driver to separate functions from probe and remove functions. Signed-off-by: Teemu Paasikivi Reviewed-by: Juuso Oikarinen Signed-off-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 80 ++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 66fb9a0a8efa..2a864b24291d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -2025,23 +2025,17 @@ static struct platform_device wl1271_device = { }; #define WL1271_DEFAULT_CHANNEL 0 -static int __devinit wl1271_probe(struct spi_device *spi) + +static struct ieee80211_hw *wl1271_alloc_hw(void) { - struct wl12xx_platform_data *pdata; struct ieee80211_hw *hw; struct wl1271 *wl; - int ret, i; - - pdata = spi->dev.platform_data; - if (!pdata) { - wl1271_error("no platform data"); - return -ENODEV; - } + int i; hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { wl1271_error("could not alloc ieee80211_hw"); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } wl = hw->priv; @@ -2050,8 +2044,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) INIT_LIST_HEAD(&wl->list); wl->hw = hw; - dev_set_drvdata(&spi->dev, wl); - wl->spi = spi; skb_queue_head_init(&wl->tx_queue); @@ -2078,6 +2070,54 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->state = WL1271_STATE_OFF; mutex_init(&wl->mutex); + /* Apply default driver configuration. */ + wl1271_conf_init(wl); + + return hw; +} + +int wl1271_free_hw(struct wl1271 *wl) +{ + ieee80211_unregister_hw(wl->hw); + + wl1271_debugfs_exit(wl); + + kfree(wl->target_mem_map); + vfree(wl->fw); + wl->fw = NULL; + kfree(wl->nvs); + wl->nvs = NULL; + + kfree(wl->fw_status); + kfree(wl->tx_res_if); + + ieee80211_free_hw(wl->hw); + + return 0; +} + +static int __devinit wl1271_probe(struct spi_device *spi) +{ + struct wl12xx_platform_data *pdata; + struct ieee80211_hw *hw; + struct wl1271 *wl; + int ret; + + pdata = spi->dev.platform_data; + if (!pdata) { + wl1271_error("no platform data"); + return -ENODEV; + } + + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + wl = hw->priv; + + dev_set_drvdata(&spi->dev, wl); + wl->spi = spi; + /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ spi->bits_per_word = 32; @@ -2119,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) } dev_set_drvdata(&wl1271_device.dev, wl); - /* Apply default driver configuration. */ - wl1271_conf_init(wl); - ret = wl1271_init_ieee80211(wl); if (ret) goto out_platform; @@ -2152,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi) { struct wl1271 *wl = dev_get_drvdata(&spi->dev); - ieee80211_unregister_hw(wl->hw); - - wl1271_debugfs_exit(wl); platform_device_unregister(&wl1271_device); free_irq(wl->irq, wl); - kfree(wl->target_mem_map); - vfree(wl->fw); - wl->fw = NULL; - kfree(wl->nvs); - wl->nvs = NULL; - kfree(wl->fw_status); - kfree(wl->tx_res_if); - - ieee80211_free_hw(wl->hw); + wl1271_free_hw(wl); return 0; } -- cgit v1.2.3 From 54f2d7361da09f3fc2b5407f93ad3b86df951577 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Feb 2010 21:47:51 +0200 Subject: MAINTAINERS: update Kalle's email address My nokia.com email address won't work anymore, use my private iki.fi address instead. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ea781c1cfb5a..2b4a4d2f2ece 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5863,7 +5863,7 @@ S: Maintained F: drivers/input/misc/wistron_btns.c WL1251 WIRELESS DRIVER -M: Kalle Valo +M: Kalle Valo L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git -- cgit v1.2.3 From 5c0ba62fd4b2dce08055a89600f1d834f9f0fe9e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 19 Feb 2010 01:46:36 +0100 Subject: ath9k: fix rate control fallback rate selection When selecting the tx fallback rate, rc.c used a separate variable 'nrix' for storing the next rate index, however it did not use that as reference for further rate index lowering. Because of that, it ended up reusing the same rate for multiple multi-rate retry stages, thus decreasing delivery probability under changing link conditions. This patch removes the separate (unnecessary) variable and fixes fallback the way it was intended to work. This should result in increased throughput and better link stability. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 74290137f43d..2880507f9d3f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -668,7 +668,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate *rates = tx_info->control.rates; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; __le16 fc = hdr->frame_control; - u8 try_per_rate, i = 0, rix, nrix; + u8 try_per_rate, i = 0, rix; int is_probe = 0; if (rate_control_send_low(sta, priv_sta, txrc)) @@ -688,26 +688,25 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, rate_table = sc->cur_rate_table; rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); - nrix = rix; if (is_probe) { /* set one try for probe rates. For the * probes don't enable rts */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - 1, nrix, 0); + 1, rix, 0); /* Get the next tried/allowed rate. No RTS for the next series * after the probe rate */ - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); + ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, nrix, 0); + try_per_rate, rix, 0); tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } else { /* Set the choosen rate. No RTS for first series entry. */ ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, nrix, 0); + try_per_rate, rix, 0); } /* Fill in the other rates for multirate retry */ @@ -716,10 +715,10 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, if (i + 1 == 4) try_per_rate = 8; - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); + ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); /* All other rates in the series have RTS enabled */ ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_per_rate, nrix, 1); + try_per_rate, rix, 1); } /* -- cgit v1.2.3 From 4a6547c748229ba0425713b4adeb0f2d4000da9e Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 18 Feb 2010 22:03:02 -0800 Subject: iwl3945: remove STATUS macros from header iwl3945 includes iwl-core.h in which these STATUS flags are already defined. This also removes a potential confusing definition with iwlcore using STATUS_MODE_PENDING with value 18 and iwl3945 defining (but not using) STATUS_CONF_PENDING for value 18. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 18 ------------------ drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 5913418872ec..521584b99fd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -45,8 +45,8 @@ #include "iwl-sta.h" #include "iwl-3945.h" #include "iwl-eeprom.h" -#include "iwl-helpers.h" #include "iwl-core.h" +#include "iwl-helpers.h" #include "iwl-led.h" #include "iwl-3945-led.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index db4137d9a3ab..ae94babe595b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -171,24 +171,6 @@ struct iwl3945_frame { #define SCAN_INTERVAL 100 -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_CONF_PENDING 18 - #define MAX_TID_COUNT 9 #define IWL_INVALID_RATE 0xFF diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3df488a8cf75..0e5a1ca30334 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -53,8 +53,8 @@ #include "iwl-commands.h" #include "iwl-sta.h" #include "iwl-3945.h" -#include "iwl-helpers.h" #include "iwl-core.h" +#include "iwl-helpers.h" #include "iwl-dev.h" #include "iwl-spectrum.h" -- cgit v1.2.3 From d2dfe6df755abb365aa3e2e67d88bda3cce5fd12 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 18 Feb 2010 22:03:04 -0800 Subject: iwlwifi: enable serialization of synchronous commands Until now it was only possible to have one synchronous command running at any time. If a synchronous command is in progress when a second request arrives then the second command will fail. Create a new mutex specific for this purpose to only allow one synchronous command at a time, but enable other commands to wait instead of fail if a synchronous command is in progress. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 -- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + drivers/net/wireless/iwlwifi/iwl-hcmd.c | 14 +++++++------- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4157c6c8645f..52b6beb371fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3364,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); + mutex_init(&priv->sync_cmd_mutex); /* Clear the driver's (not device's) station table */ iwl_clear_stations_table(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 530fae8cf16d..6347d4b5c22f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -603,7 +603,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); /*************** DRIVER STATUS FUNCTIONS *****/ #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ +/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ #define STATUS_INT_ENABLED 2 #define STATUS_RF_KILL_HW 3 #define STATUS_CT_KILL 4 diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 78298be0bdb6..7241fda022c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -530,8 +530,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", test_bit(STATUS_HCMD_ACTIVE, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", - test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", test_bit(STATUS_INT_ENABLED, &priv->status)); pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f81317d478ee..021c68658718 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1111,6 +1111,7 @@ struct iwl_priv { spinlock_t hcmd_lock; /* protect hcmd */ spinlock_t reg_lock; /* protect hw register access */ struct mutex mutex; + struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ /* basic pci-network driver stuff */ struct pci_dev *pci_dev; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 86783c27d97c..73681c4fefe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -164,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* A synchronous command can not have a callback set. */ BUG_ON(cmd->callback); - if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { - IWL_ERR(priv, - "Error sending %s: Already sending a host command\n", + IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", get_cmd_string(cmd->id)); - ret = -EBUSY; - goto out; - } + mutex_lock(&priv->sync_cmd_mutex); set_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", + get_cmd_string(cmd->id)); cmd_idx = iwl_enqueue_hcmd(priv, cmd); if (cmd_idx < 0) { @@ -193,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", + get_cmd_string(cmd->id)); ret = -ETIMEDOUT; goto cancel; } @@ -237,7 +237,7 @@ fail: cmd->reply_page = 0; } out: - clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); + mutex_unlock(&priv->sync_cmd_mutex); return ret; } EXPORT_SYMBOL(iwl_send_cmd_sync); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index d8c11f955e42..38655ad8f43c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1238,6 +1238,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) if (!(meta->flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", + get_cmd_string(cmd->hdr.cmd)); wake_up_interruptible(&priv->wait_command_queue); } } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0e5a1ca30334..54daa38ecba3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3847,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); + mutex_init(&priv->sync_cmd_mutex); /* Clear the driver's (not device's) station table */ iwl_clear_stations_table(priv); -- cgit v1.2.3 From d5755939e810f38c969a1d1b0effb2b75095b94e Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Thu, 18 Feb 2010 22:03:05 -0800 Subject: iwlwifi: indicate calib version for 6050 series Indicate calibration version to uCode Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-6000.c | 79 ++++++++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-csr.h | 2 +- 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 782e23a26984..c4844adff92a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -70,6 +70,14 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; } +/* Indicate calibration version to uCode. */ +static void iwl6050_set_calib_version(struct iwl_priv *priv) +{ + if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) + iwl_set_bit(priv, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); +} + /* NIC configuration for 6000 series */ static void iwl6000_nic_config(struct iwl_priv *priv) { @@ -96,6 +104,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); } /* else do nothing, uCode configured */ + if (priv->cfg->ops->lib->temp_ops.set_calib_version) + priv->cfg->ops->lib->temp_ops.set_calib_version(priv); } static struct iwl_sensitivity_ranges iwl6000_sensitivity = { @@ -277,6 +287,71 @@ static const struct iwl_ops iwl6000_ops = { .led = &iwlagn_led_ops, }; +static struct iwl_lib_ops iwl6050_lib = { + .set_hw_params = iwl6000_hw_set_hw_params, + .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, + .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, + .txq_set_sched = iwl5000_txq_set_sched, + .txq_agg_enable = iwl5000_txq_agg_enable, + .txq_agg_disable = iwl5000_txq_agg_disable, + .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, + .txq_free_tfd = iwl_hw_txq_free_tfd, + .txq_init = iwl_hw_tx_queue_init, + .rx_handler_setup = iwl5000_rx_handler_setup, + .setup_deferred_work = iwl5000_setup_deferred_work, + .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, + .load_ucode = iwl5000_load_ucode, + .dump_nic_event_log = iwl_dump_nic_event_log, + .dump_nic_error_log = iwl_dump_nic_error_log, + .dump_csr = iwl_dump_csr, + .dump_fh = iwl_dump_fh, + .init_alive_start = iwl5000_init_alive_start, + .alive_notify = iwl5000_alive_notify, + .send_tx_power = iwl5000_send_tx_power, + .update_chain_flags = iwl_update_chain_flags, + .set_channel_switch = iwl6000_hw_channel_switch, + .apm_ops = { + .init = iwl_apm_init, + .stop = iwl_apm_stop, + .config = iwl6000_nic_config, + .set_pwr_src = iwl_set_pwr_src, + }, + .eeprom_ops = { + .regulatory_bands = { + EEPROM_5000_REG_BAND_1_CHANNELS, + EEPROM_5000_REG_BAND_2_CHANNELS, + EEPROM_5000_REG_BAND_3_CHANNELS, + EEPROM_5000_REG_BAND_4_CHANNELS, + EEPROM_5000_REG_BAND_5_CHANNELS, + EEPROM_5000_REG_BAND_24_HT40_CHANNELS, + EEPROM_5000_REG_BAND_52_HT40_CHANNELS + }, + .verify_signature = iwlcore_eeprom_verify_signature, + .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, + .release_semaphore = iwlcore_eeprom_release_semaphore, + .calib_version = iwl5000_eeprom_calib_version, + .query_addr = iwl5000_eeprom_query_addr, + .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, + }, + .post_associate = iwl_post_associate, + .isr = iwl_isr_ict, + .config_ap = iwl_config_ap, + .temp_ops = { + .temperature = iwl5000_temperature, + .set_ct_kill = iwl6000_set_ct_threshold, + .set_calib_version = iwl6050_set_calib_version, + }, + .add_bcast_station = iwl_add_bcast_station, +}; + +static const struct iwl_ops iwl6050_ops = { + .ucode = &iwl5000_ucode, + .lib = &iwl6050_lib, + .hcmd = &iwl5000_hcmd, + .utils = &iwl5000_hcmd_utils, + .led = &iwlagn_led_ops, +}; + /* * "i": Internal configuration, use internal Power Amplifier */ @@ -380,7 +455,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, + .ops = &iwl6050_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, @@ -412,7 +487,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .ucode_api_max = IWL6050_UCODE_API_MAX, .ucode_api_min = IWL6050_UCODE_API_MIN, .sku = IWL_SKU_A|IWL_SKU_G, - .ops = &iwl6000_ops, + .ops = &iwl6050_ops, .eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6347d4b5c22f..3df79331039c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -117,6 +117,7 @@ struct iwl_apm_ops { struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); void (*set_ct_kill)(struct iwl_priv *priv); + void (*set_calib_version)(struct iwl_priv *priv); }; struct iwl_ucode_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 1e00720bf8b1..808b7146bead 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -369,7 +369,7 @@ #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) - +#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) /* GIO Chicken Bits (PCI Express bus link power management) */ #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) -- cgit v1.2.3 From 8a472da431998b7357e6dc562e79a3061ed56cad Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 18 Feb 2010 22:03:06 -0800 Subject: iwlwifi: separated time check for different type of force reset Use different timing duration check for different type of force reset, force reset request can come from different source and based on different reason; one type of reset request should not block other type of reset request. Adding structure to keep track of different force reset request. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 25 ++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-dev.h | 14 +++++++++++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 52b6beb371fe..c5b724eaf306 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3378,6 +3378,12 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->agg_tids_count = 0; + /* initialize force reset */ + priv->force_reset[IWL_RF_RESET].reset_duration = + IWL_DELAY_NEXT_FORCE_RF_RESET; + priv->force_reset[IWL_FW_RESET].reset_duration = + IWL_DELAY_NEXT_FORCE_FW_RELOAD; + /* Choose which receivers/antennas to use */ if (priv->cfg->ops->hcmd->set_rxon_chain) priv->cfg->ops->hcmd->set_rxon_chain(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index bd56827b8fef..55252a692de7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -3357,22 +3357,30 @@ static void iwl_force_rf_reset(struct iwl_priv *priv) return; } -#define IWL_DELAY_NEXT_FORCE_RESET (HZ*3) int iwl_force_reset(struct iwl_priv *priv, int mode) { + struct iwl_force_reset *force_reset; + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; - if (priv->last_force_reset_jiffies && - time_after(priv->last_force_reset_jiffies + - IWL_DELAY_NEXT_FORCE_RESET, jiffies)) { + if (mode >= IWL_MAX_FORCE_RESET) { + IWL_DEBUG_INFO(priv, "invalid reset request.\n"); + return -EINVAL; + } + force_reset = &priv->force_reset[mode]; + force_reset->reset_request_count++; + if (force_reset->last_force_reset_jiffies && + time_after(force_reset->last_force_reset_jiffies + + force_reset->reset_duration, jiffies)) { IWL_DEBUG_INFO(priv, "force reset rejected\n"); + force_reset->reset_reject_count++; return -EAGAIN; } - + force_reset->reset_success_count++; + force_reset->last_force_reset_jiffies = jiffies; IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); - switch (mode) { case IWL_RF_RESET: iwl_force_rf_reset(priv); @@ -3389,12 +3397,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode) clear_bit(STATUS_READY, &priv->status); queue_work(priv->workqueue, &priv->restart); break; - default: - IWL_DEBUG_INFO(priv, "invalid reset request.\n"); - return -EINVAL; } - priv->last_force_reset_jiffies = jiffies; - return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 021c68658718..7914d65a5a55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1036,9 +1036,21 @@ struct iwl_event_log { #define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200) #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) +#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) +#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) + enum iwl_reset { IWL_RF_RESET = 0, IWL_FW_RESET, + IWL_MAX_FORCE_RESET, +}; + +struct iwl_force_reset { + int reset_request_count; + int reset_success_count; + int reset_reject_count; + unsigned long reset_duration; + unsigned long last_force_reset_jiffies; }; struct iwl_priv { @@ -1076,7 +1088,7 @@ struct iwl_priv { u8 agg_tids_count; /* force reset */ - unsigned long last_force_reset_jiffies; + struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; /* we allocate array of iwl4965_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ -- cgit v1.2.3 From 528c3126a98e75f47fc9fa11b243c82a59271d0d Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 18 Feb 2010 22:03:07 -0800 Subject: iwlwifi: add debugfs to monitor force reset parameters Adding debugfs file to monitor the counters and other information related to "force_reset" request. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 34 ++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7241fda022c5..7bf44f146799 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2221,6 +2221,36 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_force_reset_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = file->private_data; + int i, pos = 0; + char buf[300]; + const size_t bufsz = sizeof(buf); + struct iwl_force_reset *force_reset; + + for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { + force_reset = &priv->force_reset[i]; + pos += scnprintf(buf + pos, bufsz - pos, + "Force reset method %d\n", i); + pos += scnprintf(buf + pos, bufsz - pos, + "\tnumber of reset request: %d\n", + force_reset->reset_request_count); + pos += scnprintf(buf + pos, bufsz - pos, + "\tnumber of reset request success: %d\n", + force_reset->reset_success_count); + pos += scnprintf(buf + pos, bufsz - pos, + "\tnumber of reset request reject: %d\n", + force_reset->reset_reject_count); + pos += scnprintf(buf + pos, bufsz - pos, + "\treset duration: %lu\n", + force_reset->reset_duration); + } + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + static ssize_t iwl_dbgfs_force_reset_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { @@ -2267,7 +2297,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); DEBUGFS_WRITE_FILE_OPS(internal_scan); DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); -DEBUGFS_WRITE_FILE_OPS(force_reset); +DEBUGFS_READ_WRITE_FILE_OPS(force_reset); /* * Create the debugfs files and directories @@ -2321,7 +2351,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); - DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR); + DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); -- cgit v1.2.3 From d8728ee919282c7b01b65cd479ec1e2a9c5d3ba8 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 19 Feb 2010 18:21:42 +0100 Subject: ath9k: fix beacon timer restart after a card reset In AP mode, ath_beacon_config_ap only restarts the timer if a TSF restart is requested. Apparently this was added, because this function unconditionally sets the flag for TSF reset. The problem with this is, that ath9k_hw_reset() clobbers the timer registers (specified in the initvals), thus effectively disabling the SWBA interrupt whenever a card reset without TSF reset is issued (happens in a few places in the code). This patch fixes ath_beacon_config_ap to only issue the TSF reset flag when necessary, but reinitialize the timer unconditionally. Tests show, that this is enough to keep the SWBA interrupt going after a call to ath_reset() Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 42171d043c31..b4a31a43a62c 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -526,16 +526,13 @@ static void ath_beacon_config_ap(struct ath_softc *sc, { u32 nexttbtt, intval; - /* Configure the timers only when the TSF has to be reset */ - - if (!(sc->sc_flags & SC_OP_TSF_RESET)) - return; - /* NB: the beacon interval is kept internally in TU's */ intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; intval /= ATH_BCBUF; /* for staggered beacons */ nexttbtt = intval; - intval |= ATH9K_BEACON_RESET_TSF; + + if (sc->sc_flags & SC_OP_TSF_RESET) + intval |= ATH9K_BEACON_RESET_TSF; /* * In AP mode we enable the beacon timers and SWBA interrupts to -- cgit v1.2.3 From ac5b4e168ebd9046a6cd066d50b3341353f2f309 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 19 Feb 2010 12:02:44 -0600 Subject: ssb: Add PCI ID 0x4322 to PHU handling Some of the N PHYs need a revision in the handling of the PMU. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/ssb/driver_chipcommon_pmu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 64abd11f6fbb..3d551245a4e2 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -332,6 +332,12 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) case 0x5354: ssb_pmu0_pllinit_r0(cc, crystalfreq); break; + case 0x4322: + if (cc->pmu.rev == 2) { + chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A); + chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); + } + break; default: ssb_printk(KERN_ERR PFX "ERROR: PLL init unknown for device %04X\n", @@ -417,6 +423,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) switch (bus->chip_id) { case 0x4312: + case 0x4322: /* We keep the default settings: * min_msk = 0xCBB * max_msk = 0x7FFFF -- cgit v1.2.3 From 3e60f8607e8072e8b554e9ccb8a4691c580adae4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 19:06:53 +0100 Subject: ar9170: convert to new station add/remove callbacks This converts ar9170 to use the new station add/remove callbacks instead of using the old sta_notify callback. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/main.c | 70 +++++++++++++++++----------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 91797cb6e0e8..8a964f130367 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2329,54 +2329,55 @@ out: return err; } -static void ar9170_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) +static int ar9170_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct ar9170 *ar = hw->priv; struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; unsigned int i; - switch (cmd) { - case STA_NOTIFY_ADD: - memset(sta_info, 0, sizeof(*sta_info)); + memset(sta_info, 0, sizeof(*sta_info)); - if (!sta->ht_cap.ht_supported) - break; + if (!sta->ht_cap.ht_supported) + return 0; - if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) - ar->global_ampdu_density = sta->ht_cap.ampdu_density; + if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) + ar->global_ampdu_density = sta->ht_cap.ampdu_density; - if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) - ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; + if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) + ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; - sta_info->agg[i].active = false; - sta_info->agg[i].ssn = 0; - sta_info->agg[i].tid = i; - INIT_LIST_HEAD(&sta_info->agg[i].list); - skb_queue_head_init(&sta_info->agg[i].queue); - } + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; + sta_info->agg[i].active = false; + sta_info->agg[i].ssn = 0; + sta_info->agg[i].tid = i; + INIT_LIST_HEAD(&sta_info->agg[i].list); + skb_queue_head_init(&sta_info->agg[i].queue); + } - sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - break; + sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - case STA_NOTIFY_REMOVE: - if (!sta->ht_cap.ht_supported) - break; + return 0; +} - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_INVALID; - skb_queue_purge(&sta_info->agg[i].queue); - } +static int ar9170_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; + unsigned int i; - break; + if (!sta->ht_cap.ht_supported) + return 0; - default: - break; + for (i = 0; i < AR9170_NUM_TID; i++) { + sta_info->agg[i].state = AR9170_TID_STATE_INVALID; + skb_queue_purge(&sta_info->agg[i].queue); } + + return 0; } static int ar9170_get_stats(struct ieee80211_hw *hw, @@ -2495,7 +2496,8 @@ static const struct ieee80211_ops ar9170_ops = { .bss_info_changed = ar9170_op_bss_info_changed, .get_tsf = ar9170_op_get_tsf, .set_key = ar9170_set_key, - .sta_notify = ar9170_sta_notify, + .sta_add = ar9170_sta_add, + .sta_remove = ar9170_sta_remove, .get_stats = ar9170_get_stats, .ampdu_action = ar9170_ampdu_action, }; -- cgit v1.2.3 From 17f6f054fec57b1bd5c8333bc40b1f3b2b7941aa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 19:06:54 +0100 Subject: p54: convert to new station add/remove callbacks This converts p54 to use the new station add/remove callbacks instead of using the old sta_notify callback. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/p54/main.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 3fe6366e567c..4f752a21495f 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -33,21 +33,29 @@ MODULE_DESCRIPTION("Softmac Prism54 common code"); MODULE_LICENSE("GPL"); MODULE_ALIAS("prism54common"); +static int p54_sta_add_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct p54_common *priv = hw->priv; + + /* + * Notify the firmware that we don't want or we don't + * need to buffer frames for this station anymore. + */ + + p54_sta_unlock(priv, sta->addr); + + return 0; +} + static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, enum sta_notify_cmd notify_cmd, struct ieee80211_sta *sta) { struct p54_common *priv = dev->priv; - switch (notify_cmd) { - case STA_NOTIFY_ADD: - case STA_NOTIFY_REMOVE: - /* - * Notify the firmware that we don't want or we don't - * need to buffer frames for this station anymore. - */ - p54_sta_unlock(priv, sta->addr); - break; + switch (notify_cmd) { case STA_NOTIFY_AWAKE: /* update the firmware's filter table */ p54_sta_unlock(priv, sta->addr); @@ -506,6 +514,8 @@ static const struct ieee80211_ops p54_ops = { .remove_interface = p54_remove_interface, .set_tim = p54_set_tim, .sta_notify = p54_sta_notify, + .sta_add = p54_sta_add_remove, + .sta_remove = p54_sta_add_remove, .set_key = p54_set_key, .config = p54_config, .bss_info_changed = p54_bss_info_changed, -- cgit v1.2.3 From 1d669cbf52a01490c14a999daa978e0fa00b494d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 19:06:55 +0100 Subject: mac80211_hwsim: convert to new station add/remove callbacks This converts mac80211_hwsim to use the new station add/remove callbacks instead of using the old sta_notify callback. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 00ffe6dd435e..6ea77e95277b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -771,23 +771,41 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, } } +static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + hwsim_check_magic(vif); + hwsim_set_sta_magic(sta); + + return 0; +} + +static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + hwsim_check_magic(vif); + hwsim_clear_sta_magic(sta); + + return 0; +} + static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { hwsim_check_magic(vif); + switch (cmd) { - case STA_NOTIFY_ADD: - hwsim_set_sta_magic(sta); - break; - case STA_NOTIFY_REMOVE: - hwsim_clear_sta_magic(sta); - break; case STA_NOTIFY_SLEEP: case STA_NOTIFY_AWAKE: /* TODO: make good use of these flags */ break; + default: + WARN(1, "Invalid sta notify: %d\n", cmd); + break; } } @@ -958,6 +976,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = .config = mac80211_hwsim_config, .configure_filter = mac80211_hwsim_configure_filter, .bss_info_changed = mac80211_hwsim_bss_info_changed, + .sta_add = mac80211_hwsim_sta_add, + .sta_remove = mac80211_hwsim_sta_remove, .sta_notify = mac80211_hwsim_sta_notify, .set_tim = mac80211_hwsim_set_tim, .conf_tx = mac80211_hwsim_conf_tx, -- cgit v1.2.3 From 4ca778605cfec53d8a689f0b57babb93b030c784 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 19:06:56 +0100 Subject: ath9k: convert to new station add/remove callbacks This converts ath9k to use the new station add/remove callbacks instead of using the old sta_notify callback. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9c8f925c2093..67ca4e5a6017 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1684,24 +1684,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, "Set HW RX filter: 0x%x\n", rfilt); } -static void ath9k_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) +static int ath9k_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - switch (cmd) { - case STA_NOTIFY_ADD: - ath_node_attach(sc, sta); - break; - case STA_NOTIFY_REMOVE: - ath_node_detach(sc, sta); - break; - default: - break; - } + ath_node_attach(sc, sta); + + return 0; +} + +static int ath9k_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath_wiphy *aphy = hw->priv; + struct ath_softc *sc = aphy->sc; + + ath_node_detach(sc, sta); + + return 0; } static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, @@ -2045,7 +2049,8 @@ struct ieee80211_ops ath9k_ops = { .remove_interface = ath9k_remove_interface, .config = ath9k_config, .configure_filter = ath9k_configure_filter, - .sta_notify = ath9k_sta_notify, + .sta_add = ath9k_sta_add, + .sta_remove = ath9k_sta_remove, .conf_tx = ath9k_conf_tx, .bss_info_changed = ath9k_bss_info_changed, .set_key = ath9k_set_key, -- cgit v1.2.3 From 8be987d73481831265d7e8c648bec838271bfd9b Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 19 Feb 2010 02:00:40 +0000 Subject: pfkey: fix SA and SP flush sequence RFC 2367 says flushing behavior should be: 1) user space -> kernel: flush 2) kernel: flush 3) kernel -> user space: flush event to ALL listeners This is not realistic today in the presence of selinux policies which may reject the flush etc. So we make the sequence become: 1) user space -> kernel: flush 2) kernel: flush 3) kernel -> user space: flush response to originater from #1 4) if there were no errors then: kernel -> user space: flush event to ALL listeners Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index 79d2c0f3c334..b3faede9a4f6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1712,6 +1712,23 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg return 0; } +static int unicast_flush_resp(struct sock *sk, struct sadb_msg *ihdr) +{ + struct sk_buff *skb; + struct sadb_msg *hdr; + + skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); + if (!skb) + return -ENOBUFS; + + hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); + memcpy(hdr, ihdr, sizeof(struct sadb_msg)); + hdr->sadb_msg_errno = (uint8_t) 0; + hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + + return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); +} + static int key_notify_sa_flush(struct km_event *c) { struct sk_buff *skb; @@ -1740,7 +1757,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd unsigned proto; struct km_event c; struct xfrm_audit audit_info; - int err; + int err, err2; proto = pfkey_satype2proto(hdr->sadb_msg_satype); if (proto == 0) @@ -1750,8 +1767,10 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); - if (err) - return err; + err2 = unicast_flush_resp(sk, hdr); + if (err || err2) + return err ? err : err2; + c.data.proto = proto; c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; @@ -2706,14 +2725,16 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg struct net *net = sock_net(sk); struct km_event c; struct xfrm_audit audit_info; - int err; + int err, err2; audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); - if (err) - return err; + err2 = unicast_flush_resp(sk, hdr); + if (err || err2) + return err ? err : err2; + c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; -- cgit v1.2.3 From 9e64cc9572b43afcbcd2d004538db435f2cd0587 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 19 Feb 2010 02:00:41 +0000 Subject: xfrm: Flushing empty SAD generates false events To see the effect make sure you have an empty SAD. On window1 "ip xfrm mon" and on window2 issue "ip xfrm state flush" You get prompt back in window2 and you see the flush event on window1. With this fix, you still get prompt on window1 but no event on window2. Thanks to Alexey Dobriyan for finding a bug in earlier version when using pfkey to do the flushing. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 5 ++++- net/xfrm/xfrm_state.c | 8 ++++++-- net/xfrm/xfrm_user.c | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index b3faede9a4f6..c269ce6094d6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1768,8 +1768,11 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); err2 = unicast_flush_resp(sk, hdr); - if (err || err2) + if (err || err2) { + if (err == -ESRCH) /* empty table - go quietly */ + err = 0; return err ? err : err2; + } c.data.proto = proto; c.seq = hdr->sadb_msg_seq; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index c9d6a5f1348d..9fa3322b2a7d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -603,13 +603,14 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) { - int i, err = 0; + int i, err = 0, cnt = 0; spin_lock_bh(&xfrm_state_lock); err = xfrm_state_flush_secctx_check(net, proto, audit_info); if (err) goto out; + err = -ESRCH; for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; @@ -626,13 +627,16 @@ restart: audit_info->sessionid, audit_info->secid); xfrm_state_put(x); + if (!err) + cnt++; spin_lock_bh(&xfrm_state_lock); goto restart; } } } - err = 0; + if (cnt) + err = 0; out: spin_unlock_bh(&xfrm_state_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 943c8712bd97..cd94a9dd1bad 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1524,8 +1524,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_state_flush(net, p->proto, &audit_info); - if (err) + if (err) { + if (err == -ESRCH) /* empty table */ + return 0; return err; + } c.data.proto = p->proto; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- cgit v1.2.3 From 2f1eb65f366b81aa3c22c31e6e8db26168777ec5 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Fri, 19 Feb 2010 02:00:42 +0000 Subject: xfrm: Flushing empty SPD generates false events To see the effect make sure you have an empty SPD. On window1 "ip xfrm mon" and on window2 issue "ip xfrm policy flush" You get prompt back in window2 and you see the flush event on window1. With this fix, you still get prompt on window1 but no event on window2. Thanks to Alexey Dobriyan for finding a bug in earlier version when using pfkey to do the flushing. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/key/af_key.c | 7 +++++-- net/xfrm/xfrm_policy.c | 13 ++++++++++--- net/xfrm/xfrm_user.c | 6 +++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index c269ce6094d6..a20d2fa88db9 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2735,8 +2735,11 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); err2 = unicast_flush_resp(sk, hdr); - if (err || err2) - return err ? err : err2; + if (err || err2) { + if (err == -ESRCH) /* empty table - old silent behavior */ + return 0; + return err; + } c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4368e7b88469..d6eb16d75243 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -771,7 +771,8 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) { - int dir, err = 0; + int dir, err = 0, cnt = 0; + struct xfrm_policy *dp; write_lock_bh(&xfrm_policy_lock); @@ -789,8 +790,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, audit_info->sessionid, @@ -809,8 +812,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, @@ -824,6 +829,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) } } + if (!cnt) + err = -ESRCH; atomic_inc(&flow_cache_genid); out: write_unlock_bh(&xfrm_policy_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index cd94a9dd1bad..ee04e6bf0e54 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1679,8 +1679,12 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_policy_flush(net, type, &audit_info); - if (err) + if (err) { + if (err == -ESRCH) /* empty table */ + return 0; return err; + } + c.data.type = type; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- cgit v1.2.3 From 91fea5858418127ad33e0060f726c62be0047eaf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 19 Feb 2010 08:48:47 +0000 Subject: net/pcmcia: convert to use netdev_for_each_mc_addr removed fill_multicast_tbl function in smc91c92_cs and do the work inline rewritten set_addresses function in xirc2ps_cs. This was kinda headache. Simulated the original and new functions and they bahave the same. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/pcmcia/axnet_cs.c | 7 ++-- drivers/net/pcmcia/fmvj18x_cs.c | 6 +-- drivers/net/pcmcia/nmclan_cs.c | 6 +-- drivers/net/pcmcia/smc91c92_cs.c | 33 +++++----------- drivers/net/pcmcia/xirc2ps_cs.c | 84 ++++++++++++++++++++++++---------------- 5 files changed, 67 insertions(+), 69 deletions(-) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 2ee57bd52a01..d90e0fcdbce1 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1625,8 +1625,7 @@ static inline void make_mc_bits(u8 *bits, struct net_device *dev) struct dev_mc_list *dmi; u32 crc; - for (dmi=dev->mc_list; dmi; dmi=dmi->next) { - + netdev_for_each_mc_addr(dmi, dev) { crc = ether_crc(ETH_ALEN, dmi->dmi_addr); /* * The 8390 uses the 6 most significant bits of the @@ -1652,7 +1651,7 @@ static void do_set_multicast_list(struct net_device *dev) if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { memset(ei_local->mcfilter, 0, 8); - if (dev->mc_list) + if (!netdev_mc_empty(dev)) make_mc_bits(ei_local->mcfilter, dev); } else { /* set to accept-all */ @@ -1668,7 +1667,7 @@ static void do_set_multicast_list(struct net_device *dev) if(dev->flags&IFF_PROMISC) outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); - else if(dev->flags&IFF_ALLMULTI || dev->mc_list) + else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR); else outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 3d573ed5f7c5..b9dc80b9d04a 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -1199,10 +1199,8 @@ static void set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { - unsigned int bit = - ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; + netdev_for_each_mc_addr(mclist, dev) { + unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit >> 3] |= (1 << (bit & 7)); } outb(2, ioaddr + RX_MODE); /* Use normal mode. */ diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index c42a31a97fa3..c717b143f11a 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -1475,8 +1475,7 @@ static void set_multicast_list(struct net_device *dev) { mace_private *lp = netdev_priv(dev); int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */ - int i; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; #ifdef PCMCIA_DEBUG { @@ -1496,9 +1495,8 @@ static void set_multicast_list(struct net_device *dev) if (num_addrs > 0) { /* Calculate multicast logical address filter */ memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN); - dmi = dmi->next; BuildLAF(lp->multicast_ladrf, adr); } } diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index d2e86b8887c8..d29c22a80a06 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1593,27 +1593,6 @@ static void smc_rx(struct net_device *dev) return; } -/*====================================================================== - - Calculate values for the hardware multicast filter hash table. - -======================================================================*/ - -static void fill_multicast_tbl(int count, struct dev_mc_list *addrs, - u_char *multicast_table) -{ - struct dev_mc_list *mc_addr; - - for (mc_addr = addrs; mc_addr && count-- > 0; mc_addr = mc_addr->next) { - u_int position = ether_crc(6, mc_addr->dmi_addr); -#ifndef final_version /* Verify multicast address. */ - if ((mc_addr->dmi_addr[0] & 1) == 0) - continue; -#endif - multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); - } -} - /*====================================================================== Set the receive mode. @@ -1639,8 +1618,16 @@ static void set_rx_mode(struct net_device *dev) rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti; else { if (!netdev_mc_empty(dev)) { - fill_multicast_tbl(netdev_mc_count(dev), dev->mc_list, - (u_char *)multicast_table); + struct dev_mc_list *mc_addr; + + netdev_for_each_mc_addr(mc_addr, dev) { + u_int position = ether_crc(6, mc_addr->dmi_addr); +#ifndef final_version /* Verify multicast address. */ + if ((mc_addr->dmi_addr[0] & 1) == 0) + continue; +#endif + multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); + } } rx_cfg_setting = RxStripCRC | RxEnable; } diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 4ace18a71152..4d1802e457be 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1364,47 +1364,63 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +struct set_address_info { + int reg_nr; + int page_nr; + int mohawk; + unsigned int ioaddr; +}; + +static void set_address(struct set_address_info *sa_info, char *addr) +{ + unsigned int ioaddr = sa_info->ioaddr; + int i; + + for (i = 0; i < 6; i++) { + if (sa_info->reg_nr > 15) { + sa_info->reg_nr = 8; + sa_info->page_nr++; + SelectPage(sa_info->page_nr); + } + if (sa_info->mohawk) + PutByte(sa_info->reg_nr++, addr[5 - i]); + else + PutByte(sa_info->reg_nr++, addr[i]); + } +} + /**************** * Set all addresses: This first one is the individual address, * the next 9 addresses are taken from the multicast list and * the rest is filled with the individual address. */ -static void -set_addresses(struct net_device *dev) +static void set_addresses(struct net_device *dev) { - unsigned int ioaddr = dev->base_addr; - local_info_t *lp = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; - unsigned char *addr; - int i,j,k,n; - - SelectPage(k=0x50); - for (i=0,j=8,n=0; ; i++, j++) { - if (i > 5) { - if (++n > 9) - break; - i = 0; - if (n > 1 && n <= netdev_mc_count(dev) && dmi) { - dmi = dmi->next; - } - } - if (j > 15) { - j = 8; - k++; - SelectPage(k); - } - - if (n && n <= netdev_mc_count(dev) && dmi) - addr = dmi->dmi_addr; - else - addr = dev->dev_addr; + unsigned int ioaddr = dev->base_addr; + local_info_t *lp = netdev_priv(dev); + struct dev_mc_list *dmi; + struct set_address_info sa_info; + int i; - if (lp->mohawk) - PutByte(j, addr[5-i]); - else - PutByte(j, addr[i]); - } - SelectPage(0); + /* + * Setup the info structure so that by first set_address call it will do + * SelectPage with the right page number. Hence these ones here. + */ + sa_info.reg_nr = 15 + 1; + sa_info.page_nr = 0x50 - 1; + sa_info.mohawk = lp->mohawk; + sa_info.ioaddr = ioaddr; + + set_address(&sa_info, dev->dev_addr); + i = 0; + netdev_for_each_mc_addr(dmi, dev) { + if (i++ == 9) + break; + set_address(&sa_info, dmi->dmi_addr); + } + while (i++ < 9) + set_address(&sa_info, dev->dev_addr); + SelectPage(0); } /**************** -- cgit v1.2.3 From 6e03718c852a7b2ce756e37ae340f4ebfec2f6f3 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Fri, 19 Feb 2010 05:00:52 +0000 Subject: greth: some driver cleanups On Fri, Feb 19, 2010 at 13:51 +0100, Jiri Pirko wrote: > > > >>@@ -1031,7 +1029,7 @@ static void greth_set_multicast_list(struct net_device *dev) > >> return; > >> } > >> > >>- if (dev->mc_count == 0) { > >>+ if (!netdev_mc_count(dev)) { > also please use netdev_mc_empty() here. Some driver cleanups: * convert to use phy_find_first/phy_direct_connect * convert to use netdev_mc_* helpers * fixed missing validate_addr hook * removed netdev_priv castings Signed-off-by: Denis Kirjanov Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/greth.c | 49 ++++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index 457da1c2383c..d2032339f6de 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -965,7 +965,7 @@ static int greth_set_mac_add(struct net_device *dev, void *p) struct greth_private *greth; struct greth_regs *regs; - greth = (struct greth_private *) netdev_priv(dev); + greth = netdev_priv(dev); regs = (struct greth_regs *) greth->regs; if (!is_valid_ether_addr(addr->sa_data)) @@ -988,20 +988,14 @@ static u32 greth_hash_get_index(__u8 *addr) static void greth_set_hash_filter(struct net_device *dev) { struct dev_mc_list *curr; - struct greth_private *greth = (struct greth_private *) netdev_priv(dev); + struct greth_private *greth = netdev_priv(dev); struct greth_regs *regs = (struct greth_regs *) greth->regs; u32 mc_filter[2]; - unsigned int i, bitnr; + unsigned int bitnr; mc_filter[0] = mc_filter[1] = 0; - curr = dev->mc_list; - - for (i = 0; i < dev->mc_count; i++, curr = curr->next) { - - if (!curr) - break; /* unexpected end of list */ - + netdev_for_each_mc_addr(curr, dev) { bitnr = greth_hash_get_index(curr->dmi_addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } @@ -1031,7 +1025,7 @@ static void greth_set_multicast_list(struct net_device *dev) return; } - if (dev->mc_count == 0) { + if (netdev_mc_empty(dev)) { cfg &= ~GRETH_CTRL_MCEN; GRETH_REGSAVE(regs->control, cfg); return; @@ -1160,6 +1154,7 @@ static struct net_device_ops greth_netdev_ops = { .ndo_stop = greth_close, .ndo_start_xmit = greth_start_xmit, .ndo_set_mac_address = greth_set_mac_add, + .ndo_validate_addr = eth_validate_addr, }; static inline int wait_for_mdio(struct greth_private *greth) @@ -1275,28 +1270,26 @@ static int greth_mdio_probe(struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct phy_device *phy = NULL; - u32 interface; - int i; + int ret; /* Find the first PHY */ - for (i = 0; i < PHY_MAX_ADDR; i++) { - if (greth->mdio->phy_map[i]) { - phy = greth->mdio->phy_map[i]; - break; - } - } + phy = phy_find_first(greth->mdio); + if (!phy) { if (netif_msg_probe(greth)) dev_err(&dev->dev, "no PHY found\n"); return -ENXIO; } - if (greth->gbit_mac) - interface = PHY_INTERFACE_MODE_GMII; - else - interface = PHY_INTERFACE_MODE_MII; - - phy = phy_connect(dev, dev_name(&phy->dev), &greth_link_change, 0, interface); + ret = phy_connect_direct(dev, phy, &greth_link_change, + 0, greth->gbit_mac ? + PHY_INTERFACE_MODE_GMII : + PHY_INTERFACE_MODE_MII); + if (ret) { + if (netif_msg_ifup(greth)) + dev_err(&dev->dev, "could not attach to PHY\n"); + return ret; + } if (greth->gbit_mac) phy->supported &= PHY_GBIT_FEATURES; @@ -1305,12 +1298,6 @@ static int greth_mdio_probe(struct net_device *dev) phy->advertising = phy->supported; - if (IS_ERR(phy)) { - if (netif_msg_ifup(greth)) - dev_err(&dev->dev, "could not attach to PHY\n"); - return PTR_ERR(phy); - } - greth->link = 0; greth->speed = 0; greth->duplex = -1; -- cgit v1.2.3 From e4fc85600b1b4b8114354846ab9594ad354882d0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 4 Feb 2010 18:57:42 +0000 Subject: mlx4: replace the dma_sync_single_range_for_cpu/device API There are only two users of the dma_sync_single_range_for_cpu/device API in mainline (mlx4 and ssb). The dma_sync_single_range_for_cpu/device API has never been documented and the dma_sync_single_for_cpu/device API also support a partial sync. This converts mlx4 to use the dma_sync_single_for_cpu/device API (preparations for the removal of the dma_sync_single_range_for_cpu/device API). Signed-off-by: FUJITA Tomonori Signed-off-by: David S. Miller --- drivers/net/mlx4/en_rx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 829b9ec9ff67..64394647dddc 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -508,11 +508,11 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, /* We are copying all relevant data to the skb - temporarily * synch buffers for the copy */ dma = be64_to_cpu(rx_desc->data[0].addr); - dma_sync_single_range_for_cpu(&mdev->pdev->dev, dma, 0, - length, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(&mdev->pdev->dev, dma, length, + DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, va, length); - dma_sync_single_range_for_device(&mdev->pdev->dev, dma, 0, - length, DMA_FROM_DEVICE); + dma_sync_single_for_device(&mdev->pdev->dev, dma, length, + DMA_FROM_DEVICE); skb->tail += length; } else { -- cgit v1.2.3 From 353176888386d9025062a12dcec08d49af10cf2c Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Fri, 19 Feb 2010 17:10:15 -0800 Subject: r8169: enable 64-bit DMA by default for PCI Express devices (v2) Currently use of 64-bit DMA is disabled in r8169 unless the user passes the use_dac module option. This is reasonable for conventional PCI devices where broken chipsets may not handle dual-address-cycle transfers properly for 32-bit slots and so this may not be safe. However, PCI Express should not have this problem and not using 64-bit DMA results in DMA transfers needlessly using the IOMMU or SWIOTLB. Set the use_dac module parameter to a new default value of -1 which results in 64-bit DMA being enabled by default for PCI Express devices only. Signed-off-by: Robert Hancock Signed-off-by: David S. Miller --- drivers/net/r8169.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 616ae5aa66aa..83965eeba456 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -187,7 +187,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); static int rx_copybreak = 200; -static int use_dac; +static int use_dac = -1; static struct { u32 msg_enable; } debug = { -1 }; @@ -511,7 +511,8 @@ MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); module_param(rx_copybreak, int, 0); MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); +MODULE_PARM_DESC(use_dac, "Enable PCI DAC. -1 defaults on for PCI Express only." +" Unsafe on 32 bit PCI slot."); module_param_named(debug, debug.msg_enable, int, 0); MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); MODULE_LICENSE("GPL"); @@ -2973,6 +2974,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *ioaddr; unsigned int i; int rc; + int this_use_dac = use_dac; if (netif_msg_drv(&debug)) { printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", @@ -3038,8 +3040,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->cp_cmd = PCIMulRW | RxChkSum; + tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (!tp->pcie_cap) + netif_info(tp, probe, dev, "no PCI Express capability\n"); + + if (this_use_dac < 0) + this_use_dac = tp->pcie_cap != 0; + if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { + this_use_dac && + !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + netif_info(tp, probe, dev, "using 64-bit DMA\n"); tp->cp_cmd |= PCIDAC; dev->features |= NETIF_F_HIGHDMA; } else { @@ -3058,10 +3069,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_res_4; } - tp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); - if (!tp->pcie_cap) - netif_info(tp, probe, dev, "no PCI Express capability\n"); - RTL_W16(IntrMask, 0x0000); /* Soft reset the chip. */ -- cgit v1.2.3 From 294aedcf875b982e2d3bd6d2d9b8124ccb163bf6 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 13:54:58 +0000 Subject: be2net: update copyright dates Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 2 +- drivers/net/benet/be_cmds.c | 2 +- drivers/net/benet/be_cmds.h | 2 +- drivers/net/benet/be_ethtool.c | 2 +- drivers/net/benet/be_hw.h | 2 +- drivers/net/benet/be_main.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 2734a41a4627..e3a466545d4e 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index d7546b450505..ee16b374e02c 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 01501dbae00a..3464924d6c28 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index dcc7f37b5428..9560d48944ab 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index bb2ae6f924db..5ffb149181ad 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 545c8417fc26..f66704460876 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or -- cgit v1.2.3 From 91992e446cadbbde1a304de6954afd715af5121e Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 13:57:12 +0000 Subject: be2net: Maintain tx and rx counters in driver For certain skews of the BE adapter, H/W Tx and Rx counters could be common for more than one interface. Add Tx and Rx counters in the adapter structure (to maintain stats on a per interfae basis). Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 2 ++ drivers/net/benet/be_main.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index e3a466545d4e..42c7a2bb844f 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -164,6 +164,7 @@ struct be_drvr_stats { ulong be_tx_jiffies; u64 be_tx_bytes; u64 be_tx_bytes_prev; + u64 be_tx_pkts; u32 be_tx_rate; u32 cache_barrier[16]; @@ -175,6 +176,7 @@ struct be_drvr_stats { ulong be_rx_jiffies; u64 be_rx_bytes; u64 be_rx_bytes_prev; + u64 be_rx_pkts; u32 be_rx_rate; /* number of non ether type II frames dropped where * frame len > length field of Mac Hdr */ diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index f66704460876..de0830e14aa5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -159,13 +159,10 @@ void netdev_stats_update(struct be_adapter *adapter) struct net_device_stats *dev_stats = &adapter->netdev->stats; struct be_erx_stats *erx_stats = &hw_stats->erx; - dev_stats->rx_packets = port_stats->rx_total_frames; - dev_stats->tx_packets = port_stats->tx_unicastframes + - port_stats->tx_multicastframes + port_stats->tx_broadcastframes; - dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | - (u64) port_stats->rx_bytes_lsd; - dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | - (u64) port_stats->tx_bytes_lsd; + dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts; + dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; + dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; + dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; /* bad pkts received */ dev_stats->rx_errors = port_stats->rx_crc_errors + @@ -322,12 +319,13 @@ static void be_tx_rate_update(struct be_adapter *adapter) } static void be_tx_stats_update(struct be_adapter *adapter, - u32 wrb_cnt, u32 copied, bool stopped) + u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) { struct be_drvr_stats *stats = drvr_stats(adapter); stats->be_tx_reqs++; stats->be_tx_wrbs += wrb_cnt; stats->be_tx_bytes += copied; + stats->be_tx_pkts += (gso_segs ? gso_segs : 1); if (stopped) stats->be_tx_stops++; } @@ -472,7 +470,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(adapter, wrb_cnt, copied, stopped); + be_tx_stats_update(adapter, wrb_cnt, copied, + skb_shinfo(skb)->gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); @@ -619,6 +618,7 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_compl++; stats->be_rx_frags += numfrags; stats->be_rx_bytes += pktsize; + stats->be_rx_pkts++; } static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) -- cgit v1.2.3 From 9772a43170854ec98b53b054bce9b6476f260d00 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 13:58:21 +0000 Subject: be2net: Bump the driver version number Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 42c7a2bb844f..be81fb2d10f7 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -32,7 +32,7 @@ #include "be_hw.h" -#define DRV_VER "2.101.346u" +#define DRV_VER "2.102.147u" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" -- cgit v1.2.3 From f66d744d23dcb7ef659612595e2c9fb2fde4e009 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 14:00:03 +0000 Subject: MAINTAINERS: Add two maintainers for be2net driver Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2c8b0d3d7128..9b0557a42a9a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4844,6 +4844,8 @@ F: drivers/scsi/be2iscsi/ SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER M: Sathya Perla M: Subbu Seetharaman +M: Sarveshwar Bandi +M: Ajit Khaparde L: netdev@vger.kernel.org W: http://www.serverengines.com S: Supported -- cgit v1.2.3 From 06c92ee6384c33dbb6e313c66272181db70abbb0 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sat, 20 Feb 2010 18:48:25 -0800 Subject: eepro: fix netdev_mc_count conversion Fix commit 4cd24eaf0 (net: use netdev_mc_count and netdev_mc_empty when appropriate) Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/eepro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 488bc13cc7e6..5f73ab22db16 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1288,7 +1288,7 @@ set_multicast_list(struct net_device *dev) short ioaddr = dev->base_addr; unsigned short mode; struct dev_mc_list *dmi=dev->mc_list; - int mc_count = mc_count; + int mc_count = netdev_mc_count(dev); if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) { -- cgit v1.2.3 From 4a6967b88af02eebeedfbb91bc09160750225bb5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Feb 2010 19:18:37 +0100 Subject: mwl8k: convert to new station add/remove callbacks This converts mwl8k to use the new station add/remove callbacks instead of using the old sta_notify callback. The new callbacks can sleep, so a lot of code can be removed now. Signed-off-by: Johannes Berg Acked-by: Lennert Buytenhek Signed-off-by: John W. Linville --- drivers/net/wireless/mwl8k.c | 106 +++++++++---------------------------------- 1 file changed, 22 insertions(+), 84 deletions(-) diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 6497c841fb21..ac65e13eb0de 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -188,10 +188,6 @@ struct mwl8k_priv { bool sniffer_enabled; bool wmm_enabled; - struct work_struct sta_notify_worker; - spinlock_t sta_notify_list_lock; - struct list_head sta_notify_list; - /* XXX need to convert this to handle multiple interfaces */ bool capture_beacon; u8 capture_bssid[ETH_ALEN]; @@ -3706,90 +3702,36 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) return mwl8k_cmd_set_rts_threshold(hw, value); } -struct mwl8k_sta_notify_item -{ - struct list_head list; - struct ieee80211_vif *vif; - enum sta_notify_cmd cmd; - struct ieee80211_sta sta; -}; - -static void -mwl8k_do_sta_notify(struct ieee80211_hw *hw, struct mwl8k_sta_notify_item *s) +static int mwl8k_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mwl8k_priv *priv = hw->priv; - /* - * STA firmware uses UPDATE_STADB, AP firmware uses SET_NEW_STN. - */ - if (!priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { - int rc; - - rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); - if (rc >= 0) { - struct ieee80211_sta *sta; - - rcu_read_lock(); - sta = ieee80211_find_sta(s->vif, s->sta.addr); - if (sta != NULL) - MWL8K_STA(sta)->peer_id = rc; - rcu_read_unlock(); - } - } else if (!priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { - mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); - } else if (priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { - mwl8k_cmd_set_new_stn_add(hw, s->vif, &s->sta); - } else if (priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { - mwl8k_cmd_set_new_stn_del(hw, s->vif, s->sta.addr); - } -} - -static void mwl8k_sta_notify_worker(struct work_struct *work) -{ - struct mwl8k_priv *priv = - container_of(work, struct mwl8k_priv, sta_notify_worker); - struct ieee80211_hw *hw = priv->hw; - - spin_lock_bh(&priv->sta_notify_list_lock); - while (!list_empty(&priv->sta_notify_list)) { - struct mwl8k_sta_notify_item *s; - - s = list_entry(priv->sta_notify_list.next, - struct mwl8k_sta_notify_item, list); - list_del(&s->list); - - spin_unlock_bh(&priv->sta_notify_list_lock); - - mwl8k_do_sta_notify(hw, s); - kfree(s); - - spin_lock_bh(&priv->sta_notify_list_lock); - } - spin_unlock_bh(&priv->sta_notify_list_lock); + if (priv->ap_fw) + return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr); + else + return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr); } -static void -mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, struct ieee80211_sta *sta) +static int mwl8k_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { struct mwl8k_priv *priv = hw->priv; - struct mwl8k_sta_notify_item *s; - - if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE) - return; - - s = kmalloc(sizeof(*s), GFP_ATOMIC); - if (s != NULL) { - s->vif = vif; - s->cmd = cmd; - s->sta = *sta; + int ret; - spin_lock_bh(&priv->sta_notify_list_lock); - list_add_tail(&s->list, &priv->sta_notify_list); - spin_unlock_bh(&priv->sta_notify_list_lock); + if (!priv->ap_fw) { + ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); + if (ret >= 0) { + MWL8K_STA(sta)->peer_id = ret; + return 0; + } - ieee80211_queue_work(hw, &priv->sta_notify_worker); + return ret; } + + return mwl8k_cmd_set_new_stn_add(hw, vif, sta); } static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, @@ -3849,7 +3791,8 @@ static const struct ieee80211_ops mwl8k_ops = { .prepare_multicast = mwl8k_prepare_multicast, .configure_filter = mwl8k_configure_filter, .set_rts_threshold = mwl8k_set_rts_threshold, - .sta_notify = mwl8k_sta_notify, + .sta_add = mwl8k_sta_add, + .sta_remove = mwl8k_sta_remove, .conf_tx = mwl8k_conf_tx, .get_stats = mwl8k_get_stats, .ampdu_action = mwl8k_ampdu_action, @@ -4051,11 +3994,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->radio_on = 0; priv->radio_short_preamble = 0; - /* Station database handling */ - INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker); - spin_lock_init(&priv->sta_notify_list_lock); - INIT_LIST_HEAD(&priv->sta_notify_list); - /* Finalize join worker */ INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); -- cgit v1.2.3 From 3c945e5b3719bcc18c6ddd31bbcae8ef94f3d19a Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Fri, 19 Feb 2010 17:44:42 +0000 Subject: ixgbe: prevent speculative processing of descriptors before ready The PowerPC architecture does not require loads to independent bytes to be ordered without adding an explicit barrier. In ixgbe_clean_rx_irq we load the status bit then load the packet data. With packet split disabled if these loads go out of order we get a stale packet, but we will notice the bad sequence numbers and drop it. The problem occurs with packet split enabled where the TCP/IP header and data are in different descriptors. If the reads go out of order we may have data that doesn't match the TCP/IP header. Since we use hardware checksumming this bad data is never verified and it makes it all the way to the application. This bug was found during stress testing and adding this barrier has been shown to fix it. Signed-off-by: Milton Miller Signed-off-by: Anton Blanchard Acked-by: Don Skidmore Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 43a8de3dc4d6..330879004ea1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -849,6 +849,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, break; (*work_done)++; + rmb(); /* read descriptor and rx_buffer_info after status DD */ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) { hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc)); len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >> -- cgit v1.2.3 From 7a0deb6bcda98c2a764cb87f1441eef920fd3663 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 19 Feb 2010 17:57:46 +0000 Subject: pci: add support for 82576NS serdes to existing SR-IOV quirk This patch adds support for the 82576NS Serdes adapter to the existing pci quirk for 82576 parts. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d58b94030ef3..456c265b1fe9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2534,6 +2534,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); #endif /* CONFIG_PCI_IOV */ -- cgit v1.2.3 From 8850dce170b460d9e46a827a62d6d7bb7e7cfcf3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 20 Feb 2010 10:55:25 +0000 Subject: b44: Set PHY address to NO_PHY if reset fails. Do a PHY reset to test if there is an active phy and set the PHY address to B44_PHY_ADDR_NO_PHY in case of an not active phy. This is needed for the Linksys WRTSL54GS and Asus WL-500W. This patch was used in OpenWRT for a long time. Signed-off-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/b44.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 180510ed92a5..71fa0bee8d36 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -338,7 +338,7 @@ static int b44_phy_reset(struct b44 *bp) } } - return 0; + return err; } static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags) @@ -2215,6 +2215,10 @@ static int __devinit b44_init_one(struct ssb_device *sdev, */ b44_chip_reset(bp, B44_CHIP_RESET_FULL); + /* do a phy reset to test if there is an active phy */ + if (b44_phy_reset(bp) < 0) + bp->phy_addr = B44_PHY_ADDR_NO_PHY; + netdev_info(dev, "Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n", dev->dev_addr); -- cgit v1.2.3 From 53639207c032ec63dac3661af94447f9774cd40b Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 20 Feb 2010 10:55:26 +0000 Subject: b44: use netdev_alloc_skb instead of dev_alloc_skb The conversion in bf0dcbd929faf036f1a4f2918090344d0e249cf5 missed the new allocation in b44_rx. This patch was used in OpenWRT for a long time. Signed-off-by: Hauke Mehrtens Signed-off-by: David S. Miller --- drivers/net/b44.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 71fa0bee8d36..bcb6a029a0a8 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -809,7 +809,7 @@ static int b44_rx(struct b44 *bp, int budget) struct sk_buff *copy_skb; b44_recycle_rx(bp, cons, bp->rx_prod); - copy_skb = dev_alloc_skb(len + 2); + copy_skb = netdev_alloc_skb(bp->dev, len + 2); if (copy_skb == NULL) goto drop_it_no_recycle; -- cgit v1.2.3 From 0bc88e4af07621bc4b84477374745d01a470e85d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 21 Feb 2010 17:08:47 +0000 Subject: drivers/net/typhoon.c: Use (pr|netdev)_ macro helpers David Dillow took my suggestions and improved on them. Here is this latest version. Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt Remove #define PFX Remove #define ERR_PFX Remove now unused member name from struct typhoon Use pr_ Use netdev_ Coalesce long formats Remove version information Signed-off-by: Joe Perches Signed-off-by: David Dillow Signed-off-by: Joe Perches Acked-by: David Dillow Signed-off-by: David S. Miller --- drivers/net/typhoon.c | 243 ++++++++++++++++++++------------------------------ 1 file changed, 96 insertions(+), 147 deletions(-) diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index edabc49a49bc..38c216132ef5 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -98,14 +98,10 @@ static const int multicast_filter_limit = 32; #define TX_TIMEOUT (2*HZ) #define PKT_BUF_SZ 1536 - -#define DRV_MODULE_NAME "typhoon" -#define DRV_MODULE_VERSION "1.5.9" -#define DRV_MODULE_RELDATE "Mar 2, 2009" -#define PFX DRV_MODULE_NAME ": " -#define ERR_PFX KERN_ERR PFX #define FIRMWARE_NAME "3com/typhoon.bin" +#define pr_fmt(fmt) KBUILD_MODNAME " " fmt + #include #include #include @@ -132,14 +128,12 @@ static const int multicast_filter_limit = 32; #include #include #include +#include #include "typhoon.h" -static char version[] __devinitdata = - "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; - MODULE_AUTHOR("David Dillow "); -MODULE_VERSION(DRV_MODULE_VERSION); +MODULE_VERSION(UTS_RELEASE); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(FIRMWARE_NAME); MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)"); @@ -161,8 +155,8 @@ module_param(use_mmio, int, 0); #endif struct typhoon_card_info { - char *name; - int capabilities; + const char *name; + const int capabilities; }; #define TYPHOON_CRYPTO_NONE 0x00 @@ -299,7 +293,6 @@ struct typhoon { struct basic_ring respRing; struct net_device_stats stats; struct net_device_stats stats_saved; - const char * name; struct typhoon_shared * shared; dma_addr_t shared_dma; __le16 xcvr_select; @@ -534,13 +527,13 @@ typhoon_process_response(struct typhoon *tp, int resp_size, } else if(resp->cmd == TYPHOON_CMD_HELLO_RESP) { typhoon_hello(tp); } else { - printk(KERN_ERR "%s: dumping unexpected response " - "0x%04x:%d:0x%02x:0x%04x:%08x:%08x\n", - tp->name, le16_to_cpu(resp->cmd), - resp->numDesc, resp->flags, - le16_to_cpu(resp->parm1), - le32_to_cpu(resp->parm2), - le32_to_cpu(resp->parm3)); + netdev_err(tp->dev, + "dumping unexpected response 0x%04x:%d:0x%02x:0x%04x:%08x:%08x\n", + le16_to_cpu(resp->cmd), + resp->numDesc, resp->flags, + le16_to_cpu(resp->parm1), + le32_to_cpu(resp->parm2), + le32_to_cpu(resp->parm3)); } cleanup: @@ -606,9 +599,8 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd, freeResp = typhoon_num_free_resp(tp); if(freeCmd < num_cmd || freeResp < num_resp) { - printk("%s: no descs for cmd, had (needed) %d (%d) cmd, " - "%d (%d) resp\n", tp->name, freeCmd, num_cmd, - freeResp, num_resp); + netdev_err(tp->dev, "no descs for cmd, had (needed) %d (%d) cmd, %d (%d) resp\n", + freeCmd, num_cmd, freeResp, num_resp); err = -ENOMEM; goto out; } @@ -733,7 +725,7 @@ typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) spin_unlock_bh(&tp->state_lock); err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) - printk("%s: vlan offload error %d\n", tp->name, -err); + netdev_err(tp->dev, "vlan offload error %d\n", -err); spin_lock_bh(&tp->state_lock); } @@ -1021,7 +1013,7 @@ typhoon_get_stats(struct net_device *dev) return saved; if(typhoon_do_get_stats(tp) < 0) { - printk(KERN_ERR "%s: error getting stats\n", dev->name); + netdev_err(dev, "error getting stats\n"); return saved; } @@ -1063,8 +1055,8 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) } } - strcpy(info->driver, DRV_MODULE_NAME); - strcpy(info->version, DRV_MODULE_VERSION); + strcpy(info->driver, KBUILD_MODNAME); + strcpy(info->version, UTS_RELEASE); strcpy(info->bus_info, pci_name(pci_dev)); } @@ -1366,8 +1358,8 @@ typhoon_request_firmware(struct typhoon *tp) err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev); if (err) { - printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", - tp->name, FIRMWARE_NAME); + netdev_err(tp->dev, "Failed to load firmware \"%s\"\n", + FIRMWARE_NAME); return err; } @@ -1402,7 +1394,7 @@ typhoon_request_firmware(struct typhoon *tp) return 0; invalid_fw: - printk(KERN_ERR "%s: Invalid firmware image\n", tp->name); + netdev_err(tp->dev, "Invalid firmware image\n"); release_firmware(typhoon_fw); typhoon_fw = NULL; return -EINVAL; @@ -1439,7 +1431,7 @@ typhoon_download_firmware(struct typhoon *tp) err = -ENOMEM; dpage = pci_alloc_consistent(pdev, PAGE_SIZE, &dpage_dma); if(!dpage) { - printk(KERN_ERR "%s: no DMA mem for firmware\n", tp->name); + netdev_err(tp->dev, "no DMA mem for firmware\n"); goto err_out; } @@ -1452,7 +1444,7 @@ typhoon_download_firmware(struct typhoon *tp) err = -ETIMEDOUT; if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { - printk(KERN_ERR "%s: card ready timeout\n", tp->name); + netdev_err(tp->dev, "card ready timeout\n"); goto err_out_irq; } @@ -1492,8 +1484,7 @@ typhoon_download_firmware(struct typhoon *tp) if(typhoon_wait_interrupt(ioaddr) < 0 || ioread32(ioaddr + TYPHOON_REG_STATUS) != TYPHOON_STATUS_WAITING_FOR_SEGMENT) { - printk(KERN_ERR "%s: segment ready timeout\n", - tp->name); + netdev_err(tp->dev, "segment ready timeout\n"); goto err_out_irq; } @@ -1503,8 +1494,8 @@ typhoon_download_firmware(struct typhoon *tp) * the checksum, we can do this once, at the end. */ csum = csum_fold(csum_partial_copy_nocheck(image_data, - dpage, len, - 0)); + dpage, len, + 0)); iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH); iowrite32(le16_to_cpu((__force __le16)csum), @@ -1515,7 +1506,7 @@ typhoon_download_firmware(struct typhoon *tp) iowrite32(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO); typhoon_post_pci_writes(ioaddr); iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE, - ioaddr + TYPHOON_REG_COMMAND); + ioaddr + TYPHOON_REG_COMMAND); image_data += len; load_addr += len; @@ -1526,15 +1517,15 @@ typhoon_download_firmware(struct typhoon *tp) if(typhoon_wait_interrupt(ioaddr) < 0 || ioread32(ioaddr + TYPHOON_REG_STATUS) != TYPHOON_STATUS_WAITING_FOR_SEGMENT) { - printk(KERN_ERR "%s: final segment ready timeout\n", tp->name); + netdev_err(tp->dev, "final segment ready timeout\n"); goto err_out_irq; } iowrite32(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND); if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) { - printk(KERN_ERR "%s: boot ready timeout, status 0x%0x\n", - tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS)); + netdev_err(tp->dev, "boot ready timeout, status 0x%0x\n", + ioread32(ioaddr + TYPHOON_REG_STATUS)); goto err_out_irq; } @@ -1556,7 +1547,7 @@ typhoon_boot_3XP(struct typhoon *tp, u32 initial_status) void __iomem *ioaddr = tp->ioaddr; if(typhoon_wait_status(ioaddr, initial_status) < 0) { - printk(KERN_ERR "%s: boot ready timeout\n", tp->name); + netdev_err(tp->dev, "boot ready timeout\n"); goto out_timeout; } @@ -1567,8 +1558,8 @@ typhoon_boot_3XP(struct typhoon *tp, u32 initial_status) ioaddr + TYPHOON_REG_COMMAND); if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) { - printk(KERN_ERR "%s: boot finish timeout (status 0x%x)\n", - tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS)); + netdev_err(tp->dev, "boot finish timeout (status 0x%x)\n", + ioread32(ioaddr + TYPHOON_REG_STATUS)); goto out_timeout; } @@ -1867,8 +1858,7 @@ typhoon_interrupt(int irq, void *dev_instance) typhoon_post_pci_writes(ioaddr); __napi_schedule(&tp->napi); } else { - printk(KERN_ERR "%s: Error, poll already scheduled\n", - dev->name); + netdev_err(dev, "Error, poll already scheduled\n"); } return IRQ_HANDLED; } @@ -1901,16 +1891,15 @@ typhoon_sleep(struct typhoon *tp, pci_power_t state, __le16 events) xp_cmd.parm1 = events; err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) { - printk(KERN_ERR "%s: typhoon_sleep(): wake events cmd err %d\n", - tp->name, err); + netdev_err(tp->dev, "typhoon_sleep(): wake events cmd err %d\n", + err); return err; } INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_GOTO_SLEEP); err = typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(err < 0) { - printk(KERN_ERR "%s: typhoon_sleep(): sleep cmd err %d\n", - tp->name, err); + netdev_err(tp->dev, "typhoon_sleep(): sleep cmd err %d\n", err); return err; } @@ -1961,12 +1950,12 @@ typhoon_start_runtime(struct typhoon *tp) err = typhoon_download_firmware(tp); if(err < 0) { - printk("%s: cannot load runtime on 3XP\n", tp->name); + netdev_err(tp->dev, "cannot load runtime on 3XP\n"); goto error_out; } if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) { - printk("%s: cannot boot 3XP\n", tp->name); + netdev_err(tp->dev, "cannot boot 3XP\n"); err = -EIO; goto error_out; } @@ -2070,9 +2059,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type) } if(i == TYPHOON_WAIT_TIMEOUT) - printk(KERN_ERR - "%s: halt timed out waiting for Tx to complete\n", - tp->name); + netdev_err(tp->dev, "halt timed out waiting for Tx to complete\n"); INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_TX_DISABLE); typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); @@ -2089,11 +2076,10 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type) typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL); if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_HALTED) < 0) - printk(KERN_ERR "%s: timed out waiting for 3XP to halt\n", - tp->name); + netdev_err(tp->dev, "timed out waiting for 3XP to halt\n"); if(typhoon_reset(ioaddr, wait_type) < 0) { - printk(KERN_ERR "%s: unable to reset 3XP\n", tp->name); + netdev_err(tp->dev, "unable to reset 3XP\n"); return -ETIMEDOUT; } @@ -2112,8 +2098,7 @@ typhoon_tx_timeout(struct net_device *dev) struct typhoon *tp = netdev_priv(dev); if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) { - printk(KERN_WARNING "%s: could not reset in tx timeout\n", - dev->name); + netdev_warn(dev, "could not reset in tx timeout\n"); goto truely_dead; } @@ -2122,8 +2107,7 @@ typhoon_tx_timeout(struct net_device *dev) typhoon_free_rx_rings(tp); if(typhoon_start_runtime(tp) < 0) { - printk(KERN_ERR "%s: could not start runtime in tx timeout\n", - dev->name); + netdev_err(dev, "could not start runtime in tx timeout\n"); goto truely_dead; } @@ -2148,7 +2132,7 @@ typhoon_open(struct net_device *dev) err = typhoon_wakeup(tp, WaitSleep); if(err < 0) { - printk(KERN_ERR "%s: unable to wakeup device\n", dev->name); + netdev_err(dev, "unable to wakeup device\n"); goto out_sleep; } @@ -2173,14 +2157,13 @@ out_irq: out_sleep: if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { - printk(KERN_ERR "%s: unable to reboot into sleep img\n", - dev->name); + netdev_err(dev, "unable to reboot into sleep img\n"); typhoon_reset(tp->ioaddr, NoWait); goto out; } if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) - printk(KERN_ERR "%s: unable to go back to sleep\n", dev->name); + netdev_err(dev, "unable to go back to sleep\n"); out: return err; @@ -2195,7 +2178,7 @@ typhoon_close(struct net_device *dev) napi_disable(&tp->napi); if(typhoon_stop_runtime(tp, WaitSleep) < 0) - printk(KERN_ERR "%s: unable to stop runtime\n", dev->name); + netdev_err(dev, "unable to stop runtime\n"); /* Make sure there is no irq handler running on a different CPU. */ free_irq(dev->irq, dev); @@ -2204,10 +2187,10 @@ typhoon_close(struct net_device *dev) typhoon_init_rings(tp); if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) - printk(KERN_ERR "%s: unable to boot sleep image\n", dev->name); + netdev_err(dev, "unable to boot sleep image\n"); if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) - printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name); + netdev_err(dev, "unable to put card to sleep\n"); return 0; } @@ -2225,14 +2208,12 @@ typhoon_resume(struct pci_dev *pdev) return 0; if(typhoon_wakeup(tp, WaitNoSleep) < 0) { - printk(KERN_ERR "%s: critical: could not wake up in resume\n", - dev->name); + netdev_err(dev, "critical: could not wake up in resume\n"); goto reset; } if(typhoon_start_runtime(tp) < 0) { - printk(KERN_ERR "%s: critical: could not start runtime in " - "resume\n", dev->name); + netdev_err(dev, "critical: could not start runtime in resume\n"); goto reset; } @@ -2259,8 +2240,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) spin_lock_bh(&tp->state_lock); if(tp->vlgrp && tp->wol_events & TYPHOON_WAKE_MAGIC_PKT) { spin_unlock_bh(&tp->state_lock); - printk(KERN_ERR "%s: cannot do WAKE_MAGIC with VLANS\n", - dev->name); + netdev_err(dev, "cannot do WAKE_MAGIC with VLANS\n"); return -EBUSY; } spin_unlock_bh(&tp->state_lock); @@ -2268,7 +2248,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(dev); if(typhoon_stop_runtime(tp, WaitNoSleep) < 0) { - printk(KERN_ERR "%s: unable to stop runtime\n", dev->name); + netdev_err(dev, "unable to stop runtime\n"); goto need_resume; } @@ -2276,7 +2256,7 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) typhoon_init_rings(tp); if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { - printk(KERN_ERR "%s: unable to boot sleep image\n", dev->name); + netdev_err(dev, "unable to boot sleep image\n"); goto need_resume; } @@ -2284,21 +2264,19 @@ typhoon_suspend(struct pci_dev *pdev, pm_message_t state) xp_cmd.parm1 = cpu_to_le16(ntohs(*(__be16 *)&dev->dev_addr[0])); xp_cmd.parm2 = cpu_to_le32(ntohl(*(__be32 *)&dev->dev_addr[2])); if(typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL) < 0) { - printk(KERN_ERR "%s: unable to set mac address in suspend\n", - dev->name); + netdev_err(dev, "unable to set mac address in suspend\n"); goto need_resume; } INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_SET_RX_FILTER); xp_cmd.parm1 = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST; if(typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL) < 0) { - printk(KERN_ERR "%s: unable to set rx filter in suspend\n", - dev->name); + netdev_err(dev, "unable to set rx filter in suspend\n"); goto need_resume; } if(typhoon_sleep(tp, pci_choose_state(pdev, state), tp->wol_events) < 0) { - printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name); + netdev_err(dev, "unable to put card to sleep\n"); goto need_resume; } @@ -2352,7 +2330,7 @@ out_unmap: out: if(!mode) - printk(KERN_INFO PFX "falling back to port IO\n"); + pr_info("%s: falling back to port IO\n", pci_name(pdev)); return mode; } @@ -2372,7 +2350,6 @@ static const struct net_device_ops typhoon_netdev_ops = { static int __devinit typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int did_version = 0; struct net_device *dev; struct typhoon *tp; int card_id = (int) ent->driver_data; @@ -2382,14 +2359,11 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct cmd_desc xp_cmd; struct resp_desc xp_resp[3]; int err = 0; - - if(!did_version++) - printk(KERN_INFO "%s", version); + const char *err_msg; dev = alloc_etherdev(sizeof(*tp)); if(dev == NULL) { - printk(ERR_PFX "%s: unable to alloc new net device\n", - pci_name(pdev)); + err_msg = "unable to alloc new net device"; err = -ENOMEM; goto error_out; } @@ -2397,57 +2371,48 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = pci_enable_device(pdev); if(err < 0) { - printk(ERR_PFX "%s: unable to enable device\n", - pci_name(pdev)); + err_msg = "unable to enable device"; goto error_out_dev; } err = pci_set_mwi(pdev); if(err < 0) { - printk(ERR_PFX "%s: unable to set MWI\n", pci_name(pdev)); + err_msg = "unable to set MWI"; goto error_out_disable; } err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if(err < 0) { - printk(ERR_PFX "%s: No usable DMA configuration\n", - pci_name(pdev)); + err_msg = "No usable DMA configuration"; goto error_out_mwi; } /* sanity checks on IO and MMIO BARs */ if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) { - printk(ERR_PFX - "%s: region #1 not a PCI IO resource, aborting\n", - pci_name(pdev)); + err_msg = "region #1 not a PCI IO resource, aborting"; err = -ENODEV; goto error_out_mwi; } if(pci_resource_len(pdev, 0) < 128) { - printk(ERR_PFX "%s: Invalid PCI IO region size, aborting\n", - pci_name(pdev)); + err_msg = "Invalid PCI IO region size, aborting"; err = -ENODEV; goto error_out_mwi; } if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { - printk(ERR_PFX - "%s: region #1 not a PCI MMIO resource, aborting\n", - pci_name(pdev)); + err_msg = "region #1 not a PCI MMIO resource, aborting"; err = -ENODEV; goto error_out_mwi; } if(pci_resource_len(pdev, 1) < 128) { - printk(ERR_PFX "%s: Invalid PCI MMIO region size, aborting\n", - pci_name(pdev)); + err_msg = "Invalid PCI MMIO region size, aborting"; err = -ENODEV; goto error_out_mwi; } - err = pci_request_regions(pdev, "typhoon"); + err = pci_request_regions(pdev, KBUILD_MODNAME); if(err < 0) { - printk(ERR_PFX "%s: could not request regions\n", - pci_name(pdev)); + err_msg = "could not request regions"; goto error_out_mwi; } @@ -2458,8 +2423,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ioaddr = pci_iomap(pdev, use_mmio, 128); if (!ioaddr) { - printk(ERR_PFX "%s: cannot remap registers, aborting\n", - pci_name(pdev)); + err_msg = "cannot remap registers, aborting"; err = -EIO; goto error_out_regions; } @@ -2469,8 +2433,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) shared = pci_alloc_consistent(pdev, sizeof(struct typhoon_shared), &shared_dma); if(!shared) { - printk(ERR_PFX "%s: could not allocate DMA memory\n", - pci_name(pdev)); + err_msg = "could not allocate DMA memory"; err = -ENOMEM; goto error_out_remap; } @@ -2493,7 +2456,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * 5) Put the card to sleep. */ if (typhoon_reset(ioaddr, WaitSleep) < 0) { - printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev)); + err_msg = "could not reset 3XP"; err = -EIO; goto error_out_dma; } @@ -2505,26 +2468,18 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); pci_save_state(pdev); - /* dev->name is not valid until we register, but we need to - * use some common routines to initialize the card. So that those - * routines print the right name, we keep our oun pointer to the name - */ - tp->name = pci_name(pdev); - typhoon_init_interface(tp); typhoon_init_rings(tp); if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) { - printk(ERR_PFX "%s: cannot boot 3XP sleep image\n", - pci_name(pdev)); + err_msg = "cannot boot 3XP sleep image"; err = -EIO; goto error_out_reset; } INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_MAC_ADDRESS); if(typhoon_issue_command(tp, 1, &xp_cmd, 1, xp_resp) < 0) { - printk(ERR_PFX "%s: cannot read MAC address\n", - pci_name(pdev)); + err_msg = "cannot read MAC address"; err = -EIO; goto error_out_reset; } @@ -2533,8 +2488,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) *(__be32 *)&dev->dev_addr[2] = htonl(le32_to_cpu(xp_resp[0].parm2)); if(!is_valid_ether_addr(dev->dev_addr)) { - printk(ERR_PFX "%s: Could not obtain valid ethernet address, " - "aborting\n", pci_name(pdev)); + err_msg = "Could not obtain valid ethernet address, aborting"; goto error_out_reset; } @@ -2543,8 +2497,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) */ INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS); if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) { - printk(ERR_PFX "%s: Could not get Sleep Image version\n", - pci_name(pdev)); + err_msg = "Could not get Sleep Image version"; goto error_out_reset; } @@ -2561,8 +2514,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET; if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) { - printk(ERR_PFX "%s: cannot put adapter to sleep\n", - pci_name(pdev)); + err_msg = "cannot put adapter to sleep"; err = -EIO; goto error_out_reset; } @@ -2581,19 +2533,18 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; dev->features |= NETIF_F_TSO; - if(register_netdev(dev) < 0) + if(register_netdev(dev) < 0) { + err_msg = "unable to register netdev"; goto error_out_reset; - - /* fixup our local name */ - tp->name = dev->name; + } pci_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: %s at %s 0x%llx, %pM\n", - dev->name, typhoon_card_info[card_id].name, - use_mmio ? "MMIO" : "IO", - (unsigned long long)pci_resource_start(pdev, use_mmio), - dev->dev_addr); + netdev_info(dev, "%s at %s 0x%llx, %pM\n", + typhoon_card_info[card_id].name, + use_mmio ? "MMIO" : "IO", + (unsigned long long)pci_resource_start(pdev, use_mmio), + dev->dev_addr); /* xp_resp still contains the response to the READ_VERSIONS command. * For debugging, let the user know what version he has. @@ -2603,23 +2554,20 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) * of version is Month/Day of build. */ u16 monthday = le32_to_cpu(xp_resp[0].parm2) & 0xffff; - printk(KERN_INFO "%s: Typhoon 1.0 Sleep Image built " - "%02u/%02u/2000\n", dev->name, monthday >> 8, - monthday & 0xff); + netdev_info(dev, "Typhoon 1.0 Sleep Image built %02u/%02u/2000\n", + monthday >> 8, monthday & 0xff); } else if(xp_resp[0].numDesc == 2) { /* This is the Typhoon 1.1+ type Sleep Image */ u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2); u8 *ver_string = (u8 *) &xp_resp[1]; ver_string[25] = 0; - printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version " - "%02x.%03x.%03x %s\n", dev->name, sleep_ver >> 24, - (sleep_ver >> 12) & 0xfff, sleep_ver & 0xfff, - ver_string); + netdev_info(dev, "Typhoon 1.1+ Sleep Image version %02x.%03x.%03x %s\n", + sleep_ver >> 24, (sleep_ver >> 12) & 0xfff, + sleep_ver & 0xfff, ver_string); } else { - printk(KERN_WARNING "%s: Unknown Sleep Image version " - "(%u:%04x)\n", dev->name, xp_resp[0].numDesc, - le32_to_cpu(xp_resp[0].parm2)); + netdev_warn(dev, "Unknown Sleep Image version (%u:%04x)\n", + xp_resp[0].numDesc, le32_to_cpu(xp_resp[0].parm2)); } return 0; @@ -2641,6 +2589,7 @@ error_out_disable: error_out_dev: free_netdev(dev); error_out: + pr_err("%s: %s\n", pci_name(pdev), err_msg); return err; } @@ -2665,7 +2614,7 @@ typhoon_remove_one(struct pci_dev *pdev) } static struct pci_driver typhoon_driver = { - .name = DRV_MODULE_NAME, + .name = KBUILD_MODNAME, .id_table = typhoon_pci_tbl, .probe = typhoon_init_one, .remove = __devexit_p(typhoon_remove_one), -- cgit v1.2.3 From 3b9a7728d878a3e7adc79fb89c3bb9ebc23760d7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 19 Feb 2010 23:06:27 +0000 Subject: net/arm: convert to use netdev_for_each_mc_addr Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/arm/am79c961a.c | 10 +++++----- drivers/net/arm/at91_ether.c | 7 ++----- drivers/net/arm/ixp4xx_eth.c | 13 ++++++++----- drivers/net/arm/ks8695net.c | 20 +++++++++----------- drivers/net/arm/w90p910_ether.c | 8 ++++---- 5 files changed, 28 insertions(+), 30 deletions(-) diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 1c3c1f94268e..f1f58c5e27bf 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -351,13 +351,13 @@ static struct net_device_stats *am79c961_getstats (struct net_device *dev) return &priv->stats; } -static void am79c961_mc_hash(struct dev_mc_list *dmi, unsigned short *hash) +static void am79c961_mc_hash(char *addr, unsigned short *hash) { - if (dmi->dmi_addrlen == ETH_ALEN && dmi->dmi_addr[0] & 0x01) { + if (addr[0] & 0x01) { int idx, bit; u32 crc; - crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); + crc = ether_crc_le(ETH_ALEN, addr); idx = crc >> 30; bit = (crc >> 26) & 15; @@ -387,8 +387,8 @@ static void am79c961_setmulticastlist (struct net_device *dev) memset(multi_hash, 0x00, sizeof(multi_hash)); - for (dmi = dev->mc_list; dmi; dmi = dmi->next) - am79c961_mc_hash(dmi, multi_hash); + netdev_for_each_mc_addr(dmi, dev) + am79c961_mc_hash(dmi->dmi_addr, multi_hash); } spin_lock_irqsave(&priv->chip_lock, flags); diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 17d85d98987d..8b23d5a175bf 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -558,14 +558,11 @@ static void at91ether_sethashtable(struct net_device *dev) { struct dev_mc_list *curr; unsigned long mc_filter[2]; - unsigned int i, bitnr; + unsigned int bitnr; mc_filter[0] = mc_filter[1] = 0; - curr = dev->mc_list; - for (i = 0; i < netdev_mc_count(dev); i++, curr = curr->next) { - if (!curr) break; /* unexpected end of list */ - + netdev_for_each_mc_addr(curr, dev) { bitnr = hash_get_index(curr->dmi_addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 1a5f78b160f9..6e2ae1d06df1 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -735,22 +735,25 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) static void eth_set_mcast_list(struct net_device *dev) { struct port *port = netdev_priv(dev); - struct dev_mc_list *mclist = dev->mc_list; + struct dev_mc_list *mclist; u8 diffs[ETH_ALEN], *addr; - int cnt = netdev_mc_count(dev), i; + int i; - if ((dev->flags & IFF_PROMISC) || !mclist || !cnt) { + if ((dev->flags & IFF_PROMISC) || netdev_mc_empty(dev)) { __raw_writel(DEFAULT_RX_CNTRL0 & ~RX_CNTRL0_ADDR_FLTR_EN, &port->regs->rx_control[0]); return; } memset(diffs, 0, ETH_ALEN); - addr = mclist->dmi_addr; /* first MAC address */ - while (--cnt && (mclist = mclist->next)) + addr = NULL; + netdev_for_each_mc_addr(mclist, dev) { + if (!addr) + addr = mclist->dmi_addr; /* first MAC address */ for (i = 0; i < ETH_ALEN; i++) diffs[i] |= addr[i] ^ mclist->dmi_addr[i]; + } for (i = 0; i < ETH_ALEN; i++) { __raw_writel(addr[i], &port->regs->mcast_addr[i]); diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 1dc181a9fbc3..238069699515 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -327,25 +327,24 @@ ks8695_refill_rxbuffers(struct ks8695_priv *ksp) */ static void ks8695_init_partial_multicast(struct ks8695_priv *ksp, - struct dev_mc_list *addr, - int nr_addr) + struct net_device *ndev) { u32 low, high; int i; + struct dev_mc_list *dmi; - for (i = 0; i < nr_addr; i++, addr = addr->next) { - /* Ran out of addresses? */ - if (!addr) - break; + i = 0; + netdev_for_each_mc_addr(dmi, ndev) { /* Ran out of space in chip? */ BUG_ON(i == KS8695_NR_ADDRESSES); - low = (addr->dmi_addr[2] << 24) | (addr->dmi_addr[3] << 16) | - (addr->dmi_addr[4] << 8) | (addr->dmi_addr[5]); - high = (addr->dmi_addr[0] << 8) | (addr->dmi_addr[1]); + low = (dmi->dmi_addr[2] << 24) | (dmi->dmi_addr[3] << 16) | + (dmi->dmi_addr[4] << 8) | (dmi->dmi_addr[5]); + high = (dmi->dmi_addr[0] << 8) | (dmi->dmi_addr[1]); ks8695_writereg(ksp, KS8695_AAL_(i), low); ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high); + i++; } /* Clear the remaining Additional Station Addresses */ @@ -1215,8 +1214,7 @@ ks8695_set_multicast(struct net_device *ndev) } else { /* enable specific multicasts */ ctrl &= ~DRXC_RM; - ks8695_init_partial_multicast(ksp, ndev->mc_list, - netdev_mc_count(ndev)); + ks8695_init_partial_multicast(ksp, ndev); } ks8695_writereg(ksp, KS8695_DRXC, ctrl); diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c index b7f3866d546f..febd813c916d 100644 --- a/drivers/net/arm/w90p910_ether.c +++ b/drivers/net/arm/w90p910_ether.c @@ -858,10 +858,10 @@ static void w90p910_ether_set_multicast_list(struct net_device *dev) if (dev->flags & IFF_PROMISC) rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; - else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list) - rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; - else - rx_mode = CAMCMR_ECMP | CAMCMR_ABP; + else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) + rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP; + else + rx_mode = CAMCMR_ECMP | CAMCMR_ABP; __raw_writel(rx_mode, ether->reg + REG_CAMCMR); } -- cgit v1.2.3 From 0ddf477b8a9b02412a6cabd51c486998811c7dd1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 20 Feb 2010 00:13:58 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part3 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/7990.c | 6 ++---- drivers/net/82596.c | 9 ++++++--- drivers/net/a2065.c | 6 ++---- drivers/net/amd8111e.c | 11 ++++------- drivers/net/amd8111e.h | 1 - drivers/net/appletalk/ltpc.c | 1 - drivers/net/at1700.c | 4 +--- drivers/net/atl1c/atl1c_main.c | 2 +- drivers/net/atl1e/atl1e_main.c | 2 +- drivers/net/atlx/atl2.c | 2 +- drivers/net/atlx/atlx.c | 2 +- drivers/net/atp.c | 4 +--- drivers/net/au1000_eth.c | 5 +---- drivers/net/b44.c | 8 +++++--- drivers/net/bcm63xx_enet.c | 13 +++++-------- drivers/net/benet/be_cmds.c | 10 +++++----- drivers/net/benet/be_cmds.h | 3 +-- drivers/net/benet/be_main.c | 6 +++--- drivers/net/bfin_mac.c | 6 ++---- drivers/net/bmac.c | 7 +++---- drivers/net/bnx2.c | 4 +--- drivers/net/bnx2x_main.c | 12 ++++-------- 22 files changed, 50 insertions(+), 74 deletions(-) diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 079d0be37821..4e9a5a20b6a6 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -595,9 +595,8 @@ static void lance_load_multicast (struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi=dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; /* set all multicast bits */ @@ -611,9 +610,8 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - for (i = 0; i < netdev_mc_count(dev); i++){ + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 638ce3b29854..f94d17d78bb0 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -1550,13 +1550,16 @@ static void set_multicast_list(struct net_device *dev) return; cmd = &lp->mc_cmd; cmd->cmd.command = CmdMulticastList; - cmd->mc_cnt = netdev_mc_count(dev) * 6; + cmd->mc_cnt = cnt * ETH_ALEN; cp = cmd->mc_addrs; - for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { - memcpy(cp, dmi->dmi_addr, 6); + netdev_for_each_mc_addr(dmi, dev) { + if (!cnt--) + break; + memcpy(cp, dmi->dmi_addr, ETH_ALEN); if (i596_debug > 1) DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %pM\n", dev->name, cp)); + cp += ETH_ALEN; } i596_add_cmd(dev, &cmd->cmd); } diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 6a65f660c192..bd4d829eca12 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -603,9 +603,8 @@ static void lance_load_multicast (struct net_device *dev) struct lance_private *lp = netdev_priv(dev); volatile struct lance_init_block *ib = lp->init_block; volatile u16 *mcast_table = (u16 *)&ib->filter; - struct dev_mc_list *dmi=dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; /* set all multicast bits */ @@ -619,9 +618,8 @@ static void lance_load_multicast (struct net_device *dev) ib->filter [1] = 0; /* Add addresses */ - for (i = 0; i < netdev_mc_count(dev); i++){ + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index bdffdfb4c88b..b8a59d255b49 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1377,10 +1377,11 @@ list to the device. */ static void amd8111e_set_multicast_list(struct net_device *dev) { - struct dev_mc_list* mc_ptr; + struct dev_mc_list *mc_ptr; struct amd8111e_priv *lp = netdev_priv(dev); u32 mc_filter[2] ; - int i,bit_num; + int bit_num; + if(dev->flags & IFF_PROMISC){ writel( VAL2 | PROM, lp->mmio + CMD2); return; @@ -1391,7 +1392,6 @@ static void amd8111e_set_multicast_list(struct net_device *dev) netdev_mc_count(dev) > MAX_FILTER_SIZE) { /* get all multicast packet */ mc_filter[1] = mc_filter[0] = 0xffffffff; - lp->mc_list = dev->mc_list; lp->options |= OPTION_MULTICAST_ENABLE; amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF); return; @@ -1399,7 +1399,6 @@ static void amd8111e_set_multicast_list(struct net_device *dev) if (netdev_mc_empty(dev)) { /* get only own packets */ mc_filter[1] = mc_filter[0] = 0; - lp->mc_list = NULL; lp->options &= ~OPTION_MULTICAST_ENABLE; amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF); /* disable promiscous mode */ @@ -1408,10 +1407,8 @@ static void amd8111e_set_multicast_list(struct net_device *dev) } /* load all the multicast addresses in the logic filter */ lp->options |= OPTION_MULTICAST_ENABLE; - lp->mc_list = dev->mc_list; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mc_ptr = dev->mc_list; mc_ptr && i < netdev_mc_count(dev); - i++, mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, dev) { bit_num = (ether_crc_le(ETH_ALEN, mc_ptr->dmi_addr) >> 26) & 0x3f; mc_filter[bit_num >> 5] |= 1 << (bit_num & 31); } diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index 28c60a71ed50..ac36eb6981e3 100644 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -789,7 +789,6 @@ struct amd8111e_priv{ char opened; struct net_device_stats stats; unsigned int drv_rx_errors; - struct dev_mc_list* mc_list; struct amd8111e_coalesce_conf coal_conf; struct ipg_info ipg_data; diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index dbfbd3b7ff86..8ea4ec705bef 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1125,7 +1125,6 @@ struct net_device * __init ltpc_probe(void) printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); dev->netdev_ops = <pc_netdev; - dev->mc_list = NULL; dev->base_addr = io; dev->irq = irq; dev->dma = dma; diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index fe60cd02c86c..309843ab8869 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -849,11 +849,9 @@ set_rx_mode(struct net_device *dev) outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { struct dev_mc_list *mclist; - int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { unsigned int bit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit >> 3] |= (1 << bit); diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index 3d4c0a5a77eb..50dc531a02d8 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -377,7 +377,7 @@ static void atl1c_set_multi(struct net_device *netdev) AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) { hash_value = atl1c_hash_mc_addr(hw, mc_ptr->dmi_addr); atl1c_hash_set(hw, hash_value); } diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 7d8de10ba628..73302ae468aa 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -307,7 +307,7 @@ static void atl1e_set_multi(struct net_device *netdev) AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) { hash_value = atl1e_hash_mc_addr(hw, mc_ptr->dmi_addr); atl1e_hash_set(hw, hash_value); } diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index 40cf9e5cb9e2..7061d7108f08 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -157,7 +157,7 @@ static void atl2_set_multi(struct net_device *netdev) ATL2_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); /* comoute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) { hash_value = atl2_hash_mc_addr(hw, mc_ptr->dmi_addr); atl2_hash_set(hw, hash_value); } diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index 3dc014215679..72f3306352e2 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c @@ -144,7 +144,7 @@ static void atlx_set_multi(struct net_device *netdev) iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); /* compute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) { hash_value = atlx_hash_mc_addr(hw, mc_ptr->dmi_addr); atlx_hash_set(hw, hash_value); } diff --git a/drivers/net/atp.c b/drivers/net/atp.c index a841feb5df20..6ad16205dc17 100644 --- a/drivers/net/atp.c +++ b/drivers/net/atp.c @@ -886,9 +886,7 @@ static void set_rx_mode_8012(struct net_device *dev) struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) - { + netdev_for_each_mc_addr(mclist, dev) { int filterbit = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; mc_filter[filterbit >> 5] |= 1 << (filterbit & 31); } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 9337d023919c..a66b06aa1f0b 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -1018,16 +1018,13 @@ static void au1000_multicast_list(struct net_device *dev) aup->mac->control &= ~MAC_PROMISCUOUS; printk(KERN_INFO "%s: Pass all multicast\n", dev->name); } else { - int i; struct dev_mc_list *mclist; u32 mc_filter[2]; /* Multicast hash filter */ mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, (long *)mc_filter); - } aup->mac->multi_hash_high = mc_filter[1]; aup->mac->multi_hash_low = mc_filter[0]; aup->mac->control &= ~MAC_PROMISCUOUS; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index bcb6a029a0a8..332c60356285 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1684,9 +1684,11 @@ static int __b44_load_mcast(struct b44 *bp, struct net_device *dev) int i, num_ents; num_ents = min_t(int, netdev_mc_count(dev), B44_MCAST_TABLE_SIZE); - mclist = dev->mc_list; - for (i = 0; mclist && i < num_ents; i++, mclist = mclist->next) { - __b44_cam_write(bp, mclist->dmi_addr, i + 1); + i = 0; + netdev_for_each_mc_addr(mclist, dev) { + if (i == num_ents) + break; + __b44_cam_write(bp, mclist->dmi_addr, i++ + 1); } return i+1; } diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c index 0927ffa0d753..8cdcab7655c0 100644 --- a/drivers/net/bcm63xx_enet.c +++ b/drivers/net/bcm63xx_enet.c @@ -631,16 +631,13 @@ static void bcm_enet_set_multicast_list(struct net_device *dev) return; } - for (i = 0, mc_list = dev->mc_list; - (mc_list != NULL) && (i < netdev_mc_count(dev)) && (i < 3); - i++, mc_list = mc_list->next) { + i = 0; + netdev_for_each_mc_addr(mc_list, dev) { u8 *dmi_addr; u32 tmp; - /* filter non ethernet address */ - if (mc_list->dmi_addrlen != 6) - continue; - + if (i == 3) + break; /* update perfect match registers */ dmi_addr = mc_list->dmi_addr; tmp = (dmi_addr[2] << 24) | (dmi_addr[3] << 16) | @@ -649,7 +646,7 @@ static void bcm_enet_set_multicast_list(struct net_device *dev) tmp = (dmi_addr[0] << 8 | dmi_addr[1]); tmp |= ENET_PMH_DATAVALID_MASK; - enet_writel(priv, tmp, ENET_PMH_REG(i + 1)); + enet_writel(priv, tmp, ENET_PMH_REG(i++ + 1)); } for (; i < 3; i++) { diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index ee16b374e02c..c8a2bacb1d13 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -1134,8 +1134,7 @@ err: * (mc == NULL) => multicast promiscous */ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, - struct dev_mc_list *mc_list, u32 mc_count, - struct be_dma_mem *mem) + struct net_device *netdev, struct be_dma_mem *mem) { struct be_mcc_wrb *wrb; struct be_cmd_req_mcast_mac_config *req = mem->va; @@ -1162,13 +1161,14 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); req->interface_id = if_id; - if (mc_list) { + if (netdev) { int i; struct dev_mc_list *mc; - req->num_mac = cpu_to_le16(mc_count); + req->num_mac = cpu_to_le16(netdev_mc_count(netdev)); - for (mc = mc_list, i = 0; mc; mc = mc->next, i++) + i = 0; + netdev_for_each_mc_addr(mc, netdev) memcpy(req->mac[i].byte, mc->dmi_addr, ETH_ALEN); } else { req->promiscuous = 1; diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 3464924d6c28..728b0d736929 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -912,8 +912,7 @@ extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, extern int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en); extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, - struct dev_mc_list *mc_list, u32 mc_count, - struct be_dma_mem *mem); + struct net_device *netdev, struct be_dma_mem *mem); extern int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); extern int be_cmd_get_flow_control(struct be_adapter *adapter, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index de0830e14aa5..27ccdd80257b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -577,13 +577,13 @@ static void be_set_multicast_list(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || netdev_mc_count(netdev) > BE_MAX_MC) { - be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0, + be_cmd_multicast_set(adapter, adapter->if_handle, NULL, &adapter->mc_cmd_mem); goto done; } - be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, - netdev_mc_count(netdev), &adapter->mc_cmd_mem); + be_cmd_multicast_set(adapter, adapter->if_handle, netdev, + &adapter->mc_cmd_mem); done: return; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index ef7f77113e26..587f93cf03f6 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -812,16 +812,14 @@ static void bfin_mac_timeout(struct net_device *dev) static void bfin_mac_multicast_hash(struct net_device *dev) { u32 emac_hashhi, emac_hashlo; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; - int i; u32 crc; emac_hashhi = emac_hashlo = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* skip non-multicast addresses */ if (!(*addrs & 1)) diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 189fa69c2094..119468e76323 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1000,7 +1000,7 @@ static void bmac_set_multicast(struct net_device *dev) rx_cfg = bmac_rx_on(dev, 0, 0); XXDEBUG(("bmac: multi disabled, rx_cfg=%#08x\n", rx_cfg)); } else { - for (dmi=dev->mc_list; dmi!=NULL; dmi=dmi->next) + netdev_for_each_mc_addr(dmi, dev) bmac_addhash(bp, dmi->dmi_addr); bmac_update_hash_table_mask(dev, bp); rx_cfg = bmac_rx_on(dev, 1, 0); @@ -1015,7 +1015,7 @@ static void bmac_set_multicast(struct net_device *dev) static void bmac_set_multicast(struct net_device *dev) { - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; char *addrs; int i; unsigned short rx_cfg; @@ -1039,9 +1039,8 @@ static void bmac_set_multicast(struct net_device *dev) for(i = 0; i < 4; i++) hash_table[i] = 0; - for(i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if(!(*addrs & 1)) continue; diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a6cc9d02e589..d3f739a295df 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3552,9 +3552,7 @@ bnx2_set_rx_mode(struct net_device *dev) memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { - + netdev_for_each_mc_addr(mclist, dev) { crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr); bit = crc & 0xff; regidx = (bit & 0xe0) >> 5; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 7f9db47e8cc3..5adf2a05246f 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -11483,10 +11483,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev) struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); - for (i = 0, mclist = dev->mc_list; - mclist && (i < netdev_mc_count(dev)); - i++, mclist = mclist->next) { - + i = 0; + netdev_for_each_mc_addr(mclist, dev) { config->config_table[i]. cam_entry.msb_mac_addr = swab16(*(u16 *)&mclist->dmi_addr[0]); @@ -11514,6 +11512,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) cam_entry.middle_mac_addr, config->config_table[i]. cam_entry.lsb_mac_addr); + i++; } old = config->hdr.length; if (old > i) { @@ -11555,10 +11554,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev) memset(mc_filter, 0, 4 * MC_HASH_SIZE); - for (i = 0, mclist = dev->mc_list; - mclist && (i < netdev_mc_count(dev)); - i++, mclist = mclist->next) { - + netdev_for_each_mc_addr(mclist, dev) { DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n", mclist->dmi_addr); -- cgit v1.2.3 From 7a81e9f3ca712db82344ea3ab2a5879241f59c48 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 22 Feb 2010 09:10:44 +0000 Subject: e1000: convert to use netdev_for_each_mc_addr Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 3b14dd718ab4..c99f95c1b418 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2161,29 +2161,26 @@ static void e1000_set_rx_mode(struct net_device *netdev) WARN_ON(i == rar_entries); - mc_ptr = netdev->mc_list; - - for (; i < rar_entries; i++) { - if (mc_ptr) { - e1000_rar_set(hw, mc_ptr->da_addr, i); - mc_ptr = mc_ptr->next; - } else { - E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); - E1000_WRITE_FLUSH(); + netdev_for_each_mc_addr(mc_ptr, netdev) { + if (i == rar_entries) { + /* load any remaining addresses into the hash table */ + u32 hash_reg, hash_bit, mta; + hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr); + hash_reg = (hash_value >> 5) & 0x7F; + hash_bit = hash_value & 0x1F; + mta = (1 << hash_bit); + mcarray[hash_reg] |= mta; + } + else { + e1000_rar_set(hw, mc_ptr->da_addr, i++); } } - /* load any remaining addresses into the hash table */ - - for (; mc_ptr; mc_ptr = mc_ptr->next) { - u32 hash_reg, hash_bit, mta; - hash_value = e1000_hash_mc_addr(hw, mc_ptr->da_addr); - hash_reg = (hash_value >> 5) & 0x7F; - hash_bit = hash_value & 0x1F; - mta = (1 << hash_bit); - mcarray[hash_reg] |= mta; + for (; i < rar_entries; i++) { + E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); + E1000_WRITE_FLUSH(); + E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); + E1000_WRITE_FLUSH(); } /* write the hash table completely, write from bottom to avoid -- cgit v1.2.3 From 48e2f183cb1709600012265a2e723f45a350d5fe Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 22 Feb 2010 09:22:26 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part4 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/davinci_emac.c | 5 ++--- drivers/net/e100.c | 10 +++++++--- drivers/net/eepro.c | 8 +++----- drivers/net/eexpress.c | 16 ++++++---------- drivers/net/ehea/ehea_main.c | 5 ++--- drivers/net/enic/enic_main.c | 10 ++++++---- drivers/net/epic100.c | 3 +-- drivers/net/ethoc.c | 6 +++--- drivers/net/ewrk3.c | 5 ++--- drivers/net/fealnx.c | 4 +--- drivers/net/fec.c | 6 ++---- drivers/net/fec_mpc52xx.c | 5 +---- drivers/net/forcedeth.c | 6 ++---- drivers/net/fs_enet/mac-fcc.c | 2 +- drivers/net/fs_enet/mac-fec.c | 2 +- drivers/net/fs_enet/mac-scc.c | 2 +- drivers/net/gianfar.c | 2 +- drivers/net/hamachi.c | 7 ++++--- drivers/net/hp100.c | 6 +++--- drivers/net/ibm_newemac/core.c | 2 +- drivers/net/ibmlana.c | 2 +- drivers/net/ibmveth.c | 5 ++--- drivers/net/igb/igb_main.c | 12 ++++-------- drivers/net/igbvf/netdev.c | 12 +++--------- drivers/net/ioc3-eth.c | 6 ++---- drivers/net/ipg.c | 3 +-- drivers/net/isa-skeleton.c | 2 +- drivers/net/iseries_veth.c | 6 ++---- drivers/net/ixgb/ixgb_main.c | 7 +++---- 29 files changed, 69 insertions(+), 98 deletions(-) diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index d1e03b5984c0..3f5db83c7cbb 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -965,10 +965,9 @@ static void emac_dev_mcast_set(struct net_device *ndev) mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_CLR, NULL); /* program multicast address list into EMAC hardware */ - for (mc_ptr = ndev->mc_list; mc_ptr; - mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, ndev) { emac_add_mcast(priv, EMAC_MULTICAST_ADD, - (u8 *)mc_ptr->dmi_addr); + (u8 *) mc_ptr->dmi_addr); } } else { mbp_enable = (mbp_enable & ~EMAC_MBP_RXMCAST); diff --git a/drivers/net/e100.c b/drivers/net/e100.c index e8c0e823a06f..a26ccab057d5 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1537,14 +1537,18 @@ static int e100_hw_init(struct nic *nic) static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) { struct net_device *netdev = nic->netdev; - struct dev_mc_list *list = netdev->mc_list; + struct dev_mc_list *list; u16 i, count = min(netdev_mc_count(netdev), E100_MAX_MULTICAST_ADDRS); cb->command = cpu_to_le16(cb_multi); cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); - for (i = 0; list && i < count; i++, list = list->next) - memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, + i = 0; + netdev_for_each_mc_addr(list, netdev) { + if (i == count) + break; + memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &list->dmi_addr, ETH_ALEN); + } } static void e100_set_multicast_list(struct net_device *netdev) diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 5f73ab22db16..1b05bdf62c3c 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c @@ -1287,7 +1287,7 @@ set_multicast_list(struct net_device *dev) struct eepro_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; unsigned short mode; - struct dev_mc_list *dmi=dev->mc_list; + struct dev_mc_list *dmi; int mc_count = netdev_mc_count(dev); if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) @@ -1332,10 +1332,8 @@ set_multicast_list(struct net_device *dev) outw(0, ioaddr + IO_PORT); outw(6 * (mc_count + 1), ioaddr + IO_PORT); - for (i = 0; i < mc_count; i++) - { - eaddrs=(unsigned short *)dmi->dmi_addr; - dmi=dmi->next; + netdev_for_each_mc_addr(dmi, dev) { + eaddrs = (unsigned short *) dmi->dmi_addr; outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); outw(*eaddrs++, ioaddr + IO_PORT); diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index d804ff18eda8..7013dc8a6cbc 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -1588,23 +1588,19 @@ static void eexp_setup_filter(struct net_device *dev) outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR); outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST)); - for (i = 0, dmi = dev->mc_list; i < count; i++, dmi = dmi->next) { - unsigned short *data; - if (!dmi) { - printk(KERN_INFO "%s: too few multicast addresses\n", dev->name); + i = 0; + netdev_for_each_mc_addr(dmi, dev) { + unsigned short *data = (unsigned short *) dmi->dmi_addr; + + if (i == count) break; - } - if (dmi->dmi_addrlen != ETH_ALEN) { - printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); - continue; - } - data = (unsigned short *)dmi->dmi_addr; outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR); outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i))); outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR); outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2)); outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR); outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4)); + i++; } } diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 99e4f8360d2f..b004eaba3d7b 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1967,7 +1967,7 @@ static void ehea_set_multicast_list(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); struct dev_mc_list *k_mcl_entry; - int ret, i; + int ret; if (dev->flags & IFF_PROMISC) { ehea_promiscuous(dev, 1); @@ -1997,8 +1997,7 @@ static void ehea_set_multicast_list(struct net_device *dev) goto out; } - for (i = 0, k_mcl_entry = dev->mc_list; i < netdev_mc_count(dev); i++, - k_mcl_entry = k_mcl_entry->next) + netdev_for_each_mc_addr(k_mcl_entry, dev) ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr); } diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 94749ebaaea8..cf098bb636b8 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -822,7 +822,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr) static void enic_set_multicast_list(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); - struct dev_mc_list *list = netdev->mc_list; + struct dev_mc_list *list; int directed = 1; int multicast = (netdev->flags & IFF_MULTICAST) ? 1 : 0; int broadcast = (netdev->flags & IFF_BROADCAST) ? 1 : 0; @@ -851,9 +851,11 @@ static void enic_set_multicast_list(struct net_device *netdev) * look for changes to add/del. */ - for (i = 0; list && i < mc_count; i++) { - memcpy(mc_addr[i], list->dmi_addr, ETH_ALEN); - list = list->next; + i = 0; + netdev_for_each_mc_addr(list, netdev) { + if (i == mc_count) + break; + memcpy(mc_addr[i++], list->dmi_addr, ETH_ALEN); } for (i = 0; i < enic->mc_count; i++) { diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c index 31a3adb65566..39c271b6be44 100644 --- a/drivers/net/epic100.c +++ b/drivers/net/epic100.c @@ -1403,8 +1403,7 @@ static void set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { unsigned int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f; mc_filter[bit_nr >> 3] |= (1 << bit_nr); diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index f9d5ca078743..209742304e20 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -755,7 +755,7 @@ static void ethoc_set_multicast_list(struct net_device *dev) { struct ethoc *priv = netdev_priv(dev); u32 mode = ethoc_read(priv, MODER); - struct dev_mc_list *mc = NULL; + struct dev_mc_list *mc; u32 hash[2] = { 0, 0 }; /* set loopback mode if requested */ @@ -783,8 +783,8 @@ static void ethoc_set_multicast_list(struct net_device *dev) hash[0] = 0xffffffff; hash[1] = 0xffffffff; } else { - for (mc = dev->mc_list; mc; mc = mc->next) { - u32 crc = ether_crc(mc->dmi_addrlen, mc->dmi_addr); + netdev_for_each_mc_addr(mc, dev) { + u32 crc = ether_crc(ETH_ALEN, mc->dmi_addr); int bit = (crc >> 26) & 0x3f; hash[bit >> 5] |= 1 << (bit & 0x1f); } diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c index 96817a872f47..91e59f3a9d6d 100644 --- a/drivers/net/ewrk3.c +++ b/drivers/net/ewrk3.c @@ -1169,7 +1169,7 @@ static void set_multicast_list(struct net_device *dev) static void SetMulticastFilter(struct net_device *dev) { struct ewrk3_private *lp = netdev_priv(dev); - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; u_long iobase = dev->base_addr; int i; char *addrs, bit, byte; @@ -1213,9 +1213,8 @@ static void SetMulticastFilter(struct net_device *dev) } /* Update table */ - for (i = 0; i < netdev_mc_count(dev); i++) { /* for each address in the list */ + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; if ((*addrs & 0x01) == 1) { /* multicast address? */ crc = ether_crc_le(ETH_ALEN, addrs); hashcode = crc & ((1 << 9) - 1); /* hashcode is 9 LSb of CRC */ diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c index f95b5ff0587d..9d5ad08a119f 100644 --- a/drivers/net/fealnx.c +++ b/drivers/net/fealnx.c @@ -1793,11 +1793,9 @@ static void __set_rx_mode(struct net_device *dev) rx_mode = CR_W_AB | CR_W_AM; } else { struct dev_mc_list *mclist; - int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { unsigned int bit; bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; mc_filter[bit >> 5] |= (1 << bit); diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d9d14c83f51c..9f98c1c4a344 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -1575,7 +1575,7 @@ static void set_multicast_list(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); struct dev_mc_list *dmi; - unsigned int i, j, bit, data, crc, tmp; + unsigned int i, bit, data, crc, tmp; unsigned char hash; if (dev->flags & IFF_PROMISC) { @@ -1604,9 +1604,7 @@ static void set_multicast_list(struct net_device *dev) writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); - dmi = dev->mc_list; - - for (j = 0; j < netdev_mc_count(dev); j++, dmi = dmi->next) { + netdev_for_each_mc_addr(dmi, dev) { /* Only support group multicast for now */ if (!(dmi->dmi_addr[0] & 1)) continue; diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index 10903b75802f..0dbd7219bbde 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -575,19 +575,16 @@ static void mpc52xx_fec_set_multicast_list(struct net_device *dev) out_be32(&fec->gaddr2, 0xffffffff); } else { u32 crc; - int i; struct dev_mc_list *dmi; u32 gaddr1 = 0x00000000; u32 gaddr2 = 0x00000000; - dmi = dev->mc_list; - for (i=0; idmi_addr) >> 26; if (crc >= 32) gaddr1 |= 1 << (crc-32); else gaddr2 |= 1 << crc; - dmi = dmi->next; } out_be32(&fec->gaddr1, gaddr1); out_be32(&fec->gaddr2, gaddr2); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 3eb713b014f9..ca05e5662029 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3095,7 +3095,7 @@ static void nv_set_multicast(struct net_device *dev) } else { pff |= NVREG_PFF_MYADDR; - if (dev->flags & IFF_ALLMULTI || dev->mc_list) { + if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { u32 alwaysOff[2]; u32 alwaysOn[2]; @@ -3105,8 +3105,7 @@ static void nv_set_multicast(struct net_device *dev) } else { struct dev_mc_list *walk; - walk = dev->mc_list; - while (walk != NULL) { + netdev_for_each_mc_addr(walk, dev) { u32 a, b; a = le32_to_cpu(*(__le32 *) walk->dmi_addr); b = le16_to_cpu(*(__le16 *) (&walk->dmi_addr[4])); @@ -3114,7 +3113,6 @@ static void nv_set_multicast(struct net_device *dev) alwaysOff[0] &= ~a; alwaysOn[1] &= b; alwaysOff[1] &= ~b; - walk = walk->next; } } addr[0] = alwaysOn[0]; diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 482f27d5f7d4..a761d31e3d6d 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -235,7 +235,7 @@ static void set_multicast_list(struct net_device *dev) if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next) + netdev_for_each_mc_addr(pmc, dev) set_multicast_one(dev, pmc->dmi_addr); set_multicast_finish(dev); } else diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index ddf13ef8ac87..ca806d1ab3f6 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -236,7 +236,7 @@ static void set_multicast_list(struct net_device *dev) if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next) + netdev_for_each_mc_addr(pmc, dev) set_multicast_one(dev, pmc->dmi_addr); set_multicast_finish(dev); } else diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 141dbc91e5e7..5bfc99b9475e 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -228,7 +228,7 @@ static void set_multicast_list(struct net_device *dev) if ((dev->flags & IFF_PROMISC) == 0) { set_multicast_start(dev); - for (pmc = dev->mc_list; pmc != NULL; pmc = pmc->next) + netdev_for_each_mc_addr(pmc, dev) set_multicast_one(dev, pmc->dmi_addr); set_multicast_finish(dev); } else diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index c9be090485dd..6aa526ee9096 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2867,7 +2867,7 @@ static void gfar_set_multi(struct net_device *dev) return; /* Parse the list, and set the appropriate bits */ - for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, dev) { if (idx < em_num) { gfar_set_mac_for_addr(dev, idx, mc_ptr->dmi_addr); diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index c70b147b4feb..373546dd0831 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c @@ -1859,12 +1859,13 @@ static void set_rx_mode(struct net_device *dev) writew(0x000B, ioaddr + AddrMode); } else if (!netdev_mc_empty(dev)) { /* Must use the CAM filter. */ struct dev_mc_list *mclist; - int i; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + int i = 0; + + netdev_for_each_mc_addr(mclist, dev) { writel(*(u32*)(mclist->dmi_addr), ioaddr + 0x100 + i*8); writel(0x20000 | (*(u16*)&mclist->dmi_addr[4]), ioaddr + 0x104 + i*8); + i++; } /* Clear remaining entries. */ for (; i < 64; i++) diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index debac1bc6799..b766a69bf0ca 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -2098,7 +2098,7 @@ static void hp100_set_multicast_list(struct net_device *dev) /* set hash filter to receive all multicast packets */ memset(&lp->hash_bytes, 0xff, 8); } else { - int i, j, idx; + int i, idx; u_char *addrs; struct dev_mc_list *dmi; @@ -2107,14 +2107,14 @@ static void hp100_set_multicast_list(struct net_device *dev) printk("hp100: %s: computing hash filter - mc_count = %i\n", dev->name, netdev_mc_count(dev)); #endif - for (i = 0, dmi = dev->mc_list; i < netdev_mc_count(dev); i++, dmi = dmi->next) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; if ((*addrs & 0x01) == 0x01) { /* multicast address? */ #ifdef HP100_DEBUG printk("hp100: %s: multicast = %pM, ", dev->name, addrs); #endif - for (j = idx = 0; j < 6; j++) { + for (i = idx = 0; i < 6; i++) { idx ^= *addrs++ & 0x3f; printk(":%02x:", idx); } diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index b75d27e82a3d..fb0ac6d7c040 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -395,7 +395,7 @@ static void emac_hash_mc(struct emac_instance *dev) memset(gaht_temp, 0, sizeof (gaht_temp)); - for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) { + netdev_for_each_mc_addr(dmi, dev->ndev) { int slot, reg, mask; DBG2(dev, "mc %pM" NL, dmi->dmi_addr); diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c index 052c74091d91..b5d0f4e973f7 100644 --- a/drivers/net/ibmlana.c +++ b/drivers/net/ibmlana.c @@ -420,7 +420,7 @@ static void InitBoard(struct net_device *dev) /* start putting the multicast addresses into the CAM list. Stop if it is full. */ - for (mcptr = dev->mc_list; mcptr != NULL; mcptr = mcptr->next) { + netdev_for_each_mc_addr(mcptr, dev) { putcam(cams, &camcnt, mcptr->dmi_addr); if (camcnt == 16) break; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 41b9c0efcbdd..f2b937966950 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1072,8 +1072,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); } } else { - struct dev_mc_list *mclist = netdev->mc_list; - int i; + struct dev_mc_list *mclist; /* clear the filter table & disable filtering */ lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, IbmVethMcastEnableRecv | @@ -1084,7 +1083,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); } /* add the addresses to the filter table */ - for(i = 0; i < netdev_mc_count(netdev); ++i, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, netdev) { // add the multicast address to the filter table unsigned long mcast_addr = 0; memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index f588e49c65f1..583a21c1def3 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2877,7 +2877,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr = netdev->mc_list; + struct dev_mc_list *mc_ptr; u8 *mta_list; int i; @@ -2893,14 +2893,10 @@ static int igb_write_mc_addr_list(struct net_device *netdev) return -ENOMEM; /* The shared function expects a packed array of only addresses. */ - mc_ptr = netdev->mc_list; + i = 0; + netdev_for_each_mc_addr(mc_ptr, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); - for (i = 0; i < netdev_mc_count(netdev); i++) { - if (!mc_ptr) - break; - memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); - mc_ptr = mc_ptr->next; - } igb_update_mc_addr_list(hw, mta_list, i); kfree(mta_list); diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 6029c400f2be..a77afd8a14bb 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1413,15 +1413,9 @@ static void igbvf_set_multi(struct net_device *netdev) } /* prepare a packed array of only addresses. */ - mc_ptr = netdev->mc_list; - - for (i = 0; i < netdev_mc_count(netdev); i++) { - if (!mc_ptr) - break; - memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr, - ETH_ALEN); - mc_ptr = mc_ptr->next; - } + i = 0; + netdev_for_each_mc_addr(mc_ptr, netdev) + memcpy(mta_list + (i++ * ETH_ALEN), mc_ptr->dmi_addr, ETH_ALEN); hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0); kfree(mta_list); diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 0bd5fef22d49..70871b9b045a 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1664,11 +1664,10 @@ static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static void ioc3_set_multicast_list(struct net_device *dev) { - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; struct ioc3_private *ip = netdev_priv(dev); struct ioc3 *ioc3 = ip->regs; u64 ehar = 0; - int i; netif_stop_queue(dev); /* Lock out others. */ @@ -1689,9 +1688,8 @@ static void ioc3_set_multicast_list(struct net_device *dev) ip->ehar_h = 0xffffffff; ip->ehar_l = 0xffffffff; } else { - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { char *addr = dmi->dmi_addr; - dmi = dmi->next; if (!(*addr & 1)) continue; diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 3ca49e348c9d..150415e83f61 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -608,8 +608,7 @@ static void ipg_nic_set_multicast_list(struct net_device *dev) hashtable[1] = 0x00000000; /* Cycle through all multicast addresses to filter. */ - for (mc_list_ptr = dev->mc_list; - mc_list_ptr != NULL; mc_list_ptr = mc_list_ptr->next) { + netdev_for_each_mc_addr(mc_list_ptr, dev) { /* Calculate CRC result for each multicast address. */ hashindex = crc32_le(0xffffffff, mc_list_ptr->dmi_addr, ETH_ALEN); diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index bb4a3cda6e4b..d09e4d3a15a6 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -666,7 +666,7 @@ set_multicast_list(struct net_device *dev) else if (!netdev_mc_empty(dev)) { /* Walk the address list, and load the filter */ - hardware_set_filter(dev->mc_list); + hardware_set_filter(dev); outw(MULTICAST, ioaddr); } diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index ff015e15f5d1..966de5d69521 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -961,15 +961,14 @@ static void veth_set_multicast_list(struct net_device *dev) (netdev_mc_count(dev) > VETH_MAX_MCAST)) { port->promiscuous = 1; } else { - struct dev_mc_list *dmi = dev->mc_list; - int i; + struct dev_mc_list *dmi; port->promiscuous = 0; /* Update table */ port->num_mcast = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { u8 *addr = dmi->dmi_addr; u64 xaddr = 0; @@ -978,7 +977,6 @@ static void veth_set_multicast_list(struct net_device *dev) port->mcast_addr[port->num_mcast] = xaddr; port->num_mcast++; } - dmi = dmi->next; } } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 93d018505ebb..c9fef65cb98b 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1088,10 +1088,9 @@ ixgb_set_multi(struct net_device *netdev) IXGB_WRITE_REG(hw, RCTL, rctl); - for (i = 0, mc_ptr = netdev->mc_list; - mc_ptr; - i++, mc_ptr = mc_ptr->next) - memcpy(&mta[i * IXGB_ETH_LENGTH_OF_ADDRESS], + i = 0; + netdev_for_each_mc_addr(mc_ptr, netdev) + memcpy(&mta[i++ * IXGB_ETH_LENGTH_OF_ADDRESS], mc_ptr->dmi_addr, IXGB_ETH_LENGTH_OF_ADDRESS); ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0); -- cgit v1.2.3 From e5f8d9ac46e0291594abaa76bf467a08367bcccf Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 11:09:38 +0000 Subject: isdn: fix a few Kconfig imperfections 1. Rewrite the outdated help texts for config options ISDN and ISDN_CAPI. 2. The MISDN config option appeared between ISDN_I4L and the I4L hardware driver options; move it to a less irritating place. 3. HYSDN is not in fact an I4L driver, and needn't depend on ISDN_I4L, so move it from the I4L section to the general section. 4. ISDN_HDLC is now also used by drivers outside I4L. Move it from the I4L section to the general section, too. Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/Kconfig | 43 ++++++++++++++++++++++++++++--------------- drivers/isdn/i4l/Kconfig | 7 ------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index 022a19452953..4fb601670de3 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -7,15 +7,14 @@ menuconfig ISDN depends on NET depends on !S390 ---help--- - ISDN ("Integrated Services Digital Networks", called RNIS in France) - is a special type of fully digital telephone service; it's mostly - used to connect to your Internet service provider (with SLIP or - PPP). The main advantage is that the speed is higher than ordinary - modem/telephone connections, and that you can have voice - conversations while downloading stuff. It only works if your - computer is equipped with an ISDN card and both you and your service - provider purchased an ISDN line from the phone company. For - details, read on the WWW. + ISDN ("Integrated Services Digital Network", called RNIS in France) + is a fully digital telephone service that can be used for voice and + data connections. If your computer is equipped with an ISDN + adapter you can use it to connect to your Internet service provider + (with SLIP or PPP) faster than via a conventional telephone modem + (though still much slower than with DSL) or to make and accept + voice calls (eg. turning your PC into a software answering machine + or PABX). Select this option if you want your kernel to support ISDN. @@ -39,17 +38,22 @@ menuconfig ISDN_I4L It is still available, though, for use with adapters that are not supported by the new CAPI subsystem yet. -source "drivers/isdn/mISDN/Kconfig" - source "drivers/isdn/i4l/Kconfig" menuconfig ISDN_CAPI tristate "CAPI 2.0 subsystem" help - This provides the CAPI (Common ISDN Application Programming - Interface, a standard making it easy for programs to access ISDN - hardware, see . This is needed for AVM's set - of active ISDN controllers like B1, T1, M1. + This provides CAPI (the Common ISDN Application Programming + Interface) Version 2.0, a standard making it easy for programs to + access ISDN hardware in a device independent way. (For details see + .) CAPI supports making and accepting voice + and data connections, controlling call options and protocols, + as well as ISDN supplementary services like call forwarding or + three-party conferences (if supported by the specific hardware + driver). + + Select this option and the appropriate hardware driver below if + you have an ISDN adapter supported by the CAPI subsystem. if ISDN_CAPI @@ -61,4 +65,13 @@ endif # ISDN_CAPI source "drivers/isdn/gigaset/Kconfig" +source "drivers/isdn/hysdn/Kconfig" + +source "drivers/isdn/mISDN/Kconfig" + +config ISDN_HDLC + tristate + select CRC_CCITT + select BITREVERSE + endif # ISDN diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 07c4e49f9e77..9c6650ea848e 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -134,14 +134,7 @@ source "drivers/isdn/sc/Kconfig" source "drivers/isdn/act2000/Kconfig" -source "drivers/isdn/hysdn/Kconfig" - endmenu # end ISDN_I4L endif -config ISDN_HDLC - tristate - select CRC_CCITT - select BITREVERSE - -- cgit v1.2.3 From 35e2da46d25a53e0e19956f533cc29272a6cceb2 Mon Sep 17 00:00:00 2001 From: Sriram Date: Mon, 22 Feb 2010 03:35:36 +0000 Subject: can:ti_hecc: Add pm hook-up Added the suspend and resume implementation in the HECC (CAN) driver. Signed-off-by: K R Baalaaji Signed-off-by: Sriramakrishnan Acked-by: Anant Gole Signed-off-by: David S. Miller --- drivers/net/can/ti_hecc.c | 51 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 8332e242b0be..b861cd561074 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -826,7 +826,6 @@ static int ti_hecc_open(struct net_device *ndev) return err; } - clk_enable(priv->clk); ti_hecc_start(ndev); napi_enable(&priv->napi); netif_start_queue(ndev); @@ -842,7 +841,6 @@ static int ti_hecc_close(struct net_device *ndev) napi_disable(&priv->napi); ti_hecc_stop(ndev); free_irq(ndev->irq, ndev); - clk_disable(priv->clk); close_candev(ndev); return 0; @@ -928,6 +926,7 @@ static int ti_hecc_probe(struct platform_device *pdev) netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll, HECC_DEF_NAPI_WEIGHT); + clk_enable(priv->clk); err = register_candev(ndev); if (err) { dev_err(&pdev->dev, "register_candev() failed\n"); @@ -956,6 +955,7 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); + clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); @@ -967,6 +967,48 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) return 0; } + +#ifdef CONFIG_PM +static int ti_hecc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct ti_hecc_priv *priv = netdev_priv(dev); + + if (netif_running(dev)) { + netif_stop_queue(dev); + netif_device_detach(dev); + } + + hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR); + priv->can.state = CAN_STATE_SLEEPING; + + clk_disable(priv->clk); + + return 0; +} + +static int ti_hecc_resume(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct ti_hecc_priv *priv = netdev_priv(dev); + + clk_enable(priv->clk); + + hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR); + priv->can.state = CAN_STATE_ERROR_ACTIVE; + + if (netif_running(dev)) { + netif_device_attach(dev); + netif_start_queue(dev); + } + + return 0; +} +#else +#define ti_hecc_suspend NULL +#define ti_hecc_resume NULL +#endif + /* TI HECC netdevice driver: platform driver structure */ static struct platform_driver ti_hecc_driver = { .driver = { @@ -975,6 +1017,8 @@ static struct platform_driver ti_hecc_driver = { }, .probe = ti_hecc_probe, .remove = __devexit_p(ti_hecc_remove), + .suspend = ti_hecc_suspend, + .resume = ti_hecc_resume, }; static int __init ti_hecc_init_driver(void) @@ -982,14 +1026,15 @@ static int __init ti_hecc_init_driver(void) printk(KERN_INFO DRV_DESC "\n"); return platform_driver_register(&ti_hecc_driver); } -module_init(ti_hecc_init_driver); static void __exit ti_hecc_exit_driver(void) { printk(KERN_INFO DRV_DESC " unloaded\n"); platform_driver_unregister(&ti_hecc_driver); } + module_exit(ti_hecc_exit_driver); +module_init(ti_hecc_init_driver); MODULE_AUTHOR("Anant Gole "); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 1cc523271ef0b6305c565a143e3d48f6fff826dd Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 22 Feb 2010 07:57:17 +0000 Subject: seq_file: add RCU versions of new hlist/list iterators (v3) Many usages of seq_file use RCU protected lists, so non RCU iterators will not work safely. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- fs/seq_file.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rculist.h | 5 ++++ include/linux/seq_file.h | 15 +++++++--- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/fs/seq_file.c b/fs/seq_file.c index f65b16f02da3..5afd554efad3 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -750,3 +750,74 @@ struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, return node->next; } EXPORT_SYMBOL(seq_hlist_next); + +/** + * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU + * @head: the head of the hlist + * @pos: the start position of the sequence + * + * Called at seq_file->op->start(). + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_head_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, + loff_t pos) +{ + struct hlist_node *node; + + __hlist_for_each_rcu(node, head) + if (pos-- == 0) + return node; + return NULL; +} +EXPORT_SYMBOL(seq_hlist_start_rcu); + +/** + * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU + * @head: the head of the hlist + * @pos: the start position of the sequence + * + * Called at seq_file->op->start(). Call this function if you want to + * print a header at the top of the output. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_head_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, + loff_t pos) +{ + if (!pos) + return SEQ_START_TOKEN; + + return seq_hlist_start_rcu(head, pos - 1); +} +EXPORT_SYMBOL(seq_hlist_start_head_rcu); + +/** + * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU + * @v: the current iterator + * @head: the head of the hlist + * @pos: the current posision + * + * Called at seq_file->op->next(). + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_head_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +struct hlist_node *seq_hlist_next_rcu(void *v, + struct hlist_head *head, + loff_t *ppos) +{ + struct hlist_node *node = v; + + ++*ppos; + if (v == SEQ_START_TOKEN) + return rcu_dereference(head->first); + else + return rcu_dereference(node->next); +} +EXPORT_SYMBOL(seq_hlist_next_rcu); diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 1bf0f708c4fc..701fe9cb552a 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -406,6 +406,11 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, n->next->pprev = &n->next; } +#define __hlist_for_each_rcu(pos, head) \ + for (pos = rcu_dereference((head)->first); \ + pos && ({ prefetch(pos->next); 1; }); \ + pos = rcu_dereference(pos->next)) + /** * hlist_for_each_entry_rcu - iterate over rcu list of given type * @tpos: the type * to use as a loop cursor. diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index c95bcdc18f4c..03c0232b4169 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -140,10 +140,17 @@ extern struct list_head *seq_list_next(void *v, struct list_head *head, */ extern struct hlist_node *seq_hlist_start(struct hlist_head *head, - loff_t pos); + loff_t pos); extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head, - loff_t pos); + loff_t pos); extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, - loff_t *ppos); - + loff_t *ppos); + +extern struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, + loff_t pos); +extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, + loff_t pos); +extern struct hlist_node *seq_hlist_next_rcu(void *v, + struct hlist_head *head, + loff_t *ppos); #endif -- cgit v1.2.3 From 808f5114a9206fee855117d416440e1071ab375c Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 22 Feb 2010 07:57:18 +0000 Subject: packet: convert socket list to RCU (v3) Convert AF_PACKET to use RCU, eliminating one more reader/writer lock. There is no need for a real sk_del_node_init_rcu(), because sk_del_node_init is doing the equivalent thing to hlst_del_init_rcu already; but added some comments to try and make that obvious. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- include/net/netns/packet.h | 4 +-- include/net/sock.h | 10 ++++++++ net/packet/af_packet.c | 62 +++++++++++++++++++++++----------------------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/include/net/netns/packet.h b/include/net/netns/packet.h index 637daf698884..cb4e894c0f8d 100644 --- a/include/net/netns/packet.h +++ b/include/net/netns/packet.h @@ -4,11 +4,11 @@ #ifndef __NETNS_PACKET_H__ #define __NETNS_PACKET_H__ -#include +#include #include struct netns_packet { - rwlock_t sklist_lock; + spinlock_t sklist_lock; struct hlist_head sklist; }; diff --git a/include/net/sock.h b/include/net/sock.h index 580d51fa28e9..6cb1676e409a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -381,6 +381,7 @@ static __inline__ void __sk_del_node(struct sock *sk) __hlist_del(&sk->sk_node); } +/* NB: equivalent to hlist_del_init_rcu */ static __inline__ int __sk_del_node_init(struct sock *sk) { if (sk_hashed(sk)) { @@ -421,6 +422,7 @@ static __inline__ int sk_del_node_init(struct sock *sk) } return rc; } +#define sk_del_node_init_rcu(sk) sk_del_node_init(sk) static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk) { @@ -454,6 +456,12 @@ static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list) __sk_add_node(sk, list); } +static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) +{ + sock_hold(sk); + hlist_add_head_rcu(&sk->sk_node, list); +} + static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) { hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); @@ -478,6 +486,8 @@ static __inline__ void sk_add_bind_node(struct sock *sk, #define sk_for_each(__sk, node, list) \ hlist_for_each_entry(__sk, node, list, sk_node) +#define sk_for_each_rcu(__sk, node, list) \ + hlist_for_each_entry_rcu(__sk, node, list, sk_node) #define sk_nulls_for_each(__sk, node, list) \ hlist_nulls_for_each_entry(__sk, node, list, sk_nulls_node) #define sk_nulls_for_each_rcu(__sk, node, list) \ diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 10f7295bcefb..2f0369367ee0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1262,24 +1262,22 @@ static int packet_release(struct socket *sock) net = sock_net(sk); po = pkt_sk(sk); - write_lock_bh(&net->packet.sklist_lock); - sk_del_node_init(sk); + spin_lock_bh(&net->packet.sklist_lock); + sk_del_node_init_rcu(sk); sock_prot_inuse_add(net, sk->sk_prot, -1); - write_unlock_bh(&net->packet.sklist_lock); - - /* - * Unhook packet receive handler. - */ + spin_unlock_bh(&net->packet.sklist_lock); + spin_lock(&po->bind_lock); if (po->running) { /* - * Remove the protocol hook + * Remove from protocol table */ - dev_remove_pack(&po->prot_hook); po->running = 0; po->num = 0; + __dev_remove_pack(&po->prot_hook); __sock_put(sk); } + spin_unlock(&po->bind_lock); packet_flush_mclist(sk); @@ -1291,10 +1289,10 @@ static int packet_release(struct socket *sock) if (po->tx_ring.pg_vec) packet_set_ring(sk, &req, 1, 1); + synchronize_net(); /* * Now the socket is dead. No more input will appear. */ - sock_orphan(sk); sock->sk = NULL; @@ -1478,10 +1476,11 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, po->running = 1; } - write_lock_bh(&net->packet.sklist_lock); - sk_add_node(sk, &net->packet.sklist); + spin_lock_bh(&net->packet.sklist_lock); + sk_add_node_rcu(sk, &net->packet.sklist); sock_prot_inuse_add(net, &packet_proto, 1); - write_unlock_bh(&net->packet.sklist_lock); + spin_unlock_bh(&net->packet.sklist_lock); + return 0; out: return err; @@ -2075,8 +2074,8 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void struct net_device *dev = data; struct net *net = dev_net(dev); - read_lock(&net->packet.sklist_lock); - sk_for_each(sk, node, &net->packet.sklist) { + rcu_read_lock(); + sk_for_each_rcu(sk, node, &net->packet.sklist) { struct packet_sock *po = pkt_sk(sk); switch (msg) { @@ -2104,18 +2103,19 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void } break; case NETDEV_UP: - spin_lock(&po->bind_lock); - if (dev->ifindex == po->ifindex && po->num && - !po->running) { - dev_add_pack(&po->prot_hook); - sock_hold(sk); - po->running = 1; + if (dev->ifindex == po->ifindex) { + spin_lock(&po->bind_lock); + if (po->num && !po->running) { + dev_add_pack(&po->prot_hook); + sock_hold(sk); + po->running = 1; + } + spin_unlock(&po->bind_lock); } - spin_unlock(&po->bind_lock); break; } } - read_unlock(&net->packet.sklist_lock); + rcu_read_unlock(); return NOTIFY_DONE; } @@ -2512,24 +2512,24 @@ static struct notifier_block packet_netdev_notifier = { #ifdef CONFIG_PROC_FS static void *packet_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(seq_file_net(seq)->packet.sklist_lock) + __acquires(RCU) { struct net *net = seq_file_net(seq); - read_lock(&net->packet.sklist_lock); - return seq_hlist_start_head(&net->packet.sklist, *pos); + + rcu_read_lock(); + return seq_hlist_start_head_rcu(&net->packet.sklist, *pos); } static void *packet_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct net *net = seq_file_net(seq); - return seq_hlist_next(v, &net->packet.sklist, pos); + return seq_hlist_next_rcu(v, &net->packet.sklist, pos); } static void packet_seq_stop(struct seq_file *seq, void *v) - __releases(seq_file_net(seq)->packet.sklist_lock) + __releases(RCU) { - struct net *net = seq_file_net(seq); - read_unlock(&net->packet.sklist_lock); + rcu_read_unlock(); } static int packet_seq_show(struct seq_file *seq, void *v) @@ -2581,7 +2581,7 @@ static const struct file_operations packet_seq_fops = { static int __net_init packet_net_init(struct net *net) { - rwlock_init(&net->packet.sklist_lock); + spin_lock_init(&net->packet.sklist_lock); INIT_HLIST_HEAD(&net->packet.sklist); if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops)) -- cgit v1.2.3 From 7f6b9dbd5afbd966a82dcbafc5ed62305eb9d479 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Mon, 22 Feb 2010 07:57:19 +0000 Subject: af_key: locking change Get rid of custom locking that was using wait queue, lock, and atomic to basically build a queued mutex. Use RCU for read side. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/key/af_key.c | 76 ++++++++++++-------------------------------------------- 1 file changed, 16 insertions(+), 60 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index a20d2fa88db9..da2fe5f57619 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -41,9 +41,7 @@ struct netns_pfkey { struct hlist_head table; atomic_t socks_nr; }; -static DECLARE_WAIT_QUEUE_HEAD(pfkey_table_wait); -static DEFINE_RWLOCK(pfkey_table_lock); -static atomic_t pfkey_table_users = ATOMIC_INIT(0); +static DEFINE_MUTEX(pfkey_mutex); struct pfkey_sock { /* struct sock must be the first member of struct pfkey_sock */ @@ -108,50 +106,6 @@ static void pfkey_sock_destruct(struct sock *sk) atomic_dec(&net_pfkey->socks_nr); } -static void pfkey_table_grab(void) -{ - write_lock_bh(&pfkey_table_lock); - - if (atomic_read(&pfkey_table_users)) { - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue_exclusive(&pfkey_table_wait, &wait); - for(;;) { - set_current_state(TASK_UNINTERRUPTIBLE); - if (atomic_read(&pfkey_table_users) == 0) - break; - write_unlock_bh(&pfkey_table_lock); - schedule(); - write_lock_bh(&pfkey_table_lock); - } - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&pfkey_table_wait, &wait); - } -} - -static __inline__ void pfkey_table_ungrab(void) -{ - write_unlock_bh(&pfkey_table_lock); - wake_up(&pfkey_table_wait); -} - -static __inline__ void pfkey_lock_table(void) -{ - /* read_lock() synchronizes us to pfkey_table_grab */ - - read_lock(&pfkey_table_lock); - atomic_inc(&pfkey_table_users); - read_unlock(&pfkey_table_lock); -} - -static __inline__ void pfkey_unlock_table(void) -{ - if (atomic_dec_and_test(&pfkey_table_users)) - wake_up(&pfkey_table_wait); -} - - static const struct proto_ops pfkey_ops; static void pfkey_insert(struct sock *sk) @@ -159,16 +113,16 @@ static void pfkey_insert(struct sock *sk) struct net *net = sock_net(sk); struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - pfkey_table_grab(); - sk_add_node(sk, &net_pfkey->table); - pfkey_table_ungrab(); + mutex_lock(&pfkey_mutex); + sk_add_node_rcu(sk, &net_pfkey->table); + mutex_unlock(&pfkey_mutex); } static void pfkey_remove(struct sock *sk) { - pfkey_table_grab(); - sk_del_node_init(sk); - pfkey_table_ungrab(); + mutex_lock(&pfkey_mutex); + sk_del_node_init_rcu(sk); + mutex_unlock(&pfkey_mutex); } static struct proto key_proto = { @@ -223,6 +177,8 @@ static int pfkey_release(struct socket *sock) sock_orphan(sk); sock->sk = NULL; skb_queue_purge(&sk->sk_write_queue); + + synchronize_rcu(); sock_put(sk); return 0; @@ -277,8 +233,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, if (!skb) return -ENOMEM; - pfkey_lock_table(); - sk_for_each(sk, node, &net_pfkey->table) { + rcu_read_lock(); + sk_for_each_rcu(sk, node, &net_pfkey->table) { struct pfkey_sock *pfk = pfkey_sk(sk); int err2; @@ -309,7 +265,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, if ((broadcast_flags & BROADCAST_REGISTERED) && err) err = err2; } - pfkey_unlock_table(); + rcu_read_unlock(); if (one_sk != NULL) err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); @@ -3702,8 +3658,8 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos) struct net *net = seq_file_net(f); struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - read_lock(&pfkey_table_lock); - return seq_hlist_start_head(&net_pfkey->table, *ppos); + rcu_read_lock(); + return seq_hlist_start_head_rcu(&net_pfkey->table, *ppos); } static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) @@ -3711,12 +3667,12 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos) struct net *net = seq_file_net(f); struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); - return seq_hlist_next(v, &net_pfkey->table, ppos); + return seq_hlist_next_rcu(v, &net_pfkey->table, ppos); } static void pfkey_seq_stop(struct seq_file *f, void *v) { - read_unlock(&pfkey_table_lock); + rcu_read_unlock(); } static const struct seq_operations pfkey_seq_ops = { -- cgit v1.2.3 From bf825f81b454fae2ffe1b675f3a549656726440e Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:32:54 +0000 Subject: xfrm: introduce basic mark infrastructure Add basic structuring and accessors for xfrm mark Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/linux/xfrm.h | 12 +++++++++--- include/net/xfrm.h | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 29e04beb1fc9..b971e3848493 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -267,8 +267,8 @@ enum xfrm_attr_type_t { XFRMA_ALG_COMP, /* struct xfrm_algo */ XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */ XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */ - XFRMA_SA, - XFRMA_POLICY, + XFRMA_SA, /* struct xfrm_usersa_info */ + XFRMA_POLICY, /*struct xfrm_userpolicy_info */ XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */ XFRMA_LTIME_VAL, XFRMA_REPLAY_VAL, @@ -276,17 +276,23 @@ enum xfrm_attr_type_t { XFRMA_ETIMER_THRESH, XFRMA_SRCADDR, /* xfrm_address_t */ XFRMA_COADDR, /* xfrm_address_t */ - XFRMA_LASTUSED, + XFRMA_LASTUSED, /* unsigned long */ XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ XFRMA_MIGRATE, XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */ + XFRMA_MARK, /* struct xfrm_mark */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) }; +struct xfrm_mark { + __u32 v; /* value */ + __u32 m; /* mask */ +}; + enum xfrm_sadattr_type_t { XFRMA_SAD_UNSPEC, XFRMA_SAD_CNT, diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0beb413c01c4..39f151c7f251 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -140,6 +140,7 @@ struct xfrm_state { struct xfrm_id id; struct xfrm_selector sel; + struct xfrm_mark mark; u32 genid; @@ -481,6 +482,7 @@ struct xfrm_policy { u32 priority; u32 index; + struct xfrm_mark mark; struct xfrm_selector selector; struct xfrm_lifetime_cfg lft; struct xfrm_lifetime_cur curlft; @@ -1570,4 +1572,24 @@ static inline struct xfrm_state *xfrm_input_state(struct sk_buff *skb) } #endif +static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m) +{ + if (attrs[XFRMA_MARK]) + memcpy(m, nla_data(attrs[XFRMA_MARK]), sizeof(m)); + else + m->v = m->m = 0; + + return m->v & m->m; +} + +static inline int xfrm_mark_put(struct sk_buff *skb, struct xfrm_mark *m) +{ + if (m->m | m->v) + NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m); + return 0; + +nla_put_failure: + return -1; +} + #endif /* _NET_XFRM_H */ -- cgit v1.2.3 From bd55775c8dd656fc69b3a42a1c4ab32abb7e8af9 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 16:20:22 -0800 Subject: xfrm: SA lookups signature with mark pass mark to all SA lookups to prepare them for when we add code to have them search. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 23 ++++++++++++++------ net/core/pktgen.c | 3 ++- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv4/ipcomp.c | 6 ++++-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/ipcomp6.c | 6 ++++-- net/ipv6/xfrm6_input.c | 2 +- net/key/af_key.c | 14 ++++++------ net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_state.c | 58 +++++++++++++++++++++++++++++--------------------- net/xfrm/xfrm_user.c | 17 +++++++++------ 13 files changed, 84 insertions(+), 55 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 39f151c7f251..693523c870b9 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1319,7 +1319,7 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); -extern struct xfrm_state * xfrm_stateonly_find(struct net *net, +extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, @@ -1328,8 +1328,14 @@ extern int xfrm_state_check_expire(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_add(struct xfrm_state *x); extern int xfrm_state_update(struct xfrm_state *x); -extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); -extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark, + xfrm_address_t *daddr, __be32 spi, + u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark, + xfrm_address_t *daddr, + xfrm_address_t *saddr, + u8 proto, + unsigned short family); #ifdef CONFIG_XFRM_SUB_POLICY extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, unsigned short family); @@ -1366,7 +1372,8 @@ struct xfrmk_spdinfo { u32 spdhmcnt; }; -extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq); +extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, + u32 seq); extern int xfrm_state_delete(struct xfrm_state *x); extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); @@ -1451,9 +1458,11 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int d int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); -struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, - xfrm_address_t *daddr, xfrm_address_t *saddr, - int create, unsigned short family); +struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark, + u8 mode, u32 reqid, u8 proto, + xfrm_address_t *daddr, + xfrm_address_t *saddr, int create, + unsigned short family); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 2e692afdc55d..43923811bd6a 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2188,12 +2188,13 @@ static inline int f_pick(struct pktgen_dev *pkt_dev) /* If there was already an IPSEC SA, we keep it as is, else * we go look for it ... */ +#define DUMMY_MARK 0 static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) { struct xfrm_state *x = pkt_dev->flows[flow].x; if (!x) { /*slow path: we dont already have xfrm_state*/ - x = xfrm_stateonly_find(&init_net, + x = xfrm_stateonly_find(&init_net, DUMMY_MARK, (xfrm_address_t *)&pkt_dev->cur_daddr, (xfrm_address_t *)&pkt_dev->cur_saddr, AF_INET, diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 7ed3e4ae93ae..987b47dc69ad 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -393,7 +393,7 @@ static void ah4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 1948895beb6d..14ca1f1c3fb0 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -422,7 +422,7 @@ static void esp4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); if (!x) return; NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 83ed71500898..629067571f02 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -36,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) return; spi = htonl(ntohs(ipch->cpi)); - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) return; @@ -63,6 +63,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) t->props.mode = x->props.mode; t->props.saddr.a4 = x->props.saddr.a4; t->props.flags = x->props.flags; + memcpy(&t->mark, &x->mark, sizeof(t->mark)); if (xfrm_init_state(t)) goto error; @@ -87,8 +88,9 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x) struct net *net = xs_net(x); int err = 0; struct xfrm_state *t; + u32 mark = x->mark.v & x->mark.m; - t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr.a4, + t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr.a4, x->props.saddr.a4, IPPROTO_IPIP, AF_INET); if (!t) { t = ipcomp_tunnel_create(x); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index c2f300c314be..5ac89025f9de 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -614,7 +614,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != ICMPV6_PKT_TOOBIG) return; - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); if (!x) return; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 668a46b655e6..ee9b93bdd6a2 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -365,7 +365,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != ICMPV6_PKT_TOOBIG) return; - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index bb42f39c1db8..85cccd6ed0b7 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -64,7 +64,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; spi = htonl(ntohs(ipcomph->cpi)); - x = xfrm_state_lookup(net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); + x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -92,6 +92,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) t->props.family = AF_INET6; t->props.mode = x->props.mode; memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); + memcpy(&t->mark, &x->mark, sizeof(t->mark)); if (xfrm_init_state(t)) goto error; @@ -114,10 +115,11 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x) int err = 0; struct xfrm_state *t = NULL; __be32 spi; + u32 mark = x->mark.m & x->mark.v; spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&x->props.saddr); if (spi) - t = xfrm_state_lookup(net, (xfrm_address_t *)&x->id.daddr, + t = xfrm_state_lookup(net, mark, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); if (!t) { t = ipcomp6_tunnel_create(x); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 9084582d236b..2bc98ede1235 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -101,7 +101,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, break; } - x = xfrm_state_lookup_byaddr(net, dst, src, proto, AF_INET6); + x = xfrm_state_lookup_byaddr(net, skb->mark, dst, src, proto, AF_INET6); if (!x) continue; diff --git a/net/key/af_key.c b/net/key/af_key.c index da2fe5f57619..aae3cd86ccd7 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -43,6 +43,8 @@ struct netns_pfkey { }; static DEFINE_MUTEX(pfkey_mutex); +#define DUMMY_MARK 0 +static struct xfrm_mark dummy_mark = {0, 0}; struct pfkey_sock { /* struct sock must be the first member of struct pfkey_sock */ struct sock sk; @@ -647,7 +649,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_ if (!xaddr) return NULL; - return xfrm_state_lookup(net, xaddr, sa->sadb_sa_spi, proto, family); + return xfrm_state_lookup(net, DUMMY_MARK, xaddr, sa->sadb_sa_spi, proto, family); } #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) @@ -1316,7 +1318,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h } if (hdr->sadb_msg_seq) { - x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq); + x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq); if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) { xfrm_state_put(x); x = NULL; @@ -1324,7 +1326,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h } if (!x) - x = xfrm_find_acq(net, mode, reqid, proto, xdaddr, xsaddr, 1, family); + x = xfrm_find_acq(net, &dummy_mark, mode, reqid, proto, xdaddr, xsaddr, 1, family); if (x == NULL) return -ENOENT; @@ -1373,7 +1375,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg * if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0) return 0; - x = xfrm_find_acq_byseq(net, hdr->sadb_msg_seq); + x = xfrm_find_acq_byseq(net, DUMMY_MARK, hdr->sadb_msg_seq); if (x == NULL) return 0; @@ -2572,8 +2574,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return -EINVAL; delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); - xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN, dir, - pol->sadb_x_policy_id, delete, &err); + xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN, + dir, pol->sadb_x_policy_id, delete, &err); if (xp == NULL) return -ENOENT; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index e0009c17d809..45f1c98d4fce 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -152,7 +152,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) goto drop; } - x = xfrm_state_lookup(net, daddr, spi, nexthdr, family); + x = xfrm_state_lookup(net, skb->mark, daddr, spi, nexthdr, family); if (x == NULL) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); xfrm_audit_state_notfound(skb, family, spi, seq); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 9fa3322b2a7d..9f8530356b86 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -669,7 +669,7 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, return 0; } -static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) +static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) { unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); struct xfrm_state *x; @@ -689,7 +689,7 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d return NULL; } -static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) +static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) { unsigned int h = xfrm_src_hash(net, daddr, saddr, family); struct xfrm_state *x; @@ -713,12 +713,14 @@ static inline struct xfrm_state * __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) { struct net *net = xs_net(x); + u32 mark = x->mark.v & x->mark.m; if (use_spi) - return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, - x->id.proto, family); + return __xfrm_state_lookup(net, mark, &x->id.daddr, + x->id.spi, x->id.proto, family); else - return __xfrm_state_lookup_byaddr(net, &x->id.daddr, + return __xfrm_state_lookup_byaddr(net, mark, + &x->id.daddr, &x->props.saddr, x->id.proto, family); } @@ -783,6 +785,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, int acquire_in_progress = 0; int error = 0; struct xfrm_state *best = NULL; + u32 mark = pol->mark.v & pol->mark.m; to_put = NULL; @@ -819,7 +822,7 @@ found: x = best; if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && - (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, + (x0 = __xfrm_state_lookup(net, mark, daddr, tmpl->id.spi, tmpl->id.proto, family)) != NULL) { to_put = x0; error = -EEXIST; @@ -833,6 +836,7 @@ found: /* Initialize temporary selector matching only * to current session. */ xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); + memcpy(&x->mark, &pol->mark, sizeof(x->mark)); error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); if (error) { @@ -875,7 +879,7 @@ out: } struct xfrm_state * -xfrm_stateonly_find(struct net *net, +xfrm_stateonly_find(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, u8 mode, u8 proto, u32 reqid) { @@ -971,7 +975,7 @@ void xfrm_state_insert(struct xfrm_state *x) EXPORT_SYMBOL(xfrm_state_insert); /* xfrm_state_lock is held */ -static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) +static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) { unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); struct hlist_node *entry; @@ -1026,6 +1030,8 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family x->props.family = family; x->props.mode = mode; x->props.reqid = reqid; + x->mark.v = m->v; + x->mark.m = m->m; x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; xfrm_state_hold(x); tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); @@ -1042,7 +1048,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family return x; } -static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); +static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq); int xfrm_state_add(struct xfrm_state *x) { @@ -1050,6 +1056,7 @@ int xfrm_state_add(struct xfrm_state *x) struct xfrm_state *x1, *to_put; int family; int err; + u32 mark = x->mark.v & x->mark.m; int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); family = x->props.family; @@ -1067,7 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x) } if (use_spi && x->km.seq) { - x1 = __xfrm_find_acq_byseq(net, x->km.seq); + x1 = __xfrm_find_acq_byseq(net, mark, x->km.seq); if (x1 && ((x1->id.proto != x->id.proto) || xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { to_put = x1; @@ -1076,8 +1083,8 @@ int xfrm_state_add(struct xfrm_state *x) } if (use_spi && !x1) - x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, - x->id.proto, + x1 = __find_acq_core(net, &x->mark, family, x->props.mode, + x->props.reqid, x->id.proto, &x->id.daddr, &x->props.saddr, 0); __xfrm_state_bump_genids(x); @@ -1151,6 +1158,8 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) goto error; } + memcpy(&x->mark, &orig->mark, sizeof(x->mark)); + err = xfrm_init_state(x); if (err) goto error; @@ -1342,41 +1351,41 @@ int xfrm_state_check_expire(struct xfrm_state *x) EXPORT_SYMBOL(xfrm_state_check_expire); struct xfrm_state * -xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, - unsigned short family) +xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, + u8 proto, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup(net, daddr, spi, proto, family); + x = __xfrm_state_lookup(net, mark, daddr, spi, proto, family); spin_unlock_bh(&xfrm_state_lock); return x; } EXPORT_SYMBOL(xfrm_state_lookup); struct xfrm_state * -xfrm_state_lookup_byaddr(struct net *net, +xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); + x = __xfrm_state_lookup_byaddr(net, mark, daddr, saddr, proto, family); spin_unlock_bh(&xfrm_state_lock); return x; } EXPORT_SYMBOL(xfrm_state_lookup_byaddr); struct xfrm_state * -xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, +xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); + x = __find_acq_core(net, mark, family, mode, reqid, proto, daddr, saddr, create); spin_unlock_bh(&xfrm_state_lock); return x; @@ -1423,7 +1432,7 @@ EXPORT_SYMBOL(xfrm_state_sort); /* Silly enough, but I'm lazy to build resolution list */ -static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) +static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq) { int i; @@ -1442,12 +1451,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) return NULL; } -struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) +struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_find_acq_byseq(net, seq); + x = __xfrm_find_acq_byseq(net, mark, seq); spin_unlock_bh(&xfrm_state_lock); return x; } @@ -1474,6 +1483,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) int err = -ENOENT; __be32 minspi = htonl(low); __be32 maxspi = htonl(high); + u32 mark = x->mark.v & x->mark.m; spin_lock_bh(&x->lock); if (x->km.state == XFRM_STATE_DEAD) @@ -1486,7 +1496,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) err = -ENOENT; if (minspi == maxspi) { - x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); + x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); if (x0) { xfrm_state_put(x0); goto unlock; @@ -1496,7 +1506,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) u32 spi = 0; for (h=0; hid.daddr, htonl(spi), x->id.proto, x->props.family); + x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); if (x0 == NULL) { x->id.spi = htonl(spi); break; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ee04e6bf0e54..331ae731080a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -31,6 +31,9 @@ #include #endif +#define DUMMY_MARK 0 +static struct xfrm_mark dummy_mark = {0, 0}; + static inline int aead_len(struct xfrm_algo_aead *alg) { return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); @@ -530,7 +533,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { err = -ESRCH; - x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family); + x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family); } else { xfrm_address_t *saddr = NULL; @@ -541,7 +544,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, } err = -ESRCH; - x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr, + x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr, p->proto, p->family); } @@ -958,7 +961,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, x = NULL; if (p->info.seq) { - x = xfrm_find_acq_byseq(net, p->info.seq); + x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq); if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { xfrm_state_put(x); x = NULL; @@ -966,7 +969,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, } if (!x) - x = xfrm_find_acq(net, p->info.mode, p->info.reqid, + x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid, p->info.id.proto, daddr, &p->info.saddr, 1, family); @@ -1598,7 +1601,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (r_skb == NULL) return -ENOMEM; - x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family); + x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family); if (x == NULL) { kfree_skb(r_skb); return -ESRCH; @@ -1640,7 +1643,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) return err; - x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); if (x == NULL) return -ESRCH; @@ -1767,7 +1770,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_usersa_info *p = &ue->state; - x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family); + x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family); err = -ENOENT; if (x == NULL) -- cgit v1.2.3 From 3d6acfa7641fd0a35f608b142f61e79f7ed8db43 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:32:56 +0000 Subject: xfrm: SA lookups with mark Allow mark to be added to the SA lookup Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_state.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 9f8530356b86..17d5b96f2fc8 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -682,6 +682,8 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_ad xfrm_addr_cmp(&x->id.daddr, daddr, family)) continue; + if ((mark & x->mark.m) != x->mark.v) + continue; xfrm_state_hold(x); return x; } @@ -702,6 +704,8 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_addr_cmp(&x->props.saddr, saddr, family)) continue; + if ((mark & x->mark.m) != x->mark.v) + continue; xfrm_state_hold(x); return x; } @@ -794,6 +798,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == tmpl->reqid && + (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && tmpl->mode == x->props.mode && @@ -809,6 +814,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { if (x->props.family == family && x->props.reqid == tmpl->reqid && + (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && tmpl->mode == x->props.mode && @@ -892,6 +898,7 @@ xfrm_stateonly_find(struct net *net, u32 mark, hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == reqid && + (mark & x->mark.m) == x->mark.v && !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && mode == x->props.mode && @@ -954,11 +961,13 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew) struct xfrm_state *x; struct hlist_node *entry; unsigned int h; + u32 mark = xnew->mark.v & xnew->mark.m; h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == reqid && + (mark & x->mark.m) == x->mark.v && !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) x->genid = xfrm_state_genid; @@ -980,6 +989,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); struct hlist_node *entry; struct xfrm_state *x; + u32 mark = m->v & m->m; hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.reqid != reqid || @@ -988,6 +998,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, x->km.state != XFRM_STATE_ACQ || x->id.spi != 0 || x->id.proto != proto || + (mark & x->mark.m) != x->mark.v || xfrm_addr_cmp(&x->id.daddr, daddr, family) || xfrm_addr_cmp(&x->props.saddr, saddr, family)) continue; @@ -1442,6 +1453,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 mark, u32 s hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { if (x->km.seq == seq && + (mark & x->mark.m) == x->mark.v && x->km.state == XFRM_STATE_ACQ) { xfrm_state_hold(x); return x; -- cgit v1.2.3 From 8ca2e93b557f2a0b35f7769038abf600177e1122 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:32:57 +0000 Subject: xfrm: SP lookups signature with mark pass mark to all SP lookups to prepare them for when we add code to have them search. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- include/net/xfrm.h | 5 +++-- net/key/af_key.c | 4 ++-- net/xfrm/xfrm_policy.c | 8 ++++---- net/xfrm/xfrm_user.c | 10 +++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 693523c870b9..a7df3275b860 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1450,11 +1450,12 @@ extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *); extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, +struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, + u8 type, int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err); -struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err); +struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, u32 id, int delete, int *err); int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); diff --git a/net/key/af_key.c b/net/key/af_key.c index aae3cd86ccd7..368707882647 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2326,7 +2326,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg return err; } - xp = xfrm_policy_bysel_ctx(net, XFRM_POLICY_TYPE_MAIN, + xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir - 1, &sel, pol_ctx, 1, &err); security_xfrm_policy_free(pol_ctx); @@ -2574,7 +2574,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return -EINVAL; delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); - xp = xfrm_policy_byid(net, XFRM_POLICY_TYPE_MAIN, + xp = xfrm_policy_byid(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, delete, &err); if (xp == NULL) return -ENOENT; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d6eb16d75243..e67d3ca6e657 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -635,8 +635,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) } EXPORT_SYMBOL(xfrm_policy_insert); -struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, - struct xfrm_selector *sel, +struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, + int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err) { @@ -676,8 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); -struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, - int delete, int *err) +struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, + int dir, u32 id, int delete, int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 331ae731080a..02a67b4a64dd 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1457,7 +1457,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err); + xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, delete, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1474,8 +1474,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, - delete, &err); + xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, + &p->sel, ctx, delete, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) @@ -1712,7 +1712,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err); + xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, 0, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1729,7 +1729,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err); + xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) -- cgit v1.2.3 From 34f8d8846f69f3b5bc3916ba9145e4eebae9394e Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:32:58 +0000 Subject: xfrm: SP lookups with mark Allow mark to be used when doing SP lookup Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_policy.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index e67d3ca6e657..2a6e64652654 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -556,6 +556,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) struct hlist_head *chain; struct hlist_node *entry, *newpos; struct dst_entry *gc_list; + u32 mark = policy->mark.v & policy->mark.m; write_lock_bh(&xfrm_policy_lock); chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); @@ -564,6 +565,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) hlist_for_each_entry(pol, entry, chain, bydst) { if (pol->type == policy->type && !selector_cmp(&pol->selector, &policy->selector) && + (mark & pol->mark.m) == pol->mark.v && xfrm_sec_ctx_match(pol->security, policy->security) && !WARN_ON(delpol)) { if (excl) { @@ -650,6 +652,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, ret = NULL; hlist_for_each_entry(pol, entry, chain, bydst) { if (pol->type == type && + (mark & pol->mark.m) == pol->mark.v && !selector_cmp(sel, &pol->selector) && xfrm_sec_ctx_match(ctx, pol->security)) { xfrm_pol_hold(pol); @@ -692,7 +695,8 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, chain = net->xfrm.policy_byidx + idx_hash(net, id); ret = NULL; hlist_for_each_entry(pol, entry, chain, byidx) { - if (pol->type == type && pol->index == id) { + if (pol->type == type && pol->index == id && + (mark & pol->mark.m) == pol->mark.v) { xfrm_pol_hold(pol); if (delete) { *err = security_xfrm_policy_delete( @@ -916,6 +920,7 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, int match, ret = -ESRCH; if (pol->family != family || + (fl->mark & pol->mark.m) != pol->mark.v || pol->type != type) return ret; @@ -1040,6 +1045,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc int err = 0; if (match) { + if ((sk->sk_mark & pol->mark.m) != pol->mark.v) { + pol = NULL; + goto out; + } err = security_xfrm_policy_lookup(pol->security, fl->secid, policy_to_flow_dir(dir)); @@ -1052,6 +1061,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc } else pol = NULL; } +out: read_unlock_bh(&xfrm_policy_lock); return pol; } -- cgit v1.2.3 From 6f26b61e177e57a41795355f6222cf817f1212dc Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:32:59 +0000 Subject: xfrm: Allow user space config of SAD mark Add ability for netlink userspace to manipulate the SAD and manipulate the mark, retrieve it and get events with a defined mark. MIGRATE may be added later. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 72 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 02a67b4a64dd..303092f7088b 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -32,7 +32,6 @@ #endif #define DUMMY_MARK 0 -static struct xfrm_mark dummy_mark = {0, 0}; static inline int aead_len(struct xfrm_algo_aead *alg) { @@ -449,6 +448,8 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; } + xfrm_mark_get(attrs, &x->mark); + err = xfrm_init_state(x); if (err) goto error; @@ -529,11 +530,13 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, int *errp) { struct xfrm_state *x = NULL; + struct xfrm_mark m; int err; + u32 mark = xfrm_mark_get(attrs, &m); if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { err = -ESRCH; - x = xfrm_state_lookup(net, DUMMY_MARK, &p->daddr, p->spi, p->proto, p->family); + x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); } else { xfrm_address_t *saddr = NULL; @@ -544,7 +547,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct net *net, } err = -ESRCH; - x = xfrm_state_lookup_byaddr(net, DUMMY_MARK, &p->daddr, saddr, + x = xfrm_state_lookup_byaddr(net, mark, + &p->daddr, saddr, p->proto, p->family); } @@ -686,6 +690,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x, if (x->encap) NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); + if (xfrm_mark_put(skb, &x->mark)) + goto nla_put_failure; + if (x->security && copy_sec_ctx(x->security, skb) < 0) goto nla_put_failure; @@ -950,6 +957,8 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, xfrm_address_t *daddr; int family; int err; + u32 mark; + struct xfrm_mark m; p = nlmsg_data(nlh); err = verify_userspi_info(p); @@ -960,8 +969,10 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, daddr = &p->info.id.daddr; x = NULL; + + mark = xfrm_mark_get(attrs, &m); if (p->info.seq) { - x = xfrm_find_acq_byseq(net, DUMMY_MARK, p->info.seq); + x = xfrm_find_acq_byseq(net, mark, p->info.seq); if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { xfrm_state_put(x); x = NULL; @@ -969,7 +980,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, } if (!x) - x = xfrm_find_acq(net, &dummy_mark, p->info.mode, p->info.reqid, + x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, p->info.id.proto, daddr, &p->info.saddr, 1, family); @@ -1474,8 +1485,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, - &p->sel, ctx, delete, &err); + xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, + ctx, delete, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) @@ -1547,6 +1558,7 @@ static inline size_t xfrm_aevent_msgsize(void) return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) + nla_total_size(sizeof(struct xfrm_replay_state)) + nla_total_size(sizeof(struct xfrm_lifetime_cur)) + + nla_total_size(sizeof(struct xfrm_mark)) + nla_total_size(4) /* XFRM_AE_RTHR */ + nla_total_size(4); /* XFRM_AE_ETHR */ } @@ -1579,6 +1591,9 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, x->replay_maxage * 10 / HZ); + if (xfrm_mark_put(skb, &x->mark)) + goto nla_put_failure; + return nlmsg_end(skb, nlh); nla_put_failure: @@ -1594,6 +1609,8 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, struct sk_buff *r_skb; int err; struct km_event c; + u32 mark; + struct xfrm_mark m; struct xfrm_aevent_id *p = nlmsg_data(nlh); struct xfrm_usersa_id *id = &p->sa_id; @@ -1601,7 +1618,9 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (r_skb == NULL) return -ENOMEM; - x = xfrm_state_lookup(net, DUMMY_MARK, &id->daddr, id->spi, id->proto, id->family); + mark = xfrm_mark_get(attrs, &m); + + x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); if (x == NULL) { kfree_skb(r_skb); return -ESRCH; @@ -1632,6 +1651,8 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_state *x; struct km_event c; int err = - EINVAL; + u32 mark = 0; + struct xfrm_mark m; struct xfrm_aevent_id *p = nlmsg_data(nlh); struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; @@ -1643,7 +1664,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) return err; - x = xfrm_state_lookup(net, DUMMY_MARK, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + mark = xfrm_mark_get(attrs, &m); + + x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); if (x == NULL) return -ESRCH; @@ -1729,7 +1752,8 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, ctx, 0, &err); + xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, + &p->sel, ctx, 0, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) @@ -1769,8 +1793,10 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, int err; struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_usersa_info *p = &ue->state; + struct xfrm_mark m; + u32 mark = xfrm_mark_get(attrs, &m);; - x = xfrm_state_lookup(net, DUMMY_MARK, &p->id.daddr, p->id.spi, p->id.proto, p->family); + x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); err = -ENOENT; if (x == NULL) @@ -1804,6 +1830,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_user_tmpl *ut; int i; struct nlattr *rt = attrs[XFRMA_TMPL]; + struct xfrm_mark mark; struct xfrm_user_acquire *ua = nlmsg_data(nlh); struct xfrm_state *x = xfrm_state_alloc(net); @@ -1812,6 +1839,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, if (!x) goto nomem; + xfrm_mark_get(attrs, &mark); + err = verify_newpolicy_info(&ua->policy); if (err) goto bad_policy; @@ -1824,7 +1853,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, memcpy(&x->id, &ua->id, sizeof(ua->id)); memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); - + xp->mark.m = x->mark.m = mark.m; + xp->mark.v = x->mark.v = mark.v; ut = nla_data(rt); /* extract the templates and for each call km_key */ for (i = 0; i < xp->xfrm_nr; i++, ut++) { @@ -2084,6 +2114,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, + [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, }; static struct xfrm_link { @@ -2163,7 +2194,8 @@ static void xfrm_netlink_rcv(struct sk_buff *skb) static inline size_t xfrm_expire_msgsize(void) { - return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)); + return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) + + nla_total_size(sizeof(struct xfrm_mark)); } static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) @@ -2179,7 +2211,13 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve copy_to_user_state(x, &ue->state); ue->hard = (c->data.hard != 0) ? 1 : 0; + if (xfrm_mark_put(skb, &x->mark)) + goto nla_put_failure; + return nlmsg_end(skb, nlh); + +nla_put_failure: + return -EMSGSIZE; } static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) @@ -2191,8 +2229,10 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) if (skb == NULL) return -ENOMEM; - if (build_expire(skb, x, c) < 0) - BUG(); + if (build_expire(skb, x, c) < 0) { + kfree_skb(skb); + return -EMSGSIZE; + } return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); } @@ -2280,6 +2320,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) if (c->event == XFRM_MSG_DELSA) { len += nla_total_size(headlen); headlen = sizeof(*id); + len += nla_total_size(sizeof(struct xfrm_mark)); } len += NLMSG_ALIGN(headlen); @@ -2350,6 +2391,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, { return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) + + nla_total_size(sizeof(struct xfrm_mark)) + nla_total_size(xfrm_user_sec_ctx_size(x->security)) + userpolicy_type_attrsize(); } -- cgit v1.2.3 From 295fae568885a93c39a0e29a9455054608b6cc0e Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Mon, 22 Feb 2010 11:33:00 +0000 Subject: xfrm: Allow user space manipulation of SPD mark Add ability for netlink userspace to manipulate the SPD and manipulate the mark, retrieve it and get events with a defined mark, etc. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 303092f7088b..6106b72826d3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -31,8 +31,6 @@ #include #endif -#define DUMMY_MARK 0 - static inline int aead_len(struct xfrm_algo_aead *alg) { return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); @@ -1234,6 +1232,8 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_us if (err) goto error; + xfrm_mark_get(attrs, &xp->mark); + return xp; error: *errp = err; @@ -1380,10 +1380,13 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr goto nlmsg_failure; if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; + if (xfrm_mark_put(skb, &xp->mark)) + goto nla_put_failure; nlmsg_end(skb, nlh); return 0; +nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; @@ -1455,6 +1458,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, int err; struct km_event c; int delete; + struct xfrm_mark m; + u32 mark = xfrm_mark_get(attrs, &m); p = nlmsg_data(nlh); delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; @@ -1468,7 +1473,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, delete, &err); + xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1485,7 +1490,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, &p->sel, + xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, ctx, delete, &err); security_xfrm_policy_free(ctx); } @@ -1729,13 +1734,15 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_userpolicy_info *p = &up->pol; u8 type = XFRM_POLICY_TYPE_MAIN; int err = -ENOENT; + struct xfrm_mark m; + u32 mark = xfrm_mark_get(attrs, &m); err = copy_from_user_policy_type(&type, attrs); if (err) return err; if (p->index) - xp = xfrm_policy_byid(net, DUMMY_MARK, type, p->dir, p->index, 0, &err); + xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1752,7 +1759,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, type, p->dir, + xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, ctx, 0, &err); security_xfrm_policy_free(ctx); } @@ -2424,9 +2431,12 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, goto nlmsg_failure; if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; + if (xfrm_mark_put(skb, &xp->mark)) + goto nla_put_failure; return nlmsg_end(skb, nlh); +nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; @@ -2513,6 +2523,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) + + nla_total_size(sizeof(struct xfrm_mark)) + userpolicy_type_attrsize(); } @@ -2535,10 +2546,13 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, goto nlmsg_failure; if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; + if (xfrm_mark_put(skb, &xp->mark)) + goto nla_put_failure; upe->hard = !!hard; return nlmsg_end(skb, nlh); +nla_put_failure: nlmsg_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; @@ -2575,6 +2589,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * headlen = sizeof(*id); } len += userpolicy_type_attrsize(); + len += nla_total_size(sizeof(struct xfrm_mark)); len += NLMSG_ALIGN(headlen); skb = nlmsg_new(len, GFP_ATOMIC); @@ -2610,10 +2625,14 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * if (copy_to_user_policy_type(xp->type, skb) < 0) goto nlmsg_failure; + if (xfrm_mark_put(skb, &xp->mark)) + goto nla_put_failure; + nlmsg_end(skb, nlh); return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); +nla_put_failure: nlmsg_failure: kfree_skb(skb); return -1; -- cgit v1.2.3 From 10886af54a2478f97f2d5f89bbe270b99206f8ab Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 23 Feb 2010 01:19:22 -0800 Subject: e1000: correct wrong coding style for "else" Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c99f95c1b418..319c2b5281e9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2170,8 +2170,7 @@ static void e1000_set_rx_mode(struct net_device *netdev) hash_bit = hash_value & 0x1F; mta = (1 << hash_bit); mcarray[hash_reg] |= mta; - } - else { + } else { e1000_rar_set(hw, mc_ptr->da_addr, i++); } } -- cgit v1.2.3 From 2c08522e5d2f0af2d6f05be558946dcbf8173683 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Tue, 23 Feb 2010 14:55:21 +0100 Subject: netfilter: xt_recent: fix buffer overflow e->index overflows e->stamps[] every ip_pkt_list_tot packets. Consider the case when ip_pkt_list_tot==1; the first packet received is stored in e->stamps[0] and e->index is initialized to 1. The next received packet timestamp is then stored at e->stamps[1] in recent_entry_update(), a buffer overflow because the maximum e->stamps[] index is 0. Signed-off-by: Tim Gardner Cc: stable@kernel.org Signed-off-by: Patrick McHardy --- net/netfilter/xt_recent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 132cfaa84cdc..1278f0aa7434 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -177,10 +177,10 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, static void recent_entry_update(struct recent_table *t, struct recent_entry *e) { + e->index %= ip_pkt_list_tot; e->stamps[e->index++] = jiffies; if (e->index > e->nstamps) e->nstamps = e->index; - e->index %= ip_pkt_list_tot; list_move_tail(&e->lru_list, &t->lru_list); } -- cgit v1.2.3 From 8ccb92ad41cb311e52ad1b1fe77992c7f47a3b63 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Tue, 23 Feb 2010 14:59:12 +0100 Subject: netfilter: xt_recent: fix false match A rule with a zero hit_count will always match. Signed-off-by: Tim Gardner Cc: stable@kernel.org Signed-off-by: Patrick McHardy --- net/netfilter/xt_recent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 1278f0aa7434..7073dbb8100c 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -267,7 +267,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) for (i = 0; i < e->nstamps; i++) { if (info->seconds && time_after(time, e->stamps[i])) continue; - if (++hits >= info->hit_count) { + if (info->hit_count && ++hits >= info->hit_count) { ret = !ret; break; } -- cgit v1.2.3 From ab9bdc34d68dafc6fea0ba733231f1c9696ce9c4 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 23 Feb 2010 14:02:52 -0800 Subject: Revert "iwlwifi: Monitor and recover the aggregation TX flow failure" This reverts commit 1db5950f1d0b82e07371b211a48317b8972da063. The goal of "iwlwifi: Monitor and recover the aggregation TX flow failure" is to first detect when data transmission stalls and then to recover from this situation with a reset of the radio or the firmware, depending on how bad the transmission failures are. Unfortunately we have found that this change causes excessive resets with its current detection algorithm. It also performs its recovery action when none is really needed, like when we are not associated. Revert this change until the issues have been addressed. Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 14 +---------- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 --- drivers/net/wireless/iwlwifi/iwl-rx.c | 46 ---------------------------------- 3 files changed, 1 insertion(+), 62 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c5b724eaf306..1fac015efc19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2941,21 +2941,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); - if (ret == 0) { - priv->agg_tids_count++; - IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", - priv->agg_tids_count); - } - return ret; + return iwl_tx_agg_start(priv, sta->addr, tid, ssn); case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); ret = iwl_tx_agg_stop(priv, sta->addr, tid); - if ((ret == 0) && (priv->agg_tids_count > 0)) { - priv->agg_tids_count--; - IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", - priv->agg_tids_count); - } if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else @@ -3376,7 +3365,6 @@ static int iwl_init_drv(struct iwl_priv *priv) priv->iw_mode = NL80211_IFTYPE_STATION; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; - priv->agg_tids_count = 0; /* initialize force reset */ priv->force_reset[IWL_RF_RESET].reset_duration = diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7914d65a5a55..ab891b958042 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1084,9 +1084,6 @@ struct iwl_priv { /* storing the jiffies when the plcp error rate is received */ unsigned long plcp_jiffies; - /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ - u8 agg_tids_count; - /* force reset */ struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index fed554accedc..aba8f4c20c1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -616,11 +616,6 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, #define REG_RECALIB_PERIOD (60) -/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ -#define ACK_CNT_RATIO (50) -#define BA_TIMEOUT_CNT (5) -#define BA_TIMEOUT_MAX (16) - #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" void iwl_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) @@ -630,9 +625,6 @@ void iwl_rx_statistics(struct iwl_priv *priv, int combined_plcp_delta; unsigned int plcp_msec; unsigned long plcp_received_jiffies; - int actual_ack_cnt_delta; - int expected_ack_cnt_delta; - int ba_timeout_delta; IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", (int)sizeof(priv->statistics), @@ -647,44 +639,6 @@ void iwl_rx_statistics(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif - actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - - le32_to_cpu(priv->statistics.tx.actual_ack_cnt); - expected_ack_cnt_delta = le32_to_cpu( - pkt->u.stats.tx.expected_ack_cnt) - - le32_to_cpu(priv->statistics.tx.expected_ack_cnt); - ba_timeout_delta = le32_to_cpu( - pkt->u.stats.tx.agg.ba_timeout) - - le32_to_cpu(priv->statistics.tx.agg.ba_timeout); - if ((priv->agg_tids_count > 0) && - (expected_ack_cnt_delta > 0) && - (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < - ACK_CNT_RATIO) && - (ba_timeout_delta > BA_TIMEOUT_CNT)) { - IWL_DEBUG_RADIO(priv, - "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", - actual_ack_cnt_delta, expected_ack_cnt_delta); - -#ifdef CONFIG_IWLWIFI_DEBUG - IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", - priv->delta_statistics.tx.rx_detected_cnt); - IWL_DEBUG_RADIO(priv, - "ack_or_ba_timeout_collision delta = %d\n", - priv->delta_statistics.tx.ack_or_ba_timeout_collision); -#endif - IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", - ba_timeout_delta); - if ((actual_ack_cnt_delta == 0) && - (ba_timeout_delta >= - BA_TIMEOUT_MAX)) { - IWL_DEBUG_RADIO(priv, - "call iwl_force_reset(IWL_FW_RESET)\n"); - iwl_force_reset(priv, IWL_FW_RESET); - } else { - IWL_DEBUG_RADIO(priv, - "call iwl_force_reset(IWL_RF_RESET)\n"); - iwl_force_reset(priv, IWL_RF_RESET); - } - } /* * check for plcp_err and trigger radio reset if it exceeds * the plcp error threshold plcp_delta. -- cgit v1.2.3 From 89612124d6d62230043ebd827a2b54ea5ea5280c Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 19 Feb 2010 11:49:49 -0800 Subject: iwlwifi: increase command buffer size Increase the buffer size for commands with "huge" bit set. This has been recently observed for 6050 cards where for even with huge bit set few commands were not properly allocated memory with the command overwriting the buffer allocated for it.. Also add a check to see if command size exceeds the maximum allowable size. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl-tx.c | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e91507531923..cfd6c8423113 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2612,6 +2612,7 @@ struct iwl_ssid_ie { #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) #define IWL_GOOD_CRC_TH cpu_to_le16(1) #define IWL_MAX_SCAN_SIZE 1024 +#define IWL_MAX_CMD_SIZE 4096 #define IWL_MAX_PROBE_REQUEST 200 /* diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 8f4071562857..066491fc75f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -366,7 +366,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, for (i = 0; i < actual_slots; i++) { /* only happens for cmd queue */ if (i == slots_num) - len += IWL_MAX_SCAN_SIZE; + len = IWL_MAX_CMD_SIZE; txq->cmd[i] = kmalloc(len, GFP_KERNEL); if (!txq->cmd[i]) @@ -1027,9 +1027,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* If any of the command structures end up being larger than * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries */ + * we will need to increase the size of the TFD entries + * Also, check to see if command buffer should not exceed the size + * of device_cmd and max_cmd_size. */ BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->flags & CMD_SIZE_HUGE)); + BUG_ON(fix_size > IWL_MAX_CMD_SIZE); if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { IWL_WARN(priv, "Not sending command - %s KILL\n", @@ -1073,8 +1076,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (cmd->flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; len = sizeof(struct iwl_device_cmd); - len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; - + if (idx == TFD_CMD_SLOTS) + len = IWL_MAX_CMD_SIZE; #ifdef CONFIG_IWLWIFI_DEBUG switch (out_cmd->hdr.cmd) { -- cgit v1.2.3 From fb977e2ca607a7e74946a1de798f474d1b80b9d6 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Tue, 23 Feb 2010 15:09:53 -0800 Subject: xfrm: clone mark when cloning policy When we clone the SP, we should also clone the mark. Useful for socket based SPs. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/xfrm/xfrm_policy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 2a6e64652654..34a5ef8316e7 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1154,6 +1154,7 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) } newp->lft = old->lft; newp->curlft = old->curlft; + newp->mark = old->mark; newp->action = old->action; newp->flags = old->flags; newp->xfrm_nr = old->xfrm_nr; -- cgit v1.2.3 From 72b2b1dd77e8feb0b7c0b26dee58f2a1e2c9828c Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Feb 2010 18:32:59 +0100 Subject: netfilter: xtables: replace XT_ENTRY_ITERATE macro The macro is replaced by a list.h-like foreach loop. This makes the code much more inspectable. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 9 ++ include/linux/netfilter_arp/arp_tables.h | 10 +- include/linux/netfilter_ipv4/ip_tables.h | 11 +- include/linux/netfilter_ipv6/ip6_tables.h | 10 +- net/ipv4/netfilter/arp_tables.c | 151 ++++++++++++++++++---------- net/ipv4/netfilter/ip_tables.c | 160 +++++++++++++++++++----------- net/ipv6/netfilter/ip6_tables.c | 160 +++++++++++++++++++----------- 7 files changed, 321 insertions(+), 190 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index a18119fb88f0..9df3f5a8f9f7 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -139,6 +139,7 @@ struct xt_counters_info { __ret; \ }) +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \ ({ \ @@ -163,6 +164,14 @@ struct xt_counters_info { #define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \ XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args) +#endif /* !__KERNEL__ */ + +/* pos is normally a struct ipt_entry/ip6t_entry/etc. */ +#define xt_entry_foreach(pos, ehead, esize) \ + for ((pos) = (typeof(pos))(ehead); \ + (pos) < (typeof(pos))((char *)(ehead) + (esize)); \ + (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset)) + #ifdef __KERNEL__ #include diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 0b33980611b2..e9948c0560f6 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -211,9 +211,11 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e return (void *)e + e->target_offset; } +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args) +#endif /* * Main firewall chains definitions and global var's definitions. @@ -291,14 +293,6 @@ compat_arpt_get_target(struct compat_arpt_entry *e) #define COMPAT_ARPT_ALIGN(s) COMPAT_XT_ALIGN(s) -/* fn returns 0 to continue iteration */ -#define COMPAT_ARPT_ENTRY_ITERATE(entries, size, fn, args...) \ - XT_ENTRY_ITERATE(struct compat_arpt_entry, entries, size, fn, ## args) - -#define COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ - XT_ENTRY_ITERATE_CONTINUE(struct compat_arpt_entry, entries, size, n, \ - fn, ## args) - #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _ARPTABLES_H */ diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 364973b42133..5b20ae724b41 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -227,9 +227,11 @@ ipt_get_target(struct ipt_entry *e) #define IPT_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) +#endif /* * Main firewall chains definitions and global var's definitions. @@ -317,15 +319,6 @@ compat_ipt_get_target(struct compat_ipt_entry *e) #define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args) -/* fn returns 0 to continue iteration */ -#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \ - XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args) - -/* fn returns 0 to continue iteration */ -#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ - XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \ - fn, ## args) - #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IPTABLES_H */ diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 8031eb486a10..8bb3f5ba5ff2 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -284,9 +284,11 @@ ip6t_get_target(struct ip6t_entry *e) #define IP6T_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) +#endif /* * Main firewall chains definitions and global var's definitions. @@ -345,14 +347,6 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e) #define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args) -/* fn returns 0 to continue iteration */ -#define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ - XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args) - -#define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ - XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \ - fn, ## args) - #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IP6_TABLES_H */ diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4db5c1ece0f9..f7338869fc4c 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -641,8 +641,9 @@ static int translate_table(const char *name, const unsigned int *hook_entries, const unsigned int *underflows) { + struct arpt_entry *iter; unsigned int i; - int ret; + int ret = 0; newinfo->size = size; newinfo->number = number; @@ -657,12 +658,13 @@ static int translate_table(const char *name, i = 0; /* Walk through entries, checking offsets. */ - ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, - check_entry_size_and_hooks, - newinfo, - entry0, - entry0 + size, - hook_entries, underflows, valid_hooks, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = check_entry_size_and_hooks(iter, newinfo, entry0, + entry0 + size, hook_entries, underflows, + valid_hooks, &i); + if (ret != 0) + break; + } duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); if (ret != 0) return ret; @@ -697,12 +699,16 @@ static int translate_table(const char *name, /* Finally, each sanity check must pass */ i = 0; - ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, - find_check_entry, name, size, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = find_check_entry(iter, name, size, &i); + if (ret != 0) + break; + } if (ret != 0) { - ARPT_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, &i); + xt_entry_foreach(iter, entry0, newinfo->size) + if (cleanup_entry(iter, &i) != 0) + break; return ret; } @@ -739,6 +745,7 @@ static inline int set_entry_to_counter(const struct arpt_entry *e, static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) { + struct arpt_entry *iter; unsigned int cpu; unsigned int i; unsigned int curcpu; @@ -754,22 +761,18 @@ static void get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - ARPT_ENTRY_ITERATE(t->entries[curcpu], - t->size, - set_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[curcpu], t->size) + if (set_entry_to_counter(iter, counters, &i) != 0) + break; for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - ARPT_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[cpu], t->size) + if (add_entry_to_counter(iter, counters, &i) != 0) + break; xt_info_wrunlock(cpu); } local_bh_enable(); @@ -899,7 +902,9 @@ static int compat_calc_entry(const struct arpt_entry *e, static int compat_table_info(const struct xt_table_info *info, struct xt_table_info *newinfo) { + struct arpt_entry *iter; void *loc_cpu_entry; + int ret = 0; if (!newinfo || !info) return -EINVAL; @@ -908,9 +913,12 @@ static int compat_table_info(const struct xt_table_info *info, memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); newinfo->initial_entries = 0; loc_cpu_entry = info->entries[raw_smp_processor_id()]; - return ARPT_ENTRY_ITERATE(loc_cpu_entry, info->size, - compat_calc_entry, info, loc_cpu_entry, - newinfo); + xt_entry_foreach(iter, loc_cpu_entry, info->size) { + ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); + if (ret != 0) + break; + } + return ret; } #endif @@ -1025,6 +1033,7 @@ static int __do_replace(struct net *net, const char *name, struct xt_table_info *oldinfo; struct xt_counters *counters; void *loc_cpu_old_entry; + struct arpt_entry *iter; ret = 0; counters = vmalloc_node(num_counters * sizeof(struct xt_counters), @@ -1068,8 +1077,9 @@ static int __do_replace(struct net *net, const char *name, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; - ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, - NULL); + xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) + if (cleanup_entry(iter, NULL) != 0) + break; xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, @@ -1095,6 +1105,7 @@ static int do_replace(struct net *net, const void __user *user, struct arpt_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct arpt_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1130,7 +1141,9 @@ static int do_replace(struct net *net, const void __user *user, return 0; free_newinfo_untrans: - ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1163,6 +1176,7 @@ static int do_add_counters(struct net *net, const void __user *user, const struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; + struct arpt_entry *iter; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1220,11 +1234,9 @@ static int do_add_counters(struct net *net, const void __user *user, curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; xt_info_wrlock(curcpu); - ARPT_ENTRY_ITERATE(loc_cpu_entry, - private->size, - add_counter_to_entry, - paddc, - &i); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (add_counter_to_entry(iter, paddc, &i) != 0) + break; xt_info_wrunlock(curcpu); unlock_up_free: local_bh_enable(); @@ -1388,8 +1400,10 @@ static int translate_compat_table(const char *name, unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; + struct compat_arpt_entry *iter0; + struct arpt_entry *iter1; unsigned int size; - int ret; + int ret = 0; info = *pinfo; entry0 = *pentry0; @@ -1406,11 +1420,13 @@ static int translate_compat_table(const char *name, j = 0; xt_compat_lock(NFPROTO_ARP); /* Walk through entries, checking offsets. */ - ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, - check_compat_entry_size_and_hooks, - info, &size, entry0, - entry0 + total_size, - hook_entries, underflows, &j, name); + xt_entry_foreach(iter0, entry0, total_size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, entry0 + total_size, hook_entries, underflows, + &j, name); + if (ret != 0) + break; + } if (ret != 0) goto out_unlock; @@ -1451,9 +1467,12 @@ static int translate_compat_table(const char *name, entry1 = newinfo->entries[raw_smp_processor_id()]; pos = entry1; size = total_size; - ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, - compat_copy_entry_from_user, - &pos, &size, name, newinfo, entry1); + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, + &size, name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(NFPROTO_ARP); xt_compat_unlock(NFPROTO_ARP); if (ret) @@ -1464,13 +1483,28 @@ static int translate_compat_table(const char *name, goto free_newinfo; i = 0; - ret = ARPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, - name, &i); + xt_entry_foreach(iter1, entry1, newinfo->size) { + ret = compat_check_entry(iter1, name, &i); + if (ret != 0) + break; + } if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; j -= i; - COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, - compat_release_entry, &j); - ARPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (compat_release_entry(iter0, &j) != 0) + break; + } + xt_entry_foreach(iter1, entry1, newinfo->size) + if (cleanup_entry(iter1, &i) != 0) + break; xt_free_table_info(newinfo); return ret; } @@ -1488,7 +1522,9 @@ static int translate_compat_table(const char *name, free_newinfo: xt_free_table_info(newinfo); out: - COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); + xt_entry_foreach(iter0, entry0, total_size) + if (compat_release_entry(iter0, &j) != 0) + break; return ret; out_unlock: xt_compat_flush_offsets(NFPROTO_ARP); @@ -1515,6 +1551,7 @@ static int compat_do_replace(struct net *net, void __user *user, struct compat_arpt_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct arpt_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1552,7 +1589,9 @@ static int compat_do_replace(struct net *net, void __user *user, return 0; free_newinfo_untrans: - ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1636,6 +1675,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, int ret = 0; void *loc_cpu_entry; unsigned int i = 0; + struct arpt_entry *iter; counters = alloc_counters(table); if (IS_ERR(counters)) @@ -1645,9 +1685,12 @@ static int compat_copy_entries_to_user(unsigned int total_size, loc_cpu_entry = private->entries[raw_smp_processor_id()]; pos = userptr; size = total_size; - ret = ARPT_ENTRY_ITERATE(loc_cpu_entry, total_size, - compat_copy_entry_to_user, - &pos, &size, counters, &i); + xt_entry_foreach(iter, loc_cpu_entry, total_size) { + ret = compat_copy_entry_to_user(iter, &pos, + &size, counters, &i); + if (ret != 0) + break; + } vfree(counters); return ret; } @@ -1843,13 +1886,15 @@ void arpt_unregister_table(struct xt_table *table) struct xt_table_info *private; void *loc_cpu_entry; struct module *table_owner = table->me; + struct arpt_entry *iter; private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; - ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, - cleanup_entry, NULL); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (cleanup_entry(iter, NULL) != 0) + break; if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index e94c18bdfc68..b43280aad8a2 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -288,6 +288,7 @@ static void trace_packet(const struct sk_buff *skb, const void *table_base; const struct ipt_entry *root; const char *hookname, *chainname, *comment; + const struct ipt_entry *iter; unsigned int rulenum = 0; table_base = private->entries[smp_processor_id()]; @@ -296,10 +297,10 @@ static void trace_packet(const struct sk_buff *skb, hookname = chainname = hooknames[hook]; comment = comments[NF_IP_TRACE_COMMENT_RULE]; - IPT_ENTRY_ITERATE(root, - private->size - private->hook_entry[hook], - get_chainname_rulenum, - e, hookname, &chainname, &comment, &rulenum); + xt_entry_foreach(iter, root, private->size - private->hook_entry[hook]) + if (get_chainname_rulenum(iter, e, hookname, + &chainname, &comment, &rulenum) != 0) + break; nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", @@ -826,8 +827,9 @@ translate_table(struct net *net, const unsigned int *hook_entries, const unsigned int *underflows) { + struct ipt_entry *iter; unsigned int i; - int ret; + int ret = 0; newinfo->size = size; newinfo->number = number; @@ -841,12 +843,13 @@ translate_table(struct net *net, duprintf("translate_table: size %u\n", newinfo->size); i = 0; /* Walk through entries, checking offsets. */ - ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, - check_entry_size_and_hooks, - newinfo, - entry0, - entry0 + size, - hook_entries, underflows, valid_hooks, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = check_entry_size_and_hooks(iter, newinfo, entry0, + entry0 + size, hook_entries, underflows, + valid_hooks, &i); + if (ret != 0) + break; + } if (ret != 0) return ret; @@ -878,12 +881,16 @@ translate_table(struct net *net, /* Finally, each sanity check must pass */ i = 0; - ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, - find_check_entry, net, name, size, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = find_check_entry(iter, net, name, size, &i); + if (ret != 0) + break; + } if (ret != 0) { - IPT_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, net, &i); + xt_entry_foreach(iter, entry0, newinfo->size) + if (cleanup_entry(iter, net, &i) != 0) + break; return ret; } @@ -923,6 +930,7 @@ static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) { + struct ipt_entry *iter; unsigned int cpu; unsigned int i; unsigned int curcpu; @@ -938,22 +946,18 @@ get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - IPT_ENTRY_ITERATE(t->entries[curcpu], - t->size, - set_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[curcpu], t->size) + if (set_entry_to_counter(iter, counters, &i) != 0) + break; for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - IPT_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[cpu], t->size) + if (add_entry_to_counter(iter, counters, &i) != 0) + break; xt_info_wrunlock(cpu); } local_bh_enable(); @@ -1111,7 +1115,9 @@ static int compat_calc_entry(const struct ipt_entry *e, static int compat_table_info(const struct xt_table_info *info, struct xt_table_info *newinfo) { + struct ipt_entry *iter; void *loc_cpu_entry; + int ret = 0; if (!newinfo || !info) return -EINVAL; @@ -1120,9 +1126,12 @@ static int compat_table_info(const struct xt_table_info *info, memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); newinfo->initial_entries = 0; loc_cpu_entry = info->entries[raw_smp_processor_id()]; - return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size, - compat_calc_entry, info, loc_cpu_entry, - newinfo); + xt_entry_foreach(iter, loc_cpu_entry, info->size) { + ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); + if (ret != 0) + break; + } + return ret; } #endif @@ -1236,6 +1245,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, struct xt_table_info *oldinfo; struct xt_counters *counters; void *loc_cpu_old_entry; + struct ipt_entry *iter; ret = 0; counters = vmalloc(num_counters * sizeof(struct xt_counters)); @@ -1278,8 +1288,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, - net, NULL); + xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; + xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, sizeof(struct xt_counters) * num_counters) != 0) @@ -1304,6 +1316,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) struct ipt_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct ipt_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1339,7 +1352,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1373,6 +1388,7 @@ do_add_counters(struct net *net, const void __user *user, const struct xt_table_info *private; int ret = 0; void *loc_cpu_entry; + struct ipt_entry *iter; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1430,11 +1446,9 @@ do_add_counters(struct net *net, const void __user *user, curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; xt_info_wrlock(curcpu); - IPT_ENTRY_ITERATE(loc_cpu_entry, - private->size, - add_counter_to_entry, - paddc, - &i); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (add_counter_to_entry(iter, paddc, &i) != 0) + break; xt_info_wrunlock(curcpu); unlock_up_free: local_bh_enable(); @@ -1720,8 +1734,10 @@ translate_compat_table(struct net *net, unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; + struct compat_ipt_entry *iter0; + struct ipt_entry *iter1; unsigned int size; - int ret; + int ret = 0; info = *pinfo; entry0 = *pentry0; @@ -1738,11 +1754,13 @@ translate_compat_table(struct net *net, j = 0; xt_compat_lock(AF_INET); /* Walk through entries, checking offsets. */ - ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, - check_compat_entry_size_and_hooks, - info, &size, entry0, - entry0 + total_size, - hook_entries, underflows, &j, name); + xt_entry_foreach(iter0, entry0, total_size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, entry0 + total_size, hook_entries, underflows, + &j, name); + if (ret != 0) + break; + } if (ret != 0) goto out_unlock; @@ -1783,9 +1801,12 @@ translate_compat_table(struct net *net, entry1 = newinfo->entries[raw_smp_processor_id()]; pos = entry1; size = total_size; - ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, - compat_copy_entry_from_user, - &pos, &size, name, newinfo, entry1); + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, + &size, name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(AF_INET); xt_compat_unlock(AF_INET); if (ret) @@ -1796,13 +1817,28 @@ translate_compat_table(struct net *net, goto free_newinfo; i = 0; - ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, - net, name, &i); + xt_entry_foreach(iter1, entry1, newinfo->size) { + ret = compat_check_entry(iter1, net, name, &i); + if (ret != 0) + break; + } if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; j -= i; - COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, - compat_release_entry, &j); - IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (compat_release_entry(iter0, &i) != 0) + break; + } + xt_entry_foreach(iter1, entry1, newinfo->size) + if (cleanup_entry(iter1, net, &i) != 0) + break; xt_free_table_info(newinfo); return ret; } @@ -1820,7 +1856,9 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); + xt_entry_foreach(iter0, entry0, total_size) + if (compat_release_entry(iter0, &j) != 0) + break; return ret; out_unlock: xt_compat_flush_offsets(AF_INET); @@ -1835,6 +1873,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) struct compat_ipt_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct ipt_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1873,7 +1912,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1922,6 +1963,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, int ret = 0; const void *loc_cpu_entry; unsigned int i = 0; + struct ipt_entry *iter; counters = alloc_counters(table); if (IS_ERR(counters)) @@ -1934,9 +1976,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, loc_cpu_entry = private->entries[raw_smp_processor_id()]; pos = userptr; size = total_size; - ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, - compat_copy_entry_to_user, - &pos, &size, counters, &i); + xt_entry_foreach(iter, loc_cpu_entry, total_size) { + ret = compat_copy_entry_to_user(iter, &pos, + &size, counters, &i); + if (ret != 0) + break; + } vfree(counters); return ret; @@ -2137,12 +2182,15 @@ void ipt_unregister_table(struct net *net, struct xt_table *table) struct xt_table_info *private; void *loc_cpu_entry; struct module *table_owner = table->me; + struct ipt_entry *iter; private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; - IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 4185099c2943..23926e38d36b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -318,6 +318,7 @@ static void trace_packet(const struct sk_buff *skb, const void *table_base; const struct ip6t_entry *root; const char *hookname, *chainname, *comment; + const struct ip6t_entry *iter; unsigned int rulenum = 0; table_base = private->entries[smp_processor_id()]; @@ -326,10 +327,10 @@ static void trace_packet(const struct sk_buff *skb, hookname = chainname = hooknames[hook]; comment = comments[NF_IP6_TRACE_COMMENT_RULE]; - IP6T_ENTRY_ITERATE(root, - private->size - private->hook_entry[hook], - get_chainname_rulenum, - e, hookname, &chainname, &comment, &rulenum); + xt_entry_foreach(iter, root, private->size - private->hook_entry[hook]) + if (get_chainname_rulenum(iter, e, hookname, + &chainname, &comment, &rulenum) != 0) + break; nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", @@ -857,8 +858,9 @@ translate_table(struct net *net, const unsigned int *hook_entries, const unsigned int *underflows) { + struct ip6t_entry *iter; unsigned int i; - int ret; + int ret = 0; newinfo->size = size; newinfo->number = number; @@ -872,12 +874,13 @@ translate_table(struct net *net, duprintf("translate_table: size %u\n", newinfo->size); i = 0; /* Walk through entries, checking offsets. */ - ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, - check_entry_size_and_hooks, - newinfo, - entry0, - entry0 + size, - hook_entries, underflows, valid_hooks, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = check_entry_size_and_hooks(iter, newinfo, entry0, + entry0 + size, hook_entries, underflows, + valid_hooks, &i); + if (ret != 0) + break; + } if (ret != 0) return ret; @@ -909,12 +912,16 @@ translate_table(struct net *net, /* Finally, each sanity check must pass */ i = 0; - ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, - find_check_entry, net, name, size, &i); + xt_entry_foreach(iter, entry0, newinfo->size) { + ret = find_check_entry(iter, net, name, size, &i); + if (ret != 0) + break; + } if (ret != 0) { - IP6T_ENTRY_ITERATE(entry0, newinfo->size, - cleanup_entry, net, &i); + xt_entry_foreach(iter, entry0, newinfo->size) + if (cleanup_entry(iter, net, &i) != 0) + break; return ret; } @@ -954,6 +961,7 @@ static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) { + struct ip6t_entry *iter; unsigned int cpu; unsigned int i; unsigned int curcpu; @@ -969,22 +977,18 @@ get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - IP6T_ENTRY_ITERATE(t->entries[curcpu], - t->size, - set_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[curcpu], t->size) + if (set_entry_to_counter(iter, counters, &i) != 0) + break; for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - IP6T_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_entry_to_counter, - counters, - &i); + xt_entry_foreach(iter, t->entries[cpu], t->size) + if (add_entry_to_counter(iter, counters, &i) != 0) + break; xt_info_wrunlock(cpu); } local_bh_enable(); @@ -1142,7 +1146,9 @@ static int compat_calc_entry(const struct ip6t_entry *e, static int compat_table_info(const struct xt_table_info *info, struct xt_table_info *newinfo) { + struct ip6t_entry *iter; void *loc_cpu_entry; + int ret = 0; if (!newinfo || !info) return -EINVAL; @@ -1151,9 +1157,12 @@ static int compat_table_info(const struct xt_table_info *info, memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); newinfo->initial_entries = 0; loc_cpu_entry = info->entries[raw_smp_processor_id()]; - return IP6T_ENTRY_ITERATE(loc_cpu_entry, info->size, - compat_calc_entry, info, loc_cpu_entry, - newinfo); + xt_entry_foreach(iter, loc_cpu_entry, info->size) { + ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); + if (ret != 0) + break; + } + return ret; } #endif @@ -1267,6 +1276,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, struct xt_table_info *oldinfo; struct xt_counters *counters; const void *loc_cpu_old_entry; + struct ip6t_entry *iter; ret = 0; counters = vmalloc_node(num_counters * sizeof(struct xt_counters), @@ -1310,8 +1320,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; - IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, - net, NULL); + xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; + xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, sizeof(struct xt_counters) * num_counters) != 0) @@ -1336,6 +1348,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) struct ip6t_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct ip6t_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1371,7 +1384,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1405,6 +1420,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, const struct xt_table_info *private; int ret = 0; const void *loc_cpu_entry; + struct ip6t_entry *iter; #ifdef CONFIG_COMPAT struct compat_xt_counters_info compat_tmp; @@ -1463,11 +1479,9 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, curcpu = smp_processor_id(); xt_info_wrlock(curcpu); loc_cpu_entry = private->entries[curcpu]; - IP6T_ENTRY_ITERATE(loc_cpu_entry, - private->size, - add_counter_to_entry, - paddc, - &i); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (add_counter_to_entry(iter, paddc, &i) != 0) + break; xt_info_wrunlock(curcpu); unlock_up_free: @@ -1753,8 +1767,10 @@ translate_compat_table(struct net *net, unsigned int i, j; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; + struct compat_ip6t_entry *iter0; + struct ip6t_entry *iter1; unsigned int size; - int ret; + int ret = 0; info = *pinfo; entry0 = *pentry0; @@ -1771,11 +1787,13 @@ translate_compat_table(struct net *net, j = 0; xt_compat_lock(AF_INET6); /* Walk through entries, checking offsets. */ - ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, - check_compat_entry_size_and_hooks, - info, &size, entry0, - entry0 + total_size, - hook_entries, underflows, &j, name); + xt_entry_foreach(iter0, entry0, total_size) { + ret = check_compat_entry_size_and_hooks(iter0, info, &size, + entry0, entry0 + total_size, hook_entries, underflows, + &j, name); + if (ret != 0) + break; + } if (ret != 0) goto out_unlock; @@ -1816,9 +1834,12 @@ translate_compat_table(struct net *net, entry1 = newinfo->entries[raw_smp_processor_id()]; pos = entry1; size = total_size; - ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, - compat_copy_entry_from_user, - &pos, &size, name, newinfo, entry1); + xt_entry_foreach(iter0, entry0, total_size) { + ret = compat_copy_entry_from_user(iter0, &pos, + &size, name, newinfo, entry1); + if (ret != 0) + break; + } xt_compat_flush_offsets(AF_INET6); xt_compat_unlock(AF_INET6); if (ret) @@ -1829,13 +1850,28 @@ translate_compat_table(struct net *net, goto free_newinfo; i = 0; - ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, - net, name, &i); + xt_entry_foreach(iter1, entry1, newinfo->size) { + ret = compat_check_entry(iter1, net, name, &i); + if (ret != 0) + break; + } if (ret) { + /* + * The first i matches need cleanup_entry (calls ->destroy) + * because they had called ->check already. The other j-i + * entries need only release. + */ + int skip = i; j -= i; - COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, - compat_release_entry, &j); - IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); + xt_entry_foreach(iter0, entry0, newinfo->size) { + if (skip-- > 0) + continue; + if (compat_release_entry(iter0, &j) != 0) + break; + } + xt_entry_foreach(iter1, entry1, newinfo->size) + if (cleanup_entry(iter1, net, &i) != 0) + break; xt_free_table_info(newinfo); return ret; } @@ -1853,7 +1889,9 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); + xt_entry_foreach(iter0, entry0, total_size) + if (compat_release_entry(iter0, &j) != 0) + break; return ret; out_unlock: xt_compat_flush_offsets(AF_INET6); @@ -1868,6 +1906,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) struct compat_ip6t_replace tmp; struct xt_table_info *newinfo; void *loc_cpu_entry; + struct ip6t_entry *iter; if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) return -EFAULT; @@ -1906,7 +1945,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) return 0; free_newinfo_untrans: - IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1955,6 +1996,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, int ret = 0; const void *loc_cpu_entry; unsigned int i = 0; + struct ip6t_entry *iter; counters = alloc_counters(table); if (IS_ERR(counters)) @@ -1967,9 +2009,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, loc_cpu_entry = private->entries[raw_smp_processor_id()]; pos = userptr; size = total_size; - ret = IP6T_ENTRY_ITERATE(loc_cpu_entry, total_size, - compat_copy_entry_to_user, - &pos, &size, counters, &i); + xt_entry_foreach(iter, loc_cpu_entry, total_size) { + ret = compat_copy_entry_to_user(iter, &pos, + &size, counters, &i); + if (ret != 0) + break; + } vfree(counters); return ret; @@ -2169,12 +2214,15 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table) struct xt_table_info *private; void *loc_cpu_entry; struct module *table_owner = table->me; + struct ip6t_entry *iter; private = xt_unregister_table(table); /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; - IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); + xt_entry_foreach(iter, loc_cpu_entry, private->size) + if (cleanup_entry(iter, net, NULL) != 0) + break; if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); -- cgit v1.2.3 From 0559518b5b99c591226460c0bbf8e6a570c518a8 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Feb 2010 18:33:43 +0100 Subject: netfilter: xtables: optimize call flow around xt_entry_foreach Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/arp_tables.c | 180 +++++++++++++-------------------------- net/ipv4/netfilter/ip_tables.c | 183 ++++++++++++++-------------------------- net/ipv6/netfilter/ip6_tables.c | 179 ++++++++++++++------------------------- 3 files changed, 182 insertions(+), 360 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index f7338869fc4c..5fdedeb46218 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -512,8 +512,7 @@ static inline int check_target(struct arpt_entry *e, const char *name) } static inline int -find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, - unsigned int *i) +find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) { struct arpt_entry_target *t; struct xt_target *target; @@ -538,8 +537,6 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, ret = check_target(e, name); if (ret) goto err; - - (*i)++; return 0; err: module_put(t->u.kernel.target->me); @@ -568,8 +565,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int valid_hooks, - unsigned int *i) + unsigned int valid_hooks) { unsigned int h; @@ -606,19 +602,14 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, /* Clear counters and comefrom */ e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; - - (*i)++; return 0; } -static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) +static inline void cleanup_entry(struct arpt_entry *e) { struct xt_tgdtor_param par; struct arpt_entry_target *t; - if (i && (*i)-- == 0) - return 1; - t = arpt_get_target(e); par.target = t->u.kernel.target; par.targinfo = t->data; @@ -626,7 +617,6 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - return 0; } /* Checks and translates the user-supplied table segment (held in @@ -660,10 +650,10 @@ static int translate_table(const char *name, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, - valid_hooks, &i); + entry0 + size, hook_entries, underflows, valid_hooks); if (ret != 0) break; + ++i; } duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); if (ret != 0) @@ -700,15 +690,18 @@ static int translate_table(const char *name, /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, name, size, &i); + ret = find_check_entry(iter, name, size); if (ret != 0) break; + ++i; } if (ret != 0) { - xt_entry_foreach(iter, entry0, newinfo->size) - if (cleanup_entry(iter, &i) != 0) + xt_entry_foreach(iter, entry0, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter); + } return ret; } @@ -721,27 +714,6 @@ static int translate_table(const char *name, return ret; } -/* Gets counters. */ -static inline int add_entry_to_counter(const struct arpt_entry *e, - struct xt_counters total[], - unsigned int *i) -{ - ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - -static inline int set_entry_to_counter(const struct arpt_entry *e, - struct xt_counters total[], - unsigned int *i) -{ - SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) { @@ -761,18 +733,22 @@ static void get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - xt_entry_foreach(iter, t->entries[curcpu], t->size) - if (set_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[curcpu], t->size) { + SET_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; + } for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - xt_entry_foreach(iter, t->entries[cpu], t->size) - if (add_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[cpu], t->size) { + ADD_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; + } xt_info_wrunlock(cpu); } local_bh_enable(); @@ -904,7 +880,7 @@ static int compat_table_info(const struct xt_table_info *info, { struct arpt_entry *iter; void *loc_cpu_entry; - int ret = 0; + int ret; if (!newinfo || !info) return -EINVAL; @@ -916,9 +892,9 @@ static int compat_table_info(const struct xt_table_info *info, xt_entry_foreach(iter, loc_cpu_entry, info->size) { ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); if (ret != 0) - break; + return ret; } - return ret; + return 0; } #endif @@ -1078,8 +1054,7 @@ static int __do_replace(struct net *net, const char *name, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) - if (cleanup_entry(iter, NULL) != 0) - break; + cleanup_entry(iter); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, @@ -1142,26 +1117,12 @@ static int do_replace(struct net *net, const void __user *user, free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, NULL) != 0) - break; + cleanup_entry(iter); free_newinfo: xt_free_table_info(newinfo); return ret; } -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct arpt_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - static int do_add_counters(struct net *net, const void __user *user, unsigned int len, int compat) { @@ -1234,9 +1195,10 @@ static int do_add_counters(struct net *net, const void __user *user, curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; xt_info_wrlock(curcpu); - xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (add_counter_to_entry(iter, paddc, &i) != 0) - break; + xt_entry_foreach(iter, loc_cpu_entry, private->size) { + ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); + ++i; + } xt_info_wrunlock(curcpu); unlock_up_free: local_bh_enable(); @@ -1249,17 +1211,12 @@ static int do_add_counters(struct net *net, const void __user *user, } #ifdef CONFIG_COMPAT -static inline int -compat_release_entry(struct compat_arpt_entry *e, unsigned int *i) +static inline void compat_release_entry(struct compat_arpt_entry *e) { struct arpt_entry_target *t; - if (i && (*i)-- == 0) - return 1; - t = compat_arpt_get_target(e); module_put(t->u.kernel.target->me); - return 0; } static inline int @@ -1270,7 +1227,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int *i, const char *name) { struct arpt_entry_target *t; @@ -1330,8 +1286,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, /* Clear counters and comefrom */ memset(&e->counters, 0, sizeof(e->counters)); e->comefrom = 0; - - (*i)++; return 0; release_target: @@ -1375,19 +1329,6 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, return ret; } -static inline int compat_check_entry(struct arpt_entry *e, const char *name, - unsigned int *i) -{ - int ret; - - ret = check_target(e, name); - if (ret) - return ret; - - (*i)++; - return 0; -} - static int translate_compat_table(const char *name, unsigned int valid_hooks, struct xt_table_info **pinfo, @@ -1423,12 +1364,11 @@ static int translate_compat_table(const char *name, xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, entry0 + total_size, hook_entries, underflows, - &j, name); + name); if (ret != 0) - break; + goto out_unlock; + ++j; } - if (ret != 0) - goto out_unlock; ret = -EINVAL; if (j != number) { @@ -1484,9 +1424,10 @@ static int translate_compat_table(const char *name, i = 0; xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, name, &i); + ret = check_target(iter1, name); if (ret != 0) break; + ++i; } if (ret) { /* @@ -1499,12 +1440,15 @@ static int translate_compat_table(const char *name, xt_entry_foreach(iter0, entry0, newinfo->size) { if (skip-- > 0) continue; - if (compat_release_entry(iter0, &j) != 0) + if (j-- == 0) break; + compat_release_entry(iter0); } - xt_entry_foreach(iter1, entry1, newinfo->size) - if (cleanup_entry(iter1, &i) != 0) + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter1); + } xt_free_table_info(newinfo); return ret; } @@ -1522,9 +1466,11 @@ static int translate_compat_table(const char *name, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) - if (compat_release_entry(iter0, &j) != 0) + xt_entry_foreach(iter0, entry0, total_size) { + if (j-- == 0) break; + compat_release_entry(iter0); + } return ret; out_unlock: xt_compat_flush_offsets(NFPROTO_ARP); @@ -1590,8 +1536,7 @@ static int compat_do_replace(struct net *net, void __user *user, free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, NULL) != 0) - break; + cleanup_entry(iter); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1625,7 +1570,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, compat_uint_t *size, struct xt_counters *counters, - unsigned int *i) + unsigned int i) { struct arpt_entry_target *t; struct compat_arpt_entry __user *ce; @@ -1633,14 +1578,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, compat_uint_t origsize; int ret; - ret = -EFAULT; origsize = *size; ce = (struct compat_arpt_entry __user *)*dstptr; - if (copy_to_user(ce, e, sizeof(struct arpt_entry))) - goto out; - - if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) - goto out; + if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 || + copy_to_user(&ce->counters, &counters[i], + sizeof(counters[i])) != 0) + return -EFAULT; *dstptr += sizeof(struct compat_arpt_entry); *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); @@ -1650,18 +1593,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, t = arpt_get_target(e); ret = xt_compat_target_to_user(t, dstptr, size); if (ret) - goto out; - ret = -EFAULT; + return ret; next_offset = e->next_offset - (origsize - *size); - if (put_user(target_offset, &ce->target_offset)) - goto out; - if (put_user(next_offset, &ce->next_offset)) - goto out; - - (*i)++; + if (put_user(target_offset, &ce->target_offset) != 0 || + put_user(next_offset, &ce->next_offset) != 0) + return -EFAULT; return 0; -out: - return ret; } static int compat_copy_entries_to_user(unsigned int total_size, @@ -1687,7 +1624,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, &i); + &size, counters, i++); if (ret != 0) break; } @@ -1893,8 +1830,7 @@ void arpt_unregister_table(struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (cleanup_entry(iter, NULL) != 0) - break; + cleanup_entry(iter); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index b43280aad8a2..9c8aa394c51c 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -679,7 +679,7 @@ static int check_target(struct ipt_entry *e, struct net *net, const char *name) static int find_check_entry(struct ipt_entry *e, struct net *net, const char *name, - unsigned int size, unsigned int *i) + unsigned int size) { struct ipt_entry_target *t; struct xt_target *target; @@ -716,8 +716,6 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, ret = check_target(e, net, name); if (ret) goto err; - - (*i)++; return 0; err: module_put(t->u.kernel.target->me); @@ -748,8 +746,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int valid_hooks, - unsigned int *i) + unsigned int valid_hooks) { unsigned int h; @@ -786,20 +783,15 @@ check_entry_size_and_hooks(struct ipt_entry *e, /* Clear counters and comefrom */ e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; - - (*i)++; return 0; } -static int -cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i) +static void +cleanup_entry(struct ipt_entry *e, struct net *net) { struct xt_tgdtor_param par; struct ipt_entry_target *t; - if (i && (*i)-- == 0) - return 1; - /* Cleanup all matches */ IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ipt_get_target(e); @@ -811,7 +803,6 @@ cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - return 0; } /* Checks and translates the user-supplied table segment (held in @@ -845,13 +836,11 @@ translate_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, - valid_hooks, &i); + entry0 + size, hook_entries, underflows, valid_hooks); if (ret != 0) - break; + return ret; + ++i; } - if (ret != 0) - return ret; if (i != number) { duprintf("translate_table: %u not %u entries\n", @@ -882,15 +871,18 @@ translate_table(struct net *net, /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, name, size, &i); + ret = find_check_entry(iter, net, name, size); if (ret != 0) break; + ++i; } if (ret != 0) { - xt_entry_foreach(iter, entry0, newinfo->size) - if (cleanup_entry(iter, net, &i) != 0) + xt_entry_foreach(iter, entry0, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter, net); + } return ret; } @@ -903,29 +895,6 @@ translate_table(struct net *net, return ret; } -/* Gets counters. */ -static inline int -add_entry_to_counter(const struct ipt_entry *e, - struct xt_counters total[], - unsigned int *i) -{ - ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - -static inline int -set_entry_to_counter(const struct ipt_entry *e, - struct ipt_counters total[], - unsigned int *i) -{ - SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) @@ -946,18 +915,22 @@ get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - xt_entry_foreach(iter, t->entries[curcpu], t->size) - if (set_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[curcpu], t->size) { + SET_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; + } for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - xt_entry_foreach(iter, t->entries[cpu], t->size) - if (add_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[cpu], t->size) { + ADD_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; /* macro does multi eval of i */ + } xt_info_wrunlock(cpu); } local_bh_enable(); @@ -1117,7 +1090,7 @@ static int compat_table_info(const struct xt_table_info *info, { struct ipt_entry *iter; void *loc_cpu_entry; - int ret = 0; + int ret; if (!newinfo || !info) return -EINVAL; @@ -1129,9 +1102,9 @@ static int compat_table_info(const struct xt_table_info *info, xt_entry_foreach(iter, loc_cpu_entry, info->size) { ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); if (ret != 0) - break; + return ret; } - return ret; + return 0; } #endif @@ -1289,8 +1262,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, @@ -1353,26 +1325,12 @@ do_replace(struct net *net, const void __user *user, unsigned int len) free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; } -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct ipt_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - static int do_add_counters(struct net *net, const void __user *user, unsigned int len, int compat) @@ -1446,9 +1404,10 @@ do_add_counters(struct net *net, const void __user *user, curcpu = smp_processor_id(); loc_cpu_entry = private->entries[curcpu]; xt_info_wrlock(curcpu); - xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (add_counter_to_entry(iter, paddc, &i) != 0) - break; + xt_entry_foreach(iter, loc_cpu_entry, private->size) { + ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); + ++i; + } xt_info_wrunlock(curcpu); unlock_up_free: local_bh_enable(); @@ -1476,7 +1435,7 @@ struct compat_ipt_replace { static int compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, unsigned int *size, struct xt_counters *counters, - unsigned int *i) + unsigned int i) { struct ipt_entry_target *t; struct compat_ipt_entry __user *ce; @@ -1484,14 +1443,12 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, compat_uint_t origsize; int ret; - ret = -EFAULT; origsize = *size; ce = (struct compat_ipt_entry __user *)*dstptr; - if (copy_to_user(ce, e, sizeof(struct ipt_entry))) - goto out; - - if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) - goto out; + if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 || + copy_to_user(&ce->counters, &counters[i], + sizeof(counters[i])) != 0) + return -EFAULT; *dstptr += sizeof(struct compat_ipt_entry); *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); @@ -1499,22 +1456,16 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); target_offset = e->target_offset - (origsize - *size); if (ret) - goto out; + return ret; t = ipt_get_target(e); ret = xt_compat_target_to_user(t, dstptr, size); if (ret) - goto out; - ret = -EFAULT; + return ret; next_offset = e->next_offset - (origsize - *size); - if (put_user(target_offset, &ce->target_offset)) - goto out; - if (put_user(next_offset, &ce->next_offset)) - goto out; - - (*i)++; + if (put_user(target_offset, &ce->target_offset) != 0 || + put_user(next_offset, &ce->next_offset) != 0) + return -EFAULT; return 0; -out: - return ret; } static int @@ -1551,19 +1502,14 @@ compat_release_match(struct ipt_entry_match *m, unsigned int *i) return 0; } -static int -compat_release_entry(struct compat_ipt_entry *e, unsigned int *i) +static void compat_release_entry(struct compat_ipt_entry *e) { struct ipt_entry_target *t; - if (i && (*i)-- == 0) - return 1; - /* Cleanup all matches */ COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL); t = compat_ipt_get_target(e); module_put(t->u.kernel.target->me); - return 0; } static int @@ -1574,7 +1520,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int *i, const char *name) { struct ipt_entry_target *t; @@ -1640,8 +1585,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, /* Clear counters and comefrom */ memset(&e->counters, 0, sizeof(e->counters)); e->comefrom = 0; - - (*i)++; return 0; out: @@ -1691,8 +1634,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, } static int -compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, - unsigned int *i) +compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) { struct xt_mtchk_param mtpar; unsigned int j; @@ -1711,8 +1653,6 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name, ret = check_target(e, net, name); if (ret) goto cleanup_matches; - - (*i)++; return 0; cleanup_matches: @@ -1737,7 +1677,7 @@ translate_compat_table(struct net *net, struct compat_ipt_entry *iter0; struct ipt_entry *iter1; unsigned int size; - int ret = 0; + int ret; info = *pinfo; entry0 = *pentry0; @@ -1757,12 +1697,11 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, entry0 + total_size, hook_entries, underflows, - &j, name); + name); if (ret != 0) - break; + goto out_unlock; + ++j; } - if (ret != 0) - goto out_unlock; ret = -EINVAL; if (j != number) { @@ -1818,9 +1757,10 @@ translate_compat_table(struct net *net, i = 0; xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, name, &i); + ret = compat_check_entry(iter1, net, name); if (ret != 0) break; + ++i; } if (ret) { /* @@ -1833,12 +1773,15 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, newinfo->size) { if (skip-- > 0) continue; - if (compat_release_entry(iter0, &i) != 0) + if (j-- == 0) break; + compat_release_entry(iter0); } - xt_entry_foreach(iter1, entry1, newinfo->size) - if (cleanup_entry(iter1, net, &i) != 0) + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter1, net); + } xt_free_table_info(newinfo); return ret; } @@ -1856,9 +1799,11 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) - if (compat_release_entry(iter0, &j) != 0) + xt_entry_foreach(iter0, entry0, total_size) { + if (j-- == 0) break; + compat_release_entry(iter0); + } return ret; out_unlock: xt_compat_flush_offsets(AF_INET); @@ -1913,8 +1858,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -1978,7 +1922,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, &i); + &size, counters, i++); if (ret != 0) break; } @@ -2189,8 +2133,7 @@ void ipt_unregister_table(struct net *net, struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 23926e38d36b..b7e27c19c7ab 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -710,7 +710,7 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name) static int find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, - unsigned int size, unsigned int *i) + unsigned int size) { struct ip6t_entry_target *t; struct xt_target *target; @@ -747,8 +747,6 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, ret = check_target(e, net, name); if (ret) goto err; - - (*i)++; return 0; err: module_put(t->u.kernel.target->me); @@ -779,8 +777,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int valid_hooks, - unsigned int *i) + unsigned int valid_hooks) { unsigned int h; @@ -817,20 +814,14 @@ check_entry_size_and_hooks(struct ip6t_entry *e, /* Clear counters and comefrom */ e->counters = ((struct xt_counters) { 0, 0 }); e->comefrom = 0; - - (*i)++; return 0; } -static int -cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) +static void cleanup_entry(struct ip6t_entry *e, struct net *net) { struct xt_tgdtor_param par; struct ip6t_entry_target *t; - if (i && (*i)-- == 0) - return 1; - /* Cleanup all matches */ IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); t = ip6t_get_target(e); @@ -842,7 +833,6 @@ cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) if (par.target->destroy != NULL) par.target->destroy(&par); module_put(par.target->me); - return 0; } /* Checks and translates the user-supplied table segment (held in @@ -876,13 +866,11 @@ translate_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, - valid_hooks, &i); + entry0 + size, hook_entries, underflows, valid_hooks); if (ret != 0) - break; + return ret; + ++i; } - if (ret != 0) - return ret; if (i != number) { duprintf("translate_table: %u not %u entries\n", @@ -913,15 +901,18 @@ translate_table(struct net *net, /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, name, size, &i); + ret = find_check_entry(iter, net, name, size); if (ret != 0) break; + ++i; } if (ret != 0) { - xt_entry_foreach(iter, entry0, newinfo->size) - if (cleanup_entry(iter, net, &i) != 0) + xt_entry_foreach(iter, entry0, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter, net); + } return ret; } @@ -934,29 +925,6 @@ translate_table(struct net *net, return ret; } -/* Gets counters. */ -static inline int -add_entry_to_counter(const struct ip6t_entry *e, - struct xt_counters total[], - unsigned int *i) -{ - ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - -static inline int -set_entry_to_counter(const struct ip6t_entry *e, - struct ip6t_counters total[], - unsigned int *i) -{ - SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); - - (*i)++; - return 0; -} - static void get_counters(const struct xt_table_info *t, struct xt_counters counters[]) @@ -977,18 +945,22 @@ get_counters(const struct xt_table_info *t, curcpu = smp_processor_id(); i = 0; - xt_entry_foreach(iter, t->entries[curcpu], t->size) - if (set_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[curcpu], t->size) { + SET_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; + } for_each_possible_cpu(cpu) { if (cpu == curcpu) continue; i = 0; xt_info_wrlock(cpu); - xt_entry_foreach(iter, t->entries[cpu], t->size) - if (add_entry_to_counter(iter, counters, &i) != 0) - break; + xt_entry_foreach(iter, t->entries[cpu], t->size) { + ADD_COUNTER(counters[i], iter->counters.bcnt, + iter->counters.pcnt); + ++i; + } xt_info_wrunlock(cpu); } local_bh_enable(); @@ -1148,7 +1120,7 @@ static int compat_table_info(const struct xt_table_info *info, { struct ip6t_entry *iter; void *loc_cpu_entry; - int ret = 0; + int ret; if (!newinfo || !info) return -EINVAL; @@ -1160,9 +1132,9 @@ static int compat_table_info(const struct xt_table_info *info, xt_entry_foreach(iter, loc_cpu_entry, info->size) { ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); if (ret != 0) - break; + return ret; } - return ret; + return 0; } #endif @@ -1321,8 +1293,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); xt_free_table_info(oldinfo); if (copy_to_user(counters_ptr, counters, @@ -1385,26 +1356,12 @@ do_replace(struct net *net, const void __user *user, unsigned int len) free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; } -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct ip6t_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - static int do_add_counters(struct net *net, const void __user *user, unsigned int len, int compat) @@ -1479,9 +1436,10 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, curcpu = smp_processor_id(); xt_info_wrlock(curcpu); loc_cpu_entry = private->entries[curcpu]; - xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (add_counter_to_entry(iter, paddc, &i) != 0) - break; + xt_entry_foreach(iter, loc_cpu_entry, private->size) { + ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); + ++i; + } xt_info_wrunlock(curcpu); unlock_up_free: @@ -1510,7 +1468,7 @@ struct compat_ip6t_replace { static int compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, unsigned int *size, struct xt_counters *counters, - unsigned int *i) + unsigned int i) { struct ip6t_entry_target *t; struct compat_ip6t_entry __user *ce; @@ -1518,14 +1476,12 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, compat_uint_t origsize; int ret; - ret = -EFAULT; origsize = *size; ce = (struct compat_ip6t_entry __user *)*dstptr; - if (copy_to_user(ce, e, sizeof(struct ip6t_entry))) - goto out; - - if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) - goto out; + if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 || + copy_to_user(&ce->counters, &counters[i], + sizeof(counters[i])) != 0) + return -EFAULT; *dstptr += sizeof(struct compat_ip6t_entry); *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); @@ -1533,22 +1489,16 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); target_offset = e->target_offset - (origsize - *size); if (ret) - goto out; + return ret; t = ip6t_get_target(e); ret = xt_compat_target_to_user(t, dstptr, size); if (ret) - goto out; - ret = -EFAULT; + return ret; next_offset = e->next_offset - (origsize - *size); - if (put_user(target_offset, &ce->target_offset)) - goto out; - if (put_user(next_offset, &ce->next_offset)) - goto out; - - (*i)++; + if (put_user(target_offset, &ce->target_offset) != 0 || + put_user(next_offset, &ce->next_offset) != 0) + return -EFAULT; return 0; -out: - return ret; } static int @@ -1585,19 +1535,14 @@ compat_release_match(struct ip6t_entry_match *m, unsigned int *i) return 0; } -static int -compat_release_entry(struct compat_ip6t_entry *e, unsigned int *i) +static void compat_release_entry(struct compat_ip6t_entry *e) { struct ip6t_entry_target *t; - if (i && (*i)-- == 0) - return 1; - /* Cleanup all matches */ COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); t = compat_ip6t_get_target(e); module_put(t->u.kernel.target->me); - return 0; } static int @@ -1608,7 +1553,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, const unsigned char *limit, const unsigned int *hook_entries, const unsigned int *underflows, - unsigned int *i, const char *name) { struct ip6t_entry_target *t; @@ -1674,8 +1618,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, /* Clear counters and comefrom */ memset(&e->counters, 0, sizeof(e->counters)); e->comefrom = 0; - - (*i)++; return 0; out: @@ -1725,7 +1667,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, } static int compat_check_entry(struct ip6t_entry *e, struct net *net, - const char *name, unsigned int *i) + const char *name) { unsigned int j; int ret; @@ -1744,8 +1686,6 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, ret = check_target(e, net, name); if (ret) goto cleanup_matches; - - (*i)++; return 0; cleanup_matches: @@ -1790,12 +1730,11 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, entry0, entry0 + total_size, hook_entries, underflows, - &j, name); + name); if (ret != 0) - break; + goto out_unlock; + ++j; } - if (ret != 0) - goto out_unlock; ret = -EINVAL; if (j != number) { @@ -1851,9 +1790,10 @@ translate_compat_table(struct net *net, i = 0; xt_entry_foreach(iter1, entry1, newinfo->size) { - ret = compat_check_entry(iter1, net, name, &i); + ret = compat_check_entry(iter1, net, name); if (ret != 0) break; + ++i; } if (ret) { /* @@ -1866,12 +1806,15 @@ translate_compat_table(struct net *net, xt_entry_foreach(iter0, entry0, newinfo->size) { if (skip-- > 0) continue; - if (compat_release_entry(iter0, &j) != 0) + if (j-- == 0) break; + compat_release_entry(iter0); } - xt_entry_foreach(iter1, entry1, newinfo->size) - if (cleanup_entry(iter1, net, &i) != 0) + xt_entry_foreach(iter1, entry1, newinfo->size) { + if (i-- == 0) break; + cleanup_entry(iter1, net); + } xt_free_table_info(newinfo); return ret; } @@ -1889,9 +1832,11 @@ translate_compat_table(struct net *net, free_newinfo: xt_free_table_info(newinfo); out: - xt_entry_foreach(iter0, entry0, total_size) - if (compat_release_entry(iter0, &j) != 0) + xt_entry_foreach(iter0, entry0, total_size) { + if (j-- == 0) break; + compat_release_entry(iter0); + } return ret; out_unlock: xt_compat_flush_offsets(AF_INET6); @@ -1946,8 +1891,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) free_newinfo_untrans: xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); free_newinfo: xt_free_table_info(newinfo); return ret; @@ -2011,7 +1955,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, &i); + &size, counters, i++); if (ret != 0) break; } @@ -2221,8 +2165,7 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table) /* Decrease module usage counts and free resources */ loc_cpu_entry = private->entries[raw_smp_processor_id()]; xt_entry_foreach(iter, loc_cpu_entry, private->size) - if (cleanup_entry(iter, net, NULL) != 0) - break; + cleanup_entry(iter, net); if (private->number > private->initial_entries) module_put(table_owner); xt_free_table_info(private); -- cgit v1.2.3 From dcea992aca82cb08b4674c4c783e325835408d1e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Feb 2010 18:34:48 +0100 Subject: netfilter: xtables: replace XT_MATCH_ITERATE macro The macro is replaced by a list.h-like foreach loop. This makes the code more inspectable. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- include/linux/netfilter/x_tables.h | 10 +++- include/linux/netfilter_ipv4/ip_tables.h | 6 +-- include/linux/netfilter_ipv6/ip6_tables.h | 6 +-- net/ipv4/netfilter/ip_tables.c | 78 ++++++++++++++++++++++++------- net/ipv6/netfilter/ip6_tables.c | 78 ++++++++++++++++++++++++------- net/netfilter/xt_TCPMSS.c | 12 +++-- 6 files changed, 141 insertions(+), 49 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 9df3f5a8f9f7..84c7c928e9eb 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -120,6 +120,7 @@ struct xt_counters_info { #define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define XT_MATCH_ITERATE(type, e, fn, args...) \ ({ \ @@ -139,7 +140,6 @@ struct xt_counters_info { __ret; \ }) -#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \ ({ \ @@ -172,6 +172,14 @@ struct xt_counters_info { (pos) < (typeof(pos))((char *)(ehead) + (esize)); \ (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset)) +/* can only be xt_entry_match, so no use of typeof here */ +#define xt_ematch_foreach(pos, entry) \ + for ((pos) = (struct xt_entry_match *)entry->elems; \ + (pos) < (struct xt_entry_match *)((char *)(entry) + \ + (entry)->target_offset); \ + (pos) = (struct xt_entry_match *)((char *)(pos) + \ + (pos)->u.match_size)) + #ifdef __KERNEL__ #include diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 5b20ae724b41..704a7b6e8169 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -223,11 +223,11 @@ ipt_get_target(struct ipt_entry *e) return (void *)e + e->target_offset; } +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IPT_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) -#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) @@ -315,10 +315,6 @@ compat_ipt_get_target(struct compat_ipt_entry *e) #define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) -/* fn returns 0 to continue iteration */ -#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \ - XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args) - #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IPTABLES_H */ diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 8bb3f5ba5ff2..e5ba03d783c6 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -280,11 +280,11 @@ ip6t_get_target(struct ip6t_entry *e) return (void *)e + e->target_offset; } +#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IP6T_MATCH_ITERATE(e, fn, args...) \ XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) -#ifndef __KERNEL__ /* fn returns 0 to continue iteration */ #define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) @@ -343,10 +343,6 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e) #define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s) -/* fn returns 0 to continue iteration */ -#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \ - XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args) - #endif /* CONFIG_COMPAT */ #endif /*__KERNEL__*/ #endif /* _IP6_TABLES_H */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 9c8aa394c51c..3a7fc732b918 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -366,16 +366,21 @@ ipt_do_table(struct sk_buff *skb, do { const struct ipt_entry_target *t; + const struct xt_entry_match *ematch; IP_NF_ASSERT(e); IP_NF_ASSERT(back); if (!ip_packet_match(ip, indev, outdev, - &e->ip, mtpar.fragoff) || - IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { + &e->ip, mtpar.fragoff)) { + no_match: e = ipt_next_entry(e); continue; } + xt_ematch_foreach(ematch, e) + if (do_match(ematch, skb, &mtpar) != 0) + goto no_match; + ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1); t = ipt_get_target(e); @@ -686,6 +691,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, int ret; unsigned int j; struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; ret = check_entry(e, name); if (ret) @@ -697,7 +703,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, mtpar.entryinfo = &e->ip; mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV4; - ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j); + xt_ematch_foreach(ematch, e) { + ret = find_check_match(ematch, &mtpar, &j); + if (ret != 0) + break; + } if (ret != 0) goto cleanup_matches; @@ -720,7 +730,9 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, net, &j); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, &j) != 0) + break; return ret; } @@ -791,9 +803,12 @@ cleanup_entry(struct ipt_entry *e, struct net *net) { struct xt_tgdtor_param par; struct ipt_entry_target *t; + struct xt_entry_match *ematch; /* Cleanup all matches */ - IPT_MATCH_ITERATE(e, cleanup_match, net, NULL); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, NULL) != 0) + break; t = ipt_get_target(e); par.net = net; @@ -1060,13 +1075,16 @@ static int compat_calc_entry(const struct ipt_entry *e, const struct xt_table_info *info, const void *base, struct xt_table_info *newinfo) { + const struct xt_entry_match *ematch; const struct ipt_entry_target *t; unsigned int entry_offset; int off, i, ret; off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); entry_offset = (void *)e - base; - IPT_MATCH_ITERATE(e, compat_calc_match, &off); + xt_ematch_foreach(ematch, e) + if (compat_calc_match(ematch, &off) != 0) + break; t = ipt_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; @@ -1441,7 +1459,8 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, struct compat_ipt_entry __user *ce; u_int16_t target_offset, next_offset; compat_uint_t origsize; - int ret; + const struct xt_entry_match *ematch; + int ret = 0; origsize = *size; ce = (struct compat_ipt_entry __user *)*dstptr; @@ -1453,7 +1472,11 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, *dstptr += sizeof(struct compat_ipt_entry); *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); - ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_to_user(ematch, dstptr, size); + if (ret != 0) + break; + } target_offset = e->target_offset - (origsize - *size); if (ret) return ret; @@ -1505,9 +1528,12 @@ compat_release_match(struct ipt_entry_match *m, unsigned int *i) static void compat_release_entry(struct compat_ipt_entry *e) { struct ipt_entry_target *t; + struct xt_entry_match *ematch; /* Cleanup all matches */ - COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL); + xt_ematch_foreach(ematch, e) + if (compat_release_match(ematch, NULL) != 0) + break; t = compat_ipt_get_target(e); module_put(t->u.kernel.target->me); } @@ -1522,6 +1548,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, const unsigned int *underflows, const char *name) { + struct xt_entry_match *ematch; struct ipt_entry_target *t; struct xt_target *target; unsigned int entry_offset; @@ -1550,8 +1577,12 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); entry_offset = (void *)e - (void *)base; j = 0; - ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name, - &e->ip, e->comefrom, &off, &j); + xt_ematch_foreach(ematch, e) { + ret = compat_find_calc_match(ematch, name, + &e->ip, e->comefrom, &off, &j); + if (ret != 0) + break; + } if (ret != 0) goto release_matches; @@ -1590,7 +1621,9 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, out: module_put(t->u.kernel.target->me); release_matches: - IPT_MATCH_ITERATE(e, compat_release_match, &j); + xt_ematch_foreach(ematch, e) + if (compat_release_match(ematch, &j) != 0) + break; return ret; } @@ -1604,6 +1637,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, struct ipt_entry *de; unsigned int origsize; int ret, h; + struct xt_entry_match *ematch; ret = 0; origsize = *size; @@ -1614,8 +1648,11 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, *dstptr += sizeof(struct ipt_entry); *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); - ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user, - dstptr, size); + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_from_user(ematch, dstptr, size); + if (ret != 0) + break; + } if (ret) return ret; de->target_offset = e->target_offset - (origsize - *size); @@ -1636,9 +1673,10 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, static int compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) { + struct xt_entry_match *ematch; struct xt_mtchk_param mtpar; unsigned int j; - int ret; + int ret = 0; j = 0; mtpar.net = net; @@ -1646,7 +1684,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) mtpar.entryinfo = &e->ip; mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV4; - ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j); + xt_ematch_foreach(ematch, e) { + ret = check_match(ematch, &mtpar, &j); + if (ret != 0) + break; + } if (ret) goto cleanup_matches; @@ -1656,7 +1698,9 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) return 0; cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, net, &j); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, &j) != 0) + break; return ret; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index b7e27c19c7ab..1537e6bad5d9 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -393,16 +393,21 @@ ip6t_do_table(struct sk_buff *skb, do { const struct ip6t_entry_target *t; + const struct xt_entry_match *ematch; IP_NF_ASSERT(e); IP_NF_ASSERT(back); if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, - &mtpar.thoff, &mtpar.fragoff, &hotdrop) || - IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) { + &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { + no_match: e = ip6t_next_entry(e); continue; } + xt_ematch_foreach(ematch, e) + if (do_match(ematch, skb, &mtpar) != 0) + goto no_match; + ADD_COUNTER(e->counters, ntohs(ipv6_hdr(skb)->payload_len) + sizeof(struct ipv6hdr), 1); @@ -717,6 +722,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, int ret; unsigned int j; struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; ret = check_entry(e, name); if (ret) @@ -728,7 +734,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, mtpar.entryinfo = &e->ipv6; mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV6; - ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j); + xt_ematch_foreach(ematch, e) { + ret = find_check_match(ematch, &mtpar, &j); + if (ret != 0) + break; + } if (ret != 0) goto cleanup_matches; @@ -751,7 +761,9 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, &j) != 0) + break; return ret; } @@ -821,9 +833,12 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) { struct xt_tgdtor_param par; struct ip6t_entry_target *t; + struct xt_entry_match *ematch; /* Cleanup all matches */ - IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, NULL) != 0) + break; t = ip6t_get_target(e); par.net = net; @@ -1090,13 +1105,16 @@ static int compat_calc_entry(const struct ip6t_entry *e, const struct xt_table_info *info, const void *base, struct xt_table_info *newinfo) { + const struct xt_entry_match *ematch; const struct ip6t_entry_target *t; unsigned int entry_offset; int off, i, ret; off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); entry_offset = (void *)e - base; - IP6T_MATCH_ITERATE(e, compat_calc_match, &off); + xt_ematch_foreach(ematch, e) + if (compat_calc_match(ematch, &off) != 0) + break; t = ip6t_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; @@ -1474,7 +1492,8 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, struct compat_ip6t_entry __user *ce; u_int16_t target_offset, next_offset; compat_uint_t origsize; - int ret; + const struct xt_entry_match *ematch; + int ret = 0; origsize = *size; ce = (struct compat_ip6t_entry __user *)*dstptr; @@ -1486,7 +1505,11 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, *dstptr += sizeof(struct compat_ip6t_entry); *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); - ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_to_user(ematch, dstptr, size); + if (ret != 0) + break; + } target_offset = e->target_offset - (origsize - *size); if (ret) return ret; @@ -1538,9 +1561,12 @@ compat_release_match(struct ip6t_entry_match *m, unsigned int *i) static void compat_release_entry(struct compat_ip6t_entry *e) { struct ip6t_entry_target *t; + struct xt_entry_match *ematch; /* Cleanup all matches */ - COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); + xt_ematch_foreach(ematch, e) + if (compat_release_match(ematch, NULL) != 0) + break; t = compat_ip6t_get_target(e); module_put(t->u.kernel.target->me); } @@ -1555,6 +1581,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, const unsigned int *underflows, const char *name) { + struct xt_entry_match *ematch; struct ip6t_entry_target *t; struct xt_target *target; unsigned int entry_offset; @@ -1583,8 +1610,12 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); entry_offset = (void *)e - (void *)base; j = 0; - ret = COMPAT_IP6T_MATCH_ITERATE(e, compat_find_calc_match, name, - &e->ipv6, e->comefrom, &off, &j); + xt_ematch_foreach(ematch, e) { + ret = compat_find_calc_match(ematch, name, + &e->ipv6, e->comefrom, &off, &j); + if (ret != 0) + break; + } if (ret != 0) goto release_matches; @@ -1623,7 +1654,9 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, out: module_put(t->u.kernel.target->me); release_matches: - IP6T_MATCH_ITERATE(e, compat_release_match, &j); + xt_ematch_foreach(ematch, e) + if (compat_release_match(ematch, &j) != 0) + break; return ret; } @@ -1637,6 +1670,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, struct ip6t_entry *de; unsigned int origsize; int ret, h; + struct xt_entry_match *ematch; ret = 0; origsize = *size; @@ -1647,8 +1681,11 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, *dstptr += sizeof(struct ip6t_entry); *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); - ret = COMPAT_IP6T_MATCH_ITERATE(e, xt_compat_match_from_user, - dstptr, size); + xt_ematch_foreach(ematch, e) { + ret = xt_compat_match_from_user(ematch, dstptr, size); + if (ret != 0) + break; + } if (ret) return ret; de->target_offset = e->target_offset - (origsize - *size); @@ -1670,8 +1707,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, const char *name) { unsigned int j; - int ret; + int ret = 0; struct xt_mtchk_param mtpar; + struct xt_entry_match *ematch; j = 0; mtpar.net = net; @@ -1679,7 +1717,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, mtpar.entryinfo = &e->ipv6; mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV6; - ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j); + xt_ematch_foreach(ematch, e) { + ret = check_match(ematch, &mtpar, &j); + if (ret != 0) + break; + } if (ret) goto cleanup_matches; @@ -1689,7 +1731,9 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, return 0; cleanup_matches: - IP6T_MATCH_ITERATE(e, cleanup_match, net, &j); + xt_ematch_foreach(ematch, e) + if (cleanup_match(ematch, net, &j) != 0) + break; return ret; } diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 6f21b4377dbb..0e357ac9a2a8 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -239,6 +239,7 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par) { const struct xt_tcpmss_info *info = par->targinfo; const struct ipt_entry *e = par->entryinfo; + const struct xt_entry_match *ematch; if (info->mss == XT_TCPMSS_CLAMP_PMTU && (par->hook_mask & ~((1 << NF_INET_FORWARD) | @@ -248,8 +249,9 @@ static bool tcpmss_tg4_check(const struct xt_tgchk_param *par) "FORWARD, OUTPUT and POSTROUTING hooks\n"); return false; } - if (IPT_MATCH_ITERATE(e, find_syn_match)) - return true; + xt_ematch_foreach(ematch, e) + if (find_syn_match(ematch)) + return true; printk("xt_TCPMSS: Only works on TCP SYN packets\n"); return false; } @@ -259,6 +261,7 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par) { const struct xt_tcpmss_info *info = par->targinfo; const struct ip6t_entry *e = par->entryinfo; + const struct xt_entry_match *ematch; if (info->mss == XT_TCPMSS_CLAMP_PMTU && (par->hook_mask & ~((1 << NF_INET_FORWARD) | @@ -268,8 +271,9 @@ static bool tcpmss_tg6_check(const struct xt_tgchk_param *par) "FORWARD, OUTPUT and POSTROUTING hooks\n"); return false; } - if (IP6T_MATCH_ITERATE(e, find_syn_match)) - return true; + xt_ematch_foreach(ematch, e) + if (find_syn_match(ematch)) + return true; printk("xt_TCPMSS: Only works on TCP SYN packets\n"); return false; } -- cgit v1.2.3 From 6bdb331bc6910d1ccb74dc9852fc858c5916c927 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Feb 2010 18:35:37 +0100 Subject: netfilter: xtables: optimize call flow around xt_ematch_foreach Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/ip_tables.c | 93 ++++++++++++++--------------------------- net/ipv6/netfilter/ip6_tables.c | 93 ++++++++++++++--------------------------- 2 files changed, 62 insertions(+), 124 deletions(-) diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3a7fc732b918..36edc7d5f284 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -572,14 +572,10 @@ mark_source_chains(const struct xt_table_info *newinfo, return 1; } -static int -cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) +static void cleanup_match(struct ipt_entry_match *m, struct net *net) { struct xt_mtdtor_param par; - if (i && (*i)-- == 0) - return 1; - par.net = net; par.match = m->u.kernel.match; par.matchinfo = m->data; @@ -587,7 +583,6 @@ cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) if (par.match->destroy != NULL) par.match->destroy(&par); module_put(par.match->me); - return 0; } static int @@ -612,8 +607,7 @@ check_entry(const struct ipt_entry *e, const char *name) } static int -check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, - unsigned int *i) +check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) { const struct ipt_ip *ip = par->entryinfo; int ret; @@ -628,13 +622,11 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, par.match->name); return ret; } - ++*i; return 0; } static int -find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, - unsigned int *i) +find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) { struct xt_match *match; int ret; @@ -648,7 +640,7 @@ find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, } m->u.kernel.match = match; - ret = check_match(m, par, i); + ret = check_match(m, par); if (ret) goto err; @@ -704,12 +696,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV4; xt_ematch_foreach(ematch, e) { - ret = find_check_match(ematch, &mtpar, &j); + ret = find_check_match(ematch, &mtpar); if (ret != 0) - break; + goto cleanup_matches; + ++j; } - if (ret != 0) - goto cleanup_matches; t = ipt_get_target(e); target = try_then_request_module(xt_find_target(AF_INET, @@ -730,9 +721,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + cleanup_match(ematch, net); + } return ret; } @@ -807,8 +800,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net) /* Cleanup all matches */ xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, NULL) != 0) - break; + cleanup_match(ematch, net); t = ipt_get_target(e); par.net = net; @@ -1064,13 +1056,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; } -static inline int -compat_calc_match(const struct ipt_entry_match *m, int *size) -{ - *size += xt_compat_match_offset(m->u.kernel.match); - return 0; -} - static int compat_calc_entry(const struct ipt_entry *e, const struct xt_table_info *info, const void *base, struct xt_table_info *newinfo) @@ -1083,8 +1068,7 @@ static int compat_calc_entry(const struct ipt_entry *e, off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); entry_offset = (void *)e - base; xt_ematch_foreach(ematch, e) - if (compat_calc_match(ematch, &off) != 0) - break; + off += xt_compat_match_offset(ematch->u.kernel.match); t = ipt_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; @@ -1475,11 +1459,9 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, xt_ematch_foreach(ematch, e) { ret = xt_compat_match_to_user(ematch, dstptr, size); if (ret != 0) - break; + return ret; } target_offset = e->target_offset - (origsize - *size); - if (ret) - return ret; t = ipt_get_target(e); ret = xt_compat_target_to_user(t, dstptr, size); if (ret) @@ -1496,7 +1478,7 @@ compat_find_calc_match(struct ipt_entry_match *m, const char *name, const struct ipt_ip *ip, unsigned int hookmask, - int *size, unsigned int *i) + int *size) { struct xt_match *match; @@ -1510,18 +1492,6 @@ compat_find_calc_match(struct ipt_entry_match *m, } m->u.kernel.match = match; *size += xt_compat_match_offset(match); - - (*i)++; - return 0; -} - -static int -compat_release_match(struct ipt_entry_match *m, unsigned int *i) -{ - if (i && (*i)-- == 0) - return 1; - - module_put(m->u.kernel.match->me); return 0; } @@ -1532,8 +1502,7 @@ static void compat_release_entry(struct compat_ipt_entry *e) /* Cleanup all matches */ xt_ematch_foreach(ematch, e) - if (compat_release_match(ematch, NULL) != 0) - break; + module_put(ematch->u.kernel.match->me); t = compat_ipt_get_target(e); module_put(t->u.kernel.target->me); } @@ -1579,12 +1548,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, j = 0; xt_ematch_foreach(ematch, e) { ret = compat_find_calc_match(ematch, name, - &e->ip, e->comefrom, &off, &j); + &e->ip, e->comefrom, &off); if (ret != 0) - break; + goto release_matches; + ++j; } - if (ret != 0) - goto release_matches; t = compat_ipt_get_target(e); target = try_then_request_module(xt_find_target(AF_INET, @@ -1621,9 +1589,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, out: module_put(t->u.kernel.target->me); release_matches: - xt_ematch_foreach(ematch, e) - if (compat_release_match(ematch, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + module_put(ematch->u.kernel.match->me); + } return ret; } @@ -1651,10 +1621,8 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, xt_ematch_foreach(ematch, e) { ret = xt_compat_match_from_user(ematch, dstptr, size); if (ret != 0) - break; + return ret; } - if (ret) - return ret; de->target_offset = e->target_offset - (origsize - *size); t = compat_ipt_get_target(e); target = t->u.kernel.target; @@ -1685,12 +1653,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV4; xt_ematch_foreach(ematch, e) { - ret = check_match(ematch, &mtpar, &j); + ret = check_match(ematch, &mtpar); if (ret != 0) - break; + goto cleanup_matches; + ++j; } - if (ret) - goto cleanup_matches; ret = check_target(e, net, name); if (ret) @@ -1698,9 +1665,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) return 0; cleanup_matches: - xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + cleanup_match(ematch, net); + } return ret; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1537e6bad5d9..c5a963e4b545 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -603,14 +603,10 @@ mark_source_chains(const struct xt_table_info *newinfo, return 1; } -static int -cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) +static void cleanup_match(struct ip6t_entry_match *m, struct net *net) { struct xt_mtdtor_param par; - if (i && (*i)-- == 0) - return 1; - par.net = net; par.match = m->u.kernel.match; par.matchinfo = m->data; @@ -618,7 +614,6 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) if (par.match->destroy != NULL) par.match->destroy(&par); module_put(par.match->me); - return 0; } static int @@ -642,8 +637,7 @@ check_entry(const struct ip6t_entry *e, const char *name) return 0; } -static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, - unsigned int *i) +static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) { const struct ip6t_ip6 *ipv6 = par->entryinfo; int ret; @@ -658,13 +652,11 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, par.match->name); return ret; } - ++*i; return 0; } static int -find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, - unsigned int *i) +find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) { struct xt_match *match; int ret; @@ -678,7 +670,7 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, } m->u.kernel.match = match; - ret = check_match(m, par, i); + ret = check_match(m, par); if (ret) goto err; @@ -735,12 +727,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV6; xt_ematch_foreach(ematch, e) { - ret = find_check_match(ematch, &mtpar, &j); + ret = find_check_match(ematch, &mtpar); if (ret != 0) - break; + goto cleanup_matches; + ++j; } - if (ret != 0) - goto cleanup_matches; t = ip6t_get_target(e); target = try_then_request_module(xt_find_target(AF_INET6, @@ -761,9 +752,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, err: module_put(t->u.kernel.target->me); cleanup_matches: - xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + cleanup_match(ematch, net); + } return ret; } @@ -837,8 +830,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) /* Cleanup all matches */ xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, NULL) != 0) - break; + cleanup_match(ematch, net); t = ip6t_get_target(e); par.net = net; @@ -1094,13 +1086,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; } -static inline int -compat_calc_match(const struct ip6t_entry_match *m, int *size) -{ - *size += xt_compat_match_offset(m->u.kernel.match); - return 0; -} - static int compat_calc_entry(const struct ip6t_entry *e, const struct xt_table_info *info, const void *base, struct xt_table_info *newinfo) @@ -1113,8 +1098,7 @@ static int compat_calc_entry(const struct ip6t_entry *e, off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); entry_offset = (void *)e - base; xt_ematch_foreach(ematch, e) - if (compat_calc_match(ematch, &off) != 0) - break; + off += xt_compat_match_offset(ematch->u.kernel.match); t = ip6t_get_target_c(e); off += xt_compat_target_offset(t->u.kernel.target); newinfo->size -= off; @@ -1508,11 +1492,9 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, xt_ematch_foreach(ematch, e) { ret = xt_compat_match_to_user(ematch, dstptr, size); if (ret != 0) - break; + return ret; } target_offset = e->target_offset - (origsize - *size); - if (ret) - return ret; t = ip6t_get_target(e); ret = xt_compat_target_to_user(t, dstptr, size); if (ret) @@ -1529,7 +1511,7 @@ compat_find_calc_match(struct ip6t_entry_match *m, const char *name, const struct ip6t_ip6 *ipv6, unsigned int hookmask, - int *size, unsigned int *i) + int *size) { struct xt_match *match; @@ -1543,18 +1525,6 @@ compat_find_calc_match(struct ip6t_entry_match *m, } m->u.kernel.match = match; *size += xt_compat_match_offset(match); - - (*i)++; - return 0; -} - -static int -compat_release_match(struct ip6t_entry_match *m, unsigned int *i) -{ - if (i && (*i)-- == 0) - return 1; - - module_put(m->u.kernel.match->me); return 0; } @@ -1565,8 +1535,7 @@ static void compat_release_entry(struct compat_ip6t_entry *e) /* Cleanup all matches */ xt_ematch_foreach(ematch, e) - if (compat_release_match(ematch, NULL) != 0) - break; + module_put(ematch->u.kernel.match->me); t = compat_ip6t_get_target(e); module_put(t->u.kernel.target->me); } @@ -1612,12 +1581,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, j = 0; xt_ematch_foreach(ematch, e) { ret = compat_find_calc_match(ematch, name, - &e->ipv6, e->comefrom, &off, &j); + &e->ipv6, e->comefrom, &off); if (ret != 0) - break; + goto release_matches; + ++j; } - if (ret != 0) - goto release_matches; t = compat_ip6t_get_target(e); target = try_then_request_module(xt_find_target(AF_INET6, @@ -1654,9 +1622,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, out: module_put(t->u.kernel.target->me); release_matches: - xt_ematch_foreach(ematch, e) - if (compat_release_match(ematch, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + module_put(ematch->u.kernel.match->me); + } return ret; } @@ -1684,10 +1654,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, xt_ematch_foreach(ematch, e) { ret = xt_compat_match_from_user(ematch, dstptr, size); if (ret != 0) - break; + return ret; } - if (ret) - return ret; de->target_offset = e->target_offset - (origsize - *size); t = compat_ip6t_get_target(e); target = t->u.kernel.target; @@ -1718,12 +1686,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, mtpar.hook_mask = e->comefrom; mtpar.family = NFPROTO_IPV6; xt_ematch_foreach(ematch, e) { - ret = check_match(ematch, &mtpar, &j); + ret = check_match(ematch, &mtpar); if (ret != 0) - break; + goto cleanup_matches; + ++j; } - if (ret) - goto cleanup_matches; ret = check_target(e, net, name); if (ret) @@ -1731,9 +1698,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, return 0; cleanup_matches: - xt_ematch_foreach(ematch, e) - if (cleanup_match(ematch, net, &j) != 0) + xt_ematch_foreach(ematch, e) { + if (j-- == 0) break; + cleanup_match(ematch, net); + } return ret; } -- cgit v1.2.3 From 0f234214d15fa914436d304ecf5c3e43449e79f9 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 24 Feb 2010 18:36:04 +0100 Subject: netfilter: xtables: reduce arguments to translate_table Just pass in the entire repl struct. In case of a new table (e.g. ip6t_register_table), the repldata has been previously filled with table->name and table->size already (in ip6t_alloc_initial_table). Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/arp_tables.c | 42 +++++++++++++++-------------------------- net/ipv4/netfilter/ip_tables.c | 42 +++++++++++++++-------------------------- net/ipv6/netfilter/ip6_tables.c | 42 +++++++++++++++-------------------------- 3 files changed, 45 insertions(+), 81 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 5fdedeb46218..57098dcda294 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -622,21 +622,15 @@ static inline void cleanup_entry(struct arpt_entry *e) /* Checks and translates the user-supplied table segment (held in * newinfo). */ -static int translate_table(const char *name, - unsigned int valid_hooks, - struct xt_table_info *newinfo, - void *entry0, - unsigned int size, - unsigned int number, - const unsigned int *hook_entries, - const unsigned int *underflows) +static int translate_table(struct xt_table_info *newinfo, void *entry0, + const struct arpt_replace *repl) { struct arpt_entry *iter; unsigned int i; int ret = 0; - newinfo->size = size; - newinfo->number = number; + newinfo->size = repl->size; + newinfo->number = repl->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { @@ -650,7 +644,8 @@ static int translate_table(const char *name, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, valid_hooks); + entry0 + repl->size, repl->hook_entry, repl->underflow, + repl->valid_hooks); if (ret != 0) break; ++i; @@ -659,30 +654,30 @@ static int translate_table(const char *name, if (ret != 0) return ret; - if (i != number) { + if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", - i, number); + i, repl->num_entries); return -EINVAL; } /* Check hooks all assigned */ for (i = 0; i < NF_ARP_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(repl->valid_hooks & (1 << i))) continue; if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, repl->hook_entry[i]); return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, repl->underflow[i]); return -EINVAL; } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) { + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { duprintf("Looping hook\n"); return -ELOOP; } @@ -690,7 +685,7 @@ static int translate_table(const char *name, /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, name, size); + ret = find_check_entry(iter, repl->name, repl->size); if (ret != 0) break; ++i; @@ -1101,9 +1096,7 @@ static int do_replace(struct net *net, const void __user *user, goto free_newinfo; } - ret = translate_table(tmp.name, tmp.valid_hooks, - newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, - tmp.hook_entry, tmp.underflow); + ret = translate_table(newinfo, loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; @@ -1795,12 +1788,7 @@ struct xt_table *arpt_register_table(struct net *net, loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(table->name, table->valid_hooks, - newinfo, loc_cpu_entry, repl->size, - repl->num_entries, - repl->hook_entry, - repl->underflow); - + ret = translate_table(newinfo, loc_cpu_entry, repl); duprintf("arpt_register_table: translate table gives %d\n", ret); if (ret != 0) goto out_free; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 36edc7d5f284..c92f4e541cf6 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -815,22 +815,15 @@ cleanup_entry(struct ipt_entry *e, struct net *net) /* Checks and translates the user-supplied table segment (held in newinfo) */ static int -translate_table(struct net *net, - const char *name, - unsigned int valid_hooks, - struct xt_table_info *newinfo, - void *entry0, - unsigned int size, - unsigned int number, - const unsigned int *hook_entries, - const unsigned int *underflows) +translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, + const struct ipt_replace *repl) { struct ipt_entry *iter; unsigned int i; int ret = 0; - newinfo->size = size; - newinfo->number = number; + newinfo->size = repl->size; + newinfo->number = repl->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { @@ -843,42 +836,43 @@ translate_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, valid_hooks); + entry0 + repl->size, repl->hook_entry, repl->underflow, + repl->valid_hooks); if (ret != 0) return ret; ++i; } - if (i != number) { + if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", - i, number); + i, repl->num_entries); return -EINVAL; } /* Check hooks all assigned */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(repl->valid_hooks & (1 << i))) continue; if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, repl->hook_entry[i]); return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, repl->underflow[i]); return -EINVAL; } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) return -ELOOP; /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, name, size); + ret = find_check_entry(iter, net, repl->name, repl->size); if (ret != 0) break; ++i; @@ -1311,9 +1305,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_table(net, tmp.name, tmp.valid_hooks, - newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, - tmp.hook_entry, tmp.underflow); + ret = translate_table(net, newinfo, loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; @@ -2112,11 +2104,7 @@ struct xt_table *ipt_register_table(struct net *net, loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(net, table->name, table->valid_hooks, - newinfo, loc_cpu_entry, repl->size, - repl->num_entries, - repl->hook_entry, - repl->underflow); + ret = translate_table(net, newinfo, loc_cpu_entry, repl); if (ret != 0) goto out_free; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index c5a963e4b545..f7042869198e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -845,22 +845,15 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) /* Checks and translates the user-supplied table segment (held in newinfo) */ static int -translate_table(struct net *net, - const char *name, - unsigned int valid_hooks, - struct xt_table_info *newinfo, - void *entry0, - unsigned int size, - unsigned int number, - const unsigned int *hook_entries, - const unsigned int *underflows) +translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, + const struct ip6t_replace *repl) { struct ip6t_entry *iter; unsigned int i; int ret = 0; - newinfo->size = size; - newinfo->number = number; + newinfo->size = repl->size; + newinfo->number = repl->num_entries; /* Init all hooks to impossible value. */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { @@ -873,42 +866,43 @@ translate_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + size, hook_entries, underflows, valid_hooks); + entry0 + repl->size, repl->hook_entry, repl->underflow, + repl->valid_hooks); if (ret != 0) return ret; ++i; } - if (i != number) { + if (i != repl->num_entries) { duprintf("translate_table: %u not %u entries\n", - i, number); + i, repl->num_entries); return -EINVAL; } /* Check hooks all assigned */ for (i = 0; i < NF_INET_NUMHOOKS; i++) { /* Only hooks which are valid */ - if (!(valid_hooks & (1 << i))) + if (!(repl->valid_hooks & (1 << i))) continue; if (newinfo->hook_entry[i] == 0xFFFFFFFF) { duprintf("Invalid hook entry %u %u\n", - i, hook_entries[i]); + i, repl->hook_entry[i]); return -EINVAL; } if (newinfo->underflow[i] == 0xFFFFFFFF) { duprintf("Invalid underflow %u %u\n", - i, underflows[i]); + i, repl->underflow[i]); return -EINVAL; } } - if (!mark_source_chains(newinfo, valid_hooks, entry0)) + if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) return -ELOOP; /* Finally, each sanity check must pass */ i = 0; xt_entry_foreach(iter, entry0, newinfo->size) { - ret = find_check_entry(iter, net, name, size); + ret = find_check_entry(iter, net, repl->name, repl->size); if (ret != 0) break; ++i; @@ -1342,9 +1336,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len) goto free_newinfo; } - ret = translate_table(net, tmp.name, tmp.valid_hooks, - newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, - tmp.hook_entry, tmp.underflow); + ret = translate_table(net, newinfo, loc_cpu_entry, &tmp); if (ret != 0) goto free_newinfo; @@ -2145,11 +2137,7 @@ struct xt_table *ip6t_register_table(struct net *net, loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; memcpy(loc_cpu_entry, repl->entries, repl->size); - ret = translate_table(net, table->name, table->valid_hooks, - newinfo, loc_cpu_entry, repl->size, - repl->num_entries, - repl->hook_entry, - repl->underflow); + ret = translate_table(net, newinfo, loc_cpu_entry, repl); if (ret != 0) goto out_free; -- cgit v1.2.3 From 9abd5438641425c2f8a3a399c921747a4fb55adc Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Mon, 22 Feb 2010 05:47:58 +0000 Subject: KS8695: Don't call netif_carrier_off() from ndo_stop() netif_carrier_on() and netif_carrier_off() should be called from link status interrupt handler Signed-off-by: Yegor Yefremov Signed-off-by: David S. Miller --- drivers/net/arm/ks8695net.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 238069699515..8ca639127dbc 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1333,7 +1333,6 @@ ks8695_stop(struct net_device *ndev) netif_stop_queue(ndev); napi_disable(&ksp->napi); - netif_carrier_off(ndev); ks8695_shutdown(ksp); -- cgit v1.2.3 From 2ac2ed5f2dfc97ae9ed9f446ad6e064fa821ef6d Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 13:08:51 +0000 Subject: gigaset: small documentation improvement Clarify the non-support by isdnlog, and propose a better standard debug mask. Impact: Documentation Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- Documentation/isdn/README.gigaset | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset index 794941fc9493..e472df842323 100644 --- a/Documentation/isdn/README.gigaset +++ b/Documentation/isdn/README.gigaset @@ -292,10 +292,10 @@ GigaSet 307x Device Driver to /etc/modprobe.d/gigaset, /etc/modprobe.conf.local or a similar file. Problem: - Your isdn script aborts with a message about isdnlog. + The isdnlog program emits error messages or just doesn't work. Solution: - Try deactivating (or commenting out) isdnlog. This driver does not - support it. + Isdnlog supports only the HiSax driver. Do not attempt to use it with + other drivers such as Gigaset. Problem: You have two or more DECT data adapters (M101/M105) and only the @@ -321,8 +321,8 @@ GigaSet 307x Device Driver writing an appropriate value to /sys/module/gigaset/parameters/debug, e.g. echo 0 > /sys/module/gigaset/parameters/debug switches off debugging output completely, - echo 0x10a020 > /sys/module/gigaset/parameters/debug - enables the standard set of debugging output messages. These values are + echo 0x302020 > /sys/module/gigaset/parameters/debug + enables a reasonable set of debugging output messages. These values are bit patterns where every bit controls a certain type of debugging output. See the constants DEBUG_* in the source file gigaset.h for details. -- cgit v1.2.3 From 63e055d1c6e3a5f6d370cc841d621d5fa4d5d834 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 13:09:22 +0000 Subject: bas_gigaset: collapse CR/LF at end of AT response Copy the mechanism from ser_/usb_gigaset to avoid producing spurious empty responses for CR/LF sequences from the device. Add a comment in all drivers documenting that behaviour. Correct an off by one error that might result in a one byte buffer overflow when receiving an unexpectedly long reply. Impact: minor bugfix Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 2 ++ drivers/isdn/gigaset/gigaset.h | 4 ++-- drivers/isdn/gigaset/isocdata.c | 44 ++++++++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index ccb2a7b7c41d..e913beb63f24 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -40,6 +40,8 @@ static inline int muststuff(unsigned char c) * Append received bytes to the command response buffer and forward them * line by line to the response handler. Exit whenever a mode/state change * might have occurred. + * Note: Received lines may be terminated by CR, LF, or CR LF, which will be + * removed before passing the line to the response handler. * Return value: * number of processed bytes */ diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index e963a6c2e86d..c9ccf7de2275 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -38,7 +38,7 @@ #define GIG_COMPAT {0, 4, 0, 0} #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 512 /* Max. size of a response string */ +#define MAX_RESP_SIZE 511 /* Max. size of a response string */ #define MAX_EVENTS 64 /* size of event queue */ @@ -498,7 +498,7 @@ struct cardstate { spinlock_t ev_lock; /* current modem response */ - unsigned char respdata[MAX_RESP_SIZE]; + unsigned char respdata[MAX_RESP_SIZE+1]; unsigned cbytes; /* private data of hardware drivers */ diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 85394a6ebae8..16fd3bd48883 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -905,29 +905,49 @@ void gigaset_isoc_receive(unsigned char *src, unsigned count, /* == data input =========================================================== */ +/* process a block of received bytes in command mode (mstate != MS_LOCKED) + * Append received bytes to the command response buffer and forward them + * line by line to the response handler. + * Note: Received lines may be terminated by CR, LF, or CR LF, which will be + * removed before passing the line to the response handler. + */ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; unsigned cbytes = cs->cbytes; + unsigned char c; while (numbytes--) { - /* copy next character, check for end of line */ - switch (cs->respdata[cbytes] = *src++) { - case '\r': + c = *src++; + switch (c) { case '\n': - /* end of line */ - gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); - if (cbytes >= MAX_RESP_SIZE - 1) - dev_warn(cs->dev, "response too large\n"); + if (cbytes == 0 && cs->respdata[0] == '\r') { + /* collapse LF with preceding CR */ + cs->respdata[0] = 0; + break; + } + /* --v-- fall through --v-- */ + case '\r': + /* end of message line, pass to response handler */ + if (cbytes >= MAX_RESP_SIZE) { + dev_warn(cs->dev, "response too large (%d)\n", + cbytes); + cbytes = MAX_RESP_SIZE; + } cs->cbytes = cbytes; + gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", + cbytes, cs->respdata); gigaset_handle_modem_response(cs); cbytes = 0; + + /* store EOL byte for CRLF collapsing */ + cs->respdata[0] = c; break; default: - /* advance in line buffer, checking for overflow */ - if (cbytes < MAX_RESP_SIZE - 1) - cbytes++; + /* append to line buffer if possible */ + if (cbytes < MAX_RESP_SIZE) + cs->respdata[cbytes] = c; + cbytes++; } } @@ -958,8 +978,6 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) numbytes, src); gigaset_if_receive(inbuf->cs, src, numbytes); } else { - gigaset_dbg_buffer(DEBUG_CMD, "received response", - numbytes, src); cmd_loop(src, numbytes, inbuf); } -- cgit v1.2.3 From 1528b18f7ec2b907711f37667c68e10d9296c882 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Mon, 22 Feb 2010 13:09:52 +0000 Subject: gigaset: reduce syslog clutter Improve readability of the Gigaset driver's kernel messages by removing a few unnecessary messages and limiting the emission of some debug messages more narrowly. Impact: logging Signed-off-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/asyncdata.c | 4 +-- drivers/isdn/gigaset/bas-gigaset.c | 18 ++++------- drivers/isdn/gigaset/capi.c | 15 +++------ drivers/isdn/gigaset/common.c | 49 ++++++++++++----------------- drivers/isdn/gigaset/ev-layer.c | 63 +++++++++++++++++++------------------- drivers/isdn/gigaset/gigaset.h | 7 ++--- drivers/isdn/gigaset/i4l.c | 52 ++++--------------------------- drivers/isdn/gigaset/interface.c | 12 +++----- drivers/isdn/gigaset/proc.c | 2 -- drivers/isdn/gigaset/usb-gigaset.c | 2 +- 10 files changed, 77 insertions(+), 147 deletions(-) diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index e913beb63f24..c5016bd2d94f 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -67,14 +67,14 @@ static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) /* --v-- fall through --v-- */ case '\r': /* end of message line, pass to response handler */ - gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)", - __func__, cbytes); if (cbytes >= MAX_RESP_SIZE) { dev_warn(cs->dev, "response too large (%d)\n", cbytes); cbytes = MAX_RESP_SIZE; } cs->cbytes = cbytes; + gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", + cbytes, cs->respdata); gigaset_handle_modem_response(cs); cbytes = 0; diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 95ebc5129895..0be15c70c16d 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -347,12 +347,7 @@ static inline void error_hangup(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; - gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", - __func__, bcs->channel); - - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) - dev_err(cs->dev, "event queue full\n"); - + gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL); gigaset_schedule_event(cs); } @@ -1706,8 +1701,7 @@ static void complete_cb(struct cardstate *cs) /* unqueue completed buffer */ cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, - "write_command: sent %u bytes, %u left", + gig_dbg(DEBUG_OUTPUT, "write_command: sent %u bytes, %u left", cs->curlen, cs->cmdbytes); if (cb->next != NULL) { cs->cmdbuf = cb->next; @@ -1881,13 +1875,13 @@ static int start_cbsend(struct cardstate *cs) /* check if suspend requested */ if (ucs->basstate & BS_SUSPEND) { - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); + gig_dbg(DEBUG_OUTPUT, "suspending"); return -EHOSTUNREACH; } /* check if AT channel is open */ if (!(ucs->basstate & BS_ATOPEN)) { - gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); + gig_dbg(DEBUG_OUTPUT, "AT channel not open"); rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); if (rc < 0) { /* flush command queue */ @@ -2251,7 +2245,7 @@ static int gigaset_probe(struct usb_interface *interface, int i, j; int rc; - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_INIT, "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", __func__, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); @@ -2259,7 +2253,7 @@ static int gigaset_probe(struct usb_interface *interface, /* set required alternate setting */ hostif = interface->cur_altsetting; if (hostif->desc.bAlternateSetting != 3) { - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_INIT, "%s: wrong alternate setting %d - trying to switch", __func__, hostif->desc.bAlternateSetting); if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 6f0ae32906bf..20ebcee9b0c0 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -1427,9 +1427,10 @@ static void do_connect_req(struct gigaset_capi_ctr *iif, /* queue & schedule EV_DIAL event */ if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, - bcs->at_state.seq_index, NULL)) - goto oom; - gig_dbg(DEBUG_CMD, "scheduling DIAL"); + bcs->at_state.seq_index, NULL)) { + info = CAPI_MSGOSRESOURCEERR; + goto error; + } gigaset_schedule_event(cs); ap->connected = APCONN_SETUP; send_conf(iif, ap, skb, CapiSuccess); @@ -1543,7 +1544,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_ACCEPT, NULL, 0, NULL)) return; - gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); return; @@ -1584,7 +1584,6 @@ static void do_connect_resp(struct gigaset_capi_ctr *iif, if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_HUP, NULL, 0, NULL)) return; - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); return; } @@ -1667,11 +1666,9 @@ static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); dev_kfree_skb_any(skb); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* emit DISCONNECT_B3_IND */ @@ -1770,11 +1767,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_IND */ if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* emit reply */ @@ -1817,11 +1812,9 @@ static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, /* trigger hangup, causing eventual DISCONNECT_B3_IND */ if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, EV_HUP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); return; } - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); /* NCPI parameter: not applicable for B3 Transparent */ diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 664b0c519c3e..85de3399a2f2 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -149,10 +149,8 @@ static int test_timeout(struct at_state_t *at_state) return 0; } - if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL)) - dev_err(at_state->cs->dev, "%s: out of memory\n", - __func__); + gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, + at_state->timer_index, NULL); return 1; } @@ -180,7 +178,7 @@ static void timer_tick(unsigned long data) if (cs->running) { mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); if (timeout) { - gig_dbg(DEBUG_CMD, "scheduling timeout"); + gig_dbg(DEBUG_EVENT, "scheduling timeout"); tasklet_schedule(&cs->event_tasklet); } } @@ -194,14 +192,14 @@ int gigaset_get_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { - gig_dbg(DEBUG_ANY, "could not allocate channel %d", + gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 0; } ++bcs->use_count; bcs->busy = 1; - gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 1; } @@ -213,7 +211,7 @@ struct bc_state *gigaset_get_free_channel(struct cardstate *cs) spin_lock_irqsave(&cs->lock, flags); if (!try_module_get(cs->driver->owner)) { - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_CHANNEL, "could not get module for allocating channel"); spin_unlock_irqrestore(&cs->lock, flags); return NULL; @@ -223,12 +221,12 @@ struct bc_state *gigaset_get_free_channel(struct cardstate *cs) ++cs->bcs[i].use_count; cs->bcs[i].busy = 1; spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "allocated channel %d", i); + gig_dbg(DEBUG_CHANNEL, "allocated channel %d", i); return cs->bcs + i; } module_put(cs->driver->owner); spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "no free channel"); + gig_dbg(DEBUG_CHANNEL, "no free channel"); return NULL; } @@ -238,14 +236,15 @@ void gigaset_free_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (!bcs->busy) { - gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "could not free channel %d", + bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return; } --bcs->use_count; bcs->busy = 0; module_put(bcs->cs->driver->owner); - gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); + gig_dbg(DEBUG_CHANNEL, "freed channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); } @@ -258,14 +257,15 @@ int gigaset_get_channels(struct cardstate *cs) for (i = 0; i < cs->channels; ++i) if (cs->bcs[i].use_count) { spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "could not allocate all channels"); + gig_dbg(DEBUG_CHANNEL, + "could not allocate all channels"); return 0; } for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_ANY, "allocated all channels"); + gig_dbg(DEBUG_CHANNEL, "allocated all channels"); return 1; } @@ -275,7 +275,7 @@ void gigaset_free_channels(struct cardstate *cs) unsigned long flags; int i; - gig_dbg(DEBUG_ANY, "unblocking all channels"); + gig_dbg(DEBUG_CHANNEL, "unblocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) --cs->bcs[i].use_count; @@ -287,7 +287,7 @@ void gigaset_block_channels(struct cardstate *cs) unsigned long flags; int i; - gig_dbg(DEBUG_ANY, "blocking all channels"); + gig_dbg(DEBUG_CHANNEL, "blocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; @@ -338,6 +338,8 @@ struct event_t *gigaset_add_event(struct cardstate *cs, unsigned next, tail; struct event_t *event = NULL; + gig_dbg(DEBUG_EVENT, "queueing event %d", type); + spin_lock_irqsave(&cs->ev_lock, flags); tail = cs->ev_tail; @@ -934,11 +936,8 @@ int gigaset_start(struct cardstate *cs) if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { cs->waiting = 0; - dev_err(cs->dev, "%s: out of memory\n", __func__); goto error; } - - gig_dbg(DEBUG_CMD, "scheduling START"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -973,12 +972,8 @@ int gigaset_shutdown(struct cardstate *cs) cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); + if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) goto exit; - } - - gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -1004,12 +999,8 @@ void gigaset_stop(struct cardstate *cs) cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { - dev_err(cs->dev, "%s: out of memory\n", __func__); + if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) goto exit; - } - - gig_dbg(DEBUG_CMD, "scheduling STOP"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index ddeb0456d202..c8f89b78b233 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -427,7 +427,7 @@ static int isdn_getnum(char *p) { int v = -1; - gig_dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_EVENT, "string: %s", p); while (*p >= '0' && *p <= '9') v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); @@ -444,7 +444,7 @@ static int isdn_gethex(char *p) int v = 0; int c; - gig_dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_EVENT, "string: %s", p); if (!*p) return -1; @@ -517,7 +517,6 @@ void gigaset_handle_modem_response(struct cardstate *cs) return; } cs->respdata[len] = 0; - gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); argv[0] = cs->respdata; params = 1; if (cs->at_state.getstring) { @@ -552,14 +551,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) for (j = 1; j < params; ++j) argv[j][-1] = 0; - gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); + gig_dbg(DEBUG_EVENT, "CMD received: %s", argv[0]); if (cid) { --params; - gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); + gig_dbg(DEBUG_EVENT, "CID: %s", argv[params]); } - gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); + gig_dbg(DEBUG_EVENT, "available params: %d", params - 1); for (j = 1; j < params; j++) - gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); + gig_dbg(DEBUG_EVENT, "param %d: %s", j, argv[j]); } spin_lock_irqsave(&cs->ev_lock, flags); @@ -642,7 +641,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) dev_err(cs->dev, "out of memory\n"); ++curarg; } - gig_dbg(DEBUG_CMD, "string==%s", + gig_dbg(DEBUG_EVENT, "string==%s", event->ptr ? (char *) event->ptr : "NULL"); break; case RT_ZCAU: @@ -669,7 +668,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) ++curarg; } else event->parameter = -1; - gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); + gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter); break; } @@ -684,7 +683,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) spin_unlock_irqrestore(&cs->ev_lock, flags); if (curarg != params) - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_EVENT, "invalid number of processed parameters: %d/%d", curarg, params); } @@ -705,8 +704,8 @@ static void disconnect(struct at_state_t **at_state_p) /* revert to selected idle mode */ if (!cs->cidmode) { cs->at_state.pending_commands |= PC_UMMODE; + gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } spin_unlock_irqrestore(&cs->lock, flags); @@ -784,15 +783,15 @@ static void init_failed(struct cardstate *cs, int mode) static void schedule_init(struct cardstate *cs, int state) { if (cs->at_state.pending_commands & PC_INIT) { - gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); + gig_dbg(DEBUG_EVENT, "not scheduling PC_INIT again"); return; } cs->mstate = state; cs->mode = M_UNKNOWN; gigaset_block_channels(cs); cs->at_state.pending_commands |= PC_INIT; + gig_dbg(DEBUG_EVENT, "Scheduling PC_INIT"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); } /* Add "AT" to a command, add the cid, dle encode it, send the result to the @@ -923,7 +922,7 @@ static void start_dial(struct at_state_t *at_state, void *data, } at_state->pending_commands |= PC_CID; - gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CID"); cs->commands_pending = 1; return; @@ -933,7 +932,7 @@ error: commands[i] = NULL; } at_state->pending_commands |= PC_NOCID; - gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_NOCID"); cs->commands_pending = 1; return; } @@ -955,7 +954,7 @@ static void start_accept(struct at_state_t *at_state) dev_err(at_state->cs->dev, "out of memory\n"); /* error reset */ at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); cs->commands_pending = 1; return; } @@ -964,7 +963,7 @@ static void start_accept(struct at_state_t *at_state) snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_ACCEPT"); cs->commands_pending = 1; } @@ -1009,8 +1008,8 @@ static void do_shutdown(struct cardstate *cs) if (cs->mstate == MS_READY) { cs->mstate = MS_SHUTDOWN; cs->at_state.pending_commands |= PC_SHUTDOWN; + gig_dbg(DEBUG_EVENT, "Scheduling PC_SHUTDOWN"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); } else finish_shutdown(cs); } @@ -1191,8 +1190,8 @@ static void do_action(int action, struct cardstate *cs, } spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands |= PC_CIDMODE; + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); break; case ACT_FAILINIT: dev_warn(cs->dev, "Could not initialize the device.\n"); @@ -1443,7 +1442,7 @@ static void do_action(int action, struct cardstate *cs, case ACT_GOTVER: if (cs->gotfwver == 0) { cs->gotfwver = 1; - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_EVENT, "firmware version %02d.%03d.%02d.%02d", cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); @@ -1481,8 +1480,8 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_HUP: at_state->pending_commands |= PC_HUP; + gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); cs->commands_pending = 1; - gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); break; /* hotplug events */ @@ -1519,10 +1518,10 @@ static void do_action(int action, struct cardstate *cs, cs->cidmode = ev->parameter; if (ev->parameter) { cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); } else { cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); } cs->commands_pending = 1; } @@ -1573,6 +1572,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (ev->cid >= 0) { at_state = at_state_from_cid(cs, ev->cid); if (!at_state) { + gig_dbg(DEBUG_EVENT, "event %d for invalid cid %d", + ev->type, ev->cid); gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, NULL, 0, NULL); return; @@ -1580,13 +1581,13 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else { at_state = ev->at_state; if (at_state_invalid(cs, at_state)) { - gig_dbg(DEBUG_ANY, "event for invalid at_state %p", + gig_dbg(DEBUG_EVENT, "event for invalid at_state %p", at_state); return; } } - gig_dbg(DEBUG_CMD, "connection state %d, event %d", + gig_dbg(DEBUG_EVENT, "connection state %d, event %d", at_state->ConState, ev->type); bcs = at_state->bcs; @@ -1600,11 +1601,11 @@ static void process_event(struct cardstate *cs, struct event_t *ev) if (ev->parameter != at_state->timer_index || !at_state->timer_active) { ev->type = RSP_NONE; /* old timeout */ - gig_dbg(DEBUG_ANY, "old timeout"); + gig_dbg(DEBUG_EVENT, "old timeout"); } else if (!at_state->waiting) - gig_dbg(DEBUG_ANY, "timeout occurred"); + gig_dbg(DEBUG_EVENT, "timeout occurred"); else - gig_dbg(DEBUG_ANY, "stopped waiting"); + gig_dbg(DEBUG_EVENT, "stopped waiting"); } spin_unlock_irqrestore(&cs->lock, flags); @@ -1712,11 +1713,11 @@ static void process_command_flags(struct cardstate *cs) cs->commands_pending = 0; if (cs->cur_at_seq) { - gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); + gig_dbg(DEBUG_EVENT, "not searching scheduled commands: busy"); return; } - gig_dbg(DEBUG_CMD, "searching scheduled commands"); + gig_dbg(DEBUG_EVENT, "searching scheduled commands"); sequence = SEQ_NONE; @@ -1857,7 +1858,7 @@ static void process_command_flags(struct cardstate *cs) switch (cs->mode) { case M_UNIMODEM: cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); cs->commands_pending = 1; return; #ifdef GIG_MAYINITONDIAL diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index c9ccf7de2275..1875ab80b335 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -78,9 +78,10 @@ enum debuglevel { DEBUG_STREAM = 0x00040, /* application data stream I/O events */ DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ DEBUG_LLDATA = 0x00100, /* sent/received LL data */ + DEBUG_EVENT = 0x00200, /* event processing */ DEBUG_DRIVER = 0x00400, /* driver structure */ DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ - DEBUG_WRITE = 0x01000, /* M105 data write */ + DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */ DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data @@ -785,8 +786,6 @@ static inline void gigaset_schedule_event(struct cardstate *cs) static inline void gigaset_bchannel_down(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - - gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED"); gigaset_schedule_event(bcs->cs); } @@ -795,8 +794,6 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs) static inline void gigaset_bchannel_up(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - - gig_dbg(DEBUG_CMD, "scheduling BC_OPEN"); gigaset_schedule_event(bcs->cs); } diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index c129ee47a8fb..f0acb9dc9e33 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -216,7 +216,7 @@ static int command_from_LL(isdn_ctrl *cntrl) return -EINVAL; case ISDN_CMD_DIAL: - gig_dbg(DEBUG_ANY, + gig_dbg(DEBUG_CMD, "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, cntrl->parm.setup.si1, cntrl->parm.setup.si2); @@ -304,11 +304,10 @@ static int command_from_LL(isdn_ctrl *cntrl) gigaset_free_channel(bcs); return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTD: + gig_dbg(DEBUG_CMD, "ISDN_CMD_ACCEPTD"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); @@ -318,14 +317,11 @@ static int command_from_LL(isdn_ctrl *cntrl) if (!gigaset_add_event(cs, &bcs->at_state, EV_ACCEPT, NULL, 0, NULL)) return -ENOMEM; - - gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); - break; - case ISDN_CMD_ACCEPTB: break; case ISDN_CMD_HANGUP: + gig_dbg(DEBUG_CMD, "ISDN_CMD_HANGUP"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); @@ -335,8 +331,6 @@ static int command_from_LL(isdn_ctrl *cntrl) if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) return -ENOMEM; - - gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; @@ -376,6 +370,7 @@ static int command_from_LL(isdn_ctrl *cntrl) } break; case ISDN_CMD_SETL3: /* Set L3 to given protocol */ + gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL3"); if (ch >= cs->channels) { dev_err(cs->dev, "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); @@ -390,44 +385,9 @@ static int command_from_LL(isdn_ctrl *cntrl) } break; - case ISDN_CMD_PROCEED: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); - break; - case ISDN_CMD_ALERT: - gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); - if (cntrl->arg >= cs->channels) { - dev_err(cs->dev, - "ISDN_CMD_ALERT: invalid channel (%d)\n", - (int) cntrl->arg); - return -EINVAL; - } - break; - case ISDN_CMD_REDIR: - gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); - break; - case ISDN_CMD_PROT_IO: - gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); - break; - case ISDN_CMD_FAXCMD: - gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); - break; - case ISDN_CMD_GETL2: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); - break; - case ISDN_CMD_GETL3: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); - break; - case ISDN_CMD_GETEAZ: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); - break; - case ISDN_CMD_SETSIL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); - break; - case ISDN_CMD_GETSIL: - gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); - break; + default: - dev_err(cs->dev, "unknown command %d from LL\n", + gig_dbg(DEBUG_CMD, "unknown command %d from LL", cntrl->command); return -EINVAL; } diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index d2260b0055fc..a1bcbc21ff71 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -45,8 +45,6 @@ static int if_lock(struct cardstate *cs, int *arg) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -81,8 +79,6 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) cs->waiting = 0; return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling IF_VER"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -274,7 +270,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, ? -EFAULT : 0; break; default: - gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", __func__, cmd); retval = -ENOIOCTLCMD; } @@ -455,7 +451,7 @@ static void if_throttle(struct tty_struct *tty) else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); else - gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -479,7 +475,7 @@ static void if_unthrottle(struct tty_struct *tty) else if (!cs->open_count) dev_warn(cs->dev, "%s: device not opened\n", __func__); else - gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__); + gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); mutex_unlock(&cs->mutex); } @@ -630,7 +626,7 @@ void gigaset_if_receive(struct cardstate *cs, spin_lock_irqsave(&cs->lock, flags); tty = cs->tty; if (tty == NULL) - gig_dbg(DEBUG_ANY, "receive on closed device"); + gig_dbg(DEBUG_IF, "receive on closed device"); else { tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 758a00c1d2e2..b69f73a0668f 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -48,8 +48,6 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, mutex_unlock(&cs->mutex); return -ENOMEM; } - - gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 3ab1daeb276b..9430a2bbb523 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -628,7 +628,7 @@ static int write_modem(struct cardstate *cs) struct usb_cardstate *ucs = cs->hw.usb; unsigned long flags; - gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + gig_dbg(DEBUG_OUTPUT, "len: %d...", bcs->tx_skb->len); if (!bcs->tx_skb->len) { dev_kfree_skb_any(bcs->tx_skb); -- cgit v1.2.3 From 003bdb279bb6b212f25ea4e60e0164b6109d3704 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Feb 2010 13:10:22 +0000 Subject: isdn: remove ishexdigit() in regard to isxdigit() Samll cleanup in drivers/isdn/gigaset/capi.c where own implementation of isxdigit() has been changed to kernel native one. Signed-off-by: Andy Shevchenko Acked-by: Tilman Schmidt Signed-off-by: David S. Miller --- drivers/isdn/gigaset/capi.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 20ebcee9b0c0..6643d6533ccb 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -170,20 +170,6 @@ static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, msgname, paramname); } -/* - * check for legal hex digit - */ -static inline int ishexdigit(char c) -{ - if (c >= '0' && c <= '9') - return 1; - if (c >= 'A' && c <= 'F') - return 1; - if (c >= 'a' && c <= 'f') - return 1; - return 0; -} - /* * convert hex to binary */ @@ -204,7 +190,7 @@ static int encode_ie(char *in, u8 *out, int maxlen) { int l = 0; while (*in) { - if (!ishexdigit(in[0]) || !ishexdigit(in[1]) || l >= maxlen) + if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen) return -1; out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); in += 2; -- cgit v1.2.3 From c1f51212eb809849bdc68a856ae5f424dcf20d9b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 22 Feb 2010 16:56:57 +0000 Subject: drivers/net/chelsio: Use pr_, netif_msg_ Convert CH_ and CH_DBG uses to pr_ and netif equivalents Remove CH_ and CH_DBG macro definitions Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/chelsio/common.h | 24 ++---------------------- drivers/net/chelsio/cxgb2.c | 18 +++++++++--------- drivers/net/chelsio/espi.c | 4 ++-- drivers/net/chelsio/pm3393.c | 16 +++++++++------- drivers/net/chelsio/sge.c | 10 +++++----- drivers/net/chelsio/subr.c | 32 +++++++++++++++++--------------- drivers/net/chelsio/vsc7326.c | 24 ++++++++++++------------ 7 files changed, 56 insertions(+), 72 deletions(-) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 9f89fd600643..2d11afe45310 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -36,6 +36,8 @@ * * ****************************************************************************/ +#define pr_fmt(fmt) "cxgb: " fmt + #ifndef _CXGB_COMMON_H_ #define _CXGB_COMMON_H_ @@ -55,28 +57,6 @@ #define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver" #define DRV_NAME "cxgb" #define DRV_VERSION "2.2" -#define PFX DRV_NAME ": " - -#define CH_ERR(fmt, ...) printk(KERN_ERR PFX fmt, ## __VA_ARGS__) -#define CH_WARN(fmt, ...) printk(KERN_WARNING PFX fmt, ## __VA_ARGS__) -#define CH_ALERT(fmt, ...) printk(KERN_ALERT PFX fmt, ## __VA_ARGS__) - -/* - * More powerful macro that selectively prints messages based on msg_enable. - * For info and debugging messages. - */ -#define CH_MSG(adapter, level, category, fmt, ...) do { \ - if ((adapter)->msg_enable & NETIF_MSG_##category) \ - printk(KERN_##level PFX "%s: " fmt, (adapter)->name, \ - ## __VA_ARGS__); \ -} while (0) - -#ifdef DEBUG -# define CH_DBG(adapter, category, fmt, ...) \ - CH_MSG(adapter, DEBUG, category, fmt, ## __VA_ARGS__) -#else -# define CH_DBG(fmt, ...) -#endif #define CH_DEVICE(devid, ssid, idx) \ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx } diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index a54a32b16498..0f71304e0542 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -974,7 +974,7 @@ void t1_fatal_err(struct adapter *adapter) t1_sge_stop(adapter->sge); t1_interrupts_disable(adapter); } - CH_ALERT("%s: encountered fatal error, operation suspended\n", + pr_alert("%s: encountered fatal error, operation suspended\n", adapter->name); } @@ -1018,7 +1018,7 @@ static int __devinit init_one(struct pci_dev *pdev, return err; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - CH_ERR("%s: cannot find PCI device memory base address\n", + pr_err("%s: cannot find PCI device memory base address\n", pci_name(pdev)); err = -ENODEV; goto out_disable_pdev; @@ -1028,20 +1028,20 @@ static int __devinit init_one(struct pci_dev *pdev, pci_using_dac = 1; if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - CH_ERR("%s: unable to obtain 64-bit DMA for " + pr_err("%s: unable to obtain 64-bit DMA for " "consistent allocations\n", pci_name(pdev)); err = -ENODEV; goto out_disable_pdev; } } else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { - CH_ERR("%s: no usable DMA configuration\n", pci_name(pdev)); + pr_err("%s: no usable DMA configuration\n", pci_name(pdev)); goto out_disable_pdev; } err = pci_request_regions(pdev, DRV_NAME); if (err) { - CH_ERR("%s: cannot obtain PCI resources\n", pci_name(pdev)); + pr_err("%s: cannot obtain PCI resources\n", pci_name(pdev)); goto out_disable_pdev; } @@ -1069,7 +1069,7 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->regs = ioremap(mmio_start, mmio_len); if (!adapter->regs) { - CH_ERR("%s: cannot map device registers\n", + pr_err("%s: cannot map device registers\n", pci_name(pdev)); err = -ENOMEM; goto out_free_dev; @@ -1148,8 +1148,8 @@ static int __devinit init_one(struct pci_dev *pdev, for (i = 0; i < bi->port_number; ++i) { err = register_netdev(adapter->port[i].dev); if (err) - CH_WARN("%s: cannot register net device %s, skipping\n", - pci_name(pdev), adapter->port[i].dev->name); + pr_warning("%s: cannot register net device %s, skipping\n", + pci_name(pdev), adapter->port[i].dev->name); else { /* * Change the name we use for messages to the name of @@ -1162,7 +1162,7 @@ static int __devinit init_one(struct pci_dev *pdev, } } if (!adapter->registered_device_map) { - CH_ERR("%s: could not register any net devices\n", + pr_err("%s: could not register any net devices\n", pci_name(pdev)); goto out_release_adapter_res; } diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c index 1e0749e000b0..639ff1955739 100644 --- a/drivers/net/chelsio/espi.c +++ b/drivers/net/chelsio/espi.c @@ -76,7 +76,7 @@ static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr, } while (busy && --attempts); if (busy) - CH_ERR("%s: TRICN write timed out\n", adapter->name); + pr_err("%s: TRICN write timed out\n", adapter->name); return busy; } @@ -86,7 +86,7 @@ static int tricn_init(adapter_t *adapter) int i, sme = 1; if (!(readl(adapter->regs + A_ESPI_RX_RESET) & F_RX_CLK_STATUS)) { - CH_ERR("%s: ESPI clock not ready\n", adapter->name); + pr_err("%s: ESPI clock not ready\n", adapter->name); return -1; } diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 33d674f36722..a6eb30a6e2b9 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -251,8 +251,9 @@ static int pm3393_interrupt_handler(struct cmac *cmac) /* Read the master interrupt status register. */ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &master_intr_status); - CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n", - master_intr_status); + if (netif_msg_intr(cmac->adapter)) + dev_dbg(&cmac->adapter->pdev->dev, "PM3393 intr cause 0x%x\n", + master_intr_status); /* TBD XXX Lets just clear everything for now */ pm3393_interrupt_clear(cmac); @@ -776,11 +777,12 @@ static int pm3393_mac_reset(adapter_t * adapter) successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock && is_xaui_mabc_pll_locked); - CH_DBG(adapter, HW, - "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, " - "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n", - i, is_pl4_reset_finished, val, is_pl4_outof_lock, - is_xaui_mabc_pll_locked); + if (netif_msg_hw(adapter)) + dev_dbg(&adapter->pdev->dev, + "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, " + "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n", + i, is_pl4_reset_finished, val, + is_pl4_outof_lock, is_xaui_mabc_pll_locked); } return successful_reset ? 0 : 1; } diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 8e12505ac3aa..71384114a4ed 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -953,7 +953,7 @@ int t1_sge_intr_error_handler(struct sge *sge) sge->stats.respQ_empty++; if (cause & F_RESPQ_OVERFLOW) { sge->stats.respQ_overflow++; - CH_ALERT("%s: SGE response queue overflow\n", + pr_alert("%s: SGE response queue overflow\n", adapter->name); } if (cause & F_FL_EXHAUSTED) { @@ -962,12 +962,12 @@ int t1_sge_intr_error_handler(struct sge *sge) } if (cause & F_PACKET_TOO_BIG) { sge->stats.pkt_too_big++; - CH_ALERT("%s: SGE max packet size exceeded\n", + pr_alert("%s: SGE max packet size exceeded\n", adapter->name); } if (cause & F_PACKET_MISMATCH) { sge->stats.pkt_mismatch++; - CH_ALERT("%s: SGE packet mismatch\n", adapter->name); + pr_alert("%s: SGE packet mismatch\n", adapter->name); } if (cause & SGE_INT_FATAL) t1_fatal_err(adapter); @@ -1101,7 +1101,7 @@ static void unexpected_offload(struct adapter *adapter, struct freelQ *fl) pci_dma_sync_single_for_cpu(adapter->pdev, pci_unmap_addr(ce, dma_addr), pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE); - CH_ERR("%s: unexpected offload packet, cmd %u\n", + pr_err("%s: unexpected offload packet, cmd %u\n", adapter->name, *skb->data); recycle_fl_buf(fl, fl->cidx); } @@ -1687,7 +1687,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, netif_stop_queue(dev); set_bit(dev->if_port, &sge->stopped_tx_queues); sge->stats.cmdQ_full[2]++; - CH_ERR("%s: Tx ring full while queue awake!\n", + pr_err("%s: Tx ring full while queue awake!\n", adapter->name); } spin_unlock(&q->lock); diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 2402d372c886..53bde15fc94d 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -90,7 +90,7 @@ int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1, TPI_ATTEMPTS, 3); if (tpi_busy) - CH_ALERT("%s: TPI write to 0x%x failed\n", + pr_alert("%s: TPI write to 0x%x failed\n", adapter->name, addr); return tpi_busy; } @@ -118,7 +118,7 @@ int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1, TPI_ATTEMPTS, 3); if (tpi_busy) - CH_ALERT("%s: TPI read from 0x%x failed\n", + pr_alert("%s: TPI read from 0x%x failed\n", adapter->name, addr); else *valp = readl(adapter->regs + A_TPI_RD_DATA); @@ -262,7 +262,7 @@ static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg) udelay(10); } while (busy && --attempts); if (busy) - CH_ALERT("%s: MDIO operation timed out\n", adapter->name); + pr_alert("%s: MDIO operation timed out\n", adapter->name); return busy; } @@ -581,7 +581,7 @@ int t1_seeprom_read(adapter_t *adapter, u32 addr, __le32 *data) } while (!(val & F_VPD_OP_FLAG) && --i); if (!(val & F_VPD_OP_FLAG)) { - CH_ERR("%s: reading EEPROM address 0x%x failed\n", + pr_err("%s: reading EEPROM address 0x%x failed\n", adapter->name, addr); return -EIO; } @@ -734,8 +734,9 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) break; case CHBT_BOARD_8000: case CHBT_BOARD_CHT110: - CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n", - cause); + if (netif_msg_intr(adapter)) + dev_dbg(&adapter->pdev->dev, + "External interrupt cause 0x%x\n", cause); if (cause & ELMER0_GP_BIT1) { /* PMC3393 INTB */ struct cmac *mac = adapter->port[0].mac; @@ -746,8 +747,9 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); - CH_MSG(adapter, INFO, LINK, "XPAK %s\n", - mod_detect ? "removed" : "inserted"); + if (netif_msg_link(adapter)) + dev_info(&adapter->pdev->dev, "XPAK %s\n", + mod_detect ? "removed" : "inserted"); } break; #ifdef CONFIG_CHELSIO_T1_COUGAR @@ -1084,7 +1086,7 @@ static void __devinit init_link_config(struct link_config *lc, #ifdef CONFIG_CHELSIO_T1_COUGAR if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) { - CH_ERR("%s: CSPI initialization failed\n", + pr_err("%s: CSPI initialization failed\n", adapter->name); goto error; } @@ -1105,20 +1107,20 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, adapter->sge = t1_sge_create(adapter, &adapter->params.sge); if (!adapter->sge) { - CH_ERR("%s: SGE initialization failed\n", + pr_err("%s: SGE initialization failed\n", adapter->name); goto error; } if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) { - CH_ERR("%s: ESPI initialization failed\n", + pr_err("%s: ESPI initialization failed\n", adapter->name); goto error; } adapter->tp = t1_tp_create(adapter, &adapter->params.tp); if (!adapter->tp) { - CH_ERR("%s: TP initialization failed\n", + pr_err("%s: TP initialization failed\n", adapter->name); goto error; } @@ -1138,14 +1140,14 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, adapter->port[i].phy = bi->gphy->create(adapter->port[i].dev, phy_addr, bi->mdio_ops); if (!adapter->port[i].phy) { - CH_ERR("%s: PHY %d initialization failed\n", + pr_err("%s: PHY %d initialization failed\n", adapter->name, i); goto error; } adapter->port[i].mac = mac = bi->gmac->create(adapter, i); if (!mac) { - CH_ERR("%s: MAC %d initialization failed\n", + pr_err("%s: MAC %d initialization failed\n", adapter->name, i); goto error; } @@ -1157,7 +1159,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY) mac->ops->macaddress_get(mac, hw_addr); else if (vpd_macaddress_get(adapter, i, hw_addr)) { - CH_ERR("%s: could not read MAC address from VPD ROM\n", + pr_err("%s: could not read MAC address from VPD ROM\n", adapter->port[i].dev->name); goto error; } diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c index 99b51f61fe77..c844111cffeb 100644 --- a/drivers/net/chelsio/vsc7326.c +++ b/drivers/net/chelsio/vsc7326.c @@ -48,14 +48,14 @@ static void vsc_read(adapter_t *adapter, u32 addr, u32 *val) i++; } while (((status & 1) == 0) && (i < 50)); if (i == 50) - CH_ERR("Invalid tpi read from MAC, breaking loop.\n"); + pr_err("Invalid tpi read from MAC, breaking loop.\n"); t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo); t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi); *val = (vhi << 16) | vlo; - /* CH_ERR("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", + /* pr_err("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", ((addr&0xe000)>>13), ((addr&0x1e00)>>9), ((addr&0x01fe)>>1), *val); */ spin_unlock_bh(&adapter->mac_lock); @@ -66,7 +66,7 @@ static void vsc_write(adapter_t *adapter, u32 addr, u32 data) spin_lock_bh(&adapter->mac_lock); t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF); t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF); - /* CH_ERR("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", + /* pr_err("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", ((addr&0xe000)>>13), ((addr&0x1e00)>>9), ((addr&0x01fe)>>1), data); */ spin_unlock_bh(&adapter->mac_lock); @@ -225,7 +225,7 @@ static void run_table(adapter_t *adapter, struct init_table *ib, int len) for (i = 0; i < len; i++) { if (ib[i].addr == INITBLOCK_SLEEP) { udelay( ib[i].data ); - CH_ERR("sleep %d us\n",ib[i].data); + pr_err("sleep %d us\n",ib[i].data); } else vsc_write( adapter, ib[i].addr, ib[i].data ); } @@ -241,7 +241,7 @@ static int bist_rd(adapter_t *adapter, int moduleid, int address) (address != 0x2) && (address != 0xd) && (address != 0xe)) - CH_ERR("No bist address: 0x%x\n", address); + pr_err("No bist address: 0x%x\n", address); data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) | ((moduleid & 0xff) << 0)); @@ -251,9 +251,9 @@ static int bist_rd(adapter_t *adapter, int moduleid, int address) vsc_read(adapter, REG_RAM_BIST_RESULT, &result); if ((result & (1 << 9)) != 0x0) - CH_ERR("Still in bist read: 0x%x\n", result); + pr_err("Still in bist read: 0x%x\n", result); else if ((result & (1 << 8)) != 0x0) - CH_ERR("bist read error: 0x%x\n", result); + pr_err("bist read error: 0x%x\n", result); return (result & 0xff); } @@ -268,10 +268,10 @@ static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) (address != 0x2) && (address != 0xd) && (address != 0xe)) - CH_ERR("No bist address: 0x%x\n", address); + pr_err("No bist address: 0x%x\n", address); if (value > 255) - CH_ERR("Suspicious write out of range value: 0x%x\n", value); + pr_err("Suspicious write out of range value: 0x%x\n", value); data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) | ((moduleid & 0xff) << 0)); @@ -281,9 +281,9 @@ static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) vsc_read(adapter, REG_RAM_BIST_CMD, &result); if ((result & (1 << 27)) != 0x0) - CH_ERR("Still in bist write: 0x%x\n", result); + pr_err("Still in bist write: 0x%x\n", result); else if ((result & (1 << 26)) != 0x0) - CH_ERR("bist write error: 0x%x\n", result); + pr_err("bist write error: 0x%x\n", result); return 0; } @@ -306,7 +306,7 @@ static int check_bist(adapter_t *adapter, int moduleid) column = ((bist_rd(adapter,moduleid, 0x0e)<<8) + (bist_rd(adapter,moduleid, 0x0d))); if ((result & 3) != 0x3) - CH_ERR("Result: 0x%x BIST error in ram %d, column: 0x%04x\n", + pr_err("Result: 0x%x BIST error in ram %d, column: 0x%04x\n", result, moduleid, column); return 0; } -- cgit v1.2.3 From 78ca90ea995cb86c72cde9308276d2a701bd3c40 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 22 Feb 2010 16:56:58 +0000 Subject: drivers/net/myri10ge: Use pr_ and netdev_ Add #define pr_fmt(fmt) Convert logging messages to pr_ and netdev_ Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 183 +++++++++++++++------------------------- 1 file changed, 67 insertions(+), 116 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c0884a9cba3c..1d14a8b05fa0 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -38,6 +38,8 @@ * Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006 *************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -819,9 +821,7 @@ static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) status = myri10ge_send_cmd(mgp, ctl, &cmd, 0); if (status) { - printk(KERN_ERR - "myri10ge: %s: Failed to set flow control mode\n", - mgp->dev->name); + netdev_err(mgp->dev, "Failed to set flow control mode\n"); return status; } mgp->pause = pause; @@ -837,8 +837,7 @@ myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic) ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC; status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic); if (status) - printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n", - mgp->dev->name); + netdev_err(mgp->dev, "Failed to set promisc mode\n"); } static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) @@ -1482,19 +1481,15 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) if (mgp->link_state == MXGEFW_LINK_UP) { if (netif_msg_link(mgp)) - printk(KERN_INFO - "myri10ge: %s: link up\n", - mgp->dev->name); + netdev_info(mgp->dev, "link up\n"); netif_carrier_on(mgp->dev); mgp->link_changes++; } else { if (netif_msg_link(mgp)) - printk(KERN_INFO - "myri10ge: %s: link %s\n", - mgp->dev->name, - (link_up == MXGEFW_LINK_MYRINET ? - "mismatch (Myrinet detected)" : - "down")); + netdev_info(mgp->dev, "link %s\n", + link_up == MXGEFW_LINK_MYRINET ? + "mismatch (Myrinet detected)" : + "down"); netif_carrier_off(mgp->dev); mgp->link_changes++; } @@ -1503,9 +1498,8 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) ntohl(stats->rdma_tags_available)) { mgp->rdma_tags_available = ntohl(stats->rdma_tags_available); - printk(KERN_WARNING "myri10ge: %s: RDMA timed out! " - "%d tags left\n", mgp->dev->name, - mgp->rdma_tags_available); + netdev_warn(mgp->dev, "RDMA timed out! %d tags left\n", + mgp->rdma_tags_available); } mgp->down_cnt += stats->link_down; if (stats->link_down) @@ -1576,8 +1570,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) if (send_done_count != tx->pkt_done) myri10ge_tx_done(ss, (int)send_done_count); if (unlikely(i > myri10ge_max_irq_loops)) { - printk(KERN_WARNING "myri10ge: %s: irq stuck?\n", - mgp->dev->name); + netdev_err(mgp->dev, "irq stuck?\n"); stats->valid = 0; schedule_work(&mgp->watchdog_work); } @@ -1614,16 +1607,14 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) */ ptr = mgp->product_code_string; if (ptr == NULL) { - printk(KERN_ERR "myri10ge: %s: Missing product code\n", - netdev->name); + netdev_err(netdev, "Missing product code\n"); return 0; } for (i = 0; i < 3; i++, ptr++) { ptr = strchr(ptr, '-'); if (ptr == NULL) { - printk(KERN_ERR "myri10ge: %s: Invalid product " - "code %s\n", netdev->name, - mgp->product_code_string); + netdev_err(netdev, "Invalid product code %s\n", + mgp->product_code_string); return 0; } } @@ -2009,17 +2000,15 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) mgp->small_bytes + MXGEFW_PAD, 0); if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) { - printk(KERN_ERR - "myri10ge: %s:slice-%d: alloced only %d small bufs\n", - dev->name, slice, ss->rx_small.fill_cnt); + netdev_err(dev, "slice-%d: alloced only %d small bufs\n", + slice, ss->rx_small.fill_cnt); goto abort_with_rx_small_ring; } myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 0); if (ss->rx_big.fill_cnt < ss->rx_big.mask + 1) { - printk(KERN_ERR - "myri10ge: %s:slice-%d: alloced only %d big bufs\n", - dev->name, slice, ss->rx_big.fill_cnt); + netdev_err(dev, "slice-%d: alloced only %d big bufs\n", + slice, ss->rx_big.fill_cnt); goto abort_with_rx_big_ring; } @@ -2358,7 +2347,7 @@ static int myri10ge_open(struct net_device *dev) mgp->running = MYRI10GE_ETH_STARTING; status = myri10ge_reset(mgp); if (status != 0) { - printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name); + netdev_err(dev, "failed reset\n"); goto abort_with_nothing; } @@ -2370,9 +2359,7 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, &cmd, 0); if (status != 0) { - printk(KERN_ERR - "myri10ge: %s: failed to set number of slices\n", - dev->name); + netdev_err(dev, "failed to set number of slices\n"); goto abort_with_nothing; } /* setup the indirection table */ @@ -2384,9 +2371,7 @@ static int myri10ge_open(struct net_device *dev) MXGEFW_CMD_GET_RSS_TABLE_OFFSET, &cmd, 0); if (status != 0) { - printk(KERN_ERR - "myri10ge: %s: failed to setup rss tables\n", - dev->name); + netdev_err(dev, "failed to setup rss tables\n"); goto abort_with_nothing; } @@ -2400,9 +2385,7 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_ENABLE, &cmd, 0); if (status != 0) { - printk(KERN_ERR - "myri10ge: %s: failed to enable slices\n", - dev->name); + netdev_err(dev, "failed to enable slices\n"); goto abort_with_nothing; } } @@ -2450,9 +2433,7 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_get_txrx(mgp, slice); if (status != 0) { - printk(KERN_ERR - "myri10ge: %s: failed to get ring sizes or locations\n", - dev->name); + netdev_err(dev, "failed to get ring sizes or locations\n"); goto abort_with_rings; } status = myri10ge_allocate_rings(ss); @@ -2465,9 +2446,7 @@ static int myri10ge_open(struct net_device *dev) if (slice == 0 || mgp->dev->real_num_tx_queues > 1) status = myri10ge_set_stats(mgp, slice); if (status) { - printk(KERN_ERR - "myri10ge: %s: Couldn't set stats DMA\n", - dev->name); + netdev_err(dev, "Couldn't set stats DMA\n"); goto abort_with_rings; } @@ -2498,8 +2477,7 @@ static int myri10ge_open(struct net_device *dev) status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0); if (status) { - printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n", - dev->name); + netdev_err(dev, "Couldn't set buffer sizes\n"); goto abort_with_rings; } @@ -2511,8 +2489,7 @@ static int myri10ge_open(struct net_device *dev) cmd.data0 = 0; status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_TSO_MODE, &cmd, 0); if (status && status != -ENOSYS) { - printk(KERN_ERR "myri10ge: %s: Couldn't set TSO mode\n", - dev->name); + netdev_err(dev, "Couldn't set TSO mode\n"); goto abort_with_rings; } @@ -2521,8 +2498,7 @@ static int myri10ge_open(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); if (status) { - printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n", - dev->name); + netdev_err(dev, "Couldn't bring up link\n"); goto abort_with_rings; } @@ -2575,15 +2551,12 @@ static int myri10ge_close(struct net_device *dev) status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0); if (status) - printk(KERN_ERR - "myri10ge: %s: Couldn't bring down link\n", - dev->name); + netdev_err(dev, "Couldn't bring down link\n"); wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ); if (old_down_cnt == mgp->down_cnt) - printk(KERN_ERR "myri10ge: %s never got down irq\n", - dev->name); + netdev_err(dev, "never got down irq\n"); } netif_tx_disable(dev); myri10ge_free_irq(mgp); @@ -2944,9 +2917,7 @@ abort_linearize: idx = (idx + 1) & tx->mask; } while (idx != last_idx); if (skb_is_gso(skb)) { - printk(KERN_ERR - "myri10ge: %s: TSO but wanted to linearize?!?!?\n", - mgp->dev->name); + netdev_err(mgp->dev, "TSO but wanted to linearize?!?!?\n"); goto drop; } @@ -3043,8 +3014,8 @@ static void myri10ge_set_multicast_list(struct net_device *dev) err = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1); if (err != 0) { - printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_ENABLE_ALLMULTI," - " error status: %d\n", dev->name, err); + netdev_err(dev, "Failed MXGEFW_ENABLE_ALLMULTI, error status: %d\n", + err); goto abort; } @@ -3058,9 +3029,8 @@ static void myri10ge_set_multicast_list(struct net_device *dev) err = myri10ge_send_cmd(mgp, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS, &cmd, 1); if (err != 0) { - printk(KERN_ERR - "myri10ge: %s: Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS" - ", error status: %d\n", dev->name, err); + netdev_err(dev, "Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS, error status: %d\n", + err); goto abort; } @@ -3073,18 +3043,16 @@ static void myri10ge_set_multicast_list(struct net_device *dev) &cmd, 1); if (err != 0) { - printk(KERN_ERR "myri10ge: %s: Failed " - "MXGEFW_JOIN_MULTICAST_GROUP, error status:" - "%d\t", dev->name, err); - printk(KERN_ERR "MAC %pM\n", mc_list->dmi_addr); + netdev_err(dev, "Failed MXGEFW_JOIN_MULTICAST_GROUP, error status:%d %pM\n", + err, mc_list->dmi_addr); goto abort; } } /* Enable multicast filtering */ err = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_ALLMULTI, &cmd, 1); if (err != 0) { - printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_DISABLE_ALLMULTI," - "error status: %d\n", dev->name, err); + netdev_err(dev, "Failed MXGEFW_DISABLE_ALLMULTI, error status: %d\n", + err); goto abort; } @@ -3105,9 +3073,8 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr) status = myri10ge_update_mac_address(mgp, sa->sa_data); if (status != 0) { - printk(KERN_ERR - "myri10ge: %s: changing mac address failed with %d\n", - dev->name, status); + netdev_err(dev, "changing mac address failed with %d\n", + status); return status; } @@ -3122,12 +3089,10 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) int error = 0; if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) { - printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n", - dev->name, new_mtu); + netdev_err(dev, "new mtu (%d) is not valid\n", new_mtu); return -EINVAL; } - printk(KERN_INFO "%s: changing mtu from %d to %d\n", - dev->name, dev->mtu, new_mtu); + netdev_info(dev, "changing mtu from %d to %d\n", dev->mtu, new_mtu); if (mgp->running) { /* if we change the mtu on an active device, we must * reset the device so the firmware sees the change */ @@ -3356,7 +3321,7 @@ static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(netdev); if (netif_running(netdev)) { - printk(KERN_INFO "myri10ge: closing %s\n", netdev->name); + netdev_info(netdev, "closing\n"); rtnl_lock(); myri10ge_close(netdev); rtnl_unlock(); @@ -3383,8 +3348,7 @@ static int myri10ge_resume(struct pci_dev *pdev) msleep(5); /* give card time to respond */ pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); if (vendor == 0xffff) { - printk(KERN_ERR "myri10ge: %s: device disappeared!\n", - mgp->dev->name); + netdev_err(mgp->dev, "device disappeared!\n"); return -EIO; } @@ -3463,10 +3427,9 @@ static void myri10ge_watchdog(struct work_struct *work) * if the card rebooted due to a parity error * For now, just report it */ reboot = myri10ge_read_reboot(mgp); - printk(KERN_ERR - "myri10ge: %s: NIC rebooted (0x%x),%s resetting\n", - mgp->dev->name, reboot, - myri10ge_reset_recover ? " " : " not"); + netdev_err(mgp->dev, "NIC rebooted (0x%x),%s resetting\n", + reboot, + myri10ge_reset_recover ? "" : " not"); if (myri10ge_reset_recover == 0) return; rtnl_lock(); @@ -3494,31 +3457,26 @@ static void myri10ge_watchdog(struct work_struct *work) if (cmd == 0xffff) { pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); if (vendor == 0xffff) { - printk(KERN_ERR - "myri10ge: %s: device disappeared!\n", - mgp->dev->name); + netdev_err(mgp->dev, "device disappeared!\n"); return; } } /* Perhaps it is a software error. Try to reset */ - printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n", - mgp->dev->name); + netdev_err(mgp->dev, "device timeout, resetting\n"); for (i = 0; i < mgp->num_slices; i++) { tx = &mgp->ss[i].tx; - printk(KERN_INFO - "myri10ge: %s: (%d): %d %d %d %d %d %d\n", - mgp->dev->name, i, tx->queue_active, tx->req, - tx->done, tx->pkt_start, tx->pkt_done, - (int)ntohl(mgp->ss[i].fw_stats-> - send_done_count)); + netdev_err(mgp->dev, "(%d): %d %d %d %d %d %d\n", + i, tx->queue_active, tx->req, + tx->done, tx->pkt_start, tx->pkt_done, + (int)ntohl(mgp->ss[i].fw_stats-> + send_done_count)); msleep(2000); - printk(KERN_INFO - "myri10ge: %s: (%d): %d %d %d %d %d %d\n", - mgp->dev->name, i, tx->queue_active, tx->req, - tx->done, tx->pkt_start, tx->pkt_done, - (int)ntohl(mgp->ss[i].fw_stats-> - send_done_count)); + netdev_info(mgp->dev, "(%d): %d %d %d %d %d %d\n", + i, tx->queue_active, tx->req, + tx->done, tx->pkt_start, tx->pkt_done, + (int)ntohl(mgp->ss[i].fw_stats-> + send_done_count)); } } @@ -3528,8 +3486,7 @@ static void myri10ge_watchdog(struct work_struct *work) } status = myri10ge_load_firmware(mgp, 1); if (status != 0) - printk(KERN_ERR "myri10ge: %s: failed to load firmware\n", - mgp->dev->name); + netdev_err(mgp->dev, "failed to load firmware\n"); else myri10ge_open(mgp->dev); rtnl_unlock(); @@ -3580,14 +3537,10 @@ static void myri10ge_watchdog_timer(unsigned long arg) /* nic seems like it might be stuck.. */ if (rx_pause_cnt != mgp->watchdog_pause) { if (net_ratelimit()) - printk(KERN_WARNING - "myri10ge %s slice %d:" - "TX paused, check link partner\n", - mgp->dev->name, i); + netdev_err(mgp->dev, "slice %d: TX paused, check link partner\n", + i); } else { - printk(KERN_WARNING - "myri10ge %s slice %d stuck:", - mgp->dev->name, i); + netdev_warn(mgp->dev, "slice %d stuck:", i); reset_needed = 1; } } @@ -4127,13 +4080,11 @@ static struct notifier_block myri10ge_dca_notifier = { static __init int myri10ge_init_module(void) { - printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name, - MYRI10GE_VERSION_STR); + pr_info("Version %s\n", MYRI10GE_VERSION_STR); if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX) { - printk(KERN_ERR - "%s: Illegal rssh hash type %d, defaulting to source port\n", - myri10ge_driver.name, myri10ge_rss_hash); + pr_err("Illegal rssh hash type %d, defaulting to source port\n", + myri10ge_rss_hash); myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_PORT; } #ifdef CONFIG_MYRI10GE_DCA -- cgit v1.2.3 From 52c793f24054f5dc30d228e37e0e19cc8313f086 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Mon, 22 Feb 2010 22:21:17 +0000 Subject: can: netlink support for bus-error reporting and counters This patch makes the bus-error reporting configurable and allows to retrieve the CAN TX and RX bus error counters via netlink interface. I have added support for the SJA1000. The TX and RX bus error counters are also copied to the data fields 6..7 of error messages when state changes are reported. Signed-off-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/dev.c | 6 ++++++ drivers/net/can/sja1000/sja1000.c | 25 ++++++++++++++++++++++--- include/linux/can/dev.h | 2 ++ include/linux/can/netlink.h | 18 ++++++++++++++---- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index f08f1202ff00..904aa369f80e 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -574,6 +574,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { [IFLA_CAN_BITTIMING_CONST] = { .len = sizeof(struct can_bittiming_const) }, [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, + [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) }, }; static int can_changelink(struct net_device *dev, @@ -649,6 +650,8 @@ static size_t can_get_size(const struct net_device *dev) size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ + if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ + size += sizeof(struct can_berr_counter); if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ size += sizeof(struct can_bittiming_const); @@ -659,6 +662,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); struct can_ctrlmode cm = {.flags = priv->ctrlmode}; + struct can_berr_counter bec; enum can_state state = priv->state; if (priv->do_get_state) @@ -669,6 +673,8 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) NLA_PUT(skb, IFLA_CAN_BITTIMING, sizeof(priv->bittiming), &priv->bittiming); NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); + if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec)) + NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec); if (priv->bittiming_const) NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, sizeof(*priv->bittiming_const), priv->bittiming_const); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index ace103a44833..145b1a731a53 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -130,8 +130,12 @@ static void set_normal_mode(struct net_device *dev) /* check reset bit */ if ((status & MOD_RM) == 0) { priv->can.state = CAN_STATE_ERROR_ACTIVE; - /* enable all interrupts */ - priv->write_reg(priv, REG_IER, IRQ_ALL); + /* enable interrupts */ + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + priv->write_reg(priv, REG_IER, IRQ_ALL); + else + priv->write_reg(priv, REG_IER, + IRQ_ALL & ~IRQ_BEI); return; } @@ -203,6 +207,17 @@ static int sja1000_set_bittiming(struct net_device *dev) return 0; } +static int sja1000_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct sja1000_priv *priv = netdev_priv(dev); + + bec->txerr = priv->read_reg(priv, REG_TXERR); + bec->rxerr = priv->read_reg(priv, REG_RXERR); + + return 0; +} + /* * initialize SJA1000 chip: * - reset chip @@ -437,6 +452,8 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } + cf->data[6] = txerr; + cf->data[7] = rxerr; } priv->can.state = state; @@ -567,7 +584,9 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) priv->can.bittiming_const = &sja1000_bittiming_const; priv->can.do_set_bittiming = sja1000_set_bittiming; priv->can.do_set_mode = sja1000_set_mode; - priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; + priv->can.do_get_berr_counter = sja1000_get_berr_counter; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_BERR_REPORTING; if (sizeof_priv) priv->priv = (void *)priv + sizeof(struct sja1000_priv); diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index c8c660a79f90..6e5a7f00223d 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -47,6 +47,8 @@ struct can_priv { int (*do_set_mode)(struct net_device *dev, enum can_mode mode); int (*do_get_state)(const struct net_device *dev, enum can_state *state); + int (*do_get_berr_counter)(const struct net_device *dev, + struct can_berr_counter *bec); unsigned int echo_skb_max; struct sk_buff **echo_skb; diff --git a/include/linux/can/netlink.h b/include/linux/can/netlink.h index c818335fbb13..3250de935e1a 100644 --- a/include/linux/can/netlink.h +++ b/include/linux/can/netlink.h @@ -69,6 +69,14 @@ enum can_state { CAN_STATE_MAX }; +/* + * CAN bus error counters + */ +struct can_berr_counter { + __u16 txerr; + __u16 rxerr; +}; + /* * CAN controller mode */ @@ -77,10 +85,11 @@ struct can_ctrlmode { __u32 flags; }; -#define CAN_CTRLMODE_LOOPBACK 0x1 /* Loopback mode */ -#define CAN_CTRLMODE_LISTENONLY 0x2 /* Listen-only mode */ -#define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */ -#define CAN_CTRLMODE_ONE_SHOT 0x8 /* One-Shot mode */ +#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ +#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ /* * CAN device statistics @@ -106,6 +115,7 @@ enum { IFLA_CAN_CTRLMODE, IFLA_CAN_RESTART_MS, IFLA_CAN_RESTART, + IFLA_CAN_BERR_COUNTER, __IFLA_CAN_MAX }; -- cgit v1.2.3 From f9dcbcc9e338d08c0f7de7eba4eaafbbb7f81249 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 23 Feb 2010 09:19:49 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part5 V2 removed some needless checks and also corrected bug in lp486e (dmi was passed instead of dmi->dmi_addr) Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/jme.c | 6 +----- drivers/net/korina.c | 6 ++---- drivers/net/ks8851.c | 5 ++--- drivers/net/ks8851_mll.c | 3 ++- drivers/net/ksz884x.c | 4 ++-- drivers/net/lib82596.c | 7 ++++--- drivers/net/lib8390.c | 15 ++++----------- drivers/net/ll_temac_main.c | 7 ++++--- drivers/net/lp486e.c | 4 ++-- drivers/net/mac89x0.c | 4 +--- drivers/net/macb.c | 7 ++----- drivers/net/mace.c | 11 +++++------ drivers/net/macmace.c | 12 ++++++------ drivers/net/mv643xx_eth.c | 2 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/natsemi.c | 4 ++-- drivers/net/netxen/netxen_nic_hw.c | 19 +++++++------------ drivers/net/ni5010.c | 3 ++- drivers/net/ni52.c | 8 ++++---- drivers/net/niu.c | 2 +- drivers/net/pci-skeleton.c | 6 +++--- drivers/net/pcnet32.c | 5 ++--- drivers/net/ps3_gelic_net.c | 2 +- drivers/net/qlcnic/qlcnic_hw.c | 3 +-- drivers/net/qlge/qlge_main.c | 6 ++++-- drivers/net/r6040.c | 30 +++++++++++++++--------------- drivers/net/r8169.c | 4 +--- 27 files changed, 82 insertions(+), 105 deletions(-) diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 558b6a0b15fc..0f31497833df 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -1997,7 +1997,6 @@ jme_set_multi(struct net_device *netdev) { struct jme_adapter *jme = netdev_priv(netdev); u32 mc_hash[2] = {}; - int i; spin_lock_bh(&jme->rxmcs_lock); @@ -2012,10 +2011,7 @@ jme_set_multi(struct net_device *netdev) int bit_nr; jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; - for (i = 0, mclist = netdev->mc_list; - mclist && i < netdev_mc_count(netdev); - ++i, mclist = mclist->next) { - + netdev_for_each_mc_addr(mclist, netdev) { bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); } diff --git a/drivers/net/korina.c b/drivers/net/korina.c index af0c764130e6..300c2249812d 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -482,7 +482,7 @@ static void korina_multicast_list(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); unsigned long flags; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; u32 recognise = ETH_ARC_AB; /* always accept broadcasts */ int i; @@ -502,11 +502,9 @@ static void korina_multicast_list(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { char *addrs = dmi->dmi_addr; - dmi = dmi->next; - if (!(*addrs & 1)) continue; diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index 9845ab1e5573..b5219cce12ed 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -966,13 +966,12 @@ static void ks8851_set_rx_mode(struct net_device *dev) rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA | RXCR1_RXMAFMA); } else if (dev->flags & IFF_MULTICAST && !netdev_mc_empty(dev)) { - struct dev_mc_list *mcptr = dev->mc_list; + struct dev_mc_list *mcptr; u32 crc; - int i; /* accept some multicast */ - for (i = netdev_mc_count(dev); i > 0; i--) { + netdev_for_each_mc_addr(mcptr, dev) { crc = ether_crc(ETH_ALEN, mcptr->dmi_addr); crc >>= (32 - 6); /* get top six bits */ diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index ffffb3889704..84b0e15831f9 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -1196,7 +1196,8 @@ static void ks_set_rx_mode(struct net_device *netdev) if ((netdev->flags & IFF_MULTICAST) && netdev_mc_count(netdev)) { if (netdev_mc_count(netdev) <= MAX_MCAST_LST) { int i = 0; - for (ptr = netdev->mc_list; ptr; ptr = ptr->next) { + + netdev_for_each_mc_addr(ptr, netdev) { if (!(*ptr->dmi_addr & 1)) continue; if (i >= MAX_MCAST_LST) diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c index 6f187c7e61fa..7264a3e5c2c0 100644 --- a/drivers/net/ksz884x.c +++ b/drivers/net/ksz884x.c @@ -5777,7 +5777,7 @@ static void netdev_set_rx_mode(struct net_device *dev) if (hw_priv->hw.dev_count > 1) return; - if ((dev->flags & IFF_MULTICAST) && dev->mc_count) { + if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) { int i = 0; /* List too big to support so turn on all multicast mode. */ @@ -5790,7 +5790,7 @@ static void netdev_set_rx_mode(struct net_device *dev) return; } - for (mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, dev) { if (!(*mc_ptr->dmi_addr & 1)) continue; if (i >= MAX_MULTICAST_LIST) diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c index 371b58b1d151..443c39a3732f 100644 --- a/drivers/net/lib82596.c +++ b/drivers/net/lib82596.c @@ -1396,15 +1396,16 @@ static void set_multicast_list(struct net_device *dev) cmd->cmd.command = SWAP16(CmdMulticastList); cmd->mc_cnt = SWAP16(netdev_mc_count(dev) * 6); cp = cmd->mc_addrs; - for (dmi = dev->mc_list; - cnt && dmi != NULL; - dmi = dmi->next, cnt--, cp += 6) { + netdev_for_each_mc_addr(dmi, dev) { + if (!cnt--) + break; memcpy(cp, dmi->dmi_addr, 6); if (i596_debug > 1) DEB(DEB_MULTI, printk(KERN_DEBUG "%s: Adding address %pM\n", dev->name, cp)); + cp += 6; } DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd)); i596_add_cmd(dev, &cmd->cmd); diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c index 57f25848fe80..56f66f485400 100644 --- a/drivers/net/lib8390.c +++ b/drivers/net/lib8390.c @@ -907,15 +907,8 @@ static inline void make_mc_bits(u8 *bits, struct net_device *dev) { struct dev_mc_list *dmi; - for (dmi=dev->mc_list; dmi; dmi=dmi->next) - { - u32 crc; - if (dmi->dmi_addrlen != ETH_ALEN) - { - printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); - continue; - } - crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + netdev_for_each_mc_addr(dmi, dev) { + u32 crc = ether_crc(ETH_ALEN, dmi->dmi_addr); /* * The 8390 uses the 6 most significant bits of the * CRC to index the multicast table. @@ -941,7 +934,7 @@ static void do_set_multicast_list(struct net_device *dev) if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { memset(ei_local->mcfilter, 0, 8); - if (dev->mc_list) + if (!netdev_mc_empty(dev)) make_mc_bits(ei_local->mcfilter, dev); } else @@ -975,7 +968,7 @@ static void do_set_multicast_list(struct net_device *dev) if(dev->flags&IFF_PROMISC) ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR); - else if(dev->flags&IFF_ALLMULTI || dev->mc_list) + else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR); else ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index e53440253748..a18e3485476e 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -250,9 +250,10 @@ static void temac_set_multicast_list(struct net_device *ndev) temac_indirect_out32(lp, XTE_AFM_OFFSET, XTE_AFM_EPPRM_MASK); dev_info(&ndev->dev, "Promiscuous mode enabled.\n"); } else if (!netdev_mc_empty(ndev)) { - struct dev_mc_list *mclist = ndev->mc_list; - for (i = 0; mclist && i < netdev_mc_count(ndev); i++) { + struct dev_mc_list *mclist; + i = 0; + netdev_for_each_mc_addr(mclist, ndev) { if (i >= MULTICAST_CAM_TABLE_NUM) break; multi_addr_msw = ((mclist->dmi_addr[3] << 24) | @@ -265,7 +266,7 @@ static void temac_set_multicast_list(struct net_device *ndev) (mclist->dmi_addr[4]) | (i << 16)); temac_indirect_out32(lp, XTE_MAW1_OFFSET, multi_addr_lsw); - mclist = mclist->next; + i++; } } else { val = temac_indirect_in32(lp, XTE_AFM_OFFSET); diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c index b1f5d79af61f..3e3cc04defd0 100644 --- a/drivers/net/lp486e.c +++ b/drivers/net/lp486e.c @@ -1267,8 +1267,8 @@ static void set_multicast_list(struct net_device *dev) { cmd->command = CmdMulticastList; *((unsigned short *) (cmd + 1)) = netdev_mc_count(dev) * 6; cp = ((char *)(cmd + 1))+2; - for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) { - memcpy(cp, dmi,6); + netdev_for_each_mc_addr(dmi, dev) { + memcpy(cp, dmi->dmi_addr, 6); cp += 6; } if (i596_debug & LOG_SRCDST) diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 23b633e2ac42..c292a608f9a9 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c @@ -568,9 +568,7 @@ static void set_multicast_list(struct net_device *dev) if(dev->flags&IFF_PROMISC) { lp->rx_mode = RX_ALL_ACCEPT; - } - else if((dev->flags&IFF_ALLMULTI)||dev->mc_list) - { + } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { /* The multicast-accept list is initialized to accept-all, and we rely on higher-level filtering for now. */ lp->rx_mode = RX_MULTCAST_ACCEPT; diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 7a5f89728a81..c8a18a6203c8 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -884,15 +884,12 @@ static void macb_sethashtable(struct net_device *dev) { struct dev_mc_list *curr; unsigned long mc_filter[2]; - unsigned int i, bitnr; + unsigned int bitnr; struct macb *bp = netdev_priv(dev); mc_filter[0] = mc_filter[1] = 0; - curr = dev->mc_list; - for (i = 0; i < netdev_mc_count(dev); i++, curr = curr->next) { - if (!curr) break; /* unexpected end of list */ - + netdev_for_each_mc_addr(curr, dev) { bitnr = hash_get_index(curr->dmi_addr); mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } diff --git a/drivers/net/mace.c b/drivers/net/mace.c index fdb0bbdd6782..57534f0e906d 100644 --- a/drivers/net/mace.c +++ b/drivers/net/mace.c @@ -588,7 +588,7 @@ static void mace_set_multicast(struct net_device *dev) { struct mace_data *mp = netdev_priv(dev); volatile struct mace __iomem *mb = mp->mace; - int i, j; + int i; u32 crc; unsigned long flags; @@ -598,7 +598,7 @@ static void mace_set_multicast(struct net_device *dev) mp->maccc |= PROM; } else { unsigned char multicast_filter[8]; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 8; i++) @@ -606,11 +606,10 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { crc = ether_crc_le(6, dmi->dmi_addr); - j = crc >> 26; /* bit number in multicast_filter */ - multicast_filter[j >> 3] |= 1 << (j & 7); - dmi = dmi->next; + i = crc >> 26; /* bit number in multicast_filter */ + multicast_filter[i >> 3] |= 1 << (i & 7); } } #if 0 diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 740accbf0806..4e4eac0ba176 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -496,7 +496,7 @@ static void mace_set_multicast(struct net_device *dev) { struct mace_data *mp = netdev_priv(dev); volatile struct mace *mb = mp->mace; - int i, j; + int i; u32 crc; u8 maccc; unsigned long flags; @@ -509,7 +509,7 @@ static void mace_set_multicast(struct net_device *dev) mb->maccc |= PROM; } else { unsigned char multicast_filter[8]; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < 8; i++) { @@ -518,11 +518,11 @@ static void mace_set_multicast(struct net_device *dev) } else { for (i = 0; i < 8; i++) multicast_filter[i] = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { crc = ether_crc_le(6, dmi->dmi_addr); - j = crc >> 26; /* bit number in multicast_filter */ - multicast_filter[j >> 3] |= 1 << (j & 7); - dmi = dmi->next; + /* bit number in multicast_filter */ + i = crc >> 26; + multicast_filter[i >> 3] |= 1 << (i & 7); } } diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 2733b0a3b703..c97b6e4365a9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1794,7 +1794,7 @@ oom: memset(mc_spec, 0, 0x100); memset(mc_other, 0, 0x100); - for (addr = dev->mc_list; addr != NULL; addr = addr->next) { + netdev_for_each_mc_addr(addr, dev) { u8 *a = addr->da_addr; u32 *table; int entry; diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 1d14a8b05fa0..aae2ddb5d827 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3035,7 +3035,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) } /* Walk the multicast list, and add each address */ - for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) { + netdev_for_each_mc_addr(mc_list, dev) { memcpy(data, &mc_list->dmi_addr, 6); cmd.data0 = ntohl(data[0]); cmd.data1 = ntohl(data[1]); diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index c64e5b0d3596..e52038783245 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -2495,9 +2495,9 @@ static void __set_rx_mode(struct net_device *dev) } else { struct dev_mc_list *mclist; int i; + memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int b = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff; mc_filter[b/8] |= (1 << (b & 0x07)); } diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 25f4414cc33e..a945591298a8 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -539,7 +539,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct dev_mc_list *mc_ptr; u8 null_addr[6]; - int index = 0; + int i; memset(null_addr, 0, 6); @@ -570,16 +570,13 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) netxen_nic_enable_mcast_filter(adapter); - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++) - netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr); - - if (index != netdev_mc_count(netdev)) - printk(KERN_WARNING "%s: %s multicast address count mismatch\n", - netxen_nic_driver_name, netdev->name); + i = 0; + netdev_for_each_mc_addr(mc_ptr, netdev) + netxen_nic_set_mcast_addr(adapter, i++, mc_ptr->dmi_addr); /* Clear out remaining addresses */ - for (; index < adapter->max_mc_count; index++) - netxen_nic_set_mcast_addr(adapter, index, null_addr); + while (i < adapter->max_mc_count) + netxen_nic_set_mcast_addr(adapter, i++, null_addr); } static int @@ -710,10 +707,8 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) } if (!netdev_mc_empty(netdev)) { - for (mc_ptr = netdev->mc_list; mc_ptr; - mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); - } } send_fw_cmd: diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 6a87d810e59d..c16cbfb4061b 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -651,7 +651,8 @@ static void ni5010_set_multicast_list(struct net_device *dev) PRINTK2((KERN_DEBUG "%s: entering set_multicast_list\n", dev->name)); - if (dev->flags&IFF_PROMISC || dev->flags&IFF_ALLMULTI || dev->mc_list) { + if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || + !netdev_mc_empty(dev)) { outb(RMD_PROMISC, EDLC_RMODE); /* Enable promiscuous mode */ PRINTK((KERN_DEBUG "%s: Entering promiscuous mode\n", dev->name)); } else { diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 497c6d514a68..05c29c2cef2a 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -596,7 +596,7 @@ static int init586(struct net_device *dev) struct iasetup_cmd_struct __iomem *ias_cmd; struct tdr_cmd_struct __iomem *tdr_cmd; struct mcsetup_cmd_struct __iomem *mc_cmd; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; int num_addrs = netdev_mc_count(dev); ptr = p->scb + 1; @@ -724,9 +724,9 @@ static int init586(struct net_device *dev) writew(0xffff, &mc_cmd->cmd_link); writew(num_addrs * 6, &mc_cmd->mc_cnt); - for (i = 0; i < num_addrs; i++, dmi = dmi->next) - memcpy_toio(mc_cmd->mc_list[i], - dmi->dmi_addr, 6); + i = 0; + netdev_for_each_mc_addr(dmi, dev) + memcpy_toio(mc_cmd->mc_list[i++], dmi->dmi_addr, 6); writew(make16(mc_cmd), &p->scb->cbl_offset); writeb(CUC_START, &p->scb->cmd_cuc); diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 5e604e305d95..0678f3106cbc 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -6365,7 +6365,7 @@ static void niu_set_rx_mode(struct net_device *dev) for (i = 0; i < 16; i++) hash[i] = 0xffff; } else if (!netdev_mc_empty(dev)) { - for (addr = dev->mc_list; addr; addr = addr->next) { + netdev_for_each_mc_addr(addr, dev) { u32 crc = ether_crc_le(ETH_ALEN, addr->da_addr); crc >>= 24; diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c index 11d4398eac94..36785853a149 100644 --- a/drivers/net/pci-skeleton.c +++ b/drivers/net/pci-skeleton.c @@ -1793,7 +1793,7 @@ static void netdrv_set_rx_mode(struct net_device *dev) struct netdrv_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 mc_filter[2]; /* Multicast hash filter */ - int i, rx_mode; + int rx_mode; u32 tmp; DPRINTK("ENTER\n"); @@ -1814,10 +1814,10 @@ static void netdrv_set_rx_mode(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; + rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 63e03159daf7..084d78dd1637 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -2590,7 +2590,7 @@ static void pcnet32_load_multicast(struct net_device *dev) struct pcnet32_private *lp = netdev_priv(dev); volatile struct pcnet32_init_block *ib = lp->init_block; volatile __le16 *mcast_table = (__le16 *)ib->filter; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; unsigned long ioaddr = dev->base_addr; char *addrs; int i; @@ -2611,9 +2611,8 @@ static void pcnet32_load_multicast(struct net_device *dev) ib->filter[1] = 0; /* Add addresses */ - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { addrs = dmi->dmi_addr; - dmi = dmi->next; /* multicast address? */ if (!(*addrs & 1)) diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index c19dd4a6cd76..a849f6f23a17 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -580,7 +580,7 @@ void gelic_net_set_multi(struct net_device *netdev) } /* set multicast addresses */ - for (mc = netdev->mc_list; mc; mc = mc->next) { + netdev_for_each_mc_addr(mc, netdev) { addr = 0; p = mc->dmi_addr; for (i = 0; i < ETH_ALEN; i++) { diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 8ea7f869e293..99a4d1379d00 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -453,8 +453,7 @@ void qlcnic_set_multi(struct net_device *netdev) } if (!netdev_mc_empty(netdev)) { - for (mc_ptr = netdev->mc_list; mc_ptr; - mc_ptr = mc_ptr->next) { + netdev_for_each_mc_addr(mc_ptr, netdev) { qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); } diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index c170349717c5..c26ec5d740f6 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -4270,8 +4270,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) goto exit; - for (i = 0, mc_ptr = ndev->mc_list; mc_ptr; - i++, mc_ptr = mc_ptr->next) + i = 0; + netdev_for_each_mc_addr(mc_ptr, ndev) { if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr, MAC_ADDR_TYPE_MULTI_MAC, i)) { netif_err(qdev, hw, qdev->ndev, @@ -4279,6 +4279,8 @@ static void qlge_set_multicast_list(struct net_device *ndev) ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); goto exit; } + i++; + } ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (ql_set_routing_reg (qdev, RT_IDX_MCAST_MATCH_SLOT, RT_IDX_MCAST_MATCH, 1)) { diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index b8103425facb..15d5373dc8f3 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -938,7 +938,7 @@ static void r6040_multicast_list(struct net_device *dev) u16 *adrp; u16 reg; unsigned long flags; - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; int i; /* MAC Address */ @@ -973,11 +973,9 @@ static void r6040_multicast_list(struct net_device *dev) for (i = 0; i < 4; i++) hash_table[i] = 0; - for (i = 0; i < netdev_mc_count(dev); i++) { + netdev_for_each_mc_addr(dmi, dev) { char *addrs = dmi->dmi_addr; - dmi = dmi->next; - if (!(*addrs & 1)) continue; @@ -995,17 +993,19 @@ static void r6040_multicast_list(struct net_device *dev) iowrite16(hash_table[3], ioaddr + MAR3); } /* Multicast Address 1~4 case */ - for (i = 0, dmi; (i < netdev_mc_count(dev)) && (i < MCAST_MAX); i++) { - adrp = (u16 *)dmi->dmi_addr; - iowrite16(adrp[0], ioaddr + MID_1L + 8*i); - iowrite16(adrp[1], ioaddr + MID_1M + 8*i); - iowrite16(adrp[2], ioaddr + MID_1H + 8*i); - dmi = dmi->next; - } - for (i = netdev_mc_count(dev); i < MCAST_MAX; i++) { - iowrite16(0xffff, ioaddr + MID_0L + 8*i); - iowrite16(0xffff, ioaddr + MID_0M + 8*i); - iowrite16(0xffff, ioaddr + MID_0H + 8*i); + i = 0; + netdev_for_each_mc_addr(dmi, dev) { + if (i < MCAST_MAX) { + adrp = (u16 *) dmi->dmi_addr; + iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); + iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); + iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); + } else { + iowrite16(0xffff, ioaddr + MID_0L + 8 * i); + iowrite16(0xffff, ioaddr + MID_0M + 8 * i); + iowrite16(0xffff, ioaddr + MID_0H + 8 * i); + } + i++; } } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 83965eeba456..dfc3573c91bb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4732,12 +4732,10 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0xffffffff; } else { struct dev_mc_list *mclist; - unsigned int i; rx_mode = AcceptBroadcast | AcceptMyPhys; mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); rx_mode |= AcceptMulticast; -- cgit v1.2.3 From 567ec874d15b478c8eda7e9a5d2dcb05f13f1fb5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 23 Feb 2010 23:17:07 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part6 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 4 +--- drivers/net/smc9194.c | 10 +++++----- drivers/net/smc91x.c | 7 +------ drivers/net/starfire.c | 3 +-- drivers/net/tc35815.c | 8 ++++---- drivers/net/tehuti.c | 4 +--- drivers/net/tg3.c | 5 +---- drivers/net/tlan.c | 7 ++++--- drivers/net/tsi108_eth.c | 20 +++++--------------- drivers/net/typhoon.c | 5 +---- drivers/net/ucc_geth.c | 7 +------ drivers/net/via-rhine.c | 6 ++---- drivers/net/via-velocity.c | 6 +++--- drivers/net/virtio_net.c | 5 +++-- drivers/net/vmxnet3/vmxnet3_drv.c | 11 ++++------- drivers/net/vxge/vxge-main.c | 4 +--- drivers/net/yellowfin.c | 4 ++-- drivers/net/znet.c | 3 ++- 18 files changed, 42 insertions(+), 77 deletions(-) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index ef9674c6713f..9871a2b61f86 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1341,7 +1341,6 @@ static void smc911x_set_multicast_list(struct net_device *dev) * within that register. */ else if (!netdev_mc_empty(dev)) { - int i; struct dev_mc_list *cur_addr; /* Set the Hash perfec mode */ @@ -1350,8 +1349,7 @@ static void smc911x_set_multicast_list(struct net_device *dev) /* start with a table of all zeros: reject all */ memset(multicast_table, 0, sizeof(multicast_table)); - cur_addr = dev->mc_list; - for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { + netdev_for_each_mc_addr(cur_addr, dev) { u32 position; /* do we have a pointer here? */ diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c index 41c3dddeab50..f9a960e7fc1f 100644 --- a/drivers/net/smc9194.c +++ b/drivers/net/smc9194.c @@ -434,18 +434,18 @@ static void smc_shutdown( int ioaddr ) */ -static void smc_setmulticast( int ioaddr, int count, struct dev_mc_list * addrs ) { +static void smc_setmulticast(int ioaddr, struct net_device *dev) +{ int i; unsigned char multicast_table[ 8 ]; - struct dev_mc_list * cur_addr; + struct dev_mc_list *cur_addr; /* table for flipping the order of 3 bits */ unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; /* start with a table of all zeros: reject all */ memset( multicast_table, 0, sizeof( multicast_table ) ); - cur_addr = addrs; - for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next ) { + netdev_for_each_mc_addr(cur_addr, dev) { int position; /* do we have a pointer here? */ @@ -1550,7 +1550,7 @@ static void smc_set_multicast_list(struct net_device *dev) ioaddr + RCR ); /* NOTE: this has to set the bank, so make sure it is the last thing called. The bank is set to zero at the top */ - smc_setmulticast(ioaddr, netdev_mc_count(dev), dev->mc_list); + smc_setmulticast(ioaddr, dev); } else { outw( inw( ioaddr + RCR ) & ~(RCR_PROMISC | RCR_ALMUL), diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 66450127c5a1..fc1b5a1a3583 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1413,7 +1413,6 @@ static void smc_set_multicast_list(struct net_device *dev) * within that register. */ else if (!netdev_mc_empty(dev)) { - int i; struct dev_mc_list *cur_addr; /* table for flipping the order of 3 bits */ @@ -1422,13 +1421,9 @@ static void smc_set_multicast_list(struct net_device *dev) /* start with a table of all zeros: reject all */ memset(multicast_table, 0, sizeof(multicast_table)); - cur_addr = dev->mc_list; - for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { + netdev_for_each_mc_addr(cur_addr, dev) { int position; - /* do we have a pointer here? */ - if (!cur_addr) - break; /* make sure this is a multicast address - shouldn't this be a given if we have it here ? */ if (!(*cur_addr->dmi_addr & 1)) diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 0f405ef51858..6dfa69899019 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1825,8 +1825,7 @@ static void set_rx_mode(struct net_device *dev) __le16 mc_filter[32] __attribute__ ((aligned(sizeof(long)))); /* Multicast hash filter */ memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { /* The chip uses the upper 9 CRC bits as index into the hash table */ int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23; diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index a2c635ecdab8..876f45afbed4 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1945,18 +1945,18 @@ tc35815_set_multicast_list(struct net_device *dev) /* Disable promiscuous mode, use normal mode. */ tc_writel(CAM_CompEn | CAM_BroadAcc | CAM_GroupAcc, &tr->CAM_Ctl); } else if (!netdev_mc_empty(dev)) { - struct dev_mc_list *cur_addr = dev->mc_list; + struct dev_mc_list *cur_addr; int i; int ena_bits = CAM_Ena_Bit(CAM_ENTRY_SOURCE); tc_writel(0, &tr->CAM_Ctl); /* Walk the address list, and load the filter */ - for (i = 0; i < netdev_mc_count(dev); i++, cur_addr = cur_addr->next) { - if (!cur_addr) - break; + i = 0; + netdev_for_each_mc_addr(cur_addr, dev) { /* entry 0,1 is reserved. */ tc35815_set_cam_entry(dev, i + 2, cur_addr->dmi_addr); ena_bits |= CAM_Ena_Bit(i + 2); + i++; } tc_writel(ena_bits, &tr->CAM_Ena); tc_writel(CAM_CompEn | CAM_BroadAcc, &tr->CAM_Ctl); diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 2517cc00ac2a..0c9780217c87 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c @@ -824,10 +824,8 @@ static void bdx_setmulti(struct net_device *ndev) /* TBD: sort addreses and write them in ascending order * into RX_MAC_MCST regs. we skip this phase now and accept ALL * multicast frames throu IMF */ - mclist = ndev->mc_list; - /* accept the rest of addresses throu IMF */ - for (; mclist; mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, ndev) { hash = 0; for (i = 0; i < ETH_ALEN; i++) hash ^= mclist->dmi_addr[i]; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f204f73c4f99..0d06e4007f44 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9458,15 +9458,12 @@ static void __tg3_set_rx_mode(struct net_device *dev) } else { /* Accept one or more multicast(s). */ struct dev_mc_list *mclist; - unsigned int i; u32 mc_filter[4] = { 0, }; u32 regidx; u32 bit; u32 crc; - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { - + netdev_for_each_mc_addr(mclist, dev) { crc = calc_crc (mclist->dmi_addr, ETH_ALEN); bit = ~crc & 0x7f; regidx = (bit & 0x60) >> 5; diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index e44d5a074c69..390540c101c7 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1314,7 +1314,7 @@ static struct net_device_stats *TLan_GetStats( struct net_device *dev ) static void TLan_SetMulticastList( struct net_device *dev ) { - struct dev_mc_list *dmi = dev->mc_list; + struct dev_mc_list *dmi; u32 hash1 = 0; u32 hash2 = 0; int i; @@ -1335,7 +1335,8 @@ static void TLan_SetMulticastList( struct net_device *dev ) TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF ); TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF ); } else { - for ( i = 0; i < netdev_mc_count(dev); i++ ) { + i = 0; + netdev_for_each_mc_addr(dmi, dev) { if ( i < 3 ) { TLan_SetMac( dev, i + 1, (char *) &dmi->dmi_addr ); @@ -1346,7 +1347,7 @@ static void TLan_SetMulticastList( struct net_device *dev ) else hash2 |= ( 1 << ( offset - 32 ) ); } - dmi = dmi->next; + i++; } for ( ; i < 3; i++ ) TLan_SetMac( dev, i + 1, NULL ); diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index f4b30c4826fb..647cdd1d4e20 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -1186,27 +1186,17 @@ static void tsi108_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) { int i; - struct dev_mc_list *mc = dev->mc_list; + struct dev_mc_list *mc; rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH; memset(data->mc_hash, 0, sizeof(data->mc_hash)); - while (mc) { + netdev_for_each_mc_addr(mc, dev) { u32 hash, crc; - if (mc->dmi_addrlen == 6) { - crc = ether_crc(6, mc->dmi_addr); - hash = crc >> 23; - - __set_bit(hash, &data->mc_hash[0]); - } else { - printk(KERN_ERR - "%s: got multicast address of length %d instead of 6.\n", - dev->name, - mc->dmi_addrlen); - } - - mc = mc->next; + crc = ether_crc(6, mc->dmi_addr); + hash = crc >> 23; + __set_bit(hash, &data->mc_hash[0]); } TSI_WRITE(TSI108_EC_HASHADDR, diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 38c216132ef5..e3ddcb8f29df 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -922,12 +922,9 @@ typhoon_set_rx_mode(struct net_device *dev) filter |= TYPHOON_RX_FILTER_ALL_MCAST; } else if (!netdev_mc_empty(dev)) { struct dev_mc_list *mclist; - int i; memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3f; mc_filter[bit >> 5] |= 1 << (bit & 0x1f); } diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a05720289c7e..23a97518bc1f 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2002,7 +2002,6 @@ static void ucc_geth_set_multi(struct net_device *dev) struct dev_mc_list *dmi; struct ucc_fast __iomem *uf_regs; struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; - int i; ugeth = netdev_priv(dev); @@ -2029,11 +2028,7 @@ static void ucc_geth_set_multi(struct net_device *dev) out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); - dmi = dev->mc_list; - - for (i = 0; i < netdev_mc_count(dev); - i++, dmi = dmi->next) { - + netdev_for_each_mc_addr(dmi, dev) { /* Only support group multicast for now. */ if (!(dmi->dmi_addr[0] & 1)) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 85df7ac636b5..50f881aa3939 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1705,11 +1705,9 @@ static void rhine_set_rx_mode(struct net_device *dev) rx_mode = 0x0C; } else { struct dev_mc_list *mclist; - int i; + memset(mc_filter, 0, sizeof(mc_filter)); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 4e47f2683b83..3a486f3bad3d 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1141,11 +1141,11 @@ static void velocity_set_multi(struct net_device *dev) int offset = MCAM_SIZE - vptr->multicast_limit; mac_get_cam_mask(regs, vptr->mCAMmask); - for (i = 0, mclist = dev->mc_list; - mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + i = 0; + netdev_for_each_mc_addr(mclist, dev) { mac_set_cam(regs, i + offset, mclist->dmi_addr); vptr->mCAMmask[(offset + i) / 8] |= 1 << ((offset + i) & 7); + i++; } mac_set_cam_mask(regs, vptr->mCAMmask); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index ce35b42cc2cb..e6095f3aa05f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -776,8 +776,9 @@ static void virtnet_set_rx_mode(struct net_device *dev) mac_data->entries = mc_count; addr = dev->mc_list; - for (i = 0; i < mc_count; i++, addr = addr->next) - memcpy(&mac_data->macs[i][0], addr->da_addr, ETH_ALEN); + i = 0; + netdev_for_each_mc_addr(addr, dev) + memcpy(&mac_data->macs[i++][0], addr->da_addr, ETH_ALEN); sg_set_buf(&sg[1], mac_data, sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index ee1b397417f3..cff3485d9673 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1675,15 +1675,12 @@ vmxnet3_copy_mc(struct net_device *netdev) /* We may be called with BH disabled */ buf = kmalloc(sz, GFP_ATOMIC); if (buf) { - int i; - struct dev_mc_list *mc = netdev->mc_list; + struct dev_mc_list *mc; + int i = 0; - for (i = 0; i < netdev_mc_count(netdev); i++) { - BUG_ON(!mc); - memcpy(buf + i * ETH_ALEN, mc->dmi_addr, + netdev_for_each_mc_addr(mc, netdev) + memcpy(buf + i++ * ETH_ALEN, mc->dmi_addr, ETH_ALEN); - mc = mc->next; - } } } return buf; diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index c248b01218a1..46a7c9e689ec 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -1217,9 +1217,7 @@ static void vxge_set_multicast(struct net_device *dev) } /* Add new ones */ - for (i = 0, mclist = dev->mc_list; i < netdev_mc_count(dev); - i++, mclist = mclist->next) { - + netdev_for_each_mc_addr(mclist, dev) { memcpy(mac_info.macaddr, mclist->dmi_addr, ETH_ALEN); for (vpath_idx = 0; vpath_idx < vdev->no_of_vpath; vpath_idx++) { diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index e4aab4d5b553..7d4107f5eeb0 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c @@ -1303,9 +1303,9 @@ static void set_rx_mode(struct net_device *dev) struct dev_mc_list *mclist; u16 hash_table[4]; int i; + memset(hash_table, 0, sizeof(hash_table)); - for (i = 0, mclist = dev->mc_list; mclist && i < netdev_mc_count(dev); - i++, mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { unsigned int bit; /* Due to a bug in the early chip versions, multiple filter diff --git a/drivers/net/znet.c b/drivers/net/znet.c index bc5ae0f6e934..def49d2ec69a 100644 --- a/drivers/net/znet.c +++ b/drivers/net/znet.c @@ -313,7 +313,8 @@ static void znet_set_multicast_list (struct net_device *dev) /* Byte D */ cfblk->dummy_1 = 1; /* set to 1 */ cfblk->tx_ifs_retrig = 3; /* Hmm... Disabled */ - cfblk->mc_all = (dev->mc_list || (dev->flags&IFF_ALLMULTI));/* multicast all mode */ + cfblk->mc_all = (!netdev_mc_empty(dev) || + (dev->flags & IFF_ALLMULTI)); /* multicast all mode */ cfblk->rcv_mon = 0; /* Monitor mode disabled */ cfblk->frag_acpt = 0; /* Do not accept fragments */ cfblk->tstrttrs = 0; /* No start transmission threshold */ -- cgit v1.2.3 From fbc450b137e59205b98a172326415cd981c9caa6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 23 Feb 2010 09:54:58 +0000 Subject: octeon: convert to use netdev_for_each_mc_addr Hmm so actually my original patch including this bit was correct, "list = list->next;" confused me :) - will send patch correcting that in a few. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/octeon/octeon_mgmt.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c index 3a0f910924a5..be368e5cbf75 100644 --- a/drivers/net/octeon/octeon_mgmt.c +++ b/drivers/net/octeon/octeon_mgmt.c @@ -467,7 +467,6 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); int port = p->port; - int i; union cvmx_agl_gmx_rxx_adr_ctl adr_ctl; union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; unsigned long flags; @@ -511,12 +510,8 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) } } if (multicast_mode == 0) { - i = netdev_mc_count(netdev); - list = netdev->mc_list; - while (i--) { + netdev_for_each_mc_addr(list, netdev) octeon_mgmt_cam_state_add(&cam_state, list->da_addr); - list = list->next; - } } -- cgit v1.2.3 From 9c5f9c2861909753140ad6a41cdc77cdf20c1dc9 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 24 Feb 2010 06:00:17 +0000 Subject: isa-skelton: Remove a wrong netif_wake_queue() call The netif_wake_queue() is called correctly (i.e. only on !txfull condition) from net_tx(). So Unconditional call to the netif_wake_queue() here is wrong. This might cause calling of start_xmit routine on txfull state and trigger tx-ring overflow. This fix is ported from commit 662a96bd6f020782dfbdc0d0bd177c7dbb556687 ("tc35815: Remove a wrong netif_wake_queue() call which triggers BUG_ON"). Signed-off-by: Atsushi Nemoto Signed-off-by: David S. Miller --- drivers/net/isa-skeleton.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c index d09e4d3a15a6..9e55c3007743 100644 --- a/drivers/net/isa-skeleton.c +++ b/drivers/net/isa-skeleton.c @@ -536,7 +536,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) /* Transmit complete. */ net_tx(dev); np->stats.tx_packets++; - netif_wake_queue(dev); } #endif if (status & COUNTERS_INTR) { -- cgit v1.2.3 From dee7399c2d9a1d3b0af5d68d7e0dd922e104a2a8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 24 Feb 2010 06:00:34 +0000 Subject: tc35815: Fix double locking on NAPI Isolate spinlock for tx and rx to resolve double-locking. This is potential bug while this controller does not exist on any SMP platforms, but lockdep or rt-preempt reveals this bug. Reported-by: Ralf Roesch Signed-off-by: Atsushi Nemoto Signed-off-by: David S. Miller --- drivers/net/tc35815.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 876f45afbed4..49bd84c0d583 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -402,6 +402,7 @@ struct tc35815_local { * by this lock as well. */ spinlock_t lock; + spinlock_t rx_lock; struct mii_bus *mii_bus; struct phy_device *phy_dev; @@ -835,6 +836,7 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev, INIT_WORK(&lp->restart_work, tc35815_restart_work); spin_lock_init(&lp->lock); + spin_lock_init(&lp->rx_lock); lp->pci_dev = pdev; lp->chiptype = ent->driver_data; @@ -1186,6 +1188,7 @@ static void tc35815_restart(struct net_device *dev) printk(KERN_ERR "%s: BMCR reset failed.\n", dev->name); } + spin_lock_bh(&lp->rx_lock); spin_lock_irq(&lp->lock); tc35815_chip_reset(dev); tc35815_clear_queues(dev); @@ -1193,6 +1196,7 @@ static void tc35815_restart(struct net_device *dev) /* Reconfigure CAM again since tc35815_chip_init() initialize it. */ tc35815_set_multicast_list(dev); spin_unlock_irq(&lp->lock); + spin_unlock_bh(&lp->rx_lock); netif_wake_queue(dev); } @@ -1211,11 +1215,14 @@ static void tc35815_schedule_restart(struct net_device *dev) struct tc35815_local *lp = netdev_priv(dev); struct tc35815_regs __iomem *tr = (struct tc35815_regs __iomem *)dev->base_addr; + unsigned long flags; /* disable interrupts */ + spin_lock_irqsave(&lp->lock, flags); tc_writel(0, &tr->Int_En); tc_writel(tc_readl(&tr->DMA_Ctl) | DMA_IntMask, &tr->DMA_Ctl); schedule_work(&lp->restart_work); + spin_unlock_irqrestore(&lp->lock, flags); } static void tc35815_tx_timeout(struct net_device *dev) @@ -1436,7 +1443,9 @@ static int tc35815_do_interrupt(struct net_device *dev, u32 status, int limit) if (status & Int_IntMacTx) { /* Transmit complete. */ lp->lstats.tx_ints++; + spin_lock_irq(&lp->lock); tc35815_txdone(dev); + spin_unlock_irq(&lp->lock); if (ret < 0) ret = 0; } @@ -1649,7 +1658,7 @@ static int tc35815_poll(struct napi_struct *napi, int budget) int received = 0, handled; u32 status; - spin_lock(&lp->lock); + spin_lock(&lp->rx_lock); status = tc_readl(&tr->Int_Src); do { /* BLEx, FDAEx will be cleared later */ @@ -1667,7 +1676,7 @@ static int tc35815_poll(struct napi_struct *napi, int budget) } status = tc_readl(&tr->Int_Src); } while (status); - spin_unlock(&lp->lock); + spin_unlock(&lp->rx_lock); if (received < budget) { napi_complete(napi); -- cgit v1.2.3 From e382c3018ad19744d3c5d281daf4b0e9f052af66 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Wed, 24 Feb 2010 08:41:18 +0000 Subject: sis190: handle DMA mapping errors Signed-off-by: Denis Kirjanov Signed-off-by: David S. Miller --- drivers/net/sis190.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 4487b065ef72..80af4a44580e 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -484,18 +484,24 @@ static struct sk_buff *sis190_alloc_rx_skb(struct sis190_private *tp, { u32 rx_buf_sz = tp->rx_buf_sz; struct sk_buff *skb; + dma_addr_t mapping; skb = netdev_alloc_skb(tp->dev, rx_buf_sz); - if (likely(skb)) { - dma_addr_t mapping; - - mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz, - PCI_DMA_FROMDEVICE); - sis190_map_to_asic(desc, mapping, rx_buf_sz); - } else - sis190_make_unusable_by_asic(desc); + if (unlikely(!skb)) + goto skb_alloc_failed; + mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz, + PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(tp->pci_dev, mapping)) + goto out; + sis190_map_to_asic(desc, mapping, rx_buf_sz); return skb; + +out: + dev_kfree_skb_any(skb); +skb_alloc_failed: + sis190_make_unusable_by_asic(desc); + return NULL; } static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev, @@ -1184,6 +1190,11 @@ static netdev_tx_t sis190_start_xmit(struct sk_buff *skb, } mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(tp->pci_dev, mapping)) { + netif_err(tp, tx_err, dev, + "PCI mapping failed, dropping packet"); + return NETDEV_TX_BUSY; + } tp->Tx_skbuff[entry] = skb; -- cgit v1.2.3 From 41a655ba5654e47847505c164f77f8190ca9ed27 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Wed, 24 Feb 2010 10:25:33 +0000 Subject: greth: convert to netdev_tx_t Convert to netdev_tx_t Signed-off-by: Denis Kirjanov Signed-off-by: David S. Miller --- drivers/net/greth.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index d2032339f6de..d75b46141603 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -66,8 +66,10 @@ module_param(greth_edcl, int, 0); MODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used."); static int greth_open(struct net_device *dev); -static int greth_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev); +static netdev_tx_t greth_start_xmit(struct sk_buff *skb, + struct net_device *dev); +static netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb, + struct net_device *dev); static int greth_rx(struct net_device *dev, int limit); static int greth_rx_gbit(struct net_device *dev, int limit); static void greth_clean_tx(struct net_device *dev); @@ -379,7 +381,8 @@ static int greth_close(struct net_device *dev) return 0; } -static int greth_start_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t +greth_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; @@ -441,7 +444,8 @@ out: } -static int greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t +greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) { struct greth_private *greth = netdev_priv(dev); struct greth_bd *bdp; -- cgit v1.2.3 From 43634e820e393ba48bb2efc3d330dee4203e80d8 Mon Sep 17 00:00:00 2001 From: Mallikarjuna R Chilakala Date: Thu, 25 Feb 2010 23:14:37 +0000 Subject: ixgbe: Fix DMA mapping/unmapping issues when HWRSC is enabled on IOMMU enabled kernels Work around 82599 HW issue when HWRSC is enabled on IOMMU enabled kernels. 82599 HW is updating the header information after setting the descriptor to done, resulting DMA mapping/unmapping issues on IOMMU enabled systems. To work around the issue delay unmapping of first packet that carries the header information until end of packet is reached. Signed-off-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 330879004ea1..4a0102218d39 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -818,6 +818,12 @@ static inline struct sk_buff *ixgbe_transform_rsc_queue(struct sk_buff *skb, return skb; } +struct ixgbe_rsc_cb { + dma_addr_t dma; +}; + +#define IXGBE_RSC_CB(skb) ((struct ixgbe_rsc_cb *)(skb)->cb) + static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, struct ixgbe_ring *rx_ring, int *work_done, int work_to_do) @@ -867,9 +873,21 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, rx_buffer_info->skb = NULL; if (rx_buffer_info->dma) { - pci_unmap_single(pdev, rx_buffer_info->dma, - rx_ring->rx_buf_len, - PCI_DMA_FROMDEVICE); + if ((adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) && + (!(staterr & IXGBE_RXD_STAT_EOP)) && + (!(skb->prev))) + /* + * When HWRSC is enabled, delay unmapping + * of the first packet. It carries the + * header information, HW may still + * access the header after the writeback. + * Only unmap it when EOP is reached + */ + IXGBE_RSC_CB(skb)->dma = rx_buffer_info->dma; + else + pci_unmap_single(pdev, rx_buffer_info->dma, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); rx_buffer_info->dma = 0; skb_put(skb, len); } @@ -917,6 +935,10 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, if (skb->prev) skb = ixgbe_transform_rsc_queue(skb, &(rx_ring->rsc_count)); if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) { + if (IXGBE_RSC_CB(skb)->dma) + pci_unmap_single(pdev, IXGBE_RSC_CB(skb)->dma, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) rx_ring->rsc_count += skb_shinfo(skb)->nr_frags; else @@ -3104,6 +3126,10 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter, rx_buffer_info->skb = NULL; do { struct sk_buff *this = skb; + if (IXGBE_RSC_CB(this)->dma) + pci_unmap_single(pdev, IXGBE_RSC_CB(this)->dma, + rx_ring->rx_buf_len, + PCI_DMA_FROMDEVICE); skb = skb->prev; dev_kfree_skb(this); } while (skb); -- cgit v1.2.3 From a922afb64d2e71115f122e04346163cb8c8453e3 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 25 Feb 2010 23:14:58 +0000 Subject: ixgbe: do not stop tx queues in ixgbe_set_tso Disabling TSO can cause the dev_watchdog timer to be triggered because when TSO is disabled netif_tx_stop_all_queues is called. If the watchdog timer fires while the queues are stopped and traffic has not recently been sent on a paticular queue this is falsly identified as a hang and ndo_tx_timeout() is called. This is ocossionally seen during testing. This removes the netif_tx_stop_all_queues() it is not needed. The scheduler submits skb's with dev_hard_start_xmit(), this checks if netif_needs_gso and if so it calls dev_gso_segment. Disabling TSO will cause dev_hard_start_xmit() to do the gso processing. However ixgbe does not use the features flags to determine if it needs to use tso or not instead it uses skb->gso_size so ixgbe will process these frames correctly regardless of the netdev features flag. Signed-off-by: John Fastabend Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_ethtool.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0d234346a4ea..7949a446e4c7 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -441,10 +441,8 @@ static int ixgbe_set_tso(struct net_device *netdev, u32 data) netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_TSO6; } else { - netif_tx_stop_all_queues(netdev); netdev->features &= ~NETIF_F_TSO; netdev->features &= ~NETIF_F_TSO6; - netif_tx_start_all_queues(netdev); } return 0; } -- cgit v1.2.3 From c85a26189660e1cfd1f50989468313c544487950 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 25 Feb 2010 23:15:21 +0000 Subject: ixgbe: Do not allocate too many netdev txqueues Instead of allocating 128 struct netdev_queue per device, use the minimum value between 128 and the number of possible txq's, to reduce ram usage and "tc -s -d class shod dev .." output. This patch fixes Eric Dumazet's patch to set the TX queues to the correct minimum. Signed-off-by: John Fastabend Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 4a0102218d39..a961da2f98c0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5996,6 +5996,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; static int cards_found; int i, err, pci_using_dac; + unsigned int indices = num_possible_cpus(); #ifdef IXGBE_FCOE u16 device_caps; #endif @@ -6034,7 +6035,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, pci_set_master(pdev); pci_save_state(pdev); - netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES); + if (ii->mac == ixgbe_mac_82598EB) + indices = min_t(unsigned int, indices, IXGBE_MAX_RSS_INDICES); + else + indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES); + + indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES); +#ifdef IXGBE_FCOE + indices += min_t(unsigned int, num_possible_cpus(), + IXGBE_MAX_FCOE_INDICES); +#endif + indices = min_t(unsigned int, indices, MAX_TX_QUEUES); + netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices); if (!netdev) { err = -ENOMEM; goto err_alloc_etherdev; -- cgit v1.2.3 From a9736c086cc6221659e498f0855152c32dbc1396 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Wed, 24 Feb 2010 14:42:04 +0000 Subject: cnic: Finetune iSCSI connection set up. Initialize IP ID and handle some additional connection errors. Signed-off-by: Eddie Wai Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/cnic.c | 17 ++++++++++++++++- drivers/net/cnic.h | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 6aecef930fa8..0fe83717967a 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2507,7 +2507,7 @@ static int cnic_cm_offload_pg(struct cnic_sock *csk) l4kwqe->sa5 = dev->mac_addr[5]; l4kwqe->etype = ETH_P_IP; - l4kwqe->ipid_count = DEF_IPID_COUNT; + l4kwqe->ipid_start = DEF_IPID_START; l4kwqe->host_opaque = csk->l5_cid; if (csk->vlan_id) { @@ -3046,6 +3046,14 @@ static void cnic_cm_process_offld_pg(struct cnic_dev *dev, struct l4_kcq *kcqe) clear_bit(SK_F_OFFLD_SCHED, &csk->flags); goto done; } + /* Possible PG kcqe status: SUCCESS, OFFLOADED_PG, or CTX_ALLOC_FAIL */ + if (kcqe->status == L4_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAIL) { + clear_bit(SK_F_OFFLD_SCHED, &csk->flags); + cnic_cm_upcall(cp, csk, + L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE); + goto done; + } + csk->pg_cid = kcqe->pg_cid; set_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags); cnic_cm_conn_req(csk); @@ -3083,6 +3091,13 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) } switch (opcode) { + case L5CM_RAMROD_CMD_ID_TCP_CONNECT: + if (l4kcqe->status != 0) { + clear_bit(SK_F_OFFLD_SCHED, &csk->flags); + cnic_cm_upcall(cp, csk, + L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE); + } + break; case L4_KCQE_OPCODE_VALUE_CONNECT_COMPLETE: if (l4kcqe->status == 0) set_bit(SK_F_OFFLD_COMPLETE, &csk->flags); diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h index 241d09acc0d4..1921597ab4a3 100644 --- a/drivers/net/cnic.h +++ b/drivers/net/cnic.h @@ -101,7 +101,7 @@ struct cnic_redirect_entry { #define BNX2X_KWQ_DATA(cp, x) \ &(cp)->kwq_16_data[BNX2X_KWQ_DATA_PG(cp, x)][BNX2X_KWQ_DATA_IDX(cp, x)] -#define DEF_IPID_COUNT 0xc001 +#define DEF_IPID_START 0x8000 #define DEF_KA_TIMEOUT 10000 #define DEF_KA_INTERVAL 300000 -- cgit v1.2.3 From 66883e90eaa0dd55d395c0f9a0c6da5d50809804 Mon Sep 17 00:00:00 2001 From: Eddie Wai Date: Wed, 24 Feb 2010 14:42:05 +0000 Subject: cnic: Finetune iSCSI connection reset. For bnx2 devices, always send notification to bnx2i to let it initiate the cleanup when RST is received. For bnx2x devices, add unsolicited RST_COMP handling to start the cleanup. Signed-off-by: Eddie Wai Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: David S. Miller --- drivers/net/cnic.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 0fe83717967a..40865aac2afa 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -3108,7 +3108,10 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) break; case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED: - if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) + if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) { + cnic_cm_upcall(cp, csk, opcode); + break; + } else if (test_and_clear_bit(SK_F_OFFLD_COMPLETE, &csk->flags)) csk->state = opcode; /* fall through */ case L4_KCQE_OPCODE_VALUE_CLOSE_COMP: @@ -3172,6 +3175,16 @@ static int cnic_ready_to_close(struct cnic_sock *csk, u32 opcode) if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) return 1; } + /* 57710+ only workaround to handle unsolicited RESET_COMP + * which will be treated like a RESET RCVD notification + * which triggers the clean up procedure + */ + else if (opcode == L4_KCQE_OPCODE_VALUE_RESET_COMP) { + if (!test_and_set_bit(SK_F_CLOSING, &csk->flags)) { + csk->state = L4_KCQE_OPCODE_VALUE_RESET_RECEIVED; + return 1; + } + } return 0; } @@ -3181,10 +3194,8 @@ static void cnic_close_bnx2_conn(struct cnic_sock *csk, u32 opcode) struct cnic_local *cp = dev->cnic_priv; clear_bit(SK_F_CONNECT_START, &csk->flags); - if (cnic_ready_to_close(csk, opcode)) { - cnic_close_conn(csk); - cnic_cm_upcall(cp, csk, opcode); - } + cnic_close_conn(csk); + cnic_cm_upcall(cp, csk, opcode); } static void cnic_cm_stop_bnx2_hw(struct cnic_dev *dev) -- cgit v1.2.3 From d02a5e6c2fba8b114c44cf05085fca07180f37f1 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 24 Feb 2010 14:42:06 +0000 Subject: cnic: Fix panic in cnic_iscsi_nl_msg_recv() when device is down. Some data structures are freed when the device is down and it will crash if an ISCSI netlink message is received. Add RCU protection to prevent this. In the shutdown path, ulp_ops[CNIC_ULP_L4] is assigned NULL and rcu_synchronized before freeing the data structures. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/cnic.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 40865aac2afa..45584442a35c 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -327,6 +327,12 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type, if (l5_cid >= MAX_CM_SK_TBL_SZ) break; + rcu_read_lock(); + if (!rcu_dereference(cp->ulp_ops[CNIC_ULP_L4])) { + rc = -ENODEV; + rcu_read_unlock(); + break; + } csk = &cp->csk_tbl[l5_cid]; csk_hold(csk); if (cnic_in_use(csk)) { @@ -341,6 +347,7 @@ static int cnic_iscsi_nl_msg_recv(struct cnic_dev *dev, u32 msg_type, cnic_cm_set_pg(csk); } csk_put(csk); + rcu_read_unlock(); rc = 0; } } -- cgit v1.2.3 From c76284af9ec8a010c502a70249cb74b3bb69ec6f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 24 Feb 2010 14:42:07 +0000 Subject: cnic: Simplify route checking during iSCSI connection. With a separate IP address for iSCSI, connections should proceed whether or not we can get a route to the target from the network stack. It is possible that the network IP address may not reach the iSCSI target. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Eddie Wai Signed-off-by: David S. Miller --- drivers/net/cnic.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 45584442a35c..0defe61d5bf3 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2860,8 +2860,8 @@ static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr) { struct cnic_dev *dev = csk->dev; struct cnic_local *cp = dev->cnic_priv; - int is_v6, err, rc = -ENETUNREACH; - struct dst_entry *dst; + int is_v6, rc = 0; + struct dst_entry *dst = NULL; struct net_device *realdev; u32 local_port; @@ -2877,39 +2877,31 @@ static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr) clear_bit(SK_F_IPV6, &csk->flags); if (is_v6) { -#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE)) set_bit(SK_F_IPV6, &csk->flags); - err = cnic_get_v6_route(&saddr->remote.v6, &dst); - if (err) - return err; - - if (!dst || dst->error || !dst->dev) - goto err_out; + cnic_get_v6_route(&saddr->remote.v6, &dst); memcpy(&csk->dst_ip[0], &saddr->remote.v6.sin6_addr, sizeof(struct in6_addr)); csk->dst_port = saddr->remote.v6.sin6_port; local_port = saddr->local.v6.sin6_port; -#else - return rc; -#endif } else { - err = cnic_get_v4_route(&saddr->remote.v4, &dst); - if (err) - return err; - - if (!dst || dst->error || !dst->dev) - goto err_out; + cnic_get_v4_route(&saddr->remote.v4, &dst); csk->dst_ip[0] = saddr->remote.v4.sin_addr.s_addr; csk->dst_port = saddr->remote.v4.sin_port; local_port = saddr->local.v4.sin_port; } - csk->vlan_id = cnic_get_vlan(dst->dev, &realdev); - if (realdev != dev->netdev) - goto err_out; + csk->vlan_id = 0; + csk->mtu = dev->netdev->mtu; + if (dst && dst->dev) { + u16 vlan = cnic_get_vlan(dst->dev, &realdev); + if (realdev == dev->netdev) { + csk->vlan_id = vlan; + csk->mtu = dst_mtu(dst); + } + } if (local_port >= CNIC_LOCAL_PORT_MIN && local_port < CNIC_LOCAL_PORT_MAX) { @@ -2927,9 +2919,6 @@ static int cnic_get_route(struct cnic_sock *csk, struct cnic_sockaddr *saddr) } csk->src_port = local_port; - csk->mtu = dst_mtu(dst); - rc = 0; - err_out: dst_release(dst); return rc; -- cgit v1.2.3 From a4dde3abbf87a495154a876576e1ab34b17b5ef1 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 24 Feb 2010 14:42:08 +0000 Subject: cnic: Use union for the status blocks of different devices. We only need to assign the status block address once and it also saves space in the structure. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Eddie Wai Signed-off-by: David S. Miller --- drivers/net/cnic.c | 35 +++++++++++++++++------------------ drivers/net/cnic.h | 9 ++++++--- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 0defe61d5bf3..463408f46ba6 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -900,7 +900,8 @@ static int cnic_alloc_uio(struct cnic_dev *dev) { uinfo->mem[0].memtype = UIO_MEM_PHYS; if (test_bit(CNIC_F_BNX2_CLASS, &dev->flags)) { - uinfo->mem[1].addr = (unsigned long) cp->status_blk & PAGE_MASK; + uinfo->mem[1].addr = (unsigned long) cp->status_blk.gen & + PAGE_MASK; if (cp->ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) uinfo->mem[1].size = BNX2_SBLK_MSIX_ALIGN_SIZE * 9; else @@ -1103,10 +1104,9 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) if (ret) goto error; - cp->bnx2x_status_blk = cp->status_blk; cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk; - memset(cp->bnx2x_status_blk, 0, sizeof(struct host_status_block)); + memset(cp->status_blk.bnx2x, 0, sizeof(*cp->status_blk.bnx2x)); cp->l2_rx_ring_size = 15; @@ -2205,7 +2205,7 @@ static void cnic_service_bnx2_msix(unsigned long data) { struct cnic_dev *dev = (struct cnic_dev *) data; struct cnic_local *cp = dev->cnic_priv; - struct status_block_msix *status_blk = cp->bnx2_status_blk; + struct status_block_msix *status_blk = cp->status_blk.bnx2; u32 status_idx = status_blk->status_idx; u16 hw_prod, sw_prod; int kcqe_cnt; @@ -2251,7 +2251,7 @@ static irqreturn_t cnic_irq(int irq, void *dev_instance) if (cp->ack_int) cp->ack_int(dev); - prefetch(cp->status_blk); + prefetch(cp->status_blk.gen); prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) @@ -2292,7 +2292,7 @@ static void cnic_service_bnx2x_bh(unsigned long data) struct cnic_local *cp = dev->cnic_priv; u16 hw_prod, sw_prod; struct cstorm_status_block_c *sblk = - &cp->bnx2x_status_blk->c_status_block; + &cp->status_blk.bnx2x->c_status_block; u32 status_idx = sblk->status_block_index; int kcqe_cnt; @@ -2334,7 +2334,7 @@ static int cnic_service_bnx2x(void *data, void *status_blk) struct cnic_local *cp = dev->cnic_priv; u16 prod = cp->kcq_prod_idx & MAX_KCQ_IDX; - prefetch(cp->status_blk); + prefetch(cp->status_blk.bnx2x); prefetch(&cp->kcq[KCQ_PG(prod)][KCQ_IDX(prod)]); if (likely(test_bit(CNIC_F_CNIC_UP, &dev->flags))) @@ -3409,8 +3409,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) CNIC_WR(dev, base + BNX2_HC_COM_TICKS_OFF, (64 << 16) | 220); CNIC_WR(dev, base + BNX2_HC_CMD_TICKS_OFF, (64 << 16) | 220); - cp->bnx2_status_blk = cp->status_blk; - cp->last_status_idx = cp->bnx2_status_blk->status_idx; + cp->last_status_idx = cp->status_blk.bnx2->status_idx; tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix, (unsigned long) dev); err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0, @@ -3419,7 +3418,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) tasklet_disable(&cp->cnic_irq_task); return err; } - while (cp->bnx2_status_blk->status_completion_producer_index && + while (cp->status_blk.bnx2->status_completion_producer_index && i < 10) { CNIC_WR(dev, BNX2_HC_COALESCE_NOW, 1 << (11 + sblk_num)); @@ -3427,13 +3426,13 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev) i++; barrier(); } - if (cp->bnx2_status_blk->status_completion_producer_index) { + if (cp->status_blk.bnx2->status_completion_producer_index) { cnic_free_irq(dev); goto failed; } } else { - struct status_block *sblk = cp->status_blk; + struct status_block *sblk = cp->status_blk.gen; u32 hc_cmd = CNIC_RD(dev, BNX2_HC_COMMAND); int i = 0; @@ -3490,7 +3489,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) int i; struct tx_bd *txbd; dma_addr_t buf_map; - struct status_block *s_blk = cp->status_blk; + struct status_block *s_blk = cp->status_blk.gen; sb_id = cp->status_blk_num; tx_cid = 20; @@ -3498,7 +3497,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) cnic_init_context(dev, tx_cid + 1); cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2; if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { - struct status_block_msix *sblk = cp->status_blk; + struct status_block_msix *sblk = cp->status_blk.bnx2; tx_cid = TX_TSS_CID + sb_id - 1; cnic_init_context(dev, tx_cid); @@ -3554,7 +3553,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) u32 cid_addr, sb_id, val, coal_reg, coal_val; int i; struct rx_bd *rxbd; - struct status_block *s_blk = cp->status_blk; + struct status_block *s_blk = cp->status_blk.gen; sb_id = cp->status_blk_num; cnic_init_context(dev, 2); @@ -3562,7 +3561,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev) coal_reg = BNX2_HC_COMMAND; coal_val = CNIC_RD(dev, coal_reg); if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { - struct status_block_msix *sblk = cp->status_blk; + struct status_block_msix *sblk = cp->status_blk.bnx2; cp->rx_cons_ptr = &sblk->status_rx_quick_consumer_index; coal_reg = BNX2_HC_COALESCE_NOW; @@ -3661,7 +3660,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) { struct cnic_local *cp = dev->cnic_priv; struct cnic_eth_dev *ethdev = cp->ethdev; - struct status_block *sblk = cp->status_blk; + struct status_block *sblk = cp->status_blk.gen; u32 val; int err; @@ -4250,7 +4249,7 @@ static int cnic_start_hw(struct cnic_dev *dev) cp->chip_id = ethdev->chip_id; pci_dev_get(dev->pcidev); cp->func = PCI_FUNC(dev->pcidev->devfn); - cp->status_blk = ethdev->irq_arr[0].status_blk; + cp->status_blk.gen = ethdev->irq_arr[0].status_blk; cp->status_blk_num = ethdev->irq_arr[0].status_blk_num; err = cp->alloc_resc(dev); diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h index 1921597ab4a3..d566390b8c4d 100644 --- a/drivers/net/cnic.h +++ b/drivers/net/cnic.h @@ -224,9 +224,12 @@ struct cnic_local { u16 kcq_prod_idx; u32 kcq_io_addr; - void *status_blk; - struct status_block_msix *bnx2_status_blk; - struct host_status_block *bnx2x_status_blk; + union { + void *gen; + struct status_block_msix *bnx2; + struct host_status_block *bnx2x; + } status_blk; + struct host_def_status_block *bnx2x_def_status_blk; u32 status_blk_num; -- cgit v1.2.3 From 1d9cfc4e354cd619d92bb938657dec3c533e6929 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 24 Feb 2010 14:42:09 +0000 Subject: cnic: Update version to 2.1.1. And update copyright to 2010. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/cnic.c | 2 +- drivers/net/cnic.h | 2 +- drivers/net/cnic_defs.h | 2 +- drivers/net/cnic_if.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 463408f46ba6..9781942992e9 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -1,6 +1,6 @@ /* cnic.c: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2009 Broadcom Corporation + * Copyright (c) 2006-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h index d566390b8c4d..a0d853dff983 100644 --- a/drivers/net/cnic.h +++ b/drivers/net/cnic.h @@ -1,6 +1,6 @@ /* cnic.h: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2009 Broadcom Corporation + * Copyright (c) 2006-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/cnic_defs.h b/drivers/net/cnic_defs.h index 9827b278dc7c..7ce694d41b6b 100644 --- a/drivers/net/cnic_defs.h +++ b/drivers/net/cnic_defs.h @@ -1,7 +1,7 @@ /* cnic.c: Broadcom CNIC core network driver. * - * Copyright (c) 2006-2009 Broadcom Corporation + * Copyright (c) 2006-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index 8aaf98bdd4f7..110c62072e6f 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h @@ -1,6 +1,6 @@ /* cnic_if.h: Broadcom CNIC core network driver. * - * Copyright (c) 2006 Broadcom Corporation + * Copyright (c) 2006-2010 Broadcom Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,8 +12,8 @@ #ifndef CNIC_IF_H #define CNIC_IF_H -#define CNIC_MODULE_VERSION "2.1.0" -#define CNIC_MODULE_RELDATE "Oct 10, 2009" +#define CNIC_MODULE_VERSION "2.1.1" +#define CNIC_MODULE_RELDATE "Feb 22, 2010" #define CNIC_ULP_RDMA 0 #define CNIC_ULP_ISCSI 1 -- cgit v1.2.3 From 45bb00609022ecf1d97e083666c68c74d237b799 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Thu, 25 Feb 2010 23:28:58 +0000 Subject: ipv6: Remove IPV6_ADDR_RESERVED RFC 4291 section 2.4 states that all uncategorized addresses should be considered as Global Unicast. This will remove IPV6_ADDR_RESERVED completely and return IPV6_ADDR_UNICAST in ipv6_addr_type() instead. Signed-off-by: Ulrich Weber Signed-off-by: David S. Miller --- include/net/ipv6.h | 1 - net/ipv6/addrconf.c | 3 +-- net/ipv6/addrconf_core.c | 2 +- net/ipv6/route.c | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/net/ipv6.h b/include/net/ipv6.h index d067db1f88c7..e72fb10ce573 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -73,7 +73,6 @@ #define IPV6_ADDR_SCOPE_MASK 0x00f0U #define IPV6_ADDR_MAPPED 0x1000U -#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ /* * Addr scopes diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1b327f15e7e7..88fd8c5877ee 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -992,8 +992,7 @@ struct ipv6_saddr_dst { static inline int ipv6_saddr_preferred(int type) { - if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| - IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) + if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|IPV6_ADDR_LOOPBACK)) return 1; return 0; } diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 3f82e9542eda..6b03826552e1 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c @@ -72,7 +72,7 @@ int __ipv6_addr_type(const struct in6_addr *addr) IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ } - return (IPV6_ADDR_RESERVED | + return (IPV6_ADDR_UNICAST | IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ } EXPORT_SYMBOL(__ipv6_addr_type); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 88c0a5c49ae8..b08879e97f22 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1873,7 +1873,7 @@ static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) switch (ipstats_mib_noroutes) { case IPSTATS_MIB_INNOROUTES: type = ipv6_addr_type(&ipv6_hdr(skb)->daddr); - if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) { + if (type == IPV6_ADDR_ANY) { IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); break; -- cgit v1.2.3 From 2a3f279034b46204b50408aa2c25ee0882120147 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 24 Feb 2010 12:11:19 +0000 Subject: myri10ge: optimize 4k-boundary check when stocking rx pages Small optimization to the code which checks to see if we'd cross a 4K boundary when stocking RX ring. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Guillaume Morin Signed-off-by: David S. Miller --- drivers/net/myri10ge/myri10ge.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index aae2ddb5d827..676c513e12fc 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -77,7 +77,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.5.1-1.453" +#define MYRI10GE_VERSION_STR "1.5.2-1.459" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -1200,6 +1200,9 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, { struct page *page; int idx; +#if MYRI10GE_ALLOC_SIZE > 4096 + int end_offset; +#endif if (unlikely(rx->watchdog_needed && !watchdog)) return; @@ -1241,9 +1244,9 @@ myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, #if MYRI10GE_ALLOC_SIZE > 4096 /* don't cross a 4KB boundary */ - if ((rx->page_offset >> 12) != - ((rx->page_offset + bytes - 1) >> 12)) - rx->page_offset = (rx->page_offset + 4096) & ~4095; + end_offset = rx->page_offset + bytes - 1; + if ((unsigned)(rx->page_offset ^ end_offset) > 4095) + rx->page_offset = end_offset & ~4095; #endif rx->fill_cnt++; -- cgit v1.2.3 From 914c8ad2d18b62ad1420f518c0cab0b0b90ab308 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Feb 2010 23:57:04 +0000 Subject: af_packet: do not accept mc address smaller then dev->addr_len in packet_mc_add() There is no point of accepting an address of smaller length than dev->addr_len here. Therefore change this for stonger check. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/packet/af_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2f0369367ee0..e2d1def70841 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1734,7 +1734,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq) goto done; err = -EINVAL; - if (mreq->mr_alen > dev->addr_len) + if (mreq->mr_alen != dev->addr_len) goto done; err = -ENOBUFS; -- cgit v1.2.3 From 4edb246626be6e031950205c885bdf29fb2ff1eb Mon Sep 17 00:00:00 2001 From: "Williams, Mitch A" Date: Wed, 24 Feb 2010 21:59:56 +0000 Subject: rtnetlink: clean up SR-IOV config interface This patch consists of a few minor cleanups to the SR-IOV configurion code in rtnetlink. - Remove unneccesary lock - Remove unneccesary casts - Return correct error code for no driver support These changes are based on comments from Patrick McHardy Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 42da96a4eeee..4dd4c3cdc442 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -930,10 +930,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, if (tb[IFLA_VF_MAC]) { struct ifla_vf_mac *ivm; ivm = nla_data(tb[IFLA_VF_MAC]); - write_lock_bh(&dev_base_lock); + err = -EOPNOTSUPP; if (ops->ndo_set_vf_mac) err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); - write_unlock_bh(&dev_base_lock); if (err < 0) goto errout; modified = 1; @@ -942,12 +941,11 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, if (tb[IFLA_VF_VLAN]) { struct ifla_vf_vlan *ivv; ivv = nla_data(tb[IFLA_VF_VLAN]); - write_lock_bh(&dev_base_lock); + err = -EOPNOTSUPP; if (ops->ndo_set_vf_vlan) err = ops->ndo_set_vf_vlan(dev, ivv->vf, - (u16)ivv->vlan, - (u8)ivv->qos); - write_unlock_bh(&dev_base_lock); + ivv->vlan, + ivv->qos); if (err < 0) goto errout; modified = 1; @@ -957,10 +955,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, if (tb[IFLA_VF_TX_RATE]) { struct ifla_vf_tx_rate *ivt; ivt = nla_data(tb[IFLA_VF_TX_RATE]); - write_lock_bh(&dev_base_lock); + err = -EOPNOTSUPP; if (ops->ndo_set_vf_tx_rate) err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); - write_unlock_bh(&dev_base_lock); if (err < 0) goto errout; modified = 1; -- cgit v1.2.3 From e5e26d75f490d7d41f25a4b39ed6db1713beb417 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 24 Feb 2010 14:01:38 +0000 Subject: netdev: use list_first_entry macro Use list_first_entry macro; no longer any need to use 'next' directly in list to find first entry. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 1968980f513a..eb7f1a4fefc6 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3018,7 +3018,7 @@ static void net_rx_action(struct softirq_action *h) * entries to the tail of this list, and only ->poll() * calls can remove this head entry from the list. */ - n = list_entry(list->next, struct napi_struct, poll_list); + n = list_first_entry(list, struct napi_struct, poll_list); have = netpoll_poll_lock(n); @@ -4882,7 +4882,7 @@ static void rollback_registered_many(struct list_head *head) } /* Process any work delayed until the end of the batch */ - dev = list_entry(head->next, struct net_device, unreg_list); + dev = list_first_entry(head, struct net_device, unreg_list); call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); synchronize_net(); @@ -5268,7 +5268,7 @@ void netdev_run_todo(void) while (!list_empty(&list)) { struct net_device *dev - = list_entry(list.next, struct net_device, todo_list); + = list_first_entry(&list, struct net_device, todo_list); list_del(&dev->todo_list); if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { -- cgit v1.2.3 From c43491d73ea04277c92a4aa1a7e63ccab4577756 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 25 Feb 2010 13:50:19 +0000 Subject: greth: fall through to common return statement on error There doesn't seem to be any reason to explicitly return NETDEV_TX_OK as err is set to NETDEV_TX_OK in all cases that reach this point. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/greth.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/greth.c b/drivers/net/greth.c index d75b46141603..2b9c1cbc9ec1 100644 --- a/drivers/net/greth.c +++ b/drivers/net/greth.c @@ -560,8 +560,6 @@ map_error: if (net_ratelimit()) dev_warn(greth->dev, "Could not create TX DMA mapping\n"); dev_kfree_skb(skb); - return NETDEV_TX_OK; - out: return err; } -- cgit v1.2.3 From c79c5ffdce14abb4de3878c5aa8c3c6e5093c69b Mon Sep 17 00:00:00 2001 From: Peter Waskiewicz Date: Fri, 26 Feb 2010 01:54:20 +0000 Subject: ethtool: Add n-tuple string length to drvinfo and return it The drvinfo struct should include the number of strings that get_rx_ntuple will return. It will be variable if an underlying driver implements its own get_rx_ntuple routine, so userspace needs to know how much data is coming. Signed-off-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 + net/core/ethtool.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index cca1c3de140d..f7992a256b71 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -63,6 +63,7 @@ struct ethtool_drvinfo { char reserved2[12]; __u32 n_priv_flags; /* number of flags valid in ETHTOOL_GPFLAGS */ __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ + __u32 n_ntuples; /* number of n-tuple filters from GSTRINGS */ __u32 testinfo_len; __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 31b1eddc1b84..1c94f48e27b5 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -224,6 +224,9 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS); if (rc >= 0) info.n_priv_flags = rc; + rc = ops->get_sset_count(dev, ETH_SS_NTUPLE_FILTERS); + if (rc >= 0) + info.n_ntuples = rc; } if (ops->get_regs_len) info.regdump_len = ops->get_regs_len(dev); -- cgit v1.2.3 From 6e17d45ae310758ab30623a42ad070858c9a48de Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Feb 2010 22:49:15 +0000 Subject: net: add addr len check to dev_mc_add Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/dev_mcast.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index 9e2fa39f22a3..fd91569e2394 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -96,6 +96,8 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) int err; netif_addr_lock_bh(dev); + if (alen != dev->addr_len) + return -EINVAL; err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); if (!err) __dev_set_rx_mode(dev); -- cgit v1.2.3 From fbf219f1c89b15e90ec2db5a3e9636376dc623db Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Feb 2010 05:11:08 +0000 Subject: infiniband: convert to use netdev_for_each_mc_addr Due to the loop complexicity in nes_nic.c, I'm using char* to copy mc addresses to it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/infiniband/hw/nes/nes_nic.c | 85 +++++++++++++++----------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 8 +-- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index c04f8fc6fc2d..9384f5d3d33b 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -810,6 +810,20 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p) } +static void set_allmulti(struct nes_device *nesdev, u32 nic_active_bit) +{ + u32 nic_active; + + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); + nic_active |= nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); + nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); + nic_active &= ~nic_active_bit; + nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); +} + +#define get_addr(addrs, index) ((addrs) + (index) * ETH_ALEN) + /** * nes_netdev_set_multicast_list */ @@ -818,7 +832,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; - struct dev_mc_list *multicast_addr; u32 nic_active_bit; u32 nic_active; u32 perfect_filter_register_address; @@ -831,6 +844,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) nics_per_function, 4); u8 max_pft_entries_avaiable = NES_PFT_SIZE - pft_entries_preallocated; unsigned long flags; + int mc_count = netdev_mc_count(netdev); spin_lock_irqsave(&nesadapter->resource_lock, flags); nic_active_bit = 1 << nesvnic->nic_index; @@ -845,12 +859,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) mc_all_on = 1; } else if ((netdev->flags & IFF_ALLMULTI) || (nesvnic->nic_index > 3)) { - nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); - nic_active |= nic_active_bit; - nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active); - nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL); - nic_active &= ~nic_active_bit; - nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active); + set_allmulti(nesdev, nic_active_bit); mc_all_on = 1; } else { nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL); @@ -862,19 +871,30 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) } nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n", - netdev_mc_count(netdev), !!(netdev->flags & IFF_PROMISC), + mc_count, !!(netdev->flags & IFF_PROMISC), !!(netdev->flags & IFF_ALLMULTI)); if (!mc_all_on) { - multicast_addr = netdev->mc_list; + char *addrs; + int i; + struct dev_mc_list *mcaddr; + + addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC); + if (!addrs) { + set_allmulti(nesdev, nic_active_bit); + goto unlock; + } + i = 0; + netdev_for_each_mc_addr(mcaddr, netdev) + memcpy(get_addr(addrs, i++), + mcaddr->dmi_addr, ETH_ALEN); + perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + pft_entries_preallocated * 0x8; - for (mc_index = 0; mc_index < max_pft_entries_avaiable; - mc_index++) { - while (multicast_addr && nesvnic->mcrq_mcast_filter && + for (i = 0, mc_index = 0; mc_index < max_pft_entries_avaiable; + mc_index++) { + while (i < mc_count && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, - multicast_addr->dmi_addr)) == 0)) { - multicast_addr = multicast_addr->next; - } + get_addr(addrs, i++))) == 0)); if (mc_nic_index < 0) mc_nic_index = nesvnic->nic_index; while (nesadapter->pft_mcast_map[mc_index] < 16 && @@ -890,17 +910,19 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) } if (mc_index >= max_pft_entries_avaiable) break; - if (multicast_addr) { + if (i < mc_count) { + char *addr = get_addr(addrs, i++); + nes_debug(NES_DBG_NIC_RX, "Assigning MC Address %pM to register 0x%04X nic_idx=%d\n", - multicast_addr->dmi_addr, + addr, perfect_filter_register_address+(mc_index * 8), mc_nic_index); - macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8; - macaddr_high += (u16)multicast_addr->dmi_addr[1]; - macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24; - macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16; - macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8; - macaddr_low += (u32)multicast_addr->dmi_addr[5]; + macaddr_high = ((u16) addr[0]) << 8; + macaddr_high += (u16) addr[1]; + macaddr_low = ((u32) addr[2]) << 24; + macaddr_low += ((u32) addr[3]) << 16; + macaddr_low += ((u32) addr[4]) << 8; + macaddr_low += (u32) addr[5]; nes_write_indexed(nesdev, perfect_filter_register_address+(mc_index * 8), macaddr_low); @@ -908,7 +930,6 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) perfect_filter_register_address+4+(mc_index * 8), (u32)macaddr_high | NES_MAC_ADDR_VALID | ((((u32)(1<next; nesadapter->pft_mcast_map[mc_index] = nesvnic->nic_index; } else { @@ -920,21 +941,13 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev) nesadapter->pft_mcast_map[mc_index] = 255; } } + kfree(addrs); /* PFT is not large enough */ - if (multicast_addr && multicast_addr->next) { - nic_active = nes_read_indexed(nesdev, - NES_IDX_NIC_MULTICAST_ALL); - nic_active |= nic_active_bit; - nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, - nic_active); - nic_active = nes_read_indexed(nesdev, - NES_IDX_NIC_UNICAST_ALL); - nic_active &= ~nic_active_bit; - nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, - nic_active); - } + if (i < mc_count) + set_allmulti(nesdev, nic_active_bit); } +unlock: spin_unlock_irqrestore(&nesadapter->resource_lock, flags); } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 8763c1ea5eb4..19eba3c877cb 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -767,11 +767,8 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen, - const u8 *broadcast) +static int ipoib_mcast_addr_is_valid(const u8 *addr, const u8 *broadcast) { - if (addrlen != INFINIBAND_ALEN) - return 0; /* reserved QPN, prefix, scope */ if (memcmp(addr, broadcast, 6)) return 0; @@ -811,11 +808,10 @@ void ipoib_mcast_restart_task(struct work_struct *work) clear_bit(IPOIB_MCAST_FLAG_FOUND, &mcast->flags); /* Mark all of the entries that are found or don't exist */ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) { + netdev_for_each_mc_addr(mclist, dev) { union ib_gid mgid; if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr, - mclist->dmi_addrlen, dev->broadcast)) continue; -- cgit v1.2.3 From 14f3ad6f4a12495b32b0dd743bc7179f36658208 Mon Sep 17 00:00:00 2001 From: Ulrich Weber Date: Fri, 26 Feb 2010 04:34:49 -0800 Subject: ipv6: Use 1280 as min MTU for ipv6 forwarding Clients will set their MTU to 1280 if they receive a ICMPV6_PKT_TOOBIG message with an MTU less than 1280. To allow encapsulating of packets over a 1280 link we should always accept packets with a size of 1280 for forwarding even if the path has a lower MTU and fragment the encapsulated packets afterwards. In case a forwarded packet is not going to be encapsulated a ICMPV6_PKT_TOOBIG msg will still be send by ip6_fragment() with the correct MTU. Signed-off-by: Ulrich Weber Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 1a5fe9ad1947..dabf108ad811 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -402,6 +402,7 @@ int ip6_forward(struct sk_buff *skb) struct ipv6hdr *hdr = ipv6_hdr(skb); struct inet6_skb_parm *opt = IP6CB(skb); struct net *net = dev_net(dst->dev); + u32 mtu; if (net->ipv6.devconf_all->forwarding == 0) goto error; @@ -508,10 +509,14 @@ int ip6_forward(struct sk_buff *skb) } } - if (skb->len > dst_mtu(dst)) { + mtu = dst_mtu(dst); + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + if (skb->len > mtu) { /* Again, force OUTPUT device used as source address */ skb->dev = dst->dev; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst)); + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); IP6_INC_STATS_BH(net, @@ -621,8 +626,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) mtu = ip6_skb_dst_mtu(skb); /* We must not fragment if the socket is set to force MTU discovery - * or if the skb it not generated by a local socket. (This last - * check should be redundant, but it's free.) + * or if the skb it not generated by a local socket. */ if (!skb->local_df) { skb->dev = skb_dst(skb)->dev; -- cgit v1.2.3 From 738b0343e73604750feb107e063c28b3ca36cb84 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 26 Feb 2010 05:12:02 -0800 Subject: Revert "ethtool: Add n-tuple string length to drvinfo and return it" This reverts commit c79c5ffdce14abb4de3878c5aa8c3c6e5093c69b. As Jeff points out we can't break the user visible interface like this, we need to add this into the reserved[] thing. Signed-off-by: David S. Miller --- include/linux/ethtool.h | 1 - net/core/ethtool.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index f7992a256b71..cca1c3de140d 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -63,7 +63,6 @@ struct ethtool_drvinfo { char reserved2[12]; __u32 n_priv_flags; /* number of flags valid in ETHTOOL_GPFLAGS */ __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ - __u32 n_ntuples; /* number of n-tuple filters from GSTRINGS */ __u32 testinfo_len; __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 1c94f48e27b5..31b1eddc1b84 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -224,9 +224,6 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use rc = ops->get_sset_count(dev, ETH_SS_PRIV_FLAGS); if (rc >= 0) info.n_priv_flags = rc; - rc = ops->get_sset_count(dev, ETH_SS_NTUPLE_FILTERS); - if (rc >= 0) - info.n_ntuples = rc; } if (ops->get_regs_len) info.regdump_len = ops->get_regs_len(dev); -- cgit v1.2.3 From 773c3e75d1fc7ea5058bfeab5d82bac5b85f8cd8 Mon Sep 17 00:00:00 2001 From: Sriramakrishnan Date: Fri, 26 Feb 2010 05:22:03 -0800 Subject: can: ti hecc module : add platform specific initialization callback. CAN module on AM3517 requires programming of IO expander as part of init sequence - to enable CAN PHY. Added platform specific callback to handle phy control(switch on /off). Signed-off-by: Sriramakrishnan Signed-off-by: David S. Miller --- drivers/net/can/ti_hecc.c | 17 ++++++++++++++++- include/linux/can/platform/ti_hecc.h | 8 ++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index b861cd561074..0c3d2ba0d178 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -28,9 +28,11 @@ * .mbx_offset = 0x2000, * .int_line = 0, * .revision = 1, + * .transceiver_switch = hecc_phy_control, * }; * - * Please see include/can/platform/ti_hecc.h for description of above fields + * Please see include/linux/can/platform/ti_hecc.h for description of + * above fields. * */ @@ -220,6 +222,7 @@ struct ti_hecc_priv { u32 tx_head; u32 tx_tail; u32 rx_next; + void (*transceiver_switch)(int); }; static inline int get_tx_head_mb(struct ti_hecc_priv *priv) @@ -317,6 +320,13 @@ static int ti_hecc_set_btc(struct ti_hecc_priv *priv) return 0; } +static void ti_hecc_transceiver_switch(const struct ti_hecc_priv *priv, + int on) +{ + if (priv->transceiver_switch) + priv->transceiver_switch(on); +} + static void ti_hecc_reset(struct net_device *ndev) { u32 cnt; @@ -818,10 +828,13 @@ static int ti_hecc_open(struct net_device *ndev) return err; } + ti_hecc_transceiver_switch(priv, 1); + /* Open common can device */ err = open_candev(ndev); if (err) { dev_err(ndev->dev.parent, "open_candev() failed %d\n", err); + ti_hecc_transceiver_switch(priv, 0); free_irq(ndev->irq, ndev); return err; } @@ -842,6 +855,7 @@ static int ti_hecc_close(struct net_device *ndev) ti_hecc_stop(ndev); free_irq(ndev->irq, ndev); close_candev(ndev); + ti_hecc_transceiver_switch(priv, 0); return 0; } @@ -903,6 +917,7 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->hecc_ram_offset = pdata->hecc_ram_offset; priv->mbx_offset = pdata->mbx_offset; priv->int_line = pdata->int_line; + priv->transceiver_switch = pdata->transceiver_switch; priv->can.bittiming_const = &ti_hecc_bittiming_const; priv->can.do_set_mode = ti_hecc_do_set_mode; diff --git a/include/linux/can/platform/ti_hecc.h b/include/linux/can/platform/ti_hecc.h index 4688c7bb1bd1..af17cb3f7a84 100644 --- a/include/linux/can/platform/ti_hecc.h +++ b/include/linux/can/platform/ti_hecc.h @@ -1,3 +1,6 @@ +#ifndef __CAN_PLATFORM_TI_HECC_H__ +#define __CAN_PLATFORM_TI_HECC_H__ + /* * TI HECC (High End CAN Controller) driver platform header * @@ -23,6 +26,7 @@ * @mbx_offset: Mailbox RAM offset * @int_line: Interrupt line to use - 0 or 1 * @version: version for future use + * @transceiver_switch: platform specific callback fn for transceiver control * * Platform data structure to get all platform specific settings. * this structure also accounts the fact that the IP may have different @@ -35,6 +39,6 @@ struct ti_hecc_platform_data { u32 mbx_offset; u32 int_line; u32 version; + void (*transceiver_switch) (int); }; - - +#endif -- cgit v1.2.3 From 51f0bc78680edccb6574ef56bd32f9e2939c8a5a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 26 Feb 2010 17:45:14 +0100 Subject: IPVS: ip_vs_lblcr: use list headA Use list_head rather than a custom list implementation. Signed-off-by: Simon Horman Signed-off-by: Patrick McHardy --- net/netfilter/ipvs/ip_vs_lblcr.c | 44 +++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index f7476b95ab46..caa58fa1438a 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c @@ -45,6 +45,7 @@ #include #include #include +#include /* for sysctl */ #include @@ -85,25 +86,25 @@ static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ; /* * IPVS destination set structure and operations */ -struct ip_vs_dest_list { - struct ip_vs_dest_list *next; /* list link */ +struct ip_vs_dest_set_elem { + struct list_head list; /* list link */ struct ip_vs_dest *dest; /* destination server */ }; struct ip_vs_dest_set { atomic_t size; /* set size */ unsigned long lastmod; /* last modified time */ - struct ip_vs_dest_list *list; /* destination list */ + struct list_head list; /* destination list */ rwlock_t lock; /* lock for this list */ }; -static struct ip_vs_dest_list * +static struct ip_vs_dest_set_elem * ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) { - struct ip_vs_dest_list *e; + struct ip_vs_dest_set_elem *e; - for (e=set->list; e!=NULL; e=e->next) { + list_for_each_entry(e, &set->list, list) { if (e->dest == dest) /* already existed */ return NULL; @@ -118,9 +119,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) atomic_inc(&dest->refcnt); e->dest = dest; - /* link it to the list */ - e->next = set->list; - set->list = e; + list_add(&e->list, &set->list); atomic_inc(&set->size); set->lastmod = jiffies; @@ -130,34 +129,33 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) static void ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) { - struct ip_vs_dest_list *e, **ep; + struct ip_vs_dest_set_elem *e; - for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { + list_for_each_entry(e, &set->list, list) { if (e->dest == dest) { /* HIT */ - *ep = e->next; atomic_dec(&set->size); set->lastmod = jiffies; atomic_dec(&e->dest->refcnt); + list_del(&e->list); kfree(e); break; } - ep = &e->next; } } static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) { - struct ip_vs_dest_list *e, **ep; + struct ip_vs_dest_set_elem *e, *ep; write_lock(&set->lock); - for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { - *ep = e->next; + list_for_each_entry_safe(e, ep, &set->list, list) { /* * We don't kfree dest because it is refered either * by its service or by the trash dest list. */ atomic_dec(&e->dest->refcnt); + list_del(&e->list); kfree(e); } write_unlock(&set->lock); @@ -166,7 +164,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) /* get weighted least-connection node in the destination set */ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) { - register struct ip_vs_dest_list *e; + register struct ip_vs_dest_set_elem *e; struct ip_vs_dest *dest, *least; int loh, doh; @@ -174,7 +172,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) return NULL; /* select the first destination server, whose weight > 0 */ - for (e=set->list; e!=NULL; e=e->next) { + list_for_each_entry(e, &set->list, list) { least = e->dest; if (least->flags & IP_VS_DEST_F_OVERLOAD) continue; @@ -190,7 +188,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) /* find the destination with the weighted least load */ nextstage: - for (e=e->next; e!=NULL; e=e->next) { + list_for_each_entry(e, &set->list, list) { dest = e->dest; if (dest->flags & IP_VS_DEST_F_OVERLOAD) continue; @@ -220,7 +218,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) /* get weighted most-connection node in the destination set */ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) { - register struct ip_vs_dest_list *e; + register struct ip_vs_dest_set_elem *e; struct ip_vs_dest *dest, *most; int moh, doh; @@ -228,7 +226,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) return NULL; /* select the first destination server, whose weight > 0 */ - for (e=set->list; e!=NULL; e=e->next) { + list_for_each_entry(e, &set->list, list) { most = e->dest; if (atomic_read(&most->weight) > 0) { moh = atomic_read(&most->activeconns) * 50 @@ -240,7 +238,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) /* find the destination with the weighted most load */ nextstage: - for (e=e->next; e!=NULL; e=e->next) { + list_for_each_entry(e, &set->list, list) { dest = e->dest; doh = atomic_read(&dest->activeconns) * 50 + atomic_read(&dest->inactconns); @@ -389,7 +387,7 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, /* initilize its dest set */ atomic_set(&(en->set.size), 0); - en->set.list = NULL; + INIT_LIST_HEAD(&en->set.list); rwlock_init(&en->set.lock); ip_vs_lblcr_hash(tbl, en); -- cgit v1.2.3 From a49c65037146bfb2fe300b8277b10b4479fea5fc Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 26 Feb 2010 17:48:40 +0100 Subject: netfilter: nfnetlink_log: fix silly refcount leak Quick fix for memory/module refcount leak. Reference count of listener instance never reaches 0. Start/stop of ulogd2 is enough to trigger this bug! Now, refcounting there looks very fishy in particular this code: if (!try_module_get(THIS_MODULE)) { ... and creation of listener instance with refcount 2, so it may very well be ripped and redone. :-) Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy --- net/netfilter/nfnetlink_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 285e9029a9ff..d9b8fb8ab340 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -768,7 +768,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } instance_destroy(inst); - goto out; + goto out_put; default: ret = -ENOTSUPP; break; -- cgit v1.2.3 From 6b4ff2d7675511a31980fa5379808660e1261f90 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Fri, 26 Feb 2010 17:53:31 +0100 Subject: netfilter: xtables: restore indentation Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- net/ipv4/netfilter/arp_tables.c | 23 ++++++++++++++--------- net/ipv4/netfilter/ip_tables.c | 25 +++++++++++++++---------- net/ipv6/netfilter/ip6_tables.c | 25 +++++++++++++++---------- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 57098dcda294..f07d77f65751 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -644,8 +644,10 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + repl->size, repl->hook_entry, repl->underflow, - repl->valid_hooks); + entry0 + repl->size, + repl->hook_entry, + repl->underflow, + repl->valid_hooks); if (ret != 0) break; ++i; @@ -730,7 +732,7 @@ static void get_counters(const struct xt_table_info *t, i = 0; xt_entry_foreach(iter, t->entries[curcpu], t->size) { SET_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; } @@ -741,7 +743,7 @@ static void get_counters(const struct xt_table_info *t, xt_info_wrlock(cpu); xt_entry_foreach(iter, t->entries[cpu], t->size) { ADD_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; } xt_info_wrunlock(cpu); @@ -1356,8 +1358,11 @@ static int translate_compat_table(const char *name, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, - entry0, entry0 + total_size, hook_entries, underflows, - name); + entry0, + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; @@ -1401,8 +1406,8 @@ static int translate_compat_table(const char *name, pos = entry1; size = total_size; xt_entry_foreach(iter0, entry0, total_size) { - ret = compat_copy_entry_from_user(iter0, &pos, - &size, name, newinfo, entry1); + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); if (ret != 0) break; } @@ -1617,7 +1622,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, i++); + &size, counters, i++); if (ret != 0) break; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index c92f4e541cf6..b29c66df8d1f 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -836,8 +836,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + repl->size, repl->hook_entry, repl->underflow, - repl->valid_hooks); + entry0 + repl->size, + repl->hook_entry, + repl->underflow, + repl->valid_hooks); if (ret != 0) return ret; ++i; @@ -918,7 +920,7 @@ get_counters(const struct xt_table_info *t, i = 0; xt_entry_foreach(iter, t->entries[curcpu], t->size) { SET_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; } @@ -929,7 +931,7 @@ get_counters(const struct xt_table_info *t, xt_info_wrlock(cpu); xt_entry_foreach(iter, t->entries[cpu], t->size) { ADD_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; /* macro does multi eval of i */ } xt_info_wrunlock(cpu); @@ -1540,7 +1542,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, j = 0; xt_ematch_foreach(ematch, e) { ret = compat_find_calc_match(ematch, name, - &e->ip, e->comefrom, &off); + &e->ip, e->comefrom, &off); if (ret != 0) goto release_matches; ++j; @@ -1701,8 +1703,11 @@ translate_compat_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, - entry0, entry0 + total_size, hook_entries, underflows, - name); + entry0, + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; @@ -1746,8 +1751,8 @@ translate_compat_table(struct net *net, pos = entry1; size = total_size; xt_entry_foreach(iter0, entry0, total_size) { - ret = compat_copy_entry_from_user(iter0, &pos, - &size, name, newinfo, entry1); + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); if (ret != 0) break; } @@ -1927,7 +1932,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, i++); + &size, counters, i++); if (ret != 0) break; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f7042869198e..9210e312edf1 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -866,8 +866,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter, entry0, newinfo->size) { ret = check_entry_size_and_hooks(iter, newinfo, entry0, - entry0 + repl->size, repl->hook_entry, repl->underflow, - repl->valid_hooks); + entry0 + repl->size, + repl->hook_entry, + repl->underflow, + repl->valid_hooks); if (ret != 0) return ret; ++i; @@ -948,7 +950,7 @@ get_counters(const struct xt_table_info *t, i = 0; xt_entry_foreach(iter, t->entries[curcpu], t->size) { SET_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; } @@ -959,7 +961,7 @@ get_counters(const struct xt_table_info *t, xt_info_wrlock(cpu); xt_entry_foreach(iter, t->entries[cpu], t->size) { ADD_COUNTER(counters[i], iter->counters.bcnt, - iter->counters.pcnt); + iter->counters.pcnt); ++i; } xt_info_wrunlock(cpu); @@ -1573,7 +1575,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, j = 0; xt_ematch_foreach(ematch, e) { ret = compat_find_calc_match(ematch, name, - &e->ipv6, e->comefrom, &off); + &e->ipv6, e->comefrom, &off); if (ret != 0) goto release_matches; ++j; @@ -1734,8 +1736,11 @@ translate_compat_table(struct net *net, /* Walk through entries, checking offsets. */ xt_entry_foreach(iter0, entry0, total_size) { ret = check_compat_entry_size_and_hooks(iter0, info, &size, - entry0, entry0 + total_size, hook_entries, underflows, - name); + entry0, + entry0 + total_size, + hook_entries, + underflows, + name); if (ret != 0) goto out_unlock; ++j; @@ -1779,8 +1784,8 @@ translate_compat_table(struct net *net, pos = entry1; size = total_size; xt_entry_foreach(iter0, entry0, total_size) { - ret = compat_copy_entry_from_user(iter0, &pos, - &size, name, newinfo, entry1); + ret = compat_copy_entry_from_user(iter0, &pos, &size, + name, newinfo, entry1); if (ret != 0) break; } @@ -1960,7 +1965,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, size = total_size; xt_entry_foreach(iter, loc_cpu_entry, total_size) { ret = compat_copy_entry_to_user(iter, &pos, - &size, counters, i++); + &size, counters, i++); if (ret != 0) break; } -- cgit v1.2.3 From 8266d7127c1b0bdf924066c19c71be4d351e9583 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 26 Feb 2010 12:49:20 -0800 Subject: net: Delete isa-skeleton net driver The ISA skeleton net driver has been obsolete and unmaintained for many years. Any hardware remotely like ISA will use the platform API and look much more like a PCI driver, and make much better use of netdev APIs such as NAPI. Signed-off-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/isa-skeleton.c | 718 --------------------------------------------- 1 file changed, 718 deletions(-) delete mode 100644 drivers/net/isa-skeleton.c diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c deleted file mode 100644 index 9e55c3007743..000000000000 --- a/drivers/net/isa-skeleton.c +++ /dev/null @@ -1,718 +0,0 @@ -/* isa-skeleton.c: A network driver outline for linux. - * - * Written 1993-94 by Donald Becker. - * - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency. - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * The author may be reached as becker@scyld.com, or C/O - * Scyld Computing Corporation - * 410 Severn Ave., Suite 210 - * Annapolis MD 21403 - * - * This file is an outline for writing a network device driver for the - * the Linux operating system. - * - * To write (or understand) a driver, have a look at the "loopback.c" file to - * get a feel of what is going on, and then use the code below as a skeleton - * for the new driver. - * - */ - -static const char *version = - "isa-skeleton.c:v1.51 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; - -/* - * Sources: - * List your sources of programming information to document that - * the driver is your own creation, and give due credit to others - * that contributed to the work. Remember that GNU project code - * cannot use proprietary or trade secret information. Interface - * definitions are generally considered non-copyrightable to the - * extent that the same names and structures must be used to be - * compatible. - * - * Finally, keep in mind that the Linux kernel is has an API, not - * ABI. Proprietary object-code-only distributions are not permitted - * under the GPL. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * The name of the card. Is used for messages and in the requests for - * io regions, irqs and dma channels - */ -static const char* cardname = "netcard"; - -/* First, a few definitions that the brave might change. */ - -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int netcard_portlist[] __initdata = - { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0}; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* The number of low I/O ports used by the ethercard. */ -#define NETCARD_IO_EXTENT 32 - -#define MY_TX_TIMEOUT ((400*HZ)/1000) - -/* Information that need to be kept for each board. */ -struct net_local { - struct net_device_stats stats; - long open_time; /* Useless example local info. */ - - /* Tx control lock. This protects the transmit buffer ring - * state along with the "tx full" state of the driver. This - * means all netif_queue flow control actions are protected - * by this lock as well. - */ - spinlock_t lock; -}; - -/* The station (ethernet) address prefix, used for IDing the board. */ -#define SA_ADDR0 0x00 -#define SA_ADDR1 0x42 -#define SA_ADDR2 0x65 - -/* Index to functions, as function prototypes. */ - -static int netcard_probe1(struct net_device *dev, int ioaddr); -static int net_open(struct net_device *dev); -static int net_send_packet(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t net_interrupt(int irq, void *dev_id); -static void net_rx(struct net_device *dev); -static int net_close(struct net_device *dev); -static struct net_device_stats *net_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void net_tx_timeout(struct net_device *dev); - - -/* Example routines you must write ;->. */ -#define tx_done(dev) 1 -static void hardware_send_packet(short ioaddr, char *buf, int length); -static void chipset_init(struct net_device *dev, int startp); - -/* - * Check for a network adaptor of this type, and return '0' iff one exists. - * If dev->base_addr == 0, probe all likely locations. - * If dev->base_addr == 1, always return failure. - * If dev->base_addr == 2, allocate space for the device and return success - * (detachable devices only). - */ -static int __init do_netcard_probe(struct net_device *dev) -{ - int i; - int base_addr = dev->base_addr; - int irq = dev->irq; - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return netcard_probe1(dev, base_addr); - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; netcard_portlist[i]; i++) { - int ioaddr = netcard_portlist[i]; - if (netcard_probe1(dev, ioaddr) == 0) - return 0; - dev->irq = irq; - } - - return -ENODEV; -} - -static void cleanup_card(struct net_device *dev) -{ -#ifdef jumpered_dma - free_dma(dev->dma); -#endif -#ifdef jumpered_interrupts - free_irq(dev->irq, dev); -#endif - release_region(dev->base_addr, NETCARD_IO_EXTENT); -} - -#ifndef MODULE -struct net_device * __init netcard_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_netcard_probe(dev); - if (err) - goto out; - return dev; -out: - free_netdev(dev); - return ERR_PTR(err); -} -#endif - -static const struct net_device_ops netcard_netdev_ops = { - .ndo_open = net_open, - .ndo_stop = net_close, - .ndo_start_xmit = net_send_packet, - .ndo_get_stats = net_get_stats, - .ndo_set_multicast_list = set_multicast_list, - .ndo_tx_timeout = net_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_mac_addr, - .ndo_change_mtu = eth_change_mtu, -}; - -/* - * This is the real probe routine. Linux has a history of friendly device - * probes on the ISA bus. A good device probes avoids doing writes, and - * verifies that the correct device exists and functions. - */ -static int __init netcard_probe1(struct net_device *dev, int ioaddr) -{ - struct net_local *np; - static unsigned version_printed; - int i; - int err = -ENODEV; - - /* Grab the region so that no one else tries to probe our ioports. */ - if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname)) - return -EBUSY; - - /* - * For ethernet adaptors the first three octets of the station address - * contains the manufacturer's unique code. That might be a good probe - * method. Ideally you would add additional checks. - */ - if (inb(ioaddr + 0) != SA_ADDR0 || - inb(ioaddr + 1) != SA_ADDR1 || - inb(ioaddr + 2) != SA_ADDR2) - goto out; - - if (net_debug && version_printed++ == 0) - printk(KERN_DEBUG "%s", version); - - printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cardname, ioaddr); - - /* Fill in the 'dev' fields. */ - dev->base_addr = ioaddr; - - /* Retrieve and print the ethernet address. */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(ioaddr + i); - - printk("%pM", dev->dev_addr); - - err = -EAGAIN; -#ifdef jumpered_interrupts - /* - * If this board has jumpered interrupts, allocate the interrupt - * vector now. There is no point in waiting since no other device - * can use the interrupt, and this marks the irq as busy. Jumpered - * interrupts are typically not reported by the boards, and we must - * used autoIRQ to find them. - */ - - if (dev->irq == -1) - ; /* Do nothing: a user-level program will set it. */ - else if (dev->irq < 2) { /* "Auto-IRQ" */ - unsigned long irq_mask = probe_irq_on(); - /* Trigger an interrupt here. */ - - dev->irq = probe_irq_off(irq_mask); - if (net_debug >= 2) - printk(" autoirq is %d", dev->irq); - } else if (dev->irq == 2) - /* - * Fixup for users that don't know that IRQ 2 is really - * IRQ9, or don't know which one to set. - */ - dev->irq = 9; - - { - int irqval = request_irq(dev->irq, net_interrupt, 0, cardname, dev); - if (irqval) { - printk("%s: unable to get IRQ %d (irqval=%d).\n", - dev->name, dev->irq, irqval); - goto out; - } - } -#endif /* jumpered interrupt */ -#ifdef jumpered_dma - /* - * If we use a jumpered DMA channel, that should be probed for and - * allocated here as well. See lance.c for an example. - */ - if (dev->dma == 0) { - if (request_dma(dev->dma, cardname)) { - printk("DMA %d allocation failed.\n", dev->dma); - goto out1; - } else - printk(", assigned DMA %d.\n", dev->dma); - } else { - short dma_status, new_dma_status; - - /* Read the DMA channel status registers. */ - dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | - (inb(DMA2_STAT_REG) & 0xf0); - /* Trigger a DMA request, perhaps pause a bit. */ - outw(0x1234, ioaddr + 8); - /* Re-read the DMA status registers. */ - new_dma_status = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | - (inb(DMA2_STAT_REG) & 0xf0); - /* - * Eliminate the old and floating requests, - * and DMA4 the cascade. - */ - new_dma_status ^= dma_status; - new_dma_status &= ~0x10; - for (i = 7; i > 0; i--) - if (test_bit(i, &new_dma_status)) { - dev->dma = i; - break; - } - if (i <= 0) { - printk("DMA probe failed.\n"); - goto out1; - } - if (request_dma(dev->dma, cardname)) { - printk("probed DMA %d allocation failed.\n", dev->dma); - goto out1; - } - } -#endif /* jumpered DMA */ - - np = netdev_priv(dev); - spin_lock_init(&np->lock); - - dev->netdev_ops = &netcard_netdev_ops; - dev->watchdog_timeo = MY_TX_TIMEOUT; - - err = register_netdev(dev); - if (err) - goto out2; - return 0; -out2: -#ifdef jumpered_dma - free_dma(dev->dma); -#endif -out1: -#ifdef jumpered_interrupts - free_irq(dev->irq, dev); -#endif -out: - release_region(base_addr, NETCARD_IO_EXTENT); - return err; -} - -static void net_tx_timeout(struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - - printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, - tx_done(dev) ? "IRQ conflict" : "network cable problem"); - - /* Try to restart the adaptor. */ - chipset_init(dev, 1); - - np->stats.tx_errors++; - - /* If we have space available to accept new transmit - * requests, wake up the queueing layer. This would - * be the case if the chipset_init() call above just - * flushes out the tx queue and empties it. - * - * If instead, the tx queue is retained then the - * netif_wake_queue() call should be placed in the - * TX completion interrupt handler of the driver instead - * of here. - */ - if (!tx_full(dev)) - netif_wake_queue(dev); -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * sometime after booting when the 'ifconfig' program is run. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is non-reboot way to recover if something goes wrong. - */ -static int -net_open(struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - int ioaddr = dev->base_addr; - /* - * This is used if the interrupt line can turned off (shared). - * See 3c503.c for an example of selecting the IRQ at config-time. - */ - if (request_irq(dev->irq, net_interrupt, 0, cardname, dev)) { - return -EAGAIN; - } - /* - * Always allocate the DMA channel after the IRQ, - * and clean up on failure. - */ - if (request_dma(dev->dma, cardname)) { - free_irq(dev->irq, dev); - return -EAGAIN; - } - - /* Reset the hardware here. Don't forget to set the station address. */ - chipset_init(dev, 1); - outb(0x00, ioaddr); - np->open_time = jiffies; - - /* We are now ready to accept transmit requeusts from - * the queueing layer of the networking. - */ - netif_start_queue(dev); - - return 0; -} - -/* This will only be invoked if your driver is _not_ in XOFF state. - * What this means is that you need not check it, and that this - * invariant will hold if you make sure that the netif_*_queue() - * calls are done at the proper times. - */ -static int net_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - int ioaddr = dev->base_addr; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - /* If some error occurs while trying to transmit this - * packet, you should return '1' from this function. - * In such a case you _may not_ do anything to the - * SKB, it is still owned by the network queueing - * layer when an error is returned. This means you - * may not modify any SKB fields, you may not free - * the SKB, etc. - */ - -#if TX_RING - /* This is the most common case for modern hardware. - * The spinlock protects this code from the TX complete - * hardware interrupt handler. Queue flow control is - * thus managed under this lock as well. - */ - unsigned long flags; - spin_lock_irqsave(&np->lock, flags); - - add_to_tx_ring(np, skb, length); - dev->trans_start = jiffies; - - /* If we just used up the very last entry in the - * TX ring on this device, tell the queueing - * layer to send no more. - */ - if (tx_full(dev)) - netif_stop_queue(dev); - - /* When the TX completion hw interrupt arrives, this - * is when the transmit statistics are updated. - */ - - spin_unlock_irqrestore(&np->lock, flags); -#else - /* This is the case for older hardware which takes - * a single transmit buffer at a time, and it is - * just written to the device via PIO. - * - * No spin locking is needed since there is no TX complete - * event. If by chance your card does have a TX complete - * hardware IRQ then you may need to utilize np->lock here. - */ - hardware_send_packet(ioaddr, buf, length); - np->stats.tx_bytes += skb->len; - - dev->trans_start = jiffies; - - /* You might need to clean up and record Tx statistics here. */ - if (inw(ioaddr) == /*RU*/81) - np->stats.tx_aborted_errors++; - dev_kfree_skb (skb); -#endif - - return NETDEV_TX_OK; -} - -#if TX_RING -/* This handles TX complete events posted by the device - * via interrupts. - */ -void net_tx(struct net_device *dev) -{ - struct net_local *np = netdev_priv(dev); - int entry; - - /* This protects us from concurrent execution of - * our dev->hard_start_xmit function above. - */ - spin_lock(&np->lock); - - entry = np->tx_old; - while (tx_entry_is_sent(np, entry)) { - struct sk_buff *skb = np->skbs[entry]; - - np->stats.tx_bytes += skb->len; - dev_kfree_skb_irq (skb); - - entry = next_tx_entry(np, entry); - } - np->tx_old = entry; - - /* If we had stopped the queue due to a "tx full" - * condition, and space has now been made available, - * wake up the queue. - */ - if (netif_queue_stopped(dev) && ! tx_full(dev)) - netif_wake_queue(dev); - - spin_unlock(&np->lock); -} -#endif - -/* - * The typical workload of the driver: - * Handle the network interface interrupts. - */ -static irqreturn_t net_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct net_local *np; - int ioaddr, status; - int handled = 0; - - ioaddr = dev->base_addr; - - np = netdev_priv(dev); - status = inw(ioaddr + 0); - - if (status == 0) - goto out; - handled = 1; - - if (status & RX_INTR) { - /* Got a packet(s). */ - net_rx(dev); - } -#if TX_RING - if (status & TX_INTR) { - /* Transmit complete. */ - net_tx(dev); - np->stats.tx_packets++; - } -#endif - if (status & COUNTERS_INTR) { - /* Increment the appropriate 'localstats' field. */ - np->stats.tx_window_errors++; - } -out: - return IRQ_RETVAL(handled); -} - -/* We have a good packet(s), get it/them out of the buffers. */ -static void -net_rx(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - int boguscount = 10; - - do { - int status = inw(ioaddr); - int pkt_len = inw(ioaddr); - - if (pkt_len == 0) /* Read all the frames? */ - break; /* Done for now */ - - if (status & 0x40) { /* There was an error. */ - lp->stats.rx_errors++; - if (status & 0x20) lp->stats.rx_frame_errors++; - if (status & 0x10) lp->stats.rx_over_errors++; - if (status & 0x08) lp->stats.rx_crc_errors++; - if (status & 0x04) lp->stats.rx_fifo_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - lp->stats.rx_bytes+=pkt_len; - - skb = dev_alloc_skb(pkt_len); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - dev->name); - lp->stats.rx_dropped++; - break; - } - skb->dev = dev; - - /* 'skb->data' points to the start of sk_buff data area. */ - memcpy(skb_put(skb,pkt_len), (void*)dev->rmem_start, - pkt_len); - /* or */ - insw(ioaddr, skb->data, (pkt_len + 1) >> 1); - - netif_rx(skb); - lp->stats.rx_packets++; - lp->stats.rx_bytes += pkt_len; - } - } while (--boguscount); - - return; -} - -/* The inverse routine to net_open(). */ -static int -net_close(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - lp->open_time = 0; - - netif_stop_queue(dev); - - /* Flush the Tx and disable Rx here. */ - - disable_dma(dev->dma); - - /* If not IRQ or DMA jumpered, free up the line. */ - outw(0x00, ioaddr+0); /* Release the physical interrupt line. */ - - free_irq(dev->irq, dev); - free_dma(dev->dma); - - /* Update the statistics here. */ - - return 0; - -} - -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ -static struct net_device_stats *net_get_stats(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - - /* Update the statistics from the device registers. */ - lp->stats.rx_missed_errors = inw(ioaddr+1); - return &lp->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - * num_addrs == -1 Promiscuous mode, receive all packets - * num_addrs == 0 Normal mode, clear multicast list - * num_addrs > 0 Multicast mode, receive normal and MC packets, - * and do best-effort filtering. - */ -static void -set_multicast_list(struct net_device *dev) -{ - short ioaddr = dev->base_addr; - if (dev->flags&IFF_PROMISC) - { - /* Enable promiscuous mode */ - outw(MULTICAST|PROMISC, ioaddr); - } - else if ((dev->flags&IFF_ALLMULTI) || - netdev_mc_count(dev) > HW_MAX_ADDRS) - { - /* Disable promiscuous mode, use normal mode. */ - hardware_set_filter(NULL); - - outw(MULTICAST, ioaddr); - } - else if (!netdev_mc_empty(dev)) - { - /* Walk the address list, and load the filter */ - hardware_set_filter(dev); - - outw(MULTICAST, ioaddr); - } - else - outw(0, ioaddr); -} - -#ifdef MODULE - -static struct net_device *this_device; -static int io = 0x300; -static int irq; -static int dma; -static int mem; -MODULE_LICENSE("GPL"); - -int init_module(void) -{ - struct net_device *dev; - int result; - - if (io == 0) - printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", - cardname); - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) - return -ENOMEM; - - /* Copy the parameters from insmod into the device structure. */ - dev->base_addr = io; - dev->irq = irq; - dev->dma = dma; - dev->mem_start = mem; - if (do_netcard_probe(dev) == 0) { - this_device = dev; - return 0; - } - free_netdev(dev); - return -ENXIO; -} - -void -cleanup_module(void) -{ - unregister_netdev(this_device); - cleanup_card(this_device); - free_netdev(this_device); -} - -#endif /* MODULE */ -- cgit v1.2.3 From a040d532b912b5dd7d88692b580cff9c88b987e3 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 23 Feb 2010 09:34:38 +0100 Subject: MAINTAINERS: update mwl8k maintenance status I am no longer with Marvell. Signed-off-by: Lennert Buytenhek Signed-off-by: John W. Linville --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2b4a4d2f2ece..cb0a8003b5b9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3450,9 +3450,9 @@ F: drivers/net/mv643xx_eth.* F: include/linux/mv643xx.h MARVELL MWL8K WIRELESS DRIVER -M: Lennert Buytenhek +M: Lennert Buytenhek L: linux-wireless@vger.kernel.org -S: Supported +S: Maintained F: drivers/net/wireless/mwl8k.c MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER -- cgit v1.2.3 From 7bfbae10dc10a5c94a780d117a57e875d77e8e5a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 24 Feb 2010 04:43:05 +0100 Subject: ath9k: disable RIFS search for AR91xx based chips While ath9k does not support RIFS yet, the ability to receive RIFS frames is currently enabled for most chipsets in the initvals. This is causing baseband related issues on AR9160 and AR9130 based chipsets, which can lock up under certain conditions. This patch fixes these issues by overriding the initvals, effectively disabling RIFS for all affected chipsets. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/phy.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f00f5c744f48..2e767cf22f1e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1310,6 +1310,16 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, * Necessary to avoid issues on AR5416 2.0 */ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); + + /* + * Disable RIFS search on some chips to avoid baseband + * hang issues. + */ + if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { + val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); + val &= ~AR_PHY_RIFS_INIT_DELAY; + REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); + } } static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 31de27dc0c4a..0999a495fd46 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -384,6 +384,9 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, #define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC +#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 + #define AR_PHY_M_SLEEP 0x99f0 #define AR_PHY_REFCLKDLY 0x99f4 #define AR_PHY_REFCLKPD 0x99f8 -- cgit v1.2.3 From b446918b77c717a34eaa853dfab55f579d330551 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 24 Feb 2010 14:19:37 +0100 Subject: mac80211: use listen interval 5 as default Currently if a driver does not set hw.max_listen_interval a listen interval of 1 is negotiated with the AP. Thus, the AP could drop buffered frames for us after just one beacon interval which can easily happen with the current powersave and scan implementation. To avoid this issue increase the default interval to 5 which should be a reasonable safe default. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ec8f767ba95b..06c33b68d8e5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -558,8 +558,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) debugfs_hw_add(local); + /* + * if the driver doesn't specify a max listen interval we + * use 5 which should be a safe default + */ if (local->hw.max_listen_interval == 0) - local->hw.max_listen_interval = 1; + local->hw.max_listen_interval = 5; local->hw.conf.listen_interval = local->hw.max_listen_interval; -- cgit v1.2.3 From caf66e581172dc5032bb84841a91bc7b77ad9876 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 25 Feb 2010 12:02:45 -0500 Subject: netdevice.h: check for CONFIG_WLAN instead of CONFIG_WLAN_80211 In "wireless: remove WLAN_80211 and WLAN_PRE80211 from Kconfig" I inadvertantly missed a line in include/linux/netdevice.h. I thereby effectively reverted "net: Set LL_MAX_HEADER properly for wireless." by accident. :-( Now we should check there for CONFIG_WLAN instead. Signed-off-by: John W. Linville Reported-by: Christoph Egger Cc: stable@kernel.org --- include/linux/netdevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a3fccc85b1a0..99914e6fa3fd 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -136,7 +136,7 @@ static inline bool dev_xmit_complete(int rc) * used. */ -#if defined(CONFIG_WLAN_80211) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +#if defined(CONFIG_WLAN) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else -- cgit v1.2.3 From 0e0a228398cc967c922759be36c69d32e4f62701 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 26 Feb 2010 08:13:41 +0200 Subject: mac80211: fix direct probe loop on ieee80211_work_purge If authentication has already been performed when the WLAN interface is stopped, (sometimes) the ieee80211_work_purge would corrupt some ieee80211_work-structures. The outcome is this (cleaned up): [ 2252.398681] WARNING: at net/mac80211/work.c:995 ieee80211_work_purge [ 2252.466430] Backtrace: [ 2252.529266] (ieee80211_work_purge+0x0/0xcc [mac80211]) [ 2252.546875] (ieee80211_stop+0x0/0x4c0 [mac80211]) Additionally, one would get this, going on regarless of the WLAN interface state, going on forever: [ 2252.859985] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717525) [ 2253.055419] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717524) [ 2253.250610] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717523) [ 2253.446014] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717522) [ 2253.641357] wlan0: direct probe to 00:90:4c:60:04:00 (try -996717521) Signed-off-by: Juuso Oikarinen Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/work.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 7e708d5c88b4..1e1ea3007b06 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -869,6 +869,7 @@ static void ieee80211_work_work(struct work_struct *work) break; case IEEE80211_WORK_ABORT: rma = WORK_ACT_TIMEOUT; + break; case IEEE80211_WORK_DIRECT_PROBE: rma = ieee80211_direct_probe(wk); break; -- cgit v1.2.3 From 9e3bd9190800e8209b4a3e1d724c35f0738dcad2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 26 Feb 2010 10:34:27 -0800 Subject: b43: fall back gracefully to PIO mode after fatal DMA errors This makes the b43 driver just automatically fall back to PIO mode when DMA doesn't work. The driver already told the user to do it, so rather than have the user reload the module with a new flag, just make the driver do it automatically. We keep the message as an indication that something is wrong, but now just automatically fall back to the hopefully working PIO case. (Some post-2.6.33 merge fixups by Larry Finger and yours truly... -- JWL) Signed-off-by: Linus Torvalds Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 17 ++++++++++++++++- drivers/net/wireless/b43/b43.h | 7 +++++++ drivers/net/wireless/b43/main.c | 14 ++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 073be566d05e..0a00d42642cd 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -3,7 +3,6 @@ config B43 depends on SSB_POSSIBLE && MAC80211 && HAS_DMA select SSB select FW_LOADER - select SSB_BLOCKIO ---help--- b43 is a driver for the Broadcom 43xx series wireless devices. @@ -79,6 +78,14 @@ config B43_SDIO If unsure, say N. +#Data transfers to the device via PIO. We want it as a fallback even +# if we can do DMA. +config B43_PIO + bool + depends on B43 + select SSB_BLOCKIO + default y + config B43_NPHY bool "Pre IEEE 802.11n support (BROKEN)" depends on B43 && EXPERIMENTAL && BROKEN @@ -130,4 +137,12 @@ config B43_DEBUG for production use. Only say Y, if you are debugging a problem in the b43 driver sourcecode. +config B43_FORCE_PIO + bool "Force usage of PIO instead of DMA" + depends on B43 && B43_DEBUG + ---help--- + This will disable DMA and always enable PIO instead. + Say N! + This is only for debugging the PIO engine code. You do + _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 6a6ab0f630e5..b8807fb12c92 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -702,6 +702,7 @@ struct b43_wldev { bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool qos_enabled; /* TRUE, if QoS is used. */ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ /* PHY/Radio device. */ struct b43_phy phy; @@ -886,6 +887,12 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev) return dev->__using_pio_transfers; } +#ifdef CONFIG_B43_FORCE_PIO +# define B43_PIO_DEFAULT 1 +#else +# define B43_PIO_DEFAULT 0 +#endif + /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8f7a8c0ec27d..16580d0d3a02 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -107,9 +107,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; module_param_named(verbose, b43_modparam_verbose, int, 0644); MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -static int modparam_pio; -module_param_named(pio, modparam_pio, int, 0444); -MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); +int b43_modparam_pio = B43_PIO_DEFAULT; +module_param_named(pio, b43_modparam_pio, int, 0644); +MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), @@ -1804,8 +1804,9 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) dma_reason[4], dma_reason[5]); b43err(dev->wl, "This device does not support DMA " "on your system. Please use PIO instead.\n"); - b43err(dev->wl, "Unload the b43 module and reload " - "with 'pio=1'\n"); + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = 1; + b43_controller_restart(dev, "DMA error"); return; } if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { @@ -4357,7 +4358,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - modparam_pio) { + dev->use_pio) { dev->__using_pio_transfers = 1; err = b43_pio_init(dev); } else { @@ -4824,6 +4825,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) if (!wldev) goto out; + wldev->use_pio = b43_modparam_pio; wldev->dev = dev; wldev->wl = wl; b43_set_status(wldev, B43_STAT_UNINIT); -- cgit v1.2.3 From fcb6a1c83e48c30ff99624e9c46ce301707ede05 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Fri, 26 Feb 2010 12:00:47 +0000 Subject: fs_enet: use dev_xxx instead of printk Signed-off-by: Anatolij Gustschin Acked-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 39 +++++++++++++++----------------------- drivers/net/fs_enet/mac-fcc.c | 5 +++-- drivers/net/fs_enet/mac-fec.c | 12 +++++------- drivers/net/fs_enet/mac-scc.c | 9 ++++----- 4 files changed, 27 insertions(+), 38 deletions(-) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index ec2f5034457f..c34a7e0a28ed 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -108,9 +108,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) * the last indicator should be set. */ if ((sc & BD_ENET_RX_LAST) == 0) - printk(KERN_WARNING DRV_MODULE_NAME - ": %s rcv is not +last\n", - dev->name); + dev_warn(fep->dev, "rcv is not +last\n"); /* * Check for errors. @@ -178,9 +176,8 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget) received++; netif_receive_skb(skb); } else { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s Memory squeeze, dropping packet.\n", - dev->name); + dev_warn(fep->dev, + "Memory squeeze, dropping packet.\n"); fep->stats.rx_dropped++; skbn = skb; } @@ -242,9 +239,7 @@ static int fs_enet_rx_non_napi(struct net_device *dev) * the last indicator should be set. */ if ((sc & BD_ENET_RX_LAST) == 0) - printk(KERN_WARNING DRV_MODULE_NAME - ": %s rcv is not +last\n", - dev->name); + dev_warn(fep->dev, "rcv is not +last\n"); /* * Check for errors. @@ -313,9 +308,8 @@ static int fs_enet_rx_non_napi(struct net_device *dev) received++; netif_rx(skb); } else { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s Memory squeeze, dropping packet.\n", - dev->name); + dev_warn(fep->dev, + "Memory squeeze, dropping packet.\n"); fep->stats.rx_dropped++; skbn = skb; } @@ -388,10 +382,10 @@ static void fs_enet_tx(struct net_device *dev) } else fep->stats.tx_packets++; - if (sc & BD_ENET_TX_READY) - printk(KERN_WARNING DRV_MODULE_NAME - ": %s HEY! Enet xmit interrupt and TX_READY.\n", - dev->name); + if (sc & BD_ENET_TX_READY) { + dev_warn(fep->dev, + "HEY! Enet xmit interrupt and TX_READY.\n"); + } /* * Deferred means some collisions occurred during transmit, @@ -511,9 +505,8 @@ void fs_init_bds(struct net_device *dev) for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) { skb = dev_alloc_skb(ENET_RX_FRSIZE); if (skb == NULL) { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s Memory squeeze, unable to allocate skb\n", - dev->name); + dev_warn(fep->dev, + "Memory squeeze, unable to allocate skb\n"); break; } skb_align(skb, ENET_RX_ALIGN); @@ -610,8 +603,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) * Ooops. All transmit buffers are full. Bail out. * This should not happen, since the tx queue should be stopped. */ - printk(KERN_WARNING DRV_MODULE_NAME - ": %s tx queue full!.\n", dev->name); + dev_warn(fep->dev, "tx queue full!.\n"); return NETDEV_TX_BUSY; } @@ -788,8 +780,7 @@ static int fs_enet_open(struct net_device *dev) r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, "fs_enet-mac", dev); if (r != 0) { - printk(KERN_ERR DRV_MODULE_NAME - ": %s Could not allocate FS_ENET IRQ!", dev->name); + dev_err(fep->dev, "Could not allocate FS_ENET IRQ!"); if (fep->fpi->use_napi) napi_disable(&fep->napi); return -EINVAL; @@ -1053,7 +1044,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, if (ret) goto out_free_bd; - printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); + pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); return 0; diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index a761d31e3d6d..cf4f674f9e2e 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c @@ -476,8 +476,9 @@ static void clear_int_events(struct net_device *dev, u32 int_events) static void ev_error(struct net_device *dev, u32 int_events) { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s FS_ENET ERROR(s) 0x%x\n", dev->name, int_events); + struct fs_enet_private *fep = netdev_priv(dev); + + dev_warn(fep->dev, "FS_ENET ERROR(s) 0x%x\n", int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index ca806d1ab3f6..8a632f668c1f 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -257,8 +257,7 @@ static void restart(struct net_device *dev) r = whack_reset(fep->fec.fecp); if (r != 0) - printk(KERN_ERR DRV_MODULE_NAME - ": %s FEC Reset FAILED!\n", dev->name); + dev_err(fep->dev, "FEC Reset FAILED!\n"); /* * Set station address. */ @@ -355,9 +354,7 @@ static void stop(struct net_device *dev) udelay(1); if (i == FEC_RESET_DELAY) - printk(KERN_WARNING DRV_MODULE_NAME - ": %s FEC timeout on graceful transmit stop\n", - dev->name); + dev_warn(fep->dev, "FEC timeout on graceful transmit stop\n"); /* * Disable FEC. Let only MII interrupts. */ @@ -433,8 +430,9 @@ static void clear_int_events(struct net_device *dev, u32 int_events) static void ev_error(struct net_device *dev, u32 int_events) { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s FEC ERROR(s) 0x%x\n", dev->name, int_events); + struct fs_enet_private *fep = netdev_priv(dev); + + dev_warn(fep->dev, "FEC ERROR(s) 0x%x\n", int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 5bfc99b9475e..c490a466cae1 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -367,9 +367,7 @@ static void stop(struct net_device *dev) udelay(1); if (i == SCC_RESET_DELAY) - printk(KERN_WARNING DRV_MODULE_NAME - ": %s SCC timeout on graceful transmit stop\n", - dev->name); + dev_warn(fep->dev, "SCC timeout on graceful transmit stop\n"); W16(sccp, scc_sccm, 0); C32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); @@ -429,8 +427,9 @@ static void clear_int_events(struct net_device *dev, u32 int_events) static void ev_error(struct net_device *dev, u32 int_events) { - printk(KERN_WARNING DRV_MODULE_NAME - ": %s SCC ERROR(s) 0x%x\n", dev->name, int_events); + struct fs_enet_private *fep = netdev_priv(dev); + + dev_warn(fep->dev, "SCC ERROR(s) 0x%x\n", int_events); } static int get_regs(struct net_device *dev, void *p, int *sizep) -- cgit v1.2.3 From 60ab4361adc188fb47da1c4892cc7a2bb621efef Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Fri, 26 Feb 2010 12:00:48 +0000 Subject: fs_enet: Add support for MPC512x to fs_enet driver Extend the fs_enet driver to support MPC512x FEC. Enable it with CONFIG_FS_ENET_MPC5121_FEC option. Signed-off-by: John Rigby Signed-off-by: Piotr Ziecik Signed-off-by: Wolfgang Denk Signed-off-by: Anatolij Gustschin Acked-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/fs_enet/Kconfig | 10 +++++--- drivers/net/fs_enet/fs_enet-main.c | 7 ++++++ drivers/net/fs_enet/fs_enet.h | 49 +++++++++++++++++++++++++++++++++++++- drivers/net/fs_enet/mac-fec.c | 46 +++++++++++++++++++++++------------ drivers/net/fs_enet/mii-fec.c | 4 ++-- 5 files changed, 95 insertions(+), 21 deletions(-) diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig index 562ea68ed99b..fc073b5a38c7 100644 --- a/drivers/net/fs_enet/Kconfig +++ b/drivers/net/fs_enet/Kconfig @@ -1,9 +1,13 @@ config FS_ENET tristate "Freescale Ethernet Driver" - depends on CPM1 || CPM2 + depends on CPM1 || CPM2 || PPC_MPC512x select MII select PHYLIB +config FS_ENET_MPC5121_FEC + def_bool y if (FS_ENET && PPC_MPC512x) + select FS_ENET_HAS_FEC + config FS_ENET_HAS_SCC bool "Chip has an SCC usable for ethernet" depends on FS_ENET && (CPM1 || CPM2) @@ -16,13 +20,13 @@ config FS_ENET_HAS_FCC config FS_ENET_HAS_FEC bool "Chip has an FEC usable for ethernet" - depends on FS_ENET && CPM1 + depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) select FS_ENET_MDIO_FEC default y config FS_ENET_MDIO_FEC tristate "MDIO driver for FEC" - depends on FS_ENET && CPM1 + depends on FS_ENET && (CPM1 || FS_ENET_MPC5121_FEC) config FS_ENET_MDIO_FCC tristate "MDIO driver for FCC" diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index c34a7e0a28ed..4297021214d1 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -1094,10 +1094,17 @@ static struct of_device_id fs_enet_match[] = { }, #endif #ifdef CONFIG_FS_ENET_HAS_FEC +#ifdef CONFIG_FS_ENET_MPC5121_FEC + { + .compatible = "fsl,mpc5121-fec", + .data = (void *)&fs_fec_ops, + }, +#else { .compatible = "fsl,pq1-fec-enet", .data = (void *)&fs_fec_ops, }, +#endif #endif {} }; diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index ef01e09781a5..1ece4b1a689e 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -13,9 +13,56 @@ #ifdef CONFIG_CPM1 #include +#endif + +#if defined(CONFIG_FS_ENET_HAS_FEC) +#include + +#if defined(CONFIG_FS_ENET_MPC5121_FEC) +/* MPC5121 FEC has different register layout */ +struct fec { + u32 fec_reserved0; + u32 fec_ievent; /* Interrupt event reg */ + u32 fec_imask; /* Interrupt mask reg */ + u32 fec_reserved1; + u32 fec_r_des_active; /* Receive descriptor reg */ + u32 fec_x_des_active; /* Transmit descriptor reg */ + u32 fec_reserved2[3]; + u32 fec_ecntrl; /* Ethernet control reg */ + u32 fec_reserved3[6]; + u32 fec_mii_data; /* MII manage frame reg */ + u32 fec_mii_speed; /* MII speed control reg */ + u32 fec_reserved4[7]; + u32 fec_mib_ctrlstat; /* MIB control/status reg */ + u32 fec_reserved5[7]; + u32 fec_r_cntrl; /* Receive control reg */ + u32 fec_reserved6[15]; + u32 fec_x_cntrl; /* Transmit Control reg */ + u32 fec_reserved7[7]; + u32 fec_addr_low; /* Low 32bits MAC address */ + u32 fec_addr_high; /* High 16bits MAC address */ + u32 fec_opd; /* Opcode + Pause duration */ + u32 fec_reserved8[10]; + u32 fec_hash_table_high; /* High 32bits hash table */ + u32 fec_hash_table_low; /* Low 32bits hash table */ + u32 fec_grp_hash_table_high; /* High 32bits hash table */ + u32 fec_grp_hash_table_low; /* Low 32bits hash table */ + u32 fec_reserved9[7]; + u32 fec_x_wmrk; /* FIFO transmit water mark */ + u32 fec_reserved10; + u32 fec_r_bound; /* FIFO receive bound reg */ + u32 fec_r_fstart; /* FIFO receive start reg */ + u32 fec_reserved11[11]; + u32 fec_r_des_start; /* Receive descriptor ring */ + u32 fec_x_des_start; /* Transmit descriptor ring */ + u32 fec_r_buff_size; /* Maximum receive buff size */ + u32 fec_reserved12[26]; + u32 fec_dma_control; /* DMA Endian and other ctrl */ +}; +#endif struct fec_info { - fec_t __iomem *fecp; + struct fec __iomem *fecp; u32 mii_speed; }; #endif diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index 8a632f668c1f..cd2c6cca5f24 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c @@ -80,7 +80,7 @@ */ #define FEC_RESET_DELAY 50 -static int whack_reset(fec_t __iomem *fecp) +static int whack_reset(struct fec __iomem *fecp) { int i; @@ -168,7 +168,7 @@ static void cleanup_data(struct net_device *dev) static void set_promiscuous_mode(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FS(fecp, r_cntrl, FEC_RCNTRL_PROM); } @@ -216,7 +216,7 @@ static void set_multicast_one(struct net_device *dev, const u8 *mac) static void set_multicast_finish(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; /* if all multi or too many multicasts; just enable all */ if ((dev->flags & IFF_ALLMULTI) != 0 || @@ -246,7 +246,7 @@ static void set_multicast_list(struct net_device *dev) static void restart(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; const struct fs_platform_info *fpi = fep->fpi; dma_addr_t rx_bd_base_phys, tx_bd_base_phys; int r; @@ -280,7 +280,11 @@ static void restart(struct net_device *dev) * Set maximum receive buffer size. */ FW(fecp, r_buff_size, PKT_MAXBLR_SIZE); +#ifdef CONFIG_FS_ENET_MPC5121_FEC + FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16); +#else FW(fecp, r_hash, PKT_MAXBUF_SIZE); +#endif /* get physical address */ rx_bd_base_phys = fep->ring_mem_addr; @@ -297,7 +301,11 @@ static void restart(struct net_device *dev) /* * Enable big endian and don't care about SDMA FC. */ +#ifdef CONFIG_FS_ENET_MPC5121_FEC + FS(fecp, dma_control, 0xC0000000); +#else FW(fecp, fun_code, 0x78000000); +#endif /* * Set MII speed. @@ -308,9 +316,17 @@ static void restart(struct net_device *dev) * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); +#ifndef CONFIG_FS_ENET_MPC5121_FEC FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29); FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ +#else + /* + * Only set MII mode - do not touch maximum frame length + * configured before. + */ + FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); +#endif /* * adjust to duplex mode */ @@ -339,7 +355,7 @@ static void stop(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); const struct fs_platform_info *fpi = fep->fpi; - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; struct fec_info* feci= fep->phydev->bus->priv; @@ -375,7 +391,7 @@ static void stop(struct net_device *dev) static void napi_clear_rx_event(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); } @@ -383,7 +399,7 @@ static void napi_clear_rx_event(struct net_device *dev) static void napi_enable_rx(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); } @@ -391,7 +407,7 @@ static void napi_enable_rx(struct net_device *dev) static void napi_disable_rx(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); } @@ -399,7 +415,7 @@ static void napi_disable_rx(struct net_device *dev) static void rx_bd_done(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FW(fecp, r_des_active, 0x01000000); } @@ -407,7 +423,7 @@ static void rx_bd_done(struct net_device *dev) static void tx_kickstart(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FW(fecp, x_des_active, 0x01000000); } @@ -415,7 +431,7 @@ static void tx_kickstart(struct net_device *dev) static u32 get_int_events(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; return FR(fecp, ievent) & FR(fecp, imask); } @@ -423,7 +439,7 @@ static u32 get_int_events(struct net_device *dev) static void clear_int_events(struct net_device *dev, u32 int_events) { struct fs_enet_private *fep = netdev_priv(dev); - fec_t __iomem *fecp = fep->fec.fecp; + struct fec __iomem *fecp = fep->fec.fecp; FW(fecp, ievent, int_events); } @@ -439,17 +455,17 @@ static int get_regs(struct net_device *dev, void *p, int *sizep) { struct fs_enet_private *fep = netdev_priv(dev); - if (*sizep < sizeof(fec_t)) + if (*sizep < sizeof(struct fec)) return -EINVAL; - memcpy_fromio(p, fep->fec.fecp, sizeof(fec_t)); + memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec)); return 0; } static int get_regs_len(struct net_device *dev) { - return sizeof(fec_t); + return sizeof(struct fec); } static void tx_restart(struct net_device *dev) diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 96eba4280c5c..5944b65082cb 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c @@ -52,7 +52,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) { struct fec_info* fec = bus->priv; - fec_t __iomem *fecp = fec->fecp; + struct fec __iomem *fecp = fec->fecp; int i, ret = -1; BUG_ON((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0); @@ -75,7 +75,7 @@ static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) { struct fec_info* fec = bus->priv; - fec_t __iomem *fecp = fec->fecp; + struct fec __iomem *fecp = fec->fecp; int i; /* this must never happen */ -- cgit v1.2.3 From cb395eaf439625f26c8527bb05bb905774a54c36 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Fri, 26 Feb 2010 12:00:49 +0000 Subject: fs_enet: add FEC TX buffer alignment workaround for MPC5121 MPC5121 FEC requeries 4-byte alignmnent for TX data buffers. This patch is a work around that copies misaligned tx packets to an aligned skb before sending. Signed-off-by: John Rigby Signed-off-by: Piotr Ziecik Signed-off-by: Wolfgang Denk Signed-off-by: Anatolij Gustschin Acked-by: Grant Likely Signed-off-by: David S. Miller --- drivers/net/fs_enet/fs_enet-main.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 4297021214d1..0770e2f6da6b 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -580,6 +580,40 @@ void fs_cleanup_bds(struct net_device *dev) /**********************************************************************************/ +#ifdef CONFIG_FS_ENET_MPC5121_FEC +/* + * MPC5121 FEC requeries 4-byte alignment for TX data buffer! + */ +static struct sk_buff *tx_skb_align_workaround(struct net_device *dev, + struct sk_buff *skb) +{ + struct sk_buff *new_skb; + struct fs_enet_private *fep = netdev_priv(dev); + + /* Alloc new skb */ + new_skb = dev_alloc_skb(skb->len + 4); + if (!new_skb) { + if (net_ratelimit()) { + dev_warn(fep->dev, + "Memory squeeze, dropping tx packet.\n"); + } + return NULL; + } + + /* Make sure new skb is properly aligned */ + skb_align(new_skb, 4); + + /* Copy data to new skb ... */ + skb_copy_from_linear_data(skb, new_skb->data, skb->len); + skb_put(new_skb, skb->len); + + /* ... and free an old one */ + dev_kfree_skb_any(skb); + + return new_skb; +} +#endif + static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -588,6 +622,19 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) u16 sc; unsigned long flags; +#ifdef CONFIG_FS_ENET_MPC5121_FEC + if (((unsigned long)skb->data) & 0x3) { + skb = tx_skb_align_workaround(dev, skb); + if (!skb) { + /* + * We have lost packet due to memory allocation error + * in tx_skb_align_workaround(). Hopefully original + * skb is still valid, so try transmit it later. + */ + return NETDEV_TX_BUSY; + } + } +#endif spin_lock_irqsave(&fep->tx_lock, flags); /* -- cgit v1.2.3 From 10de05afe01c12cedc42eb9ce05b111eed6c8210 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 26 Feb 2010 06:34:50 +0000 Subject: rtnetlink: ignore NETDEV_PRE_UP notifier in rtnetlink_event() Commit 3b8bcfd (net: introduce pre-up netdev notifier) added a new notifier which is run before a device is set UP for use by cfg80211. The patch missed to add the new notifier to the ignore list in rtnetlink_event(), so we currently get an unnecessary netlink notification before a device is set UP. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4dd4c3cdc442..b7c7dfd86507 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1432,6 +1432,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi case NETDEV_DOWN: rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); break; + case NETDEV_PRE_UP: case NETDEV_POST_INIT: case NETDEV_REGISTER: case NETDEV_CHANGE: -- cgit v1.2.3 From a2835763e130c343ace5320c20d33c281e7097b7 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 26 Feb 2010 06:34:51 +0000 Subject: rtnetlink: handle rtnl_link netlink notifications manually In order to support specifying device flags during device creation, we must be able to roll back device registration in case setting the flags fails without sending any notifications related to the device to userspace. This patch changes rollback_registered_many() and register_netdevice() to manually send netlink notifications for devices not handled by rtnl_link and allows to defer notifications for devices handled by rtnl_link until setup is complete. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netdevice.h | 7 ++++++- net/core/dev.c | 8 +++++++- net/core/rtnetlink.c | 4 +--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7a2aea56f195..1bfda90c2625 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -924,7 +924,12 @@ struct net_device { NETREG_UNREGISTERED, /* completed unregister todo */ NETREG_RELEASED, /* called free_netdev */ NETREG_DUMMY, /* dummy device for NAPI poll */ - } reg_state; + } reg_state:16; + + enum { + RTNL_LINK_INITIALIZED, + RTNL_LINK_INITIALIZING, + } rtnl_link_state:16; /* Called from unregister, can be used to call free_netdev */ void (*destructor)(struct net_device *dev); diff --git a/net/core/dev.c b/net/core/dev.c index eb7f1a4fefc6..75332b089529 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4865,6 +4865,10 @@ static void rollback_registered_many(struct list_head *head) */ call_netdevice_notifiers(NETDEV_UNREGISTER, dev); + if (!dev->rtnl_link_ops || + dev->rtnl_link_state == RTNL_LINK_INITIALIZED) + rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); + /* * Flush the unicast and multicast chains */ @@ -5091,7 +5095,9 @@ int register_netdevice(struct net_device *dev) * Prevent userspace races by waiting until the network * device is fully setup before sending notifications. */ - rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); + if (!dev->rtnl_link_ops || + dev->rtnl_link_state == RTNL_LINK_INITIALIZED) + rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); out: return ret; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b7c7dfd86507..020e43bfef5f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1425,9 +1425,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi struct net_device *dev = ptr; switch (event) { - case NETDEV_UNREGISTER: - rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); - break; case NETDEV_UP: case NETDEV_DOWN: rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); @@ -1437,6 +1434,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi case NETDEV_REGISTER: case NETDEV_CHANGE: case NETDEV_GOING_DOWN: + case NETDEV_UNREGISTER: case NETDEV_UNREGISTER_BATCH: break; default: -- cgit v1.2.3 From bd38081160bb3d036db98472e537b6a7dd4da51a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 26 Feb 2010 06:34:53 +0000 Subject: dev: support deferring device flag change notifications Split dev_change_flags() into two functions: __dev_change_flags() to perform the actual changes and __dev_notify_flags() to invoke netdevice notifiers. This will be used by rtnl_link to defer netlink notifications until the device has been fully configured. This changes ordering of some operations, in particular: - netlink notifications are sent after all changes have been performed. As a side effect this surpresses one unnecessary netlink message when the IFF_UP and other flags are changed simultaneously. - The NETDEV_UP/NETDEV_DOWN and NETDEV_CHANGE notifiers are invoked after all changes have been performed. Their relative is unchanged. - net_dmaengine_put() is invoked before the NETDEV_DOWN notifier instead of afterwards. This should not make any difference since both RX and TX are already shut down at this point. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 + net/core/dev.c | 163 +++++++++++++++++++++++++++++----------------- net/core/rtnetlink.c | 2 - 3 files changed, 106 insertions(+), 61 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 1bfda90c2625..c79a88be7c33 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1587,7 +1587,9 @@ extern int dev_valid_name(const char *name); extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); extern int dev_ethtool(struct net *net, struct ifreq *); extern unsigned dev_get_flags(const struct net_device *); +extern int __dev_change_flags(struct net_device *, unsigned int flags); extern int dev_change_flags(struct net_device *, unsigned); +extern void __dev_notify_flags(struct net_device *, unsigned int old_flags); extern int dev_change_name(struct net_device *, const char *); extern int dev_set_alias(struct net_device *, const char *, size_t); extern int dev_change_net_namespace(struct net_device *, diff --git a/net/core/dev.c b/net/core/dev.c index 75332b089529..e5972f7f7e1b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1113,32 +1113,13 @@ void dev_load(struct net *net, const char *name) } EXPORT_SYMBOL(dev_load); -/** - * dev_open - prepare an interface for use. - * @dev: device to open - * - * Takes a device from down to up state. The device's private open - * function is invoked and then the multicast lists are loaded. Finally - * the device is moved into the up state and a %NETDEV_UP message is - * sent to the netdev notifier chain. - * - * Calling this function on an active interface is a nop. On a failure - * a negative errno code is returned. - */ -int dev_open(struct net_device *dev) +static int __dev_open(struct net_device *dev) { const struct net_device_ops *ops = dev->netdev_ops; int ret; ASSERT_RTNL(); - /* - * Is it already up? - */ - - if (dev->flags & IFF_UP) - return 0; - /* * Is it even present? */ @@ -1187,36 +1168,57 @@ int dev_open(struct net_device *dev) * Wakeup transmit queue engine */ dev_activate(dev); - - /* - * ... and announce new interface. - */ - call_netdevice_notifiers(NETDEV_UP, dev); } return ret; } -EXPORT_SYMBOL(dev_open); /** - * dev_close - shutdown an interface. - * @dev: device to shutdown + * dev_open - prepare an interface for use. + * @dev: device to open * - * This function moves an active device into down state. A - * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device - * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier - * chain. + * Takes a device from down to up state. The device's private open + * function is invoked and then the multicast lists are loaded. Finally + * the device is moved into the up state and a %NETDEV_UP message is + * sent to the netdev notifier chain. + * + * Calling this function on an active interface is a nop. On a failure + * a negative errno code is returned. */ -int dev_close(struct net_device *dev) +int dev_open(struct net_device *dev) +{ + int ret; + + /* + * Is it already up? + */ + if (dev->flags & IFF_UP) + return 0; + + /* + * Open device + */ + ret = __dev_open(dev); + if (ret < 0) + return ret; + + /* + * ... and announce new interface. + */ + rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); + call_netdevice_notifiers(NETDEV_UP, dev); + + return ret; +} +EXPORT_SYMBOL(dev_open); + +static int __dev_close(struct net_device *dev) { const struct net_device_ops *ops = dev->netdev_ops; - ASSERT_RTNL(); + ASSERT_RTNL(); might_sleep(); - if (!(dev->flags & IFF_UP)) - return 0; - /* * Tell people we are going down, so that they can * prepare to death, when device is still operating. @@ -1252,14 +1254,34 @@ int dev_close(struct net_device *dev) dev->flags &= ~IFF_UP; /* - * Tell people we are down + * Shutdown NET_DMA */ - call_netdevice_notifiers(NETDEV_DOWN, dev); + net_dmaengine_put(); + + return 0; +} + +/** + * dev_close - shutdown an interface. + * @dev: device to shutdown + * + * This function moves an active device into down state. A + * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device + * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier + * chain. + */ +int dev_close(struct net_device *dev) +{ + if (!(dev->flags & IFF_UP)) + return 0; + + __dev_close(dev); /* - * Shutdown NET_DMA + * Tell people we are down */ - net_dmaengine_put(); + rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); + call_netdevice_notifiers(NETDEV_DOWN, dev); return 0; } @@ -4299,18 +4321,10 @@ unsigned dev_get_flags(const struct net_device *dev) } EXPORT_SYMBOL(dev_get_flags); -/** - * dev_change_flags - change device settings - * @dev: device - * @flags: device state flags - * - * Change settings on device based state flags. The flags are - * in the userspace exported format. - */ -int dev_change_flags(struct net_device *dev, unsigned flags) +int __dev_change_flags(struct net_device *dev, unsigned int flags) { - int ret, changes; int old_flags = dev->flags; + int ret; ASSERT_RTNL(); @@ -4341,17 +4355,12 @@ int dev_change_flags(struct net_device *dev, unsigned flags) ret = 0; if ((old_flags ^ flags) & IFF_UP) { /* Bit is different ? */ - ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev); + ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); if (!ret) dev_set_rx_mode(dev); } - if (dev->flags & IFF_UP && - ((old_flags ^ dev->flags) & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | - IFF_VOLATILE))) - call_netdevice_notifiers(NETDEV_CHANGE, dev); - if ((flags ^ dev->gflags) & IFF_PROMISC) { int inc = (flags & IFF_PROMISC) ? 1 : -1; @@ -4370,11 +4379,47 @@ int dev_change_flags(struct net_device *dev, unsigned flags) dev_set_allmulti(dev, inc); } - /* Exclude state transition flags, already notified */ - changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING); + return ret; +} + +void __dev_notify_flags(struct net_device *dev, unsigned int old_flags) +{ + unsigned int changes = dev->flags ^ old_flags; + + if (changes & IFF_UP) { + if (dev->flags & IFF_UP) + call_netdevice_notifiers(NETDEV_UP, dev); + else + call_netdevice_notifiers(NETDEV_DOWN, dev); + } + + if (dev->flags & IFF_UP && + (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) + call_netdevice_notifiers(NETDEV_CHANGE, dev); +} + +/** + * dev_change_flags - change device settings + * @dev: device + * @flags: device state flags + * + * Change settings on device based state flags. The flags are + * in the userspace exported format. + */ +int dev_change_flags(struct net_device *dev, unsigned flags) +{ + int ret, changes; + int old_flags = dev->flags; + + ret = __dev_change_flags(dev, flags); + if (ret < 0) + return ret; + + changes = old_flags ^ dev->flags; if (changes) rtmsg_ifinfo(RTM_NEWLINK, dev, changes); + __dev_notify_flags(dev, old_flags); return ret; } EXPORT_SYMBOL(dev_change_flags); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 020e43bfef5f..c21ec4236dd0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1427,8 +1427,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi switch (event) { case NETDEV_UP: case NETDEV_DOWN: - rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); - break; case NETDEV_PRE_UP: case NETDEV_POST_INIT: case NETDEV_REGISTER: -- cgit v1.2.3 From 3729d5021257b283f7fce33d957893162ccb2c9d Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 26 Feb 2010 06:34:54 +0000 Subject: rtnetlink: support specifying device flags on device creation commit e8469ed959c373c2ff9e6f488aa5a14971aebe1f Author: Patrick McHardy Date: Tue Feb 23 20:41:30 2010 +0100 Support specifying the initial device flags when creating a device though rtnl_link. Devices allocated by rtnl_create_link() are marked as INITIALIZING in order to surpress netlink registration notifications. To complete setup, rtnl_configure_link() must be called, which performs the device flag changes and invokes the deferred notifiers if everything went well. Two examples: # add macvlan to eth0 # $ ip link add link eth0 up allmulticast on type macvlan [LINK]11: macvlan0@eth0: mtu 1500 qdisc noqueue state UNKNOWN link/ether 26:f8:84:02:f9:2a brd ff:ff:ff:ff:ff:ff [ROUTE]ff00::/8 dev macvlan0 table local metric 256 mtu 1500 advmss 1440 hoplimit 0 [ROUTE]fe80::/64 dev macvlan0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0 [LINK]11: macvlan0@eth0: mtu 1500 link/ether 26:f8:84:02:f9:2a [ADDR]11: macvlan0 inet6 fe80::24f8:84ff:fe02:f92a/64 scope link valid_lft forever preferred_lft forever [ROUTE]local fe80::24f8:84ff:fe02:f92a via :: dev lo table local proto none metric 0 mtu 16436 advmss 16376 hoplimit 0 [ROUTE]default via fe80::215:e9ff:fef0:10f8 dev macvlan0 proto kernel metric 1024 mtu 1500 advmss 1440 hoplimit 0 [NEIGH]fe80::215:e9ff:fef0:10f8 dev macvlan0 lladdr 00:15:e9:f0:10:f8 router STALE [ROUTE]2001:6f8:974::/64 dev macvlan0 proto kernel metric 256 expires 0sec mtu 1500 advmss 1440 hoplimit 0 [PREFIX]prefix 2001:6f8:974::/64 dev macvlan0 onlink autoconf valid 14400 preferred 131084 [ADDR]11: macvlan0 inet6 2001:6f8:974:0:24f8:84ff:fe02:f92a/64 scope global dynamic valid_lft 86399sec preferred_lft 14399sec # add VLAN to eth1, eth1 is down # $ ip link add link eth1 up type vlan id 1000 RTNETLINK answers: Network is down Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/veth.c | 15 +++++++++----- include/net/rtnetlink.h | 2 ++ net/core/rtnetlink.c | 52 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 35609e64f6fd..b583d4968add 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -333,19 +333,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, struct veth_priv *priv; char ifname[IFNAMSIZ]; struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; + struct ifinfomsg *ifmp; struct net *net; /* * create and register peer first - * - * struct ifinfomsg is at the head of VETH_INFO_PEER, but we - * skip it since no info from it is useful yet */ - if (data != NULL && data[VETH_INFO_PEER] != NULL) { struct nlattr *nla_peer; nla_peer = data[VETH_INFO_PEER]; + ifmp = nla_data(nla_peer); err = nla_parse(peer_tb, IFLA_MAX, nla_data(nla_peer) + sizeof(struct ifinfomsg), nla_len(nla_peer) - sizeof(struct ifinfomsg), @@ -358,8 +356,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, return err; tbp = peer_tb; - } else + } else { + ifmp = NULL; tbp = tb; + } if (tbp[IFLA_IFNAME]) nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ); @@ -387,6 +387,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, netif_carrier_off(peer); + err = rtnl_configure_link(peer, ifmp); + if (err < 0) + goto err_configure_peer; + /* * register dev last * @@ -428,6 +432,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, err_register_dev: /* nothing to do */ err_alloc_name: +err_configure_peer: unregister_netdevice(peer); return err; diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 48d3efcb0880..af60fd050844 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -87,6 +87,8 @@ extern void rtnl_link_unregister(struct rtnl_link_ops *ops); extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]); extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net, char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]); +extern int rtnl_configure_link(struct net_device *dev, + const struct ifinfomsg *ifm); extern const struct nla_policy ifla_policy[IFLA_MAX+1]; #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c21ec4236dd0..d1472a423323 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -549,6 +549,19 @@ static void set_operstate(struct net_device *dev, unsigned char transition) } } +static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, + const struct ifinfomsg *ifm) +{ + unsigned int flags = ifm->ifi_flags; + + /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ + if (ifm->ifi_change) + flags = (flags & ifm->ifi_change) | + (dev->flags & ~ifm->ifi_change); + + return flags; +} + static void copy_rtnl_link_stats(struct rtnl_link_stats *a, const struct net_device_stats *b) { @@ -904,13 +917,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, } if (ifm->ifi_flags || ifm->ifi_change) { - unsigned int flags = ifm->ifi_flags; - - /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ - if (ifm->ifi_change) - flags = (flags & ifm->ifi_change) | - (dev->flags & ~ifm->ifi_change); - err = dev_change_flags(dev, flags); + err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); if (err < 0) goto errout; } @@ -1053,6 +1060,26 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return 0; } +int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) +{ + unsigned int old_flags; + int err; + + old_flags = dev->flags; + if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { + err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); + if (err < 0) + return err; + } + + dev->rtnl_link_state = RTNL_LINK_INITIALIZED; + rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); + + __dev_notify_flags(dev, old_flags); + return 0; +} +EXPORT_SYMBOL(rtnl_configure_link); + struct net_device *rtnl_create_link(struct net *src_net, struct net *net, char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) { @@ -1074,6 +1101,7 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, dev_net_set(dev, net); dev->rtnl_link_ops = ops; + dev->rtnl_link_state = RTNL_LINK_INITIALIZING; dev->real_num_tx_queues = real_num_queues; if (strchr(dev->name, '%')) { @@ -1203,7 +1231,7 @@ replay: if (!(nlh->nlmsg_flags & NLM_F_CREATE)) return -ENODEV; - if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) + if (ifm->ifi_index) return -EOPNOTSUPP; if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) return -EOPNOTSUPP; @@ -1234,9 +1262,15 @@ replay: err = ops->newlink(net, dev, tb, data); else err = register_netdevice(dev); - if (err < 0 && !IS_ERR(dev)) + if (err < 0 && !IS_ERR(dev)) { free_netdev(dev); + goto out; + } + err = rtnl_configure_link(dev, ifm); + if (err < 0) + unregister_netdevice(dev); +out: put_net(dest_net); return err; } -- cgit v1.2.3 From 8d6184e4881b423522136aeb3ec1cbd9c35e8813 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 27 Feb 2010 02:52:05 -0800 Subject: bonding: fix device leak on error in bond_create() When the register_netdevice() call fails, the newly allocated device is not freed. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 1787e3c86573..430c02267d7e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4946,6 +4946,8 @@ int bond_create(struct net *net, const char *name) } res = register_netdevice(bond_dev); + if (res < 0) + goto out_netdev; out: rtnl_unlock(); -- cgit v1.2.3 From da3f5cf1f8ebb0fab5c5fd09adb189166594ad6c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 23 Feb 2010 11:45:51 +0000 Subject: skbuff: align sk_buff::cb to 64 bit and close some potential holes The alignment requirement for 64-bit load/store instructions on ARM is implementation defined. Some CPUs (such as Marvell Feroceon) do not generate an exception, if such an instruction is executed with an address that is not 64 bit aligned. In such a case, the Feroceon corrupts adjacent memory, which showed up in my tests as a crash in the rx path of ath9k that only occured with CONFIG_XFRM set. This crash happened, because the first field of the mac80211 rx status info in the cb is an u64, and changing it corrupted the skb->sp field. This patch also closes some potential pre-existing holes in the sk_buff struct surrounding the cb[] area. Signed-off-by: Felix Fietkau Cc: stable@kernel.org Signed-off-by: David S. Miller --- include/linux/skbuff.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ba0f8e3a9cda..d266eeef522d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -315,22 +315,23 @@ struct sk_buff { struct sk_buff *next; struct sk_buff *prev; - struct sock *sk; ktime_t tstamp; + + struct sock *sk; struct net_device *dev; - unsigned long _skb_dst; -#ifdef CONFIG_XFRM - struct sec_path *sp; -#endif /* * This is the control buffer. It is free to use for every * layer. Please put your private variables there. If you * want to keep them across layers you have to do a skb_clone() * first. This is owned by whoever has the skb queued ATM. */ - char cb[48]; + char cb[48] __aligned(8); + unsigned long _skb_dst; +#ifdef CONFIG_XFRM + struct sec_path *sp; +#endif unsigned int len, data_len; __u16 mac_len, -- cgit v1.2.3 From 2ea186ae533c7b4f4c56811b69d3e40a6209a9c0 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Sat, 27 Feb 2010 03:28:24 -0800 Subject: ixgbe: move TC_PRIO_CONTROL check into ixgbe_select_queue() Move TC_PRIO_CONTROL check and queue remapping into ixgbe_select_queue(). Remapping queues after the qdisc can result in the wrong qdisc queue being stopped with netif_stop_subqueue(). Even if this is resolved and the correct queue is stopped it can result in a queue being blocked by TC_PRIO_CONTROL frames uneccesarily. Moving this into the select_queue routine maintains alignment between tx_rings and qdisc queues. Signed-off-by: John Fastabend Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a961da2f98c0..45e3532b166f 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5639,8 +5639,14 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb) return txq; } #endif - if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) - return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13; + if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { + if (skb->priority == TC_PRIO_CONTROL) + txq = adapter->ring_feature[RING_F_DCB].indices-1; + else + txq = (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) + >> 13; + return txq; + } return skb_tx_hash(dev, skb); } @@ -5667,14 +5673,9 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb, tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; tx_flags |= IXGBE_TX_FLAGS_VLAN; } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { - if (skb->priority != TC_PRIO_CONTROL) { - tx_flags |= ((skb->queue_mapping & 0x7) << 13); - tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; - tx_flags |= IXGBE_TX_FLAGS_VLAN; - } else { - skb->queue_mapping = - adapter->ring_feature[RING_F_DCB].indices-1; - } + tx_flags |= ((skb->queue_mapping & 0x7) << 13); + tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; + tx_flags |= IXGBE_TX_FLAGS_VLAN; } tx_ring = adapter->tx_ring[skb->queue_mapping]; -- cgit v1.2.3 From 8e5b2308489dbca27c104fc6a557d4c9348552e5 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 22 Dec 2009 09:34:20 +0100 Subject: Bluetooth: Add __init/__exit macros to Marvell SDIO driver Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of btmrvl_sdio.c driver. Signed-off-by: Peter Huewe Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 57d965b7f521..94f1f55f81f0 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -976,7 +976,7 @@ static struct sdio_driver bt_mrvl_sdio = { .remove = btmrvl_sdio_remove, }; -static int btmrvl_sdio_init_module(void) +static int __init btmrvl_sdio_init_module(void) { if (sdio_register_driver(&bt_mrvl_sdio) != 0) { BT_ERR("SDIO Driver Registration Failed"); @@ -989,7 +989,7 @@ static int btmrvl_sdio_init_module(void) return 0; } -static void btmrvl_sdio_exit_module(void) +static void __exit btmrvl_sdio_exit_module(void) { /* Set the flag as user is removing this module. */ user_rmmod = 1; -- cgit v1.2.3 From 8978111e2d148f75bd5e329a14600feadc567381 Mon Sep 17 00:00:00 2001 From: Márton Németh Date: Sun, 10 Jan 2010 13:39:15 +0100 Subject: Bluetooth: Make USB device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct usb_device_id is constant in so it is worth to make bcm203x_table also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bcm203x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index eafd4af0746e..b0c84c19f442 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -39,7 +39,7 @@ #define VERSION "1.2" -static struct usb_device_id bcm203x_table[] = { +static const struct usb_device_id bcm203x_table[] = { /* Broadcom Blutonium (BCM2033) */ { USB_DEVICE(0x0a5c, 0x2033) }, -- cgit v1.2.3 From 10f7891f998e84acfa31ac9c5a0fea052c39ecb8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 Feb 2010 08:43:17 +0300 Subject: Bluetooth: Add missing kfree() on error path in Atheros driver Add a couple kfree() calls on an error path. Signed-off-by: Dan Carpenter Signed-off-by: Marcel Holtmann --- drivers/bluetooth/ath3k.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index add9485ca5b6..128cae4e8629 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -143,6 +143,8 @@ static int ath3k_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { usb_set_intfdata(intf, NULL); + kfree(data->fw_data); + kfree(data); return -EIO; } -- cgit v1.2.3 From c13854cef4751000b968d4e8ac95796562d5b96f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 8 Feb 2010 15:27:07 +0100 Subject: Bluetooth: Convert controller hdev->type to hdev->bus The hdev->type is misnamed and should be actually hdev->bus instead. So convert it now. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bfusb.c | 2 +- drivers/bluetooth/bluecard_cs.c | 2 +- drivers/bluetooth/bpa10x.c | 2 +- drivers/bluetooth/bt3c_cs.c | 2 +- drivers/bluetooth/btmrvl_main.c | 2 +- drivers/bluetooth/btsdio.c | 2 +- drivers/bluetooth/btuart_cs.c | 2 +- drivers/bluetooth/btusb.c | 2 +- drivers/bluetooth/dtl1_cs.c | 2 +- drivers/bluetooth/hci_ldisc.c | 2 +- drivers/bluetooth/hci_vhci.c | 2 +- include/net/bluetooth/hci.h | 2 +- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 8 ++++---- net/bluetooth/hci_sysfs.c | 16 ++++++++-------- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 2a00707aba3b..005919ab043c 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -703,7 +703,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i data->hdev = hdev; - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; SET_HCIDEV_DEV(hdev, &intf->dev); diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index c2cf81144715..d9bf87ca9e83 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -736,7 +736,7 @@ static int bluecard_open(bluecard_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index c115285867c3..d945cd12433a 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -469,7 +469,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * return -ENOMEM; } - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 9f5926aaf57f..027cb8bf650f 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -582,7 +582,7 @@ static int bt3c_open(bt3c_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index f97771ce432c..53a43adf2e21 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -563,7 +563,7 @@ struct btmrvl_private *btmrvl_add_card(void *card) priv->btmrvl_dev.tx_dnld_rdy = true; - hdev->type = HCI_SDIO; + hdev->bus = HCI_SDIO; hdev->open = btmrvl_open; hdev->close = btmrvl_close; hdev->flush = btmrvl_flush; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 7e298275c8f6..76e5127884f0 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -326,7 +326,7 @@ static int btsdio_probe(struct sdio_func *func, return -ENOMEM; } - hdev->type = HCI_SDIO; + hdev->bus = HCI_SDIO; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 91c523099804..60c0953d7d00 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -500,7 +500,7 @@ static int btuart_open(btuart_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a699f09ddf7c..5d9cc53bd643 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -939,7 +939,7 @@ static int btusb_probe(struct usb_interface *intf, return -ENOMEM; } - hdev->type = HCI_USB; + hdev->bus = HCI_USB; hdev->driver_data = data; data->hdev = hdev; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 697591941e17..17788317c51a 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -485,7 +485,7 @@ static int dtl1_open(dtl1_info_t *info) info->hdev = hdev; - hdev->type = HCI_PCCARD; + hdev->bus = HCI_PCCARD; hdev->driver_data = info; SET_HCIDEV_DEV(hdev, &info->p_dev->dev); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index aa0919386b8c..76a1abb8f214 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -383,7 +383,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) hu->hdev = hdev; - hdev->type = HCI_UART; + hdev->bus = HCI_UART; hdev->driver_data = hu; hdev->open = hci_uart_open; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 7595274103fd..bb0aefdb4267 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -236,7 +236,7 @@ static int vhci_open(struct inode *inode, struct file *file) data->hdev = hdev; - hdev->type = HCI_VIRTUAL; + hdev->bus = HCI_VIRTUAL; hdev->driver_data = data; hdev->open = vhci_open_dev; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ed3aea1605e8..3350a665180f 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -43,7 +43,7 @@ #define HCI_NOTIFY_CONN_DEL 2 #define HCI_NOTIFY_VOICE_SETTING 3 -/* HCI device types */ +/* HCI bus types */ #define HCI_VIRTUAL 0 #define HCI_USB 1 #define HCI_PCCARD 2 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7b86094a894b..7e65885290d5 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -70,7 +70,7 @@ struct hci_dev { char name[8]; unsigned long flags; __u16 id; - __u8 type; + __u8 bus; bdaddr_t bdaddr; __u8 dev_name[248]; __u8 dev_class[3]; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 94ba34982021..4b62ed01ddc6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -797,7 +797,7 @@ int hci_get_dev_info(void __user *arg) strcpy(di.name, hdev->name); di.bdaddr = hdev->bdaddr; - di.type = hdev->type; + di.type = hdev->bus; di.flags = hdev->flags; di.pkt_type = hdev->pkt_type; di.acl_mtu = hdev->acl_mtu; @@ -869,8 +869,8 @@ int hci_register_dev(struct hci_dev *hdev) struct list_head *head = &hci_dev_list, *p; int i, id = 0; - BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, - hdev->type, hdev->owner); + BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name, + hdev->bus, hdev->owner); if (!hdev->open || !hdev->close || !hdev->destruct) return -EINVAL; @@ -946,7 +946,7 @@ int hci_unregister_dev(struct hci_dev *hdev) { int i; - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); write_lock_bh(&hci_dev_list_lock); list_del(&hdev->list); diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 2bc6f6a8de68..9b5f376813b7 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -166,9 +166,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn) queue_work(bt_workq, &conn->work_del); } -static inline char *host_typetostr(int type) +static inline char *host_bustostr(int bus) { - switch (type) { + switch (bus) { case HCI_VIRTUAL: return "VIRTUAL"; case HCI_USB: @@ -188,10 +188,10 @@ static inline char *host_typetostr(int type) } } -static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", host_typetostr(hdev->type)); + return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); } static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -355,7 +355,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib return count; } -static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); +static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); @@ -373,7 +373,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, show_sniff_min_interval, store_sniff_min_interval); static struct attribute *bt_host_attrs[] = { - &dev_attr_type.attr, + &dev_attr_bus.attr, &dev_attr_name.attr, &dev_attr_class.attr, &dev_attr_address.attr, @@ -414,7 +414,7 @@ int hci_register_sysfs(struct hci_dev *hdev) struct device *dev = &hdev->dev; int err; - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); dev->type = &bt_host; dev->class = bt_class; @@ -433,7 +433,7 @@ int hci_register_sysfs(struct hci_dev *hdev) void hci_unregister_sysfs(struct hci_dev *hdev) { - BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); device_del(&hdev->dev); } -- cgit v1.2.3 From ca325f698996c1a0770a67f41e7dc97a007d8bc2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 8 Feb 2010 16:22:31 +0100 Subject: Bluetooth: Convert inquiry cache to use debugfs instead of sysfs The output of the inquiry cache is only useful for debugging purposes and so move it into debugfs. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 + net/bluetooth/hci_sysfs.c | 92 +++++++++++++++++++++++++++------------- 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7e65885290d5..4c94c1e233a2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -134,6 +134,8 @@ struct hci_dev { atomic_t promisc; + struct dentry *debugfs; + struct device *parent; struct device dev; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 9b5f376813b7..f9d93f9cbcd2 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -9,6 +10,9 @@ struct class *bt_class = NULL; EXPORT_SYMBOL_GPL(bt_class); +struct dentry *bt_debugfs = NULL; +EXPORT_SYMBOL_GPL(bt_debugfs); + static struct workqueue_struct *bt_workq; static inline char *link_typetostr(int type) @@ -251,32 +255,6 @@ static ssize_t show_hci_revision(struct device *dev, struct device_attribute *at return sprintf(buf, "%d\n", hdev->hci_rev); } -static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct hci_dev *hdev = dev_get_drvdata(dev); - struct inquiry_cache *cache = &hdev->inq_cache; - struct inquiry_entry *e; - int n = 0; - - hci_dev_lock_bh(hdev); - - for (e = cache->list; e; e = e->next) { - struct inquiry_data *data = &e->data; - bdaddr_t bdaddr; - baswap(&bdaddr, &data->bdaddr); - n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", - batostr(&bdaddr), - data->pscan_rep_mode, data->pscan_period_mode, - data->pscan_mode, data->dev_class[2], - data->dev_class[1], data->dev_class[0], - __le16_to_cpu(data->clock_offset), - data->rssi, data->ssp_mode, e->timestamp); - } - - hci_dev_unlock_bh(hdev); - return n; -} - static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); @@ -363,7 +341,6 @@ static DEVICE_ATTR(features, S_IRUGO, show_features, NULL); static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL); static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL); static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL); -static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL); static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR, show_idle_timeout, store_idle_timeout); @@ -381,7 +358,6 @@ static struct attribute *bt_host_attrs[] = { &dev_attr_manufacturer.attr, &dev_attr_hci_version.attr, &dev_attr_hci_revision.attr, - &dev_attr_inquiry_cache.attr, &dev_attr_idle_timeout.attr, &dev_attr_sniff_max_interval.attr, &dev_attr_sniff_min_interval.attr, @@ -409,6 +385,46 @@ static struct device_type bt_host = { .release = bt_host_release, }; +static int inquiry_cache_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct hci_dev *hdev = file->private_data; + struct inquiry_cache *cache = &hdev->inq_cache; + struct inquiry_entry *e; + char buf[4096]; + int n = 0; + + hci_dev_lock_bh(hdev); + + for (e = cache->list; e; e = e->next) { + struct inquiry_data *data = &e->data; + bdaddr_t bdaddr; + baswap(&bdaddr, &data->bdaddr); + n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", + batostr(&bdaddr), + data->pscan_rep_mode, data->pscan_period_mode, + data->pscan_mode, data->dev_class[2], + data->dev_class[1], data->dev_class[0], + __le16_to_cpu(data->clock_offset), + data->rssi, data->ssp_mode, e->timestamp); + } + + hci_dev_unlock_bh(hdev); + + return simple_read_from_buffer(userbuf, count, ppos, buf, n); +} + +static const struct file_operations inquiry_cache_fops = { + .open = inquiry_cache_open, + .read = inquiry_cache_read, +}; + int hci_register_sysfs(struct hci_dev *hdev) { struct device *dev = &hdev->dev; @@ -428,6 +444,16 @@ int hci_register_sysfs(struct hci_dev *hdev) if (err < 0) return err; + if (!bt_debugfs) + return 0; + + hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); + if (!hdev->debugfs) + return 0; + + debugfs_create_file("inquiry_cache", 0444, hdev->debugfs, + hdev, &inquiry_cache_fops); + return 0; } @@ -435,6 +461,8 @@ void hci_unregister_sysfs(struct hci_dev *hdev) { BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); + debugfs_remove_recursive(hdev->debugfs); + device_del(&hdev->dev); } @@ -444,6 +472,8 @@ int __init bt_sysfs_init(void) if (!bt_workq) return -ENOMEM; + bt_debugfs = debugfs_create_dir("bluetooth", NULL); + bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { destroy_workqueue(bt_workq); @@ -455,7 +485,9 @@ int __init bt_sysfs_init(void) void bt_sysfs_cleanup(void) { - destroy_workqueue(bt_workq); - class_destroy(bt_class); + + debugfs_remove_recursive(bt_debugfs); + + destroy_workqueue(bt_workq); } -- cgit v1.2.3 From b914a250e7b390c713b36a9405a39c4c11abad80 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 8 Feb 2010 16:47:04 +0100 Subject: Bluetooth: Convert Marvell driver to use per adapter debugfs The debugfs support of the Marvell driver is buggy. It is limited to one controller per system. Fix this by using the controller specific debugfs directory as parent. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btmrvl_debugfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index d43b5cb864ef..3126a3d0c45c 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -26,7 +26,8 @@ #include "btmrvl_drv.h" struct btmrvl_debugfs_data { - struct dentry *root_dir, *config_dir, *status_dir; + struct dentry *config_dir; + struct dentry *status_dir; /* config */ struct dentry *psmode; @@ -363,6 +364,9 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) struct btmrvl_private *priv = hdev->driver_data; struct btmrvl_debugfs_data *dbg; + if (!hdev->debugfs) + return; + dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); priv->debugfs_data = dbg; @@ -371,9 +375,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) return; } - dbg->root_dir = debugfs_create_dir("btmrvl", NULL); - - dbg->config_dir = debugfs_create_dir("config", dbg->root_dir); + dbg->config_dir = debugfs_create_dir("config", hdev->debugfs); dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir, hdev->driver_data, &btmrvl_psmode_fops); @@ -388,7 +390,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, hdev->driver_data, &btmrvl_hscfgcmd_fops); - dbg->status_dir = debugfs_create_dir("status", dbg->root_dir); + dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); dbg->curpsmode = debugfs_create_file("curpsmode", 0444, dbg->status_dir, hdev->driver_data, @@ -425,7 +427,5 @@ void btmrvl_debugfs_remove(struct hci_dev *hdev) debugfs_remove(dbg->txdnldready); debugfs_remove(dbg->status_dir); - debugfs_remove(dbg->root_dir); - kfree(dbg); } -- cgit v1.2.3 From 943da25d95c7e8fd8c39dbf09e030f5da46f5d85 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Feb 2010 02:28:41 +0100 Subject: Bluetooth: Add controller types for BR/EDR and 802.11 AMP With the Bluetooth 3.0 specification and the introduction of alternate MAC/PHY (AMP) support, it is required to differentiate between primary BR/EDR controllers and 802.11 AMP controllers. So introduce a special type inside HCI device for differentiation. For now all AMP controllers will be treated as raw devices until an AMP manager has been implemented. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 4 ++++ include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 6 +++++- net/bluetooth/hci_sysfs.c | 20 ++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3350a665180f..fc0c502d9fd1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -52,6 +52,10 @@ #define HCI_PCI 5 #define HCI_SDIO 6 +/* HCI controller types */ +#define HCI_BREDR 0x00 +#define HCI_80211 0x01 + /* HCI device quirks */ enum { HCI_QUIRK_NO_RESET, diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4c94c1e233a2..ce3c99e5fa25 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -71,6 +71,7 @@ struct hci_dev { unsigned long flags; __u16 id; __u8 bus; + __u8 dev_type; bdaddr_t bdaddr; __u8 dev_name[248]; __u8 dev_class[3]; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4b62ed01ddc6..4ad23192c7a5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -491,6 +491,10 @@ int hci_dev_open(__u16 dev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) set_bit(HCI_RAW, &hdev->flags); + /* Treat all non BR/EDR controllers as raw devices for now */ + if (hdev->dev_type != HCI_BREDR) + set_bit(HCI_RAW, &hdev->flags); + if (hdev->open(hdev)) { ret = -EIO; goto done; @@ -797,7 +801,7 @@ int hci_get_dev_info(void __user *arg) strcpy(di.name, hdev->name); di.bdaddr = hdev->bdaddr; - di.type = hdev->bus; + di.type = (hdev->bus & 0x0f) | (hdev->dev_type << 4); di.flags = hdev->flags; di.pkt_type = hdev->pkt_type; di.acl_mtu = hdev->acl_mtu; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index f9d93f9cbcd2..1a79a6c7e30e 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -192,12 +192,30 @@ static inline char *host_bustostr(int bus) } } +static inline char *host_typetostr(int type) +{ + switch (type) { + case HCI_BREDR: + return "BR/EDR"; + case HCI_80211: + return "802.11"; + default: + return "UNKNOWN"; + } +} + static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); return sprintf(buf, "%s\n", host_bustostr(hdev->bus)); } +static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hci_dev *hdev = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type)); +} + static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); @@ -334,6 +352,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib } static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL); +static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static DEVICE_ATTR(class, S_IRUGO, show_class, NULL); static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); @@ -351,6 +370,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR, static struct attribute *bt_host_attrs[] = { &dev_attr_bus.attr, + &dev_attr_type.attr, &dev_attr_name.attr, &dev_attr_class.attr, &dev_attr_address.attr, -- cgit v1.2.3 From 705e5711b61e9622b2d88850f38c219014aa0780 Mon Sep 17 00:00:00 2001 From: Stephen Coe Date: Tue, 16 Feb 2010 11:29:44 -0500 Subject: Bluetooth: Add SCO fallback for unsupported feature error The Bluetooth SIG PTS test case: TC_AG_ACS_BV_10_I, rejects eSCO with "Unsupported Feature or Parameter Value" (0x11). This patch adds case for SCO fallback. 2007-09-20 12:20:37.787747 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 38 packets 1 2007-09-20 12:20:37.842154 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 38 voice setting 0x0060 2007-09-20 12:20:37.847037 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2007-09-20 12:20:37.855233 > HCI Event: Max Slots Change (0x1b) plen 3 handle 38 slots 1 2007-09-20 12:20:39.913354 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x11 handle 38 bdaddr 00:16:93:01:01:7A type eSCO Error: Unsupported Feature or Parameter Value 2007-09-20 12:20:39.922629 > HCI Event: Max Slots Change (0x1b) plen 3 handle 38 slots 5 2007-09-20 12:20:58.126886 < ACL data: handle 38 flags 0x02 dlen 8 L2CAP(d): cid 0x0041 len 4 [psm 0] 0000: 0b 53 01 b8 .S.. 2007-09-20 12:20:58.130138 > HCI Event: Number of Completed Packets (0x13) plen 5 handle 38 packets 1 Signed-off-by: Stephen Coe Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 592da5c909c1..6c57fc71c7e2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1698,6 +1698,7 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu hci_conn_add_sysfs(conn); break; + case 0x11: /* Unsupported Feature or Parameter Value */ case 0x1c: /* SCO interval rejected */ case 0x1a: /* Unsupported Remote Feature */ case 0x1f: /* Unspecified error */ -- cgit v1.2.3 From a2ce766238f72ff7337606c0bc96803c30c9e05c Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:39 +0000 Subject: pci: Add PCI LRDT tag size and section size This patch adds a preprocessor constant to describe the PCI VPD large resource data type tag size and an inline function to extract the large resource section size from the large resource data type tag. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 8 +++++--- drivers/net/tg3.c | 13 ++++++------- include/linux/pci.h | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d3f739a295df..bb403887b549 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7773,15 +7773,17 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) unsigned int block_end; if (val == 0x82 || val == 0x91) { - i = (i + 3 + (data[i + 1] + (data[i + 2] << 8))); + i += PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&data[i]); continue; } if (val != 0x90) goto vpd_done; - block_end = (i + 3 + (data[i + 1] + (data[i + 2] << 8))); - i += 3; + block_end = (i + PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&data[i])); + i += PCI_VPD_LRDT_TAG_SIZE; if (block_end > BNX2_VPD_LEN) goto vpd_done; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0d06e4007f44..5fccbe459949 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12590,19 +12590,18 @@ static void __devinit tg3_read_partno(struct tg3 *tp) unsigned int block_end; if (val == 0x82 || val == 0x91) { - i = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); + i += PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&vpd_data[i]); continue; } if (val != 0x90) goto out_not_found; - block_end = (i + 3 + - (vpd_data[i + 1] + - (vpd_data[i + 2] << 8))); - i += 3; + block_end = i + PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&vpd_data[i]); + + i += PCI_VPD_LRDT_TAG_SIZE; if (block_end > TG3_NVM_VPD_LEN) goto out_not_found; diff --git a/include/linux/pci.h b/include/linux/pci.h index e2575f86133a..6f62a499023f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1349,5 +1349,19 @@ static inline bool pci_is_pcie(struct pci_dev *dev) void pci_request_acs(void); + +#define PCI_VPD_LRDT_TAG_SIZE 3 + +/** + * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length + * @lrdt: Pointer to the beginning of the Large Resource Data Type tag + * + * Returns the extracted Large Resource Data Type length. + */ +static inline u16 pci_vpd_lrdt_size(const u8 *lrdt) +{ + return (u16)lrdt[1] + ((u16)lrdt[2] << 8); +} + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ -- cgit v1.2.3 From 7ad506fa1adc2da3d394c562f09b8e1b3026c402 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:40 +0000 Subject: pci: Add large and small resource data type code This patch introduces more VPD preprocessor definitions to identify some small and large resource data type item names. The patch then continues to correct how the tg3 and bnx2 drivers search for the "read-only data" large resource data type. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 23 +++++++++++++++++------ drivers/net/tg3.c | 23 +++++++++++++++++------ include/linux/pci.h | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index bb403887b549..084ef102b8c4 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7772,15 +7772,26 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) unsigned char val = data[i]; unsigned int block_end; - if (val == 0x82 || val == 0x91) { - i += PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&data[i]); + if (val & PCI_VPD_LRDT) { + if (i + PCI_VPD_LRDT_TAG_SIZE > BNX2_VPD_LEN) + break; + + if (val != PCI_VPD_LRDT_RO_DATA) { + i += PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&data[i]); + + continue; + } + } else { + if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END) + break; + + i += PCI_VPD_SRDT_TAG_SIZE + + pci_vpd_srdt_size(&data[i]); + continue; } - if (val != 0x90) - goto vpd_done; - block_end = (i + PCI_VPD_LRDT_TAG_SIZE + pci_vpd_lrdt_size(&data[i])); i += PCI_VPD_LRDT_TAG_SIZE; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5fccbe459949..ed57a62b3ac8 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12589,15 +12589,26 @@ static void __devinit tg3_read_partno(struct tg3 *tp) unsigned char val = vpd_data[i]; unsigned int block_end; - if (val == 0x82 || val == 0x91) { - i += PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&vpd_data[i]); + if (val & PCI_VPD_LRDT) { + if (i + PCI_VPD_LRDT_TAG_SIZE > TG3_NVM_VPD_LEN) + break; + + if (val != PCI_VPD_LRDT_RO_DATA) { + i += PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&vpd_data[i]); + + continue; + } + } else { + if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END) + break; + + i += PCI_VPD_SRDT_TAG_SIZE + + pci_vpd_srdt_size(&vpd_data[i]); + continue; } - if (val != 0x90) - goto out_not_found; - block_end = i + PCI_VPD_LRDT_TAG_SIZE + pci_vpd_lrdt_size(&vpd_data[i]); diff --git a/include/linux/pci.h b/include/linux/pci.h index 6f62a499023f..198d062640b7 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1350,7 +1350,28 @@ static inline bool pci_is_pcie(struct pci_dev *dev) void pci_request_acs(void); -#define PCI_VPD_LRDT_TAG_SIZE 3 +#define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */ +#define PCI_VPD_LRDT_ID(x) (x | PCI_VPD_LRDT) + +/* Large Resource Data Type Tag Item Names */ +#define PCI_VPD_LTIN_ID_STRING 0x02 /* Identifier String */ +#define PCI_VPD_LTIN_RO_DATA 0x10 /* Read-Only Data */ +#define PCI_VPD_LTIN_RW_DATA 0x11 /* Read-Write Data */ + +#define PCI_VPD_LRDT_ID_STRING PCI_VPD_LRDT_ID(PCI_VPD_LTIN_ID_STRING) +#define PCI_VPD_LRDT_RO_DATA PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RO_DATA) +#define PCI_VPD_LRDT_RW_DATA PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA) + +/* Small Resource Data Type Tag Item Names */ +#define PCI_VPD_STIN_END 0x78 /* End */ + +#define PCI_VPD_SRDT_END PCI_VPD_STIN_END + +#define PCI_VPD_SRDT_TIN_MASK 0x78 +#define PCI_VPD_SRDT_LEN_MASK 0x07 + +#define PCI_VPD_LRDT_TAG_SIZE 3 +#define PCI_VPD_SRDT_TAG_SIZE 1 /** * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length @@ -1363,5 +1384,16 @@ static inline u16 pci_vpd_lrdt_size(const u8 *lrdt) return (u16)lrdt[1] + ((u16)lrdt[2] << 8); } +/** + * pci_vpd_srdt_size - Extracts the Small Resource Data Type length + * @lrdt: Pointer to the beginning of the Small Resource Data Type tag + * + * Returns the extracted Small Resource Data Type length. + */ +static inline u8 pci_vpd_srdt_size(const u8 *srdt) +{ + return (*srdt) & PCI_VPD_SRDT_LEN_MASK; +} + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ -- cgit v1.2.3 From b55ac1b22690d2e5b02a61cf6d69c2d66969c79d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:41 +0000 Subject: pci: Add helper to find a VPD resource data type This patch adds the pci_vpd_find_tag() helper function to find VPD resource data types in a buffer. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 24 ++++-------------------- drivers/net/tg3.c | 26 +++++--------------------- drivers/pci/Makefile | 2 +- drivers/pci/vpd.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 12 ++++++++++++ 5 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 drivers/pci/vpd.c diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 084ef102b8c4..fd43feb5a350 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7769,28 +7769,12 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) } for (i = 0; i <= BNX2_VPD_LEN - 3; ) { - unsigned char val = data[i]; unsigned int block_end; - if (val & PCI_VPD_LRDT) { - if (i + PCI_VPD_LRDT_TAG_SIZE > BNX2_VPD_LEN) - break; - - if (val != PCI_VPD_LRDT_RO_DATA) { - i += PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&data[i]); - - continue; - } - } else { - if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END) - break; - - i += PCI_VPD_SRDT_TAG_SIZE + - pci_vpd_srdt_size(&data[i]); - - continue; - } + i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN, + PCI_VPD_LRDT_RO_DATA); + if (i < 0) + break; block_end = (i + PCI_VPD_LRDT_TAG_SIZE + pci_vpd_lrdt_size(&data[i])); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ed57a62b3ac8..76ad141ab448 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12547,7 +12547,7 @@ skip_phy_reset: static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[TG3_NVM_VPD_LEN]; /* in little-endian format */ - unsigned int i; + int i; u32 magic; if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || @@ -12586,28 +12586,12 @@ static void __devinit tg3_read_partno(struct tg3 *tp) /* Now parse and find the part number. */ for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) { - unsigned char val = vpd_data[i]; unsigned int block_end; - if (val & PCI_VPD_LRDT) { - if (i + PCI_VPD_LRDT_TAG_SIZE > TG3_NVM_VPD_LEN) - break; - - if (val != PCI_VPD_LRDT_RO_DATA) { - i += PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&vpd_data[i]); - - continue; - } - } else { - if ((val & PCI_VPD_SRDT_TIN_MASK) == PCI_VPD_STIN_END) - break; - - i += PCI_VPD_SRDT_TAG_SIZE + - pci_vpd_srdt_size(&vpd_data[i]); - - continue; - } + i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN, + PCI_VPD_LRDT_RO_DATA); + if (i < 0) + break; block_end = i + PCI_VPD_LRDT_TAG_SIZE + pci_vpd_lrdt_size(&vpd_data[i]); diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 4df48d58eaa6..b2f6d777a084 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ - irq.o + irq.o vpd.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSFS) += slot.o diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c new file mode 100644 index 000000000000..6bc554576f8d --- /dev/null +++ b/drivers/pci/vpd.c @@ -0,0 +1,43 @@ +/* + * File: vpd.c + * Purpose: Provide PCI VPD support + * + * Copyright (C) 2010 Broadcom Corporation. + */ + +#include + +int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt) +{ + int i; + + for (i = off; i < len; ) { + u8 val = buf[i]; + + if (val & PCI_VPD_LRDT) { + /* Don't return success of the tag isn't complete */ + if (i + PCI_VPD_LRDT_TAG_SIZE > len) + break; + + if (val == rdt) + return i; + + i += PCI_VPD_LRDT_TAG_SIZE + + pci_vpd_lrdt_size(&buf[i]); + } else { + u8 tag = val & ~PCI_VPD_SRDT_LEN_MASK; + + if (tag == rdt) + return i; + + if (tag == PCI_VPD_SRDT_END) + break; + + i += PCI_VPD_SRDT_TAG_SIZE + + pci_vpd_srdt_size(&buf[i]); + } + } + + return -ENOENT; +} +EXPORT_SYMBOL_GPL(pci_vpd_find_tag); diff --git a/include/linux/pci.h b/include/linux/pci.h index 198d062640b7..e30ceea7345b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1395,5 +1395,17 @@ static inline u8 pci_vpd_srdt_size(const u8 *srdt) return (*srdt) & PCI_VPD_SRDT_LEN_MASK; } +/** + * pci_vpd_find_tag - Locates the Resource Data Type tag provided + * @buf: Pointer to buffered vpd data + * @off: The offset into the buffer at which to begin the search + * @len: The length of the vpd buffer + * @rdt: The Resource Data Type to search for + * + * Returns the index where the Resource Data Type was found or + * -ENOENT otherwise. + */ +int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt); + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ -- cgit v1.2.3 From e1d5bdabb94da89bdb3c3f2ee105cf61fca88ec8 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:42 +0000 Subject: pci: Add VPD information field helper functions This patch adds a preprocessor constant to describe the PCI VPD information field header size and an inline function to extract the size of the information field itself. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 11 ++++++----- drivers/net/tg3.c | 7 ++++--- include/linux/pci.h | 13 +++++++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index fd43feb5a350..b808707f83ff 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7784,14 +7784,15 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) goto vpd_done; while (i < (block_end - 2)) { - int len = data[i + 2]; + int len = pci_vpd_info_field_size(&data[i]); - if (i + 3 + len > block_end) + if (i + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end) goto vpd_done; if (data[i] == 'M' && data[i + 1] == 'N') { if (len != 4 || - memcmp(&data[i + 3], "1028", 4)) + memcmp(&data[i + PCI_VPD_INFO_FLD_HDR_SIZE], + "1028", 4)) goto vpd_done; mn_match = true; @@ -7800,9 +7801,9 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) goto vpd_done; v0_len = len; - v0_str = &data[i + 3]; + v0_str = &data[i + PCI_VPD_INFO_FLD_HDR_SIZE]; } - i += 3 + len; + i += PCI_VPD_INFO_FLD_HDR_SIZE + len; if (mn_match && v0_str) { memcpy(bp->fw_version, v0_str, v0_len); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 76ad141ab448..f59f36910e98 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12604,9 +12604,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp) while (i < (block_end - 2)) { if (vpd_data[i + 0] == 'P' && vpd_data[i + 1] == 'N') { - int partno_len = vpd_data[i + 2]; + int partno_len = pci_vpd_info_field_size(&vpd_data[i]); - i += 3; + i += PCI_VPD_INFO_FLD_HDR_SIZE; if (partno_len > TG3_BPN_SIZE || (partno_len + i) > TG3_NVM_VPD_LEN) goto out_not_found; @@ -12617,7 +12617,8 @@ static void __devinit tg3_read_partno(struct tg3 *tp) /* Success. */ return; } - i += 3 + vpd_data[i + 2]; + i += PCI_VPD_INFO_FLD_HDR_SIZE + + pci_vpd_info_field_size(&vpd_data[i]); } /* Part number not found. */ diff --git a/include/linux/pci.h b/include/linux/pci.h index e30ceea7345b..cfff32fc6e35 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1373,6 +1373,8 @@ void pci_request_acs(void); #define PCI_VPD_LRDT_TAG_SIZE 3 #define PCI_VPD_SRDT_TAG_SIZE 1 +#define PCI_VPD_INFO_FLD_HDR_SIZE 3 + /** * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length * @lrdt: Pointer to the beginning of the Large Resource Data Type tag @@ -1395,6 +1397,17 @@ static inline u8 pci_vpd_srdt_size(const u8 *srdt) return (*srdt) & PCI_VPD_SRDT_LEN_MASK; } +/** + * pci_vpd_info_field_size - Extracts the information field length + * @lrdt: Pointer to the beginning of an information field header + * + * Returns the extracted information field length. + */ +static inline u8 pci_vpd_info_field_size(const u8 *info_field) +{ + return info_field[2]; +} + /** * pci_vpd_find_tag - Locates the Resource Data Type tag provided * @buf: Pointer to buffered vpd data -- cgit v1.2.3 From 4067a8541d397e9d6b443dd2ce0ecb78bfd991db Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:43 +0000 Subject: pci: Add helper to search for VPD keywords This patch adds the pci_vpd_find_info_keyword() helper function to find information field keywords within read-only and read-write large resource data type sections. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 54 +++++++++++++++++++++++++++++------------------------ drivers/net/tg3.c | 32 +++++++++++++------------------ drivers/pci/vpd.c | 18 ++++++++++++++++++ include/linux/pci.h | 17 +++++++++++++++++ 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b808707f83ff..bc23bfb687c3 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7769,48 +7769,54 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) } for (i = 0; i <= BNX2_VPD_LEN - 3; ) { - unsigned int block_end; + int j; + unsigned int block_end, rosize; i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA); if (i < 0) break; - block_end = (i + PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&data[i])); + rosize = pci_vpd_lrdt_size(&data[i]); + block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; i += PCI_VPD_LRDT_TAG_SIZE; if (block_end > BNX2_VPD_LEN) goto vpd_done; - while (i < (block_end - 2)) { - int len = pci_vpd_info_field_size(&data[i]); + j = pci_vpd_find_info_keyword(data, i, rosize, + PCI_VPD_RO_KEYWORD_MFR_ID); + if (j > 0) { + int len = pci_vpd_info_field_size(&data[j]); - if (i + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end) + if (j + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end || + len != 4 || + memcmp(&data[j + PCI_VPD_INFO_FLD_HDR_SIZE], + "1028", 4)) goto vpd_done; - if (data[i] == 'M' && data[i + 1] == 'N') { - if (len != 4 || - memcmp(&data[i + PCI_VPD_INFO_FLD_HDR_SIZE], - "1028", 4)) - goto vpd_done; - mn_match = true; + mn_match = true; + } - } else if (data[i] == 'V' && data[i + 1] == '0') { - if (len > BNX2_MAX_VER_SLEN) - goto vpd_done; + j = pci_vpd_find_info_keyword(data, i, rosize, + PCI_VPD_RO_KEYWORD_VENDOR0); + if (j > 0) { + int len = pci_vpd_info_field_size(&data[j]); - v0_len = len; - v0_str = &data[i + PCI_VPD_INFO_FLD_HDR_SIZE]; - } - i += PCI_VPD_INFO_FLD_HDR_SIZE + len; - - if (mn_match && v0_str) { - memcpy(bp->fw_version, v0_str, v0_len); - bp->fw_version[v0_len] = ' '; + j += PCI_VPD_INFO_FLD_HDR_SIZE; + if (j + len > block_end || len > BNX2_MAX_VER_SLEN) goto vpd_done; - } + + v0_len = len; + v0_str = &data[j]; } + + if (mn_match && v0_str) { + memcpy(bp->fw_version, v0_str, v0_len); + bp->fw_version[v0_len] = ' '; + goto vpd_done; + } + goto vpd_done; } diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f59f36910e98..204c565caa5a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12586,39 +12586,33 @@ static void __devinit tg3_read_partno(struct tg3 *tp) /* Now parse and find the part number. */ for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) { - unsigned int block_end; + unsigned int block_end, rosize; i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN, PCI_VPD_LRDT_RO_DATA); if (i < 0) break; - block_end = i + PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&vpd_data[i]); - + rosize = pci_vpd_lrdt_size(&vpd_data[i]); + block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; i += PCI_VPD_LRDT_TAG_SIZE; if (block_end > TG3_NVM_VPD_LEN) goto out_not_found; - while (i < (block_end - 2)) { - if (vpd_data[i + 0] == 'P' && - vpd_data[i + 1] == 'N') { - int partno_len = pci_vpd_info_field_size(&vpd_data[i]); + i = pci_vpd_find_info_keyword(vpd_data, i, rosize, + PCI_VPD_RO_KEYWORD_PARTNO); + if (i > 0) { + u8 len = pci_vpd_info_field_size(&vpd_data[i]); - i += PCI_VPD_INFO_FLD_HDR_SIZE; - if (partno_len > TG3_BPN_SIZE || - (partno_len + i) > TG3_NVM_VPD_LEN) - goto out_not_found; + i += PCI_VPD_INFO_FLD_HDR_SIZE; + if (len > TG3_BPN_SIZE || + (len + i) > TG3_NVM_VPD_LEN) + break; - memcpy(tp->board_part_number, - &vpd_data[i], partno_len); + memcpy(tp->board_part_number, &vpd_data[i], len); - /* Success. */ - return; - } - i += PCI_VPD_INFO_FLD_HDR_SIZE + - pci_vpd_info_field_size(&vpd_data[i]); + return; } /* Part number not found. */ diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c index 6bc554576f8d..a5a5ca17cfe6 100644 --- a/drivers/pci/vpd.c +++ b/drivers/pci/vpd.c @@ -41,3 +41,21 @@ int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt) return -ENOENT; } EXPORT_SYMBOL_GPL(pci_vpd_find_tag); + +int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, + unsigned int len, const char *kw) +{ + int i; + + for (i = off; i + PCI_VPD_INFO_FLD_HDR_SIZE <= off + len;) { + if (buf[i + 0] == kw[0] && + buf[i + 1] == kw[1]) + return i; + + i += PCI_VPD_INFO_FLD_HDR_SIZE + + pci_vpd_info_field_size(&buf[i]); + } + + return -ENOENT; +} +EXPORT_SYMBOL_GPL(pci_vpd_find_info_keyword); diff --git a/include/linux/pci.h b/include/linux/pci.h index cfff32fc6e35..1f4a52131c99 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1375,6 +1375,10 @@ void pci_request_acs(void); #define PCI_VPD_INFO_FLD_HDR_SIZE 3 +#define PCI_VPD_RO_KEYWORD_PARTNO "PN" +#define PCI_VPD_RO_KEYWORD_MFR_ID "MN" +#define PCI_VPD_RO_KEYWORD_VENDOR0 "V0" + /** * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length * @lrdt: Pointer to the beginning of the Large Resource Data Type tag @@ -1420,5 +1424,18 @@ static inline u8 pci_vpd_info_field_size(const u8 *info_field) */ int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt); +/** + * pci_vpd_find_info_keyword - Locates an information field keyword in the VPD + * @buf: Pointer to buffered vpd data + * @off: The offset into the buffer at which to begin the search + * @len: The length of the buffer area, relative to off, in which to search + * @kw: The keyword to search for + * + * Returns the index where the information field keyword was found or + * -ENOENT otherwise. + */ +int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, + unsigned int len, const char *kw); + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ -- cgit v1.2.3 From df25bc38b5531aa79a20e34549ea9fedf5f3ae36 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:44 +0000 Subject: bnx2: Remove now useless VPD code Now that the VPD searching code is abstracted away, the outer loop used to detect the read-only large resource data type section is useless. Signed-off-by: Matt Carlson Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 74 +++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index bc23bfb687c3..381887ba677c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7743,10 +7743,9 @@ bnx2_get_pci_speed(struct bnx2 *bp) static void __devinit bnx2_read_vpd_fw_ver(struct bnx2 *bp) { - int rc, i, v0_len = 0; + int rc, i, j; u8 *data; - u8 *v0_str = NULL; - bool mn_match = false; + unsigned int block_end, rosize, len; #define BNX2_VPD_NVRAM_OFFSET 0x300 #define BNX2_VPD_LEN 128 @@ -7768,57 +7767,42 @@ bnx2_read_vpd_fw_ver(struct bnx2 *bp) data[i + 3] = data[i + BNX2_VPD_LEN]; } - for (i = 0; i <= BNX2_VPD_LEN - 3; ) { - int j; - unsigned int block_end, rosize; - - i = pci_vpd_find_tag(data, i, BNX2_VPD_LEN, - PCI_VPD_LRDT_RO_DATA); - if (i < 0) - break; - - rosize = pci_vpd_lrdt_size(&data[i]); - block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; - i += PCI_VPD_LRDT_TAG_SIZE; - - if (block_end > BNX2_VPD_LEN) - goto vpd_done; + i = pci_vpd_find_tag(data, 0, BNX2_VPD_LEN, PCI_VPD_LRDT_RO_DATA); + if (i < 0) + goto vpd_done; - j = pci_vpd_find_info_keyword(data, i, rosize, - PCI_VPD_RO_KEYWORD_MFR_ID); - if (j > 0) { - int len = pci_vpd_info_field_size(&data[j]); + rosize = pci_vpd_lrdt_size(&data[i]); + i += PCI_VPD_LRDT_TAG_SIZE; + block_end = i + rosize; - if (j + PCI_VPD_INFO_FLD_HDR_SIZE + len > block_end || - len != 4 || - memcmp(&data[j + PCI_VPD_INFO_FLD_HDR_SIZE], - "1028", 4)) - goto vpd_done; + if (block_end > BNX2_VPD_LEN) + goto vpd_done; - mn_match = true; - } + j = pci_vpd_find_info_keyword(data, i, rosize, + PCI_VPD_RO_KEYWORD_MFR_ID); + if (j < 0) + goto vpd_done; - j = pci_vpd_find_info_keyword(data, i, rosize, - PCI_VPD_RO_KEYWORD_VENDOR0); - if (j > 0) { - int len = pci_vpd_info_field_size(&data[j]); + len = pci_vpd_info_field_size(&data[j]); - j += PCI_VPD_INFO_FLD_HDR_SIZE; - if (j + len > block_end || len > BNX2_MAX_VER_SLEN) - goto vpd_done; + j += PCI_VPD_INFO_FLD_HDR_SIZE; + if (j + len > block_end || len != 4 || + memcmp(&data[j], "1028", 4)) + goto vpd_done; - v0_len = len; - v0_str = &data[j]; - } + j = pci_vpd_find_info_keyword(data, i, rosize, + PCI_VPD_RO_KEYWORD_VENDOR0); + if (j < 0) + goto vpd_done; - if (mn_match && v0_str) { - memcpy(bp->fw_version, v0_str, v0_len); - bp->fw_version[v0_len] = ' '; - goto vpd_done; - } + len = pci_vpd_info_field_size(&data[j]); + j += PCI_VPD_INFO_FLD_HDR_SIZE; + if (j + len > block_end || len > BNX2_MAX_VER_SLEN) goto vpd_done; - } + + memcpy(bp->fw_version, &data[j], len); + bp->fw_version[len] = ' '; vpd_done: kfree(data); -- cgit v1.2.3 From 4181b2c8bc29bb756ac1816678104b528377b656 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 26 Feb 2010 14:04:45 +0000 Subject: tg3: Remove now useless VPD code Now that the VPD searching code is abstracted away, the outer loop used to detect the read-only large resource data type section is useless. Signed-off-by: Matt Carlson Acked-by: Jesse Barnes Signed-off-by: David S. Miller --- drivers/net/tg3.c | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 204c565caa5a..0fa7688ab483 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -12547,7 +12547,8 @@ skip_phy_reset: static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[TG3_NVM_VPD_LEN]; /* in little-endian format */ - int i; + unsigned int block_end, rosize, len; + int i = 0; u32 magic; if ((tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) || @@ -12569,7 +12570,7 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } } else { ssize_t cnt; - unsigned int pos = 0, i = 0; + unsigned int pos = 0; for (; pos < TG3_NVM_VPD_LEN && i < 3; i++, pos += cnt) { cnt = pci_read_vpd(tp->pdev, pos, @@ -12584,40 +12585,33 @@ static void __devinit tg3_read_partno(struct tg3 *tp) goto out_not_found; } - /* Now parse and find the part number. */ - for (i = 0; i < TG3_NVM_VPD_LEN - 2; ) { - unsigned int block_end, rosize; + i = pci_vpd_find_tag(vpd_data, 0, TG3_NVM_VPD_LEN, + PCI_VPD_LRDT_RO_DATA); + if (i < 0) + goto out_not_found; - i = pci_vpd_find_tag(vpd_data, i, TG3_NVM_VPD_LEN, - PCI_VPD_LRDT_RO_DATA); - if (i < 0) - break; + rosize = pci_vpd_lrdt_size(&vpd_data[i]); + block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; + i += PCI_VPD_LRDT_TAG_SIZE; - rosize = pci_vpd_lrdt_size(&vpd_data[i]); - block_end = i + PCI_VPD_LRDT_TAG_SIZE + rosize; - i += PCI_VPD_LRDT_TAG_SIZE; + if (block_end > TG3_NVM_VPD_LEN) + goto out_not_found; - if (block_end > TG3_NVM_VPD_LEN) - goto out_not_found; + i = pci_vpd_find_info_keyword(vpd_data, i, rosize, + PCI_VPD_RO_KEYWORD_PARTNO); + if (i < 0) + goto out_not_found; - i = pci_vpd_find_info_keyword(vpd_data, i, rosize, - PCI_VPD_RO_KEYWORD_PARTNO); - if (i > 0) { - u8 len = pci_vpd_info_field_size(&vpd_data[i]); + len = pci_vpd_info_field_size(&vpd_data[i]); - i += PCI_VPD_INFO_FLD_HDR_SIZE; - if (len > TG3_BPN_SIZE || - (len + i) > TG3_NVM_VPD_LEN) - break; - - memcpy(tp->board_part_number, &vpd_data[i], len); + i += PCI_VPD_INFO_FLD_HDR_SIZE; + if (len > TG3_BPN_SIZE || + (len + i) > TG3_NVM_VPD_LEN) + goto out_not_found; - return; - } + memcpy(tp->board_part_number, &vpd_data[i], len); - /* Part number not found. */ - goto out_not_found; - } + return; out_not_found: if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) -- cgit v1.2.3 From f6e623a65cb301088bd04794043e82bfc996c512 Mon Sep 17 00:00:00 2001 From: Johann Felix Soden Date: Mon, 15 Feb 2010 22:23:48 +0100 Subject: Bluetooth: Fix out of scope variable access in hci_sock_cmsg() The pointer data can point to the variable ctv. Access to data happens when ctv is already out of scope. Signed-off-by: Johann Felix Soden Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_sock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 688cfebfbee0..38f08f6b86f6 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -329,6 +329,9 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ } if (mask & HCI_CMSG_TSTAMP) { +#ifdef CONFIG_COMPAT + struct compat_timeval ctv; +#endif struct timeval tv; void *data; int len; @@ -339,7 +342,6 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ len = sizeof(tv); #ifdef CONFIG_COMPAT if (msg->msg_flags & MSG_CMSG_COMPAT) { - struct compat_timeval ctv; ctv.tv_sec = tv.tv_sec; ctv.tv_usec = tv.tv_usec; data = &ctv; -- cgit v1.2.3 From 87557c18ac36241b596984589a0889c5c4bf916c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:39 +0000 Subject: bridge: Do br_pass_frame_up after other ports At the moment we deliver to the local bridge port via the function br_pass_frame_up before all other ports. There is no requirement for this. For the purpose of IGMP snooping, it would be more convenient if we did the local port last. Therefore this patch rearranges the bridge input processing so that the local bridge port gets to see the packet last (if at all). Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_input.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 5ee1a3682bf2..9589937e1c0a 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -73,9 +73,6 @@ int br_handle_frame_finish(struct sk_buff *skb) if (skb2 == skb) skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) - br_pass_frame_up(br, skb2); - if (skb) { if (dst) br_forward(dst->dst, skb); @@ -83,6 +80,9 @@ int br_handle_frame_finish(struct sk_buff *skb) br_flood_forward(br, skb); } + if (skb2) + br_pass_frame_up(br, skb2); + out: return 0; drop: -- cgit v1.2.3 From 68b7c895be336b19f4c38d7cb500132fabba0afd Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:40 +0000 Subject: bridge: Allow tail-call on br_pass_frame_up This patch allows tail-call on the call to br_pass_frame_up in br_handle_frame_finish. This is now possible because of the previous patch to call br_pass_frame_up last. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_input.c | 12 +++++++----- net/bridge/br_private.h | 6 ++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 9589937e1c0a..be5ab8df6661 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -20,9 +20,9 @@ /* Bridge group multicast address 802.1d (pg 51). */ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; -static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) +static int br_pass_frame_up(struct sk_buff *skb) { - struct net_device *indev, *brdev = br->dev; + struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; brdev->stats.rx_packets++; brdev->stats.rx_bytes += skb->len; @@ -30,8 +30,8 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) indev = skb->dev; skb->dev = brdev; - NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, - netif_receive_skb); + return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, + netif_receive_skb); } /* note: already called with rcu_read_lock (preempt_disabled) */ @@ -53,6 +53,8 @@ int br_handle_frame_finish(struct sk_buff *skb) if (p->state == BR_STATE_LEARNING) goto drop; + BR_INPUT_SKB_CB(skb)->brdev = br->dev; + /* The packet skb2 goes to the local host (NULL to skip). */ skb2 = NULL; @@ -81,7 +83,7 @@ int br_handle_frame_finish(struct sk_buff *skb) } if (skb2) - br_pass_frame_up(br, skb2); + return br_pass_frame_up(skb2); out: return 0; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1f0c4f44b765..16513793156e 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -131,6 +131,12 @@ struct net_bridge struct kobject *ifobj; }; +struct br_input_skb_cb { + struct net_device *brdev; +}; + +#define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) + extern struct notifier_block br_device_notifier; extern const u8 br_group_address[ETH_ALEN]; -- cgit v1.2.3 From b33084be192ee1e347d98bb5c9e38a53d98d35e2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:41 +0000 Subject: bridge: Avoid unnecessary clone on forward path When the packet is delivered to the local bridge device we may end up cloning it unnecessarily if no bridge port can receive the packet in br_flood. This patch avoids this by moving the skb_clone into br_flood. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_forward.c | 33 ++++++++++++++++++++++----------- net/bridge/br_input.c | 5 +---- net/bridge/br_private.h | 3 ++- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index bc1704ac6cd9..6cd50c6e57cf 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -105,8 +105,9 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) /* called under bridge lock */ static void br_flood(struct net_bridge *br, struct sk_buff *skb, - void (*__packet_hook)(const struct net_bridge_port *p, - struct sk_buff *skb)) + struct sk_buff *skb0, + void (*__packet_hook)(const struct net_bridge_port *p, + struct sk_buff *skb)) { struct net_bridge_port *p; struct net_bridge_port *prev; @@ -120,8 +121,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { br->dev->stats.tx_dropped++; - kfree_skb(skb); - return; + goto out; } __packet_hook(prev, skb2); @@ -131,23 +131,34 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, } } - if (prev != NULL) { - __packet_hook(prev, skb); - return; + if (!prev) + goto out; + + if (skb0) { + skb = skb_clone(skb, GFP_ATOMIC); + if (!skb) { + br->dev->stats.tx_dropped++; + goto out; + } } + __packet_hook(prev, skb); + return; - kfree_skb(skb); +out: + if (!skb0) + kfree_skb(skb); } /* called with rcu_read_lock */ void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) { - br_flood(br, skb, __br_deliver); + br_flood(br, skb, NULL, __br_deliver); } /* called under bridge lock */ -void br_flood_forward(struct net_bridge *br, struct sk_buff *skb) +void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, + struct sk_buff *skb2) { - br_flood(br, skb, __br_forward); + br_flood(br, skb, skb2, __br_forward); } diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index be5ab8df6661..edfdaef44296 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -72,14 +72,11 @@ int br_handle_frame_finish(struct sk_buff *skb) skb = NULL; } - if (skb2 == skb) - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb) { if (dst) br_forward(dst->dst, skb); else - br_flood_forward(br, skb); + br_flood_forward(br, skb, skb2); } if (skb2) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 16513793156e..fad5a2669d34 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -180,7 +180,8 @@ extern void br_forward(const struct net_bridge_port *to, struct sk_buff *skb); extern int br_forward_finish(struct sk_buff *skb); extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); -extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb); +extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, + struct sk_buff *skb2); /* br_if.c */ extern void br_port_carrier_check(struct net_bridge_port *p); -- cgit v1.2.3 From 6088a539d8d1666dca6979b5759bf966ee9124ef Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:42 +0000 Subject: bridge: Use BR_INPUT_SKB_CB on xmit path this patch makes BR_INPUT_SKB_CB available on the xmit path so that we could avoid passing the br pointer around for the purpose of collecting device statistics. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_device.c | 2 ++ net/bridge/br_forward.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 1a99c4e04e85..be356293caa1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -26,6 +26,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; + BR_INPUT_SKB_CB(skb)->brdev = dev; + dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 6cd50c6e57cf..2e1cb434f6cd 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -111,6 +111,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, { struct net_bridge_port *p; struct net_bridge_port *prev; + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; prev = NULL; @@ -120,7 +121,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb2; if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { - br->dev->stats.tx_dropped++; + dev->stats.tx_dropped++; goto out; } @@ -137,7 +138,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, if (skb0) { skb = skb_clone(skb, GFP_ATOMIC); if (!skb) { - br->dev->stats.tx_dropped++; + dev->stats.tx_dropped++; goto out; } } -- cgit v1.2.3 From 025d89c27f54c69cd0e51666d88aada33666bb6c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:43 +0000 Subject: bridge: Split may_deliver/deliver_clone out of br_flood This patch moves the main loop body in br_flood into the function may_deliver. The code that clones an skb and delivers it is moved into the deliver_clone function. This allows this to be reused by the future multicast forward function. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_forward.c | 69 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2e1cb434f6cd..86cd0712d63e 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -11,6 +11,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -103,6 +104,44 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) kfree_skb(skb); } +static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, + void (*__packet_hook)(const struct net_bridge_port *p, + struct sk_buff *skb)) +{ + skb = skb_clone(skb, GFP_ATOMIC); + if (!skb) { + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + + dev->stats.tx_dropped++; + return -ENOMEM; + } + + __packet_hook(prev, skb); + return 0; +} + +static struct net_bridge_port *maybe_deliver( + struct net_bridge_port *prev, struct net_bridge_port *p, + struct sk_buff *skb, + void (*__packet_hook)(const struct net_bridge_port *p, + struct sk_buff *skb)) +{ + int err; + + if (!should_deliver(p, skb)) + return prev; + + if (!prev) + goto out; + + err = deliver_clone(prev, skb, __packet_hook); + if (err) + return ERR_PTR(err); + +out: + return p; +} + /* called under bridge lock */ static void br_flood(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb0, @@ -111,38 +150,22 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, { struct net_bridge_port *p; struct net_bridge_port *prev; - struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; prev = NULL; list_for_each_entry_rcu(p, &br->port_list, list) { - if (should_deliver(p, skb)) { - if (prev != NULL) { - struct sk_buff *skb2; - - if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { - dev->stats.tx_dropped++; - goto out; - } - - __packet_hook(prev, skb2); - } - - prev = p; - } + prev = maybe_deliver(prev, p, skb, __packet_hook); + if (IS_ERR(prev)) + goto out; } if (!prev) goto out; - if (skb0) { - skb = skb_clone(skb, GFP_ATOMIC); - if (!skb) { - dev->stats.tx_dropped++; - goto out; - } - } - __packet_hook(prev, skb); + if (skb0) + deliver_clone(prev, skb, __packet_hook); + else + __packet_hook(prev, skb); return; out: -- cgit v1.2.3 From eb1d16414339a6e113d89e2cca2556005d7ce919 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:45 +0000 Subject: bridge: Add core IGMP snooping support This patch adds the core functionality of IGMP snooping support without actually hooking it up. So this patch should be a no-op as far as the bridge's external behaviour is concerned. All the new code and data is controlled by the Kconfig option BRIDGE_IGMP_SNOOPING. A run-time toggle is also available. The multicast switching is done using an hash table that is lockless on the read-side through RCU. On the write-side the new multicast_lock is used for all operations. The hash table supports dynamic growth/rehashing. The hash table will be rehashed if any chain length exceeds a preset limit. If rehashing does not reduce the maximum chain length then snooping will be disabled. These features may be added in future (in no particular order): * IGMPv3 source support * Non-querier router detection * IPv6 Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/Kconfig | 12 + net/bridge/Makefile | 2 + net/bridge/br_multicast.c | 1135 +++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 139 ++++++ 4 files changed, 1288 insertions(+) create mode 100644 net/bridge/br_multicast.c diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index e143ca678881..78dd5497210a 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig @@ -31,3 +31,15 @@ config BRIDGE will be called bridge. If unsure, say N. + +config BRIDGE_IGMP_SNOOPING + bool "IGMP snooping" + default y + ---help--- + If you say Y here, then the Ethernet bridge will be able selectively + forward multicast traffic based on IGMP traffic received from each + port. + + Say N to exclude this support and reduce the binary size. + + If unsure, say Y. diff --git a/net/bridge/Makefile b/net/bridge/Makefile index f444c12cde5a..d0359ea8ee79 100644 --- a/net/bridge/Makefile +++ b/net/bridge/Makefile @@ -12,4 +12,6 @@ bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o +bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o + obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/ diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c new file mode 100644 index 000000000000..746b5a611aae --- /dev/null +++ b/net/bridge/br_multicast.c @@ -0,0 +1,1135 @@ +/* + * Bridge multicast support. + * + * Copyright (c) 2010 Herbert Xu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "br_private.h" + +static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) +{ + return jhash_1word(mdb->secret, (u32)ip) & (mdb->max - 1); +} + +static struct net_bridge_mdb_entry *__br_mdb_ip_get( + struct net_bridge_mdb_htable *mdb, __be32 dst, int hash) +{ + struct net_bridge_mdb_entry *mp; + struct hlist_node *p; + + hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { + if (dst == mp->addr) + return mp; + } + + return NULL; +} + +static struct net_bridge_mdb_entry *br_mdb_ip_get( + struct net_bridge_mdb_htable *mdb, __be32 dst) +{ + return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); +} + +struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, + struct sk_buff *skb) +{ + struct net_bridge_mdb_htable *mdb = br->mdb; + + if (!mdb || br->multicast_disabled) + return NULL; + + switch (skb->protocol) { + case htons(ETH_P_IP): + if (BR_INPUT_SKB_CB(skb)->igmp) + break; + return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr); + } + + return NULL; +} + +static void br_mdb_free(struct rcu_head *head) +{ + struct net_bridge_mdb_htable *mdb = + container_of(head, struct net_bridge_mdb_htable, rcu); + struct net_bridge_mdb_htable *old = mdb->old; + + mdb->old = NULL; + kfree(old->mhash); + kfree(old); +} + +static int br_mdb_copy(struct net_bridge_mdb_htable *new, + struct net_bridge_mdb_htable *old, + int elasticity) +{ + struct net_bridge_mdb_entry *mp; + struct hlist_node *p; + int maxlen; + int len; + int i; + + for (i = 0; i < old->max; i++) + hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) + hlist_add_head(&mp->hlist[new->ver], + &new->mhash[br_ip_hash(new, mp->addr)]); + + if (!elasticity) + return 0; + + maxlen = 0; + for (i = 0; i < new->max; i++) { + len = 0; + hlist_for_each_entry(mp, p, &new->mhash[i], hlist[new->ver]) + len++; + if (len > maxlen) + maxlen = len; + } + + return maxlen > elasticity ? -EINVAL : 0; +} + +static void br_multicast_free_pg(struct rcu_head *head) +{ + struct net_bridge_port_group *p = + container_of(head, struct net_bridge_port_group, rcu); + + kfree(p); +} + +static void br_multicast_free_group(struct rcu_head *head) +{ + struct net_bridge_mdb_entry *mp = + container_of(head, struct net_bridge_mdb_entry, rcu); + + kfree(mp); +} + +static void br_multicast_group_expired(unsigned long data) +{ + struct net_bridge_mdb_entry *mp = (void *)data; + struct net_bridge *br = mp->br; + struct net_bridge_mdb_htable *mdb; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || timer_pending(&mp->timer)) + goto out; + + if (!hlist_unhashed(&mp->mglist)) + hlist_del_init(&mp->mglist); + + if (mp->ports) + goto out; + + mdb = br->mdb; + hlist_del_rcu(&mp->hlist[mdb->ver]); + mdb->size--; + + del_timer(&mp->query_timer); + call_rcu_bh(&mp->rcu, br_multicast_free_group); + +out: + spin_unlock(&br->multicast_lock); +} + +static void br_multicast_del_pg(struct net_bridge *br, + struct net_bridge_port_group *pg) +{ + struct net_bridge_mdb_htable *mdb = br->mdb; + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *p; + struct net_bridge_port_group **pp; + + mp = br_mdb_ip_get(mdb, pg->addr); + if (WARN_ON(!mp)) + return; + + for (pp = &mp->ports; (p = *pp); pp = &p->next) { + if (p != pg) + continue; + + *pp = p->next; + hlist_del_init(&p->mglist); + del_timer(&p->timer); + del_timer(&p->query_timer); + call_rcu_bh(&p->rcu, br_multicast_free_pg); + + if (!mp->ports && hlist_unhashed(&mp->mglist) && + netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + + return; + } + + WARN_ON(1); +} + +static void br_multicast_port_group_expired(unsigned long data) +{ + struct net_bridge_port_group *pg = (void *)data; + struct net_bridge *br = pg->port->br; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || timer_pending(&pg->timer) || + hlist_unhashed(&pg->mglist)) + goto out; + + br_multicast_del_pg(br, pg); + +out: + spin_unlock(&br->multicast_lock); +} + +static int br_mdb_rehash(struct net_bridge_mdb_htable **mdbp, int max, + int elasticity) +{ + struct net_bridge_mdb_htable *old = *mdbp; + struct net_bridge_mdb_htable *mdb; + int err; + + mdb = kmalloc(sizeof(*mdb), GFP_ATOMIC); + if (!mdb) + return -ENOMEM; + + mdb->max = max; + mdb->old = old; + + mdb->mhash = kzalloc(max * sizeof(*mdb->mhash), GFP_ATOMIC); + if (!mdb->mhash) { + kfree(mdb); + return -ENOMEM; + } + + mdb->size = old ? old->size : 0; + mdb->ver = old ? old->ver ^ 1 : 0; + + if (!old || elasticity) + get_random_bytes(&mdb->secret, sizeof(mdb->secret)); + else + mdb->secret = old->secret; + + if (!old) + goto out; + + err = br_mdb_copy(mdb, old, elasticity); + if (err) { + kfree(mdb->mhash); + kfree(mdb); + return err; + } + + call_rcu_bh(&mdb->rcu, br_mdb_free); + +out: + rcu_assign_pointer(*mdbp, mdb); + + return 0; +} + +static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, + __be32 group) +{ + struct sk_buff *skb; + struct igmphdr *ih; + struct ethhdr *eth; + struct iphdr *iph; + + skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*eth) + sizeof(*iph) + + sizeof(*ih) + 4); + if (!skb) + goto out; + + skb->protocol = htons(ETH_P_IP); + + skb_reset_mac_header(skb); + eth = eth_hdr(skb); + + memcpy(eth->h_source, br->dev->dev_addr, 6); + eth->h_dest[0] = 1; + eth->h_dest[1] = 0; + eth->h_dest[2] = 0x5e; + eth->h_dest[3] = 0; + eth->h_dest[4] = 0; + eth->h_dest[5] = 1; + eth->h_proto = htons(ETH_P_IP); + skb_put(skb, sizeof(*eth)); + + skb_set_network_header(skb, skb->len); + iph = ip_hdr(skb); + + iph->version = 4; + iph->ihl = 6; + iph->tos = 0xc0; + iph->tot_len = htons(sizeof(*iph) + sizeof(*ih) + 4); + iph->id = 0; + iph->frag_off = htons(IP_DF); + iph->ttl = 1; + iph->protocol = IPPROTO_IGMP; + iph->saddr = 0; + iph->daddr = htonl(INADDR_ALLHOSTS_GROUP); + ((u8 *)&iph[1])[0] = IPOPT_RA; + ((u8 *)&iph[1])[1] = 4; + ((u8 *)&iph[1])[2] = 0; + ((u8 *)&iph[1])[3] = 0; + ip_send_check(iph); + skb_put(skb, 24); + + skb_set_transport_header(skb, skb->len); + ih = igmp_hdr(skb); + ih->type = IGMP_HOST_MEMBERSHIP_QUERY; + ih->code = (group ? br->multicast_last_member_interval : + br->multicast_query_response_interval) / + (HZ / IGMP_TIMER_SCALE); + ih->group = group; + ih->csum = 0; + ih->csum = ip_compute_csum((void *)ih, sizeof(struct igmphdr)); + skb_put(skb, sizeof(*ih)); + + __skb_pull(skb, sizeof(*eth)); + +out: + return skb; +} + +static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) +{ + struct net_bridge *br = mp->br; + struct sk_buff *skb; + + skb = br_multicast_alloc_query(br, mp->addr); + if (!skb) + goto timer; + + netif_rx(skb); + +timer: + if (++mp->queries_sent < br->multicast_last_member_count) + mod_timer(&mp->query_timer, + jiffies + br->multicast_last_member_interval); +} + +static void br_multicast_group_query_expired(unsigned long data) +{ + struct net_bridge_mdb_entry *mp = (void *)data; + struct net_bridge *br = mp->br; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || hlist_unhashed(&mp->mglist) || + mp->queries_sent >= br->multicast_last_member_count) + goto out; + + br_multicast_send_group_query(mp); + +out: + spin_unlock(&br->multicast_lock); +} + +static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) +{ + struct net_bridge_port *port = pg->port; + struct net_bridge *br = port->br; + struct sk_buff *skb; + + skb = br_multicast_alloc_query(br, pg->addr); + if (!skb) + goto timer; + + br_deliver(port, skb); + +timer: + if (++pg->queries_sent < br->multicast_last_member_count) + mod_timer(&pg->query_timer, + jiffies + br->multicast_last_member_interval); +} + +static void br_multicast_port_group_query_expired(unsigned long data) +{ + struct net_bridge_port_group *pg = (void *)data; + struct net_bridge_port *port = pg->port; + struct net_bridge *br = port->br; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || + pg->queries_sent >= br->multicast_last_member_count) + goto out; + + br_multicast_send_port_group_query(pg); + +out: + spin_unlock(&br->multicast_lock); +} + +static struct net_bridge_mdb_entry *br_multicast_get_group( + struct net_bridge *br, struct net_bridge_port *port, __be32 group, + int hash) +{ + struct net_bridge_mdb_htable *mdb = br->mdb; + struct net_bridge_mdb_entry *mp; + struct hlist_node *p; + unsigned count = 0; + unsigned max; + int elasticity; + int err; + + hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { + count++; + if (unlikely(group == mp->addr)) { + return mp; + } + } + + elasticity = 0; + max = mdb->max; + + if (unlikely(count > br->hash_elasticity && count)) { + if (net_ratelimit()) + printk(KERN_INFO "%s: Multicast hash table " + "chain limit reached: %s\n", + br->dev->name, port ? port->dev->name : + br->dev->name); + + elasticity = br->hash_elasticity; + } + + if (mdb->size >= max) { + max *= 2; + if (unlikely(max >= br->hash_max)) { + printk(KERN_WARNING "%s: Multicast hash table maximum " + "reached, disabling snooping: %s, %d\n", + br->dev->name, port ? port->dev->name : + br->dev->name, + max); + err = -E2BIG; +disable: + br->multicast_disabled = 1; + goto err; + } + } + + if (max > mdb->max || elasticity) { + if (mdb->old) { + if (net_ratelimit()) + printk(KERN_INFO "%s: Multicast hash table " + "on fire: %s\n", + br->dev->name, port ? port->dev->name : + br->dev->name); + err = -EEXIST; + goto err; + } + + err = br_mdb_rehash(&br->mdb, max, elasticity); + if (err) { + printk(KERN_WARNING "%s: Cannot rehash multicast " + "hash table, disabling snooping: " + "%s, %d, %d\n", + br->dev->name, port ? port->dev->name : + br->dev->name, + mdb->size, err); + goto disable; + } + + err = -EAGAIN; + goto err; + } + + return NULL; + +err: + mp = ERR_PTR(err); + return mp; +} + +static struct net_bridge_mdb_entry *br_multicast_new_group( + struct net_bridge *br, struct net_bridge_port *port, __be32 group) +{ + struct net_bridge_mdb_htable *mdb = br->mdb; + struct net_bridge_mdb_entry *mp; + int hash; + + if (!mdb) { + if (br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0)) + return NULL; + goto rehash; + } + + hash = br_ip_hash(mdb, group); + mp = br_multicast_get_group(br, port, group, hash); + switch (PTR_ERR(mp)) { + case 0: + break; + + case -EAGAIN: +rehash: + mdb = br->mdb; + hash = br_ip_hash(mdb, group); + break; + + default: + goto out; + } + + mp = kzalloc(sizeof(*mp), GFP_ATOMIC); + if (unlikely(!mp)) + goto out; + + mp->br = br; + mp->addr = group; + setup_timer(&mp->timer, br_multicast_group_expired, + (unsigned long)mp); + setup_timer(&mp->query_timer, br_multicast_group_query_expired, + (unsigned long)mp); + + hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); + mdb->size++; + +out: + return mp; +} + +static int br_multicast_add_group(struct net_bridge *br, + struct net_bridge_port *port, __be32 group) +{ + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *p; + struct net_bridge_port_group **pp; + unsigned long now = jiffies; + int err; + + if (ipv4_is_local_multicast(group)) + return 0; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || + (port && port->state == BR_STATE_DISABLED)) + goto out; + + mp = br_multicast_new_group(br, port, group); + err = PTR_ERR(mp); + if (unlikely(IS_ERR(mp) || !mp)) + goto err; + + if (!port) { + hlist_add_head(&mp->mglist, &br->mglist); + mod_timer(&mp->timer, now + br->multicast_membership_interval); + goto out; + } + + for (pp = &mp->ports; (p = *pp); pp = &p->next) { + if (p->port == port) + goto found; + if ((unsigned long)p->port < (unsigned long)port) + break; + } + + p = kzalloc(sizeof(*p), GFP_ATOMIC); + err = -ENOMEM; + if (unlikely(!p)) + goto err; + + p->addr = group; + p->port = port; + p->next = *pp; + hlist_add_head(&p->mglist, &port->mglist); + setup_timer(&p->timer, br_multicast_port_group_expired, + (unsigned long)p); + setup_timer(&p->query_timer, br_multicast_port_group_query_expired, + (unsigned long)p); + + rcu_assign_pointer(*pp, p); + +found: + mod_timer(&p->timer, now + br->multicast_membership_interval); +out: + err = 0; + +err: + spin_unlock(&br->multicast_lock); + return err; +} + +static void br_multicast_router_expired(unsigned long data) +{ + struct net_bridge_port *port = (void *)data; + struct net_bridge *br = port->br; + + spin_lock(&br->multicast_lock); + if (port->multicast_router != 1 || + timer_pending(&port->multicast_router_timer) || + hlist_unhashed(&port->rlist)) + goto out; + + hlist_del_init_rcu(&port->rlist); + +out: + spin_unlock(&br->multicast_lock); +} + +static void br_multicast_local_router_expired(unsigned long data) +{ +} + +static void br_multicast_send_query(struct net_bridge *br, + struct net_bridge_port *port, u32 sent) +{ + unsigned long time; + struct sk_buff *skb; + + if (!netif_running(br->dev) || br->multicast_disabled || + timer_pending(&br->multicast_querier_timer)) + return; + + skb = br_multicast_alloc_query(br, 0); + if (!skb) + goto timer; + + if (port) { + __skb_push(skb, sizeof(struct ethhdr)); + skb->dev = port->dev; + NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, + dev_queue_xmit); + } else + netif_rx(skb); + +timer: + time = jiffies; + time += sent < br->multicast_startup_query_count ? + br->multicast_startup_query_interval : + br->multicast_query_interval; + mod_timer(port ? &port->multicast_query_timer : + &br->multicast_query_timer, time); +} + +static void br_multicast_port_query_expired(unsigned long data) +{ + struct net_bridge_port *port = (void *)data; + struct net_bridge *br = port->br; + + spin_lock(&br->multicast_lock); + if (port && (port->state == BR_STATE_DISABLED || + port->state == BR_STATE_BLOCKING)) + goto out; + + if (port->multicast_startup_queries_sent < + br->multicast_startup_query_count) + port->multicast_startup_queries_sent++; + + br_multicast_send_query(port->br, port, + port->multicast_startup_queries_sent); + +out: + spin_unlock(&br->multicast_lock); +} + +void br_multicast_add_port(struct net_bridge_port *port) +{ + port->multicast_router = 1; + + setup_timer(&port->multicast_router_timer, br_multicast_router_expired, + (unsigned long)port); + setup_timer(&port->multicast_query_timer, + br_multicast_port_query_expired, (unsigned long)port); +} + +void br_multicast_del_port(struct net_bridge_port *port) +{ + del_timer_sync(&port->multicast_router_timer); +} + +void br_multicast_enable_port(struct net_bridge_port *port) +{ + struct net_bridge *br = port->br; + + spin_lock(&br->multicast_lock); + if (br->multicast_disabled || !netif_running(br->dev)) + goto out; + + port->multicast_startup_queries_sent = 0; + + if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || + del_timer(&port->multicast_query_timer)) + mod_timer(&port->multicast_query_timer, jiffies); + +out: + spin_unlock(&br->multicast_lock); +} + +void br_multicast_disable_port(struct net_bridge_port *port) +{ + struct net_bridge *br = port->br; + struct net_bridge_port_group *pg; + struct hlist_node *p, *n; + + spin_lock(&br->multicast_lock); + hlist_for_each_entry_safe(pg, p, n, &port->mglist, mglist) + br_multicast_del_pg(br, pg); + + if (!hlist_unhashed(&port->rlist)) + hlist_del_init_rcu(&port->rlist); + del_timer(&port->multicast_router_timer); + del_timer(&port->multicast_query_timer); + spin_unlock(&br->multicast_lock); +} + +static int br_multicast_igmp3_report(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + struct igmpv3_report *ih; + struct igmpv3_grec *grec; + int i; + int len; + int num; + int type; + int err = 0; + __be32 group; + + if (!pskb_may_pull(skb, sizeof(*ih))) + return -EINVAL; + + ih = igmpv3_report_hdr(skb); + num = ntohs(ih->ngrec); + len = sizeof(*ih); + + for (i = 0; i < num; i++) { + len += sizeof(*grec); + if (!pskb_may_pull(skb, len)) + return -EINVAL; + + grec = (void *)(skb->data + len); + group = grec->grec_mca; + type = grec->grec_type; + + len += grec->grec_nsrcs * 4; + if (!pskb_may_pull(skb, len)) + return -EINVAL; + + /* We treat this as an IGMPv2 report for now. */ + switch (type) { + case IGMPV3_MODE_IS_INCLUDE: + case IGMPV3_MODE_IS_EXCLUDE: + case IGMPV3_CHANGE_TO_INCLUDE: + case IGMPV3_CHANGE_TO_EXCLUDE: + case IGMPV3_ALLOW_NEW_SOURCES: + case IGMPV3_BLOCK_OLD_SOURCES: + break; + + default: + continue; + } + + err = br_multicast_add_group(br, port, group); + if (err) + break; + } + + return err; +} + +static void br_multicast_mark_router(struct net_bridge *br, + struct net_bridge_port *port) +{ + unsigned long now = jiffies; + struct hlist_node *p; + struct hlist_node **h; + + if (!port) { + if (br->multicast_router == 1) + mod_timer(&br->multicast_router_timer, + now + br->multicast_querier_interval); + return; + } + + if (port->multicast_router != 1) + return; + + if (!hlist_unhashed(&port->rlist)) + goto timer; + + for (h = &br->router_list.first; + (p = *h) && + (unsigned long)container_of(p, struct net_bridge_port, rlist) > + (unsigned long)port; + h = &p->next) + ; + + port->rlist.pprev = h; + port->rlist.next = p; + rcu_assign_pointer(*h, &port->rlist); + if (p) + p->pprev = &port->rlist.next; + +timer: + mod_timer(&port->multicast_router_timer, + now + br->multicast_querier_interval); +} + +static void br_multicast_query_received(struct net_bridge *br, + struct net_bridge_port *port, + __be32 saddr) +{ + if (saddr) + mod_timer(&br->multicast_querier_timer, + jiffies + br->multicast_querier_interval); + else if (timer_pending(&br->multicast_querier_timer)) + return; + + br_multicast_mark_router(br, port); +} + +static int br_multicast_query(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + struct iphdr *iph = ip_hdr(skb); + struct igmphdr *ih = igmp_hdr(skb); + struct net_bridge_mdb_entry *mp; + struct igmpv3_query *ih3; + struct net_bridge_port_group *p; + struct net_bridge_port_group **pp; + unsigned long max_delay; + unsigned long now = jiffies; + __be32 group; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || + (port && port->state == BR_STATE_DISABLED)) + goto out; + + br_multicast_query_received(br, port, iph->saddr); + + group = ih->group; + + if (skb->len == sizeof(*ih)) { + max_delay = ih->code * (HZ / IGMP_TIMER_SCALE); + + if (!max_delay) { + max_delay = 10 * HZ; + group = 0; + } + } else { + if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) + return -EINVAL; + + ih3 = igmpv3_query_hdr(skb); + if (ih3->nsrcs) + return 0; + + max_delay = ih3->code ? 1 : + IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE); + } + + if (!group) + goto out; + + mp = br_mdb_ip_get(br->mdb, group); + if (!mp) + goto out; + + max_delay *= br->multicast_last_member_count; + + if (!hlist_unhashed(&mp->mglist) && + (timer_pending(&mp->timer) ? + time_after(mp->timer.expires, now + max_delay) : + try_to_del_timer_sync(&mp->timer) >= 0)) + mod_timer(&mp->timer, now + max_delay); + + for (pp = &mp->ports; (p = *pp); pp = &p->next) { + if (timer_pending(&p->timer) ? + time_after(p->timer.expires, now + max_delay) : + try_to_del_timer_sync(&p->timer) >= 0) + mod_timer(&mp->timer, now + max_delay); + } + +out: + spin_unlock(&br->multicast_lock); + return 0; +} + +static void br_multicast_leave_group(struct net_bridge *br, + struct net_bridge_port *port, + __be32 group) +{ + struct net_bridge_mdb_htable *mdb; + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *p; + unsigned long now; + unsigned long time; + + if (ipv4_is_local_multicast(group)) + return; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || + (port && port->state == BR_STATE_DISABLED) || + timer_pending(&br->multicast_querier_timer)) + goto out; + + mdb = br->mdb; + mp = br_mdb_ip_get(mdb, group); + if (!mp) + goto out; + + now = jiffies; + time = now + br->multicast_last_member_count * + br->multicast_last_member_interval; + + if (!port) { + if (!hlist_unhashed(&mp->mglist) && + (timer_pending(&mp->timer) ? + time_after(mp->timer.expires, time) : + try_to_del_timer_sync(&mp->timer) >= 0)) { + mod_timer(&mp->timer, time); + + mp->queries_sent = 0; + mod_timer(&mp->query_timer, now); + } + + goto out; + } + + for (p = mp->ports; p; p = p->next) { + if (p->port != port) + continue; + + if (!hlist_unhashed(&p->mglist) && + (timer_pending(&p->timer) ? + time_after(p->timer.expires, time) : + try_to_del_timer_sync(&p->timer) >= 0)) { + mod_timer(&p->timer, time); + + p->queries_sent = 0; + mod_timer(&p->query_timer, now); + } + + break; + } + +out: + spin_unlock(&br->multicast_lock); +} + +static int br_multicast_ipv4_rcv(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + struct sk_buff *skb2 = skb; + struct iphdr *iph; + struct igmphdr *ih; + unsigned len; + unsigned offset; + int err; + + BR_INPUT_SKB_CB(skb)->igmp = 0; + BR_INPUT_SKB_CB(skb)->mrouters_only = 0; + + /* We treat OOM as packet loss for now. */ + if (!pskb_may_pull(skb, sizeof(*iph))) + return -EINVAL; + + iph = ip_hdr(skb); + + if (iph->ihl < 5 || iph->version != 4) + return -EINVAL; + + if (!pskb_may_pull(skb, ip_hdrlen(skb))) + return -EINVAL; + + iph = ip_hdr(skb); + + if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) + return -EINVAL; + + if (iph->protocol != IPPROTO_IGMP) + return 0; + + len = ntohs(iph->tot_len); + if (skb->len < len || len < ip_hdrlen(skb)) + return -EINVAL; + + if (skb->len > len) { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (!skb2) + return -ENOMEM; + + err = pskb_trim_rcsum(skb2, len); + if (err) + return err; + } + + len -= ip_hdrlen(skb2); + offset = skb_network_offset(skb2) + ip_hdrlen(skb2); + __skb_pull(skb2, offset); + skb_reset_transport_header(skb2); + + err = -EINVAL; + if (!pskb_may_pull(skb2, sizeof(*ih))) + goto out; + + iph = ip_hdr(skb2); + + switch (skb2->ip_summed) { + case CHECKSUM_COMPLETE: + if (!csum_fold(skb2->csum)) + break; + /* fall through */ + case CHECKSUM_NONE: + skb2->csum = 0; + if (skb_checksum_complete(skb2)) + return -EINVAL; + } + + err = 0; + + BR_INPUT_SKB_CB(skb)->igmp = 1; + ih = igmp_hdr(skb2); + + switch (ih->type) { + case IGMP_HOST_MEMBERSHIP_REPORT: + case IGMPV2_HOST_MEMBERSHIP_REPORT: + BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; + err = br_multicast_add_group(br, port, ih->group); + break; + case IGMPV3_HOST_MEMBERSHIP_REPORT: + err = br_multicast_igmp3_report(br, port, skb2); + break; + case IGMP_HOST_MEMBERSHIP_QUERY: + err = br_multicast_query(br, port, skb2); + break; + case IGMP_HOST_LEAVE_MESSAGE: + br_multicast_leave_group(br, port, ih->group); + break; + } + +out: + __skb_push(skb2, offset); + if (skb2 != skb) + kfree_skb(skb2); + return err; +} + +int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, + struct sk_buff *skb) +{ + if (br->multicast_disabled) + return 0; + + switch (skb->protocol) { + case htons(ETH_P_IP): + return br_multicast_ipv4_rcv(br, port, skb); + } + + return 0; +} + +static void br_multicast_query_expired(unsigned long data) +{ + struct net_bridge *br = (void *)data; + + spin_lock(&br->multicast_lock); + if (br->multicast_startup_queries_sent < + br->multicast_startup_query_count) + br->multicast_startup_queries_sent++; + + br_multicast_send_query(br, NULL, br->multicast_startup_queries_sent); + + spin_unlock(&br->multicast_lock); +} + +void br_multicast_init(struct net_bridge *br) +{ + br->hash_elasticity = 4; + br->hash_max = 512; + + br->multicast_router = 1; + br->multicast_last_member_count = 2; + br->multicast_startup_query_count = 2; + + br->multicast_last_member_interval = HZ; + br->multicast_query_response_interval = 10 * HZ; + br->multicast_startup_query_interval = 125 * HZ / 4; + br->multicast_query_interval = 125 * HZ; + br->multicast_querier_interval = 255 * HZ; + br->multicast_membership_interval = 260 * HZ; + + spin_lock_init(&br->multicast_lock); + setup_timer(&br->multicast_router_timer, + br_multicast_local_router_expired, 0); + setup_timer(&br->multicast_querier_timer, + br_multicast_local_router_expired, 0); + setup_timer(&br->multicast_query_timer, br_multicast_query_expired, + (unsigned long)br); +} + +void br_multicast_open(struct net_bridge *br) +{ + br->multicast_startup_queries_sent = 0; + + if (br->multicast_disabled) + return; + + mod_timer(&br->multicast_query_timer, jiffies); +} + +void br_multicast_stop(struct net_bridge *br) +{ + struct net_bridge_mdb_htable *mdb; + struct net_bridge_mdb_entry *mp; + struct hlist_node *p, *n; + u32 ver; + int i; + + del_timer_sync(&br->multicast_router_timer); + del_timer_sync(&br->multicast_querier_timer); + del_timer_sync(&br->multicast_query_timer); + + spin_lock_bh(&br->multicast_lock); + mdb = br->mdb; + if (!mdb) + goto out; + + br->mdb = NULL; + + ver = mdb->ver; + for (i = 0; i < mdb->max; i++) { + hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], + hlist[ver]) { + del_timer(&mp->timer); + del_timer(&mp->query_timer); + call_rcu_bh(&mp->rcu, br_multicast_free_group); + } + } + + if (mdb->old) { + spin_unlock_bh(&br->multicast_lock); + synchronize_rcu_bh(); + spin_lock_bh(&br->multicast_lock); + WARN_ON(mdb->old); + } + + mdb->old = mdb; + call_rcu_bh(&mdb->rcu, br_mdb_free); + +out: + spin_unlock_bh(&br->multicast_lock); +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index fad5a2669d34..44345c9afdd3 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -57,6 +57,41 @@ struct net_bridge_fdb_entry unsigned char is_static; }; +struct net_bridge_port_group { + struct net_bridge_port *port; + struct net_bridge_port_group *next; + struct hlist_node mglist; + struct rcu_head rcu; + struct timer_list timer; + struct timer_list query_timer; + __be32 addr; + u32 queries_sent; +}; + +struct net_bridge_mdb_entry +{ + struct hlist_node hlist[2]; + struct hlist_node mglist; + struct net_bridge *br; + struct net_bridge_port_group *ports; + struct rcu_head rcu; + struct timer_list timer; + struct timer_list query_timer; + __be32 addr; + u32 queries_sent; +}; + +struct net_bridge_mdb_htable +{ + struct hlist_head *mhash; + struct rcu_head rcu; + struct net_bridge_mdb_htable *old; + u32 size; + u32 max; + u32 secret; + u32 ver; +}; + struct net_bridge_port { struct net_bridge *br; @@ -84,6 +119,15 @@ struct net_bridge_port unsigned long flags; #define BR_HAIRPIN_MODE 0x00000001 + +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING + u32 multicast_startup_queries_sent; + unsigned char multicast_router; + struct timer_list multicast_router_timer; + struct timer_list multicast_query_timer; + struct hlist_head mglist; + struct hlist_node rlist; +#endif }; struct net_bridge @@ -124,6 +168,35 @@ struct net_bridge unsigned char topology_change; unsigned char topology_change_detected; +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING + unsigned char multicast_router; + + u8 multicast_disabled:1; + + u32 hash_elasticity; + u32 hash_max; + + u32 multicast_last_member_count; + u32 multicast_startup_queries_sent; + u32 multicast_startup_query_count; + + unsigned long multicast_last_member_interval; + unsigned long multicast_membership_interval; + unsigned long multicast_querier_interval; + unsigned long multicast_query_interval; + unsigned long multicast_query_response_interval; + unsigned long multicast_startup_query_interval; + + spinlock_t multicast_lock; + struct net_bridge_mdb_htable *mdb; + struct hlist_head router_list; + struct hlist_head mglist; + + struct timer_list multicast_router_timer; + struct timer_list multicast_querier_timer; + struct timer_list multicast_query_timer; +#endif + struct timer_list hello_timer; struct timer_list tcn_timer; struct timer_list topology_change_timer; @@ -133,6 +206,8 @@ struct net_bridge struct br_input_skb_cb { struct net_device *brdev; + int igmp; + int mrouters_only; }; #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) @@ -204,6 +279,70 @@ extern struct sk_buff *br_handle_frame(struct net_bridge_port *p, extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg); +/* br_multicast.c */ +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +extern int br_multicast_rcv(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb); +extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, + struct sk_buff *skb); +extern void br_multicast_add_port(struct net_bridge_port *port); +extern void br_multicast_del_port(struct net_bridge_port *port); +extern void br_multicast_enable_port(struct net_bridge_port *port); +extern void br_multicast_disable_port(struct net_bridge_port *port); +extern void br_multicast_init(struct net_bridge *br); +extern void br_multicast_open(struct net_bridge *br); +extern void br_multicast_stop(struct net_bridge *br); +#else +static inline int br_multicast_rcv(struct net_bridge *br, + struct net_bridge_port *port, + struct sk_buff *skb) +{ + return 0; +} + +static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, + struct sk_buff *skb) +{ + return NULL; +} + +static inline void br_multicast_add_port(struct net_bridge_port *port) +{ +} + +static inline void br_multicast_del_port(struct net_bridge_port *port) +{ +} + +static inline void br_multicast_enable_port(struct net_bridge_port *port) +{ +} + +static inline void br_multicast_disable_port(struct net_bridge_port *port) +{ +} + +static inline void br_multicast_init(struct net_bridge *br) +{ +} + +static inline void br_multicast_open(struct net_bridge *br) +{ +} + +static inline void br_multicast_stop(struct net_bridge *br) +{ +} +#endif + +static inline bool br_multicast_is_router(struct net_bridge *br) +{ + return br->multicast_router == 2 || + (br->multicast_router == 1 && + timer_pending(&br->multicast_router_timer)); +} + /* br_netfilter.c */ #ifdef CONFIG_BRIDGE_NETFILTER extern int br_netfilter_init(void); -- cgit v1.2.3 From 5cb5e947d8f82011e3d7e7017e9d10db9a40ae9f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:46 +0000 Subject: bridge: Add multicast forwarding functions This patch adds code to perform selective multicast forwarding. We forward multicast traffic to a set of ports plus all multicast router ports. In order to avoid duplications among these two sets of ports, we order all ports by the numeric value of their pointers. The two lists are then walked in lock-step to eliminate duplicates. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_forward.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 15 +++++++++++ 2 files changed, 82 insertions(+) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 86cd0712d63e..d61e6f741125 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -186,3 +186,70 @@ void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, { br_flood(br, skb, skb2, __br_forward); } + +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +/* called with rcu_read_lock */ +static void br_multicast_flood(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb, struct sk_buff *skb0, + void (*__packet_hook)( + const struct net_bridge_port *p, + struct sk_buff *skb)) +{ + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + struct net_bridge *br = netdev_priv(dev); + struct net_bridge_port *port; + struct net_bridge_port *lport, *rport; + struct net_bridge_port *prev; + struct net_bridge_port_group *p; + struct hlist_node *rp; + + prev = NULL; + + rp = br->router_list.first; + p = mdst ? mdst->ports : NULL; + while (p || rp) { + lport = p ? p->port : NULL; + rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : + NULL; + + port = (unsigned long)lport > (unsigned long)rport ? + lport : rport; + + prev = maybe_deliver(prev, port, skb, __packet_hook); + if (IS_ERR(prev)) + goto out; + + if ((unsigned long)lport >= (unsigned long)port) + p = p->next; + if ((unsigned long)rport >= (unsigned long)port) + rp = rp->next; + } + + if (!prev) + goto out; + + if (skb0) + deliver_clone(prev, skb, __packet_hook); + else + __packet_hook(prev, skb); + return; + +out: + if (!skb0) + kfree_skb(skb); +} + +/* called with rcu_read_lock */ +void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb) +{ + br_multicast_flood(mdst, skb, NULL, __br_deliver); +} + +/* called with rcu_read_lock */ +void br_multicast_forward(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb, struct sk_buff *skb2) +{ + br_multicast_flood(mdst, skb, skb2, __br_forward); +} +#endif diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 44345c9afdd3..c85943c2b23f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -293,6 +293,10 @@ extern void br_multicast_disable_port(struct net_bridge_port *port); extern void br_multicast_init(struct net_bridge *br); extern void br_multicast_open(struct net_bridge *br); extern void br_multicast_stop(struct net_bridge *br); +extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb); +extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb, struct sk_buff *skb2); #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, @@ -334,6 +338,17 @@ static inline void br_multicast_open(struct net_bridge *br) static inline void br_multicast_stop(struct net_bridge *br) { } + +static inline void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb) +{ +} + +static inline void br_multicast_forward(struct net_bridge_mdb_entry *mdst, + struct sk_buff *skb, + struct sk_buff *skb2) +{ +} #endif static inline bool br_multicast_is_router(struct net_bridge *br) -- cgit v1.2.3 From 3fe2d7c70b747d5d968f4e8fa210676d49d40059 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 28 Feb 2010 00:49:38 -0800 Subject: bridge: Add multicast start/stop hooks This patch hooks up the bridge start/stop and add/delete/disable port functions to the new multicast module. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_device.c | 6 +++++- net/bridge/br_if.c | 4 ++++ net/bridge/br_stp.c | 2 ++ net/bridge/br_stp_if.c | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index be356293caa1..91dffe7574d6 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -51,6 +51,7 @@ static int br_dev_open(struct net_device *dev) br_features_recompute(br); netif_start_queue(dev); br_stp_enable_bridge(br); + br_multicast_open(br); return 0; } @@ -61,7 +62,10 @@ static void br_dev_set_multicast_list(struct net_device *dev) static int br_dev_stop(struct net_device *dev) { - br_stp_disable_bridge(netdev_priv(dev)); + struct net_bridge *br = netdev_priv(dev); + + br_stp_disable_bridge(br); + br_multicast_stop(br); netif_stop_queue(dev); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index bc2b1badab88..b6a3872f5681 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -147,6 +147,8 @@ static void del_nbp(struct net_bridge_port *p) rcu_assign_pointer(dev->br_port, NULL); + br_multicast_del_port(p); + kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); @@ -207,6 +209,7 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name) br_netfilter_rtable_init(br); br_stp_timer_init(br); + br_multicast_init(br); return dev; } @@ -258,6 +261,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, br_init_port(p); p->state = BR_STATE_DISABLED; br_stp_port_timer_init(p); + br_multicast_add_port(p); return p; } diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index fd3f8d6c0998..edcf14b560f6 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -386,6 +386,8 @@ static void br_make_forwarding(struct net_bridge_port *p) else p->state = BR_STATE_LEARNING; + br_multicast_enable_port(p); + br_log_state(p); if (br->forward_delay != 0) diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 9a52ac5b4525..d527119e9f54 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -108,6 +108,7 @@ void br_stp_disable_port(struct net_bridge_port *p) del_timer(&p->hold_timer); br_fdb_delete_by_port(br, p, 0); + br_multicast_disable_port(p); br_configuration_update(br); -- cgit v1.2.3 From c4fcb78cf8ae55667809e54e54872a21025dd073 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:48 +0000 Subject: bridge: Add multicast data-path hooks This patch finally hooks up the multicast snooping module to the data path. In particular, all multicast packets passing through the bridge are fed into the module and switched by it. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_device.c | 15 ++++++++++++--- net/bridge/br_input.c | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 91dffe7574d6..eb7062d2e9e5 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -25,6 +25,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct net_bridge *br = netdev_priv(dev); const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; + struct net_bridge_mdb_entry *mdst; BR_INPUT_SKB_CB(skb)->brdev = dev; @@ -34,13 +35,21 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); - if (dest[0] & 1) - br_flood_deliver(br, skb); - else if ((dst = __br_fdb_get(br, dest)) != NULL) + if (dest[0] & 1) { + if (br_multicast_rcv(br, NULL, skb)) + goto out; + + mdst = br_mdb_get(br, skb); + if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) + br_multicast_deliver(mdst, skb); + else + br_flood_deliver(br, skb); + } else if ((dst = __br_fdb_get(br, dest)) != NULL) br_deliver(dst->dst, skb); else br_flood_deliver(br, skb); +out: return NETDEV_TX_OK; } diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index edfdaef44296..53b39851d87d 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -41,6 +41,7 @@ int br_handle_frame_finish(struct sk_buff *skb) struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); struct net_bridge *br; struct net_bridge_fdb_entry *dst; + struct net_bridge_mdb_entry *mdst; struct sk_buff *skb2; if (!p || p->state == BR_STATE_DISABLED) @@ -50,6 +51,10 @@ int br_handle_frame_finish(struct sk_buff *skb) br = p->br; br_fdb_update(br, p, eth_hdr(skb)->h_source); + if (is_multicast_ether_addr(dest) && + br_multicast_rcv(br, p, skb)) + goto drop; + if (p->state == BR_STATE_LEARNING) goto drop; @@ -64,8 +69,19 @@ int br_handle_frame_finish(struct sk_buff *skb) dst = NULL; if (is_multicast_ether_addr(dest)) { + mdst = br_mdb_get(br, skb); + if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) { + if ((mdst && !hlist_unhashed(&mdst->mglist)) || + br_multicast_is_router(br)) + skb2 = skb; + br_multicast_forward(mdst, skb, skb2); + skb = NULL; + if (!skb2) + goto out; + } else + skb2 = skb; + br->dev->stats.multicast++; - skb2 = skb; } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { skb2 = skb; /* Do not forward the packet since it's local. */ -- cgit v1.2.3 From 0909e11758bd28848aeb6646e021ec1e031a3f0f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:49 +0000 Subject: bridge: Add multicast_router sysfs entries This patch allows the user to forcibly enable/disable ports as having multicast routers attached. A port with a multicast router will receive all multicast traffic. The value 0 disables it completely. The default is 1 which lets the system automatically detect the presence of routers (currently this is limited to picking up queries), and 2 means that the port will always receive all multicast traffic. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 105 +++++++++++++++++++++++++++++++++++++++------- net/bridge/br_private.h | 3 ++ net/bridge/br_sysfs_br.c | 21 ++++++++++ net/bridge/br_sysfs_if.c | 18 ++++++++ 4 files changed, 133 insertions(+), 14 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 746b5a611aae..674224b6729d 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -746,12 +746,30 @@ static int br_multicast_igmp3_report(struct net_bridge *br, return err; } +static void br_multicast_add_router(struct net_bridge *br, + struct net_bridge_port *port) +{ + struct hlist_node *p; + struct hlist_node **h; + + for (h = &br->router_list.first; + (p = *h) && + (unsigned long)container_of(p, struct net_bridge_port, rlist) > + (unsigned long)port; + h = &p->next) + ; + + port->rlist.pprev = h; + port->rlist.next = p; + rcu_assign_pointer(*h, &port->rlist); + if (p) + p->pprev = &port->rlist.next; +} + static void br_multicast_mark_router(struct net_bridge *br, struct net_bridge_port *port) { unsigned long now = jiffies; - struct hlist_node *p; - struct hlist_node **h; if (!port) { if (br->multicast_router == 1) @@ -766,18 +784,7 @@ static void br_multicast_mark_router(struct net_bridge *br, if (!hlist_unhashed(&port->rlist)) goto timer; - for (h = &br->router_list.first; - (p = *h) && - (unsigned long)container_of(p, struct net_bridge_port, rlist) > - (unsigned long)port; - h = &p->next) - ; - - port->rlist.pprev = h; - port->rlist.next = p; - rcu_assign_pointer(*h, &port->rlist); - if (p) - p->pprev = &port->rlist.next; + br_multicast_add_router(br, port); timer: mod_timer(&port->multicast_router_timer, @@ -1133,3 +1140,73 @@ void br_multicast_stop(struct net_bridge *br) out: spin_unlock_bh(&br->multicast_lock); } + +int br_multicast_set_router(struct net_bridge *br, unsigned long val) +{ + int err = -ENOENT; + + spin_lock_bh(&br->multicast_lock); + if (!netif_running(br->dev)) + goto unlock; + + switch (val) { + case 0: + case 2: + del_timer(&br->multicast_router_timer); + /* fall through */ + case 1: + br->multicast_router = val; + err = 0; + break; + + default: + err = -EINVAL; + break; + } + +unlock: + spin_unlock_bh(&br->multicast_lock); + + return err; +} + +int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) +{ + struct net_bridge *br = p->br; + int err = -ENOENT; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev) || p->state == BR_STATE_DISABLED) + goto unlock; + + switch (val) { + case 0: + case 1: + case 2: + p->multicast_router = val; + err = 0; + + if (val < 2 && !hlist_unhashed(&p->rlist)) + hlist_del_init_rcu(&p->rlist); + + if (val == 1) + break; + + del_timer(&p->multicast_router_timer); + + if (val == 0) + break; + + br_multicast_add_router(br, p); + break; + + default: + err = -EINVAL; + break; + } + +unlock: + spin_unlock(&br->multicast_lock); + + return err; +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c85943c2b23f..dcdfafbe4b17 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -297,6 +297,9 @@ extern void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb); extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, struct sk_buff *skb2); +extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); +extern int br_multicast_set_port_router(struct net_bridge_port *p, + unsigned long val); #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index bee4f300d0c8..cb742016db21 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -345,6 +345,24 @@ static ssize_t store_flush(struct device *d, } static DEVICE_ATTR(flush, S_IWUSR, NULL, store_flush); +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +static ssize_t show_multicast_router(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%d\n", br->multicast_router); +} + +static ssize_t store_multicast_router(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, br_multicast_set_router); +} +static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, + store_multicast_router); +#endif + static struct attribute *bridge_attrs[] = { &dev_attr_forward_delay.attr, &dev_attr_hello_time.attr, @@ -364,6 +382,9 @@ static struct attribute *bridge_attrs[] = { &dev_attr_gc_timer.attr, &dev_attr_group_addr.attr, &dev_attr_flush.attr, +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING + &dev_attr_multicast_router.attr, +#endif NULL }; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 820643a3ba9c..696596cd3384 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -159,6 +159,21 @@ static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v) static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR, show_hairpin_mode, store_hairpin_mode); +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING +static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) +{ + return sprintf(buf, "%d\n", p->multicast_router); +} + +static ssize_t store_multicast_router(struct net_bridge_port *p, + unsigned long v) +{ + return br_multicast_set_port_router(p, v); +} +static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, + store_multicast_router); +#endif + static struct brport_attribute *brport_attrs[] = { &brport_attr_path_cost, &brport_attr_priority, @@ -176,6 +191,9 @@ static struct brport_attribute *brport_attrs[] = { &brport_attr_hold_timer, &brport_attr_flush, &brport_attr_hairpin_mode, +#ifdef CONFIG_BRIDGE_IGMP_SNOOPING + &brport_attr_multicast_router, +#endif NULL }; -- cgit v1.2.3 From 561f1103a2b70de7e06e1e7fd072a5b142a4278c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:50 +0000 Subject: bridge: Add multicast_snooping sysfs toggle This patch allows the user to disable IGMP snooping completely through a sysfs toggle. It also allows the user to reenable snooping when it has been automatically disabled due to hash collisions. If the collisions have not been resolved however the system will refuse to reenable snooping. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 61 +++++++++++++++++++++++++++++++++++++++++++---- net/bridge/br_private.h | 1 + net/bridge/br_sysfs_br.c | 18 ++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 674224b6729d..c7a1095ed84a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -656,6 +656,15 @@ void br_multicast_del_port(struct net_bridge_port *port) del_timer_sync(&port->multicast_router_timer); } +static void __br_multicast_enable_port(struct net_bridge_port *port) +{ + port->multicast_startup_queries_sent = 0; + + if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || + del_timer(&port->multicast_query_timer)) + mod_timer(&port->multicast_query_timer, jiffies); +} + void br_multicast_enable_port(struct net_bridge_port *port) { struct net_bridge *br = port->br; @@ -664,11 +673,7 @@ void br_multicast_enable_port(struct net_bridge_port *port) if (br->multicast_disabled || !netif_running(br->dev)) goto out; - port->multicast_startup_queries_sent = 0; - - if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || - del_timer(&port->multicast_query_timer)) - mod_timer(&port->multicast_query_timer, jiffies); + __br_multicast_enable_port(port); out: spin_unlock(&br->multicast_lock); @@ -1210,3 +1215,49 @@ unlock: return err; } + +int br_multicast_toggle(struct net_bridge *br, unsigned long val) +{ + struct net_bridge_port *port; + int err = -ENOENT; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev)) + goto unlock; + + err = 0; + if (br->multicast_disabled == !val) + goto unlock; + + br->multicast_disabled = !val; + if (br->multicast_disabled) + goto unlock; + + if (br->mdb) { + if (br->mdb->old) { + err = -EEXIST; +rollback: + br->multicast_disabled = !!val; + goto unlock; + } + + err = br_mdb_rehash(&br->mdb, br->mdb->max, + br->hash_elasticity); + if (err) + goto rollback; + } + + br_multicast_open(br); + list_for_each_entry(port, &br->port_list, list) { + if (port->state == BR_STATE_DISABLED || + port->state == BR_STATE_BLOCKING) + continue; + + __br_multicast_enable_port(port); + } + +unlock: + spin_unlock(&br->multicast_lock); + + return err; +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index dcdfafbe4b17..bf162fa6b23b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -300,6 +300,7 @@ extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst, extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); extern int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); +extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index cb742016db21..0ab288332fc5 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -361,6 +361,23 @@ static ssize_t store_multicast_router(struct device *d, } static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, store_multicast_router); + +static ssize_t show_multicast_snooping(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%d\n", !br->multicast_disabled); +} + +static ssize_t store_multicast_snooping(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, br_multicast_toggle); +} +static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, + show_multicast_snooping, store_multicast_snooping); #endif static struct attribute *bridge_attrs[] = { @@ -384,6 +401,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_flush.attr, #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &dev_attr_multicast_router.attr, + &dev_attr_multicast_snooping.attr, #endif NULL }; -- cgit v1.2.3 From b195167fcf089dbdc650bb874084555035f07f98 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:51 +0000 Subject: bridge: Add hash elasticity/max sysfs entries This patch allows the user to control the hash elasticity/max parameters. The elasticity setting does not take effect until the next new multicast group is added. At which point it is checked and if after rehashing it still can't be satisfied then snooping will be disabled. The max setting on the other hand takes effect immediately. It must be a power of two and cannot be set to a value less than the current number of multicast group entries. This is the only way to shrink the multicast hash. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_multicast.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 1 + net/bridge/br_sysfs_br.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index c7a1095ed84a..2559fb539836 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1261,3 +1262,43 @@ unlock: return err; } + +int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) +{ + int err = -ENOENT; + u32 old; + + spin_lock(&br->multicast_lock); + if (!netif_running(br->dev)) + goto unlock; + + err = -EINVAL; + if (!is_power_of_2(val)) + goto unlock; + if (br->mdb && val < br->mdb->size) + goto unlock; + + err = 0; + + old = br->hash_max; + br->hash_max = val; + + if (br->mdb) { + if (br->mdb->old) { + err = -EEXIST; +rollback: + br->hash_max = old; + goto unlock; + } + + err = br_mdb_rehash(&br->mdb, br->hash_max, + br->hash_elasticity); + if (err) + goto rollback; + } + +unlock: + spin_unlock(&br->multicast_lock); + + return err; +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index bf162fa6b23b..9191198c4f1b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -301,6 +301,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); extern int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); +extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 0ab288332fc5..d2ee53b3ad7d 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -378,6 +378,43 @@ static ssize_t store_multicast_snooping(struct device *d, } static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, show_multicast_snooping, store_multicast_snooping); + +static ssize_t show_hash_elasticity(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%u\n", br->hash_elasticity); +} + +static int set_elasticity(struct net_bridge *br, unsigned long val) +{ + br->hash_elasticity = val; + return 0; +} + +static ssize_t store_hash_elasticity(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_elasticity); +} +static DEVICE_ATTR(hash_elasticity, S_IRUGO | S_IWUSR, show_hash_elasticity, + store_hash_elasticity); + +static ssize_t show_hash_max(struct device *d, struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%u\n", br->hash_max); +} + +static ssize_t store_hash_max(struct device *d, struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, br_multicast_set_hash_max); +} +static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max, + store_hash_max); #endif static struct attribute *bridge_attrs[] = { @@ -402,6 +439,8 @@ static struct attribute *bridge_attrs[] = { #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &dev_attr_multicast_router.attr, &dev_attr_multicast_snooping.attr, + &dev_attr_hash_elasticity.attr, + &dev_attr_hash_max.attr, #endif NULL }; -- cgit v1.2.3 From d902eee43f1951b358d7347d9165c6af21cf7b1b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 27 Feb 2010 19:41:52 +0000 Subject: bridge: Add multicast count/interval sysfs entries This patch allows the user to the IGMP parameters related to the snooping function of the bridge. This includes various time values and retransmission limits. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_sysfs_br.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index d2ee53b3ad7d..dd321e39e621 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -415,6 +415,201 @@ static ssize_t store_hash_max(struct device *d, struct device_attribute *attr, } static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max, store_hash_max); + +static ssize_t show_multicast_last_member_count(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%u\n", br->multicast_last_member_count); +} + +static int set_last_member_count(struct net_bridge *br, unsigned long val) +{ + br->multicast_last_member_count = val; + return 0; +} + +static ssize_t store_multicast_last_member_count(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_last_member_count); +} +static DEVICE_ATTR(multicast_last_member_count, S_IRUGO | S_IWUSR, + show_multicast_last_member_count, + store_multicast_last_member_count); + +static ssize_t show_multicast_startup_query_count( + struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%u\n", br->multicast_startup_query_count); +} + +static int set_startup_query_count(struct net_bridge *br, unsigned long val) +{ + br->multicast_startup_query_count = val; + return 0; +} + +static ssize_t store_multicast_startup_query_count( + struct device *d, struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_startup_query_count); +} +static DEVICE_ATTR(multicast_startup_query_count, S_IRUGO | S_IWUSR, + show_multicast_startup_query_count, + store_multicast_startup_query_count); + +static ssize_t show_multicast_last_member_interval( + struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%lu\n", + jiffies_to_clock_t(br->multicast_last_member_interval)); +} + +static int set_last_member_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_last_member_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_last_member_interval( + struct device *d, struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_last_member_interval); +} +static DEVICE_ATTR(multicast_last_member_interval, S_IRUGO | S_IWUSR, + show_multicast_last_member_interval, + store_multicast_last_member_interval); + +static ssize_t show_multicast_membership_interval( + struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%lu\n", + jiffies_to_clock_t(br->multicast_membership_interval)); +} + +static int set_membership_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_membership_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_membership_interval( + struct device *d, struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_membership_interval); +} +static DEVICE_ATTR(multicast_membership_interval, S_IRUGO | S_IWUSR, + show_multicast_membership_interval, + store_multicast_membership_interval); + +static ssize_t show_multicast_querier_interval(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%lu\n", + jiffies_to_clock_t(br->multicast_querier_interval)); +} + +static int set_querier_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_querier_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_querier_interval(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_querier_interval); +} +static DEVICE_ATTR(multicast_querier_interval, S_IRUGO | S_IWUSR, + show_multicast_querier_interval, + store_multicast_querier_interval); + +static ssize_t show_multicast_query_interval(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%lu\n", + jiffies_to_clock_t(br->multicast_query_interval)); +} + +static int set_query_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_query_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_query_interval(struct device *d, + struct device_attribute *attr, + const char *buf, size_t len) +{ + return store_bridge_parm(d, buf, len, set_query_interval); +} +static DEVICE_ATTR(multicast_query_interval, S_IRUGO | S_IWUSR, + show_multicast_query_interval, + store_multicast_query_interval); + +static ssize_t show_multicast_query_response_interval( + struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf( + buf, "%lu\n", + jiffies_to_clock_t(br->multicast_query_response_interval)); +} + +static int set_query_response_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_query_response_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_query_response_interval( + struct device *d, struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_query_response_interval); +} +static DEVICE_ATTR(multicast_query_response_interval, S_IRUGO | S_IWUSR, + show_multicast_query_response_interval, + store_multicast_query_response_interval); + +static ssize_t show_multicast_startup_query_interval( + struct device *d, struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf( + buf, "%lu\n", + jiffies_to_clock_t(br->multicast_startup_query_interval)); +} + +static int set_startup_query_interval(struct net_bridge *br, unsigned long val) +{ + br->multicast_startup_query_interval = clock_t_to_jiffies(val); + return 0; +} + +static ssize_t store_multicast_startup_query_interval( + struct device *d, struct device_attribute *attr, const char *buf, + size_t len) +{ + return store_bridge_parm(d, buf, len, set_startup_query_interval); +} +static DEVICE_ATTR(multicast_startup_query_interval, S_IRUGO | S_IWUSR, + show_multicast_startup_query_interval, + store_multicast_startup_query_interval); #endif static struct attribute *bridge_attrs[] = { @@ -441,6 +636,14 @@ static struct attribute *bridge_attrs[] = { &dev_attr_multicast_snooping.attr, &dev_attr_hash_elasticity.attr, &dev_attr_hash_max.attr, + &dev_attr_multicast_last_member_count.attr, + &dev_attr_multicast_startup_query_count.attr, + &dev_attr_multicast_last_member_interval.attr, + &dev_attr_multicast_membership_interval.attr, + &dev_attr_multicast_querier_interval.attr, + &dev_attr_multicast_query_interval.attr, + &dev_attr_multicast_query_response_interval.attr, + &dev_attr_multicast_startup_query_interval.attr, #endif NULL }; -- cgit v1.2.3 From 024c378f0b719d43b01b875caefa19f2612e103a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 28 Feb 2010 00:51:42 -0800 Subject: bridge: Make IGMP snooping depend upon BRIDGE. Signed-off-by: David S. Miller --- net/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index 78dd5497210a..19a6b9629c51 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig @@ -34,6 +34,7 @@ config BRIDGE config BRIDGE_IGMP_SNOOPING bool "IGMP snooping" + depends on BRIDGE default y ---help--- If you say Y here, then the Ethernet bridge will be able selectively -- cgit v1.2.3 From 60bbc725b5b3009bb1bf2628ce5033d9bc108881 Mon Sep 17 00:00:00 2001 From: Ken Kawasaki Date: Sat, 27 Feb 2010 13:34:20 +0000 Subject: axnet_cs: add new id axnet_cs: add new id (corega PCC-TXM) Signed-off-by: Ken Kawasaki Signed-off-by: David S. Miller --- drivers/net/pcmcia/axnet_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index d90e0fcdbce1..09291e60d309 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -779,6 +779,7 @@ static struct pcmcia_device_id axnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5), PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e), + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061), PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90), PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2), PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), -- cgit v1.2.3 From cf0aa4e07c32b0c211c24742aa015c0e7a135293 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sat, 27 Feb 2010 19:45:37 +0000 Subject: netlink: Adding inode field to /proc/net/netlink The Inode field in /proc/net/{tcp,udp,packet,raw,...} is useful to know the types of file descriptors associated to a process. Actually lsof utility uses the field. Unfortunately, unlike /proc/net/{tcp,udp,packet,raw,...}, /proc/net/netlink doesn't have the field. This patch adds the field to /proc/net/netlink. Signed-off-by: Masatake YAMATO Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 4c5972ba8c78..320d0423a240 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1978,12 +1978,12 @@ static int netlink_seq_show(struct seq_file *seq, void *v) if (v == SEQ_START_TOKEN) seq_puts(seq, "sk Eth Pid Groups " - "Rmem Wmem Dump Locks Drops\n"); + "Rmem Wmem Dump Locks Drops Inode\n"); else { struct sock *s = v; struct netlink_sock *nlk = nlk_sk(s); - seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n", + seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu\n", s, s->sk_protocol, nlk->pid, @@ -1992,7 +1992,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) sk_wmem_alloc_get(s), nlk->cb, atomic_read(&s->sk_refcnt), - atomic_read(&s->sk_drops) + atomic_read(&s->sk_drops), + sock_i_ino(s) ); } -- cgit v1.2.3 From 6c74651c3bce418d3b29edfdeb72664f9441509a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 27 Feb 2010 12:07:33 +0000 Subject: ipoib: returned back addrlen check for mc addresses Apparently bogus mc address can break IPOIB multicast processing. Therefore returning the check for addrlen back until this is resolved in bonding (I don't see any other point from where mc address with non-dev->addr_len length can came from). Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 19eba3c877cb..d41ea27be5e1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -767,8 +767,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -static int ipoib_mcast_addr_is_valid(const u8 *addr, const u8 *broadcast) +static int ipoib_mcast_addr_is_valid(const u8 *addr, unsigned int addrlen, + const u8 *broadcast) { + if (addrlen != INFINIBAND_ALEN) + return 0; /* reserved QPN, prefix, scope */ if (memcmp(addr, broadcast, 6)) return 0; @@ -812,6 +815,7 @@ void ipoib_mcast_restart_task(struct work_struct *work) union ib_gid mgid; if (!ipoib_mcast_addr_is_valid(mclist->dmi_addr, + mclist->dmi_addrlen, dev->broadcast)) continue; -- cgit v1.2.3 From 9675478bbafed08848bf8d7e28400d5e46330b23 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 26 Feb 2010 21:43:38 +0000 Subject: ethtool: do not set some flags, if others failed NETIF_F_NTUPLE flag setting introduced a bug: non-ntuple flags like LRO may be successfully set, before ioctl(2) returns failure to userspace. The set-flags operation should be all-or-none, rather than leaving things in an inconsistent state prior to reporting failure to userspace. Signed-off-by: Jeff Garzik Signed-off-by: David S. Miller --- net/core/ethtool.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 31b1eddc1b84..0f2f82185ec4 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -135,21 +135,23 @@ u32 ethtool_op_get_flags(struct net_device *dev) int ethtool_op_set_flags(struct net_device *dev, u32 data) { const struct ethtool_ops *ops = dev->ethtool_ops; + unsigned long features = dev->features; if (data & ETH_FLAG_LRO) - dev->features |= NETIF_F_LRO; + features |= NETIF_F_LRO; else - dev->features &= ~NETIF_F_LRO; + features &= ~NETIF_F_LRO; if (data & ETH_FLAG_NTUPLE) { if (!ops->set_rx_ntuple) return -EOPNOTSUPP; - dev->features |= NETIF_F_NTUPLE; + features |= NETIF_F_NTUPLE; } else { /* safe to clear regardless */ - dev->features &= ~NETIF_F_NTUPLE; + features &= ~NETIF_F_NTUPLE; } + dev->features = features; return 0; } -- cgit v1.2.3 From 655ffee284dfcf9a24ac0343f3e5ee6db85b85c5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 27 Feb 2010 07:35:45 +0000 Subject: wireless: convert to use netdev_for_each_mc_addr also added missed locking in rndis_wlan.c Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/wireless/libertas/main.c | 8 ++++++-- drivers/net/wireless/orinoco/hw.c | 22 +++++++--------------- drivers/net/wireless/orinoco/hw.h | 2 +- drivers/net/wireless/orinoco/main.c | 3 +-- drivers/net/wireless/ray_cs.c | 8 ++++---- drivers/net/wireless/rndis_wlan.c | 15 ++++++++------- drivers/net/wireless/zd1201.c | 9 ++++----- 7 files changed, 31 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index cd8ed7fdafad..28a1c9d1627a 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -319,15 +319,18 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, { int i = nr_addrs; struct dev_mc_list *mc_list; + int cnt; if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) return nr_addrs; netif_addr_lock_bh(dev); - for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { + cnt = netdev_mc_count(dev); + netdev_for_each_mc_addr(mc_list, dev) { if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, mc_list->dmi_addr); + cnt--; continue; } @@ -337,9 +340,10 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, mc_list->dmi_addr); i++; + cnt--; } netif_addr_unlock_bh(dev); - if (mc_list) + if (cnt) return -EOVERFLOW; return i; diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 404830f47ab2..e6369242e49c 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -1028,7 +1028,7 @@ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx) } int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, - struct dev_addr_list *mc_list, + struct net_device *dev, int mc_count, int promisc) { hermes_t *hw = &priv->hw; @@ -1049,24 +1049,16 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, * group address if either we want to multicast, or if we were * multicasting and want to stop */ if (!promisc && (mc_count || priv->mc_count)) { - struct dev_mc_list *p = mc_list; + struct dev_mc_list *p; struct hermes_multicast mclist; - int i; + int i = 0; - for (i = 0; i < mc_count; i++) { - /* paranoia: is list shorter than mc_count? */ - BUG_ON(!p); - /* paranoia: bad address size in list? */ - BUG_ON(p->dmi_addrlen != ETH_ALEN); - - memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN); - p = p->next; + netdev_for_each_mc_addr(p, dev) { + if (i == mc_count) + break; + memcpy(mclist.addr[i++], p->dmi_addr, ETH_ALEN); } - if (p) - printk(KERN_WARNING "%s: Multicast list is " - "longer than mc_count\n", priv->ndev->name); - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES, HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN), diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index e2f7fdc4d45a..9799a1d14a63 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h @@ -43,7 +43,7 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, u8 *tsc, size_t tsc_len); int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, - struct dev_addr_list *mc_list, + struct net_device *dev, int mc_count, int promisc); int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]); diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index a9e9cea2d767..b42634c614b5 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1676,8 +1676,7 @@ __orinoco_set_multicast_list(struct net_device *dev) mc_count = netdev_mc_count(dev); } - err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count, - promisc); + err = __orinoco_hw_set_multicast_list(priv, dev, mc_count, promisc); return err; } diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 85905cab4f16..84c530aa52f9 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1871,10 +1871,8 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, /*===========================================================================*/ static void ray_update_multi_list(struct net_device *dev, int all) { - struct dev_mc_list *dmi, **dmip; int ccsindex; struct ccs __iomem *pccs; - int i = 0; ray_dev_t *local = netdev_priv(dev); struct pcmcia_device *link = local->finder; void __iomem *p = local->sram + HOST_TO_ECF_BASE; @@ -1895,9 +1893,11 @@ static void ray_update_multi_list(struct net_device *dev, int all) writeb(0xff, &pccs->var); local->num_multi = 0xff; } else { + struct dev_mc_list *dmi; + int i = 0; + /* Copy the kernel's list of MC addresses to card */ - for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; - dmip = &dmi->next) { + netdev_for_each_mc_addr(dmi, dev) { memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); dev_dbg(&link->dev, "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 65cbd060cc30..9f6d6bf06b8e 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1502,6 +1502,7 @@ static void set_multicast_list(struct usbnet *usbdev) filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; + netif_addr_lock_bh(usbdev->net); if (usbdev->net->flags & IFF_PROMISC) { filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | RNDIS_PACKET_TYPE_ALL_LOCAL; @@ -1515,16 +1516,15 @@ static void set_multicast_list(struct usbnet *usbdev) netdev_warn(usbdev->net, "couldn't alloc %d bytes of memory\n", size * ETH_ALEN); + netif_addr_unlock_bh(usbdev->net); return; } - mclist = usbdev->net->mc_list; - for (i = 0; i < size && mclist; mclist = mclist->next) { - if (mclist->dmi_addrlen != ETH_ALEN) - continue; - - memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); - i++; + i = 0; + netdev_for_each_mc_addr(mclist, usbdev->net) { + if (i == size) + break; + memcpy(buf + i++ * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); } ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf, @@ -1539,6 +1539,7 @@ static void set_multicast_list(struct usbnet *usbdev) kfree(buf); } + netif_addr_unlock_bh(usbdev->net); ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter)); diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 5d2b52f4717f..6917286edcae 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -875,17 +875,16 @@ static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) static void zd1201_set_multicast(struct net_device *dev) { struct zd1201 *zd = netdev_priv(dev); - struct dev_mc_list *mc = dev->mc_list; + struct dev_mc_list *mc; unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; int i; if (netdev_mc_count(dev) > ZD1201_MAXMULTI) return; - for (i=0; idmi_addr, ETH_ALEN); - mc = mc->next; - } + i = 0; + netdev_for_each_mc_addr(mc, dev) + memcpy(reqbuf + i++ * ETH_ALEN, mc->dmi_addr, ETH_ALEN); zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, netdev_mc_count(dev) * ETH_ALEN, 0); } -- cgit v1.2.3 From 86e9424d7252bae5ad1c17b4b8088193e6b27cbe Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 17 Feb 2010 19:11:33 +0200 Subject: vhost: logging thinko fix vhost was dong some complex math to get offset to log at, and got it wrong by a couple of bytes, while in fact it's simple: get address where we write, subtract start of buffer, add log base. Do it this way. Reviewed-by: Juan Quintela Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 6eb15259f5ae..db21518f7e8d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1004,10 +1004,14 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) if (unlikely(vq->log_used)) { /* Make sure data is seen before log. */ smp_wmb(); - log_write(vq->log_base, vq->log_addr + sizeof *vq->used->ring * - (vq->last_used_idx % vq->num), - sizeof *vq->used->ring); - log_write(vq->log_base, vq->log_addr, sizeof *vq->used->ring); + /* Log used ring entry write. */ + log_write(vq->log_base, + vq->log_addr + ((void *)used - (void *)vq->used), + sizeof *used); + /* Log used index update. */ + log_write(vq->log_base, + vq->log_addr + offsetof(struct vring_used, idx), + sizeof vq->used->idx); if (vq->log_ctx) eventfd_signal(vq->log_ctx, 1); } -- cgit v1.2.3 From 73a99f083009d67d8e12603420e008d5c21b0b7d Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 23 Feb 2010 11:23:45 +0200 Subject: vhost: initialize log eventfd context pointer vq log eventfd context pointer needs to be initialized, otherwise operation may fail or oops if log is enabled but log eventfd not set by userspace. When log_ctx for device is created, it is copied to the vq. This reset was missing. Reviewed-by: Juan Quintela Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index db21518f7e8d..6c31c0c9bbb9 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -121,6 +121,7 @@ static void vhost_vq_reset(struct vhost_dev *dev, vq->kick = NULL; vq->call_ctx = NULL; vq->call = NULL; + vq->log_ctx = NULL; } long vhost_dev_init(struct vhost_dev *dev, -- cgit v1.2.3 From d6db3f5c11dc7ed5712d5d5682aa34025ee5248e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 23 Feb 2010 11:25:23 +0200 Subject: vhost: fix get_user_pages_fast error handling get_user_pages_fast returns number of pages on success, negative value on failure, but never 0. Fix vhost code to match this logic. Reviewed-by: Juan Quintela Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 6c31c0c9bbb9..7cd55e078794 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -646,8 +646,9 @@ static int set_bit_to_user(int nr, void __user *addr) int bit = nr + (log % PAGE_SIZE) * 8; int r; r = get_user_pages_fast(log, 1, 1, &page); - if (r) + if (r < 0) return r; + BUG_ON(r != 1); base = kmap_atomic(page, KM_USER0); set_bit(bit, base); kunmap_atomic(base, KM_USER0); -- cgit v1.2.3 From 39286fa41a8b2c6a9c1f656a7b3c3efca95bc1b9 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Sun, 28 Feb 2010 19:39:16 +0200 Subject: vhost-net: restart tx poll on sk_sndbuf full guest to remote communication with vhost net sometimes stops until guest driver is restarted. This happens when we get guest kick precisely when the backend send queue is full, as a result handle_tx() returns without polling backend. This patch fixes this by restarting tx poll on this condition. Signed-off-by: Sridhar Samudrala Signed-off-by: Michael S. Tsirkin Tested-by: Tom Lendacky --- drivers/vhost/net.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 91a324cc2298..ad37da2b6cb5 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -114,8 +114,12 @@ static void handle_tx(struct vhost_net *net) return; wmem = atomic_read(&sock->sk->sk_wmem_alloc); - if (wmem >= sock->sk->sk_sndbuf) + if (wmem >= sock->sk->sk_sndbuf) { + mutex_lock(&vq->mutex); + tx_poll_start(net, sock); + mutex_unlock(&vq->mutex); return; + } use_mm(net->dev.mm); mutex_lock(&vq->mutex); -- cgit v1.2.3 From 76dadd76c265a0cdb5a76aa4eef03fcc9639b388 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 28 Feb 2010 01:20:36 +0000 Subject: scm: Only support SCM_RIGHTS on unix domain sockets. We use scm_send and scm_recv on both unix domain and netlink sockets, but only unix domain sockets support everything required for file descriptor passing, so error if someone attempts to pass file descriptors over netlink sockets. Cc: stable@kernel.org Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller --- net/core/scm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/scm.c b/net/core/scm.c index b7ba91b074b3..9b264634acfd 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -156,6 +156,8 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) switch (cmsg->cmsg_type) { case SCM_RIGHTS: + if (!sock->ops || sock->ops->family != PF_UNIX) + goto error; err=scm_fp_copy(cmsg, &p->fp); if (err<0) goto error; -- cgit v1.2.3 From c16cc0b464b8876cfd57ce1c1dbcb6f9a6a0bce3 Mon Sep 17 00:00:00 2001 From: Vladislav Zolotarov Date: Sun, 28 Feb 2010 00:12:02 +0000 Subject: bnx2x: Tx barriers and locks [Resending with the proper subject. Sorry for the mess. ] This patch is based on the RFC of Stanislaw Gruszka. More specifically it fixes two possible races: - One, described by Stanislaw, may lead to permanent disabling of the Tx queue. This is fixed by adding the smp_wmb() to propagate the BD consumer change towards the memory. - Second may lead to bnx2x_start_xmit() returning NETDEV_TX_BUSY. This is fixed by taking a tx_lock() before rechecking the number of available Tx BDs. thanks, vlad Signed-off-by: Stanislaw Gruszka Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 5adf2a05246f..ed785a30e98b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,8 +57,8 @@ #include "bnx2x_init_ops.h" #include "bnx2x_dump.h" -#define DRV_MODULE_VERSION "1.52.1-6" -#define DRV_MODULE_RELDATE "2010/02/16" +#define DRV_MODULE_VERSION "1.52.1-7" +#define DRV_MODULE_RELDATE "2010/02/28" #define BNX2X_BC_VER 0x040200 #include @@ -957,21 +957,34 @@ static int bnx2x_tx_int(struct bnx2x_fastpath *fp) fp->tx_pkt_cons = sw_cons; fp->tx_bd_cons = bd_cons; + /* Need to make the tx_bd_cons update visible to start_xmit() + * before checking for netif_tx_queue_stopped(). Without the + * memory barrier, there is a small possibility that + * start_xmit() will miss it and cause the queue to be stopped + * forever. + */ + smp_wmb(); + /* TBD need a thresh? */ if (unlikely(netif_tx_queue_stopped(txq))) { - - /* Need to make the tx_bd_cons update visible to start_xmit() - * before checking for netif_tx_queue_stopped(). Without the - * memory barrier, there is a small possibility that - * start_xmit() will miss it and cause the queue to be stopped - * forever. + /* Taking tx_lock() is needed to prevent reenabling the queue + * while it's empty. This could have happen if rx_action() gets + * suspended in bnx2x_tx_int() after the condition before + * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()): + * + * stops the queue->sees fresh tx_bd_cons->releases the queue-> + * sends some packets consuming the whole queue again-> + * stops the queue */ - smp_mb(); + + __netif_tx_lock(txq, smp_processor_id()); if ((netif_tx_queue_stopped(txq)) && (bp->state == BNX2X_STATE_OPEN) && (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)) netif_tx_wake_queue(txq); + + __netif_tx_unlock(txq); } return 0; } -- cgit v1.2.3 From 85b3526932645269f67fee3583fa2aa500ab4f34 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 1 Mar 2010 09:53:04 +0000 Subject: bridge: Fix build error when IGMP_SNOOPING is not enabled Fix the following build error when IGMP_SNOOPING is not enabled. In file included from net/bridge/br.c:24: net/bridge/br_private.h: In function 'br_multicast_is_router': net/bridge/br_private.h:361: error: 'struct net_bridge' has no member named 'multicast_router' net/bridge/br_private.h:362: error: 'struct net_bridge' has no member named 'multicast_router' net/bridge/br_private.h:363: error: 'struct net_bridge' has no member named 'multicast_router_timer' Signed-off-by: Sridhar Samudrala Acked-by: Randy Dunlap Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/bridge/br_private.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 9191198c4f1b..1cf2cef78584 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -302,6 +302,13 @@ extern int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); + +static inline bool br_multicast_is_router(struct net_bridge *br) +{ + return br->multicast_router == 2 || + (br->multicast_router == 1 && + timer_pending(&br->multicast_router_timer)); +} #else static inline int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, @@ -354,14 +361,11 @@ static inline void br_multicast_forward(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb2) { } -#endif - static inline bool br_multicast_is_router(struct net_bridge *br) { - return br->multicast_router == 2 || - (br->multicast_router == 1 && - timer_pending(&br->multicast_router_timer)); + return 0; } +#endif /* br_netfilter.c */ #ifdef CONFIG_BRIDGE_NETFILTER -- cgit v1.2.3 From 4ab408dea0f0dba4dec0555f4f35b7ae703f5e91 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 1 Mar 2010 03:09:26 +0000 Subject: net: fix protocol sk_buff field Commit e992cd9b72a18 (kmemcheck: make bitfield annotations truly no-ops when disabled) allows us to revert a workaround we did in the past to not add holes in sk_buff structure. This patch partially reverts commit 14d18a81b5171 (net: fix kmemcheck annotations) so that sparse doesnt complain: include/linux/skbuff.h:357:41: error: invalid bitfield specifier for type restricted __be16. Reported-by: Stefan Richter Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index d266eeef522d..03f816a9b659 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -355,8 +355,8 @@ struct sk_buff { ipvs_property:1, peeked:1, nf_trace:1; - __be16 protocol:16; kmemcheck_bitfield_end(flags1); + __be16 protocol; void (*destructor)(struct sk_buff *skb); #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) -- cgit v1.2.3 From b88aafd365bc6a2222e2d03ff320adea3a37f628 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 2 Mar 2010 03:44:41 -0800 Subject: sis190: fix cable detect via link status poll Some sis190 devices don't report LinkChange, so do polling for link status. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=11926 Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: David S. Miller --- drivers/net/sis190.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 80af4a44580e..760d9e83a465 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -285,6 +285,11 @@ struct sis190_private { struct list_head first_phy; u32 features; u32 negotiated_lpa; + enum { + LNK_OFF, + LNK_ON, + LNK_AUTONEG, + } link_status; }; struct sis190_phy { @@ -750,6 +755,7 @@ static irqreturn_t sis190_interrupt(int irq, void *__dev) if (status & LinkChange) { netif_info(tp, intr, dev, "link change\n"); + del_timer(&tp->timer); schedule_work(&tp->phy_task); } @@ -922,12 +928,15 @@ static void sis190_phy_task(struct work_struct *work) if (val & BMCR_RESET) { // FIXME: needlessly high ? -- FR 02/07/2005 mod_timer(&tp->timer, jiffies + HZ/10); - } else if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) & - BMSR_ANEGCOMPLETE)) { + goto out_unlock; + } + + val = mdio_read_latched(ioaddr, phy_id, MII_BMSR); + if (!(val & BMSR_ANEGCOMPLETE) && tp->link_status != LNK_AUTONEG) { netif_carrier_off(dev); netif_warn(tp, link, dev, "auto-negotiating...\n"); - mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); - } else { + tp->link_status = LNK_AUTONEG; + } else if ((val & BMSR_LSTATUS) && tp->link_status != LNK_ON) { /* Rejoice ! */ struct { int val; @@ -1000,7 +1009,10 @@ static void sis190_phy_task(struct work_struct *work) netif_info(tp, link, dev, "link on %s mode\n", p->msg); netif_carrier_on(dev); - } + tp->link_status = LNK_ON; + } else if (!(val & BMSR_LSTATUS) && tp->link_status != LNK_AUTONEG) + tp->link_status = LNK_OFF; + mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); out_unlock: rtnl_unlock(); @@ -1513,6 +1525,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) tp->pci_dev = pdev; tp->mmio_addr = ioaddr; + tp->link_status = LNK_OFF; sis190_irq_mask_and_ack(ioaddr); -- cgit v1.2.3 From f31e50a802baae939c49819b8acd8f077019d398 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 2 Mar 2010 03:56:39 -0800 Subject: be2net: fix tx completion polling In tx/mcc polling, napi_complete() is being incorrectly called before reaping tx completions. This can cause tx compl processing to be scheduled on another cpu concurrently which can result in a panic. This if fixed by calling napi complete() after tx/mcc compl processing but before re-enabling interrupts (via a cq notify). Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_cmds.c | 26 ++++++++++++------------- drivers/net/benet/be_cmds.h | 2 +- drivers/net/benet/be_main.c | 47 ++++++++++++++++++++++----------------------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index c8a2bacb1d13..4b1f80519ca4 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -119,10 +119,10 @@ void be_async_mcc_disable(struct be_adapter *adapter) adapter->mcc_obj.rearm_cq = false; } -int be_process_mcc(struct be_adapter *adapter) +int be_process_mcc(struct be_adapter *adapter, int *status) { struct be_mcc_compl *compl; - int num = 0, status = 0; + int num = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; spin_lock_bh(&adapter->mcc_cq_lock); @@ -135,31 +135,31 @@ int be_process_mcc(struct be_adapter *adapter) be_async_link_state_process(adapter, (struct be_async_event_link_state *) compl); } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { - status = be_mcc_compl_process(adapter, compl); + *status = be_mcc_compl_process(adapter, compl); atomic_dec(&mcc_obj->q.used); } be_mcc_compl_use(compl); num++; } - if (num) - be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); - spin_unlock_bh(&adapter->mcc_cq_lock); - return status; + return num; } /* Wait till no more pending mcc requests are present */ static int be_mcc_wait_compl(struct be_adapter *adapter) { #define mcc_timeout 120000 /* 12s timeout */ - int i, status; + int i, num, status = 0; + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + for (i = 0; i < mcc_timeout; i++) { - status = be_process_mcc(adapter); - if (status) - return status; + num = be_process_mcc(adapter, &status); + if (num) + be_cq_notify(adapter, mcc_obj->cq.id, + mcc_obj->rearm_cq, num); - if (atomic_read(&adapter->mcc_obj.q.used) == 0) + if (atomic_read(&mcc_obj->q.used) == 0) break; udelay(100); } @@ -167,7 +167,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) dev_err(&adapter->pdev->dev, "mccq poll timed out\n"); return -1; } - return 0; + return status; } /* Notify MCC requests and wait for completion */ diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 728b0d736929..cce61f9a3714 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -920,7 +920,7 @@ extern int be_cmd_get_flow_control(struct be_adapter *adapter, extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num, u32 *cap); extern int be_cmd_reset_function(struct be_adapter *adapter); -extern int be_process_mcc(struct be_adapter *adapter); +extern int be_process_mcc(struct be_adapter *adapter, int *status); extern int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon, u8 status, u8 state); extern int be_cmd_get_beacon_state(struct be_adapter *adapter, diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 27ccdd80257b..a703ed8e24fe 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -583,7 +583,7 @@ static void be_set_multicast_list(struct net_device *netdev) } be_cmd_multicast_set(adapter, adapter->if_handle, netdev, - &adapter->mc_cmd_mem); + &adapter->mc_cmd_mem); done: return; } @@ -1469,23 +1469,38 @@ int be_poll_rx(struct napi_struct *napi, int budget) return work_done; } -void be_process_tx(struct be_adapter *adapter) +/* As TX and MCC share the same EQ check for both TX and MCC completions. + * For TX/MCC we don't honour budget; consume everything + */ +static int be_poll_tx_mcc(struct napi_struct *napi, int budget) { + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); struct be_queue_info *txq = &adapter->tx_obj.q; struct be_queue_info *tx_cq = &adapter->tx_obj.cq; struct be_eth_tx_compl *txcp; - u32 num_cmpl = 0; + int tx_compl = 0, mcc_compl, status = 0; u16 end_idx; while ((txcp = be_tx_compl_get(tx_cq))) { end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, - wrb_index, txcp); + wrb_index, txcp); be_tx_compl_process(adapter, end_idx); - num_cmpl++; + tx_compl++; } - if (num_cmpl) { - be_cq_notify(adapter, tx_cq->id, true, num_cmpl); + mcc_compl = be_process_mcc(adapter, &status); + + napi_complete(napi); + + if (mcc_compl) { + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); + } + + if (tx_compl) { + be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); /* As Tx wrbs have been freed up, wake up netdev queue if * it was stopped due to lack of tx wrbs. @@ -1496,24 +1511,8 @@ void be_process_tx(struct be_adapter *adapter) } drvr_stats(adapter)->be_tx_events++; - drvr_stats(adapter)->be_tx_compl += num_cmpl; + drvr_stats(adapter)->be_tx_compl += tx_compl; } -} - -/* As TX and MCC share the same EQ check for both TX and MCC completions. - * For TX/MCC we don't honour budget; consume everything - */ -static int be_poll_tx_mcc(struct napi_struct *napi, int budget) -{ - struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); - struct be_adapter *adapter = - container_of(tx_eq, struct be_adapter, tx_eq); - - napi_complete(napi); - - be_process_tx(adapter); - - be_process_mcc(adapter); return 1; } -- cgit v1.2.3 From 2507c05ff55fbf38326b08ed27eaed233bc75042 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 2 Mar 2010 03:57:33 -0800 Subject: virtio_net: remove forgotten assignment This is no longer needed. I missed to remove this in 567ec874d15b478c8eda7e9a5d2dcb05f13f1fb5 ("net: convert multiple drivers to use netdev_for_each_mc_addr, part6") Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e6095f3aa05f..25dc77ccbf58 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -775,7 +775,6 @@ static void virtnet_set_rx_mode(struct net_device *dev) mac_data = (void *)&mac_data->macs[uc_count][0]; mac_data->entries = mc_count; - addr = dev->mc_list; i = 0; netdev_for_each_mc_addr(addr, dev) memcpy(&mac_data->macs[i++][0], addr->da_addr, ETH_ALEN); -- cgit v1.2.3